/* ==========================================================================
   Climate Shield London: the design system.

   This file replaces main.css and extra.css. It exists because the first build
   accumulated nine blues, an amber, a yellow, a green and a red with no rule
   about which one meant what, and the result read as generated rather than
   designed. Everything below is locked.

   THE FOUR LOCKS
   1. THEME.    Graphite ink and warm paper, used as a fixed rhythm: dark hero,
                light reading sections, dark call to action, dark footer. A
                section never invents its own mode.
   2. COLOUR.   Two accents and each has one job.

                ICE (#63BCE6). Action AND brand. A light sky blue used as a
                FILL WITH DARK TEXT, which is the whole trick: at 8.2:1 against
                the ink it is more readable than any dark blue button with white
                text, it separates cleanly from white, and nobody else in this
                trade does it. Deeper members of the same ramp carry links
                (#166B99 on paper) and highlights (#8FD1F0 on ink).

                WARM (#E1562B). A TINT ONLY, never a fill under text. It marks
                heating and hot water on the heat pump, solar and battery
                cards. It is not a button and must never become one.

                What is gone: the orange buttons and the sea green, both of
                which David rejected. What stays gone: the nine competing blues
                of the first build. One ramp, stated once.

                WhatsApp green belongs to WhatsApp and appears nowhere else.
   3. SHAPE.    Pill for anything interactive. 20px for panels and cards. 12px
                for inputs. No other radius exists.
   4. TYPE.     Bricolage Grotesque for display, Lexend for everything else.
                One scale, defined once, used everywhere.

   HOUSE RULES STILL IN FORCE
   No eyebrow labels above headings. No em-dashes. No decorative dots. No
   scroll cues. No stock photography. The static, no-motion view must look
   finished, because that is the view David sees.
   ========================================================================== */

@font-face{font-family:"Bricolage Grotesque";src:url(../fonts/bricolage-var.woff2)format("woff2");font-weight:600 800;font-display:swap}
@font-face{font-family:Lexend;src:url(../fonts/lexend-400.woff2)format("woff2");font-weight:400;font-display:swap}
@font-face{font-family:Lexend;src:url(../fonts/lexend-500.woff2)format("woff2");font-weight:500;font-display:swap}
@font-face{font-family:Lexend;src:url(../fonts/lexend-600.woff2)format("woff2");font-weight:600;font-display:swap}
@font-face{font-family:Lexend;src:url(../fonts/lexend-700.woff2)format("woff2");font-weight:700;font-display:swap}

:root{
  color-scheme:only light;

  /* ---- ink. Slate with a blue cast now, on David's call: the green tint in
         the dark blocks read as green and he wanted it gone. Still not navy,
         which is the colour every other installer uses, and still not black.
         Each step is a real step: these are the five dark surfaces, and a
         section picking one of them is choosing a depth. ---- */
  --ink-950:#0A1119;
  --ink-900:#0F1A24;
  --ink-850:#142333;
  --ink-800:#1A2D40;
  --ink-700:#243D55;
  --ink-600:#33536F;

  /* ---- paper. Warm. A cool grey page is what made the old build feel
         machine made, and it costs nothing to warm it. ---- */
  --paper:#FFFFFF;
  --paper-50:#F7F9FB;
  --paper-100:#EDF2F6;
  --paper-200:#DDE6ED;

  /* ---- ice. The brand and the action. Light fills carry dark text. ---- */
  --ice-900:#0B3A52;
  --ice-800:#11536F;
  --ice-700:#166B99;
  --ice-600:#1E86BC;
  --ice-500:#3AA3D8;
  --ice-400:#63BCE6;
  --ice-300:#8FD1F0;
  --ice-200:#B3DFF5;
  --ice-100:#D5EDFA;
  --ice-50:#EFF8FD;

  /* ---- warm. A tint, never a fill under text. Heating and hot water. ---- */
  --warm:#E1562B;
  --warm-300:#F7A484;
  --warm-100:#FBDDD1;
  --warm-50:#FDF1EB;
  --warm-ink:#8F2F13;

  /* ---- status. Used in verdicts and tables, not as decoration. ---- */
  /* Positive verdicts were green. David: no green anywhere except WhatsApp.
     Every place this is used pairs it with a word or a tick, so the colour is
     not carrying the meaning on its own and a blue reads as "yes" perfectly
     well. --stop stays red, because red is the one signal colour that has no
     substitute. */
  --ok:#166B99;
  --ok-50:#E7F1F8;
  --stop:#C93B3B;
  --hold:#A9701A;

  /* ---- text ---- */
  --ink:#111A22;
  --ink-2:#4B5C68;
  --ink-3:#65757F;
  --on-dark:#E7EEF4;
  --on-dark-2:#AFC0CD;
  --on-dark-3:#7A8D9C;

  /* ---- lines ---- */
  --line:#E2E7EB;
  --line-2:#C7D2DA;
  --line-dark:rgba(216,232,244,.14);
  --line-dark-2:rgba(216,232,244,.26);

  /* ---- type ---- */
  --display:"Bricolage Grotesque",Lexend,system-ui,sans-serif;
  --font:Lexend,ui-sans-serif,system-ui,"Segoe UI",Roboto,Arial,sans-serif;

  /* ---- shape. Three values. There is no fourth. ---- */
  --r-pill:999px;
  --r-panel:20px;
  --r-input:12px;

  /* ---- elevation. Tinted to the ground, never black. ---- */
  --sh-sm:0 6px 18px -10px rgba(17,26,34,.20);
  --sh:0 20px 50px -22px rgba(17,26,34,.28);
  --sh-lg:0 34px 80px -30px rgba(17,26,34,.38);
  --sh-accent:0 18px 42px -18px rgba(30,134,188,.45);

  /* ---- rhythm ---- */
  --pad:clamp(18px,4.5vw,52px);
  --gap:clamp(24px,3.4vw,48px);
  --band:clamp(60px,7.5vw,116px);
  --measure:68ch;
  --nav-h:68px;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:calc(var(--nav-h) + 28px)}
#survey{scroll-margin-top:calc(var(--nav-h) + 22px)}
body{margin:0;background:var(--paper);color:var(--ink);
  font:400 clamp(15.5px,.42vw + 14.4px,17px)/1.62 var(--font);
  -webkit-font-smoothing:antialiased;overflow-x:hidden}
img{max-width:100%;height:auto;display:block}
a{color:inherit}
h1,h2,h3,h4{margin:0;font-family:var(--display);font-weight:800;
  letter-spacing:-.03em;line-height:1.06;text-wrap:balance}
p{margin:0;text-wrap:pretty}
ul,ol{margin:0;padding:0}
table{border-collapse:collapse}
.num,.dtable td,.dtable th,.stat-n,.job dd{font-variant-numeric:tabular-nums lining-nums}

:where(a,button,input,select,summary,[tabindex]):focus-visible{
  outline:3px solid var(--ice-500);outline-offset:3px;border-radius:8px}
.skip{position:absolute;left:-9999px}
.skip:focus{left:12px;top:12px;z-index:200;background:var(--ink-900);color:#fff;
  padding:12px 18px;border-radius:var(--r-pill)}

.wrap{width:min(1240px,100% - var(--pad)*2);margin-inline:auto}
.band{padding-block:var(--band)}
/* Two light grounds and two dark ones. There was a third light one, a visible
   ice blue, and David killed it: a whole section washed in a pale blue reads as
   a coloured box rather than as a page, and it fought the blue that the buttons
   and links are already carrying. Blue on this site is for things you press and
   things you read, not for the paper behind them. */
.band--tint{background:var(--paper-50)}
.band--edge{background:var(--paper-50);border-block:1px solid var(--line)}
.band--dark{background:var(--ink-900);color:var(--on-dark)}
.band--dark h2,.band--dark h3{color:#fff}

h1{font-size:clamp(36px,5.4vw,68px);line-height:1.02}
/* THREE HEADING SIZES AND A REASON FOR EACH.

   Before this the site had a section heading at 44, and then panel headings at
   21, 22 and 23, and card headings at 17.5, 19, 20 and 22, all arbitrary. The
   rule now is about what the heading opens, not about how it looks:

     --h-section  opens a band. Every section on every page is this size.
     --h-panel    opens a card, a form or a tool inside a band. Smaller because
                  the column it sits in is narrower, not because it matters less.
     --h-card     opens one item in a grid of items.

   An h2 that is not a section heading takes --h-panel explicitly. There is no
   fourth size, and a new one needs a reason written next to it. */
:root{
  --h-section:clamp(27px,3.1vw,44px);
  --h-panel:22px;
  --h-card:clamp(18px,1.2vw + 12px,21px);
}
h2{font-size:var(--h-section)}
h3{font-size:var(--h-card);font-weight:700;letter-spacing:-.02em}
.lede{color:var(--ink-2);max-width:var(--measure);font-size:clamp(16px,.4vw + 15px,18px)}
.band--dark .lede{color:var(--on-dark-2)}
.h-block{display:grid;gap:14px;margin-bottom:var(--gap);max-width:var(--measure)}
.h-block--mid{margin-inline:auto;text-align:center}
.h-block--mid .lede{margin-inline:auto}

/* The accent phrase in a headline. A soft underline, not a highlighter. */
/* The underline is a real text-decoration, not a bar drawn under the box.

   It used to be an absolutely positioned ::after, and that only works on a span
   that never wraps, which is why the rule also carried `white-space: nowrap`.
   On a short highlight that is invisible. On a thirty character one it is a
   single unbreakable token in the middle of the headline: `text-wrap: balance`
   cannot do anything with it, so the H1 broke as "Air conditioning for the" /
   "London heat" / "your house was never built for" and the line lengths were
   all over the place, which is what David saw.

   A text-decoration underline draws on every line the span occupies, so the
   span can wrap and the browser can balance the whole headline. */
.hl{color:var(--ice-600);
  text-decoration:underline;text-decoration-thickness:.1em;
  text-underline-offset:.14em;text-decoration-color:color-mix(in srgb,var(--ice-400) 55%,transparent)}
.band--dark .hl,.hero .hl{color:var(--ice-300);
  text-decoration-color:color-mix(in srgb,var(--ice-400) 62%,transparent)}

/* ==========================================================================
   THE CAPSULE NAVIGATION
   A floating pill over the hero, the shape David asked for. It is one line at
   every desktop width, 68px tall, and it becomes a solid bar the moment the
   page scrolls so the links stay readable over light content.
   ========================================================================== */
.navwrap{position:fixed;top:14px;left:0;right:0;z-index:100;pointer-events:none}
.navwrap > .wrap{pointer-events:auto;width:min(1340px,100% - var(--pad)*2)}
.nav{display:flex;align-items:center;gap:8px;min-height:var(--nav-h);
  padding:8px 8px 8px 20px;border-radius:var(--r-pill);
  background:rgba(15,26,36,.62);border:1px solid rgba(216,232,244,.16);
  backdrop-filter:blur(18px) saturate(150%);
  -webkit-backdrop-filter:blur(18px) saturate(150%);
  box-shadow:0 18px 44px -22px rgba(0,0,0,.7);
  transition:background .25s ease,border-color .25s ease,box-shadow .25s ease}

/* Scrolled state. Solid ink so it never fights the content behind it. */
.is-stuck .nav{background:rgba(15,26,36,.94);border-color:rgba(216,232,244,.2);
  box-shadow:0 16px 40px -26px rgba(0,0,0,.85)}

.brand{display:flex;align-items:center;flex:0 0 auto;text-decoration:none;margin-right:6px}
.logo{height:46px;width:auto;display:block;font-family:var(--display)}
.logo-sub{font-family:var(--font)}
/* The footer runs the owner's supplied artwork at 90px, which is where its
   wordmark finally reaches a readable size. See the note by LOGO(). */
.logo--ftr{height:90px}

.navlinks{display:flex;align-items:center;gap:2px;margin-left:auto;list-style:none}
.navlinks > li{position:relative}
.navlinks > li > a{display:inline-flex;align-items:center;gap:5px;
  padding:11px 9px;border-radius:var(--r-pill);text-decoration:none;
  color:#DCE7F0;font-size:14.5px;font-weight:500;white-space:nowrap;
  transition:background .16s,color .16s}
.navlinks > li > a:hover,.navlinks .has-sub:hover > a{background:rgba(255,255,255,.1);color:#fff}
.navlinks a[aria-current=page]{color:#fff;background:rgba(255,255,255,.12)}
.chev{width:9px;height:6px;opacity:.6;transition:rotate .18s ease}
.has-sub:hover .chev{rotate:180deg}

/* ---- the dropdown ---------------------------------------------------------
   Rebuilt after Flame Shield's mega panel. The old one was a list of links with
   a caption, which is the default and reads as unfinished. What makes theirs
   work is three things, and all three are here: a tinted icon tile on every
   row so the eye can find a row by shape, a full sentence of plain English
   under every title, and a dark feature card in the same position in every
   panel so there is always somewhere to go if none of the rows is right.

   The panel is anchored to the item rather than the bar, and it is capped to
   the viewport, so it cannot push the document sideways. */
.sub{position:absolute;top:calc(100% + 14px);left:-14px;
  width:max-content;max-width:min(760px,calc(100vw - 40px));
  background:var(--paper);border:1px solid var(--line);border-radius:22px;
  box-shadow:0 34px 80px -30px rgba(17,26,34,.5);padding:14px;
  opacity:0;visibility:hidden;translate:0 -8px;
  transition:opacity .18s ease,translate .18s ease,visibility .18s}
/* An invisible bridge, so the pointer can cross the gap from the menu item to
   the panel without the panel closing under it on the way. */
.sub::before{content:"";position:absolute;top:-16px;left:0;right:0;height:18px}
.has-sub:hover .sub,.has-sub:focus-within .sub{opacity:1;visibility:visible;translate:0 0}
.sub-in{display:grid;grid-template-columns:minmax(0,1fr) 260px;gap:12px;align-items:stretch}
.sub-main{display:grid;align-content:start;gap:10px;padding:6px 4px 4px 6px}
.sub-intro{font-size:13px;line-height:1.5;color:var(--ink-2);max-width:52ch;
  padding:0 6px}
.mgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:2px}

.mi{display:flex;align-items:flex-start;gap:11px;padding:10px;border-radius:14px;
  text-decoration:none;color:inherit;transition:background .14s}
.mi:hover{background:var(--ice-50)}
.mi-ic{flex:none;width:36px;height:36px;border-radius:11px;display:grid;
  place-items:center;background:var(--ice-100);color:var(--ice-700)}
.mi-ic svg{width:20px;height:20px}
.mi-t{display:flex;flex-direction:column;gap:2px;min-width:0}
.mi-t b{font-size:14.5px;font-weight:650;color:var(--ink);letter-spacing:-.01em}
.mi-t small{font-size:12.5px;line-height:1.4;color:var(--ink-2)}

/* Eleven place names do not each need a sentence. They need to be scannable. */
.sub--areas{max-width:min(680px,calc(100vw - 40px))}
.mareas{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:2px}
.marea{display:flex;flex-direction:column;gap:1px;padding:9px 11px;border-radius:12px;
  text-decoration:none;color:inherit;transition:background .14s}
.marea:hover{background:var(--ice-50)}
.marea b{font-size:14px;font-weight:600;color:var(--ink);white-space:nowrap}
.marea small{font-size:11.5px;color:var(--ink-3)}
.marea--all{background:var(--paper-100)}
.marea--all b{color:var(--ice-700)}

/* The card at the end of every panel. Same shape every time, so it becomes a
   place people learn rather than a surprise. */
.mfeat{position:relative;isolation:isolate;overflow:hidden;display:flex;
  flex-direction:column;gap:6px;padding:18px 18px 16px;border-radius:18px;
  text-decoration:none;color:var(--on-dark-2);
  background:linear-gradient(140deg,var(--ink-900),var(--ink-800) 62%,var(--ice-900));
  transition:transform .2s ease}
.mfeat::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(110px at calc(100% - 42px) 34px,rgba(99,188,230,.5),transparent 72%)}
.mfeat:hover{transform:translateY(-2px)}
.mfeat-ic{width:38px;height:38px;border-radius:11px;display:grid;place-items:center;
  background:rgba(255,255,255,.12);color:var(--ice-300)}
.mfeat-ic svg{width:21px;height:21px}
.mfeat-tag{align-self:flex-start;background:var(--ice-300);color:var(--ink);
  font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  padding:4px 9px;border-radius:var(--r-pill);margin-top:4px}
.mfeat b{color:#fff;font-family:var(--display);font-size:16px;letter-spacing:-.02em;
  line-height:1.2}
.mfeat-x{font-size:12.5px;line-height:1.45;color:var(--on-dark-2)}
.mfeat-cta{display:inline-flex;align-items:center;gap:6px;margin-top:2px;
  font-size:13px;font-weight:700;color:var(--ice-300)}
.mfeat-cta svg{width:15px;height:15px}


.nav-tel{display:inline-flex;align-items:center;gap:9px;padding:0 6px 0 14px;
  color:#fff;text-decoration:none;font-weight:600;font-size:14.5px;white-space:nowrap;
  border-left:1px solid rgba(216,232,244,.2);margin-left:8px}
.nav-tel svg{width:17px;height:17px;color:var(--ice-300)}
/* Height and the capsule's own padding have to agree, or the button reads as
   sitting on top of the bar rather than inside it. 68px capsule, 8px padding,
   so the button is 52px and the gap above and below is identical. */
.nav-cta{display:inline-flex;align-items:center;justify-content:center;
  min-height:52px;padding:0 20px;border-radius:var(--r-pill);
  background:var(--ice-400);color:var(--ink);font:700 14.5px/1 var(--font);
  text-decoration:none;white-space:nowrap;flex:0 0 auto;
  transition:background .16s,transform .16s,box-shadow .16s}
.nav-cta:hover{background:var(--ice-300);color:var(--ink);transform:translateY(-1px);box-shadow:var(--sh-accent)}

/* The three lines are absolutely positioned rather than laid out by a grid gap,
   because the open state rotates them into a cross and that maths only works if
   the distance between them is a number this file decides rather than one the
   layout happens to produce. */
.burger{display:none;position:relative;width:52px;height:52px;flex:0 0 auto;
  margin-left:auto;border:1px solid rgba(216,232,244,.22);cursor:pointer;padding:0;
  border-radius:var(--r-pill);background:rgba(255,255,255,.1);
  transition:background .16s,border-color .16s}
.burger:hover{background:rgba(255,255,255,.18)}
/* The three lines are centred on the button by maths rather than by a flex gap:
   52px button, 22px lines, so the left inset is (52-22)/2 = 15, and the rows sit
   at 19 / 25 / 31 so the middle one is exactly on centre and the outer two are
   6px away. The open state rotates them into a cross and that only lands if this
   file owns the spacing. */
.burger span{position:absolute;left:15px;width:22px;height:2px;background:#fff;
  border-radius:2px;transition:transform .22s ease,opacity .16s ease}
.burger span:nth-child(1){top:19px}
.burger span:nth-child(2){top:25px}
.burger span:nth-child(3){top:31px}
.burger[aria-expanded=true] span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.burger[aria-expanded=true] span:nth-child(2){opacity:0}
.burger[aria-expanded=true] span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

/* The mobile menu.

   A paper card hanging from under the capsule over a scrim. It runs to the
   bottom of the screen now but stops 14px short of the edge on every side, so
   it still reads as a card on top of the page rather than a second screen.

   The call, WhatsApp and survey buttons that used to sit at the bottom are
   gone. They were duplicating three things the visitor already has within
   reach: the hero, the WhatsApp launcher in the corner, and the Contact row in
   this same list. A menu is for going somewhere.

   The labels are the other half of David's note. "Installation" on its own does
   not tell anybody what is being installed; every row now carries the same
   sentence the desktop dropdown uses, and the group heading is a real heading
   rather than a caption. */
.sheet{position:fixed;inset:0;z-index:99;display:flex;justify-content:center;
  align-items:flex-start;padding:calc(var(--nav-h) + 20px) 14px 14px;
  background:rgba(10,17,25,.52);
  backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
  animation:sheet-in .18s ease both}
.sheet[hidden]{display:none}
.sheet > .wrap{width:100%;max-width:560px;margin:0;
  background:var(--paper);border:1px solid var(--line);
  border-radius:24px;box-shadow:0 40px 90px -30px rgba(10,17,25,.6);
  padding:6px 14px 14px;
  max-height:calc(100dvh - var(--nav-h) - 34px);
  overflow-y:auto;overscroll-behavior:contain;
  animation:sheet-card-in .22s cubic-bezier(.16,1,.3,1) both}
@keyframes sheet-in{from{opacity:0}to{opacity:1}}
@keyframes sheet-card-in{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:none}}
.sheet ul{list-style:none}
.sheet > .wrap > ul > li{padding:14px 0;border-bottom:1px solid var(--line)}
.sheet > .wrap > ul > li:last-of-type{border-bottom:0}
/* The group heading. It was 11.5px uppercase, which is a caption, and David is
   right that it disappeared: you read "Installation" with no idea what of. */
.sheet b{display:block;font-family:var(--display);font-size:19px;font-weight:800;
  letter-spacing:-.02em;color:var(--ink);margin:0 0 2px;padding:0 6px}
.sh-note{display:block;font-size:13px;line-height:1.45;color:var(--ink-2);
  padding:0 6px;margin-bottom:8px}
.sheet a{display:flex;align-items:center;gap:12px;text-decoration:none;
  padding:9px 6px;border-radius:14px;color:var(--ink);
  transition:background .14s}
.sheet a:active{background:var(--ice-50)}
.sh-ic{flex:none;width:38px;height:38px;border-radius:12px;display:grid;
  place-items:center;background:var(--ice-100);color:var(--ice-700)}
.sh-ic svg{width:21px;height:21px}
.sh-t{display:flex;flex-direction:column;gap:1px;min-width:0;
  font-size:15.5px;font-weight:650;line-height:1.25}
.sh-t small{font-size:12.5px;font-weight:400;line-height:1.4;color:var(--ink-2)}
.sh-top{font-size:17px;font-weight:700}
.sheet ul ul{display:grid;gap:2px}

/* ==========================================================================
   TEN YEARS, AND THE IMAGE WALL

   The shape comes from the Motion marquee David sent: copy on one side, two
   vertical belts of images on the other running in opposite directions behind a
   mask that fades all four edges. Ported to the site's own belt(), which drives
   scrollTop here instead of scrollLeft, so a thumb can still stop it.

   The mask is what makes it read as a window onto something continuous rather
   than as two columns that happen to be cropped. Without it the belt has hard
   edges and looks like a bug.
   ========================================================================== */
.tenyr{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,460px);
  gap:clamp(28px,4vw,64px);align-items:center}
.tenyr-copy > p{margin-top:14px;color:var(--ink-2);max-width:56ch}
.tenyr-copy .lede{color:var(--ink);font-weight:500}

.tenyr-facts{list-style:none;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:1px;background:var(--line);border:1px solid var(--line);
  border-radius:var(--r-panel);overflow:hidden;margin-top:clamp(22px,2.4vw,30px)}
.tenyr-facts li{background:var(--paper);padding:16px 18px;display:grid;gap:2px}
.tenyr-facts b{font-family:var(--display);font-weight:800;letter-spacing:-.04em;
  font-size:clamp(26px,2.4vw,34px);line-height:1;color:var(--ice-700)}
.tenyr-facts span{font-size:13.5px;line-height:1.4;color:var(--ink-2)}
.tenyr-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:clamp(20px,2.2vw,28px)}

/* The accreditation marks. White tiles on purpose: both ship on an opaque white
   ground, and NICEIC's counters are white and part of the drawing, so keying the
   white out would open holes in the letters. A badge in a white tile is also
   how every trade body asks for its mark to be shown. */
.accs{list-style:none;display:grid;gap:10px;margin-top:clamp(22px,2.4vw,30px);
  padding-top:clamp(20px,2.2vw,26px);border-top:1px solid var(--line)}
.accs > li{display:flex;align-items:center;gap:16px}
.accs img{flex:none;height:48px;width:auto;padding:9px 14px;background:#fff;
  border:1px solid var(--line);border-radius:12px;box-sizing:content-box}
.accs span{font-size:14px;line-height:1.45;color:var(--ink-2)}
.accs-more a{display:inline-flex;align-items:center;gap:7px;font-size:13.5px;
  font-weight:600;color:var(--ice-700);text-decoration:none}
.accs-more a:hover{text-decoration:underline}
.accs-more svg{width:15px;height:15px}
/* On the accreditation page the same list runs wider and carries a full
   sentence, so the mark sits at the top of the text rather than centred on it. */
.accs--page{gap:18px;border-top:0;padding-top:0;margin-top:18px}
.accs--page > li{align-items:flex-start}
.accs--page img{height:44px}
.accs--page span{font-size:15px;color:var(--ink-2);max-width:62ch}
.accs--page strong{color:var(--ink)}



.wall{display:grid;grid-template-columns:1fr 1fr;gap:14px;height:clamp(420px,42vw,560px);
  -webkit-mask:linear-gradient(180deg,transparent,#000 14%,#000 86%,transparent);
  mask:linear-gradient(180deg,transparent,#000 14%,#000 86%,transparent)}
.wall-col{min-height:0}
/* Not scrollable by hand, on David's call. `overflow: hidden` still lets the
   belt drive scrollTop from script, so the columns keep moving; what it removes
   is the visitor being able to grab them. That matters here in a way it does
   not on the services belt: this is decoration beside the copy, and a decorative
   panel that swallows a scroll gesture on a phone is a trap. The services belt
   stays grabbable, because there the cards are the content. */
/* `overflow: hidden` is what lets the page scroll through this. The container
   has nothing of its own to scroll, so a vertical drag starting on the photos
   is handed straight to the document, which is what David asked for: on a phone
   these sit in the middle of the section and a panel that swallowed the scroll
   would trap the thumb. `touch-action: pan-y` says so explicitly rather than
   relying on the default, and `pointer-events: none` on the children stops a
   drag being read as a drag on an image.

   The belt still moves them: scrollTop is settable from script whatever the
   overflow value is. */
.wall-view{height:100%;overflow:hidden;touch-action:pan-y}
.wall-view *{pointer-events:none}
.wall-view::-webkit-scrollbar{display:none}
.wall-track{display:flex;flex-direction:column}
.wall-group{display:flex;flex-direction:column;gap:14px;flex:none;padding-bottom:14px}
.wall figure{margin:0;border-radius:16px;overflow:hidden;background:var(--paper-200);
  box-shadow:var(--sh-sm)}
.wall img{display:block;width:100%;height:auto;aspect-ratio:9/16;object-fit:cover}

/* The three arguments, as disclosures rather than columns. Same chevron and
   hairline treatment as the FAQ, so opening one behaves the way opening one
   anywhere on this site does. */
.says{margin-top:clamp(26px,3vw,40px);display:grid;gap:1px;
  background:var(--line);border:1px solid var(--line);
  border-radius:var(--r-panel);overflow:hidden}
.say{background:var(--paper)}
.say > summary{list-style:none;cursor:pointer;display:flex;align-items:center;
  justify-content:space-between;gap:14px;padding:16px 18px;
  font-family:var(--display);font-weight:800;letter-spacing:-.02em;
  font-size:var(--h-card);color:var(--ink);transition:background .14s}
.say > summary::-webkit-details-marker{display:none}
.say > summary::after{content:"";flex:0 0 auto;width:9px;height:9px;
  border-right:2.2px solid var(--ice-600);border-bottom:2.2px solid var(--ice-600);
  rotate:45deg;translate:0 -2px;transition:rotate .2s ease}
.say[open] > summary::after{rotate:225deg;translate:0 2px}
.say > summary:hover{background:var(--ice-50)}
.say > p{padding:0 18px 18px;font-size:14.5px;line-height:1.62;color:var(--ink-2);
  max-width:78ch}

/* ==========================================================================
   BUTTONS
   Pill only. Three variants and no others: solid accent, WhatsApp green
   (because it is a brand colour and reads as the product it opens), and a
   stroked ghost that adapts to the surface it sits on.
   ========================================================================== */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;
  min-height:52px;padding:0 26px;border:1.5px solid transparent;border-radius:var(--r-pill);
  background:var(--ice-400);color:var(--ink);font:700 15px/1 var(--font);text-decoration:none;
  cursor:pointer;white-space:nowrap;
  transition:background .16s ease,transform .16s ease,box-shadow .16s ease}
.btn:hover{background:var(--ice-300);color:var(--ink);transform:translateY(-2px);box-shadow:var(--sh-accent)}
.btn:active{transform:translateY(0)}
.btn--lg{min-height:58px;padding:0 30px;font-size:16px}
.btn--sm{min-height:44px;padding:0 18px;font-size:14px}
.btn--wide{width:100%}
/* The one dark fill left on the site, so it is the one button that keeps white
   text. `.btn` sets ink now, and inheriting that put dark text on dark green at
   3.65:1. White on this green is 4.71:1. */
.btn--wa{background:#16853F;color:#fff}
.btn--wa:hover{color:#fff}
.btn--wa:hover{background:#0F6D32;box-shadow:0 20px 46px -20px rgba(22,133,63,.5)}
.btn--wa svg{width:18px;height:18px}
.btn--ghost{background:transparent;color:var(--ice-700);border-color:var(--line-2)}
.btn--ghost:hover{background:var(--ice-50);border-color:var(--ice-500);
  color:var(--ice-700);box-shadow:none}
.band--dark .btn--ghost,.hero .btn--ghost{color:#fff;border-color:rgba(255,255,255,.34)}
.band--dark .btn--ghost:hover,.hero .btn--ghost:hover{background:rgba(255,255,255,.1);
  border-color:#fff;color:#fff}
/* Kept only because the heating pages ask for it by name. It used to be the
   amber button that marked heating; now that action itself is ember there is
   nothing left for it to say, and --warm as a fill fails contrast anyway:
   white on #E1562B is 3.6:1. So it is the ordinary button, and the heating
   pages are marked by the tint of the card around it instead. */
/* Warm is a tint and never a fill under text, so the heating pages use the
   ordinary button and are marked by the card around it. */
.btn--warm{background:var(--ice-400)}
.btn--warm:hover{background:var(--ice-300);box-shadow:var(--sh-accent)}

/* ==========================================================================
   THE HERO
   Split. Copy on the left, the permission check on the right, which is where
   David wants it: it is the mechanism, and burying it in its own section below
   the fold made it look like an afterthought.

   The left column keeps four elements and no more. What is deliberately not
   here any more is the strip of company facts that used to sit under the
   headline. Company number, NICEIC, Gas Safe and MCS belong in the footer and
   on the accreditation page, not under a hero.
   ========================================================================== */
/* The two columns are `align-items: start`, not centre.

   Centred was the cause of the dead space David saw. The permission check on
   the right is a tall form and the copy on the left is a headline, a line and
   two buttons; centring the short column against the tall one banks the whole
   difference as blank space above and below the headline, which then reads as
   the hero starting a third of the way down. Aligned to the top, the headline
   sits where the eye lands and the extra height belongs to the form, which is
   the thing that actually needs it. */
.hero{position:relative;isolation:isolate;background:var(--ink-950);color:#fff;
  /* +46, not +18. Measured, the form panel's top edge sat 2px below the
     navigation capsule: technically not overlapping and visually stuck to it.
     This gives 30px of air. The copy column is centred against the form so it
     follows without being pushed down. */
  padding-top:calc(var(--nav-h) + 46px);padding-bottom:clamp(38px,4.4vw,62px);overflow:clip}
.hero-bg{position:absolute;inset:0;z-index:-2}
.hero-bg img{width:100%;height:100%;object-fit:cover;object-position:58% 44%}

/* THE HERO VIDEO.

   It sits on top of the still, not instead of it. The still paints immediately
   and is what the largest contentful paint measures; the video arrives later,
   already playing, and fades in over the top. If it never arrives, or the
   visitor has asked for less motion, or the connection is metered, the still is
   the whole design and nobody can tell anything is missing.

   `object-fit: cover` on both, so the two are framed the same way and the fade
   is a fade rather than a jump. */
.hero-vid,.phero-vid{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:58% 44%;
  opacity:0;transition:opacity .9s ease;pointer-events:none}
.hero-vid[data-on],.phero-vid[data-on]{opacity:1}
/* THE VEIL, lightened 2026-09-05.

   It used to be two stacked gradients covering the whole frame, and between
   them the footage was barely visible. David: let the clip be understood.

   The darkness now goes where the text is and nowhere else. The copy sits in
   the left 45%, so the horizontal gradient is heavy there and gone by 62%; the
   right half, where the form sits on its own opaque card, is left almost clear
   and that is where most of the clip actually reads. The vertical layer is now
   only a small lift at the top and a foot at the bottom, to stop the section
   ending on a hard edge.

   The floor is not a guess. The binding constraint is the sub-paragraph, 17px
   in #D2E2EE, which needs 4.5:1. Against the brightest frame in the loop that
   works out at about 0.80 alpha where that line sits, so the gradient holds
   0.84 to 0.66 across the copy column and only falls away past it. The 54px
   headline is large text and needs 3:1, which it clears everywhere. */
.hero-veil{position:absolute;inset:0;z-index:-1;
  background:
    linear-gradient(180deg,rgba(10,17,25,.34) 0%,rgba(10,17,25,0) 26%,rgba(10,17,25,0) 64%,rgba(10,17,25,.62) 100%),
    linear-gradient(97deg,rgba(10,17,25,.84) 0%,rgba(10,17,25,.78) 26%,rgba(10,17,25,.66) 42%,rgba(10,17,25,.22) 56%,rgba(10,17,25,0) 66%)}

/* 530, not 470. "Air conditioning installation" is the longest option in the
   job select and at 470 the field was half of 470 minus a gap, which truncated
   it. A select that hides its own longest option is a select nobody trusts. */
.hero-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,530px);
  gap:var(--gap);align-items:start}
/* Centred against the form, which is what David asked for, but only up to a
   point: `align-items: center` on the grid was the original blank-space bug
   because it banked the whole height difference above and below the headline.
   Centring just this column with a cap means the copy sits in the middle of the
   form beside it while it is close in height, and stops drifting down once the
   form is much taller. */
.hero-copy{align-self:center;margin-block:clamp(0px,2vw,34px)}
/* 22ch, not 17. At 17 the headline broke into three very uneven lines because
   the measure was too narrow for `balance` to have any choices. */
.hero h1{color:#fff;font-size:clamp(36px,4.2vw,54px);max-width:22ch;text-wrap:balance}
.hero-copy > p{color:#D2E2EE;font-size:clamp(16px,.4vw + 15px,18px);max-width:44ch;margin-top:16px}
/* THE HERO BUTTONS.

   They were flat pills, and against a photograph a flat pill has nothing
   holding it to the page. Green Electro Heating's hero buttons carry a real
   shadow and a thick ring, and that is what makes them read as objects rather
   than as coloured rectangles. Three things here do it:

     a 2px ring in the button's own colour, lightened, so the edge survives
     whatever is behind it in the photograph;
     an inset highlight along the top, which is what makes a solid fill look
     like it has a surface;
     a shadow tinted to the fill rather than to black.

   Hero only. Buttons in the body of the page sit on paper and need none of it. */
.hero-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:24px}
.hero-cta .btn{min-height:58px;padding:0 30px;font-weight:800;
  border:2px solid rgba(255,255,255,.35);
  box-shadow:0 10px 26px -10px rgba(6,20,32,.75),inset 0 1px 0 rgba(255,255,255,.45)}
.hero-cta .btn:not(.btn--wa){border-color:var(--ice-200);
  box-shadow:0 12px 30px -12px rgba(30,134,188,.75),inset 0 1px 0 rgba(255,255,255,.55)}
.hero-cta .btn:not(.btn--wa):hover{border-color:#fff}
.hero-cta .btn--wa{border-color:rgba(120,220,160,.55);
  box-shadow:0 12px 30px -12px rgba(22,133,63,.8),inset 0 1px 0 rgba(255,255,255,.28)}
.hero-cta .btn--wa:hover{border-color:rgba(150,235,185,.85)}
.hero-cta .btn:hover{transform:translateY(-2px)}
.hero-cta .btn:active{transform:translateY(0) scale(.985)}

/* One breakpoint, two audiences. See the note in the home page markup. */
.only-narrow{display:none}


/* The hero form. It replaced the permission check on 2026-09-05: the hero of a
   company that sells installations should ask for the installation. */
.btn--jump{display:none}
.hero-form{background:var(--paper);border-radius:var(--r-panel);
  box-shadow:0 34px 80px -34px rgba(6,16,24,.7);overflow:hidden}
.hero-form-hd{padding:clamp(18px,1.8vw,24px) clamp(18px,1.8vw,26px) 0}
.hero-form-hd h2{font-size:var(--h-panel);color:var(--ink)}
.hero-form-hd p{margin-top:7px;font-size:13.5px;line-height:1.5;color:var(--ink-2)}
.lead--hero{padding:clamp(16px,1.6vw,22px) clamp(18px,1.8vw,26px) clamp(18px,1.8vw,24px)}
/* Nothing follows the submit button in a hero form, so the card needs its own
   bottom padding rather than borrowing the foot note's. */
.lead--hero .lead-foot[hidden]{display:none}
.lead--hero{padding-bottom:clamp(20px,2vw,26px)}
/* The job select carries the longest string in the form, so in the hero panel
   its row goes to one column and the select gets the full width of the panel.

   A postcode is eight characters and the job is a sentence, so the row is split
   0.62 to 1 rather than in half. That is enough for "Air conditioning
   installation" plus the select's own arrow with room to spare, and it keeps
   both fields on one line.

   `:nth-of-type(2)` was the obvious way to say "the second row" and it was
   wrong: nth-of-type counts among siblings of the same TAG, and the honeypot
   `.lead-hp` is a div sitting before the rows, so it took slot one and the rule
   landed on the name and phone row instead. `.lead-row + .lead-row` says the
   thing that was actually meant, which is the row that follows a row. */
.lead--hero .lead-row + .lead-row{grid-template-columns:minmax(0,0.62fr) minmax(0,1fr)}


/* ==========================================================================
   BRAND STRIP
   Logos only. David's rule: do not print the name of an accreditation unless
   there is a real mark to print with it. We have manufacturer logos and we do
   not have NICEIC, Gas Safe or MCS artwork, so those claims live in the footer
   and on the accreditation page as text in context, and this strip shows the
   five marks we actually hold files for.
   ========================================================================== */
/* The manufacturer marks.

   A continuous belt, seamless, driven by scrollLeft so a thumb can push it or
   hold it still. See the long note on `belt()` in main.js.

   No card, no border, no filter. The marks all carry a real alpha channel now,
   so they sit straight on the band in their own colours, which is what a wall
   of manufacturer artwork is supposed to look like. Fading edges rather than
   hard ones, because a belt that stops dead at the container edge reads as a
   row that has been cut off. */
.marks{background:var(--paper-50);border-block:1px solid var(--line);
  padding-block:clamp(28px,3.2vw,42px)}
/* The band carries a section heading in the page's own size and shape, not a
   caption. It used to have a paragraph under it explaining that we are not tied
   to one manufacturer, which is true and belongs on a service page rather than
   above a logo belt: a belt of five wordmarks needs a label, not an argument. */
.marks-belt{margin-top:clamp(18px,2.2vw,28px);
  -webkit-mask:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.marks-view{overflow-x:auto;overflow-y:hidden;scrollbar-width:none;
  -ms-overflow-style:none;overscroll-behavior-x:contain}
.marks-view::-webkit-scrollbar{display:none}
.marks-track{display:flex;width:max-content}
.marks-group{display:flex;align-items:center;flex:none}
.marks-i{display:grid;place-items:center;flex:none;
  padding-inline:clamp(26px,3.4vw,58px)}
.marks-i img{height:clamp(30px,2.8vw,40px);width:auto;max-width:none;
  object-fit:contain}


/* ==========================================================================
   THE PERMISSION CHECK
   A white panel inside the dark hero. It is the one thing on this site no
   competitor has, so it gets the strongest position on the page.
   ========================================================================== */
/* The check moved off the home page hero and onto the planning page, where it
   sits in a full width band rather than a 470px column. Without a cap it would
   stretch to 1240px and the three questions would look lost in it. */
.pcheck-wrap{max-width:560px;margin-inline:auto}
.pcheck-wrap .pcheck{box-shadow:var(--sh)}

.pcheck{background:#fff;border-radius:var(--r-panel);box-shadow:var(--sh-lg);
  color:var(--ink);overflow:hidden;border:1px solid rgba(255,255,255,.5)}
.pcheck-hd{padding:26px 28px 0}
.pcheck-hd h2{font-size:var(--h-panel);color:var(--ink)}
.pcheck-hd p{color:var(--ink-2);font-size:14.5px;margin-top:8px}
.pcheck-body{padding:22px 28px 28px;display:grid;gap:20px}
.fld{display:grid;gap:10px}
.fld > label,.fld > legend{font-size:14px;font-weight:600;color:var(--ink);padding:0}
fieldset{border:0;margin:0;padding:0;display:grid;gap:10px}
input[type=text]{width:100%;min-height:52px;padding:0 16px;border:1.5px solid var(--line-2);
  border-radius:var(--r-input);background:#fff;color:var(--ink);
  font:600 16px/1 var(--font);text-transform:uppercase;
  transition:border-color .15s,box-shadow .15s}
input[type=text]::placeholder{color:var(--ink-3);text-transform:none;font-weight:400}
input[type=text]:focus{border-color:var(--ice-600);box-shadow:0 0 0 4px rgba(46,138,128,.15);outline:none}

.seg{display:grid;grid-template-columns:1fr 1fr;gap:9px}
.seg label{position:relative;display:block}
.seg input{position:absolute;inset:0;opacity:0;cursor:pointer;margin:0}
.seg span{display:flex;align-items:center;justify-content:center;text-align:center;
  min-height:50px;padding:9px 12px;border:1.5px solid var(--line-2);border-radius:var(--r-input);
  font-size:14.5px;font-weight:500;cursor:pointer;background:#fff;color:var(--ink);
  transition:border-color .14s,background .14s,color .14s,transform .14s}
.seg input:hover + span{border-color:var(--ice-400)}
.seg input:checked + span{border-color:var(--ice-600);background:var(--ice-50);
  color:var(--ice-700);font-weight:700}
.seg input:focus-visible + span{outline:3px solid var(--ice-500);outline-offset:2px}
.seg--wide{grid-template-columns:1fr}
.pcheck-foot{font-size:13px;color:var(--ink-3);text-align:center}
/* ==========================================================================
   THE STEPPER
   Every calculator uses this below 720. One question on screen, a progress bar
   and a count, Back and Next. Choosing a radio advances on its own, so Next is
   only there for the steps that end in typing rather than tapping.
   ========================================================================== */
.stepnav{display:grid;gap:12px}
.stepnav[hidden]{display:none}
.stepnav-bar{height:4px;border-radius:99px;background:var(--paper-200);overflow:hidden}
.stepnav-bar i{display:block;height:100%;border-radius:99px;background:var(--ice-600);
  width:12.5%;transition:width .28s cubic-bezier(.16,1,.3,1)}
.stepnav-row{display:flex;align-items:center;justify-content:space-between;gap:12px}
.stepnav-n{font-size:13px;font-weight:600;color:var(--ink-2);
  font-variant-numeric:tabular-nums}
.stepbtn{min-height:44px;padding:0 18px;border-radius:var(--r-pill);cursor:pointer;
  border:1.5px solid var(--line-2);background:#fff;color:var(--ink);
  font:700 14px var(--font);transition:border-color .15s,background .15s,color .15s}
.stepbtn:hover:not(:disabled){border-color:var(--ice-500);color:var(--ice-700)}
.stepbtn:disabled{opacity:.42;cursor:default}
.stepbtn[hidden]{display:none}
.stepbtn--next{background:var(--ice-400);border-color:var(--ice-400);color:var(--ink)}
.stepbtn--next:hover{background:var(--ice-300);border-color:var(--ice-300);color:var(--ink)}

.verdict{padding:24px 28px;display:grid;gap:15px;border-top:1px solid var(--line)}
.verdict[hidden]{display:none}
.v-ok{background:var(--ok-50)}
.v-warn{background:var(--warm-50)}
.verdict h3{font-size:var(--h-card)}
.v-ok h3{color:var(--ok)}
.v-warn h3{color:var(--warm-ink)}
.verdict p{font-size:15px;color:var(--ink-2)}
.v-warn p{color:#7A4E14}
.cond{width:100%;font-size:14px;background:#fff;border-radius:var(--r-input);overflow:hidden}
.cond caption{text-align:left;font-size:13.5px;font-weight:600;color:var(--ink);padding-bottom:9px}
.cond th,.cond td{text-align:left;padding:11px 13px;border-bottom:1px solid var(--line)}
.cond thead th{font-size:12.5px;color:var(--ink-2);font-weight:600;background:var(--paper-50)}
.cond tbody tr:last-child td{border-bottom:0}
.cond td:last-child,.cond th:last-child{text-align:right}
.mark{font-weight:700;font-size:13.5px}
.mark--y{color:var(--ok)}
.mark--q{color:var(--hold)}
.verdict-cta{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.todo{background:#fff;border:1.5px dashed var(--line-2);color:var(--ink-2);
  padding:14px 16px;font-size:14px;border-radius:var(--r-input)}
.todo b{color:var(--ink)}

/* ==========================================================================
   PAGE HERO, for everything that is not the homepage
   ========================================================================== */
.phero{position:relative;isolation:isolate;background:var(--ink-950);color:#fff;
  padding-top:calc(var(--nav-h) + 62px);padding-bottom:clamp(46px,5vw,72px);overflow:clip}
.phero-bg{position:absolute;inset:0;z-index:-2}
.phero-bg img{width:100%;height:100%;object-fit:cover;object-position:60% 40%}
.phero-vid{object-position:60% 40%}
/* Same principle as .hero-veil above, and the page hero needs a little more
   because its copy column runs wider and its lede is longer. */
.phero-veil{position:absolute;inset:0;z-index:-1;
  background:
    linear-gradient(180deg,rgba(10,17,25,.3) 0%,rgba(10,17,25,0) 30%,rgba(10,17,25,0) 66%,rgba(10,17,25,.55) 100%),
    linear-gradient(97deg,rgba(10,17,25,.86) 0%,rgba(10,17,25,.8) 30%,rgba(10,17,25,.66) 46%,rgba(10,17,25,.26) 60%,rgba(10,17,25,.04) 72%)}
.phero-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,400px);
  gap:var(--gap);align-items:start}
.phero h1{color:#fff;max-width:17ch}
.phero .lede{color:#D2E2EE;margin-top:18px;max-width:50ch}
.phero-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:28px}

.ticks{list-style:none;display:grid;gap:11px;margin-top:26px;max-width:52ch}
.ticks li{position:relative;padding-left:30px;font-size:15.5px;color:#D5E5F1}
.ticks li::before{content:"";position:absolute;left:0;top:3px;width:19px;height:19px;
  border-radius:50%;background:rgba(99,181,170,.18)}
.ticks li::after{content:"";position:absolute;left:6px;top:9px;width:7px;height:4px;
  border-left:2px solid var(--ice-300);border-bottom:2px solid var(--ice-300);rotate:-45deg}
.ticks b{color:#fff;font-weight:700}
.band--tint .ticks li,.band .ticks li{color:var(--ink)}
.band--tint .ticks li::before,.band .ticks li::before{background:var(--ice-50)}
.band--tint .ticks li::after,.band .ticks li::after{border-color:var(--ice-600)}

/* The survey card that sits beside a page hero. */
/* The hero panel on every page that is not the home page. It is the survey form
   in a white card, the same shape as the home page's, so a person who has seen
   one has seen them all. */
.quotecard{background:var(--paper);border-radius:var(--r-panel);
  box-shadow:0 34px 80px -34px rgba(6,16,24,.7);overflow:hidden;align-self:start}
.quotecard-hd{padding:clamp(18px,1.8vw,24px) clamp(18px,1.8vw,26px) 0}
.quotecard-hd h2{font-size:var(--h-panel);color:var(--ink)}
.quotecard-hd p{margin-top:7px;font-size:13.5px;line-height:1.5;color:var(--ink-2)}
.quotecard .lead{padding:clamp(16px,1.6vw,22px) clamp(18px,1.8vw,26px) clamp(18px,1.8vw,24px)}
.quotecard .lead-row + .lead-row{grid-template-columns:minmax(0,0.62fr) minmax(0,1fr)}

/* ==========================================================================
   TOWN HERO
   The borough pages. A real photograph of the place, the headline over it, and
   the form beside it, which is the shape David asked for. The photograph is
   already graded down at build time so one scrim works across eleven images by
   eleven different photographers.
   ========================================================================== */
.thero{position:relative;isolation:isolate;background:var(--ink-950);color:#fff;
  padding-top:calc(var(--nav-h) + 22px);padding-bottom:clamp(38px,4.2vw,60px);overflow:clip}
.thero-bg{position:absolute;inset:0;z-index:-2}
.thero-bg img{width:100%;height:100%;object-fit:cover;object-position:50% 42%}
.thero-veil{position:absolute;inset:0;z-index:-1;
  background:
    linear-gradient(180deg,rgba(10,17,25,.6) 0%,rgba(10,17,25,.42) 40%,rgba(10,17,25,.9) 100%),
    linear-gradient(100deg,rgba(10,17,25,.92) 0%,rgba(10,17,25,.68) 44%,rgba(10,17,25,.2) 78%)}
.thero-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,412px);
  gap:var(--gap);align-items:start}
.thero h1{color:#fff;font-size:clamp(34px,4vw,54px);max-width:14ch}
.thero .lede{color:#D2E2EE;margin-top:16px;max-width:48ch}
.thero-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:26px}

.thero-form{background:#fff;color:var(--ink);border-radius:var(--r-panel);
  padding:clamp(20px,2vw,26px);box-shadow:var(--sh-lg);display:grid;gap:12px}
.thero-form h2{font-size:var(--h-panel)}
.thero-form > p{font-size:14px;color:var(--ink-2)}

/* Attribution is a condition of the CC BY-SA licence most of these carry, not
   decoration. Do not remove it. */
.thero-credit{position:relative;z-index:1;margin-top:26px;font-size:11.5px;
  color:rgba(221,230,237,.55);text-align:right;
  width:min(1240px,100% - var(--pad)*2);margin-inline:auto}

/* ==========================================================================
   LEAD FORM
   Posts to /api/enquiry. Works with JavaScript off; the enhancement is only
   that a fetch keeps the visitor on the page.
   ========================================================================== */
.lead{display:grid;gap:12px}
.lead-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.lead-row{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.lead .fld > label{font-size:13px;font-weight:600;color:var(--ink)}
.lead input[type=text],.lead input[type=tel],.lead input[type=email],
.lead select,.lead textarea{width:100%;min-height:50px;padding:0 14px;
  border:1.5px solid var(--line-2);border-radius:var(--r-input);background:#fff;
  color:var(--ink);font:500 15.5px/1 var(--font);text-transform:none;
  transition:border-color .15s,box-shadow .15s}
.lead textarea{min-height:82px;padding:12px 14px;line-height:1.5;resize:vertical}
.lead select{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:38px;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%234A6478' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 14px center;background-size:10px 6px}
.lead input::placeholder,.lead textarea::placeholder{color:var(--ink-3);font-weight:400}
.lead input:focus,.lead select:focus,.lead textarea:focus{outline:none;
  border-color:var(--ice-600);box-shadow:0 0 0 4px rgba(46,138,128,.15)}
.lead input[aria-invalid=true],.lead select[aria-invalid=true]{border-color:var(--stop);
  box-shadow:0 0 0 4px rgba(201,59,59,.13)}
.lead-foot{font-size:12.5px;color:var(--ink-3);line-height:1.5}
/* THE OPTION BUTTON.

   Green Electro Heating's `.opt` is the reference and David asked for it by
   name: a 2px border, a real radius, proper padding, and two things ours never
   had. It lifts on hover, and it presses. `transform: scale(.985)` on :active
   is the whole difference between a control that feels like a button and one
   that feels like a div with a border, and it costs one line.

   Used by the survey form's "when" question. The price configurator's chips
   inherit the same treatment further down. */
.opts{display:grid;gap:9px}
.opts--2{grid-template-columns:1fr 1fr}
.opt{position:relative;display:block}
.opt input{position:absolute;inset:0;opacity:0;cursor:pointer;margin:0}
.opt > span{display:grid;gap:2px;align-content:center;min-height:58px;
  padding:11px 15px;cursor:pointer;
  border:2px solid var(--line-2);border-radius:16px;background:#fff;
  transition:border-color .18s,background .18s,transform .16s,box-shadow .2s}
.opt b{font-size:14.2px;font-weight:700;color:var(--ink);line-height:1.25}
.opt em{font-style:normal;font-size:12px;color:var(--ink-3);line-height:1.3}
.opt input:hover + span{border-color:var(--ice-400);background:var(--ice-50);
  transform:translateY(-2px);box-shadow:0 8px 18px -10px rgba(30,134,188,.4)}
.opt input:active + span{transform:scale(.985)}
.opt input:checked + span{border-color:var(--ice-600);background:var(--ice-50);
  box-shadow:0 8px 20px -12px rgba(30,134,188,.5)}
.opt input:checked + span b{color:var(--ice-800)}
.opt input:focus-visible + span{outline:3px solid var(--ice-500);outline-offset:2px}

/* Same feel on the price configurator's chips and the segmented controls, so
   there is one kind of choosing on this site rather than three. */
.pcfg-chip span,.seg span{border-width:2px;border-radius:16px;
  transition:border-color .18s,background .18s,transform .16s,box-shadow .2s}
.pcfg-chip input:hover + span,.seg input:hover + span{transform:translateY(-2px);
  box-shadow:0 8px 18px -10px rgba(30,134,188,.4)}
.pcfg-chip input:active + span,.seg input:active + span{transform:scale(.985)}

/* SEND IT ANOTHER WAY. A quiet row under the submit button: the form is the
   main path and these are the two alternatives, so they are small and they do
   not compete with it. */
.lead-alt{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding-top:14px;margin-top:2px;border-top:1px solid var(--line)}
.lead-alt-l{font-size:12.5px;font-weight:600;color:var(--ink-3)}
.lead-alt-b{display:flex;gap:8px;margin-left:auto}
.lead-alt .btn{min-height:40px;padding:0 16px;font-size:13.5px}
.lead-alt .btn--wa svg{width:15px;height:15px}
/* `.hero .btn--ghost` paints ghost buttons white for the dark hero ground, and
   at two classes it reaches straight into the white form panel sitting on that
   ground. The Email button was white text on white. The lead form is always on
   a light surface wherever it appears, so it states its own colours and, being
   later in the file at the same specificity, wins. */
.lead-alt .btn--ghost{color:var(--ice-700);border-color:var(--line-2)}
.lead-alt .btn--ghost:hover{background:var(--ice-50);border-color:var(--ice-500);
  color:var(--ice-700)}

/* THE HOURS LINE. Small, factual, and it appears wherever somebody is about to
   pick up the phone rather than only in the footer. The dot and the "Open now"
   are written by JavaScript from the same `site.hours` the schema uses; with
   JavaScript off the line reads correctly without them. */
.hours{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 8px;
  font-size:12.5px;line-height:1.45;color:var(--ink-3)}
.hours-now{display:inline-flex;align-items:center;gap:6px;font-weight:700;
  color:var(--ok)}
.hours-now::before{content:"";width:7px;height:7px;border-radius:50%;
  background:var(--ok);flex:none}
.hours-now[data-shut]{color:var(--ink-2)}
.hours-now[data-shut]::before{background:var(--ink-3)}
.hours--form{padding-top:10px;margin-top:2px;border-top:1px solid var(--line)}
.hours--dark{color:var(--on-dark-3);margin-top:16px}
.hours--dark .hours-now{color:var(--ice-300)}
.hours--dark .hours-now::before{background:var(--ice-300)}
.hours--dark .hours-now[data-shut]{color:var(--on-dark-2)}
.hours--dark .hours-now[data-shut]::before{background:var(--on-dark-3)}


.lead-foot.is-err{color:var(--stop);font-weight:600}
.lead-foot.is-ok{color:var(--ok);font-weight:600}
.lead button[disabled]{opacity:.6;cursor:progress}
.lead--compact .lead-foot{font-size:12px}
.lead-done{display:grid;gap:10px;text-align:center;padding:8px 0}
.lead-done b{font-size:18px;font-family:var(--display);font-weight:800;letter-spacing:-.02em}
.lead-done p{font-size:14.5px;color:var(--ink-2)}

/* On a dark surface the form keeps its own light card, so nothing here needs an
   on-dark variant. What does need saying is the mobile collapse. */
@media (max-width:1080px){
  .ctacard--form{grid-template-columns:1fr}
  .tenyr{grid-template-columns:1fr}
  .thero-grid{grid-template-columns:1fr}
  .thero-form{max-width:520px}
  .thero-credit{text-align:left}
}
@media (max-width:720px){
  .wa-fab{width:52px;height:52px}
  .wa-fab svg{width:25px;height:25px}
  .thero{padding-top:calc(var(--nav-h) + 36px)}
  .thero h1{font-size:clamp(30px,8vw,40px);max-width:none}
  .thero-cta .btn{flex:1 1 100%}
  .lead-row{grid-template-columns:1fr}
  .thero-form{max-width:none}
}

/* ==========================================================================
   BREADCRUMBS
   ========================================================================== */
/* The nav is fixed, so whatever comes first inside main has to clear it. On
   every page except the homepage that is the breadcrumb bar. Getting this wrong
   hides the first line of the page underneath the capsule. */
.crumbs{background:var(--ink-950);color:var(--on-dark-3);font-size:13px;
  border-bottom:1px solid var(--line-dark)}
main > .crumbs:first-child{padding-top:calc(var(--nav-h) + 18px)}
.crumbs + .phero{padding-top:clamp(30px,3.2vw,48px)}
.crumbs + .band,.crumbs + .pcheck-sec{padding-top:clamp(40px,5vw,72px)}
.crumbs ol{list-style:none;display:flex;flex-wrap:wrap;gap:4px 8px;padding:12px 0}
.crumbs li:not(:last-child)::after{content:"/";padding-left:8px;opacity:.45}
.crumbs a{color:var(--on-dark-3);text-decoration:none}
.crumbs a:hover{color:var(--ice-300)}
.crumbs span{color:var(--on-dark-2);font-weight:500}

/* Legal and policy page header. No photograph: a picture on a complaints
   procedure is noise. It just needs to stop looking like an unstyled document. */
.lhead{background:var(--ink-950);color:#fff;padding-block:clamp(40px,5vw,72px) clamp(30px,3.4vw,48px);
  border-bottom:1px solid var(--line-dark)}
.lhead h1{color:#fff;font-size:clamp(30px,3.4vw,46px)}
.lhead .lede{color:var(--on-dark-2);margin-top:12px}
main > .crumbs:first-child + .lhead{padding-top:clamp(30px,3.4vw,52px)}

.faq-head{max-width:56ch}
.faq-head .lede{color:#D2E2EE;margin-top:16px}

/* ==========================================================================
   CONTENT
   ========================================================================== */
.answer{background:var(--ice-50);border-left:3px solid var(--ice-600);
  border-radius:0 var(--r-panel) var(--r-panel) 0;
  padding:clamp(22px,2.2vw,28px) clamp(22px,2.4vw,32px);display:grid;gap:12px;max-width:78ch}
.answer-t{font-size:clamp(17px,.55vw + 16px,20px);font-weight:600;color:var(--ink);line-height:1.5}
.answer-x{font-size:15.5px;color:var(--ink-2)}
.answer a{color:var(--ice-700);font-weight:600}

.prose{max-width:72ch;display:grid;gap:20px}
.prose h2{margin-top:24px}
.prose h3{margin-top:12px;font-size:clamp(18px,1.2vw,21px)}
.prose p,.prose li{font-size:16.5px;color:var(--ink-2);line-height:1.68}
.prose strong{color:var(--ink);font-weight:600}
.prose a{color:var(--ice-700);font-weight:500}
.prose ul,.prose ol{display:grid;gap:10px;padding-left:22px}
.prose li{padding-left:4px}
.prose ul li{list-style:disc}
.prose ol li{list-style:decimal}
.prose--wide{max-width:none}

.split{display:grid;grid-template-columns:minmax(0,1.18fr) minmax(0,.82fr);
  gap:var(--gap);align-items:start}
.sticky-side{position:sticky;top:calc(var(--nav-h) + 26px);display:grid;gap:18px}

/* ==========================================================================
   TABLES
   ========================================================================== */
.tbl-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--r-panel);background:#fff}
.dtable{width:100%;font-size:15px;min-width:min(560px,100%)}
.dtable caption{text-align:left;font-size:14px;font-weight:600;color:var(--ink);
  padding:18px 20px 0;caption-side:top}
.dtable th,.dtable td{text-align:left;padding:14px 20px;border-bottom:1px solid var(--line);
  vertical-align:top}
.dtable thead th{font-size:12.5px;font-weight:700;color:var(--ink);background:var(--paper-50);
  border-bottom:1px solid var(--line-2)}
.dtable tbody th{font-weight:600;color:var(--ink)}
.dtable td{color:var(--ink-2)}
.dtable tbody tr:last-child th,.dtable tbody tr:last-child td{border-bottom:0}
.yes{color:var(--ok);font-weight:700}
.no{color:var(--stop);font-weight:700}
.maybe{color:var(--hold);font-weight:700}
.tbl-note{font-size:13.5px;color:var(--ink-3);margin-top:12px}

/* ==========================================================================
   CARDS AND GRIDS
   ========================================================================== */
.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.cards--2{grid-template-columns:repeat(2,1fr)}
.cards--4{grid-template-columns:repeat(4,1fr)}
.card{background:#fff;border:1px solid var(--line);border-radius:var(--r-panel);
  padding:clamp(22px,2vw,28px);display:grid;gap:11px;align-content:start;
  transition:transform .2s ease,box-shadow .2s ease,border-color .2s}
a.card{text-decoration:none}
a.card:hover{transform:translateY(-3px);box-shadow:var(--sh);border-color:var(--ice-400)}
.card h3{font-size:var(--h-card)}
.card p{font-size:15px;color:var(--ink-2)}
.card .more{margin-top:auto;font-weight:700;font-size:14.5px;color:var(--ice-700);
  display:inline-flex;align-items:center;gap:7px}
.card .more::after{content:"";width:6px;height:6px;border-right:2px solid currentColor;
  border-top:2px solid currentColor;rotate:45deg;transition:translate .16s}
a.card:hover .more::after{translate:3px 0}
.card-n{font-family:var(--display);font-size:34px;font-weight:800;color:var(--ice-700);
  letter-spacing:-.04em;line-height:1}
.card--warm{border-color:var(--warm-100);background:var(--warm-50)}
.card--warm .card-n,.card--warm .more{color:var(--warm-ink)}
.card--warm .ic-lg{color:var(--warm)}
.band--dark .card{background:var(--ink-850);border-color:var(--line-dark);color:var(--on-dark)}
.band--dark .card p{color:var(--on-dark-2)}
.band--dark .card .more{color:var(--ice-300)}

.ic-lg{width:32px;height:32px;color:var(--ice-600);stroke:currentColor;fill:none;
  stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}

/* Feature rail: a photograph with the answer under it. Not an icon in a circle. */
.qcards{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.qcard{background:#fff;border:1px solid var(--line);border-radius:var(--r-panel);
  display:flex;flex-direction:column;overflow:hidden;
  transition:transform .2s ease,box-shadow .2s ease}
.qcard:hover{transform:translateY(-3px);box-shadow:var(--sh)}
.qcard img{aspect-ratio:5/4;object-fit:cover;width:100%}
.qcard-b{padding:24px;display:grid;gap:11px;align-content:start;flex:1}
.qcard p{font-size:15px;color:var(--ink-2)}
.qcard a{margin-top:auto;font-weight:700;font-size:14.5px;text-decoration:none;
  color:var(--ice-700);display:inline-flex;align-items:center;gap:7px;
  min-height:44px;width:max-content}
.qcard a::after{content:"";width:6px;height:6px;border-right:2px solid currentColor;
  border-top:2px solid currentColor;rotate:45deg;transition:translate .16s}
.qcard a:hover::after{translate:3px 0}

/* ==========================================================================
   PROCESS
   ========================================================================== */
.steps{display:grid;grid-template-columns:repeat(4,1fr);counter-reset:s;
  border:1px solid var(--line);border-radius:var(--r-panel);overflow:hidden;background:#fff}
.steps li{counter-increment:s;list-style:none;padding:clamp(24px,2.2vw,30px);
  display:grid;gap:9px;align-content:start}
.steps li + li{border-left:1px solid var(--line)}
.steps li::before{content:counter(s);font-family:var(--display);font-size:26px;
  font-weight:800;color:var(--ice-400);line-height:1}
.steps h3{font-size:var(--h-card)}
.steps p{font-size:14.5px;color:var(--ink-2)}

/* ==========================================================================
   RECENT INSTALLS RAIL
   ========================================================================== */
.rail{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(258px,1fr);gap:18px;
  overflow-x:auto;padding:4px 4px 20px;scroll-snap-type:x mandatory;overscroll-behavior-x:contain}
.rail::-webkit-scrollbar{height:8px}
.rail::-webkit-scrollbar-track{background:rgba(255,255,255,.08);border-radius:99px}
.rail::-webkit-scrollbar-thumb{background:var(--ice-500);border-radius:99px}
.job{scroll-snap-align:start;background:var(--ink-850);border:1px solid var(--line-dark);
  border-radius:var(--r-panel);overflow:hidden}
.job img{aspect-ratio:4/5;object-fit:cover;width:100%}
.job-b{padding:18px;display:grid;gap:11px}
.job-t{font-size:15.5px;font-weight:700;color:#fff;font-family:var(--display);letter-spacing:-.02em}
.job dl{display:grid;grid-template-columns:auto minmax(0,1fr);gap:6px 14px;font-size:13.5px;margin:0}
.job dt{color:var(--on-dark-3)}
.job dd{margin:0;text-align:right;font-weight:600;color:var(--on-dark);text-wrap:balance}

/* ==========================================================================
   SYSTEMS
   ========================================================================== */
.sys{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.sys figure{margin:0;background:#fff;border:1px solid var(--line);
  border-radius:var(--r-panel);overflow:hidden}
.sys img{aspect-ratio:4/5;object-fit:cover;width:100%}
.sys figcaption{padding:22px;display:grid;gap:9px}
.sys p{font-size:14.5px;color:var(--ink-2)}
.kw{display:inline-flex;align-items:center;font-size:12.8px;font-weight:700;
  color:var(--ice-700);background:var(--ice-50);border-radius:var(--r-pill);
  padding:6px 13px;width:max-content}


/* ==========================================================================
   PRICE CONFIGURATOR

   One block, not a wall of boxes. It used to lay eight bordered white cards out
   in two columns, all open, which David called redundant and was right about:
   eight questions on screen at once is a form, and nobody fills in a form to
   find out a price. It is a stepper at every width now, two questions to a step
   on a desktop and one on a phone, inside a single gradient card with the price
   beside it.

   The two-per-step rule is in the note on `wide` in main.js: above one question
   per step, choosing an answer does not advance, because it would take the
   question next to it away before it had been read.
   ========================================================================== */
.pcfg{position:relative;isolation:isolate;overflow:hidden;
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,364px);
  gap:clamp(18px,2vw,28px);align-items:start;
  border-radius:clamp(20px,2.2vw,28px);padding:clamp(18px,2vw,28px);
  background:linear-gradient(150deg,var(--ink-900) 0%,var(--ice-900) 58%,var(--ice-800) 100%);
  box-shadow:0 30px 70px -34px rgba(17,83,111,.6)}
.pcfg::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(120% 90% at 86% 4%,rgba(99,188,230,.3),transparent 62%)}
/* ONE PANEL, several questions. It used to be two separate white cards side by
   side inside the gradient, and David's note is exactly right: two short cards
   in a wide card leaves a band of empty gradient under them and the whole thing
   reads as unfinished. One panel holding three questions stacked is the same
   information at the same size as the price panel beside it, so the card has
   two columns of roughly equal height and no dead space.

   The questions are rows in that panel now, divided by a hairline, rather than
   eight bordered boxes. */
.pcfg-qs{order:1;align-content:start;background:rgba(255,255,255,.97);
  border-radius:18px;overflow:hidden;box-shadow:0 14px 34px -20px rgba(6,20,28,.55);
  display:grid;grid-template-columns:minmax(0,1fr);gap:0}
.pcfg-out{order:2;background:rgba(8,18,28,.55);color:var(--on-dark);
  border:1px solid rgba(216,232,244,.14);border-radius:var(--r-panel);
  padding:clamp(20px,1.9vw,26px);display:grid;gap:13px;
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}

.pcfg-figure{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
.pcfg-money{font-family:var(--display);font-weight:800;letter-spacing:-.045em;
  line-height:1;color:#fff;font-size:clamp(30px,3vw,42px);
  font-variant-numeric:tabular-nums lining-nums}
.pcfg-to{color:var(--on-dark-3);font-size:15px}
.pcfg-vat{font-size:13.5px;color:var(--on-dark-2)}

.pcfg-bd{border-top:1px solid var(--line-dark);padding-top:12px}
.pcfg-bd-t{font-size:11.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--on-dark-3);margin-bottom:4px}
.pcfg-bd .bd{background:transparent;font-size:13.5px}
.pcfg-bd .bd td{border-bottom:1px solid var(--line-dark);color:var(--on-dark-2);padding:9px 0}
.pcfg-bd .bd td:last-child{text-align:right;color:#fff;font-weight:600;white-space:nowrap}
.pcfg-bd .bd tr:last-child td{border-bottom:0}
.pcfg-cta{display:grid;gap:9px}
.pcfg-out .btn--ghost{color:#fff;border-color:rgba(255,255,255,.34)}
.pcfg-out .btn--ghost:hover{background:rgba(255,255,255,.1);border-color:#fff}
.pcfg-note{font-size:12.5px;color:var(--on-dark-3);line-height:1.5}

.pcfg-q{background:none;border:0;border-radius:0;display:grid;align-content:start;
  box-shadow:none;border-bottom:1px solid var(--line)}
.pcfg-q:last-child,.pcfg-q.is-last{border-bottom:0}
/* The panel owns the rounding, so the first and last visible rows must not
   fight it. `:has` covers the stepped case where "first" changes per step. */
[data-stepped="on"] .pcfg-q.is-current:last-of-type{border-bottom:0}

.pcfg-row{display:flex;align-items:center;justify-content:space-between;gap:12px;
  width:100%;padding:16px 18px;background:none;border:0;cursor:pointer;text-align:left;
  font:inherit;color:inherit}
.pcfg-row-l{font-size:14.5px;font-weight:700;color:var(--ink)}
.pcfg-row-v{font-size:13.5px;font-weight:600;color:var(--ice-700);text-align:right}
.pcfg-opts{padding:0 18px 18px;display:grid;gap:12px}
.pcfg-help{font-size:13px;color:var(--ink-2);line-height:1.5}
.pcfg-chips{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.pcfg-chip{position:relative;display:block}
.pcfg-chip input{position:absolute;inset:0;opacity:0;cursor:pointer;margin:0}
.pcfg-chip span{display:grid;gap:2px;min-height:52px;padding:9px 13px;align-content:center;
  border:1.5px solid var(--line-2);border-radius:var(--r-input);background:#fff;cursor:pointer;
  transition:border-color .14s,background .14s}
.pcfg-chip b{font-size:13.8px;font-weight:600;color:var(--ink);line-height:1.25}
.pcfg-chip em{font-style:normal;font-size:11.8px;color:var(--ink-3);line-height:1.3}
.pcfg-chip input:hover + span{border-color:var(--ice-400)}
.pcfg-chip input:checked + span{border-color:var(--ice-600);background:var(--ice-50)}
.pcfg-chip input:checked + span b{color:var(--ice-700);font-weight:700}
.pcfg-chip input:focus-visible + span{outline:3px solid var(--ice-500);outline-offset:2px}
/* A checkbox needs to look different from a radio, or nobody realises they can
   pick more than one. */
.pcfg-chips--check .pcfg-chip span{padding-left:40px}
.pcfg-chips--check .pcfg-chip span::before{content:"";position:absolute;left:13px;top:50%;
  translate:0 -50%;width:18px;height:18px;border:1.5px solid var(--line-2);border-radius:5px;
  background:#fff;transition:background .14s,border-color .14s}
.pcfg-chips--check .pcfg-chip span::after{content:"";position:absolute;left:18px;top:50%;
  width:8px;height:4px;border-left:2px solid #fff;border-bottom:2px solid #fff;
  rotate:-45deg;translate:0 -70%;opacity:0;transition:opacity .14s}
.pcfg-chips--check .pcfg-chip input:checked + span::before{background:var(--ice-600);
  border-color:var(--ice-600)}
.pcfg-chips--check .pcfg-chip input:checked + span::after{opacity:1}

/* The stepped state, at every width now rather than only on a phone: the
   configurator opts in with data-step-size and the other calculators still only
   step below 720. See memory/forms-are-paged-on-mobile.md and the note on the
   stepper in main.js. */
[data-stepped="on"] [data-step]{display:none}
[data-stepped="on"] [data-step].is-current{display:grid}
[data-stepped="on"] .pcfg-q{display:none}
[data-stepped="on"] .pcfg-q.is-current{display:grid}
/* While stepping, the row header is the step title rather than a control. */
[data-stepped="on"] .pcfg-row{padding-bottom:0;pointer-events:none}
[data-stepped="on"] .pcfg-row::after{content:none}
[data-stepped="on"] .pcfg-row-v{display:none}
/* The extras question spans both columns when everything is shown; stepped, it
   is a step like any other. */
[data-stepped="on"] .pcfg-q--extras{grid-column:auto}

/* The stepper furniture sits on the gradient, so it inverts. */
.pcfg .stepnav{grid-column:1/-1;order:3;padding:2px 2px 0}
.pcfg .stepnav-bar{background:rgba(255,255,255,.18)}
.pcfg .stepnav-bar i{background:var(--ice-300)}
.pcfg .stepnav-n{color:var(--on-dark-2)}
.pcfg .stepbtn{background:rgba(255,255,255,.1);border-color:rgba(216,232,244,.28);color:#fff}
.pcfg .stepbtn:hover:not(:disabled){border-color:#fff;color:#fff}
.pcfg .stepbtn--next,.pcfg .stepbtn--next:hover{background:var(--ice-300);
  border-color:var(--ice-300);color:var(--ink)}

.pcfg-src{margin-top:22px;font-size:12.8px;color:var(--ink-3);max-width:88ch;line-height:1.55}

/* The chevron only exists where the rows actually collapse. */
.pcfg-row::after{content:none}

@media (max-width:1080px){
  .pcfg{grid-template-columns:1fr}
  .pcfg-out{order:0;position:sticky;top:calc(var(--nav-h) + 14px);z-index:5}
  .pcfg-qs{order:1}
}
@media (max-width:720px){
  .pcfg-qs{grid-template-columns:1fr;gap:10px}
  /* Compact price bar: one line, no breakdown open, nothing else competing. */
  .pcfg-out{padding:14px 16px;gap:10px;border-radius:var(--r-input);
    box-shadow:0 14px 34px -18px rgba(10,17,25,.7)}
  .pcfg-money{font-size:26px}
  .pcfg-vat{display:none}
  .pcfg-note{display:none}
  .pcfg-cta{grid-template-columns:1fr}
  .pcfg-out .btn{min-height:48px;font-size:14.5px}
  /* Dead accordion, removed 2026-09-05. `.pcfg-q:not(.is-open) .pcfg-opts
     { display: none }` outlived the JS that set `.is-open`: when the stepper
     replaced the accordion nothing added that class any more, so on a phone
     every question showed its title and none of its answers. The stepper shows
     one question at a time and shows it open, and with JS off all eight are
     open, which is the right fallback. */
  .pcfg-row{padding:15px 16px 4px}
  .pcfg-chips{grid-template-columns:1fr}
  .pcfg-chip span{min-height:50px}
}

/* ==========================================================================
   SERVICES BENTO
   The layout Sentry uses, adapted. Six services, six cells, no empty tiles:
   two columns of weight and two of support, so nothing becomes a letterbox.
   Every card is a real photograph of real work with a scrim and the text at
   the bottom, which is the whole reason it beats six icons in circles.
   ========================================================================== */
/* The three wrappers around the services grid are inert at every width:
   `display: contents` removes them from the layout entirely, so the cards are
   direct children of `.svc` and the grid works as if the wrappers were not
   there. They exist because this markup was a belt on a phone for a day, and
   the bento replaced it. */
.svc-belt{display:contents}
.svc-view{display:contents}
.svc-group{display:contents}

.svc{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:14.5rem;gap:14px}
.svc-card{position:relative;display:flex;align-items:flex-end;overflow:hidden;
  border-radius:var(--r-panel);text-decoration:none;background:var(--ink-850);isolation:isolate}
.svc-card--feature{grid-column:span 2;grid-row:span 2}
.svc-card--wide{grid-column:span 2;grid-row:span 2}
.svc-card--tall{grid-column:span 1;grid-row:span 2}
.svc-media{position:absolute;inset:0;z-index:0}
.svc-media img{width:100%;height:100%;object-fit:cover;transform:scale(1.02);
  filter:brightness(.86);transition:transform .9s cubic-bezier(.16,1,.3,1),filter .3s ease}
.svc-card:hover .svc-media img{transform:scale(1.07);filter:brightness(1)}
.svc-card::before{content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,rgba(10,17,25,0) 0%,rgba(10,17,25,.2) 34%,rgba(10,17,25,.78) 72%,rgba(10,17,25,.96) 100%)}
.svc-card::after{content:"";position:absolute;inset:0;z-index:3;border-radius:inherit;
  border:1px solid rgba(216,232,244,.16);pointer-events:none;transition:border-color .2s}
.svc-card:hover::after{border-color:var(--ice-400)}
.svc-body{position:relative;z-index:2;padding:clamp(18px,1.7vw,24px);width:100%}
.svc-price{display:block;font-size:12.5px;font-weight:700;color:var(--ice-300);margin-bottom:6px}
.svc-card--warm .svc-price{color:#F7A484}
.svc-name{font-family:var(--display);font-weight:800;letter-spacing:-.025em;
  color:#fff;font-size:19px;line-height:1.12}
.svc-card--feature .svc-name,.svc-card--wide .svc-name{font-size:clamp(21px,1.8vw,26px)}
.svc-sum{margin-top:8px;font-size:14.5px;line-height:1.5;color:rgba(231,238,244,.85);max-width:40ch}
/* Only the two big cards have room for a sentence. The rest stay quiet. */
.svc-card--tall .svc-sum{display:none}
.svc-cue{display:inline-flex;align-items:center;gap:7px;margin-top:12px;
  font-size:13.5px;font-weight:700;color:#fff}
.svc-cue::after{content:"";width:6px;height:6px;border-right:2px solid currentColor;
  border-top:2px solid currentColor;rotate:45deg;transition:translate .16s}
.svc-card:hover .svc-cue::after{translate:3px 0}

/* Integrated systems. Two cards, not a grid of six: there are exactly two of
   these products and a grid with four empty cells in it is a planning error. */
.intg{display:grid;gap:14px}
.intg-card{background:var(--ink-850);border:1px solid var(--line-dark);
  border-radius:var(--r-panel);padding:clamp(20px,2vw,26px);display:grid;gap:9px}
.intg-card h3{color:#fff;font-size:18px}
.intg-brand{font-size:13px;font-weight:700;color:var(--ice-300)}

/* Pictures in the integrated band. The cards were text on a dark ground; they
   are now a photograph with the text under it, and the copy column carries a
   third. Everything sits on --ink-850 rather than a border, so the cards read
   as objects on the band rather than as boxes drawn on it. */
.intg-card{overflow:hidden;padding:0;background:var(--ink-850);border:0}
.intg-media{aspect-ratio:16/9;overflow:hidden;background:var(--ink-800)}
.intg-media img{width:100%;height:100%;object-fit:cover;display:block}
.intg-body{padding:clamp(16px,1.6vw,22px)}
.intg-body h3{margin-bottom:4px}
.intg-fig{margin:clamp(20px,2.4vw,30px) 0 0;max-width:520px}
.intg-fig img{width:100%;height:auto;border-radius:var(--r-panel);display:block}
.intg-fig figcaption{margin-top:9px;font-size:12.5px;color:var(--on-dark-3)}
.intg-copy .lede + .lede{margin-top:14px}
.intg-copy .hero-cta{margin-top:clamp(20px,2.4vw,28px)}

.intg-card p:last-child{font-size:14.8px;color:var(--on-dark-2);line-height:1.6}

/* ==========================================================================
   COVERAGE MAP
   Real London borough boundaries, generated at build time from Office for
   National Statistics data. No tile service and no third party request, so the
   map costs the visitor nothing and cannot leak them to anyone.
   ========================================================================== */
.cov{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,420px);
  gap:var(--gap);align-items:center}
.cov-map{position:relative}
.cov-map svg{width:100%;height:auto;display:block;overflow:visible}
/* EVERY BOROUGH IS FILLED, and that is the point of this rule.

   The uncovered ones used to be white at 5%, which is all but invisible on the
   dark band, so the map said "we work in eleven boroughs and those grey shapes
   are somewhere else". We cover all thirty three. The difference between the
   two fills is now the difference between "most of our work is here" and "also
   here, same price", which is what it is, rather than the difference between
   coloured and absent. */
.cov-b{fill:rgba(99,188,230,.17);stroke:rgba(143,209,240,.4);stroke-width:.9;
  transition:fill .18s ease,stroke .18s ease}
.cov-b--on{fill:rgba(99,188,230,.52);stroke:var(--ice-200);stroke-width:1.4;cursor:pointer}
a:hover .cov-b--on,a:focus-visible .cov-b--on{fill:var(--ice-500);stroke:#fff}
.cov-label{font:600 11px var(--font);fill:#fff;paint-order:stroke;
  stroke:rgba(10,17,25,.8);stroke-width:3px;stroke-linejoin:round;pointer-events:none}
.cov-base{r:5;fill:var(--warm);stroke:#fff;stroke-width:2}
.cov-base-l{font:700 11.5px var(--font);fill:#fff;paint-order:stroke;
  stroke:rgba(10,17,25,.85);stroke-width:3.5px;stroke-linejoin:round}
.cov-key{list-style:none;display:flex;flex-wrap:wrap;gap:8px 20px;margin-top:22px;
  font-size:13px;color:var(--on-dark-2)}
.cov-key i{display:inline-block;width:13px;height:13px;border-radius:4px;
  margin-right:7px;vertical-align:-2px}
.cov-key .k1{background:rgba(99,188,230,.52);border:1px solid var(--ice-200)}
.cov-key .k2{background:rgba(99,188,230,.17);border:1px solid rgba(143,209,240,.4)}
.cov-key .k3{background:var(--warm)}
.cov-list{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-top:24px}
.cov-list a{display:block;padding:11px 14px;border-radius:var(--r-input);
  border:1px solid var(--line-dark);background:rgba(255,255,255,.04);
  text-decoration:none;color:#fff;font-size:14.5px;font-weight:600;
  transition:border-color .15s,background .15s}
.cov-list a:hover{border-color:var(--ice-400);background:rgba(55,160,147,.16)}
/* The collapsed state exists only once the script has said so, so with no
   JavaScript every borough is a plain link in a plain grid. */
.cov-list[data-collapsed] a:nth-child(n+7){display:none}
.cov-more{display:none;margin-top:12px;min-height:44px;width:100%;
  padding:0 16px;border-radius:var(--r-pill);cursor:pointer;
  border:1.5px solid var(--line-dark-2);background:rgba(255,255,255,.06);
  color:#fff;font:700 14px var(--font);transition:background .16s,border-color .16s}
.cov-more:hover{background:rgba(255,255,255,.12);border-color:var(--ice-400)}
.cov-more[data-on]{display:block}

/* ==========================================================================
   AREAS
   ========================================================================== */
.areas{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:11px}
.areas a{display:flex;align-items:center;justify-content:space-between;gap:10px;
  background:#fff;border:1px solid var(--line);border-radius:var(--r-input);
  padding:15px 18px;text-decoration:none;font-weight:600;font-size:15.5px;min-height:58px;
  transition:border-color .15s,transform .15s,box-shadow .15s}
.areas a:hover{border-color:var(--ice-500);transform:translateY(-2px);
  box-shadow:var(--sh-sm);color:var(--ice-700)}
.areas a span{font-size:12.8px;color:var(--ink-3);font-weight:500}

/* ==========================================================================
   STATS
   ========================================================================== */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:22px}
.stat{display:grid;gap:5px}
.stat .n{font-family:var(--display);font-size:clamp(30px,3vw,42px);font-weight:800;
  letter-spacing:-.04em;line-height:1;color:var(--ice-700)}
.stat .l{font-size:14.5px;color:var(--ink-2)}
.band--dark .stat .n{color:var(--ice-300)}
.band--dark .stat .l{color:var(--on-dark-2)}

/* ==========================================================================
   PRICE PANEL
   ========================================================================== */
.price-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--gap);align-items:start}
.price-card{background:#fff;border:1px solid var(--line);border-radius:var(--r-panel);
  padding:clamp(24px,2.4vw,34px)}
.figure{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.figure .stat-n{font-family:var(--display);font-size:clamp(38px,5vw,62px);font-weight:800;
  letter-spacing:-.045em;line-height:1;color:var(--ice-700)}
.figure .unit{color:var(--ink-2);font-size:16px;font-weight:500}
.sub{color:var(--ink-2);font-size:15px;margin-top:10px}
.srcnote{font-size:13.5px;color:var(--ink-2);margin-top:18px;background:var(--paper-50);
  padding:15px 17px;border-radius:var(--r-input)}
.tbar{height:8px;margin-top:22px;border-radius:99px;
  background:linear-gradient(90deg,var(--warm),#F0764A 26%,#D6DEE4 52%,var(--ice-400) 76%,var(--ice-200))}
.tbar-lab{display:flex;justify-content:space-between;font-size:12.8px;color:var(--ink-2);
  margin-top:9px;font-weight:500}
.tbar-lab .w{color:var(--warm-ink)}
.tbar-lab .c{color:var(--ice-700)}
.ptable{width:100%;font-size:15px}
.ptable caption{text-align:left;font-size:14px;font-weight:600;color:var(--ink);padding-bottom:12px}
.ptable th,.ptable td{padding:13px 0;border-bottom:1px solid var(--line);text-align:left}
.ptable thead th{font-size:12.5px;color:var(--ink-2);font-weight:700}
.ptable td:last-child,.ptable th:last-child{text-align:right;font-weight:600;color:var(--ice-700)}
.ptable tbody tr:last-child td{border-bottom:0}

/* ==========================================================================
   CALCULATORS
   ========================================================================== */
.calc{background:#fff;border:1px solid var(--line);border-radius:var(--r-panel);
  box-shadow:var(--sh);overflow:hidden}
.calc-hd{padding:clamp(24px,2.2vw,30px);border-bottom:1px solid var(--line);background:var(--paper-50)}
.calc-hd h2{font-size:var(--h-section)}
.calc-hd p{font-size:14.5px;color:var(--ink-2);margin-top:9px;max-width:58ch}
.calc-body{padding:clamp(24px,2.2vw,30px);display:grid;gap:22px}
.calc .fld > label,.calc .fld > legend{font-size:15px}
.calc-out{border-top:1px solid var(--line);background:var(--ice-50);
  padding:clamp(24px,2.2vw,30px);display:grid;gap:18px}
.calc-out[hidden]{display:none}
.price-row{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
.price-row .big{font-family:var(--display);font-size:clamp(36px,4.4vw,56px);font-weight:800;
  letter-spacing:-.045em;line-height:1;color:var(--ice-700)}
.price-row .unit{color:var(--ink-2);font-size:16px}
.price-row .tag{font-size:13.5px;font-weight:700;color:var(--ok);background:var(--ok-50);
  border-radius:var(--r-pill);padding:6px 14px}
.calc-note{font-size:13.5px;color:var(--ink-2)}
.calc-cta{display:grid;grid-template-columns:1fr 1fr;gap:11px}
.bd{width:100%;font-size:14.5px;background:#fff;border-radius:var(--r-input);overflow:hidden}
.bd th,.bd td{padding:12px 16px;border-bottom:1px solid var(--line);text-align:left}
.bd thead th{font-size:12.5px;background:var(--paper-50);font-weight:700}
.bd td:last-child,.bd th:last-child{text-align:right;font-weight:600;color:var(--ink)}
.bd tbody tr:last-child td{border-bottom:0}
.bd tfoot td{font-weight:700;color:var(--ice-700);background:var(--paper-50);border-bottom:0}

/* ==========================================================================
   FAQ
   ========================================================================== */
.faq{max-width:80ch;margin-inline:auto;display:grid;gap:10px}
.faq details{background:#fff;border:1px solid var(--line);border-radius:var(--r-panel);
  overflow:hidden;transition:border-color .18s}
.faq details[open]{border-color:var(--ice-400)}
.faq summary{padding:20px 56px 20px 24px;cursor:pointer;font-weight:600;font-size:16.5px;
  list-style:none;position:relative}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"";position:absolute;right:24px;top:50%;width:9px;height:9px;
  border-right:2.2px solid var(--ice-600);border-bottom:2.2px solid var(--ice-600);
  translate:0 -62%;rotate:45deg;transition:rotate .2s ease}
.faq details[open] summary::after{rotate:225deg;translate:0 -25%}
.faq details p{padding:0 24px 20px;color:var(--ink-2);font-size:15.5px}
.faq details p + p{padding-top:0}
.faq details a{color:var(--ice-700);font-weight:500}

/* FAQ page: a jump nav and grouped sections, because thirty questions in one
   undifferentiated accordion is a page nobody reaches the bottom of. */
.faq-nav{display:flex;flex-wrap:wrap;gap:9px;margin-bottom:var(--gap)}
.faq-nav a{display:inline-flex;align-items:center;min-height:42px;padding:0 16px;
  border-radius:var(--r-pill);border:1px solid var(--line-2);background:#fff;
  text-decoration:none;font-size:14px;font-weight:600;color:var(--ink);
  transition:border-color .15s,background .15s,color .15s}
.faq-nav a:hover{border-color:var(--ice-500);background:var(--ice-50);color:var(--ice-700)}
.faq-group{margin-top:var(--band)}
.faq-group:first-of-type{margin-top:0}
.faq-group > h2{margin-bottom:var(--gap)}
.faq-group .faq{margin-inline:0;max-width:none}

/* ==========================================================================
   CLOSING CALL TO ACTION
   A card with a gradient, the shape Flame Shield uses, rather than a full bleed
   band. The band version sat directly above a footer that opened with its own
   dark call to action, so every page appeared to end twice.
   ========================================================================== */
.ctacard{position:relative;isolation:isolate;overflow:hidden;
  border-radius:clamp(20px,2.4vw,30px);
  padding:clamp(30px,4vw,58px) clamp(24px,3.4vw,52px);
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--gap);align-items:center;
  background:linear-gradient(118deg,var(--ink-900) 0%,var(--ice-700) 58%,var(--ice-500) 100%);
  box-shadow:0 30px 70px -34px rgba(17,83,111,.6)}
/* A soft light source in the top right corner, so the gradient reads as a
   material rather than as two colours meeting. */
.ctacard::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(120% 150% at 88% 0%,rgba(143,209,240,.34),transparent 58%)}
/* The one deliberate exception. It is a section heading, but it sits in a
   card beside a form, so it takes the section size capped lower. */
.ctacard h2{color:#fff;font-size:clamp(25px,2.7vw,36px);max-width:17ch}
/* Scoped to the copy column on purpose. A bare `.ctacard p` also caught the
   reassurance line inside the white form panel and painted it near-white on
   white, which is an invisible line under the one button that matters. */
.ctacard-t p{color:rgba(231,238,244,.9);max-width:50ch;margin-top:12px;
  font-size:clamp(15px,.4vw + 14px,17px)}
.ctacard-b{display:flex;flex-wrap:wrap;gap:11px}
/* On a coloured ground the accent button disappears, so the primary inverts. */
.btn--onbrand{background:var(--ice-300);color:var(--ink)}
.btn--onbrand:hover{background:var(--ice-200);color:var(--ink);
  box-shadow:0 18px 40px -18px rgba(0,0,0,.45)}
.ctacard .btn--ghost-d{color:#fff;border-color:rgba(255,255,255,.45)}
.ctacard .btn--ghost-d:hover{background:rgba(255,255,255,.14);border-color:#fff}
.ctacard-b{margin-top:26px}

/* The form variant. Every page except /contact/ ends on this, because a closing
   block whose only conversion is a link to another page loses the visitor who
   was ready on this one. Left: the argument and the two instant channels.
   Right: four fields on a white panel, because the form styles are written for
   a light ground and re-colouring them for the gradient would fork them. */
.ctacard--form{grid-template-columns:minmax(0,1fr) minmax(340px,400px);
  align-items:start;
  padding:clamp(26px,3.4vw,44px) clamp(22px,3vw,44px)}
.ctacard--form .ctacard-t{align-self:center}
.ctacard--form h2{max-width:14ch}
.ctacard--form .ctacard-t p{max-width:40ch}
.ctacard-form{background:#fff;border-radius:clamp(14px,1.4vw,18px);
  padding:clamp(18px,1.8vw,24px);box-shadow:0 20px 50px -26px rgba(10,17,25,.5)}
.ctacard-form-t{font-family:var(--display);font-weight:800;letter-spacing:-.02em;
  font-size:17px;color:var(--ink);margin:0 0 14px}
.ctacard-form .lead-foot{color:var(--ink-3)}
.ctacard-form .lead-foot.is-err{color:var(--stop)}
.ctacard-form .lead-foot.is-ok{color:var(--ok)}

/* ==========================================================================
   CONTACT
   ========================================================================== */
.contact-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,420px);
  gap:var(--gap);align-items:start}
.cmethod{display:grid;gap:12px}
.cmethod a{display:flex;gap:16px;align-items:center;background:#fff;border:1px solid var(--line);
  border-radius:var(--r-panel);padding:20px 22px;text-decoration:none;
  transition:border-color .15s,transform .15s,box-shadow .15s}
.cmethod a:hover{border-color:var(--ice-500);transform:translateY(-2px);box-shadow:var(--sh-sm)}
.cmethod .ic-lg{flex:0 0 auto}
.cmethod b{display:block;font-size:17px;font-weight:700;color:var(--ink)}
.cmethod span{display:block;font-size:14px;color:var(--ink-2);margin-top:2px}
.cmethod .is-wa .ic-lg{color:#16853F}

.imgcard{border-radius:var(--r-panel);overflow:hidden;border:1px solid var(--line);background:#fff}
.imgcard img{width:100%;aspect-ratio:4/3;object-fit:cover}
.imgcard figcaption{padding:16px 20px;font-size:14px;color:var(--ink-2)}

/* ==========================================================================
   FOOTER
   Three zones with real hierarchy: a closing call to action, then the
   navigation and the company facts side by side, then one quiet legal line.
   The old one was a four column link dump with a table in it.
   ========================================================================== */
.ftr{background:var(--ink-950);color:var(--on-dark-2);font-size:14.5px}
.ftr-cta{padding-block:var(--band);border-bottom:1px solid var(--line-dark)}
.ftr-cta-in{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--gap);align-items:center}
.ftr-cta h2{color:#fff;font-size:clamp(26px,2.8vw,40px);max-width:17ch}
.ftr-cta p{color:var(--on-dark-2);max-width:52ch;margin-top:12px}
.ftr-cta-b{display:flex;flex-wrap:wrap;gap:12px}

.ftr-main{padding-block:clamp(34px,3.4vw,50px);
  display:grid;grid-template-columns:minmax(0,1.5fr) repeat(3,minmax(0,1fr));gap:var(--gap)}
.ftr h3{color:#fff;font-size:13px;font-weight:700;letter-spacing:.01em;margin-bottom:16px}
.ftr ul{list-style:none;display:grid;gap:11px}
.ftr a{color:var(--on-dark-2);text-decoration:none}
.ftr a:hover{color:var(--ice-300)}
.ftr-about p{margin-top:18px;max-width:38ch;font-size:14px;line-height:1.62}


.ftr-nap{display:grid;gap:9px;margin-top:20px;font-size:14px}
.ftr-nap a{color:#fff;font-weight:600}
.ftr-nap span{color:var(--on-dark-3)}

/* Prefixed with .ftr for the same reason the policy links are: `.ftr ul` is
   two classes and sets display:grid for the footer's link columns, so a bare
   .soc lost and the social buttons stacked into a vertical column. Any list
   dropped into the footer has to out-specify that rule or inherit a grid. */
.ftr .soc{list-style:none;display:flex;gap:9px;margin-top:22px}
.soc a{display:grid;place-items:center;width:42px;height:42px;border-radius:var(--r-pill);
  background:rgba(255,255,255,.07);border:1px solid var(--line-dark);
  transition:background .16s,transform .16s,border-color .16s}
.soc a:hover{background:var(--ice-600);border-color:var(--ice-600);transform:translateY(-2px)}
.soc svg{width:18px;height:18px;fill:#fff}

.ftr-legal{border-top:1px solid var(--line-dark);padding-block:20px 26px;
  display:grid;gap:16px;font-size:13px;color:var(--on-dark-3)}
.ftr-legal p{max-width:96ch;line-height:1.6}
/* `.ftr ul` is two classes and this was one, so the policy links inherited the
   column grid from the footer's link lists and stacked into six rows, which is
   most of what made the footer feel long. */
.ftr .ftr-legal-nav{display:flex;flex-wrap:wrap;gap:8px 22px}

/* ==========================================================================
   WHATSAPP LAUNCHER
   Replaces the sticky bottom bar, which was eating 72px of every phone screen
   on every page.

   It opens a small compose panel rather than jumping straight out to WhatsApp,
   because a wa.me link hands us a message the visitor never wrote, and on
   desktop it throws them into WhatsApp Web with no idea what happened. Here
   they edit a draft and press send, so what arrives is in their words.
   ========================================================================== */
.wa-fab{position:fixed;right:clamp(14px,2vw,26px);bottom:clamp(14px,2vw,26px);z-index:96;
  width:58px;height:58px;border:0;border-radius:var(--r-pill);cursor:pointer;
  background:#16853F;color:#fff;display:grid;place-items:center;padding:0;
  box-shadow:0 14px 34px -10px rgba(31,168,85,.55),0 4px 10px -4px rgba(10,17,25,.4);
  transition:transform .18s ease,background .18s ease}
.wa-fab svg{width:28px;height:28px}
.wa-fab:hover{background:#0F6D32;transform:translateY(-2px) scale(1.04)}
.wa-fab[aria-expanded=true]{transform:scale(.9)}

/* The nudge. Appears once, a few seconds in, and not again in that session. */
.wa-panel{position:fixed;right:clamp(14px,2vw,26px);
  bottom:calc(clamp(14px,2vw,26px) + 70px);z-index:97;
  width:min(360px,calc(100vw - 28px));background:var(--paper-50);
  border-radius:var(--r-panel);overflow:hidden;box-shadow:var(--sh-lg);
  border:1px solid var(--line);animation:wa-pop .34s cubic-bezier(.16,1,.3,1) both}
.wa-panel[hidden]{display:none}
.wa-head{display:flex;align-items:center;gap:11px;padding:14px 16px;background:#16853F;color:#fff}
.wa-avatar{display:grid;place-items:center;width:36px;height:36px;flex:0 0 auto;
  border-radius:var(--r-pill);background:rgba(255,255,255,.2)}
.wa-avatar svg{width:19px;height:19px}
.wa-id{display:grid;gap:1px;flex:1;min-width:0}
.wa-id strong{font-size:14.5px;font-weight:700}
.wa-id small{font-size:12px;opacity:.85}
.wa-close{width:30px;height:30px;border:0;background:none;color:#fff;cursor:pointer;
  border-radius:var(--r-pill);display:grid;place-items:center;flex:0 0 auto}
.wa-close:hover{background:rgba(255,255,255,.18)}
.wa-close svg{width:14px;height:14px}
.wa-body{padding:18px 16px 8px;background:#EDE5DC}
.wa-bubble{background:#fff;border-radius:4px 14px 14px 14px;padding:12px 14px;
  box-shadow:0 1px 2px rgba(10,17,25,.14);max-width:92%}
.wa-bubble p{font-size:14.5px;line-height:1.5;color:var(--ink)}
.wa-from{display:block;margin-top:5px;font-size:11px;color:var(--ink-3)}
.wa-compose{padding:12px 14px 14px;background:#EDE5DC;display:grid;gap:9px}
.wa-compose textarea{width:100%;border:1px solid var(--line-2);border-radius:14px;
  padding:11px 13px;font:400 14.5px/1.5 var(--font);color:var(--ink);background:#fff;
  resize:vertical;min-height:76px}
.wa-compose textarea:focus{outline:none;border-color:#16853F;
  box-shadow:0 0 0 3px rgba(31,168,85,.18)}
.wa-compose-row{display:flex;align-items:center;justify-content:space-between;gap:10px}
.wa-hint{font-size:12px;color:var(--ink-2)}
.wa-send{display:inline-flex;align-items:center;gap:7px;min-height:42px;padding:0 18px;
  border:0;border-radius:var(--r-pill);background:#16853F;color:#fff;
  font:700 14px var(--font);cursor:pointer;transition:background .16s}
.wa-send:hover{background:#0F6D32}
.wa-send svg{width:15px;height:15px}

/* ==========================================================================
   UTILITIES
   ========================================================================== */
.center{text-align:center}
.muted{color:var(--ink-2)}
.small{font-size:14px}
.pill{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:700;
  color:var(--ice-700);background:var(--ice-50);border-radius:var(--r-pill);
  padding:7px 15px;width:max-content}
.pill--warm{color:var(--warm-ink);background:var(--warm-50)}
.pill--ok{color:var(--ok);background:var(--ok-50)}
.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.gallery img{border-radius:var(--r-input);aspect-ratio:3/4;object-fit:cover;width:100%;
  border:1px solid var(--line)}

/* ==========================================================================
   RESPONSIVE
   Designed at 375 first. Every multi column layout declares its collapse.
   ========================================================================== */
@media (max-width:1460px){
  .nav-tel{display:none}
}
@media (max-width:1180px){
  .navlinks > li > a{padding:10px 7px;font-size:13.5px}
  .hero-grid{grid-template-columns:1fr;align-items:start}
  .hero h1{max-width:18ch}
  .pcheck{max-width:560px}
  .cov{grid-template-columns:1fr}
  .sub{min-width:290px}
  .phero-grid{grid-template-columns:1fr}
  .quotecard{max-width:520px}
  .pcheck-grid{grid-template-columns:1fr}
  .pcheck{max-width:560px}
}
@media (max-width:1080px){
  .cards,.cards--4,.steps,.stats,.areas,.qcards,.sys{grid-template-columns:repeat(2,1fr)}
  .svc{grid-template-columns:repeat(2,1fr);grid-auto-rows:13rem}
  .svc-card--feature,.svc-card--wide{grid-column:span 2;grid-row:span 2}
  .svc-card--tall{grid-column:span 1;grid-row:span 2}
  .creds-list{grid-template-columns:repeat(2,1fr)}
  .steps li + li{border-left:0}
  .steps li:nth-child(even){border-left:1px solid var(--line)}
  .steps li:nth-child(n+3){border-top:1px solid var(--line)}
  .split,.contact-grid,.price-grid{grid-template-columns:1fr}
  .sticky-side{position:static}
  .ctacard,.ctacard--form{grid-template-columns:1fr}
  .ctacard-b{margin-top:22px}
  .ftr-main{grid-template-columns:1fr 1fr}
  .gallery{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:940px){
  .navlinks,.nav-tel{display:none}
  .burger{display:grid}
  .nav{padding-left:16px}
  .estbar-chips{display:none}
}
@media (max-width:720px){
  /* The capsule is 64px here and holds two things: the logo and the burger.
     Both were too small and the burger sat too far in from the edge, which is
     what made the three lines look dropped in at random rather than placed.
     The bar now runs closer to the screen edge (10px, not the page --pad), the
     logo is 44px instead of 36, and the burger is flush against the capsule's
     own 6px of padding so its right edge lands 16px from the screen. */
  :root{--nav-h:64px}
  .navwrap{top:10px}
  .navwrap > .wrap{width:calc(100% - 20px)}
  .nav{padding:6px 6px 6px 14px;gap:6px}
  .logo{height:44px}
  .burger{width:52px;height:52px}
  .nav-cta{display:none}
  .hero{padding-top:calc(var(--nav-h) + 40px)}
  .hero-in{max-width:none}
  .hero h1{font-size:clamp(32px,8.6vw,44px)}
  .hero p{font-size:16px;margin-top:16px}
  .hero-cta{margin-top:24px}
  .hero-cta .btn{flex:1 1 100%}
  /* The call button goes: the number is in the strip at the top of every page
     and in the WhatsApp button beside this one, and what a phone visitor needs
     here is the way down to the form. */
  .btn--callonly{display:none}
  .btn--jump{display:inline-flex}
  .only-narrow{display:inline}
  .only-wide{display:none}
  .hero-form-hd h2{font-size:19px}
  .hero-form-hd p{font-size:13px}
  /* Three buttons at three different widths reads as an accident. On a
     phone they stack, so they take the full width like the hero pair. */
  .ctacard-b .btn{flex:1 1 100%}
  /* On a phone the copy runs the full width, so the veil has to be vertical
     rather than horizontal: dark where the headline and the two buttons are,
     and then it lets go for the strip above the form, which is where the clip
     gets to be seen. */
  .hero-veil,.phero-veil{background:
    linear-gradient(180deg,rgba(10,17,25,.86) 0%,rgba(10,17,25,.8) 34%,rgba(10,17,25,.5) 58%,rgba(10,17,25,.22) 78%,rgba(10,17,25,.55) 100%)}
  .estbar-in{padding:16px 18px}
  .phero{padding-top:calc(var(--nav-h) + 40px)}
  .phero-cta .btn{flex:1 1 100%}
  .cards,.cards--2,.cards--4,.steps,.areas,.qcards,.sys{grid-template-columns:1fr}
  /* THE TEN YEARS BLOCK ON A PHONE.

     David: it has far too much writing, make it look completely different or
     take it out. On a desktop the copy sits beside the photographs and reads as
     one object; stacked on a phone it became roughly 400 words in a column,
     which nobody scrolls.

     So on a phone it is a different section rather than the same one narrower.
     The photographs come first, because they are the argument. The long second
     paragraph goes: it repeats the company detail that is already in the footer
     and on the about page. The three arguments underneath become a swipe row,
     the same shape as the services belt, so they cost one screen instead of
     three. Nothing is deleted from the page, it is re-shaped. */
  /* The order David asked for: heading, one line, the two buttons, the table,
     then the photographs. `display: contents` on the copy column is what makes
     it possible at all: the buttons and the table live inside .tenyr-copy and
     the photographs are its sibling, so without dissolving that wrapper there
     is no single flow to order them in. */
  .tenyr{grid-template-columns:1fr;gap:0}
  .tenyr-copy{display:contents}
  .tenyr-copy h2{order:1}
  .tenyr-copy .lede{order:2;font-size:16px;margin-top:12px}
  .tenyr-copy > p:not(.lede){display:none}
  .tenyr-cta{order:3;margin-top:18px}
  .tenyr-facts{order:4;grid-template-columns:1fr 1fr;margin-top:18px}
  .tenyr-facts li{padding:13px 14px}
  .tenyr-facts span{font-size:12.5px}
  .wall{order:5;height:300px;max-width:none;margin-top:18px}
  .accs{order:6;gap:12px;margin-top:18px}
  .accs span{font-size:13px}

  /* Both buttons on one row, so they read as a pair rather than a stack. They
     shrink to do it: 1 1 0 shares the width equally whatever the labels are. */
  .tenyr-cta{display:flex;flex-wrap:nowrap;gap:9px}
  .tenyr-cta .btn{flex:1 1 0;min-width:0;min-height:48px;padding:0 10px;
    font-size:13.5px;white-space:nowrap}

  /* Folded on every width now, so the phone needs no special shape for them. */
  .says{order:7;margin-top:18px}
  .say > summary{padding:14px 15px;font-size:16px}
  .say > p{padding:0 15px 15px;font-size:14px}
  /* THE BENTO ON A PHONE.

     Same idea as the desktop grid, half the columns. Six services stacked full
     width ran to about five screens, which is what the belt was for; a two
     column mosaic does the same job in one screen and keeps the thing that made
     the desktop version work, which is that the tiles are not all the same size.

     The pattern fills exactly, no holes:

        row 1-2   [ 1 . . . . . . . 1 ]   air conditioning, the headline
        row 3     [ 2 ] [ 3 ]             ducted, servicing
        row 4-5   [ 4 . . . . . . . 4 ]   heat pumps, the other money service
        row 6     [ 5 ] [ 6 ]             solar, battery

     Placed by position rather than by the span classes, because four of the six
     services share `--tall` and the phone layout needs to tell them apart. If a
     service is added or reordered, this block is where it shows. */
  /* 8.6rem, not 8. At 8 the one small tile whose name wraps to two lines,
     "Ducted air conditioning", had its price label pressed against it. Half a
     rem across four small tiles costs 20px of page and fixes all of them. */
  .svc{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:8.6rem;gap:10px}
  .svc-card,.svc-card--feature,.svc-card--wide,.svc-card--tall{
    grid-column:span 1;grid-row:span 1}
  .svc-card:nth-child(1),.svc-card:nth-child(4){grid-column:span 2;grid-row:span 2}
  .svc-body{padding:14px}
  .svc-name{font-size:16px}
  .svc-card:nth-child(1) .svc-name,
  .svc-card:nth-child(4) .svc-name{font-size:clamp(20px,5.6vw,24px)}
  .svc-price{font-size:11.5px;line-height:1.3;margin-bottom:5px}
  /* The summary only has room on the two big tiles. */
  .svc-sum{display:none}
  .svc-card:nth-child(1) .svc-sum,
  .svc-card:nth-child(4) .svc-sum{display:block;font-size:13.5px;margin-top:6px}
  .svc-cue{font-size:12.5px;white-space:nowrap}
  .svc-card--tall .svc-sum{display:block}
  /* Two columns on a phone as well, not one. Eleven boroughs in a single
     column is eleven rows of one word in a section that is mostly a map, and
     David's note is that it stretches the section for nothing. Two columns
     halves it, and the show more button halves it again until it is wanted. */
  .cov-list{grid-template-columns:1fr 1fr;gap:7px}
  .cov-list a{padding:10px 11px;font-size:13.5px}
  .creds-list,.stats{grid-template-columns:1fr 1fr}
  .steps li + li{border-left:0;border-top:1px solid var(--line)}
  .steps li:nth-child(even){border-left:0}
  .ftr-main{grid-template-columns:1fr;gap:34px}
  .calc-cta,.verdict-cta{grid-template-columns:1fr}
  .gallery{grid-template-columns:repeat(2,1fr)}
  .hl{white-space:normal}
  .answer{border-radius:var(--r-panel)}
  /* On a phone the same card goes to one column and the price leads, because
     the DOM order is result, questions, stepper. */
  .pcfg{grid-template-columns:minmax(0,1fr);gap:0;padding:14px 14px 16px}
  .pcfg-qs{grid-template-columns:minmax(0,1fr);order:0;gap:10px;margin-top:12px}
  .pcfg-row-l{font-size:16px}
  .pcfg .stepnav{order:0;margin-top:12px}
  /* Not sticky on a phone. The panel is a price, a breakdown and two buttons:
     roughly 250px, a third of the screen, and pinning it left the current
     question underneath it with nothing visible but Back and Next. It sits at
     the top of the card and scrolls with everything else.

     The inverted stepper furniture that used to be here was NOT scoped, so it
     was also repainting the Back and Next buttons of the running cost and
     sizing calculators, which sit on white. White on white. Those rules are on
     `.pcfg` now, where the gradient they were written for actually is. */
  .pcfg-out{order:0;position:static;border-radius:18px;padding:18px}

}
@media (max-width:420px){
  .seg{grid-template-columns:1fr}
  .creds-list{grid-template-columns:1fr}
}

/* ==========================================================================
   MOTION
   Instructed policy: animations run on any desktop regardless of the OS
   setting, and the preference is honoured on touch and narrow only.
   memory/motion-policy-desktop-override.md
   ========================================================================== */
@media (prefers-reduced-motion:reduce) and (max-width:899px){
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
@media (prefers-reduced-motion:reduce) and (pointer:coarse){
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
@media (prefers-reduced-transparency:reduce){
  .nav{background:rgba(15,26,36,.97);backdrop-filter:none;-webkit-backdrop-filter:none}
  .estbar-in{background:#fff;backdrop-filter:none;-webkit-backdrop-filter:none}
}
@media print{.navwrap,.sheet,.wa-fab,.wa-panel,.wa-scrim,.crumbs,.ctacard{display:none!important}}
