/*
 * Site styles. There is 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.
 *
 * COLOUR, TYPE AND SPACE ARE DIALS (#426). The first section is Dials
 * (github.com/joops/dials), copied verbatim between its begin and end
 * markers. It works out every colour, text size, space size and
 * corner from a few values called dials. This site sets its own dials in ONE
 * short block straight after the section, "This site's dials", and that block
 * is the only place in the file where a colour or a scale value is typed.
 *
 *   - Change the look by changing a dial: --brand for the brand colour,
 *     --size-min/--size-max and --ratio-min/--ratio-max for the type scale,
 *     --leading-*, --tracking-* and --weight-body/--weight-heading for line
 *     height, letter spacing and weight, --space-min/--space-max and
 *     --space-density for spacing, --radius-base for corners,
 *     --font-body/--font-heading for faces.
 *   - Everything else reads a token: --surface*, --text*, --border*, --link,
 *     --focus, --solid/--on-solid/--soft/--on-soft/--line (and the named
 *     groups --brand-*, --secondary-*, --tertiary-*, --success-* ...), --size-*,
 *     --leading, --tracking, --tracking-caps-total, --weight-strong,
 *     --space-*, --radius-*, --border-width-*. Never a hex, rgb(), hsl() or
 *     named colour, never a px/rem length, and never a typed line height,
 *     letter spacing or weight, anywhere else.
 *   - The rules are in refs/design/DESIGN.md ("Dials"). Every dial, token
 *     and class is listed in the reference for the version in the section's
 *     first line: github.com/joops/dials/blob/v0.3.0/docs/tokens.md. A
 *     gradient, a wash or a quiet coloured border is a pattern built from
 *     tokens (that reference, "Patterns"), never a token of its own.
 *     check-system.sh holds the section to _template's copy word for word,
 *     and fails a raw colour outside the dials block.
 */

/* ═══ Dials ═══ dials:begin ═════════════════════════════════════════════
 * Dials v0.3.0, VERBATIM. Never edit anything between this marker and the
 * end marker: check-system.sh fails the site if its copy differs from
 * _template's by a word. Each marker appears once; never write either in
 * prose. Set dials in "This site's dials" below; an upgrade
 * of Dials is a template change plus a migration of every site.
 * ═══════════════════════════════════════════════════════════════════════ */
/*! Dials v0.3.0 | MIT | https://github.com/joops/dials */
/* Dials: an AI-first CSS framework. This file is dials-colour.css, then
   dials-scale.css, then the fallback for older browsers; dials-base.css is optional.
   Default theme: Hi-Fi. Load its faces with:
   <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Michroma&family=Barlow:wght@400;700&family=Share+Tech+Mono&display=swap">
*/
/* ============================================================
   Dials: colour (dials-colour.css)
   Dials: seven colours and a few numbers, the only typed values.
   Derived: surfaces, text, lines and groups, worked out live with
   color-mix() and relative colour, in light and dark.
   Groups: .is-{group} points the ungrouped tokens at a group.
   Dials live on :root (and :host); the derived chain is declared on
   :root, [data-dials] and :host, so setting a dial on any
   [data-dials] element re-derives every token inside it.
   Needs color-mix(), light-dark() and relative colour. Don't
   register these with @property: they must resolve where they're
   used, which is what makes .is-dark bands work.
   ============================================================ */
:root, :host {
  /* ---- Colour dials: any CSS colour, preferably HSL ---- */
  --brand:     #f39c12;  /* the main colour: links, focus, primary buttons */
  --secondary: #2ec4b6;  /* a second colour: highlights and secondary actions (was --accent) */
  --success:   #3fbf55;  /* status: done, saved, live */
  --warning:   #f2c230;  /* status: check this */
  --danger:    #e0322b;  /* status: errors and destructive actions */
  --info:      #3b82c4;  /* status: neutral news */
  --grey:      hsl(42 7% 50%);  /* the hue and strength of the tint in paper and ink */

  /* ---- Number dials ---- */
  --balance: 0;              /* 1: every fill at --fill-lightness, so they carry equal weight. 0: exactly as set */
  --fill-lightness: 0.52;    /* the shared OKLCH lightness used when --balance is 1 */
  --dark-lift: 0.04;         /* how much lighter the fills are in dark */
  --tint-strength: 8%;       /* how much colour goes into a soft tint */
  --tint-vividness: 1;       /* 1-3: how saturated soft tints are, for crisper pastels */
  --text-contrast: 0;        /* 0-30: strengthens body, muted and quiet text and strong borders, for paper and ink that sit close together */
  --white-text-until: 0.179; /* fills below this luminance get white text, above it black. 0.179 gives each fill whichever contrasts more; held between 0.175 and 0.18333, where both still give 4.5:1: black needs (L + 0.05) / 0.05 >= 4.5, so L >= 0.175; white needs 1.05 / (L + 0.05) >= 4.5, so L <= 1.05 / 4.5 - 0.05 = 0.18333 */

  /* ---- Paper and ink: near-white and near-black, tinted by --grey at these OKLCH lightnesses.
     To use exact colours instead, set --paper-light, --paper-dark, --ink-light and/or
     --ink-dark (unset by default) to any colour. ---- */
  --paper-lightness: 0.922;       /* page background in light */
  --paper-dark-lightness: 0.186;  /* page background in dark */
  --ink-lightness: 0.213;         /* strongest text in light */
  --ink-dark-lightness: 0.934;    /* strongest text in dark */
}

/* Follow the visitor's light or dark setting. To force one, set
   :root { color-scheme: light; } (or dark) after dials.css. */
:root { color-scheme: light dark; }

:root, [data-dials], :host {
  /* ---- Internal: paper, ink and the six fills, worked out from the dials ---- */
  --dl-paper-light: var(--paper-light, oklch(from var(--grey) var(--paper-lightness) calc(c * 0.12) h));
  --dl-paper-dark:  var(--paper-dark,  oklch(from var(--grey) var(--paper-dark-lightness) calc(c * 0.15) h));
  --dl-ink-light:   var(--ink-light,   oklch(from var(--grey) var(--ink-lightness) calc(c * 0.25) h));
  --dl-ink-dark:    var(--ink-dark,    oklch(from var(--grey) var(--ink-dark-lightness) calc(c * 0.12) h));
  --dl-paper: light-dark(var(--dl-paper-light), var(--dl-paper-dark));
  --dl-ink:   light-dark(var(--dl-ink-light), var(--dl-ink-dark));
  --dl-paper-grey: oklch(from var(--dl-paper) l 0 h);  /* paper without its tint: soft tints mix into this, so they keep their own hue */

  --dl-secondary-dial: var(--accent, var(--secondary));  /* --accent is --secondary's old name: while a site still sets it, it wins */
  --dl-brand-base:     oklch(from var(--brand)              calc(l + (var(--fill-lightness) - l) * var(--balance)) c h);
  --dl-secondary-base: oklch(from var(--dl-secondary-dial)  calc(l + (var(--fill-lightness) - l) * var(--balance)) c h);
  --dl-success-base:   oklch(from var(--success)            calc(l + (var(--fill-lightness) - l) * var(--balance)) c h);
  --dl-warning-base:   oklch(from var(--warning)            calc(l + (var(--fill-lightness) - l) * var(--balance)) c h);
  --dl-danger-base:    oklch(from var(--danger)             calc(l + (var(--fill-lightness) - l) * var(--balance)) c h);
  --dl-info-base:      oklch(from var(--info)               calc(l + (var(--fill-lightness) - l) * var(--balance)) c h);
  --dl-brand:     light-dark(var(--dl-brand-base), oklch(from var(--dl-brand-base) calc(l + var(--dark-lift)) c h));
  --dl-secondary: light-dark(var(--dl-secondary-base), oklch(from var(--dl-secondary-base) calc(l + var(--dark-lift)) c h));
  --dl-success:   light-dark(var(--dl-success-base), oklch(from var(--dl-success-base) calc(l + var(--dark-lift)) c h));
  --dl-warning:   light-dark(var(--dl-warning-base), oklch(from var(--dl-warning-base) calc(l + var(--dark-lift)) c h));
  --dl-danger:    light-dark(var(--dl-danger-base), oklch(from var(--dl-danger-base) calc(l + var(--dark-lift)) c h));
  --dl-info:      light-dark(var(--dl-info-base), oklch(from var(--dl-info-base) calc(l + var(--dark-lift)) c h));

  /* ---- Surfaces ---- */
  --surface:         var(--dl-paper);                                            /* the page background */
  --surface-raised:  oklch(from var(--dl-paper) calc(l + 0.03) calc(c * 0.5) h);  /* cards, fields, popovers */
  --surface-lowered: color-mix(in oklab, var(--dl-ink) 4%, var(--dl-paper));     /* wells, table headers, quiet panels */
  --surface-sunken:  color-mix(in oklab, var(--dl-ink) 8%, var(--dl-paper));     /* code, inset areas, disabled fills */
  --surface-overlay: color-mix(in oklab, black 45%, transparent);                /* the scrim behind a dialog */

  /* ---- Text ---- */
  --text-strong:   var(--dl-ink);                                                                         /* headings, labels, emphasis */
  --text:          color-mix(in oklab, var(--dl-ink) calc(86% + var(--text-contrast) * 0.4%), var(--dl-paper));  /* body text */
  --text-muted:    color-mix(in oklab, var(--dl-ink) calc(70% + var(--text-contrast) * 1%), var(--dl-paper));    /* secondary text */
  --text-quiet:    color-mix(in oklab, var(--dl-ink) calc(64% + var(--text-contrast) * 1.2%), var(--dl-paper));  /* captions, dates, placeholders */
  --text-disabled: color-mix(in oklab, var(--dl-ink) 38%, var(--dl-paper));                                /* disabled controls: exempt from contrast rules */
  --link:          var(--brand-on-soft);                                                                  /* links: 4.5:1 on every surface */
  --link-hover:    light-dark(color(from var(--dl-brand-hover) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-brand-hover) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));  /* links on hover: a step stronger (the link 0.08 darker in OKLCH lightness in light, lighter in dark), and on to 7:1 if that's short */

  /* ---- Lines and effects ---- */
  --border-quiet:  color-mix(in oklab, var(--dl-ink) 7%, var(--dl-paper));   /* dividers that should barely show */
  --border:        color-mix(in oklab, var(--dl-ink) 13%, var(--dl-paper));  /* card and table borders: decorative */
  --border-strong: color-mix(in oklab, var(--dl-ink) calc(46% + var(--text-contrast) * 1%), var(--dl-paper));  /* field and control borders: 3:1 on surfaces */
  --focus:         var(--brand-on-soft);                                     /* the focus ring: opaque, 4.5:1 on surfaces */
  --selection:     color-mix(in oklab, var(--dl-brand) 22%, var(--dl-paper));  /* selected text background */
  --shadow-color:  light-dark(color-mix(in oklab, black 10%, transparent), color-mix(in oklab, black 45%, transparent));  /* the colour of shadows */
  --shadow-s: 0 1px 3px var(--shadow-color);    /* a slight lift: buttons, chips */
  --shadow-m: 0 4px 14px var(--shadow-color);   /* cards */
  --shadow-l: 0 12px 32px var(--shadow-color);  /* popovers, menus, dialogs */

  /* ---- Hover and pressed: the second half of a color-mix(), from Web Awesome.
     Use as color-mix(in oklch, var(--solid), var(--mix-hover)). ---- */
  --mix-hover:  oklch(from currentColor calc(1 - l) c h) 12%;  /* hover: away from the text colour */
  --mix-active: oklch(from currentColor calc(1 - l) c h) 22%;  /* pressed: further still */

  /* ---- Groups: brand, secondary, neutral, success, warning, danger, info. Five roles each:
     solid      a solid fill
     on-solid   text on it: white or black, whichever contrasts more (its sRGB luminance, as painted, vs --white-text-until)
     soft       a tinted background: the colour, held at L 0.7 or lighter in light (0.6 or darker in dark), mixed in OKLab
                into paper with its own tint taken out, so a blue soft stays blue on cream paper
     on-soft    text on soft, and coloured text on the page: the fill, moved only as far as 4.5:1 needs
     line       borders, icons and large text (24px, or 18.66px bold, and up): the dial, moved only as far as 3:1 needs

     Coloured text and lines follow one rule: keep the colour, and move it only as far as its
     contrast target needs, on the least contrasting background it sits on: its own soft tint,
     --surface-lowered or --surface-raised (--surface always lies between them). Only its
     linear-light RGB is scaled, which keeps the channels' ratios, so hue and saturation stay
     (in dark, until a channel reaches 1).
     --link-hover is the same rule at 7:1, starting from the link a step stronger.
       Y   the colour's luminance, 0.2126 r + 0.7152 g + 0.0722 b in linear sRGB (clipped to sRGB first)
       Yb  that background's luminance, as painted (clipped to sRGB)
       T   the target, plus 0.1 headroom so painting in 8 bits can't round it under the line
       light: Yt = (Yb + 0.05) / (T + 0.1) - 0.05; scale r, g and b by min(1, Yt / Y)
       dark:  Yt = (T + 0.1) * (Yb + 0.05) - 0.05; scale r, g and b by max(1, Yt / Y), each capped
              at 1; if a capped channel leaves it short, mix towards white only as far as Yt needs:
              by (Yt - Y1) / (1 - Y1), where Y1 is the luminance after scaling
     A colour that already passes keeps its exact value. CSS works out a relative colour from
     one colour's channels only, so the steps carry their numbers in colours:
       --dl-surfaces-y       the luminance of --surface-lowered in green, of --surface-raised in blue
       --dl-{group}-under    plus the soft tint's in red, mixed 50/50: Yb is min(2r, 4g, 4b) in light, max in dark
       --dl-{group}-text,    the colour, mixed 50/50 with a black whose alpha is s Yt, where s is 3 in
       --dl-{group}-line,    light (Yt is at most 0.29 there) and 1 in dark: scaling it up means Firefox
       --dl-brand-hover      rounding a mix's alpha to three decimals costs a third as much. Mixing
                             premultiplies, so the mix has alpha a = (1 + s Yt) / 2 and channels c / 2a:
                             the colour's channels are r * 2a, and Yt is (2a - 1) / s
       on-soft, line, hover  unpack both and scale, as above ---- */
  --dl-surfaces-y: color-mix(in srgb-linear, color(from var(--surface-lowered) srgb-linear 0 calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1)) 0), color(from var(--surface-raised) srgb-linear 0 0 calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))));

--dl-brand-under: color-mix(in srgb-linear, color(from var(--brand-soft) srgb-linear calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1)) 0 0), var(--dl-surfaces-y));
  --dl-brand-text:  color-mix(in srgb-linear, color(from var(--dl-brand-base) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-brand-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (4.5 + 0.1) - 0.05), 1))), color(from var(--dl-brand-under) srgb-linear 0 0 0 / calc(clamp(0, (4.5 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --dl-brand-line:  color-mix(in srgb-linear, color(from var(--brand) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-brand-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (3 + 0.1) - 0.05), 1))), color(from var(--dl-brand-under) srgb-linear 0 0 0 / calc(clamp(0, (3 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --brand-solid:    var(--dl-brand);
  --brand-on-solid: color(from var(--dl-brand) srgb-linear calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) / 1);
  --brand-soft:     oklch(from color-mix(in oklab, light-dark(oklch(from var(--dl-brand) max(l, 0.7) c h), oklch(from var(--dl-brand) min(l, 0.6) c h)) var(--tint-strength), var(--dl-paper-grey)) l calc(c * var(--tint-vividness)) h);
  --brand-on-soft:  light-dark(color(from var(--dl-brand-text) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-brand-text) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));
  --brand-line:     light-dark(color(from var(--dl-brand-line) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-brand-line) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));

  --dl-secondary-under: color-mix(in srgb-linear, color(from var(--secondary-soft) srgb-linear calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1)) 0 0), var(--dl-surfaces-y));
  --dl-secondary-text:  color-mix(in srgb-linear, color(from var(--dl-secondary-base) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-secondary-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (4.5 + 0.1) - 0.05), 1))), color(from var(--dl-secondary-under) srgb-linear 0 0 0 / calc(clamp(0, (4.5 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --dl-secondary-line:  color-mix(in srgb-linear, color(from var(--dl-secondary-dial) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-secondary-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (3 + 0.1) - 0.05), 1))), color(from var(--dl-secondary-under) srgb-linear 0 0 0 / calc(clamp(0, (3 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --secondary-solid:    var(--dl-secondary);
  --secondary-on-solid: color(from var(--dl-secondary) srgb-linear calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) / 1);
  --secondary-soft:     oklch(from color-mix(in oklab, light-dark(oklch(from var(--dl-secondary) max(l, 0.7) c h), oklch(from var(--dl-secondary) min(l, 0.6) c h)) var(--tint-strength), var(--dl-paper-grey)) l calc(c * var(--tint-vividness)) h);
  --secondary-on-soft:  light-dark(color(from var(--dl-secondary-text) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-secondary-text) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));
  --secondary-line:     light-dark(color(from var(--dl-secondary-line) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-secondary-line) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));

  --neutral-solid:    var(--dl-ink);
  --neutral-on-solid: var(--dl-paper);
  --neutral-soft:     var(--surface-lowered);
  --neutral-on-soft:  var(--text);
  --neutral-line:     var(--border);

  --dl-success-under: color-mix(in srgb-linear, color(from var(--success-soft) srgb-linear calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1)) 0 0), var(--dl-surfaces-y));
  --dl-success-text:  color-mix(in srgb-linear, color(from var(--dl-success-base) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-success-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (4.5 + 0.1) - 0.05), 1))), color(from var(--dl-success-under) srgb-linear 0 0 0 / calc(clamp(0, (4.5 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --dl-success-line:  color-mix(in srgb-linear, color(from var(--success) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-success-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (3 + 0.1) - 0.05), 1))), color(from var(--dl-success-under) srgb-linear 0 0 0 / calc(clamp(0, (3 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --success-solid:    var(--dl-success);
  --success-on-solid: color(from var(--dl-success) srgb-linear calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) / 1);
  --success-soft:     oklch(from color-mix(in oklab, light-dark(oklch(from var(--dl-success) max(l, 0.7) c h), oklch(from var(--dl-success) min(l, 0.6) c h)) var(--tint-strength), var(--dl-paper-grey)) l calc(c * var(--tint-vividness)) h);
  --success-on-soft:  light-dark(color(from var(--dl-success-text) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-success-text) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));
  --success-line:     light-dark(color(from var(--dl-success-line) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-success-line) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));

  --dl-warning-under: color-mix(in srgb-linear, color(from var(--warning-soft) srgb-linear calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1)) 0 0), var(--dl-surfaces-y));
  --dl-warning-text:  color-mix(in srgb-linear, color(from var(--dl-warning-base) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-warning-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (4.5 + 0.1) - 0.05), 1))), color(from var(--dl-warning-under) srgb-linear 0 0 0 / calc(clamp(0, (4.5 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --dl-warning-line:  color-mix(in srgb-linear, color(from var(--warning) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-warning-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (3 + 0.1) - 0.05), 1))), color(from var(--dl-warning-under) srgb-linear 0 0 0 / calc(clamp(0, (3 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --warning-solid:    var(--dl-warning);
  --warning-on-solid: color(from var(--dl-warning) srgb-linear calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) / 1);
  --warning-soft:     oklch(from color-mix(in oklab, light-dark(oklch(from var(--dl-warning) max(l, 0.7) c h), oklch(from var(--dl-warning) min(l, 0.6) c h)) var(--tint-strength), var(--dl-paper-grey)) l calc(c * var(--tint-vividness)) h);
  --warning-on-soft:  light-dark(color(from var(--dl-warning-text) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-warning-text) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));
  --warning-line:     light-dark(color(from var(--dl-warning-line) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-warning-line) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));

  --dl-danger-under: color-mix(in srgb-linear, color(from var(--danger-soft) srgb-linear calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1)) 0 0), var(--dl-surfaces-y));
  --dl-danger-text:  color-mix(in srgb-linear, color(from var(--dl-danger-base) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-danger-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (4.5 + 0.1) - 0.05), 1))), color(from var(--dl-danger-under) srgb-linear 0 0 0 / calc(clamp(0, (4.5 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --dl-danger-line:  color-mix(in srgb-linear, color(from var(--danger) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-danger-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (3 + 0.1) - 0.05), 1))), color(from var(--dl-danger-under) srgb-linear 0 0 0 / calc(clamp(0, (3 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --danger-solid:    var(--dl-danger);
  --danger-on-solid: color(from var(--dl-danger) srgb-linear calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) / 1);
  --danger-soft:     oklch(from color-mix(in oklab, light-dark(oklch(from var(--dl-danger) max(l, 0.7) c h), oklch(from var(--dl-danger) min(l, 0.6) c h)) var(--tint-strength), var(--dl-paper-grey)) l calc(c * var(--tint-vividness)) h);
  --danger-on-soft:  light-dark(color(from var(--dl-danger-text) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-danger-text) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));
  --danger-line:     light-dark(color(from var(--dl-danger-line) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-danger-line) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));

  --dl-info-under: color-mix(in srgb-linear, color(from var(--info-soft) srgb-linear calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1)) 0 0), var(--dl-surfaces-y));
  --dl-info-text:  color-mix(in srgb-linear, color(from var(--dl-info-base) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-info-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (4.5 + 0.1) - 0.05), 1))), color(from var(--dl-info-under) srgb-linear 0 0 0 / calc(clamp(0, (4.5 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --dl-info-line:  color-mix(in srgb-linear, color(from var(--info) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-info-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (3 + 0.1) - 0.05), 1))), color(from var(--dl-info-under) srgb-linear 0 0 0 / calc(clamp(0, (3 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
  --info-solid:    var(--dl-info);
  --info-on-solid: color(from var(--dl-info) srgb-linear calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) / 1);
  --info-soft:     oklch(from color-mix(in oklab, light-dark(oklch(from var(--dl-info) max(l, 0.7) c h), oklch(from var(--dl-info) min(l, 0.6) c h)) var(--tint-strength), var(--dl-paper-grey)) l calc(c * var(--tint-vividness)) h);
  --info-on-soft:  light-dark(color(from var(--dl-info-text) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-info-text) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));
  --info-line:     light-dark(color(from var(--dl-info-line) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--dl-info-line) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));
  --dl-brand-hover: color-mix(in srgb-linear, color(from light-dark(oklch(from var(--brand-on-soft) calc(l - 0.08) c h), oklch(from var(--brand-on-soft) calc(l + 0.08) c h)) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--dl-brand-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (7 + 0.1) - 0.05), 1))), color(from var(--dl-brand-under) srgb-linear 0 0 0 / calc(clamp(0, (7 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));

  /* ---- Ungrouped: components use these; .is-{group} points them at a group ---- */
  --solid:    var(--brand-solid);
  --on-solid: var(--brand-on-solid);
  --soft:     var(--brand-soft);
  --on-soft:  var(--brand-on-soft);
  --line:     var(--brand-line);

  /* ---- Deprecated: --accent's tokens, renamed --secondary-*. They still work; rename them ---- */
  --accent-solid:    var(--secondary-solid);     /* deprecated: use --secondary-solid */
  --accent-on-solid: var(--secondary-on-solid);  /* deprecated: use --secondary-on-solid */
  --accent-soft:     var(--secondary-soft);      /* deprecated: use --secondary-soft */
  --accent-on-soft:  var(--secondary-on-soft);   /* deprecated: use --secondary-on-soft */
  --accent-line:     var(--secondary-line);      /* deprecated: use --secondary-line */
}
.is-brand     { --solid: var(--brand-solid);     --on-solid: var(--brand-on-solid);     --soft: var(--brand-soft);     --on-soft: var(--brand-on-soft);     --line: var(--brand-line); }
.is-secondary { --solid: var(--secondary-solid); --on-solid: var(--secondary-on-solid); --soft: var(--secondary-soft); --on-soft: var(--secondary-on-soft); --line: var(--secondary-line); }
.is-neutral   { --solid: var(--neutral-solid);   --on-solid: var(--neutral-on-solid);   --soft: var(--neutral-soft);   --on-soft: var(--neutral-on-soft);   --line: var(--neutral-line); }
.is-success   { --solid: var(--success-solid);   --on-solid: var(--success-on-solid);   --soft: var(--success-soft);   --on-soft: var(--success-on-soft);   --line: var(--success-line); }
.is-warning   { --solid: var(--warning-solid);   --on-solid: var(--warning-on-solid);   --soft: var(--warning-soft);   --on-soft: var(--warning-on-soft);   --line: var(--warning-line); }
.is-danger    { --solid: var(--danger-solid);    --on-solid: var(--danger-on-solid);    --soft: var(--danger-soft);    --on-soft: var(--danger-on-soft);    --line: var(--danger-line); }
.is-info      { --solid: var(--info-solid);      --on-solid: var(--info-on-solid);      --soft: var(--info-soft);      --on-soft: var(--info-on-soft);      --line: var(--info-line); }
.is-accent    { --solid: var(--secondary-solid); --on-solid: var(--secondary-on-solid); --soft: var(--secondary-soft); --on-soft: var(--secondary-on-soft); --line: var(--secondary-line); }  /* deprecated: use .is-secondary */
/* A light or dark band: its own scheme, and its own background and text worked out in it */
.is-light { color-scheme: light; background-color: var(--surface); color: var(--text); }
.is-dark  { color-scheme: dark;  background-color: var(--surface); color: var(--text); }
/* ============================================================
   Dials: type and space (dials-scale.css)
   A few dials set every text size and every space size, the way
   Utopia (utopia.fyi) works them out, but the maths runs in the
   browser: change a dial and the whole scale follows. Leading,
   tracking and weight are worked out the same way, for whatever size
   they're used at. This file sets no type on any element: only
   dials-base.css does that. Dials live on
   :root (and :host); the derived scale is declared on :root,
   [data-dials] and :host, so a dial set on a [data-dials] element
   re-derives the sizes inside it.
   ============================================================ */
:root, :host {
  /* ---- Dials ---- */
  --screen-min: 360;       /* the screen widths the scale runs between, in px */
  --screen-max: 1240;
  --size-min: 16;          /* body text at the narrowest and widest screens, in px */
  --size-max: 18;
  --ratio-min: 1.2;        /* each step is this much bigger than the last: 1.2 minor third, */
  --ratio-max: 1.25;       /* 1.25 major third, 1.333 perfect fourth, 1.5 fifth, 1.618 golden */
  --space-min: var(--size-min);  /* --space-s at each end, in px: follows body text */
  --space-max: var(--size-max);  /* size unless you set a number */
  --space-density: 1;      /* scales every space size: 0.8 compact, 1.25 roomy */
  --radius-base: 3;        /* corner radius of cards and fields, in px (a number, not a length) */

  /* Faces: set per site, and load them yourself (each theme file names its Google Fonts link) */
  --font-body: "Barlow", ui-sans-serif, system-ui, sans-serif;  /* body text and controls */
  --font-heading: "Michroma", ui-sans-serif, system-ui, sans-serif;  /* headings */
  --font-mono: "Share Tech Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;  /* code, kbd, samp, pre */

  /* Border widths: every border and outline uses one of these */
  --border-width-s: 1px;   /* hairlines: cards, fields, tables */
  --border-width-m: 2px;   /* emphasis; outline offsets */
  --border-width-l: 3px;   /* focus rings, quote bars, active tabs */

  /* ---- Leading, tracking, weight and line length: unset by default ---- */
  /* While none is set, dials-base.css keeps v0.2's type. Set them in your own file; the value
     shown is what Dials uses for any you leave unset once you've set another. */
  /* --leading-body: 1.6;      line height at body size (--size-0), unitless */
  /* --leading-display: 1.15;  line height at the h1 step (--size-5) and above, unitless; sizes in between slide in a straight line */
  /* --tracking-small: 0;      letter spacing at the smallest size (--size--2), in em without the unit: positive loosens captions */
  /* --tracking-display: 0;    letter spacing at the h1 step (--size-5) and above, in em without the unit: negative tightens display type */
  /* --tracking-caps: 0;       extra letter spacing for all caps and small caps, in em without the unit (0.05 to 0.12 is usual) */
  /* --weight-body: 400;       body text weight */
  /* --weight-heading: 600;    heading weight */
  /* --line-length: none;      the longest line of running text, e.g. 65ch; unset, lines run the full width */
  /* --font-accent: var(--font-body);  a third face, for ledes, pull quotes or buttons; read it as var(--font-accent, var(--font-body)) */
}

:root, [data-dials], :host {
  /* ---- Internal: worked out from the dials, never edited by hand ---- */
  --dl-screen-range: calc(var(--screen-max) - var(--screen-min));
  --dl-fluid: calc((100vw - var(--screen-min) * 1px) / var(--dl-screen-range) * 16);  /* 0 at the narrowest, 16px at the widest */
  --dl-min-0: calc(var(--size-min) / 16);
  --dl-max-0: calc(var(--size-max) / 16);
  --dl-min--1: calc(var(--dl-min-0) / var(--ratio-min));
  --dl-max--1: calc(var(--dl-max-0) / var(--ratio-max));
  --dl-min--2: calc(var(--dl-min--1) / var(--ratio-min));
  --dl-max--2: calc(var(--dl-max--1) / var(--ratio-max));
  --dl-min-1: calc(var(--dl-min-0) * var(--ratio-min));
  --dl-max-1: calc(var(--dl-max-0) * var(--ratio-max));
  --dl-min-2: calc(var(--dl-min-1) * var(--ratio-min));
  --dl-max-2: calc(var(--dl-max-1) * var(--ratio-max));
  --dl-min-3: calc(var(--dl-min-2) * var(--ratio-min));
  --dl-max-3: calc(var(--dl-max-2) * var(--ratio-max));
  --dl-min-4: calc(var(--dl-min-3) * var(--ratio-min));
  --dl-max-4: calc(var(--dl-max-3) * var(--ratio-max));
  --dl-min-5: calc(var(--dl-min-4) * var(--ratio-min));
  --dl-max-5: calc(var(--dl-max-4) * var(--ratio-max));
  --dl-min-6: calc(var(--dl-min-5) * var(--ratio-min));
  --dl-max-6: calc(var(--dl-max-5) * var(--ratio-max));
  --dl-min-7: calc(var(--dl-min-6) * var(--ratio-min));
  --dl-max-7: calc(var(--dl-max-6) * var(--ratio-max));
  --dl-min-8: calc(var(--dl-min-7) * var(--ratio-min));
  --dl-max-8: calc(var(--dl-max-7) * var(--ratio-max));

  /* ---- Font sizes: --size-0 is body text; each number up or down is one step of the ratio,
     running in a straight line between its two ends ---- */
  --size--2: clamp(min(var(--dl-min--2), var(--dl-max--2)) * 1rem, var(--dl-min--2) * 1rem + (var(--dl-max--2) - var(--dl-min--2)) * var(--dl-fluid), max(var(--dl-min--2), var(--dl-max--2)) * 1rem);
  --size--1: clamp(min(var(--dl-min--1), var(--dl-max--1)) * 1rem, var(--dl-min--1) * 1rem + (var(--dl-max--1) - var(--dl-min--1)) * var(--dl-fluid), max(var(--dl-min--1), var(--dl-max--1)) * 1rem);
  --size-0: clamp(min(var(--dl-min-0), var(--dl-max-0)) * 1rem, var(--dl-min-0) * 1rem + (var(--dl-max-0) - var(--dl-min-0)) * var(--dl-fluid), max(var(--dl-min-0), var(--dl-max-0)) * 1rem);
  --size-1: clamp(min(var(--dl-min-1), var(--dl-max-1)) * 1rem, var(--dl-min-1) * 1rem + (var(--dl-max-1) - var(--dl-min-1)) * var(--dl-fluid), max(var(--dl-min-1), var(--dl-max-1)) * 1rem);
  --size-2: clamp(min(var(--dl-min-2), var(--dl-max-2)) * 1rem, var(--dl-min-2) * 1rem + (var(--dl-max-2) - var(--dl-min-2)) * var(--dl-fluid), max(var(--dl-min-2), var(--dl-max-2)) * 1rem);
  --size-3: clamp(min(var(--dl-min-3), var(--dl-max-3)) * 1rem, var(--dl-min-3) * 1rem + (var(--dl-max-3) - var(--dl-min-3)) * var(--dl-fluid), max(var(--dl-min-3), var(--dl-max-3)) * 1rem);
  --size-4: clamp(min(var(--dl-min-4), var(--dl-max-4)) * 1rem, var(--dl-min-4) * 1rem + (var(--dl-max-4) - var(--dl-min-4)) * var(--dl-fluid), max(var(--dl-min-4), var(--dl-max-4)) * 1rem);
  --size-5: clamp(min(var(--dl-min-5), var(--dl-max-5)) * 1rem, var(--dl-min-5) * 1rem + (var(--dl-max-5) - var(--dl-min-5)) * var(--dl-fluid), max(var(--dl-min-5), var(--dl-max-5)) * 1rem);
  --size-6: clamp(min(var(--dl-min-6), var(--dl-max-6)) * 1rem, var(--dl-min-6) * 1rem + (var(--dl-max-6) - var(--dl-min-6)) * var(--dl-fluid), max(var(--dl-min-6), var(--dl-max-6)) * 1rem);
  --size-7: clamp(min(var(--dl-min-7), var(--dl-max-7)) * 1rem, var(--dl-min-7) * 1rem + (var(--dl-max-7) - var(--dl-min-7)) * var(--dl-fluid), max(var(--dl-min-7), var(--dl-max-7)) * 1rem);  /* display type */
  --size-8: clamp(min(var(--dl-min-8), var(--dl-max-8)) * 1rem, var(--dl-min-8) * 1rem + (var(--dl-max-8) - var(--dl-min-8)) * var(--dl-fluid), max(var(--dl-min-8), var(--dl-max-8)) * 1rem);  /* display type: the top of the scale */

  /* ---- Leading, tracking and weight: worked out for the size of the element they're used on ---- */
  /* --leading and --tracking are lengths: apply them on each element that sets a font size, never
     on body, where they'd inherit as one fixed length. */
  --dl-leading-body: var(--leading-body, 1.6);
  --dl-leading-display: var(--leading-display, 1.15);
  --dl-tracking-small: var(--tracking-small, 0);
  --dl-tracking-display: var(--tracking-display, 0);
  /* body size over the h1 step, as a number: tan(atan2(a, b)) is a / b for two lengths
     (Firefox has no typed division) */
  --dl-type-q: tan(atan2(var(--size-0), var(--size-5)));
  /* leading runs in a straight line in size, m * size + g, through leading-body at --size-0 and leading-display at --size-5, the h1 step */
  --dl-leading-m: calc((var(--dl-leading-display) - var(--dl-leading-body) * var(--dl-type-q)) / max(1 - var(--dl-type-q), 0.000001));
  --dl-leading-g: calc(var(--size-0) * (var(--dl-leading-body) - var(--dl-leading-m)));
  /* how far up the scale this size is, from --size-0 (0) to --size-5 (1), and down it to --size--2, evenly per step */
  --dl-type-up: clamp(0, log(tan(atan2(var(--size-0), 1em))) / min(log(var(--dl-type-q)), -0.000001), 1);
  --dl-type-down: clamp(0, log(tan(atan2(1em, var(--size-0)))) / min(log(tan(atan2(var(--size--2), var(--size-0)))), -0.000001), 1);
  --leading: clamp(min(var(--dl-leading-body), var(--dl-leading-display)) * 1em, var(--dl-leading-m) * 1em + var(--dl-leading-g), max(var(--dl-leading-body), var(--dl-leading-display)) * 1em);  /* line height for the size it's on, from --leading-body at body size to --leading-display at --size-5 (h1) and above */
  --tracking: calc(1em * (var(--dl-tracking-display) * var(--dl-type-up) + var(--dl-tracking-small) * var(--dl-type-down)));  /* letter spacing for the size it's on: 0 at body size, --tracking-small at --size--2 and below, --tracking-display at --size-5 (h1) and above */
  --tracking-caps-total: calc(var(--tracking) + 1em * var(--tracking-caps, 0));  /* letter spacing for text in capitals: --tracking plus --tracking-caps */
  --weight-strong: min(900, var(--weight-body, 400) + 200);  /* bold within body text, buttons and labels: the body weight plus 200 */
  /* dials-base.css reads these, so an untouched site keeps v0.2's type: each is valid only once one of its dials is set */
  --dl-weight-strong-on: calc(var(--weight-strong) + 0 * var(--weight-body));

  /* ---- Space: multiples of the space base (Utopia's t-shirt sizes), times the density ---- */
  --dl-space-min: calc(var(--space-min) / 16 * var(--space-density));
  --dl-space-max: calc(var(--space-max) / 16 * var(--space-density));
  --space-3xs: clamp(calc(var(--dl-space-min) * 0.25rem), calc(var(--dl-space-min) * 0.25rem + (var(--dl-space-max) * 0.25 - var(--dl-space-min) * 0.25) * var(--dl-fluid)), calc(var(--dl-space-max) * 0.25rem));
  --space-2xs: clamp(calc(var(--dl-space-min) * 0.5rem), calc(var(--dl-space-min) * 0.5rem + (var(--dl-space-max) * 0.5 - var(--dl-space-min) * 0.5) * var(--dl-fluid)), calc(var(--dl-space-max) * 0.5rem));
  --space-xs: clamp(calc(var(--dl-space-min) * 0.75rem), calc(var(--dl-space-min) * 0.75rem + (var(--dl-space-max) * 0.75 - var(--dl-space-min) * 0.75) * var(--dl-fluid)), calc(var(--dl-space-max) * 0.75rem));
  --space-s: clamp(calc(var(--dl-space-min) * 1rem), calc(var(--dl-space-min) * 1rem + (var(--dl-space-max) * 1 - var(--dl-space-min) * 1) * var(--dl-fluid)), calc(var(--dl-space-max) * 1rem));
  --space-m: clamp(calc(var(--dl-space-min) * 1.5rem), calc(var(--dl-space-min) * 1.5rem + (var(--dl-space-max) * 1.5 - var(--dl-space-min) * 1.5) * var(--dl-fluid)), calc(var(--dl-space-max) * 1.5rem));
  --space-l: clamp(calc(var(--dl-space-min) * 2rem), calc(var(--dl-space-min) * 2rem + (var(--dl-space-max) * 2 - var(--dl-space-min) * 2) * var(--dl-fluid)), calc(var(--dl-space-max) * 2rem));
  --space-xl: clamp(calc(var(--dl-space-min) * 3rem), calc(var(--dl-space-min) * 3rem + (var(--dl-space-max) * 3 - var(--dl-space-min) * 3) * var(--dl-fluid)), calc(var(--dl-space-max) * 3rem));
  --space-2xl: clamp(calc(var(--dl-space-min) * 4rem), calc(var(--dl-space-min) * 4rem + (var(--dl-space-max) * 4 - var(--dl-space-min) * 4) * var(--dl-fluid)), calc(var(--dl-space-max) * 4rem));
  --space-3xl: clamp(calc(var(--dl-space-min) * 6rem), calc(var(--dl-space-min) * 6rem + (var(--dl-space-max) * 6 - var(--dl-space-min) * 6) * var(--dl-fluid)), calc(var(--dl-space-max) * 6rem));
  --space-4xl: clamp(calc(var(--dl-space-min) * 8rem), calc(var(--dl-space-min) * 8rem + (var(--dl-space-max) * 8 - var(--dl-space-min) * 8) * var(--dl-fluid)), calc(var(--dl-space-max) * 8rem));
  /* One-up pairs: small on phones, the next size up on desktops */
  --space-3xs-2xs: clamp(calc(var(--dl-space-min) * 0.25rem), calc(var(--dl-space-min) * 0.25rem + (var(--dl-space-max) * 0.5 - var(--dl-space-min) * 0.25) * var(--dl-fluid)), calc(var(--dl-space-max) * 0.5rem));
  --space-2xs-xs: clamp(calc(var(--dl-space-min) * 0.5rem), calc(var(--dl-space-min) * 0.5rem + (var(--dl-space-max) * 0.75 - var(--dl-space-min) * 0.5) * var(--dl-fluid)), calc(var(--dl-space-max) * 0.75rem));
  --space-xs-s: clamp(calc(var(--dl-space-min) * 0.75rem), calc(var(--dl-space-min) * 0.75rem + (var(--dl-space-max) * 1 - var(--dl-space-min) * 0.75) * var(--dl-fluid)), calc(var(--dl-space-max) * 1rem));
  --space-s-m: clamp(calc(var(--dl-space-min) * 1rem), calc(var(--dl-space-min) * 1rem + (var(--dl-space-max) * 1.5 - var(--dl-space-min) * 1) * var(--dl-fluid)), calc(var(--dl-space-max) * 1.5rem));
  --space-m-l: clamp(calc(var(--dl-space-min) * 1.5rem), calc(var(--dl-space-min) * 1.5rem + (var(--dl-space-max) * 2 - var(--dl-space-min) * 1.5) * var(--dl-fluid)), calc(var(--dl-space-max) * 2rem));
  --space-l-xl: clamp(calc(var(--dl-space-min) * 2rem), calc(var(--dl-space-min) * 2rem + (var(--dl-space-max) * 3 - var(--dl-space-min) * 2) * var(--dl-fluid)), calc(var(--dl-space-max) * 3rem));
  --space-xl-2xl: clamp(calc(var(--dl-space-min) * 3rem), calc(var(--dl-space-min) * 3rem + (var(--dl-space-max) * 4 - var(--dl-space-min) * 3) * var(--dl-fluid)), calc(var(--dl-space-max) * 4rem));
  --space-2xl-3xl: clamp(calc(var(--dl-space-min) * 4rem), calc(var(--dl-space-min) * 4rem + (var(--dl-space-max) * 6 - var(--dl-space-min) * 4) * var(--dl-fluid)), calc(var(--dl-space-max) * 6rem));
  --space-3xl-4xl: clamp(calc(var(--dl-space-min) * 6rem), calc(var(--dl-space-min) * 6rem + (var(--dl-space-max) * 8 - var(--dl-space-min) * 6) * var(--dl-fluid)), calc(var(--dl-space-max) * 8rem));
  /* Skip pairs, for gutters and section padding that need a bigger swing */
  --space-s-l: clamp(calc(var(--dl-space-min) * 1rem), calc(var(--dl-space-min) * 1rem + (var(--dl-space-max) * 2 - var(--dl-space-min) * 1) * var(--dl-fluid)), calc(var(--dl-space-max) * 2rem));
  --space-m-xl: clamp(calc(var(--dl-space-min) * 1.5rem), calc(var(--dl-space-min) * 1.5rem + (var(--dl-space-max) * 3 - var(--dl-space-min) * 1.5) * var(--dl-fluid)), calc(var(--dl-space-max) * 3rem));
  --space-l-2xl: clamp(calc(var(--dl-space-min) * 2rem), calc(var(--dl-space-min) * 2rem + (var(--dl-space-max) * 4 - var(--dl-space-min) * 2) * var(--dl-fluid)), calc(var(--dl-space-max) * 4rem));

  /* ---- Corners ---- */
  --radius-s: calc(var(--radius-base) * 0.5px);
  --radius-m: calc(var(--radius-base) * 1px);
  --radius-l: calc(var(--radius-base) * 1.6px);
  --radius-pill: 999px;
}

/* The leading and tracking gates need tan(), atan2() and log() (Chrome 120, Firefox 118, Safari 15.4).
   Without them the gates stay undefined, so dials-base.css keeps headings at --leading-display (or 1.15)
   and leaves letter spacing alone. */
@supports (width: calc(1px * tan(atan2(1px, 1px)) * log(2))) {
  :root, [data-dials], :host {
    --dl-leading-on: calc(var(--leading) + 0px * var(--leading-body, var(--leading-display)));
    --dl-tracking-on: calc(var(--tracking) + 0em * var(--tracking-small, var(--tracking-display)));
  }
}
/* ============================================================
   Dials: the fallback (src/fallback.css, built into the end of dials.css)
   For browsers with color-mix() but without relative colour or
   light-dark(): Chrome and Edge 111-122, Safari 16.2-17, Firefox
   113-127. They can't work out the derived chain above, so this
   block works every public colour token out again from the same
   dials, with color-mix() alone. It comes after the chain and uses
   the same selectors, so it wins there; a site's own file, loaded
   after dials.css, still wins over it. It never sets a dial.
   Approximations, held to the same contrast as the chain (the
   contrast check's --fallback mode):
   - The page is light. .is-dark bands are dark, .is-light bands light.
   - Paper and ink come from --grey at fixed mixes, so the four
     lightness dials, --balance, --dark-lift, --tint-vividness and
     --text-contrast have no effect. --paper-light and friends do.
   - on-solid text can't follow the fill's luminance: each group has a
     fixed choice, and its fill is pulled a fixed amount towards the
     other end so the text keeps 4.5:1 in every Dials theme. White on
     brand, secondary, danger and info, whose fills are darkened; black
     on success, whose fill is lightened, and warning, as set.
   - Coloured text and lines can't move only as far as their target
     needs: on-soft is the dial mixed a fixed amount into ink (so --link
     and --focus too), line a smaller amount, and --link-hover further
     still. The amounts hold 4.5:1 and 3:1 on every surface and soft
     tint, for every theme and for extreme dials, so they over-shoot for
     most colours. Ink is near-black on a light page and near-white in an
     .is-dark band, so the same mix works in both.
   - No calc() and no percentages computed inside color-mix(): only
     literal percentages and dials that are one (--tint-strength).
   ============================================================ */
@supports not ((color: oklch(from red l c h)) and (color: light-dark(red, red))) {
  /* ---- Internal: the scheme switches, literal percentages a band can flip ---- */
  :root, :host, .is-light {
    color-scheme: light;
    --dl-fb-dark: 0%;     /* how much of the dark paper and ink to use */
    --dl-fb-raise: 38%;   /* how much white lifts --surface-raised */
    --dl-fb-shadow: 10%;  /* the strength of shadows */
  }
  .is-dark {
    color-scheme: dark;
    --dl-fb-dark: 100%;
    --dl-fb-raise: 4%;
    --dl-fb-shadow: 45%;
  }

  /* Bands are declared here too, so every token is worked out again in a band's own scheme */
  :root, [data-dials], :host, .is-light, .is-dark {
    /* ---- Internal: paper, ink and the six fills ---- */
    --dl-paper-light: var(--paper-light, color-mix(in oklab, var(--grey) 20%, white));
    --dl-paper-dark:  var(--paper-dark,  color-mix(in oklab, var(--grey) 30%, black));
    --dl-ink-light:   var(--ink-light,   color-mix(in oklab, var(--grey) 34%, black));
    --dl-ink-dark:    var(--ink-dark,    color-mix(in oklab, var(--grey) 17%, white));
    --dl-paper: color-mix(in oklab, var(--dl-paper-dark) var(--dl-fb-dark), var(--dl-paper-light));
    --dl-ink:   color-mix(in oklab, var(--dl-ink-dark) var(--dl-fb-dark), var(--dl-ink-light));
    --dl-brand:   color-mix(in oklab, var(--brand) 72%, black);
    --dl-secondary: color-mix(in oklab, var(--accent, var(--secondary)) 67%, black);
    --dl-success: color-mix(in oklab, var(--success) 85%, white);
    --dl-warning: var(--warning);
    --dl-danger:  color-mix(in oklab, var(--danger) 78%, black);
    --dl-info:    color-mix(in oklab, var(--info) 61%, black);

    /* ---- Surfaces ---- */
    --surface:         var(--dl-paper);
    --surface-raised:  color-mix(in oklab, white var(--dl-fb-raise), var(--dl-paper));
    --surface-lowered: color-mix(in oklab, var(--dl-ink) 4%, var(--dl-paper));
    --surface-sunken:  color-mix(in oklab, var(--dl-ink) 8%, var(--dl-paper));
    --surface-overlay: color-mix(in oklab, black 45%, transparent);

    /* ---- Text: a step stronger than the chain's defaults, to cover --text-contrast ---- */
    --text-strong:   var(--dl-ink);
    --text:          color-mix(in oklab, var(--dl-ink) 94%, var(--dl-paper));
    --text-muted:    color-mix(in oklab, var(--dl-ink) 89%, var(--dl-paper));
    --text-quiet:    color-mix(in oklab, var(--dl-ink) 86%, var(--dl-paper));
    --text-disabled: color-mix(in oklab, var(--dl-ink) 38%, var(--dl-paper));
    --link:          var(--brand-on-soft);
    --link-hover:    color-mix(in oklab, var(--brand) 20%, var(--dl-ink));

    /* ---- Lines and effects ---- */
    --border-quiet:  color-mix(in oklab, var(--dl-ink) 7%, var(--dl-paper));
    --border:        color-mix(in oklab, var(--dl-ink) 13%, var(--dl-paper));
    --border-strong: color-mix(in oklab, var(--dl-ink) 64%, var(--dl-paper));
    --focus:         var(--brand-on-soft);
    --selection:     color-mix(in oklab, var(--brand) 22%, var(--dl-paper));
    --shadow-color:  color-mix(in oklab, black var(--dl-fb-shadow), transparent);
    --shadow-s: 0 1px 3px var(--shadow-color);
    --shadow-m: 0 4px 14px var(--shadow-color);
    --shadow-l: 0 12px 32px var(--shadow-color);
    --mix-hover:  black 12%;
    --mix-active: black 22%;

    /* ---- Groups: soft mixed into paper, on-soft and line mixed towards ink ---- */
    --brand-solid:    var(--dl-brand);
    --brand-on-solid: white;
    --brand-soft:     color-mix(in oklab, var(--brand) var(--tint-strength), var(--dl-paper));
    --brand-on-soft:  color-mix(in oklab, var(--brand) 26%, var(--dl-ink));
    --brand-line:     color-mix(in oklab, var(--brand) 40%, var(--dl-ink));

    --secondary-solid:    var(--dl-secondary);
    --secondary-on-solid: white;
    --secondary-soft:     color-mix(in oklab, var(--accent, var(--secondary)) var(--tint-strength), var(--dl-paper));
    --secondary-on-soft:  color-mix(in oklab, var(--accent, var(--secondary)) 26%, var(--dl-ink));
    --secondary-line:     color-mix(in oklab, var(--accent, var(--secondary)) 40%, var(--dl-ink));

    --neutral-solid:    var(--dl-ink);
    --neutral-on-solid: var(--dl-paper);
    --neutral-soft:     var(--surface-lowered);
    --neutral-on-soft:  var(--text);
    --neutral-line:     var(--border);

    --success-solid:    var(--dl-success);
    --success-on-solid: black;
    --success-soft:     color-mix(in oklab, var(--success) var(--tint-strength), var(--dl-paper));
    --success-on-soft:  color-mix(in oklab, var(--success) 26%, var(--dl-ink));
    --success-line:     color-mix(in oklab, var(--success) 40%, var(--dl-ink));

    --warning-solid:    var(--dl-warning);
    --warning-on-solid: black;
    --warning-soft:     color-mix(in oklab, var(--warning) var(--tint-strength), var(--dl-paper));
    --warning-on-soft:  color-mix(in oklab, var(--warning) 26%, var(--dl-ink));
    --warning-line:     color-mix(in oklab, var(--warning) 40%, var(--dl-ink));

    --danger-solid:    var(--dl-danger);
    --danger-on-solid: white;
    --danger-soft:     color-mix(in oklab, var(--danger) var(--tint-strength), var(--dl-paper));
    --danger-on-soft:  color-mix(in oklab, var(--danger) 26%, var(--dl-ink));
    --danger-line:     color-mix(in oklab, var(--danger) 40%, var(--dl-ink));

    --info-solid:    var(--dl-info);
    --info-on-solid: white;
    --info-soft:     color-mix(in oklab, var(--info) var(--tint-strength), var(--dl-paper));
    --info-on-soft:  color-mix(in oklab, var(--info) 26%, var(--dl-ink));
    --info-line:     color-mix(in oklab, var(--info) 40%, var(--dl-ink));

    /* ---- Ungrouped ---- */
    --solid:    var(--brand-solid);
    --on-solid: var(--brand-on-solid);
    --soft:     var(--brand-soft);
    --on-soft:  var(--brand-on-soft);
    --line:     var(--brand-line);

    /* ---- Deprecated: the old names for the secondary group ---- */
    --accent-solid:    var(--secondary-solid);
    --accent-on-solid: var(--secondary-on-solid);
    --accent-soft:     var(--secondary-soft);
    --accent-on-soft:  var(--secondary-on-soft);
    --accent-line:     var(--secondary-line);
  }
  /* the group classes again, so they still win on a [data-dials] element or a band */
  .is-brand     { --solid: var(--brand-solid);     --on-solid: var(--brand-on-solid);     --soft: var(--brand-soft);     --on-soft: var(--brand-on-soft);     --line: var(--brand-line); }
  .is-secondary { --solid: var(--secondary-solid); --on-solid: var(--secondary-on-solid); --soft: var(--secondary-soft); --on-soft: var(--secondary-on-soft); --line: var(--secondary-line); }
  .is-neutral   { --solid: var(--neutral-solid);   --on-solid: var(--neutral-on-solid);   --soft: var(--neutral-soft);   --on-soft: var(--neutral-on-soft);   --line: var(--neutral-line); }
  .is-success   { --solid: var(--success-solid);   --on-solid: var(--success-on-solid);   --soft: var(--success-soft);   --on-soft: var(--success-on-soft);   --line: var(--success-line); }
  .is-warning   { --solid: var(--warning-solid);   --on-solid: var(--warning-on-solid);   --soft: var(--warning-soft);   --on-soft: var(--warning-on-soft);   --line: var(--warning-line); }
  .is-danger    { --solid: var(--danger-solid);    --on-solid: var(--danger-on-solid);    --soft: var(--danger-soft);    --on-soft: var(--danger-on-soft);    --line: var(--danger-line); }
  .is-info      { --solid: var(--info-solid);      --on-solid: var(--info-on-solid);      --soft: var(--info-soft);      --on-soft: var(--info-on-soft);      --line: var(--info-line); }
  .is-accent    { --solid: var(--secondary-solid); --on-solid: var(--secondary-on-solid); --soft: var(--secondary-soft); --on-soft: var(--secondary-on-soft); --line: var(--secondary-line); }
}
/* Generated by tools/fallback.mjs from dials.css (src/colour.css 93ca251ad22dc853): the Hi-Fi defaults in
   the light scheme. Don't edit. The last resort, for browsers without color-mix() (Chrome and Edge
   before 111, Safari before 16.2, Firefox before 113, all 2022 or older): they can't work anything
   out, so every colour token is flat and they get the house colours, light only. Colour dials have no
   effect there; type and space work as normal. */
@supports not (color: color-mix(in srgb, red, blue)) {
  :root, [data-dials], :host, .is-light, .is-dark {
    color-scheme: light;
    --surface: #e6e5e3;
    --surface-raised: #efefee;
    --surface-lowered: #dcdcda;
    --surface-sunken: #d3d2d1;
    --surface-overlay: rgb(0 0 0 / 45%);
    --text-strong: #1a1916;
    --text: #32312e;
    --text-muted: #4f4e4c;
    --text-quiet: #5b5a58;
    --text-disabled: #91908e;
    --link: #875505;
    --link-hover: #663900;
    --border-quiet: #d5d5d3;
    --border: #c8c7c5;
    --border-strong: #807f7d;
    --focus: #875505;
    --selection: #ead6c0;
    --shadow-color: rgb(0 0 0 / 10%);
    --shadow-s: 0 1px 3px rgb(0 0 0 / 10%);
    --shadow-m: 0 4px 14px rgb(0 0 0 / 10%);
    --shadow-l: 0 12px 32px rgb(0 0 0 / 10%);
    --mix-hover: black 12%;
    --mix-active: black 22%;
    --brand-solid: #f39c12;
    --brand-on-solid: #000000;
    --brand-soft: #e7e0d8;
    --brand-on-soft: #875505;
    --brand-line: #ac6d09;
    --secondary-solid: #2ec4b6;
    --secondary-on-solid: #000000;
    --secondary-soft: #dae3e1;
    --secondary-on-soft: #156b63;
    --secondary-line: #1d897f;
    --neutral-solid: #1a1916;
    --neutral-on-solid: #e6e5e3;
    --neutral-soft: #dcdcda;
    --neutral-on-soft: #32312e;
    --neutral-line: #c8c7c5;
    --success-solid: #3fbf55;
    --success-on-solid: #000000;
    --success-soft: #dae2da;
    --success-on-soft: #206e2e;
    --success-line: #2c8c3c;
    --warning-solid: #f2c230;
    --warning-on-solid: #000000;
    --warning-soft: #e6e3da;
    --warning-on-soft: #755d12;
    --warning-line: #95771a;
    --danger-solid: #e0322b;
    --danger-on-solid: #000000;
    --danger-soft: #eadbd9;
    --danger-on-soft: #b72721;
    --danger-line: #e0322b;
    --info-solid: #3b82c4;
    --info-on-solid: #000000;
    --info-soft: #dae0e6;
    --info-on-soft: #2b6396;
    --info-line: #397ebf;
    --accent-solid: #2ec4b6;
    --accent-on-solid: #000000;
    --accent-soft: #dae3e1;
    --accent-on-soft: #156b63;
    --accent-line: #1d897f;
  }
}
/* ═══ dials:end (Dials) ═════════════════════════════════════════════════ */

/* ═══ This site's dials ═════════════════════════════════════════════════
 * The ONLY place a colour or a scale value is typed. The values reproduce
 * the site's look before Dials (the practice's Elementor kit and the scale
 * knobs fitted to live on 2026-10-03), so it looks the same. Light only, as
 * live.
 * ═══════════════════════════════════════════════════════════════════════ */
:root {
    color-scheme: light;   /* light only, as live: the practice has no dark palette */

    /* Colour dials: the kit's own hex, written as HSL to one decimal place,
     * which paints the same hex (in each comment). Each is a group with five
     * roles: --brand-solid, --brand-on-solid, --brand-soft, --brand-on-soft
     * and --brand-line.
     *  - The kit's primary and its "Crimson Red" both take white lettering
     *    (4.7:1 and 4.8:1), so their fills paint the hex itself.
     *  - The secondary is a pale sage: it is a ground and a rule colour here
     *    (the nav panel, tiles, FAQ items, hairlines), read as the dial, so
     *    it paints the hex in every browser.
     *  - The kit's other named colours (its "Text" ink, "Accent", "Cream",
     *    and the salmon cards) are site patterns derived from these dials, in
     *    the site layer's first :root. */
    --brand: hsl(196.8 22.7% 43.1%);     /* #557987, the kit's primary: tiles, panels, the alert line, icons, the header bar's gradient */
    --secondary: hsl(180 13% 72.9%);     /* #B1C3C3, the kit's secondary: the nav panel, tiles, FAQ items, hairlines */
    --tertiary: hsl(9.9 56.3% 48.4%);    /* #C14D36, "Crimson Red": every button, eyebrows, links, outlines */
    --success: hsl(126 46% 33%);         /* the status colours: the template's */
    --warning: hsl(37 74% 54%);          /* #E19E33; the kit's Cream is derived from it */
    --danger: hsl(3 56% 48%);
    --info: hsl(202 64% 41%);
    --grey: hsl(204 6% 50%);             /* the hue and strength of the kit's "Grey" #272A2C; paper and ink are exact below */

    /* Paper and ink, exact. The kit's "White" page, and an ink that puts
     * Dials' body text (--text, 86% of the ink into the paper) on the kit's
     * "Grey" #272A2C exactly: the card copy, lists and most of the site's
     * text. The ink itself, --text-strong, is the body copy and the field
     * text: #0C0F11, where live's is the kit's "Black" #000B0C. */
    --paper-light: hsl(0 0% 100%);       /* #FFFFFF */
    --ink-light: hsl(204 17.2% 5.7%);    /* #0C0F11 */

    /* Type and space: the scale the site already had (the template's eight
     * knobs, refitted to live on 2026-10-03). Body 15px on a 390px phone (the
     * owner's floor; live shrinks to 13.2) to live's 16.5 at 1440, each step
     * 1.12x (phone) to 1.145x (desktop) the last. --size-max 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.
     * Px at 1440 (390), live -> ours:
     *   fine print 12.38           -> size--2  12.58 (11.96)
     *   labels, buttons 14.44      -> size--1  14.41 (13.39)
     *   body 16.5                  -> size-0   16.50 (15.00)
     *   eyebrows, ledes 18.56      -> size-1   18.89 (16.80)
     *   card titles 20.63          -> size-2   21.63 (18.82)
     *   hours title, years 24.75   -> size-3   24.77 (21.07)
     *   band titles 33             -> size-5   32.47 (size-4 23.60 on a phone)
     *   about and hub titles 41.25 -> size-7   42.57 (size-6 29.62 on a phone)
     * Space: live's 10/20/30/40/60/80/120 rhythm is the ladder on a 20px
     * --space-s at 1440, so 1440 lands on it (Dials' --space-3xs is 5px
     * there; the old scale's was 6); a phone is 20% tighter (owner decision
     * 2026-10-03: spacing scales). */
    --screen-min: 390;
    --screen-max: 1440;
    --size-min: 15;
    --size-max: 16.4992;
    --ratio-min: 1.12;
    --ratio-max: 1.145;
    --space-min: 16;
    --space-max: 20;
    --space-density: 1;

    /* Type (Dials v0.3): weight, line height and letter spacing. Weights:
     * body 500 (Raleway Medium, live's body copy); headings, bold runs,
     * buttons and the eyebrows 700 (--weight-heading, and Dials'
     * --weight-strong, the body weight plus 200). Live sets line height by
     * role, not by size, and the site's rules read these two as numbers, so
     * each holds at every size rather than following Dials' size curve:
     * running text 1.5 (--leading-body) and the band titles 1.3
     * (--leading-display). Letter spacing: live tracks nothing but one run
     * of capitals ("WHY CHOOSE US?", 0.04em, --tracking-caps), so
     * --tracking-small and --tracking-display stay unset (0). */
    --leading-body: 1.5;
    --leading-display: 1.3;
    --tracking-caps: 0.04;
    --weight-body: 500;
    --weight-heading: 700;
    --line-length: 65ch;
    /* Port Sorell's own type tokens: live's role-by-role values that the
     * dials do not hold. Dials' size curve runs one straight line from body
     * to display leading, so it lands none of these at the sizes live uses
     * them; and Dials has one weight above the body's where live also sets
     * a regular, a semibold and a heavy. */
    --leading-card: 1.4;           /* Merriweather card and group titles, the nav, the pills */
    --leading-title: 1.2;          /* the 41px About and Patient Hub titles (live's 41.25 on 49.5) */
    --leading-footer-link: 1.25;   /* the footer's quick links, stacked on a phone */
    --leading-notes: 2;            /* the hours card's notes (Manrope, 14.4 on 28.8) */
    --weight-regular: 400;         /* Raleway Regular: the hours notes, tiles' copy, the footer tagline, field text and labels, doctors' qualifications */
    --weight-semibold: 600;        /* Raleway and Manrope SemiBold: the footer's links and copyright, doctors' roles, the hours times, sub-menus */
    --weight-heavy: 800;           /* Merriweather Black: the band titles and the About card buttons */

    /* Corners: --radius-l 20px (the header bar, photos), --radius-m 12.5px
     * (the phone nav panel), --radius-s 6.25px. The 15px cards, 10px photos
     * and 5px menus are the site's own corners (site layer). */
    --radius-base: 12.5;
    --border-width-l: 4px;

    /* Faces: Raleway for body, Merriweather for headings and the nav,
     * Manrope for the footer's link lists and the hours notes (--font-accent),
     * all from Google Fonts in each page's <head>. Three families, because
     * live has three. */
    --font-body: "Raleway", system-ui, sans-serif;
    --font-heading: "Merriweather", Georgia, serif;
    --font-accent: "Manrope", system-ui, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ── The tertiary group ───────────────────────────────────────────────────
 * A third brand colour, typically doing button and CTA work, that is neither
 * a tint of the brand nor a status colour (practices routinely have one:
 * "Button Brown", "Morning Orange"). Dials has no third brand group, so the
 * template adds one with the same five roles, worked out the way Dials v0.2.0
 * works out its own groups (each formula is Dials' brand formula with the
 * tertiary colour in it), from public tokens only. Set --tertiary above;
 * never set these. class="is-tertiary" points --solid and friends at it,
 * like .is-secondary. Declared on bands too, so a band's group follows the
 * band's own scheme.
 *
 *   --tertiary-on-soft  the fill, moved only as far as 4.5:1 needs on the
 *                       least contrasting of its soft tint, --surface-lowered
 *                       and --surface-raised; a colour that passes is kept
 *   --tertiary-line     the dial, moved only as far as 3:1 needs, the same way
 *
 * Dials carries the numbers those two need in its internal --dl-* plumbing,
 * which nothing outside Dials may read, so the template works the same
 * numbers out again from public tokens in its own --tpl-* properties: the
 * luminance of --surface-lowered and --surface-raised (Dials' --dl-surfaces-y)
 * and of the soft tint, and the colour carrying its target. They are the
 * template's plumbing: never use or set a --tpl-* property anywhere else. */
:root, [data-dials], .is-light, .is-dark {
    --tpl-tertiary-base:  oklch(from var(--tertiary) calc(l + (var(--fill-lightness) - l) * var(--balance)) c h);
    --tertiary-solid:     light-dark(var(--tpl-tertiary-base), oklch(from var(--tpl-tertiary-base) calc(l + var(--dark-lift)) c h));
    --tertiary-on-solid:  color(from var(--tertiary-solid) srgb-linear calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) calc(clamp(0, (clamp(0.175, var(--white-text-until), 0.18333) - (0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))) * 1000000, 1)) / 1);
    --tertiary-soft:      oklch(from color-mix(in oklab, light-dark(oklch(from var(--tertiary-solid) max(l, 0.7) c h), oklch(from var(--tertiary-solid) min(l, 0.6) c h)) var(--tint-strength), oklch(from var(--surface) l 0 h)) l calc(c * var(--tint-vividness)) h);
    --tpl-surfaces-y:     color-mix(in srgb-linear, color(from var(--surface-lowered) srgb-linear 0 calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1)) 0), color(from var(--surface-raised) srgb-linear 0 0 calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1))));
    --tpl-tertiary-under: color-mix(in srgb-linear, color(from var(--tertiary-soft) srgb-linear calc(0.2126 * clamp(0, r, 1) + 0.7152 * clamp(0, g, 1) + 0.0722 * clamp(0, b, 1)) 0 0), var(--tpl-surfaces-y));
    --tpl-tertiary-text:  color-mix(in srgb-linear, color(from var(--tpl-tertiary-base) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--tpl-tertiary-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (4.5 + 0.1) - 0.05), 1))), color(from var(--tpl-tertiary-under) srgb-linear 0 0 0 / calc(clamp(0, (4.5 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
    --tpl-tertiary-line:  color-mix(in srgb-linear, color(from var(--tertiary) srgb-linear clamp(0, r, 1) clamp(0, g, 1) clamp(0, b, 1) / 1), light-dark(color(from var(--tpl-tertiary-under) srgb-linear 0 0 0 / calc(clamp(0, 3 * ((min(2 * r, 4 * g, 4 * b) + 0.05) / (3 + 0.1) - 0.05), 1))), color(from var(--tpl-tertiary-under) srgb-linear 0 0 0 / calc(clamp(0, (3 + 0.1) * (max(2 * r, 4 * g, 4 * b) + 0.05) - 0.05, 1)))));
    --tertiary-on-soft:   light-dark(color(from var(--tpl-tertiary-text) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--tpl-tertiary-text) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));
    --tertiary-line:      light-dark(color(from var(--tpl-tertiary-line) srgb-linear calc(r * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(g * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) calc(b * 2 * alpha * min(1, (2 * alpha - 1) / 3 / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / 1), color(from color(from var(--tpl-tertiary-line) srgb-linear min(1, r * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, g * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) min(1, b * 2 * alpha * max(1, (2 * alpha - 1) / max(0.000001, 2 * alpha * (0.2126 * r + 0.7152 * g + 0.0722 * b)))) / alpha) srgb-linear calc(r + (1 - r) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(g + (1 - g) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) calc(b + (1 - b) * clamp(0, (2 * alpha - 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) / max(0.000001, 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b)), 1)) / 1));
}
.is-tertiary { --solid: var(--tertiary-solid); --on-solid: var(--tertiary-on-solid); --soft: var(--tertiary-soft); --on-soft: var(--tertiary-on-soft); --line: var(--tertiary-line); }
/* The tertiary group in older browsers: without relative colour or
 * light-dark() (iOS 16 and 17, Safari before 18, Chrome and Edge before 123,
 * Firefox before 128) the derivation above cannot be worked out, and Dials'
 * own fallback covers only Dials' groups. So, the way Dials' fallback does
 * its groups, under the same condition and with the same selectors as the
 * derivation: the five roles again with color-mix(in oklab, ...) alone, from
 * --tertiary and the paper (--surface) and ink (--text-strong) Dials'
 * fallback has already worked out. As in Dials v0.2.0's fallback, on-soft is
 * the colour mixed 26% into ink and the line 40% into ink; neither can move
 * only as far as it needs there, so both over-shoot for most colours. Text
 * on the fill is a fixed white, with the fill pulled towards black as Dials
 * pulls --brand (72%), so it keeps 4.5:1. A site with a very light
 * --tertiary checks it: check-contrast.mjs --fallback. */
@supports not ((color: oklch(from red l c h)) and (color: light-dark(red, red))) {
    :root, [data-dials], .is-light, .is-dark {
        --tertiary-solid:    color-mix(in oklab, var(--tertiary) 72%, black);
        --tertiary-on-solid: white;
        --tertiary-soft:     color-mix(in oklab, var(--tertiary) var(--tint-strength), var(--surface));
        --tertiary-on-soft:  color-mix(in oklab, var(--tertiary) 26%, var(--text-strong));
        --tertiary-line:     color-mix(in oklab, var(--tertiary) 40%, var(--text-strong));
    }
}

/* "Crimson Red" in Dials' fallback browsers. The template's tertiary
 * fallback above pulls the fill 72% towards black for white lettering; the
 * crimson already carries white at 4.8:1, so here it stays the crimson, as
 * modern browsers paint it (Dials' fallback rule: a fixed white on-solid). */
@supports not ((color: oklch(from red l c h)) and (color: light-dark(red, red))) {
    :root, [data-dials], .is-light, .is-dark {
        --tertiary-solid: var(--tertiary);
        --tertiary-on-solid: white;
    }
}

/* ── The template's own tokens ────────────────────────────────────────────
 * What Dials does not cover: the narrow measure, the grid, the shared control
 * corner, the tap target, layers and motion. None of them is a colour, a text
 * size, a space size or a type setting: line height, letter spacing and
 * weight are Dials' type dials and tokens since v0.3 (the template's old
 * --leading-*, --tracking-* and --weight-* are in "Old names" below). */
:root {
    /* --- Weight -------------------------------------------------------- */
    /* THREE WEIGHTS, DELIBERATELY, all from the dials: body (--weight-body),
     * emphasis (--weight-strong: nav, labels, buttons, eyebrows, strong) and
     * headline (--weight-heading). A fourth needs a reason: the face has a
     * visibly distinct cut AND the three are not creating enough contrast. A
     * flat hierarchy is almost always a spacing or size problem, not a
     * weight problem. */

    /* --- Measure ------------------------------------------------------- */
    --measure: var(--line-length);   /* body copy: the --line-length dial */
    --measure-tight: 45ch;           /* card and caption copy */

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

    /* --- Corners beyond Dials' three ----------------------------------- */
    --radius-xs: calc(var(--radius-base) * 0.333px);  /* tags, inline chips, the focus ring: a third of --radius-m, so it follows --radius-base */
    --radius-round: 50%;                   /* avatars */
    --control-radius: var(--radius-s);     /* buttons AND fields: a site sets this once, both follow */

    /* --- Touch targets ------------------------------------------------- */
    /* The smallest box a finger hits reliably: 44px (WCAG 2.5.5, Apple's
     * HIG). A fixed dimension rather than spacing, so it does not scale. */
    --target-min: 2.75rem;

    /* --- Inset shadows, from Dials' --shadow-color ------------------------ */
    --shadow-inner-s: inset 0 1px 2px 0 var(--shadow-color);
    --shadow-inner-m: inset 0 2px 6px 0 var(--shadow-color);

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

/* ═══ Old names ═══ aliases:begin ═══════════════════════════════════════
 * The template's token names before Dials (#426), each pointing at the Dials
 * token that replaces it, so markup, the Form controls section and any site
 * layer written against them keep working until #427 migrates the live
 * sites. NEVER use one in new work: use the name on the right. Delete this
 * whole block (down to aliases:end) once nothing reads any of them.
 *
 * Declared on [data-dials] and the .is-light/.is-dark bands as well as
 * :root, so a re-themed scope's or a band's aliases follow its own dials and
 * scheme, as Dials' own tokens do (its fallback works them out again there). Names Dials took over with a new meaning are NOT
 * here: --surface is now the PAGE (the old raised --surface is
 * --surface-raised), --secondary is the second brand colour's dial (it used
 * to be its fill: that is --secondary-solid), --accent is that dial's old
 * Dials name (deprecated in Dials v0.2.0: never set it), --success/--warning/
 * --danger/--info/--tertiary are dials (the fill is --success-solid ...), and --border, --border-strong, --space-*,
 * --radius-s/m/l, --shadow-* and --font-* are Dials' own. The --u-*,
 * --palette-*, --hue-*, --chroma-*, --l-* and --scheme dials are gone: set
 * the Dials dials instead. */
:root, [data-dials], .is-light, .is-dark {
    --primary: var(--brand-solid);
    --primary-hover: light-dark(oklch(from var(--brand-solid) calc(l - 0.07) c h), oklch(from var(--brand-solid) calc(l + 0.07) c h));
    --primary-light: oklch(from var(--brand-solid) calc(l + 0.11) c h);
    --primary-muted: color-mix(in oklab, var(--brand-solid) 15%, var(--surface));
    --primary-pale: var(--brand-soft);
    --on-primary: var(--brand-on-solid);
    --secondary-hover: light-dark(oklch(from var(--secondary-solid) calc(l - 0.07) c h), oklch(from var(--secondary-solid) calc(l + 0.07) c h));
    --secondary-light: oklch(from var(--secondary-solid) calc(l + 0.11) c h);
    --secondary-pale: var(--secondary-soft);
    --on-secondary: var(--secondary-on-solid);
    --tertiary-hover: light-dark(oklch(from var(--tertiary-solid) calc(l - 0.07) c h), oklch(from var(--tertiary-solid) calc(l + 0.07) c h));
    --tertiary-pale: var(--tertiary-soft);
    --on-tertiary: var(--tertiary-on-solid);
    --accent-dark: var(--primary-hover);
    --accent-pale: var(--brand-soft);
    --success-pale: var(--success-soft);
    --warning-pale: var(--warning-soft);
    --danger-pale: var(--danger-soft);
    --info-pale: var(--info-soft);
    --ink-strong: var(--text-strong);
    --ink: var(--text);
    --ink-mid: var(--text-muted);
    --ink-soft: var(--text-quiet);
    --bg: var(--surface);
    --on-bg: var(--text);
    --on-surface: var(--text);
    --step--2: var(--size--2);
    --step--1: var(--size--1);
    --step-0: var(--size-0);
    --step-1: var(--size-1);
    --step-2: var(--size-2);
    --step-3: var(--size-3);
    --step-4: var(--size-4);
    --step-5: var(--size-5);
    --step-6: var(--size-6);
    --step-7: var(--size-7);
    --step-8: var(--size-8);
    --border-thin: var(--border-width-s);
    --border-medium: var(--border-width-m);
    --border-thick: var(--border-width-l);

    /* The template's type ladder before Dials v0.3 (#436), FROZEN at its old
     * values, so a site layer written against it renders exactly as it did.
     * They do not follow the type dials, and the template reads none of them:
     * line height is var(--leading), letter spacing var(--tracking) (in
     * capitals var(--tracking-caps-total)), weight var(--weight-body),
     * var(--weight-strong) or var(--weight-heading). check-system.sh accepts
     * these values only exactly as written here. */
    --weight-400: 400;
    --weight-600: 600;
    --weight-700: 700;
    --leading-xs: 1.05;
    --leading-s: 1.18;
    --leading-m: 1.3;
    --leading-l: 1.5;
    --leading-xl: 1.6;
    --tracking-xs: -0.02em;
    --tracking-s: -0.01em;
    --tracking-m: 0;
    --tracking-l: 0.04em;
    --tracking-xl: 0.08em;
}
/* ═══ aliases:end (Old names) ═══════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════
 * 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: the base layer's body rule, from --leading-body */
}

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

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

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

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

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

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

body {
    font-family: var(--font-body);
    font-size: var(--size-0);
    font-weight: var(--weight-body);
    line-height: var(--leading-body);   /* a number, so it inherits as one; --leading is a length */
    color: var(--text);
    background: var(--surface);
}

/* 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-heading);
    line-height: var(--leading);        /* for each heading's own size: on the heading, never inherited */
    letter-spacing: var(--tracking);
    color: var(--text-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(--size-5); }
h2, .h2 { font-size: var(--size-4); }
h3, .h3 { font-size: var(--size-3); }
h4, .h4 { font-size: var(--size-2); }
h5, .h5 { font-size: var(--size-1); }
h6, .h6 {
    font-size: var(--size-0);
    letter-spacing: var(--tracking-caps-total);   /* capitals */
    text-transform: uppercase;
}

/* Dials' --leading and --tracking need log() and atan2() (Chrome and Edge
 * 120, Firefox 118, Safari 15.4). Without them Dials cannot work them out, so
 * under Dials' own condition a heading keeps --leading-display, as
 * dials-base.css does; everything else inherits the body's --leading-body,
 * and letter spacing is left alone. */
@supports not (width: calc(1px * tan(atan2(1px, 1px)) * log(2))) {
    h1, h2, h3, h4, h5, h6,
    .h1, .h2, .h3, .h4, .h5, .h6,
    .notfound__code { line-height: var(--leading-display); }
}

/* 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(--on-soft);   /* coloured text on the page */
}

/* 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(--line-length); }
.measure-tight { max-width: var(--measure-tight); }

/* Opening paragraph: larger and looser than body copy. */
.lede {
    font-size: var(--size-1);
    line-height: var(--leading);
    letter-spacing: var(--tracking);
    color: var(--text-muted);
}

/* Small label above a heading. */
.eyebrow {
    display: block;
    margin-bottom: var(--space-2xs);
    font-size: var(--size--1);
    font-weight: var(--weight-strong);
    line-height: var(--leading);
    letter-spacing: var(--tracking-caps-total);   /* capitals */
    text-transform: uppercase;
    color: var(--on-soft);
}

small, .text-small { font-size: var(--size--1); line-height: var(--leading); letter-spacing: var(--tracking); }

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

a {
    color: var(--link);
    text-decoration-thickness: var(--border-width-s);
    text-underline-offset: 0.15em;
    transition: color var(--duration-fast) var(--ease-out);
}
a:hover { color: var(--link-hover); }

/* The focus ring lives in "Form controls & focus" below. */

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 {
    /* The quote bar is a quiet border in the group's colour: Dials' subtle
     * border pattern (tokens.md, "A subtle border in a group's colour"),
     * declared here rather than at :root so it follows an .is-* class on the
     * quote. --line itself is a strong 3:1 line since Dials v0.2.0; 30% of
     * it keeps the bar about as light as it was before (the pattern's
     * example is 40%: a step darker). Decoration: no contrast promised. */
    --quote-bar: color-mix(in oklab, var(--line) 30%, var(--border));
    padding-left: var(--space-m);
    border-left: var(--border-width-l) solid var(--quote-bar);
    color: var(--text-muted);
    font-style: italic;
}

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

code, kbd, samp, pre {
    font-family: var(--font-mono);
    font-size: 0.9em;
}

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

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

figure { margin-inline: 0; }

figcaption {
    margin-top: var(--space-2xs);
    font-size: var(--size--1);
    line-height: var(--leading);
    letter-spacing: var(--tracking);
    color: var(--text-quiet);
}

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

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

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

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

/* ═══ Form controls & focus ═══ form-controls:begin ══════════════════════
 * A text field's look, and every focus ring on the site, are set ONCE,
 * here: by the --field-* and --focus-ring* tokens and a few base rules.
 * Every text-like control on the site (contact, search, careers, booking,
 * anything mediflare.js or Connect writes) inherits it, so they match by
 * construction.
 *
 * - This section is copied VERBATIM from _template and never edited in a
 *   site: check-system.sh fails the site if its copy differs by a character.
 *   A site differs only in TOKEN VALUES, set in the site layer's own :root,
 *   below this section (a later :root wins over the defaults here).
 * - Never restyle a control inside a component. A component rule may place
 *   a field (grid, margin, width) but never sets its border, radius,
 *   background or height -- check-system.sh fails the site if one does.
 * - Fields and buttons share ONE corner, --control-radius: set it in the
 *   site layer's :root and both follow. Never set --field-radius
 *   (check-system.sh fails it), except to 0px 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-width-s) solid <colour> and
 *   --field-radius: 0px (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 0px.
 * - Colours follow the band. The colour tokens are declared on the page
 *   AND on every .is-light/.is-dark band and [data-dials] scope, as Dials
 *   declares its own: a browser on Dials' fallback (no relative colour)
 *   works a token out once per scope, so declared on :root alone a field
 *   in a dark band kept the light page's border and ring. A site that
 *   changes a field COLOUR sets it on the same four selectors, after this
 *   section (:root, [data-dials], .is-light, .is-dark { --field-...: ... }),
 *   or a band keeps the default. Sizes are set on :root only.
 * - A panel on a ground that is not a Dials surface (a brand fill) re-sets
 *   the leaf colour tokens on the container, never the rules:
 *     .brand-panel {
 *         --focus-ring: var(--brand-on-solid);
 *         --field-border: var(--brand-on-solid);
 *     }
 *   --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(--size-0), 1rem);  /* never below 16px, or iOS zooms the page on focus */
    --field-leading: var(--leading);              /* Dials' leading, worked out at the field's own size */
    --field-weight: var(--weight-body);           /* 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-border-w: var(--border-width-s);
    /* 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-w: var(--border-width-m);        /* >= --field-border-w, so the ring covers the border */
}

/* The colours, on the bands too (see above). */
:root, [data-dials], .is-light, .is-dark {
    --field-bg: var(--surface-raised);            /* fields sit on the raised surface, as cards do */
    --field-ink: var(--text);
    --field-border: var(--border-strong);         /* Dials' control border: 3:1 on every surface */
    --field-border-hover: var(--text-quiet);
    --field-placeholder: var(--text-quiet);
    --focus-ring: var(--focus);                   /* Dials' focus ring: >= 3:1 on every surface, light and dark */
}

/* 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(--size--1);
    font-weight: var(--weight-strong);
    line-height: var(--leading);
    letter-spacing: var(--tracking);
    color: var(--text-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(--brand-solid); }

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, 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. Field text keeps live's Raleway Regular on 1.3. The edge is
   the template's: Dials' control border, 3:1 on every surface (until Dials
   the fields had no edge, and a white or pale fill alone fell below 3:1 on
   the header bar's sage end, the search overlay and the contact card). 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 ink, --text-strong
   (#0C0F11; live's is the kit's "Black" #000B0C), >= 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-leading: var(--leading-display);
    --field-weight: var(--weight-regular);
    --focus-ring-w: var(--border-width-m);
}
:root, [data-dials], .is-light, .is-dark {
    --field-bg: var(--surface-raised);
    --field-ink: var(--text-strong);
    --field-placeholder: var(--text-muted);
    --focus-ring: var(--text-strong);
}
.contact-form-card,
.hours-card,
.whychoose,
.policies-card--panel { --focus-ring: var(--brand-on-solid); }

/* 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; every one is at least
 * --target-min (44px) tall, the tap target. 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);
    padding: var(--space-2xs) var(--space-s);
    font-family: inherit;
    font-size: var(--size--1);
    font-weight: var(--weight-strong);
    line-height: var(--leading);        /* at each button size's own font size (.btn--sm, .btn--lg) */
    letter-spacing: var(--tracking);
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    min-block-size: var(--target-min);   /* 44px tap target, every size and variant */
    cursor: pointer;
    border: var(--border-width-s) 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(--solid);
    color: var(--on-solid);
}
/* Hover and pressed mix the fill away from its text colour (Dials' --mix-*),
 * so they work on every group: <a class="btn btn--primary is-tertiary">. */
.btn--primary:hover { background: color-mix(in oklch, var(--solid), var(--mix-hover)); color: var(--on-solid); }
.btn--primary:active { background: color-mix(in oklch, var(--solid), var(--mix-active)); color: var(--on-solid); }

.btn--secondary {
    background: transparent;
    border-color: var(--solid);
    color: var(--on-soft);
}
.btn--secondary:hover { background: var(--soft); color: var(--on-soft); }

.btn--ghost {
    background: transparent;
    color: var(--text-muted);
}
.btn--ghost:hover { background: var(--soft); color: var(--on-soft); }

.btn--sm { padding: var(--space-3xs) var(--space-xs); font-size: var(--size--2); }
.btn--cta-lg { padding: var(--space-xs) var(--space-m); font-size: var(--size-0); }   /* live's 226x55 on the About page cards */
.btn--lg { padding: var(--space-xs) var(--space-m); font-size: var(--size-0); }

/*
 * ON A BRAND-COLOURED GROUND
 *
 * A dark band is class="is-dark" on the section: Dials works every token out
 * again in the dark scheme, so the buttons above need nothing more. On a band
 * painted with a brand fill (background: var(--solid)) they invert instead:
 * the solid button goes to the raised surface, the outline picks up a
 * translucent edge in the fill's text colour. Put .on-dark on the button or
 * any ancestor.
 */
.on-dark .btn--primary,
.btn--primary.on-dark {
    background: var(--surface-raised);
    color: var(--on-soft);
}

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

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

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

.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-raised);
}

.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-raised);
    border: var(--border-width-s) 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 gradient
 * is Dials' band pattern (tokens.md, "Gradients are patterns"): from one
 * fill to another, decoration only, so no text is ever set on it.
 * The <img> has onerror="this.style.display='none'" which hides
 * the broken image, revealing this CSS background underneath.
 *
 * Derived from the site's own brand fill so a missing photo reads as part of
 * this practice rather than as a stray swatch.
 */
:root, [data-dials], .is-light, .is-dark {
    --avatar-shade: color-mix(in oklab, var(--brand-solid) 85%, black);   /* the avatar gradient's darker end: the brand fill, a step darker. color-mix() rather than relative colour, so Dials' fallback browsers draw it too */
}

.doctor-avatar {
    position: relative;
    aspect-ratio: 4 / 5;
    overflow: hidden;
    border-radius: var(--radius-s);
    background: linear-gradient(135deg, var(--avatar-shade), var(--brand-solid));
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The silhouette is an icon on the brand fill, so it is drawn in the fill's
 * own text colour, --brand-on-solid, through a mask (the shape only), and
 * keeps 3:1 in light and dark. A white silhouette fell to 2.8:1 on a dark
 * page, where the fill is lifted (mf-websites#431). */
.doctor-avatar::after {
    content: "";
    position: absolute;
    width: 40%;
    height: 40%;
    background-color: var(--brand-on-solid);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='black' 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") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='black' 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") center / contain no-repeat;
}

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

/* 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). */
.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(--size-7);   /* the site's display step, as the practice page's hero title */
    font-weight: var(--weight-heading);
    line-height: 1;
    margin: 0 0 var(--space-2xs);
    opacity: 0.55;
}
.notfound h1 { margin-top: 0; }
.notfound__lede { font-size: var(--size-1); line-height: var(--leading-body); 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-width-s) 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(--size-0);
    text-transform: uppercase;
    letter-spacing: var(--tracking-caps-total);   /* capitals */
    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-body);
    font-weight: var(--weight-semibold);
}

/* ═══════════════════════════════════════════════════════════════════════
 * 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.
 * Colours, type and space come from the dials at the top of the file.
 * ═══════════════════════════════════════════════════════════════════════ */

:root {
    --title-band: var(--size-5);      /* live's 33px band titles */
    --title-hours: var(--size-3);     /* live's 24.75px hours-card title */

    /* --- The kit's other named colours, as site patterns from the dials.
     * Each is a dial moved in OKLCH onto the kit's colour (the hex in its
     * comment), declared once here; Dials' fallback browsers get a
     * color-mix() version below. None is a Dials token. --- */
    --ps-deep: oklch(from var(--brand) calc(l - 0.1447) calc(c * 1.1909) calc(h + 4.72));         /* #275062, the kit's "Text": headings, the nav's hover, the roster */
    --ps-accent: oklch(from var(--secondary) calc(l + 0.0959) calc(c * 0.9746) h);                 /* #D0E2E2, the kit's "Accent": washes, tiles, cards, hairlines */
    --ps-cream: oklch(from var(--warning) calc(l + 0.2066) calc(c * 0.1222) calc(h + 10.29));      /* #F5EFE3, the kit's "Cream": washes, cards, the mission band */
    --ps-salmon: oklch(from var(--tertiary) calc(l + 0.072) calc(c * 0.5818) calc(h - 1.78)); /* #BD786B: the salmon cards (not in the kit) */
    --ps-salmon-deep: oklch(from var(--tertiary) calc(l - 0.1187) calc(c * 0.8675) h);       /* #91311E: the salmon tile's hover */
    /* Crimson LETTERING (eyebrows, links, roles, years): the crimson pulled
     * just far enough towards black to hold 4.5:1 on the palest wash it sits
     * on, the kit's Accent (4.6:1; 5.4:1 on the cream, 6.2:1 on white). The
     * kit's crimson itself, #C14D36, is 3.6:1 there; fills, buttons and
     * outlines keep it. color-mix(), so Dials' fallback browsers draw it too. */
    --ps-crimson-text: color-mix(in oklab, var(--tertiary) 89%, black);   /* #A5412D */
    /* The kit's "Black" #000B0C, a touch darker than the ink: the footer
     * bar's copyright and "Powered by" lines, which sit on the footer
     * gradient's teal end and keep live's 4.6:1 with it (the ink gives 4.5). */
    --ps-black: oklch(from var(--text-strong) calc(l - 0.03) calc(c * 3.6) calc(h - 36.76));   /* #000B0C */
    --shadow-bar: 0 1px 20px color-mix(in oklab, black 4%, transparent);

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

    /* --- 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, 5px menus; the 20px header bar is
     * Dials' --radius-l. */
    --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). */
    --line-box-overshoot: 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) */
}

/* On the sage secondary (the travel page's closing panel, the mega menu's
 * panel) the crimson lettering goes deeper still: 4.6:1 on #B1C3C3. */
.svc-cta--secondary,
.sub-menu { --ps-crimson-text: color-mix(in oklab, var(--tertiary) 76%, black); }   /* #853322 */

/* The site patterns in Dials' fallback browsers (no relative colour): each
 * dial mixed toward white or black to land near the kit's colour. */
@supports not ((color: oklch(from red l c h)) and (color: light-dark(red, red))) {
    :root {
        --ps-deep: color-mix(in oklab, var(--brand) 75%, black);
        --ps-accent: color-mix(in oklab, var(--secondary) 53%, white);
        --ps-cream: color-mix(in oklab, var(--warning) 18%, white);
        --ps-salmon: color-mix(in oklab, var(--tertiary) 81%, white);
        --ps-salmon-deep: color-mix(in oklab, var(--tertiary) 80%, black);
        --ps-black: color-mix(in oklab, var(--text-strong) 50%, black);
    }
}

/* ── Base ─────────────────────────────────────────────────────────── */
body { background: var(--surface); color: var(--text-strong); font-weight: var(--weight-body); }
h1, h2, h3, h4, h5, h6 { text-wrap: pretty; color: var(--ps-deep); }
.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(--brand-solid); color: var(--brand-on-solid);
}
.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(--size-1);
    font-weight: var(--weight-strong);
    line-height: var(--leading-body);
    letter-spacing: 0;
    text-transform: uppercase;
    color: var(--ps-crimson-text);
}
/* 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-heavy);
    line-height: var(--leading-display);
    color: var(--ps-deep);
}
.band-title--regular { font-weight: var(--weight-heading); }
.rule { height: 0; border: 0; border-top: var(--border-width-s) 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(--tertiary-solid);
    color: var(--brand-on-solid);
    border: 0;
    border-radius: var(--control-radius);
    font-family: var(--font-body);
    font-size: var(--size--1);
    font-weight: var(--weight-strong);
    line-height: var(--leading-body);
    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(--tertiary-solid); color: var(--brand-on-solid); transform: translateY(-8px); }
.btn--cta.btn--cta-lg { padding: var(--space-xs) var(--space-m); font-size: var(--size-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(--surface);
    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(--size-0);
    font-weight: var(--weight-heading);
    line-height: var(--leading-card);
    color: var(--brand-on-solid);
    text-decoration: none;
    transition: transform 0.3s var(--ease-out);
}
.nav-list > li > a:hover, .nav-list > li > a:focus-visible { color: var(--brand-on-solid); 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 color-mix(in oklab, black 35%, transparent);
    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(--size--1);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-display);
    color: var(--text);
    text-decoration: none;
}
.sub-menu a:hover, .sub-menu a:focus-visible, .sub-menu li.is-open > a { background: var(--ps-deep); color: var(--brand-on-solid); }
.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-width-s) solid color-mix(in oklch, var(--brand-solid) 45%, transparent);
        border-radius: 0;
        font-family: var(--font-heading);
        font-size: var(--size--1);
        font-weight: var(--weight-heading);
        color: var(--ps-deep);
        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(--ps-crimson-text); }
    .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(--ps-deep);   /* 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(--text-strong);
}
.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-width-s) solid var(--ps-deep);
    border-radius: var(--radius-card);
    font-family: var(--font-heading);
    font-size: var(--size-0);
    font-weight: var(--weight-heading);
    line-height: var(--leading-card);
    color: var(--text);
    text-decoration: none;
    transition: background var(--duration-base) var(--ease-out);
}
.pill--address { grid-column: 1; font-size: var(--size--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(--text); }
.pill__icon { width: 20px; height: 20px; flex: none; fill: var(--tertiary-solid); }

.hero__card {
    flex: 0 0 43%;
    margin-top: calc(-1 * var(--card-lift));
    padding: var(--space-panel);
    background: var(--surface);
    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(--ps-accent); }
.hero__copy p { margin: 0 0 var(--space-xs); font-weight: var(--weight-body); line-height: var(--leading-body); color: var(--text-strong); }
.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(--brand-on-solid);
}
/* 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-heading);
    line-height: var(--leading-body);
    color: var(--brand-on-solid);
}
.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(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); }
.hours-list .hours-table td:first-child::after { content: ""; flex: 1; margin: 0 var(--space-xs); border-bottom: var(--border-width-s) solid var(--border); }
.hours-list .hours-table td:last-child { font-size: var(--size-2); font-weight: var(--weight-semibold); line-height: var(--leading-body); }
.hours-list__note { display: block; margin: var(--space-xs) 0 0; font-family: var(--font-accent); font-size: var(--size--1); font-weight: var(--weight-body); line-height: var(--leading-notes); color: var(--ps-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-regular); line-height: var(--leading-body); color: var(--brand-on-solid); }
.hours-card__notes p:last-child { margin-bottom: 0; }
.hours-card__notes a { color: var(--ps-cream); text-decoration: underline; }
.hours-card__notes a:hover { color: var(--brand-on-solid); }

.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(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); }
.tile__text { display: block; font-weight: var(--weight-regular); line-height: var(--leading-body); }
.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); } }
/* Black lettering on the salmon (6.1:1; white was 3.5:1), white on its deep hover (7.9:1). */
.tile--appointments .tile__box { background: var(--ps-salmon); color: var(--text-strong); }
.tile--appointments:hover .tile__box { background: var(--ps-salmon-deep); color: var(--brand-on-solid); }
.tile--services .tile__box { background: var(--ps-accent); color: var(--text); }
.tile--services .tile__title { color: var(--ps-deep); }
.tile--services:hover .tile__box { background: var(--secondary); }
.tile--policies .tile__box { background: var(--brand-solid); color: var(--brand-on-solid); }
.tile--policies:hover .tile__box { background: var(--ps-deep); }
/* 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) ───────────────────────────────────── */
.band-values-head {
    padding-block: var(--space-band);
    border-top: var(--border-width-s) solid var(--secondary);
    background: var(--ps-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(--size-1); font-weight: var(--weight-body); line-height: var(--leading-body); color: var(--text); }

/* ── 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(--text);
}
.value-card p { margin: 0; font-weight: var(--weight-body); line-height: var(--leading-body); }
.value-card__icon { width: 50px; height: 50px; fill: var(--brand-solid); }
.value-card__icon--ink { fill: var(--ps-deep); }
.value-card__title { margin: var(--space-2xs) 0 1px; font-size: var(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--text); }
.value-card__title--brand { color: var(--ps-deep); }
.value-card__text--black { color: var(--text-strong); }
.value-card--accent-tint { background: var(--ps-accent); }
.value-card--secondary { background: var(--secondary); }
/* Black lettering and icon on the salmon (6.1:1; white was 3.5:1). */
.value-card--salmon { background: var(--ps-salmon); color: var(--text-strong); }
.value-card--salmon .value-card__icon, .value-card--salmon .value-card__title { fill: var(--text-strong); color: var(--text-strong); }
.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-width-s) 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-width-s) solid var(--tertiary-solid);
    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-body); line-height: var(--leading-body); color: var(--text-strong); }
.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(--ps-deep); }
.step__title { margin: var(--space-2xs) 0 0; font-size: var(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--text); }
.step p { margin: 0; font-weight: var(--weight-body); line-height: var(--leading-body); color: var(--text-strong); }

/* ── Footer ───────────────────────────────────────────────────────── */
.site-footer { border-top: var(--border-width-s) solid var(--brand-solid); 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-regular); line-height: var(--leading-body); color: var(--text-strong); }
.site-footer__motto { margin: calc(-1 * var(--space-s)) 0 0; font-family: var(--font-heading); font-size: var(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--text); }
.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(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--ps-deep); }
.footer-links { margin-top: calc(-1 * var(--space-2xs)); }
.footer-links li { padding-block: var(--space-3xs); line-height: 1; }
.footer-links a { font-family: var(--font-accent); font-size: var(--size--1); font-weight: var(--weight-semibold); line-height: 1; color: var(--text); text-decoration: none; }
.footer-links a:hover, .footer-links a:focus-visible { color: var(--ps-crimson-text); }
.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-width-s) solid var(--ps-deep);
}
/* 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(--size--1); font-weight: var(--weight-semibold); line-height: var(--leading-body); color: var(--ps-black); }
.powered-by { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2xs); margin: 0; font-size: var(--size--2); font-weight: var(--weight-semibold); color: var(--ps-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(--size--1); font-weight: var(--weight-semibold); color: var(--text); }
/* 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(--size--1); font-weight: var(--weight-semibold); line-height: var(--leading-body); color: var(--text); text-decoration: none; }
.footer-bar__legal a:hover, .footer-bar__legal a:focus-visible { color: var(--brand-on-solid); }

/* ── 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(--size--1);
        line-height: var(--leading-display);
        color: var(--text);
    }
    .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(--ps-deep); color: var(--brand-on-solid); }
    .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(--text);
        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(--text); }
    /* 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(--brand-on-solid); }
    .nav-list > li.nav-cta > .btn:hover, .nav-list > li.nav-cta > .btn:focus-visible { background: var(--tertiary-solid); color: var(--brand-on-solid); }

    .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(--ps-crimson-text); 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(--text); }
.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-body); color: var(--text); }
.contact-intro__lede { font-size: var(--size-1); font-weight: var(--weight-strong); color: var(--ps-crimson-text) !important; }
.contact-intro__strong { color: var(--text); }

.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 (white at 14%) with a white edge, 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(--surface) 14%, transparent);
    --field-ink: var(--brand-on-solid);
    --field-border: var(--brand-on-solid);         /* the edge, white on the teal: 4.7:1 at its light end */
    --field-border-hover: var(--brand-on-solid);
    --field-placeholder: color-mix(in oklab, var(--brand-on-solid) 80%, transparent);
}
.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(--size-0); font-weight: var(--weight-regular); color: var(--brand-on-solid); }
.form-field .req { margin-left: var(--space-3xs); color: var(--ps-accent); }
.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(--size-0); line-height: var(--leading-body); color: var(--text); }
.contact-form__note a { color: var(--ps-crimson-text); }

/* 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-width-s) solid var(--ps-accent); }
.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(--size-1); line-height: var(--leading-body); color: var(--text); }
.faq__list { display: flex; flex-direction: column; gap: var(--space-2xs); }
.faq__item { border: var(--border-width-s) solid var(--border); 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(--size-0);
    font-weight: var(--weight-semibold);
    color: var(--text);
    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(--text); }
.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-body); color: var(--text); }
.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(--surface);
}
/* 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-body); color: var(--text-strong); }
/* 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-width-s) solid var(--brand-solid); }
.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-body); color: var(--text-strong); }
/* 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(--size-3); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--ps-deep); }
.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(--size-0); font-weight: var(--weight-semibold); color: var(--ps-crimson-text); }
.person__name { margin: 0; font-family: var(--font-heading); font-size: var(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--ps-deep); }
/* 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-regular); color: var(--text); white-space: pre-line; }
.person__bio { margin: var(--space-2xs) 0 0; line-height: var(--leading-body); color: var(--text-strong); 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(--surface-lowered) 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-body); color: var(--text); }
.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(--surface);
    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(--ps-accent) 95%, transparent);
}
.services-intro .band-title { margin-block: var(--space-2xs) var(--space-s); font-weight: var(--weight-heading); line-height: var(--leading-display); color: var(--ps-deep); }
.services-intro p { margin: 0 0 var(--space-xs); font-weight: var(--weight-semibold); line-height: var(--leading-body); color: var(--text); }
.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(--surface);
    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 color-mix(in oklab, black 35%, transparent); }   /* not on focus: the ring is the focus cue */
.service-card__title {
    display: block;
    font-family: var(--font-heading);
    font-size: var(--size-2);
    font-weight: var(--weight-heading);
    line-height: var(--leading-card);
    color: var(--ps-deep);
}
/* 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(--size-0);
    font-weight: var(--weight-body);
    color: var(--ps-crimson-text);
}

@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(--size-1); line-height: var(--leading-body); color: var(--text-strong); }
.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-width-s) solid var(--brand-solid); }   /* 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(--text); }
/* 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(--tertiary-solid);
}
.timeline__year { font-family: var(--font-heading); font-size: var(--size-3); font-weight: var(--weight-heading); color: var(--ps-crimson-text); }
.timeline__title { margin: 0 0 var(--space-s); font-family: var(--font-heading); font-size: var(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--text); }
.timeline__text { margin: 0; line-height: var(--leading-body); color: var(--text); }

/* 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-body); }
.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-body); color: var(--text); }
/* 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(--ps-crimson-text); }
.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-body); color: var(--text); }
.tick-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.45em;
    width: 0.75rem;
    height: 0.4rem;
    border-left: var(--border-width-m) solid var(--tertiary-solid);
    border-bottom: var(--border-width-m) solid var(--tertiary-solid);
    transform: rotate(-45deg);
}

.band-community { padding-block: var(--space-band); border-top: var(--border-width-s) 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-body); color: var(--text); }
.band-title--small { font-size: var(--size-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-width-s) solid var(--ps-accent); }
.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(--size-1); color: var(--text); }
.commitment__list li::before {
    position: absolute;
    left: 0;
    top: 0.5em;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: var(--radius-round);
    background: var(--tertiary-solid);
}

@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-width-s) 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-width-s) solid var(--ps-deep); opacity: 0.4; }
.rule--centred { margin-inline: auto; }

.bordered-column {
    padding: var(--space-l);
    border: var(--border-width-s) solid var(--tertiary-solid);
    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(--surface);
}
.about-intro__card .band-title { margin-block: var(--space-xs) var(--space-m); font-size: var(--size-7); line-height: var(--leading-title); }   /* 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-heavy); }   /* 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-width-s) solid color-mix(in srgb, var(--text) 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(--brand-solid);   /* 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(--size-3); }
.journey-2024__copy .band-title { margin-block: var(--space-3xs) 0; font-size: var(--size-5); font-weight: var(--weight-heading); }   /* 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-body); color: var(--text); }
.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(--ps-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(--ps-accent);
}
.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(--ps-deep); }
/* 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(--size-0); font-weight: var(--weight-body); line-height: var(--leading-body); color: var(--text); }

/* (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-body); }
.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(--ps-deep); }
.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(--brand-on-solid);
}
.whychoose__title { margin: 0; font-family: var(--font-body); font-size: var(--size-1); font-weight: var(--weight-heading); letter-spacing: var(--tracking-caps-total); color: var(--brand-on-solid); }
.whychoose p:not(.whychoose__title) { margin: 0 0 var(--space-s); line-height: var(--leading-body); color: var(--brand-on-solid); }
.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-width-s) solid var(--surface); 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-body); color: var(--text-strong); }
.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(--size-2);
    font-weight: var(--weight-heading);
    line-height: var(--leading-card);
    color: var(--ps-crimson-text);
}
.policies-pair__item p { margin: 0; line-height: var(--leading-body); color: var(--text); }
.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(--size-2);
    font-weight: var(--weight-heading);
    line-height: var(--leading-card);
    color: var(--ps-deep);
}
.policies-card__title--light { color: var(--brand-on-solid); }
/* 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-width-s) solid var(--tertiary-solid); }
.rule--light-short { width: 10.8125rem; height: 0; margin: var(--space-xs) 0 var(--space-s); border: 0; border-top: var(--border-width-s) solid var(--surface); }

/* 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-body); color: var(--text); }
/* 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-body); color: var(--text); }
.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-body); color: var(--text); }
.policies-card p:last-child { margin-bottom: 0; }
.policies-card--accent-tint { padding: var(--space-l); background: var(--ps-accent); }
/* 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(--brand-on-solid); }
.policies-card--crimson { padding: var(--space-l); background: linear-gradient(var(--ps-salmon) 0%, var(--tertiary-solid) 100%); }
.policies-card--crimson p { color: var(--brand-on-solid); }
/* 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(--brand-on-solid); }
.policies-contact { line-height: var(--leading-body); }
.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: the site's crimson lettering,
 * --ps-crimson-text, which holds 4.5:1 on every pale ground 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(--ps-crimson-text); }

/* 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(--size-2);
    font-weight: var(--weight-heading);
    line-height: var(--leading-card);
    color: var(--ps-deep);
}
.policies-doc__title--light { color: var(--brand-on-solid); }
.policies-doc p { margin: 0; line-height: var(--leading-body); color: var(--text-strong); }
/* 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(--size-1);
    font-weight: var(--weight-body);
    line-height: var(--leading-body);
    color: var(--brand-on-solid);
}
.policies-doc--secondary { background: var(--secondary); }
.policies-doc--panel { background: var(--grad-panel); }
.policies-doc--panel p, .policies-doc--crimson p { color: var(--brand-on-solid); }
.policies-doc--crimson { background: linear-gradient(var(--ps-salmon) 0%, var(--tertiary-solid) 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-tint, .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-body); color: var(--text-strong); }
.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-body); color: var(--text-strong); }

/* Band 2: the four preparation tips. */
.band-appt-tips { background: var(--grad-values); padding-block: var(--space-band); border-top: var(--border-width-s) 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-body); color: var(--text); }
/* 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-width-m) solid var(--tertiary-solid); }
.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(--brand-solid); }
.appt-tip__title { margin: 0 0 var(--space-xs); font-family: var(--font-heading); font-size: var(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--text); }
.appt-tip p { margin: 0; line-height: var(--leading-body); color: var(--text); }

/* 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-width-s) 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(--text); }
.appt-types__lede { margin: 0; padding-top: var(--space-card); line-height: var(--leading-body); color: var(--text); }
.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(--ps-salmon); }
.appt-type--accent-tint { background: var(--ps-accent); }
.appt-type--secondary { background: var(--secondary); }
.appt-type__icon { display: block; width: 45px; height: 45px; margin-bottom: var(--space-group); fill: var(--ps-deep); }
.appt-type--salmon .appt-type__icon { fill: var(--text-strong); }   /* black on the salmon, as its lettering */
.appt-type__title { margin: 0 0 var(--space-s); font-family: var(--font-heading); font-size: var(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--text); }
.appt-type__title--light { color: var(--text-strong); }   /* the salmon card's title: black, 6.1:1 (white was 3.5:1) */
.appt-type p { margin: 0 0 var(--space-s); line-height: var(--leading-body); color: var(--text); }
.appt-type--salmon p { color: var(--text-strong); }
/* Live's ticks: the kit's primary on the two pale cards, and on the salmon
 * one the lettering's black (live: the kit's cream, with white lettering), 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-body); color: var(--text); }
.appt-type__list svg { flex: none; width: 15px; height: 15px; fill: var(--brand-solid); }
.appt-type--salmon .appt-type__list li { color: var(--text-strong); }
.appt-type--salmon .appt-type__list svg { fill: var(--text-strong); }
.appt-type--secondary .appt-type__icon { fill: var(--brand-solid); }  /* the third card's calendar is the primary, not the brand ink */

/* 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-width-s) 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(--surface); }
.appt-billing__card p { margin: var(--space-3xs) 0 var(--space-xs); line-height: var(--leading-body); color: var(--text); }
.appt-billing__card p:last-child { margin-bottom: 0; }
.policies-card__title--ink { color: var(--text); }

/* 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-tint { padding: var(--space-card); background: var(--ps-accent); }
.appt-info--cream { padding: var(--space-card); background: var(--ps-cream); }
.appt-info__title { margin: 0 0 var(--space-xs); font-family: var(--font-heading); font-size: var(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--text); }
.appt-info p { margin: 0 0 var(--space-xs); line-height: var(--leading-body); color: var(--text); }
.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(--size--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-body); color: var(--text); }
.appt-criteria svg { flex: none; width: var(--tick-icon); height: var(--tick-icon); margin-top: calc((1lh - var(--tick-icon)) / 2); fill: var(--text); }
/* 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(--ps-cream); padding-block: var(--space-band) var(--space-l); border-top: var(--border-width-s) 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(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--ps-deep); }
.appt-ten li p { margin: 0; line-height: var(--leading-body); color: var(--text); }
/* 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(--ps-crimson-text); }
.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-tint, .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(--size-7);
    font-weight: var(--weight-heading);
    line-height: var(--leading-title);
    color: var(--text);
}
.hub-intro__lede { margin: 0; font-size: var(--size-2); line-height: var(--leading-body); color: var(--text); }

@media (max-width: 47.9375rem) {
    .hub-main { padding-block: var(--space-band); }
    .hub-intro__title { font-size: var(--size-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(--line-box-overshoot)); }   /* 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(--line-box-overshoot)); }
/* 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-body); color: var(--text); }
/* .svc-col p outranks .eyebrow on specificity, which had turned the
 * closing card's eyebrow on /diabetes to ink. */
.svc-col > .eyebrow { color: var(--ps-crimson-text); }
.svc-title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: var(--size-2);           /* live's 20.624 */
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--ps-deep);
}
.svc-title--lg { font-size: var(--size-3); }        /* live's 24.7488 */
.svc-title--ink { color: var(--text); }
/* 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(--size-1);
    color: var(--ps-crimson-text);
}
.svc-quote { font-style: italic; }
.svc-emphasis { font-weight: var(--weight-semibold); }

/* ── 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-body);
}
.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(--tertiary-solid));
}
.svc-list > li > span,
.svc-list > li > a {
    padding-left: var(--space-3xs);
    font-weight: var(--weight-semibold);
    color: var(--text);
}
.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(--tertiary-solid));
}
.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(--ps-crimson-text); 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(--brand-solid); }
/* 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-width-s) solid var(--border); }
/* 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-body); color: var(--text); }
/* 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-body) * 1em - 8px) / 2); }
.svc-steps__mark { width: 8px; height: 8px; fill: var(--tertiary-solid); }
/* 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(--tertiary-solid); 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-body); color: var(--text); }
/* 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-body); }
.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(--line-box-overshoot)); }

/* ── 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-width-s) solid var(--tertiary-solid); 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-width-s) solid var(--secondary); }
.band-svc--rule-accent { border-top: var(--border-width-s) solid var(--ps-accent); }
/* 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-width-s) 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-width-s) solid var(--ps-accent); }
.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(--size-3);
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--ps-deep);
}
.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-body); color: var(--text); }


/* ═══ 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-body); color: var(--text); }

/* 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-width-s) solid var(--tertiary-solid);
    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(--size-1);           /* live's 18.5616 */
    font-weight: var(--weight-heading);
    line-height: var(--leading-body);
    color: var(--ps-crimson-text);
}
.svc2-fact p { margin: 0; line-height: var(--leading-body); color: var(--text); }
/* 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(--ps-deep); }
.svc2-fact__title--lg { font-family: var(--font-heading); font-size: var(--size-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-body); color: var(--text); }

/* ── 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(--tertiary-solid);
    font-family: var(--font-heading);
    font-size: var(--size-2);
    font-weight: var(--weight-heading);
    color: var(--brand-on-solid);
}
.svc2-step__copy { margin: 0; min-height: 10.9375rem; line-height: var(--leading-body); color: var(--text); }   /* 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(--text) }` 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(--brand-solid);
    color: var(--brand-on-solid);
    line-height: var(--leading-body);
}
.svc2-alert a,
.svc2-col .svc2-alert a { color: var(--brand-on-solid); 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(--ps-accent) 0%, var(--surface) 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(--ps-accent); }

/* 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(--tertiary-solid);   /* live's 7 — no border token is this wide */
    font-style: italic;
    line-height: var(--leading-body);
    color: var(--text);
}
/* .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(--text); }
.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-body); color: var(--text); }
.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(--ps-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(--brand-solid));
}
.svc2-regcard p { line-height: var(--leading-body); color: var(--text); }

/* ── 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(--size-4); text-wrap: balance; }
    .about-intro__card .band-title { font-size: var(--size-6); }
    .band-title--small,
    .band-title--hero,
    .journey-2024__copy .band-title,
    .team-cta__panel .band-title,
    .commitment__copy .band-title { font-size: var(--size-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(--size-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(--size-1); }
    .footer-links a { display: block; padding-block: var(--space-3xs); line-height: var(--leading-footer-link); }
    .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(--size-2); font-weight: var(--weight-heading); line-height: var(--leading-card); color: var(--ps-deep); }
.legal p, .legal ul, .legal dl, .legal address { margin: 0 0 var(--space-xs); line-height: var(--leading-body); color: var(--text); }
.legal .lede { font-size: var(--size-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-heading); color: var(--ps-deep); }
.legal dd { margin: 0 0 var(--space-xs); }
.legal dd address { margin: 0; }
.legal small { font-size: var(--size--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(--ps-deep);
    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(--brand-on-solid); background: var(--tertiary-solid); }
.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-body); }
/* 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(--size--1);
    line-height: var(--leading-display);
    color: var(--text-strong);
}
.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(--text-strong);
    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(--text-strong); background: var(--surface); }
.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(--size-0);
    font-weight: var(--weight-heading);
    line-height: var(--leading-card);
    color: var(--ps-deep);
    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(--ps-crimson-text); }
.mf-search__excerpt {
    display: block;
    margin-top: var(--space-3xs);
    font-size: var(--size--1);
    line-height: var(--leading-body);
    color: var(--text-strong);
}
.mf-search__excerpt mark {
    color: var(--text-strong);
    background: color-mix(in oklch, var(--tertiary-solid) 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(--surface);
}
.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(--ps-accent); }   /* 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(--ps-accent); }

/* 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(--text-strong) 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; }
