/* JJC Electrical look (22 Oct), loaded after home.css: the brand from today's LP (black sections, orange #F9811C, light grey
   #F7F7F7, Poppins, pill buttons 42px, cards 16px) on the Westplumb build. Text on orange is always dark ink (#1A1A1A):
   white on #F9811C is 2.6:1. Accent TEXT on light sections is #B45309 (4.7:1 on #F7F7F7). Phone first. */
.jj{--display:"Poppins",system-ui,sans-serif;--body:"Poppins",system-ui,sans-serif;--btn-font:"Poppins",system-ui,sans-serif;
  --bg:#F7F7F7;--text:#2B2B2B;--muted:#5C5C5C;--line:#E2E2E2;--dark:#141414;--dark-2:#1F1F1F;--card-dark:#242424;
  --orange:#F9811C;--orange-ink:#1A1A1A;--blue:#F9811C;--blue-2:#B45309;--blue-ink:#1A1A1A;--blue-soft:rgba(249,129,28,.14);
  --blue-grad:linear-gradient(135deg,#FFA54F 0%,#F9811C 55%,#ED6D15 100%);--call-bg:#F9811C;--call-ink:#1A1A1A;
  --r:16px;--r-lg:20px;--btn-r:42px;--hdr-bg:#111;--pills-bg:#1B1B1B}
.jj h1,.jj h2,.jj h3{font-stretch:normal;text-transform:none;font-weight:800;letter-spacing:-.02em;line-height:1.08}
.jj .btn{font-stretch:normal;text-transform:none;letter-spacing:0;font-weight:700}
.jj .sec-head h2,.jj .enq-copy h2,.jj .why-copy h2{font-size:clamp(27px,7.4vw,34px)}
.jj .kicker{font-size:12.5px;letter-spacing:.14em}
.jj .kicker::before{background:var(--orange)}
.jj .kicker-light{color:#FFA54F}
.jj .lead{font-size:15.5px}
.jj p{line-height:1.6}

/* header: the full JJC logo (white type, made for dark backgrounds) */
.jj .logo img{width:auto;height:40px}
@media (max-width:359px){.jj .logo img{height:34px}}
.jj .pills a{font-weight:600}

/* buttons: the Westplumb "pipe run" outline becomes a current running round the button (no pipe fittings) */
.jj .bp-fit{display:none}
.jj .btn.pr.pr[href$="#enquire"],.jj .btn.pr.pr.btn-quote{--pc:#FFFFFF;--fill:#FFFFFF;--glow:255,255,255}
.jj .btn.pr.pr.on-light{color:#1A1A1A}
.jj .btn.pr.pr.on-light[href^="tel:"]{--pc:#F9811C;--fill:#F9811C}
.jj .btn.pr.pr.on-light[href$="#enquire"],.jj .btn.pr.pr.on-light.btn-quote{--pc:#2B2B2B;--fill:#141414;--glow:20,20,20}
.jj .btn.pr.pr.is-tap,.jj .btn.pr.pr:focus-visible,.jj .btn.pr.pr:active{color:#1A1A1A}
.jj .btn.pr.pr.on-light[href$="#enquire"].is-tap,.jj .btn.pr.pr.on-light.btn-quote.is-tap,.jj .btn.pr.pr.on-light[href$="#enquire"]:focus-visible,.jj .btn.pr.pr.on-light.btn-quote:focus-visible{color:#fff}
@media (hover:hover) and (pointer:fine){.jj .btn.pr.pr:hover{color:#1A1A1A}.jj .btn.pr.pr.on-light[href$="#enquire"]:hover,.jj .btn.pr.pr.on-light.btn-quote:hover{color:#fff}}
.jj .tel-pill{--tel-pill-ink:#1A1A1A;--tel-pill-bg:rgba(249,129,28,.14);--tel-pill-line:rgba(249,129,28,.6)}
.jj :is(.enquire,.svcs,.emerg,.dispatch,.site-footer,.ve-cta,.rw-sum,.legal-cta) .tel-pill{--tel-pill-ink:#fff}
.jj :focus-visible{outline-color:#F9811C}

/* light sections: accent text deeper orange (contrast); dark sections keep #F9811C */
.jj :is(.why,.reviews,.areas,.faq,.types,.detail,.steps,.pgal,.qband) .hl{color:#B45309}
.jj .hl{background-image:linear-gradient(#F9811C,#F9811C)}
.jj :is(.ty-ic,.hero-chips svg,.wc-ic){color:#1A1A1A}
.jj .step-list li.done .st-n{color:#1A1A1A}
.jj .qw-next{color:#1A1A1A}
.jj .ve-feat .g-badge-stars{color:#FFD24D}

/* ---------- hero ---------- */
.jj .hero{background-color:#111;background-image:url(../assets/video/j-hero-poster.jpg)}
.jj .hero-shade{background:linear-gradient(0deg,rgba(17,17,17,.97) 0%,rgba(17,17,17,.88) 42%,rgba(17,17,17,.45) 64%,rgba(17,17,17,.1) 80%,rgba(17,17,17,.3) 100%)}
.jj .hero-kicker{margin-top:12px;font-weight:700;font-size:13px;letter-spacing:.12em;text-transform:uppercase;color:#FFA54F;text-shadow:0 2px 12px rgba(0,0,0,.6)}
.jj .hero-title{margin-top:6px;font-size:clamp(38px,11.4vw,52px);line-height:1.02;letter-spacing:-.025em}
.jj .hero-title.ht-long{font-size:clamp(32px,9.6vw,46px)}
.jj .ht-1{font-size:.6em;color:#FFA54F;letter-spacing:-.01em}
.jj .hero-sub{max-width:540px;font-size:17px}
.jj .hero-chips li{background:rgba(20,20,20,.55)}
.jj .oncall-face{border-color:#F9811C}
.hero-trust{display:none}
@media (min-width:701px){
  .jj .hero{background-image:none}
  .jj .hero-title{font-size:clamp(50px,min(5.4vw,9.4vh),82px)}
  .jj .hero-title.ht-long{font-size:clamp(44px,min(4.6vw,8vh),70px)}
  .jj .hero-inner{padding-bottom:150px}
  .hero-trust{display:flex;position:absolute;left:0;right:0;bottom:0;z-index:2;justify-content:center;flex-wrap:wrap;gap:0;background:rgba(17,17,17,.72);border-top:1px solid rgba(255,255,255,.12);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
  .hero-trust li{display:flex;align-items:center;gap:9px;padding:16px clamp(12px,2vw,28px);color:#fff;font-weight:600;font-size:clamp(13px,1.15vw,15.5px);white-space:nowrap}
  .hero-trust li+li{border-left:1px solid rgba(255,255,255,.12)}
  .hero-trust svg{width:22px;height:22px;color:#F9811C;flex:none}
}
@media (min-width:701px) and (max-height:800px){.jj .hero-inner{padding-bottom:120px}.hero-trust li{padding:12px 16px}}
@media (min-width:1100px){.jj .hero-shade{background:linear-gradient(90deg,rgba(17,17,17,.95) 0%,rgba(17,17,17,.84) 26%,rgba(17,17,17,.4) 46%,rgba(17,17,17,0) 62%),linear-gradient(0deg,rgba(17,17,17,.75) 0%,transparent 24%)}}
@media (min-width:701px) and (max-width:1099px){.jj .hero-shade{background:linear-gradient(90deg,rgba(17,17,17,.92) 0%,rgba(17,17,17,.6) 48%,rgba(17,17,17,0) 70%),linear-gradient(0deg,rgba(17,17,17,.75) 0%,transparent 24%)}}
@media (max-width:700px){.jj.svc-page .hero-shade{background:linear-gradient(0deg,rgba(17,17,17,.98) 0%,rgba(17,17,17,.92) 46%,rgba(17,17,17,.6) 66%,rgba(17,17,17,.15) 84%,rgba(17,17,17,.3) 100%)}}

/* quick quote right under the hero: its face avatar */
.jj .enq-face{display:flex}
.jj .enq-face img{width:58px;height:58px;aspect-ratio:1;border-radius:50%;object-fit:cover;border:3px solid #F9811C;box-shadow:none}
.jj .enq-face .enq-who-tag{position:static;background:none;padding:0;backdrop-filter:none;color:#FFA54F}
@media (min-width:701px){.jj .enq-face{display:flex;align-items:center;gap:12px;margin-bottom:16px}.jj .enq-face img{width:64px;height:64px}}
.jj .qw{background:#1F1F1F}

/* ticker: deep orange, white text (5:1) */
.jj .tk-list li{font-stretch:normal;font-weight:600;font-size:14px;letter-spacing:.04em}

/* featured review: black band, orange light */
.jj .ve-feat{background:#141414}
.jj .ve-feat::before{background:radial-gradient(40% 40% at 25% 30%,rgba(249,129,28,.28),transparent 70%),radial-gradient(35% 35% at 80% 70%,rgba(249,129,28,.16),transparent 70%)}
.jj .ve-feat blockquote{font-stretch:normal;font-weight:600;font-size:clamp(19px,5.2vw,34px);line-height:1.35;letter-spacing:-.01em}
.jj .rw-score b,.jj .stat dt,.jj .st-n{font-stretch:normal}
.jj .rw-chip[aria-pressed="true"]{background:#141414}

/* about + why */
.jj .about{background:#fff}
.jj .why{background:var(--bg)}
.jj .stat dt{font-size:32px;font-weight:800}
.jj .why-about p+p{margin-top:12px}
.jj .why-tall img{aspect-ratio:4/5;object-position:50% 25%}
.jj .why .why-media{padding-bottom:0}
.wc-grid{display:grid;gap:10px;margin-top:18px}
.wc{display:flex;gap:12px;align-items:flex-start;background:#fff;border-radius:var(--r);padding:14px;border:1px solid var(--line)}
.wc-ic{flex:none;display:grid;place-items:center;width:42px;height:42px;border-radius:12px;background:#F9811C}
.wc-ic svg{width:22px;height:22px}
.wc-b{display:flex;flex-direction:column;gap:2px;font-size:14.5px;color:var(--muted);line-height:1.45}
.wc-b b{color:var(--text);font-size:15.5px;line-height:1.3}
.why-h3{font-size:clamp(20px,5.4vw,24px);margin-top:24px}
.why-h3+p{margin-top:10px}
.jj .why-copy>p:not(.kicker):not(.lead){color:var(--muted);margin-top:10px}
@media (min-width:701px){.wc-grid{grid-template-columns:1fr 1fr;gap:12px}}
@media (hover:hover) and (pointer:fine){.wc{transition:transform .3s var(--ease),box-shadow .3s,border-color .3s}.wc:hover{transform:translateY(-3px);border-color:rgba(249,129,28,.6);box-shadow:0 14px 30px rgba(20,20,20,.08)}}

/* services: card lines always shown on phones; "Also on the job" chips */
.jj .svc-card::after{background:linear-gradient(180deg,rgba(20,20,20,0) 25%,rgba(20,20,20,.75) 55%,rgba(20,20,20,.96) 100%)}
.jj .svc-body h3{font-size:23px}
.jj .svc-card.feature h3{font-size:30px}
.jj .svc-quote{font-stretch:normal;text-transform:none;letter-spacing:0;font-weight:700}
.jj .ve .svc-card.feature .svc-media img,.jj .svc-card.feature .svc-media img{object-position:50% 22%!important}
@media (max-width:700px){.jj .svc-card.feature .svc-media{bottom:30%}}
.axs{margin-top:22px;border-radius:var(--r-lg);background:#1C1C1C;border:1px solid rgba(249,129,28,.25);padding:16px 14px}
.ax-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
.ax{position:relative;display:flex;flex-direction:column;gap:8px;padding:12px;border-radius:var(--r);background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08)}
.ax-ic{display:grid;place-items:center;width:38px;height:38px;border-radius:11px;background:rgba(249,129,28,.16);color:#F9811C}
.ax-ic svg{width:22px;height:22px}
.ax b{font-size:14px;line-height:1.3;font-weight:600}
.ax-q{display:inline-flex;align-items:center;gap:5px;margin-top:auto;min-height:44px;margin-bottom:-10px;color:#FFA54F;font-weight:700;font-size:13.5px;text-decoration:none}
.ax-q svg{width:14px;height:14px;transition:transform .25s}
.ax-line{display:flex;gap:10px;align-items:flex-start;margin-top:14px;color:#fff;font-weight:600;font-size:15px}
.ax-line svg{flex:none;width:22px;height:22px;padding:4px;border-radius:50%;background:#F9811C;color:#1A1A1A}
@media (min-width:701px){.axs{padding:22px 24px}.ax-list{grid-template-columns:repeat(5,minmax(0,1fr));gap:12px}}
@media (hover:hover) and (pointer:fine){.ax{transition:border-color .25s,transform .25s var(--ease)}.ax:hover{border-color:rgba(249,129,28,.6);transform:translateY(-3px)}.ax:hover .ax-q svg{transform:translateX(4px)}}

/* emergency (LP section, black) */
.emerg{background:#111;color:#fff}
.emerg-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:22px}   /* 23 Oct: minmax(0,…) or a child's min-content pushed it 1px past a 320 screen */
.emerg-photo{margin:0;border-radius:var(--r-lg);overflow:hidden;max-height:380px}
.emerg-photo img{width:100%;height:100%;object-fit:cover;object-position:50% 30%}
.emerg-copy>p.d-only{color:#D0D0D0;margin-top:12px}
.emerg-h3{font-size:20px;margin-top:20px}
.emerg-list{display:grid;gap:8px;margin-top:12px}
.emerg-list li{display:flex;gap:10px;align-items:flex-start;font-weight:500;font-size:15.5px}
.emerg-list svg{flex:none;width:22px;height:22px;padding:3px;border-radius:50%;background:#F9811C;color:#1A1A1A;margin-top:1px}
.emerg-safe{display:flex;gap:10px;align-items:flex-start;margin-top:16px;padding:12px 14px;border-radius:var(--r);background:rgba(249,129,28,.1);border:1px solid rgba(249,129,28,.4);color:#ECECEC;font-size:14.5px}
.emerg-safe svg{flex:none;width:22px;height:22px;color:#F9811C}
.emerg-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.emerg-chips li{padding:6px 12px;border-radius:30px;border:1px solid rgba(255,255,255,.2);font-size:13.5px;font-weight:600}
@media (min-width:701px){.emerg-grid{grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);gap:clamp(32px,5vw,72px);align-items:center}.emerg-photo{max-height:none;aspect-ratio:4/5}}

/* dispatch board (the honest version) */
.dispatch{background:#0B0B0B;color:#fff}
.disp{position:relative;border-radius:var(--r-lg);background:linear-gradient(180deg,#1A1A1A,#141414);border:1px solid rgba(249,129,28,.35);padding:18px 16px;box-shadow:0 24px 60px rgba(0,0,0,.5);overflow:hidden}
.disp::before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(0deg,rgba(255,255,255,.025) 0 1px,transparent 1px 4px);pointer-events:none}
.disp-top{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.disp-top h2{display:flex;align-items:center;gap:10px;font-size:clamp(26px,7vw,34px)}
.disp-dot{width:12px;height:12px;border-radius:50%;background:#3BD16F;box-shadow:0 0 0 0 rgba(59,209,111,.7);animation:liveE 2s infinite}
.disp-clock{display:flex;flex-direction:column;align-items:flex-end;line-height:1.1}
.disp-clock span{font-size:11.5px;letter-spacing:.12em;text-transform:uppercase;color:#B6B6B6}
.disp-clock b{font-family:ui-monospace,"SF Mono",Menlo,monospace;font-size:24px;color:#FFA54F;font-variant-numeric:tabular-nums}
.disp-status{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:14px}
.disp-status li{display:flex;align-items:center;gap:8px;padding:9px 10px;border-radius:12px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);font-size:13.5px;font-weight:600;line-height:1.25}
.disp-status .live{flex:none}
.disp-grid{display:grid;gap:14px;margin-top:16px}
.disp-lab{font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;color:#B6B6B6;font-weight:600}
.disp-sub{font-size:24px;font-weight:800;margin-top:2px;color:#fff}
.disp-dist{color:#D0D0D0;font-size:14.5px;margin-top:4px}
.disp-dist b{color:#fff}
.disp-route{position:relative;height:6px;margin-top:14px;border-radius:6px;background:rgba(255,255,255,.1);overflow:hidden}
.disp-route i{position:absolute;left:0;top:0;bottom:0;width:0;border-radius:6px;background:var(--blue-grad);box-shadow:0 0 12px rgba(249,129,28,.8);transition:width 1.6s var(--ease)}
.disp.in-view .disp-route i{width:var(--route,60%)}
.disp-jobs{display:grid;gap:6px;margin-top:8px}
.disp-jobs li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 10px;padding:10px 12px;border-radius:12px;background:rgba(255,255,255,.04);border-left:3px solid #F9811C}
.dj-t{font-weight:700;font-size:14.5px}
.dj-s{grid-column:1;color:#D0D0D0;font-size:13.5px}
.dj-d{grid-column:2;grid-row:1/3;align-self:center;color:#FFA54F;font-size:12.5px;font-weight:600;white-space:nowrap}
.disp-note{margin-top:8px;font-size:12.5px;color:#999}
.disp-call{width:100%;margin-top:18px}
@media (max-width:359px){.disp-call .btn-lab{display:none}}
@media (min-width:701px){
  .disp{padding:28px 30px}
  .disp-status{grid-template-columns:repeat(4,minmax(0,1fr))}
  .disp-grid{grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:28px}
  .disp-call{width:auto}
}
@media (prefers-reduced-motion:reduce){.disp-route i{transition:none}.disp-dot{animation:none}}

/* quote band (LP) */
.qband{background:#fff;padding:44px 0}
.qband-inner{display:grid;gap:22px;align-items:center}
.qband-photo{margin:0;border-radius:var(--r-lg);overflow:hidden}
.qband-photo img{width:100%;aspect-ratio:3/2;object-fit:cover;object-position:50% 40%}
.qband-copy h2{font-size:clamp(27px,7.4vw,38px)}
.qband-copy p{margin-top:12px;color:var(--muted)}
@media (min-width:701px){.qband{padding:clamp(56px,7vw,96px) 0}.qband-inner{grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:clamp(32px,5vw,72px)}}

/* project gallery: a swipe strip on phones, 4 x 2 on desktop (8 photos, no empty cells) */
.pgal{background:#fff}
/* Gallery (23 Oct, Edoardo: "flat as hell, photos need to pop"). Phones: a strip where the centre photo is full size and the
   others shrink and dim (jjc.js sets --d = distance from centre). Desktop: a mosaic (big 2x2, tall 1x2, singles) that rises in
   staggered, tilts toward the mouse with a glare and an orange edge. Any photo opens full screen (jjc.js lightbox). */
.pg-grid{display:flex;gap:12px;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;margin:0 -16px;padding:10px calc(50vw - min(36vw,140px)) 14px;scroll-padding-inline:calc(50vw - min(36vw,140px))}
.pg-grid::-webkit-scrollbar{display:none}
.pg-tile{--d:0;flex:none;width:min(72vw,280px);aspect-ratio:4/5;margin:0;border-radius:var(--r);overflow:hidden;scroll-snap-align:center;background:#eee;position:relative;cursor:zoom-in;
  transform:scale(calc(1 - var(--d) * .14));filter:brightness(calc(1 - var(--d) * .4)) saturate(calc(1 - var(--d) * .3));box-shadow:0 calc(18px - var(--d) * 14px) calc(40px - var(--d) * 30px) rgba(0,0,0,calc(.28 - var(--d) * .2))}
.pg-tile img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .8s var(--ease)}
.pg-tile:focus-visible{outline:3px solid #F9811C;outline-offset:3px}
.pg-tile::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;opacity:0;transition:opacity .3s;background:radial-gradient(circle at var(--gx,50%) var(--gy,30%),rgba(255,255,255,.38),rgba(255,255,255,0) 55%)}
.pg-zoom{position:absolute;right:10px;bottom:10px;width:36px;height:36px;border-radius:50%;display:grid;place-items:center;background:rgba(20,20,20,.62);color:#fff;pointer-events:none;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.pg-zoom svg{width:18px;height:18px}
@media (min-width:701px){
  .pg-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:clamp(160px,16.5vw,236px);gap:14px;overflow:visible;margin:0;padding:0;perspective:1200px}
  .pg-tile{width:auto;aspect-ratio:auto;transform:none;filter:none;box-shadow:0 14px 34px rgba(0,0,0,.14)}
  .pg-a{grid-column:span 2;grid-row:span 2}
  .pg-b{grid-row:span 2}
  .pg-zoom{opacity:0;transform:scale(.7);transition:opacity .25s,transform .25s}
  .js .pgal .pg-tile{opacity:0;transform:translateY(46px) scale(.9) rotate(calc((var(--k) - 3.5) * .8deg))}
  .js .pgal .pg-tile.pg-in{opacity:1;transform:none;transition:opacity .7s var(--ease),transform .9s cubic-bezier(.2,1.25,.4,1);transition-delay:calc(var(--k) * 80ms)}
  .js .pgal .pg-tile.pg-done{transition:transform .25s ease-out,box-shadow .3s;transition-delay:0s;transform:perspective(900px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg)) translateY(var(--ty,0px))}
}
@media (min-width:701px) and (hover:hover) and (pointer:fine){
  .pg-tile:hover{--ty:-8px;box-shadow:0 0 0 2px #F9811C,0 28px 60px rgba(249,129,28,.32);z-index:2}
  .pg-tile:hover img{transform:scale(1.07)}
  .pg-tile:hover::after{opacity:1}
  .pg-tile:hover .pg-zoom{opacity:1;transform:none}
}
@media (prefers-reduced-motion:reduce){.js .pgal .pg-tile,.js .pgal .pg-tile.pg-in,.js .pgal .pg-tile.pg-done{opacity:1;transform:none;transition:none}.pg-tile{transform:none}}
/* full-screen viewer */
.lb{position:fixed;inset:0;z-index:2147483000;display:flex;align-items:center;justify-content:center;background:rgba(8,8,8,.94);opacity:0;transition:opacity .25s;touch-action:pan-y}
.lb.on{opacity:1}
.lb[hidden]{display:none}
.lb figure{margin:0;display:flex;flex-direction:column;align-items:center;gap:12px;max-width:92vw}
.lb img{max-width:92vw;max-height:78vh;border-radius:10px;box-shadow:0 30px 80px rgba(0,0,0,.6);object-fit:contain;transition:transform .3s var(--ease),opacity .2s}
.lb figcaption{color:#ddd;font-size:14px;text-align:center;max-width:640px}
.lb figcaption b{color:#F9811C;margin-right:8px}
.lb button{position:absolute;width:48px;height:48px;border-radius:50%;border:1px solid rgba(255,255,255,.25);background:rgba(30,30,30,.8);color:#fff;display:grid;place-items:center;cursor:pointer}
.lb button svg{width:22px;height:22px}
.lb .lb-x{top:max(14px,env(safe-area-inset-top));right:14px}
.lb .lb-p{left:14px;top:50%;translate:0 -50%}.lb .lb-n{right:14px;top:50%;translate:0 -50%}
@media (max-width:700px){.lb .lb-p,.lb .lb-n{top:auto;bottom:max(18px,env(safe-area-inset-bottom));translate:none}.lb .lb-p{left:calc(50% - 60px)}.lb .lb-n{right:calc(50% - 60px)}}
@media (hover:hover) and (pointer:fine){.lb button:hover{background:#F9811C;border-color:#F9811C;color:#141414}}
.lb button:focus-visible{outline:3px solid #F9811C;outline-offset:2px}
html.lb-open,html.lb-open body{overflow:hidden}
html.lb-open .rv-pop,html.lb-open .m-bar{visibility:hidden}

/* steps, types, areas (4 regions), closing band */
.jj .st-n{font-size:20px;font-weight:800;border-radius:50%}
.jj .step-list li{font-size:15px}
.jj .ty{font-weight:600}
.ty-grid.n7 .ty:last-child{grid-column:2}
@media (min-width:701px){.ty-grid.n7,.ty-grid.n8{grid-template-columns:repeat(4,minmax(0,1fr))}.ty-grid.n7 .ty:last-child{grid-column:auto}.ty-grid.n7{justify-content:center}}
@media (min-width:701px){.ty-grid.n7{grid-template-columns:repeat(4,minmax(0,1fr))}.ty-grid.n7 .ty:nth-child(5){grid-column:1 / span 1}}
.js .areas .cov[data-f="rw"] .cov-dots .rw{opacity:1}.cov[data-f="rw"] .cov-glow .rw{opacity:.35}
.jj .cov-labels text{stroke:#141414}
.jj .ve-cta{background:radial-gradient(60% 90% at 85% 40%,rgba(249,129,28,.28),transparent 70%),#111}
@media (min-width:701px){.jj .ve-cta{background:radial-gradient(50% 90% at 20% 50%,rgba(249,129,28,.3),transparent 70%),#111}}
.jj .ve-cta h2{font-size:clamp(30px,8.4vw,60px);line-height:1.05}

/* footer: logo on black */
.jj .site-footer{background:#0B0B0B}
.jj .foot-brand img{width:180px;height:auto}

/* 22 Oct phone pass */
.jj .qw-step legend,.jj .qw-legend{font-stretch:normal;text-transform:none;font-weight:800;letter-spacing:-.015em;font-size:clamp(22px,6.2vw,28px);line-height:1.15}
.jj .qw-tile{font-weight:600}
.jj .rv-pop-head{white-space:nowrap}
@media (max-width:640px){.jj .rv-pop{padding:7px 34px 7px 9px;gap:7px}.jj .rv-pop-g .g-logo{width:20px;height:20px}.jj .rv-pop-head{font-size:12.5px}}
.jj .cov-legend{display:grid;grid-template-columns:1fr 1fr}
/* "Also on the job": the whole tile starts the quote; phones = 2 columns, icon + label + arrow */
.ax{color:#fff;text-decoration:none;min-height:100%}
.ax-q{margin:0;min-height:0}
@media (max-width:1099px){   /* phones and tablets (23 Oct: 5 columns of ~130px wrapped every label onto 3 lines at 768): compact chips that wrap (whole chip starts the quote on that job) */
  .ax-list{display:flex;flex-wrap:wrap;gap:8px}
  .ax{flex-direction:row;align-items:center;gap:8px;padding:6px 14px 6px 6px;min-height:44px;border-radius:30px}
  .ax-ic{width:30px;height:30px;border-radius:50%;flex:none}
  .ax-ic svg{width:17px;height:17px}
  .ax b{font-size:13.5px;line-height:1.25}
  .ax-q{display:none}
}
@media (max-width:480px){.disp-call{font-size:16px;padding:14px 16px}}
@media (min-width:701px){
  .axs .also-h{writing-mode:horizontal-tb;rotate:none;margin:0 0 14px;font-size:13px}
  .axs .also-h::after{width:auto;height:1px;flex:1;background:linear-gradient(90deg,rgba(249,129,28,.45),transparent)}
  .jj .ve-cta h2{font-size:clamp(36px,4.2vw,58px)}
  .jj .ve-cta h2,.jj .ve-cta p{max-width:720px}
}
@media (min-width:701px) and (max-width:1099px){.wc-grid{grid-template-columns:minmax(0,1fr)}.jj .why-grid{grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr)}}
.disp-clock span,.disp-lab{font-size:12px}

/* ---------- phone folds (22 Oct): jjc.js turns .fold into tap-to-open on phones; desktop shows everything ---------- */
.fold-ch{display:none}
.is-fold .fold-h{cursor:pointer;-webkit-tap-highlight-color:transparent}
.is-fold .fold-ch{display:inline-block;flex:none;width:9px;height:9px;margin-left:10px;border-right:2.5px solid currentColor;border-bottom:2.5px solid currentColor;transform:translateY(-3px) rotate(45deg);transition:transform .25s;color:#F9811C;vertical-align:middle}
.is-fold.open .fold-ch{transform:translateY(1px) rotate(-135deg)}
.js .is-fold:not(.open) .fold-b{display:none}
.is-fold .fold-h:focus-visible{outline:3px solid #F9811C;outline-offset:3px;border-radius:6px}
/* why cards: title row, the whole card is the tap target, chevron on the right */
.wc.is-fold{position:relative;padding:12px 40px 12px 12px;align-items:center}
.wc.is-fold.open{align-items:flex-start}
.wc.is-fold .fold-h::before{content:"";position:absolute;inset:0;border-radius:inherit}
.wc.is-fold .fold-ch{position:absolute;right:16px;top:50%;margin:0;transform:translateY(-70%) rotate(45deg)}
.wc.is-fold.open .fold-ch{top:22px;transform:translateY(-20%) rotate(-135deg)}
.wc.is-fold .fold-b{margin-top:4px}
@media (max-width:700px){
  .wc{padding:12px;align-items:center}
  .wc-ic{width:36px;height:36px;border-radius:10px}
  .wc-ic svg{width:20px;height:20px}
  .wc-grid{gap:8px}
  .why-more{margin-top:18px;border-top:1px solid var(--line);padding-top:4px}
  .why-more .why-h3{margin-top:0;padding:12px 0;font-size:18px;min-height:48px;display:flex;align-items:center;justify-content:space-between;gap:10px}
  .why-more .fold-b p{color:var(--muted);margin-top:0}
  .why-more .fold-b p+p{margin-top:10px}
  /* "Also on the job": a tap-to-open row */
  .axs.is-fold{padding:0 14px}
  .axs.is-fold .also-h{margin:0;min-height:52px;cursor:pointer}
  .axs.is-fold .also-h::after{display:none}
  .axs .ax-n{display:inline-grid;place-items:center;min-width:24px;height:24px;padding:0 6px;border-radius:12px;background:rgba(249,129,28,.18);color:#FFA54F;font-size:12px;letter-spacing:0;margin-left:2px}
  .axs.is-fold .fold-ch{margin-left:auto}
  .axs.is-fold .fold-b{padding-bottom:4px}
  .axs.is-fold .ax-line{margin:0 0 14px;padding-top:12px;border-top:1px solid rgba(255,255,255,.08)}
  /* process steps: tap a step for its line */
  .step-list li.is-fold{cursor:pointer}
  .step-list li.is-fold .fold-h{display:flex;align-items:center;min-height:40px}
  .step-list li.is-fold.open .st-more{display:block;margin-top:2px}
  /* "Read more" clamps */
  .js .clamp.is-clamp:not(.open){max-height:5em;overflow:hidden;-webkit-mask-image:linear-gradient(#000 55%,transparent);mask-image:linear-gradient(#000 55%,transparent)}
  .clamp-more{display:inline-flex;align-items:center;min-height:44px;margin-top:2px;padding:0;background:none;border:0;font:inherit;font-weight:700;font-size:15px;color:var(--blue-2,#B45309);text-decoration:underline;text-underline-offset:4px;cursor:pointer}
  .clamp-more[hidden]{display:none}
  .emerg .clamp-more,.svcs .clamp-more{color:#FFA54F}
  .emerg-p{margin-top:12px;color:#D0D0D0}
  .clamp p+p{margin-top:12px}
  /* service pages: "types we handle" as compact chips (phone kit) */
  .ty-grid{display:flex;flex-wrap:wrap;gap:8px}
  .ty{flex-direction:row;gap:8px;padding:6px 14px 6px 6px;border-radius:30px;font-size:13.5px;text-align:left;min-height:44px}
  .ty-ic{width:30px;height:30px;border-radius:50%}
  .ty-ic svg{width:17px;height:17px}
  .ty-grid.n7 .ty:last-child{grid-column:auto}
}
@media (max-width:700px){.step-list li.is-fold{position:relative}.step-list li.is-fold .fold-h::before{content:"";position:absolute;inset:0}}
@media (max-width:700px){.qband-copy .clamp p{margin-top:0}.qband-copy .clamp{margin-top:12px;color:var(--muted)}}
@media (max-width:700px){.step-list li.is-fold .st-n{pointer-events:none}}

/* ======================================================================================================================
   NEON WIRE buttons (Edoardo 22 Oct, from the button lab qa/buttons-jjc.html): Neon Tube base (dark pill, orange tube on
   call buttons, white tube on quote buttons) that flickers on the first time the button comes on screen (core.js .bp-laid);
   at rest Voltage Wave rings pulse out of the phone / arrow icon and a neon oscilloscope line runs along the bottom, while
   the Live Wire spark loops once round the edge every 6s (call and quote take turns); hover, keyboard focus and a phone tap
   = Live Wire (two sparks chasing round, blue glow). Width never changes. All motion off under reduced motion.
   !important only in this block: it replaces the Westplumb pipe/fill layer (base.css/home.css) on every page.
   ====================================================================================================================== */
.jj .btn[href^="tel:"],.jj .btn[href$="#enquire"],.jj .btn.btn-quote{
  background:#141414!important;border:0!important;text-transform:none;
  color:#FFB070!important;-webkit-text-fill-color:currentColor;
  box-shadow:inset 0 0 0 2px #FFA54F,inset 0 0 12px rgba(249,129,28,.42),0 0 10px rgba(249,129,28,.55)!important;
  text-shadow:0 0 7px rgba(249,129,28,.85)!important}
.jj .btn[href$="#enquire"],.jj .btn.btn-quote{
  color:#fff!important;
  box-shadow:inset 0 0 0 2px #fff,inset 0 0 12px rgba(92,200,255,.32),0 0 10px rgba(255,255,255,.4)!important;
  text-shadow:0 0 7px rgba(92,200,255,.9)!important}
.jj .btn.pr::before{display:none!important}                                   /* no fill sweep */
.jj .bp-fit{display:none}                                                      /* no pipe fittings */
/* first time on screen (core.js .bp-laid, 60% visible): the tube buzzes on. Lit before that, so a button the observer
   never reports (fixed bar, fold edge) can't stay dark */
.jj .btn.pr.bp-laid{animation:neonOn 1.1s ease-out both}
@keyframes neonOn{0%{filter:saturate(.35) brightness(.7)}8%{filter:brightness(1.35)}13%{filter:saturate(.35) brightness(.65)}22%{filter:brightness(1.3)}27%{filter:saturate(.5) brightness(.8)}42%{filter:brightness(1.15)}100%{filter:none}}
/* Voltage Wave: rings out of the icon (the quote's arrow 1.5s after the call's phone) */
.jj .btn .bi{position:relative;display:inline-grid;place-items:center;flex:none}
.jj .btn .bi::before,.jj .btn .bi::after{content:"";position:absolute;inset:-6px;border-radius:50%;border:2px solid currentColor;opacity:0;pointer-events:none;animation:biRing 3s infinite}
.jj .btn .bi::after{animation-delay:.45s}
.jj .btn .bi-ar::before{animation-delay:1.5s}.jj .btn .bi-ar::after{animation-delay:1.95s}
@keyframes biRing{0%{opacity:.75;transform:scale(.55)}45%,100%{opacity:0;transform:scale(1.65)}}
.jj .btn .bi-ar svg{width:18px;height:18px}
/* Live Wire (23 Oct rework, Edoardo: "a little bit off"): each spark is a comet, a bright head (.bp-run / .bp-flow) with a
   fading tail (.bp-base / .bp-tube), riding exactly on the neon tube (core.js draws the rects on the tube's centre line).
   Call buttons: light blue sparks and a blue glow; quote (white) buttons: orange sparks and an orange glow.
   Rest: one comet laps the button in 1.5s every 6s (call at 1.6s, quote at 4.6s, so they take turns).
   Hover (mouse), keyboard focus, phone tap: two comets chase round non-stop and the button glows in its spark colour. */
.jj .btn{--spk:#5CC8FF;--spk-head:#EAF9FF;--spk-rgb:92,200,255;--spk2:#FF8A2A;--spk2-head:#FFE6CF}
.jj .btn[href$="#enquire"],.jj .btn.btn-quote{--spk:#FF8A2A;--spk-head:#FFE6CF;--spk-rgb:249,129,28;--spk2:#5CC8FF;--spk2-head:#EAF9FF}
/* 23 Oct (Edoardo): on hover/tap the two chasing comets are two colours: the second one (.bp-flow + .bp-tube) takes the other colour */
.jj .btn .bp .bp-flow{stroke:var(--spk2-head);filter:drop-shadow(0 0 2px #fff) drop-shadow(0 0 4px var(--spk2)) drop-shadow(0 0 9px var(--spk2))}
.jj .btn .bp .bp-tube{stroke:var(--spk2);filter:drop-shadow(0 0 4px var(--spk2))}
.jj .btn .bp-run,.jj .btn .bp-flow,.jj .btn .bp-base,.jj .btn .bp-tube{display:inline;visibility:visible;fill:none;stroke-linecap:round;opacity:0;transition:none}
.jj .btn .bp-run,.jj .btn .bp-flow{stroke:var(--spk-head);stroke-width:4;stroke-dasharray:3.5 96.5;filter:drop-shadow(0 0 2px #fff) drop-shadow(0 0 4px var(--spk)) drop-shadow(0 0 9px var(--spk))}
.jj .btn .bp-base,.jj .btn .bp-tube{stroke:var(--spk);stroke-width:3;stroke-dasharray:9 91;filter:drop-shadow(0 0 4px rgba(var(--spk-rgb),1))}
@keyframes lwHead{0%{stroke-dashoffset:0;opacity:0}2%{opacity:1}23%{opacity:1}25%,100%{stroke-dashoffset:-100;opacity:0}}
@keyframes lwTail{0%{stroke-dashoffset:5.5;opacity:0}2%{opacity:.9}23%{opacity:.9}25%,100%{stroke-dashoffset:-94.5;opacity:0}}
@keyframes lwLoopH{from{stroke-dashoffset:0}to{stroke-dashoffset:-100}}
@keyframes lwLoopT{from{stroke-dashoffset:5.5}to{stroke-dashoffset:-94.5}}
.jj .btn.bp-laid .bp-run{animation:lwHead 6s linear 1.6s infinite}
.jj .btn.bp-laid .bp-base{animation:lwTail 6s linear 1.6s infinite}
.jj .btn.bp-laid[href$="#enquire"] .bp-run,.jj .btn.bp-laid.btn-quote .bp-run,.jj .btn.bp-laid[href$="#enquire"] .bp-base,.jj .btn.bp-laid.btn-quote .bp-base{animation-delay:4.6s}
.jj .btn.pr.is-tap .bp-run,.jj .btn.pr:focus-visible .bp-run{opacity:1;animation:lwLoopH 1.1s linear infinite}
.jj .btn.pr.is-tap .bp-base,.jj .btn.pr:focus-visible .bp-base{opacity:.9;animation:lwLoopT 1.1s linear infinite}
.jj .btn.pr.is-tap .bp-flow,.jj .btn.pr:focus-visible .bp-flow{opacity:1;animation:lwLoopH 1.1s linear -.55s infinite}
.jj .btn.pr.is-tap .bp-tube,.jj .btn.pr:focus-visible .bp-tube{opacity:.9;animation:lwLoopT 1.1s linear -.55s infinite}
.jj .btn.pr.is-tap,.jj .btn.pr:focus-visible{color:#fff!important;text-shadow:0 0 8px rgba(var(--spk-rgb),.95)!important;
  box-shadow:inset 0 0 0 2px var(--spk-head),inset 0 0 14px rgba(var(--spk-rgb),.45),0 0 0 3px rgba(var(--spk-rgb),.35),0 0 26px rgba(var(--spk-rgb),.6)!important}
.jj .btn.pr:focus-visible{outline:3px solid var(--spk);outline-offset:4px}
@media (hover:hover) and (pointer:fine){
  .jj .btn.pr:hover .bp-run{opacity:1;animation:lwLoopH 1.1s linear infinite}
  .jj .btn.pr:hover .bp-base{opacity:.9;animation:lwLoopT 1.1s linear infinite}
  .jj .btn.pr:hover .bp-flow{opacity:1;animation:lwLoopH 1.1s linear -.55s infinite}
  .jj .btn.pr:hover .bp-tube{opacity:.9;animation:lwLoopT 1.1s linear -.55s infinite}
  .jj .btn.pr:hover{color:#fff!important;text-shadow:0 0 8px rgba(var(--spk-rgb),.95)!important;
    box-shadow:inset 0 0 0 2px var(--spk-head),inset 0 0 14px rgba(var(--spk-rgb),.45),0 0 0 3px rgba(var(--spk-rgb),.35),0 0 26px rgba(var(--spk-rgb),.6)!important}
}
@media (prefers-reduced-motion:reduce){.jj .btn.pr.bp-laid,.jj .btn .bi::before,.jj .btn .bi::after{animation:none!important}.jj .btn .bi::before,.jj .btn .bi::after{display:none}
  .jj .btn .bp-run,.jj .btn .bp-flow,.jj .btn .bp-base,.jj .btn .bp-tube{animation:none!important;opacity:0!important}}
/* 22 Oct: 320-359px phones: header (logo + number + menu) and the sticky bar's buttons must fit (the quote got an arrow) */
@media (max-width:359px){.jj .hdr-call{font-size:14px;padding:9px 10px;gap:6px}.jj .hdr-ctas{gap:6px}.jj .logo img{height:30px}}
@media (max-width:374px){.jj .m-bar .btn{padding-left:12px;padding-right:12px;gap:7px}}

/* Map (Edoardo 23 Oct: no grey, no blue, no rings): every suburb is the same glowing orange dot, so the map reads as one
   coverage area. Regions appear only on demand: tap (or hover, mouse) a region in the legend or its card and that region's
   dots turn white while the rest dim. The legend chips carry no colour markers. */
.cov-dots circle,.cov-dots .rg,.cov-dots .rs,.cov-dots .rm,.cov-dots .rw{--c:#F9811C;fill:#F9811C;stroke:none}
.cov-glow circle,.cov-glow .rg,.cov-glow .rs,.cov-glow .rm,.cov-glow .rw{fill:#F9811C}
.cov-key i,.area-dot{display:none}
.cov-key{--c:#F9811C;transition:background-color .2s,border-color .2s,color .2s}
.cov-key[aria-pressed="true"],.cov[data-f="rg"] .cov-key.rg,.cov[data-f="rs"] .cov-key.rs,.cov[data-f="rm"] .cov-key.rm,.cov[data-f="rw"] .cov-key.rw{background:#F9811C;border-color:#F9811C;color:#1A1A1A}
.cov-key[aria-pressed="true"] span,.cov[data-f="rg"] .cov-key.rg span,.cov[data-f="rs"] .cov-key.rs span,.cov[data-f="rm"] .cov-key.rm span,.cov[data-f="rw"] .cov-key.rw span{color:#1A1A1A}
/* Map 23 Oct v2 (Edoardo): by default only the 59 suburbs that converted in the last 60 days of Ads show ([data-top]).
   A searched suburb outside them pops in (.is-hit). A picked region (chip or card, click only) shows ALL its suburbs in
   white while the top dots dim, and the map zooms to fit the region (core.js). */
.js .areas .cov .cov-dots circle:not([data-top]){opacity:0;pointer-events:none}
.cov .cov-glow circle:not([data-top]){opacity:0}
.cov-glow circle{transition:opacity .35s}
.js .areas .cov .cov-dots circle.is-hit{opacity:1;pointer-events:auto}
.js .areas .cov.is-settled .cov-dots circle{transition:opacity .35s,r .3s,fill .3s}
.js .areas .cov[data-f] .cov-dots circle[data-top]{opacity:.18}
.js .areas .cov[data-f="rg"] .cov-dots circle.rg,.js .areas .cov[data-f="rs"] .cov-dots circle.rs,.js .areas .cov[data-f="rm"] .cov-dots circle.rm,.js .areas .cov[data-f="rw"] .cov-dots circle.rw{opacity:1;fill:#fff;pointer-events:auto}
.cov[data-f] .cov-glow circle[data-top]{opacity:.06}
.cov[data-f="rg"] .cov-glow circle.rg,.cov[data-f="rs"] .cov-glow circle.rs,.cov[data-f="rm"] .cov-glow circle.rm,.cov[data-f="rw"] .cov-glow circle.rw{opacity:calc(.12 / var(--z));fill:#fff}
.area-card[data-region]{cursor:pointer;transition:box-shadow .2s,background-color .2s}
.area-card.is-picked{box-shadow:inset 0 0 0 2px #F9811C;background-color:rgba(249,129,28,.08)}
.area-card.is-picked h3{color:#F9811C}
@media (hover:hover) and (pointer:fine){.cov-key:hover{border-color:#F9811C}.area-card[data-region]:hover{box-shadow:inset 0 0 0 1px rgba(249,129,28,.5)}}
.area-card.is-match{box-shadow:0 0 0 2px #F9811C}   /* the searched suburb's card: brand orange, never the old grey region colour */

/* ---- Home review fixes (23 Oct) ---- */
.js .ve.jj .hero-inner>.hero-ctas{animation:none}   /* fix 1: the call + quote buttons are there from the first frame (only the headline animates) */
.disp-call .lab-s{display:none}
@media (max-width:700px){
  .disp-call .lab-l{display:none}.disp-call .lab-s{display:inline}   /* fix 4: one line on phones */
  .rw-list{align-items:flex-start}                                     /* fix 7: short reviews get short cards */
  .pgal,.steps{padding-bottom:20px}                                    /* fix 8: white sections back to back doubled the gap */
}

/* ---- Hero badges (23 Oct, home): desktop only, they replace the chips there. Neon power-on, gentle float, spark on hover ---- */
.hero-badges{display:none}
@media (min-width:1100px){
  .hero.has-badges .hero-chips{display:none}
  .hero-badges{display:grid;position:absolute;z-index:2;right:max(28px,calc((100vw - 1240px) / 2));top:calc(50% - 62px);translate:0 -50%;
    grid-template-columns:repeat(2,var(--hb));gap:4px 10px;justify-items:center;--hb:clamp(150px,14vw,200px);pointer-events:none}
  .hb{width:var(--hb);pointer-events:auto}
  .hb svg{display:block;width:100%;height:auto;overflow:visible;font-family:"Poppins",system-ui,sans-serif;filter:drop-shadow(0 14px 24px rgba(0,0,0,.55))}
  .hb-a{rotate:-8deg}
  .hb-b{rotate:7deg;margin-top:54px}
  .hb-c{grid-column:1/-1;rotate:-3deg;margin-top:-36px}
  .hb-spark{stroke:#fff;stroke-width:3.5;stroke-linecap:round;stroke-dasharray:0 100;opacity:0;filter:drop-shadow(0 0 4px #FFB466) drop-shadow(0 0 10px #F9811C)}
}
@media (min-width:1100px) and (max-height:800px){.hero-badges{--hb:clamp(140px,13vw,172px)}}
@media (min-width:1100px) and (prefers-reduced-motion:no-preference){
  .js .hb{animation:hbIn .7s cubic-bezier(.2,1.4,.4,1) both;animation-delay:calc(.9s + var(--k) * .28s)}
  .hb-a{--k:0}.hb-b{--k:1}.hb-c{--k:2}
  .js .hb svg{animation:hbBob 6s ease-in-out infinite;animation-delay:calc(var(--k) * -2s)}
  .js .hb .hb-rim{animation:hbNeon 1.1s steps(1,end) both;animation-delay:calc(1s + var(--k) * .28s)}
}
@keyframes hbIn{from{opacity:0;scale:.55}to{opacity:1;scale:1}}
@keyframes hbBob{0%,100%{translate:0 0}50%{translate:0 -9px}}
@keyframes hbNeon{0%{opacity:.15}12%{opacity:1}20%{opacity:.3}32%{opacity:1}40%{opacity:.55}52%,100%{opacity:1}}
@media (min-width:1100px) and (hover:hover) and (pointer:fine) and (prefers-reduced-motion:no-preference){
  .hb:hover .hb-spark{opacity:1;stroke-dasharray:9 91;animation:hbSpark 1.3s linear infinite}
  .hb:hover svg{filter:drop-shadow(0 14px 24px rgba(0,0,0,.55)) drop-shadow(0 0 18px rgba(249,129,28,.45))}
}
@keyframes hbSpark{from{stroke-dashoffset:100}to{stroke-dashoffset:0}}

/* ---- Review pill show-off (23 Oct, Edoardo: "stars popping out"): played by jjc.js on the pill's first appearance
   (fx = charge | drop | burst; the page uses charge), plus a short twinkle each time the quote changes. Off under reduced motion. ---- */
.rv-pop-stars,.hero-pill .g-badge-stars{position:relative}
.hero-pill{position:relative}
.rv-pop-stars svg,.hero-pill .g-badge-stars svg{transform-origin:50% 55%}
.fx-wait .rv-pop-stars svg,.fx-wait .g-badge-stars svg{opacity:0}   /* stars wait hidden until they drop in */
:is(.rv-pop-stars,.g-badge-stars) svg:nth-child(1){--i:0}:is(.rv-pop-stars,.g-badge-stars) svg:nth-child(2){--i:1}:is(.rv-pop-stars,.g-badge-stars) svg:nth-child(3){--i:2}:is(.rv-pop-stars,.g-badge-stars) svg:nth-child(4){--i:3}:is(.rv-pop-stars,.g-badge-stars) svg:nth-child(5){--i:4}
.rv-spk{position:absolute;left:0;top:0;width:var(--s,4px);height:var(--s,4px);margin:calc(var(--s,4px) / -2) 0 0 calc(var(--s,4px) / -2);border-radius:50%;background:var(--c,#FFD54F);box-shadow:0 0 6px var(--g,#F9811C);pointer-events:none;z-index:2;animation:rvSpk var(--t,.6s) cubic-bezier(.15,.7,.35,1) forwards}
@keyframes rvSpk{0%{transform:translate(0,0) scale(.6);opacity:1}25%{transform:translate(calc(var(--dx) * .45),calc(var(--dy) * .45)) scale(1.15);opacity:1}100%{transform:translate(var(--dx),var(--dy)) scale(.35);opacity:0}}
/* charge: the G pops, an orange current runs along the row, each star lights as it arrives, "5.0" glows */
.fx-charge .rv-pop-g{animation:rvPopIn .45s cubic-bezier(.3,1.7,.5,1) both}
.fx-charge .rv-pop-stars svg{animation:rvStarOn .5s cubic-bezier(.3,1.6,.5,1) both;animation-delay:calc(.3s + var(--i) * .12s)}
.fx-charge .rv-pop-stars::after{content:"";position:absolute;top:50%;left:0;width:12px;height:4px;margin:-2px 0 0 -6px;border-radius:4px;background:#fff;box-shadow:0 0 6px 2px #F9811C,0 0 14px 4px rgba(249,129,28,.6);animation:rvCurrent .62s linear .26s both}
.fx-charge .rv-pop-head b{animation:rvNum .7s ease .95s both}
@keyframes rvPopIn{0%{scale:0;rotate:-90deg}100%{scale:1;rotate:0deg}}
@keyframes rvStarOn{0%{color:#5f6368;scale:.55}50%{color:#FFE082;scale:1.6;filter:drop-shadow(0 0 5px #F9811C)}100%{color:#FBBC04;scale:1;filter:none}}
@keyframes rvCurrent{0%{left:0;opacity:0}8%{opacity:1}92%{opacity:1}100%{left:100%;opacity:0}}
@keyframes rvNum{0%,100%{text-shadow:none;scale:1}40%{text-shadow:0 0 12px #F9811C,0 0 2px #fff;scale:1.25}}
/* drop: the stars fall in one by one and bounce, a puff of sparkles where each lands */
.fx-drop :is(.rv-pop-stars,.g-badge-stars) svg{animation:rvDrop .6s cubic-bezier(.3,1.5,.55,1) both;animation-delay:calc(.15s + var(--i) * .13s)}
@keyframes rvDrop{0%{translate:0 -26px;rotate:-70deg;opacity:0}60%{opacity:1}100%{translate:0 0;rotate:0deg;opacity:1}}
/* burst: all five stars blow up from the centre with a gold ring, then a shimmer sweeps across */
.fx-burst .rv-pop-stars svg{animation:rvBurst .55s cubic-bezier(.3,1.6,.5,1) both;animation-delay:calc(.2s + (2 - var(--i)) * (2 - var(--i)) * .03s)}
.fx-burst .rv-pop-stars::before{content:"";position:absolute;left:50%;top:50%;width:20px;height:20px;margin:-10px 0 0 -10px;border-radius:50%;border:2px solid #FFD54F;box-shadow:0 0 12px #FBBC04;animation:rvRing .7s ease-out .2s both}
@keyframes rvBurst{0%{scale:0;opacity:0}70%{scale:1.4;opacity:1}100%{scale:1}}
@keyframes rvRing{0%{scale:.2;opacity:1}100%{scale:5.5;opacity:0}}
/* twinkle (each quote change): a gold glint runs over the row and the stars hop one after another */
.fx-tw :is(.rv-pop-stars,.g-badge-stars) svg{animation:rvTw .5s ease both;animation-delay:calc(var(--i) * .07s)}
@keyframes rvTw{0%,100%{scale:1;filter:none}45%{scale:1.3;filter:drop-shadow(0 0 4px #FFD54F) brightness(1.2)}}
@media (prefers-reduced-motion:reduce){.rv-spk{display:none}.rv-pop [class]{animation:none!important}}

/* ---- Service cards on phones (23 Oct, Edoardo: the text covered the photo): photo on top, clear; title, line and buttons in
   a dark panel underneath. Desktop keeps the overlay cards. ---- */
@media (max-width:700px){
  .jj .svcs .svc-card,.jj .svcs .svc-card.feature{justify-content:flex-start;min-height:0}
  .jj .svcs .svc-card .svc-media,.jj .svcs .svc-card.feature .svc-media{position:relative;inset:auto;bottom:auto;flex:none;height:200px;z-index:0}
  .jj .svcs .svc-card.feature .svc-media{height:220px}
  .jj .svcs .svc-card .svc-media::after{content:"";position:absolute;left:0;right:0;bottom:0;height:46px;background:linear-gradient(180deg,rgba(26,26,26,0),var(--card-dark,#1d1d1d))}
  .jj .svcs .svc-card::after{display:none}
  .jj .svcs .svc-card .svc-body{position:relative;z-index:1;margin-top:-18px;padding-top:0}
  .jj .svcs .svc-card .svc-media img[src*="j-svc-lighting"]{object-position:50% 18%!important}
  .jj .svcs .svc-card .svc-media img[src*="j-svc-switch"]{object-position:38% 40%!important}
}

/* ---- Phones: everything open except the FAQ and the area cards under the map (23 Oct, Edoardo) ---- */
@media (max-width:700px){
  .step-list .st-more{display:block;margin-top:2px}
  .area-list .area-pill{min-height:40px}   /* the pills are on screen now: thumb-sized */
}

/* ---- Emergency page, phones: the "James & the JJC team, On call 24/7" chip shows above the headline (23 Oct, Edoardo) ---- */
@media (max-width:700px){
  .ve.pg-emergency-electrician .hero .oncall{display:inline-flex;align-self:flex-start;gap:8px;padding:3px 12px 3px 3px;margin-bottom:2px;background:rgba(17,17,17,.78);border-color:rgba(255,255,255,.16)}   /* 23 Oct: dark chip, the pale one lost "On call 24/7" over light video frames */
  .ve.pg-emergency-electrician .hero .oncall-face{width:30px;height:30px}
  .ve.pg-emergency-electrician .hero .oncall b{font-size:12.5px}
  .ve.pg-emergency-electrician .hero .oncall span{font-size:12px}
}

/* ---- Areas street map (23 Oct, Edoardo picked the v2 map): js/map.js, JJC orange on Esri dark grey ---- */
.cov-map.is-leaflet .cov-svg{display:none}
.cov-map.is-leaflet .cov-reset{bottom:auto;top:14px;z-index:500}
#lmap{position:relative;height:clamp(360px,44vw,480px);border-radius:14px;overflow:hidden;background:#141414;margin:4px 0 10px;z-index:0;border:1px solid rgba(249,129,28,.28);box-shadow:inset 0 0 70px rgba(0,0,0,.6)}
#lmap .leaflet-container,#lmap.leaflet-container{background:#141414;font-family:inherit}
#lmap .leaflet-control-attribution{background:rgba(20,20,20,.78);color:#999;font-size:10px}
#lmap .leaflet-control-attribution a{color:#FFA54F}
#lmap .leaflet-bar a{background:#1e1e1e;color:#fff;border-bottom-color:rgba(255,255,255,.1);width:34px;height:34px;line-height:34px}
#lmap .leaflet-bar a:hover{background:#F9811C;color:#141414}
.lp-wrap{background:none;border:0}
.lp{position:absolute;left:50%;top:50%;width:9px;height:9px;margin:-4.5px 0 0 -4.5px;border-radius:50%;background:#F9811C;box-shadow:0 0 0 1.5px rgba(20,20,20,.9),0 0 10px 2px rgba(249,129,28,.6);transition:background-color .3s,transform .3s}
.lp-wrap.is-top .lp{width:12px;height:12px;margin:-6px 0 0 -6px;box-shadow:0 0 0 2px rgba(20,20,20,.9),0 0 16px 4px rgba(249,129,28,.75)}
.lp-wrap.is-top .lp::after{content:"";position:absolute;inset:-9px;border-radius:50%;border:1.5px solid rgba(249,129,28,.75);animation:lpRing 2.8s ease-out infinite;opacity:0}
.lp-wrap.is-top:nth-child(3n) .lp::after{animation-delay:.9s}.lp-wrap.is-top:nth-child(3n+1) .lp::after{animation-delay:1.8s}
@keyframes lpRing{0%{transform:scale(.4);opacity:.9}100%{transform:scale(2.3);opacity:0}}
.lp-wrap.is-pick .lp{background:#fff;box-shadow:0 0 0 2px rgba(20,20,20,.9),0 0 12px 3px rgba(255,255,255,.55)}
.lp-wrap.is-pick .lp::after{border-color:rgba(255,255,255,.7)}
.lp-wrap.is-dim{opacity:.3}
.lp-wrap.is-hit{opacity:1}
.lp-wrap.is-hit .lp{width:16px;height:16px;margin:-8px 0 0 -8px;background:#fff;box-shadow:0 0 0 3px #F9811C,0 0 24px 8px rgba(249,129,28,.8)}
.lp-wrap.is-hit .lp::after{animation-duration:1.4s;border-color:#F9811C;opacity:1}
.lp-label-wrap,.lp-base-wrap{background:none;border:0}
.lp-label{position:absolute;transform:translate(-50%,-150%);white-space:nowrap;font-weight:800;font-size:12px;color:#fff;background:rgba(20,20,20,.78);border:1px solid rgba(249,129,28,.45);border-radius:20px;padding:4px 10px;pointer-events:none;transition:opacity .3s}
.lp-label-wrap.is-off .lp-label{opacity:0}
.lp-base{position:absolute;transform:translate(-50%,-50%);white-space:nowrap;font-weight:900;font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;color:#141414;background:#F9811C;border-radius:6px;padding:3px 7px;box-shadow:0 0 0 2px rgba(20,20,20,.9),0 0 18px rgba(249,129,28,.6)}
.lp-tip{background:#1e1e1e;color:#fff;border:1px solid rgba(249,129,28,.5);border-radius:8px;font-weight:700;font-size:12.5px;padding:5px 9px;box-shadow:0 10px 24px rgba(0,0,0,.45)}
.lp-tip::before{border-top-color:#1e1e1e!important}
@media (prefers-reduced-motion:reduce){.lp-wrap.is-top .lp::after{animation:none}}
.lmap-hint{position:absolute;left:50%;top:50%;z-index:800;translate:-50% -50%;max-width:80%;padding:10px 16px;border-radius:30px;background:rgba(20,20,20,.88);color:#fff;font-weight:700;font-size:14px;text-align:center;pointer-events:none;opacity:0;transition:opacity .25s}
.lmap-hint.on{opacity:1}
.lp-wrap:not(.is-top):not(.is-pick):not(.is-hit) .lp{width:7px;height:7px;margin:-3.5px 0 0 -3.5px;background:#E07418;box-shadow:0 0 0 1.5px rgba(20,20,20,.9)}   /* every suburb: a plain dot; converting ones glow + pulse */
.leaflet-pane.lmap-edge{filter:drop-shadow(0 0 3px #F9811C) drop-shadow(0 0 9px rgba(249,129,28,.55))}   /* the neon edge of the coverage area */

/* 23 Oct final checks: on service pages the quick-quote card overlapped the hero by 96px and hid the hero trust bar
   at every desktop width. From 701px it now starts below the bar (phones keep the small overlap: no trust bar there). */
@media (min-width:701px){
  .jj.svc-page .pick-card{margin-top:0}
  .jj.svc-page .ve-picker{padding-top:clamp(28px,3vw,40px)}
}
/* 23 Oct: the street map carries the OpenStreetMap credit in its own credit line; the line under the map is for the drawn fallback */
.cov.has-lmap .cov-credit{display:none}

/* 23 Oct final checks: service collages keep faces in frame at every width (styled by photo, not by tile position).
   em-g1: face at the left edge of a portrait shot in the tall tile; sb-g2/sb-g3: James on the left third; ev-g3: two
   people at opposite edges, keep the charger and the customer on the right. */
.gal img[src*="em-g1"]{object-position:0% 45%}
.gal img[src*="sb-g2"]{object-position:15% 50%}
.gal img[src*="sb-g3"]{object-position:8% 50%}
.gal img[src*="ev-g3"]{object-position:100% 50%}
@media (max-width:700px){.rw-card blockquote{-webkit-line-clamp:5}}   /* 23 Oct: phones cap at 5 lines (Read more shows the rest) so the strip's tallest card stays close to a typical one */
/* 23 Oct final checks: 7 types on desktop = 4 + 3 centred (the 4-column grid left an empty cell at the end of row 2) */
@media (min-width:701px){
  .ty-grid.n7{grid-template-columns:repeat(8,minmax(0,1fr))}
  .ty-grid.n7 .ty,.ty-grid.n7 .ty:last-child{grid-column:span 2}
  .ty-grid.n7 .ty:nth-child(5){grid-column:2 / span 2}
}
/* 23 Oct final checks: tablets (701-1099) put call + quote side by side: stacked, the hero ran 21px past a 1024x768
   screen and cut the trust bar in half */
@media (min-width:701px) and (max-width:1099px){.ve .hero-inner>.hero-ctas{max-width:none}}
/* 23 Oct final checks: no single word or full stop alone on the last line */
.nw{white-space:nowrap}
.ve-cta .cta-inner>p,.hero-kicker{text-wrap:balance}
/* 23 Oct final checks, tablets: footer = brand and facts full width, the two link columns side by side (4 columns of
   ~150px wrapped every service link); hero trust bar 3 + 2 centred instead of 4 + 1 under 900px */
@media (min-width:701px) and (max-width:1099px){
  .foot-grid{grid-template-columns:1fr 1fr}
  .foot-brand,.foot-facts{grid-column:1/-1}
}
@media (min-width:701px) and (max-width:899px){
  .hero-trust li{flex:0 0 33.333%;justify-content:center;padding-left:8px;padding-right:8px}
  .hero-trust li:nth-child(4){border-left:0}
  .hero-trust li:nth-child(n+4){border-top:1px solid rgba(255,255,255,.12)}
}
@media (min-width:701px) and (max-width:1099px){.area-list .area-pill{min-height:40px}}   /* 23 Oct: tablets are touch screens too (34px pills at 768) */

/* 23 Oct: James's reels. One reel (Switchboard page): a single phone, centred, slight tilt, bubbles beside it on desktop */
.phones.n1{grid-template-columns:minmax(0,1fr);max-width:330px}
.phones.n1 .phone.ph1{rotate:-3deg;margin:0;max-width:270px}
@media (min-width:1001px){
  .phones.n1{grid-template-columns:minmax(150px,230px) minmax(0,1fr);max-width:560px}
  .phones.n1 .phone.ph1{grid-column:2;grid-row:1/3}
}

/* ---- 23 Oct: section tones (Edoardo: "not all dark on top and clear on bottom"). Builders add tone-d / tone-l by id
   (build_home.HOME_TONES, build_service.SVC_TONES). Dark = the hero/services dark; light = white. Accent text: #FFA54F on
   dark, #B45309 on light (both pass 4.5:1). Buttons re-style themselves (core.js marks .on-light). ---- */
.ve section.tone-d{background:#141414;color:#fff}
.ve section.tone-d :is(h2,h3,.sec-head h2){color:#fff}
.ve section.tone-d :is(.lead,.areas-note,.st-more,.why-about p,.cov-hint,.ty b){color:#CFCFCF}
.ve section.tone-d .hl{color:#FFA54F}
.ve section.tone-d .kicker{color:#FFA54F}
.jj section.tone-d .tel-pill{--tel-pill-ink:#fff}
.ve section.tone-d .step-list li{color:#fff}
.ve section.tone-d .st-b>b{color:#fff}
.ve section.tone-d .area-card{box-shadow:none}
.ve section.tone-d .why-main,.ve section.tone-d .why-small{box-shadow:0 20px 50px rgba(0,0,0,.55)}
.ve section.tone-l{background:#fff;color:#1A1A1A}
.ve section.tone-l :is(h2,h3){color:#1A1A1A}
.ve section.tone-l .hl{color:#B45309}
.ve section.tone-l .kicker,.ve section.tone-l .kicker-light{color:#B45309}
.ve section.tone-l :is(.emerg-copy>p.d-only,.emerg-p){color:#555}
.ve section.tone-l .emerg-safe{color:#1A1A1A;background:rgba(249,129,28,.08)}
.ve section.tone-l .emerg-chips li{border-color:rgba(0,0,0,.18)}
.ve section.tone-l .clamp-more{color:#B45309}
.jj section.tone-l .tel-pill{--tel-pill-ink:#1A1A1A}
.ve section.dispatch.tone-l{background:#fff}
/* the dispatch board keeps its own dark card on a light section: its text never takes the light-section colours */
.ve section.tone-l .disp,.ve section.tone-l .disp :is(h2,h3){color:#fff}
.ve section.tone-l .disp .hl{color:#FFA54F}
/* white cards inside a dark section keep dark text (the areas region cards and their suburb pills, the why cards) */
.ve section.tone-d :is(.area-card,.wc){color:#1A1A1A}
.ve section.tone-d :is(.area-card,.wc) :is(h3,b){color:#1A1A1A}
/* featured review on a light band (home: it follows the dark hero + quote form) */
.jj .ve-feat.tone-l{background:#fff;color:#1A1A1A}
.jj .ve-feat.tone-l::before{background:radial-gradient(40% 40% at 25% 30%,rgba(249,129,28,.12),transparent 70%),radial-gradient(35% 35% at 80% 70%,rgba(249,129,28,.08),transparent 70%)}
.jj .ve-feat.tone-l .g-badge-stars{color:#FBBC04}
.jj .ve-feat.tone-l .g-src{border:1px solid #DADCE0}
.jj .ve-feat.tone-l .feat-more{color:#B45309}

/* ---- 23 Oct "most leads" order (v2 merged into the root): objection strip at the top of Services; merged Why; Emergency call-now block ---- */
.obj-strip{list-style:none;margin:0 0 22px;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
.obj-strip li{display:flex;align-items:center;gap:10px;padding:12px 14px;border-radius:var(--r);background:rgba(249,129,28,.1);border:1px solid rgba(249,129,28,.35);color:#fff;font-weight:700;font-size:14.5px;line-height:1.3}
.obj-strip svg{width:20px;height:20px;flex:none;color:#F9811C}
@media (max-width:420px){.obj-strip{grid-template-columns:minmax(0,1fr)}}
@media (min-width:1100px){.obj-strip{grid-template-columns:repeat(4,minmax(0,1fr))}}
.callnow{background:#111;color:#fff;padding-top:clamp(26px,4vw,44px);padding-bottom:clamp(26px,4vw,44px)}
.callnow h2{font-size:clamp(24px,6vw,34px);margin:0 0 14px}
.callnow .emerg-list{margin:0 0 14px}
.callnow .cn-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:18px}
/* merged Why on phones: the second photo and the extra paragraphs (they repeat the About text) are desktop only (hidden, never deleted) */
@media (max-width:700px){#why.about .why-small,#why.about .why-more{display:none}}
@media (min-width:901px){.callnow .cn-grid{grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);align-items:center;gap:48px}}

/* ==== 23 Oct edit round (v2 approved by Edoardo, merged): review chip star refill, closing band photo, Process sparks ==== */
/* 2. hero review chip (round 3, Edoardo: "something usually used for a review chip"): the classic rating fill. Every 7s the five
   stars dim to grey and refill gold one by one, left to right, each with a small pop. Animates the <use> inside each star, so it
   never fights the stars' drop-in (that animates the <svg>). Off under reduced motion. */
@media (prefers-reduced-motion:no-preference){
  .js .ve .hero-pill .g-badge-stars use{transform-box:fill-box;transform-origin:50% 55%;animation:hpFill 7s cubic-bezier(.3,1.4,.5,1) 3s infinite}
  .js .ve .hero-pill .g-badge-stars svg:nth-child(2) use{animation-delay:3.12s}
  .js .ve .hero-pill .g-badge-stars svg:nth-child(3) use{animation-delay:3.24s}
  .js .ve .hero-pill .g-badge-stars svg:nth-child(4) use{animation-delay:3.36s}
  .js .ve .hero-pill .g-badge-stars svg:nth-child(5) use{animation-delay:3.48s}
}
@keyframes hpFill{0%{color:inherit;transform:none}3%{color:#DADCE0;transform:scale(.8)}9%{color:#DADCE0;transform:scale(.8)}12%{color:#FBBC04;transform:scale(1.35)}16%,100%{color:inherit;transform:none}}

/* 6. closing CTA band: James + the van (ps16), subject left, text right on desktop; phones: photo on top, text below */
.jj .ve-cta{background:linear-gradient(0deg,#111 0%,rgba(17,17,17,.97) 42%,rgba(17,17,17,.55) 62%,rgba(17,17,17,.1) 100%),url(../assets/img/j-cta-m.jpg) 50% 0/100% auto no-repeat,#111;padding-top:min(92vw,420px)}
@media (min-width:701px){
  .jj .ve-cta{background:linear-gradient(270deg,rgba(17,17,17,.97) 0%,rgba(17,17,17,.9) 38%,rgba(17,17,17,.25) 68%,rgba(17,17,17,.05) 100%),url(../assets/img/j-cta.jpg) 0% 30%/cover no-repeat,#111;
    padding-top:clamp(90px,10vw,140px);padding-bottom:clamp(90px,10vw,140px)}
  .jj .ve-cta .cta-inner{text-align:right}
  .jj .ve-cta h2,.jj .ve-cta p{margin-left:auto;max-width:560px}
  .jj .ve-cta .cta-row{justify-content:flex-end}
  .jj .ve-cta .cta-row .btn{flex:none}
}

/* 7. Process (round 2, Edoardo: "be more accurate"): each number lights up exactly when the line tip reaches its centre
   (v2 js/motion.js), the spark sits exactly on the tip (placed by js/jjc.js from the measured line) and sheds sparks like a
   sparkler while the line moves; each number bursts when it lights. Off under reduced motion. */
.ve .step-list .st-spark{position:absolute;z-index:2;left:0;top:0;width:12px;height:12px;margin:-6px 0 0 -6px;border-radius:50%;pointer-events:none;opacity:0;
  background:radial-gradient(circle,#fff 0 30%,#FFE2A8 45%,rgba(249,129,28,.7) 65%,transparent 75%);
  box-shadow:0 0 10px 3px rgba(255,190,110,.95),0 0 26px 8px rgba(249,129,28,.45);transition:opacity .25s}
.ve .step-list.is-live .st-spark{opacity:1}
.ve .step-list .st-spark::after{content:"";position:absolute;inset:-7px;border-radius:50%;border:1.5px solid rgba(255,214,150,.7);animation:stPulse .5s ease-out infinite}
@keyframes stPulse{from{transform:scale(.4);opacity:1}to{transform:scale(1.4);opacity:0}}
.st-fly{position:absolute;z-index:2;width:3px;height:3px;margin:-1.5px 0 0 -1.5px;border-radius:50%;background:#FFE9C2;box-shadow:0 0 5px 1.5px rgba(249,129,28,.9);pointer-events:none;
  animation:stFly var(--t,.5s) cubic-bezier(.2,.6,.4,1) forwards}
@keyframes stFly{from{transform:translate(0,0) scale(1);opacity:1}to{transform:translate(var(--x),var(--y)) scale(.3);opacity:0}}
.st-burst{position:absolute;width:0;height:0;pointer-events:none;z-index:3}
.st-burst i{position:absolute;left:-2px;top:-2px;width:4px;height:4px;border-radius:50%;background:#FFE3B0;box-shadow:0 0 6px 2px rgba(249,129,28,.8);
  animation:stBurst .62s cubic-bezier(.15,.7,.3,1) forwards;animation-delay:var(--dl,0s)}
@keyframes stBurst{0%{transform:rotate(var(--a)) translateX(4px) scale(1.2);opacity:1}100%{transform:rotate(var(--a)) translateX(var(--d)) scale(.2);opacity:0}}
.ve .step-list li.st-zap .st-n{animation:stZap .5s steps(1,end)}
@keyframes stZap{0%{box-shadow:0 0 0 0 rgba(249,129,28,0)}20%{box-shadow:0 0 22px 6px rgba(255,200,120,.9)}40%{box-shadow:0 0 4px 1px rgba(249,129,28,.4)}60%{box-shadow:0 0 18px 5px rgba(255,200,120,.8)}100%{box-shadow:0 0 0 0 rgba(249,129,28,0)}}
@media (prefers-reduced-motion:reduce){.ve .step-list .st-spark,.st-burst,.st-fly{display:none}}

/* ==== 23 Oct pre-publish fixes ==== */
/* 1. GHL form on phones: crop GHL's own 20px outer padding on each side (playbook), fields go ~235 -> ~275px wide */
.enq-card.ghl-mob .form-crop iframe{width:calc(100% + 40px)!important;margin-left:-20px}
/* 2. Emergency "Why" photo: keep James's head in (the service-page default 50% 60% cut it at 1280) */
.svc-page .why-main img[src*="em-why"]{object-position:40% 15%}
/* 3. hero trust bar: 3 + 2 on every tablet width (it was 4 + 1 from 900 to 1099) */
@media (min-width:701px) and (max-width:1099px){
  .hero-trust li{flex:0 0 33.333%;justify-content:center;padding-left:8px;padding-right:8px}
  .hero-trust li:nth-child(4){border-left:0}
  .hero-trust li:nth-child(n+4){border-top:1px solid rgba(255,255,255,.12)}
}
/* 4. Areas rows: the "76 suburbs" count never wraps; the "Not on the list?" line keeps its last word with the pill */
.area-n{white-space:nowrap}
.areas-note .nw{white-space:nowrap}
/* 5. "Why Homeowners…" subheading: space above its paragraph */
.why-more .fold-b>p:first-child,.why-h3+p{margin-top:10px}
/* 6. service-page H1 first line ("EV Charger Installation in") stays on one line from 320px (playbook) */
@media (max-width:700px){.jj.svc-page .hero-title .ht-1{font-size:min(.6em,6.3vw)}}
/* 7. picker headings: the highlighted words stay on one line, so the underline never runs into the next line ("new / switchboard?") */
.picker-head h2 .hl{white-space:nowrap}
/* 8. phones: each service page's hero background is its own poster (it downloaded and flashed the home photo) */
@media (max-width:700px){
  .jj.pg-emergency-electrician .hero{background-image:url(../assets/video/em-hero-poster.jpg)}
  .jj.pg-ev-charger-installation .hero{background-image:url(../assets/video/ev-hero-poster.jpg)}
  .jj.pg-ceiling-fans-lighting .hero{background-image:url(../assets/video/li-hero-poster.jpg)}
  .jj.pg-switchboard-upgrades .hero{background-image:url(../assets/video/sb-hero-poster.jpg)}
}
/* 9. Areas cards when picked: a solid light-orange card with the orange ring on any section (the 8% tint read as the dark
   section's own background, and the dark-section rule removed the ring). Heading in the deeper orange for contrast. */
.area-card.is-picked,.ve section.tone-d .area-card.is-picked{background-color:#FFF1E3;box-shadow:inset 0 0 0 2px #F9811C}
.ve section.tone-d .area-card.is-match{box-shadow:0 0 0 2px #F9811C}
.area-card.is-picked h3,.ve section.tone-d .area-card.is-picked h3{color:#B45309}
@media (hover:hover) and (pointer:fine){.ve section.tone-d .area-card[data-region]:not(.is-picked):hover{box-shadow:inset 0 0 0 2px rgba(249,129,28,.6)}}

/* photo swaps 23 Oct */
.gal img[src*="sb-g3b"]{object-position:50% 55%}
.gal img[src*="em-g2b"]{object-position:45% 50%}

/* 23 Oct v2: "trustworthy face early" (Andrew via Edoardo), photos MERGED into the section (Edoardo: "merged in the section
   better", "the photo should take all the section", home elements placed properly). No masks with hard alpha edges: the
   photo is toned down and melts into the section's own #141414 through gradients in that colour (.merge::after), so it reads
   as part of the background. Nothing in the section is replaced.
   Home desktop: heading top-left, the team fills the rest of the left side (bleeds off the left edge and the section bottom),
   the promises + call move under the form on the right. Review band desktop: James takes the whole right half, top to bottom,
   however long the review. Phones/tablets: the photo opens the section edge to edge and the first lines sit on its dark end. */
.merge{margin:0;position:relative;pointer-events:none;overflow:hidden}
.merge picture{display:contents}
.merge img{display:block;width:100%;height:100%;object-fit:cover;object-position:var(--pm,50% 30%)}
.ve .enquire{overflow:hidden}
@media (max-width:1099px){   /* phones + tablets: unchanged from the version Edoardo approved on mobile */
  .merge{--g:16px;width:calc(100% + 2 * var(--g));margin-left:calc(-1 * var(--g));height:clamp(250px,64vw,400px);
    -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 7%,#000 56%,transparent 100%);mask-image:linear-gradient(to bottom,transparent 0,#000 7%,#000 56%,transparent 100%)}
  .ve-enq .enq-photo{margin-top:-44px;margin-bottom:-92px}
  .ve-enq .enq-copy{position:relative;z-index:1}
  .rv-feat.has-photo .feat-photo{margin-left:0;width:100%;margin-top:-44px;margin-bottom:-96px}
  .rv-feat.has-photo .feat-inner{position:relative;z-index:1}
  .ve-enq .enq-copy .enq-who-tag,.ve-enq .enq-copy h2,.rv-feat.has-photo .feat-top{text-shadow:0 2px 14px rgba(0,0,0,.55)}
  .callnow .cn-photo{grid-column:1/-1;margin-top:calc(-1 * clamp(26px,4vw,44px));margin-bottom:-92px}
}
@media (min-width:701px) and (max-width:1099px){
  .merge{--g:clamp(20px,4vw,40px)}
  .ve-enq .enq-grid{grid-template-areas:"photo" "copy" "qw" "more"}
  .ve-enq .enq-photo{grid-area:photo;margin-top:calc(-1 * clamp(64px,8vw,104px))}
  .rv-feat.has-photo .feat-photo{margin-top:calc(-1 * clamp(64px,8vw,110px))}
}
@media (min-width:1100px){
  .merge img{object-position:var(--pd,50% 30%);filter:brightness(.84) saturate(.92) contrast(1.04)}
  .merge::after{content:"";position:absolute;inset:0;pointer-events:none}
  /* home (Edoardo 23 Oct: like phones/tablets, inside the central frame): the team opens the section across the frame, fading
     out on every side, and the heading + form sit over its faded bottom; promises + call back under the heading */
  .ve-enq .enq-grid{grid-template-areas:"photo photo" "copy qw" "more qw";grid-template-rows:auto auto 1fr}
  .ve-enq .enq-photo{grid-area:photo;height:clamp(420px,36vw,540px);margin:calc(-1 * clamp(64px,8vw,104px)) 0 -150px;
    -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 8%,#000 52%,transparent 100%),linear-gradient(to right,transparent 0,#000 14%,#000 86%,transparent 100%);
    -webkit-mask-composite:source-in;mask-image:linear-gradient(to bottom,transparent 0,#000 8%,#000 52%,transparent 100%),linear-gradient(to right,transparent 0,#000 14%,#000 86%,transparent 100%);mask-composite:intersect}
  .ve-enq .enq-photo img{filter:none}
  .ve-enq .enq-photo::after{content:none}
  .ve-enq .enq-copy,.ve-enq .qw{position:relative;z-index:1}
  .ve-enq .enq-copy .enq-who-tag,.ve-enq .enq-copy h2{text-shadow:0 2px 14px rgba(0,0,0,.55)}
  /* review band: James takes the whole right half, top to bottom */
  .rv-feat.has-photo .feat-photo{position:absolute;top:0;right:0;bottom:0;width:52%;z-index:0}   /* the whole height, however long the review */
  .rv-feat.has-photo .feat-photo::after{background:linear-gradient(to right,#141414 0,rgba(20,20,20,.78) 14%,rgba(20,20,20,.3) 40%,rgba(20,20,20,0) 66%),
    linear-gradient(to bottom,#141414 0,rgba(20,20,20,0) 12%,rgba(20,20,20,0) 84%,#141414 100%)}
  .rv-feat.has-photo .feat-inner{position:relative;z-index:1}
  .rv-feat.has-photo .feat-inner>*{max-width:54%}
}
/* Emergency "Call us now if..." (23 Oct): the same treatment as the home quote section, inside the central frame */
.callnow{position:relative;overflow:hidden}
.callnow .cn-grid>div:not(.merge){position:relative;z-index:1}
.callnow .cn-grid h2{text-shadow:0 2px 14px rgba(0,0,0,.55)}
@media (min-width:1100px){
  .callnow .cn-photo{grid-column:1/-1;height:clamp(400px,34vw,520px);margin:calc(-1 * clamp(26px,4vw,44px)) 0 -170px;
    -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 8%,#000 52%,transparent 100%),linear-gradient(to right,transparent 0,#000 14%,#000 86%,transparent 100%);
    -webkit-mask-composite:source-in;mask-image:linear-gradient(to bottom,transparent 0,#000 8%,#000 52%,transparent 100%),linear-gradient(to right,transparent 0,#000 14%,#000 86%,transparent 100%);mask-composite:intersect}
  .callnow .cn-photo img{filter:none}
  .callnow .cn-photo::after{content:none}
}
/* Lighting page (23 Oct): the review band's photo on the LEFT on desktop (Edoardo's shot has the wall light and switch on its left) */
@media (min-width:1100px){
  .rv-feat.has-photo.photo-left .feat-photo{right:auto;left:0}
  .rv-feat.has-photo.photo-left .feat-photo::after{background:linear-gradient(to left,#141414 0,rgba(20,20,20,.78) 14%,rgba(20,20,20,.3) 34%,rgba(20,20,20,0) 56%),
    linear-gradient(to bottom,#141414 0,rgba(20,20,20,0) 12%,rgba(20,20,20,0) 84%,#141414 100%)}
  .rv-feat.has-photo.photo-left .feat-inner>*{margin-left:auto;max-width:50%}
}
