/*
 * 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 (its deep blue, bright blue and navy, the
 * grey-blue page ground, the #363B40 body text, and its type and space
 * knobs), 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 colours measured off live (2026-09) 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. All three blues pass their contrast
     * targets as they are, so their roles paint the hex itself. */
    --brand: hsl(206.5 96.8% 24.3%);     /* #02457A, the deep blue: buttons, card titles, eyebrows, the phone menu */
    --secondary: hsl(199.9 97.5% 31.6%); /* #026B9F, the bright blue: links, the active nav, the focus ring, accent text. Live's accent is #028ABE, which fails 4.5:1 on the pale grounds; this is it darkened toward the navy (deliberate divergence 1 in CLAUDE.md). The site's pale and mid blues are derived from it (site layer) */
    --tertiary: hsl(217.5 100% 14.1%);   /* #001B48, the navy: the display titles, the footer bar, the emergency panel */
    --success: hsl(126 46% 33%);         /* the status colours: the template's */
    --warning: hsl(37 74% 54%);
    --danger: hsl(3 56% 48%);
    --info: hsl(202 64% 41%);
    --grey: hsl(210 8.5% 23.1%);         /* the body text's hue; paper and ink are exact below */

    /* Paper and ink, exact. The page is live's grey-blue ground (cards and
     * fields sit on the raised surface, a shade off white). The ink puts
     * Dials' body text (--text) on live's #363B40 exactly. --text-contrast 3
     * is the least that keeps the field and control border (--border-strong,
     * #82868A) at 3:1 on every surface with that ink; it also moves --text
     * from 86% of the ink into the paper to 87.2%, which the ink allows for. */
    --paper-light: hsl(210 18.2% 95.7%); /* #F2F4F6 */
    --ink-light: hsl(210 13.9% 14.1%);   /* #1F2429 */
    --text-contrast: 3;

    /* Type and space: live sets a fluid root and sizes in rem; here body is
     * 16px on a 390px phone (live 13.2, lifted to readable) to live's 16.5px
     * at 1440, each step 1.145x (phone) to 1.2x (desktop) the last. 1.2 is
     * the least-squares ratio of live's ladder at 1440; the phone ratio is
     * fitted to live's heading sizes at 390. Every size holds its 1440 value
     * on wider screens (the fleet's 390 -> 1440 range).
     *     live (rem)  @1440 -> step     @1440   @390 ours (live)
     *     0.75        12.37 -> size--2  12.20   12.20  (9.91)  "Powered by"
     *     0.875       14.44 -> size--1  13.75   13.97 (11.57)  footer legal row
     *     1           16.50 -> size-0   16.50   16.00 (13.22)  body
     *     1.125-1.25  18.6-20.6 -> size-1 19.80  18.32 (14.9-16.5)  ledes, cards
     *     1.5         24.75 -> size-2   23.76   20.98 (19.83)  sub-headings
     *     2           33.00 -> size-4   34.21   27.50 (26.44)  band title
     *     2.5         41.25 -> size-5   41.06   31.49 (33.05)  legal headings
     *     3           49.50 -> size-6   49.27   36.05 (39.66)  legal + policy titles
     *     3.5         57.75 -> size-7   59.12   41.28 (39.66)  section titles
     *     4.5         74.25 -> size-8   70.95   47.27 (46.27)  hero display
     * Space: live's desktop rhythm is a 10px ladder (10/20/30/40/60/80/120),
     * which --space-max 20 lands exactly at 1440 (2xs 10, xs 15, s 20, m 30,
     * l 40, xl 60, 2xl 80, 3xl 120); --space-min 16 makes a phone 20%
     * tighter (owner decision 2026-10-03: spacing scales). */
    --screen-min: 390;
    --screen-max: 1440;
    --size-min: 16;
    --size-max: 16.5;
    --ratio-min: 1.145;
    --ratio-max: 1.2;
    --space-min: 16;
    --space-max: 20;
    --space-density: 1;

    /* Type (Dials v0.3): weight, line height and letter spacing. Weights:
     * body 400 (Outfit); headings, card titles, the nav, the header button
     * and bold 700 (--weight-heading); buttons, the hero and legal page titles 600,
     * Dials' --weight-strong (the body weight plus 200). Live sets line
     * height by role, not by size, and the site's rules read these as
     * numbers so each holds at every size, rather than Dials' size curve
     * (--leading, which the template's own small print uses): body text 1.5
     * (--leading-body) and the titles 1.2 (--leading-display). Letter
     * spacing: live tracks nothing, so --tracking-small and
     * --tracking-display stay unset (0); --tracking-caps 0.08 is the 404
     * page's links title, the one run in capitals that is tracked. */
    --leading-body: 1.5;
    --leading-display: 1.2;
    --tracking-caps: 0.08;
    --weight-body: 400;
    --weight-heading: 700;
    --line-length: 65ch;
    /* Terrace Clinic's own type tokens: values measured off live, role by
     * role, that the dials do not hold. Dials' size curve runs one straight
     * line from body to display leading, so it lands none of these
     * leadings; and it has one weight above the body's (--weight-strong)
     * where live sets three. */
    --leading-hero: 1.1;      /* the hero display titles and the 404 numeral (81.7px over 74.25) */
    --leading-snug: 1.3;      /* service titles, doctors' qualifications, the legal cards' h3, search result titles, fields */
    --leading-nav: 2.125;     /* the footer's quick links: their 35px pitch is the line height alone */
    --weight-medium: 500;     /* Outfit and Karla Medium: the hero fact rows, the "/" separators, the footer links, the Karla eyebrows */
    --weight-heavy: 800;      /* Lato 800: the accreditation and note titles */

    /* Corners: --radius-l 20px (cards, the contact card, photos), --radius-m
     * 12.5px, --radius-s 6.25px; the 8px card corner is --radius-card (site
     * layer). Accent rules and active states are 4px, not Dials' 3px. */
    --radius-base: 12.5;
    --border-width-l: 4px;

    /* Faces: Outfit for body, Lato for headings, Karla for a few eyebrows and
     * the "/" separators (Google Fonts, linked in each page's <head>). */
    --font-body: "Outfit", system-ui, -apple-system, "Segoe UI", sans-serif;
    --font-heading: "Lato", Georgia, "Times New Roman", serif;
    --font-accent: "Karla", "Outfit", 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));
    }
}

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

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

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

/*
 * 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 {
    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--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.
 *
 * Deliberately written against fallbacks rather than this site's own token
 * names - every site in the fleet has a different vocabulary, and a 404 that
 * silently loses its layout because one variable is spelt differently is
 * worse than one that is slightly plainer. */
.notfound {
    padding-block: var(--space-3xl) var(--space-2xl);
    text-align: center;
}
.notfound__inner { max-width: 46rem; margin-inline: auto; }
.notfound__code {
    font-size: var(--size-5);
    font-weight: var(--weight-heading);
    line-height: var(--leading);
    letter-spacing: var(--tracking);
    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); letter-spacing: var(--tracking); 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;
    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);
    font-weight: var(--weight-strong);
}

/* ===========================================================================
 * TERRACE CLINIC — site layer
 *
 * Transcribed from https://www.terraceclinic.com.au at 1440 (design width),
 * cross-checked at 1920, 1024 and 390. Every value below was measured, not
 * chosen. Where a measurement is expressed through the scale rather than as a
 * literal, the comment names the measured pixel value it reproduces at 1440.
 *
 * Colours, text sizes, line heights, weights and spacing all come from the
 * dials in "This site's dials" at the top of the file (the fit table is in
 * its comment). Live sets a FLUID ROOT, html { font-size: calc(0.74981rem +
 * 0.31266vw) }, and states every size as a rem multiple of it; reproducing
 * that root underneath Dials' own fluid steps would scale every size twice,
 * so the root stays at 100% and the steps carry the fluidity instead.
 * =========================================================================== */

:root {
    /* --- Colour: the site's own blues -----------------------------------
     * Live's palette has a pale and a mid blue of a greener hue than its
     * three brand blues, a vivid accent and a soft slate for the nav. No
     * Dials token makes them, so each is a site pattern: a brand dial moved
     * in OKLCH onto live's own colour (in the comment), so it follows the
     * dial. Dials' contrast promises do not cover them; their pairings were
     * measured (below). Older browsers: see the fallback after this block.
     * Live's hero glows, the arch card's wash and the contact card's drop
     * shadow used four more near-copies of these (#088BBB, #A4D2E6, #D7EBF2,
     * #84B5C7), always at 12-33% opacity; they read these three now. */
    --tc-sky: oklch(from var(--secondary-solid) calc(l + 0.4168) calc(c * 0.1776) calc(h - 16));    /* #D7E8EF: tinted grounds, eyebrow pills, cards, the accreditation strip */
    --tc-mid: oklch(from var(--secondary-solid) calc(l + 0.3054) calc(c * 0.5044) calc(h - 19.9));  /* #97CADB: hairlines, separators, large decorative icons */
    --tc-vivid: oklch(from var(--secondary-solid) calc(l + 0.0935) calc(c * 1.0823) calc(h - 6.15)); /* #028ABE, live's own accent: LARGE headings only (the 24.75px/800 strip title, 3.10:1 on sky; the 33px band title, 3.54:1 on the page), and the hero glows */
    --tc-ink-soft: oklch(from var(--tertiary-solid) calc(l + 0.1702) calc(c * 0.7289) calc(h - 1.18)); /* #324A6D: the header nav (8.2:1 on the page) */
    /* The 8px card corner (hero badge, hours card, services cards, contact
     * cards): two fifths of --radius-l, the 20px card corner. */
    --radius-card: calc(var(--radius-l) * 0.4);

    /* --- Named compositions: sums of steps, never new steps -----------
     * px at 390 / 1024 / 1440, against live's measurement. */
    --space-inset-m: calc(var(--space-l) + var(--space-2xs));             /* 40 / 46 / 50; live 50 */
    --space-indent: calc(var(--space-l) + var(--space-xs));               /* 44 / 51 / 55; live 55, the about body */
    --space-block: calc(var(--space-xl) + var(--space-2xs));              /* 56 / 64 / 70; live 70 head gap, 60 phone band */
    --space-card-pad: calc(var(--space-xs) + var(--space-2xs));           /* 20 / 23 / 25; live 25 card padding, 24.7 button inline */
    --space-hero-top: calc(var(--space-3xl) + var(--space-3xl) + var(--space-2xs));   /* 250 at 1440; live 250 */
    /* A gap that OPENS with the viewport: a pair minus its own small step is
     * 0 at 390 and 40 at 1440. Live's two big insets are 0 on a phone and
     * 90 / 100 at 1440; two of these plus a step reproduce that line. */
    --space-ramp: calc(var(--space-l-2xl) - var(--space-l));                                   /*  0 / 24 / 40 */
    --space-inset-list: calc(var(--space-ramp) + var(--space-ramp) + var(--space-2xs));      /*  8 / 58 / 90; live 0 / - / 90 */
    --space-inset-head: calc(var(--space-ramp) + var(--space-ramp) + var(--space-s));        /* 16 / 67 / 100; live 0 / - / 100 */
    /* The mirror image: a gap that CLOSES as the viewport widens. A step minus
     * its own pair is positive on a narrow screen and 0 at 1440, so taking it
     * off a value leaves 1440 exactly as measured and eases everything below.
     * Used by the desktop nav (2026-10-03) to keep its six links, the logo
     * and the Call pill on one row down to 1200, as live's fluid root does.
     * px at 390 / 1200 / 1300 / 1440: */
    --space-taper: calc(var(--space-3xl) - var(--space-2xl-3xl));                              /* 32 / 7.3 / 4.3 / 0 */
    --space-taper-s: calc(var(--space-s) - var(--space-xs-s));                                 /*  4 / 0.9 / 0.5 / 0 */

    /* --- Shell -------------------------------------------------------
     * Live's INNER content measures 1350px, with a 45px gutter outside it, so
     * the container's max-width is 1350 + 2*45 = 1440. Verified at 1920, where
     * the inner still measures 1350 -- a real cap, not viewport-minus-padding.
     * The services band caps its inner at 1500 (so 1500 + 2*50 = 1600). */
    --shell: 90rem;            /* 1440px -> 1350px of content */
    --shell-wide: 100rem;      /* 1600px -> 1500px of content */
    /* MEASURED gutter: 20px@390, 30px@1024, 45px@1440. As a sum of steps:
     * 20 / 35 / 45 (Dials' s-l pair plus 3xs), so the inner is 1350 at
     * 1440, live's exactly. */
    --space-gutter: calc(var(--space-s-l) + var(--space-3xs));
    --grid-max-width: var(--shell);
    --grid-gutter: var(--space-gutter);
}
/* The site's blues in older browsers (no relative colour: iOS 16 and 17,
 * Safari before 18, Chrome and Edge before 123, Firefox before 128), under
 * Dials' own fallback condition: the brand dials mixed into white with
 * color-mix() alone, within a few units of each (the vivid accent there is
 * the bright blue itself, a little darker). */
@supports not ((color: oklch(from red l c h)) and (color: light-dark(red, red))) {
    :root {
        --tc-sky: color-mix(in oklab, var(--secondary-solid) 17%, white);
        --tc-mid: color-mix(in oklab, var(--secondary-solid) 42%, white);
        --tc-vivid: var(--secondary-solid);
        --tc-ink-soft: color-mix(in oklab, var(--tertiary-solid) 78%, white);
    }
}

/* Fields (owner, 2026-10-05: one shape for every text field, search and
 * contact alike): pills like every button here (.btn, the Call button; one
 * corner, --control-radius, for every button and field), at the contact
 * form's height (47px at the desktop, as live), with Dials' control border
 * (--border-strong, 3:1; live's mid-blue hairline was 1.6-1.8:1). The textarea
 * takes half a 44px control as its corner. The fill is per ground: the
 * contact card re-sets it. Tokens only; see Form controls. */
:root {
    --control-radius: var(--radius-pill);
    --field-h: max(var(--target-min), calc(var(--size-0) * var(--leading-body) + 2 * var(--space-2xs) + 2 * var(--border-width-s)));
    --field-pad-block: var(--space-2xs);
    --field-pad-inline: var(--space-s);
    --field-textarea-radius: calc(var(--target-min) / 2);
    --field-leading: var(--leading-snug);   /* the fields' 1.3, as before */
}
/* Field and ring colours, on the four selectors Form controls declares them
 * on. The edge does not change on hover. ONE focus ring on links, buttons
 * and fields: the bright blue the nav and links hover in, 4.6-5.8:1 on the
 * white, grey and sky grounds and 3.3:1 on the mid blue. The navy grounds
 * (the footer bar, the emergency panel, the phone menu) re-set it to the
 * mid blue: 9.4:1 on the navy, 5.5:1 on the deep blue. */
:root, [data-dials], .is-light, .is-dark {
    --field-border-hover: var(--field-border);
    --focus-ring: var(--secondary-line);
}
.site-footer__bar,
.emergency-panel,
.mobile-nav { --focus-ring: var(--tc-mid); }

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

/* Headings: live's ladder sits one step lower than the template's
 * (h1 33px, h2 27, h3 24, h4 20 at 1440), and every heading is 1.2 at
 * every size, as live's are. */
h1, .h1 { font-size: var(--size-4); }
h2, .h2 { font-size: var(--size-3); }
h3, .h3 { font-size: var(--size-2); }
h4, .h4 { font-size: var(--size-1); }
h1, h2, h3, h4, .h1, .h2, .h3, .h4 { line-height: var(--leading-display); }

/* The search box's Search button is a .btn without the class (the site's
 * button rules list both): centred, one line, and the 44px floor. */
.mf-search__submit {
    justify-content: center;
    min-block-size: var(--target-min);
    text-align: center;
    white-space: nowrap;
    cursor: pointer;
}

/* Bold runs are the headings' 700, as live's are (Dials' --weight-strong,
 * the body weight plus 200, is 600). */
strong, b { font-weight: var(--weight-heading); }

/* The 404 numeral is the hero's display size and leading; its lede keeps
 * the body's 1.5. */
.notfound__code { font-size: var(--size-8); line-height: var(--leading-hero); }
.notfound__lede { line-height: var(--leading-body); }


/* Live's root is fluid; ours is not — the steps carry the fluidity instead.
 * Stated explicitly so nobody reintroduces the double-scaling. */
html { font-size: 100%; }

/* The hero badge bleeds past the right edge by design -- live does the same,
 * deliberately, so the icon tile runs off the page. Live sets
 * `overflow-x: clip` on <body>, which does NOT stop the document scrolling:
 * measured on live, scrollWidth is 1445 against a 1440 viewport and 1110
 * against 1060, i.e. live's own page scrolls sideways at 1060-1440.
 *
 * DELIBERATE DIVERGENCE. The bleed is the design and is kept; the sideways
 * scroll is a live defect and is not. Clipping at the ROOT is what actually
 * stops it. `clip` rather than `hidden` so position:sticky still works. */
html { overflow-x: clip; }
body { overflow-x: clip; }

/* The template's body rule sets the face, size, leading and colour; the
 * page under the bands is white, as live's is. */
body { background: var(--surface-raised); }

/* The template sets text-wrap: balance and overflow-wrap: break-word on
 * every heading. Live sets neither, and they change line counts (a two-line
 * hero title becomes three). */
h1, h2, h3, h4, h5, h6 {
    text-wrap: wrap;
    overflow-wrap: normal;
}

a { color: var(--secondary-on-soft); }

/* --- Containers -------------------------------------------------------- */
.u-container {
    width: 100%;
    max-width: var(--shell);
    margin-inline: auto;
    padding-inline: var(--space-gutter);
}
.u-container--wide { max-width: var(--shell-wide); }

/* A band is the top-level rhythm unit. Live pads 120px top and bottom at
 * 1440 on every band except the accreditation strip (which is flush) and
 * the hero (250px top, to clear the 161px header that sits above it).
 * --space-3xl is that 120 at 1440 and scales to 96 at 390 (owner decision
 * 2026-10-03: spacing scales even where live's is flat). */
.band { padding-block: var(--space-3xl); background: var(--surface); }
.band--sky { background: var(--tc-sky); }

/* --- Buttons ----------------------------------------------------------- */
/* Live: rgb(2,69,122) fill, white text, 100px radius (a pill), padding
 * 12.3744px 24.7488px = 0.75rem 1.5rem of live's own root, uppercase,
 * weight 600, font 16.4992px. The header CTA is the same pill at 45px
 * inline padding and 16px block, weight 700, radius 250px. */
.btn,
.mf-search__submit {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3xs);
    padding: var(--space-2xs-xs) var(--space-card-pad);   /* live 12.4 / 24.7 at 1440 -> 15 / 25; 8 / 20 at 390 (live 9.9 / 19.8) */
    border-radius: var(--control-radius);
    background: var(--brand-solid);
    color: var(--brand-on-solid);
    font-family: var(--font-body);
    font-size: var(--size-0);
    font-weight: var(--weight-strong);
    line-height: var(--leading-body);
    text-transform: uppercase;
    text-decoration: none;
    border: 0;
    transition: background var(--duration-base) ease, transform var(--duration-base) ease;
}
/* HOVER, measured off live (2026-09-18): the fill becomes a two-stop gradient,
 * deep navy -> accent, at 249deg on the body buttons and 131deg on the header
 * CTA. A background-image cannot transition, so the gradient is a ::before at
 * opacity 0 that fades in over the flat fill.
 * DIVERGENCE: live's far stop is rgb(2,138,190), on which the white label
 * measures 3.9:1. Ours ends on --brand-bright, the same darkened accent used
 * everywhere else on this site (5.7:1), so the label passes AA across the
 * whole gradient. */
.btn,
.mf-search__submit { position: relative; isolation: isolate; }
.btn::before,
.mf-search__submit::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: var(--layer-behind);
    border-radius: inherit;
    background-image: linear-gradient(249deg, var(--brand-solid) 0%, var(--secondary-solid) 100%);
    opacity: 0;
    transition: opacity var(--duration-base) var(--ease-out);
}
.btn--head::before { background-image: linear-gradient(131deg, var(--brand-solid) 0%, var(--secondary-solid) 100%); }
.btn:hover::before, .btn:focus-visible::before,
.mf-search__submit:hover::before, .mf-search__submit:focus-visible::before { opacity: 1; }
/* the template's own hover fills would otherwise paint over the gradient's base */
.btn:hover, .btn:focus-visible, .btn--primary:hover,
.mf-search__submit:hover, .mf-search__submit:focus-visible { background: var(--brand-solid); color: var(--brand-on-solid); }
.btn svg { width: 1em; height: 1em; fill: currentColor; flex: none; }

/* MOTION, also live's: the header CTA "floats" -- lifts 8px and holds -- and
 * the body buttons "bob": the same 8px lift, then a slow drift between -8 and
 * -4px for as long as the pointer stays. transform only; hover only (a
 * keyboard focus gets the gradient but does not move); off under reduced motion. */
/* The lift is a TRANSITION on the individual `translate` property and the bob
 * is an ANIMATION on `transform`, so they compose: when the pointer leaves, the
 * bob stops and the lift eases back down. (Elementor does both on `transform`,
 * which makes live's button snap 8px on mouse-out.) */
@media (prefers-reduced-motion: no-preference) {
    .btn { transition: translate 0.3s ease-out; }
    .btn:hover { translate: 0 -8px; }
    .btn:not(.btn--head):hover { animation: btn-bob 1.5s ease-in-out 0.3s infinite alternate; }
}
@keyframes btn-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(4px); } }

/* PADDING: live states the header CTA's padding in FIXED px (16 / 45), so the
 * button grows only with its label. Ours was in em, which matched at 1440 and
 * then swelled with the fluid type -- 282x62 against live's 254x56 on a 2223px
 * screen, which is where the owner saw it as over-padded. On the space scale
 * now: --space-xs and l + 3xs are 15 / 46 at 1440 and hold there, so the
 * pill no longer swells with its label on a larger screen. */
.btn--head { padding: var(--space-xs) calc(var(--space-l) + var(--space-3xs)); font-weight: var(--weight-heading); }

/* --- Eyebrow pill ------------------------------------------------------
 * Live: sky ground, 5px radius, 10px 15px padding, 16.4992px, weight 700,
 * uppercase, bright blue. The services band's variant is outlined instead
 * of filled, and the contact band's is Karla at weight 500. */
.eyebrow {
    display: inline-block;
    padding: var(--space-2xs) var(--space-xs);   /* live 10px 15px; the tokens are 10 / 15 at 1440 */
    border-radius: var(--radius-xs);
    background: var(--tc-sky);
    color: var(--secondary-on-soft);
    font-family: var(--font-heading);
    font-size: var(--size-0);
    font-weight: var(--weight-heading);
    line-height: var(--leading-body);
    text-transform: uppercase;
    letter-spacing: normal;
    margin: 0;
}
.eyebrow--deep { color: var(--brand-on-soft); }
.eyebrow--outline {
    /* live: a 30px-tall tag -- 4px 10px padding and a 1.2 leading, not the filled pill's 10px 15px */
    padding: var(--space-3xs) var(--space-2xs);
    line-height: var(--leading-display);
    background: transparent;
    border: var(--border-width-s) solid var(--brand-line);
    color: var(--brand-on-soft);
    font-family: var(--font-accent);
    font-weight: var(--weight-medium);
}
.eyebrow--alt {
    /* live: 27px tall, 4px 10px, 1px deep-navy outline on a clear ground */
    padding: var(--space-3xs) var(--space-2xs);
    background: transparent;
    border: var(--border-width-s) solid var(--brand-line);
    font-family: var(--font-accent);
    font-weight: var(--weight-medium);
    line-height: 1;
    color: var(--brand-on-soft);
}

/* --- Display headings --------------------------------------------------
 * Live: hero 74.2465px (4.5rem) weight 600; section titles 57.7473px
 * (3.5rem) weight 700; contact title 32.9984px (2rem) weight 700. All Lato
 * on navy, except the contact title which is bright blue. Line-height
 * re-measured 2026-09-18: 1.1 on the hero (81.7 over 74.25) and 1.2 on the
 * section titles (69.3 over 57.75). */
.display {
    font-family: var(--font-heading);
    font-size: var(--size-8);
    font-weight: var(--weight-strong);
    line-height: var(--leading-hero);
    color: var(--tertiary-on-soft);
    margin: 0;
}
.section-title {
    font-family: var(--font-heading);
    font-size: var(--size-7);
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--tertiary-on-soft);
    margin: 0;
}
/* .display--sm had no rule of its own, so it fell through to .display's 74px
 * where live sets 49.5px / 700 / 1.2 in the mid navy. */
.display--sm {
    font-family: var(--font-heading);
    font-size: var(--size-6);
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--brand-on-soft);
    margin: 0;
}
.band-title {
    font-family: var(--font-heading);
    font-size: var(--size-4);
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--tc-vivid);
    margin: 0;
}

.lede { font-size: var(--size-1); line-height: var(--leading-body); margin: 0; }
.lede + .lede { margin-top: var(--space-xs); }   /* live 0.8em = 14.8px at 1440 */

/* ===========================================================================
 * HEADER — measured 161px tall at 1440. Logo 260x100 at x=45; nav centred on
 * a 655px run at 16.4992px Lato 700 with 1px sky separators between items;
 * CTA pill hard right. Live's header sits ABOVE the hero, not over it — the
 * hero's own 250px top padding is inside its band.
 * ======================================================================== */
/* MEASURED: live's header is transparent and the hero runs UNDER it -- <main>
 * starts at y=1 while the header occupies 0-161. So the header costs the page
 * no height, and the hero's 250px top padding is mostly spent repaying that
 * overlap (live's H1 lands at y=261, i.e. 100px below the header's bottom).
 * The header must therefore sit above the hero in paint order. */
.site-header {
    position: relative;
    z-index: var(--layer-nav);
    background: transparent;
    border-bottom: var(--border-width-s) solid var(--tc-mid);   /* live: 1px rgb(151,202,219) */
}
.site-main { margin-top: calc(-1 * var(--header-h)); }
:root { --header-h: 10.0625rem; }             /* 161px */
.site-header__inner {
    display: flex;
    align-items: center;
    gap: var(--space-s);
    min-height: 10.0625rem;                 /* live 161px */
    padding-block: var(--space-2xs);
}
.site-logo { flex: none; display: block; }
.site-logo img { width: 16.25rem; height: auto; display: block; }   /* 260px */

/* MEASURED: live's nav starts 50px after the logo (x=355) and is left-aligned;
 * the CTA takes the right edge. It is not centred between them. */
.site-nav { margin-inline: var(--space-m) auto; }
.site-nav ul {
    display: flex;
    align-items: center;
    list-style: none;
    margin: 0;
    padding: 0;
}
/* Live's separator is an accent hairline 18.6px tall, centred on the label,
 * with 5px of air either side -- not a full-height border. */
.site-nav li { position: relative; }
.site-nav li + li { margin-left: var(--space-3xs); padding-left: var(--space-3xs); }
.site-nav li + li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    height: 1.125em;
    border-left: var(--border-width-s) solid var(--secondary-line);
    transform: translateY(-50%);
}
.site-nav a {
    display: block;
    /* Both ease toward the collapse and are untouched at 1440 (label 16.5,
     * padding 15; live 16.5 / 14-15). Padding 15 / 9.8 / 6.1 and label
     * 16.5 / 15.9 / 15.5 at 1440 / 1300 / 1200 -- the label follows live's own
     * fluid text (16.5 / 16.1 / 15.7) rather than staying at body size. */
    padding-inline: calc(var(--space-2xs-xs) - var(--space-taper));
    font-family: var(--font-heading);
    font-size: calc(var(--size-0) - var(--space-taper-s));
    font-weight: var(--weight-heading);
    line-height: var(--leading-body);
    color: var(--text);
    text-decoration: none;
    /* A label never breaks inside the one-row bar: the row is swept at 1px
     * from the collapse to 1920 and fits everywhere, so a two-line label can
     * only mean the row ran short, which nowrap turns into a measurable
     * overflow rather than a quiet wrap. Centred all the same, so a label that
     * ever did wrap would sit centred between its two separators (the
     * separator air is symmetrical: padding + 3xs either side of the pipe). */
    white-space: nowrap;
    text-align: center;
}
.site-nav a:hover, .site-nav a:focus-visible { color: var(--secondary-on-soft); }
.site-nav a.active, .site-nav a[aria-current="page"] { color: var(--secondary-on-soft); }
.site-header .btn { flex: none; }

/* Mobile nav. Live collapses to a hamburger below 1024; we collapse at 1199
 * (see NAV COLLAPSE below) because our nav labels are wider at those widths
 * than live's. Live collapses to a panel of
 * Barlow 600 links at 20.624px. display:none while closed, deliberately: a
 * translateX(100%) drawer still contributes to document scroll width. */
.nav-toggle {
    display: none;
    flex: none;
    width: 2.75rem;
    height: 2.75rem;
    align-items: center;
    justify-content: center;
    /* live: a filled deep-navy square with white bars, 4px radius */
    background: var(--brand-solid);
    border: 0;
    border-radius: var(--radius-xs);
    color: var(--brand-on-solid);
    cursor: pointer;
}
.nav-toggle svg { width: 1.5rem; height: 1.5rem; fill: currentColor; }

/* NAV COLLAPSE at 1199, not live's 1024 (was 1299 until 2026-10-03; the
 * owner wants the full nav on 1280px laptops). MEASURED: the three header
 * blocks (260px logo, six Lato 700 links, the Call pill) leave the nav ~527px
 * at 1200, where the links at body size and 2xs-xs padding needed ~608. Live
 * fits by shrinking its logo and gutters; ours keeps both and instead eases
 * the link padding and label size on --space-taper / --space-taper-s, which
 * are 0 at 1440. Swept at 1px from 1200 to 1920 on every page: one row, no
 * label wrapped or clipped, the pill clear. 1081-1199 keeps the desktop
 * header's 161px bar and 260px logo.
 * OWNER'S CALL (2026-10-03): the menu button sits on the RIGHT beside the Call
 * pill, one group with the header's own scale gap between them (--space-s,
 * --space-xs from 1080 down) -- not centred between logo and pill as live
 * does at 1024. Its auto left margin takes all the free space. */
@media (max-width: 74.9375rem) {
    .site-nav { display: none; }
    .nav-toggle { display: inline-flex; order: 2; }
    .site-header .btn { order: 3; margin-left: 0; }
    .site-logo { order: 1; }
}

/* ===========================================================================
 * HERO — band 0. 1254px tall at 1440.
 * Ground rgb(242,244,246) under two radial gradients (transcribed verbatim
 * from live's computed background-image). Inner padding 250px top / 120px
 * bottom. Two columns: 700px copy, 570px arch photo with a 60px left margin.
 * ======================================================================== */
/* Four of live's six bands carry their own stack of radial gradients over the
 * ground -- a soft blue wash whose centres and radii differ per band. Copied
 * verbatim from live's computed background-image; this is decoration that
 * cannot be eyeballed, so it is transcribed rather than approximated. */
.hero {
    background:
        radial-gradient(1100px 800px at 85% 40%, color-mix(in srgb, var(--tc-vivid) 30%, transparent), transparent 48%),
        radial-gradient(1200px 900px at 70% 55%, color-mix(in srgb, var(--tc-mid) 22%, transparent), transparent 72%),
        radial-gradient(1300px 950px at 25% 50%, color-mix(in srgb, var(--tc-sky) 12%, transparent), transparent 78%),
        var(--surface);
    padding-block: 0;
}
.about {
    background:
        radial-gradient(900px 700px at 22% 22%, color-mix(in srgb, var(--tc-mid) 20%, transparent), transparent 50%),
        radial-gradient(1100px 850px at 45% 55%, color-mix(in srgb, var(--tc-vivid) 22%, transparent), transparent 50%),
        radial-gradient(1300px 950px at 28% 78%, color-mix(in srgb, var(--tc-sky) 14%, transparent), transparent 70%),
        var(--surface);
}
.why {
    background:
        radial-gradient(1000px 700px at 20% 25%, color-mix(in srgb, var(--tc-vivid) 28%, transparent), transparent 48%),
        radial-gradient(1100px 800px at 80% 40%, color-mix(in srgb, var(--tc-mid) 22%, transparent), transparent 72%),
        radial-gradient(1200px 850px at 30% 75%, color-mix(in srgb, var(--tc-sky) 14%, transparent), transparent 78%),
        var(--surface);
}
.services {
    background:
        radial-gradient(900px 700px at 22% 22%, color-mix(in srgb, var(--tc-mid) 20%, transparent), transparent 72%),
        radial-gradient(1100px 850px at 45% 55%, color-mix(in srgb, var(--tc-vivid) 22%, transparent), transparent 70%),
        radial-gradient(1200px 900px at 82% 50%, color-mix(in srgb, var(--tc-vivid) 28%, transparent), transparent 55%),
        radial-gradient(1300px 950px at 28% 78%, color-mix(in srgb, var(--tc-sky) 14%, transparent), transparent 80%),
        var(--surface);
}
.hero__inner {
    padding-block: var(--hero-pad-top) var(--hero-pad-bottom);
    display: flex;
    flex-direction: column;
    gap: var(--space-s);
}
/* MEASURED: live's hero pads 250px top / 120px bottom above 1024, and
 * 180px / 50px at 1024 and below. It is a breakpoint on live, not a curve,
 * so it is a breakpoint here. */
:root { --hero-pad-top: var(--space-hero-top); --hero-pad-bottom: var(--space-3xl); }   /* 250 / 120 at 1440 */

.hero__cols {
    display: grid;
    grid-template-columns: minmax(0, 700fr) minmax(0, 630fr);
    gap: var(--space-s);                      /* live 20px */
}
.hero__copy { display: flex; flex-direction: column; align-items: flex-start; }
/* stretch to the media column's height so margin-top:auto has room to work */
.hero__cols { align-items: stretch; }
.hero__copy > * + * { margin-top: 0; }
.hero .display { margin-top: var(--space-s); max-width: 100%; }               /* live 19px */
.hero__lede { margin-top: var(--space-2xs); max-width: 39rem; }   /* live 10px below the h1; 623px wide */

/* The two rule rows. Live: 500px wide, 1px top rule on the first and 1px
 * bottom rule on the second (so the pair reads as three hairlines), 10px
 * block padding, items separated by a Karla "/" at 18.1491px. */
.hero__facts { margin-top: var(--space-l); width: min(100%, 31.25rem); }
.hero__fact-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2xs) var(--space-xs);
    padding-block: var(--space-2xs);
}
/* live: row 1 is ruled top AND bottom, row 2 bottom only -- three hairlines */
.hero__fact-row { border-bottom: var(--border-width-s) solid var(--tc-mid); }
.hero__fact-row:first-child { border-top: var(--border-width-s) solid var(--tc-mid); }
.hero__fact {
    font-size: var(--size-0);
    font-weight: var(--weight-medium);
    line-height: var(--leading-body);
    color: var(--brand-on-soft);
}
.hero__sep {
    font-family: var(--font-accent);
    font-size: var(--size-1);
    font-weight: var(--weight-medium);
    line-height: 1;                           /* the larger glyph must not inflate the 46px row */
    color: var(--secondary-on-soft);
    margin: 0;
}
.hero .btn { margin-top: var(--space-l); }   /* live 40px */

/* --- The arch crops ----------------------------------------------------
 * THE KEY DETAIL OF THIS PAGE. Live draws every arch as a CSS
 * background-image on a div wearing a FIXED-PIXEL border-radius — not a
 * clip-path, not an SVG mask, not a pre-cropped image.
 *
 * Because the radius is fixed px and the box is not, the shape's CHARACTER
 * changes with the viewport, and live lets it:
 *
 *   hero portrait   1920  570x932   r 500px -> radius > half the width, so
 *                                     the top clamps to a full semicircle
 *                   1440  570x884   r 500px -> same, near-semicircular
 *                   1024  964x849   r 500px -> a shallow, wide arc
 *                    390  350x477   r 500px -> clamps to a semicircle again
 *
 *   small cards     1440  165x200   r 100px -> a tall arch
 *                   1024  231x116   r 100px -> radius > half the height, so
 *                                     the whole top rounds off
 *                    390  165x209   r 100px -> back to a tall arch
 *
 * Reproduced by stating the same fixed radii; the browser's own clamping
 * then produces live's shape at each width, because it is the same
 * mechanism. Measured against live at all three widths.
 */
.arch {
    background-repeat: no-repeat;
    background-size: cover;
    background-position: 50% 50%;
    border-radius: 500px 500px 10px 10px;
}
.arch--sm { border-radius: 100px 100px 10px 10px; }

.hero__media {
    position: relative;
    margin-left: var(--space-l-xl);          /* live 60px, inside the 630 track */
    padding-inline: var(--space-inset-m);         /* live 50px */
    /* No min-height above the stack breakpoint: live's arch is height:auto and
     * simply stretches to the copy column (856px at 1440, 932 at 1920). A
     * fixed 884px made the hero 28px taller than live's. */
    background-image: url("/assets/images/hero-doctor-patient.a7fb1fd554.webp");
}
.hero__badge {
    position: absolute;
    top: 1.875rem;                            /* 30px */
    /* Live's badge overhangs the arch but NEVER the viewport: measured, it
     * clears by 95px at 1440 and 30-50px below that. The -100px offset is
     * relative to the arch, so once the shell stops growing the badge starts
     * eating the gutter and then the edge -- it overhung by 11-16px from
     * 1120 to 1440. Clamp the pull to whatever space is actually spare. */
    right: clamp(0px, calc((100vw - var(--shell)) / 2 - var(--space-m)), var(--space-inset-m));
    display: flex;
    flex-direction: row-reverse;
    align-items: center;
    gap: var(--space-xs);                     /* live 14px */
    background: var(--tc-sky);
    border-radius: var(--radius-s);
    padding-left: var(--space-s);
    max-width: 100%;
}
.hero__badge-icon {
    flex: none;
    display: grid;
    place-items: center;
    width: 4.0625rem;                         /* 65px */
    height: 4.0625rem;
    background: var(--secondary-solid);
    border-radius: 0 20px 20px 0;
    color: var(--secondary-on-solid);
}
.hero__badge-icon svg { width: 1.6875rem; height: 1.6875rem; fill: currentColor; }
.hero__badge-title {
    font-family: var(--font-heading);
    font-size: var(--size-2);
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--brand-on-soft);
    margin: 0;
}
.hero__badge > div { text-align: center; }   /* live centres both lines */
.hero__badge p:not(.hero__badge-title) { margin: 0; font-size: var(--size-0); line-height: var(--leading-body); }

/* The row of three sits INSIDE the copy column, not below both columns --
 * measured on live, where the copy column is 700x884 (the same height as the
 * media column) and the cards land on its bottom edge. Building it as a
 * sibling row below both columns made the hero 279px too tall.
 *
 * Within that 700px column live draws 165 + 165 + 330 with two 20px gaps,
 * which is 700 exactly. margin-top:auto pushes the row to the column's
 * bottom, which is what makes the two columns the same height. */
.hero__cards {
    width: 100%;
    margin-top: auto;
    padding-top: calc(var(--space-2xl) + var(--space-s));  /* 100; live 106px between the CTA and the cards */
    display: grid;
    grid-template-columns: minmax(0, 165fr) minmax(0, 165fr) minmax(0, 330fr);
    gap: var(--space-s);                      /* live 20px */
    align-items: stretch;
}
/* Live leaves the right half of this row empty: the two arch cards sit at
 * x=45 and x=230 and the hours card at x=415, ending at 745 within the 1350
 * inner. The fourth track is that empty remainder -- stated so the three
 * blocks keep live's widths instead of stretching across the row. */
.hero__card-photo {
    position: relative;
    height: 12.5rem;                          /* live 200px, fixed */
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    padding: var(--space-2xs);
}
/* Live's own inconsistency, reproduced: only the FIRST arch card is shadowed. */
.hero__card-photo:first-child { box-shadow: 4px 4px 26px -4px color-mix(in srgb, black 18%, transparent); }
.hero__card-photo .chip {
    display: grid;
    place-items: center;
    width: 2.125rem;                          /* 34px */
    height: 2.125rem;
    border-radius: var(--radius-round);
    background: var(--tc-sky);
    color: var(--secondary-on-soft);
}
.hero__card-photo .chip svg { width: 1.0625rem; height: 1.0625rem; fill: currentColor; }

.hours-card {
    height: 12.5rem;                          /* live 200px, fixed */
    background: var(--tc-sky);
    border-radius: var(--radius-s);
    padding: var(--space-s) var(--space-s) var(--space-s) var(--space-2xs);   /* live 20px, 10px left */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-xs);                      /* live 17px */
    text-align: center;
}
.hours-card__icon {
    display: grid;
    place-items: center;
    width: 2.75rem;                           /* 44px */
    height: 2.75rem;
    border-radius: 7px;
    background: var(--tc-mid);
    color: var(--secondary-on-solid);
}
.hours-card__icon svg { width: 1.375rem; height: 1.375rem; fill: currentColor; }
.hours-card h2 {
    font-size: var(--size-2);
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--text);
    margin: 0;
}
.hours-card p { margin: 0; font-size: var(--size-0); line-height: var(--leading-body); }

/* ===========================================================================
 * ACCREDITATION STRIP — band 1. 209px tall, sky ground, flush (no band
 * padding); a 1px mid hairline top and bottom. Copy left, AGPAL badge right
 * at its natural 250x94.
 * ======================================================================== */
.accred {
    background: var(--tc-sky);
    border-top: var(--border-width-s) solid var(--tc-mid);
    border-bottom: var(--border-width-s) solid var(--tc-mid);
}
.accred__inner {
    min-height: 8rem;                         /* live content is 128px tall */
}
/* MEASURED: live holds the logo beside the copy to 1080 and folds at 1024.
 * `flex: 1 1 auto` takes its basis from the content, and the paragraph's
 * max-width made that basis 1000px -- so the row needed 1000 + 250 + gap and
 * wrapped at ~1300, growing the band from 210px to 294px. A percentage basis
 * shrinks; the max-width still caps it at live's width. */
.accred h2 {
    font-size: var(--size-2);
    font-weight: var(--weight-heavy);
    line-height: var(--leading-display);
    color: var(--tc-vivid);
    margin: 0 0 var(--space-2xs);
}
.accred p { margin: 0; font-size: var(--size-1); line-height: var(--leading-body); max-width: 62.5rem; }
.accred img { width: 15.625rem; height: auto; flex: none; }   /* MEASURED: live paints the AGPAL symbol 250x94, at its natural size. The old 19.9375rem/319px was the HEADER logo's width, mis-copied -- 28% too wide at every width >= 1024. */

/* RE-MEASURED 2026-09-18 from captures at 1024 and 768: live keeps the logo
 * BESIDE the copy through the whole tablet range, shrinking it 250 -> 165px,
 * and only folds it underneath on phones. (An earlier note had the fold at
 * 1024; the captures show otherwise.) `flex-wrap: wrap` only PERMITS a fold,
 * so the phone fold is forced by giving the copy the full row. */
/* Live shrinks the logo THROUGH the folded range -- 250px at 1024 down to
 * 165px at 768. One definition, used by both rules below. */
:root { --accred-logo-w: clamp(10.3125rem, 22vw, 15.625rem); }
@media (max-width: 64rem) and (min-width: 48rem) {
    .accred img { width: var(--accred-logo-w); }   /* live 165-250px */
}

/* ===========================================================================
 * ABOUT — band 2. 1141px. Eyebrow, 57.7px title, a 700px copy column indented
 * to x=100 for the button, then a three-up row of feature panels 418px tall:
 * an outlined card, a translucent card holding an inner card, and a
 * dot-grid panel.
 * ======================================================================== */
.about__head { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-m); }
.about__body { margin-top: var(--space-inset-m); margin-left: var(--space-indent); max-width: 62rem; }  /* live 50px top, 55px indent, 992px wide */
.about__body p { font-size: var(--size-1); line-height: var(--leading-body); margin: 0; }
.about__body p + p { margin-top: var(--space-xs); }
.about .btn { margin-top: var(--space-m); margin-left: var(--space-indent); }   /* live x=100 within a 45px gutter */

.about__panels {
    margin-top: var(--space-inset-m);                              /* live 50px */
    min-height: 26.125rem;                                     /* live 418px */
    display: grid;
    grid-template-columns: minmax(0, 315fr) minmax(0, 314fr) minmax(0, 681fr);   /* live, of 1350 */
    gap: var(--space-s);
    align-items: stretch;
}
.panel {
    border-radius: var(--radius-l);
    padding: var(--space-m) var(--space-m);   /* live 30px inline */
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--space-m);
}
.panel--outline { background: var(--surface); border: var(--border-width-s) solid var(--secondary-line); }
.panel--tint { background: color-mix(in srgb, var(--tc-mid) 31%, transparent); justify-content: flex-start; }   /* live: the card hangs 30px from the top, not centred */
/* Live: a 154deg gradient on the element, with the dot-grid texture on a
 * ::before at OPACITY 0.06 -- barely perceptible. Painting the texture
 * directly at full strength turns a whisper into a dominant pattern, which is
 * exactly what the first pass did. */
.panel--grid {
    position: relative;
    isolation: isolate;
    background-image: linear-gradient(154deg, var(--surface) 32%, color-mix(in srgb, var(--tc-mid) 72%, transparent) 100%);
    /* OWNER'S CALL (2026-09-18): brand row and copy sit as ONE block centred in
     * the panel, 80px apart (live's own gap is 75). space-between had pinned
     * them to opposite edges, which opened a hole in the middle -- ~95px on
     * desktop and ~160px on a phone, where the panel is 477px tall. */
    justify-content: center;
    gap: var(--space-2xl);
}
.panel--grid h3 { font-size: var(--size-2); }
.panel--grid .panel__item { gap: var(--space-xs); }
/* /about: the same three panels, 466px tall, holding a Telephone Calls card
 * (406px) and the practice team. */
.about__panels--tall { min-height: 29.125rem; }
.about__panels--tall .panel__card { min-height: 25.375rem; }
/* These panels' copy is 18.56px (--step-1) like every other panel -- MEASURED
 * off live's DOM. A step-0 override sat here briefly, inferred from how the
 * text wrapped in a screenshot rather than measured; the owner spotted it. */
.panel__brand-text { display: flex; flex-direction: column; }
.panel__brand-sub { font-size: var(--size-0); font-weight: var(--weight-body); line-height: var(--leading-body); text-transform: uppercase; color: var(--text); }   /* live: Outfit 16.5 / 400 */
.panel--grid .panel__team { gap: 0; max-width: 33.75rem; }   /* live 540px, so the nurses line wraps where live's does */
.panel__team .panel__note { max-width: 28rem; }                /* live 447px */
/* on /about the team block follows the brand row ~85px down; it is NOT pinned
 * to the panel's bottom edge the way the homepage's copy is */
.about__panels--tall .panel--grid { justify-content: flex-start; gap: var(--space-2xl); }
.panel__team .panel__note { margin-top: var(--space-xs); }   /* live ~15px between the title and each paragraph */   /* live 24.75px, a step above the outline panel's */
.panel--grid::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: var(--layer-behind);
    opacity: 0.06;
    border-radius: inherit;
    background-image: url("/assets/images/dot-grid.8e4544bf8b.png");
    background-repeat: no-repeat;
    background-size: cover;
    background-position: 50% 100%;
}
.panel__item { display: flex; flex-direction: column; gap: var(--space-2xs); }
.panel__icon { color: var(--tc-mid); }
.panel__icon svg { width: 2.1875rem; height: 2.1875rem; fill: currentColor; }   /* 35px */
.panel h3 {
    font-size: var(--size-1);
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--brand-on-soft);
    margin: 0;
}
.panel p { margin: 0; font-size: var(--size-1); line-height: var(--leading-body); }

/* The inner card the tint panel holds — live 254x316, ground, 20px radius,
 * 20px padding, tag pinned to the top and the copy to the bottom. The shadow
 * is live's hard-edged "second sheet" (0 15px 0 -6px), not a soft drop. */
.panel__card {
    background: var(--surface);
    border-radius: var(--radius-l);
    padding: var(--space-s);
    min-height: 19.75rem;                     /* live 316px */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2xs);
    box-shadow: 0 15px 0 -6px color-mix(in srgb, black 19%, transparent);
}
.panel__card .tag { margin-bottom: auto; }
.panel__card h3 { font-size: var(--size-2); }
.tag {
    display: inline-block;
    padding: var(--space-3xs) var(--space-2xs);   /* live 4px 10px */
    border: var(--border-width-s) solid var(--brand-line);
    border-radius: var(--radius-xs);
    font-family: var(--font-accent);
    font-size: var(--size-0);                 /* live 16.5px on a 1.2 leading: 30px tall with the 4px padding */
    font-weight: var(--weight-medium);
    line-height: var(--leading-display);
    text-transform: uppercase;
    color: var(--brand-on-soft);
}
/* The dot-grid panel's brand row and its two ticked labels. */
.panel__brand { display: flex; align-items: center; gap: var(--space-xs); flex-wrap: wrap; }
.panel__brand img { width: 4.375rem; height: 4.375rem; }      /* 70px */
.panel__brand-name {
    font-family: var(--font-heading);
    font-size: var(--size-2);
    font-weight: var(--weight-heading);
    color: var(--brand-on-soft);
}
.panel__ticks { display: flex; gap: var(--space-xs); flex-wrap: wrap; margin-left: auto; }
.panel__tick { display: inline-flex; align-items: center; gap: var(--space-3xs); font-size: var(--size-0); }
.panel__tick svg { width: 0.875rem; height: 0.875rem; fill: var(--secondary-on-soft); flex: none; }

/* ===========================================================================
 * WHY — band 3. 1246px. Left: a 540x637 SKY ARCH with a 540x675 cut-out PNG
 * standing in front of it and overhanging the arch top by 38px. Right: three
 * 700x226 rows separated by 1px hairlines.
 *
 * The photo is a transparent-background cut-out, so it is an <img> over the
 * arch rather than a background on it. Live hides the arch below 1024
 * (elementor-hidden-tablet) and keeps the photo.
 * ======================================================================== */
.why__head {
    display: grid;
    grid-template-columns: minmax(0, 639fr) minmax(0, 691fr);   /* live, of 1350 */
    gap: var(--space-s);
    align-items: start;
    padding-bottom: var(--space-inset-m);         /* live 50px */
    min-height: 16.75rem;                     /* live head block is 268px */
}
.why__head-copy { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-m); }
.why__head-side {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--space-m);
    text-align: right;
    padding: var(--space-inset-m) 0 0 var(--space-inset-head);   /* live 50px top, 100px inset */
}
.why__head-side p { margin: 0; font-size: var(--size-1); line-height: var(--leading-body); }

.why__cols {
    margin-top: 0;
    display: grid;
    grid-template-columns: minmax(0, 540fr) minmax(0, 790fr);   /* live, of 1350 */
    gap: var(--space-s);
    align-items: start;
}
.why__media { position: relative; display: flex; align-items: flex-end; justify-content: center; }
/* MEASURED on live: the arch is 637px behind a 675px photo, both bottom-
 * aligned -- so its top sits 38px BELOW the image top and the person's head
 * overhangs it. That 38px is the whole point of the composition.
 *
 * It was stated as a fixed 637px while the photo scales with the column, so
 * the relationship only held at 1440: by 1120 the photo was 521px and the
 * arch stood 116px ABOVE it, poking into the row above. Express the ratio
 * instead (637/675 = 94.4%), so the head-room scales with the image. */
.why__arch {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 94.4%;
    background: var(--tc-sky);
    border-radius: 500px 500px 10px 10px;
}
.why__photo { position: relative; display: block; width: 100%; height: auto; border-radius: var(--radius-l); }

.why__list { display: flex; flex-direction: column; gap: var(--space-s); padding-left: var(--space-inset-list); }   /* live 90px inset, 20px rows */
.why__item {
    min-height: 14.125rem;                    /* live 226px per row at 1440 */
    justify-content: center;
    padding-block: var(--space-m);
    /* live rules every row top AND bottom, so the 20px gap reads as a pair of hairlines */
    border-block: var(--border-width-s) solid var(--tc-mid);
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
}
.why__item-icon { color: var(--tc-mid); }
.why__item-icon svg { width: 2.1875rem; height: 2.1875rem; fill: currentColor; }
.why__item h3 {
    font-size: var(--size-2);
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--brand-on-soft);
    margin: 0;
}
.why__item p { margin: 0; font-size: var(--size-1); line-height: var(--leading-body); }

/* ===========================================================================
 * SERVICES — band 4. 1355px. A single 1340x1185 sky card with a 10px radius
 * inside a 1500px shell, holding a centred head and then a four-column row:
 * a ticked services list in a ground card, and three photo+copy columns.
 * ======================================================================== */
/* Live: the band pads 50px top and 120px bottom with a 50px inline gutter,
 * and holds one 1340x1185 sky card whose inner pads 80px on every side. */
.services { padding-block: var(--space-inset-m) var(--space-3xl); }
.services .u-container { padding-inline: var(--space-inset-m); }  /* live 50px */
.services__card {
    background: var(--tc-sky);
    border-radius: var(--radius-s);
    padding: var(--space-2xl);                                 /* live 80px */
}
/* RE-MEASURED 2026-09-18: live stacks tag / title / lede 20px apart and leaves
 * 45px between the lede and the cards. --space-s is the 20px token at 1440
 * (--space-m is 30, the value that once made this head 20px too tall). */
.services__head { text-align: center; display: flex; flex-direction: column; align-items: center;
    gap: var(--space-s); margin-block-end: var(--space-l); }
/* Scoped to :not(.section-title) so this cannot outrank the title's own size
 * -- `.services__head p` and `.section-title` differ by one element in
 * specificity, and this rule is later, so an unscoped version silently wins. */
/* OWNER'S CALL (2026-09-18): two lines -- "Everything You Need / for Better
 * Health" -- as in the reference. Live's box is 43% of the card, so live itself
 * flips between two lines (1700, 2223) and three (1440, 1920) as the font and
 * the box scale at different rates. A cap in em tracks the title's own size, so
 * the break holds at every width: line one is ~9.3em, and adding "for" is ~11. */
.services__head .section-title { max-width: 10em; }
.services__head p:not([class]), .services__head p.services__lede {
    margin: 0;
    font-size: var(--size-1);
    line-height: var(--leading-body);
    max-width: 42.0625rem;                                     /* live 673px */
}

.services__grid {
    margin-top: var(--space-s);                                /* live 20px */
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-m);                                       /* live 30px */
    align-items: start;
}
.services__list {
    background: var(--surface);
    border-radius: var(--radius-s);
    padding: var(--space-l);                                  /* live 40px */
    list-style: none;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: calc(var(--space-3xs) * 1.5);                         /* live 7-8px: a 35.5px pitch on 27.8px lines */
}
.services__list li { display: flex; gap: var(--space-2xs); font-size: var(--size-1); line-height: var(--leading-body); }
.services__list svg { width: 0.9375rem; height: 0.9375rem; fill: var(--secondary-on-soft); flex: none; margin-top: var(--space-2xs); }   /* live 0.45em, 8.4px at 1440 */

/* live: 40px from the photo to the title, then the copy tucked 5px under it */
.service { display: flex; flex-direction: column; gap: var(--space-3xs); text-align: center; }
.service img {
    width: 100%;
    height: auto;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--radius-l);           /* live 20px... */
    display: block;
}
.service:first-of-type img { border-radius: 10px; }   /* ...except the first photo, which live leaves at 10px */
.service h3 {
    font-size: var(--size-1);
    font-weight: var(--weight-heading);
    line-height: var(--leading-snug);
    color: var(--brand-on-soft);
    margin: var(--space-l) 0 0;              /* live 40px under the photo */
}
.service p { margin: 0; font-size: var(--size-1); line-height: var(--leading-body); }

/* ===========================================================================
 * CONTACT — band 5. 387px, 80px block padding (not 120 — measured). Left:
 * eyebrow, 33px bright-blue title, pill. Right: two 308x226 sky cards.
 * ======================================================================== */
.contact {
    padding-block: var(--space-2xl);          /* live 80px */
    background: var(--surface);
    border-top: var(--border-width-s) solid var(--tc-mid);
}
.contact__inner {
    display: grid;
    /* live: the first card starts flush at x=720, the second 60px after it
     * (720-1028, 1088-1396). The 60fr track IS that gap. */
    grid-template-columns: minmax(0, 675fr) minmax(0, 308fr) minmax(0, 60fr) minmax(0, 308fr);
    gap: 0;
    align-items: center;
}
.contact__inner > .contact-card:last-child { grid-column: 4; }
.contact__copy { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-xs); }
.contact__copy .band-title { max-width: 42.1875rem; }          /* live 675px, one line */
.contact-card {
    min-height: 14.125rem;                    /* live 226px */
    background: var(--tc-sky);
    border-radius: var(--radius-s);
    padding: var(--space-l);                 /* live 40px */
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
    height: 100%;
    justify-content: center;
}
.contact-card__icon { color: var(--tc-mid); }
.contact-card__icon svg { width: 2.1875rem; height: 2.1875rem; fill: currentColor; }
.contact-card h2 {
    font-size: var(--size-1);
    font-weight: var(--weight-heading);
    line-height: var(--leading-display);
    color: var(--brand-on-soft);
    margin: 0;
}
.contact-card p { margin: 0; font-size: var(--size-1); line-height: var(--leading-body); }

/* ===========================================================================
 * FOOTER — 527px: a 462px ground panel in four columns (logo+blurb+social,
 * Quick Links, Working Hours, map) over a 65px navy bar.
 * ======================================================================== */
.site-footer { background: var(--surface); border-top: var(--border-width-s) solid var(--secondary-line); }
.site-footer__inner {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0;                                   /* live: four flush 338px columns (45 / 383 / 720 / 1058) */
    padding-block: var(--space-2xl);          /* live 80px */
    align-items: start;
}
/* Live centres the Quick Links block inside its column (heading at x=498 of a
 * column starting at 383); the other three columns are left-aligned. */
.site-footer__inner > :nth-child(2) { justify-self: center; }
/* Live's columns are a fixed 301px tall, which is what holds the panel at
 * 462px whatever the column contents come to. */
.site-footer__inner > * { min-height: 18.8125rem; }
/* OWNER'S CALL (2026-09-18): the logo's visible top lines up with the column
 * headings and the map. The PNG carries 12px of transparent padding above the
 * mark (alpha bbox 12..88 of 101), which is 11.6px at this 338px width, so the
 * box was level with the map but the MARK sat visibly lower. Pulled up by
 * exactly that padding -- tied to the asset, so a literal rather than a token. */
.site-footer__logo { display: block; }
.site-footer__logo img { width: 21.125rem; max-width: 100%; height: auto; display: block; margin-top: calc(-1 * var(--space-2xs)); }  /* 338px wide; live pulls it up 11.6px */
.site-footer__blurb { margin: var(--space-m) 0 0; font-size: var(--size-0); line-height: var(--leading-body); }
.site-footer__social {
    display: inline-flex;
    margin-top: var(--space-m);
    color: var(--brand-on-soft);
}
.site-footer__social svg { width: 1.875rem; height: 1.875rem; fill: currentColor; }  /* 30px */
.site-footer h2 {
    font-family: var(--font-heading);
    font-size: var(--size-1);
    font-weight: var(--weight-heading);
    /* Leading 1 with the cap-height offset taken off the top, so the LETTERS
     * start on the column's top edge with the logo mark and the map. The bottom
     * margin gives back what the 1.5 leading used to occupy, so the links and
     * hours below have not moved. The trim (3xs) and the give-back (s + xs)
     * are on the space scale; live's were -0.14em and 20px + 0.64em. */
    line-height: 1;
    color: var(--brand-on-soft);
    margin: calc(-1 * var(--space-3xs)) 0 calc(var(--space-s) + var(--space-xs));
}
.site-footer__links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }   /* the 35px pitch is the line-height alone */
.site-footer__links a {
    font-size: var(--size-0);
    font-weight: var(--weight-medium);
    line-height: var(--leading-nav);                        /* live rows are 35px apart at 16.5px */
    color: var(--tc-ink-soft);
    text-decoration: none;
}
.site-footer__links a:hover, .site-footer__links a:focus-visible { color: var(--secondary-on-soft); text-decoration: underline; }
.site-footer__links a.active, .site-footer__links a[aria-current="page"] { color: var(--secondary-on-soft); }
.site-footer__hours p { margin: 0; font-size: var(--size-0); line-height: var(--leading-body); }
.site-footer__hours em { display: block; margin-top: var(--space-xs); }
/* The hours come from Rails' opening_hours_html tag: a two-column table whose
 * day groupings (Mon–Fri, "Sat, Sun") Rails computes from the data. Laid out as
 * the two text lines it replaced -- bold label and colon, then the times -- with
 * none of the template's cell padding or row rules. The hero hours card centres
 * the block as it centred the old paragraph. */
.site-footer__hours .hours-table,
.hours-card .hours-table { width: auto; margin-block: 0; font-size: var(--size-0); line-height: var(--leading-body); }
.site-footer__hours .hours-table td,
.hours-card .hours-table td { padding: 0; border: 0; }
.site-footer__hours .hours-table td:first-child,
.hours-card .hours-table td:first-child { padding-inline-end: var(--space-3xs); }
.site-footer__hours .hours-table td:first-child::after,
.hours-card .hours-table td:first-child::after { content: ":"; }
.site-footer__hours .hours-table td:first-child { font-weight: var(--weight-heading); }
.hours-card .hours-table { margin-inline: auto; }
.site-footer__map {
    width: 100%;
    max-width: 21.125rem;                     /* live 338px */
    aspect-ratio: 338 / 245;
    border: 0;
    border-radius: var(--radius-xs);
    display: block;
}

/* OWNER'S CALL (2026-09-18): more air than live's 20px bar. One 30px unit
 * (--space-l) is used for the bar's padding AND either side of the rule, so
 * copyright | credit reads as evenly spaced instead of three different gaps. */
.site-footer__bar { background: var(--tertiary-solid); color: var(--tertiary-on-solid); padding-block: var(--space-m); }
.site-footer__bar-inner {
    display: flex;
    align-items: center;
    justify-content: flex-start;              /* copyright | credit on the left; legal links pushed right by their own auto margin */
    gap: var(--space-xs) var(--space-m);       /* rows (when it wraps) / columns */
    flex-wrap: wrap;
}
.site-footer__bar p, .site-footer__bar a { font-size: var(--size--1); line-height: var(--leading-body); margin: 0; color: var(--tertiary-on-solid); }
/* Specificity: `.site-footer__bar p { margin: 0 }` is (0,1,1) and was beating a
 * bare `.site-footer__legal` (0,1,0), so the auto margin never applied and the
 * links sat on the LEFT after the credit. Two classes puts them back right. */
.site-footer__bar .site-footer__legal { display: flex; align-items: center; gap: var(--space-xs); margin-left: auto; }   /* 17px either side of the divider; live has 24, ours had 10 */
.site-footer__legal a { text-decoration: none; transition: color var(--duration-fast) var(--ease-out); }
/* hover: the light brand blue (9.6:1 on the navy), with the underline kept so
 * the state never rests on colour alone */
.site-footer__legal a:hover, .site-footer__legal a:focus-visible { color: var(--tc-mid); text-decoration: underline; text-underline-offset: 0.2em; }
.site-footer__legal span { color: var(--tc-mid); font-family: "Open Sans", var(--font-body); font-weight: var(--weight-medium); }
/* Live runs the credit straight after the copyright, behind a 1px white rule --
 * not centred in the bar. */
.powered-by { display: inline-flex; align-items: center; gap: var(--space-xs); padding-left: var(--space-m); border-left: var(--border-width-s) solid color-mix(in srgb, var(--tertiary-on-solid) 45%, transparent); }
.powered-by span { font-size: var(--size--2); color: var(--tc-sky); }
.powered-by a { display: block; transition: opacity var(--duration-fast) var(--ease-out); }
.powered-by a:hover, .powered-by a:focus-visible { opacity: 0.8; }
.powered-by img { width: 4.6875rem; height: auto; display: block; }   /* 75px */

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

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

/* ===========================================================================
 * RESPONSIVE
 *
 * Live switches to an Elementor tablet layout at 1024 and a mobile one at 767.
 * Transcribed from measurements at those widths — NOT scaled desktop.
 *
 * Every track above is stated in `fr`, never px, so nothing can refuse to
 * shrink between the breakpoints. The band-scoped collapses are restated at
 * the END of the stylesheet so they win on source order as well as
 * specificity.
 * ======================================================================== */
@media (min-width: 768px) and (max-width: 1080px) {
    /* Tablet-only floors: measured at 1024 and NOT true at 390, so they are
     * bounded rather than left to leak down through the mobile block. */
    .about__panels .panel--grid { min-height: 27.25rem; }        /* live 436px */
    .about__panels .panel--outline,
    .about__panels .panel--tint { min-height: 26.125rem; }       /* live 418px */
}

@media (max-width: 1080px) {
    /* live: header 143px, hero pads 180/50 */
    :root { --hero-pad-top: calc(var(--space-3xl) + var(--space-xl)); --hero-pad-bottom: var(--space-inset-m); --header-h: 8.9375rem; }

    .accred { padding-block: var(--space-inset-m); }   /* live @1024 is 226px tall */

    /* live @1024: logo left, the menu button CENTRED in the bar, CTA right.
     * Ours puts the menu button beside the CTA on the right (owner, 2026-10-03;
     * the nav collapse itself is the 1199 block above) */
    .site-header__inner { min-height: 8.9375rem; gap: var(--space-xs); }   /* live 143px */
    .site-logo img { width: 20.4375rem; }     /* live 327px */

    /* Live stacks the hero at 1024: copy above, photo below at full width
     * (measured 964px wide, 849 tall — a wide shallow arch). */
    .hero__cols { grid-template-columns: minmax(0, 1fr); }
    .hero__media { margin-left: 0; min-height: 53rem; }
    .hero__badge { right: 0; }   /* see also the 1400px guard on the base rule */
    /* Live's small cards go 231x116 here — squat, so the 100px radius rounds
     * the whole top. Reproduced by letting the row keep three columns while
     * the height drops. */
    /* MEASURED at 1024: live's small cards are 231x116 -- squat enough that
     * the fixed 100px radius exceeds half the height, so the whole top rounds
     * off rather than reading as an arch. The shape change is live's own, and
     * it falls out of stating the same fixed radius on the same box size.
     * height, not min-height: the base rule sets a fixed 200px. */
    /* Live holds ~193px here and only goes squat at 1024 -- see the 1024
     * block below. Dropping to 116 at 1080 made them squat a breakpoint
     * early, which is what the owner saw as "very short". */
    .hero__card-photo { height: 12.0625rem; }   /* live 193px at 1080 */

    /* live @1024: a 2-up with the dot-grid panel full width beneath it at
     * 964x436, and the copy column no longer indented. */
    .about__panels { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); min-height: 0; row-gap: var(--space-s); }
    .about__panels .panel--grid { grid-column: 1 / -1; }
    .about__body { margin-left: 0; }
    .about .btn { margin-left: 0; }

    .why__head, .why__cols { grid-template-columns: minmax(0, 1fr); }
    .why__head-side { align-items: flex-start; text-align: left; padding: 0; }
    /* MEASURED: live drops the whole media column below 1440 -- the sky arch
     * carries elementor-hidden-tablet, and the cut-out photo itself measures
     * 0x0 at both 1024 and 390. Keeping it made this band 672px too tall. */
    .why__media { display: none; }
    .why__list { padding-left: 0; }

    /* MEASURED: live hides the Open Hours card at 1024 (0x0) and brings it
     * back at 390 (350x181). */
    .hours-card { display: none; }
    /* RE-MEASURED 2026-09-18 at 1024: the two photo cards stay 231px wide at the
     * left; they do not stretch across the row. And the hero copy is CENTRED
     * from the tablet layout down, not only on phones. */
    .hero__cards { grid-template-columns: repeat(2, minmax(0, 14.4375rem)); justify-content: start; }
    /* the tall heroes only: live keeps the SHORT heroes' copy left-aligned on tablet */
    .hero:not(.hero--short) .hero__copy { align-items: center; text-align: center; }
    .hero__lede { max-width: 100%; }
    .hero__facts { width: 100%; }
    .hero__fact-row { justify-content: center; }

    .services__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .services__card { padding-inline: var(--space-m); }

    .contact__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-s); }
    .contact__inner > .contact-card:last-child { grid-column: auto; }
    .contact__copy { grid-column: 1 / -1; }

    /* live @1024: a 2x2 of 447px columns, 80px block padding, bar 96px */
    .site-footer__inner { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-inset-m) var(--space-s); }
    .site-footer__inner > :nth-child(2) { justify-self: start; }
    .site-footer__inner > * { min-height: 0; }
    .site-footer__bar { padding-block: var(--space-l); }   /* live's 96px bar */
}

@media (max-width: 767px) {
    /* live: header 210px, STACKED -- a full-width logo row above, then the
     * hamburger and the CTA side by side below. One row here put the CTA
     * 107px off the right edge at 390. */
    /* --hero-pad-top: live keeps 180px here against a 210px header, which slides
     * the hero's pill under the header's hairline. Cleared by 30px instead. */
    :root { --header-h: 13.125rem; --hero-pad-top: calc(13.125rem + var(--space-s-l)); }   /* live header 210px */
    .site-header__inner {
        flex-wrap: wrap;
        min-height: 13.125rem;
        align-content: center;
        row-gap: var(--space-s);
    }
    /* OWNER'S CALLS, not live's: once the header stacks, the logo is CENTRED on
     * its own row and the menu button and the Call button sit CENTRED TOGETHER
     * beneath it at one height (44px, the touch-target floor; 2026-09-18,
     * re-confirmed 2026-10-03). Right-aligning the pair applies only to the
     * one-row bar above 767. Live parks the menu left and the CTA right, with
     * the CTA ~9px shorter than the menu button. */
    .site-header__inner { justify-content: center; column-gap: var(--space-xs); }
    .site-logo { flex: 1 0 100%; }
    .site-logo img { width: 100%; max-width: 21.9375rem; margin-inline: auto; }   /* live 351px */
    .nav-toggle { margin-inline: 0; }
    .site-header .btn { margin-left: 0; }
    .btn--head { min-height: 2.75rem; padding: 0 calc(var(--space-s) + var(--space-3xs)); }   /* live 1.6em, 21px at 390 */

    /* MEASURED at 390: live centres the hero block and the accreditation copy
     * (text-align: center on the display, both ledes and both fact rows). */
    .hero__copy { align-items: center; text-align: center; }
    .hero__lede { max-width: 100%; }
    .hero__facts { width: 100%; }
    .hero__fact-row { justify-content: center; }
    .accred__inner { text-align: center; }
    .accred__copy { text-align: center; }

    .hero__cols { grid-template-columns: minmax(0, 1fr); }
    .hero__cards { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    /* live 350x181 at 390 -- hidden at 1024, back here */
    .hours-card { display: flex; grid-column: 1 / -1; height: 11.3125rem; }
    .hero__card-photo { height: 13.0625rem; }    /* live 209px at 390 */
    .hero__media { min-height: 29.8125rem; }         /* live 477px at 390 */
    /* MEASURED at 390: live's badge is 225px wide, hugging its text, and sits at
     * the arch's top RIGHT, 20px in from the edge and 20px down. Ours had no
     * width, so as a block it stretched across the arch's whole content box
     * (270px) and sat centred. */
    .hero__badge { position: static; width: fit-content; max-width: 100%; margin: var(--space-s-l) 0 0 auto; padding-left: var(--space-2xs); }
    .hero__media { padding-inline: var(--space-s-l); }   /* 20px at 390: the badge's inset from the arch edge */

    /* live @390: 346px tall, 40px block padding, badge stacked under the copy.
     * The desktop min-height and the 32rem copy basis together made ours 734. */
    /* live @390: 40px block padding; a centred 242px copy block with 50px
     * beneath it; two 177px cards at 25px padding, 50px apart. */
    .contact { padding-block: var(--space-l); }
    .contact__inner { row-gap: var(--space-inset-m); }
    .contact__copy { align-items: center; text-align: center; padding-bottom: var(--space-inset-m); }
    .contact__copy .band-title { max-width: 100%; }
    .contact-card { min-height: 11.0625rem; padding: var(--space-card-pad); }   /* live 177px, 25px */
    .accred__inner { flex-direction: column; align-items: flex-start; min-height: 0; }
    .accred__copy { flex: 1 1 auto; }
    .accred img { width: 15.625rem; }

    /* live @390: the three panels stack at 337 / 312 / 477 tall */
    .about__panels { grid-template-columns: minmax(0, 1fr); min-height: 0; row-gap: var(--space-s); }
    .panel { padding: var(--space-s-l); }
    .panel--outline { min-height: 21.0625rem; }   /* live 337px */
    .panel--tint    { min-height: 19.5rem; }      /* live 312px */
    .panel--grid    { min-height: 29.8125rem; }   /* live 477px */

    .services__grid { grid-template-columns: minmax(0, 1fr); }
    .contact__inner { grid-template-columns: minmax(0, 1fr); }
    /* live @390: the why rows grow to 251px as the copy wraps to more lines */
    .why__item { min-height: 15.6875rem; }

    /* live @390: four stacked columns sized by their own content
     * (222/212/109/245) with 50px between them, 50px block padding, bar 141px */
    .site-footer__inner { grid-template-columns: minmax(0, 1fr); padding-block: var(--space-inset-m); row-gap: var(--space-inset-m); }
    .site-footer__inner > * { min-height: 0; }
    .site-footer__bar-inner { flex-direction: column; align-items: flex-start; gap: var(--space-2xs); }
    .site-footer__bar .site-footer__legal { margin-left: 0; }   /* both classes, to match the base rule */
    .powered-by { padding-left: 0; border-left: 0; }
    .site-footer__bar { padding-block: var(--space-l); }
    .site-footer__bar .site-footer__bar-inner { gap: var(--space-s); }
    .site-footer__bar .site-footer__legal { width: 100%; justify-content: center; padding-top: var(--space-s); border-top: var(--border-width-s) solid color-mix(in srgb, var(--tertiary-on-solid) 20%, transparent); }
    .site-footer__bar .site-footer__bar-inner { align-items: center; text-align: center; }   /* live centres the whole bar on phones */
}

/* --- Late collapse restatements ----------------------------------------
 * Restated here, at the end of the stylesheet, so a band-scoped rule above
 * cannot beat them on source order. This is the fix for the class of bug
 * where a mobile collapse exists but loses to a later, more specific rule. */
@media (max-width: 767px) {
    .hero .hero__cols,
    .about .about__panels,
    .why .why__head,
    .why .why__cols,
    .services .services__grid,
    .contact .contact__inner,
    .site-footer .site-footer__inner { grid-template-columns: minmax(0, 1fr); }
}


/* ==========================================================================
   PHASE 2 -- /services, /about, /practice-policy, /contact, /health-info
   ========================================================================== */

/* Live paints three band grounds plus transparent. --ground already IS
 * rgb(242,244,246), so the default .band needs no modifier. */
.band--ash  { background: var(--surface); }
.band--bare { background: transparent; }

/* --- Accreditation strip -------------------------------------------------
 * MEASURED: 40px block padding, not the 120px band rhythm. The paragraph is
 * 1011px wide on /about and /health-info but 819px on /practice-policy --
 * live's own per-page override, reproduced by .accred--narrow rather than
 * averaged away. */
.accred { padding-block: var(--space-l); }   /* MEASURED 40px, both pages */
.accred__inner {
    display: flex; align-items: center; gap: var(--space-m); flex-wrap: wrap;
    justify-content: space-between;
}
/* Live puts the logo on the RIGHT (measured x=1145 of 1350). Reordered
 * visually only -- the DOM keeps heading -> prose -> logo, which is the
 * sensible reading order. */
.accred__inner img { order: 2; }
.accred__copy { order: 1; }
@media (max-width: 29.9375rem) {
    /* live keeps the logo at 250px even at 390 and lets it sit above */
    .accred__inner { gap: var(--space-xs); }
}
.accred__inner img { flex: none; width: 15.625rem; height: auto; }   /* live 250px */
/* Live shrinks the logo through the folded range (250px at 1024 -> 165px at
 * 768). This layer is appended after the base one, so the size has to be
 * restated here or the flat 250px above wins at equal specificity. */
@media (max-width: 64rem) and (min-width: 48rem) {
    .accred__inner img { width: var(--accred-logo-w); }
}
/* `flex: 1 1 30rem` sets the basis on the MAIN axis, so once .accred__inner
 * wraps to a column at narrow widths the 30rem became a 480px HEIGHT and the
 * band ran 676px against live's 368. Live stays row-direction all the way to
 * 390 with the logo at its natural 250x94, so keep the row and let the copy
 * take the remaining width. */
.accred__copy { flex: 1 1 60%; min-width: 0; max-width: 63.1875rem; }   /* live 1011px; % basis so it shrinks before wrapping */
/* The inner pages' strip title is the homepage's <h2> in a <span>: live sets
 * both at Lato 24.75 / 800. It had drifted to Karla at 20.9px. */
.accred__title {
    display: block; font-family: var(--font-heading); font-size: var(--size-2);
    font-weight: var(--weight-heavy); line-height: var(--leading-display);
    margin-block-end: var(--space-2xs);
}
.accred--narrow .accred__copy { max-width: 51.1875rem; }   /* live 819px */

/* RE-MEASURED 2026-09-18 from captures at 1024 and 768: live keeps the logo
 * BESIDE the copy through the whole tablet range, shrinking it 250 -> 165px,
 * and only folds it underneath on phones. (An earlier note had the fold at
 * 1024; the captures show otherwise.) `flex-wrap: wrap` only PERMITS a fold,
 * so the phone fold is forced by giving the copy the full row. */
@media (min-width: 48rem) {
    .accred__inner { flex-wrap: nowrap; }
}
@media (max-width: 47.9375rem) {
    .accred__inner { flex-wrap: wrap; }
    .accred__copy { flex: 1 1 100%; max-width: none; }
}

.accred--narrow .accred__title { margin-block-end: var(--space-xs); }
.accred--narrow .accred__inner { align-items: flex-start; }

/* --- Hero variants -------------------------------------------------------
 * /about and /practice-policy use a shorter hero with a plain (un-arched)
 * photo, unlike the homepage and /services which carry the arch crop. */
/* MEASURED: /about's hero content starts at y=251 under a 161px header, so
 * the band carries ~250px of top padding and ~119 bottom, and its height is
 * set by the 670px photo rather than by the copy. */
/* MEASURED: live's short hero pads 150px at 1440 and 60px at 390 -- it DOES
 * scale, unlike the band rhythm. Holding 250px to 390 cost band0 +241px. */
.hero--short .hero__inner { padding-block: var(--space-hero-top) var(--space-3xl); }   /* /about: live 250 / 119 */
/* RE-MEASURED 2026-09-18: the arch starts at y=271 and runs to the band's
 * bottom edge (271 + 680 = 951), so the band pads 270px top and NOTHING at the
 * bottom.
 * The ground carries the same three radial washes as /health-info's hero. */
.band--ash.hero--short .hero__inner { padding-block: calc(var(--space-hero-top) + var(--space-s)) 0; }   /* live 270 */
/* The copy centres on the arch LESS a 120px foot -- which is why it rides high
 * on /practice-policy (tag 32px below the arch top) and lower on /health-info,
 * where there is no CTA and the block is shorter. One rule gives both. */
.band--ash.hero--short .hero__cols--about { align-items: center; }
.band--ash.hero--short .hero__copy { padding-bottom: var(--space-3xl); }
.hero__cols--about .section-title.section-title--narrow { max-width: 31.625rem; }   /* /health-info: live wraps at 506px */
.band--ash.hero--short { background-image:
    radial-gradient(1100px 800px at 85% 40%, color-mix(in srgb, var(--tc-vivid) 30%, transparent), transparent 48%),
    radial-gradient(1200px 900px at 70% 55%, color-mix(in srgb, var(--tc-mid) 22%, transparent), transparent 72%),
    radial-gradient(1300px 950px at 25% 50%, color-mix(in srgb, var(--tc-sky) 12%, transparent), transparent 78%); }
@media (max-width: 47.9375rem) {
    /* Both selectors restated: a media query does NOT raise specificity, so a
     * bare .hero--short (0,1,0) loses to .band--ash.hero--short (0,2,0) above
     * and practice-policy kept its desktop padding at 390. */
    /* DELIBERATE DIVERGENCE (2026-09-18). Live pads these heroes 60px at 390
     * while its transparent header is 210px tall, so on live's own phone
     * layout the tag and the first line of the title sit UNDERNEATH the logo
     * and the Call button -- unreadable. Reproducing that faithfully shipped
     * the same collision here. The copy now starts a clear 30px below the
     * header instead; the 60px bottom is live's. */
    .hero--short .hero__inner,
    .band--ash.hero--short .hero__inner { padding-block: calc(var(--header-h) + var(--space-s-l)) var(--space-block); }   /* bottom: live 60 at 390 */
    .band--ash.hero--short .hero__copy { padding-bottom: 0; }
}
/* MEASURED at 1440: /about and /practice-policy split their hero 595|595
 * inside a 1290px inner -- NOT the homepage's 700|570. The copy column drives
 * how the title and lede wrap, so getting it wrong shortens the whole band. */
.hero__cols--about {
    align-items: center;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--space-inset-head);         /* live 100px between the two 595px columns */
    /* width:100% is load-bearing: this is a flex item with auto margins, so
     * without it the grid shrink-wraps its (now capped) copy and the whole
     * hero narrows. */
    width: 100%; max-width: 80.625rem; margin-inline: auto;   /* live 1290px inner */
}
.hero__cols--about .hero__lede { max-width: 33.125rem; margin-top: var(--space-m); }   /* live 530px, 30px under the title */
.hero__cols--about .section-title { margin-top: var(--space-l); max-width: 36.5625rem; }   /* live 40px under the tag, 585px */
.hero__cols--about .hero__cta { margin-block-start: var(--space-2xs); }   /* + the button's own 40px = live's ~50px */
.hero__media-plain { display: flex; justify-content: flex-end; }
.hero__media-plain img { width: 100%; height: auto; max-width: 37.1875rem;
    border-radius: 500px 500px 0 0; }   /* live 595px wide, arched top */

/* --- /about hero ---------------------------------------------------------
 * MEASURED at 1440: 595px copy | 595px photo inside a 1290px inner, with a
 * 250x340 portrait overlapping the photo's right edge by 209px. The band
 * carries a radial gradient, not a flat ground. The portrait's radius is
 * asymmetric (flat on the left edge where it meets the photo). */
.about-hero { background: radial-gradient(at 100% 50%,
    var(--tc-mid) 0%, color-mix(in srgb, var(--tc-mid) 20%, transparent) 40%); }
.about-hero__media { position: relative; }
/* ONE rule: an earlier `height: 41.875rem` and a later `height: auto` sat at
 * equal specificity, so auto won and the photo rendered 714px against live's
 * 670 -- which is what closed up the space under the hero. */
.about-hero__photo {
    /* RE-MEASURED 2026-09-18: the arch is 500x670 and sits hard LEFT in its
     * 595px column (x=770) -- it does not fill the column. */
    width: 84%; height: auto; aspect-ratio: 500 / 670;
    max-height: 41.875rem; object-fit: cover;             /* live 670px at 1440 */
    border-radius: 500px 500px 10px 10px;
}
/* MEASURED across 390-1440: live keeps this flush to the CONTENT edge, never
 * hanging off it -- it clears the viewport by 1px at every width below 1440,
 * not by the 60px a negative offset gives. A -3.75rem `right` ran it 36px
 * off-screen from 1040 to 1400, which the geometry sweep caught. Live also
 * drops it 250px -> 150px below 1024. */
/* RE-MEASURED 2026-09-18 at 1440: the 250x300 portrait sits 330px down the
 * 670px column and hangs 41px off its right edge (x=1156-1406), overlapping the
 * arch by ~115px. The overhang is taken out of the gutter, less 5px, so it can
 * never reach the viewport edge however narrow the gutter gets. */
.about-hero__portrait {
    position: absolute; top: 49.25%;             /* 330 of 670 */
    right: calc(-1 * (var(--space-gutter) - var(--space-3xs)));
    width: 42%; max-width: 15.625rem; height: auto;   /* live 250px of 595 */
    border-radius: 20px 20px 20px 0;
}
/* Below the two-column breakpoint the overlap has nothing to overlap, so the
 * portrait returns to the flow rather than hanging off the photo. */
@media (max-width: 64rem) {
    .about-hero__portrait { width: 9.375rem; }    /* live drops to 150px */
}
.hero__sep--wide { display: inline; }
.hero__cta { margin-block-start: var(--space-m); }

/* --- /services -----------------------------------------------------------
 * MEASURED at 1440: one four-track grid, 273px columns inside a 1180px inner.
 * Column 1 is the checklist, columns 2-4 the tiles. Tracks are fr-based, not
 * the literal 273px -- a px track is what broke eight pages between 1040 and
 * 1380 before, and the playbook bans them in the site layer. */
/* MEASURED: live's band carries 50px top + 120px bottom on the outer con AND
 * 80px block on the inner -- 130 top / 200 bottom in total, not the 120/120
 * band rhythm. The gap this closed was -372px. */
.svc-all { padding-block: calc(var(--space-3xl) + var(--space-2xs)) calc(var(--space-3xl) + var(--space-2xl)); }   /* 130 / 200 */
/* MEASURED: live caps the title at 507px so it wraps to THREE lines (198px
 * tall), and the aside at 673px. Left unconstrained they render one line and
 * the band comes up ~200px short -- the same trap as the homepage's services
 * title. Both are left-aligned, not centred. */
.svc-grid {
    display: grid; gap: var(--space-m); margin-block-start: var(--space-l);
    grid-template-columns: repeat(4, minmax(0, 1fr));
    align-items: start;
}
/* MEASURED: live sets the checklist items and the aside prose at 18.56px
 * (--step-1), not the 16.5px body default. Across a four-track grid that one
 * step was most of a 264px band shortfall. The phone link stays at 16.5. */
/* MEASURED: the checklist column is a CARD -- rgb(242,244,246) ground, 10px
 * radius, 40px padding. Missing it left the column 213px short and the band
 * visibly wrong, not merely mismeasured. */
.check-list { list-style: none; padding: 0; margin: 0;
    display: grid; gap: var(--space-2xs); font-size: var(--size-1); }
.check-list li { display: flex; gap: var(--space-2xs); align-items: flex-start; }
.check-list svg { flex: none; width: 0.9375rem; height: 0.9375rem;
    fill: var(--tc-mid); margin-block-start: var(--space-3xs); }   /* live 15x15, 0.35em down */
.svc-tile img { width: 100%; height: auto; aspect-ratio: 1; object-fit: cover;
    border-radius: var(--radius-m); }
.svc-tile h3 { margin-block: var(--space-xs) var(--space-3xs); font-size: var(--size-1); }
.svc-tile p  { font-size: var(--size-1); }   /* live 18.56px, not the 16.5 body default */

/* Live's own breakpoints: 4 -> 2 -> 1. Tracks collapse, they never squeeze. */
@media (max-width: 64rem) {
    .svc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 39.9375rem) {
    .svc-grid { grid-template-columns: minmax(0, 1fr); }
}

/* --- /about --------------------------------------------------------------*/
.contact-note__title {
    display: block; font-weight: var(--weight-heading); color: var(--brand-on-soft);
    margin-block-end: var(--space-3xs);
}

.team-card {
    background: var(--surface-raised);
    padding: var(--space-m); display: flex; flex-direction: column;
    gap: var(--space-2xs); align-items: flex-start;
}
.team-card img { width: 100%; max-width: 15.625rem; height: auto; border-radius: var(--radius-m); }

/* MEASURED: the head block carries a 70px bottom gap before the card grid,
 * and the lede is 1122px wide (not the 960px a default max-width gives). */
/* live: the band's inner is 1290px (x=75), and the lede and CTA sit a further
 * 90px in -- the same inset the homepage's about body uses. */
.doctors > .u-container { max-width: calc(80.625rem + 2 * var(--space-gutter)); }
.doctors .section-title { margin-block-start: var(--space-m); }
.doctors__lede { max-width: 70.125rem; margin-block-start: var(--space-m); margin-left: var(--space-inset-list); }
.doctors__lede p { font-size: var(--size-1); }
.doctors .hero__cta { margin-block: var(--space-m) var(--space-block); margin-left: var(--space-inset-list); }   /* live's 70px head gap */
/* MEASURED at 1440: live lays the five doctors out 3-up (410px tracks) then
 * 2-up (630px), each a WHITE card with 50px side padding -- not one uniform
 * auto-fit run. auto-fit would put 4 on the first row and orphan the fifth.
 * The 3/2 split is expressed in fr so no px track reaches the site layer. */
.doctors__grid {
    display: grid; gap: var(--space-m); margin-block-start: var(--space-l);
    grid-template-columns: repeat(6, minmax(0, 1fr));
}
.doctor {
    background: var(--surface-raised); border-radius: 10px;       /* live 10px */
    padding: var(--space-inset-m) var(--space-inset-m) var(--space-l);   /* live 50/50/40 */
    grid-column: span 2;
    text-align: center;                          /* live centres every line */
}
.doctor:nth-child(4), .doctor:nth-child(5) { grid-column: span 3; }

@media (max-width: 64rem) {
    .doctors__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .doctor, .doctor:nth-child(4), .doctor:nth-child(5) { grid-column: auto; }
}
@media (max-width: 39.9375rem) {
    .doctors__grid { grid-template-columns: minmax(0, 1fr); }
}
/* Five doctors in two columns (640-1024) left the fifth beside an empty cell.
 * An odd last card spans the row and is centred at one column's width. */
@media (min-width: 40rem) and (max-width: 64rem) {
    .doctor:last-child:nth-child(odd) { grid-column: 1 / -1; justify-self: center; width: calc((100% - var(--space-m)) / 2); }
}
.doctor h3 { font-size: var(--size-1); color: var(--brand-on-soft); }
/* live sets the quals and the provider number alike: body ink, one size */
.doctor__quals, .doctor__provider { margin-block: 0; font-size: var(--size-1); line-height: var(--leading-snug); color: var(--text); }
.doctor h3 { margin-block-end: var(--space-3xs); }

/* --- /practice-policy ----------------------------------------------------*/
/* MEASURED: 80px top / 120px bottom, a 70px gap under the head, and three
 * stacked radial gradients over the mist ground. */
.tips { padding-block: var(--space-2xl) var(--space-3xl);   /* live 80/120 at 1440 */ background-color: var(--surface);
    background-image:
        radial-gradient(900px 700px at 22% 22%, color-mix(in srgb, var(--tc-mid) 20%, transparent), transparent 50%),
        radial-gradient(1100px 850px at 45% 55%, color-mix(in srgb, var(--tc-vivid) 22%, transparent), transparent 50%),
        radial-gradient(1300px 950px at 28% 78%, color-mix(in srgb, var(--tc-sky) 14%, transparent), transparent 70%); }
/* live: title (810px) and lede (540px, from x=855) side by side over a 1px
 * accent rule, 64px under the title. */
.tips__head {
    display: grid; grid-template-columns: minmax(0, 810fr) minmax(0, 540fr); align-items: start;
    padding-block-end: var(--space-inset-m);   /* live 50 at 1440 */
    border-bottom: var(--border-width-s) solid var(--secondary-line);
}
.tips__lede { margin: var(--space-m) 0 0; font-size: var(--size-1); }  /* live sits 28px below the title's top */
.tips__grid {
    /* live 100px between the 383px tracks; the row gap is its own token because
     * --space-inset-head falls to 0 at phone width, where rows still need air */
    display: grid; gap: var(--space-2xl) var(--space-inset-head); margin-block-start: var(--space-block);   /* live 70 */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: start;
}
.policy__title { font-size: var(--size-1); line-height: var(--leading-body); color: var(--brand-on-soft); margin-block-end: var(--space-xs); }   /* live 20.6px, 14px above the copy */
.policy p { font-size: var(--size-1); }
.tips__photo {
    width: 100%; aspect-ratio: 383 / 232; border-radius: var(--radius-m);
    background-size: cover; background-position: 50% 50%; background-repeat: no-repeat;
}
@media (max-width: 64rem) {
    .tips__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .tips__head { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 47.9375rem) {
    .tips  { padding-block: var(--space-block) var(--space-3xl); }    /* live 60/120 at 390; the band rhythm scales now */
    .rights { padding-block: var(--space-block); }  /* live 60/60 at 390 */
}
@media (max-width: 39.9375rem) { .tips__grid { grid-template-columns: minmax(0, 1fr); } }
/* MEASURED at 1440: 425px arch photo | 850px holding TWO 400px text columns,
 * inside the 1350px shell. The photo's radius is 350/350/15/15 -- the same
 * arch mechanism as the hero crops, at a third size. */
.rights__cols {
    display: grid; gap: calc(var(--space-xl) + var(--space-xs));      /* live 75px: photo ends 470, text starts 545 */
    grid-template-columns: minmax(0, 425fr) minmax(0, 850fr);
    align-items: center;                                   /* live centres the text block on the photo */
}
.rights__photo {
    width: 100%; height: 43.1875rem; object-fit: cover;    /* live 691px */
    border-radius: 350px 350px 15px 15px;
}
.rights__text {
    display: grid; gap: var(--space-inset-m);                /* live 50px between the columns, ~60 under the title */
    grid-template-columns: repeat(2, minmax(0, 1fr));   /* live 400 + 400 */
    align-content: start;
}
.rights__head { grid-column: 1 / -1; margin-block-end: 0; }

@media (max-width: 64rem) {
    .rights__cols { grid-template-columns: minmax(0, 1fr); }
    .rights__text { grid-template-columns: minmax(0, 1fr); }
    .rights__head { grid-column: 1; }
    .rights__photo { height: auto; aspect-ratio: 425 / 691; }
}
.rights__title { font-size: var(--size-1); line-height: var(--leading-body); color: var(--brand-on-soft); margin-block-end: var(--space-s); }
.rights__col p { font-size: var(--size-0); }              /* live sets this copy at body size */
.rights__col p + p { margin-block-start: var(--space-s); }

/* --- /contact ------------------------------------------------------------*/
/* RE-BUILT 2026-09-18 from live at 1440. See the comment in contact.html. */
.contact-page {
    background:
        radial-gradient(1100px 800px at 85% 40%, color-mix(in srgb, var(--tc-vivid) 30%, transparent), transparent 48%),
        radial-gradient(1200px 900px at 70% 55%, color-mix(in srgb, var(--tc-mid) 22%, transparent), transparent 72%),
        radial-gradient(1300px 950px at 25% 50%, color-mix(in srgb, var(--tc-sky) 12%, transparent), transparent 78%),
        var(--surface);
    padding-block: var(--hero-pad-top) var(--space-3xl);      /* live 250 / 120: it runs under the header like the hero */
}
.contact-page__cols {
    display: grid; align-items: start;
    grid-template-columns: minmax(0, 592fr) minmax(0, 90fr) minmax(0, 668fr);   /* the 90fr track IS live's gutter */
}
.contact-page__cols > .contact-form-wrap { grid-column: 3; }
.contact-page__copy { display: flex; flex-direction: column; align-items: flex-start; }
.contact-page__copy .section-title { margin-top: var(--space-m); }
.contact-page__lede { max-width: 32.625rem; margin-block-start: var(--space-s); }   /* live 522px */
.contact-page__lede p { margin: 0; font-size: var(--size-0); line-height: var(--leading-body); }
.contact-page__lede p + p { margin-top: var(--space-xs); }

/* sky panel > white sheet (live's hard 0 15px 0 -6px shadow) > two gradient cards */
.contact-cluster {
    width: 100%; margin-block-start: var(--space-inset-m);
    padding: var(--space-xs) var(--space-card-pad) var(--space-card-pad);      /* live 17 / 25 / 25 */
    background: var(--tc-sky); border-radius: var(--radius-l);
}
.contact-cluster__sheet {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-s);
    padding: var(--space-s);
    background: var(--surface-raised); border-radius: var(--radius-l);
    box-shadow: 0 15px 0 -6px color-mix(in srgb, black 19%, transparent);
}
.contact-mini {
    min-height: 11rem;                                            /* live 176px */
    padding: var(--space-s) var(--space-xs);
    display: flex; flex-direction: column; justify-content: center; gap: var(--space-3xs);
    border-radius: 10px;
    background-image: linear-gradient(var(--surface-raised) 0%, var(--tc-sky) 100%);
}
.contact-mini .contact-card__icon { margin-bottom: var(--space-xs); }
.contact-mini h2 { margin: 0; font-size: var(--size-1); font-weight: var(--weight-heading); line-height: var(--leading-body); color: var(--brand-on-soft); }
.contact-mini p { margin: 0; font-size: var(--size-1); line-height: var(--leading-body); }
.contact-mini a { font-size: var(--size-0); }

/* the form card: white, 20px radius, 40px padding, live's soft blue drop */
.contact-form-wrap {
    --field-bg: color-mix(in srgb, var(--tc-sky) 38%, transparent);   /* the fields' wells on the white card */
    padding: var(--space-l);
    background: var(--surface-raised); border-radius: var(--radius-l);
    box-shadow: 7px 21px 34px 0 color-mix(in srgb, var(--tc-mid) 33%, transparent);
}
.contact-form { display: grid; gap: var(--space-2xs); }
.field { display: grid; gap: var(--space-3xs); }
/* colour stated: the base `label` rule uses --ink-strong, whose hue is rotated
 * +80deg off the brand and lands on a plum rgb(23,13,26) -- it read as pink on
 * the white card. Live's labels are body ink, rgb(54,59,64). */
.field label { font-size: var(--size-0); font-weight: var(--weight-body); line-height: var(--leading-body); color: var(--text); }
/* Send is the site's standard .btn pill (owner, 2026-10-05; live's was a
 * full-width 3px-radius bar). Only its place in the form is stated here. */
.contact-form__send { justify-self: start; margin-top: var(--space-3xs); border: 0; cursor: pointer; }
.contact-note {
    margin-block-start: var(--space-s); padding: var(--space-xs);
    background: var(--tc-sky); border-left: 5px solid var(--tc-mid);
}
.contact-note p { margin: 0; font-size: var(--size--1); line-height: var(--leading-body); }
.contact-note .contact-note__title { font-family: var(--font-heading); font-size: var(--size-0); font-weight: var(--weight-heavy); color: var(--text); }

@media (max-width: 64rem) {
    .contact-page { padding-block: var(--hero-pad-top) var(--space-2xl); }   /* --hero-pad-top is already 180px here */
    .contact-page__cols { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-inset-m); }
    .contact-page__cols > .contact-form-wrap { grid-column: auto; }
}
@media (max-width: 29.9375rem) {
    .contact-cluster__sheet { grid-template-columns: minmax(0, 1fr); }
    .contact-form-wrap { padding: var(--space-s-l); }
}

/* --- Closing CTA ---------------------------------------------------------
 * MEASURED: 80px block padding (not the 120px band rhythm), and two equal
 * columns -- 675px copy, 675px cards, inside the 1350px shell. */
.closing { padding-block: var(--space-l); }

/* --- Narrow widths -------------------------------------------------------
 * MEASURED: live drops the hero card row's hours card below 1024 on
 * /services, exactly as it does on the homepage. */
@media (max-width: 64rem) {
    .hero__media-plain { justify-content: center; }
}
@media (max-width: 47.9375rem) {
    .hero__sep--wide { display: none; }
}

/* The template sets `overflow-wrap: break-word` globally, which splits a long
 * word mid-glyph rather than pushing it to the next line. Live never does
 * this -- its headings wrap on word boundaries at every width. At 390 that
 * rendered "Comprehens / ive". Restore normal wrapping on display type; the
 * rest of the page keeps the template default. */
.display, .section-title, h1, h2, h3 { overflow-wrap: normal; }

/* --- /health-info: curated resources + advice ---------------------------
 * Six national resources plus the practice's own after-hours service: static
 * health information in place of the Your Health hub, which only subscribers
 * get (Terrace is not one). Cards are link-led: the heading IS the link, so the whole card needs
 * no redundant "read more" and screen readers get one meaningful target. */
.resources__grid {
    display: grid; gap: var(--space-m); margin-block-start: var(--space-l);
    /* Track count is stated explicitly below, not left to auto-fit: six cards
     * must read as 3x2, and auto-fit gave 4+2 at some widths. */
}
.resource-card {
    background: var(--surface-raised); border-radius: var(--radius-l); padding: var(--space-m);
}
.resource-card h3 { font-size: var(--size-1); margin-block-end: var(--space-2xs); }
.resource-card h3 a { color: var(--brand-on-soft); text-decoration: underline;
    text-underline-offset: 0.15em; }
.resource-card h3 a:hover { color: var(--tc-mid); }

.advice__inner {
    display: grid; gap: var(--space-l); align-items: start;
    grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
}
.advice__actions { display: flex; gap: var(--space-xs); flex-wrap: wrap; }
.emergency-panel {
    background: var(--tertiary-solid); color: var(--tertiary-on-solid);
    border-radius: var(--radius-l); padding: var(--space-m);
}
.emergency-panel h3 { color: var(--tertiary-on-solid); font-size: var(--size-1); margin-block-end: var(--space-2xs); }
.emergency-panel p + p { margin-block-start: var(--space-2xs); }
.emergency-panel a { color: var(--tertiary-on-solid); text-decoration: underline; }

/* The resources and advice bands share one ground, so stacked they met with
 * 120 + 120px of nothing between them; the advice band gives its half back. */
.resources + .advice { padding-block-start: 0; }
.resource-card p:last-child { margin-block-end: 0; }
.emergency-panel__block:last-child p:last-child { margin-block-end: 0; }
.advice__copy .section-title + p { margin-block-start: var(--space-s); }
.advice__copy .advice__actions { margin-block-start: var(--space-m); }

/* --- Corrections after owner review (2026-09-10) -------------------------
 * The hero lede rendered rgb(79,86,91) against live's rgb(54,59,64) -- the
 * template's muted ink rather than live's body colour. It passed AA at
 * 6.84:1, which is exactly why the contrast gate did not catch it: the gate
 * asks "is this legible", not "is this live's colour". */
.hero__lede .lede,
.hero__lede p { color: var(--text); }

/* The team card's backdrop is a linear gradient on live, not a flat white
 * panel. Measured: linear-gradient(154deg, rgb(242,244,246) 32%,
 * rgba(151,202,219,0.72) 100%) on a 681x466 box with a 20px radius. */
.team-card {
    background: linear-gradient(154deg, var(--surface) 32%, color-mix(in srgb, var(--tc-mid) 72%, transparent) 100%);
    border-radius: 20px;
}

/* The trusted band carries the same three-stop radial wash as the tips band
 * on /practice-policy -- measured on live, and previously left flat. */
.trusted {
    background-color: var(--surface);
    background-image:
        radial-gradient(900px 700px at 22% 22%, color-mix(in srgb, var(--tc-mid) 20%, transparent), transparent 50%),
        radial-gradient(1100px 850px at 45% 55%, color-mix(in srgb, var(--tc-vivid) 22%, transparent), transparent 50%),
        radial-gradient(1300px 950px at 28% 78%, color-mix(in srgb, var(--tc-sky) 14%, transparent), transparent 70%);
}

/* Two colour bugs found by diffing every text colour against live (2026-09-10).
 * The other differences on those pages are the DOCUMENTED a11y divergence --
 * live's accent rgb(2,138,190) fails AA on pale grounds, so --brand-bright is
 * deliberately rgb(2,107,159). These two were not that:
 *
 *  - .svc-tile h3 set no colour at all and inherited rgb(23,13,26), a near
 *    black that is in no palette here. Live uses its mid navy.
 *  - The closing band's title rendered deep navy where live uses the accent. */
.svc-tile h3 { color: var(--brand-on-soft); }
.closing .section-title { color: var(--secondary-on-soft); }

/* Six curated resources, held at 3x2 so the rows balance -- auto-fit reflowed
 * them to 4+2 and 2+2+2 at intermediate widths, which reads as a mistake. */
.resources__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 64rem) { .resources__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 39.9375rem) { .resources__grid { grid-template-columns: minmax(0, 1fr); } }

/* The panel now carries two headed blocks: emergency, and after hours. They
 * are different escalation paths and were reading as one paragraph. */
.emergency-panel__block + .emergency-panel__block {
    margin-block-start: var(--space-s);
    padding-block-start: var(--space-s);
    border-top: var(--border-width-s) solid color-mix(in srgb, var(--tertiary-on-solid) 22%, transparent);
}
.emergency-panel__block h3 { margin-block-end: var(--space-3xs); }

/* Three more colour mismatches from the full text-colour diff (2026-09-10).
 * All three were MY choice of token, not live's colour:
 *  - the accred strip's title is live's accent, not deep navy (it sits on the
 *    sky band, where the accent still clears AA);
 *  - the team-card tag pills carry body ink on live, not brand colour;
 *  - "Patient Rights & Privacy" is the mid navy, not the display navy. */
.accred__title { color: var(--tc-vivid); }
.rights__head { color: var(--brand-on-soft); }

/* ==========================================================================
 * PHONE ALIGNMENT — measured off live at 390 (2026-09-18).
 * Live's mobile layout CENTRES nearly every band's copy, and drops the section
 * titles from 3.5rem to 3rem (39.65px at 390). Ours had carried the desktop's
 * left alignment and the 46px title all the way down, so titles ran to three
 * lines where live's take two. At the end of the file so it wins on order.
 * The title SIZES need no rule here any more: the phone ratio (1.145) puts
 * step-7 at 41.3px and step-8 at 47.3 on a 390 screen.
 * ======================================================================== */
@media (max-width: 47.9375rem) {

    .about__head { align-items: center; text-align: center; }
    .about__body { margin-left: 0; text-align: center; }
    .about .btn { display: flex; width: fit-content; margin-inline: auto; }
    .panel--grid .panel__item { text-align: center; }

    .doctors .eyebrow { display: block; width: fit-content; margin-inline: auto; }
    .doctors .section-title, .doctors__lede { text-align: center; margin-left: 0; }
    .doctors .hero__cta { margin-left: 0; display: flex; justify-content: center; }

    .why__head-copy, .why__head-side { align-items: center; text-align: center; }
    .why__item { align-items: center; text-align: center; }

    .contact__copy { align-items: center; text-align: center; }
    .contact-card { align-items: center; text-align: center; }

    .contact-page__copy { align-items: center; text-align: center; }
    .contact-mini { align-items: center; text-align: center; }

    /* the privacy / telephone card is compact on a phone: tag, ~50px, copy --
     * the desktop's 316px floor left a hole in the middle of it */
    .panel__card, .about__panels--tall .panel__card { min-height: 0; }
    .panel__card .tag { margin-bottom: var(--space-inset-m); }
    .panel__ticks { margin-inline: auto; }
    .panel__brand { justify-content: center; }   /* logo + name centred over the centred ticks and copy */

    /* live's services card runs gutter to gutter at 390 (20px), not 40px in */
    .services .u-container { padding-inline: var(--space-gutter); }
}

/* tablet: the /about panels drop their desktop floors, as live's do */
@media (max-width: 1080px) {
    .about__panels--tall, .about__panels--tall .panel__card { min-height: 0; }
    .about__panels--tall .panel__card .tag { margin-bottom: var(--space-inset-m); }
}

/* live's tablet layout (768-1024): the two hero photo cards go squat, 231x116,
 * so the fixed 100px radius rounds the whole top. A comment in the 1080 block
 * pointed at "the 1024 block below" for this, but the rule was never written.
 * Bounded below so it cannot reach the phone layout's 209px cards. */
@media (min-width: 768px) and (max-width: 1024px) {
    .hero__card-photo { height: 7.25rem; }     /* live 116px */
}

/* Live's tablet layout takes effect AT 1024 (Elementor's breakpoint is <=1024),
 * and 1024 is an iPad in landscape. The inner pages' collapses were written as
 * max-width: 63.9375rem and so still showed the desktop layout at exactly 1024;
 * they are now max-width: 64rem throughout. */

/* /about on a phone: the team panel is sized by its content -- the homepage's
 * 477px floor left ~100px of empty gradient under the confidentiality line. */
@media (max-width: 767px) {
    .about__panels--tall .panel--grid { min-height: 0; gap: var(--space-l); }
}

/* ==========================================================================
 * LEGAL PAGES (/privacy-policy, /terms-and-conditions) -- shell measured off
 * live 2026-09-18. Live sizes the photo in VIEWPORT HEIGHT (its section is
 * 100vh, the card starts at 70vh: 1000/701 in a 1000px-tall window, 1128/790
 * in the owner's), so the overlap is stated as 30% of the photo's height and
 * holds at any window size. Clamped so a very short or very tall window cannot
 * crush the photo or push the policy a screen and a half down.
 * ======================================================================== */
.legal { --legal-photo-h: clamp(30rem, 100svh, 70rem); }
.legal__photo {
    display: block; width: 100%; height: var(--legal-photo-h);
    /* --legal-focus is set per page on the <img>: both photos are landscape, so
     * a tall phone crop would otherwise show the blank wall between the people */
    object-fit: cover; object-position: var(--legal-focus, 50%) 0;
}
@media (max-width: 767px) {
    .legal { --legal-photo-h: clamp(24rem, 75svh, 36rem); }
}
.legal__band {
    padding: 0 var(--space-gutter) var(--space-3xl);       /* live 120px under the card */
}
.legal__card {
    position: relative;
    max-width: 80.625rem; margin-inline: auto;                  /* live 1290px */
    margin-top: calc(var(--legal-photo-h) * -0.3);
    padding: max(var(--space-m), var(--space-inset-head));      /* live 100px; never less than 20-30 on a phone */
    background: var(--surface); border-radius: 10px;
}
/* THE BAND MUST START AT THE PHOTO'S FOOT, NOT AT THE CARD'S TOP. The card's
 * negative margin-top is the first thing inside the band, so without a new
 * formatting context it COLLAPSES THROUGH the band: the whole gradient rode up
 * 30% with the card and sliced the photo off flat at the card's top edge -- no
 * straddle at all. flow-root stops the collapse, so only the card moves.
 * (First shipped broken: the check printed the card's position, which was
 * right, and never the band's, which was not.) */
.legal__band { position: relative; display: flow-root; }
.legal__card h1 {
    margin: 0 0 var(--space-m);
    font-family: var(--font-body); font-size: var(--size-6); font-weight: var(--weight-strong);
    line-height: var(--leading-display); color: var(--brand-on-soft);
}
.legal__card h2 {
    margin: var(--space-m) 0 var(--space-xs);
    font-family: var(--font-heading); font-size: var(--size-5); font-weight: var(--weight-heading);
    line-height: var(--leading-display); color: var(--text);
}
.legal__card h3 {
    margin: var(--space-s) 0 var(--space-xs);
    font-family: var(--font-heading); font-size: var(--size-2); font-weight: var(--weight-heading);
    line-height: var(--leading-snug); color: var(--text);
}
.legal__card p, .legal__card li { font-size: var(--size-0); line-height: var(--leading-body); color: var(--text); }
.legal__card p { margin: 0 0 var(--space-xs); }
.legal__card .lede { font-size: var(--size-1); }
.legal__card ul, .legal__card ol { margin: 0 0 var(--space-xs); padding-left: var(--space-l); }
.legal__card li + li { margin-top: var(--space-3xs); }
.legal__card a { color: var(--secondary-on-soft); text-decoration: underline; text-underline-offset: 0.15em; }
.legal__card > :last-child { margin-bottom: 0; }

/* A line break that only exists on phones. OWNER'S CALL (2026-09-18): the band
 * title reads "Get in Touch / with Terrace Clinic" at phone width, rather than
 * breaking wherever the column happens to run out ("...with Terrace / Clinic"). */
.br-mobile { display: none; }
@media (max-width: 767px) { .br-mobile { display: inline; } }

/* ==========================================================================
 * MOBILE MENU PANEL. This had NO rules at all -- it rendered as a bare list of
 * blue underlined links in the page flow, pushing the hero down, with no close
 * icon. Built from live's (measured at 390): a full-width deep-navy panel hung
 * from the header's foot, OVER the page; centred white links in 51px rows
 * (14px 20px padding), weight 600; the menu button swaps to an X.
 * One departure: live leaves its inactive links dark grey on the navy, which
 * is close to unreadable. Every link here is white; the current page is marked
 * in the light brand blue with a bar, so the state is not colour alone.
 * No `display` on .mobile-nav itself -- that would defeat the [hidden] attribute
 * the script toggles.
 * ======================================================================== */
.mobile-nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: var(--layer-nav);
    background: var(--brand-solid);
    box-shadow: 0 18px 30px -12px color-mix(in srgb, var(--tertiary-solid) 35%, transparent);
}
.mobile-nav ul { list-style: none; margin: 0; padding: var(--space-2xs) 0; }
.mobile-nav a {
    display: block;
    padding: var(--space-xs) var(--space-s);           /* live 14px 20px -> a 51px row */
    font-family: var(--font-heading);
    font-size: var(--size-1);
    font-weight: var(--weight-heading);
    line-height: var(--leading-body);
    text-align: center;
    text-decoration: none;
    color: var(--brand-on-solid);
}
.mobile-nav li + li { border-top: var(--border-width-s) solid color-mix(in srgb, var(--brand-on-solid) 12%, transparent); }
.mobile-nav a:hover, .mobile-nav a:focus-visible { background: var(--tertiary-solid); }
.mobile-nav a:focus-visible { outline-offset: -4px; }   /* inside the row: the menu clips an outset ring */
.mobile-nav a.active, .mobile-nav a[aria-current="page"] {
    color: var(--tc-mid);
    box-shadow: inset 4px 0 0 var(--tc-mid);
}
/* the button shows bars when closed, an X when open */
.nav-toggle__close { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle__open { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle__close { display: block; }
/* never in the desktop header, whatever state the script left it in */
@media (min-width: 75rem) { .mobile-nav { display: none; } }   /* 1200: the nav collapse, and partials/scripts.html */
/* a short drop-in; transform + opacity only, and not under reduced motion */
@media (prefers-reduced-motion: no-preference) {
    .mobile-nav:not([hidden]) { animation: mobile-nav-in 0.22s var(--ease-out) both; transform-origin: top; }
}
@keyframes mobile-nav-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }

/* ==========================================================================
 * SEAMLESS BANDS -- OWNER'S CALL (2026-09-18): "no hard cuts on the gradient
 * backgrounds". Each tinted band carries its own stack of radial washes (live's,
 * verbatim), and a wash that is still a few levels off the ground where the band
 * ends meets the next band's different wash as a faint straight line. Measured
 * before this block: 5-11 levels either side of /about's doctors band, 16 into
 * and 14 out of /practice-policy's WHITE rights band, 31 where the legal pages'
 * gradient met the footer, and a raw photo edge above it.
 *
 * Fix, once, for every band: a ::before that fades the band's top and bottom
 * edge to exactly --ground, so any two neighbours meet on the same colour. The
 * fade is one band-padding tall (120px), so it lives entirely in the padding
 * and never sits behind copy. z-index -1 inside an isolated band = above the
 * band's own washes, below its content.
 * The sky accreditation strip and the footer's accent rule are deliberate solid
 * edges (live's) and are left alone.
 * ======================================================================== */
.hero, .about, .why, .services, .tips, .contact-page { position: relative; isolation: isolate; }
.hero::before, .about::before, .why::before, .services::before, .tips::before, .contact-page::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: var(--layer-behind);
    pointer-events: none;
    background:
        linear-gradient(to bottom, var(--surface) 0, transparent var(--space-3xl)),
        linear-gradient(to top, var(--surface) 0, transparent var(--space-3xl));
}
/* heroes and the contact band run UNDER the transparent header: their top wash
 * is the glow behind the nav, so only the foot is faded */
.hero::before, .contact-page::before {
    background: linear-gradient(to top, var(--surface) 0, transparent var(--hero-pad-bottom, var(--space-3xl)));
}
/* the short heroes end on a photo that sits flush on the accreditation strip --
 * nothing to fade, and a fade there would wash out the arch's foot */
.hero--short::before { content: none; }

/* flat bands that sat a few levels off the ground now share it exactly:
 * /about's doctors band was rgb(245,245,245) and /practice-policy's rights
 * band was white -- a 16-level step in and a 14-level step out */
.doctors, .rights { background: var(--surface); }

/* legal pages: the photo's foot melts into the band's first colour instead of
 * ending on a raw edge, and the band's gradient lands on the ground so it runs
 * into the footer without a step */
.legal { position: relative; }
.legal::before {
    content: "";
    position: absolute;
    left: 0; right: 0;
    top: calc(var(--legal-photo-h) * 0.62);
    height: calc(var(--legal-photo-h) * 0.38);
    pointer-events: none;
    background: linear-gradient(to bottom, transparent, var(--tc-mid));
}
.legal__band { background-image: linear-gradient(var(--tc-mid) 0%, var(--tc-sky) 55%, var(--surface) 100%); }

/* ==========================================================================
 * PHONE SPACING PASS -- measured against live at 390 (2026-09-18).
 *   accreditation strip: live runs title -> 22 -> copy -> 36 -> logo inside 40px
 *     of padding; ours was 8 / 19 / 32 -- visibly cramped beside the airy hero.
 *   about band: live is title -> ~22 -> body -> 34 -> CTA; ours 42 / 21 (the
 *     desktop's 50px body offset carried down, and a tight CTA).
 *   tint panel: its 312px floor left ~60px of empty panel under the now-compact
 *     privacy card; it hugs the card instead.
 * ======================================================================== */
@media (max-width: 767px) {
    .accred { padding-block: var(--space-inset-m); }
    .accred .accred__inner { gap: var(--space-l); }
    .accred h2, .accred .accred__title { margin-bottom: var(--space-s); }

    .about__body { margin-top: var(--space-s-l); }
    .about .btn { margin-top: var(--space-l); }

    .panel--tint, .about__panels .panel--tint { min-height: 0; }

    .hero__badge { gap: var(--space-3xs); }

    /* live keeps 3.5rem (46.3px) on the why title and the contact hero at 390;
     * the other section titles drop to 3rem, which plain step-7 already is. */
    .why .section-title, .contact-page .section-title { font-size: var(--size-8); }
    /* live's doctor cards stay ~168px tall on phones; --space-xl is 48 here (a halved step once made ours 133) */
    .doctor { padding-block: var(--space-xl); }

    /* /practice-policy on phones: live drops the tips photo, closes the items
     * up (147px pitch; ours ran 170) and puts the arch AFTER the rights copy.
     * Visual order only -- the photo is decorative to the reading order. */
    /* Get in Touch band: live runs tag -> 30 -> title -> 30 -> button -> 50 ->
     * card -> 50 -> card. Ours had 17 / 17 / 80 / 40: the copy block's bottom
     * padding AND the row gap were both being spent under the button. */
    .contact .contact__inner { row-gap: var(--space-xl); }
    .contact .contact__copy { padding-bottom: 0; gap: var(--space-l); }

    /* Dot-grid panel: live's 477px floor left ~67px of empty panel above and
     * below the centred block on phones (owner: too much space). It hugs its
     * content now, on the same 30px the cards beside it use. */
    .about__panels .panel--grid, .panel--grid { min-height: 0; padding-block: var(--space-l); }

    /* Stacked service tiles: live leaves ~60px from one tile's copy to the next
     * photo; the desktop column gutter (20px here) read as one run-on list. */
    .services .services__grid { row-gap: var(--space-xl); }

    .tips__photo { display: none; }
    /* with the photo gone, five tips in two columns (640-767) left the fifth
     * beside an empty cell: an odd last tip takes the whole row */
    .tips__grid > .policy:nth-child(odd):nth-last-child(2) { grid-column: 1 / -1; }
    .tips__grid { row-gap: var(--space-l); }
    .rights__media { order: 2; }
}

/* ===========================================================================
 * 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 search window at every width, the overlay mediflare.js builds: from
 * 768 up a centred card over a dimmed page, below 768 full screen. Two
 * buttons open it, one per width, swapping where the nav collapses
 * (1199/1200), so no width shows both and none shows neither:
 *   1200 and up    .site-search__trigger: the magnifier in the site's search
 *                  field (the --field-* tokens: white, the brand-mid edge,
 *                  the pill), 44px, beside the Call pill. Never wider: the
 *                  nav already needs the bar's whole middle (the links were
 *                  eased to fit at 1200), and measured 1200-1920 the bar has
 *                  at most ~30px beyond the last link's 32px clearance, so
 *                  there is no room for a word at any desktop width.
 *   1199 and down  .site-search__open: the magnifier beside the menu
 *                  button, on the menu button's navy square. On phones that
 *                  is the second row, with the pair; at 371 and below the
 *                  Call pill reads "Call" so the three still fit there.
 *
 * Shape: pills, like every button here (.btn, the Call pill), except the
 * phone and tablet trigger, which is the menu button's square. Search and
 * Close ARE the site's .btn: the .btn rules above list them. Focus is the
 * site's one ring (see the site :root under Form controls).
 *
 * The overlay and the popup are styled ONLY through :not([hidden]): a
 * display of their own would override [hidden] and they would never close.
 * ======================================================================== */
:root {
    --target-min: 2.75rem;   /* 44px, the touch-target floor; the menu button's own size */
    --shadow-card-soft: 7px 21px 34px 0 color-mix(in srgb, var(--tc-mid) 33%, transparent);   /* the contact form card's drop, and the search card's */
}

/* The desktop trigger, drawn as the field it opens: fill, edge, corner and
 * height are the --field-* tokens, with the glyph in the deep navy like a
 * nav label; the bright blue the nav hovers in, on a sky ground, when
 * hovered or open. The tablet and phone trigger is the menu button's twin
 * instead (see below). */
.site-search__trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    inline-size: var(--target-min);
    block-size: var(--target-min);
    padding: 0;
    color: var(--brand-on-soft);
    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);
}
/* Beside the menu button it matches it (owner, 2026-10-06): the same 44px
 * deep-navy square, 4px radius, white glyph, and like it no hover change. */
.site-search__open {
    display: none;
    flex: none;
    align-items: center;
    justify-content: center;
    inline-size: var(--target-min);
    block-size: var(--target-min);
    padding: 0;
    color: var(--brand-on-solid);
    background: var(--brand-solid);
    border: 0;
    border-radius: var(--radius-xs);
    cursor: pointer;
}
.site-search__trigger svg,
.site-search__open svg { width: 1.375rem; height: 1.375rem; fill: currentColor; }
.site-search__trigger:hover,
.site-search__trigger[aria-expanded="true"] { color: var(--secondary-on-soft); background: var(--tc-sky); }

/* Which button shows where. */
@media (max-width: 74.9375rem) {
    .site-search__trigger { display: none; }
    /* Beside the menu button, in its slot: the button gives up its auto
     * margin (it took the bar's free space) to the magnifier before it. */
    .site-search__open { display: inline-flex; order: 2; margin-inline: auto 0; }
    .nav-toggle { margin-inline: 0; }
}
@media (max-width: 767px) {
    .site-search__open { margin-inline: 0; }
}
/* 371 and below the magnifier, the menu button and the full Call pill no
 * longer fit one row, so the pill reads "Call" and keeps the number in its
 * aria-label; the three stay together under the logo (owner, 2026-10-06). */
@media (max-width: 23.1875rem) {
    .btn--head__number { display: none; }
}

/* Making room on the desktop bar. The magnifier is 44 plus the header's gap,
 * and at 1200 the bar had 27px to spare. Both the logo and the Call pill
 * ease on the site's existing --space-taper (0 at 1440 and up, so the wide
 * desktop is untouched): the logo to 227 at 1200, which is live's own logo
 * there (226), and the pill's inline padding by 18 each side. Measured from
 * 1200 to 1440 in 4px steps: the last link stays at least 32px clear of the
 * magnifier, and the pill stays flush with the container. */
@media (min-width: 75rem) {
    .site-logo img { width: calc(16.25rem - 4.5 * var(--space-taper)); }
    .btn--head { padding-inline: calc(var(--space-l) + var(--space-3xs) - 2.5 * var(--space-taper)); }
}
/* 768 to 775: the tablet bar is 4px short with the magnifier in it; the
 * logo gives up exactly what is needed, and nothing elsewhere. */
@media (min-width: 768px) and (max-width: 74.9375rem) {
    .site-logo { flex-shrink: 1; min-width: 0; }
    .site-logo img { max-width: 100%; }
}

/* 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, hairline and focus of every text field, the
 * search boxes and the contact form alike, are the --field-* tokens (Form
 * controls). */

/* Search and Close are the site's .btn (listed in its rules above); here only
 * the 44px floor. */
.mf-search__submit,
.mf-search-overlay__close {
    min-block-size: var(--target-min);
    white-space: nowrap;
    cursor: pointer;
}

.mf-search__status {
    margin: 0;
    padding-inline: var(--space-xs);
    font-size: var(--size--1);
    line-height: var(--leading-body);
    color: var(--text);
}
.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; }
.mf-search__link {
    display: block;
    padding: var(--space-2xs) var(--space-xs);
    border-radius: var(--radius-m);
    color: var(--text);
    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); 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-m);
}
/* Titles are the site's card titles: Lato 700 in the deep navy, turning the
 * bright blue the nav and links hover in. */
.mf-search__title {
    display: block;
    font-family: var(--font-heading);
    font-size: var(--size-0);
    font-weight: var(--weight-heading);
    line-height: var(--leading-snug);
    color: var(--brand-on-soft);
    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(--secondary-on-soft); }
.mf-search__excerpt {
    display: block;
    margin-top: var(--space-3xs);
    font-size: var(--size--1);
    line-height: var(--leading-body);
    color: var(--text);
}
.mf-search__excerpt mark {
    color: var(--text);
    background: color-mix(in oklch, var(--tc-mid) 60%, transparent);
    border-radius: var(--radius-xs);
}

/* Phones: full screen, on the page's ground. Close sits alone on the
 * top row, at the right 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: auto minmax(0, 1fr) auto;   /* Close · box · Search on one row */
    grid-template-rows: auto auto minmax(0, 1fr);
    gap: var(--space-xs) var(--space-2xs);
    padding-block-start: max(var(--space-s), env(safe-area-inset-top));
    padding-inline: max(var(--space-gutter), env(safe-area-inset-left)) max(var(--space-gutter), env(safe-area-inset-right));
    background: var(--surface);
}
.mf-search-overlay__header { display: contents; }
/* Close is an icon, not the site's pill: a 44px × in the navy, left of the
 * box, as on the other sites' search windows (owner, 2026-10-06). */
.mf-search-overlay__close {
    grid-column: 1;
    grid-row: 1;
    z-index: var(--layer-base);   /* above the box, which spans this row too */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--target-min);
    block-size: var(--target-min);
    padding: 0;
    font-size: 0;
    color: var(--brand-on-soft);
    background: transparent;
    border: 0;
    border-radius: var(--radius-pill);
    transition: background var(--duration-fast) var(--ease-out);
}
.mf-search-overlay__close::before {
    content: "";
    inline-size: 1.5rem;
    block-size: 1.5rem;
    background: currentColor;
    -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='2'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M6 18 18 6M6 6l12 12'/%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='2'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M6 18 18 6M6 6l12 12'/%3E%3C/svg%3E") center / contain no-repeat;
}
.mf-search-overlay__close:hover { background: color-mix(in oklch, var(--tc-mid) 45%, transparent); }
.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: center;   /* the field is --field-h; Search is the .btn, up to 1.3px taller mid-range, so they centre on one line */
}
.mf-search--overlay .mf-search__input { grid-column: 2; grid-row: 1; }
.mf-search--overlay .mf-search__submit { grid-column: 3; grid-row: 1; block-size: var(--field-h); padding-block: 0; }   /* level with the box beside it */
.mf-search--overlay .mf-search__status { grid-column: 1 / -1; grid-row: 2; }
.mf-search--overlay .mf-search__results {
    grid-column: 1 / -1;
    grid-row: 3;
    align-self: stretch;
    min-block-size: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-block-end: max(var(--space-s), env(safe-area-inset-bottom));
}
.mf-search--overlay .mf-search__link:hover,
.mf-search--overlay .mf-search__link:focus-visible { background: var(--surface-raised); }

/* From 768 up the same overlay is a centred card (the DocSearch pattern),
 * rounded like the contact form's card and on its soft blue drop, 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; 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: 768px) {
    .mf-search-overlay:not([hidden]) {
        inset: var(--space-3xl) 0 auto;
        z-index: calc(var(--layer-modal) + 1);
        inline-size: calc(100% - 2 * var(--space-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-l);
        box-shadow: var(--shadow-card-soft);
    }
    .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));
    }
}

