/* ===========================================================================
   Valmar Tank Solutions - Tauranga, working across New Zealand
   ---------------------------------------------------------------------------
   Reference: pjbuilders.co.nz (Rob, Capsule 2026-08-17) - a white-dominant
   page, full-bleed dark photographic hero, one brand colour on buttons and
   labels, Red Hat Text body. The logo decides the palette: a TEAL panel with
   two white tanks, a CHARCOAL "Valmar" wordmark and teal "TANK SOLUTIONS", on
   white. So the header is white (the badge is white-ground artwork), the
   accent is the logo teal, and the dark surfaces use the wordmark charcoal.

   Sampled from the artwork (build/images.py): teal #0098A0 (densest bin),
   charcoal #182830. Every ratio below is MEASURED (WCAG formula), and the
   numbers decide which token carries text:

       white on #0098A0 = 3.50:1   <- the raw teal FAILS AA for text
       white on #007B84 = 5.04:1   the teal that carries WHITE text (buttons)
       #00727A on white = 5.69:1   the teal for TEXT on a light surface
       #39C2CB on ink   = 7.04:1   the teal for TEXT on a dark surface
       ink on white     = 15.2:1

   So: buttons are the darker teal with white type, teal TYPE on white uses
   the darker step again, the raw logo teal is reserved for graphics (rules,
   discs), and the light teal is for type on dark. The token NAMES are
   inherited from the fleet template (--brand / --red) because ~200 rules
   reference them; both resolve to the teal system.
   =========================================================================== */

:root {
  --brand:        #0098A0;   /* logo teal. Graphics anywhere, surfaces with INK text; never text on white */
  --brand-bg:     #007B84;   /* teal surface that carries WHITE text - 5.04:1 */
  --brand-dk:     #006C74;   /* hover/pressed on a teal surface - white on it 6.18:1 */
  --brand-lt:     #39C2CB;   /* teal TEXT on dark - 7.04:1 on --ink */
  --brand-dkr:    #00727A;   /* teal TEXT on white - 5.69:1 */
  --brand-soft:   #E3F4F5;   /* pale teal wash - tints, icon discs, hover fills */

  /* The template's second family. This site has ONE accent, so these alias the teal. */
  --red:          #0098A0;
  --red-bg:       #007B84;
  --red-dk:       #006C74;
  --red-soft:     #E3F4F5;

  --ink:          #182830;   /* the wordmark charcoal - 15.2:1 on white */
  --ink-2:        #1F3038;   /* dark panels, the enquiry band and the footer */
  --ink-0:        #10191E;   /* the utility strip and the footer's bottom bar */
  --muted:        #56646B;   /* secondary copy on white - 6.1:1, on band 5.7:1 */
  --line:         #DDE5E8;
  --band:         #F1F6F7;   /* cool off-white - the light band that carries most sections */
  --white:        #ffffff;
  --shadow:       0 6px 24px rgba(24,40,48,.08), 0 2px 6px rgba(24,40,48,.05);
  --shadow-md:    0 14px 40px rgba(24,40,48,.12), 0 3px 10px rgba(24,40,48,.06);
  --shadow-lg:    0 26px 70px rgba(24,40,48,.2);

  --wrap:         1180px;
  --pad:          clamp(20px, 4vw, 34px);
  --sec-y:        clamp(60px, 7.4vw, 100px);
  /* Slightly softer than the concrete site: engineered, not brutal. */
  --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: white icons on the raw logo teal score 3.50:1, so
     the bar uses the darker button teal (white on it 5.04: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 = RED. The logo's red is the action colour on this site and the blue is the brand
   colour, which mirrors the logo's own hierarchy. --red-bg rather than the raw #ED1C24 because
   white on the logo red is 4.38:1 and fails AA for normal-size text; --red-bg is 4.84:1 and is
   visually indistinguishable. */
.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(0,152,160,.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 cyan rule under the eyebrow. Cheap, and it is the one place the raw logo cyan 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. The brief is a white-dominant design, and a full-width cyan strip
   sitting directly above a cyan-and-red 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(24,40,48,.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. Continues the header's surface so the top of every page is one dark field with
   the gold logo sitting in it, which is how the logo artwork was designed to be seen. */
.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(0,152,160,.18), transparent 70%),
    radial-gradient(46% 60% at 96% 96%, rgba(0,152,160,.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 cyan 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
   Kept dark. On a white-dominant page this one band is what stops the hero and the services
   section running into each other as one long stretch of white, and it is where the logo cyan can
   carry text at full strength (7.2:1 on --ink). */
/* GOLD band, not dark: the hero above it is already dark, so a dark strip would merge into it.
   Ink text on the logo gold measures 7.41: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. */
/* A GOLD band carries INK text - white on the gold is 2.42:1. */
.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 cyan 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: #15171B; -webkit-text-fill-color: #15171B;   /* 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: #c9d4dd;
}
.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='%2315171B'/></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: #7c8894; -webkit-text-fill-color: #7c8894; }
.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 on a light panel. #ED1C24 is only 4.38:1 on white, so the darker step is used -
   an error message is small text and has to clear AA. */
/* Error text is a real red - the gold is the ACTION colour and must not double as the warning.
   #B3261E on white is 5.9:1. */
.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; }
/* Two numbers and two addresses under one icon. Each is its own block so the tap target is a
   full line rather than a phone number wedged beside a name. */
.ftr__pair { display: grid; gap: 4px; }
.ftr__pair a { display: inline-block; }
.ftr__who { color: rgba(255,255,255,.55); font-size: 13.5px; margin-left: 6px; }
.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); }
/* A card carrying two people has two destinations, so the link is the ROW, not the card - a
   card-wide hover lift would promise a single link that is not there. Each row keeps a real
   tap target and gets its own affordance instead. */
.ccard--rows .ccard__row {
  display: block; text-decoration: none; color: inherit;
  padding: 10px 0 11px; border-top: 1px solid var(--line);
}
.ccard--rows .ccard__row:first-of-type { border-top: 0; padding-top: 2px; }
.ccard--rows .ccard__row:last-child { padding-bottom: 0; }
.ccard--rows .ccard__row:hover .ccard__v { color: var(--brand-dkr); }
.ccard--rows .ccard__row:focus-visible { outline: 2px solid var(--brand-dkr); outline-offset: 3px; }

/* --------------------------------------------------------------- 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; }

/* ===========================================================================
   RCL-specific components
   =========================================================================== */

/* --------------------------------------------------------------- full-bleed home hero
   The home page uses the client's best landscape photograph (the pool surround) under a dark
   overlay, with the copy on top. Service pages keep the split hero above. 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. */
.hero--bleed { min-height: clamp(520px, 66vh, 720px); 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 hero LOOP, over the photograph and under the overlay.

   Layering: .hero__bg is positioned with z-index 0, so it opens a stacking context and everything
   below is sealed inside it - the copy in .wrap is above all of it whatever happens here. Inside:
   photograph (auto) < video (1) < scrim (2), so the video is graded exactly like the still and the
   white type keeps the contrast that was measured against the photograph.

   It starts at opacity 0 and site.js reveals it on 'playing'. That is deliberate: the photograph
   is the LCP element and must not be replaced by a black box while a 639 kB file downloads, and
   if the video never plays - decoder refuses, autoplay blocked, file 404s - the hero simply stays
   the photograph and nobody can tell anything was meant to happen. */
.hero__vid {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 55% 50%;
  opacity: 0; transition: opacity .9s ease;
  pointer-events: none;
}
.hero__vid[data-playing] { opacity: 1; }

/* Belt and braces alongside the JS check - if the video somehow attaches under reduced motion,
   it still never becomes visible. A hero loop is exactly the "large moving background" this
   preference is about. */
@media (prefers-reduced-motion: reduce) {
  .hero__vid { display: none; }
}

/* 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.
   Sits ABOVE the video (z-index 2) so the loop is graded identically to the still. */
.hero__bg::after {
  content: ''; position: absolute; inset: 0; z-index: 2;
  background:
    linear-gradient(90deg, rgba(24,40,48,.92) 0%, rgba(24,40,48,.8) 42%, rgba(24,40,48,.4) 100%),
    linear-gradient(0deg, rgba(24,40,48,.55) 0%, rgba(24,40,48,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(24,40,48,.84) 0%, rgba(24,40,48,.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); }

/* ===========================================================================
   Valmar-specific components
   =========================================================================== */

/* 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; }
