/* =========================================================================
   Open Water Plumbing — public site
   =========================================================================
   Palette is taken from the logo's brushed-steel blue gradient, with the
   orange reserved exclusively for conversion actions. That reservation is the
   whole point: on a page where six things could be a button, the one that is
   orange is the one people press.
   ========================================================================= */

/* ---- Fonts: self-hosted so there is no third-party connection on first paint */
@font-face {
  font-family: 'Open Sans';
  src: url('/assets/fonts/opensans-var.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  src: url('/assets/fonts/poppins-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Poppins';
  src: url('/assets/fonts/poppins-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}

/* ---- Tokens ------------------------------------------------------------- */

:root {
  color-scheme: light;

  --navy:      #0b2c4a;
  --brand:     #12496f;
  --brand-2:   #2e7bb0;
  --brand-3:   #6fb1d9;
  --brand-4:   #a8d1ea;
  --accent:    #ea580c;
  --accent-2:  #c2410c;

  --ink:       #0f2438;
  --body:      #45607a;
  --muted:     #6e8aa3;
  --line:      #d8e4ee;
  --line-soft: #e9f0f6;
  --surface:   #ffffff;
  --wash:      #eef4f9;
  --wash-2:    #f6fafd;

  --ok:        #197a4b;
  --warn:      #b45309;
  --danger:    #c0392b;

  --font-head: 'Poppins', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'Open Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* 4/8 spacing rhythm */
  --sp-1: .25rem;  --sp-2: .5rem;   --sp-3: .75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;  --sp-6: 2rem;    --sp-7: 3rem;    --sp-8: 4rem;
  --sp-9: 6rem;

  --r-sm: 8px;  --r-md: 12px;  --r-lg: 18px;  --r-xl: 26px;  --r-pill: 999px;

  --shadow-1: 0 1px 2px rgba(11,44,74,.06), 0 2px 8px rgba(11,44,74,.05);
  --shadow-2: 0 4px 14px rgba(11,44,74,.08), 0 12px 32px rgba(11,44,74,.07);
  --shadow-3: 0 18px 48px rgba(11,44,74,.14);

  --container: 76rem;
  --header-h: 76px;

  /* One motion vocabulary, so nothing on the page moves to a different rhythm */
  --ease-out: cubic-bezier(.16,1,.3,1);
  --t-fast: 160ms;
  --t-mid:  240ms;

  /* Layered z-index scale */
  --z-sticky: 40; --z-header: 60; --z-drawer: 80; --z-modal: 100;
}

/* ---- Reset -------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

/*
 * `overflow-x: clip` rather than `hidden`, and on <html> rather than <body>.
 * `hidden` turns the element into a scroll container, which silently breaks
 * `position: sticky` on the header — and worse, it hides sideways overflow
 * instead of preventing it, so content simply gets cut off the edge of a phone
 * with nothing to scroll to. `clip` contains the damage without either problem;
 * the real causes are fixed below rather than papered over.
 */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  overflow-x: clip;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--body);
  background: var(--surface);
  overflow-x: clip;
}

/*
 * Grid and flex children default to `min-width: auto`, meaning they refuse to
 * shrink below their content's intrinsic size. One image with a width attribute
 * is then enough to push a whole layout wider than the phone. This is the single
 * most common cause of a "responsive" page not fitting, and the fix is global.
 */
.grid > *,
.hero__inner > *,
.page-hero__inner > *,
.cta-band__inner > *,
.form-grid > *,
.header__inner > *,
.entry-card > *,
.assurance__item > *,
.topbar__inner > * {
  min-width: 0;
}

/* Long URLs, emails and code samples must wrap rather than push the page out. */
code, .footer__contact a, .crumbs code, table.data code {
  overflow-wrap: anywhere;
  word-break: break-word;
}

h1, h2, h3, h4, h5 {
  font-family: var(--font-head);
  color: var(--ink);
  line-height: 1.18;
  margin: 0 0 var(--sp-4);
  font-weight: 700;
  letter-spacing: -.015em;
}

h1 { font-size: clamp(2rem, 1.35rem + 2.7vw, 3.4rem); }
h2 { font-size: clamp(1.55rem, 1.15rem + 1.6vw, 2.35rem); }
h3 { font-size: clamp(1.2rem, 1.05rem + .6vw, 1.5rem); }
h4 { font-size: 1.08rem; font-weight: 600; }

p  { margin: 0 0 var(--sp-4); }
p:last-child { margin-bottom: 0; }

a { color: var(--brand); text-decoration-color: color-mix(in srgb, var(--brand) 35%, transparent);
    text-underline-offset: .18em; transition: color var(--t-fast) var(--ease-out); }
a:hover { color: var(--brand-2); }

img, svg, video { max-width: 100%; height: auto; display: block; }
img { background: var(--wash); }

ul, ol { margin: 0 0 var(--sp-4); padding-left: 1.35rem; }
li { margin-bottom: var(--sp-2); }

hr { border: 0; border-top: 1px solid var(--line); margin: var(--sp-7) 0; }

/* Focus is never removed — it is restyled to match the brand. */
:focus-visible {
  outline: 3px solid var(--brand-3);
  outline-offset: 2px;
  border-radius: 4px;
}

::selection { background: var(--brand-4); color: var(--navy); }

.skip-link {
  position: absolute; left: var(--sp-4); top: -100px; z-index: var(--z-modal);
  background: var(--brand); color: #fff; padding: var(--sp-3) var(--sp-5);
  border-radius: 0 0 var(--r-md) var(--r-md); font-weight: 600;
}
.skip-link:focus { top: 0; color: #fff; }

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- Layout ------------------------------------------------------------- */

.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--sp-5); }
.container-narrow { max-width: 46rem; }

.section { padding-block: clamp(3rem, 2rem + 5vw, 5.5rem); }
.section--wash { background: var(--wash); }
.section--wash-2 { background: var(--wash-2); }
.section--navy {
  background: linear-gradient(155deg, var(--navy) 0%, var(--brand) 55%, #17557f 100%);
  color: #cfe3f1;
}
.section--navy h2, .section--navy h3, .section--navy h4 { color: #fff; }

.grid { display: grid; gap: var(--sp-5); }
/*
 * The minimums are tuned against the 76rem container, not picked by eye. At
 * 17rem a .grid-3 row fitted four columns on a 1440px screen, so every six-card
 * section broke into 4 + 2 with a hole beside it; 19rem is the widest value
 * that still resolves to three there and to two on a tablet.
 *
 * They stay `auto-fit` rather than a fixed column count on purpose: these same
 * classes render inside narrow sidebars, where a hard `repeat(3, 1fr)` squeezed
 * a review card down to one word per line.
 */
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 13.5rem), 1fr)); }

.stack > * + * { margin-top: var(--sp-4); }

/*
 * Sidebar that follows the reader on desktop only. Sticky on a phone means the
 * quote form pins itself over the article the visitor is trying to read.
 */
.sticky-side { position: static; }
@media (min-width: 62rem) {
  .sticky-side { position: sticky; top: calc(var(--header-h) + 1rem); }
}

.section-head { max-width: 44rem; margin-bottom: var(--sp-6); }
.section-head.center { margin-inline: auto; text-align: center; }
.section-head p { color: var(--body); font-size: 1.06rem; }

.eyebrow {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-family: var(--font-head); font-weight: 600; font-size: .78rem;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--brand-2); margin-bottom: var(--sp-3);
}
.eyebrow::before {
  content: ''; width: 1.75rem; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--brand-2), var(--brand-4));
}
.section--navy .eyebrow { color: var(--brand-4); }
.eyebrow.center::before { display: none; }

.lead { font-size: clamp(1.05rem, 1rem + .35vw, 1.2rem); color: var(--body); }

/* ---- Buttons ------------------------------------------------------------ */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 48px; padding: var(--sp-3) var(--sp-5);
  font-family: var(--font-head); font-weight: 600; font-size: 1rem;
  border: 1px solid transparent; border-radius: var(--r-pill);
  cursor: pointer; text-decoration: none; text-align: center;
  transition: background var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              box-shadow var(--t-mid) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
/* Press feedback uses transform only — it cannot reflow the surrounding text. */
.btn:active { transform: translateY(1px) scale(.99); }

.btn--primary {
  background: var(--accent); color: #fff;
  box-shadow: 0 4px 14px rgba(234,88,12,.28);
}
.btn--primary:hover { background: var(--accent-2); color: #fff; box-shadow: 0 6px 20px rgba(234,88,12,.34); }

.btn--brand { background: var(--brand); color: #fff; box-shadow: 0 4px 14px rgba(18,73,111,.24); }
.btn--brand:hover { background: var(--navy); color: #fff; }

.btn--ghost { background: transparent; color: var(--brand); border-color: var(--line); }
.btn--ghost:hover { background: var(--wash); color: var(--brand); border-color: var(--brand-3); }

.btn--light { background: rgba(255,255,255,.12); color: #fff; border-color: rgba(255,255,255,.34); }
.btn--light:hover { background: rgba(255,255,255,.2); color: #fff; }

/* Still 44px tall — the visual weight comes down, the tap target does not. */
.btn--sm { min-height: 44px; padding: var(--sp-2) var(--sp-4); font-size: .92rem; }
.btn--block { width: 100%; }
.btn[disabled], .btn[aria-disabled='true'] { opacity: .5; cursor: not-allowed; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

.link-arrow {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-family: var(--font-head); font-weight: 600; text-decoration: none;
  color: var(--brand-2); min-height: 44px;
}
.link-arrow svg { transition: transform var(--t-fast) var(--ease-out); }
.link-arrow:hover svg { transform: translateX(4px); }

/* ---- Header ------------------------------------------------------------- */

.topbar {
  background: var(--navy); color: #b9d4e6;
  font-size: .85rem; padding-block: var(--sp-2);
}
.topbar__inner { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); align-items: center; justify-content: space-between; }
.topbar__facts { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); align-items: center; margin: 0; padding: 0; list-style: none; }
.topbar__facts li { display: flex; align-items: center; gap: var(--sp-2); margin: 0; }
.topbar__facts svg { color: var(--brand-3); flex: none; }
/* inline-flex + nowrap: the number was wrapping under its own icon at the
   right-hand end of the bar. */
.topbar a { color: #dceaf4; text-decoration: none; font-weight: 600;
            display: inline-flex; align-items: center; gap: var(--sp-2); white-space: nowrap; }
.topbar__inner > a { flex: none; }
.topbar a:hover { color: #fff; }
@media (max-width: 60rem) { .topbar { display: none; } }

.site-header {
  position: sticky; top: 0; z-index: var(--z-header);
  background: rgba(255,255,255,.94);
  backdrop-filter: saturate(1.6) blur(12px);
  border-bottom: 1px solid var(--line-soft);
  transition: box-shadow var(--t-mid) var(--ease-out), background var(--t-mid) var(--ease-out);
}
.site-header.is-stuck { box-shadow: var(--shadow-2); background: rgba(255,255,255,.98); }

.header__inner {
  display: flex; align-items: center; gap: var(--sp-5);
  min-height: var(--header-h);
}

.brand { display: flex; align-items: center; gap: var(--sp-2); text-decoration: none; flex: none; }
.brand img { height: 52px; width: auto; background: none; }

/*
 * The logo file is a near-square lockup whose own wordmark is illegible at
 * header size, so the brand name is set in type beside it. It stays visible on
 * phones — a 46px anonymous icon is what made the header look unfinished.
 */
.brand__text {
  display: block; font-family: var(--font-head); font-weight: 700;
  color: var(--navy); font-size: .92rem; line-height: 1.12; letter-spacing: -.02em;
}
.brand__text span {
  display: block; font-size: .58rem; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--brand-2); margin-top: 2px;
}

/* Below 40rem the name wraps to two short lines and the location strapline is
   dropped, so the logo, the call button and the menu button all keep full size. */
@media (max-width: 39.99rem) {
  .brand__text { max-width: 7.5rem; }
  .brand__text span { display: none; }
  .header__inner { gap: var(--sp-3); }
}

@media (min-width: 40rem) {
  .brand { gap: var(--sp-3); }
  .brand__text { font-size: 1.02rem; }
  .brand__text span { font-size: .68rem; letter-spacing: .12em; }
}

/* Very narrow phones: the mark alone, so the call button keeps its room. */
@media (max-width: 22.5rem) {
  .brand__text { display: none; }
  .brand img { height: 46px; }
}

/*
 * The nav sits directly after the brand and takes exactly the width its items
 * need; the free space is collected by the call button's auto margin instead.
 * With `margin-left: auto` here the spare width became margin, the nav box was
 * under-allocated, and the links spilled out over the call button.
 */
.nav { flex: none; }
.header__cta { margin-left: auto; }
.nav__list { display: flex; align-items: center; gap: var(--sp-1); list-style: none; margin: 0; padding: 0; }
.nav__list > li { margin: 0; position: relative; }

.nav__list > li { flex: none; }

.nav__link {
  display: flex; align-items: center; gap: var(--sp-1);
  padding: var(--sp-3) var(--sp-3); min-height: 44px;
  font-family: var(--font-head); font-weight: 600; font-size: .95rem;
  color: var(--ink); text-decoration: none; border-radius: var(--r-sm);
  /* Two-word items like "Service Areas" were wrapping and making the whole
     header two rows tall. */
  white-space: nowrap;
  transition: color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.nav__link:hover { color: var(--brand-2); background: var(--wash); }
.nav__link[aria-current='page'], .nav__item.is-active > .nav__link { color: var(--brand-2); }
.nav__link svg { color: var(--muted); }

/* Mega menu. Hover opens it on pointer devices; the same panel is toggled by
   click/keyboard, so it is not hover-only. */
.mega {
  position: absolute; top: calc(100% + 6px); left: 50%;
  transform: translateX(-50%) translateY(-8px);
  width: min(56rem, 92vw);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-3);
  padding: var(--sp-5); opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--t-mid) var(--ease-out), transform var(--t-mid) var(--ease-out), visibility var(--t-mid);
}
.nav__item:hover > .mega,
.nav__item:focus-within > .mega,
.nav__item.is-open > .mega {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(-50%) translateY(0);
}
.mega__grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: var(--sp-5); }
.mega__col h4 { font-size: .78rem; letter-spacing: .1em; text-transform: uppercase;
                color: var(--brand-2); margin-bottom: var(--sp-3); }
.mega__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.mega__list li { margin: 0; }
.mega__list a {
  display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-2) var(--sp-3);
  min-height: 44px; border-radius: var(--r-sm); text-decoration: none;
  color: var(--ink); font-size: .93rem; font-weight: 600;
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.mega__list a:hover { background: var(--wash); color: var(--brand-2); }
.mega__list svg { color: var(--brand-2); flex: none; }
.mega__foot { margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--line-soft);
              display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; justify-content: space-between; }
.mega__foot p { margin: 0; font-size: .9rem; }

.header__cta { display: flex; align-items: center; gap: var(--sp-3); flex: none; }
.header__phone-short { display: none; }



/* Below this the full number does not fit beside the logo and the menu button,
   so the button becomes "Call" — the tel: link is identical either way. */
@media (max-width: 30rem) {
  .header__phone-full { display: none; }
  .header__phone-short { display: inline; }
}

.nav-toggle {
  display: none; margin-left: auto;
  /* flex: none so it can never be squeezed below a tappable size by a long
     brand name sitting next to it. */
  flex: 0 0 48px;
  width: 48px; height: 48px; align-items: center; justify-content: center;
  background: var(--wash); border: 1px solid var(--line); border-radius: var(--r-md);
  color: var(--brand); cursor: pointer;
}

/* ---- Mobile drawer ------------------------------------------------------ */

.nav__head { display: none; }
.nav__foot { display: none; }
.nav__quick { display: none; }

@media (max-width: 78rem) {
  /* Call button before the menu button — the thumb reaches the right edge
     first, and calling is the action that pays. */
  .nav-toggle { display: inline-flex; order: 3; margin-left: 0; }
  .header__cta { order: 2; }

  /*
   * Full-height panel anchored to the top rather than offset by the header's
   * height. Offsetting depended on --header-h matching the header exactly; the
   * moment it did not, the drawer sat over the logo or left a gap.
   */
  .nav {
    flex: 0 0 auto;
    position: fixed; top: 0; right: 0; bottom: 0; left: auto;
    width: min(23rem, 90vw); height: 100dvh;
    display: flex; flex-direction: column;
    background: var(--surface); border-left: 1px solid var(--line);
    box-shadow: var(--shadow-3); padding: 0;
    overflow-y: auto; overscroll-behavior: contain;
    z-index: var(--z-drawer);
    transform: translateX(100%); visibility: hidden;
    transition: transform var(--t-mid) var(--ease-out), visibility var(--t-mid);
  }
  .nav.is-open { transform: translateX(0); visibility: visible; }

  .nav__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--sp-3); padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--line-soft);
    position: sticky; top: 0; background: var(--surface); z-index: 2;
  }
  .nav__head span {
    font-family: var(--font-head); font-weight: 700; color: var(--navy); font-size: 1rem;
  }
  .nav-close {
    width: 44px; height: 44px; display: grid; place-items: center;
    background: var(--wash); border: 1px solid var(--line); border-radius: var(--r-md);
    color: var(--brand); cursor: pointer;
  }

  .nav__list { flex-direction: column; align-items: stretch; gap: 0; padding: var(--sp-2) var(--sp-4); }
  .nav__link {
    padding: var(--sp-3) var(--sp-2); border-bottom: 1px solid var(--line-soft);
    border-radius: 0; font-size: 1rem; justify-content: space-between;
  }
  .nav__link svg { transition: transform var(--t-fast) var(--ease-out); }
  .nav__item.is-open > .nav__link svg { transform: rotate(180deg); }

  .mega {
    position: static; transform: none; width: auto; box-shadow: none; border: 0;
    padding: var(--sp-2) 0 var(--sp-3) var(--sp-3); opacity: 1; visibility: visible;
    pointer-events: auto; display: none; background: var(--wash-2);
    border-radius: var(--r-md); margin-bottom: var(--sp-2);
  }
  /*
   * The open-state rule up in the desktop block is more specific than `.mega`
   * on its own, so its `translateX(-50%)` survived into the drawer and slid
   * every submenu half its own width off the left edge of the panel. It has to
   * be unset at the same specificity.
   */
  .nav__item:hover > .mega,
  .nav__item:focus-within > .mega,
  .nav__item.is-open > .mega { transform: none; }

  .nav__item.is-open > .mega { display: block; }
  .mega__grid { grid-template-columns: 1fr; gap: var(--sp-3); }
  .mega__foot { display: none; }
  .mega__col h4 { margin-bottom: var(--sp-1); }
  .mega__list a { min-height: 42px; font-size: .9rem; }

  /* Phone number and hours pinned to the bottom of the drawer — the one thing
     a visitor on a phone is most likely to want. */
  .nav__foot {
    display: block; margin-top: auto;
    padding: var(--sp-4) var(--sp-5) calc(var(--sp-5) + env(safe-area-inset-bottom));
    border-top: 1px solid var(--line-soft); background: var(--wash-2);
  }
  .nav__foot .btn { width: 100%; }
  .nav__foot .btn + .btn { margin-top: var(--sp-3); }
  .nav__foot p { font-size: .84rem; color: var(--muted); margin: var(--sp-3) 0 0; text-align: center; }

  .nav__quick { display: block; padding: var(--sp-5) var(--sp-4) var(--sp-4); }
  .nav__quick h4 {
    font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
    color: var(--muted); margin: 0 var(--sp-2) var(--sp-2);
  }
  .nav__quick ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
  .nav__quick li { margin: 0; }
  .nav__quick a {
    display: flex; align-items: center; gap: var(--sp-3);
    min-height: 46px; padding: var(--sp-2) var(--sp-2);
    border-radius: var(--r-sm); text-decoration: none;
    font-family: var(--font-head); font-weight: 600; font-size: .93rem; color: var(--ink);
  }
  .nav__quick a:hover { background: var(--wash); color: var(--brand-2); }
  .nav__quick svg { color: var(--brand-2); flex: none; }
}

/*
 * Scrim.
 *
 * It sits BELOW the header, not above it, and that is deliberate. The drawer is
 * a child of the header, and the header is its own stacking context (sticky
 * with a z-index, plus a backdrop-filter). A z-index on the drawer therefore
 * only orders it against its siblings inside the header — it cannot lift it
 * above an element outside. With the scrim on top, the open menu was painted
 * through 50% navy and came out grey and washed out, which is exactly how it
 * looked on a phone.
 *
 * The header keeps its own dimming layer below, so the result is the same
 * picture: page dimmed, header dimmed, drawer crisp.
 */
.nav-scrim {
  position: fixed; inset: 0; background: rgba(11,44,74,.55);
  z-index: calc(var(--z-header) - 5); opacity: 0; visibility: hidden;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  transition: opacity var(--t-mid) var(--ease-out), visibility var(--t-mid);
}
.nav-scrim.is-open { opacity: 1; visibility: visible; }

/* The header's share of the scrim. A positioned pseudo-element with z-index
   auto paints above the header's own content but below the drawer, which
   carries a positive z-index. */
.site-header::after {
  content: ''; position: absolute; inset: 0;
  background: rgba(11,44,74,.55);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--t-mid) var(--ease-out), visibility var(--t-mid);
}
body.is-nav-open .site-header::after { opacity: 1; visibility: visible; }

/* ---- Hero --------------------------------------------------------------- */

.hero {
  position: relative; overflow: hidden;
  background: linear-gradient(158deg, var(--navy) 0%, var(--brand) 48%, #1a5c8a 100%);
  color: #cfe3f1;
  /* Extra room at the bottom so the animated surface has space of its own and
     does not run into the badges. */
  padding-block: clamp(2.5rem, 1.5rem + 5vw, 5rem) clamp(6rem, 4rem + 7vw, 9rem);
}
.hero::before {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(60rem 32rem at 82% -10%, rgba(111,177,217,.32), transparent 62%),
    radial-gradient(40rem 26rem at 8% 110%, rgba(46,123,176,.28), transparent 60%);
  pointer-events: none;
}
/* ---- Animated water ------------------------------------------------------
   Light rays, drifting bubbles and three tiling wave layers. Every animation
   here is transform or opacity only, so none of it triggers layout or paint —
   it stays on the compositor and costs effectively nothing per frame.
   -------------------------------------------------------------------------- */

.hero-water {
  position: absolute; inset: 0;
  overflow: hidden; pointer-events: none;
  z-index: 0;
}

/* Sunlight through water: soft angled columns drifting at different rates. */
.hero-water__beam {
  position: absolute; top: -30%; height: 160%;
  transform-origin: top center;
  background: linear-gradient(180deg, rgba(168, 209, 234, .22), rgba(168, 209, 234, 0) 72%);
  filter: blur(6px);
  will-change: transform, opacity;
}
.hero-water__beam--a {
  left: 12%; width: 8rem; rotate: 14deg;
  animation: owp-beam 17s ease-in-out infinite;
}
.hero-water__beam--b {
  left: 46%; width: 13rem; rotate: 9deg; opacity: .7;
  animation: owp-beam 23s ease-in-out infinite -6s;
}
.hero-water__beam--c {
  left: 76%; width: 6rem; rotate: 18deg; opacity: .55;
  animation: owp-beam 19s ease-in-out infinite -11s;
}

@keyframes owp-beam {
  0%, 100% { transform: translate3d(0, 0, 0) scaleX(1); opacity: .5; }
  50%      { transform: translate3d(2.5rem, 0, 0) scaleX(1.18); opacity: .95; }
}

/*
 * Bubbles are deliberately not rendered.
 *
 * They were drawn as discrete circles, which on a flat blue field read as dust
 * on the screen rather than as water — small bright dots with hard edges drifting
 * over the headline. The markup stays so the effect can be reinstated if it is
 * ever art-directed properly; nothing renders today.
 */
.hero-water__bubbles { display: none; }

/*
 * Surface. The SVG is 200% wide so a -50% translate lands exactly one tile
 * along and loops with no seam.
 *
 * `max-width: none` is essential: the global `svg { max-width: 100% }` reset was
 * clamping this to the container width, which squashed four tiles into one
 * screen and turned a wave into lumpy blobs.
 */
.hero-water__waves {
  position: absolute; left: 0; bottom: -1px;
  width: 200%; max-width: none;
  height: clamp(56px, 8vw, 104px);
  color: var(--surface);
}
.hero-water--compact .hero-water__waves { height: clamp(38px, 5vw, 62px); }

.hero-water__wave { will-change: transform; }
.hero-water__wave path { fill: currentColor; }

.hero-water__wave--back  { opacity: .28; animation: owp-wave 34s linear infinite; }
.hero-water__wave--mid   { opacity: .55; animation: owp-wave 23s linear infinite reverse; }
.hero-water__wave--front { opacity: 1;   animation: owp-wave 17s linear infinite; }

/* The three layers sit at slightly different heights so the surface reads as
   depth rather than as one path drawn three times. */
.hero-water__wave--back  path { transform: translateY(-14px); }
.hero-water__wave--mid   path { transform: translateY(-6px); }

@keyframes owp-wave {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-1440px, 0, 0); }
}

/* Everything above the water needs to sit on top of it. */
.hero__inner, .page-hero__inner { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  /* The scene stays — it is part of the design — but nothing moves. */
  .hero-water__beam,
  .hero-water__bubbles i,
  .hero-water__wave { animation: none !important; }
  .hero-water__bubbles { display: none; }
}
.hero__inner { position: relative; display: grid; gap: var(--sp-7); align-items: center; }
@media (min-width: 62rem) { .hero__inner { grid-template-columns: 1.08fr .92fr; gap: var(--sp-8); } }

.hero h1 { color: #fff; margin-bottom: var(--sp-4); }
.hero p.lead { color: #c6dcec; max-width: 34rem; }
.hero .eyebrow { color: var(--brand-4); }

.hero__badges { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-5); list-style: none; margin: var(--sp-5) 0 0; padding: 0; }
.hero__badges li { display: flex; align-items: center; gap: var(--sp-2); margin: 0;
                   font-size: .92rem; font-weight: 600; color: #b9d4e6; white-space: nowrap; }
.hero__badges svg { color: var(--brand-4); flex: none; }

.hero__media { position: relative; }
.hero__media img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--r-xl); box-shadow: var(--shadow-3);
  border: 6px solid rgba(255,255,255,.1); background: rgba(255,255,255,.06);
}
/* Anchored inside the photo's lower-left corner rather than hanging off its
   edge, which read as a stray floating box. */
.hero__stat {
  position: absolute; left: var(--sp-4); bottom: var(--sp-4);
  background: var(--surface); color: var(--ink);
  border-radius: var(--r-md); box-shadow: var(--shadow-3);
  padding: var(--sp-3) var(--sp-4); display: flex; align-items: center; gap: var(--sp-3);
  max-width: calc(100% - var(--sp-6));
}
.hero__stat strong { display: block; font-family: var(--font-head); font-size: 1.5rem; line-height: 1; color: var(--brand); }
.hero__stat span { font-size: .82rem; color: var(--muted); }
.hero__stat .icon { color: var(--accent); flex: none; }
@media (max-width: 62rem) { .hero__stat { position: static; margin-top: var(--sp-4); max-width: none; } }

/* Entry-choice cards: residential vs commercial, above the fold. */
.entry-cards { display: grid; gap: var(--sp-4); margin-top: calc(var(--sp-7) * -1); position: relative; z-index: 2; }
@media (min-width: 48rem) { .entry-cards { grid-template-columns: 1fr 1fr; } }

.entry-card {
  display: flex; gap: var(--sp-4); align-items: flex-start;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--sp-5);
  box-shadow: var(--shadow-2); text-decoration: none;
  transition: transform var(--t-mid) var(--ease-out), box-shadow var(--t-mid) var(--ease-out),
              border-color var(--t-mid) var(--ease-out);
}
.entry-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-3); border-color: var(--brand-3); }
.entry-card__icon { transition: transform var(--t-mid) var(--ease-out), box-shadow var(--t-mid) var(--ease-out); }
.entry-card:hover .entry-card__icon { transform: scale(1.06); box-shadow: 0 8px 20px rgba(18,73,111,.26); }
.entry-card:hover .link-arrow svg { transform: translateX(5px); }
.entry-card__icon {
  flex: none; width: 52px; height: 52px; border-radius: var(--r-md);
  display: grid; place-items: center; color: #fff;
  background: linear-gradient(140deg, var(--brand-2), var(--brand));
}
.entry-card--commercial .entry-card__icon { background: linear-gradient(140deg, #f2801f, var(--accent-2)); }
.entry-card h3 { margin-bottom: var(--sp-2); font-size: 1.22rem; }
.entry-card p { font-size: .95rem; margin-bottom: var(--sp-3); }
.entry-card .link-arrow { min-height: 0; }

/* ---- Trust bar ---------------------------------------------------------- */

.trustbar { background: var(--wash); border-block: 1px solid var(--line-soft); padding-block: var(--sp-5); }
.trustbar__list { display: grid; gap: var(--sp-4); list-style: none; margin: 0; padding: 0;
                  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.trustbar__list li { display: flex; align-items: flex-start; gap: var(--sp-3); margin: 0;
                     font-weight: 600; color: var(--ink); font-size: .95rem; line-height: 1.4; }
.trustbar__list svg { margin-top: 2px; }
.trustbar__list svg { color: var(--ok); flex: none; }

.licence-strip {
  display: flex; flex-wrap: nowrap; gap: var(--sp-2); align-items: flex-start;
  font-size: .85rem; color: var(--muted); line-height: 1.5;
}
.licence-strip svg { flex: none; margin-top: 3px; }
.licence-strip strong { color: var(--ink); }

/*
 * On the navy footer the default ink colour (#0f2438) sits on #0b2c4a — about
 * 1.1:1, which is invisible rather than merely low contrast. The licence
 * numbers are a trust signal, so they get full white here.
 */
.site-footer .licence-strip { color: #b7d2e5; }
.site-footer .licence-strip strong { color: #fff; }
.site-footer .licence-strip svg { color: var(--brand-3); }

/* ---- Cards -------------------------------------------------------------- */

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--sp-5);
  box-shadow: var(--shadow-1);
  transition: transform var(--t-mid) var(--ease-out), box-shadow var(--t-mid) var(--ease-out),
              border-color var(--t-mid) var(--ease-out);
}
a.card, .card--link { text-decoration: none; display: flex; flex-direction: column; }
a.card:hover, .card--link:hover { transform: translateY(-5px); box-shadow: var(--shadow-2); border-color: var(--brand-3); }

.card h3 { font-size: 1.12rem; margin-bottom: var(--sp-2); }
.card p { font-size: .94rem; color: var(--body); }
.card .link-arrow { margin-top: auto; padding-top: var(--sp-3); }

.card__icon {
  width: 46px; height: 46px; border-radius: var(--r-md); display: grid; place-items: center;
  background: var(--wash); color: var(--brand-2); margin-bottom: var(--sp-4);
  transition: background var(--t-mid) var(--ease-out), color var(--t-mid) var(--ease-out),
              transform var(--t-mid) var(--ease-out), box-shadow var(--t-mid) var(--ease-out);
}
a.card:hover .card__icon {
  background: linear-gradient(140deg, var(--brand-2), var(--brand)); color: #fff;
  transform: scale(1.06); box-shadow: 0 6px 16px rgba(18,73,111,.28);
}
/* One hover drives every moving part of the card, rather than each piece
   waiting for the pointer to land on it individually. */
a.card:hover .link-arrow { color: var(--brand); }
a.card:hover .link-arrow svg { transform: translateX(5px); }
.card--commercial .card__icon { background: #fdf0e7; color: var(--accent-2); }
.card--commercial:hover .card__icon { background: var(--accent); color: #fff; }

/* overflow:hidden is what makes the hover zoom possible — without it the image
   simply grows past the card's rounded corner. */
.card__media {
  margin: calc(var(--sp-5) * -1) calc(var(--sp-5) * -1) var(--sp-4);
  overflow: hidden; border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.card__media img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
                   border-radius: var(--r-lg) var(--r-lg) 0 0;
                   transition: transform .7s var(--ease-out); }
a.card:hover .card__media img { transform: scale(1.06); }

/* ---- Area chips --------------------------------------------------------- */

.chip-grid { display: flex; flex-wrap: wrap; gap: var(--sp-2); list-style: none; margin: 0; padding: 0; }
.chip-grid li { margin: 0; }
.chip {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: 44px; padding: var(--sp-2) var(--sp-4);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-pill);
  font-size: .92rem; font-weight: 600; color: var(--ink); text-decoration: none;
  transition: background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}
.chip:hover { background: var(--brand); border-color: var(--brand); color: #fff; transform: translateY(-2px); }
.chip:hover svg { color: #fff; }
.chip svg { color: var(--brand-2); flex: none; }
.chip__state { font-weight: 400; color: var(--muted); font-size: .82rem; }
.chip:hover .chip__state { color: rgba(255,255,255,.75); }

/* ---- Breadcrumbs -------------------------------------------------------- */

.crumbs { background: var(--wash-2); border-bottom: 1px solid var(--line-soft); padding-block: var(--sp-3); }
.crumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2);
             list-style: none; margin: 0; padding: 0; font-size: .85rem; }
.crumbs li { display: flex; align-items: center; gap: var(--sp-2); margin: 0; color: var(--muted); }
.crumbs a { color: var(--body); text-decoration: none; display: inline-block; padding-block: var(--sp-1); }
.crumbs a:hover { color: var(--brand-2); text-decoration: underline; }
.crumbs svg { color: var(--line); flex: none; }
.crumbs [aria-current='page'] { color: var(--ink); font-weight: 600; }

/* ---- Page hero (inner pages) -------------------------------------------- */

.page-hero {
  position: relative; overflow: hidden;
  background: linear-gradient(150deg, var(--navy), var(--brand) 70%);
  color: #c6dcec; padding-block: clamp(2.5rem, 2rem + 3.5vw, 4.25rem);
}
.page-hero::before {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(46rem 24rem at 88% -20%, rgba(111,177,217,.3), transparent 62%);
}
.page-hero__inner { position: relative; display: grid; gap: var(--sp-6); align-items: center; }
@media (min-width: 58rem) { .page-hero--media .page-hero__inner { grid-template-columns: 1.15fr .85fr; } }
.page-hero h1 { color: #fff; }
.page-hero p { color: #c6dcec; }
.page-hero img { border-radius: var(--r-lg); box-shadow: var(--shadow-3);
                 aspect-ratio: 4/3; object-fit: cover; width: 100%; }
.page-hero--commercial { background: linear-gradient(150deg, #7c2d12, #b34a10 72%); }
.page-hero--commercial::before { background: radial-gradient(46rem 24rem at 88% -20%, rgba(255,190,140,.26), transparent 62%); }

/* ---- Prose -------------------------------------------------------------- */

.prose { max-width: 44rem; font-size: 1.02rem; }
.prose h2 { margin-top: var(--sp-7); }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: var(--sp-6); }
.prose ul, .prose ol { margin-bottom: var(--sp-5); }
.prose li { margin-bottom: var(--sp-2); }
.prose strong { color: var(--ink); }
.prose .callout {
  background: #fff7ed; border-left: 4px solid var(--accent);
  padding: var(--sp-4) var(--sp-5); border-radius: 0 var(--r-md) var(--r-md) 0;
  color: #7c2d12;
}
.prose img { border-radius: var(--r-md); margin-block: var(--sp-5); }

/* ---- Feature list ------------------------------------------------------- */

.checklist { list-style: none; margin: 0 0 var(--sp-5); padding: 0; display: grid; gap: var(--sp-3); }
.checklist li { display: flex; gap: var(--sp-3); align-items: flex-start; margin: 0; }
.checklist svg { color: var(--ok); flex: none; margin-top: 3px; }

/* ---- Steps -------------------------------------------------------------- */

/*
 * The number badge used to be absolutely positioned against a 2rem top padding
 * while being 2.5rem tall, so it sat on top of the step's heading on every
 * screen. It is a grid cell now: the badge and the copy cannot overlap because
 * they occupy different tracks.
 */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-5); counter-reset: step; }
@media (min-width: 52rem) { .steps { grid-template-columns: repeat(4, 1fr); gap: var(--sp-5) var(--sp-6); } }

.steps li {
  margin: 0; counter-increment: step; position: relative;
  display: grid; grid-template-columns: 44px 1fr; gap: var(--sp-2) var(--sp-4);
  align-items: start;
}
.steps li::before {
  content: counter(step);
  grid-row: 1 / span 2; grid-column: 1;
  width: 44px; height: 44px; border-radius: var(--r-pill);
  display: grid; place-items: center;
  font-family: var(--font-head); font-weight: 700; font-size: 1.1rem;
  background: linear-gradient(140deg, var(--brand-2), var(--brand));
  color: #fff; box-shadow: 0 4px 12px rgba(18,73,111,.22);
}
.steps h3 { grid-column: 2; font-size: 1.05rem; margin: 0; align-self: center; min-height: 44px;
            display: flex; align-items: center; }
.steps p { grid-column: 2; font-size: .93rem; margin: 0; }

/* Stacked on wide screens — four columns of text hanging off a badge reads as
   a ragged list, where a badge over its own paragraph reads as a step. */
@media (min-width: 52rem) {
  .steps li { grid-template-columns: 1fr; gap: var(--sp-3); }
  .steps li::before { grid-row: auto; grid-column: auto; }
  .steps h3, .steps p { grid-column: auto; }
  .steps h3 { min-height: 0; display: block; }
}

/* ---- Reviews ------------------------------------------------------------ */

.review {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: var(--sp-5); box-shadow: var(--shadow-1); display: flex; flex-direction: column;
}
.review__stars { display: flex; gap: 2px; color: #f0a30a; margin-bottom: var(--sp-3); }
.review__stars svg { fill: currentColor; }
.review blockquote { margin: 0 0 var(--sp-4); font-size: .98rem; color: var(--body); }
.review__meta { margin-top: auto; display: flex; align-items: center; gap: var(--sp-3);
                padding-top: var(--sp-3); border-top: 1px solid var(--line-soft); }
.review__avatar {
  width: 38px; height: 38px; border-radius: var(--r-pill); flex: none;
  display: grid; place-items: center; font-family: var(--font-head); font-weight: 700;
  background: var(--wash); color: var(--brand);
}
.review__meta strong { display: block; font-size: .92rem; color: var(--ink); }
.review__meta span { font-size: .8rem; color: var(--muted); }

/* ---- FAQ / accordion ---------------------------------------------------- */

.faq { border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; background: var(--surface); }
.faq details { border-bottom: 1px solid var(--line-soft); }
.faq details:last-child { border-bottom: 0; }
.faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5); min-height: 56px; cursor: pointer;
  font-family: var(--font-head); font-weight: 600; color: var(--ink); font-size: 1.02rem;
  list-style: none; transition: background var(--t-fast) var(--ease-out);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { background: var(--wash-2); }
.faq summary svg { flex: none; color: var(--brand-2); transition: transform var(--t-mid) var(--ease-out); }
.faq details[open] summary svg { transform: rotate(180deg); }
.faq__body { padding: 0 var(--sp-5) var(--sp-5); color: var(--body); }
.faq__body p:last-child { margin-bottom: 0; }

/* ---- CTA band ----------------------------------------------------------- */

.cta-band {
  position: relative; overflow: hidden;
  background: linear-gradient(150deg, var(--navy), var(--brand) 60%, #1a5c8a);
  color: #c6dcec; border-radius: var(--r-xl);
  padding: clamp(2rem, 1.5rem + 3vw, 3.25rem);
}
.cta-band::before {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(34rem 18rem at 92% 0%, rgba(111,177,217,.34), transparent 60%);
}
.cta-band__inner { position: relative; display: grid; gap: var(--sp-5); align-items: center; }
@media (min-width: 54rem) { .cta-band__inner { grid-template-columns: 1.4fr auto; } }
.cta-band h2 { color: #fff; margin-bottom: var(--sp-2); }
.cta-band p { margin: 0; }
/*
 * The two actions are inline-flex, so inside a plain .stack they simply flowed
 * onto the same line and ended up touching. This column owns its own layout.
 */
.cta-band__inner > .stack {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-4);
}
.cta-band__inner > .stack > * + * { margin-top: 0; }
@media (min-width: 54rem) { .cta-band__inner > .stack { align-items: stretch; } }

.cta-band__phone {
  display: inline-flex; align-items: center; gap: var(--sp-3); white-space: nowrap;
  font-family: var(--font-head); font-weight: 700; font-size: 1.5rem;
  color: #fff; text-decoration: none;
}
.cta-band__phone:hover { color: var(--brand-4); }

/* ---- Trust modules (financing / warranty) ------------------------------- */

.assurance { display: grid; gap: var(--sp-4); }
@media (min-width: 46rem) { .assurance { grid-template-columns: 1fr 1fr; } }
.assurance__item {
  display: flex; gap: var(--sp-4); align-items: flex-start;
  background: var(--surface); border: 1px solid var(--line);
  border-left: 4px solid var(--brand-2);
  border-radius: var(--r-md); padding: var(--sp-4) var(--sp-5);
}
.assurance__item--accent { border-left-color: var(--accent); }
.assurance__item svg { flex: none; color: var(--brand-2); margin-top: 3px; }
.assurance__item--accent svg { color: var(--accent); }
.assurance__item h3 { font-size: 1rem; margin-bottom: var(--sp-1); }
.assurance__item p { font-size: .92rem; margin: 0; }

/* ---- Brand logos -------------------------------------------------------- */

.brandstrip { display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
              gap: var(--sp-5) var(--sp-7); }
.brandstrip img {
  height: 40px; width: auto; opacity: .78; background: none;
  filter: grayscale(1) contrast(1.15);
  transition: opacity var(--t-mid) var(--ease-out), filter var(--t-mid) var(--ease-out);
}
.brandstrip img:hover { opacity: 1; filter: none; }
@media (max-width: 40rem) { .brandstrip { gap: var(--sp-5); } .brandstrip img { height: 32px; } }

/* ---- Forms -------------------------------------------------------------- */

.form-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--sp-5); box-shadow: var(--shadow-2);
}
.form-grid { display: grid; gap: var(--sp-4); }
@media (min-width: 40rem) { .form-grid--2 { grid-template-columns: 1fr 1fr; } }

.field label {
  display: block; font-family: var(--font-head); font-weight: 600;
  font-size: .9rem; color: var(--ink); margin-bottom: var(--sp-2);
}
.field .req { color: var(--danger); }
.field input, .field select, .field textarea {
  width: 100%; min-height: 48px; padding: var(--sp-3) var(--sp-4);
  font: inherit; font-size: 1rem; /* 16px stops iOS zooming the page on focus */
  color: var(--ink); background: var(--wash-2);
  border: 1px solid var(--line); border-radius: var(--r-md);
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.field textarea { min-height: 8rem; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { background: var(--surface); border-color: var(--brand-2); }
.field .hint { display: block; font-size: .82rem; color: var(--muted); margin-top: var(--sp-1); }
.field .error { display: block; font-size: .85rem; color: var(--danger); margin-top: var(--sp-1); font-weight: 600; }
.field.has-error input, .field.has-error select, .field.has-error textarea { border-color: var(--danger); background: #fef6f5; }

/* Honeypot: off-screen rather than display:none, which some bots detect. */
.hp { position: absolute !important; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.alert { padding: var(--sp-4) var(--sp-5); border-radius: var(--r-md); margin-bottom: var(--sp-5);
         border-left: 4px solid; font-size: .95rem; display: flex; gap: var(--sp-3); align-items: flex-start; }
.alert svg { flex: none; margin-top: 2px; }
.alert--success { background: #eefaf2; border-color: var(--ok); color: #14532d; }
.alert--error   { background: #fdecec; border-color: var(--danger); color: #7f1d1d; }
.alert--info    { background: var(--wash); border-color: var(--brand-2); color: var(--brand); }

/* ---- Sticky mobile CTA -------------------------------------------------- */

.sticky-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sticky);
  display: none; gap: 1px; background: var(--line);
  padding-bottom: env(safe-area-inset-bottom);
  box-shadow: 0 -6px 24px rgba(11,44,74,.16);
  transform: translateY(100%);
  transition: transform var(--t-mid) var(--ease-out);
}
.sticky-cta.is-visible { transform: translateY(0); }
.sticky-cta a {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 58px; text-decoration: none;
  font-family: var(--font-head); font-weight: 700; font-size: 1rem;
}
.sticky-cta__call { background: var(--accent); color: #fff; }
.sticky-cta__book { background: var(--brand); color: #fff; }

@media (max-width: 60rem) {
  .sticky-cta { display: flex; }
  /*
   * Reserve the bar's height so it never covers the last form field or the
   * footer's contact details. It goes on the footer rather than on the body:
   * padding on the body left a white band under the navy footer, which read as
   * an unfinished page.
   */
  .site-footer { padding-bottom: calc(58px + env(safe-area-inset-bottom)); }
}

/* ---- Footer ------------------------------------------------------------- */

.site-footer { background: var(--navy); color: #9dbdd4; padding-top: var(--sp-8); }
.site-footer h4 { color: #fff; font-size: .82rem; letter-spacing: .1em;
                  text-transform: uppercase; margin-bottom: var(--sp-4); }
.site-footer a { color: #c2dbeb; text-decoration: none; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.footer__grid { display: grid; gap: var(--sp-6); }
@media (min-width: 48rem) { .footer__grid { grid-template-columns: 1.4fr 1fr 1fr 1.2fr; } }
.footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-1); font-size: .93rem; }
.footer__list li { margin: 0; }
.footer__list a { display: inline-block; padding-block: var(--sp-1); }
/*
 * The logo is a dark navy lockup and the footer is navy, so it was very nearly
 * invisible down here. Knocking it out to white keeps one asset doing both jobs
 * rather than shipping a second file that can fall out of step with the first.
 */
.footer__brand img {
  height: 62px; width: auto; background: none; margin-bottom: var(--sp-4);
  filter: brightness(0) invert(1); opacity: .92;
}
.footer__brand p { font-size: .93rem; max-width: 26rem; }
/* The phone and email here are the two links in the footer most likely to be
   tapped on a phone, so they get a real target rather than a line of text. */
.footer__contact { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); font-size: .93rem; }
.footer__contact li { display: flex; gap: var(--sp-3); align-items: flex-start; margin: 0; }
.footer__contact a { display: inline-block; padding-block: var(--sp-1); }
.footer__contact svg { color: var(--brand-3); flex: none; margin-top: 3px; }
.footer__areas { margin-top: var(--sp-7); padding-top: var(--sp-5); border-top: 1px solid rgba(255,255,255,.1); }
.footer__areas h4 { margin-bottom: var(--sp-3); }
.footer__areas ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); font-size: .88rem; }
.footer__areas li { margin: 0; }
.footer__areas a { display: inline-block; padding-block: var(--sp-1); }
.footer__bar {
  margin-top: var(--sp-6); padding-block: var(--sp-4);
  border-top: 1px solid rgba(255,255,255,.1);
  display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-5);
  align-items: center; justify-content: space-between; font-size: .85rem;
}
.footer__copy { margin: 0; }
.footer__credit { margin: 0; color: #7e9fb8; }
.footer__credit a { color: #c2dbeb; text-decoration: none; }
.footer__credit a:hover { color: #fff; text-decoration: underline; }
.footer__credit strong { font-weight: 600; }

/* Three items in the bar, not two: copyright left, credit centred, legal right.
   Below the fold of a phone they stack and centre instead. */
@media (max-width: 48rem) {
  .footer__bar { justify-content: center; text-align: center; }
}

.footer__legal { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); list-style: none; margin: 0; padding: 0; }
.footer__legal li { margin: 0; }
.footer__legal a { display: inline-block; padding-block: var(--sp-1); }

/* ---- Sitemap page ------------------------------------------------------- */

.sitemap-group { margin-bottom: var(--sp-7); }
.sitemap-group h2 { font-size: 1.3rem; padding-bottom: var(--sp-2); border-bottom: 2px solid var(--line); }
.sitemap-cols { columns: 2 14rem; column-gap: var(--sp-6); }
.sitemap-cols ul { list-style: none; padding: 0; margin: 0; }
.sitemap-cols li { break-inside: avoid; margin-bottom: var(--sp-2); font-size: .94rem; }

/* ---- Blog --------------------------------------------------------------- */

.post-meta { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); align-items: center;
             font-size: .87rem; color: var(--muted); margin-bottom: var(--sp-4); }
.post-tag {
  display: inline-flex; align-items: center; padding: var(--sp-1) var(--sp-3);
  background: var(--wash); color: var(--brand-2); border-radius: var(--r-pill);
  font-size: .78rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}

/* ---- Animation ---------------------------------------------------------- */

/*
 * Reveal targets start hidden only when JS is present to reveal them; the
 * .js class is set by the inline head script, so a no-JS visitor sees
 * everything immediately rather than a blank page.
 *
 * The reveal itself is a plain CSS transition switched on by `.is-in`, which
 * site.js adds from an IntersectionObserver. No animation library is involved,
 * because the previous scroll-position library depended on requestAnimationFrame
 * and left whole sections at opacity 0 wherever that ticker was throttled.
 */
.js [data-reveal] {
  opacity: 0;
  /*
   * The scale is deliberately tiny. At .99 an element settles into place
   * instead of sliding into it, which is the difference between motion that
   * reads as considered and motion that reads as a template effect. Opacity
   * finishes before the transform so text is readable while it is still
   * settling — nothing is ever invisible for the full duration.
   */
  transform: translateY(16px) scale(.99);
  transition: opacity .42s var(--ease-out), transform .6s var(--ease-out);
  /*
   * Failsafe. If site.js never runs at all — parse error, blocked file, an
   * extension eating it — nothing would ever add `.is-in` and the page would
   * stay half-empty. This shows everything after four seconds without any JS
   * involved. When the script is working the transition has long finished and
   * these are the values already in effect, so it is invisible.
   */
  animation: owp-reveal-failsafe 0s linear 4s forwards;
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

@keyframes owp-reveal-failsafe { to { opacity: 1; transform: none; } }

/* Hero copy is deliberately not animated: it carries the H1, which is the
   largest contentful paint and the first thing a visitor reads. Only the
   supporting art makes an entrance. */
[data-hero-media] { animation: owp-media-in .85s var(--ease-out) both; }
[data-hero-stat]  { animation: owp-rise .6s var(--ease-out) .3s both; }

/*
 * Scaling UP to 1 rather than down to it. A hero image that starts at 1.03 and
 * shrinks would overflow its grid column for the first few frames and shove the
 * copy beside it; starting under and growing in cannot.
 */
@keyframes owp-media-in {
  from { opacity: 0; transform: translateY(22px) scale(.972); }
  to   { opacity: 1; transform: none; }
}

@keyframes owp-rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js [data-reveal] { opacity: 1 !important; transform: none !important; animation: none !important; }
  [data-hero-media], [data-hero-stat] { animation: none !important; }
  .card__media img, .card__icon, .entry-card__icon { transition: none !important; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

@media print {
  .site-header, .sticky-cta, .nav, .cta-band, .site-footer, .crumbs { display: none !important; }
  body { padding: 0; color: #000; }
}

/* ---- Ask Jack: the assistant ------------------------------------------- */
/*
 * Sits above the sticky mobile CTA rather than beside it: two competing bars
 * at the bottom of a phone screen is how people end up pressing neither.
 */

.chat { position: fixed; right: var(--sp-4); bottom: var(--sp-4); z-index: var(--z-drawer); }

.chat__launcher {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-5);
  border: 0; border-radius: var(--r-pill); cursor: pointer;
  background: var(--brand); color: #fff;
  font-family: var(--font-head); font-weight: 700; font-size: .95rem; line-height: 1;
  box-shadow: var(--shadow-2);
  transition: transform var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.chat__launcher:hover { background: var(--navy); transform: translateY(-2px); }
.chat__launcher:focus-visible { outline: 3px solid var(--brand-3); outline-offset: 3px; }
.chat__launcher-icon { display: flex; }
.chat.is-open .chat__launcher { background: var(--navy); }

/*
 * Sized to the conversation, not to the screen.
 *
 * The panel has no height of its own — it is as tall as what is in it, and it
 * grows as the conversation does, up to the cap. The cap used to be
 * 100vh - 8rem, which on a laptop let an opening greeting alone fill three
 * quarters of the window and cover the site header. Leaving more room above
 * keeps it reading as a panel on the page rather than a takeover of it.
 */
/*
 * This rule has to come first and it is not optional.
 *
 * The panel is hidden with the `hidden` attribute, which the browser styles as
 * display:none — but only in its own stylesheet, and an author `display` beats
 * a UA one. So `display: flex` below silently cancelled it: the panel was
 * visible on page load and the close button appeared to do nothing, because
 * setting hidden=true changed an attribute that no longer had any effect.
 */
.chat__panel[hidden] { display: none; }

.chat__panel {
  position: absolute; right: 0; bottom: calc(100% + var(--sp-3));
  width: min(21.5rem, calc(100vw - var(--sp-6)));
  display: flex; flex-direction: column;
  max-height: min(26rem, calc(100vh - 12rem));
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-3);
  overflow: hidden;
  transform-origin: bottom right;
  animation: chat-in var(--t-mid) var(--ease-out);
}
@keyframes chat-in {
  from { opacity: 0; transform: translateY(8px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

.chat__head {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4);
  background: var(--brand); color: #fff;
}
.chat__title {
  margin: 0; font-family: var(--font-head); font-weight: 700; font-size: 1rem;
}
.chat__note { margin: .3rem 0 0; font-size: .78rem; line-height: 1.45; color: #cfe3f2; }
.chat__close {
  margin-left: auto; flex: none; display: flex; padding: var(--sp-1);
  background: none; border: 0; color: #cfe3f2; cursor: pointer; border-radius: var(--r-sm);
}
.chat__close:hover { color: #fff; background: rgba(255,255,255,.14); }
.chat__close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.chat__log {
  flex: 0 1 auto; min-height: 0; overflow-y: auto;
  padding: var(--sp-3); background: var(--wash-2);
  display: flex; flex-direction: column; gap: var(--sp-2);
  overscroll-behavior: contain;
}

.chat__msg {
  max-width: 90%; padding: var(--sp-3);
  border-radius: var(--r-md); font-size: .87rem; line-height: 1.5;
}
.chat__msg p { margin: 0; }
.chat__msg p + p { margin-top: .6rem; }
.chat__msg--bot { align-self: flex-start; background: var(--surface); border: 1px solid var(--line); color: var(--ink); }
.chat__msg--me  { align-self: flex-end; background: var(--brand); color: #fff; }
.chat__msg--bot a { color: var(--brand); font-weight: 600; word-break: break-word; }

.chat__msg--thinking { display: flex; gap: 5px; align-items: center; padding: var(--sp-4); }
.chat__msg--thinking span {
  width: 7px; height: 7px; border-radius: 50%; background: var(--brand-3);
  animation: chat-dot 1.1s infinite ease-in-out;
}
.chat__msg--thinking span:nth-child(2) { animation-delay: .15s; }
.chat__msg--thinking span:nth-child(3) { animation-delay: .3s; }
@keyframes chat-dot {
  0%, 60%, 100% { opacity: .3; transform: translateY(0); }
  30%           { opacity: 1;  transform: translateY(-3px); }
}

.chat__chips { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.chat__chip {
  width: 100%; text-align: left; cursor: pointer;
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface); border: 1px solid var(--brand-4);
  border-radius: var(--r-md); color: var(--brand);
  font-family: inherit; font-size: .86rem; font-weight: 600; line-height: 1.4;
  transition: background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.chat__chip:hover { background: var(--wash); border-color: var(--brand-2); }
.chat__chip:focus-visible { outline: 2px solid var(--brand-2); outline-offset: 2px; }

.chat__cta {
  align-self: flex-start; text-decoration: none;
  padding: var(--sp-2) var(--sp-4); border-radius: var(--r-pill);
  background: var(--accent); color: #fff;
  font-family: var(--font-head); font-weight: 700; font-size: .85rem;
}
.chat__cta:hover { background: var(--accent-2); }

.chat__composer {
  display: flex; gap: var(--sp-2); align-items: center;
  padding: var(--sp-3); background: var(--surface); border-top: 1px solid var(--line);
}
.chat__input {
  flex: 1 1 auto; min-width: 0;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line); border-radius: var(--r-pill);
  font: inherit; font-size: .9rem; color: var(--ink); background: var(--wash-2);
}
.chat__input:focus { outline: none; border-color: var(--brand-2); background: var(--surface); }
.chat__input:disabled { opacity: .6; }
.chat__send {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; border: 0; border-radius: 50%; cursor: pointer;
  background: var(--brand); color: #fff;
}
.chat__send:hover { background: var(--navy); }
.chat__send:disabled { opacity: .5; cursor: default; }
.chat__send:focus-visible { outline: 2px solid var(--brand-2); outline-offset: 2px; }

.chat__foot {
  margin: 0; padding: 0 var(--sp-4) var(--sp-3);
  background: var(--surface); font-size: .78rem; color: var(--muted);
}
.chat__foot a { color: var(--brand); font-weight: 700; }

/*
 * The sticky Call / Book bar appears at 60rem, so the launcher has to clear it
 * from that width — not from the phone breakpoint. Tying it to 34rem left the
 * button sitting on top of "Book Online" on every tablet.
 */
@media (max-width: 60rem) {
  .chat { bottom: calc(58px + var(--sp-3) + env(safe-area-inset-bottom)); }
}

/* Phone: a sheet rather than a popover, still clear of the bar. */
@media (max-width: 34rem) {
  .chat { right: var(--sp-3); }
  .chat__launcher { padding: var(--sp-3) var(--sp-4); font-size: .9rem; }
  .chat__panel {
    position: fixed; inset: auto var(--sp-3) calc(58px + 4.5rem + env(safe-area-inset-bottom)) var(--sp-3);
    width: auto; max-height: min(26rem, calc(100vh - 14rem));
  }
}

/* The page behind a full-screen sheet should not scroll under it. */
body.is-chat-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .chat__panel { animation: none; }
  .chat__msg--thinking span { animation: none; opacity: .6; }
  .chat__launcher:hover { transform: none; }
}

@media print { .chat { display: none !important; } }

/* ---- Price book --------------------------------------------------------- */

.price-group {
  margin: var(--sp-6) 0 var(--sp-3);
  font-size: 1rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--brand-2);
}
.price-group:first-child { margin-top: var(--sp-2); }

.price-list {
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface); overflow: hidden;
}

.price-row {
  display: flex; gap: var(--sp-5); align-items: flex-start;
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--line-soft);
}
.price-row:first-child { border-top: 0; }
.price-row:nth-child(even) { background: var(--wash-2); }

.price-row__main { flex: 1 1 auto; min-width: 0; }
.price-row__main h4 {
  margin: 0 0 var(--sp-2); font-size: 1rem; line-height: 1.4; color: var(--ink);
}

.price-row__meta { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; }
.price-row__meta li {
  display: flex; gap: var(--sp-2); align-items: flex-start;
  font-size: .85rem; line-height: 1.45; color: var(--muted);
}
.price-row__meta svg { flex: none; margin-top: .15rem; }
.price-row__meta .is-in  { color: var(--ok); }
.price-row__meta .is-out { color: var(--warn); }

/*
 * The price is the thing people came for, so it gets its own column and does
 * not wrap into the description. Fixed width rather than fit-content so the
 * numbers line up down the list and can be compared at a glance.
 */
.price-row__price {
  flex: none; width: 10rem; text-align: right;
  display: flex; flex-direction: column; align-items: flex-end; gap: var(--sp-2);
}
.price-row__price strong {
  font: 700 1.5rem/1 var(--font-head); color: var(--brand); font-variant-numeric: tabular-nums;
}
.price-row__split { font-size: .74rem; color: var(--muted); }

@media (max-width: 48rem) {
  .price-row { flex-direction: column; gap: var(--sp-3); padding: var(--sp-4); }
  .price-row__price {
    width: 100%; text-align: left;
    flex-direction: row; align-items: center; justify-content: space-between;
    gap: var(--sp-3); flex-wrap: wrap;
  }
  .price-row__price strong { font-size: 1.35rem; }
}

/* ---- Quote calculator (staff) ------------------------------------------- */

.quote { padding: var(--sp-7) 0 var(--sp-8); }

.quote__head {
  display: flex; gap: var(--sp-4); align-items: flex-start; justify-content: space-between;
  flex-wrap: wrap; margin-bottom: var(--sp-6);
}
.quote__head h1 { margin: .25rem 0 .5rem; font-size: clamp(1.6rem, 3.5vw, 2.1rem); }
.quote__head .lead { margin: 0; max-width: 38rem; }

/*
 * Two columns, and the result column is sticky. Watching the number move while
 * you change a parameter is the whole point of a live calculator; a figure you
 * have to scroll to find is a figure you check once and then stop trusting.
 */
.quote__layout { display: grid; gap: var(--sp-5); align-items: start; }
@media (min-width: 64rem) {
  .quote__layout { grid-template-columns: minmax(0, 1.5fr) minmax(20rem, 1fr); }
  .quote__result { position: sticky; top: calc(var(--header-h) + var(--sp-4)); }
}

/*
 * On a phone the result column would otherwise sit under four cards of inputs,
 * so the figure is moved above them and pinned. Same reasoning as the desktop
 * sticky: a price you have to scroll to find is a price you stop checking.
 */
@media (max-width: 63.99rem) {
  .quote__result { order: -1; }
  .quote-result { position: sticky; top: var(--sp-2); z-index: var(--z-sticky); }
  .quote-breakdown { margin-top: var(--sp-5); }
}

/*
 * The Call Now / Book Online bar is for customers. On a staff pricing tool it
 * is noise covering the bottom of the screen, so it comes off this page.
 * :has() is not universal — where it is unsupported the bar simply stays,
 * which is untidy rather than broken.
 */
body:has(.quote) .sticky-cta { display: none !important; }

.quote__inputs { display: grid; gap: var(--sp-5); }

.quote-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--sp-5); box-shadow: var(--shadow-1);
}
.quote-card h2 {
  margin: 0 0 var(--sp-4); font-size: 1rem; letter-spacing: .04em;
  text-transform: uppercase; color: var(--brand-2);
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
}
.quote-card__note { margin: var(--sp-3) 0 0; font-size: .84rem; color: var(--muted); line-height: 1.55; }

.quote-grid { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }

.quote-field { display: flex; flex-direction: column; gap: .35rem; min-width: 0; }
.quote-field label { font-size: .78rem; font-weight: 700; letter-spacing: .03em;
                     text-transform: uppercase; color: var(--muted); }
.quote-field input, .quote-field select {
  width: 100%; padding: .7rem .85rem; font: inherit; font-size: .95rem; color: var(--ink);
  background: var(--wash-2); border: 1px solid var(--line); border-radius: var(--r-sm);
}
.quote-field input:focus, .quote-field select:focus {
  outline: none; border-color: var(--brand-2); background: var(--surface);
  box-shadow: 0 0 0 3px rgba(46,123,176,.16);
}

.quote-toggles { list-style: none; margin: var(--sp-4) 0 0; padding: 0; display: grid; gap: var(--sp-2); }
.quote-toggles label {
  display: flex; gap: var(--sp-3); align-items: center; cursor: pointer;
  font-size: .92rem; color: var(--ink);
}
.quote-toggles input { width: 1.1rem; height: 1.1rem; accent-color: var(--brand); }

/* ---- Result ------------------------------------------------------------- */

.quote-result {
  background: linear-gradient(160deg, var(--brand) 0%, var(--navy) 100%);
  color: #fff; border-radius: var(--r-lg); padding: var(--sp-5);
  box-shadow: var(--shadow-2); margin-bottom: var(--sp-5);
}
.quote-result__label {
  margin: 0 0 var(--sp-4); font-size: .74rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--brand-4);
}
.quote-result__range { display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--sp-2); align-items: center; }
.quote-result__range > div { text-align: center; min-width: 0; }
.quote-result__range span { display: block; font-size: .72rem; color: var(--brand-4); margin-bottom: .2rem; }
.quote-result__range strong {
  display: block; font: 700 1.05rem/1.2 var(--font-head);
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
.quote-result__range .is-mid {
  background: rgba(255,255,255,.14); border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4);
}
.quote-result__range .is-mid strong { font-size: 1.75rem; }
.quote-result__foot {
  margin: var(--sp-4) 0 0; padding-top: var(--sp-3); border-top: 1px solid rgba(255,255,255,.18);
  font-size: .76rem; color: var(--brand-4);
  display: flex; gap: var(--sp-3); align-items: center; justify-content: space-between; flex-wrap: wrap;
}
.quote-print {
  display: inline-flex; gap: .4rem; align-items: center; cursor: pointer;
  background: none; border: 0; color: #fff; font: inherit; font-size: .78rem; font-weight: 700;
  text-decoration: underline; padding: 0;
}

/* ---- Breakdown ---------------------------------------------------------- */

.quote-breakdown dl { margin: 0; display: grid; gap: 0; }
.quote-breakdown dl > div {
  display: flex; gap: var(--sp-4); justify-content: space-between; align-items: baseline;
  padding: .65rem 0; border-bottom: 1px solid var(--line-soft);
}
.quote-breakdown dt { margin: 0; font-size: .87rem; color: var(--body); }
.quote-breakdown dd { margin: 0; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.quote-breakdown .is-total { border-bottom: 0; border-top: 2px solid var(--line); margin-top: .25rem; padding-top: .8rem; }
.quote-breakdown .is-total dt { font-weight: 700; color: var(--ink); }
.quote-breakdown .is-total dd { color: var(--brand); font-size: 1.1rem; }

.quote-pill {
  font-size: .72rem; font-weight: 700; letter-spacing: 0; text-transform: none;
  background: var(--wash); color: var(--brand); border-radius: var(--r-pill);
  padding: .25rem .7rem; white-space: nowrap;
}

/* ---- Sanity check ------------------------------------------------------- */

.quote-check { margin-top: var(--sp-4); padding: var(--sp-4); border-radius: var(--r-md); border: 1px solid; }
.quote-check__row {
  display: flex; justify-content: space-between; gap: var(--sp-4);
  padding: .3rem 0; font-size: .9rem;
}
.quote-check__row strong { font-variant-numeric: tabular-nums; }
.quote-check__verdict { margin: .6rem 0 0; font-size: .85rem; font-weight: 700; }
.quote-check.is-ok   { background: #f0faf4; border-color: #a7d9bd; color: var(--ok); }
.quote-check.is-warn { background: #fff8ed; border-color: #f0c88a; color: var(--warn); }
.quote-check.is-off  { background: #fdf1f0; border-color: #eaa9a3; color: var(--danger); }
.quote-check__row span { color: var(--body); }

/* ---- Password gate ------------------------------------------------------ */

.quote-gate {
  max-width: 26rem; margin: var(--sp-7) auto; text-align: center;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--sp-6) var(--sp-5); box-shadow: var(--shadow-2);
}
.quote-gate__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 3.25rem; height: 3.25rem; border-radius: 50%;
  background: var(--wash); color: var(--brand); margin-bottom: var(--sp-3);
}
.quote-gate h1 { font-size: 1.4rem; margin-bottom: .5rem; }
.quote-gate__form { display: flex; gap: var(--sp-2); margin-top: var(--sp-4); }
.quote-gate__form input {
  flex: 1 1 auto; min-width: 0; padding: .75rem .9rem; font: inherit;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--wash-2);
}
.quote-gate__form input:focus { outline: none; border-color: var(--brand-2); background: var(--surface); }
.quote-gate__foot { margin: var(--sp-4) 0 0; font-size: .82rem; color: var(--muted); }

/* A printed quote is a leave-behind: the controls go, the numbers stay. */
@media print {
  .quote__head form, .quote-print, .quote-toggles, .quote__inputs .quote-field select { display: none !important; }
  .quote__layout { grid-template-columns: 1fr !important; }
  .quote-result { background: none !important; color: var(--ink) !important; border: 2px solid var(--ink); }
  .quote-result__label, .quote-result__range span, .quote-result__foot { color: var(--ink) !important; }
  .quote-result__range .is-mid { background: none !important; }
}

/* ---- Quote: the job picker and the sheet -------------------------------- */

.quote-card--lead { border-color: var(--brand-3); box-shadow: var(--shadow-2); }
.quote-field--wide { grid-column: 1 / -1; }

/* The chosen job, as the sheet records it. */
.quote-job {
  margin-top: var(--sp-4); padding: var(--sp-4);
  background: var(--wash); border: 1px solid var(--brand-4); border-radius: var(--r-md);
}
.quote-job__head {
  display: flex; gap: var(--sp-4); justify-content: space-between; align-items: flex-start;
  flex-wrap: wrap;
}
.quote-job__head strong { display: block; color: var(--ink); line-height: 1.4; }
.quote-job__head span { display: block; margin-top: .2rem; font-size: .76rem; color: var(--muted); }
.quote-job__price { text-align: right; flex: none; }
.quote-job__price span { display: block; font-size: .7rem; letter-spacing: .06em;
                         text-transform: uppercase; color: var(--muted); }
.quote-job__price strong {
  font: 700 1.3rem/1.1 var(--font-head); color: var(--brand); font-variant-numeric: tabular-nums;
}
.quote-job__meta { list-style: none; margin: var(--sp-3) 0 0; padding: 0; display: grid; gap: .25rem; }
.quote-job__meta li { font-size: .84rem; line-height: 1.5; color: var(--body); }
.quote-job__meta .is-in  { color: var(--ok); }
.quote-job__meta .is-out { color: var(--warn); }
.quote-job__split {
  margin: var(--sp-3) 0 0; padding-top: var(--sp-2); border-top: 1px dashed var(--brand-4);
  font-size: .8rem; color: var(--muted);
}

/* The whole sheet, collapsed until wanted. */
.quote-sheet summary { cursor: pointer; list-style: none; }
.quote-sheet summary::-webkit-details-marker { display: none; }
.quote-sheet summary h2 { margin: 0; display: flex; align-items: center; gap: var(--sp-2); }
.quote-sheet summary h2::after {
  content: ''; width: .5rem; height: .5rem; border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor; transform: rotate(45deg); margin-left: auto;
  transition: transform var(--t-fast) var(--ease-out);
}
.quote-sheet[open] summary h2::after { transform: rotate(-135deg); }

.quote-sheet__cat {
  margin: var(--sp-5) 0 var(--sp-2); font-size: 1rem; color: var(--ink);
  padding-bottom: .4rem; border-bottom: 2px solid var(--line);
}
.quote-sheet__sub {
  margin: var(--sp-4) 0 var(--sp-2); font-size: .74rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--brand-2);
}
.quote-sheet__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.quote-sheet__list button {
  width: 100%; display: flex; gap: var(--sp-4); justify-content: space-between; align-items: baseline;
  padding: .6rem .75rem; text-align: left; cursor: pointer;
  background: var(--wash-2); border: 1px solid transparent; border-radius: var(--r-sm);
  font: inherit; font-size: .88rem; color: var(--body);
}
.quote-sheet__list button:hover { background: var(--wash); border-color: var(--brand-4); color: var(--ink); }
.quote-sheet__list button:focus-visible { outline: 2px solid var(--brand-2); outline-offset: 1px; }
.quote-sheet__list strong { flex: none; color: var(--brand); font-variant-numeric: tabular-nums; }

/* The comparison lives in the result column now. */
.quote__result .quote-check { margin: 0 0 var(--sp-5); }

@media print {
  .quote-sheet, .quote-card--lead .quote-grid { display: none !important; }
  .quote-job { border: 1px solid var(--ink); background: none; }
}
/* ---- ChatDesk (the external bot) ---------------------------------------- */
/*
 * ChatDesk draws itself inside a shadow root, so its button cannot be reached
 * from this stylesheet. The clearance it needs over the sticky CTA bar is given
 * by a small stylesheet injected into that shadow root instead — see
 * footer.php. What is left here is the host element, which is ours.
 */
@media print { [data-chat-widget] { display: none !important; } }

/* ---- Job application form ----------------------------------------------- */
/*
 * The four numbered steps, the tick tiles and the resume dropzone. Everything
 * here is scoped to the application form rather than added to .field, because
 * .field already sets width:100% and min-height:48px on every input it
 * contains — correct for a text box, and the reason a checkbox has to opt out
 * of it explicitly or it renders as a 48px square block.
 */
.field input[type="checkbox"],
.field input[type="radio"] {
  width: auto; min-width: 0; min-height: 0; padding: 0;
  margin: 0; flex: none; accent-color: var(--brand);
  width: 20px; height: 20px; border-radius: 4px;
}

.apply-step {
  display: flex; align-items: center; gap: var(--sp-3);
  font-size: 1.1rem; margin: var(--sp-7) 0 var(--sp-1);
  padding-top: var(--sp-5); border-top: 1px solid var(--line-soft);
}
.form-card > .apply-step:first-of-type { margin-top: var(--sp-2); padding-top: 0; border-top: 0; }
.apply-step span {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex: none; border-radius: var(--r-sm);
  background: var(--wash); color: var(--brand);
  font-size: .9rem; font-weight: 700;
}
.apply-step__note { font-size: .88rem; color: var(--muted); margin: 0 0 var(--sp-4); }

/* Used where a group of controls needs a label but no single input owns it. */
.field__label {
  display: block; font-family: var(--font-head); font-weight: 600;
  font-size: .9rem; color: var(--ink); margin-bottom: var(--sp-2);
}

/*
 * These three are <label>s inside a .field, and `.field label` already sets
 * display:block with a bolder weight. That rule is (0,1,1) and a bare class is
 * (0,1,0), so it wins on specificity no matter how far down the file this sits
 * — which left the checkbox sitting on top of its own text. Scoping each one
 * under .field takes them to (0,2,0) and puts the flex layout back.
 */
.radio-row { display: flex; gap: var(--sp-3); }
.field .radio-pill {
  flex: 1; display: flex; align-items: center; gap: var(--sp-3);
  min-height: 48px; padding: var(--sp-3) var(--sp-4); margin: 0;
  background: var(--wash-2); border: 1px solid var(--line);
  border-radius: var(--r-md); cursor: pointer; font-weight: 500;
}
.field .radio-pill:has(input:checked) { border-color: var(--brand-2); background: var(--surface); }

.check-grid { display: grid; gap: var(--sp-3); }
@media (min-width: 40rem) { .check-grid { grid-template-columns: 1fr 1fr; } }
.field .check-tile {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: 48px; padding: var(--sp-3) var(--sp-4); margin: 0;
  background: var(--wash-2); border: 1px solid var(--line);
  border-radius: var(--r-md); cursor: pointer;
  font-size: .94rem; font-weight: 500; line-height: 1.3;
}
.field .radio-pill span, .field .check-tile span { font-weight: inherit; }
.field .check-tile:has(input:checked) { border-color: var(--brand-2); background: var(--surface); }

/* Consent wording is a sentence to read, not a field label, so it is not bold. */
.field .check-line {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  margin: 0; cursor: pointer; font-weight: 400;
  font-size: .9rem; line-height: 1.5; color: var(--body);
}
.field .check-line input { margin-top: 2px; }

/*
 * The resume field. The real <input type=file> is hidden inside the label, so
 * the whole panel is the control — a 20px-wide "Choose file" button is a hard
 * target on a phone, and this is the field most applicants use one-handed.
 */
.field .dropzone {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  padding: var(--sp-6) var(--sp-4); text-align: center; cursor: pointer;
  background: var(--wash-2); border: 2px dashed var(--line);
  border-radius: var(--r-lg);
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.field .dropzone:hover, .field .dropzone:focus-within { border-color: var(--brand-2); background: var(--surface); }
.field .dropzone svg { color: var(--brand-2); }
.field .dropzone strong { font-family: var(--font-head); font-size: .95rem; color: var(--ink); }
.field .dropzone input[type="file"] {
  width: 100%; max-width: 20rem; min-height: 0; margin-top: var(--sp-2);
  padding: var(--sp-2); font-size: .85rem; background: none; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .field .radio-pill, .field .check-tile, .field .dropzone { transition: none; }
}
