@charset "UTF-8";
/* =============================================================================
   The Electrician London Ltd — "Voltline" design system.
   Rewritten from scratch, 2026. Hand-written, no framework.

   Direction: ink-black surfaces, one electric red, warm off-white paper,
   oversized Sora display type, hairline-bordered cards, generous air.

   Contents
     01  Fonts
     02  Design tokens
     03  Reset and base
     04  Layout primitives
     05  Typography
     06  Buttons and links
     07  Header, navigation, mobile drawer
     08  Mobile bottom bar
     09  Home hero and page hero
     10  Marquee and trust bar
     11  Sections, panels, split
     12  Cards
     13  Case studies
     14  Process, stats, tables, chips
     15  FAQ
     16  Testimonials and rating
     17  Coverage
     18  Forms
     19  Emergency strip and CTA band
     20  Footer
     21  Breadcrumbs
     22  Lightbox
     23  Cookie banner
     24  Utilities
     25  Motion
     26  Reduced motion and print
   ========================================================================== */

/* -----------------------------------------------------------------------------
   01  FONTS
   Sora carries every heading. Plus Jakarta Sans carries everything else.
   Both are variable, self-hosted, and split latin / latin-ext so a page of
   English never downloads the accented glyphs.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Sora';
  src: url('../fonts/sora-latin.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Sora';
  src: url('../fonts/sora-latin-ext.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Jakarta';
  src: url('../fonts/jakarta-latin.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Jakarta';
  src: url('../fonts/jakarta-latin-ext.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* -----------------------------------------------------------------------------
   02  DESIGN TOKENS
   -------------------------------------------------------------------------- */

:root {
  /* Ink — the dark surfaces ------------------------------------------------ */
  --ink-950: #08090C;
  --ink-900: #0C0E13;
  --ink-850: #12141A;
  --ink-800: #171A21;
  --ink-700: #1F232C;
  --ink-600: #2A2F3A;
  --ink-500: #3A4150;

  /* Paper — the light surfaces -------------------------------------------- */
  --white:   #FFFFFF;
  --paper:   #F7F6F3;
  --paper-2: #EFEDE8;
  --line:    #E4E1DA;
  --line-2:  #D6D2C9;

  /* Text ------------------------------------------------------------------ */
  --text:        #0C0E13;
  --text-soft:   #565D6E;
  /* 5.11:1 on white and 4.73:1 on --paper. It carries 13px labels, so it
     has to clear 4.5:1; the lighter #7A8191 it replaced was 3.91:1. */
  --text-mute:   #666E80;
  --on-dark:     #FFFFFF;
  --on-dark-soft:#A9B0C0;
  /* 4.79:1 on the translucent panels, 6.18:1 on --ink-900. The lighter
     #767E90 it replaced measured 3.67:1 on the coverage base panel. */
  --on-dark-mute:#8A92A4;

  /* Brand — the blue of the logo bolt, used with discipline ---------------
     The bolt colour itself is 3.38:1 on white. That clears the 3:1 a graphic
     needs and fails the 4.5:1 text needs, so it is never used for words on a
     light background: --blue-deep carries white button labels at 4.74:1 and
     --blue-ink carries link text at 5.96:1. */
  /* Contrast is symmetric, so one working blue can serve both directions:
     4.74:1 against white means white labels on a blue fill pass AA and blue
     text on white passes AA, which is what lets a single token carry icons,
     fills, borders and text. The logo bolt is 3.38:1 and can do neither, so
     it stays on the mark it came from and nowhere else. */
  --blue:      #0079B8;   /* 4.74:1 both ways — the working brand colour    */
  --blue-bolt: #0093DD;   /* the logo only: 3.38:1, a graphic not a colour  */
  --blue-hot:  #54BEF0;   /* 9.19:1 on --ink-900, for accents on dark       */
  --blue-deep: #005B8A;   /* 7.33:1 — darker fills and hover                */
  --blue-ink:  #00699F;   /* 5.96:1 on white — the default link colour      */
  --blue-tint: #EDF6FD;
  --blue-line: #B9DFF3;

  /* Signal amber — stars, small highlights, never large areas ------------- */
  --amber:      #FFB800;
  --amber-ink:  #8A6100;  /* 5.54:1 on white, for text                       */
  --amber-graphic: #B8860B; /* 3.25:1 on white, for star glyphs on paper     */
  --amber-tint: #FFF6E0;

  /* Status ---------------------------------------------------------------- */
  --danger:       #B3261E;
  --danger-tint:  #FDECEA;
  --success:      #12694A;
  --success-tint: #E6F4EE;
  --warn-tint:    #FFF7E3;

  /* Radii ----------------------------------------------------------------- */
  --r-xs:  6px;
  --r-sm:  10px;
  --r-md:  16px;
  --r-lg:  24px;
  --r-xl:  32px;
  --r-pill: 999px;

  /* Shadows — soft and low, never a drop-shadow halo ---------------------- */
  --sh-1: 0 1px 2px rgba(12, 14, 19, .05);
  --sh-2: 0 4px 16px rgba(12, 14, 19, .07);
  --sh-3: 0 14px 40px rgba(12, 14, 19, .10);
  --sh-4: 0 26px 70px rgba(12, 14, 19, .16);
  --sh-blue: 0 12px 30px rgba(0, 121, 184, .30);

  /* Spacing scale --------------------------------------------------------- */
  --s-1: .25rem;  --s-2: .5rem;   --s-3: .75rem;  --s-4: 1rem;
  --s-5: 1.5rem;  --s-6: 2rem;    --s-7: 3rem;    --s-8: 4rem;
  --s-9: 5.5rem;  --s-10: 7rem;

  /* Layout ---------------------------------------------------------------- */
  --wrap: 1240px;
  --gutter: clamp(1.15rem, 4vw, 2.5rem);
  --header-h: 76px;

  /* Type scale — fluid, all clamped -------------------------------------- */
  --fs-display: clamp(2.6rem, 1.3rem + 5.4vw, 5.25rem);
  --fs-h1:      clamp(2.15rem, 1.2rem + 3.9vw, 3.9rem);
  --fs-h2:      clamp(1.8rem, 1.15rem + 2.6vw, 2.95rem);
  --fs-h3:      clamp(1.2rem, 1.02rem + .74vw, 1.55rem);
  --fs-h4:      clamp(1.05rem, .98rem + .34vw, 1.2rem);
  --fs-lede:    clamp(1.05rem, .99rem + .38vw, 1.28rem);
  --fs-body:    1.0625rem;
  --fs-sm:      .9375rem;
  --fs-xs:      .8125rem;
  --fs-micro:   .72rem;

  --ff-display: 'Sora', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --ff-body: 'Jakarta', 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;

  --ease: cubic-bezier(.22, .61, .36, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --dur: .38s;
}

/* -----------------------------------------------------------------------------
   03  RESET AND BASE
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 20px);
}

body {
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  line-height: 1.68;
  color: var(--text);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

img, picture, svg, video { display: block; max-width: 100%; }
img { height: auto; border-style: none; }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }

a { color: var(--blue-ink); text-decoration-thickness: 1px; text-underline-offset: .18em; }

/* :where() so this rule carries zero specificity and reaches only the links
   that no component has claimed. Written plainly as a:hover it would be (0,1,1)
   and beat every component that sets its own colour with a single class, which
   is how a primary button ends up painting red text on its own red fill. */
a:where(:hover) { color: var(--blue); }

ul, ol { padding: 0; list-style: none; }

/* The focus ring is two-tone and has to stay that way.

   A single colour cannot work here. Primary buttons and the emergency strip are
   filled with --blue, dark sections are filled with --ink-900, and the rest of
   the site is white, so whichever single colour is picked there is a surface
   where the ring lands on its own colour and disappears. Ink carries the ring
   on light surfaces and on the red fills; the white band carries it on the dark
   ones.

   Anything that sets box-shadow inside its own :focus-visible wipes the white
   band out. Change outline-color instead, or repeat the band. */
:focus-visible {
  outline: 3px solid var(--ink-900);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--white);
  border-radius: 3px;
}

::selection { background: var(--blue); color: #fff; }

hr { border: 0; border-top: 1px solid var(--line); margin: var(--s-7) 0; }

/* -----------------------------------------------------------------------------
   04  LAYOUT PRIMITIVES
   -------------------------------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--narrow { max-width: 820px; }

.section {
  padding-block: clamp(3.5rem, 2rem + 6vw, 7rem);
  position: relative;
}
.section--tight { padding-block: clamp(2.5rem, 1.6rem + 4vw, 4.5rem); }
.section--lg    { padding-block: clamp(4.5rem, 2.4rem + 8vw, 9rem); }

.section--alt  { background: var(--paper); }
.section--deep {
  background: var(--ink-900);
  color: var(--on-dark);
}
.section--deep h1, .section--deep h2, .section--deep h3,
.section--deep h4, .section--deep strong { color: var(--on-dark); }
.section--deep p, .section--deep li { color: var(--on-dark-soft); }

/* A faint circuit grid, so the dark sections are never a flat black slab. */
.section--deep::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .5;
  background-image:
    linear-gradient(rgba(255,255,255,.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.035) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, #000 20%, transparent 78%);
  mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, #000 20%, transparent 78%);
}
.section--deep > * { position: relative; z-index: 1; }

.grid { display: grid; gap: clamp(1.1rem, .6rem + 1.6vw, 1.9rem); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr)); }

.split {
  display: grid;
  gap: clamp(1.8rem, 1rem + 3.6vw, 4.5rem);
  align-items: start;
}
@media (min-width: 900px) {
  /* Top aligned by default. Several service pages put a very long prose column
     beside a short media column, and centring those left a half-screen hole
     above the photograph. It is also what makes --sticky-lead work: a centred
     grid item is only as tall as its content, so a sticky child inside one has
     nowhere to travel. */
  .split { grid-template-columns: 1fr 1fr; align-items: start; }
  .split--center { align-items: center; }
  .split--sticky-lead > :first-child { position: sticky; top: calc(var(--header-h) + 2rem); }
}
.split__media { position: relative; }
.split__media picture,
.split__media img { border-radius: var(--r-lg); overflow: hidden; }
.split__media > picture { box-shadow: var(--sh-3); }

/* -----------------------------------------------------------------------------
   05  TYPOGRAPHY
   -------------------------------------------------------------------------- */

h1, h2, h3, h4, h5, h6 {
  font-family: var(--ff-display);
  color: var(--text);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.03em;
  text-wrap: balance;
}

h1 { font-size: var(--fs-h1); font-weight: 800; }
h2 { font-size: var(--fs-h2); font-weight: 700; }
h3 { font-size: var(--fs-h3); line-height: 1.24; letter-spacing: -.02em; }
h4 { font-size: var(--fs-h4); line-height: 1.3;  letter-spacing: -.015em; }

h1 em, h2 em { font-style: normal; color: var(--blue); }

p { text-wrap: pretty; }

.lede,
.hero__lede {
  font-size: var(--fs-lede);
  line-height: 1.6;
  color: var(--text-soft);
}

/* The signature eyebrow: a short red rule, then small caps in red. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .7rem;
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--blue-ink);
  margin-bottom: var(--s-4);
}
.eyebrow::before {
  content: "";
  width: 28px;
  height: 3px;
  border-radius: 2px;
  background: var(--blue);
  flex: none;
}
.eyebrow--invert { color: var(--blue-hot); }
.eyebrow--invert::before { background: var(--blue-hot); }
.section--deep .eyebrow,
.on-dark .eyebrow { color: var(--blue-hot); }
.section--deep .eyebrow::before,
.on-dark .eyebrow::before { background: var(--blue-hot); }

.section-head { max-width: 60ch; margin-bottom: clamp(2rem, 1.2rem + 2.4vw, 3.4rem); }
.section-head > p { color: var(--text-soft); font-size: var(--fs-lede); margin-top: var(--s-4); }
.section--deep .section-head > p { color: var(--on-dark-soft); }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head--center .eyebrow { justify-content: center; }

/* Heading left, supporting text or a link right. */
.section-head--split {
  max-width: none;
  display: grid;
  gap: var(--s-5);
  align-items: end;
}
@media (min-width: 900px) {
  .section-head--split { grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); gap: var(--s-8); }
  .section-head--split > p { margin-top: 0; }
}

.prose > * + * { margin-top: 1.15em; }
.prose h2 { margin-top: 1.8em; }
.prose h3 { margin-top: 1.6em; }
.prose h2:first-child, .prose h3:first-child { margin-top: 0; }
.prose p, .prose li { color: var(--text-soft); }
.prose strong { color: var(--text); font-weight: 700; }
.prose ul, .prose ol { padding-left: 0; }
.prose ul li { list-style: none; position: relative; padding-left: 1.5rem; }
.prose ul li::before {
  content: "";
  position: absolute;
  left: 0; top: .62em;
  width: 7px; height: 7px;
  border-radius: 2px;
  background: var(--blue);
}
.prose ol { list-style: decimal; padding-left: 1.3rem; }
.prose ol li { padding-left: .35rem; }
.prose li + li { margin-top: .5em; }
.prose blockquote {
  border-left: 3px solid var(--blue);
  padding-left: var(--s-5);
  font-size: var(--fs-lede);
  color: var(--text);
}
.section--deep .prose p, .section--deep .prose li { color: var(--on-dark-soft); }
.section--deep .prose strong { color: #fff; }

/* Tick lists ---------------------------------------------------------------- */
.ticks { display: grid; gap: .75rem; }
.ticks li {
  position: relative;
  padding-left: 2.1rem;
  color: var(--text-soft);
  line-height: 1.55;
}
.ticks li::before {
  content: "";
  position: absolute;
  left: 0; top: .1em;
  width: 1.4rem; height: 1.4rem;
  border-radius: var(--r-xs);
  background-color: var(--blue-tint);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23E11B22' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-size: .95rem;
  background-repeat: no-repeat;
  background-position: center;
}
.ticks--row { grid-template-columns: repeat(auto-fit, minmax(min(100%, 270px), 1fr)); gap: 1.1rem 2rem; }
.section--deep .ticks li { color: var(--on-dark-soft); }
.section--deep .ticks li::before { background-color: rgba(0, 147, 221, .2); }

/* Gold is a signal here, so it has to clear 3:1 against whatever it sits on.
   --amber only manages that on the dark surfaces. */
.stars { display: inline-flex; gap: .12rem; color: var(--amber-graphic); }
.section--deep .stars, .on-dark .stars, .hero .stars, .rating-block .stars,
.card--dark .stars, .form-panel--dark .stars { color: var(--amber); }
.stars svg { width: 1rem; height: 1rem; fill: currentColor; }
.stars--lg svg { width: 1.35rem; height: 1.35rem; }

.icon { width: 1.25rem; height: 1.25rem; flex: none; stroke-width: 1.9; }

/* -----------------------------------------------------------------------------
   06  BUTTONS AND LINKS
   -------------------------------------------------------------------------- */

.btn {
  --btn-bg: var(--blue);
  --btn-fg: #fff;
  --btn-bd: var(--blue);
  /* The colour the hover wipe rises in, and the text that sits on it once
     it has. Variables rather than fixed values because an ink wipe on an
     ink surface repaints the button its own background and the control
     vanishes under the cursor. Dark contexts flip these to a white wipe. */
  --btn-wipe: var(--ink-900);
  --btn-wipe-fg: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  padding: .95rem 1.7rem;
  border: 1.5px solid var(--btn-bd);
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--ff-body);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: -.005em;
  line-height: 1.2;
  text-decoration: none;
  text-align: center;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: transform .28s var(--ease-out), box-shadow .28s var(--ease),
              background-color .22s var(--ease), border-color .22s var(--ease),
              color .22s var(--ease);
}
/* The wipe: a panel that rises from below on hover. */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--btn-wipe);
  transform: translateY(101%);
  transition: transform .42s var(--ease-out);
}
.btn:hover::before, .btn:focus-visible::before { transform: translateY(0); }
.btn:hover, .btn:focus-visible {
  color: var(--btn-wipe-fg);
  border-color: var(--btn-wipe);
  transform: translateY(-2px);
}
/* box-shadow is on :hover alone. Putting it on :focus-visible too would replace
   the white band of the focus ring, and on a dark section that band is the only
   part of the ring that is visible. */
.btn:hover { box-shadow: var(--sh-3); }
.btn:active { transform: translateY(0); }
.btn .icon { width: 1.1rem; height: 1.1rem; }

.btn--primary { --btn-bg: var(--blue); --btn-fg: #fff; --btn-bd: var(--blue); box-shadow: var(--sh-blue); }
.btn--primary:hover { box-shadow: var(--sh-3); }

.btn--solid { --btn-bg: var(--ink-900); --btn-fg: #fff; --btn-bd: var(--ink-900); --btn-wipe: var(--blue); }

.btn--outline { --btn-bg: transparent; --btn-fg: var(--text); --btn-bd: var(--line-2); }

/* On photographs and dark panels. */
.btn--ghost {
  --btn-bg: rgba(255,255,255,.08);
  --btn-fg: #fff;
  --btn-bd: rgba(255,255,255,.34);
  --btn-wipe: #fff;
  --btn-wipe-fg: var(--ink-900);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.btn--lg { padding: 1.1rem 2.1rem; font-size: 1rem; }
.btn--block { display: flex; width: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: .85rem; align-items: center; }

/* The arrow link, used wherever a section needs a way onward. */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--text);
  text-decoration: none;
  padding-bottom: 3px;
  background-image: linear-gradient(var(--blue), var(--blue));
  background-size: 0 2px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size .34s var(--ease-out), color .2s var(--ease);
}
.link-arrow::after {
  content: "";
  width: 1.1rem; height: 1.1rem;
  flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .34s var(--ease-out);
}
.link-arrow:hover { color: var(--blue); background-size: 100% 2px; }
.link-arrow:hover::after { transform: translateX(4px); }
.section--deep .link-arrow, .on-dark .link-arrow { color: #fff; background-image: linear-gradient(var(--blue-hot), var(--blue-hot)); }
.section--deep .link-arrow:hover, .on-dark .link-arrow:hover { color: var(--blue-hot); }

/* -----------------------------------------------------------------------------
   07  HEADER, NAVIGATION, MOBILE DRAWER
   Two decks: a dark utility strip carrying the credentials and the hours, and
   the white bar underneath it carrying the logo, the menu and the call to
   action. The strip slides away on scroll so the bar is all that follows you.
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--white);
  transition: box-shadow .3s var(--ease);
}

.header-strip {
  background: var(--ink-900);
  color: var(--on-dark-soft);
  font-size: var(--fs-xs);
  overflow: hidden;
  max-height: 44px;
  /* Height only. Fading a near-black strip out over a white page turns it
     into a grey smear part way through, which reads as a broken bar rather
     than a collapsing one. Clipping it keeps the strip its own colour until
     the moment it is gone. */
  transition: max-height .34s var(--ease);
}
.header-strip__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  min-height: 44px;
}
.header-strip ul { display: flex; align-items: center; gap: 1.6rem; flex-wrap: wrap; }
.header-strip li { display: inline-flex; align-items: center; gap: .5rem; }
.header-strip .icon { width: .95rem; height: .95rem; color: var(--blue-hot); }
.header-strip a { color: inherit; text-decoration: none; }
.header-strip a:hover { color: #fff; }
.header-strip__socials { display: inline-flex; gap: .4rem; }
.header-strip__socials a {
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.16);
  transition: background-color .22s var(--ease), border-color .22s var(--ease);
}
.header-strip__socials a:hover { background: var(--blue); border-color: var(--blue); }
.header-strip__socials .icon { width: .8rem; height: .8rem; color: currentColor; }
@media (max-width: 1023px) { .header-strip { display: none; } }

.site-header.is-stuck { box-shadow: 0 6px 30px rgba(12, 14, 19, .1); }
.site-header.is-stuck .header-strip { max-height: 0; }

.header-inner {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  min-height: var(--header-h);
}

/* Logo ---------------------------------------------------------------------- */
.logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--text);
  flex: none;
}

/* The wordmark carries the company name, so there is no text beside it any
   more. Lettering takes the ink of the surface through currentColor; only the
   bolt is pinned to the brand. */
.logo__mark {
  width: clamp(142px, 11vw, 176px);
  height: auto;
  flex: none;
  display: block;
}
.logo__word { fill: currentColor; }
.logo__bolt { fill: var(--blue-bolt); }

/* On the dark bands the supplied black lettering would have vanished. */
.site-footer .logo,
.mobile-nav .logo { color: #fff; }/* Desktop navigation -------------------------------------------------------- */
.nav { display: none; margin-inline: auto; }
@media (min-width: 1024px) { .nav { display: flex; align-items: center; gap: .15rem; } }

.nav__item { position: relative; }

.nav__link {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .7rem .85rem;
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  transition: color .2s var(--ease), background-color .2s var(--ease);
}
.nav__link:hover { color: var(--blue); background: var(--paper); }
.nav__link[aria-current="page"] { color: var(--blue); }
.nav__chevron { width: .8rem; height: .8rem; transition: transform .25s var(--ease); }
.nav__item:hover .nav__chevron, .nav__item:focus-within .nav__chevron { transform: rotate(180deg); }

.nav__dropdown {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  min-width: 268px;
  padding: .5rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--sh-4);
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity .24s var(--ease), transform .24s var(--ease-out), visibility .24s;
}
.nav__item:hover > .nav__dropdown,
.nav__item:focus-within > .nav__dropdown { opacity: 1; visibility: visible; transform: translateY(0); }
.nav__dropdown a {
  display: block;
  padding: .62rem .8rem;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-soft);
  text-decoration: none;
  transition: background-color .18s var(--ease), color .18s var(--ease), padding-left .22s var(--ease);
}
.nav__dropdown a:hover,
.nav__dropdown a[aria-current="page"] { background: var(--paper); color: var(--blue); padding-left: 1.05rem; }

/* Header right-hand side ---------------------------------------------------- */
.header-actions { display: flex; align-items: center; gap: .7rem; margin-left: auto; }
@media (min-width: 1024px) { .header-actions { margin-left: 0; } }

.header-phone {
  display: none;
  align-items: center;
  gap: .6rem;
  text-decoration: none;
  color: var(--text);
  padding-right: .3rem;
}
@media (min-width: 640px) { .header-phone { display: inline-flex; } }
.header-phone .icon {
  width: 40px; height: 40px;
  padding: 11px;
  border-radius: 50%;
  background: var(--blue-tint);
  color: var(--blue);
  transition: background-color .24s var(--ease), color .24s var(--ease), transform .24s var(--ease-out);
}
.header-phone:hover .icon { background: var(--blue); color: #fff; transform: rotate(-12deg); }
.header-phone span { display: grid; line-height: 1.2; }
.header-phone__label {
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-mute);
}
.header-phone__number {
  font-family: var(--ff-display);
  font-weight: 700;
  font-size: .98rem;
  letter-spacing: -.02em;
  color: var(--text);
}

.header-cta { display: none; }
@media (min-width: 1150px) { .header-cta { display: inline-flex; } }

.nav-toggle {
  display: grid;
  place-items: center;
  width: 46px; height: 46px;
  border-radius: var(--r-sm);
  background: var(--ink-900);
  color: #fff;
  transition: background-color .22s var(--ease);
}
.nav-toggle:hover { background: var(--blue); }
@media (min-width: 1024px) { .nav-toggle { display: none; } }
.nav-toggle .icon { width: 1.3rem; height: 1.3rem; }
.nav-toggle__close { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle__open { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle__close { display: block; }

/* Mobile drawer ------------------------------------------------------------- */
.mobile-nav {
  position: fixed;
  inset: 0;
  top: 0;
  z-index: 99;
  background: var(--ink-900);
  color: #fff;
  padding-top: calc(var(--header-h) + 1.5rem);
  padding-bottom: 6rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  transition: opacity .3s var(--ease), transform .34s var(--ease-out), visibility .3s;
}
.mobile-nav[hidden] { display: block; }
.mobile-nav.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
@media (min-width: 1024px) { .mobile-nav { display: none !important; } }

.mobile-nav nav > ul > li { border-bottom: 1px solid rgba(255,255,255,.09); }
.mobile-nav nav > ul > li > a {
  display: block;
  padding: 1.05rem 0;
  font-family: var(--ff-display);
  font-size: 1.28rem;
  font-weight: 700;
  letter-spacing: -.025em;
  color: #fff;
  text-decoration: none;
}
.mobile-nav nav > ul > li > a[aria-current="page"] { color: var(--blue-hot); }
.mobile-nav__sub { padding: 0 0 1rem .1rem; display: grid; gap: .1rem; }
.mobile-nav__sub a {
  display: block;
  padding: .5rem 0 .5rem 1.1rem;
  border-left: 2px solid rgba(255,255,255,.16);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--on-dark-soft);
  text-decoration: none;
}
.mobile-nav__sub a:hover, .mobile-nav__sub a[aria-current="page"] { color: var(--blue-hot); border-color: var(--blue-hot); }

.mobile-nav__foot { display: grid; gap: 1rem; margin-top: 1.8rem; }
.mobile-nav__phone {
  display: flex;
  align-items: center;
  gap: .8rem;
  padding: 1rem 1.1rem;
  border-radius: var(--r-md);
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.1);
  color: #fff;
  text-decoration: none;
}
.mobile-nav__phone .icon { width: 1.4rem; height: 1.4rem; color: var(--blue-hot); }
.mobile-nav__phone span { display: grid; }
.mobile-nav__phone .header-phone__label { color: var(--on-dark-mute); }
.mobile-nav__phone .header-phone__number { color: #fff; font-size: 1.1rem; }

/* -----------------------------------------------------------------------------
   08  MOBILE BOTTOM BAR
   -------------------------------------------------------------------------- */

.bottom-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 90;
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: var(--ink-900);
  border-top: 1px solid rgba(255,255,255,.1);
  padding-bottom: env(safe-area-inset-bottom);
  box-shadow: 0 -8px 30px rgba(8, 9, 12, .3);
}
@media (min-width: 768px) { .bottom-bar { display: none; } }
body { padding-bottom: 0; }
@media (max-width: 767px) { body { padding-bottom: 64px; } }

.bottom-bar a {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: 1.05rem .5rem;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: #fff;
  text-decoration: none;
}
.bottom-bar a + a { border-left: 1px solid rgba(255,255,255,.1); }
.bottom-bar .icon { width: 1.15rem; height: 1.15rem; }
.bottom-bar__call { background: var(--blue); }
.bottom-bar__call:hover { background: var(--blue-deep); color: #fff; }

/* -----------------------------------------------------------------------------
   09  HOME HERO AND PAGE HERO
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  background: var(--ink-950);
  color: #fff;
  isolation: isolate;
  overflow: hidden;
}

.hero__bg { position: absolute; inset: 0; z-index: -2; }
.hero__bg picture, .hero__bg img { width: 100%; height: 100%; object-fit: cover; }
/* One layer per photograph, stacked. The incoming slide is raised as well as
   faded up, so it covers the one it replaces rather than both being part
   transparent at once, which would show the section behind them. */
.hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  z-index: 0;
  transition: opacity 1.4s var(--ease);
}
.hero__slide.is-active { opacity: 1; z-index: 1; }

/* The drift restarts with each photograph rather than running one long
   timeline behind all of them. */
.hero__slide.is-active img { animation: heroDrift 26s var(--ease) infinite alternate; }

@keyframes heroDrift {
  from { transform: scale(1.02); }
  to   { transform: scale(1.11); }
}

/* Two scrims: a hard one on the left so the copy always has contrast, and a
   soft one up from the bottom so the hero can meet the next section. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to right, rgba(8,9,12,.94) 0%, rgba(8,9,12,.86) 34%, rgba(8,9,12,.45) 66%, rgba(8,9,12,.3) 100%),
    linear-gradient(to top, rgba(8,9,12,.96) 0%, rgba(8,9,12,0) 42%);
}
/* Below 1080px the copy runs most of the width, but the left-hand scrim fades
   to .3 over the right third, so the lede sat on bare photograph and fell to
   about 2.3:1 on phones. An even band keeps it above 4.5:1 across 360-1000px
   on all three slides, with the drift at its full 1.11 zoom (measured 28 Sep
   2026, worst pixel 5.11:1). The stock photographs failed the same way. */
@media (max-width: 1079px) {
  .hero::before {
    background:
      linear-gradient(rgba(8,9,12,.65), rgba(8,9,12,.65)),
      linear-gradient(to right, rgba(8,9,12,.3) 0%, rgba(8,9,12,0) 100%),
      linear-gradient(to top, rgba(8,9,12,.96) 0%, rgba(8,9,12,0) 42%);
  }
}
/* Circuit grid on top of the photograph. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.04) 1px, transparent 1px);
  background-size: 72px 72px;
  -webkit-mask-image: linear-gradient(to right, #000 0%, transparent 62%);
  mask-image: linear-gradient(to right, #000 0%, transparent 62%);
}

.hero__inner {
  padding-block: clamp(3.5rem, 2rem + 9vw, 8.5rem);
  min-height: clamp(560px, 78vh, 820px);
  display: flex;
  align-items: center;
}
.hero__content { max-width: 46rem; }

.hero__content h1 {
  font-size: var(--fs-display);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -.042em;
  color: #fff;
  margin-bottom: var(--s-5);
}
.hero__content h1 em { color: var(--blue-hot); font-style: normal; }

/* The second slide is the owner's photograph of testing at a ceiling light,
   with the electrician's face in the middle of the frame. From 820 to about
   1060px the headline runs "Electricians London" on one line straight across
   it. So on those widths the headline is held to three lines (7.25em falls
   between "actually trusts" and "London actually", so the break is the same
   with or without text-wrap: balance), and on every landscape width that
   slide is anchored top-left: the face moves right of the copy and the
   ceiling rose being tested stays in frame on wide screens. */
@media (min-width: 820px) { .hero__slide:nth-child(2) img { object-position: 25% 0%; } }
@media (min-width: 820px) and (max-width: 1099px) { .hero__content h1 { max-width: 7.25em; } }
.hero__lede { color: rgba(255,255,255,.8); max-width: 44ch; }
.hero__actions { margin-top: clamp(1.6rem, 1rem + 1.6vw, 2.4rem); }

.hero__reassure {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem .55rem;
  margin-top: clamp(1.8rem, 1.2rem + 1.8vw, 2.6rem);
}
.hero__reassure li {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem .95rem;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.07);
  border: 1px solid rgba(255,255,255,.14);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: rgba(255,255,255,.9);
}
.hero__reassure .icon { width: .95rem; height: .95rem; color: var(--blue-hot); }

/* The floating rating card at the foot of the hero. */
.hero__card {
  display: none;
  position: absolute;
  right: var(--gutter);
  bottom: clamp(2rem, 1rem + 3vw, 4rem);
  width: 300px;
  padding: 1.5rem;
  border-radius: var(--r-lg);
  background: rgba(23, 26, 33, .72);
  border: 1px solid rgba(255,255,255,.14);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  box-shadow: var(--sh-4);
}
@media (min-width: 1100px) { .hero__card { display: block; } }
.hero__card strong {
  display: block;
  font-family: var(--ff-display);
  font-size: 2.6rem;
  font-weight: 800;
  letter-spacing: -.04em;
  line-height: 1;
  color: #fff;
}
.hero__card .stars { margin: .55rem 0 .7rem; }
.hero__card p { font-size: var(--fs-xs); color: rgba(255,255,255,.72); }
.hero__card hr { border-color: rgba(255,255,255,.13); margin: 1rem 0; }

/* Page hero — every page that is not the home page --------------------------- */
.page-hero {
  position: relative;
  background: var(--ink-900);
  color: #fff;
  overflow: hidden;
  isolation: isolate;
}
.page-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(ellipse 80% 100% at 15% 0%, #000 10%, transparent 72%);
  mask-image: radial-gradient(ellipse 80% 100% at 15% 0%, #000 10%, transparent 72%);
}
/* A single red glow, bottom right, so the band is not a flat rectangle. */
.page-hero::after {
  content: "";
  position: absolute;
  right: -180px; bottom: -260px;
  width: 620px; height: 620px;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(0, 147, 221,.32) 0%, rgba(0, 147, 221,0) 68%);
  pointer-events: none;
}
.page-hero__inner {
  padding-block: clamp(2.6rem, 1.6rem + 5vw, 5.5rem);
  max-width: 56rem;
}
.page-hero h1 { color: #fff; margin-top: var(--s-3); }
.page-hero .lede { color: rgba(255,255,255,.78); margin-top: var(--s-5); max-width: 58ch; }
.page-hero__actions { margin-top: clamp(1.5rem, 1rem + 1.4vw, 2.2rem); }
.page-hero--case .page-hero__inner { max-width: 62rem; }
/* Inline links in the intro copy. The default link red is chosen for white
   paper and is unreadable on this band, so they go white and underlined. */
.page-hero p a:not(.btn):not(.link-arrow) {
  color: #fff;
  font-weight: 600;
  text-decoration-color: var(--blue-hot);
  text-decoration-thickness: 2px;
}
.page-hero p a:not(.btn):not(.link-arrow):hover { color: var(--blue-hot); text-decoration-color: var(--blue-hot); }

/* -----------------------------------------------------------------------------
   10  MARQUEE AND TRUST BAR
   -------------------------------------------------------------------------- */

/* An endless strip of what we do, between the hero and the page proper. */
.marquee {
  background: var(--blue);
  color: #fff;
  padding-block: .95rem;
  overflow: hidden;
  position: relative;
}
.marquee__track {
  display: flex;
  width: max-content;
  animation: marquee 38s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__group {
  display: flex;
  align-items: center;
  gap: 2.6rem;
  padding-right: 2.6rem;
  flex: none;
}
.marquee span {
  font-family: var(--ff-display);
  font-size: clamp(.86rem, .8rem + .3vw, 1.02rem);
  font-weight: 700;
  letter-spacing: .01em;
  text-transform: uppercase;
  white-space: nowrap;
}
.marquee .icon { width: 1rem; height: 1rem; opacity: .75; }
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Four credentials, sat under the hero on a white card that overlaps it. */
.trustbar { background: var(--white); position: relative; z-index: 2; }
.trustbar__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--sh-2);
  margin-top: clamp(-3.5rem, -2rem - 2vw, -2rem);
}
.trustbar__item {
  display: flex;
  align-items: center;
  gap: .9rem;
  padding: 1.5rem 1.4rem;
  background: var(--white);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  line-height: 1.35;
  transition: background-color .26s var(--ease);
}
.trustbar__item:hover { background: var(--paper); }
.trustbar__item .icon {
  width: 40px; height: 40px;
  flex: none;
  padding: 10px;
  border-radius: var(--r-sm);
  background: var(--blue-tint);
  color: var(--blue);
}

/* -----------------------------------------------------------------------------
   11  SECTIONS, PANELS, SPLIT EXTRAS
   -------------------------------------------------------------------------- */

/* Two big panels: residential and commercial. */
.audience {
  display: grid;
  gap: clamp(1.2rem, .7rem + 1.8vw, 2rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
}
.audience__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform .4s var(--ease-out), box-shadow .4s var(--ease), border-color .3s var(--ease);
}
.audience__panel:hover { transform: translateY(-6px); box-shadow: var(--sh-3); border-color: var(--line-2); }
.audience__panel > picture { overflow: hidden; }
.audience__panel > picture img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform .8s var(--ease-out);
}
.audience__panel:hover > picture img { transform: scale(1.06); }
.audience__body { padding: clamp(1.4rem, 1rem + 1.4vw, 2.2rem); display: flex; flex-direction: column; flex: 1; }
.audience__body h3 { margin-bottom: .7rem; }
.audience__body > p { color: var(--text-soft); font-size: var(--fs-sm); }
.audience__list { display: grid; gap: .55rem; margin: 1.2rem 0 1.6rem; }
.audience__list li {
  position: relative;
  padding-left: 1.5rem;
  font-size: var(--fs-sm);
  color: var(--text-soft);
}
.audience__list li::before {
  content: "";
  position: absolute;
  left: 0; top: .55em;
  width: 8px; height: 2px;
  border-radius: 1px;
  background: var(--blue);
}
.audience__body .btn { margin-top: auto; align-self: flex-start; }

/* A boxed aside beside the media column. */
.proof-card {
  display: flex;
  gap: 1rem;
  margin-top: 1.1rem;
  padding: 1.3rem;
  background: var(--ink-900);
  color: #fff;
  border-radius: var(--r-md);
  box-shadow: var(--sh-3);
}
.proof-card__icon {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  flex: none;
  border-radius: var(--r-sm);
  background: var(--blue);
  color: #fff;
}
.proof-card__icon .icon { width: 1.3rem; height: 1.3rem; }
.proof-card__body { display: grid; gap: .3rem; }
.proof-card__body strong { font-family: var(--ff-display); font-size: 1rem; letter-spacing: -.02em; }
.proof-card__body span { font-size: var(--fs-xs); color: var(--on-dark-soft); }
.proof-card__body .link-arrow { color: #fff; font-size: var(--fs-xs); margin-top: .3rem; background-image: linear-gradient(var(--blue-hot), var(--blue-hot)); }
.proof-card__body .link-arrow:hover { color: var(--blue-hot); }

/* Callouts ------------------------------------------------------------------ */
.callout {
  padding: 1.3rem 1.5rem;
  border-radius: var(--r-md);
  background: var(--paper);
  border-left: 3px solid var(--blue);
  font-size: var(--fs-sm);
  color: var(--text-soft);
}
.callout strong { color: var(--text); }
.callout--warn { background: var(--warn-tint); border-left-color: var(--amber); }
.section--deep .callout { background: rgba(255,255,255,.05); color: var(--on-dark-soft); }

.pullquote {
  font-family: var(--ff-display);
  font-size: clamp(1.25rem, 1rem + 1.1vw, 1.75rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -.025em;
  color: var(--text);
  padding-left: clamp(1.2rem, .6rem + 1.6vw, 2rem);
  border-left: 3px solid var(--blue);
}
.pullquote--inline { margin-block: var(--s-6); }

/* -----------------------------------------------------------------------------
   12  CARDS
   -------------------------------------------------------------------------- */

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: .85rem;
  padding: clamp(1.5rem, 1.1rem + 1.1vw, 2.1rem);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
  transition: transform .4s var(--ease-out), box-shadow .4s var(--ease), border-color .3s var(--ease);
}
/* The red bar that draws itself across the top on hover. */
.card::after {
  content: "";
  position: absolute;
  left: 0; top: 0;
  height: 3px; width: 100%;
  background: var(--blue);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .48s var(--ease-out);
}
.card:hover { transform: translateY(-6px); box-shadow: var(--sh-3); border-color: var(--line-2); }
.card:hover::after { transform: scaleX(1); }

.card h3 { margin-bottom: -.1rem; }
.card p { color: var(--text-soft); font-size: var(--fs-sm); }
.card ul { display: grid; gap: .4rem; }
.card ul li { position: relative; padding-left: 1.3rem; font-size: var(--fs-sm); color: var(--text-soft); }
.card ul li::before {
  content: "";
  position: absolute;
  left: 0; top: .58em;
  width: 7px; height: 2px;
  border-radius: 1px;
  background: var(--blue);
}

.card__icon {
  display: grid;
  place-items: center;
  width: 54px; height: 54px;
  border-radius: var(--r-md);
  background: var(--blue-tint);
  color: var(--blue);
  margin-bottom: .3rem;
  transition: background-color .34s var(--ease), color .34s var(--ease), transform .45s var(--ease-out);
}
.card__icon .icon { width: 1.55rem; height: 1.55rem; }
.card:hover .card__icon { background: var(--blue); color: #fff; transform: rotate(-8deg) scale(1.05); }

.card__link { margin-top: auto; padding-top: .5rem; }

/* A big, ghosted number in the corner: 01, 02, 03 … */
.card__num {
  position: absolute;
  right: 1.1rem; top: .4rem;
  z-index: -1;
  font-family: var(--ff-display);
  font-size: 4.6rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.06em;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--line);
  transition: -webkit-text-stroke-color .4s var(--ease), transform .5s var(--ease-out);
}
.card:hover .card__num { -webkit-text-stroke-color: var(--blue-line); transform: translateY(-4px); }

.card--dark {
  background: var(--ink-800);
  border-color: rgba(255,255,255,.09);
  color: #fff;
}
.card--dark h3 { color: #fff; }
.card--dark p, .card--dark li { color: var(--on-dark-soft); }
.card--dark .card__icon { background: rgba(0, 147, 221,.16); color: var(--blue-hot); }
.card--dark:hover { border-color: rgba(255,255,255,.2); box-shadow: 0 20px 50px rgba(0,0,0,.45); }
.card--dark .card__num { -webkit-text-stroke-color: rgba(255,255,255,.12); }
.card--dark:hover .card__num { -webkit-text-stroke-color: rgba(0, 147, 221,.55); }

/* A card whose whole surface is the link. */
.card--linked { text-decoration: none; color: inherit; }

/* Service card with a photograph on top. */
.card--media { padding: 0; gap: 0; }
.card--media > picture { overflow: hidden; }
.card--media > picture img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: transform .8s var(--ease-out);
}
.card--media:hover > picture img { transform: scale(1.07); }
.card--media .card__body { padding: clamp(1.3rem, 1rem + 1vw, 1.9rem); display: flex; flex-direction: column; gap: .8rem; flex: 1; }

/* Detail cards on the service pages. */
.detail-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(1.4rem, 1rem + 1.2vw, 2rem);
  transition: box-shadow .35s var(--ease), border-color .3s var(--ease);
}
.detail-card:hover { box-shadow: var(--sh-2); border-color: var(--line-2); }
.detail-card__head {
  display: flex;
  align-items: center;
  gap: .85rem;
  margin-bottom: .9rem;
  padding-bottom: .9rem;
  border-bottom: 1px solid var(--line);
}
.detail-card__head .icon {
  width: 42px; height: 42px;
  flex: none;
  padding: 10px;
  border-radius: var(--r-sm);
  background: var(--blue-tint);
  color: var(--blue);
}
.detail-card__head h3 { margin: 0; }
.detail-card p, .detail-card li { color: var(--text-soft); font-size: var(--fs-sm); }
.section--alt .detail-card { background: var(--white); }

/* Sibling service links at the bottom of a service page. */
.sibling-links {
  display: grid;
  gap: .8rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
.sibling-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.3rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--text);
  text-decoration: none;
  transition: background-color .26s var(--ease), border-color .26s var(--ease),
              color .26s var(--ease), transform .34s var(--ease-out);
}
.sibling-link::after {
  content: "";
  width: 1.05rem; height: 1.05rem;
  flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .3s var(--ease-out);
}
.sibling-link:hover {
  background: var(--ink-900);
  border-color: var(--ink-900);
  color: #fff;
  transform: translateY(-3px);
}
.sibling-link:hover::after { transform: translateX(4px); }

/* -----------------------------------------------------------------------------
   13  CASE STUDIES
   -------------------------------------------------------------------------- */

.cs-card {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform .4s var(--ease-out), box-shadow .4s var(--ease), border-color .3s var(--ease);
}
.cs-card:hover { transform: translateY(-6px); box-shadow: var(--sh-3); border-color: var(--line-2); }

.cs-card__media { position: relative; overflow: hidden; }
.cs-card__media img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: transform .85s var(--ease-out);
}
.cs-card:hover .cs-card__media img { transform: scale(1.07); }

.cs-card__tag {
  position: absolute;
  left: 1rem; top: 1rem;
  padding: .38rem .8rem;
  border-radius: var(--r-pill);
  background: var(--blue);
  color: #fff;
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: .09em;
  text-transform: uppercase;
}
.cs-card__body { padding: clamp(1.25rem, 1rem + .9vw, 1.7rem); display: flex; flex-direction: column; gap: .7rem; flex: 1; }
.cs-card__body h3 { font-size: 1.2rem; }
.cs-card__body p { font-size: var(--fs-sm); color: var(--text-soft); }
.cs-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem .9rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-mute);
}
.cs-card__meta span { display: inline-flex; align-items: center; gap: .35rem; }
.cs-card__meta .icon { width: .9rem; height: .9rem; color: var(--blue); }
.cs-card__foot { margin-top: auto; padding-top: .4rem; }

/* Case study page layout ---------------------------------------------------- */
.cs-main { min-width: 0; }

.cs-head { margin-bottom: var(--s-6); }
.cs-lead { font-size: var(--fs-lede); color: var(--text-soft); }
.cs-meta {
  display: grid;
  gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr));
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
  margin-block: var(--s-6);
}
.cs-meta > div { background: var(--white); padding: 1.05rem 1.15rem; }
.cs-meta dt {
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-mute);
  margin-bottom: .25rem;
}
.cs-meta dd { margin: 0; font-weight: 700; font-size: var(--fs-sm); color: var(--text); }

.cs-panel {
  padding: clamp(1.3rem, 1rem + 1vw, 1.8rem);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.cs-panel h2, .cs-panel h3 { font-size: 1.15rem; margin-bottom: .8rem; }
.cs-panel p, .cs-panel li { font-size: var(--fs-sm); color: var(--text-soft); }
.cs-panel--dark { background: var(--ink-900); border-color: var(--ink-700); color: #fff; }
.cs-panel--dark h2, .cs-panel--dark h3, .cs-panel--dark strong { color: #fff; }
.cs-panel--dark p, .cs-panel--dark li { color: var(--on-dark-soft); }
.cs-panel__phone {
  display: block;
  font-family: var(--ff-display);
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -.03em;
  color: #fff;
  text-decoration: none;
  margin-block: .5rem .9rem;
}
.cs-panel__phone:hover { color: var(--blue-hot); }
.cs-work { display: grid; gap: .6rem; }

.gallery {
  display: grid;
  gap: .8rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
}
.gallery__item {
  display: block;
  padding: 0;
  border: 0;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--paper-2);
  cursor: zoom-in;
  position: relative;
}
.gallery__item img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: transform .7s var(--ease-out), filter .4s var(--ease);
}
.gallery__item:hover img { transform: scale(1.06); filter: brightness(.88); }
.gallery__item::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.6-3.6M11 8v6M8 11h6'/%3E%3C/svg%3E") center / 2rem no-repeat;
  opacity: 0;
  transition: opacity .3s var(--ease);
  pointer-events: none;
}
.gallery__item:hover::after { opacity: 1; }

/* -----------------------------------------------------------------------------
   14  PROCESS, STATS, TABLES, CHIPS
   -------------------------------------------------------------------------- */

/* Numbered steps, joined by a dashed rule on wide screens. */
.process {
  display: grid;
  gap: clamp(1.4rem, .9rem + 1.6vw, 2.2rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  counter-reset: step;
  position: relative;
}
.process__step {
  position: relative;
  counter-increment: step;
  padding-top: 4.4rem;
}
.process__step::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  left: 0; top: 0;
  display: grid;
  place-items: center;
  width: 60px; height: 60px;
  border-radius: var(--r-md);
  background: var(--ink-900);
  color: #fff;
  font-family: var(--ff-display);
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: -.02em;
  transition: background-color .3s var(--ease), transform .4s var(--ease-out);
  z-index: 1;
}
.process__step:hover::before { background: var(--blue); transform: translateY(-4px); }
/* The dashed connector. Drawn from the middle of the badge to the next one. */
@media (min-width: 760px) {
  .process__step::after {
    content: "";
    position: absolute;
    left: 60px; top: 29px;
    right: -1.4rem;
    height: 2px;
    background-image: linear-gradient(90deg, var(--line-2) 0 8px, transparent 8px 16px);
    background-size: 16px 2px;
  }
  .process__step:last-child::after { display: none; }
}
.process__step h3 { margin-bottom: .5rem; }
.process__step p { font-size: var(--fs-sm); color: var(--text-soft); }
.section--deep .process__step::before { background: var(--blue); }
.section--deep .process__step:hover::before { background: #fff; color: var(--ink-900); }
.section--deep .process__step::after { background-image: linear-gradient(90deg, rgba(255,255,255,.22) 0 8px, transparent 8px 16px); }

/* Counters ------------------------------------------------------------------ */
.stats {
  display: grid;
  gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.stats__item {
  background: var(--white);
  padding: clamp(1.3rem, 1rem + 1vw, 1.9rem);
  display: grid;
  gap: .35rem;
  transition: background-color .3s var(--ease);
}
.stats__item:hover { background: var(--paper); }
.stats__item strong {
  font-family: var(--ff-display);
  font-size: clamp(2rem, 1.4rem + 2.2vw, 3rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.045em;
  color: var(--text);
}
.stats__item span { font-size: var(--fs-xs); font-weight: 600; color: var(--text-mute); line-height: 1.4; }
.section--deep .stats { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.1); }
.section--deep .stats__item { background: var(--ink-900); }
.section--deep .stats__item:hover { background: var(--ink-800); }
.section--deep .stats__item strong { color: #fff; }
.section--deep .stats__item span { color: var(--on-dark-mute); }
.stats--blue .stats__item strong { color: var(--blue); }

/* Tables -------------------------------------------------------------------- */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--white);
  -webkit-overflow-scrolling: touch;
}
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); min-width: 460px; }
.table th, .table td { padding: .95rem 1.1rem; text-align: left; vertical-align: top; }
.table thead th {
  background: var(--ink-900);
  color: #fff;
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: .09em;
  text-transform: uppercase;
  white-space: nowrap;
}
.table tbody tr + tr { border-top: 1px solid var(--line); }
.table tbody tr:nth-child(even) { background: var(--paper); }
.table td { color: var(--text-soft); }
.table td strong, .table th[scope="row"] { color: var(--text); font-weight: 700; }

/* Chips and code pills ------------------------------------------------------ */
.chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.cred-chip, .code-pill {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .45rem .9rem;
  border-radius: var(--r-pill);
  background: var(--paper);
  border: 1px solid var(--line);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--text-soft);
  white-space: nowrap;
}
.cred-chip .icon, .code-pill .icon { width: .95rem; height: .95rem; color: var(--blue); }
.site-footer .cred-chip {
  background: rgba(255,255,255,.06);
  border-color: rgba(255,255,255,.12);
  color: rgba(255,255,255,.82);
}
.site-footer .cred-chip .icon { color: var(--blue-hot); }

.code-pill--c1 { background: var(--danger-tint); border-color: #f3c9c6; color: #8e1f19; }
.code-pill--c2 { background: var(--warn-tint);  border-color: #f0dda6; color: #7a5800; }
.code-pill--c3 { background: var(--paper-2);    border-color: var(--line-2); color: var(--text-soft); }
.code-pill--fi { background: var(--success-tint); border-color: #b9dfd0; color: #0e5539; }

.creds { display: grid; gap: 1rem; }
.creds__row { display: flex; flex-wrap: wrap; gap: .6rem; }
.footer-creds { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.2rem; }

.confirm-mark {
  display: grid;
  place-items: center;
  width: 72px; height: 72px;
  margin-inline: auto;
  border-radius: 50%;
  background: var(--success-tint);
  color: var(--success);
  margin-bottom: var(--s-5);
}
.confirm-mark .icon { width: 2.2rem; height: 2.2rem; stroke-width: 2.6; }

.error-code {
  font-family: var(--ff-display);
  font-size: clamp(5rem, 3rem + 12vw, 11rem);
  font-weight: 800;
  line-height: .9;
  letter-spacing: -.06em;
  color: transparent;
  -webkit-text-stroke: 2px var(--blue);
}

/* -----------------------------------------------------------------------------
   15  FAQ
   -------------------------------------------------------------------------- */

.faq { display: grid; gap: .7rem; }
.faq__item {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
  transition: border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.faq__item[open] { border-color: var(--blue-line); box-shadow: var(--sh-2); }
.faq__item summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.15rem 1.35rem;
  cursor: pointer;
  list-style: none;
  font-family: var(--ff-display);
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.4;
  color: var(--text);
  transition: color .22s var(--ease);
}
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary:hover { color: var(--blue); }
.faq__item summary::after {
  content: "";
  width: 26px; height: 26px;
  flex: none;
  margin-top: .1rem;
  border-radius: 50%;
  background-color: var(--paper);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230C0E13' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
  background-size: .8rem;
  background-position: center;
  background-repeat: no-repeat;
  transition: transform .34s var(--ease-out), background-color .24s var(--ease);
}
.faq__item[open] summary { color: var(--blue); }
.faq__item[open] summary::after {
  transform: rotate(135deg);
  background-color: var(--blue);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
}
.faq__answer { padding: 0 1.35rem 1.35rem; }
.faq__answer > * + * { margin-top: .8em; }
.faq__answer p, .faq__answer li { font-size: var(--fs-sm); color: var(--text-soft); }
.section--deep .faq__item { background: var(--ink-800); border-color: rgba(255,255,255,.1); }
.section--deep .faq__item summary { color: #fff; }
.section--deep .faq__item summary::after { background-color: rgba(255,255,255,.1); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E"); }

/* -----------------------------------------------------------------------------
   16  TESTIMONIALS AND RATING
   -------------------------------------------------------------------------- */

.testimonial {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: clamp(1.5rem, 1.1rem + 1.2vw, 2.1rem);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  transition: transform .4s var(--ease-out), box-shadow .4s var(--ease), border-color .3s var(--ease);
}
.testimonial:hover { transform: translateY(-5px); box-shadow: var(--sh-3); border-color: var(--line-2); }
/* A quotation mark, set as a large glyph in the corner. */
.testimonial::before {
  content: "\201C";
  position: absolute;
  right: 1.2rem; top: .3rem;
  font-family: var(--ff-display);
  font-size: 5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--blue-tint);
  pointer-events: none;
}
.testimonial blockquote { font-size: var(--fs-sm); color: var(--text-soft); line-height: 1.7; }
.testimonial__meta {
  display: flex;
  align-items: center;
  gap: .8rem;
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.testimonial__meta strong {
  font-family: var(--ff-display);
  font-size: .98rem;
  letter-spacing: -.02em;
  color: var(--text);
  display: block;
}
.testimonial__job { font-size: var(--fs-xs); color: var(--text-mute); }
/* The initial, as an avatar. */
.testimonial__mark {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  flex: none;
  border-radius: 50%;
  background: var(--ink-900);
  color: #fff;
  font-family: var(--ff-display);
  font-weight: 800;
  font-size: 1.05rem;
}
.section--deep .testimonial { background: var(--ink-800); border-color: rgba(255,255,255,.1); }
.section--deep .testimonial::before { color: rgba(0, 147, 221,.28); }
.section--deep .testimonial blockquote { color: var(--on-dark-soft); }
.section--deep .testimonial__meta { border-top-color: rgba(255,255,255,.1); }
.section--deep .testimonial__meta strong { color: #fff; }
.section--deep .testimonial__mark { background: var(--blue); }

.rating-block {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  padding: 1.3rem 1.6rem;
  background: var(--ink-900);
  color: #fff;
  border-radius: var(--r-lg);
}
.rating-block__score {
  font-family: var(--ff-display);
  font-size: 2.6rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.045em;
  color: var(--amber);
}
.rating-block__meta { display: grid; gap: .3rem; font-size: var(--fs-xs); color: var(--on-dark-soft); }
.rating-block__meta strong { color: #fff; font-size: var(--fs-sm); }
.rating-block a { color: var(--amber); }

/* -----------------------------------------------------------------------------
   17  COVERAGE
   -------------------------------------------------------------------------- */

.coverage__intro { margin-bottom: var(--s-6); }
.coverage__areas {
  display: grid;
  gap: clamp(1rem, .7rem + 1vw, 1.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
.coverage__area {
  padding: 1.35rem 1.5rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color .3s var(--ease), box-shadow .3s var(--ease), transform .38s var(--ease-out);
}
.coverage__area:hover { border-color: var(--blue-line); box-shadow: var(--sh-2); transform: translateY(-4px); }
.coverage__area h3 {
  font-size: 1rem;
  margin-bottom: .8rem;
  padding-bottom: .7rem;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: .5rem;
}
.coverage__area h3::before {
  content: "";
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--blue);
  flex: none;
}
.coverage__places { display: flex; flex-wrap: wrap; gap: .35rem .65rem; }
.coverage__places li { font-size: var(--fs-xs); color: var(--text-soft); }
.coverage__places li + li::before { content: "•"; margin-right: .65rem; color: var(--line-2); }

.coverage__base {
  display: grid;
  gap: 1.2rem;
  padding: clamp(1.4rem, 1rem + 1.4vw, 2rem);
  background: var(--ink-900);
  color: #fff;
  border-radius: var(--r-lg);
  margin-bottom: var(--s-6);
}
@media (min-width: 760px) { .coverage__base { grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); align-items: center; } }
.coverage__base-label {
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--blue-hot);
}
.coverage__base-place {
  font-family: var(--ff-display);
  font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.1rem);
  font-weight: 800;
  letter-spacing: -.035em;
  color: #fff;
  margin-top: .3rem;
}
.coverage__base-note { font-size: var(--fs-sm); color: var(--on-dark-soft); margin-top: .5rem; }
.coverage__base-facts { display: grid; gap: .7rem; }
.coverage__base-facts li { display: flex; align-items: flex-start; gap: .65rem; font-size: var(--fs-sm); color: var(--on-dark-soft); }
.coverage__base-facts .icon { width: 1.05rem; height: 1.05rem; color: var(--blue-hot); margin-top: .25rem; }
.coverage__foot { margin-top: var(--s-6); }

.map-embed {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--paper-2);
  aspect-ratio: 16 / 10;
}
.map-embed iframe { width: 100%; height: 100%; border: 0; display: block; }

/* Contact methods ----------------------------------------------------------- */
.contact-methods {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  margin-top: var(--s-6);
}
.contact-method {
  display: flex;
  gap: .9rem;
  padding: 1.2rem 1.3rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.contact-method:hover { border-color: var(--blue-line); box-shadow: var(--sh-2); }
.contact-method > .icon {
  width: 42px; height: 42px;
  flex: none;
  padding: 10px;
  border-radius: var(--r-sm);
  background: var(--blue-tint);
  color: var(--blue);
}
.contact-method h3 {
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--text-mute);
  margin-bottom: .2rem;
}
.contact-method a {
  font-family: var(--ff-display);
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--text);
  text-decoration: none;
  overflow-wrap: anywhere;
}
.contact-method a:hover { color: var(--blue); }
.contact-method p { font-size: var(--fs-xs); color: var(--text-mute); margin-top: .25rem; }

.call-block {
  padding: clamp(1.3rem, 1rem + 1.2vw, 1.9rem);
  background: var(--blue);
  color: #fff;
  border-radius: var(--r-lg);
  box-shadow: var(--sh-blue);
}
.call-block__label {
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  opacity: .85;
}
.call-block__number {
  display: block;
  font-family: var(--ff-display);
  font-size: clamp(1.6rem, 1.2rem + 1.8vw, 2.3rem);
  font-weight: 800;
  letter-spacing: -.04em;
  color: #fff;
  text-decoration: none;
  margin-block: .35rem .4rem;
}
.call-block__number:hover { color: #fff; text-decoration: underline; }
.call-block__note { font-size: var(--fs-xs); opacity: .9; }

/* -----------------------------------------------------------------------------
   18  FORMS
   -------------------------------------------------------------------------- */

.form-panel {
  padding: clamp(1.5rem, 1.1rem + 1.6vw, 2.4rem);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-3);
}
.form-panel--dark {
  background: var(--ink-850);
  border-color: rgba(255,255,255,.1);
  color: #fff;
  box-shadow: 0 30px 70px rgba(0,0,0,.4);
}
.form-panel h2, .form-panel h3 { margin-bottom: .6rem; }
.form-panel--dark h2, .form-panel--dark h3 { color: #fff; }
.form-panel__intro { font-size: var(--fs-sm); color: var(--text-soft); margin-bottom: var(--s-5); }
.form-panel--dark .form-panel__intro { color: var(--on-dark-soft); }

.form-grid { display: grid; gap: 1.05rem; }
@media (min-width: 620px) { .form-grid--2 { grid-template-columns: 1fr 1fr; } }
.form-field--full { grid-column: 1 / -1; }

.form-field { display: grid; gap: .4rem; min-width: 0; }

.form-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--text);
}
.form-panel--dark .form-label { color: #fff; }
.req { color: var(--blue); }
.optional { color: var(--text-mute); font-weight: 500; }
.form-panel--dark .optional { color: var(--on-dark-mute); }

.form-control {
  width: 100%;
  padding: .85rem 1rem;
  background: var(--white);
  border: 1.5px solid var(--line-2);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  color: var(--text);
  transition: border-color .22s var(--ease), box-shadow .22s var(--ease), background-color .22s var(--ease);
  appearance: none;
  -webkit-appearance: none;
}
select.form-control {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23565D6E' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .9rem center;
  background-size: 1.1rem;
  padding-right: 2.6rem;
}
textarea.form-control { min-height: 8.5rem; resize: vertical; line-height: 1.6; }
.form-control::placeholder { color: var(--text-mute); }
.form-control:hover { border-color: var(--text-mute); }
/* Border only. This used to set outline:none and paint a soft red glow with
   box-shadow instead, which removed the site focus ring from every input on the
   site and replaced it with a 14%-alpha halo — the one place on the page where
   a keyboard user most needs to see where they are. The ring stays; the border
   colour is the extra signal, not the substitute. */
.form-control:focus { border-color: var(--blue); }
.form-control[aria-invalid="true"] { border-color: var(--danger); background: var(--danger-tint); }

.form-panel--dark .form-control {
  background: rgba(255,255,255,.05);
  border-color: rgba(255,255,255,.16);
  color: #fff;
}
.form-panel--dark .form-control::placeholder { color: var(--on-dark-mute); }
.form-panel--dark select.form-control {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23A9B0C0' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
.form-panel--dark .form-control:focus { border-color: var(--blue-hot); }
.form-panel--dark option { color: #111; }

.form-hint { font-size: var(--fs-xs); color: var(--text-mute); }
.form-panel--dark .form-hint { color: var(--on-dark-mute); }

.form-error {
  display: flex;
  align-items: flex-start;
  gap: .35rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--danger);
}
.form-panel--dark .form-error { color: #FF8A84; }

.form-check {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  font-size: var(--fs-xs);
  color: var(--text-soft);
  line-height: 1.55;
}
.form-panel--dark .form-check { color: var(--on-dark-soft); }
.form-check input[type="checkbox"] {
  width: 1.25rem; height: 1.25rem;
  flex: none;
  margin-top: .1rem;
  accent-color: var(--blue);
  cursor: pointer;
}

.form-foot { display: grid; gap: 1rem; margin-top: .5rem; }
.form-privacy { font-size: var(--fs-xs); color: var(--text-mute); }
.form-panel--dark .form-privacy { color: var(--on-dark-mute); }

.form-summary {
  padding: 1.1rem 1.3rem;
  border-radius: var(--r-md);
  background: var(--danger-tint);
  border: 1px solid #f0c4c0;
  color: #7d1a15;
  font-size: var(--fs-sm);
}
.form-summary h2, .form-summary h3 { font-size: 1rem; color: #7d1a15; margin-bottom: .4rem; }
.form-summary ul { display: grid; gap: .3rem; padding-left: 1.1rem; list-style: disc; }
.form-summary a { color: #7d1a15; font-weight: 700; }
.form-panel--dark .form-summary { background: rgba(179,38,30,.2); border-color: rgba(255,138,132,.4); color: #FFD9D6; }
.form-panel--dark .form-summary h2, .form-panel--dark .form-summary h3,
.form-panel--dark .form-summary a { color: #FFD9D6; }

/* The honeypot. Off-screen rather than display:none so bots still fill it. */
.hp-field {
  position: absolute !important;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

button[disabled], .btn[disabled] { opacity: .6; pointer-events: none; }

/* -----------------------------------------------------------------------------
   19  EMERGENCY STRIP AND CTA BAND
   -------------------------------------------------------------------------- */

.emergency-strip {
  position: relative;
  background: var(--blue);
  color: #fff;
  overflow: hidden;
}
/* Diagonal hazard stripes, very faint. */
.emergency-strip::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    -45deg,
    rgba(0,0,0,.09) 0 22px,
    transparent 22px 44px
  );
  pointer-events: none;
}
.emergency-strip__inner {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.3rem;
  padding-block: clamp(1.6rem, 1.2rem + 1.4vw, 2.4rem);
}
.emergency-strip__text { display: flex; align-items: center; gap: 1rem; min-width: 0; }
.emergency-strip__text > .icon {
  width: 52px; height: 52px;
  flex: none;
  padding: 12px;
  border-radius: 50%;
  background: rgba(255,255,255,.16);
  color: #fff;
  animation: pulseRing 2.6s var(--ease) infinite;
}
@keyframes pulseRing {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,255,.34); }
  55%      { box-shadow: 0 0 0 14px rgba(255,255,255,0); }
}
.emergency-strip h2 {
  color: #fff;
  font-size: clamp(1.2rem, 1rem + 1vw, 1.7rem);
  margin-bottom: .18rem;
}
.emergency-strip p { color: #fff; font-size: var(--fs-sm); }
/* The strip itself is red, so an ink wipe reads clearly against it (4.03:1)
   and is kept rather than flipped to white. */
.emergency-strip .btn {
  --btn-bg: #fff; --btn-fg: var(--blue); --btn-bd: #fff;
  --btn-wipe: var(--ink-900); --btn-wipe-fg: #fff;
  box-shadow: 0 10px 26px rgba(0,0,0,.18);
}

/* The closing call to action on every page. */
.cta-band {
  position: relative;
  background: var(--ink-950);
  color: #fff;
  overflow: hidden;
  isolation: isolate;
}
.cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px);
  background-size: 58px 58px;
  -webkit-mask-image: radial-gradient(ellipse 70% 90% at 50% 50%, #000 5%, transparent 72%);
  mask-image: radial-gradient(ellipse 70% 90% at 50% 50%, #000 5%, transparent 72%);
}
.cta-band::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  translate: -50% -50%;
  width: min(900px, 110%); height: 460px;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(0, 147, 221,.26) 0%, rgba(0, 147, 221,0) 70%);
  pointer-events: none;
}
.cta-band__inner {
  padding-block: clamp(3.2rem, 2rem + 5vw, 6rem);
  text-align: center;
  max-width: 44rem;
  margin-inline: auto;
}
.cta-band h2 {
  color: #fff;
  font-size: clamp(1.9rem, 1.2rem + 3vw, 3.2rem);
  letter-spacing: -.038em;
}
.cta-band p { color: rgba(255,255,255,.76); font-size: var(--fs-lede); margin-top: var(--s-4); }
.cta-band .btn-row { justify-content: center; margin-top: var(--s-6); }
.cta-band .eyebrow { color: var(--blue-hot); }
.cta-band .eyebrow::before { background: var(--blue-hot); }

/* -----------------------------------------------------------------------------
   20  FOOTER
   -------------------------------------------------------------------------- */

.site-footer {
  position: relative;
  background: var(--ink-950);
  color: var(--on-dark-soft);
  padding-top: clamp(3rem, 2rem + 4vw, 5rem);
  font-size: var(--fs-sm);
  overflow: hidden;
}
.site-footer::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.028) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(ellipse 100% 60% at 50% 0%, #000 5%, transparent 75%);
  mask-image: radial-gradient(ellipse 100% 60% at 50% 0%, #000 5%, transparent 75%);
}
.site-footer > .container { position: relative; z-index: 1; }

.footer-top {
  display: grid;
  gap: clamp(2rem, 1.2rem + 2.6vw, 3.4rem);
  padding-bottom: clamp(2.4rem, 1.6rem + 2.4vw, 3.6rem);
}
@media (min-width: 720px)  { .footer-top { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .footer-top { grid-template-columns: 1.7fr 1fr 1fr 1.35fr; } }

.footer-brand > p { margin-top: 1.1rem; color: var(--on-dark-mute); line-height: 1.7; font-size: var(--fs-sm); }

.footer-social { display: flex; gap: .55rem; margin-top: 1.3rem; }
.footer-social a {
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.12);
  color: #fff;
  transition: background-color .24s var(--ease), border-color .24s var(--ease), transform .3s var(--ease-out);
}
.footer-social a:hover { background: var(--blue); border-color: var(--blue); transform: translateY(-3px); }
.footer-social .icon { width: 1.05rem; height: 1.05rem; }

.footer-col h2 {
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #fff;
  margin-bottom: 1.1rem;
  padding-bottom: .7rem;
  border-bottom: 1px solid rgba(255,255,255,.1);
  position: relative;
}
.footer-col h2::after {
  content: "";
  position: absolute;
  left: 0; bottom: -1px;
  width: 34px; height: 2px;
  background: var(--blue);
}
.footer-col ul { display: grid; gap: .6rem; }
.footer-col a { color: var(--on-dark-soft); text-decoration: none; transition: color .2s var(--ease), padding-left .26s var(--ease); }
.footer-col ul:not(.footer-contact) a:hover { color: var(--blue-hot); padding-left: .35rem; }

.footer-contact li { display: flex; gap: .7rem; line-height: 1.6; }
.footer-contact .icon { width: 1.05rem; height: 1.05rem; color: var(--blue-hot); margin-top: .3rem; flex: none; }
.footer-contact a { color: #fff; font-weight: 600; }
.footer-contact a:hover { color: var(--blue-hot); }
.footer-address { font-style: normal; color: var(--on-dark-mute); }

.footer-areas {
  padding-block: 1.5rem;
  border-top: 1px solid rgba(255,255,255,.1);
  font-size: var(--fs-xs);
  color: var(--on-dark-mute);
  line-height: 1.9;
}
.footer-areas strong { color: #fff; }
.footer-areas a { color: #fff; text-decoration: none; }
.footer-areas a:hover { color: var(--blue-hot); }

.footer-bottom {
  display: grid;
  gap: 1rem;
  padding-block: 1.6rem;
  border-top: 1px solid rgba(255,255,255,.1);
  font-size: var(--fs-xs);
  color: var(--on-dark-mute);
}
@media (min-width: 900px) {
  .footer-bottom { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
  .footer-bottom > ul { justify-self: end; }
  .footer-credit { grid-column: 1 / -1; }
}
.footer-bottom ul { display: flex; flex-wrap: wrap; gap: 1.2rem; }
.footer-bottom a { color: var(--on-dark-soft); text-decoration: none; }
.footer-bottom a:hover { color: var(--blue-hot); }
.footer-credit { padding-top: .4rem; border-top: 1px solid rgba(255,255,255,.06); }
@media (max-width: 767px) { .site-footer { padding-bottom: 64px; } }

/* -----------------------------------------------------------------------------
   21  BREADCRUMBS
   -------------------------------------------------------------------------- */

.breadcrumbs { font-size: var(--fs-xs); }
.breadcrumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.breadcrumbs li { display: inline-flex; align-items: center; gap: .5rem; color: var(--text-mute); }
.breadcrumbs li + li::before { content: "/"; color: var(--line-2); }
.breadcrumbs a { color: var(--text-soft); text-decoration: none; font-weight: 600; }
.breadcrumbs a:hover { color: var(--blue); }
.breadcrumbs [aria-current="page"] { color: var(--text); font-weight: 700; }
.page-hero .breadcrumbs li { color: rgba(255,255,255,.5); }
.page-hero .breadcrumbs li + li::before { color: rgba(255,255,255,.3); }
.page-hero .breadcrumbs a { color: rgba(255,255,255,.72); }
.page-hero .breadcrumbs a:hover { color: var(--blue-hot); }
.page-hero .breadcrumbs [aria-current="page"] { color: #fff; }

/* -----------------------------------------------------------------------------
   22  LIGHTBOX
   -------------------------------------------------------------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(1rem, .6rem + 2vw, 3rem);
  background: rgba(8, 9, 12, .94);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity .28s var(--ease), visibility .28s;
}
.lightbox[hidden] { display: grid; }
.lightbox.is-open { opacity: 1; visibility: visible; }
.lightbox__figure { max-width: min(1100px, 100%); }
.lightbox__figure img {
  width: 100%;
  max-height: 78vh;
  object-fit: contain;
  border-radius: var(--r-md);
}
.lightbox__figure figcaption {
  margin-top: 1rem;
  text-align: center;
  color: rgba(255,255,255,.78);
  font-size: var(--fs-sm);
}
.lightbox__btn {
  position: absolute;
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  border-radius: 50%;
  background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.2);
  color: #fff;
  transition: background-color .22s var(--ease);
}
.lightbox__btn:hover { background: var(--blue); border-color: var(--blue); }
.lightbox__close { top: 1.2rem; right: 1.2rem; }
.lightbox__prev { left: 1.2rem; top: 50%; translate: 0 -50%; }
.lightbox__next { right: 1.2rem; top: 50%; translate: 0 -50%; }
.lightbox__btn .icon { width: 1.3rem; height: 1.3rem; }

/* -----------------------------------------------------------------------------
   23  COOKIE BANNER
   -------------------------------------------------------------------------- */

.cookie-banner {
  position: fixed;
  left: clamp(.75rem, 2vw, 1.5rem);
  bottom: clamp(.75rem, 2vw, 1.5rem);
  z-index: 150;
  width: min(420px, calc(100vw - 1.5rem));
  padding: 1.4rem 1.5rem;
  background: var(--ink-850);
  color: var(--on-dark-soft);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: var(--r-lg);
  box-shadow: 0 24px 60px rgba(0,0,0,.5);
  font-size: var(--fs-xs);
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .34s var(--ease), transform .4s var(--ease-out);
}
.cookie-banner[hidden] { display: none; }
.cookie-banner.is-visible { opacity: 1; transform: translateY(0); }
@media (max-width: 767px) { .cookie-banner { bottom: calc(64px + .75rem); } }
.cookie-banner h2 { font-size: 1rem; color: #fff; margin-bottom: .5rem; }
.cookie-banner__actions { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1rem; }
.cookie-banner__actions .btn { padding: .65rem 1.2rem; font-size: var(--fs-xs); }
.cookie-banner__actions .btn--outline { --btn-fg: #fff; --btn-bd: rgba(255,255,255,.28); }
.cookie-banner__link { margin-top: .8rem; }
.cookie-banner__link a { color: var(--blue-hot); }

/* -----------------------------------------------------------------------------
   27  COMPONENT DETAIL
   The small pieces the sections above depend on: the trust bar's two-line
   items, the years badge over the about photograph, the coverage banner and
   the number-and-denominator pairs.
   -------------------------------------------------------------------------- */

/* Trust bar item: label on top, detail underneath. */
.trustbar__item > span { display: grid; gap: .1rem; min-width: 0; }
.trustbar__item strong {
  font-family: var(--ff-display);
  font-size: .96rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--text);
}
.trustbar__item > span > span { font-size: var(--fs-xs); font-weight: 500; color: var(--text-mute); }

/* A denominator, set smaller and lighter than the score it follows. */
.hero__card strong small,
.rating-block__score small {
  font-size: .48em;
  font-weight: 700;
  opacity: .55;
  letter-spacing: 0;
}

/* The experience badge that sits over the corner of the about photograph. */
.split__media--stacked { position: relative; }
.years-badge {
  position: absolute;
  right: clamp(-.5rem, -1vw, 0rem);
  bottom: clamp(-1rem, -2vw, -.5rem);
  display: grid;
  gap: .1rem;
  padding: 1.15rem 1.4rem;
  min-width: 9.5rem;
  border-radius: var(--r-lg);
  background: var(--blue);
  color: #fff;
  box-shadow: var(--sh-blue);
}
.years-badge strong {
  font-family: var(--ff-display);
  font-size: clamp(2.1rem, 1.6rem + 1.8vw, 2.9rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.05em;
}
.years-badge span { font-size: var(--fs-micro); font-weight: 700; letter-spacing: .04em; line-height: 1.35; opacity: .95; }
/* On phones the badge hangs off the bottom edge of the photograph instead of
   sitting on it: pinned inside the bottom-right corner it covered the
   breakers and main switch in the owner's consumer unit photograph, which is
   the whole subject of the picture. Below 900px the column is a plain block,
   so the auto left margin right-aligns it. */
@media (max-width: 560px) {
  .split__media--stacked > .years-badge {
    position: relative;
    right: auto;
    bottom: auto;
    margin: -1.75rem .75rem 0 auto;
    width: max-content;
    padding: .9rem 1.1rem;
    min-width: 0;
  }
}

/* Coverage --------------------------------------------------------------- */
.coverage {
  display: grid;
  gap: clamp(1.6rem, 1rem + 2.4vw, 3rem);
  align-items: center;
}
@media (min-width: 980px) { .coverage { grid-template-columns: minmax(0, 1.35fr) minmax(0, .95fr); } }

/* The base panel sits on the dark section, so it needs to lift off it. */
.section--deep .coverage__base { background: var(--ink-800); border: 1px solid rgba(255,255,255,.1); margin-bottom: 0; }
.coverage__base-label { display: inline-flex; align-items: center; gap: .45rem; }
.coverage__base-label .icon { width: .95rem; height: .95rem; }

/* Rendered as a <dl>: pairs of small label and large figure. */
.coverage__base-facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .8rem;
  margin-block: 1.2rem;
}
.coverage__base-facts > div {
  padding: .85rem 1rem;
  border-radius: var(--r-md);
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.09);
}
.coverage__base-facts dt {
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--on-dark-mute);
}
.coverage__base-facts dd {
  margin: .15rem 0 0;
  font-family: var(--ff-display);
  font-size: 1.7rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.04em;
  color: var(--blue-hot);
}

.coverage__banner {
  position: relative;
  margin-block: clamp(2rem, 1.2rem + 2.4vw, 3.2rem);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.coverage__banner img { width: 100%; height: 100%; object-fit: cover; }
.coverage__banner figcaption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: clamp(1.6rem, 1rem + 3vw, 3rem) clamp(1.2rem, .8rem + 1.6vw, 2rem) clamp(1rem, .8rem + 1vw, 1.5rem);
  background: linear-gradient(to top, rgba(8,9,12,.9), rgba(8,9,12,0));
}
.coverage__banner figcaption span {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: #fff;
}
.coverage__banner figcaption .icon { width: 1.05rem; height: 1.05rem; color: var(--blue-hot); }

/* The count that follows each area name. */
.coverage__area h3 > span {
  margin-left: auto;
  display: grid;
  place-items: center;
  min-width: 1.75rem;
  height: 1.75rem;
  padding-inline: .4rem;
  border-radius: var(--r-pill);
  background: var(--blue-tint);
  color: var(--blue-ink);
  font-family: var(--ff-body);
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: 0;
}
.section--deep .coverage__area {
  background: var(--ink-800);
  border-color: rgba(255,255,255,.1);
}
.section--deep .coverage__area h3 { color: #fff; border-bottom-color: rgba(255,255,255,.1); }
.section--deep .coverage__area h3 > span { background: rgba(0, 147, 221,.2); color: var(--blue-hot); }
.section--deep .coverage__places li { color: var(--on-dark-soft); }
.section--deep .coverage__places li + li::before { color: var(--ink-500); }
.section--deep .coverage__area:hover { border-color: rgba(255,255,255,.24); box-shadow: 0 16px 40px rgba(0,0,0,.35); }
.coverage__foot { font-size: var(--fs-sm); }
.coverage__foot a { color: var(--blue-hot); font-weight: 700; }

/* The marquee's bolt glyph should not fight the words either side of it. */
.marquee .icon { color: rgba(255,255,255,.55); }

/* Case study card heading: it is a link, but it must read as a heading. */
.cs-card__body h3 a { color: inherit; text-decoration: none; }
.cs-card:hover .cs-card__body h3 a { color: var(--blue); }
.section--deep .cs-card__body h3 a { color: #fff; }

/* A single column, so the "check your postcode" button gets the full width of
   the panel rather than whichever half grid auto-placement handed it. */
.coverage__base { grid-template-columns: none; gap: .9rem; }
.coverage__base .btn { margin-top: .4rem; }

/* Every component below sets a text colour chosen for a white surface. When
   one lands inside a dark section it has to be told, or it renders charcoal
   on near-black. Collected here rather than repeated at each component. */
.section--deep .process__step p,
.section--deep .detail-card p,
.section--deep .detail-card li,
.section--deep .audience__body > p,
.section--deep .audience__list li,
.section--deep .cs-card__body p,
.section--deep .cs-card__meta,
.section--deep .faq__answer p,
.section--deep .faq__answer li,
.section--deep .contact-method p,
.section--deep .testimonial__job,
.section--deep .coverage__foot,
.section--deep .lede { color: var(--on-dark-soft); }

.section--deep .card,
.section--deep .detail-card,
.section--deep .cs-card,
.section--deep .contact-method,
.section--deep .audience__panel {
  background: var(--ink-800);
  border-color: rgba(255,255,255,.1);
}
.section--deep .card h3, .section--deep .detail-card h3,
.section--deep .cs-card h3, .section--deep .audience__panel h3 { color: #fff; }
.section--deep .detail-card__head { border-bottom-color: rgba(255,255,255,.1); }
.section--deep .card__icon,
.section--deep .detail-card__head .icon,
.section--deep .contact-method > .icon { background: rgba(0, 147, 221,.16); color: var(--blue-hot); }
.section--deep .contact-method a { color: #fff; }
.section--deep .contact-method a:hover { color: var(--blue-hot); }
.section--deep .contact-method h3 { color: var(--on-dark-mute); }
.section--deep .sibling-link {
  background: var(--ink-800);
  border-color: rgba(255,255,255,.1);
  color: #fff;
}
.section--deep .sibling-link:hover { background: var(--blue); border-color: var(--blue); }
.section--deep .table-wrap { background: var(--ink-800); border-color: rgba(255,255,255,.1); }
.section--deep .table td { color: var(--on-dark-soft); }
.section--deep .table tbody tr:nth-child(even) { background: rgba(255,255,255,.03); }
.section--deep .table tbody tr + tr { border-top-color: rgba(255,255,255,.08); }
.section--deep .table td strong, .section--deep .table th[scope="row"] { color: #fff; }
.section--deep .cred-chip, .section--deep .code-pill {
  background: rgba(255,255,255,.06);
  border-color: rgba(255,255,255,.12);
  color: var(--on-dark-soft);
}
.section--deep .cred-chip .icon, .section--deep .code-pill .icon { color: var(--blue-hot); }
.section--deep .map-embed { border-color: rgba(255,255,255,.12); background: var(--ink-800); }
.section--deep .pullquote { color: #fff; }

/* -----------------------------------------------------------------------------
   28  NARROW-VIEWPORT GUARDS
   Grid and flex items default to min-width:auto, which means they refuse to
   shrink below their own content and push the page wider than the phone. Every
   track that can hold a long unbroken run of text or a wide flex row is told
   it may shrink instead.
   -------------------------------------------------------------------------- */

.grid > *,
.split > *,
.section-head--split > *,
.audience > *,
.coverage > *,

/* The score row: five stars, a two-part figure and a sentence. On a phone that
   is wider than the screen as one line, so it is allowed to wrap. */
.rating-block { flex-wrap: wrap; }
.rating-block__meta { min-width: 0; flex: 1 1 12ch; }
.rating-block .stars { flex: none; }
@media (max-width: 480px) {
  .rating-block { padding: 1.1rem 1.2rem; gap: .7rem 1rem; }
  .rating-block__score { font-size: 2.1rem; }
}

/* Long email addresses and URLs in body copy. break-word rather than anywhere,
   so a break mid-word is the last resort after the <wbr> that
   email_breakable() puts before the @. */
.prose a, .footer-contact a, .contact-method a { overflow-wrap: break-word; }

/* Zero on purpose. The card now rises out of this section rather than
   dragging it up, so the section is only the part of the card below the hero
   edge; a band underneath that read as a gap. The note this rule used to
   carry, about the home page marquee sitting flush, is out of date — the home
   page has no trust bar any more. All seven pages that do have one are
   followed by a .section, which brings 112px of its own top padding. */
.trustbar { padding-bottom: 0; }

/* Restore the focus ring's white band on the buttons that carry a box-shadow
   of their own. --sh-blue on .btn--primary and the lifted shadow on the
   emergency strip button both replace the band set by :focus-visible, and on a
   dark section the band is the only half of the ring that shows. This sits
   after those rules so it wins on source order. */
.btn:focus-visible,
.nav-toggle:focus-visible,
.footer-social a:focus-visible,
.header-strip__socials a:focus-visible,
.lightbox__btn:focus-visible { box-shadow: 0 0 0 2px var(--white); }

/* -----------------------------------------------------------------------------
   29  INNER PAGE LAYOUTS
   The patterns the reference sites use on everything that is not the home page:
   a service page with a sticky sidebar, benefit grids, image collages, quote
   bands and filter chips.
   -------------------------------------------------------------------------- */

/* --- Page hero with a photograph beside the title ------------------------- */
.page-hero--split .page-hero__grid {
  display: grid;
  gap: clamp(1.8rem, 1rem + 3vw, 3.5rem);
  align-items: center;
}
@media (min-width: 1000px) {
  .page-hero--split .page-hero__grid { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); }
}
.page-hero--split .page-hero__inner { max-width: none; padding-bottom: clamp(1rem, .6rem + 1vw, 2rem); }
.page-hero__media { position: relative; }
.page-hero__media picture, .page-hero__media img {
  border-radius: var(--r-lg);
  overflow: hidden;
  width: 100%;
}
.page-hero__media > picture { box-shadow: 0 30px 70px rgba(0, 0, 0, .5); }
@media (max-width: 999px) { .page-hero__media { display: none; } }

/* --- Two photographs, offset, with the badge over the join ---------------- */
.collage {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(.6rem, .4rem + .8vw, 1rem);
  align-items: start;
}
.collage picture { border-radius: var(--r-lg); overflow: hidden; display: block; }
.collage img { width: 100%; height: 100%; object-fit: cover; }
.collage > :first-child { aspect-ratio: 3 / 4; margin-top: clamp(1.5rem, 1rem + 2vw, 3rem); }
.collage > :first-child img { aspect-ratio: 3 / 4; }
.collage > :nth-child(2) { aspect-ratio: 4 / 5; }
.collage > :nth-child(2) img { aspect-ratio: 4 / 5; }
.collage > picture { box-shadow: var(--sh-3); }

/* --- Service page: content plus a sticky sidebar -------------------------- */
.svc-layout {
  display: grid;
  gap: clamp(2rem, 1.2rem + 3vw, 3.5rem);
  align-items: start;
}
@media (min-width: 1000px) {
  .svc-layout { grid-template-columns: minmax(0, 1fr) 330px; }
  .svc-layout--left { grid-template-columns: 330px minmax(0, 1fr); }
  .svc-layout--left > .svc-aside { order: -1; }
}
.svc-main { min-width: 0; }
.svc-aside { display: grid; gap: 1.1rem; min-width: 0; }
@media (min-width: 1000px) {
  .svc-aside { position: sticky; top: calc(var(--header-h) + 1.5rem); }
}

.aside-card {
  padding: 1.4rem 1.5rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.aside-card > h2, .aside-card > h3 {
  font-size: 1.05rem;
  margin-bottom: 1rem;
  padding-bottom: .75rem;
  border-bottom: 1px solid var(--line);
}
.section--alt .aside-card { background: var(--white); }

/* The list of the other services, with the current one marked. */
.aside-nav { display: grid; gap: .35rem; }
.aside-nav a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .7rem;
  padding: .78rem .95rem;
  border-radius: var(--r-sm);
  background: var(--white);
  border: 1px solid var(--line);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-soft);
  text-decoration: none;
  transition: background-color .24s var(--ease), color .24s var(--ease),
              border-color .24s var(--ease), padding-left .26s var(--ease);
}
.aside-nav a::after {
  content: "";
  width: .95rem; height: .95rem;
  flex: none;
  opacity: .45;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .28s var(--ease-out), opacity .24s var(--ease);
}
.aside-nav a:hover { color: var(--text); border-color: var(--line-2); padding-left: 1.2rem; }
.aside-nav a:hover::after { transform: translateX(3px); opacity: 1; }
.aside-nav a[aria-current="page"] {
  background: var(--ink-900);
  border-color: var(--ink-900);
  color: #fff;
}
.aside-nav a[aria-current="page"]::after { opacity: 1; }

/* The dark "talk to us" block that sits under the sidebar nav. */
.aside-cta {
  position: relative;
  padding: 1.6rem 1.5rem;
  background: var(--ink-900);
  color: #fff;
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
}
.aside-cta::before {
  content: "";
  position: absolute;
  right: -70px; bottom: -110px;
  width: 260px; height: 260px;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(0, 147, 221,.42) 0%, rgba(0, 147, 221,0) 70%);
}
.aside-cta__icon {
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  border-radius: var(--r-md);
  background: var(--blue);
  color: #fff;
  margin-bottom: 1rem;
}
.aside-cta__icon .icon { width: 1.4rem; height: 1.4rem; }
.aside-cta h2, .aside-cta h3 { color: #fff; font-size: 1.2rem; margin-bottom: .5rem; }
.aside-cta p { color: var(--on-dark-soft); font-size: var(--fs-xs); margin-bottom: 1.1rem; }
.aside-cta__phone {
  display: block;
  font-family: var(--ff-display);
  font-size: 1.42rem;
  font-weight: 800;
  letter-spacing: -.035em;
  color: #fff;
  text-decoration: none;
  margin-bottom: 1rem;
}
.aside-cta__phone:hover { color: var(--blue-hot); }
.aside-cta .btn { width: 100%; }

/* Small credential list for the sidebar. */
.aside-list { display: grid; gap: .7rem; }
.aside-list li {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  font-size: var(--fs-xs);
  color: var(--text-soft);
  line-height: 1.5;
}
.aside-list .icon { width: 1rem; height: 1rem; color: var(--blue); margin-top: .18rem; }
.aside-list strong { color: var(--text); display: block; font-size: var(--fs-sm); }

/* --- Benefit grid: icon, title, one line. No card chrome. ---------------- */
.features {
  display: grid;
  gap: clamp(1.4rem, .9rem + 1.6vw, 2.4rem) clamp(1.4rem, 1rem + 1.8vw, 2.8rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
.feature { display: flex; gap: 1rem; }
.feature__icon {
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  flex: none;
  border-radius: var(--r-md);
  background: var(--blue-tint);
  color: var(--blue);
  transition: background-color .3s var(--ease), color .3s var(--ease), transform .4s var(--ease-out);
}
.feature:hover .feature__icon { background: var(--blue); color: #fff; transform: rotate(-8deg); }
.feature__icon .icon { width: 1.4rem; height: 1.4rem; }
.feature h3 { font-size: 1.02rem; margin-bottom: .35rem; }
.feature p { font-size: var(--fs-sm); color: var(--text-soft); }
.section--deep .feature h3 { color: #fff; }
.section--deep .feature p { color: var(--on-dark-soft); }
.section--deep .feature__icon { background: rgba(0, 147, 221,.16); color: var(--blue-hot); }

/* --- Mission / vision style pair ----------------------------------------- */
.mv-grid {
  display: grid;
  gap: clamp(1rem, .7rem + 1.2vw, 1.6rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}
.mv-card {
  position: relative;
  padding: clamp(1.5rem, 1.1rem + 1.2vw, 2.1rem);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.mv-card::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--blue);
}
.mv-card h3 { margin-bottom: .6rem; }
.mv-card p { color: var(--text-soft); font-size: var(--fs-sm); }
.section--alt .mv-card { background: var(--white); }
.section--deep .mv-card { background: var(--ink-800); border-color: rgba(255,255,255,.1); }
.section--deep .mv-card h3 { color: #fff; }
.section--deep .mv-card p { color: var(--on-dark-soft); }

/* --- A quotation given a band of its own -------------------------------- */
.quote-band {
  position: relative;
  background: var(--ink-900);
  color: #fff;
  overflow: hidden;
  isolation: isolate;
}
.quote-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(rgba(255,255,255,.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.04) 1px, transparent 1px);
  background-size: 62px 62px;
  -webkit-mask-image: radial-gradient(ellipse 70% 90% at 50% 50%, #000 5%, transparent 74%);
  mask-image: radial-gradient(ellipse 70% 90% at 50% 50%, #000 5%, transparent 74%);
}
.quote-band__inner {
  padding-block: clamp(3rem, 2rem + 4vw, 5.5rem);
  max-width: 52rem;
  margin-inline: auto;
  text-align: center;
}
.quote-band__mark {
  font-family: var(--ff-display);
  font-size: 4.5rem;
  font-weight: 800;
  line-height: .7;
  color: var(--blue);
  display: block;
  margin-bottom: .5rem;
}
.quote-band blockquote {
  font-family: var(--ff-display);
  font-size: clamp(1.25rem, 1rem + 1.5vw, 1.95rem);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -.028em;
  color: #fff;
}
.quote-band figcaption {
  margin-top: 1.4rem;
  font-size: var(--fs-sm);
  color: var(--on-dark-soft);
}
.quote-band figcaption strong { color: #fff; display: block; font-family: var(--ff-display); letter-spacing: -.02em; }
.quote-band .stars { margin-bottom: 1.2rem; }

/* --- Filter chips over a card grid --------------------------------------- */
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-bottom: clamp(1.5rem, 1rem + 1.6vw, 2.4rem);
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .55rem 1.1rem;
  border-radius: var(--r-pill);
  background: var(--white);
  border: 1px solid var(--line);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--text-soft);
  text-decoration: none;
  transition: background-color .24s var(--ease), color .24s var(--ease),
              border-color .24s var(--ease), transform .3s var(--ease-out);
}
.chip:hover { color: var(--text); border-color: var(--line-2); transform: translateY(-2px); }
.chip[aria-current="page"], .chip--on {
  background: var(--ink-900);
  border-color: var(--ink-900);
  color: #fff;
}
.chip .icon { width: .9rem; height: .9rem; }
.chip[aria-current="page"] .icon, .chip--on .icon { color: var(--blue-hot); }

/* --- A numbered definition list, for standards and codes ----------------- */
.spec-list { display: grid; gap: .8rem; }
.spec {
  display: grid;
  gap: .3rem;
  padding: 1.1rem 1.3rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  border-left: 3px solid var(--blue);
  transition: box-shadow .3s var(--ease), transform .34s var(--ease-out);
}
.spec:hover { box-shadow: var(--sh-2); transform: translateX(3px); }
.spec dt, .spec > strong {
  font-family: var(--ff-display);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--text);
}
.spec dd, .spec > span { margin: 0; font-size: var(--fs-sm); color: var(--text-soft); }
.section--alt .spec { background: var(--white); }
.section--deep .spec { background: var(--ink-800); border-color: rgba(255,255,255,.1); border-left-color: var(--blue); }
.section--deep .spec dt, .section--deep .spec > strong { color: #fff; }
.section--deep .spec dd, .section--deep .spec > span { color: var(--on-dark-soft); }

/* The credentials list on the about page, rendered as specs. */
.creds { display: grid; gap: .8rem; }
.creds__row {
  display: grid;
  gap: .3rem;
  padding: 1.1rem 1.3rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-left: 3px solid var(--blue);
  border-radius: var(--r-md);
  transition: box-shadow .3s var(--ease), transform .34s var(--ease-out);
}
.creds__row:hover { box-shadow: var(--sh-2); transform: translateX(3px); }
.creds__row dt {
  font-family: var(--ff-display);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--text);
}
.creds__row dd { margin: 0; font-size: var(--fs-sm); color: var(--text-soft); }

/* --- Contact info cards --------------------------------------------------- */
/* Four cards: four across, then two by two, then stacked. Fixed steps rather
   than auto-fit, so a card is never left alone on a row. */
.info-cards {
  display: grid;
  gap: clamp(.9rem, .6rem + 1vw, 1.4rem);
  grid-template-columns: 1fr;
}
@media (min-width: 560px)  { .info-cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .info-cards { grid-template-columns: repeat(4, 1fr); } }
.info-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: .5rem;
  padding: clamp(1.4rem, 1.1rem + 1vw, 1.9rem);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform .4s var(--ease-out), box-shadow .4s var(--ease), border-color .3s var(--ease);
}
.info-card::after {
  content: "";
  position: absolute;
  left: 0; top: 0;
  height: 3px; width: 100%;
  background: var(--blue);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .46s var(--ease-out);
}
.info-card:hover { transform: translateY(-5px); box-shadow: var(--sh-3); border-color: var(--line-2); }
.info-card:hover::after { transform: scaleX(1); }
.info-card__icon {
  display: grid;
  place-items: center;
  width: 50px; height: 50px;
  border-radius: var(--r-md);
  background: var(--blue-tint);
  color: var(--blue);
  margin-bottom: .4rem;
  transition: background-color .3s var(--ease), color .3s var(--ease);
}
.info-card:hover .info-card__icon { background: var(--blue); color: #fff; }
.info-card__icon .icon { width: 1.4rem; height: 1.4rem; }
.info-card h2, .info-card h3 { font-size: 1.08rem; }
.info-card a:not(.btn):not(.link-arrow) {
  font-family: var(--ff-display);
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--text);
  text-decoration: none;
  overflow-wrap: break-word;
}
.info-card a:not(.btn):not(.link-arrow):hover { color: var(--blue); }
.info-card a.info-card__wa:not(.btn) {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem .9rem;
  border-radius: 999px;
  background: #e8f9ef;
  color: #128c4a;
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  letter-spacing: 0;
}
.info-card a.info-card__wa:not(.btn):hover { background: #25d366; color: #fff; }
.info-card__wa .icon { width: 1.1rem; height: 1.1rem; }
.info-card p, .info-card address { font-size: var(--fs-sm); color: var(--text-soft); font-style: normal; }
.info-card__foot { margin-top: auto; padding-top: .5rem; font-size: var(--fs-xs); color: var(--text-mute); }

/* --- Opening hours table -------------------------------------------------- */
.hours { display: grid; gap: 0; }
.hours div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: .8rem 0;
  font-size: var(--fs-sm);
}
.hours div + div { border-top: 1px solid var(--line); }
.hours dt { color: var(--text-soft); }
.hours dd { margin: 0; font-weight: 700; color: var(--text); }
.hours div:last-child dd { color: var(--blue-ink); }
.section--deep .hours div + div { border-top-color: rgba(255,255,255,.1); }
.section--deep .hours dt { color: var(--on-dark-soft); }
.section--deep .hours dd { color: #fff; }
.section--deep .hours div:last-child dd { color: var(--blue-hot); }

/* The trust bar's card pulls itself up over whatever sits above it. After the
   home hero that lands on empty photograph; after a page hero it would land on
   the buttons, so a page hero that is followed by the trust bar grows enough
   bottom padding to absorb the overlap. */
.page-hero:has(+ .trustbar) { padding-bottom: clamp(3rem, 2rem + 2.5vw, 4.75rem); }

/* The lead photograph at the top of a service page's main column. */
.svc-figure { border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--sh-3); }
.svc-figure img { width: 100%; }
.svc-figure figcaption {
  padding: .9rem 1.2rem;
  background: var(--paper);
  font-size: var(--fs-xs);
  color: var(--text-soft);
}

/* -----------------------------------------------------------------------------
   30  QA FIXES
   Every rule here closes a defect found by measurement rather than by eye. The
   measured figure is quoted so the next person can tell whether a change breaks
   it again.
   -------------------------------------------------------------------------- */

/* H1 — The page hero is --ink-900, and .eyebrow is coloured --blue-ink, which is
   chosen for white paper. Measured 2.19:1 against the hero on all fifteen inner
   pages. Amber measures 11.13:1 there. .section--deep and .on-dark already had
   this override; the page hero was simply never covered by it. */
.page-hero .eyebrow { color: var(--blue-hot); }
.page-hero .eyebrow::before { background: var(--blue-hot); }

/* H2 — .callout strong sets --text, which is near-black. Inside a dark section
   the callout background is rgba(255,255,255,.05) over ink, so the emphasised
   words measured 1.00:1 and were invisible. On the emergency page that hid the
   number 105, which is the whole point of the paragraph. */
.section--deep .callout strong,
.section--deep .callout h2,
.section--deep .callout h3 { color: #fff; }
.section--deep .callout a:not(.btn):not(.link-arrow) { color: var(--blue-hot); }

/* H3 — The text column of a contact method is a flex child, so it defaults to
   min-width:auto and refuses to shrink below the width of the email address.
   At 500px that pushed the home page 15px wider than the viewport. The same
   guard is applied to the other icon-beside-text components, which have the
   same structure and would fail at some width for the same reason. */
.contact-method > div,
.feature > div,
.aside-list li > span,
.trustbar__item > span,
.proof-card__body,
.emergency-strip__text > div { min-width: 0; }

/* L1 — Breadcrumb and footer links measured 22px tall, just under the 24px
   minimum for a pointer target. Padding rather than a min-height, so the text
   baseline does not move. */
.breadcrumbs a,
.breadcrumbs [aria-current="page"] { display: inline-block; padding-block: 2px; }
.footer-contact a,
.footer-col ul a { display: inline-block; padding-block: 2px; }

/* L3 — :has() carries the hero's extra bottom padding, which stops the trust
   card overlapping the hero buttons. Firefox below 121 does not support it, so
   there the overlap is removed instead of being absorbed: the card sits under
   the hero rather than on top of the call to action. */
@supports not selector(:has(*)) {
  .trustbar__grid { margin-top: 0; }
}

/* L2 — Back to top. The longest pages run past 20,000px on a phone, which is a
   long way to swipe back. Hidden until the visitor is well down the page, and
   kept clear of the fixed call bar. */
.to-top {
  position: fixed;
  right: clamp(.9rem, 2vw, 1.6rem);
  bottom: clamp(.9rem, 2vw, 1.6rem);
  z-index: 80;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--ink-900);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow: var(--sh-3);
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity .3s var(--ease), transform .35s var(--ease-out),
              visibility .3s, background-color .24s var(--ease);
}
.to-top.is-shown { opacity: 1; visibility: visible; transform: none; }
.to-top:hover { background: var(--blue); border-color: var(--blue); }
.to-top .icon { width: 1.15rem; height: 1.15rem; }
@media (max-width: 767px) { .to-top { bottom: calc(64px + .9rem); } }
@media print { .to-top { display: none; } }

/* Floating WhatsApp button. Mirrors .to-top on the opposite corner and sits
   above the fixed call bar on phones. The label only shows on wider screens. */
.wa-float {
  position: fixed;
  left: clamp(.9rem, 2vw, 1.6rem);
  bottom: clamp(.9rem, 2vw, 1.6rem);
  z-index: 85;
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  min-height: 54px;
  padding: 0 1.25rem 0 1rem;
  border-radius: 999px;
  background: #25d366;
  color: #fff;
  font-size: var(--fs-sm);
  font-weight: 700;
  text-decoration: none;
  box-shadow: 0 10px 28px rgba(8, 9, 12, .28);
  transition: transform .24s var(--ease-out), background-color .24s var(--ease);
}
.wa-float:hover, .wa-float:focus-visible { background: #1ebe5a; color: #fff; transform: translateY(-2px); }
.wa-float .icon { width: 1.6rem; height: 1.6rem; stroke-width: 1.9; }
@media (max-width: 767px) {
  .wa-float { bottom: calc(64px + .9rem); width: 54px; padding: 0; justify-content: center; }
  .wa-float__label { display: none; }
}
@media print { .wa-float { display: none; } }

/* M4 — The vertical rhythm was tuned on a desktop viewport. On a phone the same
   padding between every band is what pushes the home page past 23,000px, so the
   section rhythm tightens below 700px. Nothing is removed; the air between
   bands is simply proportionate to the screen it is on. */
@media (max-width: 700px) {
  .section     { padding-block: 2.75rem; }
  .section--lg { padding-block: 3.25rem; }
  .section--tight { padding-block: 2rem; }
  .section-head { margin-bottom: 1.75rem; }
  .hero__inner { min-height: 0; padding-block: 3.25rem; }
  .cta-band__inner { padding-block: 2.75rem; }
  .quote-band__inner { padding-block: 2.5rem; }
  .footer-top { gap: 1.75rem; padding-bottom: 2rem; }
  .grid { gap: 1rem; }
  .process { gap: 1.5rem; }
  .process__step { padding-top: 3.9rem; }
}

/* The icon set has no upward chevron, so the downward one is turned. */
.to-top__icon { transform: rotate(180deg); }

/* The cookie banner sits bottom-left and is up to 420px wide, so on a phone it
   reaches under the back-to-top button. Rather than guess at an offset that
   would have to track the banner height, the button simply stands down while
   the banner is on screen: the banner is dismissed once, and the button only
   matters much further down the page. The button is placed after the banner in
   the DOM so this sibling selector can reach it. */
.cookie-banner.is-visible ~ .to-top { display: none; }

/* The utility strip's email link measured 22px tall, the same miss as the
   footer one. */
.header-strip a { display: inline-block; padding-block: 2px; }

/* -----------------------------------------------------------------------------
   31  HOVER STATES
   Measured by re-emitting every :hover rule against a class and reading the
   resulting foreground/background pair, so these are real ratios rather than
   guesses.
   -------------------------------------------------------------------------- */

/* The active chip set white text on an ink fill with a single class, so the
   generic .chip:hover — one class heavier — repainted the label --text and the
   word disappeared into its own background. Measured 1.00:1 on the "All
   projects" chip. The active state now restates itself for hover. */
.chip--on:hover,
.chip[aria-current="page"]:hover {
  background: var(--ink-800);
  border-color: var(--ink-800);
  color: #fff;
}

/* --blue is 4.79:1 on white but only 4.43:1 on --paper, so a hover that lands on
   a paper surface — an --alt section, or inside a .callout — fell just under
   AA. --blue-ink is 8.81:1 on white and 8.16:1 on paper and reads just as
   clearly as a hover change. */
.nav__link:hover,
.nav__dropdown a:hover,
.nav__dropdown a[aria-current="page"],
.link-arrow:hover { color: var(--blue-ink); }

/* The arrow link's underline is decoration rather than text, so it keeps the
   brighter brand red. */
.link-arrow:hover { background-image: linear-gradient(var(--blue), var(--blue)); }

/* Every surface where a button sits on ink rather than on paper. Without this
   the hover wipe repaints the button --ink-900 on an --ink-900 background and
   the control disappears: measured 1.03:1 on the home hero, 1.05:1 in the dark
   form panel and 1.11:1 in the sidebar call block. A white wipe with ink text
   reads at about 19:1 against all of them. */
.hero .btn,
.page-hero .btn,
.section--deep .btn,
.cta-band .btn,
.quote-band .btn,
.aside-cta .btn,
.form-panel--dark .btn,
.cookie-banner .btn,
.cs-panel--dark .btn,
.card--dark .btn,
.mobile-nav .btn {
  --btn-wipe: #fff;
  --btn-wipe-fg: var(--ink-900);
}

/* -----------------------------------------------------------------------------
   32  REASON GRID
   The "why us" points used .card.card--dark, which is the service card with a
   dark fill: same boxed shape, same corner numeral, same icon tile. On the home
   page that put two grids of visually identical cards a screen apart, and the
   sections read as one list. These are reasons, not services, so they get their
   own shape: a horizontal row inside a hairline matrix, with no numeral and a
   filled circular icon. Nothing here is shared with .card.
   -------------------------------------------------------------------------- */

.why-grid {
  display: grid;
  gap: 1px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.why-item {
  display: flex;
  gap: 1.1rem;
  padding: clamp(1.45rem, 1.1rem + 1.1vw, 2rem);
  background: var(--white);
  transition: background-color .32s var(--ease);
}
.why-item:hover { background: var(--paper); }
.why-item__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: 50%;
  background: var(--blue);
  color: #fff;
  transition: transform .42s var(--ease-out);
}
.why-item:hover .why-item__icon { transform: rotate(-8deg) scale(1.06); }
.why-item__icon .icon { width: 1.3rem; height: 1.3rem; }
.why-item__body { min-width: 0; }
.why-item h3 { font-size: 1.04rem; margin-bottom: .4rem; }
.why-item p { font-size: var(--fs-sm); color: var(--text-soft); }

/* On the dark bands, which is where all of them currently sit. */
.section--deep .why-grid { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.1); }
.section--deep .why-item { background: var(--ink-900); }
.section--deep .why-item:hover { background: var(--ink-800); }
.section--deep .why-item h3 { color: #fff; }
.section--deep .why-item p { color: var(--on-dark-soft); }

/* -----------------------------------------------------------------------------
   33  ADJACENT DARK BANDS
   Two --deep sections in a row share one background and read as a single slab,
   which is what made "why us" and "where we work" look merged on the home page.
   The second drops to the deeper ink and takes a hairline, so the boundary is
   legible without introducing a light band between them.
   -------------------------------------------------------------------------- */

.section--deep + .section--deep,
.section--deep + .quote-band,
.quote-band + .section--deep {
  background: var(--ink-950);
  border-top: 1px solid rgba(255, 255, 255, .14);
}
.section--deep + .section--deep .why-item,
.section--deep + .section--deep .card--dark,
.section--deep + .section--deep .coverage__area,
.section--deep + .section--deep .coverage__base { background: var(--ink-900); }

/* The area count sits on a 20%-red pill. --blue-hot measured 4.08:1 against that
   over --ink-800 and 4.53:1 over --ink-900 — a fail on one surface and a hair
   over the line on the other. White is 15.21:1 and 16.90:1 respectively, and a
   small bold numeral on a red pill reads better in white anyway. */
.section--deep .coverage__area h3 > span { color: #fff; }

/* -----------------------------------------------------------------------------
   34  MEDIA COLUMNS MATCH THEIR COPY
   A photograph keeps its own aspect ratio, so beside a long text column it ended
   up far shorter and floated in the middle of the band: measured 341px of image
   against 737px of copy on the home page, and 398 against 803 on the about page.
   The media column now stretches to the height of the row and the photograph
   fills it, cropping rather than leaving the gap.

   align-self on the media item alone, rather than align-items on the container,
   because .split--sticky-lead needs its first child to stay shorter than the row
   or position:sticky has nothing to travel through.
   -------------------------------------------------------------------------- */

@media (min-width: 900px) {
  .split__media {
    align-self: stretch;
    display: flex;
    flex-direction: column;
  }
  /* The photograph takes whatever height is left after any callout or proof
     card sitting underneath it in the same column. */
  .split__media > picture,
  .split__media > .collage { flex: 1 1 auto; min-height: 0; }
  .split__media > picture > img { width: 100%; height: 100%; object-fit: cover; }
  /* The home page's who-we-are photograph is a consumer unit whose devices
     sit right of centre; a centred cover crop in the tall box cut the main
     switch in half at 900-990px. */
  .split__media--stacked > picture > img { object-position: 54% 50%; }
  /* Same for the emergency page, where the tall box otherwise halves the
     main switch at 900-1010px. */
  .split__media > picture > img.img-focus-right { object-position: 58% 50%; }

  /* Capped. Left to grow freely against a long text column the photograph
     became a 1:1.35 crop on the home page and the collage tiles reached
     1:3, which is no longer a picture of anything. Whatever height is left
     over is centred rather than added to the image. */
  .split__media { justify-content: center; }
  /* The photograph takes its natural 16:10 as a starting height, then grows
     to fill whatever the copy beside it needs. A fixed 4:5 was wrong in both
     directions: too short beside a long column, and too TALL in a column
     that also carries a proof card or a reason grid, which left 341px of
     empty space under the copy on the home page instead of under the
     picture. The cap stops a long column turning it into a sliver. */
  .split__media > picture {
    flex: 1 1 auto;
    aspect-ratio: 16 / 10;
    min-height: 0;
    max-height: 680px;
  }

  /* The collage keeps its designed aspect ratios: its two offset tiles are
     only ~265px wide, so stretching them to the height of a long column
     turns a landscape source into a vertical sliver. */
  .split__media > .collage { flex: 0 0 auto; }
}

@media (min-width: 1000px) {
  .page-hero--split .page-hero__grid { align-items: stretch; }
  .page-hero__media { align-self: stretch; display: flex; flex-direction: column; justify-content: center; }
  .page-hero__media > picture { flex: 1 1 auto; min-height: 0; }
  .page-hero__media > picture {
    flex: 1 1 auto;
    aspect-ratio: 16 / 10;
    min-height: 0;
    max-height: 620px;
  }
  .page-hero__media > picture > img { width: 100%; height: 100%; object-fit: cover; }
}

/* A call block is a short call to action, not a photograph, so stretching it
   would give the emergency hero a red panel two thirds of a screen tall.
   Centring it against the copy puts the number at the optical middle of the
   band instead of leaving 420px of empty ink underneath it. */
@media (min-width: 900px) {
  .split > .call-block { align-self: center; }
}

/* -----------------------------------------------------------------------------
   35  ARROW LINKS DO NOT STRETCH
   .link-arrow is inline-flex, but as a child of a flex column or a grid it
   becomes a flex/grid item and the default stretch makes it as wide as its
   container. Its hover underline is painted with background-size:100%, so on a
   service card the rule ran the full 298px of the card instead of the 161px of
   the words. align-self is inert outside a flex or grid parent, so this is safe
   everywhere the component is used, and it does not disturb the margin-top:auto
   that pins the link to the bottom of a card.
   -------------------------------------------------------------------------- */

/* Both properties: in a flex column the horizontal axis is the cross axis and
   align-self governs it, but in a grid that axis is governed by justify-self.
   Each is ignored by the container type it does not apply to. */
.link-arrow { align-self: flex-start; justify-self: start; }

/* In a .btn-row the flex axis is horizontal, so flex-start would pin the link
   to the top of the row instead of centring it beside the button. */
.btn-row > .link-arrow { align-self: center; }

/* -----------------------------------------------------------------------------
   36  COVERAGE AREAS
   The place names were an inline list separated by a middot drawn with
   li + li::before. Once the list wrapped — 17 of the 39 names did — the
   separator led the new line instead of joining two names, so every card had a
   column of orphaned dots down its left edge. They are now pills, which cannot
   produce a stray separator, wrap tidily, and fill the card instead of leaving
   the shorter regions two thirds empty.
   -------------------------------------------------------------------------- */

.coverage__places {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
}
.coverage__places li {
  padding: .3rem .7rem;
  border-radius: var(--r-pill);
  background: var(--paper);
  border: 1px solid var(--line);
  font-size: var(--fs-xs);
  line-height: 1.5;
  color: var(--text-soft);
  white-space: nowrap;
}
.coverage__places li + li::before { content: none; }

.section--deep .coverage__places li {
  background: rgba(255, 255, 255, .06);
  border-color: rgba(255, 255, 255, .12);
  color: var(--on-dark-soft);
}

/* Three columns rather than four: with five regions, four left Surrey alone on
   a row with three empty cells beside it, and the extra width lets "North and
   East London" sit on one line. */
.coverage__areas { grid-template-columns: repeat(auto-fill, minmax(min(100%, 330px), 1fr)); }

/* A two-line region name pushed its count badge to the vertical middle. */
.coverage__area h3 { align-items: flex-start; }
.coverage__area h3 > span { align-self: flex-start; }

/* The regions hold very different numbers of places — five in West London,
   fourteen in Surrey — so forcing a row to one height left the small cards two
   thirds empty. Each card is now as tall as its own pills, which is the normal
   behaviour for a tag group and reads as deliberate rather than unfinished. */
.coverage__areas { align-items: start; }

/* -----------------------------------------------------------------------------
   37  FORM FIELD ALIGNMENT
   .form-field is a grid of label / control / optional hint, and as a grid item
   it stretches to the height of its row. Where one field in a pair carried a
   hint and the other did not, the hintless field had a spare row of space and
   gave it to the control: the email input measured 79px against 54px for every
   other input on the site. Packing the rows to the top keeps every control the
   same height and lets the spare space fall below, where it belongs.
   -------------------------------------------------------------------------- */

.form-field { align-content: start; }

/* -----------------------------------------------------------------------------
   38  COLLAGE FILLS ITS COLUMN
   Side by side, the two photographs were only ~265px wide, so they could not
   fill an 800px column without being cropped to 1:3 slivers — which is why the
   collage was excluded from stretching and ended up 398px tall inside an 803px
   column. The years badge is positioned against the column, so it was left
   stranded 118px below the pictures with white space between.
   Stacking them makes each tile the full width of the column, so a pair at
   close to their natural ratio fills the height, the badge lands on the lower
   photograph where it belongs, and neither image is distorted. The offset that
   gave the pair its character is kept as alternating side margins.
   -------------------------------------------------------------------------- */

@media (min-width: 900px) {
  /* flex-basis 0, not auto: with auto the collage offers its intrinsic
     height to the row and the row grows to fit it — 1278px against 803px
     of copy. At zero basis the row is sized by the copy and the collage
     takes what is left. */
  .split__media > .collage { flex: 1 1 0; min-height: 0; }

  .collage {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr 1fr;
    align-items: stretch;
  }
  /* :first-child and :nth-child are pseudo-classes, so the stacked-layout
     rules in section 29 outrank a plain type selector. The override has to
     match them or the tiles keep their 3:4 and 4:5 ratios and end up only
     295px wide in a 546px column. */
  .collage > :first-child,
  .collage > :nth-child(2) { aspect-ratio: auto; }
  .collage > :first-child {
    margin-top: 0;
    margin-right: clamp(1.75rem, 4vw, 4rem);
  }
  .collage > :nth-child(2) {
    margin-left: clamp(1.75rem, 4vw, 4rem);
  }
  .collage > :first-child img,
  .collage > :nth-child(2) img { aspect-ratio: auto; height: 100%; object-fit: cover; }
}

/* ---------------------------------------------------------------------------
   39  THE YEARS BADGE HUGS ITS PHOTOGRAPH
   The badge is positioned against the media column, not against the picture.
   That is fine while the two are the same height, but a single photograph is
   capped at 680px so an extreme crop cannot happen, and then centred in the
   leftover space. On the home page at 1024px the column ran 207px taller than
   the picture, so the badge floated 21px below the image on bare background.

   Capping the column itself is not the answer: the flex box then shrinks to
   its content and the photograph drops to about 290px. Instead the badge is
   offset by the same gap the centring creates. Above 680px of column height
   that gap is (column - 680) / 2, which is what the max() below works out;
   below it the picture fills the column and the offset falls away to zero.

   Only the single-photograph variant needs this. The collage fills its column
   by design, so its badge already sits on the lower tile.
   --------------------------------------------------------------------------- */
@media (min-width: 900px) {
  .split__media--stacked:has(> picture) > .years-badge {
    bottom: calc(clamp(-1rem, -2vw, -.5rem) + max(0px, 50% - 340px));
  }
}

/* ---------------------------------------------------------------------------
   40  AN EYEBROW SITS WITH THE HEADING IT LABELS
   .prose h2 carries margin-top: 1.8em so that a heading breaks up a run of
   body copy. That is wrong when the heading is preceded by its own eyebrow:
   the eyebrow is inline-flex, so its bottom margin cannot collapse into the
   heading's top margin and the two add up. Measured at 1440px that put 101px
   between the label and its heading, against the 16px every other eyebrow on
   the same page gets, which read as the heading having drifted loose.

   Zeroing the heading's top margin leaves the eyebrow's own 1rem, so these
   match the section-head pattern used everywhere else.
   --------------------------------------------------------------------------- */
.prose .eyebrow + h2,
.prose .eyebrow + h3 { margin-top: 0; }

/* ---------------------------------------------------------------------------
   41  BREADCRUMB CLEARANCE, AND THE TRUST CARD ACTUALLY STRADDLING THE HERO

   Two faults in the same strip, both on every page that has a page hero.

   The hero carries no padding of its own: its top space lives on
   .page-hero__inner. The breadcrumb is a sibling of .page-hero__grid, so it
   sits outside that padding and lands flush against the sticky header —
   measured 0px of clearance, with 97px of empty band below it. The space is
   moved rather than added: the breadcrumb takes a little off the top and the
   inner gives back exactly what it took, so the hero is no taller than before.

   The trust card is meant to straddle the dark hero and the white below it,
   which is what the negative margin is for. But .trustbar has no top padding
   or border, so that margin collapsed straight through it and dragged the
   whole white section up instead of just the card: the section began 56px
   above the hero's bottom edge and painted white over it. The card never
   overlapped anything — the dark band was simply cut short. A block formatting
   context stops the margin escaping, so the section stays put and only the
   card rises.
   --------------------------------------------------------------------------- */
.page-hero .breadcrumbs { padding-top: clamp(1.1rem, .8rem + .9vw, 1.75rem); }
.breadcrumbs + .page-hero__grid .page-hero__inner,
.breadcrumbs + .page-hero__inner {
  padding-top: calc(clamp(2.6rem, 1.6rem + 5vw, 5.5rem) - clamp(1.1rem, .8rem + .9vw, 1.75rem));
}

.trustbar { display: flow-root; }

/* ---------------------------------------------------------------------------
   42  TWO SECTIONS OF THE SAME COLOUR SHOULD NOT PAY FOR THE GAP TWICE
   Every band carries padding top and bottom, which is right when the next band
   is a different colour: the change of background does the separating and the
   padding gives each one air. Where two bands share a background there is no
   boundary to see, so the two paddings simply add up into one void — measured
   at 1440px, 224px between the two paper bands on the case studies page, and
   184px to 250px in nine other places across seven pages.

   The second band gives up its top padding, leaving the first band's bottom
   padding as the whole gap, which is the same rhythm a single section already
   sets. Bands of different colours are untouched.

   A flat zero is right for a normal band: its own bottom padding is already
   the whole gap — 56px on a phone, 78px on a tablet, 112px on a desktop.
   The exception is a --tight band, whose padding is smaller, and which on a
   narrow viewport left only 40px. That one case is topped up to a 3.5rem
   floor and no further.

   An earlier version topped every pair up by 4.5rem - 6vw. That holds the gap
   near 104px at every width, which is right on a desktop and much too much on
   a phone: it put 120px of empty space between two white bands on a 375px
   screen, which is a third of the screen width.

   Deliberately not extended to .section--deep: two dark bands running together
   was a different problem, and the answer there was to change one of them
   rather than to pull them closer.
   --------------------------------------------------------------------------- */
.section:not(.section--alt):not(.section--deep) + .section:not(.section--alt):not(.section--deep),
.section--alt + .section--alt { padding-top: 0; }

/* Below 700px the rhythm is already tightened by section M4: a band is
   padded 2.75rem and a tight band 2rem. Left at zero the whole gap would be
   44px, against 28px between a section head and its content — not enough of
   a step to read as a new band. Topped up to a flat 3.5rem, which is the
   same figure the clamp reaches on its own just above this breakpoint. */
@media (max-width: 700px) {
  .section:not(.section--alt):not(.section--deep) + .section:not(.section--alt):not(.section--deep),
  .section--alt + .section--alt { padding-top: .75rem; }

  .section--tight:not(.section--alt):not(.section--deep) + .section:not(.section--alt):not(.section--deep),
  .section--tight.section--alt + .section--alt { padding-top: 1.5rem; }
}

/* ---------------------------------------------------------------------------
   43  A FOUR STEP PROCESS WRAPS 4 / 2+2 / 1, NEVER 3+1
   auto-fit packs in as many 240px columns as will fit, which between about
   860px and 1200px comes to three — leaving the fourth step stranded on a row
   of its own under a row of three. Both processes on this site have exactly
   four steps, so the counts are stated rather than derived.

   The dashed connector is drawn towards the next badge and hidden on the last
   step. On two rows that is not enough: the step at the end of the first row
   trails a line into the gutter with nothing to join. Hidden per row.
   --------------------------------------------------------------------------- */
@media (min-width: 640px) {
  .process { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1200px) {
  .process { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 760px) and (max-width: 1199.98px) {
  .process__step:nth-child(2n)::after { display: none; }
}

/* ---------------------------------------------------------------------------
   44  THE SECTOR LIST
   .chips set display:flex and nothing else — no rule ever existed for its
   items — so eight icons and eight labels ran together in one cramped line,
   each icon sitting above its own label with no card, padding or separation
   to tell one sector from the next. Under a full section head it read as a
   caption rather than as content.

   Now a grid of small cards in the same language as the trust bar: the icon
   in a tinted square, the label beside it, one border and one radius. Eight
   items land as 4x2, 3x3, 2x4 or a single column depending on the width.
   --------------------------------------------------------------------------- */
.sector-grid {
  display: grid;
  gap: clamp(.7rem, .45rem + .8vw, 1.1rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 232px), 1fr));
}
.sector {
  display: flex;
  align-items: center;
  gap: .85rem;
  padding: .95rem 1.1rem;
  border-radius: var(--r-md);
  background: var(--white);
  border: 1px solid var(--line);
  box-shadow: var(--sh-1);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--text);
  line-height: 1.35;
  transition: border-color .22s var(--ease), box-shadow .22s var(--ease), transform .22s var(--ease);
}
.sector:hover {
  border-color: var(--blue);
  box-shadow: var(--sh-2);
  transform: translateY(-2px);
}
.sector__icon {
  width: 40px;
  height: 40px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--blue-tint);
  color: var(--blue);
}
.sector__icon .icon { width: 1.15rem; height: 1.15rem; }

/* On a dark band the tint and the white card would both disappear. */
.section--deep .sector {
  background: rgba(255,255,255,.05);
  border-color: rgba(255,255,255,.12);
  color: #fff;
  box-shadow: none;
}
.section--deep .sector__icon { background: rgba(0, 147, 221,.18); color: var(--blue-hot); }

/* ---------------------------------------------------------------------------
   45  THE SINGLE CASE STUDY PAGE
   Five faults in the shared template, so all six pages carry every one.

   a. The lead photograph's caption ran straight into the "What we did"
      heading. .cs-lead sets a font and a colour and no spacing at all, so the
      measured distance between the two was 0px.

   b. The key facts strip is inside .page-hero__inner, which is capped at 62rem
      for line length. That cap belongs to the prose, not to a four column data
      strip: it left the strip 248px short of the photograph directly beneath
      it at 1440px, which reads as a misalignment rather than as a measure.

   c. Four facts in a grid of auto-fit 160px tracks becomes three columns
      between about 600px and 760px, so "Completed" dropped onto a row of its
      own with two thirds of the strip empty beside it.

   d. Three gallery photographs in auto-fit 220px tracks become two columns
      between about 410px and 620px — two photographs and an orphan.

   e. Related case studies is a .grid--3 holding exactly three cards, which
      only reaches three columns at 1280px because the gaps tip auto-fill over
      even where three tracks would have fitted. From 1000 to 1279 it ran 2+1
      with a third of the row empty.

   The two counted rules use :has() so they apply to a grid holding exactly
   three items and leave every other count on auto-fit, where the general rule
   is still the right one.
   --------------------------------------------------------------------------- */
.cs-lead { margin-bottom: clamp(1.75rem, 1.1rem + 2vw, 3rem); }

.page-hero--case .cs-head { max-width: none; }
.page-hero--case .cs-head > .eyebrow,
.page-hero--case .cs-head > h1,
.page-hero--case .cs-head > .lede { max-width: 62rem; }

.cs-meta { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 760px) {
  .cs-meta { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (min-width: 620px) {
  .gallery:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* 1000px, not lower. These cards are built around a 300px minimum, and the
   gaps push auto-fill to two columns while three would still have fitted:
   at 1024px three columns come to 294px each. Forcing three any earlier
   makes them worse than the orphan does — at 620px they measured 179px
   wide by 681px tall, which is a sliver rather than a card. */
@media (min-width: 1000px) {
  .grid--3:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---------------------------------------------------------------------------
   46  THE CUSTOMER'S NAME IS NOT PART OF WHAT THEY SAID
   .pullquote styles the figure, and everything inside it inherits: the
   attribution rendered at 28px Sora 600, the same type as the quote itself,
   with 0px between the two. On five of the six case studies that made
   "Verified Checkatrade customer, Sutton SM5, 10/10" read as the closing
   sentence of the review rather than as the signature on it.

   Set in the same language the testimonial cards already use for the same
   job: the name in display type at reading size, the detail beneath it small
   and muted, and air between the words and who said them.
   --------------------------------------------------------------------------- */
.pullquote figcaption {
  margin-top: clamp(1rem, .7rem + .8vw, 1.5rem);
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--text-mute);
}
.pullquote figcaption strong {
  display: block;
  font-family: var(--ff-display);
  font-size: .98rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--text);
}
.section--deep .pullquote figcaption { color: var(--on-dark-mute); }
.section--deep .pullquote figcaption strong { color: #fff; }

/* ---------------------------------------------------------------------------
   47  THE CASE STUDY BODY, REBUILT
   The article used to sit in a two column grid beside a sticky sidebar. The
   article on these pages is three to five bullet points and a review; the
   sidebar is two panels. The sidebar won every time — by 14px on the fullest
   page and by 240px on the thinnest — and the difference read as a hole in
   the page beside a dark panel.

   So the columns now hold two pieces of content of comparable weight, the
   work and what the customer said about it, and what used to be the sidebar
   runs across the page underneath where it cannot be taller than anything.
   The review becomes a card: a bare rule could not hold a column of its own.
   --------------------------------------------------------------------------- */
.cs-grid {
  display: grid;
  gap: clamp(1.75rem, 1.1rem + 2.6vw, 3.25rem);
  align-items: start;
}
.cs-grid > * { min-width: 0; }
/* 1000px, not 900. At 900 the work column comes to 413px and the bullets
   start wrapping, which is the same cost as narrowing the column by hand. */
@media (min-width: 1000px) {
  /* Two columns only when there is a review to put in the second one.
     The work column stays the wider of the two. Giving the review more
     width does close the remaining height difference — from 170px to 85px
     at the extreme — but only by narrowing the work column until the
     bullets wrap: three of them became five lines at .92fr and six at
     .78fr. Whitespace beside a list costs less than a list that no longer
     reads a line at a time. */
  .cs-grid:has(> .pullquote) { grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); }
}
.cs-main { max-width: 68ch; }

.pullquote--card {
  margin: 0;
  padding: clamp(1.4rem, 1rem + 1.2vw, 2.1rem);
  background: var(--paper);
  border: 1px solid var(--line);
  border-left: 3px solid var(--blue);
  border-radius: var(--r-md);
  font-size: clamp(1.05rem, .92rem + .6vw, 1.35rem);
}

.cs-next {
  display: grid;
  gap: clamp(1rem, .7rem + 1vw, 1.6rem);
  margin-top: clamp(2.5rem, 1.6rem + 3vw, 4.5rem);
}
@media (min-width: 860px) {
  .cs-next { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.cs-next > * { min-width: 0; }

/* Across the page there is room for the number to sit beside the button
   rather than under it. */
.cs-panel__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .9rem 1.5rem;
  margin-top: 1.4rem;
}
.cs-panel__actions .cs-panel__phone { display: inline-flex; align-items: center; gap: .5rem; margin: 0; }

/* The label belongs beside its icon, not floating between the icon and the
   arrow. space-between was tuned for a narrow sidebar; across the wider panel
   it strands the text mid-row. Pushing only the arrow right reads correctly
   whether or not a given link has an icon — 404 and thank-you have none. */
.sibling-link { justify-content: flex-start; gap: .85rem; }
.sibling-link::after { margin-left: auto; }

/* ---------------------------------------------------------------------------
   48  THE BASE OF THE CASE STUDY HERO
   The facts strip is the last thing in the hero and three separate bottom
   spacings stacked underneath it: the strip's own 32px margin, .cs-head's
   32px margin, and the hero inner's 88px padding. That is 152px of empty
   dark band at 1280px, and the white section below then opened with another
   112px of its own before the photograph — 264px of nothing between the
   facts and the evidence.

   One spacing below the strip, and the section that follows opens with a
   matching one rather than a full section's worth, because the dark band has
   already done half the separating.
   --------------------------------------------------------------------------- */
.page-hero--case .cs-head { margin-bottom: 0; }
.page-hero--case .cs-meta { margin-bottom: 0; }
.page-hero--case .page-hero__inner { padding-bottom: clamp(2.25rem, 1.5rem + 2.4vw, 4rem); }
.cs-work { padding-top: clamp(2.25rem, 1.5rem + 2.4vw, 4rem); }

/* ---------------------------------------------------------------------------
   49  THE EMERGENCY HERO IS A SPLIT, NOT A COLUMN OF PROSE
   .page-hero__inner is capped at 56rem so a paragraph keeps a readable line
   length. This hero puts a two column split inside that cap, so the cap was
   being applied to the layout rather than to the prose: at 1280px the split
   ran 896px of a 1240px container and gave each column about 415px.

   Everything followed from that. The three reassurance chips measure 710px
   together, so in a 415px column they could only stack one per line and read
   as a column of buttons rather than a row of facts. The call card was handed
   the same 415px it did not need, and the two columns finished 211px apart.

   The split now takes the container, and the card takes the width a phone
   number actually needs rather than half the band. The lede keeps its own
   58ch measure, which is where the readable line length belonged all along.
   --------------------------------------------------------------------------- */
/* 900px, matching where .split itself becomes two columns. Starting later
   left a band from 900 to 999 with two columns still inside the 896px cap,
   which is 390px each — worse than either state on its own. */
@media (min-width: 900px) {
  .page-hero__inner:has(> .split) { max-width: none; }
    /* 20rem, not 22. The number sets at about 200px plus padding, so the card
     is comfortable at 320px, and the 32px that gives back to the copy is
     what carries two chips onto one line at 900px instead of none. */
  .page-hero__inner > .split { grid-template-columns: minmax(0, 1fr) minmax(0, 20rem); }
}

/* ---------------------------------------------------------------------------
   50  THE TEAM ON THE ABOUT PAGE
   Two portrait cards under "Who you are dealing with". Side by side and
   capped, because two 4:5 portraits stretched across the full container are
   each taller than a laptop screen. On phones each card turns sideways,
   photograph left and words right, so the pair costs one screen of scrolling
   rather than two.
   --------------------------------------------------------------------------- */
.team { margin-top: clamp(3rem, 2rem + 3vw, 4.5rem); }
/* .eyebrow is inline-flex, so it has to become a full-width flex row before
   it can centre over the cards. */
.team > .eyebrow { display: flex; justify-content: center; margin-bottom: clamp(1.1rem, .9rem + .8vw, 1.6rem); }
.team-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.1rem, .6rem + 1.6vw, 1.9rem);
  max-width: 52rem;
  margin-inline: auto;
}
.team-card {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.team-card__media picture { display: block; height: 100%; }
.team-card__media img { width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
.team-card__body {
  display: flex;
  flex-direction: column;
  gap: .45rem;
  padding: clamp(1.1rem, .9rem + .8vw, 1.6rem);
}
.team-card__body h3 { font-size: 1.25rem; }
.team-card__role {
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--blue-ink);
}
.team-card__body p:not(.team-card__role) { font-size: var(--fs-sm); color: var(--text-soft); }

@media (max-width: 560px) {
  .team-grid { grid-template-columns: 1fr; }
  .team-card { flex-direction: row; }
  .team-card__media { flex: 0 0 38%; }
  .team-card__media img { height: 100%; }
  .team-card__body { padding: 1rem; }
  .team-card__body h3 { font-size: 1.1rem; }
}

/* -----------------------------------------------------------------------------
   24  UTILITIES
   -------------------------------------------------------------------------- */

.mt-0 { margin-top: 0; }
.mt-3 { margin-top: var(--s-3); }
.mt-4 { margin-top: var(--s-4); }
.mt-5 { margin-top: var(--s-5); }
.mt-6 { margin-top: var(--s-6); }
.mt-7 { margin-top: var(--s-7); }
.mt-8 { margin-top: var(--s-8); }
.mb-0 { margin-bottom: 0; }
.mb-4 { margin-bottom: var(--s-4); }
.mb-5 { margin-bottom: var(--s-5); }
.mb-6 { margin-bottom: var(--s-6); }
.mb-7 { margin-bottom: var(--s-7); }

.text-center { text-align: center; }
.center-block { margin-inline: auto; }
.u-muted { color: var(--text-mute); }
.section--deep .u-muted, .on-dark .u-muted { color: var(--on-dark-mute); }
.u-h3 { font-family: var(--ff-display); font-size: var(--fs-h3); font-weight: 700; letter-spacing: -.02em; line-height: 1.24; }

.on-dark { color: #fff; }
.on-dark h1, .on-dark h2, .on-dark h3, .on-dark h4 { color: #fff; }
.on-dark p, .on-dark li { color: var(--on-dark-soft); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* -----------------------------------------------------------------------------
   25  MOTION
   Elements marked data-reveal start slightly low and faded; main.js adds
   .is-in when they cross into view. Without JavaScript nothing is hidden,
   because the rule only applies once the html element is marked js-ready.
   -------------------------------------------------------------------------- */

.js-ready [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .7s var(--ease), transform .8s var(--ease-out);
}
.js-ready [data-reveal].is-in { opacity: 1; transform: none; }

.js-ready [data-reveal="1"] { transition-delay: .07s; }
.js-ready [data-reveal="2"] { transition-delay: .14s; }
.js-ready [data-reveal="3"] { transition-delay: .21s; }
.js-ready [data-reveal="4"] { transition-delay: .28s; }
.js-ready [data-reveal="5"] { transition-delay: .35s; }
.js-ready [data-reveal="6"] { transition-delay: .42s; }

/* -----------------------------------------------------------------------------
   26  REDUCED MOTION AND PRINT
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .js-ready [data-reveal] { opacity: 1; transform: none; }
  .hero__bg img { animation: none; }
  .marquee__track { animation: none; }
}

@media print {
  .site-header, .mobile-nav, .bottom-bar, .cookie-banner, .lightbox,
  .marquee, .emergency-strip, .cta-band, .btn, .nav-toggle { display: none !important; }
  body { color: #000; background: #fff; font-size: 11pt; }
  .section, .section--alt, .section--deep { background: #fff !important; color: #000 !important; padding-block: 1.2rem; }
  .section--deep h1, .section--deep h2, .section--deep h3,
  .section--deep p, .section--deep li { color: #000 !important; }
  .card, .detail-card, .testimonial, .form-panel, .cs-panel {
    border: 1px solid #999 !important;
    box-shadow: none !important;
    break-inside: avoid;
  }
  a { text-decoration: underline; color: #000; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; color: #444; }
  .site-footer { background: #fff !important; color: #000 !important; }
  .site-footer * { color: #000 !important; }
}
