/* ==========================================================================
   Yorkshire Boilers & Heating Services — Global Stylesheet
   Mobile-first, navy / gold / white, conversion-focused
   ========================================================================== */

/* v2.6.18 (Stage 3 C1 font stability) — 'Inter Fallback': Arial (or the metric-identical Liberation Sans / Arimo)
   scaled to Inter's measured text widths, one face per weight group, so text wraps on the same lines before and
   after the Inter web font loads (the font swap was the remaining 0.095 mobile CLS on /boiler-quote/). Ratios were
   measured on the live site's own text: regular 107%, 600 102.5%, 700 100%, 800 101% (bold weights use real
   Arial Bold, never synthesised bold). Inter is still the first choice; once it loads nothing looks different. */
@font-face{font-family:'Inter Fallback';font-style:normal;font-weight:100 500;src:local('Arial'),local('ArialMT'),local('Liberation Sans'),local('Arimo');size-adjust:107%;ascent-override:90.54%;descent-override:22.57%;line-gap-override:0%}
@font-face{font-family:'Inter Fallback';font-style:normal;font-weight:600;src:local('Arial Bold'),local('Arial-BoldMT'),local('Liberation Sans Bold'),local('Arimo Bold');size-adjust:102.5%;ascent-override:94.51%;descent-override:23.57%;line-gap-override:0%}
@font-face{font-family:'Inter Fallback';font-style:normal;font-weight:700;src:local('Arial Bold'),local('Arial-BoldMT'),local('Liberation Sans Bold'),local('Arimo Bold');size-adjust:100%;ascent-override:96.88%;descent-override:24.16%;line-gap-override:0%}
@font-face{font-family:'Inter Fallback';font-style:normal;font-weight:800 900;src:local('Arial Bold'),local('Arial-BoldMT'),local('Liberation Sans Bold'),local('Arimo Bold');size-adjust:101%;ascent-override:95.92%;descent-override:23.92%;line-gap-override:0%}

/* v2.6.19 (Stage 3 C2) — Inter is now served from the theme (assets/fonts/, SIL Open Font License, see
   INTER-OFL-LICENSE.txt). These are byte-identical copies of the two files Google Fonts served for
   family=Inter:wght@400;600;700;800 (same SHA-256), so the text looks exactly as before; the page simply no
   longer waits for a separate stylesheet from fonts.googleapis.com plus a connection to fonts.gstatic.com.
   The latin file is also preloaded in <head> (functions.php, yb_inter_preload). */
@font-face{font-family:'Inter';font-style:normal;font-weight:100 900;font-display:swap;src:url(../fonts/inter-latin-ext-wght-normal.woff2) format('woff2');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:'Inter';font-style:normal;font-weight:100 900;font-display:swap;src:url(../fonts/inter-latin-wght-normal.woff2) format('woff2');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}
/* v2.6.19 — 'Inter Fallback Android': Android has no Arial, so the 'Inter Fallback' faces above fail there and
   text used to fall back to plain Roboto, which is narrower than Inter and wrapped differently until Inter
   arrived (up to ~0.18 simulated CLS at 375-412px). These faces scale Android's own Roboto to Inter's widths,
   measured on the site's own text: regular 107.3%, 600 107.2%, 700 108.3%, 800 109.9%. Devices that have Arial
   (Windows, macOS, iOS, Lighthouse) still use 'Inter Fallback' first, so v2.6.18 behaviour is unchanged there. */
@font-face{font-family:'Inter Fallback Android';font-style:normal;font-weight:100 500;src:local('Roboto'),local('Roboto-Regular'),local('Roboto Regular');size-adjust:107.3%;ascent-override:90.28%;descent-override:22.51%;line-gap-override:0%}
@font-face{font-family:'Inter Fallback Android';font-style:normal;font-weight:600;src:local('Roboto Bold'),local('Roboto-Bold'),local('Roboto');size-adjust:107.2%;ascent-override:90.37%;descent-override:22.53%;line-gap-override:0%}
@font-face{font-family:'Inter Fallback Android';font-style:normal;font-weight:700;src:local('Roboto Bold'),local('Roboto-Bold'),local('Roboto');size-adjust:108.3%;ascent-override:89.45%;descent-override:22.30%;line-gap-override:0%}
@font-face{font-family:'Inter Fallback Android';font-style:normal;font-weight:800 900;src:local('Roboto Bold'),local('Roboto-Bold'),local('Roboto');size-adjust:109.9%;ascent-override:88.15%;descent-override:21.98%;line-gap-override:0%}

:root{
  --navy:#061A33;
  --navy-dark:#031120;
  --gold:#D7A53A;
  --gold-light:#F3D27A;
  --white:#FFFFFF;
  --off-white:#F7F8FA;
  --grey-light:#E8ECF1;
  --text-grey:#3B4652;
  --green:#0E8F4F;
  --red:#B3261E;

  --font:'Inter','Inter Fallback','Inter Fallback Android',Arial,Helvetica,sans-serif;
  --maxw:1180px;
  --radius:10px;
  --shadow:0 6px 24px rgba(6,26,51,.10);
  --shadow-sm:0 2px 8px rgba(6,26,51,.08);
}

/* ---------- Reset ---------- */
/*
 * v1.8.5 — defensive global default for yb_icon() SVGs (functions.php).
 * Those SVGs have no width/height attribute by design (so they can be
 * sized per context via CSS) — but that means any FUTURE usage that
 * forgets to add its own explicit size falls back to the browser's raw
 * SVG default (300×150px in most browsers), exactly the oversized-phone-
 * icon bug fixed this version. This is a safety net only: it makes an
 * unconstrained icon scale sensibly with its surrounding text (1em) rather
 * than balloon to 300px — every CURRENT usage still has, and should keep,
 * its own explicit pixel size (see .header-phone svg, .icon-btn svg,
 * .sticky-cta svg) for precise control; this rule only catches the next
 * one someone forgets.
 */
svg[viewBox="0 0 24 24"]:not([width]){width:1em;height:1em}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  font-family:var(--font);
  color:var(--text-grey);
  background:var(--white);
  line-height:1.6;
  font-size:17px;
  overflow-x:hidden;
}
img{max-width:100%;height:auto;display:block}
a{color:var(--navy);text-decoration:none}
a:hover{text-decoration:underline}
ul{list-style:none}

h1,h2,h3,h4{color:var(--navy);line-height:1.2;font-weight:800;letter-spacing:-.01em}
h1{font-size:1.9rem;margin-bottom:.6rem}
h2{font-size:1.5rem;margin-bottom:.8rem}
h3{font-size:1.2rem;margin-bottom:.5rem}
p{margin-bottom:1rem}
p:last-child{margin-bottom:0}

.wrap{max-width:var(--maxw);margin:0 auto;padding:0 18px}
/* PROMPT 24 §10 — class="container" is used by _page-content-import/
   boiler-quote.html (hero H1, the builder wrap, the closing call-us
   paragraph) but no .container rule existed anywhere in this theme, so
   those blocks had no side padding and no centring max-width at all —
   at laptop/desktop widths this reads as the heading and the quote
   builder being pushed hard against the left edge of the page rather
   than sitting in the page's normal centred reading column. This
   mirrors the site's own existing .wrap convention (max-width:var(--maxw);
   centred; 18px side padding) so .container behaves exactly like every
   other page's centred content width — including a block that also
   carries its own narrower inline max-width (e.g. style="max-width:640px"):
   that inline max-width still wins, this rule's auto margins still centre
   it either way. */
.container{max-width:var(--maxw);margin:0 auto;padding:0 18px}
.section{padding:46px 0}
.section--tight{padding:30px 0}
.section--alt{background:var(--off-white)}
.section--navy{background:var(--navy);color:#dbe4ef}
.section--navy h1,.section--navy h2,.section--navy h3{color:#fff}
.eyebrow{display:inline-block;font-size:.78rem;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--gold);margin-bottom:.6rem}
.lead{font-size:1.08rem}
.center{text-align:center}

/* ---------- Skip link ---------- */
.skip{position:absolute;left:-999px;top:0;background:var(--gold);color:var(--navy);
  padding:10px 16px;z-index:2000;font-weight:700;border-radius:0 0 8px 0}
.skip:focus{left:0}

/* ---------- Buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  font-weight:700;font-size:1rem;line-height:1;text-align:center;
  padding:15px 22px;border-radius:var(--radius);border:2px solid transparent;
  cursor:pointer;transition:transform .12s ease,box-shadow .12s ease,background .12s ease;
  text-decoration:none;
}
.btn:hover{text-decoration:none;transform:translateY(-1px)}
.btn:focus-visible{outline:3px solid var(--gold-light);outline-offset:2px}
.btn--primary{background:var(--gold);color:var(--navy);box-shadow:var(--shadow-sm)}
.btn--primary:hover{background:var(--gold-light)}
.btn--secondary{background:var(--navy);color:#fff;border-color:var(--gold)}
.btn--secondary:hover{background:var(--navy-dark)}
.btn--ghost{background:transparent;color:var(--navy);border-color:var(--navy)}
.btn--ghost:hover{background:var(--navy);color:#fff}
.btn--lg{padding:17px 28px;font-size:1.06rem}
.btn--block{width:100%}
.btn-row{display:flex;flex-wrap:wrap;gap:12px}
.btn-row--center{justify-content:center}

/* ---------- Header ---------- */
.site-header{position:sticky;top:0;z-index:900;background:#fff;border-bottom:1px solid var(--grey-light);
  box-shadow:0 1px 0 rgba(6,26,51,.04)}

/*
 * v1.8.4 — CRITICAL FIX: desktop header/nav overlap.
 *
 * The v1.8.3 fix (flex + clamp() + flex-shrink) reduced the overflow but
 * real rendered screenshots showed menu items, the phone number and the
 * "Book / Get Help" button still visually overlapping at common desktop
 * widths. Root cause: flexbox has no hard containment between siblings —
 * a shrink-resistant child (long nav text, or the extra "Book / Get Help"
 * button competing for the same row) can still visually spill into a
 * neighbour's space under the wrong content-length combination, however
 * much clamp()/flex-shrink is applied.
 *
 * Fix: .header-bar is now a 3-column CSS GRID — LOGO | NAVIGATION | ACTIONS
 * — each with its OWN grid cell. Grid columns are hard containers: content
 * in one column cannot visually render inside another column's space,
 * regardless of content length. This makes overlap structurally
 * impossible, not just statistically unlikely.
 *
 * The desktop "Book / Get Help" button has also been REMOVED from the
 * header per the brief ("if it causes crowding, remove it — service pages
 * now have their own service-specific CTAs, so the generic button is not
 * essential"). Only the phone number remains in header-actions, in its
 * own dedicated, protected space.
 */
.header-bar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;
  column-gap:16px;padding:10px 18px;max-width:var(--maxw);margin:0 auto}
.header-logo{grid-column:1;min-width:0}
.header-logo .brand{display:block}
/* v1.9.1 FINDING: this rule's specificity (0,2,1 — two classes + the bare
   "img" type selector) is HIGHER than the v1.9.0 logo-sizing rule further
   down this file (`.site-header .brand__img`, 0,2,0), so it was silently
   winning the cascade regardless of source order — the desktop/mobile
   header logo has actually been rendering at this fixed 42px height all
   along, not the 47px/58px the v1.9.0 report described (those values were
   never verified against the browser's actual computed style). Left in
   place, documented, rather than deleted; superseded by the higher-
   specificity `.site-header .header-logo .brand__img` rule added in the
   v1.9.1 section below, which now reliably wins. */
.header-logo .brand img{height:42px;width:auto;display:block}

.header-navigation{grid-column:2;display:none;min-width:0;overflow:hidden}
/*
 * v1.8.6 — CRITICAL FIX: removed overflow-x:auto (an invisible horizontally
 * scrolling nav — several items were reachable only by scrolling
 * sideways, with no visible scrollbar to hint this was even possible).
 * The real fix is a wider display breakpoint (see the separate nav-only
 * media query below, now 1280px instead of 1040px) so the full grouped
 * nav only ever appears once there's genuinely enough room for it. If a
 * future menu edit still doesn't fit even at 1280px, this now wraps onto
 * a second visible line rather than hiding items behind invisible scroll.
 */
.header-navigation ul{display:flex;align-items:center;gap:clamp(10px,1vw,20px);flex-wrap:wrap;row-gap:4px}
.header-navigation a{font-weight:600;font-size:.95rem;color:var(--navy);white-space:nowrap;display:inline-block;padding:6px 0}
.header-navigation a:hover{color:var(--gold);text-decoration:none}
/*
 * Belt-and-braces: even though grid columns cannot overlap a NEIGHBOUR
 * column, an individual column's own content could in theory still be
 * wider than its column and force the grid track wider than intended. The
 * nav column scrolls horizontally (scrollbar hidden, but wheel/trackpad/
 * touch scroll still works) rather than ever being allowed to grow the
 * column — so LOGO and ACTIONS keep their reserved space unconditionally.
 */

.header-actions{grid-column:3;display:none;align-items:center;justify-self:end;min-width:0}
.header-phone{display:inline-flex;align-items:center;gap:8px;font-weight:800;color:var(--navy);
  white-space:nowrap;padding:8px 4px}
.header-phone svg,.header-phone .icon{flex-shrink:0;width:16px;height:16px}
.header-phone:hover{color:var(--gold);text-decoration:none}

.header-mobile-actions{display:flex;align-items:center;gap:8px;grid-column:2 / span 2;justify-self:end}
.icon-btn{display:inline-flex;align-items:center;gap:6px;font-weight:700;font-size:.9rem;
  padding:9px 12px;border-radius:8px}
.icon-btn--call{background:var(--gold);color:var(--navy)}
.icon-btn--call:hover{text-decoration:none}
/*
 * v1.8.5 — CRITICAL FIX: oversized phone icon in the header.
 *
 * yb_icon('phone')/yb_icon('wa')/yb_icon('survey') in functions.php emit
 * raw <svg viewBox="0 0 24 24"> markup with NO width/height attribute —
 * per the SVG spec, a browser renders an unsized inline SVG at its
 * default intrinsic size (300×150px in most browsers) unless CSS
 * constrains it. .header-phone svg was given that constraint in v1.8.4;
 * .icon-btn svg (the mobile header's Call button) was missed — this is
 * the oversized-handset bug. Every yb_icon() usage now has an explicit
 * CSS size wherever it appears, so none can ever fall back to the SVG
 * default again.
 */
.icon-btn svg{width:16px;height:16px;flex-shrink:0}
.menu-toggle{background:var(--navy);color:#fff;border:0;border-radius:8px;padding:9px 12px;
  font-weight:700;cursor:pointer;display:inline-flex;align-items:center;gap:6px;font-size:.9rem}

/* Mobile drawer */
.nav-mobile{position:fixed;inset:0 0 0 auto;width:min(86%,340px);background:var(--navy);
  color:#fff;transform:translateX(100%);transition:transform .25s ease;z-index:1100;
  padding:18px;overflow-y:auto;box-shadow:-8px 0 40px rgba(0,0,0,.3)}
.nav-mobile.open{transform:translateX(0)}
.nav-mobile .close{background:none;border:0;color:#fff;font-size:1.6rem;cursor:pointer;
  position:absolute;top:12px;right:16px;line-height:1}
.nav-mobile h2{color:var(--gold);font-size:.8rem;letter-spacing:.1em;text-transform:uppercase;
  margin:18px 0 8px}
.nav-mobile ul{display:flex;flex-direction:column;gap:2px}
.nav-mobile a{color:#fff;font-weight:600;padding:11px 8px;border-radius:8px;display:block}
.nav-mobile a:hover{background:rgba(255,255,255,.08);text-decoration:none}
.nav-overlay{position:fixed;inset:0;background:rgba(3,17,32,.55);opacity:0;visibility:hidden;
  transition:.25s;z-index:1050}
.nav-overlay.open{opacity:1;visibility:visible}
.nav-mobile .drawer-cta{margin-top:18px;display:flex;flex-direction:column;gap:10px}

/* ---------- Hero ---------- */
.hero{position:relative;background:var(--navy);color:#e7eefa;overflow:hidden}
.hero__inner{display:grid;gap:24px;padding:34px 18px 38px;max-width:var(--maxw);margin:0 auto}
.hero h1{color:#fff;font-size:2rem}
.hero p{color:#cdd9ea}
.hero .lead{font-size:1.1rem}
.hero__media{border-radius:14px;overflow:hidden;box-shadow:var(--shadow);position:relative}
.hero__media img{width:100%;height:100%;object-fit:cover;aspect-ratio:3/2}
.hero__price{display:inline-block;background:var(--gold);color:var(--navy);font-weight:800;
  padding:8px 14px;border-radius:8px;margin-bottom:14px;font-size:1rem}
.hero__cta{margin-top:18px}

/* ---------- Trust strip ---------- */
.trust-strip{background:var(--navy-dark);color:#cdd9ea;border-top:3px solid var(--gold)}
.trust-strip ul{display:grid;grid-template-columns:1fr;gap:8px;padding:16px 18px;
  max-width:var(--maxw);margin:0 auto}
.trust-strip li{display:flex;align-items:center;gap:10px;font-weight:600;font-size:.95rem}
.trust-strip li::before{content:"";flex:0 0 auto;width:18px;height:18px;border-radius:50%;
  background:var(--gold);
  -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/12px no-repeat;
  mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/12px no-repeat}

/* ---------- Cards ---------- */
.card-grid{display:grid;grid-template-columns:1fr;gap:18px}
.card{background:#fff;border:1px solid var(--grey-light);border-radius:var(--radius);
  overflow:hidden;box-shadow:var(--shadow-sm);display:flex;flex-direction:column;
  transition:transform .14s ease,box-shadow .14s ease}
.card:hover{transform:translateY(-3px);box-shadow:var(--shadow)}
.card__img{aspect-ratio:16/10;overflow:hidden;background:var(--grey-light)}
.card__img img{width:100%;height:100%;object-fit:cover}
.card__body{padding:18px 18px 20px;display:flex;flex-direction:column;flex:1}
.card__body h3{margin-bottom:.4rem}
.card__body p{font-size:.96rem;margin-bottom:14px}
.card__link{margin-top:auto;font-weight:700;color:var(--navy);display:inline-flex;align-items:center;gap:6px}
.card__link::after{content:"→";color:var(--gold);font-weight:800}
.card__link:hover{color:var(--gold);text-decoration:none}

/* ---------- Feature / two-column ---------- */
.two-col{display:grid;grid-template-columns:1fr;gap:26px;align-items:center}
.two-col__media img{border-radius:14px;box-shadow:var(--shadow);width:100%;object-fit:cover}
.ticks li{position:relative;padding-left:30px;margin-bottom:10px;font-weight:600;color:var(--navy)}
.ticks li::before{content:"";position:absolute;left:0;top:3px;width:20px;height:20px;border-radius:50%;
  background:var(--green);
  -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/13px no-repeat;
  mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/13px no-repeat}

/* ---------- Offer band ---------- */
.offer{background:linear-gradient(135deg,var(--navy),var(--navy-dark));color:#e7eefa;
  border-radius:16px;padding:28px 22px;border:1px solid rgba(215,165,58,.35)}
.offer .price{font-size:2.1rem;font-weight:800;color:var(--gold);display:block;margin:4px 0 10px}
.offer h2{color:#fff}

/* ---------- Areas ---------- */
.area-chips{display:flex;flex-wrap:wrap;gap:10px}
.area-chips a{background:#fff;border:1px solid var(--grey-light);border-radius:30px;
  padding:9px 16px;font-weight:600;font-size:.92rem;color:var(--navy);box-shadow:var(--shadow-sm)}
.area-chips a:hover{background:var(--navy);color:#fff;text-decoration:none;border-color:var(--navy)}

/* ---------- Steps ---------- */
.steps{display:grid;grid-template-columns:1fr;gap:16px;counter-reset:step}
.step{background:#fff;border:1px solid var(--grey-light);border-radius:var(--radius);
  padding:20px 18px 18px;position:relative;box-shadow:var(--shadow-sm)}
.step::before{counter-increment:step;content:counter(step);position:absolute;top:-14px;left:18px;
  width:34px;height:34px;border-radius:50%;background:var(--gold);color:var(--navy);
  font-weight:800;display:grid;place-items:center;box-shadow:var(--shadow-sm)}
.step h3{margin-top:8px}

/* ---------- FAQ accordion ---------- */
.faq{max-width:820px;margin:0 auto}
.faq details{background:#fff;border:1px solid var(--grey-light);border-radius:var(--radius);
  margin-bottom:12px;overflow:hidden;box-shadow:var(--shadow-sm)}
.faq summary{cursor:pointer;list-style:none;padding:16px 48px 16px 18px;font-weight:700;
  color:var(--navy);position:relative;font-size:1.02rem}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";position:absolute;right:18px;top:50%;transform:translateY(-50%);
  font-size:1.5rem;color:var(--gold);font-weight:800;line-height:1}
.faq details[open] summary::after{content:"–"}
.faq summary:focus-visible{outline:3px solid var(--gold-light);outline-offset:-3px}
.faq .faq__a{padding:0 18px 18px;color:var(--text-grey)}

/* ---------- Final CTA ---------- */
.cta-band{background:linear-gradient(135deg,var(--navy),var(--navy-dark));color:#e7eefa;text-align:center}
.cta-band h2{color:#fff}
.cta-band p{color:#cdd9ea;max-width:640px;margin:0 auto 18px}

/* ---------- Forms ---------- */
.form-card{background:#fff;border:1px solid var(--grey-light);border-radius:14px;
  padding:22px 20px;box-shadow:var(--shadow)}
.form-card h2,.form-card h3{color:var(--navy)}
.wpf{display:grid;gap:14px;margin-top:6px}
.wpf .field{display:flex;flex-direction:column;gap:6px}
.wpf .field--row{display:grid;grid-template-columns:1fr;gap:14px}
.wpf label{font-weight:700;color:var(--navy);font-size:.92rem}
.wpf .req{color:var(--red)}
.wpf input,.wpf select,.wpf textarea{
  font-family:inherit;font-size:1rem;padding:13px 14px;border:1.5px solid var(--grey-light);
  border-radius:9px;background:var(--off-white);color:var(--text-grey);width:100%}
.wpf input:focus,.wpf select:focus,.wpf textarea:focus{outline:none;border-color:var(--gold);
  background:#fff;box-shadow:0 0 0 3px rgba(215,165,58,.18)}
.wpf textarea{min-height:96px;resize:vertical}
.wpf fieldset{border:0}
.wpf .radio-row{display:flex;gap:18px;flex-wrap:wrap}
.wpf .radio-row label{font-weight:600;display:flex;align-items:center;gap:7px;cursor:pointer}
.wpf .radio-row input{width:auto}
.form-note{font-size:.82rem;color:var(--text-grey);margin-top:4px}
.form-success{display:none;background:#eaf7f0;border:1.5px solid var(--green);color:#0a5a33;
  padding:16px;border-radius:10px;font-weight:600;margin-top:14px}
.form-success.show{display:block}

/* ---------- Contact details block ---------- */
.contact-grid{display:grid;grid-template-columns:1fr;gap:24px}
.detail-list li{display:flex;gap:12px;padding:12px 0;border-bottom:1px solid var(--grey-light);align-items:flex-start}
.detail-list li:last-child{border-bottom:0}
.detail-list .k{font-weight:800;color:var(--navy);min-width:96px}
.detail-list a{font-weight:600}

/* ---------- Breadcrumbs ---------- */
.crumbs{background:var(--off-white);border-bottom:1px solid var(--grey-light);font-size:.86rem}
.crumbs ol{display:flex;flex-wrap:wrap;gap:6px;padding:11px 18px;max-width:var(--maxw);margin:0 auto;color:var(--text-grey)}
.crumbs li{display:flex;gap:6px;align-items:center}
.crumbs li+li::before{content:"/";color:#9aa6b3}
.crumbs a{color:var(--navy);font-weight:600}
.crumbs [aria-current]{color:var(--text-grey)}

/* ---------- Footer ---------- */
.site-footer{background:var(--navy-dark);color:#aebccd;padding:34px 0 0;font-size:.93rem} /* v1.9.1: 42px -> 34px, modest top-padding tightening (Correction 8) */
.footer-top{display:grid;grid-template-columns:1fr;gap:28px;max-width:var(--maxw);margin:0 auto;padding:0 18px}
.footer-brand img{height:54px;margin-bottom:14px}
.footer-brand p{color:#aebccd;max-width:340px}
.footer-col h3{color:#fff;font-size:.95rem;letter-spacing:.04em;margin-bottom:12px}
.footer-col ul{display:flex;flex-direction:column;gap:8px}
.footer-col a{color:#aebccd}
.footer-col a:hover{color:var(--gold);text-decoration:none}
.footer-contact li{margin-bottom:6px} /* v1.9.1: 8px -> 6px, Correction 8 */
.footer-contact a{color:#fff;font-weight:600}
.gas-badge{display:inline-flex;align-items:center;gap:8px;background:rgba(215,165,58,.14);
  border:1px solid rgba(215,165,58,.4);color:var(--gold-light);font-weight:700;
  padding:8px 12px;border-radius:8px;margin-top:14px;font-size:.85rem}
.footer-bottom{border-top:1px solid rgba(255,255,255,.08);margin-top:26px;padding:14px 18px;
  text-align:center;font-size:.82rem;color:#8595a6} /* v1.9.1: margin-top 34->26px, padding 18px->14px 18px, Correction 8 */
.footer-bottom a{color:#aebccd}

/* ---------- Mobile sticky CTA ---------- */
.sticky-cta{position:fixed;left:0;right:0;bottom:0;z-index:950;display:grid;
  grid-template-columns:1fr 1fr 1fr;background:var(--navy);border-top:2px solid var(--gold);
  box-shadow:0 -4px 18px rgba(0,0,0,.25)}
.sticky-cta a{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  padding:7px 4px;color:#fff;font-weight:700;font-size:.76rem;text-align:center;border-right:1px solid rgba(255,255,255,.1);
  min-height:48px}
.sticky-cta a:last-child{border-right:0}
.sticky-cta a:hover{text-decoration:none;background:var(--navy-dark)}
.sticky-cta a.is-primary{background:var(--gold);color:var(--navy)}
.sticky-cta a.is-primary:hover{background:var(--gold-light)}
.sticky-cta svg{width:18px;height:18px}
body{padding-bottom:62px}

/* ---------- Prose (legal pages) ---------- */
.prose{max-width:780px;margin:0 auto}
.prose h2{margin-top:1.6rem}
.prose h3{margin-top:1.2rem}
.prose ul{list-style:disc;padding-left:22px;margin-bottom:1rem}
.prose ul li{margin-bottom:6px}
.prose a{font-weight:600;text-decoration:underline}

/* ---------- Utility ---------- */
.mt0{margin-top:0}.mb0{margin-bottom:0}
.related-links{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px}
.related-links a{font-weight:600;color:var(--navy);background:var(--off-white);
  border:1px solid var(--grey-light);padding:8px 14px;border-radius:8px}
.related-links a:hover{background:var(--navy);color:#fff;text-decoration:none;border-color:var(--navy)}

/* ==========================================================================
   Tablet / Desktop
   ========================================================================== */
@media(min-width:680px){
  h1{font-size:2.3rem}
  h2{font-size:1.8rem}
  .hero h1{font-size:2.5rem}
  .card-grid{grid-template-columns:repeat(2,1fr)}
  .steps{grid-template-columns:repeat(2,1fr)}
  .trust-strip ul{grid-template-columns:repeat(2,1fr);gap:10px 26px}
  .wpf .field--row{grid-template-columns:1fr 1fr}
  .footer-top{grid-template-columns:1.4fr 1fr 1fr;gap:30px}
  .contact-grid{grid-template-columns:1.1fr .9fr}
}

/*
 * v1.8.4 — desktop nav breakpoint (raised again in v1.8.6, see below).
 * Below this width the header falls back to the compact Logo | Call | Menu
 * mobile-style layout (.header-mobile-actions) rather than attempting to
 * squeeze the full grouped nav into insufficient width.
 */
@media(min-width:1040px){
  .section{padding:48px 0}
  .hero__inner{grid-template-columns:1.05fr .95fr;align-items:center;padding:52px 18px 56px}
  .hero h1{font-size:2.9rem}
  .card-grid{grid-template-columns:repeat(3,1fr)}
  .card-grid--2{grid-template-columns:repeat(2,1fr)}
  .two-col{grid-template-columns:1fr 1fr;gap:42px}
  .two-col--reverse .two-col__media{order:2}
  .steps{grid-template-columns:repeat(4,1fr)}
  .trust-strip ul{grid-template-columns:repeat(5,1fr)}
  .footer-top{grid-template-columns:1.5fr 1fr 1fr 1fr}
  .offer{padding:36px 34px}
}

/*
 * v1.8.6 — CRITICAL FIX: the desktop nav's own switch-over is now a
 * SEPARATE, HIGHER breakpoint (1280px, up from 1040px) from the general
 * content breakpoint above. Content layout (hero columns, card grids,
 * section padding) doesn't need extra width to work correctly, so it
 * still switches at 1040px as before — but the full grouped navigation
 * specifically needs more room than that to avoid ever wrapping or
 * crowding, so it now waits until 1280px, matching the brief's suggested
 * starting point. Between 1040–1279px the header shows the compact
 * Logo | Call | Menu layout instead of a half-fitting nav.
 *
 * v1.9.0 — this breakpoint is RAISED to 1360px (see the GLOBAL DESIGN
 * SYSTEM section at the end of this file): the approved logo's wider
 * display size plus the reintroduced "Get a Quote" header button need the
 * extra room to avoid the overlap this fix originally addressed.
 *
 * PROMPT 24 — the old @media(min-width:1280px) rule that used to sit here
 * (and the matching 1280–1450px phone-font tier right after it) were both
 * confirmed dead: every property they set is unconditionally re-asserted,
 * for the opposite effect, by the real live breakpoint further down this
 * file (now split into three tiers — see "Desktop nav + actions" below),
 * which always wins the cascade because it is later in source order at
 * equal specificity. Deleted outright rather than left as inert history,
 * per the live-site header-overlap correction task: dead CSS at the exact
 * breakpoint under correction is exactly what makes a stale production
 * deploy hard to tell apart from this file, so it is not kept "for the
 * record" here — this file's own header comment block above remains the
 * record of the 1280px -> 1360px -> 1400px history.
 */
@media(min-width:1500px){
  .header-navigation ul{gap:26px}
  .header-bar{column-gap:28px}
}

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

/* ---- Finance (Ideal4Finance) ---- */
.finance-section{background:var(--off-white)}
.finance-rep{background:#fff;border:1px solid var(--light-grey);border-radius:12px;padding:18px 20px;margin:18px 0}
.finance-rep__head{margin:0 0 12px;color:var(--text-grey)}
.finance-rep__table{width:100%;border-collapse:collapse;font-size:15px}
.finance-rep__table th,.finance-rep__table td{text-align:left;padding:8px 6px;border-bottom:1px solid var(--light-grey)}
.finance-rep__table th{font-weight:600;color:var(--navy);width:60%}
.finance-rep__table td{color:var(--text-grey)}
.finance-rep__table tr:last-child th,.finance-rep__table tr:last-child td{border-bottom:0;font-weight:700;color:var(--navy)}
.finance-legal{margin-top:16px;font-size:13px;line-height:1.5;color:var(--text-grey)}
.finance-legal__disclosure,.finance-legal__risk{margin:0 0 8px}
.finance-card{background:#fff;border:1px solid var(--light-grey);border-left:4px solid var(--gold);border-radius:10px;padding:14px 16px;font-weight:600;color:var(--navy)}
/* PROMPT 15 (§1) — the "Apply Through Ideal4Finance" application section.
   Deliberately visually distinct from .finance-rep/.finance-legal above
   (a shaded box with its own left accent border, rather than the plain
   white .finance-rep card) so this reads as a separate, later step in the
   journey, never as a 4th button in the 3-tier .btn-row above it — see
   PROMPT15-FINANCE-APPLICATION-REPORT.md. */
.finance-application{background:var(--off-white);border:1px solid var(--light-grey);border-left:4px solid var(--navy);border-radius:10px;padding:18px 20px}
.finance-application h3{margin:0 0 10px;color:var(--navy)}
.finance-application__notice{margin:0 0 14px;font-size:14px;line-height:1.55;color:var(--text-grey)}
/* CONFIRMED DEFECT FIX (found while re-running the full regression suite
   after adding the button above): "Apply Through Ideal4Finance" is longer
   than any existing .btn label on this site ("Calculate My Repayments"),
   and .btn is a flex item inside .btn-row without min-width:0 — the
   default flex min-width:auto sizes it to its unbroken max-content width,
   which overflowed the 390px viewport by 72px (run-prompt9-browser-
   tests.js caught this). Scoped to .finance-application only, so no
   existing shorter-label button anywhere else changes its (already
   correct, already-tested) sizing/wrapping behaviour. */
.finance-application .btn{min-width:0;white-space:normal;text-align:center}
.footer-finance{margin-top:18px;padding-top:16px;border-top:1px solid rgba(255,255,255,.15);font-size:12px;line-height:1.5;color:rgba(255,255,255,.6)}
.footer-finance p{margin:0 0 8px}

/* Inline text-style button for secondary link rows */
.btn--link{background:none;border:0;color:var(--navy);text-decoration:underline;padding:6px 8px;font-weight:600}
.btn--link:hover{color:var(--gold)}

/* Supporting Google Maps link (small, inline — not a CTA) */
.maps-link{font-size:14px;font-weight:600;color:var(--navy);text-decoration:underline;white-space:nowrap}
.maps-link:hover{color:var(--gold)}

/* hero-van-image-css */
/* Van hero image enhancements — added for van homepage hero */
.hero__media img{object-fit:cover;object-position:center center}
.hero__copy{background:rgba(6,26,51,.72);border-radius:12px;padding:28px 24px;backdrop-filter:blur(2px)}
.van-caption{font-size:12px;color:var(--text-grey,#6b7280);padding:6px 8px;
  background:rgba(0,0,0,.55);color:#cdd9ea;text-align:center;border-radius:0 0 14px 14px}
@media(min-width:920px){
  .hero__copy{background:rgba(6,26,51,.80);padding:36px 32px}
}


/* ==========================================================================
   Homepage survey form — dark CTA band overrides
   Scoped entirely to .home-survey-form-section so no other WPForms instance
   on the site is affected. The cta-band section is navy, so labels and text
   must be light; inputs stay white with dark text for readability.
   ========================================================================== */

/* --- Container --- */
.home-survey-form-section {
  margin-top: 36px;
  max-width: 760px;
  margin-left: auto;
  margin-right: auto;
  text-align: left;
}

/* --- WPForms container reset --- */
.home-survey-form-section .wpforms-container,
.home-survey-form-section .wpforms-form {
  margin: 0;
  padding: 0;
}

/* --- Labels: white on dark background --- */
.home-survey-form-section .wpforms-field-label,
.home-survey-form-section label,
.home-survey-form-section .wpforms-label-hide + .wpforms-field-label {
  color: #ffffff !important;
  font-weight: 700;
  font-size: .92rem;
}

/* --- Sub-labels: light grey --- */
.home-survey-form-section .wpforms-field-sublabel,
.home-survey-form-section .wpforms-field-description {
  color: #cdd9ea !important;
  font-size: .82rem;
}

/* --- Required asterisk: gold --- */
.home-survey-form-section .wpforms-required-label,
.home-survey-form-section .wpforms-field-label .wpforms-required-label {
  color: var(--gold-light) !important;
}

/* --- Input, select, textarea: white background, navy text --- */
.home-survey-form-section input[type="text"],
.home-survey-form-section input[type="email"],
.home-survey-form-section input[type="tel"],
.home-survey-form-section input[type="number"],
.home-survey-form-section input[type="url"],
.home-survey-form-section select,
.home-survey-form-section textarea {
  background: #ffffff !important;
  color: var(--navy) !important;
  border: 1.5px solid rgba(255, 255, 255, .35) !important;
  border-radius: var(--radius);
  padding: 11px 14px;
  font-size: 1rem;
  width: 100%;
}

.home-survey-form-section input:focus,
.home-survey-form-section select:focus,
.home-survey-form-section textarea:focus {
  border-color: var(--gold) !important;
  outline: none;
  box-shadow: 0 0 0 3px rgba(215, 165, 58, .25);
}

.home-survey-form-section textarea {
  min-height: 96px;
  resize: vertical;
}

/* --- Field spacing --- */
.home-survey-form-section .wpforms-field {
  margin-bottom: 18px;
}

/* --- Two-column row on wider screens --- */
@media (min-width: 600px) {
  .home-survey-form-section .wpforms-field-row,
  .home-survey-form-section .wpforms-columns-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
  }
}

/* --- Submit button: gold with navy text --- */
.home-survey-form-section .wpforms-submit,
.home-survey-form-section button[type="submit"],
.home-survey-form-section input[type="submit"] {
  background: var(--gold) !important;
  color: var(--navy) !important;
  border: none !important;
  border-radius: var(--radius);
  padding: 14px 32px;
  font-size: 1.05rem;
  font-weight: 800;
  cursor: pointer;
  width: 100%;
  margin-top: 8px;
  letter-spacing: .01em;
  transition: background .2s, transform .1s;
}

.home-survey-form-section .wpforms-submit:hover,
.home-survey-form-section button[type="submit"]:hover {
  background: var(--gold-light) !important;
  transform: translateY(-1px);
}

/* --- Error messages: stay visible on dark background --- */
.home-survey-form-section .wpforms-field-container .wpforms-error,
.home-survey-form-section label.wpforms-error {
  color: #ffb3b0 !important;
  font-size: .85rem;
  margin-top: 4px;
}

/* --- Mobile: single column, comfortable tap targets --- */
@media (max-width: 599px) {
  .home-survey-form-section input[type="text"],
  .home-survey-form-section input[type="email"],
  .home-survey-form-section input[type="tel"],
  .home-survey-form-section select,
  .home-survey-form-section textarea {
    font-size: 16px; /* prevents iOS zoom on focus */
    padding: 13px 14px;
  }
  .home-survey-form-section .wpforms-submit,
  .home-survey-form-section button[type="submit"] {
    padding: 15px 24px;
  }
}

/* ==========================================================================
   Contact Page — Conversion Redesign
   Scoped to .contact-intro / .contact-enquiry-section / .btn-row--stack-sm
   so nothing here affects any other page or any other WPForms instance.
   ========================================================================== */

/* --- Compact intro (no tall hero) --- */
.contact-intro{padding-top:22px}
.contact-intro h1{font-size:1.55rem}
.contact-trust-line{display:inline-block;background:var(--navy);color:#fff;
  font-size:.85rem;font-weight:700;padding:8px 14px;border-radius:999px;margin-top:2px}

/* --- Force direct-contact buttons to stack on narrow phones --- */
.btn-row--stack-sm{flex-direction:column}
.btn-row--stack-sm .btn{width:100%}
@media(min-width:480px){
  .btn-row--stack-sm{flex-direction:row}
  .btn-row--stack-sm .btn{width:auto;flex:1}
}
.contact-subhead{font-size:1.05rem;margin-bottom:14px}

/* --- Enquiry form (WPForms #38) mobile styling --- */
.contact-enquiry-section .form-card{padding:20px 16px 22px}
.contact-enquiry-section h2{font-size:1.25rem}

#wpforms-form-38,
.contact-enquiry-section [id^="wpforms-"]{width:100%}

#wpforms-form-38 .wpforms-field,
.contact-enquiry-section [id^="wpforms-"] .wpforms-field{
  width:100% !important;float:none !important;clear:both !important;padding:0 0 14px !important;
}
#wpforms-form-38 .wpforms-field-row,
#wpforms-form-38 .wpforms-one-half,
#wpforms-form-38 .wpforms-one-third{width:100% !important;float:none !important;clear:both !important}

#wpforms-form-38 input[type="text"],
#wpforms-form-38 input[type="tel"],
#wpforms-form-38 input[type="email"],
#wpforms-form-38 select,
#wpforms-form-38 textarea{
  width:100% !important;box-sizing:border-box;min-height:54px;font-size:16px !important;
  padding:12px 14px;border:1.5px solid var(--grey-light);border-radius:9px;
  background:var(--off-white);color:var(--text-grey);
}
#wpforms-form-38 textarea{min-height:90px;max-height:160px;resize:vertical}

#wpforms-form-38 input:focus,
#wpforms-form-38 select:focus,
#wpforms-form-38 textarea:focus{
  outline:none;border-color:var(--gold);background:#fff;box-shadow:0 0 0 3px rgba(215,165,58,.18);
}

#wpforms-form-38 label,
#wpforms-form-38 .wpforms-field-label{
  font-weight:700;color:var(--navy);font-size:.95rem;display:block;margin-bottom:6px;
  white-space:normal;overflow-wrap:break-word;
}

#wpforms-form-38 .wpforms-error,
#wpforms-form-38 label.wpforms-error{color:var(--red);font-weight:700;font-size:.85rem;margin-top:4px}
#wpforms-form-38 input.wpforms-error,
#wpforms-form-38 select.wpforms-error,
#wpforms-form-38 textarea.wpforms-error{border-color:var(--red)}

#wpforms-form-38 button[type="submit"],
#wpforms-form-38 .wpforms-submit{
  width:100% !important;background:var(--gold) !important;color:var(--navy) !important;
  font-weight:800 !important;font-size:1.05rem !important;min-height:54px;border:none !important;
  border-radius:9px !important;cursor:pointer;margin-top:6px;
}
#wpforms-form-38 button[type="submit"]:hover,
#wpforms-form-38 .wpforms-submit:hover{background:var(--gold-light) !important}

.contact-reassurance{margin-top:14px}
.contact-privacy{font-size:.78rem;color:var(--text-grey)}
.contact-seo-line{margin-top:14px;font-size:.92rem;color:var(--text-grey)}

@media(min-width:680px){
  .contact-intro h1{font-size:2rem}
}

/* ==========================================================================
   Contact form (WPForms #38) — shorter optional textarea (v1.3.0)
   Reduces the existing #wpforms-form-38 textarea height only; every other
   rule in the block above (inputs, submit button, errors) is unchanged.
   ========================================================================== */
#wpforms-form-38 textarea{min-height:80px;max-height:110px}

/* --- Spacing for the new Call/WhatsApp row above the general form --- */
.contact-direct-row{margin-bottom:18px}

/* ==========================================================================
   Paid Landing Pages (Google Ads / Mailshot) — v1.3.0
   Scoped to .paid-landing-page (page-landing-paid.php template), .hero__trust
   / .hero__supporting (landing hero only), .landing-form-card, and
   .mailshot-panel (Contact page only). Nothing here changes any other page,
   template, or WPForms instance.
   ========================================================================== */

/* --- Trust points on the dark landing hero (light text + gold tick) --- */
.hero__trust{margin:14px 0 20px}
.hero__trust li{position:relative;padding-left:28px;margin-bottom:8px;font-weight:600;
  color:#e7eefa;font-size:.96rem}
.hero__trust li::before{content:"";position:absolute;left:0;top:3px;width:18px;height:18px;
  border-radius:50%;background:var(--gold);
  -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/12px no-repeat;
  mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/12px no-repeat}
.hero__supporting{font-size:.92rem;margin-top:14px;color:#cdd9ea}
.hero__supporting a{color:var(--gold-light);font-weight:700;text-decoration:underline}

/* --- Compact section padding on the landing pages only (no oversized gaps) --- */
.paid-landing-page .hero__inner{padding:26px 18px 30px}
.paid-landing-page .section{padding:34px 0}
.paid-landing-page .section--tight{padding:22px 0}

/* --- Landing booking forms: 48px+ tap targets, 16px inputs, no iOS zoom.
   Uses the generic [id^="wpforms-"] attribute selector (not a hard-coded
   form ID) because these forms don't have their WPForms IDs yet. --- */
.landing-form-card [id^="wpforms-"]{width:100%}
.landing-form-card [id^="wpforms-"] .wpforms-field{
  width:100% !important;float:none !important;clear:both !important;padding:0 0 14px !important}
.landing-form-card [id^="wpforms-"] .wpforms-field-row,
.landing-form-card [id^="wpforms-"] .wpforms-one-half,
.landing-form-card [id^="wpforms-"] .wpforms-one-third{
  width:100% !important;float:none !important;clear:both !important}
.landing-form-card [id^="wpforms-"] input[type="text"],
.landing-form-card [id^="wpforms-"] input[type="tel"],
.landing-form-card [id^="wpforms-"] input[type="email"],
.landing-form-card [id^="wpforms-"] select,
.landing-form-card [id^="wpforms-"] textarea{
  width:100% !important;box-sizing:border-box;min-height:54px;font-size:16px !important;
  padding:14px;border:1.5px solid var(--grey-light);border-radius:9px;
  background:var(--off-white);color:var(--text-grey)}
.landing-form-card [id^="wpforms-"] textarea{min-height:92px;max-height:110px;resize:vertical}
.landing-form-card [id^="wpforms-"] input:focus,
.landing-form-card [id^="wpforms-"] select:focus,
.landing-form-card [id^="wpforms-"] textarea:focus{
  outline:none;border-color:var(--gold);background:#fff;box-shadow:0 0 0 3px rgba(215,165,58,.18)}
.landing-form-card [id^="wpforms-"] label,
.landing-form-card [id^="wpforms-"] .wpforms-field-label{
  font-weight:700;color:var(--navy);font-size:.95rem;display:block;margin-bottom:6px;
  white-space:normal;overflow-wrap:break-word}
.landing-form-card [id^="wpforms-"] .wpforms-error,
.landing-form-card [id^="wpforms-"] label.wpforms-error{color:var(--red);font-weight:700;font-size:.85rem;margin-top:4px}
.landing-form-card [id^="wpforms-"] input.wpforms-error,
.landing-form-card [id^="wpforms-"] select.wpforms-error,
.landing-form-card [id^="wpforms-"] textarea.wpforms-error{border-color:var(--red)}
.landing-form-card [id^="wpforms-"] button[type="submit"],
.landing-form-card [id^="wpforms-"] .wpforms-submit{
  width:100% !important;min-height:54px;background:var(--gold) !important;color:var(--navy) !important;
  font-weight:800 !important;font-size:1.05rem !important;border:none !important;border-radius:9px !important;
  cursor:pointer;margin-top:6px}
.landing-form-card [id^="wpforms-"] button[type="submit"]:hover,
.landing-form-card [id^="wpforms-"] .wpforms-submit:hover{background:var(--gold-light) !important}

/* --- Mailshot panel (Contact page only) — built on the existing .cta-band
   navy-gradient band, with small panel-specific tweaks --- */
.mailshot-panel{padding:26px 20px}
.mailshot-panel .eyebrow{color:var(--gold-light)}
.mailshot-panel h2{font-size:1.35rem;margin-bottom:.5rem}
.mailshot-panel__support{font-size:.92rem;opacity:.92}
.mailshot-panel__secondary{font-size:.88rem;margin-top:14px}
.mailshot-panel__qualification{font-size:.78rem;color:#9fb0c4;margin-top:8px;
  max-width:640px;margin-left:auto;margin-right:auto}

/* --- Simplified landing-page footer --- */
.footer-landing__inner{padding:26px 18px;text-align:center}
.footer-landing__name{color:#fff;font-weight:700;margin-bottom:10px}
.footer-landing__list{display:flex;flex-direction:column;gap:8px;align-items:center}
.footer-landing__list a{color:#aebccd}
.footer-landing__list a:hover{color:var(--gold)}
@media(min-width:480px){
  .footer-landing__list{flex-direction:row;justify-content:center;flex-wrap:wrap;gap:16px}
}

/* ==========================================================================
   Site-wide mobile usability update — v1.4.0
   Overrides typography, spacing, forms, sticky bar and header sizing across
   the whole site via source-order cascade (later rule of equal specificity
   wins) — no existing selector is removed, only superseded where noted.
   ========================================================================== */

/* --- A. Global mobile typography & spacing (320px+) --- */
body{font-size:17px;line-height:1.5}
h1{font-size:clamp(2rem,8.5vw,2.8rem)}
h2{font-size:clamp(1.65rem,6.5vw,2.2rem)}
h3{font-size:clamp(1.3rem,5vw,1.7rem)}
.hero h1{font-size:clamp(2rem,8.5vw,2.9rem)}
.wrap{padding:0 20px}
.section{padding:30px 0}
.section--tight{padding:22px 0}
.card__body{padding:20px 20px 22px}
.form-card{padding:22px 20px}
h1,h2,h3{word-break:normal;overflow-wrap:anywhere}
.header-phone,.hero__price,.btn{white-space:nowrap}

@media(min-width:680px){
  .section{padding:38px 0}
}
@media(min-width:920px){
  .section{padding:60px 0} /* desktop section padding unchanged from original */
}

/* --- B. Normal mobile header: compact, legible, 48px+ tap targets --- */
.header-bar{padding:12px 20px;min-height:76px}
.brand img{height:38px}
.menu-toggle,.icon-btn--call{min-height:48px;padding:10px 14px}
@media(min-width:920px){
  .header-bar{min-height:auto}
  .brand img{height:42px}
  /*
   * v1.8.4 — FIX: this rule was silently overriding the v1.8.3
   * "reduce empty space" fix (which set .section to 48px at ≥1040px,
   * further up this file) because it appears LATER in the cascade with
   * equal specificity and its own ≥920px condition is also true at any
   * width ≥1040px — so the desktop padding reduction from the previous
   * release was never actually taking effect. Corrected to match.
   */
  .section{padding:48px 0}
}

/* --- C. Paid landing-page header: compact single row, no number in button --- */
body.paid-landing .header-bar{min-height:72px;padding:12px 20px}
body.paid-landing .brand img{height:34px}
body.paid-landing .header-bar .btn{white-space:nowrap;padding:12px 18px;min-height:48px}

/*
 * v1.8.4 — reduced sticky bar height slightly (68px → 58px min-height,
 * tighter internal padding/icon size) while keeping every link's own
 * min-height at 48px (WCAG-minimum tap target, unchanged). body's bottom
 * padding trimmed to match — still enough clearance that page content
 * (including the last field/button of an inline form) is never covered.
 */
.sticky-cta{min-height:var(--sticky-h);padding-bottom:env(safe-area-inset-bottom)}
.sticky-cta a{min-height:48px}
/* v1.9.1 (Correction 6): buffer widened 16px -> 20px and tied to --sticky-h
   instead of a hardcoded 62px, so the clearance can never fall short of the
   bar's actual height. Calculation: sticky-bar min-height (58px) + the
   device's safe-area inset (0 on most Android/desktop, ~34px on an iPhone
   with a home indicator) + a 20px visual buffer above the bar. This is
   body's bottom padding, i.e. empty space AFTER the real page content
   (including the footer's last line and any inline form) — the fixed bar
   only ever overlaps that empty padding area, never actual content, in a
   real (non-full-page-screenshot) viewport. See the Stage 2.1 report for
   the scrolled-viewport verification that confirms this. */
body{padding-bottom:calc(var(--sticky-h) + env(safe-area-inset-bottom) + 20px)}
@media(min-width:920px){
  body{padding-bottom:0}
}
html{scroll-padding-top:96px} /* keeps anchor scrolls (#booking-form etc.) clear of the sticky header */

/* --- P. Forms: global 48px+/16px/52-56px/90-110px baseline. Existing scoped
   blocks (#wpforms-form-38, .landing-form-card, .home-survey-form-section)
   already meet or exceed this and are unaffected — this is the site-wide
   floor for any other WPForms instance (e.g. form 319 on repair/service/CP12
   pages, form 315 on the free-survey page) that didn't have scoped rules. --- */
.wpforms-container input[type="text"],
.wpforms-container input[type="email"],
.wpforms-container input[type="tel"],
.wpforms-container input[type="number"],
.wpforms-container select,
.wpforms-container textarea{
  font-size:16px !important;min-height:52px;padding:13px 14px;box-sizing:border-box;
  border:1.5px solid var(--grey-light);border-radius:9px;background:var(--off-white);
  color:var(--text-grey);width:100%}
.wpforms-container textarea{min-height:92px;max-height:110px;resize:vertical}
.wpforms-container .wpforms-field{margin-bottom:16px}
.wpforms-container label,.wpforms-container .wpforms-field-label{
  font-weight:700;color:var(--navy);font-size:.95rem;display:block;margin-bottom:6px}
.wpforms-container button[type="submit"],
.wpforms-container .wpforms-submit{
  min-height:52px;background:var(--gold) !important;color:var(--navy) !important;
  font-weight:800 !important;border:none !important;border-radius:9px !important;cursor:pointer}
@media(max-width:599px){
  .wpforms-container button[type="submit"],
  .wpforms-container .wpforms-submit{width:100% !important}
}
/* Honeypot / anti-spam fields must never be visible, regardless of theme CSS resets */
.wpforms-field-hp,input[name*="hp-"],.wpforms-hp{
  position:absolute !important;left:-9999px !important;top:-9999px !important;
  width:1px !important;height:1px !important;overflow:hidden !important}

/* --- N. Areas page: expandable region groups (mobile-compact accordion,
   built on the same visual language as .faq — all links/text unchanged) --- */
.area-groups{max-width:900px;margin:0 auto}
.area-group{background:#fff;border:1px solid var(--grey-light);border-radius:var(--radius);
  margin-bottom:12px;overflow:hidden;box-shadow:var(--shadow-sm)}
.area-group summary{cursor:pointer;list-style:none;padding:16px 48px 16px 18px;font-weight:800;
  color:var(--navy);position:relative;font-size:1.05rem}
.area-group summary::-webkit-details-marker{display:none}
.area-group summary::after{content:"+";position:absolute;right:18px;top:50%;transform:translateY(-50%);
  font-size:1.5rem;color:var(--gold);font-weight:800;line-height:1}
.area-group[open] summary::after{content:"–"}
.area-group .area-chips{padding:0 18px 18px}

/* --- Q. Layout shift: images already carry width/height attributes
   site-wide, which is the reliable, broadly-supported way to reserve
   space and prevent CLS — no additional CSS is needed or added here. --- */

/* ==========================================================================
   Site-wide mobile usability update — v1.5.0
   Homepage service chooser, mobile breadcrumb reduction, and read-more
   disclosure styling. Nothing here removes existing markup or schema —
   only visual presentation on top of it.
   ========================================================================== */

/* --- R. Homepage service chooser (below hero/trust-strip) --- */
.service-chooser{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin-top:18px}
.service-chooser__item{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:8px;background:#fff;border:1px solid var(--grey-light);border-radius:var(--radius);
  padding:18px 10px;min-height:96px;box-shadow:var(--shadow-sm);text-align:center;
  font-weight:700;color:var(--navy);transition:transform .14s ease,box-shadow .14s ease}
.service-chooser__item:hover{transform:translateY(-2px);box-shadow:var(--shadow);text-decoration:none}
.service-chooser__icon{font-size:1.6rem;line-height:1}
.service-chooser__label{font-size:.92rem}
@media(min-width:680px){
  .service-chooser{grid-template-columns:repeat(4,1fr);gap:16px}
  .service-chooser__item{padding:22px 14px;min-height:110px}
  .service-chooser__icon{font-size:1.9rem}
  .service-chooser__label{font-size:1rem}
}

/* --- S. Breadcrumbs: hidden on mobile to save first-screen space, restored
   on tablet/desktop. This only affects the *visible* trail — BreadcrumbList
   JSON-LD is emitted separately in <head> by the SEO plugin and is
   completely unaffected by this rule. --- */
.crumbs{display:none}
@media(min-width:920px){
  .crumbs{display:block}
}

/* --- T. Read-more progressive disclosure (used for long intro paragraphs
   moved below the main CTA on service/local pages). Content stays in the
   HTML at all times for indexing and accessibility; this only toggles
   visibility, and the button never covers essential price/regulatory text. --- */
.read-more__extra[hidden]{display:none}
.read-more__toggle{background:none;border:1.5px solid var(--navy);color:var(--navy);
  font-weight:700;font-size:.92rem;padding:10px 16px;border-radius:8px;cursor:pointer;
  display:inline-flex;align-items:center;gap:6px;min-height:44px}
.read-more__toggle:hover{background:var(--navy);color:#fff}
.read-more__toggle:focus-visible{outline:3px solid var(--gold-light);outline-offset:2px}

/* ==========================================================================
   v1.6.0 — Leaflet-inspired conversion design system
   New, additive component classes only — no existing selector above this
   point has been edited. Everything here is either a brand-new class
   (.offer-band, .offer-price, .trust-mini, .service-btns, .ticks--2col) or
   scoped to a specific body/page class inside a mobile media query.
   No min-height, no 100vh, no justify-content:space-between on stacked
   content, no oversized cards.
   ========================================================================== */

/* --- Offer band: compact navy/gold/white campaign block, leaflet price
   emphasis in the (very limited) red accent, same as the printed leaflet. --- */
.offer-band{background:var(--navy);color:#fff;text-align:center;padding:28px 0}
.offer-band .wrap{max-width:640px}
.offer-band h1{color:#fff;font-size:clamp(1.6rem,6vw,2.1rem);line-height:1.15;margin-bottom:6px}
.eyebrow--gold{color:var(--gold-light)}
.offer-price{font-weight:800;color:var(--red);line-height:1;margin:6px 0 4px;
  font-size:clamp(3.2rem,15vw,4.4rem)}
.offer-price__currency{font-size:.5em;font-weight:700;vertical-align:top;margin-right:2px}
.offer-price__note{color:#dbe4ef;font-size:.98rem;margin-bottom:14px}
.offer-benefits{display:flex;flex-direction:column;gap:8px;max-width:420px;margin:0 auto 18px;text-align:left}
.offer-benefits li{display:flex;align-items:center;gap:10px;font-weight:600;font-size:.95rem;color:#fff}
.offer-benefits li::before{content:"";flex:0 0 auto;width:18px;height:18px;border-radius:50%;
  background:var(--gold);
  -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/12px no-repeat;
  mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/12px no-repeat}
.offer-form-section{padding-top:24px}
@media(min-width:920px){
  .offer-band{padding:40px 0}
}

/* --- Compact 2-column checklist (mobile stays 1-column). Reuses the
   existing .ticks tick-icon styling, just adds a column layout on top. --- */
.ticks--2col{column-gap:28px}
@media(min-width:680px){
  .ticks--2col{display:grid;grid-template-columns:1fr 1fr;gap:4px 28px}
  .ticks--2col li{margin-bottom:8px}
}

/* --- Compact rectangular service buttons (NOT cards) — used in the
   homepage hero and the Contact-page "Need Help With Something Else?"
   section. Small, tappable, text-only rectangles. --- */
.service-btns{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px}
.service-btn{display:inline-flex;align-items:center;justify-content:center;
  padding:12px 18px;min-height:44px;border-radius:8px;font-weight:700;font-size:.94rem;
  border:2px solid var(--navy);color:var(--navy);background:#fff;text-decoration:none}
.service-btn:hover{background:var(--navy);color:#fff;text-decoration:none}
.service-btn--primary{background:var(--gold);border-color:var(--gold);color:var(--navy)}
.service-btn--primary:hover{background:var(--gold-light);border-color:var(--gold-light);color:var(--navy)}
.service-btns--hero{margin-top:14px}

/* --- Compact 3-item trust list (replaces a 5-item .trust-strip in hero
   areas where the brief calls for "only three trust points near the top"). --- */
.trust-mini{background:var(--off-white);border-top:3px solid var(--gold);border-bottom:1px solid var(--grey-light)}
.trust-mini ul{max-width:var(--maxw);margin:0 auto;padding:14px 20px;display:grid;
  grid-template-columns:1fr;gap:8px}
.trust-mini li{display:flex;align-items:center;gap:10px;font-weight:700;font-size:.92rem;color:var(--navy)}
.trust-mini li::before{content:"";flex:0 0 auto;width:16px;height:16px;border-radius:50%;background:var(--gold);
  -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/11px no-repeat;
  mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/11px no-repeat}
@media(min-width:480px){
  .trust-mini ul{grid-template-columns:repeat(3,1fr);gap:10px 16px}
}

/* PROMPT 25 — /boiler-quote/'s own trust strip (the .trust-mini--boiler-
   quote-strip instance in _page-content-import/boiler-quote.html, and ONLY
   that instance — the shared .trust-mini component is untouched and still
   shows on every other page at every width, including on /boiler-quote/
   itself at tablet/desktop widths) is hidden on small mobile, where it was
   pushing the builder's first question below the fold. display:none (not
   visibility:hidden/opacity) removes it from layout entirely, so no empty
   gap is left behind — the section immediately below it keeps its own
   normal top padding, nothing more. 600px matches the brief's own stated
   threshold; the theme's existing general mobile tier sits one pixel
   narrower, at 599px (see the two max-width:599px rules elsewhere in this
   file), so this is consistent with that convention. */
@media(max-width:600px){
  .trust-mini--boiler-quote-strip{display:none}
}

/* --- Homepage only: .yb-home-order lays out hero / trust-mini / van-image
   as three siblings. By default (no rule outside the two media queries
   below) they simply stack in source order — hero, trust, image — which
   is exactly the required mobile order, so mobile needs no extra rule
   beyond the image-size reduction. At ≥920px a CSS grid restores the
   original two-column look: hero copy stays full-height on the left,
   the van image sits beside it on the right, and trust-mini spans full
   width underneath — closely matching the pre-v1.6.0 desktop appearance. --- */
@media(max-width:767px){
  body.yb-homepage .yb-home-hero__inner{padding:20px 20px 22px}
  body.yb-homepage .yb-home-media img{aspect-ratio:16/9;max-height:200px}
  body.yb-homepage .yb-home-media .van-caption{display:none}
}
@media(min-width:920px){
  body.yb-homepage .yb-home-hero__inner{grid-template-columns:1fr}
  body.yb-homepage .yb-home-order{
    display:grid;
    grid-template-columns:1.05fr .95fr;
    grid-template-areas:"hhero hmedia" "htrust htrust";
    align-items:stretch;
  }
  body.yb-homepage .yb-home-hero{grid-area:hhero}
  body.yb-homepage .yb-home-media{grid-area:hmedia;align-self:center;padding:0 18px}
  body.yb-homepage .yb-home-trust{grid-area:htrust}
}

/* ==========================================================================
   v1.7.0 — Annual Boiler Service £70 / Annual Service Plan £6-a-month
   (mailshot landing page, Bradford page refresh, homepage/contact cards)

   All new, scoped rules appended below. Nothing above this point in the
   file was edited. Reuses existing tokens (--navy, --gold, --red, --radius,
   --shadow) and existing components (.offer-band, .card-grid, .ticks,
   .faq, .form-card, .sticky-cta, .service-btns) rather than introducing a
   parallel colour system — see AUDIT-v1.7.0.md.
   ========================================================================== */

/* --- Plan band: "Plan Ahead for Next Year" £6/month section. Navy
   background, gold border, white text, per brief — a distinct block from
   .offer-band (which is navy-only, no border) so the two offers are never
   visually confused with each other. --- */
.plan-band{background:var(--navy);border:2px solid var(--gold);border-radius:var(--radius);
  color:#fff;padding:28px 20px;margin:0 auto;max-width:760px}
.plan-band h2{color:#fff;text-align:center;font-size:clamp(1.3rem,5vw,1.7rem)}
.plan-band__price{display:block;text-align:center;font-weight:800;color:var(--gold-light);
  font-size:clamp(1.8rem,7vw,2.4rem);line-height:1;margin:10px 0}
.plan-band__price small{display:block;font-weight:700;font-size:.9rem;color:#dbe4ef;margin-top:6px;letter-spacing:.04em}
.plan-band p{color:#dbe4ef;text-align:center;max-width:560px;margin:0 auto 14px}
.plan-band .ticks{max-width:420px;margin:0 auto 18px}
.plan-band .ticks li{color:#fff}
.plan-band .ticks li::before{background:var(--gold)}
.plan-band__exclusions{background:rgba(0,0,0,.18);border:1px solid rgba(255,255,255,.25);
  border-radius:8px;padding:14px 16px;margin:18px auto;max-width:620px;font-size:.92rem;color:#f3f6fb}
.plan-band__exclusions p{margin-bottom:8px;color:#f3f6fb}
.plan-band__exclusions p:last-child{margin-bottom:0}
.plan-band .btn-row{justify-content:center;margin-top:16px}

/* --- Four equal service-benefit cards ("Why Annual Boiler Servicing
   Matters"). Reuses .card-grid's responsive column behaviour; icons are
   plain inline SVG in navy/gold, no animation, no extra image requests. --- */
.benefit-cards{display:grid;grid-template-columns:1fr;gap:16px}
@media(min-width:620px){ .benefit-cards{grid-template-columns:repeat(2,1fr)} }
@media(min-width:920px){ .benefit-cards{grid-template-columns:repeat(4,1fr)} }
.benefit-card{background:#fff;border:1px solid var(--grey-light);border-radius:var(--radius);
  padding:20px 18px;text-align:left}
.benefit-card__icon{width:40px;height:40px;border-radius:10px;background:var(--off-white);
  border:1px solid var(--grey-light);display:flex;align-items:center;justify-content:center;margin-bottom:12px}
.benefit-card__icon svg{width:22px;height:22px;color:var(--navy)}
.benefit-card h3{font-size:1.05rem;margin-bottom:6px}
.benefit-card p{font-size:.94rem;margin-bottom:0;color:var(--text-grey)}

/* --- Trust panel used on the mailshot landing page: same visual language
   as .trust-strip but with the tagline + contact block the brief asks for. --- */
.trust-panel{background:var(--navy-dark);color:#cdd9ea;border-top:3px solid var(--gold);padding:28px 0}
.trust-panel .tagline{display:block;text-align:center;color:var(--gold-light);font-weight:800;
  letter-spacing:.12em;font-size:.85rem;margin-bottom:16px}
.trust-panel ul{max-width:var(--maxw);margin:0 auto;padding:0 18px;display:grid;
  grid-template-columns:1fr;gap:10px}
.trust-panel li{display:flex;align-items:center;gap:10px;font-weight:600;font-size:.95rem}
.trust-panel li::before{content:"";flex:0 0 auto;width:18px;height:18px;border-radius:50%;background:var(--gold);
  -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/12px no-repeat;
  mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/12px no-repeat}
.trust-panel__contact{max-width:var(--maxw);margin:18px auto 0;padding:16px 18px 0;border-top:1px solid rgba(255,255,255,.12);
  display:flex;flex-wrap:wrap;gap:16px;justify-content:center;font-size:.92rem}
.trust-panel__contact a{color:#fff;font-weight:700}
.trust-panel__logos{max-width:var(--maxw);margin:20px auto 0;padding:0 18px;display:flex;flex-wrap:wrap;
  gap:14px 22px;justify-content:center;align-items:center;opacity:.85}
.trust-panel__logos span{font-size:.82rem;font-weight:700;color:#aebdd1;letter-spacing:.02em}
@media(min-width:620px){ .trust-panel ul{grid-template-columns:repeat(2,1fr);gap:10px 24px} }
@media(min-width:920px){ .trust-panel ul{grid-template-columns:repeat(3,1fr)} }

/* --- Contact-page and homepage compact £70 service card, replacing the
   old full-width £70 offer band embed (see CHANGED-FILES.md). Built on
   the existing .form-card visual language so it doesn't need new tokens. --- */
.service-offer-card{background:#fff;border:2px solid var(--gold);border-radius:var(--radius);
  box-shadow:var(--shadow-sm);padding:22px 20px;text-align:center;max-width:520px;margin:0 auto}
.service-offer-card .eyebrow{color:var(--navy)}
.service-offer-card__price{font-weight:800;color:var(--red);font-size:clamp(1.8rem,7vw,2.3rem);line-height:1;margin:4px 0 8px}
.service-offer-card__price small{display:block;font-size:1rem;font-weight:700;color:var(--text-grey);margin-top:4px}
.service-offer-card p{margin-bottom:14px}
.service-offer-card .btn{width:100%}
.service-offer-card__secondary{font-size:.9rem;color:var(--text-grey);margin-top:12px;margin-bottom:0}

/* --- Plan-interest checkbox on the £70 booking form: WPForms renders this
   as an ordinary checkbox field once created in the admin (see
   ANNUAL-SERVICE-PLAN-FORM-MANUAL-CHANGES.md) — this only makes it a
   little more visually prominent than a default WPForms checkbox, it does
   not create the field itself. --- */
.landing-form-card .wpforms-field-checkbox .yb-plan-interest-label,
.landing-form-card [id^="wpforms-"] .wpforms-field-checkbox{
  background:var(--off-white);border:1px solid var(--grey-light);border-radius:8px;padding:10px 12px}

/* --- Legal/terms page prose (Annual Boiler & Heating Service Plan Terms).
   Matches the existing .legal-page.prose spacing used by page-legal.php. --- */
.legal-page .yb-legal-placeholder{display:block;background:#FFF6E5;border:1px dashed var(--gold);
  border-radius:8px;padding:10px 14px;margin:10px 0;font-size:.92rem;color:#7a5b12}
.legal-page .yb-legal-placeholder strong{color:#5c4409}

/* --- v1.7.1: £70 one-off vs £6/month plan comparison grid — reuses the
   existing .service-offer-card / .plan-band panel styles side by side, on
   /boiler-servicing/, /boiler-service-bradford/ and
   /annual-service-plan-terms/. Single column on mobile, two columns from
   680px up. --- */
.compare-grid{display:grid;grid-template-columns:1fr;gap:18px}
@media(min-width:680px){ .compare-grid{grid-template-columns:1fr 1fr;align-items:start} }
.compare-grid .service-offer-card,.compare-grid .plan-band{margin:0;height:100%}
.plan-card__label{display:inline-block;background:var(--gold);color:var(--navy);font-weight:800;
  font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;padding:4px 10px;border-radius:20px;margin-bottom:10px}

/* --- Mobile responsiveness for the new blocks above. Desktop (≥920px)
   restores multi-column layouts already handled inline above; this block
   only tightens padding at small widths, matching the rest of the file's
   mobile-first pattern. --- */
@media(max-width:767px){
  .plan-band{padding:22px 16px}
  .service-offer-card{padding:18px 16px}
  .trust-panel{padding:22px 0}
}

/* ==========================================================================
   v1.8.0 — SIMPLIFIED HOMEPAGE + DYNAMIC FORM + DROPDOWN NAV
   ========================================================================== */

/* --- Homepage "What Do You Need?" compact boxes (replaces old .card-grid
   service cards on the homepage — small boxes, no big imagery). --- */
/* PROMPT 12 (§9 regression pass): the base (mobile, single-column) track
   below was still bare `1fr` — the v2.5.0/Prompt 9 comment immediately
   below already explains why that's unsafe, but the fix it describes was
   only ever applied to the >=560px/>=920px rules, not this one. Found via
   a real-browser overflow check at 320px on /contact/: a `.need-box`
   containing a `.btn--block` forced this single track past the viewport
   (23px overflow, confirmed empirically), the exact "auto min-sizing"
   mechanism the comment below already names. minmax(0,1fr) here is the
   same, already-proven, purely-mechanical fix — one column still gets
   100% of the row width in the normal case; this only lets it shrink
   below its content's natural width instead of forcing the row wider
   than the viewport. */
.need-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:12px}
/* v2.5.0 — Prompt 9: bare `1fr` grid tracks default to min-width:auto, so a
   .need-box whose content (price/sub-copy) has a wider intrinsic minimum
   than its share of the row forces the whole grid past the viewport edge
   (confirmed via real-browser overflow testing on the homepage's 4-up row
   and the contact page's need-grid at 1024-1440px). minmax(0,1fr) is the
   standard, purely-mechanical fix for this — every track still gets an
   equal 1fr share in the normal case; this only lets a track shrink below
   its content's natural width instead of forcing the row wider than the
   viewport. No visual change to spacing/sizing in any passing case. */
@media(min-width:560px){ .need-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)} }
@media(min-width:920px){ .need-grid{grid-template-columns:repeat(4,minmax(0,1fr))} }
.need-box{background:#fff;border:1px solid #e3e8ef;border-radius:12px;padding:18px;
  display:flex;flex-direction:column;gap:6px;box-shadow:var(--shadow-sm)}
.need-box h3{font-size:1rem;margin:0}
.need-box__price{font-weight:800;font-size:1.3rem;color:var(--navy)}
.need-box__sub{font-size:.85rem;color:var(--text-grey)}
/* PROMPT 14 (§5) — live /contact/ regression fix: 7 of the 8 card CTA
   buttons were overlapping their neighbouring card. Root cause is the same
   "auto min-sizing" bug class already fixed elsewhere in this file
   (.need-grid above, .cta-band/.compare-grid/.hero__cta/.btn-row further
   down) but in its FLEX-ITEM form rather than its grid-track form:
   .need-box is `display:flex;flex-direction:column`, and its `.btn` child
   is a flex item — a flex item's default min-width is `auto`, meaning its
   intrinsic content width (here, the sitewide `.btn{white-space:nowrap}`
   rule's un-wrapped label text, ~line 840) can exceed the flex container's
   actual width and force the button to render wider than its own card,
   visually overlapping the next one. `.btn--block`'s `width:100%` alone
   does not fix this — width:100% of an oversized auto min-width flex item
   still overflows. Fixed with the same two-part pattern already proven
   sitewide: `min-width:0` overrides the flex-item default so the button
   can actually shrink to its container's width, and `white-space:normal`
   (+ `overflow-wrap:break-word` as a defensive fallback for any future
   very-long label/very-narrow card combination, and `text-align:center`
   so a wrapped 2-line label stays centred) lets the label text wrap onto a
   second line instead of forcing the box wider. Scoped to `.need-box .btn`
   only — every other `.btn` sitewide is unaffected. See
   PROMPT14-CONTACT-CARD-QA.md for the before/after browser verification. */
.need-box .btn{
  margin-top:8px; width:100%; min-width:0; box-sizing:border-box;
  white-space:normal; overflow-wrap:break-word; word-break:break-word;
  text-align:center;
}
.hero__trust{font-size:.85rem;color:var(--gold-light);font-weight:700;margin-top:6px}

/* --- Recent Work & Reviews (homepage) --- */
.review-grid{display:grid;grid-template-columns:1fr;gap:14px;text-align:left}
@media(min-width:768px){ .review-grid{grid-template-columns:repeat(3,1fr)} }
.review-card{background:#fff;border:1px solid #e3e8ef;border-radius:12px;padding:16px;
  font-style:normal;font-size:.92rem;color:var(--text-grey);min-height:64px}

/* --- Desktop dropdown submenus (HEATING / REPAIRS & SERVICING).
   Only activates once a real 2-level WordPress menu exists — see
   MENU-SETUP.md. Hover + keyboard focus, matches existing nav-desktop. --- */
@media(min-width:960px){
  .nav-desktop li{position:relative}
  .nav-desktop .sub-menu{display:none;position:absolute;top:100%;left:0;min-width:220px;
    background:#fff;border:1px solid #e3e8ef;border-radius:10px;box-shadow:0 12px 28px rgba(6,26,51,.14);
    padding:8px;z-index:40;flex-direction:column;gap:0}
  .nav-desktop li:hover > .sub-menu,
  .nav-desktop li:focus-within > .sub-menu{display:flex}
  .nav-desktop .sub-menu a{padding:9px 10px;border-radius:6px;font-weight:500}
  .nav-desktop .sub-menu a:hover{background:#f4f6f9}
  .nav-desktop .menu-item-has-children > a::after{content:"▾";margin-left:5px;font-size:.7em}
}

/* --- Mobile accordion submenus (tap to expand, not full nav dump). --- */
.nav-mobile .menu-item-has-children > a{display:flex;align-items:center;justify-content:space-between}
.nav-mobile .menu-item-has-children > a::after{content:"+";font-size:1.2em;line-height:1;margin-left:8px}
.nav-mobile .menu-item-has-children.is-open > a::after{content:"−"}
.nav-mobile .sub-menu{display:none;padding-left:12px;border-left:2px solid rgba(255,255,255,.15);margin:2px 0 6px}
.nav-mobile .menu-item-has-children.is-open > .sub-menu{display:block}
.nav-mobile .sub-menu a{font-weight:500;font-size:.92rem}

/* ==========================================================================
   SITE-WIDE DYNAMIC FORM (YBDynamicForm) — one reusable progressive form.
   Mobile: near-full-screen bottom sheet. Desktop: centred modal.
   ========================================================================== */
/*
 * v2.0.0 (Prompt 3) — z-index raised from 200 to 1000. The mobile sticky
 * action bar (.sticky-cta, z-index:950 — see ~line 354) previously
 * outranked this modal, so it could render ON TOP of an open modal on
 * mobile. Two independent fixes are applied for this: this z-index raise
 * (belt-and-braces, in case the suppression class below is ever skipped),
 * and body.yb-modal-open below, which actually hides .sticky-cta outright
 * while the modal is open (site.js toggles this class in openForm()/
 * closeForm()) and restores it on close.
 */
.yb-df{position:fixed;inset:0;z-index:1000}
.yb-df[hidden]{display:none}
.yb-df__scrim{position:absolute;inset:0;background:rgba(6,26,51,.55);
  animation:yb-df-fade .18s ease}
@keyframes yb-df-fade{from{opacity:0}to{opacity:1}}
.yb-df__panel{position:absolute;left:0;right:0;bottom:0;background:#fff;border-radius:18px 18px 0 0;
  max-height:88vh;display:flex;flex-direction:column;box-shadow:0 -12px 32px rgba(0,0,0,.25);
  animation:yb-df-up .22s ease;
  /* v2.0.0 — respects the home-indicator/gesture-bar safe area on notched
     phones so the sheet's bottom edge (and the submit button inside it)
     is never obscured. Harmless 0px on devices without one. */
  padding-bottom:env(safe-area-inset-bottom)}
@keyframes yb-df-up{from{transform:translateY(100%)}to{transform:translateY(0)}}
@media(min-width:720px){
  .yb-df__panel{left:50%;right:auto;bottom:auto;top:50%;transform:translate(-50%,-50%);
    width:min(560px,92vw);max-height:82vh;border-radius:16px;padding-bottom:0}
  @keyframes yb-df-up{from{opacity:0;transform:translate(-50%,-46%)}to{opacity:1;transform:translate(-50%,-50%)}}
}
/* v2.0.0 — while the modal is open, suppress the sticky mobile action bar
   (site.js adds/removes this class on <body> in openForm()/closeForm()),
   restoring it automatically on close. Scoped to body.yb-modal-open only,
   so paid-landing pages (which never add this class — they have no modal
   shell at all, see page-landing-paid.php/footer-landing.php) are
   completely unaffected. */
body.yb-modal-open .sticky-cta{display:none}
.yb-df__head{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid #eef1f5;position:relative}
.yb-df__progress{position:absolute;top:0;left:0;right:0;height:4px;background:#eef1f5;border-radius:0}
.yb-df__progress-bar{display:block;height:100%;width:0%;background:var(--gold);transition:width .2s ease}
.yb-df__title{flex:1;font-size:1.02rem;margin:0;color:var(--navy)}
/* v2.0.0 — the calculated "Step X of N" / "Final step" text, now rendered
   in the modal head too (previously inline-chrome-only; see
   assets/js/site.js renderStep()). Kept compact so it never crowds the
   title/close button at narrow widths. */
.yb-df__step-text{font-size:.78rem;font-weight:700;color:var(--text-grey);white-space:nowrap}
.yb-df__back,.yb-df__close{background:none;border:0;font-size:1.3rem;line-height:1;cursor:pointer;
  color:var(--text-grey);padding:4px 8px;border-radius:6px;min-width:44px;min-height:44px}
.yb-df__back:hover,.yb-df__close:hover{background:#f4f6f9}
.yb-df__body{padding:18px 16px 22px;overflow-y:auto}
.yb-df__question{font-weight:800;color:var(--navy);font-size:1.15rem;margin:0 0 14px}
.yb-df__options{display:grid;grid-template-columns:1fr;gap:10px}
@media(min-width:480px){ .yb-df__options--2col{grid-template-columns:1fr 1fr} }
.yb-df__option{display:block;width:100%;text-align:left;background:#fff;border:2px solid #e3e8ef;
  border-radius:12px;padding:16px 16px;font-weight:700;font-size:1rem;color:var(--navy);
  cursor:pointer;min-height:52px}
.yb-df__option:hover,.yb-df__option:focus-visible{border-color:var(--gold);background:#fffaf0;outline:none}
.yb-df__option.is-selected{border-color:var(--gold);background:var(--gold-light)}
.yb-df__field{margin-bottom:14px}
.yb-df__field label{display:block;font-weight:700;font-size:.88rem;color:var(--navy);margin-bottom:6px}
.yb-df__field input,.yb-df__field select,.yb-df__field textarea{width:100%;padding:12px 14px;
  border:1.5px solid #dbe1e8;border-radius:10px;font-size:1rem;font-family:inherit}
.yb-df__field input:focus,.yb-df__field select:focus,.yb-df__field textarea:focus{
  border-color:var(--gold);outline:none}
.yb-df__error{color:#B3261E;font-size:.82rem;margin-top:4px;display:none}
.yb-df__error.is-visible{display:block}
.yb-df__submit{margin-top:6px}
.yb-df__note{font-size:.8rem;color:var(--text-grey);margin-top:10px}

@media(max-width:767px){
  .yb-df__option{min-height:56px;font-size:1.02rem}
}

/* ==========================================================================
   v2.0.0 (Prompt 3) — COMPACT CTA PANEL
   Replaces the old .yb-convert-hero__form-panel's <div data-yb-inline-form>
   mount (a full visible progressive wizard rendered inline on the page) on
   every one of the 13 dynamic-form pages. Each panel is now a short,
   route-appropriate heading, one reassurance line, a single gold button
   (data-yb-open-form/data-yb-route, opening the shared modal — see
   assets/js/site.js) and optional factual microcopy. No fields are shown
   until the button is pressed; there is exactly one customer-facing wizard
   instance sitewide (the modal), never a second inline one alongside it.
   ========================================================================== */
.yb-cta-panel{background:#fff;border:1.5px solid #e3e8ef;border-radius:14px;
  padding:22px 20px;text-align:left}
.yb-cta-panel__heading{font-size:1.15rem;font-weight:800;color:var(--navy);margin:0 0 8px}
.yb-cta-panel__reassurance{font-size:.92rem;color:var(--text-grey);margin:0 0 16px}
.yb-cta-panel__btn{min-height:52px}
.yb-cta-panel__note{font-size:.8rem;color:var(--text-grey);margin:12px 0 0}
@media(max-width:767px){
  .yb-cta-panel{padding:20px 16px}
  .yb-cta-panel__btn{min-height:56px}
}

/* ==========================================================================
   v1.8.3 — CONVERSION-FIRST LAYOUT, INLINE FORM, GRACEFUL IMAGE FALLBACK
   ========================================================================== */

/*
 * PROBLEM → SOLUTION → PRICE → FORM above-the-fold layout for the core
 * money pages. Two columns on desktop (left: proposition, right: the
 * inline 3-step form); single column, form-directly-after-CTA on mobile.
 * A missing/failed image never leaves a blank column — see
 * .yb-convert-hero__media img fallback below.
 */
.yb-convert-hero{background:var(--navy);color:#e7eefa;padding:26px 0 30px}
.yb-convert-hero__inner{display:grid;gap:22px;max-width:var(--maxw);margin:0 auto;padding:0 18px}
.yb-convert-hero__problem{color:var(--gold-light);font-weight:800;font-size:.85rem;letter-spacing:.02em;text-transform:uppercase;margin:0 0 6px}
.yb-convert-hero h1{color:#fff;font-size:clamp(1.7rem,5.5vw,2.5rem);margin:0 0 10px;line-height:1.15}
.yb-convert-hero__price{display:block;font-weight:800;color:#fff;font-size:clamp(1.6rem,5vw,2.1rem);line-height:1.15}
.yb-convert-hero__price small{display:block;font-size:.5em;font-weight:700;color:var(--gold-light);text-transform:none;letter-spacing:0}
.yb-convert-hero__finance-terms{font-size:.82rem;color:#cdd9ea;margin:6px 0 0}
.yb-convert-hero__supporting{font-size:1rem;color:#dfe8f5;margin:10px 0 0;max-width:46ch}
.yb-convert-hero__inclusions{font-size:.85rem;color:var(--gold-light);font-weight:700;margin:8px 0 0}
.yb-convert-hero .trust-mini{margin-top:14px;background:transparent;padding:0}
.yb-convert-hero .trust-mini ul{justify-content:flex-start;gap:14px 18px}
.yb-convert-hero .trust-mini li{color:#cdd9ea;font-size:.82rem}
.yb-convert-hero__cta{margin-top:16px}
/*
 * v1.8.5 — CTA HIERARCHY: the service-specific form CTA is the primary
 * action (full-width gold on mobile, so it's unmistakably the main
 * button); Call is visually smaller/secondary, never competing for the
 * same visual weight. Both were previously the same size, which is what
 * made the Call button read as the primary action when it was the only
 * button actually present in the hero.
 */
.yb-convert-hero__cta .btn--primary{width:100%}
.yb-convert-hero__cta .btn--ghost{font-size:.92rem;padding:12px 20px;min-height:auto}
@media(min-width:480px){
  .yb-convert-hero__cta .btn--primary{width:auto;flex:1 1 auto}
  .yb-convert-hero__cta .btn--ghost{flex:0 0 auto}
}

/* Right column: the inline 3-step form, in a light card so it reads as an
   action panel against the dark hero, not more hero copy. */
.yb-convert-hero__form-panel{background:#fff;border-radius:14px;padding:18px 16px 20px;box-shadow:0 14px 32px rgba(0,0,0,.28);color:var(--navy);scroll-margin-top:90px}

@media(min-width:960px){
  .yb-convert-hero{padding:40px 0 46px}
  .yb-convert-hero__inner{grid-template-columns:1.1fr .9fr;align-items:start;gap:36px}
  .yb-convert-hero__form-panel{position:sticky;top:88px}
}

/* Graceful degrade: if a hero image is used elsewhere on the site and
   fails to load, collapse its column rather than leaving a blank navy
   block — the broken-image icon is hidden and the sibling proposition
   column expands to use the freed space. */
.hero__media img{ }
.hero__media img:not([src]),
.hero__media img[src=""]{display:none}
.hero__inner:has(.hero__media img:not([src])),
.hero__inner:has(.hero__media img[src=""]){grid-template-columns:1fr}
/* Belt-and-braces JS fallback (onerror="this.closest('.hero__inner').classList.add('yb-img-failed')")
   for browsers without :has() support. */
.yb-img-failed{grid-template-columns:1fr !important}
.yb-img-failed .hero__media{display:none}

/* ---------- Dynamic form: details step (compact multi-field screen) ---------- */
.yb-df__details{display:flex;flex-direction:column;gap:14px;margin-bottom:6px}
.yb-df__chip-row{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}
.yb-df__chip{border:1.5px solid #dbe1e8;background:#fff;border-radius:999px;padding:8px 14px;
  font-size:.88rem;font-weight:600;color:var(--navy);cursor:pointer}
.yb-df__chip:hover,.yb-df__chip:focus-visible{border-color:var(--gold);outline:none}
.yb-df__chip.is-selected{background:var(--navy);border-color:var(--navy);color:#fff}

/* Multi-select options (CP12 appliances) reuse .yb-df__option but need
   their own selected state distinct from single-select's auto-advance. */
.yb-df__option--multi.is-selected{border-color:var(--navy);background:var(--navy);color:#fff}

/* Repair-routing warning banner inside the contact step. */
.yb-df__notice{background:#FFF7E6;border:1px solid #F3D27A;border-radius:10px;padding:12px 14px;
  margin-bottom:16px;font-size:.92rem;color:var(--navy)}

/* v1.8.6.2 — non-editable "You're requesting: X" reassurance line, Step 3. */
.yb-df__confirm{font-size:.88rem;color:var(--text-grey);margin:0 0 14px;padding-bottom:10px;
  border-bottom:1px solid #eef1f5}
.yb-df__confirm strong{color:var(--navy)}

/* v1.8.6.1 — real consent checkbox (Step 3) + submission error state. */
.yb-df__field--consent{margin-bottom:14px}
.yb-df__consent-label{display:flex;align-items:flex-start;gap:10px;cursor:pointer;font-size:.9rem;
  color:var(--navy);line-height:1.4}
.yb-df__consent-label input[type="checkbox"]{width:20px;height:20px;flex-shrink:0;margin-top:1px;accent-color:var(--gold)}
.yb-df__field--consent.is-invalid .yb-df__consent-label{color:var(--red)}
.yb-df__field--consent.is-invalid .yb-df__consent-label input{outline:2px solid var(--red);outline-offset:2px}
.yb-df__submit.is-submitting{opacity:.7;cursor:wait}
.yb-df__submit-error{display:none;background:#FDEBEA;border:1px solid var(--red);border-radius:10px;
  padding:12px 14px;margin-top:12px;font-size:.9rem;color:var(--red)}
.yb-df__submit-error.is-visible{display:block}
/* v2.0.0 — showSubmissionError() moves focus here (role="alert",
   tabindex="-1") so a keyboard/screen-reader user lands on the error
   summary immediately; an explicit focus outline ensures that's visible
   even in browsers that suppress the default ring on script-focused,
   non-interactive elements. */
.yb-df__submit-error:focus{outline:2px solid var(--red);outline-offset:2px}
/* Phone fallback link appended inside the error message by sitePhoneLink(). */
.yb-df__submit-error a{color:var(--red);font-weight:700;text-decoration:underline}

/* ---------- Inline-mounted form (no modal chrome) ---------- */
.yb-df-inline{display:flex;flex-direction:column;gap:10px}
.yb-df-inline__head{display:flex;align-items:center;gap:8px}
.yb-df-inline__title{flex:1;font-size:1rem;margin:0;color:var(--navy)}
.yb-df-inline__step-text{font-size:.78rem;font-weight:700;color:var(--text-grey);white-space:nowrap}
.yb-df-inline .yb-df__progress{height:4px;background:#eef1f5;border-radius:2px;overflow:hidden}
.yb-df-inline .yb-df__progress-bar{display:block;height:100%;width:0%;background:var(--gold);transition:width .2s ease}
.yb-df-inline__body{padding-top:2px}
.yb-df-inline .yb-df__question{font-weight:800;color:var(--navy);font-size:1.05rem;margin:2px 0 12px}
.yb-df-inline .yb-df__option{padding:13px 14px;min-height:46px;font-size:.95rem}
.yb-df-inline .yb-df__field input{padding:11px 13px}

/* Compact trust strip near a conversion section (brief's TRUST STRIP spec) */
.yb-trust-compact{display:flex;flex-wrap:wrap;gap:10px 18px;font-size:.85rem;color:var(--text-grey);margin:14px 0}
.yb-trust-compact span{white-space:nowrap}

/* ==========================================================================
   v1.8.4 — "ONLY ONE VISIBLE ENQUIRY FORM" (audit fix)
   ========================================================================== */
/*
 * Every core/lightweight service page now has TWO WPForms instances in the
 * DOM: the visible, inline-mounted 3-step form near the top of the page
 * (the customer-facing UI), and a real embedded [wpforms id="..."] used
 * purely as the technical submission backend, which the inline form
 * populates and submits programmatically (see submitForm() in site.js).
 * That second instance must stay technically present/functional but be
 * invisible to a real visitor — this is that visual hiding, applied via a
 * class rather than `display:none` (which some form libraries treat as
 * "don't validate/submit") or deleting the markup (which would break the
 * JS handoff entirely).
 */
.yb-visually-hidden-form{
  position:absolute!important;
  width:1px!important;height:1px!important;
  padding:0!important;margin:-1px!important;
  overflow:hidden!important;
  clip:rect(0,0,0,0)!important;
  white-space:nowrap!important;
  border:0!important;
}

/* ==========================================================================
   v1.8.6 — PRICE→CTA IMMEDIATE: supporting copy moved out of the hero
   ========================================================================== */
/*
 * The .yb-convert-hero__finance-terms/__supporting/__inclusions paragraphs
 * used to sit inside the dark-navy hero (light text colours). v1.8.6 moved
 * them to a plain white section directly below the hero/form, per the
 * "nothing between price and CTA" fix — this context override gives them
 * readable dark-on-light colours in their new location without touching
 * their original (still-valid) styling for any future use inside the hero.
 */
.yb-post-hero-supporting{padding-top:0}
.yb-post-hero-supporting .yb-convert-hero__finance-terms{color:var(--text-grey)}
.yb-post-hero-supporting .yb-convert-hero__supporting{color:var(--text-grey);max-width:none}
.yb-post-hero-supporting .yb-convert-hero__inclusions{color:var(--navy)}

/* ==========================================================================
   v1.8.7 — HOMEPAGE SERVICE SELECTOR (replaces the old decorative hero)
   ========================================================================== */
/*
 * Background image (supplied boiler-room photo) with a navy overlay so the
 * image stays "recognisable but subdued" while text/cards stay highly
 * legible — per the brief. Deliberately NOT a tall hero: padding is
 * modest (compact on mobile, comfortable but not oversized on desktop),
 * and the cards themselves — not the image — are the dominant visual
 * element, sitting on solid white above the dark backdrop.
 */
.yb-home-selector{
  position:relative;
  background-image:linear-gradient(rgba(6,26,51,.88), rgba(6,26,51,.88)), url('../img/homepage-service-selector-bg.jpg');
  background-size:cover;
  background-position:center;
  background-repeat:no-repeat;
  padding:28px 0 32px;
}
.yb-home-selector__heading{
  color:#fff;
  text-align:center;
  font-size:clamp(1.6rem,6vw,2.4rem);
  margin:0 0 8px;
}
.yb-home-selector__sub{
  color:#dfe8f5;
  text-align:center;
  font-size:1rem;
  margin:0 auto 20px;
  max-width:44ch;
}
.yb-home-selector__grid{margin-top:0}

@media(min-width:920px){
  .yb-home-selector{padding:44px 0 48px}
  .yb-home-selector__sub{margin-bottom:26px}
}

/* ==========================================================================
   v1.9.0 — GLOBAL DESIGN SYSTEM (Stage 2)

   Everything below is additive: it layers new tokens and rebuilt header /
   navigation / footer / button / card rules on top of the file above via
   normal cascade order (later rule of equal specificity wins), the same
   pattern every prior versioned block in this file already uses. Nothing
   above this line was deleted. Scope is strictly global chrome — no
   individual page content, hero, or form markup is touched here.

   Colour values are UNCHANGED from the existing :root block above (they
   already matched the approved navy/gold/white identity exactly) — this
   section only adds the small set of SUPPORTING tokens the brief asks for
   (borders, muted text, card shadow, focus ring, overlay, hover/active)
   plus a spacing/typography/radius scale, then rebuilds header, nav,
   footer and the button/card system on top of them.
   ========================================================================== */

:root{
  /* --- Supporting tokens (additive; --navy/--gold/etc. above are untouched) --- */
  --border:#DCE3EC;
  --border-strong:#C6D0DC;
  --muted:#6B7684;
  --overlay:rgba(3,17,32,.55);
  --focus-ring:#8FB4E8;
  --hover-tint:rgba(6,26,51,.06);
  --active-tint:rgba(6,26,51,.10);
  --shadow-md:0 10px 28px rgba(6,26,51,.14);
  --touch:44px;

  /* --- Spacing scale --- */
  --space-3xs:4px;
  --space-2xs:8px;
  --space-xs:12px;
  --space-sm:16px;
  --space-md:24px;
  --space-lg:32px;
  --space-xl:48px;
  --space-2xl:64px;

  /* --- Radius scale (­--radius above stays the general default) --- */
  --radius-sm:6px;
  --radius-lg:14px;
  --radius-pill:999px;

  /* --- Content widths --- */
  --maxw-wide:1240px;

  /* --- Header heights (see YB-1.9.0-01 in CHANGED-FILES.md re: the logo
     width/header-height trade-off; raised in v1.9.1 to fit the enlarged
     logo — see the v1.9.1 correction notes further down this file) --- */
  --header-h-desktop:88px;
  --header-h-mobile:70px;
  --sticky-h:58px; /* v1.9.1: named so the sticky-bar height and the body
    bottom-clearance calc() that protects footer content from it (Correction
    6) can never drift apart — see .sticky-cta and the max-width:1399.98px
    block further down this file. */
  --header-maxw-desktop:1280px; /* v1.9.1: header-only, 40px wider than the
    shared --maxw-wide (1240px) — recovers room in the nav track for the
    enlarged logo/dropdown toggles without touching --maxw-wide itself,
    which the footer's legal row also relies on. See the FINDING comment at
    the @media(min-width:1400px) header-bar rule further down this file. */

  /* --- Type scale (base sizes; .hero h1 and other page-hero overrides
     further down the file are intentionally left untouched) --- */
  --fs-h1:clamp(1.9rem,1.5rem + 1.8vw,2.75rem);
  --fs-h2:clamp(1.5rem,1.25rem + 1.1vw,2.05rem);
  --fs-h3:clamp(1.15rem,1.05rem + .5vw,1.4rem);
  --fs-body:1rem;
  --fs-small:.9rem;
  --fs-label:.78rem;
  --fs-button:1rem;
  --fs-nav:.95rem;
  --fs-price:1.15rem;
  --lh-tight:1.2;
  --lh-normal:1.6;
  --fw-regular:400;
  --fw-semibold:600;
  --fw-bold:700;
  --fw-extrabold:800;
}

/* ---------- Base type scale (global, non-hero) ---------- */
h1{font-size:var(--fs-h1);line-height:var(--lh-tight)}
h2{font-size:var(--fs-h2);line-height:var(--lh-tight)}
h3{font-size:var(--fs-h3);line-height:var(--lh-tight)}
body{font-size:var(--fs-body)}
.lead{font-size:1.08rem;max-width:72ch}
/* Deliberately NOT a blanket p{max-width} rule: this theme's ~150 existing
   pages use paragraphs inside grids, cards and multi-column layouts where a
   flat character-count cap would cause unpredictable rewrapping — that is
   individual-page-content risk, out of scope this stage. The 65-72ch
   measure is applied only to .lead (page intros) here; the brief's
   "readable paragraph width" requirement is otherwise satisfied by the
   existing --maxw content container (1180px) each page already renders in. */

/* ==========================================================================
   Button system — extends the existing .btn / .btn--primary / .btn--secondary
   / .btn--ghost classes already used across every page, rather than
   replacing them. New additions: a light/outline variant for dark
   backgrounds, a compact header CTA, a directional text link, disabled
   state, and a guaranteed 44px touch target. Every existing data-yb-*,
   tracking and modal attribute on any .btn element is untouched by this
   stage — only visual rules are added here.
   ========================================================================== */
.btn{min-height:var(--touch);font-family:var(--font)}
.btn:active{transform:translateY(0);filter:brightness(.96)}
.btn[disabled],.btn.is-disabled{opacity:.55;cursor:not-allowed;pointer-events:none;transform:none}
.btn--white{background:#fff;color:var(--navy);border-color:#fff}
.btn--white:hover{background:var(--off-white)}
.btn--outline-light{background:transparent;color:#fff;border-color:rgba(255,255,255,.7)}
.btn--outline-light:hover{background:rgba(255,255,255,.12);color:#fff}
.btn--sm{padding:10px 16px;font-size:.92rem;min-height:40px}
.btn--header{padding:11px 18px;font-size:.92rem;min-height:40px;border-radius:var(--radius-sm);
  white-space:nowrap;box-shadow:none}
.btn--header:hover{transform:none;box-shadow:var(--shadow-sm)}
.btn--text{display:inline-flex;align-items:center;gap:6px;background:none;border:0;padding:4px 2px;
  color:var(--navy);font-weight:700;min-height:auto}
.btn--text::after{content:"→";transition:transform .15s ease}
.btn--text:hover::after{transform:translateX(3px)}
.btn--text:hover{background:none;text-decoration:underline;transform:none}
@media(prefers-reduced-motion:reduce){
  .btn,.btn--text::after{transition:none}
}

/* ==========================================================================
   Card system — new, restrained, reusable component classes. These are not
   yet applied to any existing page markup (that is individual-page work,
   out of scope this stage); they are available for Stage 3+ to adopt.
   ========================================================================== */
.yb-card{
  background:#fff;border:1px solid var(--border);border-radius:var(--radius);
  padding:var(--space-md);box-shadow:var(--shadow-sm);
}
.yb-card:focus-within,.yb-card:hover{box-shadow:var(--shadow)}
.yb-card--service{display:flex;flex-direction:column;gap:var(--space-2xs);text-align:left}
.yb-card--trust{text-align:center;padding:var(--space-sm)}
.yb-card--pricing{border-color:var(--gold);border-width:2px}
.yb-card--pricing .yb-card__price{font-size:var(--fs-price);font-weight:var(--fw-extrabold);color:var(--navy)}
.yb-card--selectable{cursor:pointer;transition:transform .14s ease,box-shadow .14s ease}
.yb-card--selectable:hover,.yb-card--selectable:focus-visible{transform:translateY(-2px);box-shadow:var(--shadow)}
.yb-card--selectable:focus-visible{outline:3px solid var(--focus-ring);outline-offset:2px}
.yb-card--dark{background:var(--navy);color:#dbe4ef;border-color:var(--navy-dark)}
.yb-card--dark h3{color:#fff}
@media(prefers-reduced-motion:reduce){
  .yb-card--selectable{transition:none}
}

/* ==========================================================================
   v1.9.0 — HEADER, NAVIGATION, MOBILE DRAWER, FOOTER (Stage 2)

   Overrides/extends the header, nav and footer rules earlier in this file
   via normal cascade (later, equal-or-higher specificity wins) — nothing
   above this block is deleted. The desktop nav breakpoint moves from
   1280px to 1360px in this section only (see the Stage 2 report: the
   approved logo's ~3:1 aspect ratio plus the new header CTA button need
   the extra width to avoid the v1.8.4 overlap bug reappearing).

   v1.9.1 (Prompt 2.1 — visual corrections): the desktop logo is enlarged
   here (~172px -> ~209px rendered width, same intrinsic aspect ratio) and
   the breakpoint below is raised again, 1360px -> 1400px, because the
   larger logo leaves less room for the nav before it would start crowding
   the phone number / Get a Quote button at 1360-1399px. Header height rises
   from 84px to 88px (--header-h-desktop, within the 86-90px target) to fit
   the taller logo without the header looking stretched. Mobile logo goes
   47px -> 52px tall (~140px -> ~155px wide) and --header-h-mobile 66px ->
   70px to match. Nothing else in this block changed.
   ========================================================================== */

/* ---------- Header shell ---------- */
.header-bar{
  max-width:var(--maxw-wide);
  min-height:var(--header-h-mobile);
  padding:9px 20px; /* v1.9.1: 11px -> 9px, keeps mobile header compact at the taller 52px logo */
  column-gap:var(--space-md);
}
.site-header .brand{display:block;line-height:0}
/* v1.9.1: selector strengthened to `.site-header .header-logo .brand__img`
   (three classes) specifically to OUTWEIGH the legacy `.header-logo .brand
   img` rule near the top of this file (two classes + the bare "img" type
   selector) — see the FINDING comment there. Without this the enlargement
   below would have no visible effect, exactly as in v1.9.0. */
.site-header .header-logo .brand__img{height:52px;width:auto;display:block} /* v1.9.1: was governed by the 42px legacy rule; now 52px (~155px wide) */
/* v1.9.2 (Correction — paid-landing logo distortion, ROOT CAUSE CONFIRMED):
   header-landing.php's <a class="brand"> has NO `.header-logo` wrapper div
   (unlike header.php), so the two rules below were the ONLY CSS anywhere in
   this file matching the paid-landing `.brand__img` — and neither set
   `width`. The <img> itself carries HTML `width="620" height="208"`
   (intrinsic 620x208, ratio ~2.98:1) for CLS purposes. With `height` set by
   CSS but no CSS `width`, the browser fell back to the HTML width="620"
   attribute as the used value while height stayed at the small CSS value,
   stretching the logo horizontally to a measured 620x48px (ratio ~12.92:1)
   at 1024px — confirmed empirically with the Playwright harness before this
   fix was written. Fix: set `width:auto` explicitly (so the box is derived
   from height + intrinsic ratio, not the HTML attribute), plus
   `max-width:100%` and `object-fit:contain` as belt-and-suspenders so the
   image can never stretch even if a future ancestor constrains its box.
   Selector also duplicated onto `.header-bar--landing .brand__img` (no
   `body.paid-landing` dependency) for the same reason Correction 7 in
   v1.9.1 duplicated the header-bar layout fix: guaranteed to apply
   regardless of body_class() output on any page/plugin/cache context. Only
   `assets/css/style.css` changed for this fix — header-landing.php's
   markup was inspected and does not contribute to the distortion, so it was
   left untouched. */
body.paid-landing .site-header .brand__img,
.header-bar--landing .brand__img{height:40px;width:auto;max-width:100%;object-fit:contain}
@media(min-width:640px){
  body.paid-landing .site-header .brand__img,
  .header-bar--landing .brand__img{height:48px;width:auto}
}
/* v1.9.2 (SUPERSEDED this round — see v1.9.3 note below): measured with the
   test harness (getBoundingClientRect, not visual inspection) — at 320px and
   360px the fixed-width, non-shrinking Call button (.header-bar--landing
   .btn, flex-shrink:0, ~204px wide including its icon+label, a v1.9.1
   Correction-7 rule left untouched this round) plus the 16px gap left only
   ~59px (320px) / ~99px (360px) of flex space for the logo. Below 40px
   height, the intrinsic-ratio-derived width (~119px) exceeded that space,
   so the flex item was being forced to shrink narrower than its height
   implied — which broke width:auto's ratio guarantee just as surely as the
   original bug, only inside the flex algorithm instead of the img-sizing
   algorithm. v1.9.2 fixed that by reducing the logo to 16px/30px tall at
   these two bands — ratio-correct, but too small to read as the company
   identity (Prompt 2.3 finding).

   v1.9.3 — NARROW-MOBILE CORRECTION. The 16px/30px rules below are REMOVED
   (not present anywhere below this comment) and replaced with the block
   further down that keeps the logo at a legible ~38px tall below 390px.
   The compression bug they were working around is fixed differently this
   round, at its actual source: `.header-bar--landing .brand` (the flex item
   containing the logo) now gets `flex:0 0 auto;min-width:0` so it is never
   flex-shrunk below its content size in the first place, and the Call
   button is deliberately narrowed (not left at its ~204px desktop width) so
   the two together comfortably fit — see the `.header-bar--landing
   .landing-call` narrow-width rule below. This means the logo can stay at a
   legible height instead of being shrunk to fit around an oversized button. */
@media(min-width:1400px){ /* v1.9.1: breakpoint raised 1360px -> 1400px, see block comment above */
  /* v1.9.1 FINDING: measuring the nav's own container box (as the Stage 2
     testing did) looked collision-free, but the actual last link ("Areas")
     was overflowing OUTSIDE that box by 50-85px at every width from 1400 to
     1920 — invisible unless you measure the link itself, not its container.
     Root cause: --maxw-wide (1240px) caps the header's total width, so
     nav's 1fr track never exceeds ~665px regardless of viewport, while the
     6-item nav (now with two 30px dropdown toggles, up from 22px) needs
     ~646px of links alone; the old vw-scaling gap (clamp(10px,1vw,22px))
     made this WORSE at wider screens instead of better, since it kept
     growing after the header itself stopped growing. This was very likely
     already marginal/overflowing in v1.9.0 too, just not caught because
     verification measured the same container box. Fixed with a header-only
     max-width (doesn't touch the shared --maxw-wide used by the footer) and
     three fixed (no longer viewport-scaling) spacing reductions — see the
     three declarations below and the .yb-nav-list/.header-actions rules
     further down. Re-verified: ~21px of clear margin at every tested width
     from 1400 to 1920, not just a container-level "no overlap". */
  .header-bar{min-height:var(--header-h-desktop);padding:9px 24px;max-width:var(--header-maxw-desktop);column-gap:20px} /* v1.9.1: 13px -> 9px vertical; max-width 1240->1280px (header-only); column-gap 24->20px, all to recover room for the enlarged logo + dropdown toggles */
  .site-header .header-logo .brand__img{height:70px} /* v1.9.1: was governed by the 42px legacy rule; now 70px (~209px wide, within the 205-215px target) */
  .header-actions{gap:12px} /* v1.9.1: 16px -> 12px */
}

/* CONFIRMED PRE-EXISTING BUG (present before v1.9.0, not introduced by this
   stage): .header-bar's base rule is `display:grid;grid-template-columns:
   auto 1fr auto` (three tracks, for the standard header's logo/nav/actions).
   header-landing.php only ever renders TWO children (brand + Call button),
   so the button lands in the wide "1fr" middle track and stretches to fill
   it edge-to-edge. In scope this stage under "PAID-LANDING HEADER: apply
   the new type, spacing, colour and button system" — fixed here by giving
   the simpler landing header its own flex layout instead of the 3-column
   grid. No markup, destination, or tracking attribute changed.

   v1.9.1 (Correction 7): this fix relied only on `body.paid-landing`, whose
   presence depends on body_class() output on whatever page loads this
   header — not guaranteed identical on every page/plugin/cache context.
   header-landing.php now also writes a `header-bar--landing` class directly
   in its own markup (see that file), so the same flex layout applies
   deterministically to every page that includes this header, regardless of
   body classes. Both selectors are kept (redundant, harmless) rather than
   removing the body.paid-landing one. */
body.paid-landing .header-bar,
.header-bar--landing{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}
body.paid-landing .header-bar .btn,
.header-bar--landing .btn{flex-shrink:0;flex-grow:0;width:auto;min-width:190px} /* controlled min-width per spec; no max-width — the Call label must never clip, and flex (not grid/1fr) already stops it stretching */

/* v1.9.3 (Prompt 2.3 — NARROW-MOBILE PAID-LANDING HEADER CORRECTION): below
   390px the full "Call 0333 242 1490" button (~204px) plus a legible-height
   logo cannot both fit in a single row without the logo being crushed (the
   exact v1.9.2 trade-off this corrects). Fix narrows the button instead —
   visible label shortens to "Call Now" and the button's own min/max-width
   shrink to fit — while the logo grows back to a legible ~38px tall
   (~113px wide, matching its ~2.98:1 intrinsic ratio) and its flex item is
   pinned to its content size so it can never be compressed again.

   .header-bar--landing .brand gets flex:0 0 auto + min-width:0 so it is
   never flex-shrunk (root cause of the v1.9.2 16px/30px sizes — see the
   comment above the logo rules). .brand__img itself gets an explicit
   height, width:auto, max-width:none (no % cap needed once its flex
   parent can't shrink it) and flex-shrink:0 (harmless — img is not itself
   a flex item here, .brand is, but this keeps the box-sizing intent
   explicit if the markup ever changes).

   The visible "Call Now" label is CSS-generated (::after), NOT a second
   real <span> — see header-landing.php's v1.9.3 comment for why: site.js's
   click-tracking reads the anchor's `textContent` verbatim for the
   `phone_click` event's `link_text`, and generated content is never part
   of `textContent`. Using a real second span (as a literal, simplified
   sketch of this fix might suggest) would silently change what every
   phone-click event reports at ALL widths, not just narrow ones — exactly
   the kind of tracking regression this project has repeatedly guarded
   against. `.landing-call__full` is hidden with the theme's existing
   visually-hidden technique (matches `.yb-visually-hidden-form` elsewhere
   in this file) rather than `display:none`, so it stays in the layout flow
   as an accessibility no-op — belt-and-suspenders alongside the anchor's
   own `aria-label`, which remains the sole authoritative accessible name
   at every width either way. */
@media(max-width:389.98px){
  body.paid-landing .site-header .brand__img,
  .header-bar--landing .brand__img{
    height:38px;width:auto;max-width:none;object-fit:contain;flex-shrink:0;
  }
  .header-bar--landing .brand{flex:0 0 auto;min-width:0}
  body.paid-landing .header-bar .landing-call,
  .header-bar--landing .landing-call{
    width:auto;min-width:108px;max-width:120px;min-height:48px;
    padding:12px 10px;gap:6px;flex:0 0 auto;
  }
  .landing-call__full{
    position:absolute;width:1px;height:1px;padding:0;margin:-1px;
    overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;
  }
  .landing-call::after{content:"Call Now"}
}

/* ---------- Desktop nav + actions: three tiers (PROMPT 24) ----------
 * Base state below is the narrowest/compact one (mobile-first); each
 * @media(min-width) block progressively widens what's shown as the
 * viewport grows, so nothing ever has to be "re-hidden" by a later,
 * narrower rule — removing the earlier correction-round pattern of a
 * min-width block and a separate max-width block each re-asserting the
 * opposite of the other (a real source of the "which one actually wins"
 * confusion the dead 1280px rule above left behind).
 *
 * Tier 1 (<1180px) — compact header: Logo | Call | Menu, mobile drawer,
 *   sticky bottom CTA bar. Unchanged from the previous single compact tier,
 *   just renamed/renumbered now that a second, wider compact-ish tier
 *   exists above it.
 * Tier 2 (1180px–1399.98px) — PROMPT 24 new tier. The full nav and the
 *   gold "Get a Quote" CTA both comfortably fit this width (the header-bar
 *   is already capped at --header-maxw-desktop/1280px wide and centred —
 *   see the >=1400px tier below — so nav+CTA together need no more room
 *   here than they already use inside that same 1280px cap), but the
 *   phone number is the first thing dropped as the viewport narrows, per
 *   the live-site header-overlap correction brief: "hide the phone number
 *   before any overlap occurs; keep the gold CTA if space permits."
 *   Nothing here lets the full nav + phone + CTA combination render below
 *   1400px — only nav + CTA, with the phone number hidden.
 * Tier 3 (>=1400px) — wide desktop: full nav, phone number and CTA all
 *   shown together (unchanged from the previous 1360px -> 1400px history
 *   documented above).
 */
.header-navigation,.header-actions{display:none}
.header-mobile-actions{display:flex}
.menu-toggle{display:inline-flex}
body{padding-bottom:calc(var(--sticky-h) + env(safe-area-inset-bottom) + 20px)}
.sticky-cta{display:grid}
/* .header-navigation and .header-actions are both display:none in this
   base (<1180px) state, so the header-bar grid's 3rd ("auto") column and
   its column-gap would otherwise be reserved for nothing — that wasted
   space was part of why the enlarged mobile logo collided with Call/Menu
   at 320px (Correction 1/2, carried over unchanged). Two real tracks is
   enough here. */
.header-bar{grid-template-columns:auto 1fr}

@media(min-width:1180px){ /* Tier 2 starts: nav + CTA, phone hidden */
  .header-navigation{display:block}
  .header-actions{display:flex;align-items:center;gap:calc(var(--space-sm) - 4px)}
  .header-phone{display:none}
  .header-mobile-actions{display:none}
  .menu-toggle{display:none}
  body{padding-bottom:0}
  .sticky-cta{display:none}
  .header-bar{grid-template-columns:auto 1fr auto}
}

@media(min-width:1400px){ /* Tier 3 starts: phone reappears alongside nav + CTA */
  .header-actions{gap:var(--space-sm)}
  .header-phone{display:inline-flex}
}
/* v1.9.1 (Correction 1/2 follow-up): even after the grid fix above, the
   full 155px-wide logo still overlaps the Call/Menu controls at the
   narrowest tested width (320px only — 360px and up have a comfortable
   margin). The brief explicitly allows the complete logo to run slightly
   narrower than the 145-165px target "where it fits" rather than forcing
   the emblem-only crop; it is still the full logo, unrearranged, just
   ~131px wide here. Call/Menu padding is tightened slightly too (both stay
   above the 44px WCAG touch-target minimum via min-height:48px, untouched). */
@media(max-width:359.98px){
  .site-header .header-logo .brand__img{height:44px}
  .menu-toggle,.icon-btn--call{padding:10px 10px}
  .header-mobile-actions{gap:6px}
}

/* ---------- Desktop nav list + accessible dropdowns ---------- */
/* The original .header-navigation rule (earlier in this file) sets
   overflow:hidden to stop long nav content breaking the grid column —
   that would also clip every dropdown panel below it, so it's relaxed
   here now that dropdowns need to render outside the header row. */
.header-navigation{overflow:visible}
.nav-desktop .yb-nav-list{display:flex;align-items:center;gap:10px;flex-wrap:nowrap} /* v1.9.1: was clamp(10px,1vw,22px) — the vw-scaling grew the gap at WIDER viewports even though the header's own max-width caps the nav track's actual size there, making the overflow finding above worse, not better, at large screens. Fixed 10px throughout. */
.nav-desktop li{position:relative}
.nav-desktop > .yb-nav-list > li{display:flex;align-items:center}
.nav-desktop a{font-weight:var(--fw-semibold);font-size:var(--fs-nav);color:var(--navy);white-space:nowrap}
.nav-desktop > .yb-nav-list > li > a{padding:8px 2px}
.nav-desktop .yb-nav-parent{cursor:pointer}

/* Toggle button injected by site.js next to any parent item's link.
   Kept small and restrained — this is the "adjacent toggle button" the
   brief asks for, not a redesign of the link itself. */
/* v1.9.1 (Correction 3): control area enlarged 22px -> 30px (spec: ~28-32px),
   corner radius rounded toward a pill so the hover/focus tint reads as a
   restrained circular tap target rather than a hard grey square; the SVG
   itself was fixed in site.js (square viewBox, was distorting on rotate). */
.yb-subnav-toggle{
  display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;margin-left:2px;padding:0;
  background:none;border:0;border-radius:var(--radius-pill);
  color:var(--navy);cursor:pointer;flex-shrink:0;
}
.yb-subnav-toggle:hover{background:var(--hover-tint)}
.yb-subnav-toggle:focus-visible{outline:3px solid var(--focus-ring);outline-offset:1px}
.yb-subnav-toggle svg{width:13px;height:13px;transition:transform .15s ease}
.menu-item-has-children.is-open > .yb-subnav-toggle svg{transform:rotate(180deg)}
@media(prefers-reduced-motion:reduce){
  .yb-subnav-toggle svg{transition:none}
}
/* Once JS has enhanced a menu (added the toggle button), hide the old
   decorative ::after arrow so it isn't shown twice. */
.nav-desktop .menu-item-has-children.yb-enhanced > a::after{display:none}

.nav-desktop .sub-menu{
  display:none;position:absolute;top:100%;left:0;margin-top:6px;min-width:240px;max-width:252px;
  background:#fff;border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:var(--shadow-md);padding:8px;z-index:960;
  align-items:stretch; /* overrides the old .header-navigation ul{align-items:center}
                           rule, which would otherwise centre each dropdown item */
}
/* v1.9.1 (Correction 4): the Repairs & Servicing panel (6 children, incl.
   the longer "Air Source Heat Pump Servicing" label) previously had no
   max-width, so it grew to fit that label on one unwrapped line — wider
   than the Heating & Heat Pumps panel (5 shorter children) and reading as
   visually inconsistent between the two dropdowns. Widened + capped here
   so the long label wraps to two left-aligned lines instead (per spec)
   and both panels read as one consistent system. Matched structurally via
   :has() (a 6th child = the Repairs group) rather than nth-child position
   or hardcoded text, so it keeps working if the item order or source (real
   WP menu vs. fallback) changes; browsers without :has() simply keep the
   240-252px base width, which still fully wraps and displays correctly. */
.nav-desktop .sub-menu:has(li:nth-child(6)){min-width:255px;max-width:275px}
.nav-desktop .menu-item-has-children.is-open > .sub-menu,
.nav-desktop .menu-item-has-children:hover > .sub-menu,
.nav-desktop .menu-item-has-children:focus-within > .sub-menu{display:flex;flex-direction:column}
.nav-desktop .sub-menu--align-right{left:auto;right:0}
.nav-desktop .sub-menu a{padding:9px 10px;border-radius:var(--radius-sm);font-weight:var(--fw-regular);
  display:block;width:100%;text-align:left;white-space:normal;line-height:1.35}
.nav-desktop .sub-menu a:hover,.nav-desktop .sub-menu a:focus-visible{background:var(--hover-tint);text-decoration:none}
.nav-desktop a[aria-current="page"],.nav-mobile a[aria-current="page"]{color:var(--gold)}
.nav-desktop a:focus-visible,.nav-mobile a:focus-visible{outline:3px solid var(--focus-ring);outline-offset:2px;border-radius:4px}

/* ---------- Mobile drawer ---------- */
.nav-mobile{padding:20px}
.nav-mobile .brand{display:block;margin-bottom:6px}
/* PROMPT 10 (§14): reversed/light logo sizing for the navy drawer background.
   max-width reserves clearance from the absolutely-positioned .close button
   (top:12px;right:16px) so the wordmark can never run underneath it, and the
   image keeps its own aspect ratio via width/height attributes + height:auto. */
.nav-mobile__brand{display:block;margin:2px 46px 10px 0}
.nav-mobile__logo-img{height:56px;width:auto;max-width:100%;display:block}
.nav-mobile h2{font-size:var(--fs-label)}
.nav-mobile .yb-nav-parent{background:none;border:0;width:100%;text-align:left;font:inherit;color:inherit;cursor:pointer}
.nav-mobile a,.nav-mobile .yb-nav-parent{min-height:var(--touch);display:flex;align-items:center}
.nav-mobile .menu-item-has-children > a,
.nav-mobile .menu-item-has-children > .yb-nav-parent{display:flex;align-items:center;justify-content:space-between}
.nav-mobile a:focus-visible,.nav-mobile .yb-nav-parent:focus-visible{outline:3px solid var(--gold-light);outline-offset:-2px}

/* [inert] fallback for browsers that don't yet support the attribute
   natively — site.js only sets it on the background wrapper while the
   drawer is open, so this rule is inert (no pun intended) the rest of
   the time. */
[inert]{pointer-events:none !important}

/* ---------- Footer: four columns + logo plate + legal row ---------- */
.footer-top{grid-template-columns:1fr;gap:var(--space-xl) var(--space-lg)}
.footer-logo-plate{
  display:inline-block;background:#fff;padding:10px 16px;border-radius:var(--radius-sm);
  border:1px solid rgba(255,255,255,.12);margin-bottom:var(--space-sm);line-height:0;
}
.footer-logo-plate img{height:40px;width:auto;display:block}
.footer-legal-name{color:#fff;font-weight:var(--fw-bold);margin-bottom:6px}
.footer-brand img{margin-bottom:0} /* supersedes the old flat .footer-brand img rule now that the logo lives in .footer-logo-plate */
.footer-col h3{font-size:var(--fs-label);text-transform:uppercase;letter-spacing:.06em}
.footer-legal-row{
  /* v1.9.1: margin-top 32px->24px, padding-top 24px->16px (Correction 8) */
  max-width:var(--maxw-wide);margin:var(--space-md) auto 0;padding:var(--space-sm) 18px 0;
  border-top:1px solid rgba(255,255,255,.1);
  display:flex;flex-wrap:wrap;gap:8px 20px;
}
.footer-legal-row ul{display:flex;flex-wrap:wrap;gap:8px 20px}
.footer-legal-row a{color:#9fb0c4;font-size:var(--fs-small)}
.footer-legal-row a:hover,.footer-legal-row a:focus-visible{color:var(--gold);text-decoration:none}
@media(min-width:680px){
  .footer-top{grid-template-columns:1.3fr 1fr 1fr 1fr}
}
@media(min-width:1040px){
  .footer-top{grid-template-columns:1.4fr 1fr 1fr 1fr;gap:var(--space-xl)}
}

/* ==========================================================================
   v1.9.1 (Prompt 2.1, Correction 5) — MOBILE FOOTER ACCORDIONS

   Progressive enhancement: footer.php renders every group's toggle button
   with aria-expanded="true" and its panel fully visible by default, so a
   visitor with JavaScript disabled (or before assets/js/site.js runs) sees
   every link exactly as in v1.9.0 — nothing is hidden by CSS alone. The
   .is-collapsed class below is only ever added by site.js, and only below
   the footer's own 680px single-column breakpoint (see .footer-top above).
   At 680px and up the toggle is inert (site.js sets tabindex="-1" and
   never collapses it there) and reads visually as a plain heading — the
   existing four-column footer is otherwise untouched.

   The chevron intentionally reuses the same square-viewBox SVG as the
   Correction-3 desktop dropdown toggle (rather than the mobile nav
   drawer's older "+"/"−" glyphs) since both are new/changed in this same
   correction round and this keeps their icon language consistent.
   ========================================================================== */
.footer-accordion-heading{margin:0}
.footer-accordion-toggle{
  all:unset;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;
  width:100%;cursor:pointer;color:#fff;font-size:var(--fs-label);font-weight:var(--fw-bold);
  text-transform:uppercase;letter-spacing:.06em;padding:6px 0;min-height:var(--touch);
}
.footer-accordion-toggle:focus-visible{outline:3px solid var(--focus-ring);outline-offset:2px;border-radius:4px}
.footer-accordion-chevron{width:14px;height:14px;flex-shrink:0;margin-left:8px;color:#9fb0c4;transition:transform .15s ease}
.footer-accordion-toggle[aria-expanded="true"] .footer-accordion-chevron{transform:rotate(180deg)}
.footer-accordion-panel.is-collapsed{display:none}
@media(max-width:679.98px){
  .footer-col--accordion{border-top:1px solid rgba(255,255,255,.12);padding-top:var(--space-xs)}
  .footer-col--accordion .footer-accordion-panel{padding-top:var(--space-2xs)}
}
@media(min-width:680px){
  /* Plain heading again at tablet/desktop — site.js also sets tabindex="-1"
     and forces aria-expanded="true"/removes .is-collapsed at this width. */
  .footer-accordion-toggle{cursor:default}
  .footer-accordion-chevron{display:none}
}
@media(prefers-reduced-motion:reduce){
  .footer-accordion-chevron{transition:none}
}

/* ==========================================================================
   v2.1.0 (PROMPT 4 — HOMEPAGE CONVERSION REDESIGN)
   Every new selector below is either unique to the rebuilt front-page.php
   markup (the .yb-home-* prefix) or a new MODIFIER class added alongside
   an existing shared component (.need-box, .card, .btn, .trust-mini,
   .cta-band) — no existing shared selector's base definition is changed,
   so no other page's layout is affected by anything in this block. All
   colours, spacing, radii and shadows below reuse the existing v1.9.0
   design tokens (--navy/--gold/--white/--radius/--shadow/etc.) rather
   than introducing new ones.
   ========================================================================== */

/* ---------- 1-3. Hero (photo background desktop/tablet, stacked block+photo mobile) ---------- */
.yb-home-hero{
  position:relative;
  overflow:hidden;
  display:flex;
  flex-direction:column;
  background:var(--navy);
}
.yb-home-hero__media{
  position:relative;
  order:2;
  width:100%;
  aspect-ratio:820/941;
}
.yb-home-hero__media img{
  width:100%;height:100%;object-fit:cover;object-position:center top;display:block;
}
.yb-home-hero__scrim{
  display:none; /* only needed once the photo sits BEHIND the text at tablet/desktop widths */
}
.yb-home-hero__inner{
  position:relative;
  order:1;
  z-index:1;
  max-width:var(--maxw);
  margin:0 auto;
  width:100%;
  padding:28px 20px 24px;
  color:#fff;
}
.yb-home-hero__eyebrow{
  color:var(--gold-light);font-weight:800;font-size:.78rem;letter-spacing:.04em;
  text-transform:uppercase;margin:0 0 8px;
}
.yb-home-hero__h1{
  color:#fff;font-size:clamp(1.6rem,6vw,2.3rem);line-height:1.16;margin:0 0 12px;
}
.yb-home-hero__offer{
  font-weight:800;color:#fff;font-size:clamp(1.15rem,4.4vw,1.5rem);margin:0 0 8px;line-height:1.25;
}
.yb-home-hero__offer span{color:var(--gold-light)}
.yb-home-hero__supporting{
  font-size:.98rem;color:#dfe8f5;margin:0 0 18px;max-width:46ch;
}
.yb-home-hero__cta{margin:0 0 12px}
.yb-home-hero__cta .btn{width:100%}
.yb-home-hero__reassurance{
  font-size:.82rem;color:#cdd9ea;margin:0;
}

@media(min-width:768px){
  .yb-home-hero{
    display:block; /* photo becomes an absolutely-positioned background layer again */
    min-height:clamp(420px,56vw,620px);
  }
  .yb-home-hero__media{
    position:absolute;inset:0;order:0;width:100%;height:100%;aspect-ratio:auto;
  }
  .yb-home-hero__media img{object-position:center center}
  .yb-home-hero__scrim{
    display:block;position:absolute;inset:0;
    /*
     * v2.1.0 correction (screenshot-harness testing at 768px found the
     * previous stops — 92%/82%/35%/5% opacity at 0/32/58/78% — let hero
     * copy run into the low-opacity fade zone on narrower tablet widths,
     * where the text sat directly over the bright white van body with
     * insufficient contrast. The dark zone is widened and the fade holds
     * more opacity for longer, verified visually at 768/1024/1366/1440/
     * 1920px after this change (see the Stage 4 report's image/contrast
     * verification section).
     */
    background:linear-gradient(90deg,rgba(6,26,51,.94) 0%,rgba(6,26,51,.9) 40%,rgba(6,26,51,.55) 62%,rgba(6,26,51,.1) 85%);
  }
  .yb-home-hero__inner{
    padding:0 32px;height:100%;min-height:clamp(420px,56vw,620px);
    display:flex;flex-direction:column;justify-content:center;
  }
  .yb-home-hero__inner{max-width:var(--maxw)}
  .yb-home-hero__eyebrow,.yb-home-hero__h1,.yb-home-hero__offer,.yb-home-hero__supporting,.yb-home-hero__cta,.yb-home-hero__reassurance{
    /* Narrower than the 1024px+ column so copy stays inside the gradient's
       solid-dark zone at 768-1023px tablet widths (see the note above). */
    max-width:400px;
  }
  .yb-home-hero__cta{display:flex;gap:14px;flex-wrap:wrap}
  .yb-home-hero__cta .btn{width:auto}
}
@media(min-width:1024px){
  .yb-home-hero__h1{font-size:clamp(2rem,3.6vw,2.6rem)}
  .yb-home-hero__offer{font-size:clamp(1.35rem,2.4vw,1.7rem)}
  .yb-home-hero__eyebrow,.yb-home-hero__h1,.yb-home-hero__offer,.yb-home-hero__supporting,.yb-home-hero__cta,.yb-home-hero__reassurance{
    max-width:560px;
  }
}

/* ---------- 4. Trust strip (reuses .trust-mini as-is; no override needed) ---------- */

/* ---------- 5. Four primary problem cards (reuses .need-grid/.need-box) ---------- */
.yb-home-primary__sub{color:var(--text-grey);margin-top:-6px;margin-bottom:22px}
.yb-home-primary__icon{display:inline-flex;width:34px;height:34px;color:var(--gold);margin-bottom:8px}
.yb-home-primary__icon svg{width:100%;height:100%}
.yb-home-primary__copy{font-size:.9rem;color:var(--text-grey);margin:2px 0 12px}
.yb-home-primary__card--featured{
  border-color:var(--gold);
  box-shadow:0 8px 22px rgba(215,165,58,.18);
}
@media(min-width:920px){
  .yb-home-primary__card--featured{transform:translateY(-4px)}
}

/* ---------- 6. Additional services (compact link list, deliberately lighter weight than the 4 primary cards) ---------- */
.yb-home-more__list{
  display:grid;grid-template-columns:1fr;gap:2px;
  max-width:760px;margin:18px auto 0;
  border:1px solid var(--grey-light);border-radius:var(--radius);overflow:hidden;background:#fff;
}
.yb-home-more__list li{border-bottom:1px solid var(--grey-light)}
.yb-home-more__list li:last-child{border-bottom:0}
.yb-home-more__list a{
  display:block;padding:13px 18px;font-weight:700;font-size:.94rem;color:var(--navy);
}
.yb-home-more__list a:hover{background:var(--off-white);text-decoration:none}
.yb-home-more__list a:focus-visible{outline:3px solid var(--gold-light);outline-offset:-3px}
@media(min-width:680px){
  .yb-home-more__list{grid-template-columns:1fr 1fr}
  .yb-home-more__list li{border-right:1px solid var(--grey-light)}
  .yb-home-more__list li:nth-child(2n){border-right:0}
}

/* ---------- 7. Why choose (reuses .card/.card-grid) ---------- */
.yb-home-why__card p{font-size:.92rem;color:var(--text-grey);margin:0}

/* ---------- 8. Recent work & reviews ---------- */
.yb-home-work__grid{margin-top:8px;margin-bottom:8px}
.yb-home-work__photo{background:#fff;border:1px solid var(--grey-light);border-radius:var(--radius);overflow:hidden}
.yb-home-work__photo img{width:100%;height:auto;aspect-ratio:3/2;object-fit:cover}
.yb-home-work__photo figcaption{padding:10px 14px;font-size:.86rem;font-weight:700;color:var(--navy)}
.yb-home-work__reviews{margin-top:28px;padding-top:24px;border-top:1px solid var(--grey-light)}
.yb-home-work__reviews p{color:var(--text-grey)}

/* ---------- 9. Three-step process ---------- */
.yb-home-steps__grid{display:grid;grid-template-columns:1fr;gap:20px;margin-top:22px}
.yb-home-steps__step{text-align:center;max-width:320px;margin:0 auto}
.yb-home-steps__num{
  display:inline-flex;align-items:center;justify-content:center;
  width:40px;height:40px;border-radius:50%;background:var(--navy);color:#fff;
  font-weight:800;font-size:1.1rem;margin-bottom:10px;
}
.yb-home-steps__step p{font-size:.92rem;color:var(--text-grey);margin:0}
@media(min-width:768px){
  .yb-home-steps__grid{grid-template-columns:repeat(3,1fr)}
  .yb-home-steps__step{max-width:none}
}
/* PROMPT 20 — 5-step variant (boiler-installation.html's merged "How
   Pricing Works" + "3-step process" section). auto-fit rather than a
   fixed repeat(5,1fr) so it degrades gracefully on medium widths instead
   of squeezing 5 equal columns into a tablet-width wrap. */
.yb-home-steps__grid--5{grid-template-columns:1fr}
@media(min-width:768px){
  .yb-home-steps__grid--5{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
}

/* ---------- 10. Areas covered (reuses .section--alt; only heading/paragraph spacing) ---------- */
.yb-home-areas p{color:var(--text-grey);margin:12px 0 18px}

/* ---------- 11. Final CTA (reuses .cta-band as-is; no override needed) ---------- */

/* ==========================================================================
   v2.2.0 (PROMPT 5 — BOILER REPLACEMENT LANDING PAGE)
   New components for the rebuilt /boiler-installation/ page only. These are
   deliberately NEW, separately-named classes (yb-svc-*) rather than reused
   yb-home-* selectors, so this page's markup can never accidentally change
   the homepage's own approved v2.1.0/v2.1.1 hero/sections by sharing a
   selector — the homepage's CSS above is untouched. Where an existing
   shared component already fits (.trust-mini, .card/.card-grid, .ticks,
   .ticks--2col, .yb-home-primary__icon, .yb-home-steps__*, .yb-home-work__
   reviews, .faq, .cta-band) this page reuses it as-is; only genuinely new
   visual needs (a photo-background hero distinct from the plain .hero used
   by every OTHER service page, and a highlighted from-price conditions
   panel) get new rules below.
   ========================================================================== */

/* ---------- 1-3. Photo-background hero + offer + CTA (one coherent unit,
   same convention as the homepage's yb-home-hero, mirrored on its own
   selector so .hero — used by every other service page — is untouched) ---------- */
.yb-svc-hero{
  position:relative;
  overflow:hidden;
  display:flex;
  flex-direction:column;
  background:var(--navy);
}
.yb-svc-hero__media{
  position:relative;
  order:2;
  width:100%;
  aspect-ratio:860/754;
}
.yb-svc-hero__media img{
  width:100%;height:100%;object-fit:cover;object-position:center top;display:block;
}
.yb-svc-hero__scrim{ display:none; }
.yb-svc-hero__inner{
  position:relative;
  order:1;
  z-index:1;
  max-width:var(--maxw);
  margin:0 auto;
  width:100%;
  padding:26px 20px 22px;
  color:#fff;
}
/* PROMPT 16 (§5) — compact Gas Safe trust badge, new for this stage. Reuses
   the same small-gold-dot-before-text convention already established by
   .trust-mini li (see that rule above) at a smaller scale appropriate for
   sitting above the hero's own eyebrow line, rather than inventing a new
   visual language. Page-scoped in effect (only boiler-installation.html's
   markup adds this element), but left as a plain, un-namespaced class on
   the shared .yb-svc-hero component — like every other .yb-svc-hero__*
   class here, it does nothing unless a content file actually uses it, so
   the other 8 pages sharing this component are byte-for-byte unaffected. */
.yb-svc-hero__gassafe{
  display:flex;align-items:center;gap:8px;
  font-weight:700;font-size:.78rem;color:#eef3fa;margin:0 0 6px;
}
.yb-svc-hero__gassafe::before{
  content:"";flex:0 0 auto;width:11px;height:11px;border-radius:50%;background:var(--gold);
}
.yb-svc-hero__eyebrow{
  color:var(--gold-light);font-weight:800;font-size:.78rem;letter-spacing:.04em;
  text-transform:uppercase;margin:0 0 8px;
}
.yb-svc-hero__h1{
  color:#fff;font-size:clamp(1.6rem,6vw,2.2rem);line-height:1.16;margin:0 0 12px;
}
.yb-svc-hero__supporting{
  font-size:.98rem;color:#dfe8f5;margin:0 0 18px;max-width:46ch;
}
/* PROMPT 16 (§2, §3) — compact "fine print" lines added directly beneath
   .yb-svc-hero__supporting: deliberately smaller and tighter than
   __supporting itself (rather than reusing that class outright) so three
   extra lines of copy do not meaningfully add to the hero's visual weight
   or compete with the H1 — this is the mechanism behind the brief's "must
   not visually dominate the H1" / "without overcrowding" requirements.
   Same colour family as __supporting/__reassurance for visual consistency
   with the rest of the design system. */
.yb-svc-hero__detail{
  font-size:.8rem;line-height:1.35;color:#cdd9ea;margin:0 0 2px;max-width:46ch;
}
.yb-svc-hero__detail--last{
  margin:0 0 12px;
}
/* v2.4.0 (Prompt 7): additive-only price badge for the eight rebuilt
   service pages' .yb-svc-hero — the boiler-replacement landing page bakes
   its price into the H1 text instead, so this class is new, but the hero
   component itself (.yb-svc-hero/__media/__inner/__eyebrow/__h1/etc.) is
   entirely unchanged from v2.2.0. Only shown on pages with a genuinely
   approved, evidenced price — never fabricated for central heating, ASHP
   installation or air conditioning. */
.yb-svc-hero__price{
  display:inline-block;font-weight:800;color:var(--navy);background:var(--gold-light);
  padding:7px 16px;border-radius:999px;font-size:.92rem;margin:0 0 14px;
  /* PROMPT 11 (§7 QA fix): at >=768px .yb-svc-hero__inner becomes a column
     flexbox (see the @media(min-width:768px) block below) and this pill is
     a direct flex-item child of it. Flex's default align-items:stretch was
     stretching the pill to the full (400-540px) column width instead of
     letting it stay pill-shaped, which on 5 of 9 service pages visually
     overlapped the hero photo's own detail (e.g. boiler-repairs' diagnostic
     meter). align-self:flex-start opts this one element out of the stretch;
     harmless outside a flex context, where align-self has no effect. */
  align-self:flex-start;
}
.yb-svc-hero__price small{font-weight:700;font-size:.85em}
/* v2.4.0 (Prompt 7) — NARROW-MOBILE CTA-BAND WRAP FIX: browser-driven
   testing at 320px found the final .cta-band CTA button overflowing the
   viewport (button rendered ~342px wide inside a 320px viewport) on pages
   whose approved CTA wording is longer than the short labels .cta-band was
   originally designed around (e.g. "Request an Air Conditioning Quote" vs
   the older "Get My AC Quote"). Root cause: the sitewide `.btn{white-space:
   nowrap}` rule (untouched, ~line 840) keeps a long label on one line
   regardless of available width. The hero's own CTA row already avoids
   this because .yb-svc-hero__cta .btn is set to width:100% above; the
   final CTA band has no equivalent width constraint. Fixed narrowly, at
   the same sub-390px breakpoint already used elsewhere in this file for
   similar narrow-mobile corrections, scoped to cta-band's own button row
   only: this only changes rendering once a label no longer fits on one
   line, so the many shorter, pre-existing CTA-band buttons on every other
   page are visually unaffected. */
@media(max-width:389.98px){
  .cta-band .btn-row .btn{ white-space:normal; text-align:center; }
  /* PROMPT 11 (§5 QA fix): same root cause and same fix as the CTA-band
     wrap fix immediately above — the sitewide `.btn{white-space:nowrap}`
     rule kept "Read Our Google Reviews (opens in a new tab)" on one line,
     overflowing the viewport by ~69px at 320px and ~29px at 360px. This is
     the only other CTA-style button sitewide long enough to hit the same
     issue, so it gets the identical narrow-mobile treatment rather than a
     new pattern. */
  .yb-reviews-block__link .btn{ white-space:normal; text-align:center; }
  /* PROMPT 12 (§9 regression pass): same root cause again, found this stage
     after regenerating the browser-test render fixtures from current
     source and re-running the full suite. boiler-servicing.html's
     "Choose Your Option" compare-grid CTA button grew from "Book My Boiler
     Service" to "Book My £70 Boiler Service" back in Prompt 11 (a genuine,
     approved price-accuracy fix — see CHANGED-FILES.md "v2.6.1" §3) but
     nothing at the time re-tested this specific 320/360px case, so the 5
     extra characters pushed it over the same sitewide `.btn{white-space:
     nowrap}` threshold as the two fixes above (17px overflow at 320px,
     confirmed via a real headless-browser measurement, not just visual
     inspection). Scoped to this one button only — every other
     `.compare-grid` button sitewide is short enough to be unaffected. */
  .compare-grid .btn{ white-space:normal; text-align:center; }
  /* PROMPT 12 (§9 regression pass): a fourth instance of the same root
     cause, also found via the same regenerated-fixture full-suite run.
     The generic `.hero__cta` (used by page.php-template pages — about,
     contact, boiler-finance, reviews, areas-covered, etc. — as opposed to
     service pages' `.yb-svc-hero__cta`, which already sets `.btn{width:
     100%}` and was never affected) has no width/wrap constraint on its
     buttons at all. /boiler-finance/'s hero uses the approved "Request My
     Free Boiler Survey" wording (this project's longest standard CTA
     label) as a `.btn--secondary.btn--lg`, which overflowed the viewport
     by 9px at 320px (confirmed via a real headless-browser measurement).
     Scoped to `.hero__cta` only, at the same breakpoint as the three
     fixes above: shorter hero CTAs on every other page using this
     component are visually unaffected. */
  .hero__cta .btn{ white-space:normal; text-align:center; }
  /* PROMPT 12 (§9 regression pass): a fifth instance, and a general
     closing fix. After the four scoped fixes above, /boiler-finance/
     still overflowed by 9px at 320px — traced to a plain, bare `.btn-row`
     in ordinary page-body content (not inside `.hero__cta`, `.cta-band`,
     `.compare-grid`, or the reviews block) wrapping the same "Request My
     Free Boiler Survey" label. This exact bare-`.btn-row`-plus-long-label
     combination is a generic content pattern, not specific to one page,
     so — rather than add a sixth, seventh, etc. narrowly-scoped selector
     every time it recurs on a different page — this is a general
     `.btn-row .btn` rule, added last so normal cascade order still lets
     it act as the catch-all it's intended to be. It has the exact same
     white-space:normal/text-align:center declarations as the four rules
     above, so it changes nothing about them (a button already covered by
     a more specific selector renders identically either way); it only
     additionally protects any other bare `.btn-row` sitewide long enough
     to hit this same 320px-wide overflow. The four scoped rules above are
     left in place rather than removed, since they are still correct,
     already-verified, and harmless to keep. */
  .btn-row .btn{ white-space:normal; text-align:center; }
}
/* PROMPT 14 (§6.5 regression fix, found by this stage's own real-browser
   overflow sweep — see tests/browser/run-prompt9-browser-tests.js Section
   E / tests/browser/run-prompt14-mobile-hero-tests.js): the same root
   cause as every fix in the @media(max-width:389.98px) block immediately
   above (the sitewide `.btn{white-space:nowrap}` rule keeping a long
   `.yb-ext-link-label`-suffixed CTA on one line and forcing it past the
   viewport), but this time hit at exactly 390px — one of this project's
   own required test widths, and just outside that block's 389.98px
   ceiling. "Calculate My Repayments (opens in a new tab)" (the new
   finance-calculator CTA, §6.1-§6.3) is longer than any previously-fixed
   label ("Request My Free Boiler Survey", "Read Our Google Reviews (opens
   in a new tab)"), so it needed a wider ceiling than those did:
   /boiler-finance/'s CTA row overflowed by 20px at exactly 390px width
   (confirmed via a real headless-browser measurement — the identical
   button on /boiler-installation/'s narrower finance strip happened not
   to visibly overflow at 390px purely by coincidental left-offset
   alignment, which is not something to rely on). Scoped to only the 3
   `[data-yb-finance-calc-source]` links this stage added (the finance
   page, the boiler-installation strip, and each package card's inline
   text link — the last of these already wraps naturally as inline text,
   so this rule is a no-op there, not a conflict), at a wider breakpoint
   (480px, comfortably covering 390/412/430) than the general block above
   needed, rather than widening that shared block's own breakpoint and
   risking an unreviewed visual change to every other button sitewide
   between 390px and 480px. */
@media(max-width:480px){
  .btn-row .btn[data-yb-finance-calc-source]{ white-space:normal; text-align:center; }
}
.yb-svc-hero__cta{margin:0 0 12px}
.yb-svc-hero__cta .btn{width:100%}
.yb-svc-hero__reassurance{
  font-size:.82rem;color:#cdd9ea;margin:0;
}

@media(min-width:768px){
  .yb-svc-hero{
    display:block; /* photo becomes an absolutely-positioned background layer */
    min-height:clamp(360px,46vw,520px); /* compact: offer+CTA stay above the fold on common laptop heights */
  }
  .yb-svc-hero__media{
    position:absolute;inset:0;order:0;width:100%;height:100%;aspect-ratio:auto;
  }
  .yb-svc-hero__media img{object-position:center center}
  .yb-svc-hero__scrim{
    display:block;position:absolute;inset:0;
    /* Same contrast-tested gradient shape as the homepage hero's v2.1.0
       correction (see style.css "v2.1.0 correction" note above) — a wide,
       high-opacity dark zone under the text column, fading out only where
       the engineer/boiler need to stay visible on the right. */
    background:linear-gradient(90deg,rgba(6,26,51,.94) 0%,rgba(6,26,51,.9) 40%,rgba(6,26,51,.55) 62%,rgba(6,26,51,.1) 85%);
  }
  .yb-svc-hero__inner{
    padding:0 32px;height:100%;min-height:clamp(360px,46vw,520px);
    display:flex;flex-direction:column;justify-content:center;
  }
  .yb-svc-hero__inner{max-width:var(--maxw)}
  /* PROMPT 16 — .yb-svc-hero__gassafe/__detail (new this stage) added to
     this existing shared list so they get the same "stay inside the
     gradient's solid-dark zone" treatment as every other hero text
     element, rather than being left unconstrained and running out past
     the readable band into the lighter, photo-only part of the gradient. */
  .yb-svc-hero__gassafe,.yb-svc-hero__eyebrow,.yb-svc-hero__h1,.yb-svc-hero__supporting,.yb-svc-hero__detail,.yb-svc-hero__cta,.yb-svc-hero__reassurance{
    max-width:400px; /* keeps copy inside the gradient's solid-dark zone at 768-1023px */
  }
  .yb-svc-hero__cta{display:flex;gap:14px;flex-wrap:wrap}
  .yb-svc-hero__cta .btn{width:auto}
  /* PROMPT 16 — checked whether this route's extra §2/§3/§5 copy needed a
     >=768px height adjustment too (as it did on mobile, below). It does
     not: at >=768px .yb-svc-hero__media is a full absolutely-positioned
     background layer behind a gradient scrim (not a stacked block above/
     below the text, as on mobile), so the "leave a genuine untinted photo
     strip below the text" concern that required the mobile-only fix below
     does not apply here — the photo is always the whole box's background
     regardless of how tall the text content makes that box. Confirmed via
     real rendered-page measurement at 768/1024/1280/1440px: the text
     column never overflows the hero box at any of these widths (verified
     both before and after the mobile-only fix below), so no >=768px CSS
     change was needed or made.
     */
}
@media(min-width:1024px){
  .yb-svc-hero__h1{font-size:clamp(1.9rem,3.4vw,2.4rem)}
  .yb-svc-hero__gassafe,.yb-svc-hero__eyebrow,.yb-svc-hero__h1,.yb-svc-hero__supporting,.yb-svc-hero__detail,.yb-svc-hero__cta,.yb-svc-hero__reassurance{
    max-width:540px;
  }
}

/* ==========================================================================
   v2.5.1 (PROMPT 9.1 — MOBILE HERO IMAGE CORRECTION)
   Below 768px, .yb-home-hero and .yb-svc-hero previously stacked the hero
   photo as its own block underneath the text (display:flex;flex-direction:
   column with the media/inner children ordered via `order`) instead of
   showing it as a background layer the way the >=768px breakpoint already
   does (untouched above — position:absolute;inset:0 media + gradient scrim
   + relatively-positioned text on top). This block applies that exact same,
   already-approved technique down to mobile widths, for real photographic
   heroes only:
     - .yb-home-hero is always a real photo (homepage only), so it's
       corrected directly.
     - .yb-svc-hero is shared by 11 pages (9 as of Prompt 9.1, +2 in Prompt
       14 — see below). As of Prompt 9.1, 4 (air-conditioning, air-source-
       heat-pump-service, boiler-cover-plans, central-heating-installation)
       were a deliberate navy-only hero with NO .yb-svc-hero__media element
       in their markup at all (no honest local photo existed for them —
       see PROMPT9.1-CHANGED-FILES.md). Gating every rule below behind the
       .yb-svc-hero--photo modifier (added only to content files that
       carry real approved photography) means a genuinely navy-only page
       receives ZERO CSS from this block and stays byte-for-byte visually
       unaffected.

       PROMPT 14 (§3.1) — 1 of those 4 navy-only .yb-svc-hero pages now
       also carries real approved photography and the --photo modifier:
       central-heating-installation (see
       PROMPT14-HERO-VISIBILITY-REPORT.md). air-conditioning, air-source-
       heat-pump-service and boiler-cover-plans remain genuinely navy-only
       (no photo added, no change; boiler-cover-plans/"Boiler Care" is
       explicitly out of scope for a new hero photo this stage — see §3.5
       and PROMPT14-BOILER-CARE-STATUS.md). Separately (§3.3),
       gas-fire-cooker-checks — previously built on the DIFFERENT
       .yb-convert-hero component (used by Power Flushing too; Power
       Flushing is explicitly not given a photo hero this stage, see §3.4)
       — is also rebuilt onto this same .yb-svc-hero--photo system; it was
       never one of this block's "4 navy-only .yb-svc-hero pages" since it
       wasn't a .yb-svc-hero page at all until now.
   Every declaration here is wrapped in max-width:767.98px specifically so
   nothing in this block can ever apply at >=768px — the existing, already-
   approved tablet/desktop rules above are untouched and remain in full
   control from 768px up, per the brief's explicit "do not change desktop/
   tablet" requirement. No base rule above is edited or removed; this block
   only adds new, mobile-gated overrides.

   v2.6.0 (PROMPT 10 §12 — MOBILE HERO CONTRAST CORRECTION): the v2.5.1
   scrim above was a heavy, near-uniform navy tint (.90/.85/.92 opacity at
   every stop) that made the approved photographs hard to see on mobile.
   Replaced with a single directional gradient — strongest top-left,
   fading toward the bottom-right — which Prompt 11's accessibility audit
   then had to raise back up to .69-.78 through the middle/end stops to
   restore WCAG contrast for the supporting/reassurance text. The net
   result, still in place through v2.6.3, was a gradient that only ever
   ranged between about 65% and 78% opacity across the WHOLE photo — i.e.
   still a near-uniform dark tint over the entire image, just with a
   slightly lighter middle band. Confirmed as a genuine, still-unresolved
   visibility problem by the Prompt 14 brief (only the new-boiler hero —
   boiler-installation, whose photo has enough large-scale brightness/
   colour contrast of its own to still read through this tint — was
   judged "reasonably visible"; the other 5 darker/tighter indoor shots
   were not).

   v2.6.4 (PROMPT 14 §4 — MOBILE HERO VISIBILITY REDESIGN): replaces the
   whole-photo tint above with a STRUCTURED treatment, combining two of
   the brief's three suggested techniques: a solid-ish navy text panel
   (background moved from the removed __scrim element onto __inner
   itself, sized to the text content it actually contains, not the full
   hero box) sitting on a photo that otherwise carries ZERO tint. Because
   __inner is the only in-flow child of the (flex) hero box while __media
   is absolutely positioned (unchanged below), __inner's own rendered
   height is only as tall as its own text/CTA content — the hero box's
   min-height (increased below, giving each hero more room than its text
   needs) guarantees a real, untinted, fully clear strip of the actual
   photograph beneath the panel on every route, in addition to whatever
   the photo's own bright/light areas already show through at the panel's
   own soft bottom fade. This is a strictly additive visibility
   improvement over the v2.6.0/11 gradient — every photo, including
   boiler-installation's, now shows MORE of itself, more clearly, not
   less. Panel opacity (.90-.92) is close enough to the sitewide solid
   --navy (already used at full opacity with white text elsewhere, e.g.
   .hero) that text contrast is comfortably >=4.5:1 regardless of what's
   behind it — verified against real rendered screenshots, not opacity
   arithmetic alone, at all 8 required widths on every affected route; see
   PROMPT14-HERO-VISIBILITY-REPORT.md and PROMPT14-ACCESSIBILITY-AUDIT.md.
   The text-shadow kept below is now belt-and-braces insurance for the
   panel's own soft-fade edge, not the primary contrast mechanism. */
@media(max-width:767.98px){
  /* ---- Homepage hero (always real photography) ---- */
  .yb-home-hero{
    /* PROMPT 14 §4: taller than the v2.5.1/10 box (was clamp(460px,124vw,
       620px)) specifically so the text panel below never has to consume
       the whole box — there is always genuine spare height left over as a
       clearly visible, untinted strip of the actual photograph. */
    min-height:clamp(500px,150vw,660px);
  }
  .yb-home-hero__media{
    position:absolute;inset:0;width:100%;height:100%;
  }
  .yb-home-hero__media img{
    /* Same source image and reasoning as before (yorkshire-boilers-
       homepage-hero-mobile.webp) — engineer's face sits in the image's
       upper third, so biasing the crop upward keeps him and the van
       signage in frame instead of centring on his torso. A taller box
       (above) now shows more of this image's height than before, not
       less, so the same object-position remains correct. */
    object-position:center 18%;
  }
  .yb-home-hero__scrim{
    /* PROMPT 14 §4: the whole-photo gradient tint is removed — replaced
       by the __inner text panel immediately below. The photo itself now
       carries no tint at all outside the panel's own footprint. */
    display:none;
  }
  .yb-home-hero__inner{
    background:linear-gradient(180deg,rgba(6,26,51,.92) 0%,rgba(6,26,51,.92) 82%,rgba(6,26,51,0) 100%);
    border-radius:0 0 18px 18px;
    padding-bottom:32px;
  }

  /* ---- Service-page hero — photo pages only (.yb-svc-hero--photo) ---- */
  .yb-svc-hero--photo{
    /* PROMPT 14 §4: same reasoning as the homepage hero above — taller
       than the previous clamp(420px,112vw,560px) so a genuine, untinted
       strip of photograph is always visible below the text panel. */
    min-height:clamp(480px,145vw,620px);
  }
  /* PROMPT 16 (§2/§7 QA) — boiler-installation-ONLY mobile hero height
     increase. This route's __inner panel now carries meaningfully more
     copy than the other 7 photo-hero routes (the Gas Safe badge plus the
     three new fine-print lines required by §2/§3), which measured out at
     ~565-566px tall at 360-390px widths against the shared clamp above —
     tall enough to consume the ENTIRE box (min-height is a minimum, so the
     box grows with its content), leaving zero visible strip of the
     approved photograph at exactly the narrowest required test widths.
     That would silently defeat the whole point of the v2.6.4 "always leave
     a genuine untinted photo strip" redesign for this one route. Fixed by
     giving ONLY this route's mobile hero more room via the existing
     .yb-svc-hero--boiler-installation modifier (already present in this
     page's own markup, used elsewhere in this file for its object-position
     override) — every other .yb-svc-hero--photo route keeps the exact
     clamp(480px,145vw,620px) above, byte-for-byte unaffected. Verified via
     real rendered-page measurement at 360/390/430px: restores a genuine
     ~80-195px gap between the text panel and the hero's bottom edge at
     every required mobile width (see PROMPT16 implementation report). */
  .yb-svc-hero--boiler-installation{
    min-height:clamp(600px,178vw,740px);
  }
  .yb-svc-hero--photo .yb-svc-hero__media{
    position:absolute;inset:0;width:100%;height:100%;
  }
  .yb-svc-hero--photo .yb-svc-hero__scrim{
    display:none; /* PROMPT 14 §4 — see the homepage __scrim rule above. */
  }
  .yb-svc-hero--photo .yb-svc-hero__inner{
    background:linear-gradient(180deg,rgba(6,26,51,.92) 0%,rgba(6,26,51,.92) 82%,rgba(6,26,51,0) 100%);
    border-radius:0 0 18px 18px;
    padding-bottom:32px;
  }
  /* Per-page mobile object-position — each source image is a landscape
     photo being shown in a taller-than-wide mobile hero box, so a
     straight "center center" crop can cut the wrong side of a wide shot.
     Each value below was chosen by inspecting where the engineer/
     equipment actually sits in that specific photo, then confirmed
     against real-browser screenshots — see PROMPT9.1-AFFECTED-ROUTES.csv
     / PROMPT9.1-MOBILE-HERO-REPORT.md for the original 5, and
     PROMPT14-HERO-VISIBILITY-REPORT.md for the 2 new routes added this
     stage (central-heating, gas-safety's sibling gas-fire hero). Desktop/
     tablet keep their existing, unchanged "center center" crop from the
     >=768px rule above — these overrides never apply there. */
  .yb-svc-hero--boiler-installation .yb-svc-hero__media img{ object-position:56% center; }
  .yb-svc-hero--boiler-repairs .yb-svc-hero__media img{ object-position:58% center; }
  .yb-svc-hero--boiler-servicing .yb-svc-hero__media img{ object-position:45% center; }
  /* PROMPT 15 (§6) — the ashp-install object-position-only tweak that used
     to live on this line ("62% center") is REMOVED here, not just edited:
     it is fully superseded by the dedicated .yb-svc-hero--ashp-install
     block below, which replaces this route's whole mobile media treatment
     (not just its crop position) — see that block's own comment for why. */
  .yb-svc-hero--gas-safety .yb-svc-hero__media img{ object-position:50% center; }
  /* PROMPT 14 §3.1/§3.3 — the two new photo heroes this stage. */
  .yb-svc-hero--central-heating .yb-svc-hero__media img{ object-position:68% center; }
  .yb-svc-hero--gas-fire .yb-svc-hero__media img{ object-position:38% center; }

  /* PROMPT 15 (§6) — CONFIRMED DEFECT FIX, ASHP mobile hero. The shared
     .yb-svc-hero--photo treatment above (full-bleed, absolutely-positioned
     photo behind the text panel, object-fit:cover) forces a tall,
     portrait-shaped box onto this landscape source photo. Every
     object-position value tried in Prompt 14 still left the outdoor
     heat-pump unit either cropped off one edge or reduced to a small
     sliver beside a large area of plain paving/wall — the pixel-variation
     test Prompt 14 relied on passed (the crop DID contain non-navy
     pixels), but an ordinary person looking at the actual screenshot
     could not identify the heat-pump unit, which was the real, original
     complaint. See PROMPT15-ASHP-MOBILE-HERO-REPORT.md for the
     screenshot evidence and the alternatives that were tried and
     rejected before this one.

     Fix: this route gets its own mobile treatment, undoing the shared
     absolute/full-bleed rules above and returning .yb-svc-hero__media to
     NORMAL DOCUMENT FLOW (order:2, i.e. still visually below __inner —
     the base .yb-svc-hero rule earlier in this file already puts __media
     after __inner in source/flex order; this only removes the __photo
     mobile override's position:absolute, it does not change ordering).
     The image FILE this route's mobile <source> points to
     (assets/img/mobile-webp/air-source-heat-pump-installation-yorkshire-
     mobile.webp) was also replaced — same source photograph, re-cropped
     (not merely repositioned) to 2:1, tightly framing the heat-pump unit
     and a meaningful part of the engineer, still the same genuine,
     unedited, untinted photograph — so the alt text on the <img> element
     ("Air source heat pump outdoor unit installed at a Yorkshire
     property") remains fully accurate and is intentionally left
     unchanged. Desktop/tablet (>=768px) are completely unaffected: the
     desktop <picture> source/file/crop are untouched, and this whole
     block lives inside the same max-width:767.98px query as every other
     mobile-only hero rule in this file. */
  .yb-svc-hero--ashp-install{
    min-height:0;
  }
  .yb-svc-hero--ashp-install .yb-svc-hero__media{
    position:relative;inset:auto;width:100%;height:auto;aspect-ratio:2/1;
  }
  .yb-svc-hero--ashp-install .yb-svc-hero__media img{
    width:100%;height:100%;aspect-ratio:2/1;object-fit:cover;object-position:center center;
  }
  .yb-svc-hero--ashp-install .yb-svc-hero__inner{
    border-radius:18px 18px 0 0;
  }

  /* Belt-and-braces edge-contrast insurance for text sitting near the
     panel's own soft bottom fade (see the v2.6.4 block comment above) —
     no longer the primary contrast mechanism now the panel itself is
     close to solid navy. Desktop/tablet (>=768px, whose own left-to-right
     gradient was never changed) are untouched. */
  .yb-home-hero__eyebrow,.yb-home-hero__h1,.yb-home-hero__offer,.yb-home-hero__supporting,.yb-home-hero__reassurance,
  .yb-svc-hero--photo .yb-svc-hero__eyebrow,.yb-svc-hero--photo .yb-svc-hero__h1,
  .yb-svc-hero--photo .yb-svc-hero__supporting,.yb-svc-hero--photo .yb-svc-hero__reassurance{
    text-shadow:0 1px 3px rgba(3,17,32,.55),0 1px 12px rgba(3,17,32,.35);
  }
}

/* ---------- 6. Highlighted from-price-conditions info panel ---------- */
.yb-svc-info-panel{
  background:#FFF8E8;border:1px solid var(--gold-light);border-left:4px solid var(--gold);
  border-radius:var(--radius);padding:20px 22px;
}
.yb-svc-info-panel p{color:var(--navy);font-size:.94rem;margin:0 0 10px}
.yb-svc-info-panel p:last-child{margin-bottom:0}
.yb-svc-info-panel__close{font-weight:700}
/* PROMPT 20 — "See Installation Details" expandable disclosure inside
   the info panel (boiler-installation.html's "About Your Price"
   section). Reuses the site's existing .faq +/– summary treatment so it
   reads as a familiar expandable control, not a new interaction pattern. */
.yb-svc-info-panel__details{margin-top:14px;border-top:1px solid var(--gold-light);padding-top:14px}
.yb-svc-info-panel__details summary{
  cursor:pointer;list-style:none;font-weight:700;color:var(--navy);
  position:relative;padding-right:28px;
}
.yb-svc-info-panel__details summary::-webkit-details-marker{display:none}
.yb-svc-info-panel__details summary::after{content:"+";position:absolute;right:0;top:0}
.yb-svc-info-panel__details[open] summary::after{content:"–"}
.yb-svc-info-panel__details-body{margin-top:10px}
.yb-svc-info-panel__details-body p{color:var(--navy);font-size:.94rem;margin:0 0 10px}
.yb-svc-info-panel__details-body p:last-child{margin-bottom:0}

/* ---------- 7. Boiler choice tiers (reuses .card/.card-grid + the existing
   .yb-home-primary__icon treatment; only a tiny price/CTA layout tweak) ---------- */
.yb-boiler-tier__price{display:block;font-weight:800;color:var(--navy);font-size:1.15rem;margin:2px 0 10px}
.yb-boiler-tier__cta{margin-top:auto}

/* ---------- 11. Optional add-ons list (reuses .ticks; no override needed) ---------- */

@media(prefers-reduced-motion:reduce){
  .yb-svc-hero{transition:none}
}

/* ---------- Reduced motion: nothing above animates by default, this is a defensive no-op guard ---------- */
@media(prefers-reduced-motion:reduce){
  .yb-home-primary__card--featured{transition:none}
}

/* ==========================================================================
   PROMPT 10 (§3/§27) — the old Prompt 6 (v2.3.0) ten-step Boiler Package
   Builder CSS block (.yb-pkgb-* — 86 rules covering its option lists,
   package-selection cards, per-package price summary, upgrade toggles,
   photo-upload slots and review/submit screen) has been REMOVED along with
   the wizard itself (assets/js/package-builder.js, deleted; the
   window.YBPackageBuilder divert branch in assets/js/site.js, removed).
   None of these selectors are emitted by any template any more — see
   PROMPT10-CHANGED-FILES.md. The new package-card component's styling
   lives in the "PROMPT 10 — Boiler package cards" block below.
   ========================================================================== */

/* ==========================================================================
   PROMPT 10 (§4/§6/§9/§10) — Boiler package cards (Budget / Most Popular /
   Premium). Rendered server-side by yb_pkg_render_package_cards_html() —
   see inc/package-builder.php. Mobile-first: single column below 900px,
   three columns at/above it. --full (the boiler-replacement landing page)
   shows the inclusions ticklist and warranty line; --compact (homepage
   teaser) omits them per §10 ("keep concise, don't duplicate the boiler
   landing page") — both share every other rule below.
   ========================================================================== */
.yb-pkg-cards{
  display:grid;grid-template-columns:1fr;gap:20px;margin-top:22px;align-items:stretch;
}
@media(min-width:900px){
  .yb-pkg-cards{grid-template-columns:repeat(3,1fr)}
}
.yb-pkg-card{
  position:relative;background:#fff;border:1px solid var(--grey-light);border-radius:var(--radius);
  padding:22px 20px 20px;display:flex;flex-direction:column;box-shadow:var(--shadow);
}
.yb-pkg-card--featured{
  border:2px solid var(--gold);box-shadow:0 10px 28px rgba(215,165,58,.22);
}
.yb-pkg-card__badge{
  position:absolute;top:-13px;left:20px;background:var(--gold);color:var(--navy);font-weight:800;
  font-size:.74rem;letter-spacing:.04em;text-transform:uppercase;padding:5px 12px;border-radius:999px;
  box-shadow:0 3px 8px rgba(0,0,0,.18);
}
.yb-pkg-card__media{display:block;margin:6px auto 12px;width:120px;height:120px}
.yb-pkg-card__media img{width:100%;height:100%;object-fit:contain}
.yb-pkg-card__name{font-size:1.15rem;color:var(--navy);margin:0 0 2px}
.yb-pkg-card__model{font-size:.86rem;color:var(--text-grey);margin:0 0 10px}
.yb-pkg-card__price{font-size:1.5rem;font-weight:800;color:var(--navy);margin:0 0 8px}
/* PROMPT 14 (§6.3) — deliberately small/secondary: the cash price above
   (.yb-pkg-card__price, 1.5rem/800 weight) stays the visually primary
   figure; this line is sized down and coloured with the muted grey already
   used for .yb-pkg-card__best-for immediately below it, and its link is a
   plain underlined text link rather than a second .btn, so it can never
   visually compete with the card's own primary "Discuss This Package"
   button further down. */
.yb-pkg-card__finance{font-size:.82rem;color:var(--text-grey);margin:0 0 8px;line-height:1.4}
.yb-pkg-card__finance-link{color:var(--navy);font-weight:600;text-decoration:underline}
.yb-pkg-card__finance-link:hover{color:var(--navy-dark)}
.yb-pkg-card__best-for{font-size:.9rem;color:var(--text-grey);margin:0 0 10px;min-height:2.6em}
.yb-pkg-card__why{font-size:.88rem;color:var(--navy);margin:0 0 12px;line-height:1.5}
.yb-pkg-card__ticks{margin:0 0 12px}
.yb-pkg-card__warranty{font-size:.84rem;color:var(--text-grey);margin:0 0 16px;line-height:1.45}
.yb-pkg-card__cta{margin-top:auto}
.yb-pkg-cards__help{margin-top:18px}

/* PROMPT 14 (§6.3) — compact finance info strip below the package grid on
   /boiler-installation/ ("Want To Spread The Cost?"). Deliberately compact
   (max-width constrained by the containing .wrap in the HTML) and visually
   secondary to the package cards above it — a plain bordered panel, not a
   heavy navy band, so it reads as a helpful aside rather than competing
   with the cash-price-led package decision itself. */
.yb-finance-strip__panel{
  background:#fff;border:1px solid #e3e8ef;border-radius:12px;
  padding:20px 22px;text-align:center;box-shadow:var(--shadow-sm);
}
.yb-finance-strip__heading{font-size:1.15rem;margin:0 0 8px;color:var(--navy)}
.yb-finance-strip__copy{font-size:.92rem;color:var(--text-grey);margin:0 0 14px;line-height:1.5}
/* Accessibility fix (found by this stage's own axe-core sweep, see
   tests/browser/run-prompt9-browser-tests.js Section K): the sitewide
   default link style (`a{color:var(--navy);text-decoration:none}`, see
   near the top of this file) relies on colour alone to distinguish a link
   from surrounding text — fine for links that stand alone (buttons, nav,
   card titles), but the "boiler finance" link inside this strip's own
   prose sentence sits inline in a full paragraph of body text, which is
   exactly the axe "link-in-text-block" WCAG 1.4.1 failure case (colour
   alone is not sufficient to convey the link). Underlining it here,
   matching the sitewide `.prose a` pattern already used for the same
   in-paragraph-link situation elsewhere in this theme, is scoped to this
   one inline link and does not touch the sitewide default. */
.yb-finance-strip__copy a{text-decoration:underline;font-weight:600}

/* ==========================================================================
   PROMPT 10 (§18/19) — Genuine Google review display. yb_reviews_render_html()
   in inc/reviews.php. .yb-ext-link-label is the small, visible "(opens in a
   new tab)" cue used on every external Google link this stage adds.
   ========================================================================== */
.yb-reviews-block__empty{color:var(--text-grey);text-align:center;max-width:520px;margin:0 auto 14px}
/* PROMPT 13 — grid tracks changed from bare 1fr to minmax(0,1fr) at both
   the base (single-column) and >=768px (3-column) rules. This is the
   same fix already applied to .need-grid (Prompt 9/12) and documented
   there: a bare 1fr track's minimum width defaults to auto, which can
   force the track (and the viewport) wider than available space to fit
   its content instead of letting long review text wrap normally.
   Reviews.json now carries several longer genuine review excerpts
   (Prompt 13) than this component was originally styled against, so
   this fix is applied proactively here rather than waiting to find the
   same class of bug a fourth time — verified via real headless-browser
   scrollWidth/clientWidth measurement at all 8 required widths with 0px
   overflow; see PROMPT13-TEST-RESULTS.md. */
.yb-reviews-block__grid{display:grid;grid-template-columns:minmax(0,1fr);gap:16px;margin-bottom:14px}
@media(min-width:768px){ .yb-reviews-block__grid{grid-template-columns:repeat(3,minmax(0,1fr))} }
.yb-review-card{background:#fff;border:1px solid var(--grey-light);border-radius:var(--radius);padding:18px;overflow-wrap:break-word;word-wrap:break-word}
.yb-review-card__stars{color:var(--gold);letter-spacing:2px;margin:0 0 8px;font-size:1rem}
.yb-review-card__excerpt{font-size:.92rem;color:var(--navy);margin:0 0 10px;line-height:1.5}
.yb-review-card__meta{font-size:.82rem;color:var(--text-grey);margin:0}
.yb-reviews-block__link{text-align:center;margin:6px 0 0}
.yb-ext-link-label{font-size:.78rem;color:var(--text-grey);font-weight:400}
/* PROMPT 14 (§6.2/§6.3) — this label was previously only ever used inside
   .btn--ghost (white/transparent background), where its var(--text-grey)
   colour comfortably passes contrast. The new "Calculate My/Repayments"
   external-finance-link CTAs reuse it inside .btn--primary (gold
   background) too; text-grey-on-gold measures ~4.3:1, under the 4.5:1
   normal-text AA threshold at this label's small .78rem size. Scoped
   override: inside a gold .btn--primary specifically, the label instead
   inherits the button's own navy text colour (the same colour as the rest
   of the button's label, already relied on sitewide and comfortably AA
   compliant), rather than introducing a new, unverified colour pairing. */
.btn--primary .yb-ext-link-label{color:inherit}

/* ==========================================================================
   v2.6.20 (Stage 3 C3) — compact cookie banner (WPConsent Lite 1.2.0)
   --------------------------------------------------------------------------
   Styling only. The banner lives in WPConsent's shadow root, so these rules
   use the ::part() names the plugin exposes; no plugin file is changed.
   Wording, button labels/order/colours and the hidden "Powered by" link are
   WPConsent settings (Banner Design > Content / Style), not theme code.
   Consent categories, defaults, Google Consent Mode and script blocking are
   untouched.
   - Below 1180px (where the theme's fixed "call / quote" bar is shown) the
     banner sits at the TOP of the screen, so it no longer covers the
     quotation builder's answer buttons or the call bar.
   - Phones: smaller text, "Reject optional" and "Accept all" side by side
     at the same size and colour (44px tall), "Cookie settings" full width
     underneath. Safe-area insets respected; scrolls inside itself if a
     very short screen needs it.
   - v2.6.21: banner starts below the sticky header; menu drawer stacks
     above the banner when opened.
   - v2.6.22: the floating settings icon is replaced by a footer
     "Cookie settings" button (see the v2.6.22 block at the end of this file). To keep
     the first question clear at 360-430px with the header now visible, the
     phone banner is 16px shorter: 6px top/bottom padding (was 10), line
     height 1.3 (was 1.35), 6px gaps (was 8) and a 40px "Cookie settings"
     button (was 44; "Reject optional" and "Accept all" stay 44px).
   - Cookie settings panel: buttons at least 44px tall on phones.
   - Below 1180px the floating Cookie Preferences button sits above the call bar.
   ========================================================================== */
#wpconsent-container::part(wpconsent-button-accept),
#wpconsent-container::part(wpconsent-button-cancel){font-weight:700;min-width:150px;min-height:40px;border:2px solid #fff}
#wpconsent-container::part(wpconsent-button-preferences){background:transparent;color:#fff;border:2px solid rgba(255,255,255,.75);font-weight:600;min-height:40px}
#wpconsent-container::part(wpconsent-button-accept):focus-visible,
#wpconsent-container::part(wpconsent-button-cancel):focus-visible,
#wpconsent-container::part(wpconsent-button-preferences):focus-visible{outline:3px solid #ffcd2a;outline-offset:2px}
@media (max-width:1179.98px){
  /* v2.6.21: the banner starts just below the sticky header (70px + its 1px border) instead of
     covering the logo, Call and Menu. Was top:0 in v2.6.20. */
  #wpconsent-container::part(wpconsent-banner){top:calc(var(--header-h-mobile,70px) + 1px);bottom:auto;padding-top:8px}
  /* v2.6.21: now that the Menu button can be reached while the banner is open, the opened menu
     drawer (and its dimmed backdrop) must sit above WPConsent's banner layer (z-index 900000). */
  html.yb-nav-open .nav-overlay.open{z-index:900001}
  html.yb-nav-open .nav-mobile.open{z-index:900002}
}
@media (max-width:767.98px){
  #wpconsent-root{--wpconsent-font-size:14px !important}
  #wpconsent-container::part(wpconsent-banner){padding:6px calc(14px + env(safe-area-inset-right)) 6px calc(14px + env(safe-area-inset-left));line-height:1.3;max-height:60vh;max-height:60dvh;overflow-y:auto}
  #wpconsent-container::part(wpconsent-banner-body){margin:0;padding:0 0 6px}
  #wpconsent-container::part(wpconsent-banner-footer){display:grid;grid-template-columns:1fr 1fr;gap:6px}
  #wpconsent-container::part(wpconsent-button-cancel),
  #wpconsent-container::part(wpconsent-button-accept){min-height:44px;min-width:0;font-size:15px;margin:0;width:100%}
  #wpconsent-container::part(wpconsent-button-preferences){grid-column:1 / -1;order:3;min-height:40px;font-size:14px;margin:0;width:100%}
  #wpconsent-container::part(wpconsent-preferences-accept-button),
  #wpconsent-container::part(wpconsent-preferences-cancel-button),
  #wpconsent-container::part(wpconsent-preferences-save-button){min-height:44px}
}
/* v2.6.22: on 480-767px screens the three banner buttons sit in one row (all 44px tall) so the
   banner stays clear of the first question at 600px (131px tall instead of 177px). */
@media (min-width:480px) and (max-width:767.98px){
  #wpconsent-container::part(wpconsent-banner-footer){grid-template-columns:1fr 1fr 1fr}
  #wpconsent-container::part(wpconsent-button-preferences){grid-column:auto;min-height:44px}
}


/* v2.6.21 (Stage 3) — WCAG 1.4.1: the three links in the "Prefer to talk it through?" line under the
   quotation builder (phone, boiler installation, contact us) were distinguishable from the surrounding
   text by colour only. Underline them. Scoped to that one section (the section straight after the
   builder section); text and destinations unchanged; underlines do not change line height. */
.yb-quote-builder-section + .section p.center a{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}
.yb-quote-builder-section + .section p.center a:hover,
.yb-quote-builder-section + .section p.center a:focus-visible{text-decoration-thickness:2px}


/* v2.6.22 (Stage 3) — footer "Cookie settings" button + mobile-menu quote button text.
   1. The footer button (inc/v2622-cookie-settings.php) opens WPConsent's existing Cookie settings panel
      via WPConsent's supported `wpconsent-open-preferences` class. It looks like the neighbouring
      footer links but has a 44px-tall touch target and a visible keyboard focus ring.
   2. With that button on every page, WPConsent's small floating icon is hidden. Scoped to
      body.yb-has-cookie-settings, which is only added when the footer button is rendered.
      `!important` is needed because WPConsent sets display:block inline on the icon.
   3. On the page a menu item points to, `.nav-mobile a[aria-current="page"]` turns its text gold.
      For the drawer's gold "Get a Boiler Quote" button on /boiler-quote/ that meant gold-on-gold
      (unreadable). Navy #04194e text in every state; size and link unchanged.
      The generic drawer-link hover rule (`.nav-mobile a:hover`, a faint white wash) also out-ranked
      `.btn--primary:hover`, so on hover/tap this gold button lost its gold background on every page.
      Its hover/focus/active background is now the theme's own `.btn--primary:hover` gold-light. */
.yb-cookie-settings-link{
  -webkit-appearance:none;appearance:none;background:none;border:0;margin:0;
  display:inline-flex;align-items:center;min-height:44px;padding:0 2px;
  font:inherit;font-size:var(--fs-small);line-height:1.3;color:#9fb0c4;cursor:pointer;
  text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px;
}
.yb-cookie-settings-link:hover,
.yb-cookie-settings-link:focus-visible{color:var(--gold);text-decoration-thickness:2px}
.yb-cookie-settings-link:focus-visible{outline:2px solid var(--gold);outline-offset:2px;border-radius:4px}
.footer-legal-row{align-items:center}
.footer-landing__list .yb-cookie-settings-link{color:#aebccd}
.footer-landing__list .yb-cookie-settings-link:hover,
.footer-landing__list .yb-cookie-settings-link:focus-visible{color:var(--gold)}
body.yb-has-cookie-settings #wpconsent-container::part(wpconsent-settings-button){display:none !important}
.nav-mobile a.btn--primary[aria-current="page"],
.nav-mobile a.btn--primary[aria-current="page"]:hover,
.nav-mobile a.btn--primary[aria-current="page"]:focus,
.nav-mobile a.btn--primary[aria-current="page"]:focus-visible,
.nav-mobile a.btn--primary[aria-current="page"]:active{color:#04194e}
.nav-mobile .drawer-cta a.btn--primary:hover,
.nav-mobile .drawer-cta a.btn--primary:focus-visible,
.nav-mobile .drawer-cta a.btn--primary:active{background:var(--gold-light)}
