/* ═══════════════════════════════════════════════════════════
   BP LANDSCAPING — site design layer
   Ported from the approved prototype onto the CMS block markup.

   Loads LAST, after styles.css and the inline theme <style>, so the
   :root block below is the site's source of truth for design tokens.
   Bespoke components only — anything the theme schema already does
   well (widths, gaps) is left to the framework variables.

   Section map (widget css_class → component):
     bp-hero     banner   home hero, full-bleed video
     bp-mast     banner   interior page masthead
     bp-intro    overview lead-in prose
     bp-reels    videos   9:16 horizontal video rail
     bp-svc      strips   numbered service rows
     bp-off      rte      off-season block, winter palette
     bp-logos    photos   client logo row
     bp-cards    pages    card grid
     bp-cta      rte      closing call to action
   ═══════════════════════════════════════════════════════════ */

/* ── 1. TOKENS ───────────────────────────────────────────── */
/* NOTE ON UNITS: styles.css sets html{font-size:62.5%}, so 1rem = 10px on
   this site. The prototype was authored against a 16px root, so every rem
   below is the prototype's value x1.6 and lands on the same pixel size.
   Anything added here later must follow the same convention. */
:root{
  /* Brand — sampled from the BP mark */
  --brand:#008240; --brand-700:#04693A; --brand-500:#0E9A52;
  --brand-300:#63C692; --brand-100:#D7EDE1;

  /* Growing season */
  --ink:#0A120E; --ink-2:#101B15; --ink-3:#182720;
  --bone:#F5F2EB; --bone-2:#ECE7DC; --bone-3:#DED7C7;
  --mute:#5E6B62;

  /* Off season */
  --slate:#0B141B; --slate-2:#101E28;
  --ice:#E9F1F6; --ice-2:#B6CFDE; --frost:#79ADCC;

  /* Semantic — re-pointed per section theme */
  --bp-bg:var(--bone);
  --bp-fg:var(--ink);
  --bp-soft:var(--mute);
  --bp-line:rgba(10,18,14,.14);
  --bp-accent:var(--brand);

  /* Type */
  --sans:"Inter Tight",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --serif:"Instrument Serif",ui-serif,Georgia,"Times New Roman",serif;

  --fs-display:clamp(4.64rem,7.6vw,13.12rem);
  --fs-h1:clamp(3.84rem,6.2vw,10.24rem);
  --fs-h2:clamp(3.12rem,4.2vw,6.4rem);
  --fs-h3:clamp(2.16rem,2.1vw,3.2rem);
  --fs-lead:clamp(1.696rem,1.35vw,2.272rem);
  --fs-body:clamp(1.6rem,.55vw + 1.36rem,1.8rem);
  --fs-label:1.1rem;

  /* Space */
  --sec:clamp(8rem,11vw,17.6rem);
  --gut:clamp(2rem,4.4vw,7.2rem);
  --maxw:1560px;

  /* Motion */
  --e-out:cubic-bezier(.22,1,.36,1);
  --e-soft:cubic-bezier(.4,0,.2,1);
  --t-fast:.18s; --t-mid:.32s;

  /* ── Framework variable mapping ───────────────────────────
     Re-point the theme schema's own variables so untouched
     framework components inherit the BP palette for free. */
  --color-bg:var(--bone);
  --color-bg-light:var(--bone-2);
  --color-bg-dark:var(--ink);
  --color-main:var(--brand);
  --color-body:var(--ink);
  --color-heading:var(--ink);
  --color-border:var(--bp-line);

  --font-heading:var(--sans);
  --font-body:var(--sans);
  --font-accent:var(--serif);

  --section-inline:var(--gut);
  --content-width-xl:var(--maxw);
  --content-width-lg:1280px;
  --content-width-md:940px;
  --content-width-sm:720px;
}

/* Winter. Applied by the season engine to <html>. Only the dark
   surfaces swing to the ice palette — the whole page turning blue
   would read as a different brand, not a different season. */
html.season-winter{
  --brand-300:#8FD0AE;
}

/* ── 2. BASE ─────────────────────────────────────────────── */
body{
  background:var(--bone);
  color:var(--ink);
  font-family:var(--sans);
  font-size:var(--fs-body);
  line-height:1.6;
  letter-spacing:-.005em;
  -webkit-font-smoothing:antialiased;
}

/* styles.css sets html,body{height:100%} AND body{overflow-x:hidden
   !important}. Together those make the BODY the scroll container: the page
   still scrolls visually, but window.scrollY stays pinned at 0, which breaks
   the sticky-header logic and anything else that measures scroll position.
   The !important means the overflow cannot be overridden, so drop the height
   constraint instead — with height:auto the body grows with its content and
   the root scrolls again, exactly as the framework intends elsewhere. */
html,body{height:auto}
body{min-height:100svh}

h1,h2,h3,h4{
  font-family:var(--sans);
  font-weight:400;
  line-height:1.02;
  letter-spacing:-.03em;
  text-wrap:balance;
}
p{text-wrap:pretty}

/* The signature: an italic serif word inside a sans headline.
   Authored in the CMS by wrapping the accent word in <em>. */
/* The banner title is a div.h0 and the CMS already wraps the accent word
   in <b>, so the signature treatment hooks straight onto existing markup —
   no extra editing needed for hero headlines. */
h1 em,h2 em,h3 em,.h2 em,
.h0 em,.h0 b,
.banner-content .h0 b{
  font-family:var(--serif);
  font-style:italic;
  font-weight:400;
  letter-spacing:-.015em;
  padding-right:.06em;
}

::selection{background:var(--brand);color:#fff}

:focus-visible{
  outline:2px solid var(--bp-accent);
  outline-offset:3px;
  border-radius:2px;
}

/* ── 3. SECTION RHYTHM + THEMES ──────────────────────────── */
/* One selector per theme at matching specificity so nothing in
   this file cancels a sibling rule out. */
section.content_container{
  padding-block:var(--sec);
  padding-inline:var(--gut);
  background:var(--bp-bg);
  color:var(--bp-fg);
}
section.content_container.compact{padding-block:clamp(4.8rem,6vw,8.8rem)}
section.content_container.spacious{padding-block:clamp(11.2rem,14vw,22.4rem)}

section.content_container.light{
  --bp-bg:var(--bone-2);
}
section.content_container.dark{
  --bp-bg:var(--ink);
  --bp-fg:var(--bone);
  --bp-soft:rgba(245,242,235,.62);
  --bp-line:rgba(245,242,235,.16);
  --bp-accent:var(--brand-300);
}
section.content_container.colour{
  --bp-bg:var(--ink);
  --bp-fg:var(--bone);
  --bp-soft:rgba(245,242,235,.7);
  --bp-line:rgba(245,242,235,.18);
  --bp-accent:var(--brand-300);
}

section.content_container .editable_content{color:var(--bp-fg)}
section.content_container h1,
section.content_container h2,
section.content_container h3{color:var(--bp-fg)}

/* ── 4. EYEBROW ──────────────────────────────────────────── */
/* The CMS emits the eyebrow as <p class="h6">. The prototype pairs
   it with a short accent rule; there is no element for one, so it
   is drawn with ::before rather than asking editors to add markup. */
.editable_content p.h6{
  display:flex;
  align-items:center;
  gap:1.12rem;
  margin:0 0 clamp(2rem,2.4vw,3.2rem);
  font-family:var(--sans);
  font-size:var(--fs-label);
  font-weight:500;
  letter-spacing:.19em;
  text-transform:uppercase;
  line-height:1;
  color:var(--bp-soft);
}
.editable_content p.h6::before{
  content:"";
  flex:none;
  width:clamp(24px,3vw,48px);
  height:1px;
  background:var(--bp-accent);
}

/* ── 5. HEADINGS + PROSE ─────────────────────────────────── */
.editable_content h2{
  font-size:var(--fs-h2);
  letter-spacing:-.035em;
  max-width:20ch;
  margin:0 0 clamp(1.6rem,2vw,2.4rem);
}
.editable_content h3{
  font-size:var(--fs-h3);
  letter-spacing:-.03em;
  margin:0 0 1.2rem;
}
.editable_content p{
  max-width:62ch;
  margin:0 0 1.76rem;
  color:var(--bp-soft);
}
/* The lead paragraph. Not `p:first-of-type` — the eyebrow is itself a <p>,
   so first-of-type matches the eyebrow and the lead never got sized. The
   paragraph that follows the heading is the reliable hook. */
.editable_content h2 + p,
.editable_content .h2 + p{
  font-size:var(--fs-lead);
  line-height:1.55;
}
.editable_content > *:last-child{margin-bottom:0}

/* ── 6. BUTTONS ──────────────────────────────────────────── */
/* The fill rises from the bottom on hover — the prototype's one
   piece of button personality, kept and applied everywhere. */
a.button,
.btn-wrapper a.button,
span.button,
button.button{
  position:relative;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:1.12rem;
  min-height:52px;
  padding:0 2.56rem;
  border:1px solid var(--brand);
  border-radius:999px;
  background:var(--brand);
  color:#fff;
  font-family:var(--sans);
  font-size:1.4rem;
  font-weight:500;
  letter-spacing:.02em;
  text-transform:none;
  overflow:hidden;
  isolation:isolate;
  transition:color var(--t-mid) var(--e-soft),
             border-color var(--t-mid) var(--e-soft),
             transform var(--t-fast) var(--e-out);
}
a.button::before,
span.button::before,
button.button::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:-1;
  border-radius:inherit;
  background:var(--ink);
  transform:translateY(101%);
  transition:transform .45s var(--e-out);
}
a.button::after{
  content:"→";
  font-size:1em;
  line-height:1;
  transition:transform var(--t-mid) var(--e-out);
}
a.button:hover::before,
a.button:focus-visible::before{transform:translateY(0)}
a.button:hover::after{transform:translateX(4px)}
a.button:hover,
a.button:focus-visible{color:#fff;border-color:var(--ink)}
a.button:active{transform:scale(.975)}

/* On dark surfaces the solid green button loses its edge — outline it. */
section.content_container.dark a.button,
section.content_container.colour a.button{
  background:transparent;
  border-color:rgba(245,242,235,.35);
  color:var(--bone);
}
section.content_container.dark a.button::before,
section.content_container.colour a.button::before{background:var(--brand)}
section.content_container.dark a.button:hover,
section.content_container.colour a.button:hover{border-color:var(--brand);color:#fff}

.btn-wrapper{margin-top:0;}

/* ── 6b. PRELOADER ───────────────────────────────────────── */
/* Hidden unless <html> carries .js-loading, which the gate script in
   metatags-icons-css.php adds once per session and never with JS off or
   under reduced motion. Default-hidden is the safe direction: a broken
   gate shows no loader rather than a permanent cover. */
.bp-loader{display:none}

html.js-loading .bp-loader{
  position:fixed;
  inset:0;
  z-index:120;
  display:grid;
  place-items:center;
  background:var(--ink);
  color:var(--brand-300);
  transition:transform .9s var(--e-out);
  /* Pure-CSS failsafe. If bp.js never runs — blocked, 404, JS error — the
     loader still clears itself rather than covering the site forever. The
     0s duration with a 6s delay is a one-shot "jump to the end state". */
  animation:bpLoaderFailsafe 0s 6s forwards;
}
@keyframes bpLoaderFailsafe{
  to{transform:translateY(-101%);visibility:hidden}
}
html.js-loading .bp-loader.is-done{transform:translateY(-101%)}

.bp-loader__inner{
  display:grid;
  justify-items:center;
  gap:2rem;
}
.bp-loader__mark{width:7.4rem;height:8.1rem}
.bp-loader__path{
  stroke-dasharray:2400;
  stroke-dashoffset:2400;
  animation:bpLoaderDraw 1.5s var(--e-soft) forwards;
}
@keyframes bpLoaderDraw{to{stroke-dashoffset:0}}

.bp-loader__meta{
  font-size:var(--fs-label);
  letter-spacing:.34em;
  text-transform:uppercase;
  color:rgba(245,242,235,.5);
  opacity:0;
  animation:bpLoaderFade .5s .5s forwards;
}
@keyframes bpLoaderFade{to{opacity:1}}

.bp-loader__bar{
  position:absolute;
  left:var(--gut);
  right:var(--gut);
  bottom:clamp(3.2rem,5vh,5.6rem);
  height:1px;
  background:rgba(245,242,235,.16);
  overflow:hidden;
}
.bp-loader__fill{
  display:block;
  height:100%;
  width:100%;
  background:var(--brand-300);
  transform:scaleX(0);
  transform-origin:left;
  animation:bpLoaderFill 1.5s var(--e-soft) forwards;
}
@keyframes bpLoaderFill{to{transform:scaleX(1)}}

/* Winter: the mark and the progress bar pick up the ice accent. */
html.season-winter.js-loading .bp-loader{
  background:var(--slate);
  color:var(--frost);
}
html.season-winter.js-loading .bp-loader__fill{background:var(--frost)}

/* ── 7. HEADER ───────────────────────────────────────────── */
/* Transparent over the hero, solid once scrolled. .is-stuck is set
   by bp.js. */
header.full_header{
  position:fixed;
  top:0;left:0;right:0;
  z-index:90;
  background:transparent;
  color:var(--bone);
  border-bottom:1px solid transparent;
  transition:background .45s var(--e-soft),
             color .4s var(--e-soft),
             border-color .45s var(--e-soft),
             transform .5s var(--e-out);
}
header.full_header .jqueryslidemenu{
  display:flex;
  align-items:center;
  gap:clamp(1.6rem,3vw,4rem);
  max-width:var(--maxw);
  margin-inline:auto;
  padding:clamp(1.44rem,1.6vw,2.16rem) 0;
  transition:padding .4s var(--e-soft);
}

header.full_header .logo{
  flex:none;
  display:flex;
  align-items:center;
  min-height:44px;
}
/* The supplied logo is a dark mark; invert it while the header floats
   over the video, restore it once the bar goes solid. */
header.full_header .logo img{
  width:100%;
  height:auto;
  filter:brightness(0) invert(1);
  transition:filter .4s var(--e-soft),height .4s var(--e-soft);
}
header.full_header.is-stuck .logo img{filter:none}

header.full_header nav{
  flex:0 1 auto;
  width:auto;
  margin-left:auto;
}
header.full_header nav ul{
  display:flex;
  align-items:center;
  justify-content:flex-end;
  gap:clamp(1.44rem,1.9vw,3.2rem);
  width:auto;
  margin:0;
  list-style:none;
}
header.full_header nav ul li{margin:0;padding:0}
header.full_header nav a{
  position: relative;
  display: block;
  padding: 0.56rem 0;
  font-size: 1.6rem;
  font-weight: 400;
  letter-spacing: .01em;
  color: var(--color-bone);
  white-space: nowrap;
}
header.full_header nav a::after{
  content:"";
  position:absolute;
  left:0;bottom:0.16rem;
  width:100%;height:1px;
  background:currentColor;
  transform:scaleX(0);
  transform-origin:right;
  transition:transform .4s var(--e-out);
}
header.full_header nav a:hover::after,
header.full_header nav a:focus-visible::after{transform:scaleX(1);transform-origin:left}
header.full_header nav li.Selected > a{color:var(--brand-300)}
header.full_header nav li.Selected > a::after{transform:scaleX(1);transform-origin:left}
header.full_header.is-stuck a.header-phone-link,
header.full_header.is-stuck  nav a{
  color: var(--color-ink);
}
header.full_header .header-cta{
  flex:none;
  min-height:44px;
  padding:0 2rem;
  font-size:1.6rem;
  background:transparent;
  border-color:currentColor;
  color:inherit;
  margin: 0;
}
header.full_header .header-cta::before{background:var(--brand)}
header.full_header .header-cta:hover{color:#fff;border-color:var(--brand)}
header.full_header .header-cta::after{content:none}

/* The .top-header utility bar duplicates the footer and breaks the
   overlay by pushing the hero down. Its one unique item, the phone, now
   renders inside the main header (includes/header.php). */
.top-header{display:none}

header.full_header .header-phone-link{
  display:none;
  align-items:center;
  gap:0.8rem;
  flex:none;
  min-height:44px;
  font-weight:400;
  font-variant-numeric:tabular-nums;
  color:inherit;
  white-space:nowrap;
  font-size: 1.6rem;
  text-decoration: none;
}
header.full_header .header-phone-link i{font-size:.8em;opacity:.7}
header.full_header .header-phone-link:hover{color:var(--brand-300)}
header.full_header.is-stuck .header-phone-link:hover{color:var(--brand)}
@media (min-width:900px){
  header.full_header .header-phone-link{display:inline-flex}
}

/* Mobile header shares the overlay treatment. */
/* The framework swaps the two headers at 1024px — stay inside that
   breakpoint or both render at once on desktop. */
@media (max-width:1023.98px){
  header.mobile_header{
    position: sticky;
    top: 0;
    left: 0;
    right: 0;
    z-index: 90;
    display: flex;
    align-items: center;
    gap: 1.2rem;
    padding: 1.2rem var(--gut);
    background: transparent;
    color: var(--bone);
    transition: background .45s var(--e-soft), color .4s var(--e-soft);
    margin-bottom: -94px;
    box-shadow: none;
  }
  header.mobile_header .logo_area img{
    width:auto;
    height:40px;
    filter:brightness(0) invert(1);
  }
  header.mobile_header.is-stuck{
    background:rgba(245,242,235,.94);
    -webkit-backdrop-filter:blur(14px) saturate(1.4);
    backdrop-filter:blur(14px) saturate(1.4);
    color:var(--ink);
  }
  header.mobile_header.is-stuck .logo_area img{filter:none}
  header.mobile_header .mobile-call,
  header.mobile_header .menu-btn{
    display:grid;
    place-content:center;
    width:44px;height:44px;
    color:inherit;
  }
  header.mobile_header .mobile-cta{
    min-height:40px;
    padding:0 1.6rem;
    font-size:1.2rem;
    background:var(--brand);
    border-color:var(--brand);
    color:#fff;
  }
  header.mobile_header .mobile-cta::after{content:none}
  body:not(.has-hero) header.mobile_header{
    position:sticky;
    background:var(--bone);
    color:var(--ink);
  }
  body:not(.has-hero) header.mobile_header .logo_area img{filter:none}
}

/* Tight desktop widths: recover space before anything is allowed to wrap.
   Below 1024px the framework swaps to the mobile header anyway. */
@media (min-width:1024px) and (max-width:1319.98px){
  header.full_header .jqueryslidemenu{gap:1.6rem}
  header.full_header nav ul{gap:1.4rem}
  header.full_header .logo {width:8rem}
}
@media (min-width:1024px) and (max-width:1179.98px){
  header.full_header .header-phone-link{display:none}
}

/* Scrolled state */
header.full_header.is-stuck{
  background:rgba(245,242,235,.9);
  -webkit-backdrop-filter:blur(14px) saturate(1.4);
  backdrop-filter:blur(14px) saturate(1.4);
  border-bottom-color:rgba(10,18,14,.08);
  color:var(--ink);
}
header.full_header.is-stuck .jqueryslidemenu{padding-block:1.12rem}
header.full_header.is-stuck nav li.Selected > a,
header.full_header.is-stuck nav a:hover{color:var(--brand)}
header.full_header.is-hidden{transform:translateY(-100%)}

/* Interior pages have no full-bleed hero behind the bar, so it can
   never be transparent there. bp.js adds .has-hero to <body>.
body:not(.has-hero) header.full_header{
  position:sticky;
  background:var(--bone);
  color:var(--ink);
  border-bottom-color:var(--bp-line);
}
body:not(.has-hero) header.full_header .logo img{filter:none}*/

/* ── 8. HERO (banner) ────────────────────────────────────── */
.banner-container-constrained{
  position:relative;
  isolation:isolate;
  background:var(--ink);
  /* Height comes from the slide's own min-height below, not the theme's
     --hero-height, so the two cannot disagree. */
  height:auto;
}
.banner-container-constrained .ms-banner-constrained{
  margin:0;
  padding:0;
  list-style:none;
}
.banner-container-constrained li.ms-overlay{
  position:relative;
  display:flex;
  flex-direction:column;
  justify-content:flex-end;
  height:auto;
  min-height:100svh;
  padding:calc(env(safe-area-inset-top) + 11.2rem) 0 5.6rem;
  color:var(--bone);
  overflow:hidden;
}
.banner-container-constrained .img-wrapper{
  position:absolute;
  inset:0;
  z-index:0;
  overflow:hidden;
}
.banner-container-constrained .img-wrapper img,
.banner-container-constrained .banner-video{
  width:100%;
  height:100%;
  object-fit:cover;
}
/* Three stacked scrims: a top bar for the header, a left column so the
   headline always lands on a dark field whatever frame the video is on,
   and a bottom anchor for the meta bar. */
.banner-container-constrained .img-wrapper::after{
  content:"";
  position:absolute;
  inset:0;
  background:
    linear-gradient(180deg,rgba(10,18,14,.74) 0%,rgba(10,18,14,.26) 24%,rgba(10,18,14,.18) 42%,rgba(10,18,14,.80) 80%,rgba(10,18,14,.95) 100%),
    linear-gradient(90deg,rgba(10,18,14,.66) 0%,rgba(10,18,14,.4) 38%,transparent 72%),
    radial-gradient(120% 80% at 15% 85%,rgba(4,60,32,.5),transparent 62%);
}
html.season-winter .banner-container-constrained .img-wrapper::after{
  background:
    linear-gradient(180deg,rgba(11,20,27,.76) 0%,rgba(11,20,27,.28) 24%,rgba(11,20,27,.2) 42%,rgba(11,20,27,.82) 80%,rgba(11,20,27,.96) 100%),
    linear-gradient(90deg,rgba(11,20,27,.68) 0%,rgba(11,20,27,.42) 38%,transparent 72%),
    radial-gradient(120% 80% at 15% 85%,rgba(22,48,63,.55),transparent 62%);
}

.banner-container-constrained .banner-details{
  position:relative;
  z-index:1;
  width:100%;
  max-width:var(--maxw);
  margin-inline:auto;
  padding:0 var(--gut) clamp(4rem,6vh,7.2rem);
  z-index: 3;
}
.banner-container-constrained .banner-content{max-width:min(100%,1100px)}

.banner-container-constrained .banner-content .h6,
.banner-container-constrained .banner-content .small-title{
  display:flex;
  align-items:center;
  gap:1.12rem;
  margin-bottom:clamp(1.6rem,2vw,2.4rem);
  font-size:var(--fs-label);
  font-weight:500;
  letter-spacing:.19em;
  text-transform:uppercase;
  color:rgba(245,242,235,.72);
}
.banner-container-constrained .banner-content .h6::before,
.banner-container-constrained .banner-content .small-title::before{
  content:"";
  flex:none;
  width:clamp(24px,3vw,48px);
  height:1px;
  background:var(--brand-300);
}

.banner-container-constrained .banner-content h1,
.banner-container-constrained .banner-content h2,
.banner-container-constrained .banner-content .h1{
  font-size:var(--fs-display);
  font-weight:400;
  letter-spacing:-.042em;
  line-height:.95;
  max-width:17ch;
  color:var(--bone);
  margin:0 0 clamp(2rem,2.6vw,3.2rem);
}
.banner-container-constrained .banner-content .h0{
  font-size:var(--fs-display);
  font-weight:400;
  letter-spacing:-.042em;
  line-height:.95;
  max-width:17ch;
  color:var(--bone);
  margin:0 0 clamp(2rem,2.6vw,3.2rem);
}
.bp-mast .banner-content .h0{
  font-size:clamp(3.84rem,6.4vw,10.56rem);
  letter-spacing:-.042em;
  line-height:.96;
  max-width:16ch;
}
.banner-container-constrained .banner-content p{
  font-size:var(--fs-lead);
  line-height:1.5;
  color:rgba(245,242,235,.82);
  max-width:52ch;
  margin:0 0 clamp(2.8rem,3vw,4rem);
}
.banner-container-constrained .banner-content a.button{
  background:var(--brand);
  border-color:var(--brand);
  color:#fff;
  min-height:60px;
  padding:0 3.2rem;
  font-size:1.5rem;
}
.banner-container-constrained .banner-content a.button::before{background:var(--ink)}

/* Hero meta bar. Content comes from data attributes on the banner so
   it stays editable without new widget markup — bp.js writes them. */
/* Pinned to the foot of the hero rather than appended after it — the bar is
   a sibling of the slide list, so in flow it would land below the fold. */
.banner-container-constrained .bp-herobar{
  position:absolute;
  left:0;right:0;bottom:0;
  z-index:2;
  width:100%;
  max-width:var(--maxw);
  margin-inline:auto;
  padding:1.76rem var(--gut) calc(env(safe-area-inset-bottom) + 1.76rem);
  border-top:1px solid rgba(245,242,235,.16);
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1.6rem;
  font-size:var(--fs-label);
  letter-spacing:.19em;
  text-transform:uppercase;
  color:rgba(245,242,235,.62);
}
.banner-container-constrained .bp-herobar span{white-space:nowrap}
.banner-container-constrained .bp-herobar span:first-child{display:none}
@media (min-width:600px){
  .banner-container-constrained .bp-herobar span:first-child{display:block;width: 20.4rem;}
}
.banner-container-constrained .bp-herobar a{
  text-decoration: none;
    color: rgba(245, 242, 235, .62);
}
.banner-container-constrained .bp-herobar a:hover{
  color: white;
}
/* Carousel chrome — quiet it down to match the prototype. */
.banner-previous,.banner-next{
  width:52px;height:52px;
  display:grid;place-content:center;
  border:1px solid rgba(245,242,235,.28);
  border-radius:999px;
  background:transparent;
  color:var(--bone);
  transition:background var(--t-mid),color var(--t-mid),border-color var(--t-mid);
}
.banner-previous:hover,.banner-next:hover{
  background:var(--bone);color:var(--ink);border-color:var(--bone);
}
.banner_pagination{gap:0.8rem}
.banner_pagination div i{font-size:7px;opacity:.4;color:var(--bone)}
.banner_pagination div.active i{opacity:1;color:var(--brand-300)}

/* Interior page masthead — same banner widget, shorter, no video. */
/* header.php also emits .inner_header, the framework's own inner-page
   banner image. Every section here uses a banner widget as its masthead,
   so that block is a second hero stacked above the real one — 284px of
   duplicate art pushing the actual title below the fold. */
.inner_header{display:none}

/* styles.css sets height:var(--hero-height) on the CONTAINER (100svh).
   Release it there — releasing it on the slide alone does nothing. */
.bp-mast,
.bp-mast .ms-banner-constrained,
.bp-mast .ms-banner-constrained > li{height:auto;min-height:0}
.bp-mast li.ms-overlay{
  height:auto;
  min-height:clamp(420px,56svh,620px);
  padding-top:calc(env(safe-area-inset-top) + 6.4rem);
}
.bp-mast .banner-content h1,
.bp-mast .banner-content h2{
  font-size:clamp(3.84rem,6.4vw,10.56rem);
  letter-spacing:-.042em;
  line-height:.96;
  max-width:16ch;
}
.bp-mast .bp-herobar{display:none}

/* ── 9. OVERVIEW / INTRO ─────────────────────────────────── */
.bp-intro .editable_content{
  display:grid;
  gap:clamp(2.4rem,3vw,4.8rem);
  align-items:start;
}
@media (min-width:1000px){
  .bp-intro .editable_content{
    grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
    /* Tight rows, wide columns: the eyebrow should sit right on top of the
       heading, not float a full section gap above it. */
    row-gap:clamp(1.6rem,2vw,2.4rem);
    column-gap:clamp(4.8rem,6vw,11.2rem);
    align-content:start;
  }
  /* Eyebrow + heading stack in the left column; the prose fills the right
     and starts level with the eyebrow, as in the prototype.

     `grid-row:1 / -1` looked right but silently did nothing useful: -1
     resolves against the EXPLICIT grid, and with no grid-template-rows the
     explicit grid has no line 2, so the prose collapsed into row 1 and its
     full height became row 1's height — which pushed the heading 235px
     below the eyebrow instead of 43px. Span counts avoid the whole issue. */
  .bp-intro .editable_content{grid-template-rows:auto auto}
  .bp-intro .editable_content p.h6{grid-column:1;grid-row:1;margin-bottom:0}
  .bp-intro .editable_content h2{grid-column:1;grid-row:2;align-self:start;margin-bottom:0}
  .bp-intro .editable_content p:not(.h6){
    grid-column:2;
    grid-row:1 / span 2;
    align-self:start;
    /* The prototype drops the prose a touch below the eyebrow so it reads
       as a second voice rather than a second column of the same line. */
    padding-top:1.6rem;
    margin-bottom:0;
  }
  /* Any further paragraphs simply follow underneath in the right column. */
  .bp-intro .editable_content p:not(.h6) ~ p:not(.h6){
    grid-row:auto;
    padding-top:0;
    margin-top:1.76rem;
  }
}
.bp-intro .editable_content h2{max-width:15ch}

/* ── 10. STRIPS ──────────────────────────────────────────── */
section.content_container.strip-list-wrapper{padding-inline:var(--gut)}
.strip-list-wrapper > .editable_content{
  max-width:var(--maxw);
  margin-inline:auto;
  padding-bottom:clamp(4rem,5vw,6.4rem);
}
.strip-list{
  display:grid;
  gap:clamp(2.8rem,3.5vw,5.6rem);
  align-items:center;
  max-width:var(--maxw);
  margin-inline:auto;
  padding-block:clamp(2.4rem,3vw,4rem);
  border-top:1px solid var(--bp-line);
}
.strip-list:first-of-type{border-top:0}
@media (min-width:900px){
  .strip-list{
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    gap:clamp(4.8rem,6vw,9.6rem);
  }
  /* Alternate the image side so a long run of strips has a rhythm
     instead of a hard left edge all the way down. */
  .strip-list:nth-of-type(even) > .img-wrapper{order:2}
}
.strip-list > .img-wrapper{
  position:relative;
  overflow:hidden;
  aspect-ratio:4/3;
}
.strip-list > .img-wrapper img{
  width:100%;height:100%;
  object-fit:cover;
  transition:transform .9s var(--e-out);
}
.strip-list:hover > .img-wrapper img{transform:scale(1.04)}
.strip-list > .content{max-width:56ch}

/* styles.css sets .strip-list .editable_content{width:calc(60% - 8rem)} for
   its own 40/60 absolute-image layout. The selector is unscoped, so it also
   hits the NESTED .editable_content inside it — the copy ends up at 60% of
   60%, which is what squeezed descriptions to a word per line. Both layouts
   here size their own columns, so the width is released. */
.strip-list .editable_content{width:auto}
.strip-list > .content{display:block}

/* The empty .anchor div is a scroll target, not content. Left as a grid item
   it silently eats the first cell and pushes the image and copy out of their
   columns. Absolutely positioned children are not grid items, so it keeps
   working as a fragment target without taking part in the layout. */
.strip-list > .anchor{
  position:absolute;
  top:0;
  left:0;
  width:0;
  height:0;
}

/* Numbered service rows — used where the strips genuinely are a
   sequence of named services, set by the bp-svc class. */
.bp-svc .strip-list{
  grid-template-columns:none;
  gap:1.6rem 2.4rem;
  border-top:1px solid var(--bp-line);
  padding-block:clamp(2.4rem,3.4vw,4.16rem);
}
.bp-svc .strip-list > .img-wrapper{display:none}
.bp-svc .strip-list > .content{max-width:none}
.bp-svc .strip-list h3{
  font-size:clamp(2.32rem,3.1vw,4.64rem);
  letter-spacing:-.035em;
  transition:transform .5s var(--e-out);
}
.bp-svc .strip-list:hover h3{transform:translateX(10px)}

/* ── 10b. SERVICE ROWS (.bp-services) ────────────────────── */
/* The prototype's #services: a ruled list rather than a gallery. The
   numbering is real information here — these are the service tiers in the
   order the business sells them — so the counter earns its place.
   Images are suppressed: the row is a name and a promise, and the strips
   only carry placeholder art anyway. */
section.content_container.bp-services{
  counter-reset:bpsvc;
}
/* styles.css zebra-stripes strips with .strip-list:nth-of-type(2n). These
   rows are separated by rules, not blocks of colour — a banded second row
   breaks the list into pairs. */
.bp-services .strip-list,
.bp-services .strip-list:nth-of-type(2n){background:transparent}
.bp-services > .editable_content{
  max-width:var(--maxw);
  margin-inline:auto;
  padding-bottom:clamp(3.2rem,5vw,5.6rem);
}

.bp-services .strip-list{
  counter-increment:bpsvc;
  position:relative;
  display:grid;
  align-items:start;
  gap:1.44rem 2rem;
  grid-template-columns:auto 1fr;
  grid-template-areas:
    "no title"
    "desc desc";
  max-width:var(--maxw);
  margin-inline:auto;
  padding-block:clamp(2.4rem,3.4vw,4.16rem);
  border-top:1px solid var(--bp-line);
  border-bottom:0;
  transition:color var(--t-mid) var(--e-soft);
}
.bp-services .strip-list:last-of-type{
  border-bottom:1px solid var(--bp-line);
}

/* The green rule that sweeps across the row on hover. Sits on the row's
   own bottom edge, so it reads as the rule lighting up. */
.bp-services .strip-list::after{
  content:"";
  position:absolute;
  left:0;right:0;bottom:-1px;
  height:1px;
  background:var(--brand);
  transform:scaleX(0);
  transform-origin:left;
  transition:transform .6s var(--e-out);
}
.bp-services .strip-list:hover::after,
.bp-services .strip-list:focus-within::after{transform:scaleX(1)}

/* The number. */
.bp-services .strip-list::before{
  content:counter(bpsvc,decimal-leading-zero);
  grid-area:no;
  align-self:start;
  padding-top:.55em;
  font-size:var(--fs-label);
  letter-spacing:.2em;
  color:var(--bp-soft);
  font-variant-numeric:tabular-nums;
}

/* The row's own image is not laid out inline — it is the source for the
   hover preview below. Kept in the DOM so the markup, alt text and any
   lightbox wiring are untouched. */
.bp-services .strip-list > .img-wrapper{
  position:absolute;
  width:0;
  height:0;
  overflow:hidden;
  opacity:0;
  pointer-events:none;
}

/* Hover preview. The prototype's answer to "a service list that still shows
   the work": one floating panel that follows the cursor and swaps its image
   to whichever row is hovered, rather than a column of thumbnails competing
   with the type. bp.js builds and drives it. */
.bp-svc-ghost{
  position:fixed;
  top:0;
  left:0;
  z-index:5;
  width:min(20vw,29rem);
  aspect-ratio:4/3;
  border-radius:3px;
  overflow:hidden;
  pointer-events:none;
  opacity:0;
  transform:translate3d(-50%,-50%,0) scale(.92);
  transition:opacity .35s var(--e-soft),transform .5s var(--e-out);
  will-change:transform,opacity;
  box-shadow:0 30px 70px -30px rgba(10,18,14,.6);
}
.bp-svc-ghost.is-on{opacity:1}
.bp-svc-ghost img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
/* No cursor to follow, and no room to spare. */
@media (max-width:899px),(pointer:coarse){
  .bp-svc-ghost{display:none}
}
@media (prefers-reduced-motion:reduce){
  .bp-svc-ghost{display:none}
}


.bp-services .strip-list > .content{
  display:contents;
  max-width:none;
}
.bp-services .strip-list .editable_content{width:auto}
.bp-services .strip-title{
  grid-area:title;
  margin:0;
  font-size:clamp(2.32rem,3.1vw,4.64rem);
  font-weight:400;
  letter-spacing:-.035em;
  line-height:1.02;
  transition:transform .5s var(--e-out);
}
.bp-services .strip-list > .content > .editable_content{
  grid-area:desc;
  min-width:0;
}
.bp-services .strip-list .editable_content p{
  margin:0;
  font-size:1.5rem;
  line-height:1.6;
  color:var(--bp-soft);
  max-width:52ch;
}

.bp-services .strip-list:hover,
.bp-services .strip-list:focus-within{color:var(--brand-700)}

@media (min-width:900px){
  .bp-services .strip-list{
    grid-template-columns:8rem minmax(0,1.05fr) minmax(0,1fr) auto;
    grid-template-areas:"no title desc arrow";
    align-items:center;
    gap:clamp(2.4rem,3vw,5.6rem);
  }
  .bp-services .strip-list::before{align-self:center;padding-top:0}
  .bp-services .strip-list:hover .strip-title,
  .bp-services .strip-list:focus-within .strip-title{transform:translateX(10px)}
}

/* The arrow. Only ever rendered when the row actually has somewhere to go —
   bp.js promotes a link out of the description into this slot. A circle
   that leads nowhere is decoration, so no link means no arrow. */
.bp-services .bp-svc__go{
  grid-area:arrow;
  justify-self:start;
  width:4.6rem;
  height:4.6rem;
  display:grid;
  place-content:center;
  flex:none;
  border:1px solid var(--bp-line);
  border-radius:999px;
  color:inherit;
  font-size:1.5rem;
  line-height:1;
  transition:background var(--t-mid),color var(--t-mid),
             border-color var(--t-mid),transform .45s var(--e-out);
}
@media (min-width:900px){
  .bp-services .bp-svc__go{justify-self:end}
}
.bp-services .strip-list:hover .bp-svc__go,
.bp-services .strip-list:focus-within .bp-svc__go{
  background:var(--brand);
  border-color:var(--brand);
  color:#fff;
  transform:rotate(45deg);
}

/* ── 10c. SERVICE ROWS — Pages widget variant ────────────────
   Some services sections (e.g. Commercial Landscaping) are a Pages
   widget rather than the strips widget, so they ship .flex > .card
   markup instead of .strip-list. Re-skin that markup into the same
   ruled, numbered list — same rule, same hover sweep, same arrow,
   same hover-preview ghost (bp.js targets .card too). */
.bp-services .flex{
  display:block;
}
.bp-services .card{
  counter-increment:bpsvc;
  position:relative;
  display:grid;
  align-items:start;
  gap:1.44rem 2rem;
  grid-template-columns:auto 1fr;
  grid-template-areas:
    "no title"
    "desc desc";
  max-width:var(--maxw);
  margin-inline:auto;
  padding:clamp(2.4rem,3.4vw,4.16rem) 0;
  border-radius:0;
  background:none;
  box-shadow:none;
  overflow:visible;
  border-top:1px solid var(--bp-line);
  border-right:0;
  border-left:0;
  border-bottom:0;
  color:inherit;
  text-decoration:none;
  transition:color var(--t-mid) var(--e-soft);
}
.bp-services .card:last-of-type{
  border-bottom:1px solid var(--bp-line);
}
.bp-services .card::after{
  content:"";
  position:absolute;
  left:0;right:0;bottom:-1px;
  height:1px;
  background:var(--brand);
  transform:scaleX(0);
  transform-origin:left;
  transition:transform .6s var(--e-out);
}
.bp-services .card:hover::after,
.bp-services .card:focus-within::after{transform:scaleX(1)}
.bp-services .card::before{
  content:counter(bpsvc,decimal-leading-zero);
  grid-area:no;
  align-self:start;
  padding-top:.55em;
  font-size:var(--fs-label);
  letter-spacing:.2em;
  color:var(--bp-soft);
  font-variant-numeric:tabular-nums;
}
.bp-services .card > .img-wrapper{
  position:absolute;
  width:0;
  height:0;
  overflow:hidden;
  opacity:0;
  pointer-events:none;
}
.bp-services .card > .content-wrapper{
  display:contents;
  padding:0;
}
.bp-services .card .cf-title{
  grid-area:title;
  margin:0;
  font-size:clamp(2.32rem,3.1vw,4.64rem);
  font-weight:400;
  letter-spacing:-.035em;
  line-height:1.02;
  transition:transform .5s var(--e-out);
}
.bp-services .card .cf-title a{
  color:inherit;
  text-decoration:none;
}
.bp-services .card p{
  grid-area:desc;
  min-width:0;
  margin:0;
  font-size:1.5rem;
  line-height:1.6;
  color:var(--bp-soft);
  max-width:52ch;
}
.bp-services .card:hover,
.bp-services .card:focus-within{color:var(--brand-700)}

@media (min-width:900px){
  .bp-services .card{
    grid-template-columns:8rem minmax(0,1.05fr) minmax(0,1fr) auto;
    grid-template-areas:"no title desc arrow";
    align-items:center;
    gap:clamp(2.4rem,3vw,5.6rem);
  }
  .bp-services .card::before{align-self:center;padding-top:0}
  .bp-services .card:hover .cf-title,
  .bp-services .card:focus-within .cf-title{transform:translateX(10px)}
}

/* The Pages widget's "Learn More" button becomes the same arrow-circle
   as the strips widget's bp-svc__go. Label stays for assistive tech,
   visually replaced by the arrow glyph. */
.bp-services .card .button{
  grid-area:arrow;
  justify-self:start;
  width:4.6rem;
  height:4.6rem;
  display:grid;
  place-content:center;
  flex:none;
  margin:0;
  border:1px solid var(--bp-line);
  border-radius:999px;
  background:none;
  color:transparent;
  font-size:1.5rem;
  line-height:1;
  text-decoration:none;
  transition:background var(--t-mid),color var(--t-mid),
             border-color var(--t-mid),transform .45s var(--e-out);
}
.bp-services .card .button::after{
  content:"→";
  position:absolute;
  inset:0;
  display:grid;
  place-content:center;
  color:var(--ink);
}
.bp-services .card:hover .button::after,
.bp-services .card:focus-within .button::after{color:#fff}
@media (min-width:900px){
  .bp-services .card .button{justify-self:end}
}
.bp-services .card:hover .button,
.bp-services .card:focus-within .button{
  background:var(--brand);
  border-color:var(--brand);
  transform:rotate(45deg);
}
.bp-services .card:hover .button::after,
.bp-services .card:focus-within .button::after{
  transform:rotate(-45deg);
}

/* ── 11. VIDEO RAIL (videos widget) ──────────────────────── */
.bp-reels{
  --bp-bg:var(--ink);
  --bp-fg:var(--bone);
  --bp-soft:rgba(245,242,235,.58);
  --bp-line:rgba(245,242,235,.18);
  --bp-accent:var(--brand-300);
  padding-inline:0;
}
.bp-reels > .editable_content,
.bp-reels > .content > .editable_content{
  max-width:var(--maxw);
  margin-inline:auto;
  padding-inline:var(--gut);
  padding-bottom:clamp(3.2rem,4vw,5.6rem);
}
.bp-reels .swipebox_video_full{
  display:flex;
  gap:clamp(1.2rem,1.6vw,2.4rem);
  padding-inline:var(--gut);
  overflow-x:auto;
  overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  scroll-padding-left:var(--gut);
  scrollbar-width:none;
}
.bp-reels .swipebox_video_full::-webkit-scrollbar{display:none}
.bp-reels .swipebox_video_gallery{
  position:relative;
  flex:0 0 auto;
  width:min(74vw,340px);
  aspect-ratio:9/16;
  scroll-snap-align:start;
  overflow:hidden;
  border-radius:3px;
  background:var(--ink-3);
  isolation:isolate;
  display:block;
}
@media (min-width:768px){
  .bp-reels .swipebox_video_gallery{width:clamp(280px,26vw,400px)}
}
.bp-reels .swipebox_video_gallery img{
  width:100%;height:100%;
  object-fit:cover;
  filter:saturate(.9);
  transition:transform .8s var(--e-out),filter .5s var(--e-soft);
}
.bp-reels .swipebox_video_gallery::after{
  content:"";
  position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,rgba(10,18,14,.35),transparent 34%,transparent 58%,rgba(10,18,14,.72));
}
.bp-reels .swipebox_video_gallery:hover img,
.bp-reels .swipebox_video_gallery:focus-visible img{transform:scale(1.06);filter:saturate(1.05)}
/* Background preview. The widget stores Vimeo links and a poster, not an
   mp4, so the looping preview is Vimeo's own background player: no controls,
   muted, looping. bp.js injects it only while the card is on screen.

   pointer-events:none is load-bearing — the card is still a link to the
   lightbox, and without it every click would land on the iframe instead. */
.bp-reels .swipebox_video_gallery .bp-reel-bg{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  border:0;
  z-index:0;
  pointer-events:none;
  filter:saturate(.9);
  opacity:0;
  transition:opacity .6s var(--e-soft);
}
/* Only revealed once the player confirms it is ready. Until then — and
   forever, if the video is private or embedding is blocked — the poster
   underneath is what shows. */
.bp-reels .swipebox_video_gallery .bp-reel-bg.is-ready{opacity:1}

@media (prefers-reduced-motion:reduce){
  .bp-reels .swipebox_video_gallery .bp-reel-bg{display:none}
}

/* Play affordance drawn in CSS — the widget emits no play button. */
.bp-reels .swipebox_video_gallery::before{
  content:"▶";
  position:absolute;z-index:2;
  left:50%;top:50%;
  translate:-50% -50%;
  width:64px;height:64px;
  display:grid;place-content:center;
  padding-left:4px;
  font-size:18px;
  border-radius:999px;
  background:rgba(245,242,235,.14);
  -webkit-backdrop-filter:blur(8px);
  backdrop-filter:blur(8px);
  border:1px solid rgba(245,242,235,.4);
  color:var(--bone);
  transition:transform .45s var(--e-out),background .3s;
}
.bp-reels .swipebox_video_gallery:hover::before,
.bp-reels .swipebox_video_gallery:focus-visible::before{
  transform:scale(1.1);
  background:var(--brand);
}

/* ── 12. CLIENT LOGOS (photos widget) ────────────────────── */
.bp-logos{--bp-bg:var(--bone-2)}
.bp-logos .flex{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:clamp(3.2rem,7vw,9.6rem);
  max-width:var(--maxw);
  margin-inline:auto;
  padding-block:clamp(3.2rem,4vw,5.6rem);
  border-top:1px solid var(--bp-line);
}
.bp-logos .flex > *{flex:0 0 auto;width:auto;max-width:22rem}
.bp-logos img{
  width:auto;
  height:clamp(26px,3.6vw,44px);
  object-fit:contain;
  filter:grayscale(1) contrast(.85);
  opacity:.55;
  transition:filter .5s var(--e-soft),opacity .5s var(--e-soft),transform .5s var(--e-out);
}
.bp-logos li:hover img,
.bp-logos a:hover img{filter:none;opacity:1;transform:translateY(-3px)}

/* Certification badges read as marks, not logos — keep them colour. */
.bp-creds img{filter:none;opacity:.85}

/* ── 13. CARDS (pages widget) ────────────────────────────── */
.bp-cards .card{
  display:block;
  background:transparent;
  border:0;
  border-top:1px solid var(--bp-line);
  padding-top:2.4rem;
  transition:color var(--t-mid);
}
.bp-cards .card .img-wrapper{
  position:relative;
  overflow:hidden;
  aspect-ratio:4/5;
  margin-bottom:2rem;
}
.bp-cards .card .img-wrapper img{
  width:100%;height:100%;
  object-fit:cover;
  transition:transform .9s var(--e-out);
}
.bp-cards .card:hover .img-wrapper img{transform:scale(1.05)}
.bp-cards .card .content-wrapper h3,
.bp-cards .card .content-wrapper .h3{
  font-size:var(--fs-h3);
  letter-spacing:-.03em;
  margin-bottom:0.96rem;
}
.bp-cards .card:hover{color:var(--brand-700)}
.bp-cards .card .button{
  min-height:0;
  padding:0;
  background:none;
  border:0;
  border-radius:0;
  color:var(--bp-accent);
  font-size:var(--fs-label);
  letter-spacing:.19em;
  text-transform:uppercase;
}
.bp-cards .card .button::before{content:none}

/* ── 14. OFF-SEASON BLOCK ────────────────────────────────── */
/* The one place the winter palette takes over regardless of season —
   it is literally the off-season mention. */
section.content_container.bp-off{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  background:
    radial-gradient(120% 90% at 50% -10%,#16303f 0%,transparent 58%),
    linear-gradient(180deg,var(--slate-2),var(--slate) 62%);
  --bp-fg:var(--ice);
  --bp-soft:rgba(233,241,246,.62);
  --bp-accent:var(--frost);
  --bp-line:rgba(233,241,246,.16);
  color:var(--ice);
}
section.content_container.bp-off .editable_content h2{color:var(--ice)}
.bp-off .bp-snow,
.bp-off .bp-pollen{
  position:absolute;
  inset:0;
  z-index:0;
  pointer-events:none;
}
.bp-off .content{position:relative;z-index:1}
.bp-off a.button{
  background:transparent;
  border-color:rgba(233,241,246,.32);
  color:var(--ice);
}
.bp-off a.button::before{background:var(--ice)}
.bp-off a.button:hover{color:var(--slate);border-color:var(--ice)}

/* In summer the off-season block promotes winter work, so it keeps the
   ice palette. In winter it promotes landscaping — swing it back to
   the growing-season palette so the two never look identical. The
   winter-only widget can also opt in explicitly with `bp-off-summer`,
   which swaps the snowfall for drifting pollen and leaves (bp.js). */
html.season-winter section.content_container.bp-off,
section.content_container.bp-off.bp-off-summer{
  background:
    radial-gradient(120% 90% at 50% -10%,#12331f 0%,transparent 58%),
    linear-gradient(180deg,var(--ink-2),var(--ink) 62%);
  --bp-fg:var(--bone);
  --bp-soft:rgba(245,242,235,.62);
  --bp-accent:var(--brand-300);
  --bp-line:rgba(245,242,235,.16);
  color:var(--bone);
}
html.season-winter section.content_container.bp-off .editable_content h2,
section.content_container.bp-off.bp-off-summer .editable_content h2{color:var(--bone)}
html.season-winter .bp-off .bp-snow,
.bp-off.bp-off-summer .bp-snow{display:none}
html.season-winter .bp-off a.button,
.bp-off.bp-off-summer a.button{border-color:rgba(245,242,235,.32);color:var(--bone)}
html.season-winter .bp-off a.button::before,
.bp-off.bp-off-summer a.button::before{background:var(--bone)}
html.season-winter .bp-off a.button:hover,
.bp-off.bp-off-summer a.button:hover{color:var(--ink);border-color:var(--bone)}

/* ── 15. CLOSING CTA ─────────────────────────────────────── */
section.content_container.bp-cta{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  min-height:clamp(460px,72svh,760px);
  display:grid;
  align-items:center;
  background:var(--ink);
  --bp-fg:var(--bone);
  --bp-soft:rgba(245,242,235,.7);
  --bp-accent:var(--brand-300);
  --bp-line:rgba(245,242,235,.18);
  color:var(--bone);
}
.bp-cta .content{position:relative;z-index:1;max-width:var(--maxw)}
.bp-cta .editable_content h2{
  font-size:var(--fs-h1);
  letter-spacing:-.04em;
  line-height:.98;
  max-width:15ch;
  color:var(--bone);
}
.bp-cta .editable_content p{
  font-size:var(--fs-lead);
  color:rgba(245,242,235,.8);
  max-width:54ch;
}

/* ── 16. FORMS ───────────────────────────────────────────── */
.form-wrapper,
form .form-row{max-width:var(--maxw);margin-inline:auto}
form label{
  display:block;
  margin-bottom:0.8rem;
  font-size:var(--fs-label);
  font-weight:500;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--bp-soft);
}
form input[type="text"],
form input[type="email"],
form input[type="tel"],
form input[type="number"],
form select,
form textarea{
  width:100%;
  min-height:56px;
  padding: 2.4rem .8rem .8rem;
  background:transparent;
  border:1px solid var(--bp-line);
  border-radius:3px;
  font-family:var(--sans);
  font-size:1.6rem;
  color:var(--bp-fg);
  transition:border-color var(--t-mid),background var(--t-mid);
}
form textarea{min-height:160px;resize:vertical}
form input:focus,
form select:focus,
form textarea:focus{
  border-color:var(--brand);
  background:rgba(255,255,255,.6);
  outline:none;
}
form input::placeholder,
form textarea::placeholder{color:var(--bp-soft);opacity:.7}
form button.button{
  border-radius:999px;
  min-height:5.6rem;
  padding:0 3.2rem;
}
form button[type="submit"],
form input[type="submit"]{
  min-height:56px;
  padding:0 3.2rem;
  border:1px solid var(--brand);
  border-radius:999px;
  background:var(--brand);
  color:#fff;
  font-family:var(--sans);
  font-size:1.5rem;
  font-weight:500;
  letter-spacing:.02em;
  cursor:pointer;
  transition:background var(--t-mid),border-color var(--t-mid),transform var(--t-fast);
}
form button[type="submit"]:hover,
form input[type="submit"]:hover{background:var(--ink);border-color:var(--ink)}
form button[type="submit"]:active{transform:scale(.98)}

/* Checkbox / radio rows. The conditional "Multiple Properties" control
   was overlapping the field beneath it. */
form fieldset{
  border:0;
  margin:0;
  padding:0;
  min-width:0;
  display:flex;
  flex-wrap:wrap;
  gap:1.6rem 2.4rem;
}
form .form-checkbox-option,
form label.form-checkbox-option{
  position:static;
  display:flex;
  align-items:center;
  gap:.8rem;
  min-height:4.4rem;
  margin:0;
  font-size:1.5rem;
  font-weight:400;
  letter-spacing:0;
  text-transform:none;
  color:var(--bp-fg);
  cursor:pointer;
}
form .form-checkbox-option input[type="checkbox"],
form .form-checkbox-option input[type="radio"]{
  width:1.8rem;
  height:1.8rem;
  min-height:0;
  margin:0;
  padding:0;
  flex:none;
  accent-color:var(--brand);
}

/* Native select arrow replaced with the design's own chevron. */
form select{
  appearance:none;
  -webkit-appearance:none;
  padding-right:4rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%235E6B62' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 1.6rem center;
  background-size:1.2rem;
}

/* ── 17. FOOTER ──────────────────────────────────────────── */
/* Real structure (6 direct children of .content):
     a.logo  p.footer-message  div.sitemap
     div.footer-contact  div.footer-social  p.signature
   Auto-placement would deal those across three columns in the wrong
   order, so each one is placed explicitly. */
footer.vertical-footer{
  background:var(--ink);
  color:var(--bone);
  padding-block: 4rem 2.4rem;
  padding-inline:var(--gut);
  --bp-line:rgba(245,242,235,.14);
}
footer.vertical-footer .content{
  max-width:var(--maxw);
  margin-inline:auto;
  display:grid;
  grid-template-columns:1fr;
  gap:clamp(3.2rem,5vw,5.6rem);
  align-items:start;
}
/* The framework centres the footer columns; this design sets them left,
   and a centred narrow column was breaking the address onto one word
   per line. */
   footer.vertical-footer .content{
    
        row-gap: 2.4rem;
   }
footer.vertical-footer .content,
footer.vertical-footer .sitemap,
footer.vertical-footer .footer-contact,
footer.vertical-footer .footer-social,
footer.vertical-footer .signature,
footer.vertical-footer .h4{text-align:left}
footer.vertical-footer .footer-contact li{text-wrap:pretty}
@media (min-width:760px){
  footer.vertical-footer .content{grid-template-columns:1fr 1fr}
  footer.vertical-footer .logo{grid-column:1;grid-row:1}
  footer.vertical-footer .footer-message{grid-column:1;grid-row:2}
  footer.vertical-footer .footer-social{grid-column:1;grid-row:3}
  footer.vertical-footer .sitemap{grid-column:2;grid-row:1 / span 2}
  footer.vertical-footer .footer-contact{grid-column:2;grid-row:3}
  footer.vertical-footer .signature{grid-column:1 / -1}
}
@media (min-width:1100px){
  footer.vertical-footer .content{
    grid-template-columns:minmax(0,1.2fr) minmax(0,1.3fr) minmax(26rem,1fr);
    column-gap:clamp(3.2rem,4vw,7.2rem);
  }
  footer.vertical-footer .logo{grid-column:1;grid-row:1}
  footer.vertical-footer .footer-message{grid-column:1;grid-row:2}
  footer.vertical-footer .footer-social{grid-column:1;grid-row:3}
  footer.vertical-footer .sitemap{grid-column:2;grid-row:1 / span 3}
  footer.vertical-footer .footer-contact{grid-column:3;grid-row:1 / span 3}
  footer.vertical-footer .signature{grid-column:1 / -1;grid-row:4}
}
footer.vertical-footer .sitemap, footer.vertical-footer .footer-contact{
  margin-top: 152px;
}
/* The mark is a tall crest — bound its height, not its width. */
footer.vertical-footer .logo{display:block;margin:0}
footer.vertical-footer .logo img{
  width:auto;
  height:clamp(8rem,9vw,11.2rem);
  margin:0;
}
footer.vertical-footer .footer-message{
  margin:0;
  color:rgba(245,242,235,.6);
  font-size:1.5rem;
  line-height:1.6;
  max-width:38ch;
}
footer.vertical-footer .footer-message{
  padding-top: 2.4rem;
  border-top: 2px solid hsla(0 0% 100% / .08);
    max-width: 100%;
    width: 100%;
}
/* Column headings. The sitemap's own .h4 duplicates the "Sitemap" label
   that the nav already prints as a nav-heading, so hide that one only. */
footer.vertical-footer .h4{
  font-size:var(--fs-label);
  font-weight:500;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:rgba(245,242,235,.45);
  margin:0 0 2rem;
  line-height:1.4;
}
footer.vertical-footer .sitemap > .h4{display:none}

footer.vertical-footer .sitemap nav > ul{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(2.4rem,3vw,4rem);
  margin:0;
  padding:0;
  list-style:none;
}
footer.vertical-footer nav ul ul{
  display:block;
  margin:0;
  padding:0;
  list-style:none;
}
footer.vertical-footer nav li{margin:0;padding:0}
footer.vertical-footer li.nav-heading > span{
  display:block;
  font-size:var(--fs-label);
  font-weight:500;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:rgba(245,242,235,.45);
  margin-bottom:1.2rem;
}
footer.vertical-footer nav a{
  display:flex;
  align-items:center;
  min-height:3.6rem;
  font-size:1.5rem;
  line-height:1.5;
  color:rgba(245,242,235,.82);
  transition:color var(--t-fast),transform var(--t-fast) var(--e-out);
}
footer.vertical-footer nav a:hover{color:var(--brand-300);transform:translateX(3px)}

/* Contact list: the framework leaves this as a flex row, which runs the
   address, email and phone into each other. */
footer.vertical-footer .footer-contact ul{
  display:flex;
  gap:1.6rem;
  margin:0;
  padding:0;
  list-style:none;
}
/* styles.css lays these out three-across (width:33.333%, centred), which
   in a single narrow column breaks the street address to one word per
   line. Both properties have to be named to win. */
footer.vertical-footer .footer-contact li{
  width:100%;
  text-align:left;
  margin:0;
  padding:0;
  font-size:1.5rem;
  line-height:1.55;
  color:rgba(245,242,235,.7);
}
footer.vertical-footer .footer-contact strong{
  display:block;
  text-align:left;
  font-size:var(--fs-label);
  font-weight:500;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:rgba(245,242,235,.45);
  margin-bottom:.4rem;
}
footer.vertical-footer .footer-contact a{
  display:inline-flex;
  align-items:center;
  min-height:3.6rem;
  font-size:1.5rem;
  color:rgba(245,242,235,.82);
  transition:color var(--t-fast);
}
footer.vertical-footer .footer-contact a:hover{color:var(--brand-300)}

/* Social. The real markup nests .social_media > ul inside the outer ul. */
footer.vertical-footer .footer-social ul{
  margin:0;
  padding:0;
  list-style:none;
}
footer.vertical-footer .footer-social .social_media ul{
  display:flex;
  flex-wrap:wrap;
  justify-content: flex-start;
  gap:.96rem;
}
footer.vertical-footer .footer-social li{margin:0;padding:0}
footer.vertical-footer .footer-social a{
  width:4.4rem;
  height:4.4rem;
  display:grid;
  place-content:center;
  border:1px solid var(--bp-line);
  border-radius:999px;
  color:rgba(245,242,235,.82);
  background:transparent;
  transition:background var(--t-mid),color var(--t-mid),border-color var(--t-mid),transform var(--t-fast);
}
footer.vertical-footer .footer-social a:hover{
  background:var(--brand);
  border-color:var(--brand);
  color:#fff;
  transform:translateY(-2px);
}
footer.vertical-footer .footer-social svg{width:1.8rem;height:1.8rem;fill:currentColor}
footer.vertical-footer .footer-social i{font-size:1.6rem}

footer.vertical-footer .signature{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:.8rem 1.2rem;
  margin:0;
  padding-top:clamp(3.2rem,4vw,4.8rem);
  border-top:1px solid var(--bp-line);
  font-size:1.3rem;
  color:rgba(245,242,235,.45);
}
footer.vertical-footer .signature a{
  color:rgba(245,242,235,.6);
  transition:color var(--t-fast);
}
footer.vertical-footer .signature a:hover{color:var(--bone)}
footer.vertical-footer .signature span{opacity:.4}

/* ── 17b. JOIN UTILITIES ─────────────────────────────────── */
/* Several scope sections are authored as two widgets — an rte intro
   followed by a gallery. These let the pair render as one block:
   put bp-join-bottom on the intro and bp-join-top on the gallery,
   and give both the same theme class. */
section.content_container.bp-join-bottom{padding-bottom:clamp(3.2rem,4vw,5.6rem)}
section.content_container.bp-join-top{padding-top:0}

/* Centre a section's heading block — used on the credibility and
   reviews intros, where the content below is a centred row. */
section.content_container.bp-centre .editable_content{
  max-width:68ch;
  margin-inline:auto;
  text-align:center;
}
section.content_container.bp-centre .editable_content h2{max-width:none}
section.content_container.bp-centre .editable_content p{max-width:none}
section.content_container.bp-centre .editable_content p.h6{justify-content:center}
section.content_container.bp-centre .btn-wrapper{text-align:center}

/* ── 18. SCROLL REVEAL ───────────────────────────────────── */
/* bp.js adds .bp-in when the element enters the viewport. */
.bp-rise{
  opacity:0;
  transform:translateY(30px);
  transition:opacity .8s var(--e-soft),transform .9s var(--e-out);
}
.bp-rise.bp-in{opacity:1;transform:none}

/* ── 19. REDUCED MOTION ──────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
  .bp-rise{opacity:1 !important;transform:none !important}
  .bp-off .bp-snow,.bp-off .bp-pollen{display:none}
  /* The gate script normally stops the loader ever showing, but the
     preference can be turned on after the class was set. */
  html.js-loading .bp-loader{display:none}
}
