@charset "UTF-8";
/* Swanbourne Construction Ltd — site stylesheet
   Mobile-first. Navy #1D262F, gold #C2A35A. Source Serif 4 headings, Inter body.

   HEADINGS WERE FRAUNCES until 19 August 2026. James: "I don't like the way the j
   looks. It looks a little bit childish. The f looks weird." He was right, and it is
   the typeface working as designed — Fraunces has a "wonk" axis and deliberately
   irregular letterforms, which read as characterful on a magazine and as unserious on
   a builder quoting quarter-of-a-million-pound jobs. Source Serif 4 keeps the warmth
   of a serif so nothing else in the design had to move, and has entirely conventional
   j, f and g. Swap it by changing the two @font-face rules and --font-head below.
   Self-hosted fonts only — nothing is loaded from Google.
   Accessibility targets: 16px minimum body, 4.5:1 contrast, 48px tap targets,
   visible focus, works at 200% text zoom. */

/* ---------- FONTS ---------- */
@font-face{font-family:Inter;src:url(/css/fonts/inter-400.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215}
@font-face{font-family:Inter;src:url(/css/fonts/inter-500.woff2) format("woff2");font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:Inter;src:url(/css/fonts/inter-600.woff2) format("woff2");font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:Inter;src:url(/css/fonts/inter-700.woff2) format("woff2");font-weight:700;font-style:normal;font-display:swap}
/* Archivo, added 30 September 2026. James picked it from the typeface options.
   Headings only — Inter still does all the reading, because Archivo is a touch
   wide for long paragraphs. Source Serif 4 is left below as a fallback and can
   be restored by changing --font-head back. Self-hosted, as everything else is. */
@font-face{font-family:Archivo;font-style:normal;font-weight:600;font-display:swap;src:url(/css/fonts/archivo-600.woff2) format("woff2")}
@font-face{font-family:Archivo;font-style:normal;font-weight:700;font-display:swap;src:url(/css/fonts/archivo-700.woff2) format("woff2")}
@font-face{font-family:Archivo;font-style:normal;font-weight:800;font-display:swap;src:url(/css/fonts/archivo-800.woff2) format("woff2")}

/* ---------- TOKENS ---------- */
:root{
  --navy:#1D262F;
  --navy-90:#26313d;
  --navy-80:#33414f;
  --gold:#C2A35A;
  --gold-dark:#7a5f28;      /* clears 4.5:1 on white and on --bg-sand */
  --ink:#1a1f25;
  --body:#333c46;
  --muted:#5a6672;          /* 4.6:1 on white */
  --line:#dfe3e8;
  --bg:#ffffff;
  --bg-tint:#f6f7f9;
  --bg-sand:#faf7f0;
  --success:#1f6b45;
  --radius:4px;
  --wrap:1180px;
  --narrow:760px;
  --bar-h:64px;             /* sticky mobile bar height */
  --font-body:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --font-head:Archivo,"Helvetica Neue",Arial,sans-serif;
}

/* ---------- RESET ---------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;overflow-x:hidden}
body{overflow-x:hidden}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*{animation-duration:.01ms!important;transition-duration:.01ms!important}}
body{
  margin:0;
  font-family:var(--font-body);
  font-size:1.0625rem;       /* 17px — above the 16px minimum */
  line-height:1.65;
  color:var(--body);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
  /* room for the sticky mobile contact bar so it never covers content */
  padding-bottom:calc(var(--bar-h) + env(safe-area-inset-bottom,0px));
}
@media(min-width:900px){body{padding-bottom:0}}
img,picture,video,svg{max-width:100%;height:auto;display:block}
h1,h2,h3,h4{font-family:var(--font-head);color:var(--navy);line-height:1.2;margin:0 0 .5em;font-weight:700;text-wrap:balance}
h1{font-size:clamp(1.85rem,5.2vw,3rem);letter-spacing:-.015em}
h2{font-size:clamp(1.45rem,3.6vw,2.1rem);margin-top:2.2em}
h3{font-size:clamp(1.15rem,2.4vw,1.4rem);margin-top:1.8em}
h4{font-size:1.05rem;font-family:var(--font-body);font-weight:700;margin-top:1.5em}
p,ul,ol,table,blockquote{margin:0 0 1.15em}
li{margin-bottom:.4em}
ul,ol{padding-left:1.35em}
a{color:var(--gold-dark);text-underline-offset:.16em;text-decoration-thickness:1px}
a:hover{color:var(--navy)}
strong{color:var(--ink);font-weight:600}
hr{border:0;border-top:1px solid var(--line);margin:2.5em 0}
small{font-size:.9rem}
:focus-visible{outline:3px solid var(--gold);outline-offset:2px;border-radius:2px}

/* ---------- LAYOUT ---------- */
.wrap{width:100%;max-width:var(--wrap);margin-inline:auto;padding-inline:1.15rem}
@media(min-width:700px){.wrap{padding-inline:2rem}}
.prose{max-width:var(--narrow)}
.section{padding-block:2.75rem}
@media(min-width:900px){.section{padding-block:4rem}}
.tint{background:var(--bg-tint)}
.sand{background:var(--bg-sand)}
.dark{background:var(--navy);color:#e7ebef}
.dark h2,.dark h3,.dark h4{color:#fff}
.dark a{color:var(--gold)}
.dark a:hover{color:#fff}
.skip{position:absolute;left:-9999px;top:0;background:var(--navy);color:#fff;padding:.85rem 1.25rem;z-index:200}
.skip:focus{left:0}

/* ---------- HEADER ---------- */
.hdr{background:var(--navy);color:#fff;position:sticky;top:0;z-index:100}
/* Wraps rather than overflowing when the visitor has text enlarged to 200%. */
.hdr__in{display:flex;align-items:center;gap:.75rem 1rem;min-height:66px;flex-wrap:wrap;padding-block:.35rem}
.hdr__logo{display:flex;align-items:center;gap:.6rem;min-width:0;max-width:100%;overflow-wrap:anywhere;color:#fff;text-decoration:none;font-family:var(--font-head);font-weight:700;font-size:1.12rem;line-height:1.05;padding:.4rem 0}
.hdr__logo span{display:block;font-family:var(--font-body);font-weight:500;font-size:.66rem;letter-spacing:.13em;text-transform:uppercase;color:var(--gold)}
.hdr__spacer{flex:1 1 0;min-width:0}
/* desktop phone + CTA, permanently visible top right */
.hdr .hdr__tel{display:none;color:#fff;text-decoration:none;font-weight:700;font-size:1.18rem;white-space:nowrap;padding:.5rem .25rem}
.hdr__tel small{display:block;font-size:.66rem;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--gold)}
.hdr__tel:hover{color:var(--gold)}
.hdr .hdr__wa{display:none;align-items:center;gap:.4rem;color:#fff;text-decoration:none;font-weight:600;font-size:1rem;padding:.6rem .5rem}
.hdr__wa:hover{color:var(--gold)}
.hdr .hdr__cta{display:none}
@media(min-width:900px){
  .hdr .hdr__tel{display:block}
  .hdr .hdr__wa{display:inline-flex}
  .hdr .hdr__cta{display:inline-flex}
}
/* nav */
.navbtn{margin-left:auto;flex:0 0 auto;display:inline-flex;align-items:center;gap:.45rem;min-height:48px;padding:.55rem .8rem;background:transparent;border:1px solid rgba(255,255,255,.35);color:#fff;font:600 1rem/1 var(--font-body);border-radius:var(--radius);cursor:pointer}
@media(min-width:900px){.navbtn{display:none}}
.nav{display:none;background:var(--navy-90);border-top:1px solid rgba(255,255,255,.12)}
.nav.open{display:block}
@media(min-width:900px){
  .nav{display:block;background:var(--navy-90);border-top:1px solid rgba(255,255,255,.1)}
  .nav__list{display:flex;gap:0;justify-content:flex-start;flex-wrap:wrap}
  .nav__list a{padding:.7rem .62rem;font-size:1rem;white-space:nowrap}
}
.nav__list{list-style:none;margin:0;padding:.35rem 0}
.nav__list a{display:block;color:#fff;text-decoration:none;font-weight:500;padding:.85rem .9rem;min-height:48px;border-radius:var(--radius)}
.nav__list a:hover,.nav__list a[aria-current=page]{background:rgba(255,255,255,.1);color:#e6d19a}
.nav__list a[aria-current=page]{font-weight:700}
/* mobile-only phone row inside the drawer */
.nav__tel{display:flex;gap:.5rem;padding:.6rem .9rem 1rem}
@media(min-width:900px){.nav__tel{display:none}}
.nav__tel a{flex:1;text-align:center;background:var(--gold);color:var(--navy);font-weight:700;border-radius:var(--radius)}

/* ---------- BUTTONS ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  min-height:48px;padding:.8rem 1.35rem;
  font:700 1rem/1.2 var(--font-body);
  border-radius:var(--radius);border:2px solid transparent;
  text-decoration:none;cursor:pointer;text-align:center;
}
.btn--gold{background:var(--gold);color:var(--navy);border-color:var(--gold)}
.btn--gold:hover{background:#d4b872;color:var(--navy)}
.btn--navy{background:var(--navy);color:#fff;border-color:var(--navy)}
.btn--navy:hover{background:var(--navy-80);color:#fff}
.btn--ghost{background:transparent;color:var(--navy);border-color:var(--navy)}
.btn--ghost:hover{background:var(--navy);color:#fff}
.dark .btn--ghost,
.cta .btn--ghost,
.hero .btn--ghost{color:#fff;border-color:rgba(255,255,255,.75);background:rgba(0,0,0,.2)}
.dark .btn--ghost:hover,
.cta .btn--ghost:hover,
.hero .btn--ghost:hover{background:#fff;color:var(--navy);border-color:#fff}
/* the light CTA variant keeps dark text on its sand background */
.cta--light .btn--ghost{color:var(--navy);border-color:var(--navy);background:transparent}
.cta--light .btn--ghost:hover{background:var(--navy);color:#fff}
.btn--wide{width:100%}
@media(min-width:560px){.btn--wide{width:auto}}

/* ---------- HERO ---------- */
/* Heading and CTA are readable before the image loads: the navy base colour is
   painted immediately and the text sits on it, not on the photograph. */
.hero{position:relative;background:var(--navy);color:#fff;overflow:hidden}
.hero__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.38}
.hero::after{content:'';position:absolute;inset:0;z-index:1;background:linear-gradient(100deg,rgba(29,38,47,.82) 0%,rgba(29,38,47,.5) 55%,rgba(29,38,47,.25) 100%)}
.hero__in{position:relative;z-index:2;padding-block:3rem 2.5rem;max-width:44rem}
@media(min-width:900px){.hero__in{padding-block:5.5rem 4.5rem}}
.hero h1{color:#fff;margin-bottom:.55em;text-shadow:0 1px 18px rgba(0,0,0,.5)}
.hero__lede{font-size:1.15rem;color:#eef1f4;margin-bottom:1.6em;text-shadow:0 1px 12px rgba(0,0,0,.5)}
@media(min-width:900px){.hero__lede{font-size:1.3rem}}
.hero__btns{display:flex;flex-direction:column;gap:.7rem}
@media(min-width:560px){.hero__btns{flex-direction:row;flex-wrap:wrap}}

/* ---------- TRUST BAR ---------- */
.trustbar{background:var(--navy-90);color:#e7ebef;border-top:1px solid rgba(255,255,255,.1);font-size:1rem}
.trustbar ul{display:flex;flex-wrap:wrap;gap:.4rem 1.4rem;list-style:none;margin:0;padding:.85rem 0;align-items:center;justify-content:center}
@media(min-width:900px){.trustbar ul{justify-content:space-between;flex-wrap:nowrap;padding:.7rem 0}}
.trustbar li{display:flex;align-items:center;gap:.4rem;margin:0;white-space:nowrap}
.trustbar strong{color:#fff;font-weight:600}

/* ---------- STARS ---------- */
.stars{display:inline-flex;gap:1px;vertical-align:-3px}
.stars svg{width:17px;height:17px;fill:var(--gold);flex:none}

/* ---------- CARDS & GRIDS ---------- */
.grid{display:grid;gap:1.1rem;grid-template-columns:1fr}
@media(min-width:640px){.grid--2,.grid--3,.grid--4{grid-template-columns:repeat(2,1fr)}}
@media(min-width:960px){.grid--3{grid-template-columns:repeat(3,1fr)}.grid--4{grid-template-columns:repeat(4,1fr)}}
.card{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:1.35rem;display:flex;flex-direction:column}
.card h3{margin-top:0;font-size:1.2rem}
.card p{font-size:1rem;color:var(--muted)}
.card__more{margin-top:auto;padding-top:.6rem;font-weight:600}
.tint .card{background:#fff}

/* two homepage entry points */
.entry{display:grid;gap:1.1rem;grid-template-columns:1fr}
@media(min-width:800px){.entry{grid-template-columns:1fr 1fr}}
.entry__col{border:2px solid var(--line);border-radius:var(--radius);padding:1.5rem;background:#fff;display:flex;flex-direction:column}
.entry__col--a{border-color:var(--navy)}
.entry__col--b{border-color:var(--gold)}
.entry__col h3{margin-top:0}
.entry__col .btn{margin-top:auto}

/* Wide components break out of the 760px reading column on large screens, so the
   two entry points and the review grid use the full width of the page while the
   prose stays at a comfortable measure. */
@media(min-width:1000px){
  .prose > .entry,
  .prose > .rv__grid,
  .prose > .rv__head,
  .prose > .pm,
  .prose > .grid{
    /* These blocks are wider than the reading column and break out of it.
       The old rule widened them and stopped there, which worked only while
       .prose sat hard left inside .wrap. Now the bands centre the reading
       column, so widening alone pushed them off the right-hand edge — the
       two entry cards were hanging 96px past the viewport. Equal negative
       margins either side centre them on the page instead. */
    width:min(calc(var(--wrap) - 4rem), calc(100vw - 4rem));
    margin-inline:calc((var(--narrow) - min(calc(var(--wrap) - 4rem), calc(100vw - 4rem))) / 2);
  }
}

/* ---------- CTA BLOCKS ---------- */
.cta{background:var(--navy);color:#fff;border-radius:var(--radius);padding:1.6rem;margin-block:2.25rem}
.cta h2,.cta h3,.cta .cta__h{color:#fff;margin-top:0}
/* The call-to-action blocks repeat down a long page, which is right for
   conversion and wrong for the heading outline — the same H2 appearing
   four times on one page tells Google nothing. They keep their size and
   weight and stop being headings. */
.cta .cta__h{font:700 clamp(1.3rem,3.4vw,1.75rem)/1.2 var(--font-head);letter-spacing:-.02em;margin:0 0 .6rem}
.cta p{color:#dfe5ea}
.cta__btns{display:flex;flex-direction:column;gap:.65rem;margin-top:1.1rem}
@media(min-width:560px){.cta__btns{flex-direction:row;flex-wrap:wrap}}
.cta__trust{margin:.95rem 0 0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:.35rem 1.1rem;font-size:1rem;color:#dbe2e9}
.cta__trust li{display:flex;align-items:center;gap:.35rem;margin:0}
.cta--light{background:var(--bg-sand);color:var(--body);border:1px solid #ece4d3}
.cta--light h2,.cta--light h3{color:var(--navy)}
.cta--light p{color:var(--body)}
.cta--light .cta__trust{color:var(--muted)}

/* ---------- TABLES ---------- */
.tablewrap{overflow-x:auto;margin-bottom:1.3em;-webkit-overflow-scrolling:touch}
table{border-collapse:collapse;width:100%;font-size:1rem;min-width:30rem}
caption{text-align:left;font-size:.92rem;color:var(--muted);padding-bottom:.5rem;font-style:normal}
th,td{border:1px solid var(--line);padding:.65rem .8rem;text-align:left;vertical-align:top}
th{background:var(--bg-tint);font-weight:600;color:var(--navy)}

/* ---------- CALLOUTS ---------- */
.note{border-left:4px solid var(--gold);background:var(--bg-sand);padding:1rem 1.15rem;margin-block:1.5em;border-radius:0 var(--radius) var(--radius) 0}
.note p:last-child{margin-bottom:0}
.note--warn{border-left-color:#a8322a;background:#fdf4f3}
blockquote{border-left:4px solid var(--line);padding-left:1.1rem;margin-left:0;color:var(--muted);font-style:normal}
/* Definition lists carry the opening hours. A dt is a label, not a sentence, so
   it is set apart rather than indented — the browser default leaves the two
   reading as one limp paragraph. */
main dl{margin:0 0 1.15em;padding:1.1rem 1.25rem;border-left:4px solid var(--gold);background:rgba(0,0,0,.03)}
main dt{font-weight:700;font-size:1.08rem}
main dd{margin:.2rem 0 1rem;color:var(--muted)}
main dd:last-child{margin-bottom:0}

/* ---------- BREADCRUMBS ---------- */
.crumbs{font-size:.88rem;padding-block:.85rem;border-bottom:1px solid var(--line);color:var(--muted)}
.crumbs ol{list-style:none;display:flex;flex-wrap:wrap;gap:.3rem;margin:0;padding:0}
.crumbs li{margin:0;display:flex;align-items:center;gap:.3rem}
.crumbs li+li::before{content:"›";color:var(--line);font-size:1.05rem;line-height:1}
.crumbs a{color:var(--muted)}
.crumbs [aria-current=page]{color:var(--ink);font-weight:600}

/* ---------- REVIEWS ---------- */
.rv__head{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem 1.2rem;margin-bottom:1.4rem;padding-bottom:1.1rem;border-bottom:1px solid var(--line)}
.rv__score{font-family:var(--font-head);font-size:2.4rem;font-weight:700;color:var(--navy);line-height:1}
.rv__meta{font-size:1rem;color:var(--muted)}
.rv__grid{display:grid;gap:1.1rem;grid-template-columns:1fr}
@media(min-width:700px){.rv__grid{grid-template-columns:1fr 1fr}}
@media(min-width:1050px){.rv__grid{grid-template-columns:repeat(3,1fr)}}
/* No carousel. Every review is rendered in full, in the page, at once. */
.rv{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:1.2rem}
.rv p{font-size:1rem;margin-bottom:.9em}
.rv__who{font-size:.9rem;color:var(--muted);margin:0}
.rv__who b{color:var(--ink);font-weight:600}

/* ---------- FORM ---------- */
.form{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:1.4rem}
.field{margin-bottom:1.1rem}
.field label{display:block;font-weight:600;color:var(--navy);margin-bottom:.35rem;font-size:1rem}
.field .hint{display:block;font-weight:400;color:var(--muted);font-size:.88rem;margin-top:-.15rem;margin-bottom:.35rem}
input,select,textarea{
  width:100%;font:400 1.0625rem/1.4 var(--font-body);color:var(--ink);
  padding:.75rem .85rem;min-height:48px;
  border:1px solid #b9c1ca;border-radius:var(--radius);background:#fff;
}
textarea{min-height:8rem;resize:vertical}
input:focus,select:focus,textarea:focus{border-color:var(--navy);outline:3px solid var(--gold);outline-offset:1px}
.req{color:#a8322a}
.hp{position:absolute!important;left:-9999px!important;width:1px;height:1px;overflow:hidden}
.form__promise{background:var(--bg-sand);border-left:4px solid var(--gold);padding:.85rem 1rem;margin-bottom:1.1rem;font-size:1rem}
.form__promise p{margin:0}
.form__privacy{font-size:.88rem;color:var(--muted);margin:.85rem 0 0}
.err{background:#fdf4f3;border-left:4px solid #a8322a;padding:.85rem 1rem;margin-bottom:1.1rem}
.err ul{margin:.4em 0 0;padding-left:1.2em}

/* ---------- FIGURES ---------- */
figure{margin:1.8em 0}
figure img{border-radius:var(--radius);width:100%}
figcaption{font-size:.9rem;color:var(--muted);margin-top:.55rem}

/* ---------- FOOTER ---------- */
.ft{background:var(--navy);color:#ccd5de;font-size:1rem;margin-top:3rem}
.ft a{color:#e7ebef;text-decoration:none}
.ft a:hover{color:var(--gold);text-decoration:underline}
.ft__grid{display:grid;gap:1.9rem;grid-template-columns:1fr;padding-block:2.75rem}
@media(min-width:700px){.ft__grid{grid-template-columns:1fr 1fr}}
@media(min-width:1000px){.ft__grid{grid-template-columns:1.3fr 1fr 1fr 1fr}}
.ft h2,.ft .ft__h{color:#fff;font-size:1rem;font-family:var(--font-body);font-weight:700;letter-spacing:.06em;text-transform:uppercase;margin:0 0 .9rem}
.ft ul{list-style:none;margin:0;padding:0}
.ft li{margin-bottom:.5rem}
.ft__tel{display:block;color:#fff;font-weight:700;font-size:1.15rem;margin-bottom:.35rem;text-decoration:none}
.ft__tel:hover{color:var(--gold)}
.ft__tel span{display:block;font-size:.72rem;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--gold)}
.ft__hours{color:var(--gold);font-weight:600;margin:.15rem 0 .9rem}
.ft address{font-style:normal;line-height:1.6;margin-bottom:1rem}
.ft__social{display:flex;gap:.75rem;margin-top:1rem}
.ft__social a{display:inline-flex;align-items:center;justify-content:center;width:48px;height:48px;border:1px solid rgba(255,255,255,.28);border-radius:var(--radius)}
.ft__social svg{width:20px;height:20px;fill:currentColor}
.ft strong,.ft b{color:#fff}
.dark strong,.cta strong{color:#fff}
.ft__legal{border-top:1px solid rgba(255,255,255,.16);padding-block:1.5rem;font-size:.88rem;color:#9dabb8;line-height:1.7}
.ft__legal p{margin:0 0 .35em}

/* ---------- STICKY CONTACT BAR (mobile) ---------- */
/* Fixed to the bottom, visible at all times, never scrolls away.
   Three equal buttons, each at least 48px tall, icon plus text label.
   Body padding above compensates so it never covers content.
   env(safe-area-inset-bottom) keeps it clear of the iOS home indicator. */
.stickybar{
  position:fixed;left:0;right:0;bottom:0;z-index:150;
  display:grid;grid-template-columns:repeat(3,1fr);
  background:var(--navy);border-top:2px solid var(--gold);
  padding-bottom:env(safe-area-inset-bottom,0px);
  box-shadow:0 -2px 14px rgba(0,0,0,.28);
}
.stickybar a{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  min-height:var(--bar-h);padding:.45rem .25rem;
  color:#fff;text-decoration:none;font:700 1rem/1.15 var(--font-body);
  border-right:1px solid rgba(255,255,255,.16);
}
.stickybar a:last-child{border-right:0}
.stickybar a:hover,.stickybar a:focus-visible{background:var(--navy-80);color:var(--gold)}
.stickybar svg{width:22px;height:22px;fill:var(--gold);flex:none}
@media(min-width:900px){.stickybar{display:none}}

/* desktop floating quote button — stays visible as the page scrolls */
.floatq{display:none}
@media(min-width:900px){
  .floatq{
    display:inline-flex;position:fixed;right:1.5rem;bottom:1.5rem;z-index:150;
    box-shadow:0 6px 22px rgba(29,38,47,.32);
  }
}

/* ---------- UTILITIES ---------- */
.vh{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.lede{font-size:1.15rem;color:var(--ink)}
.center{text-align:center}
.mt0{margin-top:0}
.linklist{list-style:none;padding:0;columns:2;column-gap:1.5rem}
.linklist li{margin-bottom:.45em;break-inside:avoid}
@media(max-width:560px){.linklist{columns:1}}

/* ---------- PRINT (used by /price-guide/print/) ---------- */
@media print{
  body{padding:0;font-size:11pt;color:#000;background:#fff}
  .hdr,.nav,.stickybar,.floatq,.crumbs,.cta,.trustbar,.ft__social,.skip,.no-print{display:none!important}
  .ft{background:#fff;color:#000;margin-top:1rem;border-top:1px solid #000}
  .ft a{color:#000}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:9pt;color:#444}
  a[href^="/"]::after{content:""}
  h1,h2,h3{color:#000;page-break-after:avoid}
  table,figure,.note{page-break-inside:avoid}
  .wrap{max-width:100%;padding:0}
}

/* ---------- SELECTED WORK GALLERY ---------- */
/* Every photograph is shown in the page. No carousel, no lightbox dependency —
   a grid loads faster and nobody has to click to see the work. */
.gallery{display:grid;gap:1.2rem;grid-template-columns:1fr;margin-block:1.8rem}
@media(min-width:640px){.gallery{grid-template-columns:repeat(2,1fr)}}
@media(min-width:960px){.gallery{grid-template-columns:repeat(3,1fr)}}
.gallery figure{margin:0;display:flex;flex-direction:column}
.gallery figure img{aspect-ratio:4/3;object-fit:cover;width:100%}
.gallery figcaption{margin-top:.5rem;font-size:.95rem}

/* ============================================================================
   LOGO
   James's own artwork. The supplied file is a stacked logo on a solid navy
   tile, and that navy measures exactly #1D262F — the brand colour. The tile has
   been keyed out to real transparency (build/logo.py) and rebuilt as a
   horizontal lockup, so it sits on any dark shade without a visible box.
   ========================================================================== */
.hdr__logo{display:flex;align-items:center;padding:.35rem 0;flex:0 1 auto;min-width:0}
.hdr__logo img{height:46px;width:auto;max-width:100%}
@media(min-width:900px){.hdr__logo img{height:56px}}
.ft__logo{width:132px;height:auto;margin-bottom:1rem}

/* ============================================================================
   DARK THEME  —  <body class="t-dark">
   Currently on the homepage only, so the two can be compared side by side.
   Built on the same two brand colours: navy #1D262F and gold #C2A35A. The page
   sits a shade below the brand navy so that panels in #1D262F lift off it, and
   so the logo's own navy is never the darkest thing on screen.
   Every pairing below clears 4.5:1; the accessibility script checks it.
   ========================================================================== */
.t-dark{
  --d-bg:#0f151b;           /* page — a step below brand navy */
  --d-panel:#1a232c;        /* cards, form, table heads */
  --d-panel-2:#1D262F;      /* brand navy — alternating bands */
  --d-line:rgba(255,255,255,.13);
  --d-line-strong:rgba(255,255,255,.24);
  --d-text:#cfd8e1;         /* 12.6:1 on --d-bg */
  --d-strong:#ffffff;
  --d-muted:#a3b1be;        /* 7.6:1 on --d-bg */
  --gold-dark:#C2A35A;      /* on dark, the brand gold is the accessible one */
  background:var(--d-bg);
  color:var(--d-text);
}
.t-dark h1,.t-dark h2,.t-dark h3,.t-dark h4{color:var(--d-strong)}
.t-dark strong,.t-dark b{color:var(--d-strong)}
.t-dark main a:not(.btn){color:var(--gold-dark)}
.t-dark main a:not(.btn):hover{color:#e6d19a}
/* buttons keep their own colours on every theme */
.t-dark .btn--gold{color:var(--navy)}
.t-dark .btn--gold:hover{color:var(--navy)}
.t-dark hr{border-top-color:var(--d-line)}
.t-dark .lede{color:var(--d-strong)}
.t-dark blockquote{border-left-color:var(--d-line-strong);color:var(--d-muted)}
.t-dark main dl{background:rgba(255,255,255,.04)}
.t-dark main dd{color:var(--d-muted)}
.t-dark small,.t-dark figcaption,.t-dark .rv__who,.t-dark .form__privacy,
.t-dark .field .hint,.t-dark .rv__meta{color:var(--d-muted)}

/* bands */
.t-dark .tint{background:var(--d-panel-2)}
.t-dark .sand{background:var(--d-panel)}

/* hero — the photograph carries more of the frame on a dark page */
.t-dark .hero{background:var(--d-panel-2)}
.t-dark .hero__img{opacity:.5}
.t-dark .hero::after{background:linear-gradient(100deg,
  rgba(15,21,27,.9) 0%,rgba(15,21,27,.62) 52%,rgba(15,21,27,.3) 100%)}
.t-dark .trustbar{background:var(--d-panel-2);border-top-color:var(--d-line)}

/* breadcrumbs */
.t-dark .crumbs{border-bottom-color:var(--d-line);color:var(--d-muted)}
.t-dark .crumbs a{color:var(--d-muted)}
.t-dark .crumbs [aria-current=page]{color:var(--d-strong)}
.t-dark .crumbs li+li::before{color:var(--d-line-strong)}

/* cards and panels */
.t-dark .card,
.t-dark .tint .card,
.t-dark .rv,
.t-dark .form,
.t-dark .entry__col{background:var(--d-panel);border-color:var(--d-line)}
.t-dark .card p{color:var(--d-muted)}
.t-dark .entry__col--a{border-color:var(--d-line-strong)}
.t-dark .entry__col--b{border-color:var(--gold)}

/* calls to action — the gold panel is the loud one on a dark page */
.t-dark .cta{background:var(--d-panel-2);border:1px solid var(--d-line)}
.t-dark .cta--light{background:linear-gradient(180deg,#20303c 0%,#1a2630 100%);
  border:1px solid rgba(194,163,90,.4);color:var(--d-text)}
.t-dark .cta--light h2,.t-dark .cta--light h3{color:var(--d-strong)}
.t-dark .cta--light p{color:var(--d-text)}
.t-dark .cta--light .cta__trust{color:var(--d-muted)}
.t-dark .cta--light .btn--ghost{color:#fff;border-color:rgba(255,255,255,.7);
  background:rgba(0,0,0,.2)}
.t-dark .cta--light .btn--ghost:hover{background:#fff;color:var(--navy)}

/* notes */
.t-dark .note{background:var(--d-panel);border-left-color:var(--gold);color:var(--d-text)}
.t-dark .note--warn{background:#2a1b1a;border-left-color:#d4736a}

/* tables */
.t-dark table{color:var(--d-text)}
.t-dark th,.t-dark td{border-color:var(--d-line)}
.t-dark th{background:var(--d-panel);color:var(--d-strong)}
.t-dark caption{color:var(--d-muted)}

/* form */
.t-dark .field label{color:var(--d-strong)}
.t-dark input,.t-dark select,.t-dark textarea{background:#0d1319;color:var(--d-strong);
  border-color:#43505d}
.t-dark input::placeholder,.t-dark textarea::placeholder{color:#8fa0ae}
.t-dark input:focus,.t-dark select:focus,.t-dark textarea:focus{border-color:var(--gold)}
.t-dark .form__promise{background:var(--d-panel-2);border-left-color:var(--gold)}
.t-dark .err{background:#2a1b1a;border-left-color:#d4736a}

/* buttons — the outline button needs to be light on every dark surface */
.t-dark .btn--ghost{color:#fff;border-color:rgba(255,255,255,.7);background:rgba(0,0,0,.2)}
.t-dark .btn--ghost:hover{background:#fff;color:var(--navy);border-color:#fff}
.t-dark .btn--navy{background:#2a3a49;border-color:#2a3a49;color:#fff}
.t-dark .btn--navy:hover{background:#36495a;color:#fff}

/* reviews */
.t-dark .rv__head{border-bottom-color:var(--d-line)}
.t-dark .rv__score{color:var(--d-strong)}

/* gallery figures get a hairline so they do not float on the dark ground */
.t-dark .gallery figure img,.t-dark figure img{border:1px solid var(--d-line)}

/* footer sits at the very bottom of the scale so the page reads as layered */
.t-dark .ft{background:#0b1116;border-top:1px solid var(--d-line)}

/* Dark theme: put back the link colours that were deliberately not gold.
   The generic `.t-dark a` rule is more specific than the component rules, so
   these restore the intended hierarchy — gold is for links inside prose, not
   for every link on the page. */
.t-dark .cta__trust,.t-dark .trustbar{color:#dbe3ea}

/* The footer already changes colour, so it does not also need a gap above it. */
.t-dark .ft{margin-top:0}

/* ---------- PRICE MATCH GUARANTEE ---------- */
/* The badge is the picture; the promise is live text beside it, so it can be
   read aloud, indexed, and reflowed. On a phone the badge sits above the words
   rather than shrinking them. */
.pm{display:grid;gap:1.4rem;align-items:start;margin-block:1.6rem}
@media(min-width:720px){.pm{grid-template-columns:200px minmax(0,42rem);gap:2.6rem}}
.pm__badge{justify-self:center;display:flex;flex-direction:column;align-items:center;gap:.6rem;text-decoration:none;border-radius:var(--radius)}
.pm__badge img{width:180px;height:auto}
.pm__badge-cue{font-size:1rem;font-weight:600;color:var(--gold);text-decoration:underline;text-underline-offset:3px;text-align:center}
.pm__badge:hover .pm__badge-cue{color:#e6d19a}
@media(min-width:720px){.pm__badge{justify-self:start;position:sticky;top:7.5rem}
  .pm__badge img{width:200px}}
.pm__promise{
  font-family:var(--font-head);
  font-size:clamp(1.25rem,2.6vw,1.6rem);
  line-height:1.3;color:var(--navy);
  border-left:4px solid var(--gold);
  padding-left:1rem;margin-bottom:1.1em;text-wrap:balance;
}
.t-dark .pm__promise{color:#fff}

/* ============================================================================
   DROPDOWN NAVIGATION
   Every parent is a real link to its own page. The children appear on hover,
   on keyboard focus, or by pressing the caret — so nothing is reachable only
   by hovering, which would strand touchscreen and keyboard users.
   ========================================================================== */
.nav__list .has-sub{position:relative;display:flex;align-items:center;flex-wrap:wrap}
.subtog{
  display:inline-flex;align-items:center;justify-content:center;
  width:44px;min-height:48px;margin-left:-.35rem;
  background:transparent;border:0;cursor:pointer;color:#fff;border-radius:var(--radius);
}
.subtog svg{width:20px;height:20px;fill:currentColor;transition:transform .15s ease}
.has-sub.open > .subtog svg{transform:rotate(180deg)}
.subtog:hover{color:var(--gold)}

.sub{list-style:none;margin:0;padding:0}
.sub a{
  display:block;color:#e7ebef;text-decoration:none;font-weight:500;
  padding:.7rem .9rem;min-height:48px;font-size:1rem;
}
.sub a:hover,.sub a[aria-current=page]{background:rgba(255,255,255,.12);color:var(--gold)}

/* --- mobile: the submenu is an accordion inside the drawer --- */
@media(max-width:899px){
  .nav__list .has-sub{width:100%}
  .nav__list .has-sub > a{flex:1}
  .sub{display:none;width:100%;background:rgba(0,0,0,.22);border-radius:var(--radius);
       margin:0 0 .35rem}
  .has-sub.open > .sub{display:block}
  .sub a{padding-left:1.9rem}
}

/* --- desktop: a real dropdown panel --- */
@media(min-width:900px){
  .nav__list{align-items:stretch}
  .nav__list .has-sub{flex-wrap:nowrap}
  .subtog{width:26px;min-height:26px;padding:0}
  .sub{
    position:absolute;top:100%;left:0;z-index:120;
    min-width:15rem;padding:.4rem;
    background:var(--navy);border:1px solid rgba(255,255,255,.18);
    border-radius:0 0 var(--radius) var(--radius);
    box-shadow:0 14px 30px rgba(0,0,0,.42);
    opacity:0;visibility:hidden;transform:translateY(-6px);
    transition:opacity .13s ease, transform .13s ease, visibility .13s;
  }
  .has-sub:hover > .sub,
  .has-sub:focus-within > .sub,
  .has-sub.open > .sub{opacity:1;visibility:visible;transform:none}
  .has-sub:hover > a,.has-sub:focus-within > a{color:#e6d19a}
  /* keeps the pointer from falling through the gap between bar and panel */
  .has-sub::after{content:"";position:absolute;left:0;right:0;top:100%;height:8px}
}
@media(prefers-reduced-motion:reduce){.sub{transition:none}.subtog svg{transition:none}}

/* the dark theme keeps the same panel colour — it is already the brand navy */
.t-dark .sub{background:#16202a;border-color:rgba(255,255,255,.16)}

/* ---------- REVIEWS: "show all" ---------- */
.rv__more{margin-top:1.2rem}
.rv__more > summary{
  cursor:pointer;display:inline-flex;align-items:center;gap:.5rem;
  min-height:48px;padding:.7rem 1.15rem;
  border:2px solid var(--navy);border-radius:var(--radius);
  font-weight:700;color:var(--navy);list-style:none;
}
.rv__more > summary::-webkit-details-marker{display:none}
.rv__more > summary::after{content:"▾";font-size:1.1em;line-height:1}
.rv__more[open] > summary::after{content:"▴"}
.rv__more > summary:hover{background:var(--navy);color:#fff}
.rv__more .rv__grid{margin-top:1.1rem}
.t-dark .rv__more > summary{border-color:rgba(255,255,255,.5);color:#fff}
.t-dark .rv__more > summary:hover{background:#fff;color:var(--navy)}
.rv__who span{color:inherit}

/* The required-field marker is dark red, which fails on a dark background. */
.t-dark .req{color:#ff9a90}
.t-dark .note--warn{border-left-color:#ff9a90}
.t-dark .err{border-left-color:#ff9a90}

/* ---------- GALLERY ----------
   One picture at a time, arrows either side, thumbnails underneath. James was
   specific: "I don't want to have to click on every image and come out of it to
   go to the next one." So no lightbox — the large image is the page.
   Without JavaScript the stage hides and the thumbnails become an ordinary
   grid, so the page still works. .gal--live is added by the script. */
/* Break out of the 760px reading column. Photographs are the content on this
   page and a text measure is the wrong width for them.
   The two expressions have to agree exactly: the element is --gal-w wide and is
   pulled out by half the difference on EACH side. Setting the width and the
   margin from different expressions puts the whole gallery off-centre, and
   html{overflow-x:hidden} then hides the evidence rather than the bug. */
.prose > .gal{width:100%}
@media(min-width:860px){
  /* .prose is LEFT-aligned inside .wrap, not centred — so the gallery grows to
     the right rather than out of both sides. Centring it instead pushed the
     left-hand arrow off the screen. The 17px is a scrollbar allowance: 100vw
     counts the scrollbar and the wrap's content box does not. */
  .prose > .gal{
    --gal-w:min(calc(var(--wrap) - 4rem), calc(100vw - 4rem - 17px));
    width:var(--gal-w);
    margin-right:calc(var(--narrow) - var(--gal-w));
  }
}
/* MEASURED 30 September 2026: this block used to start .gal__stage at
   display:none and let the script reveal it. That produced a cumulative
   layout shift of 0.619 on a phone — a Core Web Vitals failure — because the
   whole stage appeared and shoved the thumbnails down the moment JavaScript
   ran. The stage is in the HTML with photograph one already in it, so it can
   simply be visible from the start. The script now only wires the arrows up.
   Anything that must not move before JavaScript runs is styled here, not
   under .gal--live. */
.gal__stage{display:block;position:relative}
/* On a phone the arrows sit ON the picture. Putting them either side works on a
   laptop and is wrong at 390px, where two 48px buttons take a quarter of the
   width and shrink the photograph to a stamp — which defeats the point of the
   page. Above 720px they move outside, where they never cover the work. */
.gal__nav{position:absolute;top:calc(50% - 32px);z-index:2;
  background:rgba(15,21,27,.72);color:#fff;border-color:rgba(255,255,255,.35);
  backdrop-filter:blur(2px)}
.gal__nav--prev{left:.4rem}
.gal__nav--next{right:.4rem}
/* with no JavaScript the arrows do nothing, so they are not offered */
.gal:not(.gal--live) .gal__nav{visibility:hidden}
@media(min-width:720px){
  .gal__stage{display:grid;grid-template-columns:auto 1fr auto;
    align-items:center;gap:.35rem}
  .gal__nav{position:static;background:var(--bg);color:var(--navy);
    border-color:var(--line);backdrop-filter:none}
  .t-dark .gal__nav{background:transparent;border-color:var(--d-line-strong);color:#fff}
}
.gal__fig{margin:0;min-width:0}
/* A fixed box so the page does not jump as you click through a library that
   mixes portrait and landscape. contain, never cover — cropping somebody's
   finished work to fit a shape is not a decision a photograph should make. */
.gal__img{width:100%;height:auto;background:var(--bg-tint);border-radius:var(--radius);
  aspect-ratio:3/2;max-height:74vh;object-fit:contain}
.t-dark .gal__img{background:#131b23}
.gal__nav{display:inline-flex;align-items:center;justify-content:center;width:48px;height:64px;
  padding:0;border:1px solid var(--line);background:var(--bg);color:var(--navy);
  border-radius:var(--radius);cursor:pointer}
.gal__nav svg{width:24px;height:24px}
.gal__nav:hover{background:var(--gold);border-color:var(--gold);color:var(--navy)}
.t-dark .gal__nav{background:transparent;border-color:var(--d-line-strong);color:#fff}
.t-dark .gal__nav:hover{background:var(--gold);color:var(--navy)}
.gal__cap{display:flex;flex-wrap:wrap;gap:.2rem .75rem;align-items:baseline;
  margin-top:.7rem;font-size:1rem;color:var(--muted)}
.t-dark .gal__cap{color:var(--d-muted)}
.gal__count{flex:0 0 auto;font-weight:700;color:var(--navy)}
.t-dark .gal__count{color:var(--gold)}
.gal__thumbs{list-style:none;margin:1.25rem 0 0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:.5rem}
/* The horizontal strip was replaced on 30 September 2026. Ninety-nine photographs
   in a 132px scroller read as one long blur and nobody could tell what they were
   clicking. A grid of larger thumbnails costs vertical space and is worth it. */
.gal__thumbs,.gal--live .gal__thumbs{display:grid;
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:.6rem;overflow:visible}
.gal__thumbs li{margin:0;min-width:0}
/* An <a>, not a <button> — with no JavaScript it still opens the photograph. */
.gal__thumb{display:block;padding:0;border:2px solid transparent;background:none;
  cursor:pointer;border-radius:var(--radius);overflow:hidden;width:100%;
  text-decoration:none;line-height:0}
.gal__thumb,.gal--live .gal__thumb{width:100%}
.gal__thumb img{width:100%;height:118px;object-fit:cover;display:block;
  transition:transform .18s ease}
.gal__thumb:hover img,.gal__thumb:focus-visible img{transform:scale(1.04)}
@media(min-width:760px){.gal__thumb img{height:132px}}
.gal__thumb[aria-current=true]{border-color:var(--gold)}
.gal__thumb:hover{border-color:var(--navy)}
.t-dark .gal__thumb:hover{border-color:#fff}
@media(min-width:760px){
  .gal--live .gal__stage{gap:.9rem}
  .gal__nav{width:56px;height:96px}
}

/* Portrait photographs in the reading column.
   Every photograph on the site was landscape until the showroom pictures
   arrived. A 3:4 portrait at the full 760px measure is over a thousand pixels
   tall — one picture fills a laptop screen and four of them bury the section
   they belong to. Capping the height and centring keeps them in proportion
   without cropping anybody's work, and landscape shots are untouched because
   their height never reaches the cap. */
main figure img{max-height:68vh;width:auto;margin-inline:auto}
@media(max-width:700px){main figure img{max-height:80vh}}


/* Gallery stage — sticky on a wide screen so the picture you are choosing stays
   visible while you scroll the thumbnails underneath it. */
@media(min-width:900px){
  .gal--live .gal__stage{position:sticky;top:1rem;z-index:2;
    background:var(--d-bg,#1D262F);padding-bottom:.5rem}
}
.gal__thumb[aria-current=true]{border-color:var(--gold);box-shadow:0 0 0 2px var(--gold)}


/* A face beside the call-to-action. The audit was blunt that this site had no
   photograph of a human being on it anywhere, and that a builder asking for a
   stranger's house keys should have one. Portrait left, words right, stacked on
   a phone so neither gets squeezed. */
.cta--face{display:grid;gap:1.25rem;align-items:center}
.cta__face{width:100%;max-width:220px;height:auto;border-radius:var(--radius);
  display:block;margin-inline:auto;justify-self:center}
@media(min-width:620px){
  .cta--face{grid-template-columns:200px 1fr;gap:1.6rem;align-items:center}
  .cta__face{max-width:200px;margin-inline:0}
}
.cta--face .cta__body>.mt0{margin-top:0}

/* The portrait on the About page sits in the reading column, capped so one
   photograph does not fill a laptop screen on its own. */
.fig--portrait img{max-width:340px;width:100%;height:auto;margin-inline:auto;display:block}


/* Archivo sets tighter and heavier than the serif it replaced. Without this the
   headings look loose and under-weight at the same sizes. */
h1,h2,h3,h4,.h-like{font-weight:700;letter-spacing:-.018em}
h1{font-weight:800;letter-spacing:-.025em}
.hero h1{letter-spacing:-.03em}


/* =====================================================================
   DESIGN PASS — 30 September 2026
   James picked: Archivo headings, the four-tier link and button rule,
   homepage option C, and the homepage rhythm fixes. What follows is all
   of that. Nothing here changes any page's content, only how it reads.
   ===================================================================== */

/* ---- 1. THE FOUR TIERS ---------------------------------------------
   The site had no rule about what a link looks like and what a button
   looks like, so the same job was being done three ways on one screen.
   Primary = the one action. Secondary = the alternative, outlined.
   Quiet = "more about this over here", with an arrow so it does not read
   as a stray underline. Inline = inside a sentence, and restrained. */

.btn{white-space:nowrap}

/* Secondary: a box, not a block of colour. Replaces every bare "call us"
   link, and the navy-on-navy button that did not read as a button. */
.btn--secondary{background:transparent;color:var(--d-strong);border:2px solid #55636f}
.btn--secondary:hover,.btn--secondary:focus-visible{border-color:var(--gold);color:var(--gold)}
.t-light .btn--secondary{color:var(--navy);border-color:#b9c2cb}
.t-light .btn--secondary:hover{border-color:var(--navy)}

/* Quiet: still a link, but it reads as a destination. */
.lnk{display:inline-flex;align-items:center;gap:.4rem;font-weight:600;
  color:var(--gold);text-decoration:none;
  border-bottom:1px solid rgba(194,163,90,.35);padding-bottom:2px}
.lnk:hover,.lnk:focus-visible{border-bottom-color:var(--gold)}
.lnk::after{content:"→";font-weight:400;transition:transform .15s ease}
.lnk:hover::after{transform:translateX(3px)}
.t-light .lnk{color:var(--gold-dark);border-bottom-color:rgba(122,95,40,.35)}

/* Inline: same colour as the sentence, gold rule underneath. Loud enough
   to be obviously a link, quiet enough that the sentence still reads.
   Descendant, not child — most of these sit inside <strong> or <em>. */
.prose a:not(.btn):not(.lnk):not([class]),
.prose strong > a:not(.btn):not(.lnk),
.prose em > a:not(.btn):not(.lnk){
  color:inherit;text-decoration:none;
  box-shadow:inset 0 -2px 0 rgba(194,163,90,.55);padding-bottom:1px}
.prose a:not(.btn):not(.lnk):not([class]):hover,
.prose strong > a:not(.btn):not(.lnk):hover,
.prose em > a:not(.btn):not(.lnk):hover{box-shadow:inset 0 -2px 0 var(--gold)}
.t-light .prose a:not(.btn):not(.lnk):not([class]),
.t-light .prose strong > a:not(.btn):not(.lnk){box-shadow:inset 0 -2px 0 rgba(122,95,40,.5)}
/* Never restyle links that are doing a different job. Only the underline is
   removed — the colour is left alone, because `color:revert` on an anchor hands
   it back to the browser default, which is blue, and it turned every button on
   the site blue. */
.prose .actions a,.prose .cta__btns a,.prose .gal__thumb,
.prose .rv a,.prose .figures a,.prose a.btn{box-shadow:none}

/* A row of actions. Primary first, secondary beside it, never three. */
.actions{display:flex;flex-wrap:wrap;gap:12px;margin:1.6rem 0 0}
.actions .btn{flex:0 1 auto}
@media(max-width:520px){.actions{flex-direction:column}.actions .btn{width:100%}}

/* ---- 2. HOMEPAGE RHYTHM --------------------------------------------
   Fourteen identical sections in one column is what made the page feel
   long. Alternating bands, one full-width moment and a numbers row give
   the eye something to measure progress against. */
.band{padding:clamp(2.5rem,6vw,4.5rem) 0}
.band--a{background:var(--d-bg)}
.band--b{background:var(--d-panel)}
.band > .wrap > .prose{max-width:var(--narrow,68ch);margin-inline:auto}
.band h2:first-child{margin-top:0}

/* The numbers, as a band rather than small print in a box. */
.figures{background:linear-gradient(180deg,#141d25,#111922);
  border-block:1px solid #26313c;padding:clamp(1.8rem,4vw,2.6rem) 0}
.figures ul{list-style:none;margin:0;padding:0;display:grid;gap:1.6rem;
  grid-template-columns:repeat(2,1fr);text-align:center}
@media(min-width:760px){.figures ul{grid-template-columns:repeat(4,1fr)}}
.figures li{margin:0}
.figures b{display:block;font:800 clamp(1.9rem,4.5vw,2.7rem)/1 var(--font-head);
  color:var(--gold);letter-spacing:-.02em}
.figures span{display:block;margin-top:.45rem;font-size:.95rem;color:var(--d-muted)}

/* The full-width moment. One per page — the point is that it is rare. */
.feature{margin:0;padding:0}
.feature__media{position:relative;background:#0b1015}
.feature__media img{display:block;width:100%;height:auto;max-height:70vh;object-fit:cover}
.feature__media video{display:block;width:100%;height:auto;max-height:80vh;background:#000}
.feature figcaption{max-width:64ch;margin:1.1rem auto 0;padding:0 1.25rem;
  color:var(--d-muted);font-size:.95rem;text-align:center}

/* Click to play. The film is 17MB — preload="none" means not one byte of
   it is fetched until somebody actually asks for it. */
.vplay{position:absolute;inset:0;display:grid;place-items:center;border:0;
  background:linear-gradient(180deg,rgba(11,16,21,.15),rgba(11,16,21,.55));
  cursor:pointer;width:100%;padding:0}
.vplay:hover .vplay__mark,.vplay:focus-visible .vplay__mark{transform:scale(1.07);
  background:var(--gold);color:#241d0c}
.vplay__mark{width:84px;height:84px;border-radius:50%;display:grid;place-items:center;
  background:rgba(15,21,27,.78);border:2px solid var(--gold);color:var(--gold);
  transition:transform .18s ease,background .18s ease,color .18s ease}
.vplay__mark svg{width:32px;height:32px;margin-left:5px}
.vplay__label{position:absolute;top:clamp(1rem,4vw,2.2rem);left:0;right:0;
  color:#fff;font:600 1.05rem/1.4 var(--font-body);text-align:center;letter-spacing:.01em;
  text-shadow:0 2px 14px rgba(0,0,0,.85);padding:0 1.25rem}

.small{font-size:.95rem;color:var(--d-muted)}
.t-light .small{color:var(--muted)}
.mt{margin-top:.7rem}
.btn--wide + .small.mt{margin-top:.8rem}

.feature__media{position:relative}
.vposter{display:block;width:100%;height:auto;max-height:80vh;object-fit:cover}
.feature__media video{display:block;width:100%;height:auto;max-height:80vh;background:#000}
.feature__media video:not([data-playing]){position:absolute;inset:0;opacity:0;pointer-events:none}
.feature__media video[data-playing]{position:static;opacity:1;pointer-events:auto}

/* Footer navigation is a list of links, not words in a sentence, so the inline
   exception to the 44px target size does not apply to it. On a phone these were
   coming out around 20px tall and sitting on top of each other. */
@media(max-width:760px){
  .ft__grid ul li{margin:0}
  .ft__grid ul a,.ft__tel{display:flex;align-items:center;min-height:44px;padding:2px 0}
  .ft__legal a{display:inline-flex;align-items:center;min-height:44px}
}
.ft__tel{min-height:44px;display:inline-flex;align-items:center}


/* =====================================================================
   NAVIGATION, 30 September 2026
   Twelve top-level items wrapped onto two rows and put 211px of header
   above every page. Six items fit one row. Nothing was deleted — the
   services moved into a panel, so every service and town page keeps its
   link for crawling as well as for browsing.
   ===================================================================== */

@media(min-width:1000px){
  .hdr__in{padding-block:.85rem}
  .nav__list > li > a{padding:.85rem .95rem;font-size:1.02rem;letter-spacing:.005em}
  /* Centred, which is what James asked for and what suits six items. The phone
     numbers sit right so the bar stays balanced rather than lopsided. */
  .nav .wrap{display:flex;align-items:center;justify-content:center;gap:1rem;position:relative}
  .nav__list{flex-wrap:nowrap;justify-content:center}
  .nav .nav__tel{position:absolute;right:0;top:50%;transform:translateY(-50%)}

  /* The services panel. One row of the bar opens a proper board rather than
     a thin column of links — that is the bit that stops it feeling cheap.
     These selectors have to out-rank the generic .sub rules above, which
     position every submenu against its own <li> and cap it at 15rem. */
  .nav__list .has-mega{position:static}
  .nav{position:relative}
  .nav .nav__list .mega{
    position:absolute;left:0;right:0;top:100%;width:auto;min-width:0;
    z-index:60;display:none;grid-template-columns:1.15fr 1fr .85fr;gap:2.2rem;
    padding:2rem clamp(1.25rem,4vw,3rem) 2.4rem;
    background:#16202a;border:0;border-top:2px solid var(--gold);border-radius:0;
    box-shadow:0 22px 44px rgba(0,0,0,.5);
    opacity:1;visibility:visible;transform:none}
  .nav .nav__list .has-mega:hover > .mega,
  .nav .nav__list .has-mega:focus-within > .mega,
  .nav .nav__list .mega[data-open]{display:grid}
  .mega__col ul{list-style:none;margin:0;padding:0}
  .mega__col li{margin:0 0 .9rem}
  .mega__h{margin:0 0 1.1rem;font:700 .76rem/1 var(--font-body);letter-spacing:.14em;
    text-transform:uppercase;color:var(--gold)}
  .nav__list .mega__svc{display:block;color:var(--d-strong);text-decoration:none;
    font:600 1.02rem/1.3 var(--font-body);padding:0;min-height:0;background:none}
  .nav__list .mega__svc:hover,.nav__list .mega__svc:focus-visible{color:var(--gold);background:none}
  .mega__towns{display:block;margin-top:.25rem;font-size:.86rem;color:var(--d-muted)}
  .nav__list .mega__towns a{display:inline;padding:0;min-height:0;font-weight:400;
    color:var(--d-muted);text-decoration:none;background:none;white-space:nowrap}
  .nav__list .mega__towns a:hover{color:var(--gold);background:none;text-decoration:underline}
  .mega__col--aside{border-left:1px solid #2b3742;padding-left:2rem}
  .mega__note{font-size:.9rem;color:var(--d-muted);margin:.9rem 0 0;line-height:1.5}
  .nav__list .mega__col--aside .btn{margin-top:1.1rem;color:#241d0c;min-height:48px}
  .nav__list .mega__note a{display:inline;padding:0;min-height:0;background:none}
}

/* On a phone the panel is just an accordion like every other submenu. */
@media(max-width:999px){
  .mega{display:none}
  .mega[data-open]{display:block}
  .mega__col{margin-bottom:1.25rem}
  .mega__col ul{list-style:none;margin:0;padding:0}
  .mega__col li{margin:0}
  .mega__h{margin:.4rem 0 .5rem;font:700 .74rem/1 var(--font-body);letter-spacing:.14em;
    text-transform:uppercase;color:var(--gold)}
  .mega__svc{display:flex;align-items:center;min-height:44px;color:var(--d-strong);
    text-decoration:none;font-weight:600}
  /* The towns read as one line of text under each service, not as a column of
     inline-flex boxes with the separators stranded between them. */
  .mega__towns{display:block;padding:.15rem 0 .75rem;font-size:.92rem;line-height:2.1;
    color:var(--d-muted)}
  .nav__list .mega__towns a{display:inline;min-height:0;padding:.45rem .15rem;
    font-weight:400;color:var(--d-muted);text-decoration:none;background:none}
  .mega__col--aside .btn{width:100%}
}

/* contact form error banner (revealed only when send.php bounces back) */
.form__err{border:2px solid #c0564d;background:rgba(192,86,77,.12);border-radius:8px;
  padding:.9rem 1.1rem;margin:0 0 1.2rem}
.form__err p{margin:0}

/* two photographs side by side (vehicles on the About page) */
.figpair{display:grid;gap:1.1rem;grid-template-columns:1fr;margin:1.4rem 0}
@media(min-width:700px){.figpair{grid-template-columns:1fr 1fr}}
.figpair figure{margin:0}
.figpair img{width:100%;height:auto}

/* gallery introduction: the page used to be 128 words of text behind
   99 photographs, which is thin for a page we would like to rank */
.gal-intro{max-width:64ch;margin:0 0 1.6rem}
.gal-intro p{margin:.7rem 0}

/* ---------------------------------------------------------------------
   Tap targets. Measured 1 October 2026 in a real browser: eight controls
   came out between 20px and 23px tall on desktop, just under the 24px
   WCAG 2.2 minimum. Mobile was already fine — the desktop rules are what
   shrink them.

   None of this changes the layout. The dropdown toggles get an invisible
   pseudo-element that extends the clickable box outwards; the inline links
   get vertical padding, which on an inline element grows the hit area
   without altering the line box. Nothing moves by a pixel.
   --------------------------------------------------------------------- */
@media(min-width:1000px){
  .subtog{position:relative}
  .subtog::after{content:"";position:absolute;left:-1px;right:-1px;top:-3px;bottom:-3px}
}
.crumbs a,.crumbs [aria-current=page]{display:inline-block;padding-block:.15rem}
.cta__trust a{display:inline-block;padding-block:.15rem}
.trustbar a{display:inline-block;padding-block:.15rem}
.rv__meta a{padding-block:.2rem}

/* replaces the last of the inline style attributes, flagged 1 October */
.ft__h--gap{margin-top:1.5rem}
.hint--inline{display:inline;font-weight:400}

/* "leave a review" ask, under the testimonials. His review count is the one
   place competitors are well ahead — the link is live from 1 October 2026. */
.rv__ask{margin:1.8rem 0 0;padding:1.2rem 1.3rem;border:1px solid var(--d-line);
  border-radius:var(--radius);max-width:62ch}
.rv__ask p{margin:0 0 .8rem}
.rv__ask p:last-child{margin:0}

/* ---------------------------------------------------------------------
   Cookie consent bar. Sits above the sticky call bar on a phone and above
   the floating quote button on a laptop, so it never covers either. Hidden
   until the script shows it, and gone for good once answered.
   --------------------------------------------------------------------- */
.ckbar{position:fixed;left:0;right:0;bottom:0;z-index:200;
  background:var(--navy);color:#e7ebef;border-top:2px solid var(--gold);
  padding:1rem 1rem calc(1rem + env(safe-area-inset-bottom,0px));
  display:grid;gap:.8rem;align-items:center;font-size:.95rem;line-height:1.5}
.ckbar[hidden]{display:none}
.ckbar__txt{margin:0;max-width:70ch}
.ckbar__txt a{color:var(--gold)}
.ckbar__btns{display:flex;gap:.6rem;flex-wrap:wrap}
.ckbar .btn{padding:.6rem 1.1rem;font-size:.95rem}
@media(min-width:720px){
  .ckbar{grid-template-columns:1fr auto;gap:1.4rem;padding-inline:1.5rem}
}
/* While the bar is up, lift the mobile call bar and the floating quote button
   clear of it. The height is measured by the script and set as --ckbar-h,
   because the bar's height depends on the text wrapping and a fixed guess got
   it wrong: at 390px the bar is 186px tall and a 7.5rem lift left it sitting
   on top of the call buttons. */
.has-ckbar .stickybar{bottom:calc(var(--ckbar-h, 0px) + .25rem)}
.has-ckbar .floatq{bottom:calc(var(--ckbar-h, 0px) + 1rem)}
