/* <button> carries a UA default border of 2px OUTSET, a 3D bevel that renders
   light on the top-left and dark on the bottom-right. With border-radius:100px that
   shows as pale arcs around the pill - the "partial white corners" on the nav CTA.
   .btn already set border:none; these did not. */
:root{--ink:#0a0d08;--ink2:#141a11;--paper:#fff;--cream:#f5f7f0;--neon:#C3F53C;--neon-d:#7fae00;--neon-txt:#547800;--muted:#5a625c;--line:#e4e8e0}.w{max-width:1180px;margin:0 auto;padding:0 40px;position:relative;z-index:2}.btn{display:inline-flex;align-items:center;gap:10px;background:var(--neon);color:var(--ink);font-family:'Bebas Neue';font-size:23px;letter-spacing:.5px;padding:15px 32px;border-radius:100px;cursor:pointer;border:none;transition:transform .15s,filter .15s}
/* A .btn is inline-flex with gap:10px, so ANY element inside the label becomes a
   flex item and the gap lands on both sides of it. That put 10px either side of the
   injected review count in "Read all 775+ reviews". The label is wrapped in .btn-t so
   the button has ONE flex child and the gap can only separate the label from an icon,
   which is what it is for. */
.btn>.btn-t{display:inline;white-space:normal}
.btn:hover{transform:translateY(-2px);filter:brightness(1.06)}.btn-lg{font-size:28px;padding:18px 42px}.nav{position:fixed;top:0;left:0;right:0;z-index:100;display:flex;justify-content:space-between;align-items:center;padding:20px 48px;transition:background .25s ease,backdrop-filter .25s ease,padding .2s ease}.nav.scrolled{background:rgba(10,13,8,.82);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);padding:12px 48px;border-bottom:1px solid rgba(255,255,255,.08)}.nav .brand{font-family:'Bebas Neue';font-size:26px;letter-spacing:2px;color:var(--neon)}.nav a.ph{color:var(--neon);font-weight:700;display:inline-flex;align-items:center;gap:8px;text-decoration:none}.nav a.ph svg{width:16px;height:16px;flex-shrink:0}.nav .right{display:flex;align-items:center;gap:22px}.nav .menu{color:#fff;font-weight:600}.capture .btn{white-space:nowrap}.hero-rate .st{color:#ffb400;letter-spacing:2px}.rev .st{color:#ffb400;letter-spacing:2px;font-size:15px}.foot .brand{font-family:'Bebas Neue';font-size:22px;letter-spacing:2px;color:var(--neon)}@media(max-width:820px){.w{padding:0 22px}.nav{padding:16px 22px}.nav.scrolled{padding:10px 22px}.nav a.ph span{display:none}.nav a.ph svg{width:19px;height:19px}}:root{--slice:-8deg;--sage:#F0F9E5;--green-solid:#6EE268;--green-pale:#ECFEC6}@media(min-width:768px){:root{--slice:-11deg}}.sec .w{position:relative;z-index:1}.footer{--charcoal:#0d1410;--white:#fff;--orange:#1f9d5c;--display:'Bebas Neue',sans-serif;background:var(--charcoal);padding:60px 0 30px;border-top:1px solid rgba(195,245,60,.16);position:relative;z-index:2}.footer-top-row{display:grid;grid-template-columns:1.8fr 1fr 1fr 1fr 1fr 1fr;gap:28px;padding-bottom:40px;border-bottom:1px solid rgba(255,255,255,.08)}.f-brand-block{padding-right:8px}.f-logo{font-family:var(--display);font-size:20px;color:var(--white);display:flex;align-items:center;gap:9px;margin-bottom:16px}.f-legal-text{font-size:12px;font-weight:300;color:rgba(255,255,255,.32);line-height:1.65;margin-bottom:18px}.f-address{display:flex;flex-direction:column;gap:2px;margin-bottom:16px;font-size:13px;color:rgba(255,255,255,.5)}.f-address-label{font-size:11.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.25)}.f-contact-item{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600;color:var(--orange);transition:color .15s;width:fit-content}.f-contact-item svg{color:var(--orange);flex-shrink:0}.f-contact-item:hover{color:var(--white)}.f-social{display:flex;gap:10px}.f-social-icon{width:34px;height:34px;border-radius:50%;border:1px solid rgba(255,255,255,.12);display:grid;place-items:center;color:rgba(255,255,255,.5);transition:all .2s;flex-shrink:0}.f-social-icon:hover{background:var(--orange);border-color:var(--orange);color:var(--white)}.f-col h4{font-size:11.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.25);margin-bottom:16px}.f-col ul{list-style:none;display:flex;flex-direction:column;gap:9px}.f-col ul li a{font-size:13px;font-weight:300;color:rgba(255,255,255,.4)}.f-col ul li a:hover{color:var(--white)}.footer-locations{padding:32px 0;border-bottom:1px solid rgba(255,255,255,.08)}.footer-locations h4{font-size:11.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.25);margin-bottom:16px}.f-locations-grid{display:flex;flex-wrap:wrap;gap:10px 20px}.f-locations-grid a{font-size:13px;font-weight:300;color:rgba(255,255,255,.4)}.f-locations-grid a:hover{color:var(--white)}
/* the see-all that ends the locations grid. WEIGHT only, no colour: the town links render
   full white on most templates and .4 on others, so a fixed colour here made the see-all
   DIMMER than the list on the majority of pages. Element selector under an existing
   class, so it cannot collide with anything in the one-file cascade. */
.f-locations-grid a b{font-weight:600}
.footer-bot{display:flex;justify-content:space-between;align-items:flex-start;padding-top:26px;flex-wrap:wrap;gap:20px}.footer-bot-l{max-width:540px}/* 6px left the Add to Preferred Sources button crowding the line above it. */
.f-app-note{font-size:12px;color:rgba(255,255,255,.35);font-weight:300;margin-bottom:14px}.f-app-badges{display:flex;gap:10px;margin-bottom:14px;flex-wrap:wrap}.f-trademark-note{font-size:11px;color:rgba(255,255,255,.2);font-weight:300;margin-bottom:12px}.f-legal{font-size:12px;color:rgba(255,255,255,.2);font-weight:300}.app-badge{display:inline-flex;align-items:center;gap:9px;background:#000;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:7px 14px;color:var(--white);transition:all .2s}.app-badge:hover{background:#1a1a1a;border-color:rgba(255,255,255,.3)}.app-badge span{display:flex;flex-direction:column;line-height:1.15}.app-badge small{font-size:9px;font-weight:400;color:rgba(255,255,255,.75);letter-spacing:.02em}.app-badge strong{font-size:14px;font-weight:600;letter-spacing:.01em}@media(max-width:1100px){.footer-top-row{grid-template-columns:1fr 1fr 1fr}.f-brand-block{grid-column:1/-1}.f-locations-grid{gap:8px 16px}}@media(max-width:768px){.footer-top-row{grid-template-columns:1fr}.footer-bot{flex-direction:column;align-items:flex-start}}.f-logo{font-family:'Bebas Neue',sans-serif;font-size:24px;letter-spacing:.04em}.f-col h4, .footer-locations h4, .f-address-label{font-family:'Inter',sans-serif;font-weight:700;letter-spacing:.14em}.f-col ul li a, .f-locations-grid a{font-family:'Inter',sans-serif}.s4g-fab{position:fixed;right:20px;bottom:20px;z-index:900;display:flex;flex-direction:column;gap:12px}.fab{width:54px;height:54px;border-radius:50%;display:grid;place-items:center;box-shadow:0 6px 22px rgba(0,0,0,.28);cursor:pointer;border:none;transition:transform .15s,box-shadow .15s;text-decoration:none}.fab:hover{transform:translateY(-3px);box-shadow:0 10px 28px rgba(0,0,0,.34)}.fab-call{background:#12140f;color:var(--neon)}.fab-wa{background:#25D366;color:#fff}.fab-top{background:#0a0d08;color:#fff;opacity:0;pointer-events:none}.fab-top.show{opacity:1;pointer-events:auto}@media(max-width:600px){
/* The fixed action bar is 96px tall and holds only Freephone and WhatsApp - no
   quote button. Nothing reserved space for it, so at 390x600 it covered 56px of
   the 58px hero quote button on the brand pages, leaving a visitor with no quote
   CTA at all on landing. Measured 23 Sep 2026.
   Page heroes set their own min-height in inline <style>, so these need to beat
   that in specificity, not source order - hence the body prefix. */
/* NOT fixed here, deliberately: at 390x600 the hero CTA is still partly under the
   bar on landing. The hero sets padding:96px 0 40px !important and its content is
   522px tall, so 96+522 = 618 against 504 of usable height - it does not fit, and
   no rule here can win against !important anyway. Scrolling ~60px reveals it.
   Fixing it means reducing hero density per template, which is a design change. */
body{padding-bottom:calc(96px + env(safe-area-inset-bottom))}
.s4g-fab{right:14px;bottom:14px;gap:10px}.fab{width:50px;height:50px}}.s4g-fab{right:auto;left:20px}@media(max-width:600px){.s4g-fab{left:14px;right:auto}}.s4g-chat-bubble{position:fixed;right:22px;bottom:22px;z-index:955;width:60px;height:60px;border-radius:50%;background:#1f9d5c;display:grid;place-items:center;box-shadow:0 8px 26px rgba(0,0,0,.32);cursor:pointer;border:none;transition:transform .18s}.s4g-chat-bubble:hover{transform:scale(1.06)}.s4g-chat-bubble>span{position:absolute;display:grid;place-items:center;transition:opacity .2s,transform .25s}@media(max-width:600px){.s4g-chat-bubble{right:16px;bottom:16px}}.s4g-fab{gap:14px}.fab{position:relative;width:52px;height:52px;box-shadow:0 6px 18px rgba(0,0,0,.32),0 0 0 1.5px rgba(255,255,255,.22)}.fab svg{transition:transform .18s}.fab:hover{transform:translateY(-3px)}.fab:hover svg{transform:scale(1.08)}.fab::after{content:attr(data-tip);position:absolute;left:calc(100% + 14px);top:50%;transform:translateY(-50%) translateX(-6px);white-space:nowrap;background:#0a0d08;color:#fff;padding:9px 14px;border-radius:10px;font-size:13px;font-weight:600;font-family:'Inter',sans-serif;letter-spacing:.01em;opacity:0;pointer-events:none;transition:opacity .18s ease,transform .18s ease;box-shadow:0 6px 18px rgba(0,0,0,.28)}.fab::before{content:"";position:absolute;left:calc(100% + 8px);top:50%;transform:translateY(-50%) translateX(-6px);border:6px solid transparent;border-right-color:#0a0d08;opacity:0;transition:opacity .18s,transform .18s}.fab:hover::after, .fab:hover::before{opacity:1;transform:translateY(-50%)}.fab-wa{background:#25D366}.fab-wa::after{content:"WhatsApp us"}.fab-wa{animation:fabPulse 2.6s ease-out infinite}@media(max-width:600px){.fab::after, .fab::before{display:none}}.nav-cta{background:var(--neon);color:var(--ink);font-family:'Inter',sans-serif;font-weight:700;font-size:14px;letter-spacing:.01em;padding:10px 20px;border-radius:100px;transition:transform .15s,background .15s;box-shadow:0 4px 14px rgba(195,245,60,.35);border:0}.nav-cta:hover{background:#fff;transform:translateY(-1px)}@media(max-width:600px){.nav-cta{padding:8px 15px;font-size:13px}}
/* At 320px the header's three groups do not fit, and pages were failing two different
   ways by accident: where the label could wrap it did, giving a 52px-tall button under a
   36px one; where it could not, the nav rendered 348px wide inside a 320px viewport and
   the whole page scrolled sideways. nowrap makes the failure consistent, then the padding
   comes in to make it fit. The phone icon stays: on mobile it is the only tap-to-call in
   the header, and the fixed bottom bar is below the fold on first paint. */
.nav-cta{white-space:nowrap}
@media(max-width:359px){.nav{padding:14px 13px}.nav-cta{padding:7px 11px;font-size:12px}}@supports(padding:env(safe-area-inset-bottom)){.s4g-fab{bottom:calc(14px + env(safe-area-inset-bottom))}.s4g-chat-bubble{bottom:calc(16px + env(safe-area-inset-bottom))}}.mbar{display:none}@media(max-width:600px){.mbar{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:960;gap:8px;padding:10px 10px calc(10px + env(safe-area-inset-bottom));background:rgba(11,14,9,.9);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);border-top:1px solid rgba(195,245,60,.22);box-shadow:0 -10px 34px rgba(0,0,0,.5)}.mbar-btn{flex:1;display:flex;flex-direction:column;align-items:center;gap:5px;padding:9px 4px;border-radius:15px;background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.09);text-decoration:none;cursor:pointer;font-family:'Inter',sans-serif;transition:background .15s,transform .1s}.mbar-btn:active{background:rgba(255,255,255,.13);transform:scale(.97)}.mb-ic{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;box-shadow:0 4px 12px rgba(0,0,0,.35)}.mb-ic svg{width:19px;height:19px}.mbar-btn.call .mb-ic{background:var(--neon);color:var(--ink)}.mbar-btn.wa .mb-ic{background:#25D366;color:#fff}.mbar-btn.chat .mb-ic{background:#1f9d5c;color:#fff}.mb-l{font-family:'Inter',sans-serif;font-size:11.5px;font-weight:600;letter-spacing:.01em;color:#fff}.s4g-fab{display:none!important}.s4g-chat-bubble{display:none!important}.btn-lg{font-size:18px;padding:14px 26px;white-space:nowrap}.capture .btn{width:100%;justify-content:center}}.qm{position:fixed;inset:0;z-index:1200;display:flex;align-items:center;justify-content:center;padding:20px;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .28s ease,visibility 0s linear .28s}.qm.open{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .28s ease}.qm-bd{position:absolute;inset:0;background:rgba(6,8,5,.72);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}.qm-card{position:relative;width:100%;max-width:480px;background:#ffffff;border:1px solid rgba(0,0,0,.08);border-radius:22px;box-shadow:0 30px 80px rgba(0,0,0,.42);padding:38px 34px 30px;color:#0f1409;max-height:calc(100vh - 40px);overflow-y:auto;transform:translateY(18px) scale(.975);opacity:0;transition:transform .34s cubic-bezier(.22,.61,.36,1),opacity .3s ease;will-change:transform,opacity}.qm.open .qm-card{transform:none;opacity:1}@media(prefers-reduced-motion:reduce){.qm{transition:opacity .12s ease}.qm-card{transition:none}}.qm-x{position:absolute;top:16px;right:16px;width:34px;height:34px;border-radius:50%;background:rgba(0,0,0,.06);border:none;color:#0f1409;font-size:20px;line-height:1;cursor:pointer;transition:background .15s}.qm-x:hover{background:rgba(0,0,0,.12)}.qm-eye{font-family:'Inter',sans-serif;font-weight:700;font-size:12px;letter-spacing:.15em;text-transform:uppercase;color:#4e8a10}.qm-card h3{font-family:'Bebas Neue',sans-serif;text-transform:uppercase;font-size:clamp(30px,7vw,40px);line-height:.95;letter-spacing:.01em;margin:10px 0 12px;color:#0f1409}.qm-sub{font-size:15px;color:#5f6b52;line-height:1.55;margin-bottom:22px}.qm-in{width:100%;background:#f4f6ef;border:1.5px solid #dfe3d6;border-radius:12px;padding:15px 16px;font-size:16px;color:#0f1409;font-family:'Inter',sans-serif;margin-bottom:12px;transition:border-color .15s,box-shadow .15s}.qm-in::placeholder{color:#9aa48c}.qm-in:focus{outline:none;border-color:#9ccc2b;box-shadow:0 0 0 3px rgba(195,245,60,.28)}.qm-in.err{border-color:#ff5a5a}.qm .btn-lg{width:100%;justify-content:center;margin-top:6px}.qm-trust{text-align:center;font-size:12.5px;color:#6b7360;margin-top:16px}.qm-trust .st{color:#F5A623;letter-spacing:1px}.qm-tick{width:66px;height:66px;border-radius:50%;background:var(--neon);color:var(--ink);display:grid;place-items:center;font-size:34px;margin:0 auto 6px;font-weight:700}.qm-c{text-align:center}.qm-field{margin-bottom:14px;text-align:left}.qm-field>label{display:block;font-size:13px;font-weight:600;color:#3f473a;margin-bottom:8px}.qm-seg{display:grid;grid-template-columns:1fr 1fr;gap:10px}.qm-seg-btn{display:flex;align-items:center;justify-content:center;gap:8px;padding:13px 10px;border-radius:12px;background:#f4f6ef;border:1.5px solid #dfe3d6;color:#3f473a;font-family:'Inter',sans-serif;font-size:14px;font-weight:600;cursor:pointer;transition:all .15s}.qm-seg-btn svg{width:18px;height:18px;flex-shrink:0}.qm-seg-btn.on{background:#eef8d6;border-color:#9ccc2b;color:#0f1409}.qm-err{color:#ff7a7a;font-size:13px;text-align:center;margin-top:10px}.qm .iti{width:100%;display:block;margin-bottom:12px}.qm .iti input.qm-in{margin-bottom:0}.qm .iti__selected-flag{background:transparent;border-radius:12px 0 0 12px}.qm .iti--separate-dial-code .iti__selected-dial-code{color:#0f1409;font-family:'Inter',sans-serif}.qm .iti__arrow{border-top-color:#5f6b52}.qm .iti__country-list{background:#fff;color:#0f1409;border:1px solid #e0e4d8;box-shadow:0 12px 34px rgba(0,0,0,.22)}.qm .iti__country.iti__highlight{background:#f1f5e6}.qm .iti__country{color:#0f1409}.qm .iti__dial-code{color:#8a9280}.qm-fe{font-size:12px;color:#ff7a7a;margin:-8px 0 10px;display:none}.qm-fe.show{display:block}.nav .menu{background:none;border:none;cursor:pointer;font-family:'Inter',sans-serif;color:#fff;font-weight:600;font-size:15px;padding:6px 2px;display:inline-flex;align-items:center;gap:11px}.nav .menu:hover{color:var(--neon)}.mbars{position:relative;width:28px;height:15px;flex-shrink:0}.mbars i{position:absolute;left:0;height:3px;border-radius:3px;background:currentColor;transition:transform .32s cubic-bezier(.6,.2,.2,1),width .3s ease,top .3s ease,bottom .3s ease}.mbars i:nth-child(1){top:1px;width:28px}.mbars i:nth-child(2){bottom:1px;width:19px}body.menu-open .mbars i:nth-child(1){top:50%;transform:translateY(-50%) rotate(45deg);width:28px}body.menu-open .mbars i:nth-child(2){bottom:50%;transform:translateY(50%) rotate(-45deg);width:28px}body.menu-open .nav{background:#0b0f0a}@media(max-width:760px){.menu-word{display:none}.nav .menu{gap:0}}.sec-neon .btn, .sec[data-tone="neon"] .btn{background:var(--ink);color:#fff}.sec-neon .btn:hover, .sec[data-tone="neon"] .btn:hover{background:#000}@keyframes fabPulse{0%{box-shadow:0 8px 24px rgba(0,0,0,.22),0 0 0 0 rgba(37,211,102,.5)}70%{box-shadow:0 8px 24px rgba(0,0,0,.22),0 0 0 12px rgba(37,211,102,0)}100%{box-shadow:0 8px 24px rgba(0,0,0,.22),0 0 0 0 rgba(37,211,102,0)}}.footer a,.footer .f-address,.footer .f-contact-item,.footer .f-col ul li a,.footer .f-locations-grid a,.footer .f-legal-text,.footer .f-app-note{color:#fff}.footer .f-col ul li a:hover,.footer .f-locations-grid a:hover{color:var(--neon)}.footer .footer-locations h4,.footer .f-address-label,.footer .f-col-title,.footer h4{color:rgba(255,255,255,.7)}.footer .f-legal,.footer .f-trademark-note{color:rgba(255,255,255,.6)}
/* live mega-menu CSS (verbatim from home-v3-kk.html) */
.megamenu{position:fixed;inset:0;z-index:1000;overflow-y:auto;opacity:0;pointer-events:none;clip-path:inset(0 0 100% 0);
  background:radial-gradient(120% 80% at 82% 0%,rgba(195,245,60,.12),transparent 55%),#0b0f0a;
  padding:24px clamp(22px,5vw,66px) 40px;transition:opacity .34s ease,clip-path .44s cubic-bezier(.16,.84,.34,1)}.megamenu.open{opacity:1;pointer-events:auto;clip-path:inset(0 0 0 0)}@media(max-width:760px){.megamenu{padding-top:18px}.megamenu .mm-top{display:none}}@media(prefers-reduced-motion:reduce){.megamenu{transition:opacity .2s ease}.megamenu,.megamenu.open{clip-path:none}}.mm-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:clamp(26px,5vw,56px)}.mm-brand{font-family:'Bebas Neue';font-size:26px;letter-spacing:2px;color:var(--neon)}.mm-x{background:none;border:1px solid rgba(255,255,255,.22);color:#fff;width:44px;height:44px;border-radius:50%;
  font-size:24px;line-height:1;cursor:pointer;display:grid;place-items:center;transition:background .15s,transform .25s}.mm-x:hover{background:rgba(255,255,255,.1);transform:rotate(90deg)}.mm-body{position:relative;max-width:1080px;margin:0 auto;min-height:340px}.mm-cat{background:none;border:none;cursor:pointer;text-align:left;width:100%;text-decoration:none;
  font-family:'Bebas Neue','Oswald','Arial Narrow',sans-serif;text-transform:uppercase;letter-spacing:.02em;
  font-size:clamp(34px,5vw,58px);line-height:1.04;color:rgba(255,255,255,.5);padding:5px 0;
  display:flex;align-items:center;gap:14px;transition:color .15s}.mm-cat .plus{margin-left:auto;font-family:'Inter';font-size:24px;color:var(--neon);font-weight:400;transition:transform .3s ease}.mm-group.on .mm-cat,.mm-cat:hover{color:#fff}.mm-group.on .mm-cat{color:var(--neon)}.mm-sub{list-style:none;margin:0;padding:0}.mm-sub a{color:rgba(255,255,255,.82);text-decoration:none;font:600 clamp(17px,2vw,21px)/1 'Inter',sans-serif;
  padding:13px 0;border-bottom:1px solid rgba(255,255,255,.09);display:flex;align-items:center;justify-content:space-between;
  transition:color .15s,padding-left .15s}.mm-sub a::after{content:"\2192";opacity:0;color:var(--neon);transition:opacity .15s}.mm-sub a:hover{color:var(--neon);padding-left:8px}.mm-sub a:hover::after{opacity:1}.mm-foot{max-width:1080px;margin:clamp(30px,6vw,58px) auto 0;display:flex;flex-wrap:wrap;align-items:center;
  gap:16px 26px;border-top:1px solid rgba(255,255,255,.12);padding-top:26px}.mm-quote{background:var(--neon);color:var(--ink);font-family:'Bebas Neue';font-size:22px;letter-spacing:.03em;
  text-transform:uppercase;border:none;border-radius:100px;padding:13px 28px;cursor:pointer;display:inline-flex;gap:9px;align-items:center;transition:filter .15s}.mm-quote:hover{filter:brightness(1.06)}.mm-contact{display:flex;flex-wrap:wrap;gap:8px 20px;align-items:center;color:rgba(255,255,255,.7);font-size:14px}.mm-contact a{color:var(--neon);text-decoration:none;font-weight:700;display:inline-flex;gap:7px;align-items:center}.mm-trust{margin-left:auto;color:rgba(255,255,255,.5);font-size:13px}.mm-trust .stars{color:#C3F53C;letter-spacing:1px}@media(min-width:761px){.mm-group{width:34%}.mm-cat .plus{display:none}.mm-sub{position:absolute;top:2px;left:42%;width:58%;display:block;opacity:0;visibility:hidden;
    transform:translateY(12px);transition:opacity .32s ease,transform .32s cubic-bezier(.2,.7,.3,1),visibility .32s}.mm-group.on .mm-sub{opacity:1;visibility:visible;transform:none}.mm-sub a,.mm-sub .mm-desc{opacity:0;transform:translateY(6px);transition:opacity .3s ease,transform .3s ease}.mm-group.on .mm-sub a,.mm-group.on .mm-sub .mm-desc{opacity:1;transform:none}.mm-group.on .mm-sub a{transition-delay:.06s}}.mm-desc{color:rgba(255,255,255,.6);font:400 15px/1.5 'Inter',sans-serif;margin:0 0 14px;max-width:36ch}.mm-go{color:var(--neon)!important;font-weight:700;border-bottom:none!important}.mm-go::after{content:none!important}.mm-cols{column-count:2;column-gap:38px}.mm-cols a{break-inside:avoid}@media(max-width:760px){.mm-cols{column-count:1}}@media(max-width:760px){.mm-group{border-bottom:1px solid rgba(255,255,255,.12)}.mm-cat{font-size:30px;padding:16px 0}.mm-sub{max-height:0;overflow:hidden;padding:0;transition:max-height .42s cubic-bezier(.4,0,.2,1)}.mm-group.on .mm-cat .plus{transform:rotate(45deg)}.mm-trust{margin-left:0}}@media(prefers-reduced-motion:reduce){.megamenu,.mm-sub,.mm-x{transition:none;animation:none}}

/* header always dark (per Shishir) */
.nav{background:rgba(10,13,8,.92);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid rgba(255,255,255,.08)}

/* ===== KK shared page components (promoted from location pilot) ===== */

.press-marquee{overflow:hidden;-webkit-mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);margin-top:28px}
.press-marquee+.press-marquee{margin-top:20px}
.press-row{display:flex;align-items:center;gap:0;width:max-content}
.press-row.l{animation:pressL 36s linear infinite}
.press-row.r{animation:pressR 44s linear infinite}
.press-marquee:hover .press-row{animation-play-state:paused}
@keyframes pressL{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.press-row img{height:clamp(50px,5vw,66px);width:auto;filter:grayscale(100%);opacity:.62;flex-shrink:0}
.press-row a{display:inline-flex;flex-shrink:0}
.press-row>*{margin-right:64px}
@media(max-width:640px){.press-row img{height:60px}.press-row>*{margin-right:40px}.press-marquee{margin-top:20px}}
.faqband .in{max-width:1160px;margin:0 auto;padding:0 34px;display:grid;grid-template-columns:.8fr 1.2fr;gap:54px;align-items:start}
.faqband .fqhead{position:sticky;top:104px;align-self:start}
@media(max-width:820px){.faqband .fqhead{position:static}}
.faqband .fqhead .k{font-family:var(--disp);font-size:clamp(28px,3.4vw,40px);letter-spacing:.04em;color:var(--ink);margin-bottom:12px;line-height:.9}
.faqband .fqhead p{font-size:15px;color:var(--muted);line-height:1.55;max-width:30ch}
.faqsec .faq{margin-top:-4px}
.faqsec .faq details{border-bottom:1px solid #e0e3d8;padding:16px 0}
.faqsec .faq details:first-child{padding-top:0}
.faqsec .faq details:last-child{border-bottom:0}
.faqsec .faq summary{font-weight:700;font-size:17px;color:var(--ink);cursor:pointer;list-style:none;display:flex;justify-content:space-between;gap:12px;align-items:center}
.faqsec .faq summary::-webkit-details-marker{display:none}
.faqsec .faq summary::after{content:'+';color:var(--neon-txt);font-size:22px;line-height:1}
.faqsec .faq details[open] summary::after{content:'\2013'}
.faqsec .faq .faq-a{overflow:hidden}
.faqsec .faq p{font-size:16px;color:#40463a;margin:10px 0 0;line-height:1.65}

/* mobile: clear the fixed .mbar contact bar so the footer copyright is not clipped */
@media(max-width:600px){.footer{padding-bottom:calc(104px + env(safe-area-inset-bottom))}}

/* KK custom dropdown (.ksel) — reusable branded select */
.ksel{position:relative}
.ksel-btn{width:100%;display:flex;align-items:center;justify-content:space-between;gap:10px;font-family:'Inter';font-size:15px;font-weight:600;padding:13px 15px;border:1.5px solid var(--line);border-radius:11px;background:var(--paper);color:var(--ink);cursor:pointer;text-align:left}
.ksel-btn:hover{border-color:var(--neon-txt)}
.ksel.open .ksel-btn{border-color:var(--neon-txt);box-shadow:0 0 0 3px rgba(195,245,60,.35)}
.ksel-ch{width:12px;height:8px;color:var(--neon-txt);flex:none;transition:transform .2s}
.ksel.open .ksel-ch{transform:rotate(180deg)}
.ksel-list{position:absolute;top:calc(100% + 6px);left:0;right:0;z-index:30;background:#fff;border:1px solid var(--line);border-radius:12px;box-shadow:0 22px 46px -18px rgba(20,26,17,.45);padding:6px;max-height:268px;overflow:auto;display:none}
.ksel.open .ksel-list{display:block}
.ksel-list button{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;text-align:left;font-family:'Inter';font-size:14.5px;font-weight:500;color:var(--read,#22271e);padding:11px 12px;border:0;border-radius:8px;background:transparent;cursor:pointer}
.ksel-list button:hover{background:var(--sage)}
.ksel-list button.on{color:var(--neon-txt);font-weight:700;background:var(--sage)}
.ksel-list button.on::after{content:'\2713';color:var(--neon-txt);font-weight:700}

.ksel[data-value=""] .ksel-val{color:var(--muted)}
/* ===== Primary-CTA attention (opt-in) — add class="ctaAnim" to ONE primary button per page and wrap its arrow in <span class="ar">. Double-streak sheen (ambient) + arrow nudges on hover. Reduced-motion safe. ONE per view only. ===== */
.ctaAnim{position:relative;overflow:hidden}
.ctaAnim .ar{display:inline-block;transition:transform .22s ease}
.ctaAnim:hover .ar{transform:translateX(6px)}
.ctaAnim::after{content:'';position:absolute;top:0;left:-60%;width:30%;height:100%;background:linear-gradient(100deg,transparent,rgba(255,255,255,.7),transparent);transform:skewX(-18deg);animation:ctaSheen 3.6s ease-in-out infinite;pointer-events:none}
.ctaAnim::before{content:'';position:absolute;top:0;left:-60%;width:16%;height:100%;z-index:1;background:linear-gradient(100deg,transparent,rgba(255,255,255,.55),transparent);transform:skewX(-18deg);animation:ctaSheen 3.6s ease-in-out .28s infinite;pointer-events:none}
@keyframes ctaSheen{0%{left:-60%}55%{left:135%}100%{left:135%}}
@media(prefers-reduced-motion:reduce){.ctaAnim::after,.ctaAnim::before{animation:none}}.footer .f-legal-tm{font-size:11px;font-weight:300;line-height:1.6;color:rgba(255,255,255,.85);margin-top:8px;white-space:nowrap}@media(max-width:760px){.footer .f-legal-tm{white-space:normal}}

/* FAQ reveal + card hover, added 2026-08-14. Both reuse conventions already in the
   project rather than inventing new ones:
     card hover  copies .lib-card:hover exactly -- translateY(-3px), border-color neon,
                 .15s -- so cards behave the same wherever they appear
     FAQ         no page had a smooth <details> anywhere, including home. Native details
                 snaps open. Animating height needs a wrapper element inside .a, which
                 would mean editing 142 pages, so this fades and lifts the answer in
                 instead: no markup change, and the harsh jump goes. The +/- marker
                 rotates with it. */
.card{transition:transform .15s,border-color .15s}
.card:hover{transform:translateY(-3px);border-color:var(--neon)}
a.card:hover{text-decoration:none}
@keyframes faqReveal{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:none}}
.faq details[open] .a,.faq details[open] .faq-a{animation:faqReveal .24s ease both}
.faq summary::after{transition:transform .22s ease}
.faq details[open] summary::after{transform:rotate(180deg)}
@media(prefers-reduced-motion:reduce){
 .card,.card:hover{transition:none;transform:none}
 .faq details[open] .a,.faq details[open] .faq-a{animation:none}
 .faq summary::after{transition:none}}

/* ── .aa-img ─────────────────────────────────────────────────────────────────
   Image wrapper for a card or an .ib grid column. Copied VERBATIM from
   kk-theme.css so the class name means exactly one thing on this site. The two
   sheets are never loaded together (checked: no page loads both), so this is a
   second copy rather than a cascade conflict — but keep them identical. The
   .imgband name already drifted into two different components across these two
   sheets and it is one copy-paste away from causing damage.
   Added 2026-08-15: solar-pv-system used .aa-img and neither its stylesheet nor
   its inline CSS defined it, so the image rendered raw at 1200px and broke the
   grid. Same class of bug as .ksel, .grid, .ic, .ib. */
.aa-img{aspect-ratio:16/10;overflow:hidden;background:var(--sage);border-radius:12px;margin-bottom:14px}
.aa-img.wide{aspect-ratio:1200/630}
.aa-img img{width:100%;height:100%;object-fit:cover;transition:transform .35s ease}
.card:hover .aa-img img,.aa-card:hover .aa-img img{transform:scale(1.05)}

/* ── .midcta.onimg ───────────────────────────────────────────────────────────
   Full-bleed photographic variant of the mid-page CTA: the copy sits ON the
   image instead of stacked above it. Lives here, in the sheet all three sibling
   pages already load, rather than inline — .midcta is currently inlined
   SEPARATELY into solar-pv-system, solar-inverter and solar-ev-chargers-uk and
   the three copies have already drifted into two variants. The other two pages
   opt in by adding the class; nothing about their present appearance changes.
   The gradient is a scrim, not decoration: it is what keeps the heading legible
   over a photograph whose brightness we do not control per viewport. */
.midcta.onimg{position:relative;overflow:hidden;background:#0c120b;padding:0}
/* The band has to be tall enough for the photograph to be a photograph. At the first
   attempt it was 292px, which showed a 36% horizontal slice of the image under a heavy
   scrim, and the picture simply disappeared — it read as a flat dark bar. */
.midcta.onimg>.lwrap{position:relative;z-index:2;padding-top:clamp(74px,9.5vw,142px);padding-bottom:clamp(74px,9.5vw,142px)}
.midcta-media{position:absolute;inset:0;z-index:0}
/* Focal point is a property of the IMAGE, not of the component: the survey photo puts
   its subject high in frame, the inverter-assessment one puts the hands low. Each page
   sets --focal on the <img> rather than overriding the shared rule and forking it. */
.midcta-media img{width:100%;height:100%;object-fit:cover;object-position:50% var(--focal,38%);display:block}
/* Scrim: heavy enough to hold white text at AA over an unpredictable photograph, light
   enough that the right-hand third still reads as a picture. The first values (.90 → .16)
   were tuned by eye against a bright test image and killed a flat overcast one. */
.midcta.onimg::after{content:'';position:absolute;inset:0;z-index:1;background:linear-gradient(90deg,rgba(6,9,5,.88) 0%,rgba(6,9,5,.70) 30%,rgba(6,9,5,.34) 58%,rgba(6,9,5,.10) 100%)}
.midcta.onimg .midcta-h{color:#fff}
.midcta.onimg .midcta-p{color:rgba(255,255,255,.86)}
/* Below 700px .midcta-in already stacks to a column, so the copy occupies the
   full width and a left-weighted scrim no longer covers it. Go vertical. */
@media(max-width:700px){
 .midcta.onimg::after{background:linear-gradient(180deg,rgba(6,9,5,.72) 0%,rgba(6,9,5,.86) 62%,rgba(6,9,5,.92) 100%)}
 .midcta-media img{object-position:50% var(--focal-m,var(--focal,34%))}}

/* ── .locp.full ──────────────────────────────────────────────────────────────
   Body copy is clamped to 62ch for readability, which is right for prose and
   wrong for a lead-in sitting directly above or below a full-width table or
   stat row: the paragraph stops two thirds of the way across and the block
   reads as broken alignment rather than as a measure.
   Added 2026-08-15. class="locp full" was ALREADY in the markup in 12 places
   across solar-inverter, solar-ev-chargers-uk and solar-pv-system, and .full
   was defined nowhere in the project, so every one of them was silently still
   clamped. check_component_css.py does not catch this by design — it reports a
   component styled elsewhere but not here, and .full was styled nowhere at all. */
.locp.full{max-width:none}
/* .lede.full - a section intro that spans the grid it introduces. Note the font-size:
   .lede is 19px capped at 60ch (~634px, ~70 characters per line, which is right).
   Removing the cap alone would stretch the SAME 19px across 1092px and give ~126
   characters per line - roughly double the readable maximum, measured on this page.
   Wide intros work by being LARGER, not just wider, so the measure stays sane. */
.mfgsec .lede.full{max-width:none;font-size:clamp(20px,1.75vw,24px);line-height:1.55}
/* ...except above a .rtable-wrap, which caps ITSELF at 940px and centres. Letting the
   lede run to the full 1160 there would create the same mismatch in reverse - the
   intro overhanging the table it introduces. Match the block instead of the container.
   :has() is the right tool: the correct width depends on what follows, which no class
   on the paragraph can know. Browsers without :has() get the full-width version, which
   is a small overhang rather than a break. */
.mfgsec .lede.full:has(+ .rtable-wrap){max-width:940px;margin-left:auto;margin-right:auto}
/* A one-line note under a full-width table reads as a caption, so centre it. */
.rtable-wrap+p{text-align:center;max-width:none;margin-top:18px}

/* ── .restsplit ──────────────────────────────────────────────────────────────
   Two parallel lists side by side instead of stacked. The planning section on
   sector-logistics ran to 826px as one column: a huge heading, a five-item list,
   a subheading, a four-item list, a closing line and a button, all left-aligned
   with the right half of the band empty. The two lists are parallel content, so
   they belong beside each other; the closing line and CTA stay full width below. */
.restsplit{display:grid;grid-template-columns:1fr 1fr;gap:44px;align-items:start;margin-top:22px}
.restsplit>*{min-width:0}
/* An <h3>, not a <div>. The first version of this split turned the subheading into a
   div and check_heading_reuse caught it: sector-logistics dropped from 17%% to 14%%
   heading overlap with the page it replaces. A layout change should not quietly
   delete a heading. */
.restsplit .restsplit-h{font-family:var(--disp);font-weight:400;font-size:25px;letter-spacing:.4px;margin:0 0 10px}
.restsplit ul.uselist{margin-top:0}
.restsec .restsplit+p{margin-top:26px}
@media(max-width:860px){.restsplit{grid-template-columns:1fr;gap:26px}}

/* ── .slinks ─────────────────────────────────────────────────────────────────
   "Where to go next" - the related-pages block at the foot of 18 pages. Moved
   here from a per-page <style> block in the BODY of each of those 18 files. All
   18 copies were byte-identical, so this is a lift-and-shift, not a merge.
   (Worth knowing for next time: those body blocks are why a head-only search
   reports .slinks as undefined. It is not.)
   Redesigned at the same time because it read as a footer afterthought: a 26px
   heading and four 36px pills in a 244px strip. Same markup, no HTML change
   beyond deleting the old <style> - the links become real cards in a grid, and
   the hub link takes the lead. Hover matches .card elsewhere on the site. */
.slinks{background:#fff;border-top:1px solid var(--line,#e3e7dc);padding:clamp(54px,6vw,86px) 0}
.slinks .in{max-width:1160px;margin:0 auto;padding:0 34px}
.slinks h3{font-family:'Bebas Neue';font-size:clamp(30px,3.4vw,42px);letter-spacing:.5px;line-height:1.03;margin:0 0 10px}
.slinks p{color:#5a655d;font-size:15.5px;line-height:1.6;margin:0 0 26px;max-width:70ch}
/* Every one of the 18 blocks has exactly 4 links, one of them the hub - counted,
   not assumed - so an explicit layout beats auto-fit. auto-fit gave 4 columns with
   the hub spanning 2, which left the fourth card stranded alone on a second row. */
.slinks .row{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
/* Cards carry the destination page's own hero as a thumbnail, so "Warehouses" is a
   picture of a warehouse roof rather than a word in a box. Thumbnails are 640x400
   derivatives in dist/img/next/, not the heroes themselves - the commercial hub's
   hero alone is 2.2MB, and four of those at the foot of every page would be absurd.
   13 thumbnails, 13-37KB each, ~100KB per page, all lazy. */
.slinks .row a{display:flex;flex-direction:column;align-items:stretch;padding:0;overflow:hidden;
  border-radius:14px;border:1px solid var(--line,#e3e7dc);background:#fbfcf8;color:#25332a;
  font-weight:600;font-size:16px;line-height:1.3;text-decoration:none;
  transition:transform .15s,border-color .15s,background .15s}
.slinks .row a:hover{transform:translateY(-3px);border-color:var(--neon-d,#7fae00);background:#fff}
.slinks .sl-th{display:block;aspect-ratio:16/10;overflow:hidden;background:var(--sage,#F0F9E5)}
.slinks .sl-th img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .35s ease}
.slinks .row a:hover .sl-th img{transform:scale(1.05)}
/* A label alone made the cards read as a link list with pictures stuck on, and left
   the wide dark hub card looking empty. Each carries a one-line description of what
   is actually on the far side. */
.slinks .sl-t{display:block;padding:15px 18px}
.slinks .sl-n{display:block}
.slinks .sl-d{display:block;margin-top:6px;font-weight:400;font-size:13.5px;line-height:1.5;color:#5a655d}
.slinks .row a.hub .sl-d{color:rgba(255,255,255,.72);font-size:15px;margin-top:8px}
/* No measure cap on the hub description: capped at 62ch it wrapped to two short
   lines and left the right 40% of a very wide dark card empty, which is what made
   it look unfinished. Uncapped it runs to one line across the card. */
/* The hub is the parent page, so it leads: full first row, and horizontal rather than
   stacked so a wide card does not become a wide photograph. */
.slinks .row a.hub{grid-column:1/-1;display:grid;grid-template-columns:290px 1fr;align-items:stretch;
  background:var(--ink,#0a0d08);color:#fff;border-color:var(--ink,#0a0d08)}
.slinks .row a.hub:hover{background:#141a11;border-color:var(--neon,#C3F53C)}
.slinks .row a.hub .sl-th{aspect-ratio:auto;min-height:132px}
.slinks .row a.hub .sl-t{align-self:center;padding:24px 30px;font-size:20px}
@media(max-width:820px){.slinks .in{padding:0 22px}
 .slinks .row{grid-template-columns:1fr}
 .slinks .row a.hub{grid-column:auto;grid-template-columns:1fr;font-size:17px}
 .slinks .row a.hub .sl-th{aspect-ratio:16/10;min-height:0}
 .slinks .row a.hub .sl-t{padding:15px 18px;font-size:17px}}
@media(prefers-reduced-motion:reduce){
 .slinks .row a,.slinks .row a:hover,.slinks .sl-th img,.slinks .row a:hover .sl-th img{transition:none;transform:none}}

/* ── .cta.onimg ──────────────────────────────────────────────────────────────
   Photographic variant of the big end-of-page CTA, the sibling of .midcta.onimg.
   The difference that matters: .cta .in is CENTRED (max-width:840px, margin auto,
   text-align:center), so the copy sits across the middle of the frame and the
   left-to-right scrim used by .midcta.onimg would leave the headline half-lit.
   This one uses an even wash plus a soft vignette, so the picture survives at the
   edges while the middle stays dark enough to hold white text at any viewport.
   .cta is inlined into 68 pages and already carries position:relative and
   overflow:hidden, so any of them can opt in by adding the class and one <img>. */
.cta.onimg{background:#0a0d08}
/* The scrim CANNOT live on .cta::after. That pseudo-element is already taken: the page's
   own CSS uses it for a decorative 320x320 hatched corner (and ::before for another
   pattern). A higher-specificity .cta.onimg::after still inherited the 320px width and
   height, so the scrim rendered as a square in the top-right instead of covering the
   band - and it cost a red-paint test to find, because getComputedStyle happily reported
   the right background all along. The scrim gets its own element. */
.cta.onimg::before,.cta.onimg::after{content:none}
.cta.onimg>.cta-media{position:absolute;inset:0;z-index:0}
.cta.onimg>.cta-media img{width:100%;height:100%;object-fit:cover;object-position:50% var(--focal,50%);display:block}
/* Scrim shape is driven by MEASUREMENT, not taste: over this dusk photograph the bright
   sky sits behind the eyebrow and headline while dark ground sits behind the paragraph,
   so an even wash leaves the top failing contrast. Vertical and top-heavy, with a radial
   vignette under it. Re-measure whenever a new photograph goes in; 4.5:1 vs white. */
.cta.onimg>.cta-media::after{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(6,9,5,.54) 0%,rgba(6,9,5,.50) 42%,rgba(6,9,5,.34) 74%,rgba(6,9,5,.48) 100%),
             radial-gradient(96% 130% at 50% 46%,rgba(6,9,5,0),rgba(6,9,5,.14) 70%,rgba(6,9,5,.30))}
@media(max-width:700px){
 .cta.onimg>.cta-media::after{background:linear-gradient(180deg,rgba(6,9,5,.84),rgba(6,9,5,.93))}
 .cta.onimg>.cta-media img{object-position:50% var(--focal-m,var(--focal,50%))}}


/* ── .nextc thumbnails ───────────────────────────────────────────────────────
   The second "Where to go next" component. Four pages use .nextc instead of
   .slinks, and it is the RICHER of the two - eyebrow, title, description and a
   per-card CTA already - it simply had no imagery. Same thumbnails, same
   dist/img/next/ set, so nothing new is generated except the one target these
   pages reach that the .slinks pages do not.
   The thumb bleeds out with negative margins because .nextc carries its padding
   on the card itself; restructuring the markup to a padded inner would have
   touched every card on four pages for no gain.
   Two components doing one job is worth converging eventually - flagged, not
   done here, because .nextc is the better of the two and merging is a rewrite
   of the 18 .slinks blocks rather than a CSS change. */
.nextc{overflow:hidden;transition:transform .15s,border-color .15s,box-shadow .15s}
.nextc .nx-th{display:block;margin:-22px -24px 14px;aspect-ratio:16/10;overflow:hidden;
  border-radius:15px 15px 0 0;background:var(--sage,#F0F9E5)}
.nextc .nx-th img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .35s ease}
.nextc:hover .nx-th img{transform:scale(1.05)}
@media(prefers-reduced-motion:reduce){
 .nextc,.nextc:hover,.nextc .nx-th img,.nextc:hover .nx-th img{transition:none;transform:none}}

/* Two share bars where there was one. The single bar mixed panel brands with inverter
   and battery brands on one 100% denominator, so "Fox ESS 69%" was comparing brands
   that do not compete: every install has both a panel and an inverter. Flagged in
   Steve Liu's local pages spec 2026-08-15 and confirmed - the five segments summed to
   exactly 100.00% and 176/254 gave precisely the 69.29% the bar drew.
   The second bar needs air under the first one's basis line, or the two charts read
   as one. */
.fitcol .fitbasis+.barcol-h{margin-top:26px;padding-top:22px;border-top:1px solid var(--line,#e3e7dc)}

/* Review-count link. The 4.9 / 1,000+ claim has to be traceable, so "1,000+ reviews"
   links to /reviews, where all four platforms are listed with their own scores. It
   inherits its colour deliberately: these sit inside trust strips and a default blue
   link would read as a stray element on 153 pages. The underline is the whole
   affordance. */
.revlink{color:inherit;text-decoration:underline;text-underline-offset:.18em;
  text-decoration-thickness:1px;text-decoration-color:currentColor;opacity:.94}
.revlink:hover,.revlink:focus-visible{opacity:1;text-decoration-thickness:2px}
/* On a .disp heading the font is ~76px, and text-underline-offset:auto puts the rule
   ~16px below the baseline - far enough that on a two-line heading it floats between
   the lines and reads as a stray rule cutting through the second one. Hug the text
   instead, and scale with the type so it holds at every heading size. Small-text
   .revlink instances (hero rate, ticker) keep the browser default, which is correct
   there. */
.disp .revlink{text-underline-offset:.07em;text-decoration-thickness:.042em}
.disp .revlink:hover,.disp .revlink:focus-visible{text-decoration-thickness:.06em}


/* Related-stories card thumbnail. The .im slot shipped as a gradient plus a letter
   watermark on all 28 case studies; the photograph goes underneath the watermark,
   which is absolutely positioned, so both read. */
.relc .im img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;opacity:.92;transition:transform .3s ease}
.relc:hover .im img{transform:scale(1.05)}
.relc .im .wm,.relc .im .cat,.relc .im .chip{z-index:1}

/* LIVE CHAT, HIDDEN NOT DELETED. 26 Aug 2026. The button was visible on every mobile
   page and did nothing: it toggles #s4gChat, which no page renders, so tapping it threw
   "Cannot read properties of null". The markup and s4gChatToggle() are left in place so
   the button returns the day a chat service exists behind it (see
   docs/specs/smart-ai-chat-spec.md). .mbar is flex with flex:1 children, so the two
   remaining buttons expand to fill and no gap is left. */
.mbar-btn.chat{display:none}

/* WCAG 2.2.2, see the matching block in kk-theme.css: this file carries two of the
   six marquee tracks, so it needs the same reduced-motion freeze. */
@media(prefers-reduced-motion:reduce){
 .brand-track,.case-track,.vstrip-track,.cert-track,.press-row,.review-track{
   animation:none!important}

 /* Frozen at frame 0, two things that are harmless while scrolling become permanent:
    the edge fade dims whatever sits at the first and last position (the Tesla logo,
    first in the row and first named in the copy, rendered almost invisible), and
    overflow:hidden puts everything past the first screenful out of reach for good.
    Swap the fade for a real scroller so reduced motion costs no content. */
 .brand-marquee,.case-marquee,.vstrip-marquee,.cert-marquee,.press-marquee{
   -webkit-mask:none!important;mask:none!important;
   overflow-x:auto!important;overflow-y:hidden!important}
 .review-scroll{-webkit-mask:none!important;mask:none!important;overflow-y:auto!important}
}

/* Tap targets, 17 Sep 2026, from the responsive audit. WCAG 2.5.8 (AA) wants 24x24 CSS px
   and every one of these was under it, worst the header phone link at 19x19 once its text
   label is hidden below 820px.

   TWO TECHNIQUES, ON PURPOSE. In the nav the layout must not move, so the hit area is grown
   with an ABSOLUTELY POSITIONED PSEUDO-ELEMENT: it is out of flow, so the flex row is
   untouched, and it still counts as part of the link for hit testing. The first attempt used
   padding with an equal negative margin, which reads as layout-neutral and is not: under
   justify-content:space-between the nav visibly shifted, caught by a pixel diff.

   In the footer, padding IS right: those links genuinely are too cramped, so growing them is
   the fix rather than a side effect, and the list gaps are reduced by what the padding adds
   so the rhythm barely changes. Pseudo-elements would be wrong there because at a 25px pitch
   two 24px hit areas would overlap and you would tap the wrong link. */
.nav a.ph,.nav .menu,.mm-contact a{position:relative}
.nav a.ph::after,.nav .menu::after,.mm-contact a::after{content:"";position:absolute;
  top:50%;left:50%;transform:translate(-50%,-50%);
  width:max(100%,44px);height:max(100%,44px)}
.f-contact-item{padding:4px 0}
.f-col ul li a,.f-locations-grid a{display:inline-block;padding:4px 0}
.f-col ul{gap:1px}
.f-locations-grid{gap:2px 20px}

/* FAQ question layout. The page CSS makes <summary> a flex row with
   justify-content:space-between, and in a flex container EVERY text node becomes
   its own item - so "What does Solar4Good's", the <span data-fig> score and
   "score actually mean?" were spread into three columns, plus the + marker as a
   fourth. Any question containing an inline element breaks the same way, so this
   fixes the class, not the one question.
   Block layout lets the text flow; the + is positioned instead of flexed.
   There are THREE FAQ implementations - .locfaq (93 pages), .faqsec .faq (65) and
   .tri (1) - so all three are named here. Fixing only the first missed the very
   page the defect was reported on.
   body prefix so it beats the page inline rules, which have equal specificity and
   come later in source order. */
body .locfaq summary,body .faqsec .faq summary,body .tri summary{display:block;position:relative;padding-right:48px}
body .locfaq summary::after,body .faqsec .faq summary::after,body .tri summary::after{position:absolute;right:22px;top:50%;transform:translateY(-50%);line-height:1}

/* Tap targets. WCAG 2.2 AA (2.5.8) asks for 24x24 CSS px. Measured on a phone,
   exactly THREE controls failed it, all in the header: the phone icon at 19x19
   and the breadcrumb links at 14px tall. The footer links people worried about
   are 24px and already pass, so they are left alone rather than padded out and
   made to look loose. The phone icon gets 44x44 because it is an icon-only
   control with no text to aim at. */
/* FIXED 26 Sep. This was unconditional while .nav a.ph span{display:none} sits inside
   @media(max-width:820px). So at 820px and up the box was 44px wide with the number
   still visible, and "0800 999 1454" wrapped to FOUR lines and spilled out of the
   header over the hero - on every page using this sheet. The 44x44 tap target belongs
   with the icon-only state, so it moves under the same breakpoint; above it the base
   .ph inline-flex lays the icon and number out on one line, as the homepage already
   does, and min-height keeps the target honest for a mouse. */
.nav a.ph{min-height:44px;display:inline-flex;align-items:center;gap:8px}
@media(max-width:820px){.nav a.ph{width:44px;height:44px;display:grid;place-items:center}}
.crumbs a,.crumbs span{display:inline-block;padding:5px 0}

/* Sticky quote CTA (Mitesh, 26 Sep): once past the hero, anyone who does not want to
   read can go straight to a quote. It joins the existing .s4g-fab rail rather than
   inventing a second floating thing, and it is a labelled pill, not another icon,
   because the whole point is that it reads as the quote button at a glance.
   Selector is .s4g-fab .fab-quote so it beats the plain .fab width rules that appear
   later in this file inside media queries. */
.s4g-fab .fab-quote{width:auto;height:52px;padding:0 20px;border-radius:999px;background:var(--neon);color:var(--ink);font-weight:800;font-size:14px;letter-spacing:.02em;white-space:nowrap;opacity:0;pointer-events:none;transform:translateY(6px);transition:opacity .18s ease,transform .18s ease}
.s4g-fab .fab-quote.show{opacity:1;pointer-events:auto;transform:none}
.s4g-fab .fab-quote::after{display:none}
@media (max-width:480px){.s4g-fab .fab-quote{height:46px;padding:0 15px;font-size:13px}}
@media (prefers-reduced-motion:reduce){.s4g-fab .fab-quote{transition:none}}

/* Mobile has no .s4g-fab rail (it is display:none under 600px), so Mitesh's "go
   straight to a quote" button joins the .mbar instead of floating over content.
   Four buttons at 390px leaves ~86px each, which fits the 11.5px label. */
.mbar-btn.quote .mb-ic{background:var(--neon);color:var(--ink)}
.mbar-btn.quote{font-family:'Inter',sans-serif}

/* Two mobile defects found by qa_layout_defects.mjs, both of which scroll the WHOLE
   page sideways at 390px - the worst kind, because every section then looks broken.
   1. the author-card avatar had no width constraint and rendered at its intrinsic
      600px inside a 390px screen (solar4good-recognised-by-fmb was 418px, the
      renewable-energy guide 600px).
   2. a raw https:// URL pasted into body copy is one unbreakable word.
   Fixed generically rather than per page, so the next post that does either is safe. */
.author .av img,.acard .av img{max-width:100%;height:auto;display:block}
/* The blog body is article.article, not .post-body - the first selector missed it
   and the page still scrolled sideways. Anchors need it explicitly: a bare URL is
   one unbreakable word and inherits nothing useful from the paragraph. */
.article p,.article li,.article a,.article td,
.post-body p,.post-body li,.post-body a,.locp,.letter p{overflow-wrap:break-word;word-break:break-word}

/* Video lightbox. reviews.html loads kk-chrome.css ONLY, and these rules lived in
   kk-theme.css, so the lightbox markup added on 26 Sep to fix the dead videos would
   have rendered completely unstyled there. Same three-stylesheet trap as always:
   patching one sheet does nothing on pages that load another. Keep these identical. */
.vlb{position:fixed;inset:0;z-index:1300;display:none;align-items:center;justify-content:center;padding:24px}
.vlb.open{display:flex}
.vlb-bd{position:absolute;inset:0;background:rgba(4,6,3,.9);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.vlb-frame{position:relative;width:100%;max-width:980px}
.vlb-embed{position:relative;width:100%;aspect-ratio:16/9;background:#000;border-radius:16px;overflow:hidden;box-shadow:0 30px 90px rgba(0,0,0,.65)}
.vlb-embed iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.vlb-x{position:absolute;top:-48px;right:0;width:40px;height:40px;border-radius:50%;background:rgba(255,255,255,.14);border:none;color:#fff;font-size:22px;line-height:1;cursor:pointer;transition:background .15s}
.vlb-x:hover{background:rgba(255,255,255,.26)}
.vlb{padding:16px}
.vlb-x{top:-42px}

/* CASE-STUDY PROJECT FILM. A click-through card, never an inline embed. The site already
   links out to YouTube everywhere else, it keeps a case study light, and it means no
   third-party cookie is set before the visitor has chosen to watch -- which matters while
   the consent banner is unresolved. Lives here, not in kk-theme.css, because case studies
   load kk-chrome.css; the home page's .vfeature/.vsmall set is kk-theme-only and would
   render as unstyled markup here. */
.csvideo{background:var(--cream);padding:clamp(48px,6vw,88px) 0}
.csvideo .w{max-width:1000px}
.csvid-card{position:relative;display:block;border-radius:18px;overflow:hidden;background:var(--ink);margin-top:18px;aspect-ratio:16/9}
.csvid-card img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .5s ease}
.csvid-card:hover img,.csvid-card:focus-visible img{transform:scale(1.03)}
.csvid-card::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(10,13,8,.10) 0%,rgba(10,13,8,.18) 55%,rgba(10,13,8,.62) 100%)}
.csvid-play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:2;width:72px;height:72px;border-radius:50%;background:var(--neon);display:flex;align-items:center;justify-content:center;box-shadow:0 12px 34px rgba(10,13,8,.38);transition:transform .25s ease}
.csvid-card:hover .csvid-play{transform:translate(-50%,-50%) scale(1.08)}
.csvid-cap{position:absolute;left:clamp(16px,3vw,26px);bottom:clamp(14px,2.4vw,22px);z-index:2;color:#fff}
.csvid-cap b{display:block;font-size:clamp(16px,2.1vw,21px);line-height:1.25}
.csvid-cap span{display:block;font-size:13px;opacity:.82;margin-top:3px}
@media (prefers-reduced-motion:reduce){.csvid-card img,.csvid-play{transition:none}.csvid-card:hover img{transform:none}}
