/*
 * 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;   /* light only, as live: the dark-scheme blocks are deleted */

    /* 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-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 */

    /* --- 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.
 */
/* Port Sorell 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 beside --scheme above. Once the colours
 * go through the roles, that block would start flipping them. */

/* ═══════════════════════════════════════════════════════════════════════
 * 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; }

* { 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%;
}

/* 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 are rounded by default. The square-photo bug on Wellbrook was an
 * <img> with no radius sitting beside cards that had one. */
img, picture, video, canvas, svg {
    height: auto;
}

/*
 * Logos, icons and inline SVG are not photographs — a background plate and a
 * radius are wrong for them, and show up as a white box on a dark footer.
 */
img[class*="logo"], img[class*="icon"], .logo img, svg {
    border-radius: 0;
    background: none;
}

/* Opt out where a radius is wrong: full-bleed art, decorative crops. */
img.is-flush, .is-flush img { border-radius: 0; background: none; }

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 inherit typography rather than using browser chrome. */
:where(input, button, textarea, select) { font: inherit; }   /* zero specificity: "Form controls" below must win */

/* ═══ 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) ═════════════════════════ */

/* This site's field look (owner, 2026-10-05: one shape for every text field,
   search and contact alike). Pills with no edge, because every button here is
   a crimson pill (.btn--cta, the Book button): one corner, --control-radius,
   for every button and field; the textarea takes the pill's own corner, half the control
   height. The fill and ink are set per ground: these are the light grounds'
   (the search panel); the overlay and the contact card's dark teal re-set
   them on their own containers.
   ONE focus ring for links, buttons and fields: the kit's "Black" #000B0C,
   measured by painting at >= 4.1:1 on every light and mid ground the site
   has -- white 19.9, accent 14.9, cream 17.4, the bar's gradient 4.3 to 10.9,
   crimson 4.2, salmon 5.8. Only the dark teal grounds (the contact card, the
   hours card, the why-choose panel, the policies panel) re-set it, to white:
   14.4:1 on their dark end, 4.7:1 on their light one. */
:root {
    --control-radius: var(--radius-pill);
    --field-h: var(--target-min);
    --field-pad-block: var(--space-2xs);
    --field-pad-inline: var(--space-s);
    --field-textarea-radius: calc(var(--target-min) / 2);
    --field-bg: var(--paper);
    --field-ink: var(--ink-black);
    --field-border-w: 0px;                    /* no edge: the fill is the field */
    --field-border: transparent;
    --field-border-hover: transparent;
    --field-placeholder: var(--ink-mid);
    --focus-ring: var(--ink-black);
    --focus-ring-w: var(--border-medium);
}
.contact-form-card,
.hours-card,
.whychoose,
.policies-card--panel { --focus-ring: var(--paper); }

/* 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,
.mf-search__submit,
.mf-search-overlay__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-3xs);
    min-block-size: var(--target-min);   /* the 44px tap target */
    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--cta-lg { padding: var(--space-xs) var(--space-m); font-size: var(--step-0); }   /* live's 226x55 on the About page cards */
.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.
 *
 * On this site's tokens, like the rest of the stylesheet (2026-10-03): the
 * template ships these rules against literals so they survive any site's
 * vocabulary, and the site layer below defines every token used here. */
.notfound {
    padding-block: var(--space-2xl-3xl) var(--space-xl-2xl);
    text-align: center;
}
.notfound__inner { max-width: 46rem; margin-inline: auto; }

/* Decorative, aria-hidden in the markup - the <h1> carries the meaning. Sized
 * large but kept at a legible contrast: a very pale numeral fails WCAG even
 * when it is ornamental. */
.notfound__code {
    font-size: var(--step-7);   /* the site's display step, as the practice page's hero title */
    font-weight: var(--weight-700);
    line-height: var(--leading-2xs);
    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;
    /* The rule is a hairline of the surrounding ink rather than a named border
     * token, so it follows whatever ground the page sets. */
    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);
}


/* ═══════════════════════════════════════════════════════════════════════
 * PORT SORELL MEDICAL CENTRE — site layer
 *
 * Everything above this line is the shared template. Everything below
 * retunes it to the practice's own design, transcribed from the WordPress
 * site at www.psmed.com.au on 2026-09-08. Values are measured, not chosen:
 * where a number looks odd (a 1290 shell with a 1350 booking band and a
 * 1360 header bar, a card lifted 150px over the video, a tile dropped 75px,
 * an hours card pulled 209px up the page) it is because the source has it.
 * ═══════════════════════════════════════════════════════════════════════ */

:root {
    /* --- Scale: the template's eight knobs, fitted to live (2026-10-03).
     * Live's root font is 12px + 0.3125vw (16.5 at 1440, 15.2 at 1024, 13.2
     * at 390) and every size is a rem multiple of it: 0.75 / 0.875 / 1 /
     * 1.125 / 1.25 / 1.5 / 2 / 2.5. Body is live's 16.5 at 1440 and holds the
     * owner's 15px floor on a phone. The max font is 16.4992, not 16.5: this
     * renderer snaps font sizes to whole pixels, so 16.5 renders as 17 where
     * 16.4992 renders as 16, and every paragraph wraps wider.
     *
     * The ratio is fitted so each live size keeps a step of its own; live's
     * two display sizes sit on the display steps. Px at 1440 (390), live ->
     * ours:
     *   fine print 12.38 -> step--2 12.58 (11.96)
     *   labels, buttons 14.44 -> step--1 14.41 (13.39)
     *   body 16.5 -> step-0 16.50 (15.00)
     *   eyebrows, ledes 18.56 -> step-1 18.89 (16.80)
     *   card titles 20.63 -> step-2 21.63 (18.82)
     *   hours title, years 24.75 -> step-3 24.77 (21.07)
     *   band titles 33 -> step-5 32.47 (26.44; 23.60 at step-4 on a phone)
     *   the about card and hub titles 41.25 -> step-7 42.57 (29.62 at step-6)
     *
     * Spacing: live's 10/20/30/40/60/80/120 rhythm is the template ladder on
     * a 20px unit (--u-space-max 1.25), so 1440 lands on it exactly; a phone
     * is 20% tighter (--u-space-min 1). --- */
    --u-min-vw: 390;
    --u-max-vw: 1440;
    --u-min-font: 15;
    --u-max-font: 16.4992;
    --u-min-ratio: 1.12;
    --u-max-ratio: 1.145;
    --u-space-min: 1;
    --u-space-max: 1.25;
    --title-band: var(--step-5);      /* live's 33px band titles */
    --title-hours: var(--step-3);     /* live's 24.75px hours-card title */

    /* Leading: the template's ladder plus live's own values. 2xs = 1 (the
     * footer lists), s1 = 1.2 (display titles), s2 = 1.25 (footer links on a
     * phone), m2 = 1.4 (Merriweather card titles, nav, pills), 2xl = 2 (the
     * hours notes). xs/s/m/l/xl keep the template's values: its headings and
     * buttons use s. */
    --leading-2xs: 1;
    --leading-s1: 1.2;
    --leading-s2: 1.25;
    --leading-m2: 1.4;
    --leading-2xl: 2;

    /* --- Palette: the Elementor kit, through the dials. --- */
    --palette-hue: 224.1;               /* primary #557987 */
    --palette-chroma: 0.0461;
    --l-primary: 0.5543;                /* --primary's own lightness (the template's --primary line reads it) */
    --l-hover: 0.48;
    --palette-secondary-shift: -27.3;   /* secondary #B1C3C3 */
    --chroma-secondary: 0.0197;
    --l-secondary: 0.8035;
    --palette-tertiary-shift: -191.1;   /* "Crimson Red" #C14D36: every button */
    --chroma-tertiary: 0.154;
    --l-tertiary: 0.5702;

    /* Neutrals: ink is the kit's "Grey" #272A2C, the ground is pure white. */
    --hue-neutral: 236.7;
    --chroma-ink: 0.0046;
    --l-ink: 0.2828;
    --l-ink-mid: 0.40;
    --l-bg: 1;
    --chroma-ground: 0;
    --l-on-solid: 1;                    /* text on a fill is the kit's White, #FFFFFF */
    --l-border: 0.8822;                 /* #D8D8D8, the rule grey (live's hours separator and list rules) */
    --chroma-border: 0;

    /* The kit's named colours, by their kit names. */
    --brand-ink: oklch(0.4096 0.0549 228.8);     /* "Text" #275062 — headings */
    --accent-tint: oklch(0.8994 0.0192 196.8);   /* "Accent" #D0E2E2 */
    --cream: oklch(0.9535 0.0172 84.6);          /* "Cream" #F5EFE3 */
    --ink-black: oklch(0.136 0.0231 200.3);      /* "Black" #000B0C — body copy */
    --paper: var(--surface);                     /* "White": the surface role, oklch(1 0 0) on the neutral dials */
    --crimson: var(--tertiary);
    --salmon: oklch(0.6422 0.0896 31.3);         /* #BD786B — card colour, not in the kit */
    --salmon-deep: oklch(0.4515 0.1336 33.1);    /* #91311E — its hover */
    --rule-grey: var(--border);                  /* #D8D8D8 — hours separator: the border role, on the neutral dials */
    --pill-ink: oklch(0.3211 0 0);               /* #333 — the contact pills */
    /* Colours no role derives, named once here so no rule writes one inline. */
    --field-tint: oklch(0.9870 0.0107 76.60);    /* rgb(255, 250, 243): the contact form's wells, laid at 14% */
    --faq-rule: oklch(0.87 0.004 250);           /* the FAQ items' outline; no live measurement recorded, value kept */
    --photo-ground: oklch(0.97 0 0);             /* under the team CTA's photograph until it loads; not measured */
    --video-ground: oklch(0 0 0);                /* the video box before the player paints */
    --shadow-bar: 0 1px 20px oklch(0 0 0 / 0.04);

    /* Gradients, verbatim from the source's computed styles. */
    --grad-bar: linear-gradient(167deg, var(--primary) 37%, var(--secondary) 100%);
    --grad-hero: linear-gradient(180deg, var(--paper) 0%, var(--accent-tint) 100%);
    --grad-info: linear-gradient(180deg, var(--accent-tint) 0%, var(--cream) 100%);
    --grad-values: linear-gradient(180deg, var(--cream) 0%, var(--paper) 100%);
    --grad-booking: linear-gradient(180deg, var(--paper) 0%, var(--accent-tint) 100%);
    --grad-footer: linear-gradient(180deg, var(--accent-tint) 0%, var(--primary) 100%);
    --grad-hours: linear-gradient(327deg, var(--primary) 0%, var(--ink) 100%);
    --grad-step: linear-gradient(327deg, var(--primary) 0%, var(--secondary) 100%);
    --grad-panel: linear-gradient(var(--primary) 0%, var(--brand-ink) 100%);
    --grad-paper-cream: linear-gradient(var(--paper) 0%, var(--cream) 100%);
    --grad-cream-accent: linear-gradient(var(--cream) 0%, var(--accent-tint) 100%);
    /* The closing panel's own grounds, one per page, all measured off live. */
    --grad-panel-card: linear-gradient(var(--secondary) 0%, var(--accent-tint) 100%);   /* #B1C3C3 -> #D0E2E2 */
    --grad-panel-sec-cream: linear-gradient(var(--secondary) 0%, var(--cream) 100%);    /* #B1C3C3 -> #F5EFE3 */
    --grad-panel-accent-cream: linear-gradient(var(--accent-tint) 0%, var(--cream) 100%); /* #D0E2E2 -> #F5EFE3 */
    --grad-panel-paper-cream: linear-gradient(var(--paper) 0%, var(--cream) 100%);      /* #FFFFFF -> #F5EFE3 */
    --grad-cream-secondary: linear-gradient(var(--cream) 0%, var(--secondary) 100%);  /* #F5EFE3 -> #B1C3C3 */
    --grad-form: linear-gradient(var(--ink) 0%, var(--primary) 100%);

    /* --- Typefaces: Merriweather for headings and the nav, Raleway for
     * everything else, Manrope for the footer link lists and the hours notes
     * (three families, because the source uses three). --- */
    --font-body: "Raleway", system-ui, sans-serif;
    --font-heading: "Merriweather", Georgia, serif;
    --font-list: "Manrope", system-ui, sans-serif;
    --weight-500: 500;   /* body copy on this site is Raleway 500 */
    --weight-800: 800;   /* the two 800-weight display titles */

    /* --- Shells: 1290 for most bands (75px margins at 1440), 1350 for the
     * booking band and the footer, 1400 for the header bar. --- */
    --shell: 80.625rem;
    --shell-wide: 84.375rem;
    --shell-header: 87.5rem;
    --grid-max-width: var(--shell);
    --grid-gutter: var(--space-l);    /* live's fixed 40px outer padding (32 at 390), and 20 below 768 */

    /* Named spacings, every one a sum of steps. Band padding is live's 80
     * at 1440 and 48 on a phone (the owner's 2026-10-01 sweep tightened phone
     * bands to 44: desktop rhythm on a 390 screen left every seam 120-200px
     * of empty ground). The three below it are live's Elementor values that
     * fall between the ladder's steps. */
    --space-band: var(--space-xl-2xl);                          /* 80 (48 on a phone) */
    --space-card: calc(var(--space-s-l) + var(--space-2xs));     /* 50 (26): card and panel insets, and the gaps between cards and columns; a phone keeps the 28 the sweep gave its cards */
    --space-panel: calc(var(--space-xl) + var(--space-2xs));     /* 70 (56): the deep panels' inset, and the footer's */
    --space-column: calc(var(--space-xl-2xl) + var(--space-s));  /* 100 (64): the wide gap between a band's columns */
    --space-group: calc(var(--space-s) + var(--space-xs));       /* 35 (28): between a block's groups, and a title's foot */

    /* Radii: 15px cards, 10px photos, 20px header bar, 5px menus. */
    --radius-card: 0.9375rem;
    --radius-photo: 0.625rem;
    --radius-menu: 0.3125rem;

    /* Fixed dimensions (not spacing, so not on the scale): the touch target,
     * and the icon boxes whose first-line centring the margins compute. */
    --target-min: 44px;        /* WCAG 2.5.5 target, and the drawer's sub-toggle */
    --contact-icon: 22px;
    --tick-icon: 14px;
    --svc-marker-size: 8px;    /* the service lists' disc; ticks and icons reset it */
    /* Typographic, not spacing: how far an element's line box overshoots its
     * text on each side. Unregistered, so 1lh and 1em resolve on the element
     * that uses it (a 20.6px title on 1.3 leading: 3px). */
    --half-leading: calc((1lh - 1em) / 2);

    /* The two lifts the source builds its hero on: the white card rides 150px
     * up over the video, and the Working Hours card rides 209px up from the
     * band-2 grid into the hero band. Both are measured, neither is 50:50 —
     * see CLAUDE.md, "Deliberate deviations". Both are sums of steps, so
     * they exact at 1440 and ride 20% less on a narrow screen. */
    --card-lift: calc(var(--space-3xl) + var(--space-m));                     /* 150 */
    --hours-lift: calc(var(--space-3xl) + var(--space-2xl) + var(--space-2xs));   /* 210 (live 209) */
}

/* The site's design is a fixed light palette: color-scheme is pinned to
 * light beside --scheme in the template's root block, and no dark-scheme
 * block remains to flip it. */

/* ── Base ─────────────────────────────────────────────────────────── */
body { background: var(--paper); color: var(--ink-black); font-weight: var(--weight-500); }
/* Photographs carry their own radius per component; logos, badges and icons carry none. */
img { border-radius: 0; background: none; }
h1, h2, h3, h4, h5, h6 { letter-spacing: var(--tracking-m); text-wrap: pretty; color: var(--brand-ink); }
.u-container { max-width: calc(var(--grid-max-width) + 2 * var(--grid-gutter)); }
.u-container--wide { --grid-max-width: var(--shell-wide); }
.center { text-align: center; }

/* Skip link */
.skip-link {
    position: absolute; left: var(--space-s); top: -100%;
    z-index: var(--layer-top);
    padding: var(--space-2xs) var(--space-s);
    background: var(--primary); color: var(--paper);
}
.skip-link:focus { top: var(--space-s); }

/* ── Type roles ───────────────────────────────────────────────────── */
/* Eyebrow: Raleway 700 at 18.56px, crimson, no tracking. The source writes
 * the capitals into the copy; uppercase here renders the merge tag the same. */
.eyebrow {
    display: block;
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--step-1);
    font-weight: var(--weight-700);
    line-height: var(--leading-l);
    letter-spacing: var(--tracking-m);
    text-transform: uppercase;
    color: var(--crimson);
}
/* Band titles: Merriweather 800 33px on 1.3 (700 on the booking card). */
.band-title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: var(--title-band);
    font-weight: var(--weight-800);
    line-height: var(--leading-m);
    color: var(--brand-ink);
}
.band-title--regular { font-weight: var(--weight-700); }
.rule { height: 0; border: 0; border-top: var(--border-thin) solid var(--secondary); }

/* Buttons: the source's one button — crimson pill, Raleway 700 14.4px,
 * 12/20 padding (10/25 in the header), text-shadow none, no border. Hover
 * is Elementor's "float" (page) and "grow" (header). */
.btn--cta,
.mf-search__submit,
.mf-search-overlay__close {
    padding: var(--space-2xs) var(--space-s);
    background: var(--crimson);
    color: var(--paper);
    border: 0;
    border-radius: var(--control-radius);
    font-family: var(--font-body);
    font-size: var(--step--1);
    font-weight: var(--weight-700);
    line-height: var(--leading-l);
    transition: transform 0.3s var(--ease-out), background var(--duration-fast) var(--ease-out);
}
.btn--cta:hover, .btn--cta:focus-visible,
.mf-search__submit:hover, .mf-search__submit:focus-visible,
.mf-search-overlay__close:hover, .mf-search-overlay__close:focus-visible { background: var(--crimson); color: var(--paper); transform: translateY(-8px); }
.btn--cta.btn--cta-lg { padding: var(--space-xs) var(--space-m); font-size: var(--step-0); }   /* the bare .btn--cta-lg sits earlier in the file and loses to .btn--cta */
.btn--cta-nav,
.mf-search__submit,
.mf-search-overlay__close { padding: var(--space-2xs) calc(var(--space-xs) + var(--space-2xs)); }
.btn--cta-nav:hover, .btn--cta-nav:focus-visible,
.mf-search__submit:hover, .mf-search__submit:focus-visible,
.mf-search-overlay__close:hover, .mf-search-overlay__close:focus-visible { transform: scale(1.1); }

/* ── Header ───────────────────────────────────────────────────────── */
/* A white sticky band holding a floating gradient bar (live's 0 4px 6px band
 * shadow is dropped so the bar floats on plain white — owner, 2026-09-27):
 * 1360 wide at 1440, radius 20, 10px padding, grid 1fr 3fr 1fr with the nav
 * centred in the middle track and the button centred in the last. */
.site-header {
    position: sticky;
    top: 0;
    z-index: var(--layer-nav);
    background: var(--paper);
    transition: background-color var(--duration-base) var(--ease-out);
}
/* Once the page has scrolled, the white band goes away and only the bar
 * floats over the content (owner, 2026-09-30). The band's padding still
 * occupies the top of the viewport, so it stops catching clicks and the bar
 * and skip link take them back. */
.site-header.is-stuck { background-color: transparent; pointer-events: none; }
.site-header.is-stuck .site-bar,
.site-header.is-stuck .skip-link { pointer-events: auto; }
.site-header__inner {
    max-width: calc(var(--shell-header) + 2 * var(--grid-gutter));
    margin-inline: auto;
    padding: var(--space-l) var(--grid-gutter);   /* 40 / 30 / 30 on the source */
}
.site-bar {
    display: grid;
    grid-template-columns: 1fr 3fr 1fr;
    gap: var(--space-3xs);
    align-items: center;
    padding: var(--space-2xs);   /* 10, 20 on a phone */
    border-radius: var(--radius-l);
    background: var(--grad-bar);
    box-shadow: var(--shadow-bar);
}
.site-logo { display: block; padding-left: var(--space-xs); }
.site-logo img { width: 100%; height: auto; }

.primary-nav { justify-self: center; }
.nav-list { display: flex; flex-wrap: wrap; justify-content: center; }
.nav-list li { position: relative; }
.nav-list > li > a {
    display: flex;
    align-items: center;
    gap: var(--space-3xs);
    padding: var(--space-xs) var(--space-xs);
    font-family: var(--font-heading);
    font-size: var(--step-0);
    font-weight: var(--weight-700);
    line-height: var(--leading-m2);
    color: var(--paper);
    text-decoration: none;
    transition: transform 0.3s var(--ease-out);
}
.nav-list > li > a:hover, .nav-list > li > a:focus-visible { color: var(--paper); transform: scale(1.2); }
.nav-caret { width: 0.6em; height: 1em; fill: currentColor; flex: none; }
.sub-toggle { display: none; }
.nav-list > li.nav-cta { display: none; }   /* the phone drawer's booking row; see the phone block */

/* Dropdowns: pale-teal panel, radius 5, Merriweather 700 0.9rem, dark text,
 * hover swaps to white on the brand ink. Nested panels open to the right.
 *
 * The panel is always in the layout and opens by fading and sliding the
 * last 6px (owner, 2026-10-01: the instant pop read as bolted on). The
 * top-level panel hangs from the BAR's bottom edge rather than the link's —
 * the bar pads 10 — with its top corners square against it and a soft
 * shadow, so it reads as the bar extending. An invisible 10px bridge above
 * it keeps the pointer's path from the link to the panel inside the item,
 * so crossing the gap does not close it. Visibility is delayed on close so
 * the fade-out is seen; on open it switches at once. */
.sub-menu {
    position: absolute;
    top: calc(100% + 1.375rem);   /* the bar's bottom edge: its 10 of padding plus the 12 the link sits above it */
    left: 0;
    z-index: var(--layer-overlay);
    min-width: 15em;
    --menu-pad: var(--space-3xs);
    padding: var(--menu-pad);
    background: var(--secondary);
    /* 15 outside, 5 of inset, so a row's 10 is concentric with the corner it
     * sits in: the hover block follows the panel's edge instead of cutting
     * a square into a round corner. */
    border-radius: 0 0 var(--radius-card) var(--radius-card);
    box-shadow: 0 14px 28px -14px oklch(0 0 0 / 0.35);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    pointer-events: none;
    transition: opacity var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out), visibility 0s linear var(--duration-base);
}
.sub-menu::before { content: ""; position: absolute; left: 0; right: 0; top: -1.375rem; height: 1.375rem; }
.sub-menu .sub-menu { top: 0; left: 100%; border-radius: var(--radius-menu); transform: translateX(-6px); }
.sub-menu .sub-menu::before { top: 0; bottom: 0; left: -0.5rem; right: auto; width: 0.5rem; height: auto; }
.nav-caret { transition: transform var(--duration-base) var(--ease-out); }
.nav-list > li:hover > a > .nav-caret, .nav-list > li:focus-within > a > .nav-caret, .nav-list > li.is-open > a > .nav-caret { transform: rotate(180deg); }
/* Rows match the mega panel's: Raleway 600, padded 4/10 so the text lines up
 * with the bar link's own 15px inset, each row its own rounded hover. */
.sub-menu a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2xs);
    padding: var(--space-2xs) var(--space-2xs);
    border-radius: var(--radius-photo);
    font-family: var(--font-body);
    font-size: var(--step--1);
    font-weight: var(--weight-600);
    line-height: var(--leading-m);
    color: var(--ink);
    text-decoration: none;
}
.sub-menu a:hover, .sub-menu a:focus-visible, .sub-menu li.is-open > a { background: var(--brand-ink); color: var(--paper); }
.sub-menu .nav-caret { transform: rotate(-90deg); }
.nav-list li:hover > .sub-menu,
.nav-list li:focus-within > .sub-menu,
.nav-list li.is-open > .sub-menu { opacity: 1; visibility: visible; transform: none; pointer-events: auto; transition-delay: 0s; }

/* The Services mega menu (owner, 2026-10-01). Nine services, four of them
 * with their own flyout, made a three-level hover tree that is hard to
 * steer at any age; this lays the whole tree out in one panel, every page
 * one hover away. The bar and the other two dropdowns are unchanged.
 *
 * The panel hangs from the BAR (the item goes static, the bar relative) and
 * is inset by the bar's own radius on each side, so its square top edge
 * meets the flat part of the bar's bottom and the rounded corners stay
 * clear. Each child group is a column: its link is the heading, its nested
 * list sits open beneath it with the flyout styling undone. The .mega-group
 * wrapper exists only to give the five standalone services a column of
 * their own; the drawer flattens it back out. */
/* Scoped to the wide layout: these selectors outrank the drawer block's,
 * and would otherwise open every group inside the drawer. */
@media (min-width: 64.0625rem) {
    .site-bar { position: relative; }
    .nav-list > li.mega { position: static; }
    .nav-list > li.mega > .sub-menu {
        top: 100%;
        left: var(--radius-l);
        right: var(--radius-l);
        display: grid;
        grid-template-columns: repeat(5, minmax(0, 1fr));
        grid-template-rows: auto auto;
        gap: var(--space-m);
        min-width: 0;
        padding: var(--space-m) var(--space-l) var(--space-l);
        border-radius: 0 0 var(--radius-l) var(--radius-l);
    }
    /* Each column spans the panel's two rows through subgrid, so the heading
     * row is one height across the panel and the rules under the headings
     * line up even where a heading wraps. Without subgrid the columns still
     * lay out, with the rules at their own heights. */
    .nav-list > li.mega > .sub-menu > li { display: grid; grid-template-rows: subgrid; grid-row: span 2; row-gap: var(--space-2xs); min-width: 0; }
    .nav-list > li.mega > .sub-menu > li > a {
        display: flex;
        align-items: flex-end;
        padding: 0 var(--space-2xs) var(--space-2xs);
        margin-bottom: 0;
        border-bottom: var(--border-thin) solid color-mix(in oklch, var(--primary) 45%, transparent);
        border-radius: 0;
        font-family: var(--font-heading);
        font-size: var(--step--1);
        font-weight: var(--weight-700);
        color: var(--brand-ink);
        text-wrap: balance;
    }
    .nav-list > li.mega > .sub-menu > li > a:hover,
    .nav-list > li.mega > .sub-menu > li > a:focus-visible { background: transparent; color: var(--crimson); }
    .nav-list > li.mega > .sub-menu .nav-caret { display: none; }
    .nav-list > li.mega .sub-menu .sub-menu {
        position: static;
        display: block;
        min-width: 0;
        padding: 0;
        background: transparent;
        border-radius: 0;
        box-shadow: none;
        opacity: 1;
        /* INHERIT, never visible/auto: a visible, pointer-catching child of a
         * hidden panel is still hoverable, so the closed panel opened from
         * anywhere over its columns and swallowed clicks on the page under
         * the bar (owner, 2026-10-01: "only when you hover Services"). */
        visibility: inherit;
        pointer-events: inherit;
        transform: none;
        transition: none;
    }
    .nav-list > li.mega .sub-menu .sub-menu::before { content: none; }
    .nav-list > li.mega .sub-menu .sub-menu a { display: block; }
}

.site-bar__actions { display: flex; justify-content: center; align-items: center; }
.nav-toggle {
    display: none;
    width: 44px;    /* live's is 33; 44 is the touch-target floor */
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 3px;
    background: var(--secondary);
    color: var(--brand-ink);   /* the kit's "Text" ink: 4.6:1 on the secondary tile, where the old white was 1.8:1 (WCAG 1.4.11) */
    cursor: pointer;
}
.nav-toggle svg { width: 22px; height: 22px; margin: auto; fill: currentColor; }
.nav-toggle__close, .nav-toggle[aria-expanded="true"] .nav-toggle__open { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle__close { display: block; }

/* ── Hero (band 1) ────────────────────────────────────────────────── */
.hero { background: var(--grad-hero); padding-block: var(--space-s); }
.hero__video {
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--radius-card);
    background: var(--video-ground);
}
.hero__video iframe { display: block; width: 100%; height: 100%; border: 0; }
.hero__row { display: flex; align-items: flex-start; gap: var(--space-s); }
.hero__contact {
    flex: 0 0 50%;
    display: grid;
    grid-template-columns: 1.5fr 1fr;
    gap: var(--space-s) var(--space-group);
    align-items: start;
    padding: var(--space-card) 0 0 var(--space-s);
}
.pill {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    margin: 0;
    padding: var(--space-s);
    border: var(--border-thin) solid var(--brand-ink);
    border-radius: var(--radius-card);
    font-family: var(--font-heading);
    font-size: var(--step-0);
    font-weight: var(--weight-700);
    line-height: var(--leading-m2);
    color: var(--pill-ink);
    text-decoration: none;
    transition: background var(--duration-base) var(--ease-out);
}
.pill--address { grid-column: 1; font-size: var(--step--1); }   /* live sets it a touch under body (15.7 at 1440); at body size the address wraps in its 50% track, so the step below */
.pill--phone, .pill--fax { grid-column: 2; width: 83%; }
a.pill:hover, a.pill:focus-visible { background: var(--secondary); color: var(--pill-ink); }
.pill__icon { width: 20px; height: 20px; flex: none; fill: var(--crimson); }

.hero__card {
    flex: 0 0 43%;
    margin-top: calc(-1 * var(--card-lift));
    padding: var(--space-panel);
    background: var(--paper);
    border-radius: var(--radius-card);
}
.band-title--hero { max-width: 37.5rem; margin-top: var(--space-s); }
.rule--hero { width: 28%; margin: var(--space-l) 0 var(--space-s); border-top-color: var(--accent-tint); }
.hero__copy p { margin: 0 0 var(--space-xs); font-weight: var(--weight-500); line-height: var(--leading-l); color: var(--ink-black); }
.hero__copy p:last-child { margin-bottom: 0; }
.hero__actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-s);
    align-items: end;
    margin-top: var(--space-card);
}
.hero__actions .btn--cta { justify-self: start; }
.hero__badge { width: 100%; max-width: 211px; height: auto; }

/* ── Hours + tiles (band 2) ───────────────────────────────────────── */
.band-info { background: var(--grad-info); padding: var(--space-s) 0 var(--space-2xl-3xl); }
.info-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));   /* minmax(0): a tile's min-content once pushed these past the band at 1025 */
    gap: var(--space-m);
    align-items: start;
}
.hours-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-m);              /* 30 (fixed on the source; scales here) */
    margin-top: calc(-1 * var(--hours-lift));
    padding: var(--space-card) var(--space-l);   /* 50 / 40 (fixed on the source; scales here) */
    border-radius: var(--radius-card);
    background: var(--grad-hours);
    color: var(--paper);
}
/* The source's headings and lists carry Elementor's own negative margins;
 * they are kept so the card lands at its measured 535px. */
.hours-card__title {
    margin: calc(-1 * var(--space-xs)) 0 calc(-1 * var(--space-2xs));
    font-size: var(--title-hours);
    font-weight: var(--weight-700);
    line-height: var(--leading-l);
    color: var(--paper);
}
.hours-list { margin: calc(-1 * var(--space-s)) 0 calc(-1 * var(--space-2xs)); padding-top: var(--space-xs); }
/* The rows are the opening_hours_html table from Rails (day | time), drawn as
 * live's day, hairline, time: the first cell grows and carries the rule. */
.hours-list .hours-table { margin: 0; }
.hours-list .hours-table tbody { display: grid; gap: var(--space-xs); }
.hours-list .hours-table tr { display: flex; align-items: center; }
.hours-list .hours-table td { padding: 0; border: 0; vertical-align: baseline; }
.hours-list .hours-table td:first-child { display: flex; flex: 1; align-items: center; font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); }
.hours-list .hours-table td:first-child::after { content: ""; flex: 1; margin: 0 var(--space-xs); border-bottom: var(--border-thin) solid var(--rule-grey); }
.hours-list .hours-table td:last-child { font-size: var(--step-2); font-weight: var(--weight-600); line-height: var(--leading-l); }
.hours-list__note { display: block; margin: var(--space-xs) 0 0; font-family: var(--font-list); font-size: var(--step--1); font-weight: var(--weight-500); line-height: var(--leading-2xl); color: var(--cream); }
.hours-card__notes { margin: calc(-1 * var(--space-3xs)) 0 var(--space-xs); }
.hours-card__notes p { margin: 0 0 calc(var(--space-xs) + var(--space-2xs)); font-weight: var(--weight-400); line-height: var(--leading-l); color: var(--paper); }
.hours-card__notes p:last-child { margin-bottom: 0; }
.hours-card__notes a { color: var(--cream); text-decoration: underline; }
.hours-card__notes a:hover { color: var(--paper); }

.tile { display: grid; gap: var(--space-m); align-self: start; text-decoration: none; }
.tile__box {
    display: block;
    padding: var(--space-l);
    border-radius: var(--radius-card);
    transition: background 0.3s var(--ease-out);
}
.tile__title { display: block; margin: var(--space-2xs) 0 var(--space-xs); font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); }
.tile__text { display: block; font-weight: var(--weight-400); line-height: var(--leading-l); }
.tile__photo { width: 100%; height: auto; aspect-ratio: 267 / 180; object-fit: cover; border-radius: var(--radius-photo); }
/* 1025-1199: the four-up row is at its narrowest, and "Appointments" at its
 * title size no longer fits a 40px inset, so the tiles' inline padding steps
 * down (measured 1025-1440 in 5px steps: nothing clips, nothing overruns). */
@media (min-width: 64.0625rem) and (max-width: 74.9375rem) { .tile__box { padding-inline: var(--space-s); } }
.tile--appointments .tile__box { background: var(--salmon); color: var(--paper); }
.tile--appointments:hover .tile__box { background: var(--salmon-deep); }
.tile--services .tile__box { background: var(--accent-tint); color: var(--ink); }
.tile--services .tile__title { color: var(--brand-ink); }
.tile--services:hover .tile__box { background: var(--secondary); }
.tile--policies .tile__box { background: var(--primary); color: var(--paper); }
.tile--policies:hover .tile__box { background: var(--brand-ink); }
/* The middle tile sits 75px lower than its neighbours; the negative bottom
 * margin keeps the grid row at the height of the other two. */
.tile--offset { margin-top: calc(var(--space-xl) + var(--space-xs)); margin-bottom: calc(-1 * calc(var(--space-xl) + var(--space-xs))); }

/* ── Core values intro (band 3) ───────────────────────────────────── */
/* On this band's cream ground the standard crimson eyebrow measures 4.18:1,
 * just under AA. --salmon-deep carries the same hue at a passing contrast. */
.band-values-head .eyebrow { color: var(--salmon-deep); }
.band-values-head {
    padding-block: var(--space-band);
    border-top: var(--border-thin) solid var(--secondary);
    background: var(--cream);
}
.values-head { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-m); }
.values-head .band-title { margin-top: var(--space-m); }
.rule--values { width: 41%; margin: calc(var(--space-xs) + var(--space-2xs)) 0 var(--space-xs); }
.values-head__lede { margin: 0; padding-top: var(--space-card); font-size: var(--step-1); font-weight: var(--weight-500); line-height: var(--leading-l); color: var(--ink); }

/* ── Core values (band 4) ─────────────────────────────────────────── */
/* The band spacing, not the larger 2xl-3xl step: a divider follows this
 * band, and the mismatch put 2.5x more space above the line than below. */
.band-values { background: var(--grad-values); padding-bottom: var(--space-band); }
.values-row { display: grid; gap: var(--space-m); }
.values-row--a, .values-row--c { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); }
.values-row--b { grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); }
.values-row--b, .values-row--c { margin-top: var(--space-card); }
.values-pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-s); }
.value-card {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: var(--space-xs);
    padding: var(--space-l);
    border-radius: var(--radius-card);
    text-align: center;
    color: var(--ink);
}
.value-card p { margin: 0; font-weight: var(--weight-500); line-height: var(--leading-l); }
.value-card__icon { width: 50px; height: 50px; fill: var(--primary); }
.value-card__icon--ink { fill: var(--brand-ink); }
.value-card__title { margin: var(--space-2xs) 0 1px; font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--ink); }
.value-card__title--brand { color: var(--brand-ink); }
.value-card__text--black { color: var(--ink-black); }
.value-card--accent { background: var(--accent-tint); }
.value-card--secondary { background: var(--secondary); }
.value-card--salmon { background: var(--salmon); color: var(--paper); }
.value-card--salmon .value-card__icon, .value-card--salmon .value-card__title { fill: var(--paper); color: var(--paper); }
.values-photo { border-radius: var(--radius-card); background-size: cover; background-position: center; }
.values-photo--doctors { background-image: url("/assets/images/doctors-outside-port-sorell-medical-centre.a012d5d455.webp"); }
.values-photo--carport { background-image: url("/assets/images/port-sorell-medical-centre-carport.4e7dd3b12a.webp"); }
.values-photo--team {
    display: flex;
    align-items: flex-end;
    padding: 0 0 var(--space-l) var(--space-l);
    background-image: url("/assets/images/port-sorell-medical-centre-team.47664f90b3.webp");
    background-position: center bottom;
}

/* ── Appointment booking (band 5) ─────────────────────────────────── */
.band-booking {
    padding-block: var(--space-band);
    border-top: var(--border-thin) solid var(--secondary);
    background: var(--grad-booking);
}
.booking { display: grid; grid-template-columns: 1fr 1fr; padding-inline: calc(var(--grid-gutter) + var(--space-s)); }
.booking__left { display: grid; gap: var(--space-m); padding-right: calc(var(--space-xs) + var(--space-2xs)); }
.booking-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-s);
    min-height: 24.0625rem;
    padding: var(--space-l);
    border: var(--border-thin) solid var(--crimson);
    border-radius: var(--radius-card);
}
.booking-card .eyebrow { margin-top: calc(var(--space-xs) + var(--space-2xs)); }
.booking-card .band-title { margin-bottom: calc(-1 * var(--space-2xs)); }
.booking-card__text { margin: 0; font-weight: var(--weight-500); line-height: var(--leading-l); color: var(--ink-black); }
.booking-card__action { margin: var(--space-xs) 0 0; }
.booking__photo {
    min-height: 24.6875rem;
    border-radius: var(--radius-card);
    background: url("/assets/images/receptionist-on-phone-port-sorell-medical-centre.daca54d79c.webp") center / cover;
}
.booking__steps { display: grid; gap: var(--space-m); align-content: start; }
.step {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    padding: var(--space-l) var(--space-xl) calc(var(--space-l) - var(--space-3xs));
    border-radius: var(--radius-card);
    background: var(--grad-step);
}
.step__icon { width: 50px; height: 50px; fill: var(--brand-ink); }
.step__title { margin: var(--space-2xs) 0 0; font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--ink); }
.step p { margin: 0; font-weight: var(--weight-500); line-height: var(--leading-l); color: var(--ink-black); }

/* ── Footer ───────────────────────────────────────────────────────── */
.site-footer { border-top: var(--border-thin) solid var(--primary); background: var(--grad-footer); }
.site-footer__inner {
    max-width: calc(var(--shell-wide) + 2 * var(--grid-gutter));
    margin-inline: auto;
    padding-inline: var(--grid-gutter);
}
.site-footer__grid { display: grid; grid-template-columns: 1fr 2fr; padding-block: var(--space-panel); }
.site-footer__brand { display: flex; flex-direction: column; gap: var(--space-m); padding-right: var(--space-column); }
.site-footer__logo { width: 18.75rem; max-width: 100%; height: auto; }
.site-footer__tagline { margin: 0; font-weight: var(--weight-400); line-height: var(--leading-l); color: var(--ink-black); }
.site-footer__motto { margin: calc(-1 * var(--space-s)) 0 0; font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--ink); }
.site-footer__right { display: grid; grid-template-columns: 2fr 1.6fr; gap: var(--space-card); }
.site-footer__links { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-card); }
.site-footer__col { display: flex; flex-direction: column; gap: var(--space-m); }
.site-footer__title { margin: calc(-1 * var(--space-3xs) / 2) 0; font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--brand-ink); }
.footer-links { margin-top: calc(-1 * var(--space-2xs)); }
.footer-links li { padding-block: var(--space-3xs); line-height: var(--leading-2xs); }
.footer-links a { font-family: var(--font-list); font-size: var(--step--1); font-weight: var(--weight-600); line-height: var(--leading-2xs); color: var(--ink); text-decoration: none; }
.footer-links a:hover, .footer-links a:focus-visible { color: var(--crimson); }
.site-footer__map { height: 18.75rem; overflow: hidden; border-radius: var(--radius-photo); }
.site-footer__map iframe { display: block; width: 100%; height: 100%; border: 0; }

.footer-bar {
    display: grid;
    grid-template-columns: 0.5fr 1fr;
    gap: var(--space-s);
    align-items: center;
    padding-block: var(--space-m);   /* fixed 30 on the source */
    border-top: var(--border-thin) solid var(--brand-ink);
}
/* The source's bar is 46px tall inside its 30px padding (Elementor's image widget box). */
.footer-bar__left { display: flex; align-items: center; gap: var(--space-xs); min-height: 2.875rem; }
.footer-bar__copyright { margin: 0; font-size: var(--step--1); font-weight: var(--weight-600); line-height: var(--leading-l); color: var(--ink-black); }
.powered-by { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2xs); margin: 0; font-size: var(--step--2); font-weight: var(--weight-600); color: var(--ink-black); }
/* flex-shrink would compress the width while the fixed height held, squashing
 * the logo on a narrow bar. It keeps its own aspect ratio and wraps instead. */
.powered-by img { height: 27px; width: auto; flex: none; }
/* The footer ground is pale, so the credit uses the logo with dark lettering
 * (owner, 2026-10-01); the template defaults to the white-lettered one. */
.powered-by .mf-logo-light { display: inline; }
.powered-by .mf-logo-dark { display: none; }
/* row-gap separates the wrapped rows so adjacent links clear the WCAG 2.2
 * target-spacing minimum; the source wraps them with no gap at all. */
.footer-bar__legal { display: flex; flex-wrap: wrap; justify-content: flex-end; row-gap: var(--space-3xs); }
.footer-bar__legal li { display: flex; align-items: center; }
/* The separator trails its item rather than leading the next, so a wrapped
 * row never opens on a stray pipe. */
.footer-bar__legal li:not(:last-child)::after { content: "|"; margin: 0 var(--space-3xs); font-size: var(--step--1); font-weight: var(--weight-600); color: var(--ink); }
/* padding-block lifts the touch target to the 24px WCAG 2.2 minimum; the
 * negative margin keeps the bar the height the source renders it at. */
.footer-bar__legal a { display: inline-block; padding-block: var(--space-3xs); margin-block: calc(-1 * var(--space-3xs)); font-size: var(--step--1); font-weight: var(--weight-600); line-height: var(--leading-l); color: var(--ink); text-decoration: none; }
.footer-bar__legal a:hover, .footer-bar__legal a:focus-visible { color: var(--paper); }

/* ── Tablet (the source's 1024 breakpoint) ────────────────────────── */
@media (max-width: 64rem) {
    .site-header__inner { padding-block: var(--space-m); }
    /* Below 1025 the nav leaves the bar for the drawer, so the middle column
     * has nothing in it. Collapse to logo | actions and push the actions to
     * the right edge, keeping the booking button and the hamburger together
     * against the bar's inner padding rather than centred in a dead third. */
    .site-bar { grid-template-columns: auto 1fr; }
    /* The logo's left edge is the drawer rows' text edge: the list's 4 of
     * inset plus the row's 12, so the open drawer reads as one column. */
    .site-logo { padding-left: calc(var(--space-3xs) + var(--space-xs)); }
    .site-logo img { max-width: 173px; }
    .site-bar__actions { grid-column: 2; grid-row: 1; justify-content: flex-end; }
    .nav-toggle { display: flex; }
    /* The nav becomes a drawer under the bar. The source's own drawer is a
     * 76px-wide box hanging off the toggle; this one spans the bar. The row
     * is stated because auto-placement put the drawer in row 2 and then the
     * actions in row 3: the hamburger turned into a close button at the
     * BOTTOM of the open drawer, below the fold on a phone. */
    .primary-nav { display: none; grid-column: 1 / -1; grid-row: 2; justify-self: stretch; margin-top: var(--space-2xs); }
    .primary-nav.is-open { display: block; }
    .nav-list { flex-direction: column; padding: var(--space-3xs); background: var(--secondary); border-radius: var(--radius-m); }
    .nav-list li { position: static; }
    .sub-menu li + li { margin-top: 0; }
    /* Every row is a 44px target with its text centred on the chevron. */
    .nav-list > li > a, .sub-menu a {
        display: flex;
        align-items: center;
        min-height: 44px;
        padding: var(--space-3xs) var(--target-min) var(--space-3xs) var(--space-xs);   /* clear of the 44px sub-toggle */
        border-radius: var(--radius-menu);
        font-size: var(--step--1);
        line-height: var(--leading-m);
        color: var(--ink);
    }
    .nav-list > li > a:hover, .nav-list > li > a:focus-visible { transform: none; }
    .nav-list > li > a.active, .nav-list a:hover, .nav-list a:focus-visible { background: var(--brand-ink); color: var(--paper); }
    .nav-list .nav-caret { display: none; }
    .nav-list li.has-sub { position: relative; }   /* must outrank .nav-list li { position: static } above, or the toggle escapes to the viewport corner */
    .sub-toggle {
        display: flex;
        position: absolute;
        top: 0;       /* the row is 44 high, so this centres on it; 50% would centre on the open group */
        right: 0;
        width: var(--target-min);
        height: var(--target-min);
        padding: 0;
        border: 0;
        background: transparent;
        color: var(--ink);
        cursor: pointer;
    }
    .sub-toggle svg { width: 14px; height: 14px; margin: auto; fill: currentColor; transition: transform var(--duration-base) var(--ease-out); }
    .sub-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
    .sub-menu, .sub-menu .sub-menu { display: none; position: static; min-width: 0; padding: 0 0 0 var(--space-xs); border-radius: 0; box-shadow: none; opacity: 1; visibility: visible; transform: none; pointer-events: auto; transition: none; }
    .sub-menu::before { content: none; }
    .nav-list li:hover > .sub-menu, .nav-list li:focus-within > .sub-menu { display: none; }
    .nav-list li.is-open > .sub-menu { display: block; }
    .sub-menu li.is-open > a { background: transparent; color: var(--ink); }
    /* The mega menu's Health Services group is a desktop column only: in the
     * drawer its five links sit directly under Services, as live's do. */
    .nav-list .mega-group { display: contents; }
    .nav-list .mega-group > a, .nav-list .mega-group > .sub-toggle { display: none; }
    .nav-list .mega-group > .sub-menu { display: contents; }
    .nav-list > li.nav-cta { display: none; }

    .hero { padding-bottom: var(--space-band); }
    .band-info { padding-block: var(--space-band); }
    .band-values { padding-bottom: var(--space-band); }
    .hero__row { flex-wrap: wrap; }
    .hero__contact, .hero__card { flex-basis: 100%; }
    .hero__contact { padding-left: 0; }
    .hero__card { margin-top: 0; }
    /* The eyebrow is scoped to the homepage hero. As a bare `.eyebrow` this
     * centred EVERY eyebrow on the site below 1025, over titles and copy that
     * stay left-aligned (owner, 2026-10-01). An eyebrow follows its block. */
    .band-title--hero, .hero__copy, .hero .eyebrow { text-align: center; }
    .band-title--hero { max-width: 70%; margin-inline: auto; }
    .rule--hero { margin-inline: auto; }
    .hero__copy { max-width: 80%; margin-inline: auto; }
    .hero__actions { justify-content: center; }

    .info-grid { grid-template-columns: 1fr; }
    .hours-card { --hours-lift: calc(var(--space-2xl) + var(--space-s)); }   /* 100 */
    /* The source's hours card goes full-width here but keeps its text in the
     * original narrow column - 525 of 864 inner px - so the notes still wrap
     * as they do on the desktop card rather than running the full width. */
    .hours-list, .hours-card__notes { max-width: 60.8%; }
    .tile { grid-template-columns: 1fr 1fr; align-items: stretch; }
    .tile__box { display: flex; flex-direction: column; justify-content: center; padding: var(--space-card); text-align: center; }
    .tile__photo { height: 100%; aspect-ratio: auto; }
    .tile--offset { margin-block: 0; }

    .values-head { grid-template-columns: 1fr; text-align: center; }
    .values-head .band-title { max-width: 507px; margin-inline: auto; }
    .rule--values { margin-inline: auto; }
    .values-head__lede { max-width: 90%; margin-inline: auto; padding-top: 0; }
    /* One column, and equal rows: the source's rows are 1fr, so each photo cell
     * takes the height of the card pair beside it. */
    .values-row--a, .values-row--b, .values-row--c { grid-template-columns: minmax(0, 1fr); grid-auto-rows: 1fr; gap: var(--space-card); }
    .values-photo--team { order: 2; min-height: 19.375rem; background-position: center; }   /* the photo box: 230 over the button and its 40 inset */

    .booking { grid-template-columns: 1fr; padding-inline: var(--grid-gutter); }
    .booking__left { gap: var(--space-card); padding-right: 0; }
    .booking-card { min-height: 15.625rem; text-align: center; align-items: center; }
    .booking__photo { min-height: 23.4375rem; }
    .booking__steps { margin-top: calc(var(--space-xs) + var(--space-2xs)); }

    /* Below the desktop the source's footer container adds its own 50px
     * lead-in above the grid, and its paddings/gaps are fixed 50, not fluid. */
    .site-footer__inner { padding-top: var(--space-card); }
    .site-footer__grid { grid-template-columns: 1fr; gap: var(--space-card); padding-block: var(--space-card); }
    .site-footer__brand { padding-right: 0; }
    .site-footer__right { grid-template-columns: 1fr; }
    .footer-bar { grid-template-columns: 1fr; }
    .footer-bar__legal { justify-content: flex-start; }
}

/* ── Phone (the source's 767 breakpoint) ──────────────────────────── */
@media (max-width: 47.9375rem) {
    :root { --grid-gutter: calc(var(--space-s) + var(--space-3xs)); }   /* 20 on a 390 phone */
    .site-bar { grid-template-columns: 1.5fr 0.5fr; padding: var(--space-s); }
    .site-logo img { max-width: 176px; }
    .btn--cta-nav { display: none; }
    .site-bar__actions { justify-self: end; }
    /* The booking button leaves the bar on a phone and closes the drawer
     * instead, full width, so it is still one tap from the menu. */
    .nav-list > li.nav-cta { display: block; padding: var(--space-xs) var(--space-3xs) var(--space-3xs); }
    .nav-list > li.nav-cta > .btn { display: flex; min-height: 44px; padding: var(--space-2xs) var(--space-s); border-radius: var(--control-radius); color: var(--paper); }
    .nav-list > li.nav-cta > .btn:hover, .nav-list > li.nav-cta > .btn:focus-visible { background: var(--crimson); color: var(--paper); }

    .hero__contact { grid-template-columns: 1fr; gap: var(--space-s); padding: var(--space-s) var(--space-xs); }
    .pill { padding: var(--space-xs); border-radius: var(--radius-photo); gap: var(--space-2xs); }
    .pill--phone, .pill--fax { grid-column: 1; width: 100%; }
    .pill__icon { width: 15px; height: 15px; }
    .pill--address .pill__icon { width: 18px; height: 18px; }
    .hero__card { margin-top: calc(-1 * calc(var(--space-xs) + var(--space-2xs))); padding: var(--space-card); }
    .band-title--hero, .hero__copy { max-width: 100%; }
    .hero__actions { grid-template-columns: 1fr; justify-items: center; }
    .hero__badge { max-width: 211px; }

    .tile { grid-template-columns: 1fr; }
    .tile__box { padding: calc(var(--space-xs) + var(--space-2xs)); }
    .tile--services .tile__box { order: -1; }
    .tile__photo { height: auto; aspect-ratio: 267 / 180; }

    .values-pair { grid-template-columns: minmax(0, 1fr); }
    .values-photo--team { min-height: 36rem; }   /* 500 over the button and its inset */
    .hours-card { padding: var(--space-l); }   /* flat 40 on the source's phone card */
    /* The narrow-column constraint is a tablet-only trait; the phone card is
     * already narrow, so the text fills it as it does on the desktop card. */
    .hours-list, .hours-card__notes { max-width: none; }

    .booking-card { min-height: 0; }
    .booking__photo { min-height: 21.875rem; }
    .step { padding: var(--space-l); }

}

/* ── Scroll entrance (one-way) ────────────────────────────────────── */
/* Elements opt in with data-reveal="up|down|left|right|fade" and an optional
 * data-reveal-stagger="<ms>"; partials/scripts.html reveals them once, the
 * first time they enter the viewport, and never re-hides them. Short travel
 * (26px / 18px) on purpose. Hidden only under .js so a failed script leaves
 * the page visible. */
.js [data-reveal] {
    opacity: 0;
    transition: opacity 760ms cubic-bezier(0.22, 0.61, 0.36, 1), transform 760ms cubic-bezier(0.22, 0.61, 0.36, 1);
    transition-delay: var(--reveal-delay, 0ms);
    will-change: opacity, transform;
}
.js [data-reveal="up"]    { transform: translateY(26px); }
.js [data-reveal="down"]  { transform: translateY(-26px); }
.js [data-reveal="left"]  { transform: translateX(-18px); }
.js [data-reveal="right"] { transform: translateX(18px); }
.js [data-reveal="fade"]  { transform: none; }
.js [data-reveal][data-revealed] { opacity: 1; transform: none; }
.js [data-reveal][data-reveal-done] { will-change: auto; transition: none; }
@media (prefers-reduced-motion: reduce) {
    .js [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* ── Accessibility floor ──────────────────────────────────────────── */
/* Links sit in the surrounding ink at rest and turn crimson on hover and
 * focus (owner, 2026-09-30: "red only on hover"). The underline stays at
 * rest so a link is findable without hovering — live distinguishes its
 * links by colour alone, which fails WCAG 1.4.1. */
/* Live colours every link in the page body crimson with no underline, and
 * that is kept (owner, 2026-10-01: "red ones stay red without underline").
 * The underline arrives on hover and focus. The few links live leaves in
 * the surrounding ink — on the dark and crimson grounds — keep an underline
 * at rest instead, since colour alone cannot mark them there. */
main a:not([class]) { color: var(--crimson); text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 2px; transition: color var(--duration-fast) var(--ease-out), text-decoration-color var(--duration-fast) var(--ease-out); }
main a:not([class]):hover, main a:not([class]):focus-visible { text-decoration-color: currentColor; }
main .whychoose a, main .policies-card--crimson a, main .hours-card a, main .svc2-alert a { color: inherit; text-decoration-color: color-mix(in oklch, currentColor 55%, transparent); }
main .whychoose a:hover, main .policies-card--crimson a:hover, main .hours-card a:hover, main .svc2-alert a:hover { text-decoration-color: currentColor; }

/* ── Contact page ─────────────────────────────────────────────────── */
/* Band 1: three columns on the source (379 + 417 + 455, gap 50) — the
 * email-caution copy, the practice details, and the enquiry form card. */
.band-contact { background: var(--grad-paper-cream); padding-block: var(--space-band); }
.contact-intro {
    display: grid;
    grid-template-columns: minmax(0, 379fr) minmax(0, 417fr) minmax(0, 455fr);
    gap: var(--space-card);
    align-items: start;
}
.contact-intro__copy .eyebrow { color: var(--ink); }
.contact-intro__copy .band-title { margin-block: var(--space-3xs) var(--space-s); }
.contact-intro__copy p { margin: 0 0 calc(var(--space-xs) + var(--space-2xs)); line-height: var(--leading-l); color: var(--pill-ink); }
.contact-intro__lede { font-size: var(--step-1); font-weight: var(--weight-700); color: var(--crimson) !important; }
.contact-intro__strong { color: var(--pill-ink); }

.contact-intro__photo { align-self: start; aspect-ratio: 417 / 620; border-radius: var(--radius-card); background: url('/assets/images/contact-port-sorell-medical-centre.e046414997.webp') center top / cover no-repeat; }

/* The form card carries the source's teal ground; its fields are barely-tinted
 * wells (--field-tint at 14%) with no border, labels in white above. The field
 * look itself is the --field-* tokens, re-set here for the dark ground. */
.contact-form-card {
    padding: var(--space-card); border-radius: var(--radius-card); background: var(--grad-form);
    --field-bg: color-mix(in srgb, var(--field-tint) 14%, transparent);
    --field-ink: var(--paper);
}
.contact-form { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-s); }
.form-field { display: flex; flex-direction: column; gap: var(--space-3xs); min-width: 0; }
.form-field--full { grid-column: 1 / -1; }
.form-field label { font-size: var(--step-0); font-weight: var(--weight-400); color: var(--paper); }
.form-field .req { margin-left: var(--space-3xs); color: var(--accent-tint); }
.contact-form__submit { grid-column: 1 / -1; justify-self: start; }   /* the standard .btn--cta pill: no radius or padding of its own */
/* The card and its note share a column, so the note sits 22px under the
 * card (the source's gap) rather than at the foot of the tallest column. */
.contact-form-col { display: flex; flex-direction: column; gap: var(--space-s); }
.contact-form__note { margin: 0; font-size: var(--step-0); line-height: var(--leading-l); color: var(--pill-ink); }
.contact-form__note a { color: var(--crimson); }

/* On the desktop the three columns stand as one block (owner, 2026-10-01):
 * the row stretches to the copy, the photograph fills its track, and the
 * form card grows to the note with the message box taking the extra room.
 * Below the fold the columns stack and keep their own heights. */
@media (min-width: 64.0625rem) {
    .contact-intro { align-items: stretch; }
    .contact-intro__photo { align-self: stretch; aspect-ratio: auto; min-height: 20rem; }
    .contact-form-card { flex: 1; display: flex; }
    .contact-form { flex: 1; grid-template-rows: auto auto 1fr auto auto; }
    .form-field--full textarea { flex: 1; }
}

/* Band 2: the FAQ accordion beside the location map, two equal columns. */
.band-faq { background: var(--grad-cream-accent); padding-block: var(--space-band); border-top: var(--border-thin) solid var(--accent-tint); }
.faq { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-card); align-items: start; }
.faq__lede { margin: var(--space-2xs) 0 var(--space-m); font-size: var(--step-1); line-height: var(--leading-l); color: var(--ink); }
.faq__list { display: flex; flex-direction: column; gap: var(--space-2xs); }
.faq__item { border: var(--border-thin) solid var(--faq-rule); border-radius: var(--radius-card); background: var(--secondary); }
.faq__q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-s);
    padding: var(--space-s);
    font-size: var(--step-0);
    font-weight: var(--weight-600);
    color: var(--ink);
    cursor: pointer;
    list-style: none;
}
.faq__toggle { position: relative; flex: none; width: 0.9em; height: 0.9em; }
.faq__toggle::before, .faq__toggle::after { content: ""; position: absolute; inset: 50% auto auto 0; width: 100%; height: 2px; margin-top: -1px; background: var(--ink); }
.faq__toggle::after { transform: rotate(90deg); transition: transform var(--duration-slow) var(--ease-out); }
.faq__item[open] .faq__toggle::after { transform: rotate(0deg); }
.faq__q::-webkit-details-marker { display: none; }
/* The open/close motion is driven from scripts.html: the item's height is
 * animated between its summary-only and full heights, and the answer fades
 * in a beat behind it. Height is a layout property, but an accordion has no
 * transform-only equivalent, and it is one short run on a small box rather
 * than a continuous animation. Reduced motion skips it entirely. */
.faq__item.is-animating { overflow: hidden; }
.faq__a { padding: 0 var(--space-s) var(--space-s); }
.faq__a p { margin: 0 0 var(--space-2xs); line-height: var(--leading-l); color: var(--ink); }
.faq__a p:last-child { margin-bottom: 0; }
.faq__map { overflow: hidden; border-radius: var(--radius-photo); aspect-ratio: 573 / 420; }
.faq__map iframe { display: block; width: 100%; height: 100%; border: 0; }

@media (max-width: 64rem) {
    /* The source drops to one column here; the form leads, since it is what
     * the page is for, and the caution copy reads beneath it. */
    .contact-intro { grid-template-columns: minmax(0, 1fr); }
    .contact-form-col { order: -1; }
    .faq { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 47.9375rem) {
    .contact-form { grid-template-columns: minmax(0, 1fr); }
    .contact-form__submit { justify-self: stretch; text-align: center; }
}

/* ── Doctors and Staff ────────────────────────────────────────────── */
/* Band 1: two columns on the source (810 + 590) — the doctors photograph
 * beside the intro copy, on the same white-to-accent wash as every hero. */
/* Live pads this band 40 above and 80 below, sets the photograph at 810 from
 * 50 inside the shell and the 510 card 60 over it, ending 40 short of the
 * shell's right edge: an inner row of 1260. Measured 2026-09-30. */
.band-team-intro { background: var(--grad-hero); padding-block: var(--space-l) var(--space-band); }
.team-intro { display: grid; grid-template-columns: minmax(0, 810fr) minmax(0, 450fr); gap: 0; align-items: start; padding-inline: var(--space-xl) var(--space-card); }
.team-intro__photo {
    min-height: 45.5rem;          /* the source's 728 */
    border-radius: var(--radius-card);
    background: url('/assets/images/port-sorell-medical-centre-team.47664f90b3.webp') center / cover no-repeat;
}
.team-intro__card {
    position: relative;
    z-index: var(--layer-raised);
    margin: var(--space-l) 0 0 calc(-1 * var(--space-xl));  /* 40 down, 60 over the photograph */
    padding: var(--space-card);
    border-radius: var(--radius-card);
    background: var(--paper);
}
/* Live's card is 648 tall: 16 under the eyebrow, 29 under the title, 14.85
 * between paragraphs, the button and the badge on one row 28 apart. Ours
 * had wrapped the badge under the button and stood 738. Measured 2026-10-01. */
.team-intro__card .band-title { max-width: 19.8125rem; margin-block: var(--space-xs) var(--space-m); }   /* live's 317: "Your Local / Healthcare Heroes" */
.team-intro__card p:not(.eyebrow) { margin: 0 0 var(--space-xs); line-height: var(--leading-l); color: var(--ink-black); }
/* Qualified with the card: `.team-intro__card p:not(.eyebrow)` outranks a bare
 * class and had zeroed this margin, leaving the row 20 high of live's. */
/* The button and the badge share ONE row. Live's 187 + 28 + 195 is exactly
 * the card's 410, so with wrapping allowed a fraction of a pixel in how a
 * browser sets the button's label dropped the badge to a second line
 * (owner, 2026-10-01). The row cannot wrap; the button keeps its size, the
 * badge sits on the card's inner edge and is the one that gives if the card
 * narrows. Phones stack them, as the About card does. */
.team-intro__card p.team-intro__actions { display: flex; flex-wrap: nowrap; align-items: center; justify-content: space-between; gap: var(--space-s); margin: var(--space-group) 0 0; }
.team-intro__actions .btn { flex: none; padding-block: var(--space-xs); }   /* live's 52 */
.team-intro__badge { flex: 0 1 195px; min-width: 0; width: 195px; max-width: 100%; height: auto; }
/* On a narrow desktop the card is too slim for both: the badge would shrink
 * below a legible 150, so the pair stacks there instead. */
@media (min-width: 64.0625rem) and (max-width: 77.5rem) {
    .team-intro__card p.team-intro__actions { flex-wrap: wrap; justify-content: flex-start; }
    .team-intro__badge { flex: none; }
}

/* Band 2: the roster itself. */
.band-team { background: var(--grad-info); padding-bottom: var(--space-band); border-top: var(--border-thin) solid var(--primary); }
.band-team > .u-container { --grid-max-width: var(--shell-wide); }   /* live's roster runs the 1350 shell, portraits from x=45 */   /* live's hairline, in the kit's primary here */
/* Live: the hairline, 130 of air, then the heading pair inset 10 inside the
 * shell (eyebrow at x=55, copy 645 wide from x=740), 70 above the roster. */
.team-head { display: grid; grid-template-columns: minmax(0, 635fr) minmax(0, 645fr); gap: var(--space-card); align-items: start; padding-block: calc(var(--space-3xl) + var(--space-2xs)) var(--space-panel); padding-inline: calc(var(--grid-gutter) + var(--space-2xs)); }   /* 130 / 70 */
.team-head .band-title { margin-top: var(--space-3xs); }
.team-head__lede { margin: 0; line-height: var(--leading-l); color: var(--ink-black); }
/* The roster's two groups, doctors then staff, each under its own heading (#288). */
.team-group { margin: 0 0 var(--space-m); font-family: var(--font-heading); font-size: var(--step-3); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--brand-ink); }
.team-grid + .team-group { margin-top: var(--space-panel); }
.team-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-group); }   /* live's 35 between rows */
.person { display: grid; grid-template-columns: 153px minmax(0, 1fr); gap: var(--space-s); align-items: start; }   /* 20: text from x=218 */
.person__photo { width: 153px; height: 153px; border-radius: var(--radius-card); object-fit: cover; }
.person__role { margin: 0; font-size: var(--step-0); font-weight: var(--weight-600); color: var(--crimson); }
.person__name { margin: 0; font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--brand-ink); }
/* quals and bio come from Rails as plain text: keep its line breaks. */
.person__quals { margin: var(--space-3xs) 0 0; font-weight: var(--weight-400); color: var(--pill-ink); white-space: pre-line; }
.person__bio { margin: var(--space-2xs) 0 0; line-height: var(--leading-l); color: var(--ink-black); white-space: pre-line; }

/* Band 3: the closing card over the practice exterior. */
.band-team-cta {
    padding-block: var(--space-2xl-3xl);        /* 120: (804 - 564) / 2 on the source; 64 on a phone */
    background: var(--photo-ground) url('/assets/images/practice-building-wide.f325e54d2d.webp') center / cover no-repeat;
}
.team-cta { display: grid; grid-template-columns: 1fr 1fr; min-height: 35.25rem; margin-inline: var(--space-m); }
.team-cta__panel {
    display: flex; flex-direction: column; justify-content: center;
    padding: var(--space-card);
    border-radius: var(--radius-card) 0 0 var(--radius-card);
    background: var(--grad-cream-accent);
}
.team-cta__panel .band-title { margin-block: var(--space-2xs) var(--space-s); }
.team-cta__panel p:not(.eyebrow):not(.team-cta__action) { margin: 0 0 var(--space-s); line-height: var(--leading-l); color: var(--ink); }
.team-cta__action { margin-top: var(--space-2xs); }
.team-cta__photo { border-radius: 0 var(--radius-card) var(--radius-card) 0; background: url('/assets/images/doctors-outside-port-sorell-medical-centre.a012d5d455.webp') center / cover no-repeat; }
.team-cta__action { margin: 0; }

@media (max-width: 64rem) {
    .team-intro, .team-head { grid-template-columns: minmax(0, 1fr); }
    .team-intro { padding-inline: var(--grid-gutter); }
    .team-intro__photo { min-height: 0; aspect-ratio: 944 / 560; }
    .team-intro__card { margin: 0; }
    .team-cta { grid-template-columns: minmax(0, 1fr); margin-inline: 0; }
    .team-cta__panel { border-radius: var(--radius-card) var(--radius-card) 0 0; }
    .team-cta__photo { min-height: 18rem; border-radius: 0 0 var(--radius-card) var(--radius-card); }
}

@media (max-width: 47.9375rem) {
    /* The portrait stacks above the detail rather than shrinking below the
     * size at which a face is still readable. */
    .person { grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center; }
    .team-group { text-align: center; }
    .team-intro__actions { justify-content: center; }
}

/* ── Services ─────────────────────────────────────────────────────── */
/* Re-measured off live at 1440 on 2026-10-01 (owner: "no images should be
 * overlapping each other"). The earlier build put the flank tiles 137px UP
 * the hero photograph and the wide tile 130px under the card. On live the
 * only thing that overlaps a photograph is the white card:
 *
 *   photo    45,171  1350x509        (the wide 1350 shell, flush under the header)
 *   card     395,481  650x564        rides 199 up the photo, padded 70
 *   flanks   45 / 1073, y714  323x653   34 BELOW the photo's bottom edge
 *   under    398,1064  645x303       19 below the card, ending with the flanks
 */
.band-services-intro { position: relative; background: var(--grad-hero); padding-block: 0; }   /* live sets the hero photograph straight under the header */
.band-services-intro > .u-container { --grid-max-width: var(--shell-wide); position: relative; z-index: var(--layer-base); }
.services-hero { display: block; width: 100%; height: auto; aspect-ratio: 1350 / 509; object-fit: cover; border-radius: var(--radius-card); }
.services-composition {
    position: relative;
    display: grid;
    grid-template-columns: 323fr 645fr 323fr;
    grid-template-rows: auto minmax(20.125rem, 1fr);   /* the wide tile is 303, under its 19 of clearance */
    column-gap: var(--space-m);
}
.services-intro {
    grid-column: 2; grid-row: 1;
    position: relative; z-index: var(--layer-raised);
    margin-top: calc(-1 * (var(--space-3xl) + var(--space-2xl)));      /* the card rides 200px up into the photograph (live 199) */
    padding: var(--space-panel);
    border-radius: var(--radius-card);
    background: var(--paper);
    text-align: center;
}
.services-intro .eyebrow { margin: 0; }
.service-card--flank { grid-row: 1 / 3; margin-top: var(--space-group); }   /* 34 clear of the photograph */
.service-card--flank-l { grid-column: 1; }
.service-card--flank-r { grid-column: 3; }
.service-card--under { grid-column: 2; grid-row: 2; margin-top: var(--space-s); }   /* 19 clear of the card */
/* the strip: the band's ground for the tiles' last 203px */
.band-services-intro::after {
    content: "";
    position: absolute; left: 0; right: 0; bottom: 0;
    height: 12.6875rem;
    background: color-mix(in oklab, var(--accent-tint) 95%, transparent);
}
.services-intro .band-title { margin-block: var(--space-2xs) var(--space-s); font-weight: var(--weight-700); line-height: var(--leading-m); color: var(--brand-ink); }
.services-intro p { margin: 0 0 var(--space-xs); font-weight: var(--weight-600); line-height: var(--leading-l); color: var(--ink); }
.services-intro__action { margin: var(--space-group) 0 0; }   /* live: 49 from the copy to its 226x55 button */
.services-intro { min-height: 35.25rem; }               /* live's 564, so the tiles beneath land on live's lines */

/* The tiles: a photo ground with a white label card pinned to the bottom.
 * Four of the thirteen run double height on the source, which the grid
 * reproduces with an explicit row span rather than a masonry library.
 *
 * The grids fill by COLUMN, as live's do: a tall tile owns its column and
 * the short ones pair up beneath each other (Early Pregnancy over Mental
 * Health, Diabetes over Skin Checks). Filling by row put Diabetes under
 * Early Pregnancy and the tall My Health Record tile in the wrong column. */
.band-services { padding-block: var(--space-m); }             /* 30 / 30 */
.band-services--a { background: var(--grad-info); }
.band-services--b { background: var(--grad-cream-accent); padding-block: var(--space-s) var(--space-band); }   /* 20 / 80 */
.band-services > .u-container { --grid-max-width: var(--shell-wide); }
.services-grid {
    --tile-row: 143px;            /* short tile = 2 rows + gap = 316 */
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: repeat(4, var(--tile-row));
    grid-auto-flow: column;
    gap: var(--space-m);
}
.services-grid--b { --tile-row: 157.5px; }   /* 345 short, 721 tall */
.service-card {
    --card-inset: var(--space-m);   /* live pads the tile 30 around its label */
    --label-width: 80%;           /* 296 of the 370 inside a 430 tile */
    position: relative;
    display: flex;
    align-items: flex-end;
    grid-row: span 2;
    padding: var(--card-inset);
    border-radius: var(--radius-card);
    background: var(--card-photo) center / cover no-repeat;
    text-decoration: none;
    overflow: hidden;
}
/* The three hero tiles pad 20 at the sides and 50 beneath, and their labels
 * run the tile's width (three quarters of it on the wide one). */
.service-card--flank, .service-card--under { padding: var(--space-s) var(--space-s) var(--space-card); --label-width: 100%; }
.service-card--under { --label-width: 75%; background-position: center bottom; }
.service-card--tall { grid-row: span 4; }
.service-card__label {
    position: relative;
    display: block;
    width: var(--label-width);
    padding: var(--space-xs) var(--space-m) var(--space-s);
    border-radius: var(--radius-photo);
    background: var(--paper);
    transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
}
.service-card:hover .service-card__label, .service-card:focus-visible .service-card__label { transform: translateY(-4px); }
.service-card:hover .service-card__label { box-shadow: 0 10px 20px -10px oklch(0 0 0 / 0.35); }   /* not on focus: the ring is the focus cue */
.service-card__title {
    display: block;
    font-family: var(--font-heading);
    font-size: var(--step-2);
    font-weight: var(--weight-700);
    line-height: var(--leading-m2);
    color: var(--brand-ink);
}
/* Live's LEARN MORE is the body size in crimson at 500, with no arrow. */
.service-card__more {
    display: block;
    margin-top: var(--space-3xs);
    font-size: var(--step-0);
    font-weight: var(--weight-500);
    color: var(--crimson);
}

@media (max-width: 64rem) {
    .services-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: none; grid-auto-flow: row; grid-auto-rows: var(--tile-row); }
    .services-composition { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; margin-top: var(--space-m); gap: var(--space-m); }
    .services-intro, .service-card--flank, .service-card--under { grid-column: auto; grid-row: auto; margin-top: 0; margin-inline: 0; min-height: 18rem; }
    .services-intro { padding: var(--space-l); min-height: 0; }
    .service-card--flank, .service-card--under { padding: var(--card-inset); --label-width: 80%; }
    .band-services-intro { padding-bottom: var(--space-m); }
    .band-services-intro::after { content: none; }
}

@media (max-width: 47.9375rem) {
    /* One column, and every tile the same height — a masonry rhythm needs at
     * least two columns to read as one, and uneven single-column tiles just
     * look like a mistake. */
    .services-grid { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; }
    .service-card, .service-card--tall { grid-row: auto; min-height: 15rem; --card-inset: var(--space-s); --label-width: 100%; }
}

/* ── The Practice ─────────────────────────────────────────────────── */
/* Live: no padding above — the photograph sits straight under the header —
 * and the row runs the full 1350 shell: card 562 from x=50 riding 120 over
 * the 898 photograph from x=492, the card centred on the photo's height.
 * Measured 2026-09-30; the owner found the old 80/80 band airy. */
.band-about-intro { background: var(--grad-hero); padding-block: 0 var(--space-card); }   /* live: 51 from the photo to the line */
.band-about-intro > .u-container { --grid-max-width: var(--shell-wide); }
/* THE HAIRLINES ON THIS PAGE ARE BAND BORDERS, NOT <hr>s (2026-10-01). Live
 * draws each one as the next section's own top border, so it runs the full
 * viewport. As `.band-divider` elements inside the shell they stopped at
 * 1350, and the first one's bottom margin fell out of a band with no padding
 * and showed as an 80px white gap under the hero. */
/* The source's two blocks overlap by 120px rather than sitting in separate
 * tracks: card 562 wide from x50, photo 898 from x492. A single row with the
 * card overlapping the photo's track reproduces that; the negative margin on
 * the card is what creates the 120. */
.about-intro { display: grid; grid-template-columns: minmax(0, 447fr) minmax(0, 898fr); gap: 0; }
.about-intro__lede { margin: 0; font-size: var(--step-1); line-height: var(--leading-l); color: var(--ink-black); }
.about-intro__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-m); margin-top: var(--space-l); }
.about-intro__badge { width: 198px; max-width: 100%; height: auto; }
.about-intro__photo { width: 100%; height: auto; border-radius: var(--radius-card); }

/* The timeline: four milestones across, each a year, a title and its text. */
.band-journey { background: var(--grad-info); padding-top: var(--space-band); padding-bottom: var(--space-band); border-top: var(--border-thin) solid var(--primary); }   /* live: the line, then 81 to the eyebrow */
.band-journey > .u-container { --grid-max-width: var(--shell-wide); }
.journey-head { max-width: 46rem; margin-inline: auto; text-align: center; }
.journey-head .band-title { margin-top: var(--space-3xs); }
.eyebrow--ink { color: var(--ink); }
/* Space above and below the whole timeline, so the rule is not crowded by
 * the heading above it or the 2024 block below. */
/* Live: four 338 columns with no gap, everything centred, 40 of inset each
 * side, the rule 74 below the year's top and the title 117. Measured
 * 2026-09-30; ours had been left-aligned in gapped columns. */
.timeline { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; margin: var(--space-panel) 0 calc(var(--space-3xl) + var(--space-m)); padding: 0; list-style: none; }   /* 150 under the last milestone (live 147) */
/* The heading block follows a divider, so it needs no extra lead-in of its
 * own - the divider's margin is already the gap. */
.band-journey > .u-container:first-child { padding-top: 0; }
.journey-head { margin-top: 0; }
.timeline__item { position: relative; padding-top: var(--space-l); }
/* The node on the rule, which is what makes four columns read as a sequence. */
.timeline__item::before {
    position: absolute;
    top: -0.5rem;
    left: 0;
    width: 0.875rem;
    height: 0.875rem;
    border-radius: var(--radius-round);
    background: var(--crimson);
}
.timeline__year { font-family: var(--font-heading); font-size: var(--step-3); font-weight: var(--weight-700); color: var(--crimson); }
.timeline__title { margin: 0 0 var(--space-s); font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--ink); }
.timeline__text { margin: 0; line-height: var(--leading-l); color: var(--ink); }

/* Live: photographs 602 wide (two 291 squares on a 20 gap, the wide one
 * below), a 25 gap, then the 723 card padded 50. Measured 2026-09-30. */
.journey-2024 { display: grid; grid-template-columns: minmax(0, 602fr) minmax(0, 723fr); gap: calc(var(--space-xs) + var(--space-2xs)); align-items: center; margin-top: 0; }
.journey-2024__photos { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-s); }
.journey-2024__copy.bordered-column { padding: var(--space-card); }
.journey-2024__copy .rule--grey { width: 17.875rem; max-width: 100%; margin: var(--space-m) 0 var(--space-card); border-top-color: var(--secondary); opacity: 1; }
.journey-2024__copy .tick-list { gap: 0; }
.journey-2024__copy .tick-list li { line-height: var(--leading-l); }
.journey-2024__photos img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-card); }
.journey-2024__wide { grid-column: 1 / -1; }
.journey-2024__copy p:not(.eyebrow) { margin: 0 0 var(--space-s); line-height: var(--leading-l); color: var(--ink); }
/* The prose link only - not the button, whose own white-on-crimson would
 * otherwise be overridden into crimson-on-crimson and vanish. */
.journey-2024__copy p > a:not(.btn), .journey-2024__copy a:not(.btn) { color: var(--crimson); }
.journey-2024__action { margin-top: var(--space-group); }   /* live: 54 from the paragraph above */

/* A tick list, the source's own check-icon bullets. */
.tick-list { margin: 0 0 var(--space-s); padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--space-2xs); }
.tick-list li { position: relative; padding-left: var(--space-m); line-height: var(--leading-l); color: var(--ink); }
.tick-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.45em;
    width: 0.75rem;
    height: 0.4rem;
    border-left: var(--border-medium) solid var(--crimson);
    border-bottom: var(--border-medium) solid var(--crimson);
    transform: rotate(-45deg);
}

.band-community { padding-block: var(--space-band); border-top: var(--border-thin) solid var(--secondary); }
/* Live: three 427 columns on a 30 gap across the 1350 shell, the card padded 50. */
.band-community > .u-container { --grid-max-width: var(--shell-wide); }
.community { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-m); align-items: start; }
.community__copy.bordered-column { padding: var(--space-card); }
.community__copy .band-title { margin-block: var(--space-2xs) var(--space-s); }
.community__copy p:not(.eyebrow), .community__facts p:not(.eyebrow) { margin: 0 0 var(--space-s); line-height: var(--leading-l); color: var(--ink); }
.band-title--small { font-size: var(--step-3); }
.community__photos { display: grid; gap: var(--space-m); }
.community__photos img { width: 100%; height: auto; border-radius: var(--radius-card); }

.band-building {
    min-height: 43.75rem;         /* the source's 700px; the mission card takes 125 of it */
    background: url('/assets/images/practice-building-wide.f325e54d2d.webp') center / cover no-repeat;
}

.band-mission { padding-block: var(--space-band); }
.mission-head { max-width: 40rem; margin-inline: auto; }
.mission-grid { margin-top: var(--space-panel); }

/* The nurses photo takes the third values row on this page (the homepage
 * uses the carport there). */
.values-photo--nurses { background-image: url('/assets/images/practice-nurses.d5eab43d81.webp'); }

.band-commitment { background: var(--grad-booking); padding-block: var(--space-band); }
/* room for the card's overhang below the photograph */
/* Live: the divider, 41 down to the row, the photograph 750 and the card
 * 500 on a 50 gap, both 739 tall, the panel overhanging 123 and the band
 * closing 120 under it. Measured 2026-09-30. */
.band-commitment { padding-top: var(--space-l); padding-bottom: calc(var(--space-3xl) + var(--space-3xl)); border-top: var(--border-thin) solid var(--accent-tint); }
.band-commitment > .u-container { --grid-max-width: var(--shell-wide); }
.commitment { display: grid; grid-template-columns: minmax(0, 750fr) minmax(0, 500fr); gap: var(--space-column); }   /* live: photo 45-795, card 895-1395 */
.commitment__photo {
    display: flex;
    min-height: 46.1875rem;       /* the source's 739 */
    border-radius: var(--radius-photo);
    background: url('/assets/images/practice-why-choose.52f31e088e.webp') center / cover no-repeat;
}
.commitment__copy .band-title { margin-block: var(--space-s) var(--space-s); max-width: 20.625rem; }
.commitment__copy > p:last-child { margin-bottom: 0; }   /* the button's paragraph: live's card closes 51 under the button */   /* live wraps it at 330: three lines */
.commitment__copy.bordered-column { padding: var(--space-card) 0 var(--space-card) var(--space-card); }   /* live: no right padding */
.rule--commit { width: 11.5rem; margin: 0 0 var(--space-group); }
.commitment__list { margin: 0 0 var(--space-group); padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--space-s); }
.commitment__list li { position: relative; font-size: var(--step-1); color: var(--ink); }
.commitment__list li::before {
    position: absolute;
    left: 0;
    top: 0.5em;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: var(--radius-round);
    background: var(--crimson);
}

@media (max-width: 64rem) {
    .about-intro { grid-template-columns: minmax(0, 1fr); }
    .timeline { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .journey-2024, .community, .commitment { grid-template-columns: minmax(0, 1fr); }
    .band-building { min-height: 28rem; }
    .commitment__photo { min-height: 22rem; }
}

@media (max-width: 47.9375rem) {
    .timeline { grid-template-columns: minmax(0, 1fr); }
    .journey-2024__photos { grid-template-columns: minmax(0, 1fr); }
    .about-intro__actions { justify-content: center; }
}

/* ── Recurring devices ────────────────────────────────────────────────
 * Four patterns the source uses across every page, defined once here so a
 * new page picks them up rather than reinventing them:
 *   .band-divider    a hairline closing or opening a band
 *   .rule--grey      the short divider that sits under a section title
 *   .bordered-column a crimson-outlined column (the source's 1px #C14D36, r15)
 *   .overlap         a block riding up into the band above it
 * ------------------------------------------------------------------- */
/* Space on both sides: a divider hard against the content above or below it
 * reads as an underline, not a separator. */
/* A divider that OPENS a section is the first thing in it, so the section's
 * own top padding already sits above the line and the preceding section's
 * bottom padding sits above that. Left alone the gap above ends up two or
 * three times the gap below. Pulling the divider up by the section's top
 * padding puts the line in the middle of the seam, with the band's spacing
 * either side of it. */
.band-divider {
    height: 0;
    margin-block: var(--space-band);
    border: 0;
    border-top: var(--border-thin) solid var(--secondary);
}
:is(section) > .u-container:first-child > .band-divider:only-child,
:is(section) > .u-container:first-child .band-divider {
    margin-top: calc(-1 * var(--space-band));
}
/* ...and one that CLOSES a band is the last thing in it, so the band's own
 * bottom padding is already the space below the line. */
:is(section) > .u-container:last-child > .band-divider:only-child,
:is(section) > .u-container:last-child .band-divider {
    margin-bottom: 0;
}

.rule--grey { width: 12.5rem; height: 0; margin-block: var(--space-s); border: 0; border-inline: 0; border-top: var(--border-thin) solid var(--brand-ink); opacity: 0.4; }
.rule--centred { margin-inline: auto; }

.bordered-column {
    padding: var(--space-l);
    border: var(--border-thin) solid var(--crimson);
    border-radius: var(--radius-card);
}

/* A block that rides up into the band above. The preceding band pads itself
 * by the same token, so the depth is set in exactly one place.
 * RULE: the .overlap block carries no full-bleed background. Its raised
 * child is the thing that overlaps; a ground on the block itself just hides
 * the band it rides into (see .band-mission for the shape that works). */
:root { --overlap-depth: calc(var(--space-3xl) + var(--space-3xs)); }   /* 126 (live's 125), the source's mission-card ride */
.overlap { position: relative; z-index: var(--layer-raised); margin-top: calc(-1 * var(--overlap-depth)); }
:is(section):has(+ .overlap) { padding-bottom: calc(var(--overlap-depth) + var(--space-xl)); }

/* ── The Practice: revisions from the owner's review ──────────────── */
/* (1) The hero copy is a white card riding 120px over the photograph, the
 * way the source lays it out — not a bare column beside it. */
.about-intro { align-items: center; }
.about-intro__card {
    position: relative;
    z-index: var(--layer-raised);
    margin: 0 calc(-1 * var(--space-3xl)) 0 var(--space-3xs);   /* 5 in from the shell, 120 over the photograph: a 562 card in a 447 track */
    padding: var(--space-card);         /* live's 50 all round; the 54 down is the card centred on a 524 photo */
    border-radius: var(--radius-card);
    background: var(--paper);
}
.about-intro__card .band-title { margin-block: var(--space-xs) var(--space-m); font-size: var(--step-7); line-height: var(--leading-s1); }   /* live's 41.25 on 49.5, 16 under the eyebrow and 29 over the lede */
.about-intro__card .about-intro__actions { justify-content: space-between; margin: var(--space-group) 0 0; }   /* the badge ends on the card's inner edge */
.about-intro__actions .btn { padding-block: var(--space-xs); font-weight: var(--weight-800); }   /* live's 187x52 */
.about-intro__photo { position: relative; }

/* (3) The timeline connects: one rule across the row, a node per milestone,
 * and the year sits above the rule rather than below it. */
.timeline { position: relative; }
.timeline__item { padding: 0 var(--space-l); border-top: 0; text-align: center; }
.timeline__item::before { content: none; }
/* the connecting rule, drawn once behind the whole row */
.timeline::before {
    content: "";
    position: absolute;
    top: 4.625rem;
    left: 0;
    right: 0;
    border-top: var(--border-thin) solid color-mix(in srgb, var(--ink) 22%, transparent);
}
.timeline__year { position: static; margin: 0 0 calc(var(--space-2xl) + var(--space-3xs)); }   /* 86 under the year: the rule sits 43 in, the title 43 past it */
.timeline__node {
    position: absolute;
    top: 4.125rem;
    left: 50%;
    margin-left: calc(-1 * var(--space-2xs));
    width: 1rem;                  /* the source's 16px */
    height: 1rem;
    border-radius: var(--radius-round);
    background: var(--primary);   /* the practice green, not the button crimson */
}

/* (4) The 2024 column is bordered, its eyebrow crimson, its title present. */
.journey-2024__copy .eyebrow { margin: 0; font-size: var(--step-3); }
.journey-2024__copy .band-title { margin-block: var(--space-3xs) 0; font-size: var(--step-5); font-weight: var(--weight-700); }   /* live's 33 / 700 */

/* (5) Growing together: the caption under the team photo, and column 3's
 * photograph above its copy. */
.community__caption { margin: 0; line-height: var(--leading-l); color: var(--ink); }
.community__facts-photo { width: 100%; height: auto; margin-bottom: var(--space-m); border-radius: var(--radius-photo); }
.band-community { background: var(--grad-values); }

/* (6) The mission is one floating white card offset up over the photo band,
 * with the source's numbered circles. */
/* The source's band here is cream, and the card riding up into the photo
 * above it is accent-tint - not white, which read as a floating panel from
 * a different site. */
/* An .overlap block must not paint a full-bleed ground of its own: the
 * negative margin puts the block over the band above, and a background on
 * the block simply covers what it rides into - which is exactly what made
 * this card look as if the photograph had shrunk. The cream ground starts
 * where the overlap ends, on a pseudo-element, so the photograph shows
 * through the top 125px and only the card sits on it. */
.band-mission { position: relative; background: none; padding-top: 0; padding-bottom: var(--space-band); }
.band-mission::before { content: ""; position: absolute; inset: var(--overlap-depth) 0 0 0; z-index: var(--layer-behind); background: var(--cream); }
.mission-card-outer { position: relative; }
.mission-card-outer {
    max-width: 68.75rem;          /* the source's 1100 */
    margin-inline: auto;
    padding: var(--space-panel);
    border-radius: var(--radius-card);
    background: var(--accent-tint);
}
.mission-head { text-align: center; }
.mission-head .band-title { margin-top: var(--space-2xs); }
.mission-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-l); margin: 0; padding: 0; list-style: none; }   /* the title rule's margin is the gap */
.mission-item { display: flex; flex-direction: column; align-items: center; gap: var(--space-s); text-align: center; }
.mission-item__num { width: 42px; height: 42px; flex: none; fill: var(--brand-ink); }
/* The statement is a heading on the source, but it reads as body copy - the
 * weight and size stay those of a paragraph. */
.mission-item__text { margin: 0; font-family: var(--font-body); font-size: var(--step-0); font-weight: var(--weight-500); line-height: var(--leading-l); color: var(--ink); }

/* (7) The commitment: PSMC letterforms, and WHY CHOOSE US as an offset card
 * overlaid on the photograph rather than a button. */
.commitment__list li { display: flex; align-items: flex-start; gap: var(--space-xs); padding-left: 0; line-height: var(--leading-l); }
.commitment__list li > span { max-width: 21.125rem; }   /* live wraps the item text at 338 */
.commitment__list li::before { content: none; }
.commitment__letter { flex: none; width: 30px; height: 30px; margin-top: 0; fill: var(--brand-ink); }
.commitment__photo { position: relative; }
/* The source's card: a gradient panel hanging off the photograph's
 * bottom-right corner. The photograph and the bordered column beside it end
 * level with each other (both y6555 on the source) and the card hangs 123px
 * below both, which is what makes it read as offset rather than contained. */
/* The source's photograph and bordered column are the same height and end
 * level with each other; only the card hangs below them. */
.commitment { align-items: stretch; }
.commitment__photo { align-items: flex-end; justify-content: flex-end; padding: 0; }
.whychoose {
    width: min(38.6875rem, 92%);
    margin: 0 calc(-1 * (var(--space-l) + var(--space-xs))) calc(-1 * var(--space-3xl)) 0;   /* 55 past the photo's edge, 120 below it (live 54, 123) */
    padding: var(--space-card);
    border-radius: var(--radius-photo);
    background: var(--grad-panel);
    color: var(--paper);
}
.whychoose__title { margin: 0; font-family: var(--font-body); font-size: var(--step-1); font-weight: var(--weight-700); letter-spacing: var(--tracking-l); color: var(--paper); }
.whychoose p:not(.whychoose__title) { margin: 0 0 var(--space-s); line-height: var(--leading-l); color: var(--paper); }
.whychoose p:last-child { margin-bottom: 0; }
.rule--light { width: 4rem; height: 0; margin: var(--space-s) 0 var(--space-group); border: 0; border-top: var(--border-thin) solid var(--paper); opacity: 0.7; }   /* live: first paragraph 92 under the title */

@media (max-width: 64rem) {
    /* Folded, the card no longer rides over the photograph, so its offsets go
     * and a gap keeps the two from touching. */
    .about-intro { row-gap: var(--space-m); }
    .about-intro__card { margin-right: 0; margin-top: 0; }
    .timeline::before { content: none; }
    /* No rule to hang the year over once the row folds, so the year sits
     * close to its title and the items take a gap of their own. */
    .timeline { gap: var(--space-l); }
    .timeline__item { padding: 0; text-align: left; }
    .timeline__year { position: static; margin-bottom: var(--space-2xs); }
    .timeline__node { display: none; }
    .mission-grid { grid-template-columns: minmax(0, 1fr); }
    .overlap { margin-top: var(--space-l); }
    :is(section):has(+ .overlap) { padding-bottom: var(--space-band); }
    .whychoose { width: 100%; margin: 0; }
    .band-commitment { padding-bottom: var(--space-band); }
}

/* The contact page's Our Location column carries the source's crimson
 * outline, the same device as the booking card and the practice columns. */
.faq__location.bordered-column { align-self: start; }
.faq__location .faq__lede { margin-bottom: var(--space-m); }

/* mediflare.js appends HotDoc's lightbox container after the footer. The
 * container renders nothing while closed, but the <p> HotDoc puts inside it
 * carries a default margin that still contributes height, so documentElement
 * ran ~30px past the footer and left a strip of background below it.
 *
 * Zero that margin and nothing else. Do NOT hide the container: HotDoc's own
 * CDN script decides how to reveal it, so a display rule here silently breaks
 * the booking modal - which it did, until the click was actually tested. */
.hotdoc-lightbox > p { margin: 0; }

/* ── Practice Policies ────────────────────────────────────────────────
 * Measured off /practice-policies-2 at 1440. The page is a mosaic of
 * cards on four washes, and every size below is the source's own pixels
 * turned into rems of the 16px root — pinned, not fluid, because the
 * cards butt against each other and a 3px drift per card compounds.
 * ------------------------------------------------------------------- */

/* Every band on this page uses the source's 1350 shell (45px margins at
 * 1440), not the site's usual 1290 one. */
.band-policies-intro > .u-container,
.band-policies-pair > .u-container,
.band-policies-fees > .u-container,
.band-policies-mosaic > .u-container,
.band-policies-docs > .u-container { --grid-max-width: var(--shell-wide); }

/* Band 1: photo 713 + card 587, gap 50, on the white-to-accent wash.
 * The source's inner container pads 0 top and 30 bottom. */
.band-policies-intro { background: var(--grad-hero); padding-block: 0 var(--space-m); }
.policies-intro { display: grid; grid-template-columns: 713fr 587fr; gap: var(--space-card); align-items: stretch; }
.policies-intro__photo {
    min-height: 36.0625rem;                    /* the source's 577 */
    border-radius: var(--radius-card);
    background: url("/assets/images/policies-practice-exterior.5a1cd78053.webp") center / cover no-repeat;
}
.policies-intro__card { padding: var(--space-card); }
/* The source centres the eyebrow over left-aligned copy. */
.eyebrow--centred { text-align: center; }
.policies-intro__card .band-title { margin-block: var(--space-2xs) 0; }
.policies-intro__card p:not(.eyebrow) { margin: 0 0 var(--space-xs); line-height: var(--leading-l); color: var(--ink-black); }
.policies-intro__action { margin-top: var(--space-s); }

/* Band 2: 393 + 524 + 393 with a 20px gap, on accent-to-cream. The two
 * text columns have no ground of their own on the source — only the
 * photograph is a card. */
.band-policies-pair { background: var(--grad-info); padding-block: 0 var(--space-band); }   /* the source's 0/80 */
.policies-pair { display: grid; grid-template-columns: 393fr 524fr 393fr; gap: var(--space-s); align-items: start; }
/* The two text columns are cards on the source too — radius 15, 40px
 * padding, and a ground at zero alpha (transparent here, which paints the
 * same), so they read as plain columns while
 * still being cards. Reproduced as such rather than flattened away. */
.policies-pair__item {
    padding: var(--space-l) var(--space-l) var(--space-m);
    border-radius: var(--radius-card);
    background: transparent;
}
.policies-pair__item--wide { padding-bottom: var(--space-l); background: transparent; }
.policies-pair__title {
    margin: 0 0 var(--space-xs);
    font-family: var(--font-heading);
    font-size: var(--step-2);
    font-weight: var(--weight-700);
    line-height: var(--leading-m2);
    color: var(--crimson);
}
.policies-pair__item p { margin: 0; line-height: var(--leading-l); color: var(--ink); }
.policies-pair__photo {
    min-height: 19.1875rem;                    /* 307 */
    border-radius: var(--radius-card);
    background: url("/assets/images/policies-reception-desk.7b05fe9764.webp") center / cover no-repeat;
}

/* The card title shared by every policy card: Merriweather 700 at step-2,
 * brand ink, with the short crimson rule beneath it. */
.policies-card__title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: var(--step-2);
    font-weight: var(--weight-700);
    line-height: var(--leading-m2);
    color: var(--brand-ink);
}
.policies-card__title--light { color: var(--paper); }
/* The source's rules under a card title: crimson on light grounds, white on
 * dark ones, both short and both carrying space beneath. */
.rule--crimson { width: 19.25rem; height: 0; margin: var(--space-xs) 0 var(--space-s); border: 0; border-top: var(--border-thin) solid var(--crimson); }
.rule--light-short { width: 10.8125rem; height: 0; margin: var(--space-xs) 0 var(--space-s); border: 0; border-top: var(--border-thin) solid var(--paper); }

/* Band 3: one 1350 bordered card, two 624 columns inside it. */
.band-policies-fees { background: var(--grad-values); padding-block: var(--space-band) var(--space-group); }   /* 80/35 */
.policies-fees { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-s); }
.policies-fees__col { padding: var(--space-2xs); }
.policies-fees p { margin: 0 0 var(--space-xs); line-height: var(--leading-l); color: var(--pill-ink); }
/* list-style back: the template's :where(ul,ol)[class] reset strips it. */
.policies-list { margin: 0; padding-left: var(--space-l); list-style: disc; line-height: var(--leading-l); color: var(--pill-ink); }
.policies-list li { display: list-item; }
.policies-list li { margin-bottom: 0; }

/* Band 4: the mosaic. Left 675, right 635, 35px gap; the right column
 * starts 5px lower on the source, which is the card's own border. */
.band-policies-mosaic { background: var(--grad-paper-cream); padding-block: 0 var(--space-band); }
.policies-mosaic { display: grid; grid-template-columns: 675fr 635fr; gap: var(--space-m) var(--space-group); align-items: start; }
.policies-mosaic__col { display: flex; flex-direction: column; gap: var(--space-s); }
.policies-card { border-radius: var(--radius-card); }
.policies-card p { margin: 0 0 var(--space-xs); line-height: var(--leading-l); color: var(--pill-ink); }
.policies-card p:last-child { margin-bottom: 0; }
.policies-card--accent { padding: var(--space-l); background: var(--accent-tint); }
/* The teal card is a gradient frame with a 10px inset holding the copy. */
.policies-card--panel { padding: var(--space-2xs); background: var(--grad-panel); }
.policies-card--panel .policies-card__inner {
    padding: var(--space-l);
    border-radius: var(--radius-card);
    background: transparent;
}
.policies-card--panel p { color: var(--paper); }
.policies-card--crimson { padding: var(--space-l); background: linear-gradient(var(--salmon) 0%, var(--crimson) 100%); }
.policies-card--crimson p { color: var(--paper); }
/* The template's link colour is brand ink, which on this crimson ground is
 * both illegible and wrong — the source's link here is white. */
main .policies-card--crimson p a,
main .policies-card--crimson p a:hover,
main .policies-card--crimson p a:focus-visible { color: var(--paper); }
.policies-contact { line-height: var(--leading-l); }
.policies-mosaic__photo {
    min-height: 33rem;                         /* 528 */
    border-radius: var(--radius-card);
    background: url("/assets/images/policies-carport-walkway.e207aee7a9.webp") center / cover no-repeat;
}
/* Feedback 497 + referrals 818, gap 35. */
.policies-feedback { display: grid; grid-template-columns: 497fr 818fr; gap: var(--space-group); margin-top: var(--space-m); align-items: start; }
/* Side by side, the two cards share the taller one's height (owner, 2026-10-01). */
@media (min-width: 64.0625rem) { .policies-feedback { align-items: stretch; } }

/* The source's inline links inside the policy cards are crimson (#C14D36),
 * not the template's brand ink. Crimson clears AA on the white and cream
 * grounds these sit on; it does NOT on the cream card ground used elsewhere,
 * which is why the site's rule is salmon-deep there and crimson only here. */
/* Excluding the crimson card in the selector itself, rather than restating
 * it afterwards — a later same-specificity rule was silently winning and
 * putting crimson text back on the crimson ground. */
main .policies-fees a,
main .policies-card:not(.policies-card--crimson) a:not(.btn) { color: var(--crimson); }

/* Band 5: the six policy cards, three across on cream-to-accent. */
.band-policies-docs { background: var(--grad-cream-accent); padding-block: var(--space-band); }
.policies-docs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-m) calc(var(--space-xs) + var(--space-2xs)); }
.policies-doc {
    display: block;
    padding: var(--space-l);
    border-radius: var(--radius-card);
    text-decoration: none;
}
.policies-doc__title {
    margin: 0 0 var(--space-xs);
    font-family: var(--font-heading);
    font-size: var(--step-2);
    font-weight: var(--weight-700);
    line-height: var(--leading-m2);
    color: var(--brand-ink);
}
.policies-doc__title--light { color: var(--paper); }
.policies-doc p { margin: 0; line-height: var(--leading-l); color: var(--ink-black); }
/* The source marks this subtitle as a heading, so it stays one; it reads as
 * a continuation of the title above it, which is what the type says. */
.policies-doc__sub {
    margin: calc(-1 * var(--space-2xs)) 0 var(--space-2xs);
    font-family: var(--font-body);
    font-size: var(--step-1);
    font-weight: var(--weight-500);
    line-height: var(--leading-l);
    color: var(--paper);
}
.policies-doc--secondary { background: var(--secondary); }
.policies-doc--panel { background: var(--grad-panel); }
.policies-doc--panel p, .policies-doc--crimson p { color: var(--paper); }
.policies-doc--crimson { background: linear-gradient(var(--salmon) 0%, var(--crimson) 100%); }
a.policies-doc { transition: transform 0.3s var(--ease-out); }
a.policies-doc:hover, a.policies-doc:focus-visible { transform: translateY(-6px); }

@media (max-width: 64rem) {
    /* A DELIBERATE DEVIATION, owner's call 2026-09-08. The source has no
     * tablet override on these sections, so at 1024 it leaves every one of
     * them in its desktop column — text jammed into roughly 300px with half
     * the viewport empty, which is why live stands 9591px tall here against
     * our 6435. That is an Elementor oversight rather than a design, so the
     * clone stops at desktop and phone and this band stays readable. */
    .policies-intro, .policies-pair, .policies-fees, .policies-mosaic, .policies-feedback { grid-template-columns: minmax(0, 1fr); }
    .policies-docs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .policies-intro__photo { min-height: 20rem; }
    .policies-mosaic__photo { min-height: 20rem; }
    .policies-pair__item { padding: 0; }
}

@media (max-width: 47.9375rem) {
    .policies-docs { grid-template-columns: minmax(0, 1fr); }
    .policies-list { padding-left: var(--space-s); }
    .policies-intro__card, .policies-card--accent, .policies-card--crimson, .policies-doc { padding: var(--space-m); }
    .policies-card--panel .policies-card__inner { padding: var(--space-m); }
    .rule--crimson { width: 12rem; }
}

/* ── Appointment ──────────────────────────────────────────────────────
 * Measured off /appointment-2 at 1440. 164 words over 7975px: the page is
 * composition, not prose, so nearly every number here is one of the
 * source's own fixed pixels. Bands 1/3/4/5 sit on the 1350 shell, bands
 * 2/6/7 on the site's usual 1290 one — the source alternates them and the
 * difference is visible where a card edge lines up with the one above it.
 * ------------------------------------------------------------------- */
.band-appt-hero > .u-container,
.band-appt-types > .u-container,
.band-appt-billing > .u-container,
.band-appt-mosaic > .u-container { --grid-max-width: var(--shell-wide); }

/* Band 1: card 520 + photo 780, gap 50, then the note strip 120px below. */
.band-appt-hero { background: var(--grad-paper-cream); padding-block: var(--space-l) var(--space-band); }
/* Live's card is the full height of the row (585, the photograph's) with its
 * text centred inside, not a short card pinned to the top. Measured 2026-09-30. */
.appt-hero { display: grid; grid-template-columns: 520fr 780fr; gap: var(--space-card); align-items: stretch; }
.appt-hero__card { display: flex; flex-direction: column; justify-content: center; padding: var(--space-l); }
.appt-hero__card .band-title { margin-block: var(--space-2xs) var(--space-s); }
.appt-hero__card p:not(.eyebrow) { margin: 0 0 var(--space-xs); line-height: var(--leading-l); color: var(--ink-black); }
.appt-hero__action { margin-top: calc(var(--space-xs) + var(--space-2xs)); }
.appt-hero__photo { width: 100%; height: auto; border-radius: var(--radius-l); }   /* the source's 20, not 15 */
/* Three notes across, 383 wide with the source's 100px gap. */
.appt-notes { display: grid; grid-template-columns: repeat(3, 383fr); justify-content: space-between; gap: var(--space-column); margin-top: var(--space-2xl-3xl); }
.appt-notes p { margin: 0; line-height: var(--leading-l); color: var(--ink-black); }

/* Band 2: the four preparation tips. */
.band-appt-tips { background: var(--grad-values); padding-block: var(--space-band); border-top: var(--border-thin) solid var(--secondary); }
.appt-tips__head { text-align: center; }
.appt-tips__head .band-title { margin-bottom: var(--space-group); }
.appt-tips__lede { max-width: 64.5rem; margin: 0 auto; line-height: var(--leading-l); color: var(--pill-ink); }
/* The source's divider here is a 323x2 crimson rule, not the hairline. */
.rule--thick { width: 20.1875rem; height: 0; margin: var(--space-group) auto 0; border: 0; border-top: var(--border-medium) solid var(--crimson); }
.appt-tips { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-panel) var(--space-column); margin-top: var(--space-card); }
.appt-tip__icon { display: block; width: 45px; height: 45px; margin-bottom: var(--space-s); fill: var(--primary); }
.appt-tip__title { margin: 0 0 var(--space-xs); font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--ink); }
.appt-tip p { margin: 0; line-height: var(--leading-l); color: var(--ink); }

/* Band 3: the three appointment-type cards. The head is a 540/513/297 row
 * on the source, with the button pushed to the right of it. */
.band-appt-types { background: var(--grad-paper-cream); padding-block: var(--space-band); border-top: var(--border-thin) solid var(--secondary); }
.appt-types__head { display: grid; grid-template-columns: 540fr 513fr 297fr; gap: 0; align-items: end; padding-bottom: var(--space-panel); }
.appt-types__title .eyebrow { margin-bottom: var(--space-group); }
.band-title--ink { color: var(--ink); }
.appt-types__lede { margin: 0; padding-top: var(--space-card); line-height: var(--leading-l); color: var(--ink); }
.appt-types__action { margin: 0; padding-top: var(--space-l); text-align: right; }
/* The source's three cards are one height (628 at 1440) — the grid stretches
 * them rather than letting each shrink to its own copy. */
.appt-types { display: grid; grid-template-columns: 397fr 397fr 496fr; gap: var(--space-m); align-items: stretch; }
.appt-type { padding: var(--space-card); border-radius: var(--radius-card); }
.appt-type--salmon { background: var(--salmon); }
.appt-type--accent { background: var(--accent-tint); }
.appt-type--secondary { background: var(--secondary); }
.appt-type__icon { display: block; width: 45px; height: 45px; margin-bottom: var(--space-group); fill: var(--brand-ink); }
.appt-type--salmon .appt-type__icon { fill: var(--paper); }
.appt-type__title { margin: 0 0 var(--space-s); font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--ink); }
.appt-type__title--light { color: var(--paper); }
.appt-type p { margin: 0 0 var(--space-s); line-height: var(--leading-l); color: var(--ink); }
.appt-type--salmon p { color: var(--paper); }
/* Live's ticks: the kit's primary on the two pale cards, white on the crimson
 * one, each centred on its row (a wrapped row's tick sits mid-way, not on
 * the first line) with 11 between tick and text. They were all one dark
 * grey, top-aligned (owner, 2026-10-01). */
.appt-type__list { display: flex; flex-direction: column; gap: var(--space-2xs); margin: var(--space-s) 0 0; padding: 0; list-style: none; }
.appt-type__list li { display: flex; align-items: center; gap: var(--space-2xs); line-height: var(--leading-l); color: var(--ink); }
.appt-type__list svg { flex: none; width: 15px; height: 15px; fill: var(--primary); }
.appt-type--salmon .appt-type__list li { color: var(--paper); }
.appt-type--salmon .appt-type__list svg { fill: var(--cream); }   /* live's ticks here are the kit's cream, #F5EFE3 */
.appt-type--secondary .appt-type__icon { fill: var(--primary); }  /* the third card's calendar is the primary, not the brand ink */
.appt-type__link { margin: var(--space-s) 0 0; }
/* The template's `main a:not([class])` is specificity 0,2,1, so a plain
 * `.class a` loses to it. Every link-colour override below matches that
 * bar deliberately — this is why the selectors look heavier than they need
 * to. Crimson fails AA on the secondary ground, so this one is salmon-deep. */
main .appt-type__link a, main .appt-type__link a:hover { color: var(--salmon-deep); }

/* Band 4: the mirrored billing pair, 662 columns with a 30px gap. */
.band-appt-billing { background: var(--grad-cream-accent); padding-block: var(--space-band) 0; border-top: var(--border-thin) solid var(--secondary); }   /* the hairline live draws over the billing band */
.appt-billing { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-m); align-items: start; }
.appt-billing__photo { width: 100%; height: auto; border-radius: var(--radius-card); }
.appt-billing__photo--bg {
    min-height: 24.9375rem;                     /* the source's 399 */
    border-radius: var(--radius-card);
    background: url("/assets/images/appointment-practice-exterior.e44725c655.webp") center / cover no-repeat;
}
.appt-billing__card { padding: var(--space-l); border-radius: var(--radius-card); }
.appt-billing__card--paper { background: var(--paper); }
.appt-billing__card p { margin: var(--space-3xs) 0 var(--space-xs); line-height: var(--leading-l); color: var(--ink); }
.appt-billing__card p:last-child { margin-bottom: 0; }
.policies-card__title--ink { color: var(--ink); }

/* Band 5: the practice-information mosaic. The source is TWO 660 columns
 * with a 30px gap, and four blocks flowing into them in order — the two
 * card stacks fill row 1, then the photographs and the telephone card fill
 * row 2. It reads as a mosaic because the four blocks are different heights,
 * not because there are three columns. */
/* Band 5 runs accent-to-cream, the reverse of the band above it. */
.band-appt-mosaic { background: var(--grad-info); padding-block: var(--space-m) var(--space-band); }
/* Two 660px text columns on the source at 1350, plus the photo pair that
 * sits beside the Telephone Consultations card in the left-hand one. */
.appt-mosaic { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-m); align-items: start; }
.appt-mosaic__col { display: flex; flex-direction: column; gap: var(--space-m); }
.appt-info { padding: var(--space-l); border-radius: var(--radius-card); }
.appt-info--secondary { padding: var(--space-card); background: var(--secondary); }
.appt-info--accent { padding: var(--space-card); background: var(--accent-tint); }
.appt-info--cream { padding: var(--space-card); background: var(--cream); }
.appt-info__title { margin: 0 0 var(--space-xs); font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--ink); }
.appt-info p { margin: 0 0 var(--space-xs); line-height: var(--leading-l); color: var(--ink); }
.appt-info p:last-child { margin-bottom: 0; }
.appt-info__action { margin-top: var(--space-s); }
.btn--cta-small { padding: var(--space-2xs) var(--space-m); font-size: var(--step--2); }
.appt-criteria { display: flex; flex-direction: column; gap: var(--space-2xs); margin: 0 0 var(--space-xs); padding: 0; list-style: none; }
.appt-criteria li { display: flex; align-items: flex-start; gap: var(--space-3xs); line-height: var(--leading-l); color: var(--pill-ink); }
.appt-criteria svg { flex: none; width: var(--tick-icon); height: var(--tick-icon); margin-top: calc((1lh - var(--tick-icon)) / 2); fill: var(--pill-ink); }
/* The two photos beside the Telephone Consultations card. The source draws
 * these as CSS backgrounds on empty divs, not <img>, and lazily — an image
 * crawl of the page reports none here and will talk you into deleting them.
 * Measured on live: 660x464 and 660x350 at 1440, both keeping those heights
 * at 1024 and 390 while the width tracks the column. */
.appt-mosaic__photo { border-radius: var(--radius-card); background-position: center; background-size: cover; background-repeat: no-repeat; }
.appt-mosaic__photo--a { min-height: 29rem;   background-image: url("/assets/images/appointment-reception-team.503c28b9b3.webp"); }
.appt-mosaic__photo--b { min-height: 21.875rem; background-image: url("/assets/images/appointment-reception-counter.52af025498.webp"); }

/* Bands 6-7: the ten tips. */
.band-appt-tips-head { background: var(--cream); padding-block: var(--space-band) var(--space-l); border-top: var(--border-thin) solid var(--secondary); }
/* The source runs this band cream-to-accent, continuing the wash the tips
 * heading above it sits on: linear-gradient(#F5EFE3 0%, #D0E2E2 100%),
 * which is exactly --grad-cream-accent. Without it the band falls through
 * to white and the page ends on a bare strip. */
.band-appt-ten { background: var(--grad-cream-accent); padding-block: 0 var(--space-3xl); }
.appt-ten { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-panel); align-items: start; }
.appt-ten__col { display: flex; flex-direction: column; gap: var(--space-card); margin: 0; padding: var(--space-panel) 0; list-style: none; }
.appt-ten__title { margin: 0 0 var(--space-xs); font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--brand-ink); }
.appt-ten li p { margin: 0; line-height: var(--leading-l); color: var(--ink); }
/* The source's inline links here are crimson. The button inside the same
 * block is NOT — it is white on crimson, so the rule must not reach it, or
 * the label disappears into its own ground. `p a` alone did exactly that. */
main .appt-ten__resource p:not(.appt-ten__action) a { color: var(--crimson); }
.appt-ten__action { margin-top: var(--space-s); }
.appt-ten__photo {
    align-self: stretch;
    min-height: 55.6875rem;                     /* the source's 891 */
    border-radius: var(--radius-card);
    background: url("/assets/images/appointment-tips-vaccine-fridge.ea3a3735cc.webp") center / cover no-repeat;
}

@media (max-width: 64rem) {
    .appt-hero, .appt-tips { grid-template-columns: minmax(0, 1fr); }
    /* The source keeps billing 2-up at this width and stacks the mosaic to a
     * single column — measured on live at 1024: billing's four cards sit in a
     * 2x2 (two at y=4415, two at y=4901), the mosaic is one 944px column.
     * These two collapse at OPPOSITE breakpoints; do not unify them. */
    .appt-mosaic { grid-template-columns: minmax(0, 1fr); }
    .appt-notes { grid-template-columns: minmax(0, 1fr); gap: var(--space-l); margin-top: var(--space-card); }
    .appt-types__head { grid-template-columns: minmax(0, 1fr); gap: var(--space-m); padding-bottom: var(--space-card); }
    .appt-types__lede, .appt-types__action { padding-top: 0; text-align: left; }
    .appt-types { grid-template-columns: minmax(0, 1fr); }   /* the source stacks these at 1024: three 944px cards, 350/350/467 */
    .appt-ten { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-l); }
    .appt-ten__photo { grid-column: 1 / 3; grid-row: 1; min-height: 25rem; }
    .appt-ten__col { padding: 0; }
}

@media (max-width: 47.9375rem) {
    .appt-types, .appt-billing, .appt-ten { grid-template-columns: minmax(0, 1fr); }
    .appt-ten__photo { grid-column: auto; grid-row: auto; }
    .appt-hero__card, .appt-type, .appt-info, .appt-info--secondary,
    .appt-info--accent, .appt-info--cream, .appt-billing__card { padding: var(--space-m); }
    .rule--thick { width: 12rem; }
}

/* ── Patient Hub ──────────────────────────────────────────────────────
 * 30 words of our own copy above the Connect "Your Health" widget, which
 * renders everything else. The source's hub sits on a 1140 shell with 72px
 * of band padding and no wash — a plain white page, so that is what this is.
 * The widget brings its own styling; the site layer only sets the intro.
 * ------------------------------------------------------------------- */
.hub-main { padding-block: var(--space-panel); }            /* the source's 72 */
.hub > .u-container, .hub { --grid-max-width: 71.25rem; }   /* 1140 */
.hub-intro { margin-bottom: var(--space-s); }
.hub-intro__title {
    margin: 0 0 var(--space-xs);
    font-family: var(--font-heading);
    font-size: var(--step-7);
    font-weight: var(--weight-700);
    line-height: var(--leading-s1);
    color: var(--pill-ink);
}
.hub-intro__lede { margin: 0; font-size: var(--step-2); line-height: var(--leading-l); color: var(--pill-ink); }

@media (max-width: 47.9375rem) {
    .hub-main { padding-block: var(--space-band); }
    .hub-intro__title { font-size: var(--step-6); }
}

/* ── Health-service pages (phase 2c) ──────────────────────────────────
 * Nine pages share one shape, so they share one set of rules rather than
 * carrying nine near-identical copies: /vaccinations, /travel-vaccinations,
 * /skin-checks-and-excision, /diabetes, /mental-health, /mens-health,
 * /womens-health, /preventative-health-advice, and the article index at
 * /health-topics.
 *
 * The source builds each of them from an Elementor grid whose columns are
 * measured, not chosen: a hero band laying an eyebrow and an H1 across the
 * full 1350 shell and then splitting the rest into three tracks with the
 * photograph in the last, followed by prose bands that split into a titled
 * column plus one or two list columns. The widths below are live's own.
 * ------------------------------------------------------------------- */

/* The section shells. Live pads every one of these bands 80px top and
 * bottom inside a 1350 (or 1290) inner, and the last content band runs into
 * the footer's own gradient, so it gets --grad-footer's opening colour. */
.band-svc {
    padding-block: var(--space-band);
    background: var(--grad-hero);
}
/* The hero band opens tight: live gives it 20px above the eyebrow, not the
 * 80 that every other band on these pages carries. */
.band-svc--hero { padding-top: var(--space-s); }
/* Live closes the list bands with 120px rather than 80 — the extra 40 is
 * the source's, and without it the band lands 8% short. */
.band-svc--deep { padding-bottom: var(--space-2xl-3xl); }
.band-svc--paper-cream  { background: var(--grad-paper-cream); }
.band-svc--info         { background: var(--grad-info); }
.band-svc--cream-accent { background: var(--grad-cream-accent); }
.band-svc--values       { background: var(--grad-values); }
/* A band with no wash of its own: the source leaves these transparent and
 * lets the page ground show, which is white. */
/* These bands sit on live's 1350 shell, not the 1290 the rest of the site
 * uses, so the width is stated here rather than left on --shell. A handful
 * of bands DO use 1290 and opt back down with --narrow. */
.band-svc > .u-container { --grid-max-width: var(--shell-wide); }
.band-svc--narrow > .u-container { --grid-max-width: var(--shell); }   /* live's 1290 inner */

/* ── The hero: eyebrow + H1 across the full width, then three tracks ──
 * Live's tracks vary per page (363/372/433, 281/454/433, 245/490/433 …),
 * so the widths are set per page below; this is the shared frame. The
 * photograph is the third track and keeps live's 15px radius. */
/* The hero is ONE grid, not a heading block above a row of columns: the
 * photograph starts level with the eyebrow at the very top of the band and
 * runs down past it, while the eyebrow and H1 span only the two prose
 * tracks beside it. Splitting the heading out into its own full-width block
 * (the obvious reading of the band) pushes the photo down by the height of
 * the title and makes the band ~230px too tall.
 *
 * The two prose tracks differ on every page (363/372, 281/454, 245/490,
 * 326/408 …) because the source sizes them to the copy rather than to a
 * grid, so each page states its own pair and only the photograph's 433 and
 * the gap are shared. Getting these wrong rewraps every paragraph, which is
 * the other way a band ends up 200px out. */
.svc-hero {
    display: grid;
    /* The last track is the photo's own 433; the two prose tracks and the
     * gaps between all three are per page, since the source distributes the
     * 1350 differently on each one. */
    /* All three tracks are stated as fr, in the source's own pixel ratios, so
     * the row scales with the shell instead of overflowing it. As fixed px
     * the grid stayed wider than its container everywhere between the desktop
     * shell and the 64rem tablet override: the page scrolled sideways
     * continuously from 1380 down to 1040, worst at the narrow end (+356px),
     * on all eight of these pages. It read as clean at exactly 1440 and 1024,
     * which is the whole reason a gate sampling only those widths passed it.
     * The photo scales with the prose rather than holding 433 against it —
     * pinning the photo squeezed the first column to 135px and broke its
     * heading over four lines. At 1440 the tracks still compute to the
     * source's exact pixels. */
    grid-template-columns: var(--svc-hero-cols, 1fr 1fr) var(--svc-hero-photo, 433fr);
    column-gap: var(--svc-hero-gap, var(--space-card));
    row-gap: 0;
    align-items: start;
    /* The source's grid row is taller than the tallest thing in it on a few
     * pages — Elementor sizes the container, not the content — so the band
     * carries space the columns do not account for. Stated per page where
     * live has it rather than padded onto a column, which would move the
     * copy instead of the band's floor. */
    min-height: var(--svc-hero-min, 0);
}
/* The heading block spans the prose tracks and the space below it is the
 * source's own, measured per page (live leaves 119px on /womens-health).
 * On several pages the source also indents the prose columns 41px inside
 * the shell while leaving the heading on the edge, which --svc-hero-indent
 * reproduces. */
.svc-hero__head { grid-column: 1 / 3; margin-bottom: var(--svc-hero-lead, var(--space-l)); }
/* :first-of-type would match on the element name, and .svc-hero__head is a
 * div too, so the indent has to hang off the head instead. Translate, not
 * margin: a margin narrows the track, which rewraps the column's copy —
 * live keeps the column its stated width and simply moves it right. */
.svc-hero > .svc-hero__head + .svc-col { transform: translateX(var(--svc-hero-indent, 0)); }
.svc-hero__head .band-title { margin-top: var(--space-2xs); max-width: 54rem; }
/* The photo column spans both grid rows so it can start at the top. */
/* The source stacks the pitch under the photograph with Elementor's own
 * negative top margins (-20, -25) rather than a gap, so the run reads
 * tighter than the site's default rhythm. Reproduced as a gap rather than
 * as negative margins, because the effect is the spacing, not the mechanism.
 * The default is the source's most common value; pages that differ set it. */
.svc-hero__aside {
    grid-column: 3;
    grid-row: 1 / span 2;
    display: flex;
    flex-direction: column;
    gap: var(--svc-aside-gap, var(--space-2xs));
}
.svc-hero__aside > p { margin: 0; }
/* Same 14 under a title here as in the columns (live: 14 on both aside titles measured). */
.svc-hero__aside > .svc-title:not(:last-child) { margin-bottom: calc(var(--svc-title-gap, var(--space-xs)) - var(--svc-aside-gap, var(--space-2xs)) - var(--half-leading)); }   /* the last term is the title's half-leading, the 3px its line box overshoots the text */
.svc-photo {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius-card);
    object-fit: cover;
}
/* The hero photo is a fixed box on the source, not a free aspect ratio —
 * each page states its own height because live crops them differently. */

/* ── The prose columns ───────────────────────────────────────────────── */
/* The source does not align these columns to a common top: each Elementor
 * widget carries its own offset, so a column often starts 20-70px below its
 * neighbour. That drop is load-bearing — the grid takes its height from the
 * lowest-ending column, so flattening every column to the same top makes the
 * band short by exactly the offset. --svc-col-drop states it per column. */
.svc-col {
    display: flex;
    flex-direction: column;
    gap: var(--space-s);
    margin-top: var(--svc-col-drop, 0);
}
.svc-col > * { margin: 0; }
/* The gap under a title is tighter than the column's: live renders 14px
 * between a title's text and the paragraph beneath it on most of these
 * columns (measured 2026-09-30, owner found ours too far). The column gap
 * is 20 and the heading's line box overshoots its text by 3 (its half-
 * leading), so the title gives the difference back. Columns live sets wider state --svc-title-gap. */
.svc-col > .svc-title:not(:last-child) { margin-bottom: calc(var(--svc-title-gap, var(--space-xs)) - var(--space-s) - var(--half-leading)); }
/* The source often packs several paragraphs and a list into ONE Elementor
 * widget, where they run at the paragraph's own 14.85px bottom margin
 * rather than the column's gap. Split into separate blocks here, that
 * becomes a full column gap between each and the column grows ~45px.
 * .svc-run keeps such a run together at the source's tighter rhythm. */
.svc-run { display: flex; flex-direction: column; gap: var(--space-xs); }   /* live's 14.85 */
.svc-run > * { margin: 0; }
.svc-col p { line-height: var(--leading-l); color: var(--ink); }
/* .svc-col p outranks .eyebrow on specificity, which had turned the
 * closing card's eyebrow on /diabetes to ink. */
.svc-col > .eyebrow { color: var(--crimson); }
.svc-title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: var(--step-2);           /* live's 20.624 */
    font-weight: var(--weight-700);
    line-height: var(--leading-m);
    color: var(--brand-ink);
}
.svc-title--lg { font-size: var(--step-3); }        /* live's 24.7488 */
.svc-title--ink { color: var(--ink); }
/* Live marks a few of these section titles up as headings but renders them
 * in the eyebrow's crimson Raleway rather than Merriweather. */
.svc-title--crimson {
    font-family: var(--font-body);
    font-size: var(--step-1);
    color: var(--crimson);
}
.svc-quote { font-style: italic; }
.svc-emphasis { font-weight: var(--weight-600); }

/* ── The list: live's marker is a crimson 8px disc, not a tick ───────
 * Measured off the source: an 8x8 filled circle in Crimson Red, 2px of
 * margin and 5px of padding between it and the label, the label itself
 * Raleway 600 rather than the 400 of the surrounding prose, and 3.5px of
 * padding under each row. Reproduced rather than swapped for the tick used
 * on /appointment, because these two lists sit on the same site and the
 * difference is the source's, not ours. */
/* The row spacing is a variable because live sets it per list, not per
 * site: Elementor's "space between" is 7px in the hero lists and 25px in
 * the services band, and it splits that in half above and below each row.
 * A single hard-coded value collapses the wider lists by ~100px a column,
 * which is most of a band's height. */
.svc-list { margin: 0; padding: 0; list-style: none; --svc-list-gap: calc(var(--space-3xs) / 2); }   /* half of 3xs: live's 7 */
.svc-list--roomy { --svc-list-gap: calc((var(--space-xs) + var(--space-2xs)) / 2); }   /* half of xs + 2xs: live's 25 */
.svc-list > li {
    display: flex;
    align-items: flex-start;
    padding-bottom: var(--svc-list-gap);
    line-height: var(--leading-l);
}
.svc-list > li + li { margin-top: var(--svc-list-gap); }
/* The source pads the bottom of every row except the last and adds the same
 * value as a top margin to every row except the first, so N rows carry
 * 2(N-1) halves of the gap between them and none at the ends. */
.svc-list > li:last-child { padding-bottom: 0; }
.svc-list > li > svg {
    flex: none;
    width: var(--svc-marker-size);
    height: var(--svc-marker-size);
    margin: 0;
    /* the disc sits on the text's first line, not its top edge */
    margin-top: calc((1lh - var(--svc-marker-size)) / 2);
    fill: var(--svc-marker, var(--crimson));
}
.svc-list > li > span,
.svc-list > li > a {
    padding-left: var(--space-3xs);
    font-weight: var(--weight-600);
    color: var(--ink);
}
.svc-list > li > a { display: flex; align-items: flex-start; padding-left: 0; }
.svc-list > li > a > svg {
    flex: none;
    width: var(--svc-marker-size); height: var(--svc-marker-size);
    margin: calc((1lh - var(--svc-marker-size)) / 2) 0 0 0;
    fill: var(--svc-marker, var(--crimson));
}
.svc-list > li > a > span { padding-left: var(--space-3xs); }
/* Live draws these rows exactly like the unlinked ones: no underline, the
 * label in the same ink, nothing to distinguish a link but the cursor. That
 * is faithful but it is not usable, so the underline appears on hover and
 * on keyboard focus rather than never — the row still reads as live's at
 * rest, and it announces itself the moment anyone reaches for it. */
/* :where() to raise the specificity to (0,2,1) so it actually beats the
 * accessibility floor's `main a:not([class])` above. Without it the floor won
 * on source order AND specificity, and every linked row in these lists was
 * underlined at rest on the 2c pages too — the opposite of what this rule
 * says and what CLAUDE.md recorded. Found in a screenshot of the 2d hero
 * card, not by a probe: computed colour was correct, so only the decoration
 * gave it away. `:where(a)` does NOT work here — it contributes zero
 * specificity by definition, so the first fix changed nothing. `main` in the
 * selector matches the floor's own (0,2,1) and then wins on source order. */
/* Crimson and underlined, like every other prose link: the source draws
 * these list links in crimson too (measured on /vaccinations — "Coronavirus
 * (COVID-19)" and "Travel Vaccinations" are both rgb(193,77,54)), and this
 * rule had them on plain ink. The underline is ours by the same standing
 * decision as the floor above. */
/* Rows that are links: ink at rest like the rows beside them, crimson on
 * hover and focus (owner, 2026-09-30). The underline is the affordance. */
main .svc-list a { color: var(--crimson); text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 2px; transition: text-decoration-color var(--duration-fast) var(--ease-out); }
main .svc-list a:hover, main .svc-list a:focus-visible { text-decoration-color: currentColor; }
main .svc-list a > span { color: inherit; }

/* THE MARKER IS PER LIST, NOT PER SITE. The source uses two Font Awesome
 * glyphs in these lists -- fa-circle (an 8px crimson disc) and fa-check (a
 * crimson tick) -- and picks between them list by list. The 2c pages happened
 * to use the disc almost throughout, which read as "this site's marker" and
 * became the only one implemented; across the fifteen 2d children the TICK is
 * in fact the more common of the two, and several pages carry both. It is
 * detected per list off the source's own path data rather than judged from a
 * screenshot, where an 8px disc and a small tick are easy to confuse.
 *
 * The tick is wider than the disc and sits on the text's first line the same
 * way. `.svc-list--tick` only resizes the box; the glyph itself comes from
 * `#i-check` in partials/icons.html, which the site already carried. */
.svc-list--tick > li > svg,
.svc-list--tick > li > a > svg { --svc-marker-size: var(--tick-icon); }
/* The marker's COLOUR is per list as well. Read off live's Elementor CSS on
 * 2026-09-30: the hero-card lists fill their glyph with Crimson Red, and
 * every list in the wide band beneath (the topics, the common vaccinations,
 * the risk factors, "how we can help") fills it with the kit's primary. */
.svc-list--primary { --svc-marker: var(--primary); }
/* Live rules the band lists: a 1px #D8D8D8 line under every row but the
 * last (Elementor's icon-list divider). The hero-card lists have none. */
.svc-list--rule > li:not(:last-child) { border-bottom: var(--border-thin) solid var(--rule-grey); }
/* Lists whose glyphs are proper icons (the travel page's kit, pills and
 * map) rather than a marker: a 16px box, on the first line like the tick. */
.svc-list--icons > li > svg,
.svc-list--icons > li > a > svg { --svc-marker-size: 1rem; }

/* The 🔹 steps on /skin-checks-and-excision. The source writes them as one
 * paragraph with the emoji opening each line and <br><br> between, which is
 * a list wearing a paragraph's clothes; marked up as a list here and spaced
 * to the source's own double break. */
.svc-steps { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--space-s); }
.svc-steps > li { line-height: var(--leading-l); color: var(--ink); }
/* The bullet sits beside the text, so the row cannot be a flex container:
 * flex would make every inline element in the text its own ITEM, which turned
 * the tel: link in the skin-checks list into a 39px block and broke
 * "03 6428 7720" over three lines (live renders it inline at 102x20).
 * A floated marker keeps the text a single continuous run instead. */
.svc-steps > li { position: relative; padding-left: var(--space-xs); }
.svc-steps__mark { position: absolute; left: 0; top: calc((var(--leading-l) * 1em - 8px) / 2); }
.svc-steps__mark { width: 8px; height: 8px; fill: var(--crimson); }
/* An inline glyph standing in for one of the source's emoji. */
/* display:inline-block is load-bearing, not tidiness. The template's reset
 * gives every <svg> `display: block`, so this icon opened a line box of its
 * own and pushed the sentence beside it onto the next line — a paragraph that
 * should stand 47px stood 64, and its 17px of phantom space repeated wherever
 * the glyph appears. Found on /mymedicare band 2 measuring 11.9% over live
 * with an identical line and character count; it was already doing the same
 * thing on /mens-health and /preventative-health-advice, which shipped with
 * it. `vertical-align` cannot apply to a block box at all, so the alignment
 * below was inert until this line existed. */
.svc-inline-icon { display: inline-block; width: 0.875em; height: 0.875em; margin-right: var(--space-3xs); fill: var(--crimson); vertical-align: -0.05em; }

/* The source also writes some of these lists as paragraphs inside <li>,
 * which is how it gets a blank line between items. Kept, because collapsing
 * them to plain <li> closes gaps live leaves open. */
/* The template's `:where(ul, ol)[class]` reset strips list-style from any
 * classed list, so this one has to ask for its markers back explicitly. Live
 * draws them — a plain disc, the browser default — and without this the rows
 * render as bare indented text, which is what shipped on the 2c pages. */
.svc-list--prose { margin: 0; padding-left: var(--space-l); list-style: disc; }   /* live indents these 40 */
.svc-list--prose > li { display: list-item; }
/* The row gap is PER LIST, like the marker. Live reports margin-bottom: 0 on
 * /diabetes and /womens-health/cervical-screening — where a fixed 10 used to
 * sit here and added a line's worth per list — and 15 on several lists of
 * /mymedicare and /mens-health/prostate-cancer. It is Elementor's per-widget
 * setting, not a site rule, so the default stays 0 (which is what every page
 * shipped before this measured against) and a list that live spaces states
 * --svc-prose-gap itself. */
.svc-list--prose > li { margin-bottom: var(--svc-prose-gap, var(--space-3xs)); line-height: var(--leading-l); color: var(--ink); }
/* Rows that are links get live's own 15px (the value every 2e list carries):
 * at line-height alone the underlined rows run together and each is a thin
 * target for an older patient's finger. Owner asked for tight spacing to be
 * loosened, 2026-09-30. */
.svc-list--prose:has(> li > a, > li > p > a) > li { margin-bottom: var(--svc-prose-gap, var(--space-xs)); }
.svc-list--prose > li:last-child { margin-bottom: 0; }
.svc-list--prose > li > p { margin: 0; line-height: var(--leading-l); }
.svc-list--prose > li > p + p { margin-top: var(--space-2xs); }

/* ── Two- and three-column prose bands ──────────────────────────────── */
/* Per-page tracks go through a variable, never an inline
 * grid-template-columns: an inline declaration beats the media queries
 * below and pins the desktop tracks at every width, which is a horizontal
 * overflow on a phone rather than a stacked column. */
.svc-split {
    display: grid;
    grid-template-columns: var(--svc-split-cols, 1fr 1fr);
    gap: var(--svc-split-gap, var(--space-card));
    align-items: start;
}
.svc-split--3 { --svc-split-cols: 1fr 1fr 1fr; }
/* A titled column beside one or two list columns: the source's most common
 * second band. The title column is narrower than the lists it introduces. */
/* Live's three tracks here are equal thirds of the 1350 shell with the
 * gaps taken out of them (383 + 383 + 383 + 2 x 100). The gap is wider than
 * the page's usual 50 because the source sets it that way, and it matters:
 * the list items wrap onto a second line at 383 and do not at 400, which is
 * most of this band's height. */
.svc-listband {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-column);
    align-items: start;
}
.svc-listband__intro { display: flex; flex-direction: column; gap: var(--space-s); align-items: flex-start; --svc-title-gap: var(--space-s); }   /* 20 (live's 22) */
.svc-listband__intro > * { margin: 0; }
.svc-listband__intro > .svc-title:not(:last-child) { margin-bottom: calc(var(--svc-title-gap) - var(--space-s) - var(--half-leading)); }

/* ── The closing call-to-action band ─────────────────────────────────
 * A photograph beside a short pitch. Live floats the photo left of centre
 * (95 and 101 against a 45 shell edge) and the copy starts at 750/770. */
/* The source insets this block 50px inside the shell — the photograph sits
 * at x=95 against a 45 band edge — and pads the band itself 120 rather than
 * 80, so the whole thing floats. Both are live's, and without them the band
 * lands ~180px short. */
.svc-cta {
    display: grid;
    /* fr, not px, for the same reason as .svc-hero above: a fixed first track
     * plus a 1fr second one cannot shrink below its stated width, so this band
     * pushed /diabetes sideways from 1360 down to 1040 even after the hero was
     * fixed. The ratio is the source's own 575 against the 775 left of a 1350
     * shell; at 1440 it still computes to 575. */
    grid-template-columns: var(--svc-cta-cols, 575fr 775fr);
    gap: var(--space-column);
    align-items: center;
    /* 50 on all four sides: the photograph sits at x=95 against a 45 band
     * edge and the block stands 567 tall around a 467 image. */
    padding: var(--space-card);
}
.band-svc--float { padding-block: var(--space-2xl-3xl); }
/* The closing block's own ground, per page. /vaccinations and
 * /travel-vaccinations fill it with the kit's secondary; /skin-checks
 * outlines it in crimson. Radius 15, padding 50: measured on live's own
 * container. Both were missing, so the photo and pitch floated on the band. */
.svc-cta--secondary { background: var(--secondary); border-radius: var(--radius-card); }
.svc-cta--outlined { border: var(--border-thin) solid var(--crimson); border-radius: var(--radius-card); }
/* Live opens every band after the hero with a 1px hairline in the kit's
 * secondary (accent on a couple, indistinguishable at 1px). */
.band-svc--rule { border-top: var(--border-thin) solid var(--secondary); }
.band-svc--rule-accent { border-top: var(--border-thin) solid var(--accent-tint); }
/* A hero that is the page's only band carries live's hairline on its own bottom edge. */
.band-svc--rule-bottom { border-bottom: var(--border-thin) solid var(--secondary); }
/* /practice-policies: live opens the fees and documents bands with an accent hairline. */
.band-policies-fees, .band-policies-docs { border-top: var(--border-thin) solid var(--accent-tint); }
.svc-cta__copy { display: flex; flex-direction: column; gap: var(--space-s); align-items: flex-start; }
.svc-cta__copy > * { margin: 0; }
.svc-cta__title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: var(--step-3);
    font-weight: var(--weight-700);
    line-height: var(--leading-m);
    color: var(--brand-ink);
}
.svc-cta__photo { border-radius: var(--radius-card); width: 100%; height: auto; object-fit: cover; }

/* ── Responsive ──────────────────────────────────────────────────────
 * Below 1025 the three hero tracks become one column with the photograph
 * first, which is what live does on a phone; at 1024 live has no tablet
 * override on these sections at all and leaves the text in its desktop
 * column with half the viewport empty (see CLAUDE.md deviations), so the
 * clone uses the full width there instead of reproducing the oversight. */
@media (max-width: 64rem) {
    /* Live has no tablet override on these sections at all — it leaves them
     * in their desktop columns with half the viewport empty. The clone uses
     * the full width instead; see CLAUDE.md, "Deliberate deviations".
     *
     * Every per-page value below is reset, not merely overridden, because a
     * fixed pixel track that survives to a narrow viewport is a horizontal
     * overflow. !important is doing real work here rather than papering over
     * specificity: the per-page geometry is set as an inline custom property
     * on the element (it is per-instance data, not a class), and an inline
     * declaration beats a stylesheet rule at any specificity. This is the
     * one mechanism that can take it back at a breakpoint. */
    .svc-hero {
        --svc-hero-cols: 1fr 1fr !important;
        --svc-hero-gap: var(--space-l) !important;
        --svc-hero-lead: 0 !important;
        --svc-hero-indent: 0 !important;
        --svc-hero-min: 0 !important;
        grid-template-columns: 1fr 1fr;
        /* Once the columns fold, the outlined card sat hard against the
         * heading beneath it and the button against the photograph: the
         * desktop row-gap of 0 is right for a single row, not a stack. */
        row-gap: var(--space-l);
    }
    .svc-hero > .svc-col { --svc-col-drop: 0 !important; }
    /* Spans the folded row and stays AFTER the prose, which is its DOM order.
     * `grid-row: auto` alone let auto-placement float it into the first free
     * row — above the copy — while live keeps the photograph below the prose
     * at every folded width (measured: photo at y=1203 on live's own 390,
     * with the copy from y=501). An earlier `order: -1` here asserted the
     * opposite and was simply wrong about the source. */
    .svc-hero__aside { grid-column: 1 / -1; grid-row: auto; order: 1; flex-direction: row; flex-wrap: wrap; align-items: flex-start; }
    .svc-hero__aside .svc-photo { max-width: 433px; }
    .svc-hero__head { grid-column: 1 / -1; }
    .svc-listband { grid-template-columns: 1fr 1fr; }
    .svc-listband__intro { grid-column: 1 / -1; }
    .svc-cta { --svc-cta-cols: 1fr 1fr !important; gap: var(--space-l); padding: 0; }
    .svc-cta--secondary, .svc-cta--outlined { padding: var(--space-l); }   /* live pads its panel 30 on a phone */
    .svc-split, .svc-split--3 { --svc-split-cols: 1fr 1fr !important; --svc-split-gap: var(--space-l) !important; }
    /* An odd last item would sit beside an empty cell once three columns
     * fold to two: it takes the whole row instead. */
    .svc-split > :last-child:nth-child(odd) { grid-column: 1 / -1; }
    .band-svc--float { padding-block: var(--space-band); }
}
@media (max-width: 47.9375rem) {
    .svc-hero { --svc-hero-cols: 1fr !important; grid-template-columns: 1fr; }
    .svc-split, .svc-split--3 { --svc-split-cols: 1fr !important; }
    .svc-cta { --svc-cta-cols: 1fr !important; }
    .svc-listband { grid-template-columns: 1fr; gap: var(--space-l); }
    .svc-hero__aside { flex-direction: column; }
    .svc-hero__aside .svc-photo { max-width: none; }
}

/* The three age bands on /preventative-health-advice. Live renders each as
 * a heading and a line of copy in a 585 column, 78px apart. */
.svc-eligibility { display: flex; flex-direction: column; gap: var(--space-s); }
.svc-eligibility__row > * { margin: 0; }
.svc-eligibility__row p { line-height: var(--leading-l); color: var(--ink); }


/* ═══ The 15 health-topic CHILD pages (phase 2d) ══════════════════════
 * /mens-health/*, /womens-health/* and /preventative-health-advice/*.
 *
 * These are one level below the 2c service pages and the source builds them
 * from a DIFFERENT Elementor shape, not the same one nested. Where a 2c hero
 * lays the eyebrow and H1 across the whole 1350 shell and then splits it into
 * three tracks (.svc-hero), a 2d hero splits the shell in two — 867 of copy
 * and the 433 photograph — and puts the heading INSIDE the copy half, with a
 * nested two-column grid under it. That is why these get their own block
 * rather than more variables on .svc-hero: the heading spans a different
 * thing, and bending .svc-hero to do both would need the head's grid-column
 * to change per page, which is a shape, not a measurement.
 *
 * The measurements below are live's own at 1440 and identical on all 15
 * pages: 866.656/433.344 with a 50 gap, the nested pair at 408.328 each with
 * a 50 gap and a 100px lead-in, and the aside on a 35 gap. Only the photo's
 * height and the per-page column offsets differ, and those are inline.
 * ------------------------------------------------------------------- */

/* ── The hero ────────────────────────────────────────────────────── */
/* fr, not px, throughout — see the note on .svc-hero above; a fixed track
 * cannot shrink and scrolls the page sideways between the breakpoints. */
.svc2-hero {
    display: grid;
    grid-template-columns: 867fr 433fr;
    gap: var(--space-card);
    align-items: start;
}
.svc2-hero__main { display: flex; flex-direction: column; }
/* The eyebrow and H1 sit on a 35 gap and the nested prose grid begins 100px
 * below them. Live states that 100 as a margin on the grid rather than as the
 * flex gap, and the difference is visible: a gap would also separate the
 * eyebrow from the title. */
/* Live's gap here reads as 35 on the widget boxes, but Elementor's heading
 * widget is SHORTER than the text inside it (the h1 renders 43px tall in a
 * 19px box and overflows it upward), so 35 between the boxes is about 11
 * between the rendered lines. Set from the rendered text instead — the
 * eyebrow's baseline to the title's — which is what a reader sees. */
.svc2-hero__head { display: flex; flex-direction: column; gap: var(--space-xs); }
.svc2-hero__head .band-title { margin: 0; }
.svc2-hero__head .eyebrow { margin: 0; }
.svc2-cols2 {
    display: grid;
    grid-template-columns: var(--svc2-cols, 1fr 1fr);
    /* 50 in the hero's nested pair, 100 where the source uses this shape as a
     * band of its own (the 595/595 rows). The gap is part of the track maths,
     * not decoration: 595fr + 595fr on a 50 gap computes to 620 each in a 1290
     * shell, which is live's columns 25px too wide and its band 13% short. */
    gap: var(--svc2-gap2, var(--space-card));
    align-items: start;
    margin-top: var(--svc2-lead, var(--space-column));
}
/* The photo column: image, then whatever the source stacks under it. */
.svc2-aside { display: flex; flex-direction: column; gap: var(--space-group); }
.svc2-aside > * { margin: 0; }

/* ── The prose column ────────────────────────────────────────────── */
/* Live's own gap between a heading and the copy under it in these columns is
 * 35 in the plain columns and 20 or 30 inside the cards, so it is a variable
 * rather than one value. */
.svc2-col {
    display: flex;
    flex-direction: column;
    gap: var(--svc2-gap, var(--space-group));
    margin-top: var(--svc2-drop, 0);
    /* Live pads these columns per-instance and arbitrarily — 0, 10, 20, 40 and
     * 55 all appear across the 2d pages, an Elementor per-widget setting rather
     * than a rule. It is load-bearing where it narrows the text measure: on
     * /high-blood-pressure the 625 track carries 20px, so live wraps that copy
     * at 585 and we wrapped it at 625, costing one line box against an
     * otherwise identical band. Stated per column where live has it. */
    padding: var(--svc2-col-pad, 0);
}
.svc2-col > * { margin: 0; }
.svc2-col p { line-height: var(--leading-l); color: var(--ink); }

/* The second column of a 2d hero is a bordered card on ALL FIFTEEN pages:
 * the site's existing .bordered-column device — 1px crimson, 15px radius —
 * padded 40 top and bottom and 41 each side (measured as a 326 inner in a
 * 408 track), on a 20 or 30 gap. The padding alone is NOT the device: the
 * first build of this band read the geometry dump, saw only the padding and
 * shipped a bare column, which is visibly a different design beside live's
 * outlined box. A geometry probe reports boxes, not their edges — the border
 * only showed up in a screenshot. Which column of the pair is the card varies
 * per page (it is the second on eleven, the first on four), so it is a class
 * on the column rather than a nth-child rule. */
.svc2-card {
    padding: var(--space-l) var(--space-l);   /* live's 40 / 41 */
    border: var(--border-thin) solid var(--crimson);
    border-radius: var(--radius-card);
    --svc2-gap: var(--space-m);
}
/* The same 40/41 inset WITHOUT the crimson outline. The source uses both --
 * a bordered card where the block is a call-out, a bare inset where it is
 * only padding -- so the two are separate classes and the decoration scan
 * says which is which per page, rather than being inferred from the padding.
 * (Checked: /mens-health/depression-in-men's resources band is padded 40 and
 * has no border; its hero card has both.) */
.svc2-pad { padding: var(--space-l); --svc2-gap: var(--space-m); }

/* A column the source pads only 10px, which insets it slightly rather than
 * making it a card. Kept distinct from .svc2-card so the two do not drift.
 * Its blocks sit 20 apart, not the 35 of a plain column — measured off live's
 * own stack, where 25 put the band 32% over. */
/* Vertical only. The source's container carries 10px on all four sides, but
 * its list and text widgets are full-bleed inside it and keep the track's own
 * 417 -- measured on live, where "Set reminders (with both yourself and your
 * doctor)" sits on ONE line at 417 and wraps to two at 397. Reproducing the
 * horizontal 10 wrapped three rows across the page and put the band 27% over. */
.svc2-inset { padding-block: var(--space-2xs); --svc2-gap: var(--space-s); }

/* ── The three-track prose rows ──────────────────────────────────── */
/* The source's most common second band: three equal columns, at 417 with a 50
 * gap on the 1350 shell, or 383/363 with a 100 gap. Stated per band. */
.svc2-cols3 {
    display: grid;
    grid-template-columns: var(--svc2-cols, 1fr 1fr 1fr);
    gap: var(--svc2-gap3, var(--space-card));
    align-items: start;
}

/* ── The fact block (Elementor's icon-box) ───────────────────────── */
/* A crimson Raleway 700 line and a paragraph under it, 4px apart, stacked at
 * 20px. The source marks the crimson line up as a heading of whatever level
 * happened to be to hand (h3, h4 and h6 all appear on the same page), so the
 * markup here levels them to the page's own outline and the LOOK comes from
 * the class rather than the tag. */
/* Live stacks these 20 apart and leaves 10 between a fact's own title and its
 * paragraph — measured on /preventative-health-advice/cardiovascular-disease,
 * where each block stands 88 tall. At 15 and 4 they came out 77 and the band
 * was 8.5% short. */
/* Live stacks these 20 apart. The gap INSIDE a block varies: 10 where the
 * heading is Merriweather (cardiovascular-disease's risk band, measured at 88
 * per block) and effectively 0 where it is the crimson Raleway used as a
 * label (45-49's health-check card, where title and copy touch). One value
 * for both put 45-49's hero 7.6% over while making cardiovascular exact, so
 * it is a variable and each page states which it is. */
.svc2-facts { display: flex; flex-direction: column; gap: var(--space-s); margin-top: var(--svc2-drop, 0); }
.svc2-fact { display: flex; flex-direction: column; gap: var(--svc2-fact-gap, var(--space-2xs)); }
.svc2-facts--tight { --svc2-fact-gap: 0; }
.svc2-fact > * { margin: 0; }
.svc2-fact__title {
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--step-1);           /* live's 18.5616 */
    font-weight: var(--weight-700);
    line-height: var(--leading-l);
    color: var(--crimson);
}
.svc2-fact p { margin: 0; line-height: var(--leading-l); color: var(--ink); }
/* A few of these carry the brand ink rather than the crimson — the source
 * uses the colour to separate a group's own title from the facts under it. */
.svc2-fact__title--brand { color: var(--brand-ink); }
.svc2-fact__title--lg { font-family: var(--font-heading); font-size: var(--step-3); }

/* ── The closing panel: a photograph beside a padded pitch ───────── */
/* Live's shape: a 1200 inner centred in the band, split 550/550 on a 100 gap
 * with 50 of padding around the pair; the photograph is a CSS background on
 * an empty div (NOT an <img>), and the copy column is padded 70 top and
 * bottom. The photo is a background on the source and is reproduced as one,
 * because it is decorative — the copy beside it carries the meaning — and an
 * <img> here would need alt text inventing for a stock photograph. */
.svc2-panel {
    display: grid;
    grid-template-columns: var(--svc2-panel-cols, 1fr 1fr);
    gap: var(--space-column);
    align-items: stretch;
    /* --svc2-panel-max is the CONTENT width (live's 1200; 1140 and 1250 on two
     * pages) and the panel is that plus its own inline padding. Measured
     * 2026-09-30 off live's rounded box, which is the full 1350 shell padded
     * 50 left and 100 right on five pages, 50/50 on /high-cholesterol, and a
     * 1290 box inset 30 each side on /45-49. The earlier build had taken the
     * 1200 content box for the panel and ran the photo flush to its edge —
     * the owner saw it as "no padding". Tracks are unchanged, so no rewrap. */
    max-width: calc(var(--svc2-panel-max, 75rem) + var(--svc2-panel-pad-l, var(--space-card)) + var(--svc2-panel-pad-r, var(--space-column)));
    margin-inline: auto;
    padding: var(--space-card) var(--svc2-panel-pad-r, var(--space-column)) var(--space-card) var(--svc2-panel-pad-l, var(--space-card));
    /* Live rounds the whole panel AND gives it its own wash at a 15px radius.
     * The first build left it transparent because the probe that found the
     * tracks reported only geometry; the ground showed up in a screenshot
     * beside live, where the panel reads as a tinted card and ours read as
     * bare page.
     *
     * The wash is PER PAGE, not one gradient. Measured on all six panels:
     * secondary→accent (45-49), secondary→cream (both blood-pressure pages),
     * accent→cream (high-cholesterol), white→cream (breast-cancer-screening)
     * and flat white (75-year). A single default would have been wrong on
     * five of the six — which is the same mistake as the bare panel, one step
     * later. So the default is the commonest and each page states its own. */
    border-radius: var(--radius-card);
    background: var(--svc2-panel-bg, var(--grad-panel-card));
}
.svc2-panel__photo {
    border-radius: var(--radius-card);
    background-size: cover;
    background-position: 50% 50%;
    background-repeat: no-repeat;
    min-height: var(--svc2-panel-photo-h, 22.8125rem);   /* live's 365 default */
}
.svc2-panel__copy {
    display: flex;
    flex-direction: column;
    gap: var(--space-group);
    align-items: flex-start;
    justify-content: center;
    padding-block: var(--space-panel);
}
.svc2-panel__copy > * { margin: 0; }
.svc2-panel__copy p { line-height: var(--leading-l); color: var(--ink); }

/* ── A photograph as a background beside prose ───────────────────── */
/* The same device at band scale: an empty div carrying the photo as a cover
 * background, filling its grid track. Decorative, so aria-hidden and no alt. */
.svc2-photoblock {
    border-radius: var(--radius-card);
    background-size: cover;
    background-position: var(--svc2-photo-pos, 50% 50%);
    background-repeat: no-repeat;
    min-height: var(--svc2-photo-h, 22.5rem);
}

/* ── The four numbered step cards on /womens-health/breast-cancer-screening
 * A photograph, a numbered disc, then the copy. The disc does NOT ride over
 * the photograph: measured on live, the photo ends at y=1537, the disc starts
 * at 1536 and the copy at 1605 — flush, not overlapping. A -34.5px margin was
 * assumed here from the look of a small screenshot and made the card 114px
 * short (23% on the band). Every step's copy block is 175 tall on live
 * regardless of how much text is in it, which is what keeps the four cards
 * level, so the copy is given that height rather than left to its content. */
.svc2-steps4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-m); align-items: start; }
.svc2-step { display: flex; flex-direction: column; }
.svc2-step__photo { display: block; width: 100%; height: auto; border-radius: var(--radius-l); object-fit: cover; }   /* live's 20px radius */
.svc2-step__num {
    align-self: center;
    margin-top: 0;             /* flush under the photograph — live does not overlap them */
    width: 4.5rem; height: 4.3125rem;   /* live's 72 x 69 */
    display: grid; place-items: center;
    border-radius: var(--radius-round);
    background: var(--crimson);
    font-family: var(--font-heading);
    font-size: var(--step-2);
    font-weight: var(--weight-700);
    color: var(--paper);
}
.svc2-step__copy { margin: 0; min-height: 10.9375rem; line-height: var(--leading-l); color: var(--ink); }   /* live's 175 */
@media (max-width: 47.9375rem) { .svc2-step__copy { min-height: 0; } }

/* ── The urgent-help strip on /mens-health/depression-in-men ─────── */
/* Live sets this one line in white on the brand's own primary, padded 20 —
 * measured (rgb(255,255,255) on the source), not chosen.
 *
 * The selectors below are qualified with .svc2-col because this strip IS a <p>
 * inside one, and `.svc2-col p { color: var(--ink) }` above beats a bare
 * `.svc2-alert` on specificity. That put dark ink on the primary at 3.07:1 and
 * the two links at 1.85:1 — a genuine WCAG failure on the one block on this
 * site whose whole job is to be read in a crisis. axe found it only after the
 * reveals were settled; before that it was masked by a phantom contrast
 * failure on a button still at 0x0 mid-entry, on a different page. */
.svc2-alert,
.svc2-col .svc2-alert {
    margin: 0;
    padding: var(--space-s) var(--space-s);
    border-radius: var(--radius-card);
    background: var(--primary);
    color: var(--paper);
    line-height: var(--leading-l);
}
.svc2-alert a,
.svc2-col .svc2-alert a { color: var(--paper); text-decoration: underline; text-underline-offset: 2px; }

/* ── Responsive ──────────────────────────────────────────────────
 * Same reasoning as the 2c pages: below 1025 live has no tablet override on
 * these sections at all and leaves them in their desktop columns with half
 * the viewport empty, so the clone uses the full width instead. Every
 * per-page custom property is RESET here, not merely overridden, and with
 * !important, because the per-page geometry is an inline declaration on the
 * element and nothing weaker can take it back. */
@media (max-width: 64rem) {
    .svc2-hero { grid-template-columns: 1fr 1fr; gap: var(--space-l); }
    /* The photograph stays AFTER the prose when the layout folds. Live puts
     * it at y=1203 on its own 390 with the copy from y=501; an order that
     * lifts it above the copy is wrong about the source. DOM order is
     * already correct, so it only has to keep it. */
    .svc2-hero__main { grid-column: 1 / -1; }
    .svc2-aside { grid-column: 1 / -1; flex-direction: row; flex-wrap: wrap; align-items: flex-start; }
    .svc2-aside .svc-photo { max-width: 433px; }
    /* A lone photograph in the folded aside centres rather than sitting in
     * the left half with nothing beside it. */
    .svc2-aside:has(> :only-child) { justify-content: center; }
    .svc2-cols2 { --svc2-cols: 1fr 1fr !important; --svc2-lead: var(--space-l) !important; --svc2-gap2: var(--space-l) !important; }
    .svc2-cols3 { --svc2-cols: 1fr 1fr !important; --svc2-gap3: var(--space-l) !important; }
    .svc2-cols3 > :last-child:nth-child(odd) { grid-column: 1 / -1; }   /* no empty cell beside a third column folded to two */
    .svc2-col, .svc2-facts { --svc2-drop: 0 !important; }
    .svc2-panel { --svc2-panel-cols: 1fr 1fr !important; gap: var(--space-l); padding: var(--space-l); }
    .svc2-panel__copy { padding-block: 0; }
    .svc2-steps4 { grid-template-columns: 1fr 1fr; }
    .svc2-card { padding: var(--space-l); }
}
@media (max-width: 47.9375rem) {
    .svc2-hero { grid-template-columns: 1fr; }
    .svc2-cols2 { --svc2-cols: 1fr !important; }
    .svc2-cols3 { --svc2-cols: 1fr !important; }
    .svc2-panel { --svc2-panel-cols: 1fr !important; }
    .svc2-steps4 { grid-template-columns: 1fr; }
    .svc2-aside { flex-direction: column; }
    .svc2-aside .svc-photo { max-width: none; }
    .svc2-card { padding: var(--space-s) 0; }
}

/* Band padding on the 2d pages, measured off live band by band rather than
 * assumed. Three shapes recur, and the difference between them is up to 40px
 * a band, which compounds down a six-band page:
 *   80/80   the default .band-svc
 *   80/120  .band-svc--deep (already defined above)
 *   120/120 .band-svc--pad120
 * The hero is its own case again: live opens it 42 above the eyebrow on the
 * pages whose eyebrow is a heading widget and 20 on the pages where it is
 * not, so --hero (20) and --hero42 are separate. */
.band-svc--pad120 { padding-block: var(--space-2xl-3xl); }
.band-svc--hero42 { padding-top: var(--space-l); }   /* 40 (live's 42) */
/* A band the source opens or closes at 40 or 20 rather than 80. Only
 * /womens-health/breast-cancer-screening uses these, where a three-band run
 * is deliberately tight so the numbered cards read as one block. */
.band-svc--pad80-40 { padding-block: var(--space-band) var(--space-l); }
.band-svc--pad40-20 { padding-block: var(--space-l) var(--space-s); }
.band-svc--pad40-120 { padding-block: var(--space-l) var(--space-2xl-3xl); }

/* A band the source opens flush and closes at 80 — /mens-health/depression-
 * in-men's resources band, which live starts hard against the band above it. */
.band-svc--pad0-80 { padding-block: 0 var(--space-band); }

/* The row of three small photographs above the urgent-help strip on
 * /mens-health/depression-in-men. Live: 185 each on a 20 gap, 10px radius —
 * the site's photo radius, not the 15 its cards use. */
.svc2-trio { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-s); }
.svc2-trio__photo { display: block; width: 100%; height: auto; border-radius: var(--radius-photo); object-fit: cover; }
/* The trio stays three across on a phone: folded to two, the third photo
 * sat alone beside an empty cell. */

/* The FAQ pairs on /preventative-health-advice/gp-management-plan-and-team-
 * care-arrangements: two columns of fact blocks, 451 each on a 60 gap, the
 * rows flowing down the pair rather than across it. */
.svc2-faq { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-xl-2xl) var(--space-xl); align-items: start; }
@media (max-width: 47.9375rem) { .svc2-faq { grid-template-columns: 1fr; } }

/* An accent-to-white wash. The source uses it on one band of the GPMP page
 * and nowhere else, so it is stated rather than left to --grad-hero, which
 * runs the other way. */
.band-svc--accent-paper { background: linear-gradient(var(--accent-tint) 0%, var(--paper) 100%); }

/* A flat accent ground with no gradient. The source leaves the closing band
 * of /womens-health/breast-cancer-screening on the plain accent tint, which
 * .band-svc--plain (transparent, so white shows through) would get wrong. */
.band-svc--accent-flat { background: var(--accent-tint); }

/* A cream-to-secondary wash. /mymedicare's registration band closes on the
 * kit's secondary rather than the accent every other band runs to, which is
 * how the three registration cards sit against a darkening ground. */
.band-svc--cream-secondary { background: var(--grad-cream-secondary); }

/* An ordered list used as a card row carries no numbers of its own: the
 * numerals are drawn as .svc2-step__num, which is the design. The template's
 * [class] reset already strips the marker; this states the intent. */
.svc2-steps4 { list-style: none; margin: 0; padding: 0; }


/* ═══ The four online-services pages (phase 2e) ═══════════════════════
 * /request-repeat-prescription, /clinical-reminder-system,
 * /my-health-record and /mymedicare — the last of the migration.
 *
 * All four are built from the SAME Elementor shape as the 2d children, so
 * they reuse .svc2-* wholesale: an 867/433 hero with the heading inside the
 * copy half, a nested pair 100 below it, a bordered .svc2-card on one of the
 * two columns, and the aside stacking the photograph over whatever else the
 * source puts there. Only the three devices below are new, and each is a
 * thing the 2d pages genuinely do not have.
 * ------------------------------------------------------------------- */

/* ── The widget-box collapse, stated as a rule rather than absorbed ──
 * Elementor's text-editor widget box collapses to ZERO (measured: a 408x0 box
 * rendering 20px of text) while its heading widget under-reports by 3 on one
 * line and 24 on an h1. So live's "30px gap" between two widgets renders as
 * about 12 between the words a reader sees, and its "35" renders as about 19.
 * Setting our column gap to live's box value therefore draws 16px too much
 * whitespace at every block boundary — on /clinical-reminder-system that was
 * eight boundaries and put the band 14.3% over with an IDENTICAL line and
 * character count, which is the signature of spacing rather than a rewrap.
 *
 * Measured, not derived: on live's three columns the rendered gap is
 * (box gap − 16) everywhere EXCEPT immediately before a heading, where it is
 * (box gap − 3) because only the heading's own 3px of overflow applies there.
 * So the column carries the rendered gap and a non-first heading takes the
 * 13px back. Reproducing the collapse itself — a negative margin on every
 * heading, shrinking its box below its own text — would be a worse page for
 * the same number, which is why 2d declined to do it band by band; this states
 * the SPACING live draws instead, which is what a reader actually sees.
 *
 * Opt-in per column (.svc2-col--ink), because the 2c/2d pages already shipped
 * measured against the box gap and re-dialling them here would move fifteen
 * pages that were signed off. Set --svc2-gap to the RENDERED gap on a column
 * that carries it, not to live's box value. */
.svc2-col--ink > :is(h2, h3, h4):not(:first-child) {
    margin-top: var(--svc2-gap-lead, var(--space-xs));   /* live's 13 — the heading box's own share */
}
/* The same collapse in the photo column. Live's aside is on a 35 gap and it
 * renders as 33 under the photograph (an <img> has a real box, so nothing
 * collapses there) and as 10 under the heading (the text-editor beneath it
 * has a zero-height box). One gap cannot be both, so the aside states the
 * photo's 35 and the blocks below it take the rendered 10. */
.svc2-aside--ink { gap: var(--space-group); }
.svc2-aside--ink > :is(h2, h3, h4) + * { margin-top: calc(var(--space-2xs) - var(--space-group)); }   /* 35 -> live's rendered 10 */

/* ── The card's inset, stated from the source rather than back-derived ──
 * Live's bordered container is padded 40 on ALL FOUR sides, border-box, with
 * the 1px outline inside that — so a 490 track leaves 408 of text measure.
 * .svc2-card's 41 was back-derived from "a 326 inner in a 408 track" without
 * subtracting the border, which happens to land on the 2d pages' own tracks
 * and comes up 2px short on a 490 one. Two pixels is enough to rewrap: on
 * /clinical-reminder-system it moved "National Screening Program
 * Participation" from live's break to a different one.
 *
 * A variant rather than a change to .svc2-card, because the fifteen 2d pages
 * were measured and signed off against the 41 and re-dialling it here would
 * move all of them for a fault they do not exhibit. */
.svc2-card--40 { padding: var(--space-l); }

/* ── The pull-quote (Elementor's blockquote, "border" skin) ──────────
 * A 7px crimson rule down the left with 20 of padding beside it, no
 * background and no radius, and the content italicised by the source's own
 * <i>. Measured on /mymedicare (two of them) and /request-repeat-prescription
 * (one); identical on all three, so it is a class rather than per-instance.
 * The italic is carried by the class, not by an <em> in the markup, because
 * live's <i> is presentational here — it is styling the whole quote, not
 * emphasising a phrase within it. */
.svc2-quote {
    margin: 0;
    padding-left: var(--space-s);            /* live's 20 */
    border-left: 7px solid var(--crimson);   /* live's 7 — no border token is this wide */
    font-style: italic;
    line-height: var(--leading-l);
    color: var(--ink);
}
/* .svc2-col p sets the colour on every paragraph in a column and beats a bare
 * .svc2-quote on specificity, the same trap .svc2-alert hit. */
.svc2-col .svc2-quote { color: var(--ink); }
.svc2-quote > p { margin: 0; }
.svc2-quote > p + p { margin-top: var(--space-s); }

/* ── The centred band lead-in ────────────────────────────────────────
 * /mymedicare's registration band opens with an eyebrow, a title and a line
 * of copy, all centred, above the three cards. Live gives the block a 35 gap
 * and closes it at 40 before the cards; the copy is held to 675 of the 1350
 * shell, which is where its two lines break. Without that measure it runs the
 * full width on one line and the band comes up ~28px short. */
.svc2-lead {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* The rendered gap, not live's box gap — see the collapse note above.
     * Live draws 14 between the eyebrow and the title and 25 between the title
     * and the copy; its 35 box gap renders as neither. */
    gap: var(--svc2-lead-gap, var(--space-xs));   /* live's rendered 14 */
    text-align: center;
    padding-bottom: var(--space-group);   /* live's rendered 36 to the cards */
}
.svc2-lead > :is(h2, h3) + * { margin-top: var(--space-2xs); }   /* 14 -> live's 25 UNDER the title, not above it */
.svc2-lead > * { margin: 0; }
.svc2-lead p:not(.eyebrow) { line-height: var(--leading-l); color: var(--ink); }
.svc2-lead__copy { max-width: 42.1875rem; }   /* live's 675 */

/* ── The registration cards ──────────────────────────────────────────
 * /mymedicare's three "how to register" cards: 430 each on a 30 gap, padded
 * 50, radius 15, a 45px icon stacked 20 above the title and the list 40 below
 * it. Each card carries a DIFFERENT flat ground — cream, accent, secondary,
 * left to right — and each icon a different colour. That is the source's
 * design (the three steps read as a progression), so the ground and the ink
 * are per-card custom properties rather than one value.
 *
 * A flat colour, not a gradient: measured as a single rgb() on each card. */
.svc2-regcards {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;   /* fr, never px — a fixed track scrolls the page sideways */
    gap: var(--space-m);                  /* live's 30 */
    align-items: stretch;
}
.svc2-regcard {
    display: flex;
    flex-direction: column;
    gap: var(--space-m);                       /* live's rendered 29 between the title and the list */
    padding: var(--space-card);             /* live's 50 */
    border-radius: var(--radius-card);
    background: var(--svc2-regcard-bg, var(--cream));
}
.svc2-regcard > * { margin: 0; }
/* Live's icon-box widget stacks the 45px glyph and the title 20 apart on its
 * own box, which — the collapse again — renders as 29 between the glyph and
 * the words. The rendered value is what a reader sees, so that is what is
 * stated; the card comes out 11px tall on the box value. */
.svc2-regcard__head { display: flex; flex-direction: column; gap: var(--space-m); }   /* live's rendered 29 */
.svc2-regcard__icon {
    width: 2.8125rem; height: 2.8125rem;   /* live's 45 — no token is this size */
    fill: var(--svc2-regcard-ink, var(--primary));
}
.svc2-regcard p { line-height: var(--leading-l); color: var(--ink); }

/* ── Responsive ─────────────────────────────────────────────────────
 * Same reasoning as every other band on these pages: below 1025 the source
 * has no tablet override, so the clone takes the full width rather than
 * reproducing three 300px columns with half the viewport empty. */
@media (max-width: 64rem) {
    .svc2-regcards { grid-template-columns: 1fr 1fr; }
    .svc2-regcards > :last-child:nth-child(odd) { grid-column: 1 / -1; }   /* no empty cell beside the third card */
}
@media (max-width: 47.9375rem) {
    .svc2-regcards { grid-template-columns: 1fr; }
    .svc2-lead__copy { max-width: none; }
}

/* ── Phone and tablet polish (owner's sweep, 2026-10-01) ──────────────
 * Last in the file on purpose: these restate values that page blocks
 * above set at equal specificity. */
@media (max-width: 64rem) {
    /* The source centres this one eyebrow over left-aligned copy on the
     * desktop; once the card is a single narrow column that reads as a
     * mistake, so it follows its block like every other eyebrow. */
    .eyebrow--centred { text-align: inherit; }
}
@media (max-width: 47.9375rem) {
    /* Spacing: the phone's tighter band rhythm is no longer re-dialled here.
     * --space-band and the deep paddings sit on pairs (48 and 64 on a phone),
     * so they tighten with the knobs rather than by redeclaring a step. */
    /* Bands whose padding is stated in fixed rems for the desktop measure. */
    .band-svc[style*="padding"] { padding-block: var(--space-band) !important; }
    .team-head { padding-block: var(--space-band) var(--space-l); }
    .timeline { margin-bottom: var(--space-band); }   /* the desktop's 147 under the last milestone */

    /* Titles: 24 rather than 30, balanced, so a title of up to about 45
     * characters holds to two lines in the 350 column. The really long ones
     * (55 characters and over) still take three. */
    .band-title { font-size: var(--step-4); text-wrap: balance; }
    .about-intro__card .band-title { font-size: var(--step-6); }
    .band-title--small,
    .band-title--hero,
    .journey-2024__copy .band-title,
    .team-cta__panel .band-title,
    .commitment__copy .band-title { font-size: var(--step-3); }

    /* Cards keep about 28 of padding rather than the desktop's 40-50, which
     * left a 268px text column inside a 350 card: --space-card is 26 here. */
    .svc2-pad, .svc2-card, .mission-card-outer, .svc2-regcard, .contact-form-card { padding-inline: var(--space-card); }

    /* ONE ALIGNMENT PER BLOCK. Where the content under a heading is
     * left-aligned on a phone, the heading is too; where it is centred (the
     * staff roster), the heading follows it. */
    .appt-tips__head, .journey-head { text-align: left; margin-inline: 0; }
    .appt-tips__head .rule, .journey-head .rule { margin-inline: 0; }
    .team-head { text-align: center; }
    .hero__actions .btn--cta { justify-self: center; }   /* the hero card is centred; its button was not */
    .team-intro__card p.team-intro__actions { flex-wrap: wrap; justify-content: center; }
    .team-intro__badge { flex: none; }

    /* The hours card rides up over the hero card's foot, so the hero card
     * keeps a deeper bottom than the 28 its sides take. */
    .hero__card { padding-bottom: var(--space-panel); }

    /* ── Footer ──
     * Logo and line, the two link lists side by side, the map, then the
     * credit and the policy documents as a plain list. The pipe separators
     * are a desktop device: wrapped, they landed at the start of each line. */
    .site-footer__inner { padding-top: var(--space-l); }
    .site-footer__grid { gap: var(--space-l); padding-block: var(--space-l); }
    .site-footer__brand { gap: var(--space-s); }
    .site-footer__logo { width: 13.75rem; }
    .site-footer__motto { margin-top: calc(-1 * var(--space-2xs)); font-size: var(--step-1); }
    .site-footer__right { gap: var(--space-l); }
    .site-footer__links { grid-template-columns: 1fr 1fr; gap: var(--space-s); }
    .site-footer__col { gap: var(--space-xs); }
    .site-footer__title { font-size: var(--step-1); }
    .footer-links a { display: block; padding-block: var(--space-3xs); line-height: var(--leading-s2); }
    .footer-links li { padding-block: var(--space-3xs); }
    .site-footer__map { height: 13.75rem; }
    .footer-bar { gap: var(--space-s); padding-block: var(--space-m); }
    .footer-bar__left { flex-direction: column; align-items: flex-start; gap: var(--space-2xs); min-height: 0; }
    .footer-bar__legal { flex-direction: column; align-items: flex-start; row-gap: 0; order: -1; }
    .footer-bar__legal li:not(:last-child)::after { content: none; }
    .footer-bar__legal a { padding-block: var(--space-3xs); margin-block: 0; }
}


/* ── Legal prose: the website privacy policy and terms of use ─────────
 * The template's two website legal pages (owner rule: every site carries
 * both). Live has no plain prose page to clone, so this is the minimum
 * layout on the site's own type: the band title for the h1, the card-title
 * voice (Merriweather 700, step-2) for the section heads, body copy at the
 * site's measure. The practice's clinical policies stay the PDFs. */
.band-legal { background: var(--grad-paper-cream); padding-block: var(--space-band); }
.legal { max-width: var(--measure); }
.legal .band-title { margin: 0 0 var(--space-m); }
.legal h2 { margin: var(--space-l) 0 var(--space-xs); font-family: var(--font-heading); font-size: var(--step-2); font-weight: var(--weight-700); line-height: var(--leading-m2); color: var(--brand-ink); }
.legal p, .legal ul, .legal dl, .legal address { margin: 0 0 var(--space-xs); line-height: var(--leading-l); color: var(--ink); }
.legal .lede { font-size: var(--step-1); }
.legal ul { padding-left: var(--space-m); }
.legal li + li { margin-top: var(--space-3xs); }
.legal address { font-style: normal; }
.legal dt { font-family: var(--font-heading); font-weight: var(--weight-700); color: var(--brand-ink); }
.legal dd { margin: 0 0 var(--space-xs); }
.legal dd address { margin: 0; }
.legal small { font-size: var(--step--1); }
/* A legal page is read for its links (the PDF, the OAIC): underline them
 * outright rather than only on hover, as the site's other prose does. */
.legal a:not([class]) { text-decoration-color: currentColor; }

/* ── Site search ──────────────────────────────────────────────────────
 * The platform component (mediflare.js) writes the box unstyled, with
 * mf-search__* class hooks; every rule here is this site's, on its tokens.
 * Contract and the three placements: "Site search" in /srv/sites/CLAUDE.md.
 *
 * One placement at every width: one button (.site-search__trigger,
 * data-mf-search-open) opens the one overlay mediflare.js builds
 * (.mf-search-overlay). From 768 up the overlay is a centred card over a
 * dimmed page; below 768 it fills the screen. The trigger sits beside the
 * booking button, drawn as the site's own field (a white pill, no edge: the
 * --field-* tokens), and on phones it is the magnifier beside the hamburger.
 * Never inside the menu.
 *
 * The header must not wrap or change height, so the trigger shortens where
 * the bar is tight (measured 768-1920 every 20px, and +-1 at each edge):
 *   768-1024    magnifier and "Search…" (the bar is logo | actions, with room)
 *   1025-1439   the magnifier alone in its field, a 44px pill: the actions
 *               track is already wider than its 1fr there, so any more width
 *               would come out of the logo and change the header's height
 *   1440 up     magnifier and "Search…", with the bar's tracks restated so
 *               the extra width comes out of the nav's spare track, never
 *               the logo's (see the @media block after the trigger)
 *
 * One shape for the search controls: pills, because every button on this
 * site is a crimson pill (.btn--cta). Focus is the site's one ring, the
 * kit's "Black" (see the site :root under Form controls): it holds 4.3:1
 * even on the bar gradient's darkest end, #557987.
 *
 * The overlay is styled ONLY through :not([hidden]): a display of its own
 * would override [hidden] and it would never close. */
/* The trigger, drawn as the field it opens: fill, edge, corner and height
 * are the --field-* tokens. The glyph keeps the brand ink and the word is
 * the field's placeholder ink; it turns crimson like the booking button on
 * hover and while the window is open. */
.site-search__trigger {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    gap: var(--space-2xs);
    min-inline-size: var(--field-h);
    min-block-size: var(--field-h);
    padding: 0;
    font-size: var(--field-font-size);
    font-weight: var(--field-weight);
    line-height: var(--field-leading);
    white-space: nowrap;
    color: var(--brand-ink);
    background: var(--field-bg);
    border: var(--field-border-w) solid var(--field-border);
    border-radius: var(--field-radius);
    cursor: pointer;
    transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.site-search__trigger svg { flex: none; width: 18px; height: 18px; fill: currentColor; }
.site-search__text { display: none; color: var(--field-placeholder); }   /* the name is the aria-label */
/* The ellipsis is drawn, not spoken: the name stays "Search this site". */
.site-search__text::after { content: "\2026" / ""; }
.site-search__trigger:hover,
.site-search__trigger[aria-expanded="true"] { color: var(--paper); background: var(--crimson); }
.site-search__trigger:hover .site-search__text,
.site-search__trigger[aria-expanded="true"] .site-search__text { color: inherit; }

/* The bands with room: the word shows and the pill takes the field's
 * padding. */
@media (min-width: 48rem) and (max-width: 64rem), (min-width: 90rem) {
    .site-search__trigger { justify-content: flex-start; padding-inline: var(--field-pad-inline) var(--space-l); }
    .site-search__text { display: inline; }
}
/* From 1440 the bar's three tracks are restated so the wider trigger is
 * paid for by the nav's track, which has 130px+ of slack there, and never
 * by the logo's: the logo keeps exactly the width 1fr 3fr 1fr gave it (a
 * fifth of the bar less its gaps), so it, and the header's height, do not
 * move. The nav stays centred in what is left. */
@media (min-width: 90rem) {
    .site-bar { grid-template-columns: calc((100% - 2 * var(--space-3xs)) / 5) minmax(0, 1fr) auto; }
}

/* The actions: booking button, search, hamburger. The search sits closer
 * to the hamburger than the booking button does. */
.site-bar__actions { gap: var(--space-2xs); }
.site-bar__actions > .btn--cta-nav { margin-inline-end: calc(var(--space-m) - var(--space-2xs)); }
@media (min-width: 64.0625rem) {
    /* On the desktop the search sits beside the booking button, not a
     * full gap away from it. */
    .site-bar__actions > .btn--cta-nav { margin-inline-end: 0; }
}
/* Making room for it: the trigger is 44 plus a gap, and in the bar's
 * last 1fr track below 1280 that width comes out of the nav, which
 * already wraps below 1165. The nav links' inline padding steps down one
 * size there, which gives the room back: the nav keeps one row wherever
 * it had one (and gains it from 1115), and no label breaks. */
@media (min-width: 64.0625rem) and (max-width: 79.9375rem) {
    .nav-list > li > a { padding-inline: var(--space-2xs); }
}

/* The box, wherever it sits. */
.mf-search__form {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-2xs);
    align-items: center;
}
.mf-search__label,
.mf-search__status,
.mf-search__results { grid-column: 1 / -1; }
.mf-search__input { grid-column: 1 / -1; }
[data-mf-search-submit] .mf-search__input { grid-column: auto; }
/* Read out, never shown: the magnifier and the placeholder say it. */
.mf-search__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* TEXT CONTROLS: the shape is the --field-* tokens (Form controls), and
 * focus is the site's one ring (see the site :root under Form controls). */
.mf-search__input { font-weight: var(--weight-500); }
/* Search and Close ARE the site's booking button: the .btn, .btn--cta and
 * .btn--cta-nav rules above list them beside the classes (the component
 * writes its own buttons, so they cannot carry the classes). What is left
 * here is only what the markup would otherwise say: the site's button
 * labels are set in capitals, and the 44px floor. */
.mf-search__submit,
.mf-search-overlay__close {
    min-block-size: var(--target-min);
    text-transform: uppercase;
}

.mf-search__status {
    margin: 0;
    padding-inline: var(--space-xs);
    font-size: var(--step--1);
    line-height: var(--leading-m);
    color: var(--ink-black);
}
.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__result { margin: 0; }
/* Rows are the dropdown menus' rows: rounded, each its own block. */
.mf-search__link {
    display: block;
    padding: var(--space-2xs) var(--space-xs);
    border-radius: var(--radius-photo);
    color: var(--ink-black);
    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-black); background: var(--paper); }
.mf-search__link:focus-visible {
    outline-offset: calc(var(--focus-ring-w) * -1);   /* inset: a scrolling list clips an outset ring */
    border-radius: var(--radius-photo);
}
/* Titles are the site's card titles: Merriweather 700 in the "Text" ink,
 * crimson when reached, as the mega menu's headings are. */
.mf-search__title {
    display: block;
    font-family: var(--font-heading);
    font-size: var(--step-0);
    font-weight: var(--weight-700);
    line-height: var(--leading-m2);
    color: var(--brand-ink);
    transition: color var(--duration-fast) var(--ease-out);
}
.mf-search__link:hover .mf-search__title,
.mf-search__link:focus-visible .mf-search__title { color: var(--crimson); }
.mf-search__excerpt {
    display: block;
    margin-top: var(--space-3xs);
    font-size: var(--step--1);
    line-height: var(--leading-l);
    color: var(--ink-black);
}
.mf-search__excerpt mark {
    color: var(--ink-black);
    background: color-mix(in oklch, var(--crimson) 22%, transparent);
    border-radius: var(--radius-xs);
}

/* Phones: full screen, on the page's white. Close sits alone on
 * the top row, at the right where a phone's close usually is and above the
 * box, so what is seen matches the focus order (Close, the box, Search); the
 * box and Search share the next row at full width, and the results scroll
 * below them, inside the overlay. The page behind is locked by mediflare.js.
 * 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: minmax(0, 1fr) auto;
    grid-template-rows: auto 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(--grid-gutter), env(safe-area-inset-left)) max(var(--grid-gutter), env(safe-area-inset-right));
    background: var(--paper);
}
.mf-search-overlay__header { display: contents; }
.mf-search-overlay__close {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
    position: relative;
    z-index: var(--layer-base);   /* above the box, which spans this cell too */
}
.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;   /* the field and Search share one height */
}
.mf-search--overlay { --field-bg: var(--accent-tint); }   /* the field on the overlay's white */
.mf-search--overlay .mf-search__input { grid-column: 1; grid-row: 2; }
.mf-search--overlay .mf-search__submit { grid-column: 2; grid-row: 2; }
.mf-search--overlay .mf-search__status { grid-column: 1 / -1; grid-row: 3; }
.mf-search--overlay .mf-search__results {
    grid-column: 1 / -1;
    grid-row: 4;
    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(--accent-tint); }

/* From 768 up the same overlay is a centred card (the DocSearch pattern),
 * offset from the top rather than vertically centred, so it grows downward
 * with its results up to the viewport, past which they scroll inside it. A
 * press on the dimmed page, Close or Esc closes it (mediflare.js, #249). It
 * refines the full-screen rules above at equal specificity, so it must stay
 * after them. Stacking: the backdrop is body::after at --layer-modal, above
 * the sticky header (--layer-nav) and the dropdowns (--layer-overlay); the
 * card sits one above it, since body::after follows the overlay in tree
 * order and would paint over it at an equal z-index. */
@media (min-width: 48rem) {
    .mf-search-overlay:not([hidden]) {
        inset: var(--space-3xl) 0 auto;
        z-index: calc(var(--layer-modal) + 1);
        inline-size: calc(100% - 2 * var(--grid-gutter));
        max-inline-size: calc(var(--measure-tight) + var(--space-3xl));
        max-block-size: calc(100dvh - 2 * var(--space-3xl));
        margin-inline: auto;
        padding: var(--space-s);
        border-radius: var(--radius-card);
        box-shadow: var(--shadow-l);
    }
    .mf-search--overlay .mf-search__results { padding-block-end: 0; }
    html[data-mf-search-overlay="open"] body::after {
        content: "";
        position: fixed;
        inset: 0;
        z-index: var(--layer-modal);
        background: color-mix(in oklch, var(--ink-black) 50%, transparent);
        -webkit-backdrop-filter: blur(var(--space-3xs));
        backdrop-filter: blur(var(--space-3xs));
    }
}

/* Doctor photos come from the app (photo_url, #301), inside a .doctor-avatar box
 * that shows the fallback for a doctor without one. The box keeps the photo's own
 * size and shape, which .doctor-avatar would otherwise set. */
.person__photo.doctor-avatar { aspect-ratio: auto; border-radius: var(--radius-card); display: flex; }
/* The fallback's gradient is for a doctor with no photo: under a photo it shows as
 * a hairline ring at the anti-aliased edge, so a box holding a photo has none. */
.doctor-avatar:has(img) { background: none; }
