/* ===========================================================================
   Roofing Company Tauranga
   ---------------------------------------------------------------------------
   The design is a deliberate MATCH of asphaltshinglesqueenstown.co.nz, which
   Richard named as the reference. That site belongs to the same operator, so
   this is one brand family rather than an "inspired by".

   The tokens below were read out of the reference's own stylesheets, not
   guessed from a screenshot:
     wp-content/uploads/bb-theme/skin-69e97fb3b8f58.css   type + link colour
     wp-content/uploads/bb-plugin/cache/10-layout.css     row colours + padding
   That is where #1799d0, the Mulish 800 / Red Hat Text pairing and the
   near-black #0f1113 come from. Guessing from a screenshot is what produced a
   wrong first build on the last site in this fleet.

   Re-theming is one block: every colour is a custom property here.
   =========================================================================== */

:root {
  /* 🔴 THREE blues, and which one you use depends on what sits on top of it.
     Measured, not eyeballed: white text on the reference's #1799d0 is 3.23:1, which fails WCAG AA
     for normal-size text. The reference site itself has that problem; copying it would have
     shipped an accessibility failure across the whole services band, the utility bar, the FAQ
     bars and the form's submit button.
       --brand      #1799d0  the reference blue. Icons, glyphs, rules, tick discs, the hero H1 -
                             anything decorative or large. Non-text graphics need 3:1, and it
                             clears that.
       --brand-bg   #127aa8  SAME hue and saturation, darker. Any surface that carries white BODY
                             text. 4.80:1 against white. Visually near-identical.
       --brand-dkr  #0e5f83  brand-coloured TEXT on a white background. 7.04:1. */
  --brand:        #1799d0;   /* the reference's blue - accents, icons, large display type */
  --brand-bg:     #127aa8;   /* surfaces carrying white body text - 4.80:1 */
  --brand-dk:     #127aa8;   /* hover/pressed (same value as --brand-bg) */
  --brand-dkr:    #0e5f83;   /* brand text on white - 7.04:1 */
  --ink:          #0f1113;   /* near-black: body copy, dark sections */
  --ink-2:        #2a2e33;   /* dark panels */
  --muted:        #565c63;   /* secondary copy on white - 7.0:1 */
  --line:         #dfe3e7;
  --band:         #f4f6f8;   /* light grey band */
  --white:        #ffffff;
  --shadow:       0 10px 34px rgba(15,17,19,.10);
  --shadow-lg:    0 22px 60px rgba(15,17,19,.20);

  --wrap:         1180px;
  --pad:          clamp(20px, 4vw, 34px);
  --sec-y:        clamp(56px, 7.2vw, 92px);
  --radius:       4px;       /* the reference is close to square - 4px, not 12px */

  --hdr-h:        84px;
  --hdr-h-stuck:  66px;
  --util-h:       40px;

  /* Float bar (fleet component) - overridable from /dash via /api/config. */
  --fb-bg:        var(--brand);
  --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; }
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;
}
.btn:hover { background: var(--brand-bg); border-color: var(--brand-bg); transform: translateY(-2px); }
.btn:hover::before { background: #fff; }
.btn--ghost { background: transparent; color: var(--ink); }
.btn--ghost:hover { background: var(--ink); border-color: var(--ink); color: #fff; }
.btn--ghost:hover::before { background: var(--brand); }
.btn--light { background: #fff; color: var(--ink); border-color: #fff; }
.btn--light:hover { background: var(--brand-bg); border-color: var(--brand-bg); color: #fff; }
.btn--full { width: 100%; justify-content: center; }
.btn--sm { padding: 11px 18px; font-size: 13.5px; }

/* Inline text link with the underline the reference uses. */
.tlink {
  color: var(--brand-dkr); font-weight: 700; text-decoration: none;
  border-bottom: 2px solid rgba(23,153,208,.4);
}
.tlink:hover { border-bottom-color: var(--brand); }

.eyebrow {
  display: inline-block;
  font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 13px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--brand-dkr); margin-bottom: 12px;
}

/* --------------------------------------------------------------- utility bar */
.util { background: var(--brand-bg); color: #fff; }
.util__in {
  min-height: var(--util-h);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 12.5px; letter-spacing: .05em; text-transform: uppercase;
}
.util__tag { color: #fff; }
.util__phone { color: #fff; text-decoration: none; white-space: nowrap; }
.util__phone:hover { text-decoration: underline; }
@media (max-width: 700px) {
  .util__tag { display: none; }
  .util__in { justify-content: center; }
}

/* --------------------------------------------------------------- header */
.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(15,17,19,.09); }
.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); }

.brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; color: var(--ink); flex: 0 0 auto; }
.brand__mark { width: 42px; height: 42px; flex: 0 0 auto; color: var(--brand); transition: width .2s, height .2s; }
.hdr[data-stuck] .brand__mark { width: 36px; height: 36px; }
.brand__txt { display: flex; flex-direction: column; line-height: 1; }
.brand__name {
  font-family: 'Mulish', sans-serif; font-weight: 800; font-size: 19px;
  letter-spacing: -.015em; color: var(--ink);
}
.brand__sub {
  font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 11.5px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--brand-dkr); margin-top: 4px;
}

/* 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: 22px; flex-wrap: nowrap; margin-left: auto; }
.nav > a, .nav__dropbtn {
  font-family: 'Mulish', sans-serif; font-weight: 800;
  font-size: 13.5px; letter-spacing: .045em; 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. */
.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(--muted);
}
.nav-m__cta {
  margin-top: 14px; text-align: center; background: var(--ink); 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(--brand); }

@media (max-width: 1120px) {
  .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
   Photo, dark gradient in the lower half only, copy bottom-left. Straight off
   the reference: the gradient does NOT cover the whole photograph, which is
   what keeps the roof visible and stops it reading as a stock banner. */
.hero { position: relative; background: var(--ink); overflow: hidden; }
.hero__bg { position: absolute; inset: 0; }
.hero__bg img { width: 100%; height: 100%; object-fit: cover; }
.hero::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(0deg, rgba(15,17,19,.94) 12%, rgba(15,17,19,.72) 42%, rgba(15,17,19,.18) 78%, rgba(15,17,19,.05) 100%);
}
.hero__in {
  position: relative; z-index: 2;
  min-height: clamp(430px, 62vh, 640px);
  display: flex; flex-direction: column; justify-content: flex-end;
  padding-top: clamp(60px, 12vh, 130px); padding-bottom: clamp(38px, 6vh, 66px);
  color: #fff;
}
.hero--sm .hero__in { min-height: clamp(320px, 44vh, 460px); }
.hero__copy { max-width: 760px; }
.hero .eyebrow { color: #7ecdf0; }
.hero h1 { color: var(--brand); margin-bottom: .38em; }
/* Display type scales to the CONTENT, not to one clamp(). build.mjs measures
   each H1 and stamps the bucket - these run from 22 to 58 characters, and a
   single size either shrinks the short ones or takes the long ones to five
   lines and pushes the CTA off screen. */
h1[data-len="short"] { font-size: clamp(34px, 5.6vw, 60px); }
h1[data-len="long"]  { font-size: clamp(30px, 4.7vw, 51px); }
h1[data-len="xlong"] { font-size: clamp(27px, 3.9vw, 43px); }
.hero__lede { font-size: clamp(16.5px, 1.5vw, 18.5px); color: rgba(255,255,255,.93); max-width: 700px; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 13px; margin-top: 26px; }
.hero__cta .btn--ghost { color: #fff; border-color: rgba(255,255,255,.55); }
.hero__cta .btn--ghost:hover { background: #fff; border-color: #fff; color: var(--ink); }

/* --------------------------------------------------------------- trust strip */
.trust { background: var(--ink); 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: var(--brand); 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: #7ecdf0; }
.sec--dark a:not(.btn):not(.tlink) { color: #7ecdf0; }
/* 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. */
.sec--brand { background: var(--brand-bg); color: #fff; }
.sec--brand h2, .sec--brand h3 { color: #fff; }
/* Fully opaque, not a white at 85-94% alpha. Compositing white down over a mid blue costs real
   contrast, and on a background already close to the AA threshold it is what tips it under. */
.sec--brand .eyebrow { color: #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(24px, 3vw, 38px); }
.card { display: block; text-decoration: none; color: inherit; }
.card__img { display: block; overflow: hidden; border-radius: var(--radius); background: var(--ink); }
.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-top: 17px; }
.card h3 { font-size: 21px; margin-bottom: .42em; }
.card__p { display: block; font-size: 15.5px; line-height: 1.62; }
.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: #fff; }
.sec--brand .card h3 { color: #fff; }
.sec--brand .card__p { color: #fff; }
.sec--brand .card__more { color: #fff; }

/* --------------------------------------------------------------- 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); 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(22px, 2.6vw, 34px); }
.area { background: #fff; border-radius: var(--radius); padding: 26px 26px 28px; border-top: 3px solid var(--brand); box-shadow: var(--shadow); }
.area h3 { font-size: 19px; }
.area p { font-size: 15.5px; margin-bottom: 0; color: var(--muted); }

/* --------------------------------------------------------------- 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: #fff;
  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; }
.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 */
.reviews { text-align: center; }
.reviews__stars { margin: 0 auto 16px; }
.reviews__note { max-width: 660px; margin: 0 auto 30px; color: var(--muted); }
.reviews__slot { margin: 0 auto; min-height: 0; }
.reviews__slot:empty { display: none; }
.reviews__cta { display: flex; flex-wrap: wrap; gap: 13px; justify-content: center; margin-top: 34px; }
/* Trustindex is staged hidden at the top of <main> and moved into the slot by
   site.js. Off-canvas rather than display:none - the widget measures itself as
   it initialises, and a display:none parent gives it a zero-width viewport, so
   the slider renders with every card collapsed. */
/* 🔴 Park it at a fixed negative offset, NOT at left: -100vw.
   The stage has to keep a real width (the widget measures itself as it initialises and a
   zero-width or display:none parent makes the slider render with every card collapsed), so at
   -100vw on a 375px phone its right edge lands at -375 + 1180 = 805px - and the QA sweep caught
   exactly that: 805px of horizontal overflow on every page at 375px wide. A fixed -1400px puts
   the right edge at -220px, off-canvas at every viewport, and overflow to the LEFT does not
   extend the scrollable area in an LTR document.

   The fix is deliberately NOT `overflow-x: hidden` on the body. That hides the symptom, keeps the
   1180px element in the layout, and is how a 156px blowout survived unnoticed on the last site
   built from this template. */
.ti-stage { position: absolute; left: -1400px; top: 0; width: 1180px; height: 1px; overflow: hidden; }
.reviews__slot .ti-widget { margin: 0 auto !important; }

/* --------------------------------------------------------------- gallery */
.gal { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.gal__btn { padding: 0; border: 0; background: var(--ink); 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); }
.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(--brand-bg); color: #fff; border-radius: var(--radius); padding: clamp(26px, 3.6vw, 42px); }
.callout h2, .callout h3 { color: #fff; margin-top: 0; }
.callout p { color: #fff; }
.callout .btn { background: #fff; color: var(--ink); border-color: #fff; }
.callout .btn::before { background: var(--brand); }
.callout .btn:hover { background: var(--ink); border-color: var(--ink); color: #fff; }
.callout .btn:hover::before { background: #fff; }

/* --------------------------------------------------------------- enquiry */
.enq { background: #fff; padding: var(--sec-y) 0; border-top: 1px solid var(--line); }
.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); }
.enq__copy > p { color: var(--muted); }
.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-dkr); text-decoration: none;
}
.enq__big svg { color: var(--brand); }
.enq__big:hover { color: var(--brand); }
.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: var(--ink); }
.enq__facts svg { color: var(--brand); flex: 0 0 auto; margin-top: 4px; }
.enq__facts a { color: var(--brand-dkr); }
.enq__note { font-size: 15px; color: var(--muted); margin: 0; }

/* 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. */
.form { background: var(--ink-2); border-radius: var(--radius); padding: clamp(24px, 3.4vw, 38px); }
.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: 13px;
  letter-spacing: .05em; text-transform: uppercase; color: #ffffff;
}
.form .form__row input,
.form .form__row select,
.form .form__row textarea {
  width: 100%; padding: 12px 14px; font: inherit; font-size: 16px;
  color: #0f1113; -webkit-text-fill-color: #0f1113;   /* WebKit honours this over color */
  background: #ffffff; border: 1px solid #ffffff; border-radius: 3px;
}
.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='%230f1113'/></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: #6b7178; -webkit-text-fill-color: #6b7178; }
.form .form__row input:focus, .form .form__row select:focus, .form .form__row textarea:focus { outline: 3px solid var(--brand); outline-offset: 1px; }
.form .btn { background: var(--brand-bg); border-color: var(--brand-bg); color: #ffffff; margin-top: 8px; }
.form .btn::before { background: #ffffff; }
.form .btn:hover { background: #ffffff; border-color: #ffffff; color: #0f1113; }
.form .btn:hover::before { background: var(--brand); }
.form .err { display: block; color: #ffc4c4; font-size: 13.5px; margin-top: 5px; }
.form .form__msg { margin: 14px 0 0; font-size: 15px; color: #ffffff; }
.form .form__msg.err { color: #ffc4c4; }
.form .form__legal { margin: 14px 0 0; font-size: 13px; color: rgba(255,255,255,.72); }
/* 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); 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); }
.brand--ftr { color: #fff; margin-bottom: 16px; }
.brand--ftr .brand__name { color: #fff; }
.brand--ftr .brand__sub { color: var(--brand); }
.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); }
.ftr__btm-wrap { background: var(--ink); }
.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); }
