/* ===========================================================================
   Advanced Building Consultants (ABC Inspections) - Tauranga, Bay of Plenty
   ---------------------------------------------------------------------------
   Pre-purchase building inspections. Rebuilt 2026-08-31 from the live
   concrete5 site at www.abcinspections.co.nz; structure and components come
   from the fleet template (valmartanksolutions), the palette does not.

   THE LOGO DECIDES THE PALETTE. The client's 2026-08-26 artwork is a house
   outline in a COPPER gradient beside an "ABC" wordmark, supplied on two
   grounds - white (charcoal wordmark) and black (white wordmark). So: white
   header carrying the white-ground lockup, warm near-black dark surfaces
   carrying the black-ground one, and copper as the single accent. Nothing is
   invented; both files are the client's own.

   Sampled from the artwork (build/images.py): copper #B07850 is the densest
   bin, the ground is a warm near-black. Every ratio below is MEASURED with the
   WCAG formula, and the numbers decide which token is allowed to carry text:

       white on #B07850  =  3.06:1   <- the raw logo copper FAILS AA for text
       white on #8C5A3C  =  5.76:1   the copper that carries WHITE text
       white on #7A4E33  =  7.08:1   hover/pressed on a copper surface
       #8C5A3C on white  =  5.76:1   copper TEXT on a light surface
       #D9A57E on ink    =  8.12:1   copper TEXT on a dark surface
       ink on white      = 17.70:1
       muted on white    =  7.33:1   (6.64:1 on the band, still comfortably AA)

   So the raw logo copper is reserved for GRAPHICS - rules, icon discs, the
   button glyph - and never carries type. Type on copper uses the darker step.

   The token NAMES are inherited from the fleet template (--brand / --red)
   because around 200 rules downstream reference them. This site has ONE
   accent, so both families resolve to the same copper system.
   =========================================================================== */

:root {
  --brand:        #B07850;   /* logo copper. Graphics only - never type on white */
  --brand-bg:     #8C5A3C;   /* copper surface that carries WHITE text - 5.76:1 */
  --brand-dk:     #7A4E33;   /* hover/pressed on a copper surface - white on it 7.08:1 */
  --brand-lt:     #D9A57E;   /* copper TEXT on dark - 8.12:1 on --ink */
  --brand-dkr:    #8C5A3C;   /* copper TEXT on white - 5.76:1 */
  --brand-soft:   #F5EBE3;   /* pale copper wash - tints, icon discs, hover fills */

  /* The template's second family. This site has ONE accent, so these alias the copper. */
  --red:          #B07850;
  --red-bg:       #8C5A3C;
  --red-dk:       #7A4E33;
  --red-soft:     #F5EBE3;

  --ink:          #1A1816;   /* the logo's own warm near-black - 17.70:1 on white */
  --ink-2:        #26221E;   /* dark panels, the enquiry band and the footer */
  --ink-0:        #121110;   /* the utility strip and the footer's bottom bar */
  --muted:        #5C554E;   /* secondary copy - 7.33:1 on white, 6.64:1 on the band */
  --line:         #E4DED7;
  --band:         #F7F3EF;   /* warm off-white - the light band that carries most sections */
  --white:        #ffffff;
  --shadow:       0 6px 24px rgba(26,24,22,.08), 0 2px 6px rgba(26,24,22,.05);
  --shadow-md:    0 14px 40px rgba(26,24,22,.12), 0 3px 10px rgba(26,24,22,.06);
  --shadow-lg:    0 26px 70px rgba(26,24,22,.2);

  --wrap:         1180px;
  --pad:          clamp(20px, 4vw, 34px);
  --sec-y:        clamp(60px, 7.4vw, 100px);
  --radius:       8px;
  --radius-sm:    5px;

  --hdr-h:        88px;
  --hdr-h-stuck:  70px;
  --util-h:       40px;

  /* Float bar (fleet component) - overridable from /dash via /api/config.
     Re-themed, not pasted. The fleet default is white icons on --brand, which
     here would be white on #B07850 = 3.06:1, under the 3:1 WCAG 1.4.11 wants
     for a UI component and well under what an icon needs to read. So the bar
     uses the darker button copper (white on it 5.76:1) and matches the primary
     CTA, which is the same action. */
  --fb-bg:        var(--brand-bg);
  --fb-icon:      #ffffff;
  --fb-hover-bg:  var(--ink);
  --fb-hover-icon:#ffffff;
}
/* --------------------------------------------------------------- fonts
   Self-hosted, latin subset only: 43 kB for the pair against a Google Fonts
   round trip plus a render-blocking stylesheet. The reference pairs Mulish 800
   for headings with Red Hat Text for body, and that pairing is most of why it
   reads the way it does. */
@font-face {
  font-family: 'Mulish';
  src: url('/assets/fonts/mulish-800-latin.woff2') format('woff2');
  font-weight: 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Red Hat Text';
  src: url('/assets/fonts/redhattext-400-latin.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Red Hat Text';
  src: url('/assets/fonts/redhattext-700-latin.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}

/* --------------------------------------------------------------- reset */
*, *::before, *::after { box-sizing: border-box; }
/* scroll-padding-top clears the sticky header on an in-page jump. Without it #enquire lands
   with the form's first label hidden behind the header, which reads as a broken anchor. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: calc(var(--hdr-h) + 16px); }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
body {
  margin: 0;
  font-family: 'Red Hat Text', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: 17px;
  line-height: 1.68;
  color: var(--ink);
  background: var(--white);
  /* NOT overflow-x: hidden. That hides a real horizontal overflow rather than
     fixing it - on the last site in this fleet it concealed a 156px blowout on
     a 375px viewport and the page looked perfect. Measure
     documentElement.scrollWidth against clientWidth instead. */
}
img, svg, video { max-width: 100%; height: auto; display: block; }
/* <picture> defaults to display:inline, so it does not establish a block box for the <img>
   inside it. Every photograph on this site is wrapped in one (WebP source + JPEG fallback),
   so leaving it inline puts an inline wrapper around a block image in a grid cell - which
   creates baseline gaps under the image and makes width/aspect-ratio resolve against the
   wrong box. Set it once here rather than per component. */
picture { display: block; }
a { color: var(--brand-dkr); }
h1, h2, h3, h4 {
  font-family: 'Mulish', 'Red Hat Text', system-ui, sans-serif;
  font-weight: 800;
  line-height: 1.14;
  letter-spacing: -.012em;
  margin: 0 0 .5em;
  text-wrap: balance;
}
p { margin: 0 0 1.05em; }
p:last-child, ul:last-child, ol:last-child { margin-bottom: 0; }
ul, ol { margin: 0 0 1.05em; padding-left: 1.25em; }
li { margin-bottom: .4em; }
:focus-visible { outline: 3px solid var(--brand); outline-offset: 3px; }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: #fff; padding: 12px 18px;
}
.skip:focus { left: 0; }

/* --------------------------------------------------------------- buttons
   🔴 Components must beat prose. `.prose a` is (0,1,1) and `.btn` is (0,1,0),
   so a body-link colour rule silently wins over a button's own colour - which
   on prestigepainters rendered every in-prose CTA at 1.00:1, invisible, and
   only looked right on hover. Body link rules below are scoped with
   :not(.btn):not(.tlink) for exactly that reason. */
.btn {
  display: inline-flex; align-items: center; gap: 11px;
  padding: 15px 26px;
  background: var(--ink); color: #fff;
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 15px;
  letter-spacing: .04em; text-transform: uppercase;
  text-decoration: none; border: 2px solid var(--ink); border-radius: var(--radius);
  cursor: pointer; transition: background .16s, color .16s, border-color .16s, transform .16s;
}
/* The ring-and-arrow glyph, drawn in CSS rather than shipped as an <svg> in
   every button, so a colour change is one rule. */
/* 🔴 A CSS mask uses the ALPHA channel only - colour is irrelevant. Drawing a white arrow on
   top of a black circle therefore masks NOTHING out and renders as a solid disc, which is exactly
   what shipped on the first deploy. The arrow has to be a hole: one path, fill-rule="evenodd", so
   the inner subpath subtracts from the outer one. */
.btn::before {
  content: ''; flex: 0 0 auto; width: 19px; height: 19px; border-radius: 50%;
  background: var(--brand);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill-rule='evenodd' d='M12 1a11 11 0 1 0 0 22 11 11 0 0 0 0-22zM10 7l5 5-5 5z'/></svg>") center/contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill-rule='evenodd' d='M12 1a11 11 0 1 0 0 22 11 11 0 0 0 0-22zM10 7l5 5-5 5z'/></svg>") center/contain no-repeat;
}
/* PRIMARY = COPPER. The logo has a single accent, so the primary button carries it. --brand-bg
   (#8C5A3C) rather than the raw logo copper #B07850, because white on the raw copper is 3.06:1
   and fails AA for normal-size text; --brand-bg is 5.76:1 and reads as the same colour. */
.btn { background: var(--brand-bg); color: #fff; border-color: var(--brand-bg); }
.btn::before { background: #fff; }
.btn:hover {
  background: var(--brand-dk); border-color: var(--brand-dk);
  transform: translateY(-2px); box-shadow: var(--shadow-md);
}
.btn:hover::before { background: #fff; }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--ghost::before { background: var(--brand-dkr); }
.btn--ghost:hover { background: var(--ink); border-color: var(--ink); color: #fff; }
.btn--ghost:hover::before { background: var(--brand-lt); }
/* Ghost button on a DARK surface (hero, enquiry band): white type and a translucent rule. */
.hero .btn--ghost, .enq .btn--ghost, .sec--dark .btn--ghost { color: #fff; border-color: rgba(255,255,255,.42); }
.hero .btn--ghost::before, .enq .btn--ghost::before, .sec--dark .btn--ghost::before { background: var(--brand-lt); }
.hero .btn--ghost:hover, .enq .btn--ghost:hover, .sec--dark .btn--ghost:hover { background: #fff; border-color: #fff; color: var(--ink); }
.hero .btn--ghost:hover::before, .enq .btn--ghost:hover::before, .sec--dark .btn--ghost:hover::before { background: var(--ink); }
.btn--light { background: #fff; color: var(--ink); border-color: #fff; }
.btn--light::before { background: var(--brand-dkr); }
.btn--light:hover { background: var(--ink); border-color: var(--ink); color: #fff; }
.btn--light:hover::before { background: var(--brand-lt); }
.btn--full { width: 100%; justify-content: center; }
.btn--sm { padding: 11px 18px; font-size: 13.5px; }

/* Inline text link. */
.tlink {
  color: var(--brand-dkr); font-weight: 700; text-decoration: none;
  border-bottom: 2px solid rgba(176,120,80,.45);
}
.tlink:hover { border-bottom-color: var(--brand); }

.eyebrow {
  display: inline-block;
  font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 12.5px; letter-spacing: .15em; text-transform: uppercase;
  color: var(--brand-dkr); margin-bottom: 13px;
}
/* A short copper rule under the eyebrow. Cheap, and it is the one place the raw logo copper can
   be used at full strength on white without a contrast problem, because it is a graphic and not
   text. */
.eyebrow::after {
  content: ''; display: block; width: 34px; height: 3px; border-radius: 2px;
  background: var(--brand); margin-top: 9px;
}
.sec__head--c .eyebrow::after, .center .eyebrow::after { margin-left: auto; margin-right: auto; }

/* --------------------------------------------------------------- utility bar
   Dark, not brand-coloured. This is a white-dominant design, and a full-width copper strip
   sitting directly above a copper-and-charcoal logo makes the header read as two competing
   bands. */
.util { background: var(--ink-0); color: rgba(255,255,255,.8); border-bottom: 1px solid rgba(255,255,255,.06); }
.util__in {
  min-height: var(--util-h);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  font-size: 13px;
}
.util__tag { display: inline-flex; align-items: center; gap: 8px; }
.util__tag svg { color: var(--brand-lt); flex: 0 0 auto; }
.util__right { display: inline-flex; align-items: center; gap: 20px; }
.util__hrs { color: rgba(255,255,255,.6); }
.util__phone {
  display: inline-flex; align-items: center; gap: 8px;
  color: #fff; text-decoration: none; white-space: nowrap;
  font-family: 'Mulish', sans-serif; font-weight: 800; letter-spacing: .02em;
}
.util__phone svg { color: var(--brand-lt); }
.util__phone:hover { color: var(--brand-lt); }
.util__phone:hover svg { color: #fff; }
@media (max-width: 900px) { .util__hrs { display: none; } }
@media (max-width: 700px) {
  .util__tag { display: none; }
  .util__in { justify-content: center; }
}

/* --------------------------------------------------------------- header */
/* WHITE header, as the reference has it. The badge is white-ground artwork with a charcoal
   wordmark, so white is the surface it was drawn for. */
.hdr {
  position: sticky; top: 0; z-index: 90;
  background: #fff; border-bottom: 1px solid var(--line);
  transition: box-shadow .2s;
}
.hdr[data-stuck] { box-shadow: 0 4px 22px rgba(18,17,16,.12); }
.hdr__in {
  min-height: var(--hdr-h);
  display: flex; align-items: center; justify-content: space-between; gap: 22px;
  transition: min-height .2s;
}
.hdr[data-stuck] .hdr__in { min-height: var(--hdr-h-stuck); }

/* The REAL logo artwork, not a redrawn SVG lockup. The client has a proper two-ink mark and
   substituting a generic house-and-pipe glyph for it would be a downgrade. It carries no black
   (checked in build/images.py, which prints the near-black pixel count), so the same file sits on
   the white header and on the dark footer without a knocked-out variant. */
.brand { display: inline-flex; align-items: center; text-decoration: none; flex: 0 0 auto; }
/* The artwork is wide (about 3:1), so the height is what sets its footprint: 58px tall is
   ~172px wide, which is what the nav has room for at 1120px. */
.brand__logo {
  width: auto; height: 54px; transition: height .2s;
}
.hdr[data-stuck] .brand__logo { height: 46px; }
@media (max-width: 560px) { .brand__logo { height: 42px; } }

/* nowrap on purpose. With wrap, "Contact" silently drops to a second row and
   the header grows 60px at 1280px wide. The burger takes over at 1120px. */
.nav { display: flex; align-items: center; gap: 20px; flex-wrap: nowrap; margin-left: auto; }
.nav > a, .nav__dropbtn {
  font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 13px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink); text-decoration: none; white-space: nowrap;
  background: none; border: 0; padding: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
}
.nav > a:hover, .nav__dropbtn:hover,
.nav > a[aria-current="page"], .nav__drop[data-current] .nav__dropbtn { color: var(--brand-dkr); }
.nav__home { color: var(--ink); }
.nav__home svg { display: block; }

.nav__drop { position: relative; }
.nav__panel {
  position: absolute; top: calc(100% + 14px); left: 50%; transform: translateX(-50%) translateY(-6px);
  min-width: 268px; background: #fff; border: 1px solid var(--line); border-top: 3px solid var(--brand);
  box-shadow: var(--shadow); padding: 8px; border-radius: var(--radius);
  display: flex; flex-direction: column;
  opacity: 0; visibility: hidden; transition: opacity .16s, transform .16s, visibility .16s;
}
.nav__drop:hover .nav__panel,
.nav__drop:focus-within .nav__panel,
.nav__drop[data-open] .nav__panel { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
/* A gap between the button and the panel breaks a hover journey; this bridges it. */
.nav__drop::after { content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 16px; }
.nav__panel a {
  font-family: 'Red Hat Text', sans-serif; font-weight: 700; font-size: 15px;
  text-transform: none; letter-spacing: 0;
  color: var(--ink); text-decoration: none; padding: 9px 13px; border-radius: 3px;
}
.nav__panel a:hover, .nav__panel a[aria-current="page"] { background: var(--band); color: var(--brand-dkr); }

.hdr__cta { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; }
.hdr__quote {
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--ink); color: #fff; text-decoration: none;
  padding: 12px 20px; border-radius: var(--radius);
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 13.5px;
  letter-spacing: .045em; text-transform: uppercase;
  transition: background .16s;
}
.hdr__quote svg { color: var(--brand); }
.hdr__quote:hover { background: var(--brand-bg); }
.hdr__quote:hover svg { color: #fff; }

.burger { display: none; width: 44px; height: 44px; background: none; border: 0; padding: 10px; cursor: pointer; }
.burger span { display: block; height: 2.5px; background: var(--ink); margin: 4px 0; border-radius: 2px; transition: transform .2s, opacity .2s; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* Mobile menu. Collapse is scoped to .cnc-js so a no-JS visitor and every
   crawler get the full list rather than an empty bar. */
/* Dark, to match the header it drops out of. */
.nav-m { display: none; border-top: 1px solid var(--line); padding: 10px var(--pad) 22px; background: #fff; }
.nav-m a {
  display: block; padding: 12px 2px; text-decoration: none; color: var(--ink);
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 15px;
  border-bottom: 1px solid var(--line);
}
.nav-m__label {
  margin: 16px 0 2px; font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--brand-dkr);
}
.nav-m__cta {
  margin-top: 14px; text-align: center; background: var(--brand-bg); color: #fff !important;
  border-radius: var(--radius); border-bottom: 0 !important; text-transform: uppercase;
  letter-spacing: .045em; font-size: 14px;
}
.nav-m__cta--alt { background: var(--band); color: var(--ink) !important; }

@media (max-width: 1240px) {
  .nav { display: none; }
  .burger { display: block; }
  .cnc-js .nav-m { display: none; }
  .cnc-js .nav-m[data-open] { display: block; }
  .nav-m { display: block; }
}
@media (max-width: 560px) {
  .hdr__quote span { display: none; }
  .hdr__quote { padding: 12px 14px; }
  .brand__name { font-size: 17px; }
}

/* --------------------------------------------------------------- hero
   SPLIT hero: type on white at the left, one photograph at the right.
   Deliberately not the template's full-bleed dark banner. Two reasons, and the second is the
   one that actually decided it:
     1. The brief is "the clean white aesthetic" of the Webflow reference the client named. A
        black-gradient banner is the opposite of that.
     2. The client's strongest photographs are PORTRAIT interiors (1440x1800 bathrooms). A
        full-bleed 16:5 banner crops those to a strip of wall. A portrait media panel shows them
        at their best, and it means the design does not depend on owning one perfect landscape
        photograph - which this client does not have. */
/* DARK hero. The header above it is white (it carries the white-ground lockup), so the hero is
   the site's first dark field and the copper eyebrow and rules read at full strength against
   it. */
.hero { position: relative; background: var(--ink-2); color: #fff; overflow: hidden; }
.hero::before {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(58% 70% at 8% 18%, rgba(176,120,80,.18), transparent 70%),
    radial-gradient(46% 60% at 96% 96%, rgba(176,120,80,.10), transparent 72%);
  pointer-events: none;
}
.hero .eyebrow { color: var(--brand-lt); }
.hero .eyebrow::after { background: var(--brand-lt); }
.hero__grid {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: 1.02fr .98fr;
  gap: clamp(30px, 5vw, 68px); align-items: center;
  padding-top: clamp(42px, 6vw, 78px); padding-bottom: clamp(42px, 6vw, 78px);
}
.hero__grid--sm { padding-top: clamp(34px, 4.4vw, 58px); padding-bottom: clamp(34px, 4.4vw, 58px); }
.hero__copy { max-width: 620px; }
.hero__copy--wide { max-width: 820px; }
.hero h1 { color: #fff; margin-bottom: .42em; }
/* Display type scales to the CONTENT, not to one clamp(). build.mjs measures each H1 and stamps
   the bucket - these run from 12 to 48 characters, and a single size either shrinks the short
   ones or takes the long ones to four lines and pushes the CTA below the fold on a phone. */
h1[data-len="short"] { font-size: clamp(33px, 5.2vw, 56px); }
h1[data-len="long"]  { font-size: clamp(29px, 4.4vw, 48px); }
h1[data-len="xlong"] { font-size: clamp(26px, 3.7vw, 41px); }
.hero__lede { font-size: clamp(16.5px, 1.5vw, 18.5px); color: rgba(255,255,255,.82); max-width: 620px; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 13px; margin-top: 28px; }
.hero__cta--c { justify-content: center; }

/* Three short proofs under the CTAs. Ticks rather than bullets, and set small - they are
   reassurance, not content. */
.hero__pts {
  list-style: none; padding: 0; margin: 30px 0 0;
  display: flex; flex-wrap: wrap; gap: 10px 26px;
  font-size: 14.5px; color: rgba(255,255,255,.86);
}
.hero__pts li { position: relative; padding-left: 25px; margin: 0; }
.hero__pts li::before {
  content: ''; position: absolute; left: 0; top: 50%; margin-top: -8px;
  width: 17px; height: 17px; border-radius: 50%; background: var(--brand);
}
.hero__pts li::after {
  content: ''; position: absolute; left: 4.5px; top: 50%; margin-top: -3.5px;
  width: 8px; height: 4.5px; border-left: 2px solid #fff;
  border-bottom: 2px solid #fff; transform: rotate(-45deg);
}

/* The media panel. A slight lift and a copper corner accent so the photograph reads as placed
   rather than pasted. */
.hero__media { position: relative; }
.hero__media picture, .hero__media img {
  display: block; width: 100%; border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
.hero__media img { object-fit: cover; aspect-ratio: 4 / 5; }
.hero__media--sm img { aspect-ratio: 4 / 3; }
.hero__media::after {
  content: ''; position: absolute; right: -14px; bottom: -14px; z-index: -1;
  width: 58%; height: 46%; border-radius: var(--radius);
  background: var(--brand); opacity: .55;
}
/* A hero with no media panel (Contact, Areas, Our Work, 404) - copy only, centred band. */
.hero--plain { padding: clamp(44px, 6vw, 80px) 0 clamp(38px, 5vw, 66px); }
.hero--plain .hero__copy { max-width: 820px; }

@media (max-width: 880px) {
  .hero__grid { grid-template-columns: 1fr; gap: 34px; }
  /* Media BELOW the copy on a phone: the headline and the phone number are what the visitor came
     for, and a 4:5 portrait photograph above them pushes both off the first screen. */
  .hero__media { order: 2; max-width: 520px; }
  .hero__media img { aspect-ratio: 4 / 3; }
  .hero__media::after { display: none; }
}

/* --------------------------------------------------------------- trust strip
   A COPPER band, not a dark one: the hero directly above it is dark, so a dark strip would merge
   into it and the page would read as one long stretch. --brand-bg (#8C5A3C) rather than the raw
   logo copper, because white on the raw copper is 3.06:1 and these labels are small uppercase
   type; on --brand-bg they measure 5.76:1. */
.trust { background: var(--brand-bg); color: #fff; }
.trust__in {
  display: flex; flex-wrap: wrap; gap: 12px clamp(18px, 2.4vw, 34px);
  justify-content: center; padding: 20px 0;
}
/* Sized so all four items sit on ONE row from about 1180px up. At 13px with a 38px gap the
   fourth wrapped onto a line by itself, which reads as a layout fault rather than a design. */
.trust__item {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: clamp(11.5px, 1.05vw, 12.5px); letter-spacing: .03em; text-transform: uppercase;
  color: #fff; white-space: nowrap;
}
@media (max-width: 720px) { .trust__item { white-space: normal; } }
.trust__item svg { color: #fff; flex: 0 0 auto; }

/* --------------------------------------------------------------- sections */
.sec { padding: var(--sec-y) 0; }
.sec--white { background: #fff; }
.sec--band { background: var(--band); }
.sec--dark { background: var(--ink); color: #fff; }
.sec--dark h2, .sec--dark h3 { color: #fff; }
.sec--dark .eyebrow { color: var(--brand-lt); }
.sec--dark .eyebrow::after { background: var(--brand-lt); }
.sec--dark a:not(.btn):not(.tlink) { color: var(--brand-lt); }
/* The brand band. Its own text colour is white, so every child that must stay
   readable states its colour explicitly - a row with a colour set is exactly
   what makes an embedded panel render white on white. */
/* The copper band carries WHITE text - 5.76:1 on --brand-bg. */
.sec--brand { background: var(--brand-bg); color: #fff; }
.sec--brand h2, .sec--brand h3 { color: #fff; }
.sec--brand .eyebrow { color: #fff; }
.sec--brand .eyebrow::after { background: #fff; }
.sec--brand .sec__head p { color: #fff; }

.sec__head { max-width: 780px; margin-bottom: clamp(30px, 4vw, 46px); }
.sec__head--c { margin-left: auto; margin-right: auto; text-align: center; }
/* 52px section headings, larger than the H1, exactly as the reference has it. */
.sec h2 { font-size: clamp(29px, 3.6vw, 46px); }
.sec__head p { font-size: 17.5px; color: var(--muted); margin-bottom: 0; }
.sec--dark .sec__head p { color: rgba(255,255,255,.86); }
.sec__after { margin-top: 26px; }

/* --------------------------------------------------------------- prose */
.prose { max-width: 780px; }
.prose h2 { font-size: clamp(25px, 2.7vw, 34px); margin-top: 1.7em; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { font-size: clamp(19px, 1.8vw, 23px); margin-top: 1.5em; }
.prose > p:first-child { font-size: 18.5px; }
/* :not(.btn):not(.tlink) - see the note on .btn above. A bare `.prose a` rule
   outranks .btn and silently repaints every in-prose button. */
.prose a:not(.btn):not(.tlink) { color: var(--brand-dkr); text-decoration: underline; text-underline-offset: 3px; }
.prose a:not(.btn):not(.tlink):hover { color: var(--brand); }
.prose ul { list-style: none; padding-left: 0; }
.prose ul li { position: relative; padding-left: 32px; margin-bottom: .6em; }
.prose ul li::before {
  content: ''; position: absolute; left: 0; top: .42em;
  width: 20px; height: 20px; border-radius: 50%; background: var(--brand);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='12' fill='black'/></svg>") center/contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='12' fill='black'/></svg>") center/contain no-repeat;
}
.prose ul li::after {
  content: ''; position: absolute; left: 5px; top: .68em;
  width: 10px; height: 6px; border-left: 2.4px solid #fff; border-bottom: 2.4px solid #fff;
  transform: rotate(-45deg);
}
.prose ol { padding-left: 1.3em; }
.prose ol li::marker { font-family: 'Mulish', sans-serif; font-weight: 800; color: var(--brand-dkr); }

/* Two-column: prose left, media right. */
.split { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(30px, 5vw, 64px); align-items: start; }
.split--flip .split__media { order: -1; }
.split__media img { width: 100%; border-radius: var(--radius); box-shadow: var(--shadow); }
/* The copy column on a service page runs to several thousand pixels and the media column is one
   photograph, so without this the right-hand side is mostly empty space. Sticky keeps the photo
   in view as the copy scrolls past it. Desktop only - on a stacked layout it would pin the image
   over the text. */
@media (min-width: 901px) {
  .split__media { position: sticky; top: calc(var(--hdr-h) + 22px); }
}
@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; }
  .split--flip .split__media { order: 0; }
}

/* --------------------------------------------------------------- service cards
   Photo, bold heading, copy - no bordered card and no hover lift, matching the
   reference. The whole tile is the link, so the markup uses <a> with <span>
   children (a <div> or <p> inside an <a> is invalid). */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(285px, 1fr)); gap: clamp(22px, 2.6vw, 32px); }
/* A real surface rather than a bare image and some text. On a white-dominant design the cards
   are the only thing giving the services section structure, so they get a white panel, a hairline
   and a lift on hover. */
.card {
  display: block; text-decoration: none; color: inherit;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; transition: transform .22s, box-shadow .22s, border-color .22s;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: transparent; }
.card__img { display: block; overflow: hidden; background: var(--band); }
.card__img picture { display: block; }
.card__img img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; transition: transform .5s ease; }
.card:hover .card__img img { transform: scale(1.045); }
.card__body { display: block; padding: 22px 24px 26px; }
.card h3 { font-size: 20px; margin-bottom: .42em; color: var(--ink); }
.card__p { display: block; font-size: 15.5px; line-height: 1.62; color: var(--muted); }
.card__more { color: var(--brand-dkr); }
.card__more {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 13px;
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 13px;
  letter-spacing: .07em; text-transform: uppercase;
}
.card__more::after {
  content: ''; width: 15px; height: 9px; background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 12'><path d='M0 5h15L11 1l1.4-1.4L19 6l-6.6 6.4L11 11l4-4H0z' fill='black'/></svg>") center/contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 12'><path d='M0 5h15L11 1l1.4-1.4L19 6l-6.6 6.4L11 11l4-4H0z' fill='black'/></svg>") center/contain no-repeat;
  transition: transform .2s;
}
.card:hover .card__more::after { transform: translateX(4px); }
/* On the brand band every card element states its colour outright. Inheriting
   from the row is what renders a panel white on white. */
.sec--brand .card { color: var(--ink); }
.sec--brand .card h3 { color: var(--ink); }
.sec--brand .card__p { color: var(--muted); }
.sec--brand .card__more { color: var(--brand-dkr); }

/* --------------------------------------------------------------- features */
.feats { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: clamp(24px, 3vw, 40px); }
.feat__img { border-radius: var(--radius); overflow: hidden; margin-bottom: 18px; }
.feat__img img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.feat h3 { font-size: 20px; }
.feat p { font-size: 15.5px; margin-bottom: 0; }

/* Tick list - 30px brand discs with the same white tick in each, as the
   reference does, rather than a different pictogram per row. */
.ticks { list-style: none; padding: 0; margin: 0; display: grid; gap: 15px; }
.ticks li { position: relative; padding-left: 44px; margin: 0; font-size: 16.5px; }
.ticks li strong { font-family: 'Mulish', sans-serif; font-weight: 800; }
.ticks li::before {
  content: ''; position: absolute; left: 0; top: .16em;
  width: 28px; height: 28px; border-radius: 50%; background: var(--brand);
}
.ticks li::after {
  content: ''; position: absolute; left: 8px; top: .58em;
  width: 12px; height: 7px; border-left: 2.6px solid #fff; border-bottom: 2.6px solid #fff;
  transform: rotate(-45deg);
}
.sec--dark .ticks li { color: rgba(255,255,255,.94); }

/* --------------------------------------------------------------- numbered steps */
.steps { list-style: none; padding: 0; margin: 0; counter-reset: s; display: grid; gap: 26px; }
.steps li { counter-increment: s; position: relative; padding-left: 66px; margin: 0; }
.steps li::before {
  content: counter(s, decimal-leading-zero);
  position: absolute; left: 0; top: -2px;
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 30px;
  color: var(--brand-dkr); line-height: 1;
}
.steps h3 { font-size: 19px; margin-bottom: .28em; }
.steps p { font-size: 15.5px; margin-bottom: 0; }

/* --------------------------------------------------------------- areas */
.areas { display: grid; grid-template-columns: repeat(auto-fit, minmax(285px, 1fr)); gap: clamp(20px, 2.4vw, 30px); }
.area {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 26px 26px 28px; position: relative; overflow: hidden;
  transition: box-shadow .22s, border-color .22s;
}
/* A copper bar down the left edge rather than across the top - it reads as a list of places
   rather than as another row of cards, which is what the top border made it look like next to
   the service grid. */
.area::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--brand);
}
.area:hover { box-shadow: var(--shadow-md); border-color: transparent; }
.area h3 { font-size: 18.5px; }
.area p { font-size: 15.5px; margin-bottom: 0; color: var(--muted); }
.sec--band .area { border-color: transparent; box-shadow: var(--shadow); }

/* --------------------------------------------------------------- brands strip */
.brands { background: #fff; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 30px 0; }
.brands__label {
  text-align: center; font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 12px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 16px;
}
/* Product/supplier names as type, not as logo files - the client displays these
   marks on their own site but we hold no artwork licence, and set as type they
   cannot be mistaken for accreditation badges. */
.brands__list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 12px 34px;
}
.brands__list li {
  margin: 0; font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: clamp(15px, 1.7vw, 20px); letter-spacing: .02em; color: var(--ink);
}

/* --------------------------------------------------------------- FAQ
   Bright photo behind a near-white panel with brand accordion bars, as the
   reference has it - not a darkened photo with white text on hairlines. */
.faq-sec { position: relative; background: var(--ink); }
.faq-sec__bg { position: absolute; inset: 0; }
.faq-sec__bg img { width: 100%; height: 100%; object-fit: cover; }
.faq-sec > .wrap { position: relative; z-index: 2; }
.faq-panel {
  background: rgba(255,255,255,.96); border-radius: var(--radius);
  padding: clamp(26px, 4vw, 52px); max-width: 900px; margin: 0 auto;
  box-shadow: var(--shadow-lg);
}
.faq-panel h2 { text-align: center; color: var(--ink); }
.faq-panel > p { text-align: center; color: var(--muted); max-width: 640px; margin: 0 auto 28px; }
.faq details { border-radius: var(--radius); margin-bottom: 10px; overflow: hidden; }
.faq summary {
  list-style: none; cursor: pointer;
  background: var(--brand-bg); color: var(--ink);
  padding: 15px 52px 15px 20px; position: relative;
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 16px;
  border-radius: var(--radius);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ''; position: absolute; right: 19px; top: 50%; margin-top: -8px;
  width: 16px; height: 16px; background: #fff;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 3h2v18h-2z M3 11h18v2H3z' fill='black'/></svg>") center/contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 3h2v18h-2z M3 11h18v2H3z' fill='black'/></svg>") center/contain no-repeat;
  transition: transform .2s;
}
.faq details[open] summary { background: var(--ink); border-radius: var(--radius) var(--radius) 0 0; color: #fff; }
.faq details[open] summary::after { transform: rotate(45deg); }
.faq__a { padding: 18px 20px 20px; background: #fff; border: 1px solid var(--line); border-top: 0; border-radius: 0 0 var(--radius) var(--radius); }
.faq__a p:last-child { margin-bottom: 0; }
.faq__a { font-size: 16px; }

/* --------------------------------------------------------------- reviews
   REMOVED. The roofing template this was cloned from carried a Trustindex review slider - a
   .reviews block, a .reviews__slot, and a .ti-stage parked off-canvas at left:-1400px because the
   widget had to keep a real width while it measured itself.
   GD Plumbing has no reviews feed, so the markup, the JS and these rules were all taken out
   rather than left as dead weight. If reviews are ever added, restore the whole set from
   _R/roofingcompanytauranga.co.nz - including the off-canvas staging trick, which is not
   guessable and which exists because `left: -100vw` put 805px of horizontal overflow on every
   page at 375px wide. */

/* --------------------------------------------------------------- gallery */
.gal { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.gal__btn { padding: 0; border: 0; background: var(--band); cursor: zoom-in; border-radius: var(--radius); overflow: hidden; display: block; }
.gal__btn img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; transition: transform .45s, opacity .2s; }
.gal__btn:hover img { transform: scale(1.05); opacity: .88; }

.lb { position: fixed; inset: 0; z-index: 200; background: rgba(9,10,11,.94); display: none; align-items: center; justify-content: center; padding: 5vh 6vw; }
.lb[data-open] { display: flex; }
.lb__img { max-width: 100%; max-height: 82vh; object-fit: contain; border-radius: var(--radius); }
.lb__cap { position: absolute; left: 0; right: 0; bottom: 3.4vh; text-align: center; color: rgba(255,255,255,.9); font-size: 14.5px; padding: 0 8vw; margin: 0; }
.lb__btn { position: absolute; background: rgba(255,255,255,.12); color: #fff; border: 0; cursor: pointer; width: 52px; height: 52px; border-radius: 50%; font-size: 30px; line-height: 1; }
.lb__btn:hover { background: var(--brand-bg); color: #fff; }
.lb__close { top: 3vh; right: 3vw; font-size: 34px; }
.lb__prev { left: 2vw; top: 50%; margin-top: -26px; }
.lb__next { right: 2vw; top: 50%; margin-top: -26px; }
body[data-lb] { overflow: hidden; }
body[data-lb] .hdr, body[data-lb] .util, body[data-lb] .floatbar { visibility: hidden; }

/* --------------------------------------------------------------- callout */
.callout { background: var(--ink-2); color: #fff; border-radius: var(--radius); padding: clamp(26px, 3.6vw, 42px); }
.callout h2, .callout h3 { color: #fff; margin-top: 0; }
.callout p { color: rgba(255,255,255,.86); }
.callout .eyebrow { color: var(--brand-lt); }

/* --------------------------------------------------------------- enquiry */
/* DARK enquiry band. With a dark header and footer, a dark enquiry section makes the page read
   as one composition rather than a light page with dark ends. The form itself stays a WHITE card
   so it is unmistakably the thing to fill in. Every colour is stated, nothing inherits. */
.enq { background: var(--ink-2); color: #fff; padding: var(--sec-y) 0; border-top: 1px solid rgba(255,255,255,.08); }
.enq__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 5vw, 68px); align-items: start; }
.enq h2 { font-size: clamp(27px, 3.2vw, 40px); color: #fff; }
.enq .eyebrow { color: var(--brand-lt); }
.enq .eyebrow::after { background: var(--brand-lt); }
.enq__copy > p { color: rgba(255,255,255,.82); }
.enq__big {
  display: inline-flex; align-items: center; gap: 13px; margin: 8px 0 22px;
  font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: clamp(23px, 2.6vw, 31px); color: var(--brand-lt); text-decoration: none;
}
.enq__big svg { color: var(--brand-lt); }
.enq__big:hover { color: #fff; }
.enq__facts { list-style: none; padding: 0; margin: 0 0 18px; display: grid; gap: 12px; }
.enq__facts li { display: flex; gap: 12px; align-items: flex-start; margin: 0; font-size: 15.5px; color: rgba(255,255,255,.9); }
.enq__facts svg { color: var(--brand-lt); flex: 0 0 auto; margin-top: 4px; }
.enq__facts a { color: #fff; }
.enq__note { font-size: 15px; color: rgba(255,255,255,.72); margin: 0; }
.enq__note strong { color: #fff; }

/* Dark form panel on a white section, as the reference has it.
   🔴 Every text element below states its own colour at two or more classes.
   A widget styled with single-class selectors, or one relying on
   `color: inherit`, renders white on its own white card the moment a parent
   row sets a colour - which is exactly the bug that reads as "nearly working"
   because the panel around it still looks perfect. */
/* LIGHT form panel, not the template's dark one - the brief is a white-dominant design and a
   near-black block is the heaviest object on the page.
   🔴 Every colour below was changed in ONE pass. The template's version assumed a dark panel:
   white labels, #ffc4c4 errors, white message text. Converting the background without converting
   all of those leaves white-on-white labels - the exact "widget vanishes on its own card" failure
   the fleet notes describe, and it looks fine right up until someone tries to read it. Each rule
   states its colour outright rather than inheriting. */
.form {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: clamp(24px, 3.4vw, 38px); box-shadow: var(--shadow-md);
}
.form__h {
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 20px;
  color: var(--ink); margin: 0 0 20px;
}
.form .form__row { margin-bottom: 15px; }
.form .form__row label {
  display: block; margin-bottom: 6px;
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 12.5px;
  letter-spacing: .05em; text-transform: uppercase; color: var(--ink);
}
.form .form__row input,
.form .form__row select,
.form .form__row textarea {
  width: 100%; padding: 12px 14px; font: inherit; font-size: 16px;
  color: #1A1816; -webkit-text-fill-color: #1A1816;   /* WebKit honours this over color */
  background: var(--band); border: 1.5px solid var(--line); border-radius: var(--radius-sm);
  transition: border-color .15s, background .15s;
}
.form .form__row input:hover, .form .form__row select:hover, .form .form__row textarea:hover {
  border-color: #D8CFC6;
}
.form .form__row select { appearance: none; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'><path d='M6 8 0 0h12z' fill='%231A1816'/></svg>"); background-repeat: no-repeat; background-position: right 14px center; background-size: 11px; padding-right: 38px; }
.form .form__row textarea { resize: vertical; min-height: 118px; }
.form .form__row input::placeholder,
.form .form__row textarea::placeholder { color: #776E66; -webkit-text-fill-color: #776E66; }
.form .form__row input:focus, .form .form__row select:focus, .form .form__row textarea:focus {
  outline: 3px solid var(--brand); outline-offset: 1px; background: #fff; border-color: var(--brand);
}
.form .btn { margin-top: 10px; }
/* Error text stays a real RED. The copper is the ACTION colour and must not double as the
   warning - an error the same colour as the submit button does not read as an error. #B3261E on
   white is 5.9:1, so it clears AA at this small size. */
.form .err { display: block; color: #B3261E; font-size: 13.5px; margin-top: 5px; font-weight: 700; }
.form .form__msg { margin: 14px 0 0; font-size: 15px; color: var(--ink); }
.form .form__msg.err { color: #B3261E; }
.form .form__legal { margin: 14px 0 0; font-size: 13px; color: var(--muted); }
/* Honeypot: off-canvas, not display:none or type=hidden - capable bots skip both. */
.hp { position: absolute; left: -9999px; top: 0; width: 1px; height: 1px; overflow: hidden; }

@media (max-width: 860px) { .enq__grid { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------- footer */
.ftr { background: var(--ink-2); color: rgba(255,255,255,.86); font-size: 15.5px; }
.ftr__grid { display: grid; grid-template-columns: 1fr 1fr 1.15fr; gap: clamp(28px, 4vw, 54px); padding-top: clamp(42px, 5vw, 66px); padding-bottom: 30px; }
.ftr__h {
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 20px;
  color: #fff; margin: 0 0 16px;
}
.ftr a { color: rgba(255,255,255,.86); text-decoration: none; }
.ftr a:hover { color: #fff; text-decoration: underline; }
.ftr__contact { list-style: none; padding: 0; margin: 0; display: grid; gap: 13px; }
.ftr__contact li { display: flex; gap: 12px; align-items: flex-start; margin: 0; }
.ftr__contact svg { color: var(--brand-lt); flex: 0 0 auto; margin-top: 4px; }
.ftr__links { display: flex; flex-direction: column; }
.ftr__links a { padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,.12); }

.ftr__grid p { color: rgba(255,255,255,.8); }
.ftr__areas-row { padding-bottom: 34px; border-top: 1px solid rgba(255,255,255,.12); padding-top: 28px; }
.ftr__areas-row .ftr__h { font-size: 17px; margin-bottom: 8px; }
.ftr__areas { margin: 0; color: rgba(255,255,255,.8); font-size: 15px; }
.ftr__areas .tlink { color: #fff; border-bottom-color: var(--brand-lt); }
.ftr__btm-wrap { background: var(--ink-0); }
.ftr__btm { padding: 17px 0; text-align: center; font-size: 14px; color: rgba(255,255,255,.72); }
/* The whole phrase is the link, not just the brand name - one credit unit and
   a bigger tap target. Underline on hover only, so it reads as a credit rather
   than competing with the footer nav. */
.ftr__credit { color: rgba(255,255,255,.72) !important; text-decoration: none; }
.ftr__credit:hover { color: #fff !important; text-decoration: underline; }
@media (max-width: 800px) { .ftr__grid { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------- float bar
   Fleet component. Lower right per the fleet standard rather than vertically
   centred as the reference has it - that is a cross-site convention, not a
   per-site design choice. */
.floatbar { position: fixed; right: 18px; bottom: 18px; z-index: 95; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.floatbar__list { display: flex; flex-direction: column; gap: 10px; }
.floatbar__btn {
  width: 50px; height: 50px; border-radius: 50%;
  background: var(--fb-bg); color: var(--fb-icon);
  display: grid; place-items: center; border: 0; cursor: pointer;
  box-shadow: 0 6px 20px rgba(15,17,19,.28);
  transition: transform .18s, background .18s, color .18s, opacity .18s;
}
.floatbar__btn:hover { background: var(--fb-hover-bg); color: var(--fb-hover-icon); }
.cnc-js .floatbar:not([data-open]) .floatbar__list { opacity: 0; visibility: hidden; transform: translateY(10px); pointer-events: none; }
.cnc-js .floatbar .floatbar__list { transition: opacity .2s, transform .2s, visibility .2s; }
/* 🔴 Restate the hover transform AFTER the collapse rule. An equal-specificity
   `transform: none` later in the file wins, which is why the hover scale never
   fired in the jedibuilders reference implementation. */
.floatbar__btn:hover { transform: scale(1.08); }
.floatbar__toggle:hover { transform: scale(1.08); }

.fb-pop { position: fixed; inset: 0; z-index: 190; background: rgba(9,10,11,.6); display: none; align-items: center; justify-content: center; padding: 24px; }
.fb-pop[data-open] { display: flex; }
.fb-pop__card { background: #fff; border-radius: var(--radius); padding: 34px 40px; text-align: center; position: relative; max-width: 380px; }
.fb-pop__card p { color: var(--muted); font-size: 15px; }
.fb-pop__num { display: block; font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 29px; color: var(--brand-dkr); text-decoration: none; margin: 6px 0 10px; }
.fb-pop__close { position: absolute; top: 8px; right: 12px; background: none; border: 0; font-size: 28px; line-height: 1; cursor: pointer; color: var(--muted); }

/* --------------------------------------------------------------- reveal
   🔴 threshold: 0 with rootMargin only. A ratio threshold never fires on a copy
   column taller than about 16 viewports, which is most service pages, and the
   whole body then sits at opacity 0 until the visitor happens to scroll.
   All of it is scoped to .cnc-js so no-JS visitors and crawlers see everything. */
.cnc-js [data-reveal] { opacity: 0; transform: translateY(16px); transition: opacity .55s ease, transform .55s ease; }
.cnc-js [data-reveal].is-in { opacity: 1; transform: none; }
.cnc-js [data-reveal][data-delay="1"] { transition-delay: .09s; }
.cnc-js [data-reveal][data-delay="2"] { transition-delay: .18s; }
@media (prefers-reduced-motion: reduce) {
  .cnc-js [data-reveal] { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------- misc */
.lead { font-size: 19px; }
.center { text-align: center; }
.mt0 { margin-top: 0; }
.stack > * + * { margin-top: clamp(28px, 3.4vw, 46px); }

/* ===========================================================================
   Site-specific components (inherited from the gdplumbing build)
   Added for this build - the split hero's supporting pieces, the contact
   cards, the footer's real logo, and the wide FAQ used on pages with no
   media column. Kept at the end so they cannot be missed when re-theming.
   =========================================================================== */

/* --------------------------------------------------------------- split media caption */
.split__cap {
  margin: 14px 0 0; font-size: 14px; color: var(--muted); line-height: 1.5;
}
.split__media picture { display: block; }
.split__media img { border-radius: var(--radius); box-shadow: var(--shadow-md); }

/* --------------------------------------------------------------- wide FAQ
   The FAQ on these pages sits in a normal section rather than inside the
   template's dark photo panel, so it needs its own width and centring. */
.faq--wide { max-width: 860px; margin: 0 auto; }

/* 🔴 STATE EVERY COLOUR. The base .faq summary rule above was written for the dark template and
   sets `color: #fff` to sit on a brand-blue bar. Overriding only the BACKGROUND to white left
   white text on a white bar - six unreadable questions that render as blank grey slabs, and the
   page otherwise looks completely finished. That is the same class of bug as the embedded-widget
   rule in the fleet notes, and it was caught here by looking at a screenshot rather than by
   reading the CSS. The plus/minus glyph is a mask painted with `background`, so it needs its
   colour restated too or it stays white and disappears with the text. */
.faq summary {
  background: #fff; color: var(--ink);
  border: 1px solid var(--line);
  transition: border-color .16s, background .16s;
}
.faq summary::after { background: var(--brand-dkr); }
.faq summary:hover { border-color: var(--brand); background: var(--brand-soft); }
.faq details[open] summary {
  background: var(--ink); color: #fff; border-color: var(--ink);
}
.faq details[open] summary::after { background: var(--brand-lt); }
.faq__a { border-color: var(--line); color: var(--ink); }
.faq__a p { color: var(--muted); }

/* --------------------------------------------------------------- contact cards */
.ccards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: clamp(18px, 2.2vw, 26px);
}
.ccard {
  display: block; text-decoration: none; color: inherit;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 28px 26px 30px;
  transition: transform .22s, box-shadow .22s, border-color .22s;
}
/* Only the ones that actually go somewhere get the affordance. A hover lift on
   a static address panel promises a link that is not there. */
a.ccard:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: transparent; }
.ccard__ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--brand-soft); color: var(--brand-dkr); margin-bottom: 16px;
}
.ccard__l {
  display: block; font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--brand-dkr); margin-bottom: 7px;
}
.ccard__v {
  display: block; font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 18px; color: var(--ink); line-height: 1.3;
  /* An email address has no spaces to break at and will otherwise push the
     card wider than its column on a phone. */
  overflow-wrap: anywhere;
}
.ccard__n { display: block; margin-top: 6px; font-size: 14.5px; color: var(--muted); }

/* --------------------------------------------------------------- footer additions */
.ftr__logo {
  width: auto; height: 64px; margin-bottom: 16px;
}
.ftr__tag {
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 15px;
  color: var(--brand-lt); margin-top: 14px;
}
.ftr__social { display: flex; gap: 10px; margin-top: 18px; }
.ftr__social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  background: rgba(255,255,255,.09); color: #fff;
  transition: background .18s, color .18s;
}
.ftr__social a:hover { background: var(--brand-bg); color: #fff; }

/* --------------------------------------------------------------- header quote button
   Gold with ink type, to match the primary CTA - it is the same action. */
.hdr__quote {
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--brand-bg); color: #fff; text-decoration: none;
  padding: 12px 18px; border-radius: var(--radius-sm);
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 13.5px;
  letter-spacing: .03em; white-space: nowrap;
  transition: background .16s, transform .16s;
}
.hdr__quote svg { color: #fff; }
.hdr__quote:hover { background: var(--brand-dk); transform: translateY(-1px); }
.hdr__quote:hover svg { color: #fff; }
@media (max-width: 620px) { .hdr__quote span { display: none; } .hdr__quote { padding: 11px 13px; } }

/* --------------------------------------------------------------- utilities */
.pt0 { padding-top: 0; }

/* ===========================================================================
   ABC-specific components
   =========================================================================== */

/* --------------------------------------------------------------- full-bleed hero
   Every page uses one, over a photograph under a dark overlay with the copy on top. The image is
   a real <img> inside .hero__bg rather than a CSS background so it goes through pic() - WebP
   source, alt text, width/height - like every other photograph on the site.

   🔴 THE MAX HEIGHT IS SET BY THE SOURCE, NOT BY TASTE. Every hero photograph on this site comes
   from the old concrete5 slideshow and is 1920x500 - that is all the resolution the client has,
   and build/images.py refuses to upscale. With object-fit:cover a 1920x500 source fills any box
   up to 1920 wide and 500 tall at NATIVE size or better, and starts upscaling the moment the box
   is taller than 500. So the cap is 500px, and the hero is native-resolution on every viewport
   from a phone up to a 1920 desktop. Raising this number costs sharpness immediately.
   If the client ever supplies real inspection photography, raise it then. */
.hero--bleed { min-height: clamp(400px, 56vh, 500px); display: flex; align-items: center; }
.hero--bleed::before { display: none; }
.hero__bg { position: absolute; inset: 0; z-index: 0; }
.hero__bg picture, .hero__bg img { width: 100%; height: 100%; }
.hero__bg img { object-fit: cover; object-position: 50% 55%; }
/* The overlay. Dark enough at the left for white type to clear AA against the brightest part
   of any photograph, fading out to the right so the picture still reads as a picture. */
.hero__bg::after {
  content: ''; position: absolute; inset: 0;
  background:
    linear-gradient(90deg, rgba(18,17,16,.92) 0%, rgba(18,17,16,.8) 42%, rgba(18,17,16,.4) 100%),
    linear-gradient(0deg, rgba(18,17,16,.55) 0%, rgba(18,17,16,0) 40%);
}
.hero--bleed .wrap { position: relative; z-index: 2; padding-top: clamp(54px, 7vw, 96px); padding-bottom: clamp(54px, 7vw, 96px); }
.hero--bleed .hero__copy { max-width: 720px; }
.hero--bleed .hero__lede { color: rgba(255,255,255,.88); }
@media (max-width: 880px) {
  .hero--bleed { min-height: 0; }
  .hero__bg::after {
    background: linear-gradient(180deg, rgba(18,17,16,.84) 0%, rgba(18,17,16,.88) 100%);
  }
}

/* --------------------------------------------------------------- split hero photo card on dark */
.hero__media picture, .hero__media img { box-shadow: 0 20px 50px rgba(0,0,0,.45); }

/* --------------------------------------------------------------- cards on the warm band */
.sec--band .card { border-color: transparent; box-shadow: var(--shadow); }

/* --------------------------------------------------------------- dropdown on the dark header */
.nav__panel { border-top-color: var(--brand); }

/* ===========================================================================
   Components inherited from the fleet template
   =========================================================================== */

/* The hero's second paragraph - the brief's longer positioning line, set smaller than the lede. */
.hero__sub { font-size: 15.5px; color: rgba(255,255,255,.76); max-width: 640px; margin-top: -2px; }

/* Two-up technology features on the band: white cards with the product shot on top. */
.feats--2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.feat--card {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--shadow);
}
.feat--card .feat__img { margin: 0; border-radius: 0; }
.feat--card .feat__img img { transition: none; }
.feat--card h3, .feat--card p { padding: 0 24px; }
.feat--card h3 { margin-top: 20px; }
.feat--card p { margin-bottom: .8em; }
.feat--card p:last-child { padding-bottom: 24px; }

/* The six-step process on a dark section: a grid of numbered steps rather than a single column. */
.steps--grid { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 30px 34px; }
.steps--grid li::before { color: var(--brand-lt); }
.steps--grid h3 { color: #fff; }
.steps--grid p { color: rgba(255,255,255,.82); }

/* Standards teaser: the dark callout at full width. */
.callout--wide { max-width: none; }
.callout--wide h2 { font-size: clamp(25px, 2.9vw, 36px); }
.callout--wide .eyebrow::after { background: var(--brand-lt); }
.callout .btn--light { margin-top: 6px; }
.prose .callout { margin: 1.6em 0; }
.prose .callout .eyebrow { margin-bottom: 8px; }
.prose .callout p { color: rgba(255,255,255,.88); }

/* The scope note - the brief's own disclaimer, on every service page. Quiet, but not hidden. */
.note {
  margin: 1.8em 0; padding: 18px 22px; border-left: 4px solid var(--brand);
  background: var(--band); border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 15px; color: var(--muted);
}
.note p { margin: 0; }
.note strong { color: var(--ink); }

/* Specification tables on the technology page. */
.spec { width: 100%; border-collapse: collapse; margin: 0 0 1.4em; font-size: 15.5px; }
.spec th, .spec td { text-align: left; vertical-align: top; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.spec th { width: 34%; font-family: 'Mulish', sans-serif; font-weight: 800; color: var(--ink); font-size: 13.5px; letter-spacing: .02em; }
.spec td { color: var(--muted); }
.spec tr:first-child th, .spec tr:first-child td { border-top: 2px solid var(--brand); }
@media (max-width: 560px) {
  .spec th, .spec td { display: block; width: auto; padding: 8px 0; border: 0; }
  .spec th { padding-top: 12px; }
  .spec td { border-bottom: 1px solid var(--line); padding-bottom: 12px; }
}

/* Footer: a second heading inside the contact column, for the resource links. */
.ftr__h--sm { font-size: 15px; margin-top: 26px; margin-bottom: 8px; }

/* ===========================================================================
   ABC-specific components
   ---------------------------------------------------------------------------
   Added for this build. Everything above came from the fleet template; the
   blocks below exist because this site's content is shaped differently - four
   pages, ten bare service labels with no descriptions, and two long list-heavy
   sections on the leaky buildings page.
   =========================================================================== */

/* --------------------------------------------------------------- interior page hero
   The same full-bleed treatment as the home page but shorter, so an interior page puts its
   first paragraph on the opening screen. Same 500px source ceiling as .hero--bleed - see the
   note there before raising either number. */
.hero--page { position: relative; min-height: clamp(300px, 40vh, 400px); display: flex; align-items: flex-end; }
.hero--page::before { display: none; }
.hero--page .wrap {
  position: relative; z-index: 2;
  padding-top: clamp(46px, 6vw, 76px); padding-bottom: clamp(34px, 4.4vw, 54px);
}
.hero--page .hero__copy { max-width: 760px; }
.hero--page h1 { margin-bottom: .3em; }
.hero--page .hero__lede { color: rgba(255,255,255,.9); margin-bottom: 0; }
.hero--sm { min-height: 0; }

/* Breadcrumb trail. A real <nav>, and the current page is NOT a link - a self-link on the page
   you are already on is noise for a screen reader and does nothing for anyone else. */
.crumbs {
  font-size: 13px; letter-spacing: .02em; margin-bottom: 14px;
  color: rgba(255,255,255,.66);
}
.crumbs a { color: rgba(255,255,255,.88); text-decoration: none; border-bottom: 1px solid rgba(255,255,255,.34); }
.crumbs a:hover { color: #fff; border-bottom-color: #fff; }
.crumbs span[aria-hidden] { margin: 0 7px; color: rgba(255,255,255,.4); }

/* --------------------------------------------------------------- the "WE OFFER" grid
   🔴 LABELS ONLY, NO DESCRIPTIONS - and the design has to carry that.
   The client's list is ten bare strings; writing a sentence under each would be inventing copy
   about a professional service on their behalf. So the tile is built to look finished WITHOUT a
   paragraph: a copper disc, the label, and nothing else. A card designed for a heading plus body
   copy looks broken when the body copy is missing, which is why this is not .cards.
   Auto-fit at 250px puts the ten items on 4 / 3 / 2 / 1 columns as the viewport narrows, so a
   short list never leaves a lone orphan on the last row at the common widths. */
.svcs {
  list-style: none; padding: 0; margin: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: clamp(14px, 1.8vw, 20px);
}
.svc {
  display: flex; align-items: center; gap: 15px; margin: 0;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px 20px;
  transition: box-shadow .22s, border-color .22s, transform .22s;
}
.svc:hover { box-shadow: var(--shadow-md); border-color: transparent; transform: translateY(-2px); }
.svc__ico {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--brand-soft); color: var(--brand-dkr);
}
.svc h3 {
  margin: 0; font-size: 16px; line-height: 1.32; color: var(--ink);
  letter-spacing: -.005em;
}

/* --------------------------------------------------------------- contact cards */
.contact-cards {
  list-style: none; padding: 0; margin: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(18px, 2.4vw, 28px);
}
.contact-card {
  margin: 0; text-align: center;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 30px 24px 28px; box-shadow: var(--shadow);
}
.contact-card__ico {
  display: grid; place-items: center; width: 52px; height: 52px; margin: 0 auto 16px;
  border-radius: 50%; background: var(--brand-soft); color: var(--brand-dkr);
}
/* An <h2> here, not an <h3>: these are the page's top-level sections under the H1, and the
   heading outline has to describe the page rather than the visual weight. Sized down to match
   the card. */
.contact-card h2 {
  font-size: 13px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); margin-bottom: .7em;
}
.contact-card p { margin: 0; color: var(--muted); font-size: 15.5px; }
/* The phone number and the email are the point of this page, so they are set as display type and
   are real links. word-break stops the long email address blowing out a narrow card. */
.contact-card__big {
  font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: clamp(17px, 1.9vw, 21px); line-height: 1.3;
  color: var(--brand-dkr); text-decoration: none; overflow-wrap: anywhere;
}
.contact-card__big:hover { color: var(--brand-dk); text-decoration: underline; text-underline-offset: 3px; }

/* --------------------------------------------------------------- two prose columns
   The leaky buildings page has two list-heavy sections of similar length that belong side by
   side. align-items:start so a shorter column does not stretch. */
.cols2 {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: clamp(28px, 4vw, 56px); align-items: start;
}
.cols2 .prose { max-width: none; }
@media (max-width: 700px) { .cols2 { grid-template-columns: 1fr; } }

/* Narrow measure for a short page. The meth testing page is two paragraphs; at the full 1180px
   wrap they run to well over 100 characters a line, which is unreadable. */
.wrap--narrow { max-width: 760px; }

/* --------------------------------------------------------------- notes
   .note--lead is the meth testing page's opening statement, which is the one thing on that page
   a visitor has to read: bigger, ink rather than muted, on the copper wash rather than the band.
   .note--c is a centred full-width closing callout. */
.note--lead {
  margin-top: 0; font-size: clamp(17px, 1.8vw, 19.5px); line-height: 1.55;
  color: var(--ink); background: var(--brand-soft); padding: 22px 26px;
}
.note--c {
  margin: clamp(32px, 4vw, 48px) auto 0; max-width: 900px; text-align: center;
  border-left: 0; border-top: 4px solid var(--brand);
  border-radius: 0 0 var(--radius) var(--radius);
  background: #fff; padding: 24px 28px; font-size: 16.5px; color: var(--ink);
}

/* A WARNING list, not a tick list. The leaky-home "features" and "signs" lists are things you do
   NOT want to find, so a green-tick affordance would read as a checklist of good news. Same
   geometry, different glyph: a copper disc with an exclamation mark.
   🔴 The ::after tick from .ticks has to be cancelled explicitly - it is a separate rule and
   simply restyling ::before would leave the tick sitting on top of the new mark. */
.ticks--warn li::before { background: var(--brand-dkr); }
.ticks--warn li::after {
  content: '!'; left: 0; top: .16em; width: 28px; height: 28px;
  border: 0; transform: none;
  display: grid; place-items: center;
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 16px; color: #fff;
}

/* A portrait photograph in the media column - the one genuine job photo on the site is 600x800.
   Capped so it does not tower over the copy beside it on a wide screen. */
.split__media--tall img { max-width: 420px; margin-inline: auto; }
@media (max-width: 900px) { .split__media--tall img { max-width: 340px; } }

/* --------------------------------------------------------------- hero image: cap it at its source
   🔴 MEASURED FIX, not a guess. build/shots.mjs reported the home hero rendering into a 1440x689
   box from a 1920x500 source - object-fit:cover then scales it 1.38x and it is visibly soft.
   min-height on .hero--bleed does not prevent that: the SECTION grows to fit its copy, and the
   image box grows with it.

   Every hero photograph on this site is 1920x500, because that is the resolution the client has
   (they are the old concrete5 slideshow frames) and build/images.py refuses to upscale. With cover,
   a 1920x500 source fills any box up to 1920 wide at native size or better PROVIDED the box is no
   more than 500 tall. So the image box is capped at 500 and the section's own --ink-2 carries the
   rest, with the overlay fading to solid ink at the bottom edge so there is no visible seam.

   The alternative - shortening the hero copy until it fits 500px - would mean cutting the client's
   own opening paragraph, which is frozen. Capping the image is the change that costs nothing.

   If real inspection photography ever arrives, raise the cap and regenerate. */
.hero--bleed .hero__bg,
.hero--page .hero__bg { bottom: auto; height: min(100%, 500px); }

.hero--bleed .hero__bg::after,
.hero--page .hero__bg::after {
  background:
    linear-gradient(90deg, rgba(18,17,16,.90) 0%, rgba(18,17,16,.78) 44%, rgba(18,17,16,.42) 100%),
    /* Fades into the section's own background so the capped image has no visible bottom edge. */
    linear-gradient(180deg, rgba(38,34,30,0) 58%, var(--ink-2) 100%);
}
/* Mobile: the copy sits OVER the photo rather than beside it, so the scrim has to be heavier than
   the desktop one - but not so heavy that the photograph stops being a photograph. At .82/.86 the
   image was effectively invisible on a phone. These values are checked, not chosen: build/shots.mjs
   runs the same WCAG contrast sweep under iPhone 13 emulation as it does on desktop, so a scrim
   that is too light fails the run rather than shipping. */
@media (max-width: 880px) {
  .hero--bleed .hero__bg::after,
  .hero--page .hero__bg::after {
    background:
      linear-gradient(180deg, rgba(18,17,16,.62) 0%, rgba(18,17,16,.78) 52%, var(--ink-2) 100%);
  }
}

/* --------------------------------------------------------------- trust strip: no orphan
   🔴 The template sizes this strip so four items sit on ONE row from about 1180px up, and its own
   comment says a fourth item wrapping onto a line by itself "reads as a layout fault rather than a
   design". That is exactly what happened here, because THIS site's four labels are the client's own
   claims and two of them are long ("Public Liability and Professional Indemnity insurance", "Over
   25 Years Building & Construction Experience"). Shortening them is not available - they are
   quoted, and the verifier checks them against the live site.

   So: below the width where four fit, go to a 2x2 grid. Two balanced rows read as deliberate;
   3 + 1 reads as broken. Below 620px it becomes a single column.
   The auto-fit breakpoint is set from the measured label widths, not guessed. */
.trust__in {
  display: grid; grid-template-columns: repeat(4, 1fr);
  justify-content: stretch; align-items: start;
  gap: 16px clamp(16px, 2.4vw, 34px); padding: 22px 0;
}
/* 🔴 WRAP THE LABELS, do not try to fit them on one line. Measured: these four labels total about
   1290px at this size, and .wrap is capped at 1180 - so on THIS site they can never sit on a
   single row at any viewport width, and the template's nowrap left the fourth stranded on a line
   of its own at every desktop size. Four equal columns with wrapping labels reads as one
   deliberate band; 3 + 1 reads as a bug. */
.trust__item { white-space: normal; align-items: flex-start; text-align: left; line-height: 1.32; }
.trust__item svg { margin-top: 1px; }
@media (max-width: 900px) { .trust__in { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .trust__in { grid-template-columns: 1fr; } }

/* ===========================================================================
   ADDED 2026-09-01 - the services/prices page, the "Why ABC" page, the Mount
   band and the leaky-buildings teaser.

   Everything below is new surface for content folded in from the Lovable
   preview the client approved (Capsule note, 2026-09-01). No existing rule was
   changed: the two new pages are additions, and a rebuild of a live ranking
   site is the last place to start refactoring a stylesheet that is already
   measured and passing.
   =========================================================================== */

/* --------------------------------------------------------------- taller hero
   🔴 The 500px cap two blocks up is not arbitrary - it is the pixel height of
   every photograph the client owns, and raising it upscales them. hero-mount.jpg
   is the ONE exception on this site: a 4896x3264 public-domain original, cut to
   1920x720. So the cap is lifted BY OPT-IN, on a class, rather than globally.
   Do not put .hero--tall on a page whose banner is one of the 1920x500 slides -
   build/shots.mjs measures the rendered box against the intrinsic size and will
   report it, but the result on screen is simply a soft picture. */
.hero--tall .hero__bg { height: min(100%, 720px); }
.hero--page.hero--tall { min-height: clamp(340px, 46vh, 470px); }

/* --------------------------------------------------------------- Mount band
   Full-bleed photograph with the service area over it. Same mechanics as
   .hero--bleed: a real <img> so it goes through pic() and gets a WebP source,
   a scrim on ::after, and - the part that matters for the contrast sweep in
   build/shots.mjs - a painted background-color ON THE SECTION. The sweep walks
   up to the nearest painted background, so a transparent section would have it
   comparing white text against the page behind, which is both wrong and
   flattering. --ink is what the scrim fades into, so it is the honest answer. */
.mount { position: relative; background: var(--ink); color: #fff; padding: var(--sec-y) 0; overflow: hidden; }
.mount__bg { position: absolute; inset: 0; z-index: 0; }
.mount__bg picture, .mount__bg img { width: 100%; height: 100%; display: block; }
.mount__bg img { object-fit: cover; object-position: 50% 42%; }
.mount__bg::after {
  content: ''; position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(18,17,16,.72) 0%, rgba(18,17,16,.66) 45%, rgba(18,17,16,.82) 100%);
}
.mount__in { position: relative; z-index: 2; text-align: center; }
.mount h2 { color: #fff; }
.mount .eyebrow { color: var(--brand-lt); }
.mount .eyebrow::after { background: var(--brand-lt); }
/* .sec__head p is --muted, which on this ground would be unreadable. Stated, not inherited. */
.mount .sec__head p { color: rgba(255,255,255,.9); }
.mount__note { margin: 26px 0 0; font-size: 15.5px; color: rgba(255,255,255,.86); }
.mount__note a { color: var(--brand-lt); font-weight: 700; }
.mount__note a:hover { color: #fff; }
@media (max-width: 700px) {
  .mount__bg::after {
    background: linear-gradient(180deg, rgba(18,17,16,.80) 0%, rgba(18,17,16,.76) 45%, rgba(18,17,16,.88) 100%);
  }
}

/* --------------------------------------------------------------- area chips
   Chips, not links. These are not pages, and a suburb link that lands on a page
   which does not mention the suburb is worse than plain text. Wrapping chips
   also beat a stacked column badly on a phone when this was measured on
   karinwerner: eight items stacked is ~312px of screen, chips are ~168px. */
.pills {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 10px;
}
.pills li {
  margin: 0; padding: 9px 17px; border-radius: 999px;
  font-size: 14.5px; line-height: 1.2;
  background: rgba(255,255,255,.10); border: 1px solid rgba(255,255,255,.22);
  color: #fff;
}
/* On a WHITE section (/why-abc/) the same component has to invert, or it is a
   white chip on white. Both grounds are stated; neither inherits. */
.sec--white .pills li, .sec--band .pills li {
  background: var(--brand-soft); border-color: transparent; color: var(--brand-dkr);
  font-weight: 700;
}

/* --------------------------------------------------------------- price cards
   Unlike .svc - which is label-only because the client's ten-item list has no
   descriptions - each of these HAS a description, so this is a real card: icon,
   heading, body. No price line: all pricing is on request (2026-09-15).
   Flex, not grid: there are SEVEN cards (Healthy Homes added 2026-09-07), and an auto-fit grid
   strands the seventh hard left under a full row. Fixed per-row widths with no flex-grow keep
   every card the same width, and justify-content centres the last row. */
.prices {
  --pg: clamp(18px, 2.2vw, 26px);
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--pg);
}
.price {
  flex: 0 0 100%;
  display: flex; flex-direction: column; margin: 0;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 26px 26px 24px;
  transition: box-shadow .22s, border-color .22s, transform .22s;
}
@media (min-width: 680px) { .price { flex-basis: calc((100% - var(--pg)) / 2); } }
@media (min-width: 1000px) { .price { flex-basis: calc((100% - 2 * var(--pg)) / 3); } }
.price:hover { box-shadow: var(--shadow-md); border-color: transparent; transform: translateY(-3px); }
.price__ico {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 50px; height: 50px; border-radius: 50%; margin-bottom: 17px;
  background: var(--brand-soft); color: var(--brand-dkr);
}
.price h3 { font-size: 19px; line-height: 1.3; margin-bottom: .5em; color: var(--ink); }
.price__p { font-size: 15.5px; line-height: 1.62; color: var(--muted); margin: 0; }
.prices__note {
  max-width: 760px; margin: clamp(26px, 3vw, 36px) auto 0; text-align: center;
  font-size: 15.5px; color: var(--muted);
}

/* --------------------------------------------------------------- scope list
   The live site's own "interior, exterior, roof, subfloor, and roof cavity"
   sentence, opened out. A definition list in spirit, so the area reads as the
   label and the detail as the value. */
.scope { list-style: none; padding: 0; margin: 0; display: grid; gap: 2px; }
.scope li {
  margin: 0; padding: 14px 0; border-bottom: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline;
}
.scope li:last-child { border-bottom: 0; }
.scope strong {
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 16.5px;
  color: var(--ink); min-width: 108px;
}
.scope span { font-size: 15.5px; color: var(--muted); flex: 1 1 220px; }

/* --------------------------------------------------------------- two-column headings
   .cols2 columns are half width, so the section h2 scale is far too big in
   them. Same type ramp, one step down. */
.cols2 h2 { font-size: clamp(24px, 2.5vw, 31px); margin: 0 0 .55em; }
.cols2 .lead-p { font-size: 16.5px; color: var(--muted); margin-bottom: 1.5em; }
.sec--brand .cols2 .lead-p, .sec--dark .cols2 .lead-p { color: rgba(255,255,255,.88); }

/* --------------------------------------------------------------- centred CTA under a grid */
.sec__after--c { text-align: center; margin-top: clamp(28px, 3.4vw, 40px); }

/* --------------------------------------------------------------- leaky teaser
   On the copper band, where white text measures 5.76:1. Narrow measure: this is
   the longest single run of prose on the home page and at the full 1180px wrap
   it runs well past 100 characters a line. */
.leakteaser { max-width: 820px; margin: 0 auto; text-align: center; }
.leakteaser p { color: #fff; font-size: 16.5px; }
.leakteaser__cta { margin: 30px 0 0; }
