/* ============================================================================
   Halloway Plumbing & Drain  |  portfolio demonstration build
   Sirocco Innovations  |  slate item 1, Standard tier, six pages
   ----------------------------------------------------------------------------
   HALLOWAY PLUMBING & DRAIN IS A FICTIONAL COMPANY. The name was searched
   against US plumbing businesses and returns nothing. Every phone number is in
   the 555-01XX range reserved for fiction. There is no street address, no
   license number, and no invented review anywhere in this build.

   No web fonts, no CDN, no external requests, no build step, no JavaScript.

   ----------------------------------------------------------------------------
   PALETTE: DEEP HARBOUR. See Landing Pages/PALETTES.md for the library and the
   reasoning. Token names match that file exactly, so the whole scheme swaps by
   replacing the :root block below and nothing else.

   Two earlier attempts are worth knowing about, because both failures are ones
   any build in this repo could repeat:

   1. THE FIRST VERSION WAS COLD AND UGLY. Gray-blue ground, saturated teal, a
      saturated red emergency bar stacked above the header, and a hero that was
      40% empty space because there was no photograph in it. Three stacked bars
      read as a cookie notice, not a business, and red is the grammar of an
      error message.

   2. THE SECOND VERSION WAS WARM AND WRONG. Cream, near black and brass. It
      looked good and it did not read as plumbing. Brass is what a tap is
      plated with, so it signals fixtures, showrooms and luxury remodelling.
      Copper is what a plumber actually cuts and sweats. That scheme is kept in
      PALETTES.md under "Warm Brass" for the trades it does suit.

   THIS VERSION keeps the layout, type and copy of the second and moves only
   the colour: a deep maritime navy base with a true copper accent. Warm metal
   on a cool ground is the contrast that made the brass version feel expensive,
   and the base now says water rather than bakery.

   COLOUR CARRIES MEANING. Copper marks the thing to act on: the call button,
   the emergency route, section rules, active nav. It is never used as
   decoration on something inert.

   ----------------------------------------------------------------------------
   MEASURED CONTRAST, not estimated:

     ink   #131820 on paper 16.62:1    soft  #414a57 on paper  8.37:1
     mute  #5d6875 on paper  5.29:1    accent #9c4f1c on paper 5.52:1
     ink   on white         17.87:1    soft  on white          9.00:1
     mute  on white          5.69:1    accent on white         5.94:1
     ink   on tint          15.28:1    soft  on tint           7.70:1
     mute  on tint           4.87:1    accent on tint          5.08:1
     on-dark #eef3f8 on dark 14.19:1   mute-dark #a2b3c6 on dark 7.39:1
     accent-lt #e59460 on dark 6.59:1  on-dark on deep        16.13:1
     mute-dark on deep       8.40:1    accent-lt on deep       7.49:1
     white on accent 5.92:1            ink on accent-lt        7.41:1

   ONE RESTRICTION. --accent-lt #e59460 is for DARK grounds only. It measures
   2.24:1 on paper and must never carry text on a light background. On light
   grounds the accent is --accent.

   THE HERO WAS MEASURED AGAINST RENDERED PIXELS, NOT AGAINST A FLAT COLOUR.
   Text in the hero sits on a photograph under a gradient scrim, so the real
   background varies pixel by pixel and no swatch can tell you the answer. The
   page was rendered with the hero text hidden, then every pixel behind each
   run of text was sampled and the WORST case taken:

     eyebrow, accent-lt   4.92:1     headline, on-dark      6.82:1
     lede, on-dark 90%    8.99:1     trust lines, on-dark   9.67:1
     trust captions, mute-dark       5.26:1

   --accent-lt was lightened from #e08a4a to #e59460 for exactly this reason.
   On flat grounds the darker value passed comfortably; over the brightest
   part of the photograph it measured 4.45:1, just under AA.

   TYPE. Palatino leads the display stack rather than Georgia, deliberately:
   Georgia is the default system serif and every other build in this repo
   reaches for it first. Palatino Linotype ships on Windows, Palatino on macOS,
   Georgia catches the rest. A serif carries "established, been here since
   2009" in a way a grotesque does not, and it is the single change that moved
   this build furthest from generic. UI, labels and body stay on system sans.
   ========================================================================= */

:root {
  --paper:     #f8f7f4;
  --white:     #ffffff;
  --tint:      #eaeef3;
  --ink:       #131820;
  --soft:      #414a57;
  --mute:      #5d6875;
  --accent:    #9c4f1c;
  --accent-lt: #e59460;   /* dark grounds only, 2.24:1 on paper */
  --dark:      #10233b;
  --deep:      #0a1728;
  --on-dark:   #eef3f8;
  --mute-dark: #a2b3c6;
  --rule:      #dde3ea;
  --rule-soft: #e9edf3;

  --serif: "Palatino Linotype", Palatino, "Book Antiqua", "Iowan Old Style",
           Georgia, serif;
  --sans:  system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
           Arial, sans-serif;

  --wrap: 1140px;
  --gap:  clamp(60px, 8vw, 112px);

  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; background: var(--paper); }

body {
  margin: 0;
  background: var(--paper);
  color: var(--soft);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3 {
  font-family: var(--serif);
  color: var(--ink);
  font-weight: 400;
  line-height: 1.13;
  letter-spacing: -0.017em;
  margin: 0 0 0.45em;
}
h1 { font-size: clamp(2.4rem, 5.6vw, 4rem); }
h2 { font-size: clamp(1.75rem, 3.4vw, 2.6rem); }
h3 { font-size: 1.2rem; letter-spacing: -0.01em; }

h4 {
  font-family: var(--sans); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--mute);
  margin: 0 0 1.1em;
}

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }
a { color: var(--accent); text-underline-offset: 3px; }
img { max-width: 100%; display: block; }
strong { color: var(--ink); font-weight: 600; }

/* ── Layout ──────────────────────────────────────────────────────────────────
   .wrap owns the gutter with a `padding: 0 26px` shorthand. Any class sharing
   an element with it sets padding-top / padding-bottom ONLY. A `padding: X 0`
   on a partner deletes left and right at every width, because the shorthand
   writes all four sides.
   ------------------------------------------------------------------------- */

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 26px; }
.narrow > * { max-width: 660px; }

.section { padding-top: var(--gap); padding-bottom: var(--gap); }
.section--tint { background: var(--tint); }
.section--rule { border-top: 1px solid var(--rule); }

.lede { font-size: 1.2rem; line-height: 1.62; color: var(--soft); }
.muted { color: var(--mute); font-size: 0.94rem; }

/* Section headers. The eyebrow sits on a hairline rule so a heading has a
   visible anchor rather than floating in whitespace. */
/* Sized in rem, not ch. `ch` resolves against the element's OWN font, so a
   60ch cap set on a sans container silently throttles a much larger serif
   heading inside it and breaks two word headings onto two lines. */
.head { max-width: 44rem; margin-bottom: clamp(34px, 4.5vw, 56px); }
.head h2 { margin-bottom: 0.3em; }
.head p { color: var(--mute); margin: 0; font-size: 1.04rem; max-width: 56ch; }

.eyebrow {
  display: block; margin: 0 0 1.4em; padding-bottom: 0.9em;
  border-bottom: 1px solid var(--rule);
  font-family: var(--sans); font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.19em; text-transform: uppercase; color: var(--accent);
}
.head .eyebrow, .narrow .eyebrow { max-width: 22rem; }

/* ── Demo banner ─────────────────────────────────────────────────────────── */

.demonote {
  background: var(--dark); color: rgba(238,243,248,0.72);
  font-size: 0.78rem; line-height: 1.5; text-align: center;
  padding: 7px 26px;
}
.demonote a { color: var(--accent-lt); text-underline-offset: 2px; }
.demonote a:hover { color: #fff; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.55em;
  min-height: 54px; padding: 15px 30px;
  background: var(--accent); color: var(--white);
  font-family: var(--sans); font-size: 1rem; font-weight: 650;
  letter-spacing: -0.005em; text-decoration: none; cursor: pointer;
  border: 1px solid transparent; border-radius: 2px;
  transition: background 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}
.btn:hover { background: #7e3f16; color: var(--white); }
.btn svg { width: 19px; height: 19px; flex: none; }

.btn--outline { background: transparent; color: var(--ink); border-color: #cdd6e0; }
.btn--outline:hover { background: var(--tint); border-color: var(--accent); color: var(--ink); }

.btn--onDark { background: var(--on-dark); color: var(--ink); }
.btn--onDark:hover { background: var(--white); color: var(--ink); }

.btn--ghost { background: transparent; color: var(--on-dark); border-color: rgba(238,243,248,0.4); }
.btn--ghost:hover { background: rgba(238,243,248,0.12); color: var(--on-dark); }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; margin-top: 2em; }

.textlink {
  display: inline-flex; align-items: center; gap: 0.45em; min-height: 44px;
  font-family: var(--sans); font-weight: 650; font-size: 0.97rem;
  color: var(--accent); text-decoration: none;
}
.textlink:hover { text-decoration: underline; }
.textlink svg { width: 15px; height: 15px; flex: none; transition: transform 0.16s ease; }
.textlink:hover svg { transform: translateX(3px); }

/* ── Header ──────────────────────────────────────────────────────────────────
   One bar, not three. The "24 hours" line that used to be its own red strip is
   now a caption under the call button, where it qualifies the action instead
   of shouting above it.
   ------------------------------------------------------------------------- */

.header {
  background: var(--paper); border-bottom: 1px solid var(--rule);
  position: sticky; top: 0; z-index: 40;
}
.header__inner {
  position: relative;
  display: flex; align-items: center; flex-wrap: wrap; gap: 16px;
  min-height: 84px;
}

.brand { display: inline-flex; align-items: center; gap: 12px; margin-right: auto;
         min-height: 44px; text-decoration: none; min-width: 0; }
.brand svg { width: 36px; height: 36px; flex: none; }
.brand b {
  display: block; font-family: var(--serif); font-size: 1.3rem; font-weight: 400;
  color: var(--ink); letter-spacing: -0.015em; white-space: nowrap; line-height: 1.15;
}
.brand small {
  display: block; font-size: 0.71rem; font-weight: 700; letter-spacing: 0.17em;
  text-transform: uppercase; color: var(--mute);
}

.nav { display: flex; gap: 26px; }
.nav a {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: 0.96rem; color: var(--soft); text-decoration: none;
  border-bottom: 2px solid transparent; white-space: nowrap;
}
.nav a:hover { color: var(--ink); }
.nav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--accent); }

.header__call { display: flex; flex-direction: column; align-items: flex-end;
                justify-content: center; min-height: 44px;
                text-decoration: none; min-width: 0; }
.header__call .num {
  display: inline-flex; align-items: center; gap: 9px; min-height: 34px;
  font-size: 1.16rem; font-weight: 700; color: var(--ink);
  letter-spacing: -0.02em; white-space: nowrap;
}
.header__call svg { width: 17px; height: 17px; color: var(--accent); flex: none; }
.header__call .lbl {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--accent); white-space: nowrap;
}
.header__call:hover .num { color: var(--accent); }

/* ── Hero ────────────────────────────────────────────────────────────────────
   Full bleed photograph under a warm gradient scrim. The scrim is warm brown
   rather than neutral black so the photograph's own tone carries through
   instead of being greyed out.

   The four trust lines sit inside the hero. They are the things that actually
   win this job, and in the first version they were 2000px down the page.
   ------------------------------------------------------------------------- */

.hero { position: relative; overflow: hidden; background: var(--dark); }

/* The photograph is a dark, warm interior shot. Lifting it slightly before the
   scrim goes on keeps the chrome and the highlights readable, otherwise the
   right hand side turns to mud and the hero reads as a flat brown panel. */
.hero__bg {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  filter: brightness(1.18) saturate(1.05);
}

/* Warm brown rather than neutral black, so the photograph's own tone carries
   through instead of being greyed out. Heavy on the left where the type sits,
   released on the right so the picture is actually visible. */
/* TWO layers, and the order matters. The first listed paints on top.

   The diagonal is the main scrim: heavy on the left where the type sits,
   released to 24% on the right so the photograph is visible.

   The vertical one exists because the trust strip runs the FULL width of the
   hero, straight across the released side of the diagonal. With a dark
   photograph that was fine. With this one, which is a pale towel across the
   middle and right, the trust captions measured 1.44:1. Anchoring the bottom
   band independently means the strip stays legible whatever photograph is
   dropped in behind it, which is the part that should not be re-litigated
   every time the image changes. */
.hero::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(to top,
      rgba(7,17,30,0.95) 0px, rgba(7,17,30,0.93) 120px,
      rgba(7,17,30,0.62) 190px, rgba(7,17,30,0) 260px),
    linear-gradient(102deg,
      rgba(8,19,33,0.94) 0%, rgba(10,23,40,0.86) 38%,
      rgba(13,29,50,0.56) 68%, rgba(16,35,59,0.24) 100%);
}
.hero__inner {
  position: relative; z-index: 2; max-width: 41rem;
  padding-top: clamp(54px, 6.8vw, 96px);
  padding-bottom: clamp(44px, 5.4vw, 68px);
}
/* Explicit cap so the hairline under the eyebrow is a deliberate length rather
   than whatever the container happens to be. Comfortably fits the label on one
   line at every width. */
.hero .eyebrow { color: var(--accent-lt); border-bottom-color: rgba(229,148,96,0.34); max-width: 26rem; }
.hero h1 { color: var(--on-dark); margin-bottom: 0.34em; }
/* :not(.eyebrow) is load bearing. `.hero p` is specificity (0,0,1,1) and
   `.eyebrow` is (0,0,1,0), so without the exclusion these rules capture the
   eyebrow and silently render it at 1.2rem with a 40ch cap instead of 0.74rem.
   The same trap applies to .pagehead p and .band p below. */
.hero p:not(.eyebrow) { color: rgba(238,243,248,0.9); font-size: 1.2rem; max-width: 40ch; }

.hero__call {
  display: inline-flex; align-items: center; gap: 14px;
  margin-top: 1.9em; padding: 14px 30px 14px 22px;
  background: var(--accent-lt); border-radius: 2px; text-decoration: none;
  transition: background 0.16s ease;
}
.hero__call:hover { background: #eda06e; }
.hero__call svg { width: 30px; height: 30px; color: var(--ink); flex: none; }
.hero__call .num {
  display: block; font-size: clamp(1.5rem, 3.6vw, 1.95rem); font-weight: 700;
  color: var(--ink); letter-spacing: -0.03em; line-height: 1.1;
}
.hero__call .lbl {
  display: block; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.15em;
  text-transform: uppercase; color: rgba(19,24,32,0.72);
}

/* Trust lines, inside the hero, on the scrim. */
.hero__trust {
  position: relative; z-index: 2; list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  border-top: 1px solid rgba(238,243,248,0.18);
}
/* Uniform padding on all four, including the first.

   DELIBERATE, do not "fix" this back. Padding only the items that sit against
   a divider keeps the first item's text on the same left edge as the eyebrow
   and headline above it, but it makes the four boxes internally inconsistent.
   Uniformity was chosen over that alignment. The first item's text now starts
   20px in from the headline, which is intended.

   The vertical dividers disappear at one column, so the padding comes off
   there rather than eating width on a 320px screen. */
.hero__trust > li {
  min-width: 0;
  padding: 20px 20px 26px;
  border-right: 1px solid rgba(238,243,248,0.15);
}
.hero__trust > li:last-child { border-right: 0; }
.hero__trust b {
  display: block; font-family: var(--serif); font-size: 1.28rem; font-weight: 400;
  color: var(--on-dark); letter-spacing: -0.012em; margin-bottom: 2px;
}
.hero__trust span { display: block; font-size: 0.86rem; color: var(--mute-dark); line-height: 1.45; }
/* Two columns. The uniform padding from the base rule carries through, so only
   the dividers and the vertical rhythm change here. */
@media (max-width: 860px) {
  .hero__trust { grid-template-columns: repeat(2, 1fr); gap: 0 20px; }
  .hero__trust > li:nth-child(2n) { border-right: 0; }
  .hero__trust > li { padding-top: 18px; padding-bottom: 18px; }
  .hero__trust > li:nth-child(-n+2) { border-bottom: 1px solid rgba(238,243,248,0.15); }
}

/* One column: no vertical dividers left to clear, so the horizontal padding
   comes off rather than indenting every line on a 320px screen. */
@media (max-width: 460px) {
  .hero__trust { grid-template-columns: 1fr; }
  .hero__trust > li { border-right: 0; padding-left: 0; padding-right: 0; }
  .hero__trust > li:not(:last-child) { border-bottom: 1px solid rgba(238,243,248,0.15); }
}

/* ── Quick routes ────────────────────────────────────────────────────────────
   Three tiles under the hero. Somebody arriving mid emergency reaches the
   right page in one tap without reading a service list.
   ------------------------------------------------------------------------- */

.routes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0;
          list-style: none; margin: 0; padding: 0;
          border: 1px solid var(--rule); background: var(--white); }
.routes > li { min-width: 0; border-right: 1px solid var(--rule); }
.routes > li:last-child { border-right: 0; }
.routes a {
  display: flex; align-items: center; gap: 16px; height: 100%;
  padding: 26px 26px; text-decoration: none;
  border-top: 3px solid transparent;
  transition: background 0.16s ease, border-top-color 0.16s ease;
}
.routes a:hover { background: var(--tint); border-top-color: var(--accent); }
.routes .urgent { border-top-color: var(--accent); }
.routes svg { width: 27px; height: 27px; color: var(--accent); flex: none; }
.routes b { display: block; font-family: var(--serif); font-size: 1.16rem; font-weight: 400;
            color: var(--ink); letter-spacing: -0.012em; }
.routes span { display: block; font-size: 0.9rem; color: var(--mute); line-height: 1.45; }
@media (max-width: 880px) {
  .routes { grid-template-columns: 1fr; }
  .routes > li { border-right: 0; border-bottom: 1px solid var(--rule); }
  .routes > li:last-child { border-bottom: 0; }
  .routes a { padding: 20px 22px; }
}

/* ── Service cards ───────────────────────────────────────────────────────── */

.svcgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0;
           border-top: 1px solid var(--rule); }
/* Flex column with the link pushed to the bottom. Grid items already stretch
   to the tallest in the row, so `margin-top: auto` on the link makes the three
   "read more" links sit on one line regardless of how long each description
   runs. Without it they float directly under text of differing lengths and the
   row looks ragged. */
.svc { min-width: 0; display: flex; flex-direction: column;
       padding: 34px 32px 36px; border-right: 1px solid var(--rule);
       border-bottom: 1px solid var(--rule); }
.svc .textlink { margin-top: auto; align-self: flex-start; }
.svc:last-child { border-right: 0; }
/* Direct child only. `.svc svg` and `.textlink svg` are both specificity
   (0,0,1,1), and this block sits later in the stylesheet, so the descendant
   form won and dressed the arrow inside the card's link as a 28px card icon
   carrying an 18px bottom margin. That is what pushed the arrows up off the
   text. The child combinator scopes this to the icon it was written for. */
.svc > svg { width: 28px; height: 28px; color: var(--accent); margin-bottom: 18px; }
.svc h3 { margin-bottom: 0.4em; }
.svc p { font-size: 0.97rem; color: var(--mute); margin: 0 0 1em; }
@media (max-width: 900px) {
  .svcgrid { grid-template-columns: 1fr; }
  .svc { border-right: 0; padding: 28px 0 30px; }
}

/* ── Statement band ──────────────────────────────────────────────────────────
   One promise, set large. This is the marketing centre of the page: the thing
   a competitor will not say out loud.
   ------------------------------------------------------------------------- */

.statement { background: var(--deep); color: var(--mute-dark); }
.statement .wrap { padding-top: var(--gap); padding-bottom: var(--gap); }
.statement .eyebrow { color: var(--accent-lt); border-bottom-color: rgba(229,148,96,0.32); }
.statement q {
  display: block; quotes: none; max-width: 22ch;
  font-family: var(--serif); font-size: clamp(1.9rem, 4.4vw, 3.1rem);
  line-height: 1.16; letter-spacing: -0.018em; color: var(--on-dark);
}
.statement .after { margin-top: 1.6em; max-width: 46ch; font-size: 1.04rem; }

/* ── Split feature ───────────────────────────────────────────────────────── */

.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(30px, 5vw, 72px);
         align-items: center; }
.split > * { min-width: 0; }
.split--flip .split__media { order: 2; }
/* Two text columns of unequal length should align at the top, not the middle,
   or the two headings sit at different heights and the grid stops reading as a
   grid. Used on the contact page. */
.split--top { align-items: start; }
.split__media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
                    border-radius: 2px; background: var(--tint); }
@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; }
  .split--flip .split__media { order: 0; }
}

/* ── Numbered steps ──────────────────────────────────────────────────────── */

.steps { counter-reset: s; list-style: none; margin: 0; padding: 0;
         display: grid; grid-template-columns: repeat(4, 1fr); gap: 34px 30px; }
.steps > li { counter-increment: s; min-width: 0; padding-top: 20px;
              border-top: 1px solid var(--rule); }
.steps > li::before {
  content: counter(s, decimal-leading-zero); display: block; margin-bottom: 12px;
  font-family: var(--serif); font-size: 1.5rem; color: var(--accent); line-height: 1;
}
.steps h3 { font-size: 1.1rem; margin-bottom: 0.3em; }
.steps p { font-size: 0.95rem; color: var(--mute); margin: 0; }
@media (max-width: 900px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .steps { grid-template-columns: 1fr; } }

/* ── Checklists ──────────────────────────────────────────────────────────── */

.checks { list-style: none; margin: 0; padding: 0;
          display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 40px; }
.checks > li { min-width: 0; position: relative; padding: 13px 0 13px 30px;
               border-bottom: 1px solid var(--rule-soft); font-size: 0.99rem; }
.checks > li::before {
  content: ""; position: absolute; left: 2px; top: 20px;
  width: 12px; height: 7px;
  border-left: 2px solid var(--accent); border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}
@media (max-width: 640px) { .checks { grid-template-columns: 1fr; } }

/* ── Service groups, services hub ────────────────────────────────────────── */

.groups { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(30px, 4vw, 52px); }
.groups > * { min-width: 0; }
.group h3 { display: flex; align-items: center; gap: 11px;
            padding-bottom: 14px; margin-bottom: 6px;
            border-bottom: 1px solid var(--accent); font-size: 1.2rem; }
.group h3 svg { width: 21px; height: 21px; color: var(--accent); flex: none; }
.group ul { list-style: none; margin: 0; padding: 0; }
.group li { padding: 11px 0; border-bottom: 1px solid var(--rule-soft);
            font-size: 0.96rem; color: var(--soft); }
.group li:last-child { border-bottom: 0; }
@media (max-width: 940px) { .groups { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .groups { grid-template-columns: 1fr; } }

/* ── Symptom tables ──────────────────────────────────────────────────────── */

.symptoms { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.symptoms > li {
  padding: 20px 0; border-bottom: 1px solid var(--rule-soft);
  display: grid; grid-template-columns: 19rem 1fr; gap: 8px 40px; align-items: baseline;
}
.symptoms > li > * { min-width: 0; }
.symptoms .sym { font-family: var(--serif); font-size: 1.14rem; color: var(--ink);
                 letter-spacing: -0.012em; }
.symptoms .cause { font-size: 0.97rem; color: var(--mute); }
@media (max-width: 700px) { .symptoms > li { grid-template-columns: 1fr; } }

/* ── Dark bands ──────────────────────────────────────────────────────────── */

.band { background: var(--dark); color: var(--mute-dark); }
.band h2, .band h3, .band strong { color: var(--on-dark); }
.band p:not(.eyebrow) { max-width: 56ch; }
.band .eyebrow { color: var(--accent-lt); border-bottom-color: rgba(229,148,96,0.32); }
.band a { color: var(--accent-lt); }
.band .lede { color: rgba(238,243,248,0.86); }

.assure { list-style: none; margin: 0; padding: 0;
          display: grid; grid-template-columns: repeat(3, 1fr); gap: 40px; }
.assure > li { min-width: 0; padding-top: 22px; border-top: 1px solid rgba(238,243,248,0.2); }
.assure h3 { font-size: 1.2rem; margin-bottom: 0.4em; }
.assure p { font-size: 0.96rem; margin: 0; }
@media (max-width: 780px) { .assure { grid-template-columns: 1fr; gap: 28px; } }

/* ── Page head, inner pages ──────────────────────────────────────────────────
   Inner pages get a compact dark head rather than a full photographic hero, so
   the home page keeps its impact and the service pages get to the content
   fast. Same family, different weight.
   ------------------------------------------------------------------------- */

.pagehead { background: var(--dark); color: var(--mute-dark); }
.pagehead .wrap { padding-top: clamp(48px, 6vw, 78px); padding-bottom: clamp(44px, 5.5vw, 70px); }
.pagehead .eyebrow { color: var(--accent-lt); border-bottom-color: rgba(229,148,96,0.32); max-width: 22rem; }
.pagehead h1 { color: var(--on-dark); margin-bottom: 0.32em; font-size: clamp(2.1rem, 4.6vw, 3.2rem); }
.pagehead p:not(.eyebrow) { color: rgba(238,243,248,0.82); max-width: 56ch; margin: 0; font-size: 1.12rem; }

/* ── Coverage chips ──────────────────────────────────────────────────────── */

.towns { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.towns li { border: 1px solid var(--rule); border-radius: 2px; padding: 9px 17px;
            font-size: 0.94rem; color: var(--soft); background: var(--white); }

/* ── FAQ ─────────────────────────────────────────────────────────────────── */

.faq { max-width: 46rem; border-top: 1px solid var(--rule); }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  list-style: none; cursor: pointer;
  display: flex; justify-content: space-between; align-items: center; gap: 24px;
  padding: 20px 0; min-width: 0;
  font-family: var(--serif); font-size: 1.18rem; color: var(--ink); letter-spacing: -0.012em;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::marker { content: ""; }
.faq summary::after {
  content: ""; flex: none; width: 9px; height: 9px;
  border-right: 2px solid var(--accent); border-bottom: 2px solid var(--accent);
  transform: translateY(-3px) rotate(45deg); transition: transform 0.16s ease;
}
.faq details[open] summary::after { transform: translateY(2px) rotate(-135deg); }
.faq .answer { padding-bottom: 22px; }
.faq .answer p { font-size: 1rem; max-width: 62ch; }

/* ── Contact methods and hours ───────────────────────────────────────────── */

.methods { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.methods li { border-bottom: 1px solid var(--rule-soft); }
.methods a, .methods .row {
  display: flex; align-items: baseline; gap: 22px; min-height: 44px;
  padding: 19px 2px; text-decoration: none; color: var(--ink); min-width: 0;
}
.methods a:hover .m-value { color: var(--accent); }
.m-label { flex: none; width: 5rem; font-size: 0.72rem; font-weight: 700;
           letter-spacing: 0.15em; text-transform: uppercase; color: var(--mute); }
.m-value { font-family: var(--serif); font-size: 1.2rem; letter-spacing: -0.014em;
           transition: color 0.16s ease; min-width: 0; }
.m-value small { display: block; font-family: var(--sans); font-size: 0.9rem;
                 letter-spacing: 0; color: var(--mute); margin-top: 2px; }

.hours { width: 100%; border-collapse: collapse; font-size: 0.97rem; }
.hours caption { text-align: left; caption-side: top; padding-bottom: 12px; }
.hours th, .hours td { text-align: left; padding: 13px 0; border-bottom: 1px solid var(--rule-soft); }
.hours th { font-weight: 600; color: var(--ink); }
.hours td { color: var(--mute); text-align: right; }

.spaced-h { margin-top: 2.6rem; }

/* ── Form ────────────────────────────────────────────────────────────────── */

.formcard { border: 1px solid var(--rule); background: var(--white); }
.formcard__body { padding: clamp(24px, 3vw, 34px); }
.formcard__foot { border-top: 1px solid var(--rule); background: var(--tint);
                  padding: 10px 22px; font-size: 0.92rem; color: var(--mute); }
.formcard__foot a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 700; }

.field { margin-bottom: 19px; }
.field label { display: block; font-size: 0.88rem; font-weight: 650; color: var(--ink); margin-bottom: 7px; }
.field label span { font-weight: 400; color: var(--mute); }
.field input, .field textarea, .field select {
  width: 100%; font: inherit; font-size: 0.98rem; color: var(--ink);
  background: var(--white); border: 1px solid #cdd6e0; border-radius: 2px; padding: 13px 14px;
}
.field textarea { min-height: 140px; resize: vertical; }
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  outline: 2px solid var(--accent); outline-offset: -1px; border-color: transparent;
}
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 19px; }
.pair > * { min-width: 0; }
@media (max-width: 520px) { .pair { grid-template-columns: 1fr; gap: 0; } }

/* ── Footer ──────────────────────────────────────────────────────────────── */

.footer { background: var(--dark); color: var(--mute-dark);
          padding-top: clamp(50px, 6vw, 72px); padding-bottom: 30px; font-size: 0.95rem; }
.footer__grid { display: grid; grid-template-columns: 1.8fr 1fr 1fr; gap: 40px; padding-bottom: 38px; }
.footer__grid > * { min-width: 0; }
.footer h4 { color: var(--on-dark); }
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer strong { color: var(--on-dark); }
.footer a { color: var(--mute-dark); text-decoration: none; }
.footer a:hover { color: var(--on-dark); text-decoration: underline; }

/* Scoped to `li a` and `p a`, never a bare `.footer a`. A bare descendant
   selector is specificity (0,0,1,1) against `.brand` at (0,0,1,0), so a
   display rule would capture the footer logo link and stack its children
   vertically on mobile only. */
.footer li a, .footer p a { display: inline-block; padding: 10px 0; }   /* 45px */

.footer__brand b { display: block; font-family: var(--serif); font-weight: 400;
                   color: var(--on-dark); font-size: 1.3rem; letter-spacing: -0.015em;
                   margin-top: 12px; }
.footer__bar { border-top: 1px solid rgba(238,243,248,0.16); padding-top: 22px;
               display: flex; flex-wrap: wrap; justify-content: space-between;
               gap: 8px 24px; font-size: 0.87rem; color: #7d8b9c; }

/* Without these the three footer columns hold their ratio all the way down and
   the narrow third column pushes "Drains and sewers" past the right edge. */
@media (max-width: 720px) {
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 30px; }
  .footer__brand { grid-column: 1 / -1; }
}
@media (max-width: 440px) {
  .footer__grid { grid-template-columns: 1fr; }
}

/* ── Focus ───────────────────────────────────────────────────────────────── */

a:focus-visible, button:focus-visible, summary:focus-visible {
  outline: 3px solid var(--accent); outline-offset: 2px;
}
.band a:focus-visible, .footer a:focus-visible, .hero a:focus-visible,
.pagehead a:focus-visible, .statement a:focus-visible { outline-color: var(--accent-lt); }

.skip { position: absolute; left: -9999px; top: 0; z-index: 70;
        background: var(--ink); color: var(--paper); padding: 13px 20px; }
.skip:focus { left: 0; color: var(--paper); }

/* ── Wrapping guards ─────────────────────────────────────────────────────────
   Dots and @ signs are not line-break opportunities, so an email address is
   one unbreakable atom. Flex and grid children default to `min-width: auto`
   and cannot shrink below their content, which gives the page a hard minimum
   width, visible as a pale strip down the right edge on a phone.

   `anywhere`, not `break-word`. Only `anywhere` reduces an element's MINIMUM
   width, which is the value a grid track consults. `break-word` looks like a
   fix and changes nothing.
   ------------------------------------------------------------------------- */

a[href^="mailto:"], a[href^="tel:"], a[href^="http"], .m-value {
  overflow-wrap: anywhere;
}

/* ── Fixed call bar, phones only ─────────────────────────────────────────────
   Below 780px a call button is pinned to the bottom of the viewport on every
   page, so the number is reachable without scrolling however far down somebody
   has read. `body` gets matching bottom padding at the same breakpoint so the
   bar never covers the last line of the footer.
   ------------------------------------------------------------------------- */

.callbar { display: none; }

@media (max-width: 780px) {
  body { padding-bottom: 76px; }
  .callbar {
    display: flex; align-items: center; gap: 10px;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    padding: 11px 14px calc(11px + env(safe-area-inset-bottom, 0px));
    background: var(--paper); border-top: 1px solid var(--rule);
    box-shadow: 0 -4px 20px rgba(10,23,40,0.14);
  }
  .callbar a {
    flex: 1 1 0; min-width: 0;
    display: inline-flex; align-items: center; justify-content: center; gap: 9px;
    min-height: 52px; padding: 13px 10px; border-radius: 2px;
    text-decoration: none; font-size: 1.02rem; font-weight: 700; white-space: nowrap;
  }
  .callbar .c-call { background: var(--accent); color: #fff; }
  .callbar .c-emg { background: transparent; color: var(--ink);
                    border: 1px solid #cdd6e0; flex: 0 1 auto;
                    padding-left: 18px; padding-right: 18px; }
  .callbar svg { width: 18px; height: 18px; flex: none; }
}

/* ── Mobile menu ─────────────────────────────────────────────────────────── */

.mobmenu { display: none; }

@media (max-width: 940px) {
  .nav { display: none; }
  .mobmenu { display: block; }

  /* The phone sits to the LEFT of the menu button wherever the menu exists.
     Both are direct children of .header__inner, so order alone does it, and
     the brand keeps order 0 with its margin-right:auto so it still holds the
     left edge. */
  .header__call { order: 1; }
  .mobmenu { order: 2; }

  /* One height for the menu button whatever the label does: 46 with the word,
     46 as an icon. Vertical padding goes to zero and min-height decides, and
     the .header prefix is there so this beats the padding shorthand further
     down this block, which is the same specificity and would win on order. */
  .header .mobmenu > summary { padding-top: 0; padding-bottom: 0; }
  .mobmenu > summary {
    list-style: none; cursor: pointer;
    display: inline-flex; align-items: center; gap: 9px; min-height: 46px;
    padding: 11px 17px; background: transparent;
    border: 1px solid #cdd6e0; border-radius: 2px;
    color: var(--ink); font-size: 0.94rem; font-weight: 650; white-space: nowrap;
  }
  .mobmenu > summary::-webkit-details-marker { display: none; }
  .mobmenu > summary::marker { content: ""; }
  .mobmenu > summary svg { width: 18px; height: 18px; }
  .mobmenu[open] > summary { background: var(--tint); border-color: var(--accent); }
  .mobmenu > ul {
    position: absolute; right: 26px; top: calc(100% + 12px); z-index: 60;
    min-width: 244px; max-width: calc(100vw - 52px);
    margin: 0; padding: 8px; list-style: none;
    background: var(--white); border: 1px solid var(--rule);
    box-shadow: 0 6px 14px rgba(10,23,40,0.07), 0 22px 48px rgba(10,23,40,0.18);
  }
  .mobmenu a { display: block; padding: 13px 15px; font-size: 0.97rem;
               color: var(--soft); text-decoration: none; }
  .mobmenu a:hover { background: var(--tint); color: var(--ink); }
  .mobmenu a[aria-current="page"] { background: var(--tint); color: var(--ink); font-weight: 650; }

  .header__inner { min-height: 74px; }
}

/* Below 600px the header number drops to its label only, so the row still fits
   at 320px. The fixed call bar is carrying the number by then. */
@media (max-width: 600px) {
  .header__call .num { font-size: 1rem; }
  .header__call .lbl { display: none; }
  .brand b { font-size: 1.14rem; }
  .brand svg { width: 32px; height: 32px; }
}

/* Below 560px the header runs out of room and the call link wraps onto a row
   of its own, where it reads as a stray icon rather than a control. It is
   dropped entirely instead, because the fixed call bar is pinned to the bottom
   of the screen at every width under 780px and is carrying the number far more
   prominently than the header ever did. Removing it leaves a clean two item
   header: the wordmark and Menu. */
@media (max-width: 560px) {
  .header__call { display: none; }
}

/* Below 440px the Menu button dropped to a second row, taking the header to
   109px on a sticky bar. Measured at 320px: the brand alone is 202px wide
   against 268px of usable width, and the labelled menu button needs about
   95 more.

   Two changes, both needed. The brand loses its sub label and drops a size,
   which takes it to about 150. The menu button keeps its icon and loses the
   word, which takes it to 46. Together that is roughly 208 against 268, with
   room to spare for a wider font stack. */
@media (max-width: 440px) {
  .brand small { display: none; }
  .brand b { font-size: 1.08rem; }
  .brand svg { width: 30px; height: 30px; }
  .header__inner { gap: 10px; }
  .mobmenu > summary { padding-left: 12px; padding-right: 12px; gap: 0; }
  .mobmenu > summary .lbl { display: none; }
}

@media (max-width: 420px) {
  .actions .btn { flex: 1 1 100%; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
