/* ==========================================================================
   Self-hosted fonts. Previously pulled from fonts.googleapis.com, which cost a
   render-blocking round trip to a second origin before first paint (750ms on a
   throttled mobile trace) and sent every visitor IP to Google. Latin subset only.
   The two faces used above the fold are preloaded in each page head.
   ========================================================================== */
@font-face{font-family:'Montserrat';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/montserrat-400.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Montserrat';font-style:normal;font-weight:600;font-display:swap;src:url('fonts/montserrat-600.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Montserrat';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/montserrat-700.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/open-sans-400.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Open Sans';font-style:normal;font-weight:600;font-display:swap;src:url('fonts/open-sans-600.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Open Sans';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/open-sans-700.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}

/* ==========================================================================
   Mobi-Vac — design tokens measured off the live Wix test site
   (obrst166.wixstudio.com/mobivac, read via getComputedStyle 2026-09-09).
   These supersede the older Figma-prototype values in Mobivac_Brand_UI_Reference.docx.
   ========================================================================== */
:root {
  --indigo:       #211652;  /* primary dark — headings, dark sections, pricing card */
  --indigo-soft:  #2C1F66;  /* hover / gradient partner */
  --charcoal:     #2F2B36;  /* secondary dark surface */
  --amber:        #DF864A;  /* the accent, as actually rendered on the test site */
  --amber-dark:   #C9743A;
  --band:         #F7F7F7;  /* alternating light band */
  --white:        #FFFFFF;
  --border:       #E6E6E6;
  --ink:          #33313A;  /* body copy */
  --muted:        #76747B;  /* secondary copy, form placeholders */
  --maxw:         1280px;
  --radius:       10px;
  --radius-btn:   6px;
  --header-h:     75px;  /* actual sticky header height; keep in step with .header__logo img below */

  /* indigo-tinted shadows rather than neutral grey, so depth reads as part of the palette */
  --shadow-sm:    0 1px 2px rgba(33,22,82,.05), 0 2px 8px rgba(33,22,82,.05);
  --shadow-md:    0 2px 6px rgba(33,22,82,.06), 0 12px 28px rgba(33,22,82,.10);
  --shadow-lg:    0 4px 10px rgba(33,22,82,.07), 0 24px 50px rgba(33,22,82,.13);
}

/* the column keeps growing on big monitors instead of stranding content mid-screen */
@media (min-width: 1600px) { :root { --maxw: 1380px; } }

* { box-sizing: border-box; }
/* keeps the sticky header from covering the top of the section a #anchor link jumps
   to, e.g. Get a quote on a service page landing on the breadcrumb/form instead of
   under the header. --header-h tracks the real header height per breakpoint. */
html { scroll-behavior: smooth; scroll-padding-top: var(--header-h); -webkit-tap-highlight-color: transparent; }
body {
  margin: 0;
  font-family: 'Open Sans', system-ui, -apple-system, sans-serif;
  font-size: 17px;
  line-height: 1.7;
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; height: auto; display: block; }
.skip-link { position: absolute; left: -9999px; top: 12px; z-index: 100; background: var(--amber); color: #fff; font-weight: 700; padding: 10px 16px; border-radius: 4px; }
.skip-link:focus { left: 12px; }
a { color: var(--amber); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 {
  font-family: 'Montserrat', system-ui, sans-serif;
  font-weight: 700;
  color: var(--indigo);
  margin: 0 0 .5em;
  line-height: 1.2;
  text-wrap: balance;
}
h1 { font-size: clamp(2.1rem, 4.6vw, 3.5rem); line-height: 1.12; letter-spacing: -.015em; }
h2 { font-size: clamp(1.7rem, 3.1vw, 2.6rem); letter-spacing: -.01em; }
h3 { font-size: 1.2rem; }

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }
.section { padding: 92px 0; }
.section--tight { padding: 56px 0; }
.section--band { background: var(--band); }
.section--indigo { background: var(--indigo); color: #fff; }
.section--indigo h2, .section--indigo h3 { color: #fff; }

/* photo-backed dark section: the image carries texture, the overlay keeps text legible */
.section--photo { position: relative; overflow: hidden; }
.section--photo > .wrap { position: relative; z-index: 2; }
.section__bg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 45%;
}
/* svc-moss.jpg is a portrait shot with the operator high and to the left. The default
   centre crop cuts him out entirely on a wide band, so pull the focal point up and across. */
.section__bg[src*="svc-moss"] { object-position: 30% 14%; }

/* same gradient as the homepage hero, so every photo-backed band matches */
.section--photo::after {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(96deg, rgba(33,22,82,.75) 0%, rgba(33,22,82,.58) 46%, rgba(33,22,82,.16) 100%);
}

/* Eyebrow — Open Sans 700, amber, typed in caps (no CSS transform, matching the test site).
   The short amber rule is the one repeated detail that marks every section opening. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 11px;
  font-weight: 700;
  font-size: 13px;
  color: var(--amber);
  margin: 0 0 14px;
  letter-spacing: .04em;
}
/* The eyebrow is the amber caps alone, with no leading rule. The flex row and gap stay so centred sections still centre. */
.wrap[style*="center"] .eyebrow { justify-content: center; }
.lead { font-size: 1.12rem; color: var(--muted); max-width: 64ch; }
.section--indigo .lead { color: rgba(255,255,255,.78); }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  background: var(--amber);
  border: 1px solid var(--amber);
  color: #fff;
  font-family: 'Open Sans', sans-serif;
  font-weight: 700;
  font-size: 15px;
  /* One box for every button on the site: same width, same height everywhere, on
     desktop and on mobile. The label is centred inside a fixed box rather than the box
     shrink-wrapping the label, which is what used to make widths drift per section. */
  width: 275px;
  max-width: 100%;
  min-height: 50px;
  padding: 12px 22px;
  border-radius: var(--radius-btn);
  cursor: pointer;
  line-height: 1.2;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

/* Three button types, and only three.
   1. Primary amber: solid, hollows out to amber text on an amber border. */
.btn:hover { background: transparent; border-color: var(--amber); color: var(--amber); text-decoration: none; }

/* 2. Ghost on dark: white outline that turns amber. */
.btn--outline { background: transparent; border-color: #fff; color: #fff; }
.btn--outline:hover { background: transparent; border-color: var(--amber); color: var(--amber); }

/* 3. Indigo outline on light: fills solid, border matching the fill. */
.btn--outline-indigo { background: transparent; border-color: var(--indigo); color: var(--indigo); }
.btn--outline-indigo:hover { background: var(--indigo); border-color: var(--indigo); color: #fff; }

.btn--lg { padding: 12px 22px; font-size: 15px; }   /* kept for markup compatibility; the box is now uniform */

/* ---------- header ---------- */
.header {
  position: sticky; top: 0; z-index: 60;
  background: var(--indigo);
  border-bottom: 1px solid rgba(255,255,255,.12);
  transition: box-shadow .25s ease;
}
/* Stays solid indigo the whole way down. .is-scrolled only lifts it off the page with a
   shadow once the reader leaves the top; the colour never changes. */
.header.is-scrolled { box-shadow: 0 6px 24px rgba(0,0,0,.22); }
/* the logo is dark navy artwork, so it needs a light plate on the indigo bar */
.header__logo img { background: #fff; border-radius: 6px; padding: 6px 10px; }
.header__inner {
  position: relative;
  display: flex; align-items: center; gap: 30px;
  padding: 10px 24px; max-width: var(--maxw); margin: 0 auto;
}
.header__logo img { height: 54px; width: auto; }
.nav { display: flex; align-items: center; gap: 30px; margin-left: auto; }
.nav > a, .nav__trigger { color: #fff; font-weight: 600; font-size: 16px; }
.nav > a:hover, .nav__trigger:hover { color: var(--amber); text-decoration: none; }

/* ---------- services dropdown ---------- */
.nav__item { position: relative; }
.nav__trigger {
  display: flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: 'Open Sans', sans-serif; line-height: inherit;
}
.nav__trigger svg { transition: transform .18s ease; }
.nav__menu {
  position: absolute; top: calc(100% + 18px); left: 50%; transform: translateX(-50%) translateY(-6px);
  min-width: 258px; background: #fff;
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 8px; display: flex; flex-direction: column;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
}
/* bridges the gap so the menu doesn't close as the pointer travels to it */
.nav__menu::before { content: ''; position: absolute; left: 0; right: 0; top: -18px; height: 18px; }
.nav__menu a {
  padding: 10px 14px; border-radius: var(--radius-btn);
  color: var(--indigo); font-size: 15px; font-weight: 600; white-space: nowrap;
}
.nav__menu a:hover { background: var(--band); color: var(--amber); text-decoration: none; }

.nav__item--has-menu:hover .nav__menu,
.nav__item--has-menu:focus-within .nav__menu,
.nav__item--has-menu.is-open .nav__menu {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(-50%) translateY(0);
}
.nav__item--has-menu:hover .nav__trigger svg,
.nav__item--has-menu.is-open .nav__trigger svg { transform: rotate(180deg); }
.header__phone {
  display: flex; align-items: center; gap: 8px;
  color: var(--amber); font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: 19px;
  white-space: nowrap;
}
.header__phone:hover { text-decoration: none; }
.nav-toggle { display: none; }

/* ---------- hero ---------- */
/* min-height so the hero holds the fold on a big monitor instead of looking letterboxed;
   the stats row is pushed to the bottom of that space with margin-top:auto */
.hero { position: relative; background: var(--indigo); overflow: hidden; display: flex; min-height: clamp(580px, 80vh, 840px); }
.hero__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 62% 40%; }
/* Brand indigo wash, so the banner reads as one block with the nav above and the trust
   strip below. Slightly lighter than the original so more of the roof shows through. */
.hero::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(96deg, rgba(33,22,82,.75) 0%, rgba(33,22,82,.58) 46%, rgba(33,22,82,.16) 100%);
}
.hero__inner {
  position: relative; z-index: 2;
  padding-top: clamp(88px, 9vw, 130px);
  width: 100%;
  display: flex; flex-direction: column;
}
.hero h1 { color: #fff; max-width: 17ch; margin-bottom: 18px; }
.hero__kicker {
  display: flex; align-items: center; gap: 11px;
  color: var(--amber); font-weight: 700; font-size: 13px; margin: 0 0 16px; letter-spacing: .04em;
}
.hero__sub { color: #F7F7F7; font-size: clamp(1.05rem, 1.6vw, 1.3rem); line-height: 1.5; max-width: 48ch; margin: 0 0 32px; }
.hero__cta { display: flex; gap: 14px; flex-wrap: wrap; }

.hero__stats {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px;
  margin-top: auto; padding: 34px 0 60px;
}
/* back to the lighter weight, sized up so the figures still carry */
.hero__stats .stat strong {
  display: block; font-family: 'Montserrat', sans-serif; font-weight: 400;
  font-size: clamp(2.1rem, 3.8vw, 2.9rem); color: var(--amber); line-height: 1.15;
}
.hero__stats .stat span { color: rgba(255,255,255,.85); font-size: 15px; }

/* ---------- trust strip ---------- */
.strip { background: var(--indigo); border-top: 1px solid rgba(255,255,255,.12); color: #fff; padding: 16px 0; }
.strip__inner { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px 32px; align-items: center; font-size: 14px; }
.strip__item { display: flex; align-items: center; justify-content: center; gap: 9px; }
.strip__item svg { flex: none; color: var(--amber); }
.strip a { color: #fff; font-weight: 700; }

/* ---------- grids ---------- */
.grid { display: grid; gap: 26px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }

/* ---------- FEATURED SERVICE (image + text, alternating) ---------- */
.feature { display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: center; margin-top: 52px; }
.feature + .feature { margin-top: 72px; }
.feature__media img { width: 100%; height: 440px; object-fit: cover; border-radius: var(--radius); box-shadow: var(--shadow-lg); }
.feature--flip .feature__media { order: 2; }

.feature h3 { font-size: clamp(1.5rem, 2.5vw, 2rem); margin-bottom: 16px; }
.feature p { margin: 0 0 16px; color: var(--muted); }
.feature .btn { margin-top: 20px; }

/* three inclusions under each feature block, so the column has substance beside the photo */
.feature__points { list-style: none; margin: 20px 0 0; padding: 18px 0 0; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 11px; }
.feature__points li { display: flex; align-items: flex-start; gap: 11px; font-size: 15px; line-height: 1.5; }
.feature__points svg { flex: none; margin-top: 3px; color: var(--amber); }

.mini-band { margin-top: 72px; }

/* ---------- COMPACT SERVICE CARD (no image) ---------- */
.mini {
  position: relative;
  background: #fff; border: 1px solid var(--border); border-radius: var(--radius);
  padding: 28px 26px; display: flex; flex-direction: column;
  box-shadow: var(--shadow-sm);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.mini:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: #d5d2e0; }
.mini__icon { display: block; color: var(--amber); margin-bottom: 16px; }
.mini__icon svg { width: 42px; height: 42px; display: block; }
.mini h3 {
  font-size: 1rem; text-transform: uppercase; letter-spacing: .02em;
  line-height: 1.35; margin-bottom: 12px;
}
.mini p { margin: 0 0 20px; font-size: 15px; line-height: 1.6; color: var(--muted); }
.mini__link { margin-top: auto; font-weight: 700; font-size: 14px; color: var(--amber); }
/* The whole card is the click target, not just the link. A stretched pseudo element over
   the card keeps one real link in the markup, so it stays keyboard reachable and screen
   readers still announce a single destination. */
.mini:has(.mini__link) { cursor: pointer; }

/* A phone number split across two lines reads as broken copy, which is exactly what
   happened to "Ask Johno on 021 622 761" on the commercial page. */
a[href^="tel:"] { white-space: nowrap; }
.mini__link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.mini:has(.mini__link:focus-visible) { outline: 3px solid var(--amber); outline-offset: 3px; }
.mini__link:focus-visible { outline: none; }

/* ---------- COMMERCIAL BLOCK ---------- */
.commercial {
  display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center;
  background: #fff; border-radius: var(--radius);
  overflow: hidden; margin-top: 72px;
}
.commercial__media { align-self: stretch; }
/* The photo is only half the card, so the card's own overflow:hidden rounds its left
   corners and nothing else. It carries its own radius to get all four. */
.commercial__media img { width: 100%; height: 100%; min-height: 380px; object-fit: cover; border-radius: var(--radius); }
.commercial__body { padding: 44px 48px 44px 0; }
.commercial__body h3 { font-size: clamp(1.4rem, 2.3vw, 1.85rem); margin-bottom: 16px; }
.commercial__body p { color: var(--muted); margin: 0 0 16px; }
.accred {
  display: flex; align-items: center; gap: 26px; flex-wrap: wrap;
  margin: 26px 0; padding: 20px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border);
}
/* the two badges are different shapes — Site Safe is a stacked lockup, Totika a wide
   wordmark — so cap the width too, or Totika optically dwarfs it */
.accred img { height: 52px; width: auto; max-width: 132px; object-fit: contain; }
.accred p { margin: 0; font-size: 13.5px; max-width: 30ch; }

/* ---------- client logo marquee ---------- */
.marquee { margin-top: 40px; overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent); mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent); }
.marquee__track { display: flex; width: max-content; animation: marquee 42s linear infinite; }
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__group { display: flex; align-items: center; gap: 72px; padding-right: 72px; flex: none; }
.marquee img { height: 66px; width: auto; object-fit: contain; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .marquee { overflow-x: auto; }
  .marquee__track { animation: none; }
}

/* ---------- testimonials ---------- */
.quote-card {
  background: #fff; border-radius: var(--radius); padding: 24px;
  display: flex; flex-direction: column; height: 100%;
}
.quote-card .stars { color: var(--amber); letter-spacing: 2px; margin-bottom: 12px; font-size: 14px; }
.quote-card p { margin: 0 0 16px; font-size: 14.5px; line-height: 1.6; color: var(--ink); }
.quote-card cite { margin-top: auto; font-style: normal; font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: 14px; color: var(--indigo); }

/* ---------- split ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: center; }
.split img { border-radius: var(--radius); box-shadow: var(--shadow-lg); }
.pull {
  font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: 1.25rem;
  color: var(--indigo); line-height: 1.4; border-left: 3px solid var(--amber);
  padding-left: 20px; margin: 28px 0 0;
}

/* ---------- our work: stacked before/after beside the copy + USP list ---------- */
.work { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: 60px; align-items: center; }
.work__copy .lead { margin-bottom: 34px; }

.usps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 26px; }
.usp { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 20px; align-items: start; }
.usp__icon { color: var(--amber); }
.usp__icon img { width: 52px; height: auto; display: block; }
.usp h3 { font-size: 1.05rem; margin-bottom: 6px; }
.usp p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--muted); }

/* ---------- before / after ---------- */
.ba { display: grid; gap: 20px; }
.ba figure { position: relative; margin: 0; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-md); }
.ba img { width: 100%; height: 260px; object-fit: cover; display: block; }
.ba figcaption {
  position: absolute; left: 14px; bottom: 14px;
  font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: 12px; letter-spacing: .14em;
  color: #fff; background: rgba(33,22,82,.86); padding: 7px 14px; border-radius: 4px;
}
.ba figcaption.is-after { background: var(--amber); }

/* ---------- areas ---------- */
.areas { display: flex; flex-wrap: wrap; gap: 10px; margin: 26px 0 0; padding: 0; }
.areas li { list-style: none; background: #fff; border: 1px solid var(--border); border-radius: var(--radius-btn); padding: 9px 18px; font-size: 14px; }

/* ---------- FAQ (hairline rows, matching the test site) ---------- */
.faq { margin-top: 34px; border-top: 1px solid var(--border); }
.faq details { border-bottom: 1px solid var(--border); padding: 4px 0; }
.faq summary {
  font-family: 'Montserrat', sans-serif; font-weight: 600; font-size: 1.05rem; color: var(--indigo);
  cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center;
  gap: 18px; padding: 22px 2px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ''; flex: none; width: 11px; height: 11px; border-right: 2px solid var(--amber); border-bottom: 2px solid var(--amber);
  transform: rotate(45deg) translate(-2px, -2px); transition: transform .2s ease;
}
.faq details[open] summary::after { transform: rotate(-135deg) translate(-4px, -4px); }
.faq details p { margin: 0 0 22px; font-size: 15.5px; color: var(--muted); max-width: 80ch; }

/* ---------- quote form ---------- */
.quote-split { display: grid; grid-template-columns: 1fr 1.05fr; gap: 60px; align-items: center; }
.contact-list { list-style: none; padding: 0; margin: 28px 0 0; }
.contact-list li { display: flex; align-items: center; gap: 11px; margin-bottom: 13px; font-size: 15px; color: rgba(255,255,255,.85); }
.contact-list svg { flex: none; color: var(--amber); }
.contact-list a { color: #fff; font-weight: 700; }


/* ---------- footer ---------- */
.footer { background: var(--indigo); color: rgba(255,255,255,.72); padding: 66px 0 26px; font-size: 14.5px; }
.footer .footer__title { color: #fff; font-size: 13px; letter-spacing: .1em; text-transform: uppercase; margin: 0 0 18px; }
.footer a { color: rgba(255,255,255,.72); }
.footer a:hover { color: var(--amber); }
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li { margin-bottom: 4px; }
.footer li a { display: inline-block; padding: 3px 0; }
.footer__logo { height: 78px; width: auto; margin-bottom: 18px; background: #fff; border-radius: 6px; padding: 10px 14px; }
.footer__badges { display: flex; gap: 16px; align-items: center; margin-top: 20px; }
.footer__badges img { height: 42px; width: auto; max-width: 108px; object-fit: contain; background: #fff; border-radius: 4px; padding: 6px 9px; }
.footer__bottom {
  border-top: 1px solid rgba(255,255,255,.15); margin-top: 46px; padding-top: 22px;
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  font-size: 13px; color: rgba(255,255,255,.55);
}

/* ---------- review slider ---------- */
.reviews__top { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 40px; align-items: end; }
.reviews__top .lead { margin: 0; }

.rscore {
  display: flex; align-items: center; gap: 16px;
  background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.16);
  border-radius: var(--radius); padding: 18px 24px;
}
.rscore__fig { font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: 2.2rem; color: #fff; line-height: 1; }
.rscore__stars { position: relative; display: inline-block; font-size: 15px; letter-spacing: 2px; line-height: 1; }
.rscore__stars i { font-style: normal; color: rgba(255,255,255,.28); }
.rscore__stars b { position: absolute; inset: 0; overflow: hidden; white-space: nowrap; color: #F4B400; font-weight: 400; }
.rscore__label { display: block; font-size: 12.5px; color: rgba(255,255,255,.72); margin-top: 6px; }

.rslider { margin-top: 40px; }
.rslider__track {
  display: flex; gap: 24px; overflow-x: auto; scroll-snap-type: x mandatory;
  scroll-behavior: smooth; padding-bottom: 4px;
  scrollbar-width: none; -ms-overflow-style: none;
}
.rslider__track::-webkit-scrollbar { display: none; }

.rcard {
  flex: 0 0 calc((100% - 48px) / 3); scroll-snap-align: start;
  background: #fff; border-radius: var(--radius); padding: 26px 26px 22px;
  display: flex; flex-direction: column; min-height: 232px;
}
.rcard__stars { color: var(--amber); font-size: 15px; letter-spacing: 2px; margin-bottom: 14px; line-height: 1; }
.rcard blockquote { margin: 0 0 18px; font-size: 15px; line-height: 1.6; color: var(--ink); }
.rcard__by { margin-top: auto; padding-top: 16px; border-top: 1px solid var(--border); }
.rcard__by cite { display: block; font-style: normal; font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: 14px; color: var(--indigo); }
.rcard__by span { font-size: 12.5px; color: var(--muted); }

.rslider__nav { display: flex; align-items: center; justify-content: center; gap: 18px; margin-top: 30px; }
.rslider__nav button {
  width: 44px; height: 44px; border-radius: 50%; cursor: pointer; flex: none;
  background: transparent; border: 1px solid rgba(255,255,255,.35); color: #fff;
  display: grid; place-items: center;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.rslider__nav button:hover:not([disabled]) { border-color: var(--amber); color: var(--amber); }
.rslider__nav button[disabled] { opacity: .3; cursor: default; }
.rslider__dots { display: flex; align-items: center; gap: 16px; }
.rslider__dots button {
  position: relative; width: 8px; height: 8px; padding: 0; border-radius: 99px; flex: none;
  background: rgba(255,255,255,.32); border: 0; cursor: pointer;
  transition: width .22s ease, background .22s ease;
}
.rslider__dots button::before { content: ''; position: absolute; inset: -8px; }
.rslider__dots button.is-active { width: 26px; background: var(--amber); }

@media (max-width: 980px) {
  .reviews__top { grid-template-columns: 1fr; gap: 26px; align-items: start; }
  .rscore { justify-self: start; }
  .rcard { flex-basis: calc((100% - 24px) / 2); }
}
@media (max-width: 660px) {
  .rcard { flex-basis: 100%; min-height: 0; padding: 22px 22px 18px; }
  .rslider__track { gap: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .rslider__track { scroll-behavior: auto; }
}

/* ---------- form success and error states ---------- */
.form-done {
  background: #fff; border-radius: var(--radius); padding: 40px 34px; text-align: center;
  box-shadow: var(--shadow-lg); color: var(--ink);
}
.form-done svg { color: var(--amber); margin: 0 auto 16px; display: block; }
.form-done h3 { margin-bottom: 10px; }
.form-done p { margin: 0; color: var(--muted); font-size: 15px; line-height: 1.6; }
/* inside the service page hero card the surrounding card already supplies the chrome */
/* ---------- quote card ----------
   One form, used on the homepage and on every service page, so it lives in the
   shared sheet rather than in service.css. ---------- */
.qcard { background: #fff; border-radius: var(--radius); box-shadow: var(--shadow-lg); overflow: hidden; }
.qcard__head { background: var(--indigo); padding: 17px 22px; }
.qcard__head h2 { color: #fff; font-size: 1.18rem; margin-bottom: 4px; }
.qcard__head p { margin: 0; font-size: 13px; color: rgba(255,255,255,.8); line-height: 1.45; }
.qcard__head a { color: #fff; font-weight: 700; }
/* 'Call Johno on 021 622 761' gets its own line, and the number is held together with
   non-breaking spaces, so a narrow card can never split it across two lines. */
.qcard__call { display: block; margin-top: 3px; }
.qcard__call a { white-space: nowrap; }
.qcard__body { padding: 18px 22px 20px; }
.qcard label { display: block; font-size: 12px; font-weight: 700; margin-bottom: 4px; color: var(--indigo); }
.qcard label span { font-weight: 400; color: var(--muted); }
.qcard input, .qcard select, .qcard textarea {
  width: 100%; padding: 9px 12px; border: 1px solid var(--border); border-radius: var(--radius-btn);
  font-family: inherit; font-size: 14px; margin-bottom: 11px; background: #fff; color: var(--ink);
}
.qcard input::placeholder, .qcard textarea::placeholder { color: #a5a3ad; }
.qcard input:focus, .qcard select:focus, .qcard textarea:focus {
  outline: none; border-color: var(--amber); box-shadow: 0 0 0 3px rgba(223,134,74,.18);
}
.qcard textarea { min-height: 66px; resize: vertical; }
/* display:flex promotes the inline-flex button to block level so the auto margins
   can actually centre it. As inline-flex it only centred under the mobile rule. */
.qcard .btn { display: flex; margin-left: auto; margin-right: auto; }
.qcard__note { font-size: 12px; color: var(--muted); margin: 9px 0 0; text-align: center; line-height: 1.45; }
.qcard__note a { font-weight: 700; }
.qcard__row { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; }
@media (max-width: 660px) {
  .qcard__row { grid-template-columns: 1fr; }
  .qcard__head, .qcard__body { padding-left: 20px; padding-right: 20px; }

  /* Label and field share a row instead of stacking, so the form takes about
     half the vertical space and is more likely to fit the screen without
     scrolling past it. .qcard__row > div is the existing first/last name and
     email/phone wrapper; .qcard__field is the same pattern applied to the
     single fields (address, service, message). */
  .qcard__row > div, .qcard__field { display: flex; align-items: center; gap: 10px; }
  /* Every field is 11px from the next, whichever wrapper it sits in. The row's
     own grid gap only separates the two fields inside it, so without the
     margin the last field of one row sat flush against the first of the next
     (the fields' own margin-bottom is zeroed just below). */
  .qcard__row, .qcard__field { margin-bottom: 11px; }
  /* text-align: left overrides the centred text inherited from .shero__inner's
     mobile centring, which was pushing short labels like "Phone" toward the
     field and leaving long ones like "First name" hard against the left edge,
     an uneven ragged column. A narrower fixed width than the desktop 96px
     gives the field more room without sitting hard against the label. */
  .qcard label { width: 82px; flex: 0 0 82px; margin-bottom: 0; text-align: left; }
  /* min-width: 0 overrides the flex item default of min-width: auto, which for
     a <select> is its longest <option> text — without it the field refuses to
     shrink to the row and overflows the card. */
  .qcard input, .qcard select, .qcard textarea { flex: 1 1 auto; width: auto; min-width: 0; margin-bottom: 0; }
  .qcard textarea { align-self: flex-start; }
}
.qcard .form-done { box-shadow: none; border-radius: 0; padding: 34px 26px; }

.form-error {
  margin: 14px 0 0; padding: 12px 14px;
  background: #FCEDE9; border: 1px solid #E9BFB4; border-radius: var(--radius-btn);
  color: #8C3B26; font-size: 13.5px; line-height: 1.5;
}
.form-error a { color: #8C3B26; font-weight: 700; text-decoration: underline; }

/* ---------- floating Google review badge ---------- */
.gbadge {
  position: fixed; right: 18px; bottom: 18px; z-index: 70;
  width: 166px; background: #fff;
  border: 1px solid var(--border); border-radius: 11px;
  box-shadow: 0 4px 12px rgba(33,22,82,.10), 0 18px 40px rgba(33,22,82,.16);
  padding: 13px 13px 12px; text-align: center;
  opacity: 0; transform: translateY(14px); pointer-events: none;
  transition: opacity .3s ease, transform .3s ease;
}
.gbadge.is-in { opacity: 1; transform: none; pointer-events: auto; }
.gbadge__close {
  position: absolute; top: 6px; right: 6px;
  width: 24px; height: 24px; border: 0; background: none; cursor: pointer;
  color: var(--muted); border-radius: 50%; display: grid; place-items: center; line-height: 1;
}
.gbadge__close:hover { background: var(--band); color: var(--indigo); }
.gbadge__brand { display: flex; align-items: center; justify-content: center; gap: 6px; margin-bottom: 7px; }
.gbadge__brand svg { width: 16px; height: 16px; flex: none; }
.gbadge__brand span { font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: 12.5px; color: #5f6368; }
.gbadge__score { display: flex; align-items: center; justify-content: center; gap: 6px; margin-bottom: 2px; }
.gbadge__score b { font-family: 'Montserrat', sans-serif; font-size: 1.15rem; color: var(--indigo); line-height: 1; }
/* two stacked star rows, the gold one clipped to the exact rating, so 4.4 renders as
   4.4 rather than being rounded to a whole star */
.gbadge__stars { position: relative; display: inline-block; font-size: 15px; letter-spacing: 1px; line-height: 1; }
.gbadge__stars i { font-style: normal; color: #dadce0; }
.gbadge__stars b {
  position: absolute; inset: 0; overflow: hidden; white-space: nowrap;
  color: #F4B400; font-weight: 400; width: 0;
}
.gbadge__count { font-size: 12px; color: var(--muted); margin: 0 0 10px; }
.gbadge__stars { font-size: 13px; }
.gbadge .btn { width: 100%; min-height: 0; border-radius: 99px; font-size: 12.5px; padding: 8px 12px; }

/* ---------- back to top ----------
   Bottom centre, and it only surfaces once scrolling has actually stopped, so it never
   sits over the content while the reader is moving. */
.to-top {
  position: fixed; left: 50%; bottom: 84px; z-index: 71;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 20px 10px 16px; border-radius: 99px; cursor: pointer;
  background: var(--indigo); border: 1px solid rgba(255,255,255,.22); color: #fff;
  font-family: 'Open Sans', sans-serif; font-weight: 700; font-size: 13.5px; line-height: 1;
  box-shadow: 0 4px 12px rgba(33,22,82,.22), 0 14px 34px rgba(33,22,82,.24);
  opacity: 0; transform: translate(-50%, 14px); pointer-events: none;
  transition: opacity .28s ease, transform .28s ease, background .15s ease, border-color .15s ease;
}
.to-top.is-in { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.to-top svg { flex: none; }
.to-top:hover { background: var(--amber); border-color: var(--amber); }
.to-top:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }

@media (max-width: 660px) {
  .gbadge { right: 12px; bottom: 12px; width: 148px; padding: 11px 11px 10px; }
  .gbadge .btn { font-size: 12px; padding: 8px 10px; }
  /* clear of the review badge on a narrow screen */
  .to-top { bottom: 96px; left: 20px; transform: translate(0, 14px); padding: 9px 16px 9px 13px; font-size: 12.5px; }
  .to-top.is-in { transform: translate(0, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .gbadge, .to-top { transition: none; }
}

/* ---------- hero entry fade ----------
   A CSS animation, not the scroll reveal below. The hero is on screen at load, so
   reveal.js adds data-reveal and is-in in the same task: the opacity 0 state is never
   painted and there is nothing to transition from, which is why the hero sat there
   fully formed while everything below it faded. An animation has no such problem, and
   because it is pure CSS it still runs if the JS never loads.

   Homepage hero children are the kicker, headline, sub, buttons and stat row. On the
   service and about heroes the text column's children are staggered, and the quote
   card comes in last as one block rather than field by field. */
@media (prefers-reduced-motion: no-preference) {
  .hero__inner > *,
  .shero__inner > div:first-child > *,
  .shero__inner > .qcard {
    animation: hero-in .68s cubic-bezier(.22,.61,.36,1) both;
  }
  .hero__inner > :nth-child(1),
  .shero__inner > div:first-child > :nth-child(1) { animation-delay: .06s; }
  .hero__inner > :nth-child(2),
  .shero__inner > div:first-child > :nth-child(2) { animation-delay: .15s; }
  .hero__inner > :nth-child(3),
  .shero__inner > div:first-child > :nth-child(3) { animation-delay: .24s; }
  .hero__inner > :nth-child(4),
  .shero__inner > div:first-child > :nth-child(4) { animation-delay: .33s; }
  .hero__inner > :nth-child(n+5),
  .shero__inner > div:first-child > :nth-child(n+5) { animation-delay: .42s; }
  .shero__inner > .qcard { animation-delay: .3s; }
}
@keyframes hero-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- scroll reveal ----------
   Gated behind .has-reveal, which JS only adds when an observer is available and the
   viewer has not asked for reduced motion. Without it every element renders normally,
   so nothing is ever stranded at opacity 0 waiting on a script that did not run. */
.has-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .55s cubic-bezier(.22,.61,.36,1), transform .55s cubic-bezier(.22,.61,.36,1);
}
.has-reveal [data-reveal].is-in { opacity: 1; transform: none; }
/* stagger children of a revealed group */
.has-reveal [data-reveal-group] > * { transition-delay: calc(var(--i, 0) * 70ms); }

@media (prefers-reduced-motion: reduce) {
  .has-reveal [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ---------- responsive ---------- */
@media (max-width: 980px) {
  .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .split, .quote-split { grid-template-columns: 1fr; gap: 38px; }
  .section { padding: 64px 0; }
  .hero { min-height: 0; }
  .hero__inner { padding-top: 64px; }
  .hero__stats { margin-top: 48px; grid-template-columns: repeat(2, 1fr); gap: 26px 24px; padding-bottom: 44px; }
  .feature, .commercial, .work { grid-template-columns: 1fr; gap: 34px; margin-top: 40px; }
  .feature + .feature { margin-top: 54px; }
  .work { margin-top: 0; }
  .ba { grid-template-columns: 1fr 1fr; }
  .mini-band { margin-top: 40px; }
  .feature-band { padding: 26px 20px; margin-top: 40px; }
  .feature-band .feature { gap: 30px; }
  .feature--flip .feature__media { order: 0; }
  .feature__media img { height: 300px; }
  .commercial__media img { min-height: 260px; height: 260px; }
  .commercial__body { padding: 0 28px 36px; }
  .marquee__group { gap: 52px; padding-right: 52px; }
  .nav { display: none; }
  .nav.is-open {
    display: flex; flex-direction: column; align-items: stretch;
    position: absolute; top: 100%; left: 0; right: 0;
    background: var(--indigo); border-bottom: 1px solid rgba(255,255,255,.12);
    padding: 18px 24px 22px; gap: 16px;
    max-height: calc(100vh - 80px); overflow-y: auto;
  }
  /* the dropdown becomes an inline expanding list rather than a floating panel */
  .nav__item { position: static; }
  .nav__trigger { width: 100%; justify-content: space-between; }
  .nav__menu {
    position: static; transform: none; min-width: 0; opacity: 1; visibility: visible;
    background: transparent; box-shadow: none; border-radius: 0;
    border: 0; border-left: 2px solid rgba(255,255,255,.2);
    padding: 0 0 0 12px; margin: 14px 0 2px; gap: 2px;
    display: none; pointer-events: auto;
  }
  .nav__menu::before { display: none; }
  .nav__item--has-menu.is-open .nav__menu { display: flex; transform: none; }
  .nav__menu a { padding: 9px 10px; font-weight: 400; color: rgba(255,255,255,.82); }
  .nav__menu a:hover { background: rgba(255,255,255,.08); color: var(--amber); }
  /* Phone number then menu toggle, both hard against the right edge.
     The auto margin has to sit on the phone, not on the toggle: an auto margin eats all
     the free space BEFORE the element it is on, so putting it on the toggle stranded the
     phone back beside the logo. On the phone it moves the pair across together, and the
     header__inner gap keeps the original spacing between the two. */
  .header__phone { margin-left: auto; }
  /* white on the indigo bar: the default indigo glyph was invisible against it */
  .nav-toggle {
    display: block; order: 3; background: none;
    border: 1px solid rgba(255,255,255,.35); color: #fff;
    border-radius: var(--radius-btn); padding: 9px 12px; cursor: pointer; font-size: 18px; line-height: 1;
  }
  .nav-toggle:hover { border-color: var(--amber); color: var(--amber); }
  .strip__inner { grid-template-columns: 1fr; justify-items: start; gap: 10px; }
  .strip__item { justify-content: flex-start; }
}
@media (max-width: 660px) {
  body { font-size: 16px; }
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
  .usp { grid-template-columns: 44px minmax(0, 1fr); gap: 16px; }
  .usp__icon img { width: 42px; }
  .form__row { grid-template-columns: 1fr; }
  .header__logo img { height: 44px; }
  :root { --header-h: 65px; }
  .header__phone { font-size: 16px; }
  .form { padding: 24px; }
  .feature__media img { height: 240px; }
  .marquee img { height: 50px; }
  .marquee__group { gap: 40px; padding-right: 40px; }
  .accred { gap: 18px; }
  .accred img { height: 44px; }
}

/* ---------- centred hero on phones ----------
   Once the hero collapses to a single column the left-aligned block reads as though it
   is hugging the edge; centring the pill, headline and subhead balances it. The ticked
   list stays left-aligned, because centring ragged multi-line list items looks worse
   than the alignment mismatch does. */
@media (max-width: 720px) {
  .hero__inner { align-items: center; text-align: center; }
  .hero h1, .hero__sub { max-width: none; }
  .hero__kicker { justify-content: center; }
  .hero__cta { justify-content: center; }
}

/* ---------- buttons centre on phones ----------
   display:flex promotes the inline-flex button to block level so the auto margins can
   actually centre it, whatever container it happens to sit in. */
@media (max-width: 720px) {
  .btn { display: flex; margin-left: auto; margin-right: auto; }
  .cta-band__actions { justify-content: center; }
  .area-panel .btn { align-self: center; }
  .feature .btn, .commercial__body .btn { margin-top: 24px; }
}

/* legal links in the footer bar */
.footer__legal { display: flex; flex-wrap: wrap; gap: 18px; }
.footer__legal a { padding: 2px 0; }
.footer__bottom a, .footer__legal a { color: rgba(255,255,255,.62); }
.footer__bottom a:hover, .footer__legal a:hover { color: var(--amber); text-decoration: none; }
.footer__bottom > span a { text-decoration: underline; text-underline-offset: 2px; }
@media (max-width: 760px) { .footer__legal { justify-content: center; gap: 14px; } }
