/* ==========================================================================
   NextPoint Electrics: site stylesheet
   Every value below comes from /OS/brand/tokens.md, /OS/brand/colours.md and
   /OS/brand/typography.md. Do not introduce a colour or a spacing value that
   is not in those files.

   Fonts are self hosted, not loaded from Google Fonts. Both are SIL Open Font
   Licence 1.1, free to self host commercially. Self hosting means no third
   party request, nothing to disclose in a privacy policy, and a faster first
   paint.
   ========================================================================== */

@font-face{font-family:'Archivo';font-style:normal;font-weight:600;font-display:swap;
  src:url('fonts/archivo-latin-600-normal.woff2') format('woff2')}
@font-face{font-family:'Archivo';font-style:normal;font-weight:700;font-display:swap;
  src:url('fonts/archivo-latin-700-normal.woff2') format('woff2')}
@font-face{font-family:'Archivo';font-style:normal;font-weight:800;font-display:swap;
  src:url('fonts/archivo-latin-800-normal.woff2') format('woff2')}
@font-face{font-family:'Archivo';font-style:normal;font-weight:900;font-display:swap;
  src:url('fonts/archivo-latin-900-normal.woff2') format('woff2')}
/* Archivo, mechanically compressed on the x axis by _build/make-compressed.py.
   Used for the above-the-fold wordmark only, and subset to caps and a full stop,
   which is why it is 1.7KB rather than 14. font-display:block, not swap: this is
   the largest thing on the first screen and a swap from a wide fallback to a
   compressed face is a visible reflow of the headline. */
@font-face{font-family:'NP Display';font-style:normal;font-weight:400;
  font-display:block;
  src:url('fonts/np-display-compressed.woff2') format('woff2')}
/* The brand display face, per /OS/brand/typography.md. It replaces the
   x-scaled Oswald instance on the fold headline: that was artificial
   condensing, which the same document forbids, tracked at .213em against a
   spec of +0.02em. Bebas ships in one weight and is SIL OFL like the others. */
/* Archivo, condensed to 78% of its width and 800 weight, instanced out of the
   variable font as a single static cut and subset to the characters the
   headline uses: 5.7KB. A real width axis drawn by the type designer, not a
   horizontal squeeze, so it does not break the brand rule against artificial
   condensing. Used only for the home headline, which in Luke's 12/09 mock is a
   wider, heavier face than the Bebas wordmark below it. */
@font-face{font-family:'Archivo Condensed';font-style:normal;font-weight:800;
  font-display:block;
  src:url('fonts/archivo-condensed-800.woff2') format('woff2')}
@font-face{font-family:'Bebas Neue';font-style:normal;font-weight:400;
  font-display:block;
  src:url('fonts/bebas-neue-latin-400-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;
  src:url('fonts/inter-latin-400-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;
  src:url('fonts/inter-latin-500-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;
  src:url('fonts/inter-latin-600-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;
  src:url('fonts/inter-latin-700-normal.woff2') format('woff2')}

:root{
  /* Brand, print safe */
  --np-navy:#000D23;
  --np-blue:#0868CF;
  --np-white:#FFFFFF;
  /* System, screen only */
  --np-sky:#7FB8F5;
  --np-slate:#4A5568;
  /* Interaction */
  --np-blue-hover:#075AB5;
  --np-blue-active:#0651A4;
  /* Surfaces */
  --np-surface-50:#F0F6FC;
  --np-surface-100:#E6F0FA;
  /* Alternating section band. Was #EDF3FA, a blue tint. Luke moved it to a
     neutral grey on 21/08/2026: the tint was large enough to push the palette
     past the "blue is about one part in twelve" proportion the brand guide
     asks for, and it made the page read washed out. Grey carries the rhythm,
     blue is left to the buttons, headings and icons. Not a brand colour and
     never goes to print: screen surface only. */
  /* Deepened from #F1F2F4 on 31/08/2026. At 4% off white the tint was not a
     band at all: three near-identical light greys stacked, and no contrast
     anywhere in the top third of the page. Still the neutral grey Luke moved
     to on 21/08 rather than the blue tint that washed the palette out — just
     dark enough to be a surface. */
  --np-band:#E9ECF1; --np-band-edge:#D9DEE6;
  /* --np-border (#DAE8F8) measures ~1.05:1 on white, so the step connector
     drawn in it was invisible on every page. One step darker, 30/08/2026. */
  --np-rule:#C2CFE0;
  --np-border:#DAE8F8;
  --np-border-strong:#C1D9F3;
  --np-input-border:#4A5568;
  --np-navy-copy:#DAE8F8;
  --np-sky-hover:#A6CFF8;
  /* Status */
  --np-success:#0F7A45;
  --np-warning:#8A5A00;
  --np-danger:#B54708;
  /* Spacing, 4px base */
  --sp-1:4px;  --sp-2:8px;  --sp-3:12px; --sp-4:16px; --sp-5:24px;
  --sp-6:32px; --sp-7:48px; --sp-8:64px; --sp-9:96px; --sp-10:128px;
  /* Radius */
  --r-sm:4px; --r-md:8px; --r-lg:12px; --r-xl:20px; --r-full:999px;
  /* Borders */
  --bw-hair:1px; --bw-standard:2px; --bw-heavy:4px;
  /* Shadows */
  --sh-1:0 1px 2px rgba(0,13,35,.08);
  --sh-2:0 2px 8px rgba(0,13,35,.10);
  --sh-3:0 8px 24px rgba(0,13,35,.12);
  --sh-4:0 16px 48px rgba(0,13,35,.16);
  /* Motion */
  --mo-fast:120ms; --mo-base:200ms; --mo-slow:320ms;
  --mo-ease:cubic-bezier(.2,0,.2,1);
  /* Type */
  --font-display:'Archivo',system-ui,sans-serif;
  --font-compressed:'NP Display','Archivo',system-ui,sans-serif;
  /* Fold headline only for now. The eyebrows and pill labels stay on
     NP Display until Luke decides whether Bebas goes sitewide. */
  --font-wordmark:'Bebas Neue',Impact,'Arial Narrow Bold',sans-serif;
  --font-hero:'Archivo Condensed','Archivo',system-ui,sans-serif;
  /* One rail for everything above the fold, 12/09/2026. Measured at 1920 before
     this: top bar 370-1550, header 356-1564, promise strip 410-1488, wordmark
     378-1542. Four bands on four measures, 54px of spread on the left edge and
     76px on the right, because each had been solved on its own and never
     against the others. The header's measure becomes the master, since the logo
     and the call button are the outermost objects and the eye reads them as the
     page edge. */
  --fold-rail:min(calc(100% - 40px), max(var(--fold-measure), 980px));

  /* ------------------------------------------------- the first screen unit
     Every measurement above the fold is a fraction of ONE number, taken from
     Luke's mock up at 1548px wide:

       picture   556  = 35.92%        ELECTRICIANS  2.52% type, 5.04% padding
       strip      63  =  4.07%        BUILT IN...   1.17% type
       place names       4.30% type, 12.05% column gap

     The first build sized all of that in vw and let only the PICTURE flex to
     keep "Built in Ocean Grove" above the fold. That was the mistake. These
     proportions need 56.4% of the screen WIDTH in vertical space below the
     header, and Luke's 1920x837 window has 37%. So the picture collapsed to
     445px while the type stayed full size, and the fold came out squat with a
     slab of white under the foot line.

     --fw caps the unit at the width the available HEIGHT can actually carry,
     so the whole block scales together and the proportions hold exactly. On a
     tall window it is the real viewport width and the fold is the mock, pixel
     for pixel; on a short one everything shrinks in step. svh rather than vh,
     so a phone's collapsing address bar cannot push the foot line under the
     fold on first paint. */
  --fw:min(100vw, calc((100svh - 127px) * 1.937));
  /* The wordmark's ink span, 82.2% of the unit, taken from the mock: GEELONG's
     left edge at 170 and the full stop after SURF COAST at 1443 of 1548. The
     header uses the same number, so the logo lines up with the G and the Call
     button lines up with that full stop. */
  --fold-measure:min(94vw, calc(var(--fw) * .822));
  /* The promise strip's height, needed by the hero overlay (which stops
     above it) and by the titleband's remainder arithmetic. One token so
     the three cannot drift. Measured off Luke's 12/09 mock: 48px of
     1619. */
  /* --fold-rail written in viewport units instead of percentages. The rail
     itself uses 100%, which resolves against whatever box it is read in, so
     reading it inside a grid cell gives the cell's width, not the page's.
     Anything that needs the rail as an absolute length uses this one. */
  --fold-rail-vw:min(calc(100vw - 40px), max(var(--fold-measure), 980px));
  --strip-h:calc(var(--fw) * .0331);
  /* How far the electrician's hand and the multimeter in it come down past
     the bottom of the picture, over the promise strip and a little below it.
     Luke's 13/09 mock: the leads finish 14px under a 51px strip on a 1706
     frame. */
  /* How far the cut-out hangs below the picture, so the multimeter clears the
     promise bar instead of being cropped with the rest of him.
     The figure is placed by the picture, which is full bleed, so it scales with
     the window WIDTH; the picture's height scales with --fw, which is capped by
     the window HEIGHT. On a short wide window the two come apart and the
     picture cuts him off at the belt. This is the difference, computed: the
     meter finishes 708 rows down a 2026-wide artwork, so it wants
     100vw * 708/2026 of room measured from the top of the cut-out. Whatever the
     picture does not give it, the drop does. Zero when the window is tall
     enough that the picture already carries the meter. */
  /* Was a correction for the picture and the cut-out drifting apart on short
     wide windows, back when both were pinned to the top. The picture is bottom
     anchored now, so the two are deliberately independent and the drop only did
     harm: at 1568x726 it let the hand and meter hang 58px past the blue bar and
     sit across SURF COAST. Zero keeps him inside the fold. */
  --fg-drop:0px;
  /* How far his hair breaks up over the white header. Measured off Luke's
     13/09 mock: the top of his hair is 9px above the top of the picture on a
     1706 frame. */
  --fg-rise:calc(var(--fw) * .0128);
  /* The step in the promise bar: the third cell sits 17px lower than the other
     two, same mock. */
  /* 13/09: flat. Luke's mock does have a step, but only 11px on an 1798 frame,
     which reads as a straight bar; the site's read as broken. His call: flat. */
  --strip-step:0px;
  --font-body:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,Arial,sans-serif;
  /* Layout */
  --content-max:1180px;
  --measure:68ch;
  --header-h:68px;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  font-family:var(--font-body);
  font-size:16px;
  line-height:1.55;
  color:var(--np-navy);
  background:var(--np-white);
  padding-bottom:72px; /* clears the mobile sticky action bar */
}
img{max-width:100%;height:auto;display:block}

/* --------------------------------------------------------------- headings */
h1,h2{font-family:var(--font-display);font-weight:700;letter-spacing:-.015em;margin:0}
h1{font-size:33px;line-height:1.12}
h2{font-size:26px;line-height:1.2}
@media (min-width:768px){h1{font-size:46px}h2{font-size:33px}}
@media (min-width:1100px){h1{font-size:52px;line-height:1.08}h2{font-size:36px}}
h3{font-family:var(--font-body);font-weight:600;font-size:20px;line-height:1.3;letter-spacing:-.01em;margin:0}
h4{font-family:var(--font-body);font-weight:600;font-size:17px;line-height:1.4;margin:0}
p{margin:0 0 var(--sp-4);max-width:var(--measure)}
ul,ol{margin:0 0 var(--sp-4);padding-left:var(--sp-5);max-width:var(--measure)}
li{margin-bottom:var(--sp-2)}
.lede{font-size:17px;line-height:1.6;color:var(--np-slate);max-width:64ch}
/* 14/09/2026: the eyebrows came off the condensed display face. Compressed
   letterforms + wide tracking + all caps stack up, and at label size the words
   lose their shape and stop being readable at a glance. NP Display also ships
   one weight, so the 700 below was being faked by the browser, thickening
   strokes that had no room. Archivo reads instantly, still looks like a label
   rather than body copy, and matches the heading directly beneath it. The
   condensed faces stay where they are large and short: NP Display on the fold
   headline, Bebas on the place names. Contrast was never the issue, blue on
   white measures 5.4:1. */
.eyebrow{font-family:var(--font-display);font-size:14px;font-weight:700;
  line-height:1.45;letter-spacing:.10em;text-transform:uppercase;
  color:var(--np-blue);margin:0 0 var(--sp-3)}
.small{font-size:14px;line-height:1.5;color:var(--np-slate)}
strong{font-weight:600}
.tnum{font-variant-numeric:tabular-nums}

@media (min-width:768px){
  h1{font-size:48px}
  h2{font-size:34px}
  h3{font-size:22px}
  h4{font-size:18px}
  .lede{font-size:18px;line-height:1.6}
}

/* ------------------------------------------------------------------ links */
a{color:var(--np-blue);text-decoration:underline;text-underline-offset:2px;transition:color var(--mo-fast) var(--mo-ease)}
a:hover{color:var(--np-blue-hover)}
:focus-visible{outline:3px solid var(--np-blue);outline-offset:2px;border-radius:var(--r-sm)}
.on-navy :focus-visible,.footer :focus-visible,.hero :focus-visible{outline-color:var(--np-sky)}

.skip{position:absolute;left:-9999px;top:0;background:var(--np-navy);color:var(--np-white);
  padding:var(--sp-3) var(--sp-4);z-index:200;text-decoration:none;border-radius:0 0 var(--r-md) 0}
.skip:focus{left:0}

/* ------------------------------------------------------------- containers */
.container{width:100%;max-width:var(--content-max);margin:0 auto;padding:0 20px}
@media (min-width:768px){.container{padding:0 32px}}
@media (min-width:1024px){.container{padding:0 40px}}

.section{padding:var(--sp-8) 0}
@media (min-width:768px){.section{padding:var(--sp-9) 0}}
.section--tint{background:var(--np-surface-50)}
.section--navy{background:var(--np-navy);color:var(--np-navy-copy)}
.section--navy h1,.section--navy h2,.section--navy h3,.section--navy h4{color:var(--np-white)}
.section--navy a:not(.btn){color:var(--np-sky)}
.section--navy a:not(.btn):hover{color:var(--np-sky-hover)}
.section--navy .lede,.section--navy .small,.section--navy .eyebrow{color:var(--np-navy-copy)}
.section-head{margin-bottom:var(--sp-6)}
.section-head p{margin-bottom:0}

/* ---------------------------------------------------------------- buttons */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);
  min-height:48px;padding:14px 24px;border-radius:var(--r-md);
  border:var(--bw-standard) solid transparent;
  font-family:var(--font-body);font-weight:600;font-size:16px;line-height:1;letter-spacing:.01em;
  text-decoration:none;cursor:pointer;text-align:center;
  transition:background-color var(--mo-base) var(--mo-ease),color var(--mo-base) var(--mo-ease),border-color var(--mo-base) var(--mo-ease)}
.btn--primary{background:var(--np-blue);border-color:var(--np-blue);color:var(--np-white)}
.btn--primary:hover{background:var(--np-blue-hover);border-color:var(--np-blue-hover);color:var(--np-white)}
.btn--primary:active{background:var(--np-blue-active);border-color:var(--np-blue-active)}
.btn--sky{background:var(--np-sky);border-color:var(--np-sky);color:var(--np-navy)}
.btn--sky:hover{background:var(--np-sky-hover);border-color:var(--np-sky-hover);color:var(--np-navy)}
.btn--secondary{background:transparent;border-color:var(--np-navy);color:var(--np-navy)}
.btn--secondary:hover{background:var(--np-navy);color:var(--np-white)}
.btn--outline-sky{background:transparent;border-color:var(--np-sky);color:var(--np-sky)}
.btn--outline-sky:hover{background:var(--np-sky);color:var(--np-navy)}
.btn--sm{min-height:44px;padding:10px 16px;font-size:15px}
.btn-row{display:flex;flex-wrap:wrap;gap:var(--sp-3);margin-bottom:var(--sp-4)}
.btn-row .btn{flex:1 1 220px}
@media (min-width:600px){.btn-row .btn{flex:0 0 auto}}

/* ----------------------------------------------------------------- header */
.topbar{background:var(--np-navy);color:var(--np-navy-copy);font-size:14px;display:none}
@media (min-width:1024px){.topbar{display:block}}
.topbar .container{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);min-height:46px;
  width:var(--fold-rail);max-width:none;padding-left:0;padding-right:0}
.topbar a{color:var(--np-sky)}
.topbar ul{display:flex;gap:var(--sp-5);list-style:none;margin:0;padding:0;max-width:none}
.topbar li{margin:0}

.header{position:sticky;top:0;z-index:100;background:var(--np-white);border-bottom:var(--bw-hair) solid var(--np-border);box-shadow:var(--sh-2)}
/* Three columns, so the nav sits on the centre of the gap between the logo and
   the Call button rather than wherever flex leaves it. Luke asked for exactly
   that on 30/08/2026; as a flex row with margin-left:auto on the actions, the
   nav was pinned 42px left of that centre. The container is wider than the site
   default because the mock runs the logo and the button close to the edges. */
/* padding:0 here, not the container default of 40px: max-width is a border-box
   measurement, so the default padding would inset the logo 40px inside the G of
   GEELONG rather than lining up with it. The width guard keeps a margin on
   screens too narrow for the measure. */
.header .container{display:grid;grid-template-columns:auto 1fr auto;
  align-items:center;gap:var(--sp-4);min-height:var(--header-h);
  padding-left:0;padding-right:0;
  width:var(--fold-rail);max-width:none}
/* 13/09: Luke asked for the logo in off the left edge and the Quote button in
   off the right. 56px each side, desktop only: on a 390px phone the rail is
   350px wide and 112px of padding crushed the logo to 19px. */
@media (min-width:1024px){
  /* 13/09: the logo's black rectangle sat 11px right of the headline, because
     the logo file carries 8px of its own padding. Pulled in by that 11px so the
     rectangle lands on 338, the same vertical edge as the kicker, the headline,
     the sub line and the Request a Quote button below it. The button steps out
     the same 11px the other way, so the two edges stay symmetrical. */
  .header .container{padding-left:21px;padding-right:21px}
  /* The nav column is 1fr, so shrinking the padding would hand the slack to the
     links and move them. This margin gives that slack straight back, so the logo
     and the button move and the six links do not shift a pixel. */
  .nav{margin-left:35px;margin-right:35px}
}
.brand{display:flex;align-items:center;flex:0 0 auto;padding:var(--sp-2) 0;text-decoration:none}
.brand img{width:170px;height:auto}
@media (min-width:1024px){.brand img{width:190px}}
.header-actions{display:flex;align-items:center;justify-content:flex-end;gap:var(--sp-2)}

/* Desktop navigation */
.nav{display:none}
@media (min-width:1024px){
  /* Same day: the six links were clumped in the middle with a wide hole either
     side. Stretched across the free space between the logo and the button and
     spaced evenly, which is what he meant by fitting better. */
  .nav{display:block;justify-self:stretch}
  /* Between 1024 and 1180 the nav, the logo and the call button together are
     wider than the viewport, which pushed the page 6px sideways. Tighten the
     nav spacing across that band rather than dropping anything. */
  @media (max-width:1180px){
    .nav{justify-self:center}
    .nav a,.nav .navtop{padding-left:9px;padding-right:9px;font-size:14.5px}
    .header-actions .btn{padding-left:16px;padding-right:16px;font-size:14.5px}
  }
  /* Back to var(--sp-1). Luke asked for the five items compressed together as
     they were originally; the wide gaps were my change, not his, and spreading
     them across the bar is not what he wanted. The logo and the Call button are
     held out at the edges by the header measure instead. */
  .nav > ul{display:flex;align-items:center;justify-content:space-evenly;gap:var(--sp-1);
    list-style:none;margin:0;padding:0;max-width:none}
  .nav > ul > li{position:relative;margin:0}
  .nav a,.nav .navtop{display:block;padding:var(--sp-3) var(--sp-3);color:var(--np-navy);text-decoration:none;font-weight:500;font-size:15px;white-space:nowrap;border-radius:var(--r-sm)}
  .nav a:hover,.nav .navtop:hover{color:var(--np-blue);background:var(--np-surface-50)}
  .nav [aria-current="page"]{color:var(--np-blue);box-shadow:inset 0 -3px 0 var(--np-blue)}
  .nav .navtop{background:none;border:0;font-family:var(--font-body);cursor:pointer}
  .nav .navtop::after{content:"";display:inline-block;width:6px;height:6px;margin-left:8px;vertical-align:2px;
    border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg)}
  .submenu{position:absolute;top:100%;left:0;min-width:290px;background:var(--np-white);
    border:var(--bw-hair) solid var(--np-border);border-radius:var(--r-lg);box-shadow:var(--sh-3);
    padding:var(--sp-2);list-style:none;margin:0;display:none;z-index:110}
  .submenu li{margin:0}
  .submenu a{padding:var(--sp-3);font-weight:400;white-space:normal}
  .has-sub:hover .submenu,.has-sub:focus-within .submenu{display:block}
}

/* Mobile navigation */
.navtoggle{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);
  min-height:48px;min-width:48px;padding:0 var(--sp-3);background:transparent;
  border:var(--bw-standard) solid var(--np-navy);border-radius:var(--r-md);color:var(--np-navy);
  font-family:var(--font-body);font-weight:600;font-size:15px;cursor:pointer}
@media (min-width:1024px){.navtoggle{display:none}}
.navtoggle .bars{display:block;width:18px;height:2px;background:currentColor;position:relative}
.navtoggle .bars::before,.navtoggle .bars::after{content:"";position:absolute;left:0;width:18px;height:2px;background:currentColor}
.navtoggle .bars::before{top:-6px}
.navtoggle .bars::after{top:6px}

.mobilenav{display:none;background:var(--np-white);border-top:var(--bw-hair) solid var(--np-border);
  max-height:calc(100vh - var(--header-h));overflow-y:auto}
.mobilenav[data-open="true"]{display:block}
@media (min-width:1024px){.mobilenav{display:none !important}}
.mobilenav ul{list-style:none;margin:0;padding:0;max-width:none}
.mobilenav li{margin:0;border-bottom:var(--bw-hair) solid var(--np-border)}
.mobilenav a{display:block;padding:var(--sp-4) 20px;min-height:48px;color:var(--np-navy);
  text-decoration:none;font-weight:600;font-size:16px}
.mobilenav a:hover{background:var(--np-surface-50)}
.mobilenav .sub a{padding-left:36px;font-weight:400;color:var(--np-slate)}
.mobilenav .sub li{border-bottom:0}
.mobilenav .sub{background:var(--np-surface-50);padding:var(--sp-2) 0}

/* ------------------------------------------------------------------- hero */
.hero{background:var(--np-navy);color:var(--np-navy-copy);padding:var(--sp-8) 0 var(--sp-7)}
@media (min-width:768px){.hero{padding:var(--sp-9) 0 var(--sp-8)}}
.hero h1,.hero .hero-h1{color:var(--np-white);margin-bottom:var(--sp-4);max-width:none;line-height:1.08;font-weight:900;font-family:var(--font-display)}
.hero .lede{color:var(--np-navy-copy);margin-bottom:var(--sp-5)}
.hero .eyebrow{color:var(--np-sky)}
.hero a:not(.btn){color:var(--np-sky)}

.hero-grid{display:grid;gap:var(--sp-6)}
@media (min-width:900px){.hero-grid{grid-template-columns:1.25fr .75fr;align-items:start;gap:var(--sp-7)}}
.hero-points{list-style:none;padding:0;margin:0}
.hero-points li{position:relative;padding-left:28px;margin-bottom:var(--sp-3);font-size:16px}
.hero-points li::before{content:"";position:absolute;left:0;top:7px;width:9px;height:15px;
  border-right:3px solid var(--np-sky);border-bottom:3px solid var(--np-sky);transform:rotate(45deg)}
.hero-card{background:rgba(255,255,255,.06);border:var(--bw-hair) solid rgba(127,184,245,.35);
  border-radius:var(--r-lg);padding:var(--sp-5)}
.hero-card h2{font-size:22px;margin-bottom:var(--sp-3)}
.hero-note{font-size:14px;color:var(--np-navy-copy);margin:0}

/* -------------------------------------------------------------- trust bar */
.trustbar{background:var(--np-surface-50);border-bottom:var(--bw-hair) solid var(--np-border)}
.trustbar ul{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3) var(--sp-4);
  list-style:none;margin:0;padding:var(--sp-5) 0;max-width:none}
@media (min-width:900px){.trustbar ul{grid-template-columns:repeat(5,1fr)}}
.trustbar li{margin:0;font-size:14px;line-height:1.4;color:var(--np-navy);padding-left:26px;position:relative}
.trustbar li::before{content:"";position:absolute;left:0;top:4px;width:8px;height:13px;
  border-right:3px solid var(--np-blue);border-bottom:3px solid var(--np-blue);transform:rotate(45deg)}
.trustbar strong{display:block;font-weight:600}

/* ------------------------------------------------------------------ cards */
.grid{display:grid;gap:var(--sp-5)}
.grid--2{grid-template-columns:1fr}
.grid--3{grid-template-columns:1fr}
@media (min-width:640px){.grid--2,.grid--3{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1000px){.grid--3{grid-template-columns:repeat(3,1fr)}}

.card{background:var(--np-white);border:var(--bw-hair) solid var(--np-border);border-radius:var(--r-lg);
  padding:var(--sp-5);box-shadow:var(--sh-1);
  transition:box-shadow var(--mo-base) var(--mo-ease),transform var(--mo-base) var(--mo-ease)}
.card:hover{box-shadow:var(--sh-3);transform:translateY(-2px)}
.card h3{margin-bottom:var(--sp-2)}
.card p{font-size:15px;color:var(--np-slate);margin-bottom:var(--sp-3)}
.card p:last-child{margin-bottom:0}
.card .cardlink{font-weight:600;font-size:15px;text-decoration:none}
.card .cardlink:hover{text-decoration:underline}
.card .cardlink::after{content:" \203A"}
.card--flat:hover{box-shadow:var(--sh-1);transform:none}

/* ------------------------------------------------------------- prose bits */
.prose{max-width:var(--measure)}
.prose h2{margin:var(--sp-7) 0 var(--sp-4)}
.prose h2:first-child{margin-top:0}
.prose h3{margin:var(--sp-6) 0 var(--sp-3)}

.callout{border-left:var(--bw-heavy) solid var(--np-blue);background:var(--np-surface-50);
  padding:var(--sp-4) var(--sp-5);border-radius:0 var(--r-md) var(--r-md) 0;margin:0 0 var(--sp-5);max-width:var(--measure)}
.callout p:last-child{margin-bottom:0}
.callout h3{margin-bottom:var(--sp-2)}

.pricebox{border:var(--bw-standard) solid var(--np-border);border-radius:var(--r-lg);
  padding:var(--sp-5);background:var(--np-white);margin:0 0 var(--sp-5);max-width:var(--measure)}
.pricebox .amount{font-family:var(--font-display);font-weight:700;font-size:38px;line-height:1;letter-spacing:-.02em;
  color:var(--np-navy);font-variant-numeric:tabular-nums;display:block;margin-bottom:var(--sp-1)}
.pricebox .terms{font-size:14px;color:var(--np-slate);margin:0}

.checklist{list-style:none;padding:0}
.checklist li{position:relative;padding-left:28px;margin-bottom:var(--sp-3)}
.checklist li::before{content:"";position:absolute;left:0;top:6px;width:8px;height:13px;
  border-right:3px solid var(--np-success);border-bottom:3px solid var(--np-success);transform:rotate(45deg)}

.steps{list-style:none;counter-reset:s;padding:0;max-width:var(--measure)}
.steps li{counter-increment:s;position:relative;padding-left:48px;margin-bottom:var(--sp-5)}
.steps li::before{content:counter(s);position:absolute;left:0;top:0;width:34px;height:34px;
  display:flex;align-items:center;justify-content:center;background:var(--np-navy);color:var(--np-white);
  border-radius:var(--r-full);font-family:var(--font-display);font-weight:700;font-size:16px;line-height:1;padding-top:0}
.steps h3{margin-bottom:var(--sp-1)}
.steps p{margin-bottom:0;font-size:15px;color:var(--np-slate)}

/* --------------------------------------------------------------- reviews */
.review{background:var(--np-white);border:var(--bw-hair) solid var(--np-border);border-radius:var(--r-lg);
  padding:var(--sp-5);margin:0;box-shadow:var(--sh-1);display:flex;flex-direction:column}
.review blockquote{margin:0 0 var(--sp-4);font-size:15px;line-height:1.6;color:var(--np-navy)}
.review blockquote p{margin-bottom:var(--sp-3)}
.review blockquote p:last-child{margin-bottom:0}
.review figcaption{margin-top:auto;font-size:14px;color:var(--np-slate)}
.review figcaption b{display:block;color:var(--np-navy);font-weight:600;font-size:15px}
.stars{color:var(--np-warning);letter-spacing:2px;font-size:15px;margin-bottom:var(--sp-3)}
/* Rating line under the H1 in the hero. Desktop only: on a phone the fold is
   deliberately just photo, eyebrow and headline, and Luke asked for mobile to be
   left alone. max-width:none and auto side margins because .titleband paragraphs
   inherit a 686px cap with zero side margins, which pins the box left and
   centres the stars inside the box rather than on the page. */
.hero-rating{display:none}
@media (min-width:1024px){
  .hero-rating{display:flex;align-items:center;justify-content:center;gap:10px;
    margin:14px auto 0;max-width:none;font-family:var(--font-body);font-size:15px;
    font-weight:600;color:var(--np-slate)}
  .hero-rating .stars{color:var(--np-warning);letter-spacing:2px;font-size:16px;
    margin:0}
  .hero-rating b{color:var(--np-navy);font-weight:800}
}

/* -------------------------------------------------------------------- FAQ */
.faq{max-width:var(--measure)}
.faq details{border-bottom:var(--bw-hair) solid var(--np-border)}
.faq summary{cursor:pointer;padding:var(--sp-4) 40px var(--sp-4) 0;font-weight:600;font-size:17px;
  position:relative;list-style:none;min-height:48px;display:flex;align-items:center}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"";position:absolute;right:8px;top:50%;width:10px;height:10px;
  border-right:2px solid var(--np-blue);border-bottom:2px solid var(--np-blue);
  transform:translateY(-70%) rotate(45deg);transition:transform var(--mo-base) var(--mo-ease)}
.faq details[open] summary::after{transform:translateY(-30%) rotate(-135deg)}
.faq .answer{padding:0 0 var(--sp-4)}
.faq .answer p:last-child{margin-bottom:0}

/* ------------------------------------------------------------ suburb bits */
.arealist,.linklist{columns:2;column-gap:var(--sp-5);list-style:none;padding:0;max-width:none}
@media (min-width:768px){.arealist,.linklist{columns:3}}
@media (min-width:1024px){.arealist,.linklist{columns:4}}
.arealist li,.linklist li{margin-bottom:var(--sp-2);break-inside:avoid}
.arealist a{font-size:15px}

.photoslot{border:2px dashed var(--np-border-strong);background:var(--np-surface-50);
  border-radius:var(--r-lg);padding:var(--sp-5);margin:0 0 var(--sp-5);max-width:var(--measure)}
.photoslot p{font-size:14px;color:var(--np-slate);margin-bottom:var(--sp-2)}
.photoslot p:last-child{margin-bottom:0}
.photoslot .tag{display:inline-block;font-size:12px;font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;color:var(--np-warning);margin-bottom:var(--sp-2)}

/* ------------------------------------------------------------------ forms */
.form{max-width:560px}
.field{margin-bottom:var(--sp-4)}
.field label{display:block;font-weight:600;font-size:15px;margin-bottom:var(--sp-2)}
.field .hint{display:block;font-weight:400;font-size:14px;color:var(--np-slate);margin-top:2px}
.field input,.field select,.field textarea{
  width:100%;min-height:48px;padding:12px 14px;font-family:var(--font-body);font-size:16px;
  color:var(--np-navy);background:var(--np-white);
  border:var(--bw-standard) solid var(--np-input-border);border-radius:var(--r-md)}
.field textarea{min-height:132px;resize:vertical}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:3px solid var(--np-blue);outline-offset:1px;border-color:var(--np-blue)}
.form .btn{width:100%}
@media (min-width:600px){.form .btn{width:auto}}

/* ------------------------------------------------------- sticky call bar */
.actionbar{position:fixed;left:0;right:0;bottom:0;z-index:120;background:var(--np-navy);
  border-top:var(--bw-hair) solid rgba(127,184,245,.4);
  display:flex;justify-content:center;align-items:center;gap:var(--sp-2);padding:var(--sp-2);
  box-shadow:0 -2px 8px rgba(0,13,35,.25)}
@media (min-width:1024px){.actionbar{display:none}}
.actionbar a,.actionbar button{
  display:flex;align-items:center;justify-content:center;min-height:48px;padding:var(--sp-2);
  border-radius:var(--r-md);font-family:var(--font-body);font-weight:600;font-size:15px;
  text-decoration:none;cursor:pointer;border:var(--bw-standard) solid var(--np-sky)}
.actionbar .a-call{background:var(--np-sky);color:var(--np-navy);border-color:var(--np-sky)}
.actionbar .a-text,.actionbar .a-quote{background:transparent;color:var(--np-sky)}

/* ----------------------------------------------------------------- footer */
.footer a:not(.btn){color:var(--np-sky);text-decoration:none}
.footer a:not(.btn):hover{color:var(--np-sky-hover);text-decoration:underline}
/* ================================================================== footer
   Rebuilt to the layout of responseelectricianperth.com.au at Luke's request,
   measured off their live site rather than eyeballed: three columns, 48px gap,
   1140px measure, 56px top padding, 13px/700 uppercase column titles with 2px
   tracking in the accent, 14-15px semibold links, and a thin legal bar on a 1px
   10%-white rule. Our fonts and our navy throughout.

   Two deliberate departures from their spec. They set the licence line at 40%
   white, which over #000D23 is 3.77:1 and fails AA, so ours is 50% for 5.3:1.
   And their footer logo is a flat mark; ours is the reversed lockup, per
   brand/logo-rules.md, on the navy the page supplies rather than a panel. */
.footer{background:var(--np-navy);color:var(--np-navy-copy);padding:56px 0 32px}
.footer .container{max-width:1140px}
.np-f{display:grid;gap:48px}
/* Luke wanted more air between the logo block and CONTACT. The brand column
   gets the extra width rather than the gap growing, so the right-hand two
   columns move right without the footer getting wider. */
@media (min-width:900px){.np-f{grid-template-columns:1.9fr 1.42fr 1fr;gap:56px}}

/* The logo file carries clear space inside it, so the grid boxes lined up but
   the drawn border sat 2px below the cap tops of CONTACT and FOLLOW US.
   Measured off the live page: labels 395, border 398. This puts the border
   on the same line as the labels, which is the outermost shape the eye
   aligns to. Desktop only; below 900px the columns stack and there is
   nothing to line up with. */
.np-f-logo{display:inline-block;margin-bottom:22px}
@media (min-width:900px){.np-f-logo{margin-top:-3px}}
.np-f-logo img{width:190px;height:auto;display:block}
.np-f-tag{font-size:14px;font-weight:500;line-height:1.6;
  color:rgba(255,255,255,.6);margin:0 0 18px;max-width:44ch}
.np-f-lic{font-size:12px;font-weight:600;letter-spacing:1px;text-transform:uppercase;
  color:rgba(255,255,255,.5);margin:0}

.np-f-title{font-family:var(--font-body);font-size:13px;font-weight:700;letter-spacing:2px;
  text-transform:uppercase;color:var(--np-sky);margin-bottom:18px}

/* .footer a:not(.btn) sets sky blue at (0,2,1) and silently beat a plain class
   here, which is why the phone and email came out blue instead of white. */
.footer a.np-f-line{display:flex;align-items:center;gap:12px;font-size:15px;font-weight:600;
  color:var(--np-white);text-decoration:none;margin-bottom:14px;min-height:24px;
  overflow-wrap:anywhere}
.footer a.np-f-line:hover{color:var(--np-white);text-decoration:underline}
.footer a.np-f-line svg{flex:0 0 auto;color:var(--np-blue)}
.np-f-addr{display:flex;gap:12px;font-size:13px;font-weight:500;line-height:1.6;
  color:rgba(255,255,255,.6);margin:16px 0 0;max-width:none}
.np-f-addr svg{flex:0 0 auto;margin-top:3px;color:var(--np-blue)}

.np-f-social{display:flex;gap:10px;margin-bottom:18px}
.footer a.np-f-soc{display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;border-radius:var(--r-full);background:rgba(255,255,255,.10);
  border:var(--bw-hair) solid rgba(255,255,255,.16);color:var(--np-white);text-decoration:none}
.footer a.np-f-soc:hover{background:var(--np-blue);border-color:var(--np-blue);color:var(--np-white)}
.footer a.np-f-soc svg{color:var(--np-white)}
.np-f-awards{font-size:13px;font-weight:500;line-height:1.65;
  color:rgba(255,255,255,.6);margin:0;max-width:none}

.np-f-bottom{border-top:var(--bw-hair) solid rgba(255,255,255,.10);margin-top:44px;
  padding-top:24px;display:flex;justify-content:space-between;align-items:center;
  gap:16px;flex-wrap:wrap}
.np-f-bottom p{font-size:12.5px;font-weight:500;letter-spacing:.3px;
  color:rgba(255,255,255,.6);margin:0;max-width:none}
/* WCAG 2.2 SC 2.5.8: these came out 19px tall and failed the 24px minimum. */
.np-f-legal{display:flex;gap:20px;align-items:center}
.np-f-legal a{display:inline-flex;align-items:center;min-height:24px}
.footer a.np-f-legal-link,.np-f-legal a{font-size:12.5px;font-weight:600;
  color:rgba(255,255,255,.68);text-decoration:none}
.np-f-legal a:hover{color:var(--np-white);text-decoration:underline}


/* ------------------------------------------------------------ breadcrumbs */
.crumbs{background:var(--np-surface-50);border-bottom:var(--bw-hair) solid var(--np-border);
  padding:var(--sp-3) 0;font-size:14px}
.crumbs ol{list-style:none;display:flex;flex-wrap:wrap;gap:var(--sp-2);margin:0;padding:0;max-width:none}
.crumbs li{margin:0}
.crumbs li+li::before{content:"\203A";margin-right:var(--sp-2);color:var(--np-slate)}
.crumbs a{color:var(--np-blue)}
.crumbs [aria-current="page"]{color:var(--np-slate)}

/* --------------------------------------------------------------- utility */
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.mb-0{margin-bottom:0}
.cta-band{background:var(--np-navy);color:var(--np-navy-copy);padding:var(--sp-8) 0}
.cta-band h2{color:var(--np-white);margin-bottom:var(--sp-3)}
.cta-band p{color:var(--np-navy-copy)}
.cta-band a:not(.btn){color:var(--np-sky)}

@media (prefers-reduced-motion:reduce){
  *{transition:none !important;animation:none !important}
}

/* -------------------------------------------------------------- imagery
   Two components. .hero-photo is a real photograph in the hero. .photoslot
   is a deliberately visible placeholder: it names the exact shot to take and
   the file name to save it as, so nothing ships looking finished when it is
   not. Replace the <div class="photoslot-fill"> with an <img> and delete the
   .photoslot-brief paragraph.                                             */
.hero-photo{margin:0;border-radius:var(--r-lg);overflow:hidden;border:var(--bw-hair) solid rgba(127,184,245,.35)}
.hero-photo img{display:block;width:100%;height:auto;background:#0a1a33}
.hero-photo figcaption{padding:var(--sp-3);font-size:14px;color:var(--np-navy-copy);background:rgba(255,255,255,.06)}

.photoslot{margin:0 0 var(--sp-6);border:var(--bw-standard) dashed var(--np-input-border);
  border-radius:var(--r-lg);background:var(--np-surface-50);padding:var(--sp-4)}
.photoslot-fill{display:flex;align-items:center;justify-content:center;text-align:center;
  aspect-ratio:3/2;background:var(--np-surface-100);border-radius:var(--r-md);
  color:var(--np-slate);font-size:14px;padding:var(--sp-5)}
.photoslot-brief{margin:var(--sp-3) 0 0;font-size:14px;color:var(--np-slate)}
.photoslot-brief b{color:var(--np-navy)}
.photoslot-brief code{font-size:13px;background:var(--np-white);border:var(--bw-hair) solid var(--np-border);
  border-radius:var(--r-sm);padding:1px 5px}
.hero-aside{display:grid;gap:var(--sp-4)}
.photoslot .tag,.hero-photo .tag{display:inline-block;font-family:var(--font-body);font-weight:500;
  font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:var(--np-slate);margin:0 0 var(--sp-2)}
.photoslot p{font-size:14px;color:var(--np-slate);margin:0 0 var(--sp-2)}
.photoslot p:last-child{margin-bottom:0}
.photoslot strong{color:var(--np-navy)}
.photoslot code{font-size:13px;background:var(--np-white);border:var(--bw-hair) solid var(--np-border);
  border-radius:var(--r-sm);padding:1px 5px;word-break:break-all}

/* Header call button: the full number on desktop where there is room, the word
   alone on a phone. The number is never hidden from the visitor, it sits in the
   hero, the sticky bar, the FAQ and the footer on every page. */
.btn.nowrap{white-space:nowrap}
.calllabel-full{display:none}
.calllabel-short{display:inline}
/* Montserrat is wider than the previous face, so the full phone label no
   longer fits beside the nav at 1024. It switches in at 1200 instead. */
@media (min-width:1100px){.calllabel-full{display:inline}.calllabel-short{display:none}}
/* The hamburger must not be squashed by the label beside it. */
.navtoggle .bars{flex:0 0 18px}

/* ---------------------------------------------------- contrast repairs
   Found by the WCAG 2.2 AA pass over all 46 pages at 390px and 1440px.
   Slate is 7.53:1 on white but only 2.58:1 on the navy footer, so small
   text on navy takes --np-navy-copy instead (15.36:1). The amber used for
   star glyphs is 5.93:1 on white and 3.28:1 on navy, so on navy the stars
   take --np-navy-copy too. Both replacements are existing palette values,
   not new colours. */
.footer .small,.footer p,.cta-band .small,.hero .small{color:var(--np-navy-copy)}
.hero .stars,.footer .stars,.cta-band .stars{color:var(--np-navy-copy)}

/* Long email addresses must not push a 390px viewport sideways. */
body{overflow-wrap:break-word}
a,code,.hero-points li,.checklist li{overflow-wrap:anywhere}


/* ---------------------------------------------------------- real photos
   .jobshot is a published photograph, as opposed to .photoslot which is a
   placeholder still waiting on one. */
.jobshot{margin:0 0 var(--sp-6);border:var(--bw-hair) solid var(--np-border);
  border-radius:var(--r-lg);overflow:hidden;background:var(--np-surface-50)}
.jobshot img{display:block;width:100%;height:auto}
.jobshot figcaption{padding:var(--sp-3) var(--sp-4);font-size:14px;color:var(--np-slate);
  border-top:var(--bw-hair) solid var(--np-border)}


/* ==================================================== home hero, image only
   The illustration owns the whole above-the-fold area with nothing over it.
   The heading, the line under it and the buttons sit in the band directly
   below, where the trust strip used to be. */
.hero--home{position:relative;padding:0;background:var(--np-navy);height:var(--hero-h)}
/* Luke wanted the mobile fold to show exactly three things: the photo, the
   eyebrow, and the H1, with the paragraph below the line. That cannot be a
   fixed height, because a number that fits an iPhone 14 overshoots an SE and
   undershoots a Pro Max, so the hero is sized from the screen instead.
   The 311px reserves what sits between the image and the fold, measured
   rather than guessed: 75 header + 24 gap + 35 eyebrow + 8 gap + 82 H1,
   plus the 73px .actionbar that floats over the bottom of the viewport, plus
   14px so the descender on "Bay" does not touch the bar. Verified at
   390x844, 393x852, 375x667 and 430x932: 14px clearance on all four and the
   lede hidden on all four. Desktop is untouched. */
:root{--hero-h:clamp(210px, calc(100vh - 313px), 700px)}
/* Luke on a real phone: the H1 was still under the action bar. 100vh on
   mobile is the viewport with the browser toolbar HIDDEN, so it is taller
   than what you can actually see and the hero overshot by roughly the
   toolbar height. svh is the viewport at its smallest, toolbar showing,
   which is the honest number here. Headless Chrome has no toolbar, so vh
   and svh are identical in the test rig: this could not have been caught
   locally, only on a handset. Clearance tuned to 16px: measured the H1 ink rather than the box and the
   descenders reach the box edge, so box clearance is real visible gap. 16px
   is the floor that survives a pixel or two of variation between devices
   while giving the photo every remaining pixel. */
@supports (height:100svh){
  :root{--hero-h:clamp(210px, calc(100svh - 313px), 700px)}
}

@media (min-width:768px){:root{--hero-h:clamp(360px, 52vh, 500px)}}
/* Desktop fold, sized from the screen rather than a fixed height so it lands
   the same way on a 768-tall laptop and a 1080 monitor. Mobile is untouched.

   What has to fit above the fold and why the two numbers differ:
   photo, eyebrow, H1, the rating line, and on wide screens the lede as well,
   with the Call and Request a callback buttons fully below the fold so no
   half-button peeks.

   The .callpill is anchored bottom right. On a 1440+ screen the lede's text
   ends at 1096px and the pill starts at 1121px, so they sit side by side. Below
   1440 the pill is proportionally closer to the middle and the text runs into
   it, so those widths push the lede under the fold instead. Measured with
   Range.getClientRects on the text, not the element box: the box is full width
   and reports a collision that the visible text does not have. That mistake sent
   an earlier version of this layout the wrong way.

   Verified at 1440x900, 1536x864, 1600x900, 1920x1080, 1366x768, 1280x800 and
   1024x768: no overlap with the pill, no peeking buttons. */
@media (min-width:1024px){
  :root{--hero-h:clamp(380px, calc(100vh - 411px), 900px)}
  .titleband .lede{margin-top:124px}
}
@media (min-width:1440px){
  :root{--hero-h:clamp(380px, calc(100vh - 405px), 900px)}
  .titleband .lede{margin-top:0}
}
.hero--home .container{display:none}
.hero-scene{position:absolute;inset:0;overflow:hidden}
.hero-scene img{width:100%;height:100%;object-fit:cover;object-position:58% 52%;display:block}
@media (max-width:700px){.hero-scene img{object-position:63% 55%}}

/* --------------------------------------------------------- the title band
   Sits directly under the image, in the slot the trust strip used to hold. */
.titleband{background:var(--np-white);border-bottom:var(--bw-hair) solid var(--np-border)}
.titleband .container{padding-top:var(--sp-5);padding-bottom:var(--sp-7);text-align:center}
@media (min-width:768px){.titleband .container{padding-top:var(--sp-6);padding-bottom:var(--sp-8)}}
.titleband .eyebrow{color:var(--np-blue);margin-left:auto;margin-right:auto}
.titleband h1{color:var(--np-navy);margin:0 auto var(--sp-4);max-width:24ch;
  /* A third larger than the old heading, but tied to the viewport so it
     still lands on one line on a narrow laptop instead of wrapping under
     the floating call pill. */
  font-size:clamp(34px, 8.2vw, 44px);line-height:1.08}
@media (min-width:768px){.titleband h1{font-size:clamp(44px, 5.1vw, 69px);line-height:1.04}}
.titleband .lede{margin:0 auto var(--sp-6);max-width:60ch;color:var(--np-slate)}
/* With 30px of clearance under the H1 the lede box starts inside that gap and
   its first line peeks above the action bar. Pushing it down on phones keeps
   the fold to the three things Luke asked for while leaving the H1 room.
   Must sit after the margin shorthand above, which resets margin-top to 0 at
   the same specificity. */
@media (max-width:767.98px){
  .titleband .lede{margin-top:var(--sp-6)}
}
.titleband .btn-row{justify-content:center}


/* ============================================== home page, centred throughout
   Luke asked for the home page centred rather than left aligned, and for the
   other pages to stay left aligned. Paragraph measure is tightened at the same
   time: centred text is harder to read than left aligned, because the eye has
   to hunt for the start of each line, and shorter lines take most of that cost
   back. */
body.home .section-head{text-align:center}
body.home .section-head .eyebrow,
body.home .section-head .lede,
body.home .section-head h2{margin-left:auto;margin-right:auto}
body.home .prose{max-width:64ch;margin-left:auto;margin-right:auto;text-align:center}
body.home .prose h2,body.home .prose h3{margin-left:auto;margin-right:auto}
body.home .prose p{margin-left:auto;margin-right:auto;max-width:58ch}
body.home .card{text-align:center}
body.home .card p{margin-left:auto;margin-right:auto}
/* 14/09/2026: the review quotes came off centre. Six lines of centred body
   copy reads as a generic testimonial and is slower to scan; every real review
   interface, Google's included, sets them left. */
body.home .steps{max-width:60ch;margin-left:auto;margin-right:auto;text-align:center}
/* padding-left was zeroed here to undo the 48px indent the vertical numbered
   list uses, but the card rule further down sets padding:76px 16px 0, and
   this selector (0,2,2) beats it (0,1,1) on the left only. Result: 16px of
   padding on the right and none on the left, so the text centred inside a
   lopsided box and landed 8px left of its own number, on all four steps at
   every width. Luke found it on a phone; it was on desktop too.
   Both sides stated so they cannot drift apart again. */
body.home .steps li{padding-left:var(--sp-4);padding-right:var(--sp-4);
  padding-top:46px}
body.home .steps li::before{left:50%;transform:translateX(-50%)}
body.home .steps p{margin-left:auto;margin-right:auto}
body.home .callout{text-align:center;border-left:0;border-top:var(--bw-heavy) solid var(--np-blue);
  max-width:64ch;margin-left:auto;margin-right:auto}
body.home .faq{max-width:70ch;margin-left:auto;margin-right:auto}
body.home .arealist{text-align:center}
body.home .btn-row{justify-content:center}
body.home .cta-band{text-align:center}
body.home .cta-band .lede,body.home .cta-band .small{margin-left:auto;margin-right:auto}
/* The area list button sits on its own line, so centre the line it is on. */
body.home .section .btn--secondary{display:block;width:max-content;margin-left:auto;margin-right:auto}

/* Two actions on the sticky mobile bar rather than three, each with an icon.
   Fewer choices at the moment of deciding means a faster decision, and both
   remaining actions are direct contact rather than a form. */
.actionbar a,.actionbar button{display:flex;align-items:center;justify-content:center;gap:8px}
.actionbar svg{width:18px;height:18px;flex:0 0 18px}

/* ==========================================================================
   Styling cues taken from responseelectricianperth.com.au, rebuilt in plain
   CSS. Nothing was copied from their code, and none of their claims were
   copied either: their "30,000+ families" and "Electrician of the Year" are
   theirs, not ours.
   ========================================================================== */

/* Pill buttons, the roundest thing on their page. */
.btn{border-radius:var(--r-full)}
.titleband .btn{padding:16px 34px;font-size:16.5px}

/* One word of the headline in blue, with a full stop, is their signature. */
.accent{color:var(--np-blue)}

/* Their service cards: a soft blue icon chip, a blue edge, a light lift. */
.card--icon{border-left:4px solid var(--np-blue);text-align:left}
body.home .card--icon{text-align:center}
.cardicon{display:inline-flex;align-items:center;justify-content:center;
  width:52px;height:52px;border-radius:var(--r-lg);background:var(--np-surface-100);
  color:var(--np-blue);margin:0 0 var(--sp-4)}
body.home .cardicon{margin-left:auto;margin-right:auto}
.cardicon svg{width:26px;height:26px}

/* The little rating chips under their main button. */
.ratingchips{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--sp-3);
  margin:var(--sp-5) auto 0;padding:0;list-style:none;max-width:none}
.ratingchips li{margin:0}
.ratingchips > li > a,.ratingchips > li > span{display:inline-flex;align-items:center;gap:9px;
  background:var(--np-white);border:var(--bw-hair) solid var(--np-border);
  border-radius:var(--r-full);padding:9px 17px;font-size:14px;color:var(--np-navy);
  text-decoration:none;box-shadow:var(--sh-1);white-space:nowrap}
.ratingchips > li > a:hover{border-color:var(--np-blue)}
.ratingchips b{font-weight:700;font-family:var(--font-display)}
.ratingchips .stars{margin:0;font-size:13px;letter-spacing:.5px}
.ratingchips .src{color:var(--np-slate)}

/* ------------------------------------------------------- the audience pick
   Two boxes under the licence line, one for homeowners and one for property
   managers, so the two audiences split before they scroll. They repeat the
   destinations of the "Which one are you?" section further down the page on
   purpose: most visitors decide in the first screen or not at all. */
.pickrow{display:grid;gap:var(--sp-4);margin:var(--sp-6) auto 0;
  max-width:820px;text-align:left}
@media (min-width:640px){.pickrow{grid-template-columns:1fr 1fr}}
.pick{display:flex;align-items:flex-start;gap:var(--sp-4);
  background:var(--np-white);border:var(--bw-hair) solid var(--np-border);
  border-radius:var(--r-lg);padding:var(--sp-5);text-decoration:none;
  box-shadow:var(--sh-1);
  transition:border-color .15s ease,box-shadow .15s ease,transform .15s ease}
/* Light the whole box up on hover and on keyboard focus, so it is obvious the
   box itself is the link rather than just the line of text inside it. */
.pick:hover,.pick:focus-visible{border-color:var(--np-blue);box-shadow:var(--sh-3);
  transform:translateY(-2px)}
.pick-ico{flex:0 0 72px;width:72px;height:72px;display:inline-flex;
  align-items:center;justify-content:center;border-radius:var(--r-md);
  background:var(--np-surface-100);color:var(--np-navy);
  transition:background-color .15s ease,color .15s ease}
.pick:hover .pick-ico,.pick:focus-visible .pick-ico{background:var(--np-blue);
  color:var(--np-white)}
.pick-ico svg{width:54px;height:54px}
@media (prefers-reduced-motion:reduce){
  .pick{transition:border-color .15s ease,box-shadow .15s ease}
  .pick:hover,.pick:focus-visible{transform:none}
}
.pick-txt{display:flex;flex-direction:column;gap:4px;min-width:0}
.pick-txt b{font-family:var(--font-display);font-weight:700;font-size:17px;
  color:var(--np-navy);line-height:1.25}
.pick-txt > span{font-size:14.5px;color:var(--np-slate);line-height:1.5}
.pick-txt > .pick-go{font-size:14px;font-weight:600;color:var(--np-blue);margin-top:2px}
.pick:hover .pick-go{text-decoration:underline}

/* Their floating contact pill, bottom right, desktop only. The phone bar at
   the bottom of the screen already covers this on mobile, so the two never
   appear at once. */
.callpill{display:none}
@media (min-width:1024px){
  .callpill{display:flex;align-items:center;gap:var(--sp-4);position:fixed;
    right:24px;bottom:24px;z-index:115;background:var(--np-navy);
    border-radius:var(--r-full);padding:10px 10px 10px var(--sp-5);box-shadow:var(--sh-4)}
  .callpill .lbl{display:block;font-size:11px;font-weight:600;letter-spacing:.08em;
    text-transform:uppercase;color:var(--np-sky);line-height:1.3}
  .callpill .num{display:block;font-family:var(--font-display);font-weight:700;
    font-size:19px;color:var(--np-white);text-decoration:none;line-height:1.2}
  .callpill .num:hover{color:var(--np-sky)}
  .callpill .btn{padding:11px 20px;font-size:14.5px}
}
/* The number in the pill is a tap target, so it has to clear 24px. */
@media (min-width:1024px){
  .callpill .num{padding:3px 0;min-height:26px;display:inline-flex;align-items:center}
}
/* The pill is a floating catch for people already reading the page, so it stays
   out of the way until the first scroll rather than sitting on top of the
   heading the moment the page opens. It is hidden in the stylesheet and shown
   by the script, so there is no flash of it before the script runs. */
@media (min-width:1024px){
  .callpill{opacity:0;visibility:hidden;transform:translateY(10px);
    transition:opacity .18s ease,transform .18s ease,visibility .18s}
  .callpill.is-on{opacity:1;visibility:visible;transform:none}
}
@media (prefers-reduced-motion:reduce){
  .callpill{transition:none}
}

/* ---------------------------------------------- sticky mobile bar, v2
   Matching how responseelectricianperth.com.au builds theirs: a dark bar,
   Call Now as a filled rounded button carrying the weight, and SMS Us as a
   plain bold label beside it rather than a second competing button. Their
   blue is #00A4E4; this uses NextPoint Blue so the site keeps one blue.
   Their SMS link puts the mobile number in the page source. Ours does not,
   it is assembled on tap, because you asked for the number not to be shown. */
.actionbar{background:var(--np-navy);padding:10px 14px 12px;gap:10px;
  box-shadow:0 -6px 20px rgba(0,13,35,.35)}
.actionbar a,.actionbar button{font-family:var(--font-display);font-weight:700;
  font-size:15px;letter-spacing:0;min-height:50px}
.actionbar .a-call{flex:0 1 195px;background:var(--np-blue);color:var(--np-white);
  border:0;border-radius:14px}
.actionbar .a-call:hover{background:var(--np-blue-hover)}
.actionbar .a-text{flex:0 1 195px;background:transparent;color:var(--np-white);
  border:2px solid rgba(255,255,255,.9);border-radius:14px}
.actionbar .a-text:hover{background:rgba(255,255,255,.08)}
.actionbar svg{width:19px;height:19px;flex:0 0 19px}


/* ==========================================================================
   VISUAL REFRESH, AUGUST 2026
   Luke asked for the layout treatment from responseelectricianperth.com.au:
   the same information, but broken up as you scroll instead of one long white
   page. Their system, measured off their site, is:

     section padding 80px, eyebrow 13px 700 tracking 2.5px above a heavy
     centred heading, cards with a coloured left edge and an icon tile, and a
     band rhythm of white, light grey, off white, with a dark band for the
     numbers and a dark band for the closing call to action, plus one
     full width colour band as a statement.

   Rebuilt here in our own palette. Nothing of theirs is copied, and no content
   moved: this is a design layer over the pages that already exist.
   ========================================================================== */

/* ------------------------------------------------- band rhythm and spacing */
.section{padding:var(--sp-8) 0}
@media (min-width:768px){.section{padding:80px 0}}
/* The old tint was almost the same value as white, so the alternation did not
   read. Three distinct light levels now, plus the two dark bands. */
.section--tint{background:var(--np-band);border-top:var(--bw-hair) solid var(--np-band-edge);
  border-bottom:var(--bw-hair) solid var(--np-band-edge)}
.section--navy{background:var(--np-navy);color:var(--np-navy-copy)}
.section--blue{background:var(--np-blue);color:var(--np-white);text-align:center}
.section--blue h2,.section--blue h3{color:var(--np-white)}
.section--blue .lede,.section--blue p{color:rgba(255,255,255,.92)}
.section--blue .eyebrow{color:rgba(255,255,255,.85)}
.section--blue .btn--primary{background:var(--np-white);color:var(--np-blue);border-color:var(--np-white)}
.section--blue .btn--primary:hover{background:#EAF3FF;color:var(--np-blue)}
.section--blue .btn--secondary{border-color:rgba(255,255,255,.9);color:var(--np-white)}
.section--blue .btn--secondary:hover{background:rgba(255,255,255,.12);color:var(--np-white)}

/* ------------------------------------------------------- section headings */
.section-head{margin-bottom:var(--sp-7);text-align:center}
/* .section-head is centred on every page, but only the h2 and the lede had the
   auto side margins that make centring work on a block with a max-width. The
   eyebrow is a <p>, so it inherited the 305px measure cap with margin-left:0 and
   sat pinned to the left of the container: on the Ocean Grove page its centre
   was at 562 against a heading centre of 960. The home page looked right only
   because a body.home rule set the margins there. Fixed where it belongs. */
.section-head .eyebrow{margin-left:auto;margin-right:auto;max-width:none;
  color:var(--np-blue);font-weight:700;
  text-transform:uppercase;margin-bottom:var(--sp-3)}
.section-head h2{margin-left:auto;margin-right:auto;max-width:27ch}
.section-head .lede{margin-left:auto;margin-right:auto;max-width:62ch;color:var(--np-slate)}
/* Service areas heading and its line share one measure, so the paragraph runs to
   the same width as the heading above it. 720px is the heading's own single-line
   width at 40px measured, not guessed.
   The default .section-head h2 cap is 22ch and this heading is 33 characters, so
   it wrapped no matter how wide the column was. Raised rather than forced with
   white-space:nowrap: nowrap held one line on desktop but ran the heading clean
   off the side of a 390px phone. This way it holds one line down to tablet and
   wraps properly below that. */
.areas-head h2{max-width:720px}
.areas-head .lede{max-width:720px}
.section--navy .section-head .eyebrow{color:var(--np-sky)}
.section--navy .section-head .lede{color:var(--np-navy-copy)}
@media (min-width:768px){
  .section-head h2{font-size:38px}
}

/* ------------------------------------------------------------------ cards */
.card{background:var(--np-white);border:var(--bw-hair) solid var(--np-border);
  border-left:var(--bw-heavy) solid var(--np-blue);
  border-radius:var(--r-lg);box-shadow:var(--sh-2);padding:var(--sp-6)}
.card:hover{box-shadow:var(--sh-3);transform:translateY(-3px);border-left-color:var(--np-navy)}
.card h3{font-size:19px;margin-bottom:var(--sp-3)}
.card p{font-size:15.5px;line-height:1.6}
.cardicon{width:48px;height:48px;border-radius:var(--r-md);background:var(--np-surface-100);
  color:var(--np-blue);display:inline-flex;align-items:center;justify-content:center;
  margin-bottom:var(--sp-4)}
.cardicon svg{width:26px;height:26px}
.card .cardlink{display:inline-block;margin-top:var(--sp-2);color:var(--np-blue)}
/* Cards sitting on a dark band become dark tiles, the way their numbers band
   does, rather than white blocks punched out of the navy. */
.section--navy .card{background:rgba(255,255,255,.06);border-color:rgba(127,184,245,.28);
  border-left-color:var(--np-sky);box-shadow:none}
.section--navy .card:hover{background:rgba(255,255,255,.10);border-left-color:var(--np-white)}
.section--navy .card h3{color:var(--np-white)}
.section--navy .card p{color:var(--np-navy-copy)}
.section--navy .cardicon{background:rgba(127,184,245,.16);color:var(--np-sky)}
.section--navy .card .cardlink{color:var(--np-sky)}

/* ---------------------------------------------------------- the trust bar
   Same five facts as before, presented as their numbers band: a dark strip
   with the figure large in blue and the label small underneath. */
.trustbar{background:var(--np-white);border-bottom:var(--bw-hair) solid var(--np-border);
  padding:var(--sp-7) 0}
.trustbar ul{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4);
  max-width:1100px;margin:0 auto;padding:0;list-style:none}
@media (min-width:900px){.trustbar ul{grid-template-columns:repeat(5,1fr)}}
.trustbar li{margin:0;padding:var(--sp-5) var(--sp-3);text-align:center;
  background:var(--np-white);border:var(--bw-hair) solid var(--np-border);
  border-radius:var(--r-lg);box-shadow:var(--sh-1);
  color:var(--np-slate);font-size:13.5px;line-height:1.45}
.trustbar li::before{display:none}
.trustbar strong{display:block;font-family:var(--font-display);font-weight:700;
  font-size:23px;line-height:1.15;color:var(--np-blue);margin-bottom:6px}
@media (min-width:768px){.trustbar strong{font-size:27px}}

/* -------------------------------------------------------------------- FAQ
   White rows on a tinted band, each one its own card with a plus toggle. */
.faq details{background:var(--np-white);border:var(--bw-hair) solid var(--np-border);
  border-radius:var(--r-md);margin-bottom:var(--sp-3);box-shadow:var(--sh-1)}
.faq summary{padding:var(--sp-4) 52px var(--sp-4) var(--sp-5)}
.faq summary::after{right:20px}
.faq details[open]{border-color:var(--np-border-strong);box-shadow:var(--sh-2)}
.faq .answer{padding:0 var(--sp-5) var(--sp-5)}

/* ------------------------------------------------------------- steps, 1-4 */
.steps li::before{background:var(--np-blue);color:var(--np-white);border-radius:var(--r-full);
  width:38px;height:38px;display:flex;align-items:center;justify-content:center;
  font-family:var(--font-display);font-weight:700;font-size:17px}

/* ------------------------------------------------------- closing CTA band */
.cta-band{padding:var(--sp-9) 0;text-align:center}
.cta-band .container > *{margin-left:auto;margin-right:auto}
.cta-band h2{max-width:20ch}
.cta-band .lede{max-width:56ch}
.cta-band .btn-row{justify-content:center}
@media (min-width:768px){.cta-band h2{font-size:40px}}

/* Reviews are the one dark band on the page, so the quote cards become dark
   tiles like the numbers tiles on the reference layout. */
.section--navy .review{background:rgba(255,255,255,.06);
  border-color:rgba(127,184,245,.28);box-shadow:none}
.section--navy .review blockquote{color:var(--np-white)}
.section--navy .review figcaption{color:var(--np-navy-copy)}
.section--navy .review figcaption b{color:var(--np-white)}
.section--navy .stars{color:var(--np-navy-copy)}

/* Long prose is where the page felt heaviest. Wider leading, slightly larger
   type and a tighter measure, so a long section reads as something you can
   get through rather than a wall. */
.prose{max-width:68ch}
.prose p{font-size:17px;line-height:1.78;margin-bottom:var(--sp-5)}
.prose h2{margin-top:var(--sp-7)}
.prose h2:first-child{margin-top:0}
.prose h3{margin-top:var(--sp-6)}
.prose ul,.prose ol{font-size:16.5px;line-height:1.7}
.prose li{margin-bottom:var(--sp-4)}
@media (min-width:768px){
  .prose p{font-size:17.5px}
}

/* ==========================================================================
   STRUCTURE, NOT JUST COLOUR
   The first pass only recoloured the bands. These are the structural moves
   from the reference layout: steps run across the page instead of down it,
   the statement runs full width in colour, the area list becomes a grid of
   tiles, and the closing block gets their three-tier action stack.
   ========================================================================== */

/* --------------------------------------------- steps run across, not down */
.steps{max-width:none;display:grid;gap:var(--sp-5);counter-reset:s}
@media (min-width:640px){.steps{grid-template-columns:1fr 1fr}}
.steps li{padding:var(--sp-6) var(--sp-5) var(--sp-5);margin-bottom:0;text-align:center;
  background:var(--np-white);border:var(--bw-hair) solid var(--np-border);
  border-radius:var(--r-lg);box-shadow:var(--sh-1);padding-top:56px}
.steps li::before{left:50%;top:var(--sp-5);transform:translateX(-50%);
  width:44px;height:44px;font-size:18px;background:var(--np-blue)}
.steps h3{font-size:17px;margin-bottom:var(--sp-2)}
.steps p{font-size:15px;line-height:1.6}
.section--navy .steps h3{color:var(--np-white)}
.section--navy .steps p{color:var(--np-navy-copy)}

/* ------------------------------------- the statement runs the full width */
.callout{max-width:none;border-left:0;border-radius:var(--r-lg);text-align:center;
  background:var(--np-blue);color:var(--np-white);
  margin-top:var(--sp-7);margin-bottom:var(--sp-7);
  padding:var(--sp-6) var(--sp-5)}
/* Only a statement that sits in a full width column runs to the edges of the
   screen. Inside a two column layout, like the contact page, that would push
   the page sideways, so there it stays a contained blue block. */
.container > .prose > .callout{border-radius:0;
  margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);
  margin-top:var(--sp-8);margin-bottom:var(--sp-8);
  padding:var(--sp-8) var(--sp-5)}
.callout h3{color:var(--np-white);font-size:26px;max-width:24ch;margin:0 auto var(--sp-3)}
.callout p{color:rgba(255,255,255,.94);font-size:17px;line-height:1.7;
  max-width:60ch;margin-left:auto;margin-right:auto}
.callout a{color:var(--np-white);text-decoration:underline}
@media (min-width:768px){
  .callout{padding:72px var(--sp-6)}
  .callout h3{font-size:32px}
  .callout p{font-size:18px}
}
/* On a dark band the statement inverts, so two dark blocks do not collide. */
.section--navy .callout{background:rgba(127,184,245,.10);
  border-top:var(--bw-hair) solid rgba(127,184,245,.28);
  border-bottom:var(--bw-hair) solid rgba(127,184,245,.28)}

/* ------------------------------------------------- service areas as tiles */
.arealist{columns:auto;display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3)}
@media (min-width:640px){.arealist{grid-template-columns:repeat(3,1fr)}}
@media (min-width:1024px){.arealist{grid-template-columns:repeat(4,1fr)}}
.arealist li{margin-bottom:0}
.arealist a{display:flex;align-items:center;justify-content:center;text-align:center;
  min-height:52px;padding:var(--sp-3) var(--sp-4);background:var(--np-white);
  border:var(--bw-hair) solid var(--np-border);border-radius:var(--r-md);
  color:var(--np-navy);text-decoration:none;font-weight:600;font-size:14.5px;
  box-shadow:var(--sh-1);transition:border-color .15s ease,color .15s ease,box-shadow .15s ease}
.arealist a:hover{border-color:var(--np-blue);color:var(--np-blue);box-shadow:var(--sh-2)}
.section--navy .arealist a{background:rgba(255,255,255,.06);color:var(--np-white);
  border-color:rgba(127,184,245,.28);box-shadow:none}
.section--navy .arealist a:hover{color:var(--np-sky);border-color:var(--np-sky)}

/* ---------------------------------------------- heavier section headings */
h2{letter-spacing:-.015em}
.section-head h2{font-size:30px}
@media (min-width:768px){.section-head h2{font-size:40px}}
@media (min-width:1100px){.section-head h2{font-size:44px}}

/* --------------------------------------------------- closing action stack */
.cta-band .btn-row{gap:var(--sp-4);margin-top:var(--sp-6)}
.cta-band .btn--secondary{border-color:rgba(255,255,255,.85);color:var(--np-white)}
.cta-band .btn--secondary:hover{background:rgba(255,255,255,.12);color:var(--np-white)}
.cta-band .small{margin-top:var(--sp-6)}
/* The home page centring block sets a measure and auto margins on the
   statement, which outranks the plain class selector above. Restate it here at
   equal specificity so the statement runs full width on the home page too. */
body.home .callout{max-width:none;border-top:0}
body.home .container > .prose > .callout{
  margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw)}

/* A button sitting on the blue statement has to invert, or it is blue on blue. */
.callout .btn--secondary,.callout .btn--primary{background:var(--np-white);
  color:var(--np-blue);border-color:var(--np-white)}
.callout .btn--secondary:hover,.callout .btn--primary:hover{background:#EAF3FF;
  color:var(--np-blue);border-color:#EAF3FF}
/* The steps sit inside the prose column, which is deliberately narrow for
   reading. Four columns need the full container width, so they break out of
   the measure rather than squeezing into it. */
/* The steps break out of the reading column symmetrically, and only once the
   page is wide enough to hold four across. A transform was used here first,
   which centred the painted box but left a layout box wider than the screen
   and 48px of sideways scroll with it. */
@media (min-width:1200px){
  /* body.home .steps sets a 60ch measure, which outranks a plain class rule,
     so the width release has to sit at this specificity too. */
  .container > .prose > .steps{margin-left:-207px;margin-right:-207px;
    max-width:none;width:auto}
}

/* ==========================================================================
   REFERENCE COMPONENTS, MEASURED
   Buttons, the step line and the location tiles rebuilt to match the shapes
   measured off the reference site: 14px radius, weight 800, no border and no
   shadow on buttons; the process shown as a connector line with numbered
   circles rather than boxes; and each area as a tile with a pin icon and a
   "view" link. Our palette, our words, their shapes.
   ========================================================================== */

/* ---------------------------------------------------------------- buttons */
.btn{border-radius:14px;font-weight:800;letter-spacing:.01em;border-width:0;
  padding:16px 32px;font-size:16px;min-height:52px}
.btn--primary{background:var(--np-blue);color:var(--np-white)}
.btn--primary:hover{background:var(--np-blue-hover)}
.btn--secondary{background:transparent;border-width:2px;border-style:solid;
  border-color:var(--np-navy);color:var(--np-navy)}
.btn--lg,.cta-band .btn,.callout .btn{padding:18px 44px;font-size:17.5px;min-height:58px}
.btn--sm{padding:11px 20px;font-size:14px;min-height:44px}
.titleband .btn{padding:18px 40px;font-size:17px}
.header .btn{border-radius:14px}

/* --------------------------------------------------- the process, as a line
   Their version is not a row of boxes. It is a thin line across the page with
   a numbered circle sitting on it, and the words underneath. */
.steps{max-width:none;display:grid;gap:var(--sp-5);counter-reset:s;position:relative;
  padding-top:0}
@media (min-width:640px){.steps{grid-template-columns:1fr 1fr}}
/* The connector is drawn between each circle and the next one, rather than as
   one line across the whole row. Pages have three steps or four, and a single
   line sized for four ran out into empty space on the three step pages. */
@media (min-width:1200px){
  /* .prose ol caps lists at a reading measure, which also caught the steps
     and squeezed four columns into two. */
  .prose > .steps,.steps{max-width:none;
    grid-template-columns:repeat(auto-fit,minmax(160px,1fr));justify-content:stretch}
  .steps li::after{content:"";position:absolute;top:28px;
    left:calc(50% + 34px);right:calc(-50% + 34px);height:2px;
    background:var(--np-border-strong);z-index:0}
  .steps li:last-child::after{display:none}
}
.section--navy .steps li::after{background:rgba(127,184,245,.3)}
.steps li{background:none;border:0;box-shadow:none;border-radius:0;
  padding:76px var(--sp-4) 0;margin-bottom:0;text-align:center;position:relative;z-index:1}
.steps li::before{content:counter(s);position:absolute;left:50%;top:0;
  transform:translateX(-50%);width:58px;height:58px;border-radius:var(--r-full);
  background:var(--np-blue);color:var(--np-white);display:flex;align-items:center;
  justify-content:center;font-family:var(--font-display);font-weight:700;font-size:23px;
  box-shadow:0 0 0 6px var(--np-white),0 6px 16px rgba(8,104,207,.28);z-index:2}
.steps h3{font-size:18px;margin-bottom:var(--sp-2);color:var(--np-navy)}
.steps p{font-size:15.5px;line-height:1.65;color:var(--np-slate)}
/* The step number sits on a ring the colour of whatever band it is on, so it
   has to follow --np-band or the ring shows as a pale blue halo. */
.section--tint .steps li::before{box-shadow:0 0 0 6px var(--np-band),0 6px 16px rgba(8,104,207,.28)}
.section--navy .steps::before{background:rgba(127,184,245,.3)}
.section--navy .steps li::before{box-shadow:0 0 0 6px var(--np-navy)}
.section--navy .steps h3{color:var(--np-white)}
.section--navy .steps p{color:var(--np-navy-copy)}

/* ------------------------------------------------- areas, as tiles with a pin */
.arealist{columns:auto;display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4)}
@media (min-width:640px){.arealist{grid-template-columns:repeat(3,1fr)}}
@media (min-width:1024px){.arealist{grid-template-columns:repeat(4,1fr)}}
.arealist li{margin-bottom:0}
.arealist a{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  text-align:center;gap:6px;min-height:132px;padding:var(--sp-5) var(--sp-3);
  background:var(--np-surface-50);border:var(--bw-hair) solid transparent;
  border-radius:var(--r-lg);color:var(--np-navy);text-decoration:none;
  font-family:var(--font-display);font-weight:700;font-size:16px;box-shadow:none;
  transition:background-color .15s ease,border-color .15s ease,box-shadow .15s ease}
.arealist a::before{content:"";display:block;width:44px;height:44px;margin-bottom:var(--sp-2);
  border-radius:var(--r-md);background-color:var(--np-surface-100);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230868CF' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21s7-5.7 7-11a7 7 0 1 0-14 0c0 5.3 7 11 7 11z'/%3E%3Ccircle cx='12' cy='10' r='2.6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:center;background-size:24px 24px}
.arealist a::after{content:"View suburb \2192";display:block;font-family:var(--font-body);
  font-weight:600;font-size:14px;color:var(--np-blue)}
.arealist a:hover{background:var(--np-white);border-color:var(--np-blue);box-shadow:var(--sh-2)}
.section--navy .arealist a{background:rgba(255,255,255,.06);color:var(--np-white);
  border-color:rgba(127,184,245,.22)}
.section--navy .arealist a::before{background-color:rgba(127,184,245,.16)}
.section--navy .arealist a::after{color:var(--np-sky)}
.section--navy .arealist a:hover{background:rgba(255,255,255,.12);border-color:var(--np-sky)}

/* ==========================================================================
   BLOCKS CENTRED ON THE PAGE
   Every constrained block sat hard against the left edge of the container,
   leaving a wide empty margin down the right of every page. The text stays
   left aligned and nothing about the blocks changes: the column itself now
   sits in the middle of the page.

   This also fixes the full width statement and the process line, both of
   which were centred on the reading column rather than on the page, so they
   ran off to the left. Once the column is centred they land correctly.
   ========================================================================== */
.prose,.pricebox,.checklist,.photoslot,.faq,.table-wrap,
.section > .container > .callout{margin-left:auto;margin-right:auto}
.prose > .pricebox,.prose > .checklist,.prose > .photoslot{margin-left:auto;margin-right:auto}
/* Inside a two column layout the block should fill its column, not centre
   within it, so the grid children opt out. */
.grid .prose,.grid .pricebox,.grid .checklist,.grid .photoslot,.grid .faq{
  margin-left:0;margin-right:0}

/* The Homeowners dropdown carries fifteen services, which is taller than the
   screen on a 1440x800 laptop. Cap it to what is actually visible and let it
   scroll, so the last item is always reachable. */
@media (min-width:1024px){
  .nav .submenu{max-height:calc(100vh - var(--header-h) - 56px);overflow-y:auto;
    overscroll-behavior:contain}
}

/* ==========================================================================
   OUTLINE BUTTONS GOT NO OUTLINE
   The button restyle set border-width to 0 across the board, which is right
   for the filled buttons and wrong for the outline ones. On a navy band that
   left "Send a message" as bare sky-blue text with no button shape around it,
   on every page with a hero or a closing call to action. The outline is white
   here rather than sky, so it reads as a button at a glance against navy, and
   it matches the SMS button on the phone bar.
   ========================================================================== */
/* Third button under the two primaries in the closing CTA: quieter than the
   outline, so the order reads Call, then SMS, then the form. Sky rather than
   blue because the band is navy.
   This has to sit AFTER .btn{border-width:0} further up, which is the same rule
   that once made the Send a message button invisible on dark bands. Declared
   earlier at the same specificity it silently loses its border. */
.btn--ghost-sky{background:transparent;color:var(--np-sky);border-width:2px;
  border-style:solid;border-color:rgba(127,184,245,.5);font-weight:700}
.btn--ghost-sky:hover{background:rgba(127,184,245,.12);color:var(--np-sky-hover);
  border-color:rgba(127,184,245,.8)}
/* A <button> does not inherit the page font the way an <a> does. */
button.btn{font-family:var(--font-display);cursor:pointer}
/* ------------------------------------------- quick callback form in the CTA
   Luke wanted the reference site's behaviour: two buttons and a quiet third
   one, and the third drops a short form open underneath it in place.

   <details>/<summary> rather than a JS toggle, so it opens with scripting off
   and the keyboard and screen reader behaviour is the browser's rather than
   hand-rolled. The summary is styled as the button; the default disclosure
   triangle is removed on both engines. */
/* Luke wanted this sitting twice as far below the two primaries. Measured
   at 16px, so 32px. */
.quickform{margin-top:var(--sp-6)}
.quickform > summary{display:inline-flex;list-style:none;cursor:pointer}
.quickform > summary::-webkit-details-marker{display:none}
.quickform > summary::marker{content:""}
.quickform[open] > summary{margin-bottom:var(--sp-5)}

.quickform-body{max-width:640px;margin:0 auto;text-align:left}
.qf-grid{display:grid;gap:var(--sp-3)}
@media (min-width:560px){.qf-grid{grid-template-columns:1fr 1fr}}
.quickform-body .field{margin-bottom:var(--sp-3)}
.quickform-body input,.quickform-body textarea{
  width:100%;min-height:52px;padding:14px 16px;border-radius:var(--r-md);
  border:var(--bw-hair) solid rgba(255,255,255,.22);background:rgba(255,255,255,.06);
  color:var(--np-white);font-family:var(--font-body);font-size:16px}
.quickform-body textarea{min-height:110px;resize:vertical}
/* Placeholder text is the only visible field name here, so it has to clear AA
   against the field background rather than sit at the usual faded grey. */
.quickform-body ::placeholder{color:rgba(255,255,255,.72);opacity:1}
.quickform-body input:focus,.quickform-body textarea:focus{
  border-color:var(--np-sky);background:rgba(255,255,255,.10)}
.qf-submit{width:100%;margin-top:var(--sp-2)}
/* Closing-CTA button sizes, measured off responseelectricianperth.com.au:
   their Call is 237x62 and Send SMS 170x62 at padding 18px 36px / 18px, and the
   disclosure below is 341x46 at padding 12px 28px / 14px / weight 700. Ours were
   244x58, 182x58 and 431x58, so the two primaries gain height and lose width,
   and the disclosure drops to a genuinely secondary size.
   Scoped to .cta-band (0,2,0) so it beats .btn further up without !important. */
.cta-band .btn--sky,.cta-band .btn--outline-sky{
  padding:18px 34px;font-size:18px;min-height:62px}
/* Luke: "my call looks crappy" against the reference site's bright one. It was
   using Sky, which brand/colours.md defines for small text on navy, not for a
   button fill, so it read as a highlighter mark. NextPoint Blue is the colour
   the guide assigns to buttons. White on #0868CF is 5.40:1 (AA), and the fill
   against navy is 3.60:1, which clears the 3:1 SC 1.4.11 needs for the control
   edge. No new colour introduced, which the guide reserves for Luke.
   For the record, the reference site's cyan #00A4E4 with white is 2.83:1 and
   fails; copying it would have put the site in breach. */
.btn--sky{background:var(--np-blue);color:var(--np-white);
  box-shadow:0 6px 20px rgba(8,104,207,.45)}
.btn--sky:hover,.btn--sky:focus-visible{background:var(--np-blue-hover);color:var(--np-white)}
/* The quiet second action: white at 10% over navy, so it is the palette's own
   white rather than a new grey. The reference site borders this at 25% white,
   which is 2.17:1 against navy and misses the 3:1 minimum for a control edge;
   40% gives 3.77:1 and looks the same. */
.btn--outline-sky{background:rgba(255,255,255,.10);
  border-color:rgba(255,255,255,.40);color:var(--np-white)}
.btn--outline-sky:hover,.btn--outline-sky:focus-visible{background:rgba(255,255,255,.17);
  border-color:rgba(255,255,255,.60);color:var(--np-white)}
.cta-band .btn--ghost-sky{padding:12px 24px;font-size:14px;font-weight:700;
  min-height:46px;letter-spacing:0;
  /* Greyed to match Send SMS, border included, at Luke's direction. Same
     approach: white at low alpha over navy, not a new grey. Border at 35% is
     3.15:1 against navy, which clears the 3:1 SC 1.4.11 wants for a control
     edge; below that the outline stops being discernible. */
  background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.35);
  color:rgba(255,255,255,.86)}
.cta-band .btn--ghost-sky:hover{background:rgba(255,255,255,.11);
  border-color:rgba(255,255,255,.55);color:var(--np-white)}

/* Keeps "Hervey Bay CBD" together so CBD never orphans onto its own line. */
.nowrap{white-space:nowrap}
.qf-note{font-size:13px;color:var(--np-navy-copy);margin:var(--sp-3) 0 0;text-align:center}
.btn--outline-sky{border-width:2px;border-style:solid}
.btn--outline-sky:hover,.btn--outline-sky:focus-visible{
  background:rgba(255,255,255,.14);border-color:var(--np-white);color:var(--np-white)}

/* The button under a suburb grid, "See the full service area" and "All 23
   service areas", sat hard left on all 48 places it appears. It is a single
   action closing a centred grid, so it centres with the grid. */
.arealist + p{text-align:center;margin-top:var(--sp-6);
  /* the paragraph inherits the reading measure, so it was centring the button
     inside a 686px column rather than across the page */
  max-width:none;width:100%;margin-left:0;margin-right:0}
.arealist + p > .btn{display:inline-flex;width:auto;margin-left:auto;margin-right:auto}
body.home .arealist + p > .btn{display:inline-flex}

/* ------------------------------------------------- the owner block
   A photo of Luke beside a short statement in his own voice. It replaced a
   long passage about Hervey Bay housing eras: a real face and a real promise
   convert better than a paragraph about switchboards, and the housing material
   still lives on the suburb pages. Written to survive the business growing,
   so it says the standard is his rather than that he is the only one. */
.ownerblock{display:grid;gap:var(--sp-6);align-items:center;max-width:none;
  margin:0 auto}
@media (min-width:900px){
  /* Desktop stays exactly as it was: "The owner" at the top of the writing
     column, NOT above the photo. Luke asked for the move on mobile only.
     The eyebrow now sits outside .ownerblock-copy in the markup, so grid areas
     put it back where it belongs rather than editing the HTML a second time.
     The photo spans both rows and align-content centres the pair, reproducing
     what align-items:center did when the right side was a single item. */
  .ownerblock{grid-template-columns:minmax(0,0.85fr) minmax(0,1fr);
    grid-template-areas:"photo eyebrow" "photo copy";
    grid-template-rows:auto auto;align-content:center;
    column-gap:var(--sp-8);row-gap:0}
  .ownerblock-photo{grid-area:photo;align-self:center}
  .ownerblock-eyebrow{grid-area:eyebrow;align-self:end}
  .ownerblock-copy{grid-area:copy}
}
/* "The owner" above the photo on phones, starting on the photo's left edge.
   Desktop keeps it at the top of the writing column (see the grid areas above).

   Two things this has to undo, both caused by the element leaving
   .ownerblock-copy:
   1. body.home .prose p gives every paragraph auto side margins and a 58ch cap,
      so the BLOCK centred itself and text-align alone did nothing.
   2. .prose p sets font-size:17px at (0,1,1), which beat a plain
      .ownerblock-eyebrow (0,1,0) and rendered the label at 17px instead of 13.
      Luke spotted it before I did.

   Absolutely positioned on mobile so it occupies the 64px of section padding
   that already sits above the photo. In flow it pushed the photo down 86px,
   which is not what was asked for: the label goes in the existing gap, the
   photo does not move. */
body.home .prose .ownerblock-eyebrow{margin-left:0;margin-right:0;
  max-width:none;text-align:left;font-size:14px;font-weight:700;
  letter-spacing:.10em;text-transform:uppercase;color:var(--np-blue)}
@media (max-width:899.98px){
  .ownerblock{position:relative}
  body.home .prose .ownerblock-eyebrow{position:absolute;top:-34px;left:0;margin:0}
}
/* The colour came from .ownerblock-copy .eyebrow, which no longer matches now
   that the element has moved out of that column. */
.ownerblock-eyebrow{font-family:var(--font-display);
  color:var(--np-blue);font-size:14px;font-weight:700;
  letter-spacing:.10em;text-transform:uppercase;margin:0 0 var(--sp-3)}
.ownerblock-photo{width:100%;height:auto;border-radius:var(--r-lg);
  box-shadow:var(--sh-3);display:block}
.ownerblock-copy{text-align:left}
.ownerblock-copy .eyebrow{color:var(--np-blue);font-weight:700;
  text-transform:uppercase;margin-bottom:var(--sp-3)}
.ownerblock-copy h2{margin-bottom:var(--sp-4);max-width:20ch}
@media (min-width:768px){.ownerblock-copy h2{font-size:34px}}
.ownerblock-copy p{font-size:17px;line-height:1.7;margin-bottom:var(--sp-4);
  max-width:52ch}
.ownerblock-copy .small{font-size:14.5px;color:var(--np-slate)}
/* Luke: "the hanging looks funny ... really unorganised". Cause found by
   measuring: body.home .prose gives every child margin-left/right:auto, so each
   element centred itself AT ITS OWN max-width. Eyebrow started at 727px, the
   heading at 754px, paragraphs at 712px, the small line at 716px: four different
   left edges. Invisible elsewhere on the home page because that text is centred;
   visible here because this column is left-aligned. Specificity has to beat
   body.home .prose p (0,2,2), hence the long selector rather than !important. */
body.home .prose .ownerblock-copy > *{margin-left:0;margin-right:0}
body.home .prose .ownerblock-copy h2{max-width:22ch}
body.home .prose .ownerblock-copy p{max-width:52ch}
body.home .prose .ownerblock-copy .small{max-width:52ch}
/* The heading inherited .prose h2{margin-top:48px}, which pushed the whole
   copy column 48px taller than the photo beside it, so "The owner" floated
   above the top of the picture on desktop and sat a long way from the name on
   mobile. Zeroed here only; the 12px eyebrow margin is the gap that remains. */
body.home .prose .ownerblock-copy h2{margin-top:0}
/* Trailing margin on the last line made the column 368px against a 364px
   photo, so align-items:center could not sit the text inside the picture: it
   overhung 2px top and bottom with 16px of dead space below the last line.
   Zeroing it lets the copy centre truly within the photo's height. */
body.home .prose .ownerblock-copy > *:last-child{margin-bottom:0}
/* Luke, on mobile: "it all has to read from the centre". Below the stacking
   breakpoint the photo is full width, so centred copy reads as one block under
   it. On desktop the copy sits beside a left-aligned photo and needs the shared
   left edge to agree with it, so it stays left there. */
@media (max-width:899.98px){
  body.home .prose .ownerblock-copy{text-align:center}
  body.home .prose .ownerblock-copy > *{margin-left:auto;margin-right:auto}
}
/* The owner block sits inside the prose column, which is deliberately narrow
   for reading. A photo beside text needs the full container. */
@media (min-width:1200px){
  .container > .prose > .ownerblock{margin-left:-207px;margin-right:-207px;
    max-width:none;width:auto}
}

/* ============================================ the process graphic, measured
   Luke compared ours against the reference site and it looked weaker. The
   numbers off theirs: a 60px circle in the brand blue, no ring, a coloured
   glow beneath it rather than a grey drop shadow, the numeral at 22px and
   very heavy, the title at 18px heavy, body at 15px on 24px leading.

   The white ring was the main problem. It made the circle read as a sticker
   pasted on the page rather than a marker sitting on the line. Removed, and
   the shadow is now tinted with the brand blue so the circle glows instead of
   casting a grey blur. Rubik 800 was added for the numeral, because 700 next
   to their 900 was the other half of the difference.
   ========================================================================== */
.steps li::before{width:60px;height:60px;font-size:22px;font-weight:800;
  box-shadow:0 4px 16px rgba(8,104,207,.34);border:0}
.section--tint .steps li::before{box-shadow:0 4px 16px rgba(8,104,207,.34)}
.section--navy .steps li::before{box-shadow:0 4px 18px rgba(127,184,245,.30)}
.steps li{padding-top:82px}
.steps h3{font-size:18px;font-weight:800;margin-bottom:8px;letter-spacing:-.005em}
.steps p{font-size:15px;line-height:1.6}
@media (min-width:1200px){
  .steps li::after{top:29px}
}

/* ==========================================================================
   THE REFERENCE TYPE AND COMPONENT SYSTEM, IN OUR PALETTE
   Luke asked for the site to look identical to the reference, in NextPoint
   colours. Every value below was read off their live site rather than judged
   by eye:

     Montserrat throughout. h1 64/900 at -1.5px tracking, h2 40/900 at -0.5px,
     h3 28/900, lede 20/500 on 32px, card body 14/500 on 21px, links 13/600,
     eyebrow 13/700 at 2.5px tracking.
     Cards: 20px radius, 4px coloured left edge, 32px by 28px padding,
     shadow 0 8px 32px at 10% and a tight second shadow under it.
     Icon tiles: 56px at 16px radius on a pale tint of the brand colour.
     Sections: 80px top and bottom.

   Their #00A4E4 maps to our blue, their #0A0A12 to our navy, their #555 to
   our slate, their #E8F6FD to our lightest surface. Nothing of theirs is
   copied but the measurements.
   ========================================================================== */

h1,h2,h3,h4{font-family:var(--font-display)}
h1{font-weight:900;letter-spacing:-1.2px;line-height:1.08}
h2{font-weight:900;letter-spacing:-.5px;line-height:1.12}
h3{font-weight:900;letter-spacing:-.2px;line-height:1.2}
body{font-family:var(--font-body);font-weight:400}

.titleband h1{font-size:clamp(38px, 8.4vw, 46px);letter-spacing:-.8px}
@media (min-width:768px){
  .titleband h1{font-size:clamp(46px, 5.4vw, 64px);letter-spacing:-1.2px;line-height:1.08}
}
.hero h1,.hero .hero-h1{font-size:clamp(32px, 7.6vw, 40px);letter-spacing:-.8px}
@media (min-width:768px){.hero h1,.hero .hero-h1{font-size:clamp(40px, 4.4vw, 52px);letter-spacing:-1.2px}}
.section-head h2{font-size:clamp(28px, 6.4vw, 34px);letter-spacing:-.5px}
@media (min-width:768px){.section-head h2{font-size:40px}}
@media (min-width:1100px){.section-head h2{font-size:40px}}
.prose h2{font-size:clamp(26px, 6vw, 30px);letter-spacing:-.5px}
@media (min-width:768px){.prose h2{font-size:34px}}
.prose h3{font-size:22px;letter-spacing:-.2px}
@media (min-width:768px){.prose h3{font-size:24px}}

.lede{font-size:17px;line-height:1.6;font-weight:400;color:var(--np-slate)}
@media (min-width:768px){.lede{font-size:20px;line-height:32px}}
.hero .lede{color:var(--np-navy-copy)}

/* ------------------------------------------------------------ their cards */
.card{border-radius:20px;padding:32px 28px;border-left-width:4px;
  box-shadow:0 8px 32px rgba(0,13,35,.10),0 2px 6px rgba(0,13,35,.06)}
.card:hover{box-shadow:0 14px 40px rgba(0,13,35,.14),0 2px 6px rgba(0,13,35,.06)}
.card h3{font-size:20px;font-weight:800;letter-spacing:-.2px;margin-bottom:12px}
.card p{font-size:15px;line-height:1.6;font-weight:400}
.card .cardlink{font-size:13.5px;font-weight:600}
.cardicon{width:56px;height:56px;border-radius:16px;background:var(--np-surface-100)}
.cardicon svg{width:28px;height:28px}
.review{border-radius:20px;padding:32px 28px;
  box-shadow:0 8px 32px rgba(0,13,35,.10),0 2px 6px rgba(0,13,35,.06)}
.review blockquote{font-size:15px;line-height:1.65;font-weight:400}
.arealist a{border-radius:20px}
.arealist a::before{border-radius:16px;width:56px;height:56px}
.faq details{border-radius:16px}
.faq summary{font-size:16.5px;font-weight:700}
.pick,.ownerblock-photo,.callout{border-radius:20px}
.trustbar li{border-radius:20px}

/* ------------------------------------------------------ their type weights */
.eyebrow{font-weight:700;letter-spacing:.10em}
.btn{font-family:var(--font-display);font-weight:800}
.steps h3{font-weight:800}
.trustbar strong{font-weight:900;letter-spacing:-.5px}
.ratingchips b{font-weight:800}
.header .brand + .nav a,.nav a,.nav .navtop{font-weight:600}
.footer h2,.footer h3{font-weight:800}
/* Montserrat's shorter content box dropped the card links to 21px tall, under
   the 24px minimum. They are standalone actions at the foot of a card rather
   than links inside a sentence, so the exemption does not apply to them. */
.cardlink{display:inline-flex;align-items:center;min-height:26px}
/* An FAQ question is a heading in everything but tag name, and it sits directly
   under an Archivo h2. It was inheriting the body face, which the font check
   caught on all 53 pages that carry an FAQ. */
.faq summary{font-family:var(--font-display);letter-spacing:-.2px}

/* Home page FAQ reads from the left, questions and answers alike, on desktop
   and mobile. It was briefly centred at Luke's request and he changed his mind
   after seeing it: left is easier with questions of varying length, because
   every line starts in the same place.
   summary is display:flex, so justify-content does the work, not text-align.
   Padding stays asymmetric here on purpose: 52px on the right reserves room for
   the chevron, and with a left-aligned label there is nothing to knock off
   centre, unlike the centred version which needed both sides matched. */
body.home .faq summary{justify-content:flex-start;text-align:left;
  padding-left:var(--sp-5);padding-right:52px}
body.home .faq .answer{text-align:left}

/* ============================================ phone: centred footer
   Luke's call, mobile only. Desktop keeps its left-aligned reading rhythm.

   .faq summary is display:flex, so text-align alone does nothing: it needs
   justify-content. Its padding is asymmetric (52px right for the chevron, 24px
   left), which would push a centred label off by half the difference, so both
   sides are matched. Same trap as the numbered steps.

   The footer columns become flex columns rather than relying on text-align,
   because the contact rows and the social buttons are flex children that
   text-align cannot move.

   The address is the exception: phone and email are an icon plus one line and
   centre fine as a flex pair, but the address wraps to two lines and the pin
   ends up stranded at the far left. It goes inline with the first line instead. */
@media (max-width:767.98px){

  .np-f{text-align:center}
  .np-f-brand,.np-f-col{display:flex;flex-direction:column;align-items:center}
  .np-f-tag{max-width:38ch}
  .footer a.np-f-line{justify-content:center}
  .np-f-addr{display:block;text-align:center}
  .np-f-addr svg{display:inline-block;vertical-align:-3px;margin-right:6px}
  .np-f-social{justify-content:center}
  .np-f-bottom{justify-content:center;text-align:center}
  .np-f-legal{justify-content:center}
}

/* ===================================== suburb cards, lifted off the page
   Rebuilt to the proportions of responseelectricianperth.com.au, measured off
   their live page: 20px gap, 20px radius, no border, 52px icon tile at 14px
   radius with a 26px pin, name 16px/800, link line 13px/500, hover lift.
   Colours are ours: the light blue surface Luke reserved for the service area
   cards and the service icons, NextPoint Blue for the pin and the link.

   The cards had NO box-shadow at all, which is why they read as painted on
   rather than raised. The shadow is deliberately two layers: a tight 1-2px
   contact edge directly under the card, plus a wide soft one. A single large
   blur reads as fog, not lift, which is what Luke was describing.

   Worth recording for whoever revisits this: the card is a light tint on a
   white section, so it is DARKER than the page behind it. Real raised objects
   catch more light than their surroundings, so this reads as a recess more than
   a bump no matter how the shadow is tuned. White card on a tinted band was
   offered and Luke chose this one. If it ever looks flat again, that inversion
   is the reason, not the shadow values. */
.arealist{gap:20px}
.arealist a{flex-direction:column;justify-content:center;min-height:170px;
  padding:28px 24px;border:0;border-radius:20px;
  /* White on the tinted band. The card has to be LIGHTER than the ground or it
     reads as a recess however the shadow is tuned; this was blue-on-white and
     looked painted on. The section is forced to the tint in build.py so the
     ground is there to sit on. */
  background:var(--np-white);
  box-shadow:0 1px 2px rgba(0,13,35,.10), 0 12px 28px rgba(0,13,35,.13);
  font-family:var(--font-display);font-size:16px;font-weight:800;
  color:var(--np-navy);letter-spacing:-.01em;
  transition:transform .22s ease, box-shadow .22s ease}
.arealist a::before{width:52px;height:52px;border-radius:14px;
  background-color:var(--np-surface-100);background-size:26px 26px;
  margin-bottom:14px}
.arealist a::after{font-family:var(--font-body);font-size:13px;font-weight:500;
  color:var(--np-blue);margin-top:6px}
.arealist a:hover{transform:translateY(-4px);border:0;background:var(--np-white);
  box-shadow:0 2px 4px rgba(0,13,35,.12), 0 20px 40px rgba(0,13,35,.20)}
/* Restated after the block above, which sets background and shadow for every
   instance. On a navy band the light fill and the dark shadow both disappear. */
.section--navy .arealist a{background:rgba(255,255,255,.06);color:var(--np-white);
  box-shadow:none}
.section--navy .arealist a::before{background-color:rgba(127,184,245,.16)}
.section--navy .arealist a::after{color:var(--np-sky)}
.section--navy .arealist a:hover{background:rgba(255,255,255,.12);
  transform:translateY(-4px);box-shadow:none}
@media (prefers-reduced-motion:reduce){.arealist a{transition:none}
  .arealist a:hover{transform:none}}

/* Below 1024 the cue would sit on a hero that is not full height and duplicates
   what the sticky action bar already offers. Declared BEFORE the desktop block:
   after it, this wins at equal specificity and the cue never appears. */
.herocue{display:none}
.anchor-target{display:block;height:0;overflow:hidden}

/* Below 1024 the cue would sit on a hero that is not full height and duplicates
   what the sticky action bar already offers. Declared BEFORE the desktop block
   below, not after it: both selectors are (0,1,0), so whichever is written last
   wins, and a trailing hide silently kills the cue at every width. */
.herocue{display:none}

/* ====================================== desktop: text over a full-screen hero
   Luke's call, desktop only. Mobile is untouched: below 1024 the titleband is
   an ordinary white band under the image, exactly as it was.

   The titleband is POSITIONED over the hero rather than duplicated into it, so
   there is still one H1 on the page. Duplicating the markup would have given
   the home page two, which is worse for search than any layout gain.

   Every number here was measured, not chosen. The layout was rebuilt against
   the mockup Luke approved by differencing screenshots: eyebrow at y210 to his
   210, headline at 239 to his 243, rating at 384 to his 387, lede at 426 to his
   428, all at 1440x900.

   The illustration is 2100x794, an aspect of 2.65, against a hero of roughly
   1.85, so cover crops about 30% off the sides at full-screen height. Centred,
   so the crop is symmetric. A taller re-render nearer 1600x900 is the only way
   to show the whole scene at this height. */

/* Two ledes ship in the markup and one shows at a time. The long one is the
   mobile band, where there is room for it; the short one is the overlay line,
   where there is not. Toggled rather than swapped in script so both are present
   with JS off and the correct one paints on first render, not after a repaint. */
.lede--short{display:none}

/* ------------------------------------------- above the fold, 30/08/2026
   Luke's mock up moved the headline OFF the picture and put it underneath, so
   the whole desktop overlay that used to live here is deleted rather than
   overridden. It set .titleband to position:absolute over a full viewport high
   hero, with a solved scrim behind white text and the scroll cue at the foot.
   None of that has anything to hold on to now: the picture carries no text, so
   it needs no scrim, and the heading sits in normal flow on a light band.
   Deleted outright because a dead absolute-positioning rule further up the file
   is exactly the trap that has bitten this stylesheet repeatedly. */
.anchor-target{display:block;height:0;overflow:hidden}

/* ------------------------------------------------- home intro band (mock)
   The block Luke asked for between the hero and the services grid: the claim,
   the one-line summary of how the business runs, and a single call to action.
   Built from the page's existing section-head rather than new furniture, so it
   inherits the centring, the measure and the type scale already in use. */
.intro-band{padding-top:var(--sp-8);padding-bottom:var(--sp-8)}
.intro-head{margin-bottom:0}
/* section-head caps h2 at 22ch, which broke "Electrical Work. Done Right."
   across two lines. Released here so it sets on one line wherever it fits and
   wraps only when the container is genuinely too narrow. */
.intro-head h2{max-width:none}
.intro-head .lede{max-width:68ch}
/* The three-claim line is a separate thought from the paragraph above it, so it
   gets air rather than sitting as a fourth line of the same block. */
.intro-claims{margin-top:var(--sp-4)}
.intro-cta{margin-top:var(--sp-6);margin-bottom:0}

/* ------------------------------------------------- owner band and step rail
   Replaces the old .ownerblock and .steps on the home page, to the layout Luke
   supplied. Both live outside .prose now, which is deliberate: the home page
   centres every direct child of .prose at its own max-width, and that is what
   made the old owner copy hang on four different left edges. */
.ownergrid{display:grid;gap:var(--sp-6);align-items:center}
@media (min-width:900px){
  .ownergrid{grid-template-columns:minmax(0,40%) minmax(0,1fr);gap:var(--sp-8)}
}
.ownergrid-photo{width:100%;height:auto;display:block;border-radius:var(--r-lg)}
.ownergrid-copy .eyebrow{color:var(--np-blue);margin-bottom:var(--sp-3)}
.ownergrid-copy h2{max-width:18ch;margin:0 0 var(--sp-4)}
.ownergrid-copy p{max-width:56ch}
/* Luke's earlier call, kept: centred on a phone, left from 900 up. */
.ownergrid-copy{text-align:center}
@media (min-width:900px){.ownergrid-copy{text-align:left}}
@media (min-width:900px){.ownergrid-copy h2,.ownergrid-copy p{margin-left:0;margin-right:0}}
@media (max-width:899.98px){.ownergrid-copy h2,.ownergrid-copy p{margin-left:auto;margin-right:auto}}

.cred{display:flex;gap:12px;align-items:flex-start;justify-content:center;
  font-size:15px;line-height:1.5;color:var(--np-navy);margin:var(--sp-5) 0 0}
@media (min-width:900px){.cred{justify-content:flex-start}}
.cred svg{flex:0 0 auto;width:24px;height:24px;color:var(--np-blue);margin-top:1px}

/* The rail: four numbered stops with a hairline running between the circle
   centres. Drawn per item as a line from this circle's centre to the next
   one's, rather than one line under the whole row, so it cannot poke out
   past the first and last circles. */
/* ul,ol at line 106 caps every list at the reading measure, which squeezed the
   four columns into 686px of a 1180px container. Same trap the .prose ol note
   further up records. */
.steprail{list-style:none;margin:0;padding:0;max-width:none;display:grid;gap:var(--sp-6)}
.steprail li{text-align:center;position:relative}
.steprail-n{display:inline-flex;align-items:center;justify-content:center;
  width:48px;height:48px;border-radius:var(--r-full);background:var(--np-blue);
  color:var(--np-white);font-family:var(--font-body);font-weight:700;font-size:20px;
  position:relative;z-index:1}
/* section-head caps h2 at 22ch, which broke this heading over two lines. */
.steprail-head h2{max-width:none}
.steprail h3{margin:var(--sp-4) 0 var(--sp-2);font-size:19px}
.steprail p{margin:0;color:var(--np-slate);font-size:15px;line-height:1.6;
  max-width:34ch;margin-left:auto;margin-right:auto}
@media (min-width:820px){
  .steprail{grid-template-columns:repeat(4,1fr);gap:var(--sp-5)}
  .steprail li::before{content:"";position:absolute;top:23px;left:50%;width:100%;
    height:2px;background:var(--np-rule);z-index:0}
  .steprail li:last-child::before{display:none}
}

/* --------------------------------------------------------- promise boxes
   Replaces the old .statband, which had markup but no CSS at all and so
   rendered as a raw bullet list on navy. Three boxes carrying the three
   promises: $0 call out, fixed price, lifetime warranty. Luke picked the
   navy treatment (option A) on 30/08/2026.
   .pboxes is a <ul>, so it needs max-width:none or the list rule at the top
   of this file caps it at the reading measure and the three columns squeeze
   into 686px of an 1180px container. Same trap as .steprail and .prose ol. */
.pboxes{list-style:none;margin:0;padding:0;max-width:none;display:grid;gap:var(--sp-4);grid-template-columns:1fr}
@media (min-width:820px){.pboxes{grid-template-columns:repeat(3,1fr);gap:var(--sp-5)}}
.pbox{display:flex;flex-direction:column;align-items:center;text-align:center;
  border-radius:var(--r-lg);padding:var(--sp-6) var(--sp-5) calc(var(--sp-6) - 4px);
  background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.22)}
.pbox-i{display:flex;align-items:center;justify-content:center;height:40px;margin-bottom:var(--sp-4)}
.pbox-i svg{height:36px;width:auto;color:var(--np-white)}
.pbox-v{font-family:var(--font-display);font-weight:700;font-size:40px;line-height:1;
  letter-spacing:-.02em;display:block;color:var(--np-white)}
@media (min-width:820px){.pbox-v{font-size:46px}}
.pbox-l{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:.10em;
  text-transform:uppercase;margin-top:var(--sp-3);display:block;color:#7FB4EF}
.pbox-p{font-size:15px;line-height:1.55;margin:var(--sp-3) auto 0;max-width:30ch;
  color:var(--np-navy-copy)}

/* ------------------------------------------------ mid page call to action
   .midcta and .midcta-line existed in the markup with no CSS at all, so the
   line inherited the reading measure from the p rule at the top of this file
   and sat hard left. Same trap as .statband-list and .pboxes.
   The reference site breaks its page with three of these one-line strips,
   which is what keeps a long service page from reading as one slab. */
.midcta{padding:var(--sp-7) 0}
@media (min-width:768px){.midcta{padding:56px 0}}
.midcta .container{display:flex;flex-direction:column;align-items:center;gap:var(--sp-5)}
.midcta-line{max-width:56ch;margin:0 auto;text-align:center;
  font-family:var(--font-display);font-weight:700;letter-spacing:-.01em;
  font-size:21px;line-height:1.35}
@media (min-width:768px){.midcta-line{font-size:25px}}
.section--navy .midcta-line{color:var(--np-white)}
.section--brand .midcta-line{color:var(--np-white)}
.midcta .btn-row{margin:0;display:flex;flex-wrap:wrap;gap:var(--sp-3);justify-content:center}
/* A solid white button is the only one that carries enough weight on the
   brand blue band. Navy label so it clears AA against white. */
.btn--onbrand{background:var(--np-white);border-color:var(--np-white);color:var(--np-navy)}
.btn--onbrand:hover,.btn--onbrand:focus-visible{background:#EAF1FB;border-color:#EAF1FB;color:var(--np-navy)}

/* ------------------------------------------------------ the promise band
   Brand blue rather than one of the three neutral bands, so it is forced in
   the solver from the section's own class. White on NextPoint Blue measures
   5.4:1, which clears AA for body text, so the copy is plain white rather
   than faded. */
.section--brand{background:var(--np-blue);color:var(--np-white)}
.promiseband .eyebrow{color:var(--np-white)}
/* section-head caps h2 at 22ch and the lede at 62ch; both break this block
   in the wrong places. */
.promise-head h2{color:var(--np-white);max-width:none}
.promise-head .lede{color:var(--np-white);max-width:66ch}
.promise-list{list-style:none;margin:var(--sp-6) 0 0;padding:0;max-width:none;
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:var(--sp-2);color:var(--np-white);font-size:17px}
.promise-list li{display:flex;align-items:center}
/* A separator rather than a bullet: it belongs between the items, so it hangs
   off the second and third rather than marking all three. */
.promise-list li + li::before{content:"\2022";margin:0 var(--sp-4);
  color:rgba(255,255,255,.7)}
/* Stacked on a phone, where a separator sitting at the start of a wrapped line
   reads as a stray bullet rather than as punctuation between two items. */
@media (max-width:639.98px){
  .promise-list{flex-direction:column;gap:var(--sp-3)}
  .promise-list li + li::before{content:none}
}
/* The closing heading on the home page is longer than the 20ch the band caps
   at, and broke across two lines. Released on the home page only, so the
   shorter, page-specific headings on the other 54 pages keep their measure. */
body.home .cta-band h2{max-width:none}
body.home .cta-band .lede{max-width:62ch}

/* ------------------------------------------------- home page area cards
   Eight cards in place of the 22-name list, Luke's call. Built on the same
   .card .card--icon as the services grid so the two read as one system, with
   a tighter row because a suburb name is one line rather than a paragraph. */
.areacards{list-style:none;margin:0;padding:0;max-width:none;
  display:grid;gap:var(--sp-4);grid-template-columns:repeat(2,1fr)}
@media (min-width:700px){.areacards{grid-template-columns:repeat(4,1fr)}}
.areacards .card{text-align:center;padding:var(--sp-5) var(--sp-4)}
.areacards h3{font-size:17px;margin:var(--sp-3) 0 var(--sp-2)}
.areacards .cardlink{margin-top:0}
/* p is capped at the reading measure by --measure, with margin-left:0, so
   text-align:center was centring the button inside 686px of an 1180px
   container rather than on the page. Same trap as the step rail. */
.areacards-all{max-width:none;text-align:center;margin:var(--sp-6) auto 0}

/* ------------------------------------------- closing band into the footer
   One continuous navy block divided by a hairline rather than by a 149px gap,
   Luke's call. Both already use --np-navy, so only the spacing and the rule
   change.

   The rule hangs off the call to action's own container rather than the
   footer's, so it can only ever appear under a closing band. All 55 pages carry
   one today, but a page built without it would otherwise get a stray line under
   a white section. It is set to the footer's 1140px measure so the rule lines
   up with the columns beneath it rather than running wider than them; measured
   at 1140 from x150, identical to the footer columns. */
.cta-band .container{max-width:1140px;padding-bottom:22px;
  border-bottom:var(--bw-hair) solid rgba(255,255,255,.10)}
.cta-band{padding-bottom:0}
.footer{padding-top:44px}

/* The rating line under the hero headline. Both hero variants are dark navy, so
   the base rule further up (slate text, navy bold, dark amber stars) is wrong on
   every page that uses it: the bold "5.0" measured 1:1, navy on navy. White
   throughout, and aligned left with the headline rather than centred, because the
   whole hero column is left aligned and the base rule centres it. */
@media (min-width:1024px){
  .hero-rating--svc{justify-content:flex-start;margin:16px 0 0;color:#EAF0F8}
  .hero-rating--svc .stars{color:var(--np-white)}
  .hero-rating--svc b{color:var(--np-white)}
}

/* The chips are nowrap so a rating never breaks across two lines mid-phrase.
   That held while the licence chip read "REC 92971". The Victorian one is longer
   and pushed the chip to 396px inside a 390px screen, which scrolled the whole
   page sideways. Narrow screens only: below 480px the chip may wrap, above it
   the nowrap rule further up still applies. */
@media (max-width:479px){
  .ratingchips > li > a,.ratingchips > li > span{white-space:normal;text-align:left}
}

/* ================================================ above the fold, 30/08/2026
   Three bands, in the order Luke drew them: picture, promise strip, wordmark.

   The picture is a banner rather than a full height hero. Its height comes from
   an aspect ratio so it crops the same way at every width instead of getting
   letterboxed, and it is capped so it cannot eat a laptop screen whole. */
.hero--home{position:relative;padding:0;background:var(--np-navy);height:auto}
.hero--home .container{display:none}
/* Height is set directly rather than through aspect-ratio. With aspect-ratio and
   width:auto, a max-height clamp re-solves the WIDTH to keep the ratio, which
   pulled the picture in to 806px of a 1440px screen and left navy either side.

   The picture is the only flexible band on the first screen, so it is the one
   that gives. Luke's requirement is that "Built in Ocean Grove" is visible
   without scrolling, and the four bands above and below it are all sized to
   their content. So the picture takes whatever height is left after them:
   the top bar and header, the promise strip, and the wordmark block, measured
   at the widths this page actually renders at. The floor stops it collapsing
   to a letterbox on a short laptop; the ceiling stops it swallowing a tall
   monitor. Uses svh rather than vh so a phone's collapsing address bar does
   not push the foot line under the fold on first paint. */
.hero--home .hero-scene{position:relative;inset:auto;overflow:hidden;width:100%;
  height:calc(var(--fw) * .3592)}
/* The strip was a 70px navy slab between the picture and the headline, which
   made the first screen three bands of equal weight with nothing to say which
   one mattered. Halved to 36px it reads as a rule instead of a band, and the
   36px it gave up goes back to the picture, where the three people were being
   cropped at the knees. Luke's call on 31/08/2026 after seeing four versions.
   The label loses size but gains letter-spacing, so it reads as a considered
   caption rather than shrunken body copy. */
@media (min-width:768px){
  .hero--home .hero-scene{height:calc(var(--fw) * .4097)}
}
/* Top anchored, not centred. The picture and the cut-out of the electrician
   laid over it are two images that have to stay registered to each other at
   every width. Both are scaled by width and pinned to the top of the box, so
   whatever a short window crops off the bottom, it crops off both by the same
   amount and they cannot drift. */
.hero--home .hero-scene img{width:100%;height:100%;object-fit:cover;
  object-position:50% 100%;display:block}
/* On a phone the wordmark stacks and the promise strip is three rows deep, so
   the arithmetic above would leave the picture almost nothing. Below 700px the
   picture gets a plain height and the foot line sits just under the fold, which
   is the honest trade: a 380px picture that shows the three people beats a
   120px one that shows nobody. */
@media (max-width:700px){
  /* The min() is for short phones. On an iPhone SE, 375x667, the header, the
     three-row promise strip, the wordmark and the sticky call bar leave 229px
     for the picture, and the 250px floor pushed "Built in Ocean Grove" 4px
     behind the call bar. Taller phones are untouched: at 844px the cap is 414
     and the clamp still wins. */
  /* 14/09/2026, Luke's call: the mobile fold was unbalanced. The picture sat at
     250px under a 152px promise strip, so the strip took more height than the
     image and 294px of the screen below it was empty.

     The picture now takes its height from the image itself rather than a fixed
     px value. Every earlier attempt here hard-coded the header, call bar and
     strip as pixels, which was right at 390x844 and clipped the wordmark behind
     the call bar at 360x800 (-6px) and 430x932 (-13px). Letting the aspect
     ratio drive it scales correctly at every width with no arithmetic to get
     wrong. Suburbs with no illustration yet hold the same shape so the
     placeholder does not collapse. */
  /* One shape for every suburb, not each image's own. Letting the file decide
     gave Ocean Grove a 464px fold and Barwon Heads 394px, so two pages that are
     meant to be identical apart from the picture were visibly different. The
     box is pinned; the picture covers it. */
  /* .hero--sub, NOT .hero--home. The home page fold carries the same
     .hero--home class but is a different thing: its headline, sub line and two
     buttons sit OVER the picture. Pinning that hero to a portrait box collapsed
     the overlay onto the promise strip and the reviews. Only the suburb fold,
     which carries no text on the picture, gets the fixed shape. */
  /* 0.94, not 0.84. Luke asked for the picture as large as it can be while
     "What customers say" still clears the fixed call bar, with the lede below
     it cut off. The heading and the lede have NO gap between them, so this is a
     knife edge rather than a range: at 0.94 the heading clears by 3px at
     360x800 and 9px at 390x844. Anything that lengthens that heading tips it
     back behind the bar. */
  .hero--sub .hero-scene{height:auto;max-height:none;aspect-ratio:0.94}
  .hero--sub .hero-scene img{width:100%;height:100%;display:block;
    object-fit:cover;object-position:50% 50%}
  .hero--sub .hero-scene--placeholder{height:auto;aspect-ratio:0.94}


  /* The breadcrumb cost 47px between the wordmark and the reviews, which put
     the rating badge below the call bar where nobody could see it. Hidden on
     phones only; it stays in the markup for search results and is still there
     from 701px up. */
  .crumbs{display:none}
}

/* The promise strip. A list, because it is three of the same kind of thing, and
   the rules between them are borders on the list items rather than characters,
   so a screen reader does not read a pipe out loud. */
.promisestrip{display:flex;flex-direction:column;gap:0;margin:0;padding:0;
  list-style:none;max-width:none;background:var(--np-navy);color:var(--np-white)}
.promisestrip li{display:flex;align-items:center;justify-content:center;
  gap:clamp(11px,1.32vw,22px);
  margin:0;padding:12px 20px;font-family:var(--font-body);font-size:14px;
  font-weight:400;letter-spacing:.02em;text-transform:uppercase;
  border-top:1px solid rgba(255,255,255,.16)}
.promisestrip li:first-child{border-top:0}
/* Height is what is set, not width: the van is a wider drawing than the tag and
   the shield and must not be squashed into a square to match them. */
.promisestrip svg{height:26px;width:auto;flex:0 0 auto;color:var(--np-white)}
/* From the mock, measured at 1548px: strip 63px tall, icons 32px square, labels
   13px cap height, 23px between icon and label. Each is written as a fraction of
   the viewport so the strip keeps its proportions at any width.

   The three items are one centred group with equal padding rather than three
   equal thirds. Thirds leave "$0 call-out fee" adrift in a cell far wider than
   it needs, which is what made the row look lopsided. */
/* Three columns rather than a centred flex row. As a flex row the three items
   simply sat side by side, so the middle one landed wherever the first item's
   width left it: 984 against a page centre of 960 at Luke's window, which is
   what he could see was off. 1fr auto 1fr puts the middle promise dead centre,
   directly under BELLARINE and the ELECTRICIANS box, and makes the outer two
   symmetric about it.

   The navy runs the full width of the screen; the padding pulls the three items
   in to the same measure the wordmark uses, so the strip and the headline below
   it start and finish on the same lines. */
@media (min-width:768px){
  /* Equal thirds, not 1fr auto 1fr. The three phrases measure 283, 366 and
     241px, so centring the middle one left the gaps at 51px and 72px and pulled
     the strip 11px off the page centre. A third each puts the dividers on even
     lines, which is what the eye actually measures. */
  .promisestrip{display:grid;grid-template-columns:1fr 1fr 1fr;
    /* Symmetric again. The 2% left shift was there to keep "Lifetime
       workmanship warranty" out from under the hand holding the multimeter.
       Nothing crosses the bar now, so the shift only left the middle label
       56px off the page centre while BELLARINE below it sat dead on it. */
    padding-left:calc((100% - var(--fold-rail)) / 2);
    padding-right:calc((100% - var(--fold-rail)) / 2)}
  /* The side padding is set by what the columns can carry, not by taste: at
     .038 the first item was wider than its column and spilled out of it, which
     put the dividers and the centring out. */
  .promisestrip li{justify-self:stretch;justify-content:center;
    padding:calc(var(--fw) * .0062) calc(var(--fw) * .026);
    gap:calc(var(--fw) * .0133);
    border-top:0;border-left:1px solid rgba(255,255,255,.22);
    font-size:calc(var(--fw) * .0087);letter-spacing:.02em}
  .promisestrip li:first-child{border-left:0}
  .promisestrip svg{height:calc(var(--fw) * .0163);width:auto}
}

/* The wordmark headline. One h1, set as five lines of display type, in caps
   with wide tracking so it echoes the boxed NEXTPOINT lockup rather than the
   body copy. Archivo is not a condensed face and the font CDNs are unreachable
   from the build box, so the width comes from tracking and weight rather than
   from a narrow cut. */
.titleband{background:var(--np-white);border-bottom:0}
/* The mock sets the place names 25px under the promise strip. That is tighter
   than any other band on the site, and deliberately so: the strip and the
   wordmark read as one block, not two. */
/* The wordmark sits inside .container, which carries 40px of side padding,
   so --fold-rail resolved against a content box already 80px narrower and
   came out 904px against the other bands' 980 at a 1024 screen. Put the
   container itself on the rail with no padding, the way the header and the
   top bar are, and let the row fill it. */
.titleband .container{max-width:none;width:var(--fold-rail);
  padding-left:0;padding-right:0;padding-top:calc(var(--fw) * .009);
  padding-bottom:calc(var(--fw) * .023);text-align:center}
/* Written as .titleband h1.wordmark, not .wordmark. Two rules further up the
   file already target .titleband h1: one caps it at 24ch and one sets a font
   size. Both are (0,1,1) and both would beat a bare .wordmark class, which is
   what pushed the three place names off the right of the screen.

   Every number below was measured off Luke's own mock up (1548px wide) and is
   expressed as a fraction of the viewport so it holds at any width:
     row of place names   cap height 55px, ink width 1273px, space-between
     ELECTRICIANS box     575px wide, 72px tall
     BUILT IN OCEAN GROVE cap height 15px, width 311px
     vertical gaps        25px above the row, 25px to the box, 27px to the foot */
.titleband .wordmark{margin:0;color:var(--np-navy);
  font-family:var(--font-wordmark);font-weight:400;text-transform:uppercase;
  max-width:none;width:100%;letter-spacing:0;
  display:flex;flex-direction:column;align-items:center}

/* space-between, not a gap. In the mock the outer edges of GEELONG and COAST sit
   on a fixed measure and the air falls where it falls; a fixed gap drifts off
   that measure as the words change length. */
/* Three columns, not space-between. Luke asked for BELLARINE on the centre of
   the page with GEELONG and SURF COAST balanced either side, and space-between
   cannot do that: it equalises the OUTER edges, which throws the middle word off
   centre by half the difference between the two outer words, 48px here.
   1fr auto 1fr puts the middle column on the page centre and the equal column
   gap gives the two outer words the same air. The cost is that the outer edges
   no longer align, because "Surf Coast." is 97px longer than "Geelong." — that
   asymmetry sits out at the margins where the eye does not measure it, rather
   than beside the centre word where it does. */
/* Option A, Luke's pick on 31/08/2026: even air either side of BELLARINE, and
   BELLARINE itself locked to the page centre with the ELECTRICIANS box and the
   foot line. The three cannot all hold at once — even gaps, a centred middle
   word and outer edges flush to one measure — because "Surf Coast." is 95px
   longer than "Geelong." Something has to give, and it is the outer edges: they
   sit slightly right of the promise strip above. A centre line running down
   three elements is what the eye follows; an edge alignment across a change of
   colour and scale is not. */
/* 13/09: Luke read "Built in Ocean Grove" as off centre. It was not — it sat on
   the page centre to the pixel — but the three names have different widths, so
   centring the GROUP put BELLARINE, the word the eye uses as the anchor, 28px
   left of it. The mock centres the MIDDLE word and lets the group sit slightly
   right. A three column grid, 1fr auto 1fr, does that: the centre column lands
   on the page centre and the two gaps stay equal. */
.wordmark-row{display:grid;grid-template-columns:1fr auto 1fr;align-items:baseline;
  column-gap:calc(var(--fw) * .0515);
  /* The 94vw cap predates the rail and undercuts it below about 1043px,
     which put the wordmark 18px inside every other band at 1024. The rail
     already carries its own 100% - 40px guard, so the cap is redundant. */
  width:100%;line-height:1;
  font-size:calc(var(--fw) * .0399);letter-spacing:.02em;
  margin-bottom:calc(var(--fw) * .0137)}
.wordmark-word--l{justify-self:end}
.wordmark-word--c{justify-self:center}
.wordmark-word--r{justify-self:start}
/* Letter-spacing is added after every character including the last, so each word
   carries a trailing sliver of air that is real layout width. Left in, it shifts
   the centre word off the page centre and makes the two gaps unequal by the
   width of one space. Pulled back on all three. */
.wordmark-word{white-space:nowrap;margin-right:-.02em}
/* The trailing letter-space after the final full stop is real width and pushes
   the last word off the right edge of the measure. Pulled back so the ink lines
   up with the row, which is what the eye reads. */

/* Not a rectangle. Measured off Luke's original design: two vertical rules
   starting level with the cap tops, closed by a rule below the baseline, and
   OPEN along the top. At 1564px wide his was 466 wide by 41 tall around a 23px
   cap, with the letters 347 wide inside it.

   Drawn as a pseudo-element rather than a border on the box, because the top of
   a border box sits above the caps by the font's internal leading and no amount
   of padding pulls it back down to meet them. */
.wordmark-box{display:inline-block;position:relative;line-height:1;
  font-size:calc(var(--fw) * .0221);letter-spacing:.525em;
  padding:0 calc(var(--fw) * .0286) 0 calc(var(--fw) * .0286 + .525em);
  /* The rule hangs .58em BELOW the box, which margin-bottom knows nothing
     about. Left out of the sum it ate the gap under the bracket, and on a
     phone the rule landed on top of BUILT IN OCEAN GROVE. The .0155 is the
     gap Luke's original leaves: 20px under a 45px cap height. */
  margin-bottom:calc(.58em + var(--fw) * .0155)}
.wordmark-box::before{content:"";position:absolute;left:0;right:0;
  top:.128em;bottom:-.58em;
  border-left:2px solid var(--np-navy);
  border-right:2px solid var(--np-navy);
  border-bottom:2px solid var(--np-navy)}

.wordmark-foot{line-height:1;font-size:calc(var(--fw) * .0185);
  letter-spacing:.16em;font-weight:400;padding-left:.16em}

/* The rating and the two buttons under the wordmark. They are not in Luke's
   mock up, which stops at "Built in Ocean Grove". They stay because without
   them the first screen carries no way to ring: the only call action would be
   the header pill, and on a phone that is a 44px target competing with the
   menu. Flagged to Luke on 30/08/2026; his call to remove them. */
.titleband .hero-rating{margin-top:clamp(20px,2.6vw,30px)}
.titleband .btn-row{justify-content:center;margin-top:var(--sp-4)}

/* The place names run space-between across a fixed measure, which is right on a
   wide screen and impossible on a narrow one: three words that cannot wrap ran
   straight off the right of a 390px phone. Below 700px they stack and centre.
   Written after the desktop rule, not before, because both are (0,1,0). */
/* The desktop rule sets display:grid. This block used to override only flex
   properties, which a grid ignores, so the three names sat in a three column
   grid stretched across the full width of a phone and ran together with no
   margins. display:flex has to be restated here for the wrap to happen. */
@media (max-width:700px){
  .wordmark-row{display:flex;flex-wrap:wrap;justify-content:center;width:100%;
    column-gap:.34em;row-gap:.06em;
    font-size:clamp(27px,8.6vw,40px);letter-spacing:.02em;
    margin-bottom:clamp(8px,2.4vw,14px)}
  .wordmark-word{margin-right:0}
  .wordmark-word--l,.wordmark-word--c,.wordmark-word--r{justify-self:auto}
  .wordmark-box{font-size:clamp(14px,4.1vw,21px);letter-spacing:.34em;
    padding:0 clamp(16px,5vw,30px) 0 calc(clamp(16px,5vw,30px) + .34em);
    margin-bottom:calc(.58em + clamp(7px,2.2vw,13px))}
  .wordmark-foot{font-size:clamp(10px,2.9vw,14px);letter-spacing:.16em;
    padding-left:.16em}
  .titleband .container{padding-top:clamp(12px,3.4vw,20px);
    padding-bottom:clamp(18px,5vw,30px)}
}

/* ------------------------------------------ the owner band on navy, 31/08/2026
   The section was written for the tint and carries two things that vanish on a
   dark ground: .ownergrid-copy .eyebrow is pinned blue at (0,2,0), which beats
   the .section--navy .eyebrow rule, and .cred's text inherits body navy, which
   measured 1:1 against the band. Both are fixed here rather than by loosening
   the originals, because on every other page the section is still on the tint
   and both rules are right there. */
.section--navy .ownergrid-copy .eyebrow{color:var(--np-sky)}
.section--navy .cred{color:var(--np-navy-copy)}
.section--navy .cred svg{color:var(--np-sky)}
/* A photograph with a bright sky in it floats on navy with nothing to hold it.
   A hairline gives it an edge without turning it into a framed picture. */
.section--navy .ownergrid-photo img{box-shadow:0 0 0 1px rgba(255,255,255,.16)}

/* Sized up in Aug 2026 to compensate for the condensed face reading small at
   a given size. That face is gone, so the compensation goes with it. */
.eyebrow{font-size:14px}
@media (min-width:1024px){.eyebrow{font-size:15px}}

/* ------------------------------------------------ service area zones, 31/08/2026
   Three zones behind three tabs, replacing eleven suburb cards. The tab row is
   the point of the section now, so the tabs are sized as controls rather than
   as labels: 44px minimum, real hit area, an obvious selected state.

   Everything below [data-enhanced] only applies once site.js has run. Without
   it all three panels stay open as plain lists, which is what a crawler reads
   and what someone gets if the script never loads. */
.zones{margin-top:var(--sp-6)}
.zonetabs{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--sp-3);
  margin-bottom:var(--sp-6)}
.zonetab{display:inline-flex;align-items:center;gap:10px;min-height:52px;
  padding:12px 26px;border:var(--bw-hair) solid var(--np-border-strong);
  border-radius:var(--r-full);background:var(--np-white);color:var(--np-navy);
  font-family:var(--font-display);font-weight:700;font-size:15px;letter-spacing:.08em;
  text-transform:uppercase;cursor:pointer;
  transition:background-color .15s ease,border-color .15s ease,color .15s ease}
.zonetab svg{width:20px;height:20px;flex:0 0 auto;color:var(--np-blue);
  transition:color .15s ease}
.zonetab-n{font-family:var(--font-body);font-size:12.5px;font-weight:600;
  letter-spacing:0;color:var(--np-slate);background:var(--np-band);
  border-radius:var(--r-full);padding:2px 9px;transition:background-color .15s ease,color .15s ease}
.zonetab:hover{border-color:var(--np-blue)}
.zonetab[aria-selected="true"]{background:var(--np-navy);border-color:var(--np-navy);
  color:var(--np-white)}
.zonetab[aria-selected="true"] svg{color:var(--np-white)}
.zonetab[aria-selected="true"] .zonetab-n{background:rgba(255,255,255,.16);
  color:var(--np-white)}

.zonelist{display:grid;gap:var(--sp-2) var(--sp-5);margin:0;padding:0;
  list-style:none;max-width:none;
  grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}
.zonelist li{margin:0;font-size:15.5px;color:var(--np-navy);
  padding:9px 0 9px 20px;position:relative;
  border-bottom:var(--bw-hair) solid var(--np-band-edge)}
.zonelist li::before{content:"";position:absolute;left:2px;top:50%;
  width:6px;height:6px;margin-top:-3px;border-radius:50%;background:var(--np-blue)}
.zonelist a{color:var(--np-navy);text-decoration:none;
  text-decoration-line:underline;text-underline-offset:3px;
  text-decoration-color:var(--np-border-strong)}
.zonelist a:hover{color:var(--np-blue);text-decoration-color:currentColor}
.zonepanel{outline-offset:4px}
/* Before the script runs every zone is visible, so each needs its own heading
   in that state. After it runs the tab row is the heading. */
.zonepanel + .zonepanel{margin-top:var(--sp-5)}
[data-enhanced] .zonepanel + .zonepanel{margin-top:0}
@media (max-width:520px){
  .zonetabs{gap:var(--sp-2)}
  .zonetab{font-size:16px;padding:11px 18px;letter-spacing:.12em}
  .zonelist{grid-template-columns:1fr 1fr;gap:0 var(--sp-4)}
}

/* ELECTRICIANS came out on 31/08/2026, Luke's call. Two things follow from it.
   The bracket's bottom rule was what BUILT IN OCEAN GROVE sat on, so the foot
   line needs its own air; and with only two lines left, the foot has to carry
   more weight than it did as the third of three.

   Measured off Luke's own example at 1710px wide: place names 54px cap, foot
   line 21px cap and 428px wide, 32px between them. That puts the foot at 0.389
   of the place names rather than the 0.272 it was. */
.wordmark-row{margin-bottom:calc(var(--fw) * .0178)}
.wordmark-foot{font-size:calc(var(--fw) * .0167)}
@media (max-width:700px){
  .wordmark-row{margin-bottom:clamp(10px,3.2vw,19px)}
  .wordmark-foot{font-size:clamp(12px,3.6vw,18px)}
}

/* The fold runs to the bottom of the screen. Without this the bands above it
   added up to 868px of a 945px window and 77px of the navy reviews section
   showed under the headline, which read as a colour creeping up from the bottom
   rather than as the next section starting. The subtraction uses the same 120px
   of chrome the --fw formula does, so the two cannot drift apart.

   The wordmark is centred in whatever height is left rather than pinned under
   the rule. Luke's pick on 31/08/2026 from four versions. It does mean the
   headline sits a little differently on a tall window than a short one; the
   trade is the air above it, which is what he was after. */
@media (min-width:768px){
  .titleband{min-height:calc(100svh - 120px - var(--fw) * .4097 - var(--strip-h));
    display:flex;flex-direction:column;justify-content:center}
  /* This rule sits after the one that puts the container on the rail and is
     the same specificity, so a bare width:100% here silently undid it and put
     the wordmark back on the full viewport. Carry the rail through. */
  .titleband > .container{width:var(--fold-rail);padding-top:0;
    padding-bottom:calc(var(--fw) * .005)}
}

/* Luke's pick from four, 31/08/2026. The picture takes .4000 of the unit and
   the white band takes whatever is left of the screen, so the fold always ends
   on white and no part of the navy section below shows under it.

   The .005 padding-bottom on the container is not decoration: the flex centring
   above centres the h1's BOX, and the font's internal leading leaves more space
   under the last baseline than above the first cap. Measured, that put the
   wording 7px low. This pushes it back so the white above the ink equals the
   white below it, which is what the eye actually reads. */
@media (min-width:768px){
  .hero--home .hero-scene{height:calc(var(--fw) * .4097)}
  .titleband{min-height:calc(100svh - 120px - var(--fw) * .4097)}
}

/* -------------------------------------------- the suburb fold, 31/08/2026
   Same three bands as the home page. Two differences, both deliberate.

   The wordmark is one line, not two: "Built in Ocean Grove" under "Electrician
   Ocean Grove" would say the same thing twice. With one line the band needs
   less height, so the picture takes more.

   The picture is a marked placeholder until Luke's Ocean Grove illustration
   exists. It says what it is rather than borrowing the Geelong waterfront,
   which is a different place and would be a small lie on a page about this
   one. */
.hero-scene--placeholder{display:flex;align-items:center;justify-content:center;
  /* background-color first, then the stripes over it. A gradient alone is not a
     background-color, so the contrast checker walked up the tree, found nothing
     and scored the text against itself at 1:1. */
  background-color:#E6EBF2;
  background-image:repeating-linear-gradient(45deg,#DDE4EC 0 22px,transparent 22px 44px);
  color:var(--np-navy);text-align:center;font-family:var(--font-body);
  font-size:clamp(14px,1.15vw,19px);line-height:1.6;letter-spacing:.02em}
.hero-scene--placeholder b{display:inline-block;margin-top:6px;
  font-family:var(--font-display);font-weight:700;letter-spacing:.10em;
  text-transform:uppercase;color:var(--np-navy);font-size:1em}

.wordmark-row--one{grid-template-columns:1fr;justify-items:center}
.wordmark-row--one .wordmark-word{justify-self:center}
/* 14/09/2026. The picture's share of the fold and the band's are two halves of
   one sum, and the fold has to come to exactly one screen. Previously the band
   got a min-height of "screen minus picture" and the picture a fixed .4550 of
   --fw, but that height was only ever applied to .hero-scene--placeholder. The
   first suburb to get a real illustration (Ocean Grove) therefore had a picture
   sized by its own aspect ratio and a band that swelled to absorb the
   difference: 398px of mostly white at 1280.

   Inverted instead of re-tuned. The band is now sized by its own content, which
   is what makes the spacing around the wordmark even, and the picture takes
   everything left over. The sum is exact by construction rather than by a
   fraction that has to be re-guessed whenever the type changes.

   .0621 is the band's measured content height as a fraction of --fw: 80/1280,
   89/1440, 104/1680, 115/1846 all land on .062. It is only a floor for the
   picture, so if the band ever renders taller the picture gives way rather than
   the fold overflowing.

   181px is the chrome above and below the picture, measured rather than
   assumed: the utility bar, header and promise strip come to 151px at 1366 and
   181px at 1920. The old figure here was 120px, which is why the fold ran off
   the bottom of the screen the moment the picture was sized from it. The worst
   case is used so no width overflows; narrower screens give up a few pixels of
   picture rather than pushing the heading out of sight. */
@media (min-width:768px){
  .titleband--sub{min-height:0}
  .hero--sub .hero-scene,
  .hero--home .hero-scene--placeholder{
    height:calc(100svh - 181px - var(--fw) * .0621)}
  .hero--sub .hero-scene img{width:100%;height:100%;object-fit:cover;
    object-position:50% 35%;display:block}
}

/* The one-line wordmark sat 26px high in its band: 21px of white above the ink
   and 47px below. That is the font's own metrics, not the padding — with
   line-height 1 on caps, the space under the baseline is bigger than the space
   over the cap, and flex centring centres the BOX, not the letters. The padding
   pushes it back down so the two are equal. The home page's three-line block
   needs a different figure, which is why this is scoped to the suburb fold. */
/* 14/09/2026. Evened by pulling the band's floor UP rather than pushing the
   text down. Padding-top grows the band 1:1, which works against the whole
   point of the change, so the surplus under the baseline is cropped with a
   negative margin instead: the gaps match AND the band gets shorter.
   Measured off rendered pixels, not element boxes, at 1280x800, 1440x900,
   1680x1050 and 1920x1080: the slack ran 11-16px, a consistent .0088 of --fw. */
@media (min-width:768px){
  .titleband--sub > .container{padding-top:calc(var(--fw) * .0132);padding-bottom:0}
  .titleband--sub .wordmark{margin-bottom:calc(var(--fw) * -.0088)}
}

/* ------------------------------------------------------------ nearby suburbs
   A plain internal-link paragraph under the related-services cards. Cheap to
   maintain and it gives every neighbouring suburb page a link from the one
   page that already ranks. */
.nearby{margin-top:var(--sp-7);text-align:center}
.nearby h3{font-size:17px;margin-bottom:var(--sp-3)}
.nearby p{max-width:62ch;margin-left:auto;margin-right:auto;color:var(--np-slate);font-size:15px}
/* .prose sat hard left with the whole right half of the container empty, the
   only block on the page that did not centre. The copy stays left aligned,
   which is correct for reading; the column itself now centres. */
.prose{margin-left:auto;margin-right:auto}

/* Stacked ledes in a section head ran together: .lede has no bottom margin
   because it is normally the only paragraph in the block. */
.section-head .lede + .lede{margin-top:var(--sp-4)}

/* =========================================================== the wash hero
   Modelled on the reference site's service hero, measured off their page:
   a 165deg gradient from off-white through a pale tint and back, one centred
   headline at 64px/1.08 with -1.5px tracking capped at 880px, a 20px/32px sub
   line capped at 660px, one button, two proof chips. Theirs is #FAF9F7 to
   #E8F6FD; ours runs the same shape through NextPoint blue instead of cyan.

   Selectors are doubled (.hero.hero--wash) on purpose. The base .hero rules
   set a navy ground and pale copy at the same specificity, and relying on
   source order alone is exactly what put white type on white earlier in this
   build. */
.hero.hero--wash{background-color:#EDF2FB;
  background-image:linear-gradient(165deg,#FBFBFD 0%,#E2ECFA 50%,#FBFBFD 100%);
  color:var(--np-navy);text-align:center;padding:var(--sp-8) 0 var(--sp-7);border-bottom:0}
@media (min-width:768px){.hero.hero--wash{padding:88px 0 80px}}
/* 14/09, Luke: "made nicer with a better font to bring it to life". The
   headline was Archivo at the same weight as the body copy, only larger, which
   is why it read flat. Moved onto the condensed face the home hero already
   uses for ELECTRICAL WORK. DONE RIGHT., set in caps, so a service page opens
   with the same voice as the front door.

   Condensed is doing real work here, not just styling: "Oven and Cooktop
   Installation Geelong" is 36 characters and would wrap past three lines at
   this size in the normal-width cut. */
.hero.hero--wash h1{font-family:var(--font-hero);font-weight:800;color:var(--np-navy);
  text-transform:uppercase;letter-spacing:-.005em;line-height:.9;
  font-size:clamp(40px,7.2vw,92px);
  max-width:1000px;margin:0 auto}
.hero.hero--wash h1 .accent{color:var(--np-blue)}
.hero.hero--wash .lede{font-size:17px;line-height:1.6;color:var(--np-slate);
  max-width:660px;margin:var(--sp-5) auto 0}
@media (min-width:768px){.hero.hero--wash .lede{font-size:20px;line-height:32px}}
.hero.hero--wash .btn-row{display:flex;justify-content:center;margin-top:var(--sp-6)}

/* The proof chips. Real claims only: the Google rating that already runs in
   the footer, and the REC number Victoria requires on advertising. The
   reference site's second chip is a Facebook rating, which we do not have. */
.herochips{list-style:none;display:flex;flex-wrap:wrap;justify-content:center;
  gap:var(--sp-3);margin:var(--sp-6) auto 0;padding:0;max-width:none}
.herochips li{display:flex;align-items:center;gap:8px;background:var(--np-white);
  border:var(--bw-hair) solid var(--np-border);border-radius:var(--r-full);
  box-shadow:var(--sh-1);padding:9px 16px;font-size:13.5px;color:var(--np-slate)}
.herochips b{color:var(--np-navy)}
.herochips svg{height:16px;width:16px;flex:0 0 auto;color:var(--np-blue)}
/* .hero .stars is pale navy copy for the dark heroes and vanishes on this one. */
.hero.hero--wash .stars{color:var(--np-warning);margin:0;font-size:13px;letter-spacing:1px}
/* Review cards stretched to the tallest in the row, so one long quote left the
   two beside it with a block of empty card under the text. Let each card be
   its own height instead. */
.grid--3 .review,.grid--2 .review{align-self:stretch}
/* The service link list on suburb pages. Same column behaviour as .linklist,
   with a little more room and a marker, because these are the main way into
   the service pages from a suburb page rather than a footnote. */
.linklist--svc{columns:1;margin-top:var(--sp-6);text-align:left;
  max-width:min(100%,760px);margin-left:auto;margin-right:auto}
@media (min-width:640px){.linklist--svc{columns:2;column-gap:var(--sp-7)}}
.linklist--svc li{margin-bottom:0;break-inside:avoid;border-bottom:var(--bw-hair) solid var(--np-border)}
.linklist--svc a{display:block;padding:14px 4px;text-decoration:none;font-weight:600;
  color:var(--np-navy);min-height:44px}
.linklist--svc a:hover,.linklist--svc a:focus-visible{color:var(--np-blue)}
.linklist--svc a::after{content:" \203A";color:var(--np-blue)}

/* ================================================= the fold, 12/09/2026
   Luke's design: the headline moves back onto the picture, left aligned, with a
   kicker above it, a sub line, two buttons, and the promise strip laid over the
   foot of the image rather than sitting under it as its own band. The place
   names stay below on white. */
/* clip on x, visible on y. The cut-out has to escape the box downwards, past
   the promise bar, and the bar's own 100vw backgrounds have to be cut off at
   the edge of the page: plain overflow:visible let those run off the right and
   gave the whole site a horizontal scrollbar at 768, 1024 and 1440. clip is
   the one value that can be set on a single axis without forcing the other to
   scroll. */
.hero--home .hero-scene:not(.hero-scene--placeholder){position:relative;isolation:isolate;
  overflow-x:clip;overflow-y:visible}
/* The top of his hair, and only that, painted over the white header so he
   breaks the frame the way he does in Luke's mock. It cannot be done inside
   the picture: the header is sticky at z-index 100 and the picture sits in its
   own stacking context underneath it. So this is a separate sliver, as tall as
   the rise and no taller, carrying the same cut-out on the same box, sitting
   above the header at 101. Kept to the rise so that the only thing that ever
   crosses the header on the way up the page is 10px of hair. */
.hero--home{position:relative}
.hero-hair{position:absolute;left:0;right:0;top:calc(-1 * var(--fg-rise));
  height:var(--fg-rise);overflow:hidden;z-index:101;pointer-events:none}
.hero-hair img{position:absolute;left:0;top:0;width:100%;display:block;
  height:calc(var(--fw) * .4097 + var(--fg-rise) + var(--fg-drop));
  object-fit:cover;object-position:50% 0}
.hero--home .hero-scene:not(.hero-scene--placeholder) > picture,
.hero--home .hero-scene:not(.hero-scene--placeholder) img{position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover}

/* Type on a photograph needs a ground, not a hope. The left two thirds carry
   the copy, so the scrim is heaviest there and clears entirely by the time it
   reaches the figure on the right. Verified by sampling the rendered pixels,
   not by eye: see verify-hero-contrast.js. */
/* 15/09/2026. The new hero photograph puts bright sand and surf under the right
   hand end of the headline, where the old gradient had already faded out. On the
   previous picture that area was dark water, so it never showed. Measured over
   the headline box at 1440 wide, 5.5% of the pixels behind the white type fell
   under the 3.0:1 large-text minimum, effectively all of them in the right third.
   The dark end is unchanged; the fade is held further across and then drops
   away, so the right of the picture is as clear as it was. */
.hero-scrim{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(to right,
      rgba(0,13,35,.64) 0%, rgba(0,13,35,.62) 20%,
      rgba(0,13,35,.60) 36%, rgba(0,13,35,.56) 48%,
      rgba(0,13,35,.40) 58%, rgba(0,13,35,.16) 67%,
      rgba(0,13,35,0) 75%)}

/* Every number below is measured off the mock Luke sent on 12/09/2026, a
   1619 x 971 frame, and written as a fraction of that frame so the block holds
   its proportions at any width. The measurements, in his pixels:
     hero band        120 to 769, 649 tall, strip laid over its last 48
     copy left edge   104
     kicker           cap 14, cap top 245
     headline         cap 57, cap tops 287 and 359, so 72 between baselines
     sub line         cap 18, cap top 443
     buttons          64 tall, 276 and 277 wide, 19 apart, top 498
     promise strip    48 tall
   The copy block runs 245 to 561, centred in the picture above the strip. */
.hero-overlay{position:absolute;inset:0 0 var(--strip-h) 0;z-index:2;
  display:flex;align-items:flex-start;
  padding:calc(var(--fw) * .0687) calc((100% - var(--fold-rail)) / 2) 0;
  padding-left:calc((100% - var(--fold-rail)) / 2 + var(--fw) * .0156)}
.hero-overlay-inner{max-width:calc(var(--fw) * .42);position:relative;isolation:isolate}
/* A soft plate behind the copy only. The page-wide haze is the light one Luke
   asked for; this carries the contrast where the words actually are, and stops
   at the edge of the block instead of washing half the picture. */
.hero-overlay-inner::before{content:"";position:absolute;z-index:-1;
  pointer-events:none;
  left:calc(var(--fw) * -.16);right:calc(var(--fw) * -.30);
  top:calc(var(--fw) * -.13);bottom:calc(var(--fw) * -.15);
  /* The ellipse must reach zero before the box edge or it cuts off as a hard
     vertical line: 45% centre with a 44% radius lands the left edge at 1%. */
  background:radial-gradient(44% 48% at 45% 50%,
    rgba(0,13,35,.58) 0%, rgba(0,13,35,.52) 36%,
    rgba(0,13,35,.36) 58%, rgba(0,13,35,.16) 78%,
    rgba(0,13,35,.04) 90%, rgba(0,13,35,0) 100%)}
/* The heavy display face carries a wider left side bearing than the kicker's
   face, so with both boxes on the same left edge the kicker's ink sat 4px left
   of the E in ELECTRICAL and read as hanging out. Pushed across by the
   difference, in --fw units so it holds at every width. */
.hero-kicker{font-family:var(--font-compressed);font-weight:400;text-transform:uppercase;
  letter-spacing:.34em;font-size:calc(var(--fw) * .0107);line-height:1;color:#BBD4F2;
  margin-left:calc(var(--fw) * .0025);
  margin-bottom:calc(var(--fw) * .0150)}
/* 13/09: the picture became the clean illustration, which is a much brighter
   image than the photograph it replaced, and Luke had already asked for the haze
   to be pulled back. The headline landed on the white pavilion roof at 1.9:1.
   Rather than put the haze back over half the page, the shadow is kept tight to
   the letters: it darkens only the pixels the eye reads the edge against, so it
   buys the contrast without the storm cloud he did not want. */
.hero-line{font-family:var(--font-hero);font-weight:800;text-transform:uppercase;
  line-height:.854;letter-spacing:-.005em;font-size:calc(var(--fw) * .0494);
  color:var(--np-white);
  text-shadow:0 1px 2px rgba(0,13,35,.55),
              0 2px 10px rgba(0,13,35,.70),
              0 4px 26px rgba(0,13,35,.55)}
.hero-sub{margin:calc(var(--fw) * -.0134) 0 0;max-width:none;color:rgba(255,255,255,.94);
  font-size:calc(var(--fw) * .0150);line-height:1.45;
  text-shadow:0 1px 2px rgba(0,13,35,.60), 0 2px 12px rgba(0,13,35,.62)}
.hero-kicker{text-shadow:0 1px 8px rgba(0,13,35,.70)}
/* body.home .btn-row centres every button row on the home page, which pushed
   these two 53px right of the headline they sit under. Written long-hand so it
   outranks it. */
body.home .btn-row.hero-cta{margin-top:calc(var(--fw) * .0202);margin-bottom:0;
  display:flex;flex-wrap:wrap;justify-content:flex-start;
  gap:calc(var(--fw) * .0117)}
/* The buttons in the mock are wider and squarer than the site's pill: 64 tall
   on a 14px radius, not a capsule. Sized here rather than on .btn--lg so the
   rest of the site keeps the pill it already uses. */
.hero-cta .btn{min-height:calc(var(--fw) * .0448);
  padding:0 calc(var(--fw) * .0228);
  font-family:var(--font-body);font-weight:600;
  font-size:calc(var(--fw) * .0135);line-height:1;
  border-radius:calc(var(--fw) * .0086)}
.hero-cta .btn--onimage{border-width:2px}
.btn--onimage{background:rgba(0,13,35,.64);border-color:rgba(255,255,255,.90);
  color:var(--np-white)}
.btn--onimage:hover,.btn--onimage:focus-visible{background:rgba(0,13,35,.78);
  border-color:#fff;color:var(--np-white)}

/* The electrician's hand and the multimeter in it, cut out of the same picture
   and laid back over the promise strip so they come down in front of it and
   finish just under its bottom edge. Everything else about him stops at the
   top of the bar, which is what Luke's 13/09 mock shows: he stands behind the
   bar, the tool in his hand comes in front of it.

   One image, not two. It is the same file as the picture underneath, on the
   same box and the same object-fit, so the two are registered at every width;
   the clip below is what decides which part of him is allowed past the bar.

   Written as .hero--home .hero-scene img.hero-fg, not .hero-fg: two rules
   further up set height:100% on every img in this box, and a bare class loses
   to both. Unqualified, the cut-out came out the same height as the picture
   and the multimeter was sliced off at its bottom edge. */
.hero--home .hero-scene img.hero-fg{position:absolute;left:0;right:auto;
  bottom:auto;width:100%;
  top:calc(-1 * var(--fg-rise));
  height:calc(100% + var(--fg-rise) + var(--fg-drop));
  object-fit:cover;object-position:50% 0;
  /* Full width down to the top of the bar, then a tab 67.5% wide carrying the
     hand, the multimeter and the coiled leads past it. 67.5% is where the leads
     end and his trouser leg starts, measured off the cut-out; the picture is
     never cropped horizontally at any width this fold uses, so that holds.
     Right of the tab he is cut at the top of the STEPPED cell, not at the top
     of the other two, or a slice of the photograph shows through his body in
     the gap between the two levels. */
  /* 13/09: nothing crosses the bar any more, so there is no tab. The browser
     cuts him at the top of the strip itself, which means no rounding gap and no
     few-pixel overlap from wherever the cut-out happens to end. */
  clip-path:inset(0 0 calc(var(--fg-drop) + var(--strip-h) - var(--strip-step)) 0);
  z-index:4;pointer-events:none;user-select:none}

/* The step in the bar. The third cell sits lower than the other two and its
   navy runs off the right of the screen, which is what Luke's mock shows: the
   bar is interrupted where he stands and picks up again underneath him. The
   label stays centred in the third it started in, so it lands just right of
   the step rather than out at the margin. Painted with a 100vw pseudo-element
   rather than by widening the cell, because widening the cell would drag the
   label right with it. */
/* The third label used to carry a big left padding to clear the hand and meter
   coming down through the bar. Nothing crosses the bar now, so it goes back to
   sitting centred in its own third like the other two, which is what makes the
   three read as evenly spaced. */
.promisestrip--onimage li:last-child{top:var(--strip-step);white-space:nowrap}
.promisestrip--onimage li:last-child::before{right:auto;width:100vw}

/* No background on the strip itself: each cell paints its own, because the
   third one sits lower than the other two and a background on the whole strip
   would fill the gap above it. The first cell's navy runs off the left of the
   screen and the third one's off the right, which is what the mock shows. */
.promisestrip--onimage{position:absolute;left:0;right:0;bottom:0;z-index:3;
  height:var(--strip-h);
  grid-template-rows:var(--strip-h);align-items:stretch;
  background:none;border-top:0}
.promisestrip--onimage li::before{content:"";position:absolute;
  top:0;bottom:0;left:0;right:0;background:var(--np-navy);
  border-top:1px solid rgba(255,255,255,.16);z-index:-1}
.promisestrip--onimage li{position:relative}
.promisestrip--onimage li:first-child::before{left:-100vw}

@media (max-width:700px){
  .hero-overlay{position:static;padding:0 20px}
  .hero-overlay-inner{max-width:none;padding:var(--sp-7) 0 var(--sp-6)}
  /* Scoped away from the suburb placeholder, which is also a .hero-scene inside
     .hero--home. Unscoped, this painted navy over it and dropped its label to
     1:1 on every one of the eleven suburb pages. */
  .hero--home .hero-scene:not(.hero-scene--placeholder){height:auto;min-height:0;
    background:var(--np-navy);display:flex;flex-direction:column}
  .hero--home .hero-scene:not(.hero-scene--placeholder) > picture,
  .hero--home .hero-scene:not(.hero-scene--placeholder) img{position:relative;height:auto}
  .hero-scrim{display:none}
  /* The copy sits on a plain navy block on a phone, so the haze behind it has
     nothing to do and would only show as a smudge. */
  .hero-overlay-inner::before{display:none}
  /* Written long-hand: a bare .hero-fg loses to .hero--home .hero-scene img,
     which sets display:block two hundred lines further up. */
  .hero--home .hero-scene img.hero-fg{display:none}
  .hero-hair{display:none}
  .promisestrip--onimage{position:static;background:var(--np-navy);backdrop-filter:none}
  .hero-kicker{font-size:12px;letter-spacing:.20em}
  .hero-line{font-size:clamp(32px,10.5vw,46px)}
  .hero-sub{font-size:16px;max-width:none}
  /* The desktop button is sized in fold units, and a fold unit on a phone is
     the phone's own width: 390 * .0135 is a 5px label. Plain pixels here. */
  body.home .btn-row.hero-cta{gap:10px;margin-top:20px;margin-bottom:0}
  .hero-cta .btn{min-height:52px;padding:14px 22px;font-size:16px;
    border-radius:12px}
}

/* ------------------------------------------------- review cards, 14/09/2026
   Rebuilt to the shape Google uses: avatar, name, source, stars, then the
   quote. The avatar carries the reviewer's initials on a hue derived from
   their name, which is what Google renders for a reviewer with no photo, and
   the small G badge is what marks the card as a Google review rather than a
   testimonial we wrote. Star colour moved off --np-warning, which rendered a
   muddy brown at rgb(138,90,0) and did not read as a rating. */
/* .review figcaption above still carries margin-top:auto from when the caption
   sat at the BOTTOM of a column-flex card. The caption is now first, so that
   rule pushed each header down by whatever slack the card had and the six
   headers landed at different heights. Outranked here rather than deleted,
   because the old rule still does its job on any caption that is not a
   review-who. */
.review .review-who{display:grid;grid-template-columns:auto 1fr;
  column-gap:13px;row-gap:1px;align-items:center;
  margin:0 0 var(--sp-4);padding:0;font-size:14px}
/* Let the quote take the slack instead, so cards in a row end level. */
.review blockquote{flex:1 1 auto}
.review-avwrap{grid-row:1 / span 3;position:relative;display:inline-block;line-height:0}
.review-av{width:42px;height:42px;border-radius:999px;display:grid;place-items:center;
  background:hsl(var(--h) 60% 92%);color:hsl(var(--h) 68% 28%);
  font-family:var(--font-display);font-weight:800;font-size:15px;line-height:1;
  letter-spacing:.01em}
.review-gb{position:absolute;right:-4px;bottom:-2px;background:var(--np-white);
  border-radius:999px;padding:2px;line-height:0;box-shadow:0 1px 3px rgba(0,13,35,.22)}
.review-gb .gmark{width:14px;height:14px;display:block}
.review-nm{grid-column:2;color:var(--np-navy);font-weight:700;font-size:15px;line-height:1.25}
.review-src{grid-column:2;color:var(--np-slate);font-size:12.5px;line-height:1.3}
.review-who .stars{grid-column:2;margin:2px 0 0;font-size:13.5px;letter-spacing:2px;line-height:1}
.review blockquote{margin:0}
.review-sum{display:inline-flex;align-items:center;gap:13px;margin:0 0 var(--sp-3);
  padding:9px 20px 9px 15px;background:var(--np-white);
  border:var(--bw-hair) solid var(--np-border);border-radius:var(--r-full);
  box-shadow:0 2px 10px rgba(0,13,35,.06)}
.review-sum .gmark{width:24px;height:24px;flex:0 0 24px}
.review-sum-n{font-family:var(--font-display);font-weight:800;font-size:32px;
  line-height:1;color:var(--np-navy)}
.review-sum-b{display:flex;flex-direction:column;align-items:flex-start;gap:1px}
.review-sum-b .stars{margin:0;font-size:15px;letter-spacing:2px;line-height:1}
.review-sum-t{font-size:13px;color:var(--np-slate)}
.review-sum-t b{color:var(--np-navy);font-weight:700}
/* Gold, not the amber warning token. Decorative: every star row carries an
   aria-label, so contrast is not load bearing here. */
.stars{color:#E8A200}
/* On the dark band the tiles keep their own ground, so the avatar and badge
   need the light treatment rather than inheriting the card's transparency. */
.section--navy .review-src{color:var(--np-navy-copy)}
.section--navy .review-nm{color:var(--np-white)}
.section--navy .review-gb{background:var(--np-navy)}
/* The global p{max-width:var(--measure)} caps every paragraph at 68ch for
   readability. This wrapper is a <p> holding a button, so it inherited the cap:
   686px inside a 1200px container, pinned left, and the button centred itself
   inside the wrong box, landing 207px left of the review grid's centre at 1280
   and above. Only looked right at 390, where the container is narrower than the
   cap anyway. Opt this one wrapper out and centre it on the container. */
.review-cta{text-align:center;margin:var(--sp-6) auto 0;max-width:none}
.review-cta a{display:inline-flex;align-items:center;gap:10px;min-height:48px;
  font-family:var(--font-display);font-weight:800;font-size:15px;color:var(--np-navy);
  text-decoration:none;background:var(--np-white);
  border:var(--bw-hair) solid var(--np-border);border-radius:var(--r-full);
  padding:12px 26px;box-shadow:0 2px 10px rgba(0,13,35,.06);
  transition:border-color var(--mo-fast) var(--mo-ease)}
.review-cta a:hover{border-color:var(--np-blue)}
.review-cta .gmark{width:18px;height:18px;flex:0 0 18px}



/* ------------------------------------------------ mobile promise strip, 14/09
   One row of three rather than three stacked rows: 152px down to about 70px,
   and the height goes to the picture. Navy, which Luke chose over the white
   version: it reads as one dark band with the header above it and leaves the
   white wordmark band below as its own step.

   Written at the END of the file deliberately. The first attempt put it in the
   max-width:700px block further up, which sits BEFORE the base .promisestrip
   rules; same specificity, so the base flex-direction:column won and the strip
   stayed 238px tall. */
@media (max-width:700px){
  /* :not(.promisestrip--onimage) matters. The home page runs the other variant,
     which sits OVER the picture and is re-laid-out for mobile by its own rules
     further up. Applying the one-line treatment to it collided the three
     promises with the GEELONG. BELLARINE. SURF COAST. wordmark underneath. */
  .promisestrip:not(.promisestrip--onimage){flex-direction:row;
    justify-content:space-evenly;align-items:stretch}
  .promisestrip:not(.promisestrip--onimage) li{flex:1 1 0;flex-direction:column;
    gap:4px;padding:9px 4px;font-size:10.5px;text-align:center;
    line-height:1.25;border-top:0}
  .promisestrip:not(.promisestrip--onimage) svg{height:17px}
}

/* ------------------------------------------- first section on a phone, 14/09
   64px of section padding is a desktop figure. On a phone it left only 16px of
   the 56px Google rating pill clear of the fixed call bar, so the strongest
   proof on the page read as a sliver. 20px clears the whole pill.

   .section--lead is stamped by the build. No CSS selector reaches this element
   on its own: main > section.section:first-of-type matches nothing, because the
   first <section> child of main is the fold, which carries .hero and not
   .section. Two earlier attempts at this silently did nothing. */
@media (max-width:700px){
  .section--lead{padding-top:20px}
}

/* --------------------------------------- home promise strip on a phone, 14/09
   Two faults, both live and neither introduced today.

   1. .promisestrip--onimage carries height:var(--strip-h) so the bar can hug
      the bottom of the desktop picture. On a phone the mobile override turns it
      static but leaves the height, so the box stayed 12.9px while its three
      items rendered at 50px each and overflowed: they ran from y700 to y852,
      straight over the GEELONG. BELLARINE. SURF COAST. band at y713 and behind
      the fixed call bar at y771. The second and third promises were unreadable.
   2. Stacked three-deep it cost 152px of a phone screen.

   Height released, and the same one-row treatment the suburb folds use. 152px
   down to about 78px, and nothing overlaps. */
@media (max-width:700px){
  .hero--home .promisestrip--onimage{height:auto;min-height:0;
    flex-direction:row;justify-content:space-evenly;align-items:stretch}
  .hero--home .promisestrip--onimage li{flex:1 1 0;flex-direction:column;gap:4px;
    padding:9px 4px;font-size:10.5px;text-align:center;line-height:1.25;border-top:0}
  .hero--home .promisestrip--onimage li::before{display:none}
  .hero--home .promisestrip--onimage svg{height:17px}
  /* the last cell carries white-space:nowrap so "Fast local response" stays on
     one line against the desktop picture. On a phone it made that cell 134px
     against 113px for the other two, so the three thirds were not thirds. */
  .hero--home .promisestrip--onimage li:last-child{white-space:normal;top:0}
}

/* ------------------------------------------- home fold on a phone, 14/09/2026
   Luke's call: on a phone the home fold reads like a suburb fold and nothing
   else. The kicker, headline, sub line and the two buttons come off entirely,
   leaving picture, promise strip, place-name band, then the reviews. Desktop is
   untouched and keeps all of it over the picture.

   Hidden rather than moved. Two attempts at relocating the block below the band
   both broke the fold: lifting it out of .hero killed every ".hero h1" rule it
   inherits, and moving .titleband in collapsed the band to nothing. Hiding it
   needs no markup change at all, and the sticky Call now / SMS us bar already
   carries both actions the buttons offered. */
@media (max-width:700px){
  .hero--home .hero-overlay{display:none}
  .hero--home .hero-scene:not(.hero-scene--placeholder) > picture{
    display:block;width:100%;aspect-ratio:0.94}
  .hero--home .hero-scene:not(.hero-scene--placeholder) > picture img{
    width:100%;height:100%;object-fit:cover;object-position:50% 35%;display:block}
}

/* The three zone anchors at the top of the "Where we work" section on
   /service-areas/. They exist so the menu links point at something real:
   without JavaScript, and before site.js runs, following one lands the section
   top just under the sticky header with all three lists open, which is a
   correct page rather than a bare list. site.js then refines that to centred.
   Pointing the links at the panels themselves is what caused the fault: the
   browser aimed at where a panel sat BEFORE the other two collapsed. */
.zone-anchor{scroll-margin-top:calc(var(--header-h) + 90px)}


/* ---------------------------------------------------------------------------
   Service areas fold: stacked zone buttons.
   18/09/2026, Luke supplied the layout. These are real links to the same tab
   panels the zones section answers to, so the fold is the way into them.
   They live in the page rather than the artwork for the reason recorded
   elsewhere in this sheet: the fold is full bleed and crops 9% off each edge
   at 1440 and 30% at 768, so anything painted near the edge loses characters
   on a laptop and vanishes on a tablet.
   --------------------------------------------------------------------------- */
/* the scrim went out with the wordmark block it was written for; the buttons
   still need the picture knocked back behind them */
.hero--sub .hero-scene .scene-scrim{position:absolute;inset:0;z-index:1;
  pointer-events:none;
  background:linear-gradient(to right,
      rgba(0,13,35,.66) 0%,  rgba(0,13,35,.60) 24%,
      rgba(0,13,35,.44) 38%, rgba(0,13,35,.20) 52%,
      rgba(0,13,35,0)   66%)}

.hero--sub .hero-scene .scene-panel--stack{position:absolute;inset:0;z-index:2;
  display:flex;align-items:center;pointer-events:none}
.hero--sub .hero-scene .zonebtns{pointer-events:auto;display:flex;
  flex-direction:column;gap:clamp(10px,1.4vw,18px);
  width:min(1200px,92vw);margin:0 auto;padding:0 20px}
@media (min-width:768px){.hero--sub .hero-scene .zonebtns{padding:0 32px}}
@media (min-width:1024px){.hero--sub .hero-scene .zonebtns{padding:0 40px}}

/* .hero a:not(.btn) sets links to sky blue at 0-2-1, so these need the same
   weight to stay white */
.hero .zonebtn,.hero .zonebtn:not(.btn){
  display:flex;align-items:center;justify-content:space-between;gap:var(--sp-5);
  width:clamp(240px,26vw,360px);min-height:clamp(54px,5vw,74px);
  padding:0 clamp(18px,1.7vw,26px);border-radius:999px;text-decoration:none;
  font-family:var(--font-hero);font-weight:800;text-transform:uppercase;
  letter-spacing:.01em;font-size:clamp(20px,2.1vw,30px);line-height:1;
  color:var(--np-white);background:rgba(0,13,35,.88);
  border:2px solid rgba(120,180,255,.90);
  box-shadow:0 0 0 1px rgba(8,104,207,.35), 0 0 22px rgba(56,130,246,.45),
             inset 0 0 18px rgba(56,130,246,.18);
  transition:background .15s ease,border-color .15s ease,box-shadow .15s ease,
             transform .15s ease}
.hero .zonebtn span{white-space:nowrap}
.hero .zonebtn .scene-chev{width:1em;height:1em;flex:0 0 auto;opacity:.95}
.hero .zonebtn:hover,.hero .zonebtn:focus-visible{
  background:linear-gradient(180deg,rgba(14,116,224,.96),rgba(8,80,170,.96));
  border-color:rgba(160,205,255,1);
  box-shadow:0 0 0 1px rgba(8,104,207,.55), 0 0 30px rgba(56,130,246,.70),
             inset 0 0 20px rgba(120,180,255,.25);
  transform:translateY(-1px)}
.hero .zonebtn:focus-visible{outline:3px solid var(--np-white);outline-offset:3px}
@media (prefers-reduced-motion:reduce){.hero .zonebtn{transition:none}
  .hero .zonebtn:hover{transform:none}}

@media (max-width:700px){
  /* the phone crop puts open water at the bottom, so the buttons sit there and
     the scrim runs down the picture rather than across it */
  .hero--sub .hero-scene .scene-panel--stack{align-items:flex-end;
    padding-bottom:16px}
  /* the phone crop puts the bright beach low in the frame, so the scrim runs
     down the picture instead of across it */
  .hero--sub .hero-scene .scene-scrim{
    background:linear-gradient(to bottom,
        rgba(0,13,35,0)   18%, rgba(0,13,35,.55) 38%,
        rgba(0,13,35,.86) 56%, rgba(0,13,35,.92) 100%)}
  .hero--sub .hero-scene .zonebtns{gap:9px}
  .hero .zonebtn,.hero .zonebtn:not(.btn){width:min(300px,78%);
    min-height:50px;font-size:20px;padding:0 16px}
}
