/* ===== tokens.css ===== */
/* =============================================================================
   TOKENS — the only place a raw value is allowed to exist.
   =============================================================================

   Rules enforced by review:
     1. No hex colour, px size, or duration literal appears anywhere else in
        this codebase. Everything references a token.
     2. Tokens are named for PURPOSE, never appearance. `--accent-cta`, not
        `--orange-600`. Palettes change; purpose does not.
     3. Semantic colours (success / warning / danger / info) mean the same thing
        on every screen. They are never re-themed to fit one page.

   ---------------------------------------------------------------------------
   THE PALETTE IS THE LOGO'S, SAMPLED FROM THE ARTWORK — not invented.
   Median hues taken off the supplied logo and business card:

     #e31600  fire red      20.6k px    #fd7701  flame orange  29.9k px
     #014ab3  brand azure   87.4k px    #fdca1d  trust gold    (card only)

   Azure is the dominant brand colour by a factor of four, so AZURE IS THE
   PRIMARY CTA, not the orange. That also resolves a clash that would have bitten
   us later: a red primary button is indistinguishable from a danger state. Here
   red earns a job where urgency IS the meaning, and nowhere else.

     --accent-cta  #014ab3  the one primary action per view. White ink 7.98:1.
     --urgent      #e31600  the emergency call-now control, and only that.
                            White ink 4.82:1, so it clears the floor as a button.
     --accent      #fd7701  DECORATIVE ONLY — 2.69:1 on white. Icons, rules,
                            gradient edges. Never a text or button colour.
     --trust-gold  #fdca1d  11.1:1 on brand-900, ~1.6:1 on white. Dark
                            surfaces only; on a light panel it is invisible.

   So: one primary accent (azure), one urgency colour (red), one decorative
   heat tint (orange), one dark-surface trust tint (gold). The heat/cool pair
   below carries MEANING — which half of the trade a service belongs to — and
   is never used for chrome.
   ------------------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  /* --- Brand navy -> azure ramp. Header, footer, dark sections. ---------- */
  --brand-900: #061325;
  --brand-800: #09203f;
  --brand-700: #0b2f5e;
  --brand-600: #014ab3; /* the logo's azure, sampled */
  --brand-500: #1565d8;

  /* --- Accent / primary CTA: see the palette note above. ----------------- */
  --accent: #fd7701; /* DECORATIVE ONLY — 2.69:1, never text or buttons */
  --accent-cta: #014ab3;
  --accent-cta-hover: #0a5ccf;
  --accent-cta-active: #013c92;
  --accent-ink: #ffffff;
  --accent-wash: #eaf1fb;
  --accent-wash-border: #c2d6f2;

  /* --- Urgency. The 24/7 emergency control, and nothing else. ------------ */
  --urgent: #e31600;
  --urgent-hover: #c41200;
  --urgent-active: #a30f00;
  --urgent-ink: #ffffff;
  --urgent-wash: #fdecea;

  /* --- Trust gold. Dark surfaces ONLY (1.6:1 on white — invisible). ------ */
  --trust-gold: #fdca1d;
  --trust-gold-dim: #c99c0a;

  /* --- Domain hues. Meaning, not decoration: these two tell heating apart
         from cooling in icons, service cards and badges. Never used for
         chrome, buttons, links or text. ------------------------------------ */
  --domain-cool: #014ab3;
  --domain-cool-wash: #eaf1fb;
  --domain-heat: #c21f00;
  --domain-heat-wash: #fdeee9;

  /* --- Surface ramp (light). 0 is the page, each step recedes. ----------- */
  --surface-0: #ffffff;
  --surface-1: #f7f9fb;
  --surface-2: #eef2f6;
  --surface-3: #e2e8ee;
  --surface-inverse: var(--brand-900);

  /* --- Borders ----------------------------------------------------------- */
  --border-subtle: #e2e8ee;
  --border-default: #cdd7e1;
  --border-strong: #9fb0c0;
  --border-inverse: #1f3650;

  /* --- Ink ramp. Exactly three steps. A fourth always becomes a mistake. - */
  --ink-1: #0c1824; /* primary text   — 15.8:1 on surface-0 */
  --ink-2: #41556a; /* secondary text —  7.6:1 on surface-0 */
  --ink-3: #64788d; /* meta / muted   —  4.6:1 on surface-0, the floor */
  --ink-on-brand: #ffffff;
  --ink-on-brand-2: #c3d3e2;

  /* --- Semantic. Same meaning everywhere, forever. ----------------------- */
  --success: #157347;
  --success-wash: #e8f5ee;
  --success-border: #b6ddc7;
  --warning: #946c00;
  --warning-wash: #fdf6e3;
  --warning-border: #ecdca8;
  --danger: #a82018;
  --danger-wash: #fdecea;
  --danger-border: #f2c3bf;
  --info: var(--brand-600);
  --info-wash: #eaf1f8;
  --info-border: #c3d8ea;

  /* --- Focus. Never removed, only replaced. ------------------------------ */
  --focus-ring: var(--brand-600);
  --focus-ring-offset: var(--surface-0);
  --focus-ring-width: 3px;

  /* --- Type ---------------------------------------------------------------
         System stack on purpose: zero font requests, zero layout shift, no
         FOUT on a slow phone connection — which is the device a customer with
         a dead air conditioner is actually holding. If a display face is
         added later it goes HERE and nowhere else. --------------------- */
  --font-sans: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto,
    'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
    'Liberation Mono', monospace;

  /* Fluid scale, 1.25 ratio at the small end opening to ~1.33 at the large.
     clamp() means no breakpoint-specific font sizes anywhere downstream. */
  --text-xs: 0.78rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-md: clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem);
  --text-lg: clamp(1.1875rem, 1.1rem + 0.4vw, 1.375rem);
  --text-xl: clamp(1.375rem, 1.25rem + 0.7vw, 1.75rem);
  --text-2xl: clamp(1.625rem, 1.4rem + 1.1vw, 2.25rem);
  --text-3xl: clamp(2rem, 1.6rem + 1.9vw, 3rem);
  --text-4xl: clamp(2.375rem, 1.8rem + 2.8vw, 3.75rem);

  --leading-tight: 1.15;
  --leading-snug: 1.3;
  --leading-normal: 1.55;
  --leading-relaxed: 1.7;

  --weight-normal: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  --tracking-tight: -0.02em;
  --tracking-normal: 0;
  --tracking-wide: 0.04em;
  --tracking-caps: 0.08em;

  /* Measure. Body copy past ~70 characters is measurably harder to read. */
  --measure: 68ch;
  --measure-narrow: 52ch;

  /* --- Space. 4px base. Only these values appear in layout code. --------- */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 2.5rem;
  --space-8: 3rem;
  --space-9: 4rem;
  --space-10: 5rem;
  --space-11: 6.5rem;
  --space-12: 8rem;

  /* Vertical rhythm for page sections, fluid so small screens do not waste
     half a viewport on whitespace. */
  --section-y: clamp(var(--space-8), 6vw, var(--space-11));

  /* --- Layout ------------------------------------------------------------ */
  --container-max: 75rem; /* 1200px */
  --container-narrow: 48rem; /* 768px — prose and forms */
  --container-wide: 85rem;
  --gutter: clamp(var(--space-4), 4vw, var(--space-7));

  /* --- Radius ------------------------------------------------------------ */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 14px;
  --radius-xl: 22px;
  --radius-pill: 999px;

  /* --- Elevation. Two levels plus a focus-adjacent one. Any more and the
         page stops having a readable depth order. -------------------------- */
  --shadow-sm: 0 1px 2px rgb(9 23 37 / 0.06), 0 1px 3px rgb(9 23 37 / 0.08);
  --shadow-md: 0 4px 8px rgb(9 23 37 / 0.06), 0 10px 24px rgb(9 23 37 / 0.09);
  --shadow-lg: 0 10px 20px rgb(9 23 37 / 0.08), 0 24px 48px rgb(9 23 37 / 0.12);

  /* --- Motion. Transform and opacity only — see base.css. ---------------- */
  --duration-instant: 90ms;
  --duration-fast: 150ms;
  --duration-base: 220ms;
  --duration-slow: 360ms;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* --- Z index. A named scale, because magic numbers in z-index are how you
         end up with a modal behind a sticky header. ------------------------ */
  --z-base: 0;
  --z-raised: 10;
  --z-sticky: 100;
  --z-header: 200;
  --z-overlay: 300;
  --z-modal: 400;
  --z-toast: 500;

  /* --- Control sizing. 44px minimum touch target, non-negotiable. -------- */
  --control-height: 2.75rem; /* 44px */
  --control-height-lg: 3.25rem; /* 52px */
  --control-padding-x: var(--space-5);
  --tap-min: 44px;
}

/* =============================================================================
   DARK THEME
   Only the surface, ink, border and wash tokens are redefined. Brand, accent,
   semantic hues, spacing, type and motion are theme-independent by design —
   that is the whole payoff of naming tokens for purpose.
   ========================================================================== */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --surface-0: #0b1520;
    --surface-1: #101e2c;
    --surface-2: #16293a;
    --surface-3: #1e3549;
    --surface-inverse: #050d16;

    --border-subtle: #1c3145;
    --border-default: #27415a;
    --border-strong: #3d5a76;

    --ink-1: #eef4f9;
    --ink-2: #b2c4d4;
    --ink-3: #8b9fb2;

    /* The CTA step is tuned for white-on-accent against a LIGHT page. On a
       dark page the brighter decorative step reads better and still clears
       4.5:1 with near-black ink, so the ink flips instead of the hue. */
    --accent-cta: #2f7fe8;
    --accent-cta-hover: #4a92ee;
    --accent-cta-active: #1f6ac9;
    --accent-ink: #04101f;
    --accent-wash: #0d2748;
    --accent-wash-border: #1b4272;

    --urgent: #ff4a33;
    --urgent-hover: #ff6250;
    --urgent-active: #e03520;
    --urgent-ink: #1a0300;
    --urgent-wash: #351009;

    --domain-cool: #5aa9dc;
    --domain-cool-wash: #10283a;
    --domain-heat: #ff7a5c;
    --domain-heat-wash: #341a0f;

    --success: #4cc08a;
    --success-wash: #0f2a1e;
    --success-border: #1f4c36;
    --warning: #ddb33e;
    --warning-wash: #2b2210;
    --warning-border: #4d3d14;
    --danger: #f08279;
    --danger-wash: #2e1512;
    --danger-border: #552320;
    --info-wash: #11263a;
    --info-border: #234a6b;

    --focus-ring: #7cb6e8;
    --focus-ring-offset: var(--surface-0);

    --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.4);
    --shadow-md: 0 4px 10px rgb(0 0 0 / 0.45), 0 12px 28px rgb(0 0 0 / 0.35);
    --shadow-lg: 0 12px 24px rgb(0 0 0 / 0.5), 0 28px 56px rgb(0 0 0 / 0.45);
  }
}

/* Explicit opt-in, for the footer theme toggle and for print. */
:root[data-theme='dark'] {
  --surface-0: #0b1520;
  --surface-1: #101e2c;
  --surface-2: #16293a;
  --surface-3: #1e3549;
  --surface-inverse: #050d16;

  --border-subtle: #1c3145;
  --border-default: #27415a;
  --border-strong: #3d5a76;

  --ink-1: #eef4f9;
  --ink-2: #b2c4d4;
  --ink-3: #8b9fb2;

  --accent-cta: #2f7fe8;
  --accent-cta-hover: #4a92ee;
  --accent-cta-active: #1f6ac9;
  --accent-ink: #04101f;
  --accent-wash: #0d2748;
  --accent-wash-border: #1b4272;

  --urgent: #ff4a33;
  --urgent-hover: #ff6250;
  --urgent-active: #e03520;
  --urgent-ink: #1a0300;
  --urgent-wash: #351009;

  --domain-cool: #5aa9dc;
  --domain-cool-wash: #10283a;
  --domain-heat: #ff7a5c;
  --domain-heat-wash: #341a0f;

  --success: #4cc08a;
  --success-wash: #0f2a1e;
  --success-border: #1f4c36;
  --warning: #ddb33e;
  --warning-wash: #2b2210;
  --warning-border: #4d3d14;
  --danger: #f08279;
  --danger-wash: #2e1512;
  --danger-border: #552320;
  --info-wash: #11263a;
  --info-border: #234a6b;

  --focus-ring: #7cb6e8;

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.4);
  --shadow-md: 0 4px 10px rgb(0 0 0 / 0.45), 0 12px 28px rgb(0 0 0 / 0.35);
  --shadow-lg: 0 12px 24px rgb(0 0 0 / 0.5), 0 28px 56px rgb(0 0 0 / 0.45);
}


/* ===== base.css ===== */
/* =============================================================================
   BASE — reset, document defaults, typography, focus, motion.
   No component lives here. No layout lives here.
   ========================================================================== */

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

/* Margin is a layout decision, made by the layout layer, never inherited from
   the browser's defaults. */
* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Sticky header height, so in-page anchors do not land under it. */
  scroll-padding-top: calc(var(--header-height, 4rem) + var(--space-5));
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  background-color: var(--surface-0);
  color: var(--ink-1);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  font-weight: var(--weight-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* A long service name must never widen the page on a phone. */
  overflow-wrap: break-word;
}

/* --- Media ---------------------------------------------------------------- */
img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
  /* Keeps a broken or still-loading image from collapsing the layout. */
  background-color: var(--surface-2);
}

/* NO global `fill` here, deliberately.

   A CSS declaration beats an SVG presentation attribute, so `svg { fill:
   currentColor }` silently overrode the `fill="none"` that every outline icon
   carries — turning each closed path into a solid blob. It looked fine on the
   open-path icons, which is why it survived until a check-in-a-circle rendered
   as a black disc.

   Icons set their own fill and stroke in icons.js. The only thing stated here
   is that they inherit the text colour, via currentColor on the attribute. */
svg {
  color: inherit;
}

/* --- Headings ------------------------------------------------------------- */
h1,
h2,
h3,
h4,
h5,
h6 {
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--ink-1);
  text-wrap: balance; /* no orphaned single word on a headline */
}

h1 {
  font-size: var(--text-4xl);
}
h2 {
  font-size: var(--text-3xl);
}
h3 {
  font-size: var(--text-xl);
}
h4 {
  font-size: var(--text-lg);
}
h5,
h6 {
  font-size: var(--text-md);
}

p {
  text-wrap: pretty;
}

/* --- Links ---------------------------------------------------------------
   Underlined by default. An un-underlined link inside a paragraph is a link
   that some portion of readers will never find. Chrome links (nav, buttons,
   cards) opt out explicitly with .u-nolink, which is a deliberate act.
   ----------------------------------------------------------------------- */
a {
  color: var(--brand-600);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color var(--duration-fast) var(--ease-out);
}

a:hover {
  color: var(--accent-cta);
  text-decoration-thickness: 2px;
}

a.u-nolink {
  text-decoration: none;
  color: inherit;
}

/* --- Lists ---------------------------------------------------------------- */
ul,
ol {
  padding-inline-start: var(--space-5);
}

li + li {
  margin-top: var(--space-2);
}

/* --- Form elements inherit type. The browser default of 13px monospace-ish
       in a form field is a readability bug, not a style choice. ----------- */
input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

textarea {
  resize: vertical;
}

button {
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
}

button:disabled {
  cursor: not-allowed;
}

fieldset {
  border: none;
  padding: 0;
  min-width: 0; /* Chrome ignores flex/grid shrink on fieldset without this */
}

legend {
  padding: 0;
}

/* --- Tables --------------------------------------------------------------- */
table {
  border-collapse: collapse;
  width: 100%;
}

th {
  text-align: start;
  font-weight: var(--weight-semibold);
}

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

hr {
  border: none;
  border-top: 1px solid var(--border-subtle);
}

/* --- Focus ---------------------------------------------------------------
   The ring is never removed, only replaced. :focus-visible means a mouse
   click on a button does not leave a ring behind, but a Tab press always does.
   ----------------------------------------------------------------------- */
:focus {
  outline: none;
}

:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Inside a dark section the light-page ring disappears. */
.theme-inverse :focus-visible {
  outline-color: var(--ink-on-brand);
}

/* --- Selection ------------------------------------------------------------ */
::selection {
  background-color: var(--accent-wash);
  color: var(--ink-1);
}

/* --- Skip link -----------------------------------------------------------
   Visible the instant it has focus. A keyboard user should not have to tab
   through eleven nav items on every page to reach the content.
   ----------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  inset-inline-start: var(--space-4);
  inset-block-start: var(--space-4);
  z-index: var(--z-toast);
  padding: var(--space-3) var(--space-5);
  background-color: var(--surface-0);
  color: var(--ink-1);
  border: 2px solid var(--focus-ring);
  border-radius: var(--radius-md);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  box-shadow: var(--shadow-md);
  transform: translateY(-200%);
  transition: transform var(--duration-fast) var(--ease-out);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

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

/* --- Motion -------------------------------------------------------------
   Honour the OS setting. Note this kills smooth scrolling too: a user who has
   asked for reduced motion did not mean "except for scrolling".
   ----------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Progressive enhancement hook --------------------------------------
   `no-js` is on <html> in the markup and removed by the first inline script.
   So the default state of every rule is the WORKING, no-JavaScript state, and
   JS presence is what changes things. If the script never loads, the page is
   still correct. This is the opposite of hiding content and revealing it with
   JS, which fails closed into a blank page.
   ----------------------------------------------------------------------- */
.js-only {
  display: none;
}

html:not(.no-js) .js-only {
  display: revert;
}

html:not(.no-js) .no-js-only {
  display: none;
}

/* --- Utilities (deliberately few) --------------------------------------- */
.u-measure {
  max-width: var(--measure);
}

.u-measure-narrow {
  max-width: var(--measure-narrow);
}

.u-center {
  text-align: center;
}

.u-nowrap {
  white-space: nowrap;
}

.u-mt-0 {
  margin-block-start: 0;
}

/* --- Print ---------------------------------------------------------------
   Someone will print a confirmed appointment and stick it on the fridge.
   ----------------------------------------------------------------------- */
@media print {
  :root {
    --surface-0: #fff;
    --surface-1: #fff;
    --surface-2: #fff;
    --ink-1: #000;
    --ink-2: #222;
    --ink-3: #444;
  }

  .site-header,
  .site-footer,
  .no-print {
    display: none !important;
  }

  a[href^='http']::after {
    content: ' (' attr(href) ')';
    font-size: var(--text-xs);
    color: var(--ink-3);
  }

  .card,
  .panel {
    border: 1px solid #999 !important;
    box-shadow: none !important;
    break-inside: avoid;
  }
}


/* ===== layout.css ===== */
/* =============================================================================
   LAYOUT — containers, sections, grids, and the site shell (header / footer).
   ========================================================================== */

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

.container--narrow {
  max-width: var(--container-narrow);
}
.container--wide {
  max-width: var(--container-wide);
}

/* --- Sections ------------------------------------------------------------- */
.section {
  padding-block: var(--section-y);
}

.section--tight {
  padding-block: calc(var(--section-y) * 0.6);
}

.section--alt {
  background-color: var(--surface-1);
}

/* A dark band. `theme-inverse` also re-points the focus ring and the secondary
   button, which is why it is a theme class and not just a background colour. */
.theme-inverse {
  background-color: var(--brand-900);
  color: var(--ink-on-brand);
}

.theme-inverse h1,
.theme-inverse h2,
.theme-inverse h3,
.theme-inverse h4 {
  color: var(--ink-on-brand);
}

.theme-inverse p,
.theme-inverse li {
  color: var(--ink-on-brand-2);
}

.theme-inverse a {
  color: #ffffff;
}

/* --- Section headings ----------------------------------------------------- */
.section-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-bottom: var(--space-7);
  max-width: var(--measure);
}

.section-head--center {
  margin-inline: auto;
  text-align: center;
  align-items: center;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--accent-cta);
}

.theme-inverse .eyebrow {
  color: var(--trust-gold);
}

/* The one place the decorative orange is allowed to be a graphic element. */
.eyebrow::before {
  content: '';
  width: var(--space-5);
  height: 3px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--accent), var(--urgent));
}

.section-lead {
  font-size: var(--text-md);
  color: var(--ink-2);
  line-height: var(--leading-relaxed);
}

.theme-inverse .section-lead {
  color: var(--ink-on-brand-2);
}

/* --- Grids ----------------------------------------------------------------
   auto-fit + minmax means no breakpoint lists. The grid reflows on content
   width, so it is correct at every size including ones nobody tested.
   ----------------------------------------------------------------------- */
.grid {
  display: grid;
  gap: var(--space-5);
}

.grid--2 {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}
.grid--3 {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.grid--4 {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
}

/* Asymmetric split for "content + sidebar" layouts. */
.split {
  display: grid;
  gap: var(--space-7);
  align-items: start;
}

@media (min-width: 60rem) {
  .split {
    grid-template-columns: 1fr 22rem;
    gap: var(--space-8);
  }
  .split--reverse {
    grid-template-columns: 22rem 1fr;
  }
  .split--even {
    grid-template-columns: 1fr 1fr;
  }
}

.stack > * + * {
  margin-top: var(--space-4);
}
.stack--lg > * + * {
  margin-top: var(--space-6);
}
.stack--sm > * + * {
  margin-top: var(--space-2);
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}

/* =============================================================================
   SITE HEADER
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background-color: var(--surface-0);
  border-bottom: 1px solid var(--border-subtle);
  /* Measured by app.js into --header-height for scroll-padding. */
}

.site-header__inner {
  width: 100%;
  max-width: var(--container-wide);
  margin-inline: auto;
  padding: var(--space-3) var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

/* --- Brand lockup ---------------------------------------------------------
   The emblem is an image; the COMPANY NAME IS TEXT. A picture of a word is
   not selectable, not translatable, not resizable with the user's font
   settings, and goes soft on a display the raster was not cut for.
   ----------------------------------------------------------------------- */
.brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: none;
  margin-inline-end: auto;
}

.brand__emblem {
  width: 59px;
  height: 48px;
  object-fit: contain;
  background: none;
  flex: none;
}

.brand__text {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
}

.brand__name {
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  color: var(--ink-1);
}

.brand__tag {
  font-size: var(--text-xs);
  color: var(--ink-3);
}

@media (max-width: 44rem) {
  .brand__tag {
    display: none;
  }
  .brand__name {
    font-size: var(--text-base);
  }
  .brand__emblem {
    width: 44px;
    height: 36px;
  }
}

/* --- Navigation -----------------------------------------------------------
   <details> so it opens with no JavaScript. On wide screens the disclosure
   furniture is hidden and the list is simply always visible.
   ----------------------------------------------------------------------- */
.site-nav {
  position: relative;
}

.site-nav__toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--control-height);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--ink-2);
  cursor: pointer;
  list-style: none;
}

.site-nav__toggle::-webkit-details-marker {
  display: none;
}

.site-nav__toggle:hover {
  background-color: var(--surface-2);
  color: var(--ink-1);
}

.site-nav__panel {
  position: absolute;
  inset-inline-end: 0;
  inset-block-start: calc(100% + var(--space-2));
  min-width: 13rem;
  padding: var(--space-2);
  background-color: var(--surface-0);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.site-nav__list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.site-nav__list li {
  margin: 0;
}

.site-nav__link {
  display: block;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--ink-2);
  text-decoration: none;
}

.site-nav__link:hover {
  background-color: var(--surface-2);
  color: var(--ink-1);
}

.site-nav__link--current {
  color: var(--accent-cta);
  font-weight: var(--weight-semibold);
}

@media (min-width: 60rem) {
  .site-nav__toggle {
    display: none;
  }

  .site-nav__panel {
    position: static;
    padding: 0;
    border: none;
    box-shadow: none;
    background: none;
    min-width: 0;
  }

  .site-nav__list {
    display: flex;
    gap: var(--space-1);
  }

  /* A <details> with the summary hidden still needs its content shown when
     closed on desktop. */
  .site-nav:not([open]) .site-nav__panel {
    display: block;
  }

  .site-nav__link--current {
    position: relative;
  }

  .site-nav__link--current::after {
    content: '';
    position: absolute;
    inset-inline: var(--space-4);
    inset-block-end: 2px;
    height: 2px;
    border-radius: var(--radius-pill);
    background-color: var(--accent-cta);
  }
}

/* --- Header actions ------------------------------------------------------- */
.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: none;
}

/* NOTE on the selectors below: components.css is loaded AFTER this file, so
   `.btn { display: inline-flex }` beats a bare `.site-header__book
   { display: none }` on equal specificity and the button stays visible. The
   parent is in the selector deliberately, to win that tie. Flattening these
   back to a single class reintroduces 150px of horizontal scroll on a phone. */
@media (max-width: 60rem) {
  .site-header__actions .site-header__book {
    display: none; /* the sticky action bar carries it on small screens */
  }
}

@media (max-width: 30rem) {
  .site-header__call .site-header__call-text {
    display: none; /* icon-only call button; the tap target stays 44px */
  }
  .site-header__actions .site-header__call {
    padding-inline: var(--space-3);
  }
}

/* Belt and braces: nothing in the shell may widen the page. A long service
   name or a future button cannot reintroduce a horizontal scrollbar. */
.site-header__inner {
  min-width: 0;
}

.brand {
  min-width: 0;
}

.brand__text {
  min-width: 0;
}

.brand__name {
  overflow-wrap: anywhere;
}

/* =============================================================================
   STICKY ACTION BAR (small screens only)
   The two things a person on a phone with a dead system actually wants, pinned
   where their thumb already is.
   ========================================================================== */
.action-bar {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: var(--z-sticky);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4)
    calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  background-color: var(--surface-0);
  border-top: 1px solid var(--border-subtle);
  box-shadow: 0 -4px 16px rgb(9 23 37 / 0.1);
}

@media (min-width: 60rem) {
  .action-bar {
    display: none;
  }
}

/* Reserve the space so the bar never covers the end of the page. */
@media (max-width: 60rem) {
  body {
    padding-bottom: 4.75rem;
  }
}

/* =============================================================================
   SITE FOOTER
   ========================================================================== */
.site-footer {
  margin-top: var(--space-10);
}

.site-footer__inner {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding: var(--space-9) var(--gutter) var(--space-7);
  display: grid;
  gap: var(--space-7);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
}

.site-footer__brand {
  grid-column: 1 / -1;
  max-width: 22rem;
}

@media (min-width: 60rem) {
  .site-footer__brand {
    grid-column: span 1;
  }
}

.site-footer__lockup {
  width: 200px;
  height: auto;
  background: none;
}

.site-footer__tagline {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--ink-on-brand-2);
}

.site-footer__heading {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--trust-gold);
  margin-bottom: var(--space-4);
}

.site-footer__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.site-footer__list li {
  margin: 0;
  font-size: var(--text-sm);
}

.site-footer__list a {
  color: var(--ink-on-brand-2);
  text-decoration: none;
}

.site-footer__list a:hover {
  color: #fff;
  text-decoration: underline;
}

.site-footer__list--contact li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.site-footer__list--contact svg {
  flex: none;
  margin-top: 1px;
  color: var(--trust-gold);
}

.site-footer__legal {
  border-top: 1px solid rgb(255 255 255 / 0.12);
  padding: var(--space-5) var(--gutter);
  max-width: var(--container-max);
  margin-inline: auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
  align-items: center;
  justify-content: space-between;
  font-size: var(--text-xs);
  color: var(--ink-on-brand-2);
}

.site-footer__legal p {
  margin: 0;
  font-size: var(--text-xs);
}

.site-footer__licence {
  opacity: 0.85;
}

.site-footer__links a {
  color: var(--ink-on-brand-2);
}


/* ===== components.css ===== */
/* =============================================================================
   COMPONENTS — the primitive set. Build these once; compose everything else.
   BEM: block__element--modifier. Modifiers carry STATE.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   BUTTON
   Every interactive control is a state machine:
     IDLE -> HOVER -> ACTIVE -> LOADING -> (SUCCESS | ERROR) -> IDLE, + DISABLED
   Each of those has a visual here. A control that looks identical while it is
   working is a control the user will click a second time.
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-height);
  min-width: var(--tap-min);
  padding: var(--space-3) var(--control-padding-x);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  /* Transform and opacity only. Never width/height/padding on hover. */
  transition:
    transform var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out),
    opacity var(--duration-fast) var(--ease-out);
}

.btn:active {
  transform: translateY(1px);
}

.btn:disabled,
.btn[aria-disabled='true'] {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* --- Variants -------------------------------------------------------------
   Named for PURPOSE. `--primary` is the one action the page wants most; there
   is never more than one per view.
   ----------------------------------------------------------------------- */
.btn--primary {
  background-color: var(--accent-cta);
  color: var(--accent-ink);
  box-shadow: var(--shadow-sm);
}

.btn--primary:hover:not(:disabled) {
  background-color: var(--accent-cta-hover);
  box-shadow: var(--shadow-md);
}

.btn--primary:active:not(:disabled) {
  background-color: var(--accent-cta-active);
}

.btn--secondary {
  background-color: var(--surface-0);
  color: var(--ink-1);
  border-color: var(--border-default);
}

.btn--secondary:hover:not(:disabled) {
  border-color: var(--border-strong);
  background-color: var(--surface-1);
}

.btn--brand {
  background-color: var(--brand-700);
  color: var(--ink-on-brand);
}

.btn--brand:hover:not(:disabled) {
  background-color: var(--brand-600);
}

.btn--ghost {
  background-color: transparent;
  color: var(--ink-2);
}

.btn--ghost:hover:not(:disabled) {
  background-color: var(--surface-2);
  color: var(--ink-1);
}

/* The 24/7 emergency call control. The ONLY place brand red is a button —
   urgency is the meaning. Never use it for a second "also important" action,
   or it stops meaning anything. */
.btn--urgent {
  background-color: var(--urgent);
  color: var(--urgent-ink);
  box-shadow: var(--shadow-sm);
}

.btn--urgent:hover:not(:disabled) {
  background-color: var(--urgent-hover);
  box-shadow: var(--shadow-md);
}

.btn--urgent:active:not(:disabled) {
  background-color: var(--urgent-active);
}

.btn--danger {
  background-color: var(--danger);
  color: #fff;
}

.btn--danger:hover:not(:disabled) {
  filter: brightness(0.92);
}

/* On a dark section the secondary button needs inverted ink. */
.theme-inverse .btn--secondary {
  background-color: transparent;
  color: var(--ink-on-brand);
  border-color: rgb(255 255 255 / 0.35);
}

.theme-inverse .btn--secondary:hover:not(:disabled) {
  background-color: rgb(255 255 255 / 0.1);
  border-color: rgb(255 255 255 / 0.6);
}

/* --- Sizes --------------------------------------------------------------- */
.btn--lg {
  min-height: var(--control-height-lg);
  padding-inline: var(--space-6);
  font-size: var(--text-md);
}

.btn--sm {
  min-height: 2.25rem;
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
}

.btn--block {
  display: flex;
  width: 100%;
}

/* --- LOADING state -------------------------------------------------------
   Driven by `data-state="loading"`, set by behaviour.js. The label is held in
   place (no width jump) and the spinner replaces it in the same box.
   ----------------------------------------------------------------------- */
.btn[data-state='loading'] {
  pointer-events: none;
  position: relative;
  color: transparent;
}

.btn[data-state='loading']::after {
  content: '';
  position: absolute;
  inset: 50% auto auto 50%;
  width: 1.1em;
  height: 1.1em;
  margin: -0.55em 0 0 -0.55em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  color: var(--accent-ink);
  animation: spin 620ms linear infinite;
}

.btn--secondary[data-state='loading']::after,
.btn--ghost[data-state='loading']::after {
  color: var(--ink-2);
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* A button that just succeeded says so for a beat before returning to idle. */
.btn[data-state='success'] {
  background-color: var(--success);
  color: #fff;
}

.btn__icon {
  flex: none;
  width: 1.15em;
  height: 1.15em;
}

/* -----------------------------------------------------------------------------
   FIELD — label + control + hint + error, as one unit.
   The error message is always rendered in the DOM (empty when valid) and
   wired with aria-describedby, so a screen reader announces the change rather
   than the message appearing out of nowhere.
   -------------------------------------------------------------------------- */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--ink-1);
}

.field__required {
  color: var(--danger);
  margin-inline-start: 0.15em;
}

.field__optional {
  font-weight: var(--weight-normal);
  color: var(--ink-3);
  margin-inline-start: 0.35em;
}

.field__control,
.input,
.select,
.textarea {
  width: 100%;
  min-height: var(--control-height);
  padding: var(--space-3) var(--space-4);
  background-color: var(--surface-0);
  color: var(--ink-1);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}

.input::placeholder,
.textarea::placeholder {
  color: var(--ink-3);
}

.input:hover,
.select:hover,
.textarea:hover {
  border-color: var(--border-strong);
}

.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible {
  border-color: var(--focus-ring);
  outline-offset: 0;
}

.select {
  /* Native select arrow, drawn so it matches in both themes. */
  appearance: none;
  padding-inline-end: var(--space-8);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position:
    calc(100% - 1.25rem) calc(50% + 2px),
    calc(100% - 0.85rem) calc(50% + 2px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

.textarea {
  min-height: 7rem;
  line-height: var(--leading-normal);
}

.field__hint {
  font-size: var(--text-sm);
  color: var(--ink-3);
}

.field__error {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--danger);
}

/* Empty error element takes no space — but it stays in the DOM so that
   aria-describedby always points at something that exists. */
.field__error:empty {
  display: none;
}

.field--error .input,
.field--error .select,
.field--error .textarea {
  border-color: var(--danger);
  background-color: var(--danger-wash);
}

/* -----------------------------------------------------------------------------
   CHECKBOX / RADIO
   The native control stays visible and native. It is already accessible, it
   already works without JS, and re-implementing it with a div is how keyboard
   support gets lost.
   -------------------------------------------------------------------------- */
.choice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  min-height: var(--tap-min);
  padding: var(--space-2) 0;
  cursor: pointer;
}

.choice__input {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.15rem;
  accent-color: var(--accent-cta);
  cursor: pointer;
}

.choice__label {
  font-size: var(--text-base);
  line-height: var(--leading-snug);
}

.choice__note {
  display: block;
  font-size: var(--text-sm);
  color: var(--ink-3);
  margin-top: var(--space-1);
}

/* -----------------------------------------------------------------------------
   CARD
   -------------------------------------------------------------------------- */
.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background-color: var(--surface-0);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.card--flat {
  box-shadow: none;
  background-color: var(--surface-1);
}

.card--interactive {
  transition:
    transform var(--duration-base) var(--ease-out),
    box-shadow var(--duration-base) var(--ease-out),
    border-color var(--duration-base) var(--ease-out);
}

.card--interactive:hover,
.card--interactive:focus-within {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--border-default);
}

.card__eyebrow {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-3);
}

.card__title {
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
}

.card__body {
  color: var(--ink-2);
  font-size: var(--text-base);
}

.card__footer {
  margin-top: auto;
  padding-top: var(--space-2);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.card__price {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--ink-2);
}

/* The icon plate. Hue comes from the service's domain (heat vs cool), which is
   meaning, not decoration — see the tokens note. */
.card__icon {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius-md);
  background-color: var(--surface-2);
  color: var(--ink-2);
}

.card__icon svg {
  width: 1.5rem;
  height: 1.5rem;
}

.card__icon--cool {
  background-color: var(--domain-cool-wash);
  color: var(--domain-cool);
}

.card__icon--heat {
  background-color: var(--domain-heat-wash);
  color: var(--domain-heat);
}

.card__icon--accent {
  background-color: var(--accent-wash);
  color: var(--accent-cta);
}

/* -----------------------------------------------------------------------------
   PANEL — a heavier container for forms and confirmations.
   -------------------------------------------------------------------------- */
.panel {
  background-color: var(--surface-0);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.panel__header {
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--border-subtle);
  background-color: var(--surface-1);
}

.panel__title {
  font-size: var(--text-lg);
}

.panel__subtitle {
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  color: var(--ink-2);
}

.panel__body {
  padding: var(--space-6);
}

.panel__footer {
  padding: var(--space-5) var(--space-6);
  border-top: 1px solid var(--border-subtle);
  background-color: var(--surface-1);
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  align-items: center;
}

@media (max-width: 30rem) {
  .panel__body,
  .panel__header,
  .panel__footer {
    padding-inline: var(--space-4);
  }
}

/* -----------------------------------------------------------------------------
   BADGE
   -------------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0.2rem var(--space-3);
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-default);
  background-color: var(--surface-2);
  color: var(--ink-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  white-space: nowrap;
}

.badge--success {
  background-color: var(--success-wash);
  border-color: var(--success-border);
  color: var(--success);
}
.badge--warning {
  background-color: var(--warning-wash);
  border-color: var(--warning-border);
  color: var(--warning);
}
.badge--danger {
  background-color: var(--danger-wash);
  border-color: var(--danger-border);
  color: var(--danger);
}
.badge--info {
  background-color: var(--info-wash);
  border-color: var(--info-border);
  color: var(--info);
}
.badge--accent {
  background-color: var(--accent-wash);
  border-color: var(--accent-wash-border);
  color: var(--accent-cta);
}

/* Status never rides on colour alone — a dot shape plus the written word. */
.badge__dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background-color: currentColor;
  flex: none;
}

/* -----------------------------------------------------------------------------
   ALERT — a message with a reason. "Failed" is not a message.
   -------------------------------------------------------------------------- */
.alert {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border-default);
  border-inline-start-width: 4px;
  border-radius: var(--radius-md);
  background-color: var(--surface-1);
  font-size: var(--text-base);
}

.alert__icon {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.15rem;
}

.alert__title {
  font-weight: var(--weight-bold);
  margin-bottom: var(--space-1);
}

.alert__body {
  color: var(--ink-2);
}

.alert__body > * + * {
  margin-top: var(--space-2);
}

.alert--success {
  background-color: var(--success-wash);
  border-color: var(--success-border);
  border-inline-start-color: var(--success);
}
.alert--warning {
  background-color: var(--warning-wash);
  border-color: var(--warning-border);
  border-inline-start-color: var(--warning);
}
.alert--danger {
  background-color: var(--danger-wash);
  border-color: var(--danger-border);
  border-inline-start-color: var(--danger);
}
.alert--info {
  background-color: var(--info-wash);
  border-color: var(--info-border);
  border-inline-start-color: var(--info);
}

/* -----------------------------------------------------------------------------
   SLOT PICKER — the arrival-window chooser. The core of the booking flow.

   Deliberate decision: the native radio stays VISIBLE inside each slot.
   The tempting version hides the radio and paints the selected state with
   `:has(:checked)`. If `:has()` is unsupported or the stylesheet fails to
   load, that version leaves the customer with no way to tell what they picked.
   A visible radio plus a highlight as an enhancement cannot fail that way.
   -------------------------------------------------------------------------- */
.slots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: var(--space-3);
}

.slot {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--control-height-lg);
  padding: var(--space-3) var(--space-4);
  background-color: var(--surface-0);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}

.slot:hover {
  border-color: var(--border-strong);
  background-color: var(--surface-1);
}

.slot__input {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--accent-cta);
  cursor: pointer;
}

.slot__text {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.slot__time {
  font-weight: var(--weight-semibold);
  font-size: var(--text-base);
  line-height: var(--leading-snug);
}

.slot__meta {
  font-size: var(--text-xs);
  color: var(--ink-3);
}

/* Enhancement only. Nothing depends on this to be usable. */
.slot:has(.slot__input:checked) {
  border-color: var(--accent-cta);
  background-color: var(--accent-wash);
  box-shadow: 0 0 0 1px var(--accent-cta) inset;
}

.slot:has(.slot__input:disabled) {
  opacity: 0.5;
  cursor: not-allowed;
  background-color: var(--surface-2);
}

/* -----------------------------------------------------------------------------
   STEPPER — where the customer is in the booking flow.
   An ordered list, because that is what it is.
   -------------------------------------------------------------------------- */
.stepper {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  padding: 0;
  margin: 0;
  list-style: none;
  counter-reset: step;
}

.stepper__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--ink-3);
  counter-increment: step;
  margin: 0;
}

.stepper__item::before {
  content: counter(step);
  display: grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--border-default);
  background-color: var(--surface-0);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
}

.stepper__item--current {
  color: var(--ink-1);
  font-weight: var(--weight-semibold);
}

.stepper__item--current::before {
  background-color: var(--accent-cta);
  border-color: var(--accent-cta);
  color: var(--accent-ink);
}

.stepper__item--done {
  color: var(--ink-2);
}

/* A check mark replaces the number, so completion is shape as well as colour. */
.stepper__item--done::before {
  content: '\2713';
  background-color: var(--success);
  border-color: var(--success);
  color: #fff;
}

/* -----------------------------------------------------------------------------
   ACCORDION — built on <details>/<summary>, so it opens with no JavaScript
   and is keyboard operable for free.
   -------------------------------------------------------------------------- */
.accordion {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background-color: var(--surface-0);
  overflow: hidden;
}

.accordion + .accordion {
  margin-top: var(--space-3);
}

.accordion__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  min-height: var(--tap-min);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  list-style: none;
  transition: background-color var(--duration-fast) var(--ease-out);
}

.accordion__summary::-webkit-details-marker {
  display: none;
}

.accordion__summary:hover {
  background-color: var(--surface-1);
}

.accordion__summary::after {
  content: '';
  flex: none;
  width: 0.55rem;
  height: 0.55rem;
  border-right: 2px solid var(--ink-3);
  border-bottom: 2px solid var(--ink-3);
  transform: rotate(45deg) translateY(-2px);
  transition: transform var(--duration-fast) var(--ease-out);
}

.accordion[open] > .accordion__summary::after {
  transform: rotate(-135deg) translateY(-2px);
}

.accordion__body {
  padding: 0 var(--space-5) var(--space-5);
  color: var(--ink-2);
}

.accordion__body > * + * {
  margin-top: var(--space-3);
}

/* -----------------------------------------------------------------------------
   TOAST — transient confirmation. Polite live region; never steals focus.
   -------------------------------------------------------------------------- */
.toast-region {
  position: fixed;
  inset-block-end: var(--space-5);
  inset-inline: var(--space-4);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  max-width: 28rem;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-pill);
  background-color: var(--surface-inverse);
  color: var(--ink-on-brand);
  box-shadow: var(--shadow-lg);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  pointer-events: auto;
  animation: toast-in var(--duration-base) var(--ease-spring);
}

.toast--success .toast__dot {
  background-color: var(--success);
}
.toast--danger .toast__dot {
  background-color: var(--danger);
}

.toast__dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  flex: none;
  background-color: var(--accent);
}

.toast[data-state='leaving'] {
  animation: toast-out var(--duration-fast) var(--ease-out) forwards;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(0.75rem);
  }
}

@keyframes toast-out {
  to {
    opacity: 0;
    transform: translateY(0.5rem);
  }
}

/* -----------------------------------------------------------------------------
   SPINNER / SKELETON — the "we are working" vocabulary.
   -------------------------------------------------------------------------- */
.spinner {
  display: inline-block;
  width: 1.25rem;
  height: 1.25rem;
  border: 2px solid var(--border-default);
  border-top-color: var(--accent-cta);
  border-radius: 50%;
  animation: spin 620ms linear infinite;
}

.loading-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-5);
  color: var(--ink-2);
  font-size: var(--text-sm);
}

.skeleton {
  border-radius: var(--radius-md);
  background: linear-gradient(
    90deg,
    var(--surface-2) 25%,
    var(--surface-3) 37%,
    var(--surface-2) 63%
  );
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
}

@keyframes shimmer {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: 0 0;
  }
}

.skeleton--slot {
  height: var(--control-height-lg);
}

/* -----------------------------------------------------------------------------
   SUMMARY LIST — label/value pairs. Used by the confirmation and admin views.
   -------------------------------------------------------------------------- */
.summary {
  display: grid;
  gap: var(--space-3);
  margin: 0;
}

.summary__row {
  display: grid;
  grid-template-columns: minmax(7rem, 11rem) 1fr;
  gap: var(--space-2) var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.summary__row:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.summary__label {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--ink-3);
}

.summary__value {
  margin: 0;
  color: var(--ink-1);
}

@media (max-width: 30rem) {
  .summary__row {
    grid-template-columns: 1fr;
    gap: var(--space-1);
  }
}

/* -----------------------------------------------------------------------------
   TESTIMONIAL
   -------------------------------------------------------------------------- */
.quote {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5);
  background-color: var(--surface-0);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.quote__stars {
  display: flex;
  gap: 0.1rem;
  color: var(--accent);
}

.quote__stars svg {
  width: 1.05rem;
  height: 1.05rem;
}

.quote__text {
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--ink-1);
}

.quote__cite {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  font-style: normal;
  margin-top: auto;
}

.quote__name {
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
}

.quote__meta {
  font-size: var(--text-xs);
  color: var(--ink-3);
}

/* -----------------------------------------------------------------------------
   DATA TABLE — admin schedule.
   -------------------------------------------------------------------------- */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background-color: var(--surface-0);
}

.table {
  min-width: 46rem;
  font-size: var(--text-sm);
}

.table th,
.table td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: top;
}

.table thead th {
  background-color: var(--surface-1);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--ink-3);
  position: sticky;
  top: 0;
}

.table tbody tr:last-child td {
  border-bottom: none;
}

.table tbody tr:hover {
  background-color: var(--surface-1);
}

.table__empty {
  padding: var(--space-8);
  text-align: center;
  color: var(--ink-3);
}

/* -----------------------------------------------------------------------------
   PILL LIST — service-area cities, serviced brands.
   -------------------------------------------------------------------------- */
.pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0;
  margin: 0;
  list-style: none;
}

.pills li {
  margin: 0;
}

.pill {
  display: inline-block;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  background-color: var(--surface-1);
  font-size: var(--text-sm);
  color: var(--ink-2);
}

.theme-inverse .pill {
  background-color: rgb(255 255 255 / 0.08);
  border-color: rgb(255 255 255 / 0.18);
  color: var(--ink-on-brand-2);
}


/* ===== pages.css ===== */
/* =============================================================================
   PAGE COMPOSITIONS — layouts that belong to a specific kind of page.
   Anything reused across three or more pages has graduated to components.css.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   HERO

   The hero photo is used at its NATIVE aspect ratio (4.47:1) inside a frame,
   rather than stretched behind the text as a full-bleed background. That is a
   constraint turned into a decision: the source is 1600x358, and covering a
   tall hero box would mean upscaling the one part of the image with real
   detail in it — the house. In a frame it is never asked for a pixel it does
   not have.
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(90rem 40rem at 15% -10%, rgb(1 74 179 / 0.45), transparent 60%),
    radial-gradient(60rem 30rem at 95% 0%, rgb(220 90 16 / 0.22), transparent 55%),
    var(--brand-900);
}

.hero__inner {
  display: grid;
  gap: var(--space-7);
  padding-block: clamp(var(--space-8), 7vw, var(--space-11));
  align-items: center;
}

@media (min-width: 64rem) {
  .hero__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: var(--space-9);
  }
}

.hero__title {
  font-size: var(--text-4xl);
  line-height: 1.08;
  margin-block: var(--space-3) var(--space-4);
  max-width: 18ch;
}

.hero__title-accent {
  display: block;
  background: linear-gradient(94deg, var(--accent) 0%, #ffb067 55%, #ffd9b5 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* The gradient is decoration. If background-clip:text is unsupported the
     text falls back to this colour rather than disappearing — a headline you
     cannot read is a worse outcome than a headline that is not orange. */
  -webkit-text-fill-color: transparent;
}

@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .hero__title-accent {
    background: none;
    color: #ffc08a;
    -webkit-text-fill-color: #ffc08a;
  }
}

.hero__lead {
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--ink-on-brand-2);
  max-width: 46ch;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-6);
}

.hero__points {
  list-style: none;
  padding: 0;
  margin-top: var(--space-6);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
}

.hero__points li {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--text-sm);
  color: var(--ink-on-brand-2);
}

.hero__points svg {
  color: var(--trust-gold);
  flex: none;
}

.hero__media {
  position: relative;
}

.hero__media picture {
  display: block;
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  border: 1px solid rgb(255 255 255 / 0.14);
}

.hero__image {
  width: 100%;
  height: auto;
  background: none;
}

/* -----------------------------------------------------------------------------
   TRUST STRIP — the company's own three values.
   -------------------------------------------------------------------------- */
.trust {
  background-color: var(--surface-1);
  border-bottom: 1px solid var(--border-subtle);
  padding-block: var(--space-7);
}

.trust__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}

.trust__item {
  display: flex;
  gap: var(--space-4);
  margin: 0;
  align-items: flex-start;
}

.trust__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius-md);
  background-color: var(--accent-wash);
  color: var(--accent-cta);
  border: 1px solid var(--accent-wash-border);
}

.trust__name {
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  margin-bottom: var(--space-1);
}

.trust__blurb {
  font-size: var(--text-sm);
  color: var(--ink-2);
  line-height: var(--leading-normal);
}

/* -----------------------------------------------------------------------------
   STEPS
   -------------------------------------------------------------------------- */
.steps {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-7);
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  counter-reset: s;
}

.steps__item {
  position: relative;
  margin: 0;
  padding: var(--space-6) var(--space-5) var(--space-5);
  background-color: var(--surface-0);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.steps__num {
  position: absolute;
  inset-block-start: calc(var(--space-5) * -1 + 0.4rem);
  inset-inline-start: var(--space-5);
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background-color: var(--accent-cta);
  color: var(--accent-ink);
  font-weight: var(--weight-bold);
  font-size: var(--text-sm);
  box-shadow: var(--shadow-sm);
}

.steps__title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-2);
}

.steps__item p {
  color: var(--ink-2);
  font-size: var(--text-base);
}

/* -----------------------------------------------------------------------------
   BAND — a full-bleed photo section with content over it.
   -------------------------------------------------------------------------- */
.band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background-color: var(--brand-900);
}

.band picture {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.band__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: none;
}

/* The scrim. Without it, white text over a photo is a coin flip — this is the
   difference between "looks moody" and "cannot be read in sunlight". */
.band__overlay {
  position: relative;
  padding-block: clamp(var(--space-8), 6vw, var(--space-10));
  background: linear-gradient(
    100deg,
    rgb(6 19 37 / 0.94) 0%,
    rgb(6 19 37 / 0.84) 45%,
    rgb(6 19 37 / 0.9) 100%
  );
  color: var(--ink-on-brand);
}

.band__grid {
  display: grid;
  gap: var(--space-7);
}

@media (min-width: 52rem) {
  .band__grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-9);
  }
}

.band__half p {
  color: var(--ink-on-brand-2);
  max-width: 44ch;
  margin-top: var(--space-3);
}

.band__icon {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-4);
}

.band__icon--heat {
  background-color: rgb(255 122 92 / 0.16);
  color: #ff9b78;
  border: 1px solid rgb(255 122 92 / 0.3);
}

.band__icon--cool {
  background-color: rgb(90 169 220 / 0.16);
  color: #8ccbf0;
  border: 1px solid rgb(90 169 220 / 0.3);
}

.band__title {
  font-size: var(--text-2xl);
  color: var(--ink-on-brand);
}

.band__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-5);
  font-weight: var(--weight-semibold);
  color: #fff;
  text-decoration: none;
  border-bottom: 2px solid var(--trust-gold);
  padding-bottom: 2px;
}

.band__link:hover {
  color: var(--trust-gold);
}

/* -----------------------------------------------------------------------------
   CTA
   -------------------------------------------------------------------------- */
.cta {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background-color: var(--brand-800);
}

.cta picture {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.cta__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: none;
}

.cta__inner {
  position: relative;
  padding-block: clamp(var(--space-8), 6vw, var(--space-10));
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
}

/* The band-light tile is a pale image, so the scrim here is light and the
   text goes dark — the opposite of the .band treatment. Contrast is decided
   per image, never assumed. */
.cta:not(.cta--plain)::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    180deg,
    rgb(255 255 255 / 0.82) 0%,
    rgb(255 255 255 / 0.9) 100%
  );
}

.cta:not(.cta--plain) .cta__title {
  color: var(--ink-1);
}

.cta:not(.cta--plain) .cta__lead {
  color: var(--ink-2);
}

.cta__title {
  font-size: var(--text-3xl);
  max-width: 20ch;
}

.cta__lead {
  font-size: var(--text-md);
  max-width: 52ch;
  line-height: var(--leading-relaxed);
}

.cta__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: center;
  margin-top: var(--space-2);
}

/* -----------------------------------------------------------------------------
   SMALL PIECES
   -------------------------------------------------------------------------- */
/* The image column is shorter than the prose column it sits beside; aligned to
   the start it leaves a long empty gutter. Centred, it reads as a pair. */
@media (min-width: 60rem) {
  .media-frame {
    align-self: center;
  }
}

.media-frame picture {
  display: block;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border-subtle);
}

.media-frame img {
  width: 100%;
  height: auto;
  background: none;
}

.checklist {
  list-style: none;
  padding: 0;
  margin-top: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.checklist li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin: 0;
  color: var(--ink-2);
}

.checklist svg {
  flex: none;
  margin-top: 2px;
  color: var(--success);
}

.section-more {
  margin-top: var(--space-6);
}

.section-more a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  color: var(--accent-cta);
}

.section-more a:hover {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

.service-card {
  height: 100%;
}

/* The whole card is clickable, but the ACCESSIBLE name and the focus target
   stay on the real link in the heading. No div-with-onclick. */
.service-card__link::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.service-card {
  position: relative;
}

/* -----------------------------------------------------------------------------
   INNER PAGE HEADER
   -------------------------------------------------------------------------- */
.page-head {
  padding-block: var(--space-8) var(--space-7);
  background-color: var(--surface-1);
  border-bottom: 1px solid var(--border-subtle);
}

.page-head__title {
  font-size: var(--text-3xl);
  margin-top: var(--space-3);
  max-width: 22ch;
}

.page-head__lead {
  margin-top: var(--space-4);
  font-size: var(--text-md);
  color: var(--ink-2);
  max-width: var(--measure);
  line-height: var(--leading-relaxed);
}

.crumbs__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
}

.crumbs__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  color: var(--ink-3);
}

.crumbs__item a {
  color: var(--ink-2);
  text-decoration: none;
}

.crumbs__item a:hover {
  text-decoration: underline;
}

.crumbs__sep {
  color: var(--border-strong);
}

/* =============================================================================
   BOOKING PAGE
   ========================================================================== */
.book__stepper {
  margin-bottom: var(--space-6);
}

.book__alert {
  margin-bottom: var(--space-5);
}

.book__picker {
  margin-bottom: var(--space-5);
}

.book__row {
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 38rem) {
  .book__row {
    grid-template-columns: 1fr 1fr;
  }
}

.book__hint {
  margin-top: var(--space-4);
}

.book__subhead {
  font-size: var(--text-lg);
  margin-bottom: var(--space-4);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border-subtle);
}

.book__details .panel__body > * + * {
  margin-top: var(--space-5);
}

.book__details [data-customer] > * + * {
  margin-top: var(--space-4);
}

.slot-field {
  border: none;
  padding: 0;
}

.slot-field .field__hint {
  margin-bottom: var(--space-4);
}

.book__reassure {
  font-size: var(--text-sm);
  color: var(--ink-3);
  margin: 0;
  flex: 1 1 14rem;
}

/* The honeypot. NOT display:none — some bots deliberately skip hidden fields,
   so it is moved off-screen instead, kept out of the tab order, and hidden
   from assistive technology by aria-hidden on the wrapper. */
.trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.book__help {
  margin-top: var(--space-7);
  padding: var(--space-6);
  background-color: var(--surface-1);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}

.book__help-title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-3);
}

.book__help p {
  color: var(--ink-2);
  margin-bottom: var(--space-4);
  max-width: var(--measure);
}

/* =============================================================================
   CONFIRMATION / APPOINTMENT PAGE
   ========================================================================== */
.confirm__banner {
  margin-bottom: var(--space-6);
}

.confirm__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.confirm__title {
  font-size: var(--text-2xl);
  margin-top: var(--space-2);
}

.confirm__actions {
  justify-content: space-between;
}

.confirm__cancel {
  margin: 0;
}

.confirm__cancel-btn {
  color: var(--danger);
}

.confirm__cancel-btn:hover {
  background-color: var(--danger-wash);
}

.confirm__locked {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--ink-2);
  margin: 0;
}

.confirm__locked svg {
  flex: none;
  margin-top: 2px;
  color: var(--warning);
}

.confirm__next {
  margin-top: var(--space-7);
}

.confirm__next-title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-4);
}

.confirm__steps {
  color: var(--ink-2);
  padding-inline-start: var(--space-5);
}

.confirm__steps li {
  margin-bottom: var(--space-3);
}

.confirm__call {
  margin-top: var(--space-5);
  color: var(--ink-2);
}

.confirm__print {
  margin-top: var(--space-6);
}

.confirm code {
  background-color: var(--surface-2);
  padding: 0.15em 0.45em;
  border-radius: var(--radius-sm);
  letter-spacing: 0.08em;
}

/* =============================================================================
   SERVICES / ABOUT / AREA / LEGAL
   ========================================================================== */
.service-group + .service-group {
  margin-top: var(--space-9);
}

.service-detail__media {
  margin-bottom: var(--space-6);
}

.service-detail__para {
  color: var(--ink-2);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  max-width: var(--measure);
}

.service-detail__para + .service-detail__para {
  margin-top: var(--space-4);
}

.service-detail__block {
  margin-top: var(--space-7);
}

.service-detail__block h2 {
  font-size: var(--text-xl);
  margin-bottom: var(--space-4);
}

/* The booking panel follows you down a long service page, but only where
   there is room for it. On a short viewport a sticky panel eats the screen. */
@media (min-width: 60rem) and (min-height: 44rem) {
  .service-aside {
    position: sticky;
    top: calc(var(--header-height, 4.5rem) + var(--space-5));
  }
}

.service-aside__price {
  font-size: var(--text-lg);
  margin-top: var(--space-2);
}

.service-aside__note {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--ink-3);
}

.service-aside__related {
  margin-top: var(--space-6);
  padding: var(--space-5);
  background-color: var(--surface-1);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-subtle);
}

.service-aside__related-title {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--space-3);
}

.service-aside__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.service-aside__list li {
  margin: 0;
  font-size: var(--text-sm);
}

.area__pills .pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.area__pills svg {
  color: var(--accent-cta);
}

.area__counties {
  margin-top: var(--space-7);
}

.area__counties h3 {
  font-size: var(--text-base);
  margin-bottom: var(--space-3);
}

.area__cta {
  margin-top: var(--space-5);
}

.contact__hours {
  margin-top: var(--space-8);
  padding: var(--space-6);
  background-color: var(--surface-1);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  max-width: var(--measure);
}

.contact__hours h2 {
  font-size: var(--text-xl);
  margin-bottom: var(--space-3);
}

.contact__hours p + p {
  margin-top: var(--space-3);
  color: var(--ink-2);
}

.contact__hours svg {
  display: inline;
  vertical-align: -3px;
  color: var(--accent-cta);
}

/* --- Prose (legal pages) -------------------------------------------------- */
.prose h2 {
  font-size: var(--text-xl);
  margin-top: var(--space-7);
  margin-bottom: var(--space-3);
}

.prose h2:first-child {
  margin-top: 0;
}

.prose p {
  color: var(--ink-2);
  line-height: var(--leading-relaxed);
}

.prose p + p {
  margin-top: var(--space-3);
}

.prose__meta {
  margin-top: var(--space-7);
  font-size: var(--text-sm);
  color: var(--ink-3);
}

/* --- 404 ------------------------------------------------------------------ */
.notfound__links {
  list-style: none;
  padding: 0;
  margin: var(--space-6) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.notfound__links li {
  margin: 0;
}

.notfound__links a {
  font-weight: var(--weight-semibold);
}

.notfound__call {
  margin-top: var(--space-6);
  color: var(--ink-2);
}
