/* --- fonts, folded in from fonts.css ------------------------------
   Kept as its own file it cost a whole render-blocking round trip —
   160ms measured, to deliver 493 bytes over the wire. @font-face must
   still come first so faces are known before any rule references them. */
/* Rubik - self-hosted variable font. Google Fonts is a construction-time
   convenience only; production self-hosts and caches for a year (see .htaccess).
   Filename IS the version: never overwrite a shipped woff2 in place. */
@font-face{
  font-family:'Rubik';
  font-style:italic;
  font-weight:300 900;
  font-display:swap;
  src:url('/assets/fonts/rubik-latin-ext-italic.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family:'Rubik';
  font-style:italic;
  font-weight:300 900;
  font-display:swap;
  src:url('/assets/fonts/rubik-latin-italic.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Rubik';
  font-style:normal;
  font-weight:300 900;
  font-display:swap;
  src:url('/assets/fonts/rubik-latin-ext-normal.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family:'Rubik';
  font-style:normal;
  font-weight:300 900;
  font-display:swap;
  src:url('/assets/fonts/rubik-latin-normal.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   Giant Landscaping Services - design system
   Built for WebJIVE mini-CMS. No Tailwind CDN, no framework, no builder classes.

   Palette is the client's own, lifted from the live site and contrast-audited:
     green  #2A7D2E  5.16:1 on white - PASSES AA, usable for small text
     yellow #FFD51E  1.42:1 on white - DECORATION ONLY, never text
   The green needing no deepened variant is unusual and worth keeping true: if the
   brand green is ever changed, re-run the contrast audit before shipping it.
   ========================================================================== */

:root{
  /* brand */
  --gl-green:#2A7D2E;
  --gl-green-dk:#1F5F22;
  --gl-green-lt:#3D9942;
  --gl-yellow:#FFD51E;          /* decorative fills only - fails AA as text */
  --gl-ink:#1E1E1E;
  --gl-forest:#273227;          /* dark sections, footer */
  --gl-wash:#F8FEE7;            /* pale green page wash */
  --gl-muted:#5A5A5A;           /* 7.0:1 on white */
  --gl-line:#E3E8DC;
  --gl-white:#FFFFFF;

  /* type */
  --gl-font:'Rubik',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  --gl-h1:clamp(2.1rem,1.35rem + 3.2vw,3.9rem);
  --gl-h2:clamp(1.65rem,1.2rem + 1.9vw,2.6rem);
  --gl-h3:clamp(1.22rem,1.05rem + .7vw,1.55rem);
  --gl-lead:clamp(1.05rem,1rem + .35vw,1.22rem);

  /* rhythm */
  --gl-wrap:1200px;
  --gl-wrap-header:1320px;      /* header needs more room than body copy */
  --gl-gut:clamp(1.15rem,.7rem + 2vw,2.5rem);
  --gl-sec:clamp(3.25rem,2rem + 5vw,6rem);
  --gl-nav-h:78px;

  --gl-r:14px;
  --gl-shadow:0 1px 2px rgba(39,50,39,.06),0 8px 26px -12px rgba(39,50,39,.22);
  --gl-shadow-lift:0 12px 40px -12px rgba(39,50,39,.32);
  --gl-ease:cubic-bezier(.22,.61,.36,1);
}

/* --- reset ------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html,body{margin:0}                       /* kills the 8px edge-sliver bug */
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  font-family:var(--gl-font);font-size:1.0625rem;line-height:1.68;
  color:var(--gl-ink);background:var(--gl-white);
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
img{max-width:100%;height:auto;display:block}   /* MUST precede any width/height attrs */
svg{display:block}
a{color:var(--gl-green);text-underline-offset:.18em}
a:hover{color:var(--gl-green-dk)}
h1,h2,h3,h4{line-height:1.16;margin:0 0 .55em;font-weight:700;letter-spacing:-.018em}
h1{font-size:var(--gl-h1);font-weight:800}
h2{font-size:var(--gl-h2)}
h3{font-size:var(--gl-h3)}
p{margin:0 0 1.15em}
ul,ol{margin:0 0 1.15em;padding-left:1.35em}
li{margin:.3em 0}
:focus-visible{outline:3px solid var(--gl-green);outline-offset:3px;border-radius:4px}

/* --- skip link ---------------------------------------------------------- */
.gl-skip{
  position:absolute;left:-9999px;top:0;z-index:2000;
  background:var(--gl-forest);color:#fff;padding:.85rem 1.35rem;
  border-radius:0 0 var(--gl-r) 0;font-weight:600;text-decoration:none;
}
.gl-skip:focus{left:0}

/* --- layout ------------------------------------------------------------- */
.gl-wrap{max-width:var(--gl-wrap);margin-inline:auto;padding-inline:var(--gl-gut)}
.gl-wrap--narrow{max-width:820px}
.gl-section{padding-block:var(--gl-sec)}
/* A full section's padding directly under a hero reads as dead space. */
.gl-phero + .gl-section,.gl-bc + .gl-section,.gl-hero + .gl-section{
  padding-top:clamp(2.25rem,1.5rem + 2.5vw,3.5rem)}
.gl-section--wash{background:var(--gl-wash)}
.gl-section--forest{background:var(--gl-forest);color:#EEF3EC}
.gl-section--forest h2,.gl-section--forest h3{color:#fff}
.gl-section--forest a{color:#B9E8BC}

/* --- header ------------------------------------------------------------- */
.gl-header{
  position:sticky;top:0;z-index:900;background:rgba(255,255,255,.94);
  backdrop-filter:saturate(1.6) blur(10px);
  border-bottom:1px solid var(--gl-line);
  transition:box-shadow .3s var(--gl-ease),background .3s var(--gl-ease);
}
.gl-header.is-stuck{box-shadow:0 6px 26px -14px rgba(39,50,39,.4)}
.gl-header__bar{
  display:flex;align-items:center;gap:.9rem;
  min-height:var(--gl-nav-h);
  max-width:var(--gl-wrap-header);margin-inline:auto;padding-inline:var(--gl-gut);
}
.gl-logo{flex:0 0 auto;display:flex;align-items:center}
.gl-logo img{height:46px;width:auto}
.gl-nav{margin-left:auto;display:none}
@media (min-width:1150px){.gl-nav{display:block}}
/* nowrap on BOTH axes: the row must never wrap to a second line, and a label
   must never break mid-phrase ("Service / Areas"). */
.gl-nav>ul{display:flex;flex-wrap:nowrap;align-items:center;gap:.1rem;
  list-style:none;margin:0;padding:0}
.gl-nav>ul>li>a{white-space:nowrap}
.gl-nav a{
  display:block;padding:.6rem .58rem;border-radius:9px;
  font-size:.895rem;font-weight:600;color:var(--gl-ink);text-decoration:none;
  transition:background .2s var(--gl-ease),color .2s var(--gl-ease);
}
.gl-nav a:hover{background:var(--gl-wash);color:var(--gl-green-dk)}
.gl-nav a[aria-current="page"]{color:var(--gl-green);box-shadow:inset 0 -3px 0 var(--gl-yellow)}

/* dropdown */
.gl-nav li{position:relative}
.gl-nav__sub{
  position:absolute;top:calc(100% + 8px);left:0;min-width:260px;
  background:#fff;border:1px solid var(--gl-line);border-radius:var(--gl-r);
  box-shadow:var(--gl-shadow-lift);padding:.45rem;list-style:none;margin:0;
  opacity:0;visibility:hidden;transform:translateY(-8px);
  transition:opacity .22s var(--gl-ease),transform .22s var(--gl-ease),visibility .22s;
}
.gl-nav li:hover>.gl-nav__sub,
.gl-nav li:focus-within>.gl-nav__sub{opacity:1;visibility:visible;transform:translateY(0)}
.gl-nav__sub a{font-weight:500;font-size:.9rem;padding:.55rem .7rem;white-space:normal}
.gl-nav__top>a::after{content:'';display:inline-block;width:.4em;height:.4em;margin-left:.42em;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:translateY(-2px) rotate(45deg);opacity:.55}

.gl-header__cta{
  flex:0 0 auto;display:inline-flex;align-items:center;gap:.5rem;
  background:var(--gl-green);color:#fff;text-decoration:none;font-weight:700;
  padding:.72rem 1.15rem;border-radius:999px;font-size:.95rem;white-space:nowrap;
  transition:transform .2s var(--gl-ease),background .2s var(--gl-ease);
}
.gl-header__cta:hover{background:var(--gl-green-dk);color:#fff;transform:translateY(-1px)}
@media (max-width:640px){.gl-header__cta span{display:none}}

.gl-burger{
  margin-left:auto;display:inline-flex;flex-direction:column;justify-content:center;
  gap:5px;width:46px;height:46px;padding:11px;background:none;
  border:1px solid var(--gl-line);border-radius:11px;cursor:pointer;
}
@media (min-width:1150px){.gl-burger{display:none}}
.gl-burger span{display:block;height:2px;background:var(--gl-ink);border-radius:2px;
  transition:transform .28s var(--gl-ease),opacity .2s}
.gl-burger[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.gl-burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.gl-burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

.gl-mobile{display:none;border-top:1px solid var(--gl-line);background:#fff;
  max-height:calc(100vh - var(--gl-nav-h));overflow-y:auto}
.gl-mobile.is-open{display:block}
@media (min-width:1150px){.gl-mobile{display:none!important}}
.gl-mobile ul{list-style:none;margin:0;padding:0}
.gl-mobile a{display:block;padding:.9rem var(--gl-gut);text-decoration:none;
  color:var(--gl-ink);font-weight:600;border-bottom:1px solid var(--gl-line)}
.gl-mobile__sub a{padding-left:calc(var(--gl-gut) + 1.1rem);font-weight:500;
  font-size:.95rem;color:var(--gl-muted)}

/* --- buttons ------------------------------------------------------------ */
.gl-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.55rem;
  padding:.92rem 1.7rem;border-radius:999px;font-weight:700;font-size:1.02rem;
  text-decoration:none;border:2px solid transparent;cursor:pointer;
  transition:transform .2s var(--gl-ease),box-shadow .2s var(--gl-ease),background .2s;
}
.gl-btn--primary{background:var(--gl-green);color:#fff;box-shadow:0 8px 22px -12px rgba(42,125,46,.9)}
.gl-btn--primary:hover{background:var(--gl-green-dk);color:#fff;transform:translateY(-2px);
  box-shadow:0 14px 30px -12px rgba(42,125,46,.85)}
.gl-btn--ghost{background:transparent;color:#fff;border-color:rgba(255,255,255,.55)}
.gl-btn--ghost:hover{background:rgba(255,255,255,.14);color:#fff;border-color:#fff}
.gl-btn--outline{background:var(--gl-green-dk);color:#fff;border-color:var(--gl-green-dk);
  box-shadow:0 8px 22px -12px rgba(31,95,34,.9)}
.gl-btn--outline:hover{background:var(--gl-green);color:#fff;border-color:var(--gl-green);
  transform:translateY(-2px);box-shadow:0 14px 30px -12px rgba(31,95,34,.85)}

/* --- hero --------------------------------------------------------------- */
/* Stacking: NEVER negative z-index here. A z-index:-2 background layer paints
   behind the nearest opaque ancestor background (the white <body>), so the photo
   silently disappeared and only the scrim showed -- a flat grey hero that looked
   like a heavy overlay and was actually a missing image. All layers are >= 0. */
.gl-hero{position:relative;color:#fff;overflow:hidden;
  padding-block:clamp(3.75rem,2rem + 9vw,7.5rem)}
.gl-hero__bg{position:absolute;inset:0;z-index:0;
  background-position:center;background-size:cover;background-repeat:no-repeat}
.gl-hero::after{                       /* readability scrim */
  content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(92deg,rgba(16,29,16,.86) 0%,rgba(16,29,16,.70) 40%,
             rgba(16,29,16,.42) 68%,rgba(16,29,16,.26) 100%);
}
.gl-hero>.gl-wrap{position:relative;z-index:2}
.gl-hero__eyebrow{
  display:inline-flex;align-items:center;gap:.5rem;margin-bottom:1.1rem;
  background:var(--gl-yellow);color:#3A2E00;   /* dark ink ON the yellow - 9.4:1 */
  font-weight:700;font-size:.79rem;letter-spacing:.1em;text-transform:uppercase;
  padding:.42rem .95rem;border-radius:999px;
}
.gl-hero h1{max-width:16ch;margin-bottom:.5em;color:#fff;text-wrap:balance;
  text-shadow:0 2px 18px rgba(10,20,10,.5)}
.gl-hero__sub{font-size:var(--gl-lead);max-width:52ch;color:#F2F7F1;margin-bottom:2rem;
  text-shadow:0 1px 12px rgba(10,20,10,.55)}
.gl-hero__cta{display:flex;flex-wrap:wrap;gap:.9rem}
/* Hero standard: the primary CTA owns its row; phone links sit BELOW it. */
.gl-hero__phones{display:flex;flex-wrap:wrap;gap:1.4rem;margin-top:1.6rem;
  font-weight:600;position:relative;z-index:2}
.gl-hero__phones a{color:#fff;text-decoration:none;display:inline-flex;align-items:center;gap:.5rem}
.gl-hero__phones a:hover{text-decoration:underline}

/* page hero (interior pages) */
.gl-phero{position:relative;color:#fff;overflow:hidden;
  padding-block:clamp(2.6rem,1.6rem + 5vw,4.75rem)}
.gl-phero>.gl-wrap{position:relative;z-index:2}
.gl-phero::after{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(92deg,rgba(16,29,16,.84) 0%,rgba(16,29,16,.68) 42%,
             rgba(16,29,16,.40) 70%,rgba(16,29,16,.26) 100%)}
.gl-phero__bg{position:absolute;inset:0;z-index:0;
  background-position:center;background-size:cover;background-repeat:no-repeat}
.gl-phero h1{color:#fff;margin:0;max-width:20ch;text-wrap:balance;
  text-shadow:0 2px 18px rgba(10,20,10,.5)}
.gl-phero p{color:#F2F7F1;max-width:52ch;margin:.85rem 0 0;font-size:var(--gl-lead);
  text-shadow:0 1px 12px rgba(10,20,10,.55)}
.gl-phero--plain{background:var(--gl-forest)}
.gl-phero--plain::after{display:none}

/* --- breadcrumbs -------------------------------------------------------- */
.gl-bc{background:var(--gl-wash);border-bottom:1px solid var(--gl-line);font-size:.86rem}
.gl-bc ol{display:flex;flex-wrap:wrap;gap:.4rem;align-items:center;
  list-style:none;margin:0;padding:.72rem 0;max-width:var(--gl-wrap)}
.gl-bc li{display:flex;align-items:center;gap:.4rem;margin:0}
.gl-bc li+li::before{content:'/';color:#9AA79A}
.gl-bc a{color:var(--gl-green);text-decoration:none;padding:.15rem 0}
.gl-bc a:hover{text-decoration:underline}
.gl-bc [aria-current]{color:var(--gl-muted)}

/* --- prose (converted page bodies) -------------------------------------- */
.gl-prose{max-width:74ch}
.gl-prose--wide{max-width:none}
.gl-prose h2{margin-top:2.1em}
.gl-prose h3{margin-top:1.6em}
.gl-prose>*:first-child{margin-top:0}
.gl-prose img{border-radius:var(--gl-r);margin-block:1.6rem}
/* ⚠ `.gl-prose img` is (0,1,1) and beats ANY single-class component rule, so it
   leaks into every component rendered inside an article. It has now silently
   broken three: the author avatar (14px corners instead of a circle), and the
   city-card photos (a 25.6px top margin pushed each photo down inside its
   fixed-ratio box, showing a band of the pale wash above and clipping the
   bottom off the picture). Neutralise it ONCE for component images; each
   component then styles its own. Add new components to this list. */
.gl-prose :is(.gl-city,.gl-card,.gl-cities,.gl-quotes,.wj-author-box,
              .gl-mediatext,.gl-gallery) img{margin:0;border-radius:0}
.gl-prose figure{margin:1.8rem 0}
.gl-prose figcaption{font-size:.88rem;color:var(--gl-muted);margin-top:.55rem}
.gl-prose blockquote{
  margin:1.9rem 0;padding:1.15rem 1.5rem;background:var(--gl-wash);
  border-left:5px solid var(--gl-yellow);border-radius:0 var(--gl-r) var(--gl-r) 0;
}
.gl-prose blockquote p:last-child{margin-bottom:0}
.gl-prose table{width:100%;border-collapse:collapse;margin:1.6rem 0;font-size:.95rem}
.gl-prose th,.gl-prose td{padding:.72rem .9rem;border:1px solid var(--gl-line);text-align:left}
.gl-prose th{background:var(--gl-wash);font-weight:700}
.gl-table-scroll{overflow-x:auto;margin:1.6rem 0}

/* --- grids & cards ------------------------------------------------------ */
.gl-grid{display:grid;gap:clamp(1.1rem,.7rem + 1.4vw,1.9rem)}
.gl-grid--2{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}
.gl-grid--3{grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr))}
.gl-grid--4{grid-template-columns:repeat(auto-fit,minmax(min(100%,225px),1fr))}

.gl-card{
  background:#fff;border:1px solid var(--gl-line);border-radius:var(--gl-r);
  overflow:hidden;box-shadow:var(--gl-shadow);display:flex;flex-direction:column;
  transition:transform .32s var(--gl-ease),box-shadow .32s var(--gl-ease),
             border-color .32s var(--gl-ease);
}
.gl-card:hover{transform:translateY(-6px);box-shadow:var(--gl-shadow-lift);
  border-color:#C8DCC4}
.gl-card__media{position:relative;overflow:hidden;aspect-ratio:16/10;
  background:#EEEFEC;line-height:0}
.gl-card__media img{width:100%;height:100%;object-fit:cover;
  transition:transform .6s var(--gl-ease)}
.gl-card:hover .gl-card__media img{transform:scale(1.06)}
.gl-card__body{padding:1.35rem 1.4rem 1.5rem;display:flex;flex-direction:column;flex:1}
/* Card titles are <h2> in the collection templates and <h3> elsewhere — target
   BOTH. Scoping this to h3 alone left every blog card underlined and set at the
   full h2 display size. */
.gl-card__body :is(h2,h3,h4){margin-bottom:.42em;font-size:1.16rem;line-height:1.3}
.gl-card__body :is(h2,h3,h4) a{text-decoration:none;color:var(--gl-ink)}
.gl-card__body :is(h2,h3,h4) a:hover{color:var(--gl-green);text-decoration:underline}
.gl-card__meta{font-size:.83rem;color:var(--gl-muted);margin-bottom:.5rem;
  text-transform:uppercase;letter-spacing:.055em;font-weight:600}
.gl-card__more{margin-top:auto;padding-top:.9rem;font-weight:700;color:var(--gl-green);
  text-decoration:none;display:inline-flex;align-items:center;gap:.4rem;align-self:flex-start}
.gl-card__more:hover{gap:.7rem}
.gl-card__more span{transition:transform .25s var(--gl-ease)}
.gl-card__more:hover span{transform:translateX(3px)}

/* service tile - icon-led, no image needed */
.gl-tile{
  background:#fff;border:1px solid var(--gl-line);border-radius:var(--gl-r);
  padding:1.6rem 1.5rem;text-decoration:none;color:inherit;display:block;
  position:relative;overflow:hidden;
  transition:transform .3s var(--gl-ease),box-shadow .3s var(--gl-ease);
}
.gl-tile::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:4px;
  background:var(--gl-yellow);transform:scaleY(0);transform-origin:bottom;
  transition:transform .34s var(--gl-ease);
}
.gl-tile:hover{transform:translateY(-4px);box-shadow:var(--gl-shadow-lift)}
.gl-tile:hover::before{transform:scaleY(1)}
.gl-tile h3{margin-bottom:.35em;font-size:1.12rem}
.gl-tile p{margin:0;color:var(--gl-muted);font-size:.94rem}
.gl-tile__icon{width:46px;height:46px;margin-bottom:.95rem;color:var(--gl-green)}

/* --- stats -------------------------------------------------------------- */
.gl-stats{display:grid;gap:1.5rem;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,170px),1fr));text-align:center}
.gl-stat__num{font-size:clamp(2.1rem,1.4rem + 2.4vw,3.1rem);font-weight:800;
  line-height:1;color:var(--gl-green);font-variant-numeric:tabular-nums}
.gl-section--forest .gl-stat__num{color:var(--gl-yellow)}   /* large text: 3:1 OK on forest */
.gl-stat__label{font-size:.88rem;font-weight:600;margin-top:.55rem;
  letter-spacing:.045em;text-transform:uppercase;opacity:.85}

/* --- accordion (replaces the Easy Accordion plugin) --------------------- */
.gl-acc{border:1px solid var(--gl-line);border-radius:var(--gl-r);overflow:hidden;background:#fff}
.gl-acc+.gl-acc{margin-top:.7rem}
.gl-acc summary{
  cursor:pointer;padding:1.05rem 3rem 1.05rem 1.3rem;font-weight:700;position:relative;
  list-style:none;transition:background .2s var(--gl-ease);
}
.gl-acc summary::-webkit-details-marker{display:none}
.gl-acc summary:hover{background:var(--gl-wash)}
.gl-acc summary::after{
  content:'';position:absolute;right:1.3rem;top:50%;width:.6em;height:.6em;
  border-right:2.5px solid var(--gl-green);border-bottom:2.5px solid var(--gl-green);
  transform:translateY(-70%) rotate(45deg);transition:transform .28s var(--gl-ease);
}
.gl-acc[open] summary::after{transform:translateY(-25%) rotate(-135deg)}
.gl-acc__body{padding:0 1.3rem 1.25rem;border-top:1px solid var(--gl-line)}
.gl-acc__body>*:first-child{margin-top:1rem}
.gl-acc__body>*:last-child{margin-bottom:0}

/* --- gallery ------------------------------------------------------------ */
/* legacy flat gallery (kept: harmless if any page still uses it) */
.gl-gallery{display:grid;gap:.85rem;
  grid-template-columns:repeat(auto-fill,minmax(min(100%,235px),1fr))}
.gl-gallery a{display:block;border-radius:11px;overflow:hidden;aspect-ratio:4/3;
  background:#EEEFEC;line-height:0}
.gl-gallery img{width:100%;height:100%;object-fit:cover;transition:transform .5s var(--gl-ease)}
.gl-gallery a:hover img{transform:scale(1.07)}

/* responsive video */
.gl-video{position:relative;aspect-ratio:16/9;border-radius:var(--gl-r);
  overflow:hidden;background:#000;margin-block:1.6rem}
.gl-video iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

/* --- forms -------------------------------------------------------------- */
.gl-form{display:grid;gap:1.1rem}
.gl-field{display:grid;gap:.4rem}
.gl-field--half{grid-column:span 1}
@media (min-width:640px){.gl-form--2col{grid-template-columns:1fr 1fr}
  .gl-field--full{grid-column:1/-1}}
.gl-field label{font-weight:600;font-size:.93rem}
.gl-req{color:#B3261E;margin-left:.15em}
.gl-field input,.gl-field select,.gl-field textarea{
  width:100%;padding:.8rem .95rem;border:1.5px solid var(--gl-line);border-radius:10px;
  font:inherit;font-size:1rem;background:#fff;color:var(--gl-ink);
  transition:border-color .2s var(--gl-ease),box-shadow .2s var(--gl-ease);
}
.gl-field input:focus,.gl-field select:focus,.gl-field textarea:focus{
  outline:none;border-color:var(--gl-green);box-shadow:0 0 0 3px rgba(42,125,46,.16)}
.gl-field textarea{min-height:145px;resize:vertical}
.gl-hint{font-size:.84rem;color:var(--gl-muted)}
.gl-checks{display:grid;gap:.55rem;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,235px),1fr))}
.gl-check{display:flex;align-items:flex-start;gap:.6rem;padding:.62rem .75rem;
  border:1.5px solid var(--gl-line);border-radius:10px;cursor:pointer;
  font-size:.94rem;line-height:1.4;transition:border-color .2s,background .2s}
.gl-check:hover{border-color:var(--gl-green-lt);background:var(--gl-wash)}
.gl-check input{margin-top:.18rem;width:1.05rem;height:1.05rem;accent-color:var(--gl-green);flex:0 0 auto}
.gl-check:has(input:checked){border-color:var(--gl-green);background:var(--gl-wash)}
.gl-fieldset{border:1px solid var(--gl-line);border-radius:var(--gl-r);padding:1.3rem;margin:0}
.gl-fieldset legend{font-weight:700;padding-inline:.5rem}
/* honeypot - visually hidden but not display:none (bots skip display:none) */
.gl-hp{position:absolute!important;left:-9999px!important;width:1px;height:1px;overflow:hidden}
.gl-formnote{font-size:.84rem;color:var(--gl-muted);margin-top:.4rem}

/* --- footer ------------------------------------------------------------- */
.gl-footer{background:var(--gl-forest);color:#CFDACD;padding-block:clamp(2.75rem,2rem + 3vw,4.25rem) 0}
.gl-footer h2,.gl-footer h3,.gl-footer [role="heading"]{color:#fff;font-size:1.02rem;
  margin-bottom:.95rem;font-weight:700;letter-spacing:.02em}
.gl-footer a{color:#CFDACD;text-decoration:none}
.gl-footer a:hover{color:#fff;text-decoration:underline}
.gl-footer__grid{display:grid;gap:2.1rem;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,215px),1fr))}
.gl-footer ul{list-style:none;margin:0;padding:0}
.gl-footer li{margin:0}
.gl-footer li a{display:block;padding:.42rem 0;font-size:.94rem}  /* >=24px tap target */
.gl-footer__logo img{height:56px;width:auto;margin-bottom:1.1rem}
.gl-footer__social{display:flex;gap:.6rem;margin-top:1.1rem}
.gl-footer__social a{display:inline-flex;align-items:center;justify-content:center;
  width:42px;height:42px;border-radius:11px;background:rgba(255,255,255,.09);
  transition:background .22s var(--gl-ease),transform .22s var(--gl-ease)}
.gl-footer__social a:hover{background:var(--gl-green);transform:translateY(-2px)}
.gl-footer__social svg{width:19px;height:19px;fill:currentColor}
.gl-footer__bar{margin-top:2.75rem;border-top:1px solid rgba(255,255,255,.14);
  padding-block:1.4rem;font-size:.87rem;display:flex;flex-wrap:wrap;gap:.7rem 1.5rem;
  align-items:center;justify-content:space-between}
.gl-footer__bar nav{display:flex;flex-wrap:wrap;gap:1.1rem}

/* --- sticky mobile call bar --------------------------------------------- */
.gl-callbar{
  position:fixed;left:0;right:0;bottom:0;z-index:800;display:grid;
  grid-template-columns:1fr 1fr;gap:1px;background:var(--gl-line);
  box-shadow:0 -4px 18px -8px rgba(39,50,39,.4);
  transform:translateY(100%);transition:transform .34s var(--gl-ease);
}
.gl-callbar.is-in{transform:translateY(0)}
@media (min-width:900px){.gl-callbar{display:none}}
.gl-callbar a{display:flex;align-items:center;justify-content:center;gap:.5rem;
  padding:.95rem .6rem;font-weight:700;text-decoration:none;font-size:.96rem}
.gl-callbar a:first-child{background:var(--gl-green);color:#fff}
.gl-callbar a:last-child{background:#fff;color:var(--gl-green-dk)}
body{padding-bottom:env(safe-area-inset-bottom)}
@media (max-width:899px){body.has-callbar{padding-bottom:58px}}

/* ==========================================================================
   Motion. Everything below is progressive enhancement: with JS off, or with
   prefers-reduced-motion, content is fully visible and static.
   ========================================================================== */
.gl-reveal{opacity:0;transform:translateY(22px);
  transition:opacity .7s var(--gl-ease),transform .7s var(--gl-ease)}
.gl-reveal.is-in{opacity:1;transform:none}
.gl-reveal--d1{transition-delay:.09s}
.gl-reveal--d2{transition-delay:.18s}
.gl-reveal--d3{transition-delay:.27s}
.gl-reveal--d4{transition-delay:.36s}

.gl-hero__bg{animation:gl-kb 22s var(--gl-ease) forwards;transform-origin:center;
  will-change:transform}
@keyframes gl-kb{from{transform:scale(1.08)}to{transform:scale(1)}}

.gl-underline{background-image:linear-gradient(var(--gl-yellow),var(--gl-yellow));
  background-repeat:no-repeat;background-position:0 88%;background-size:0 .3em;
  transition:background-size .7s var(--gl-ease) .25s}
.is-in .gl-underline,.gl-underline.is-in{background-size:100% .3em}

/* No JS: never leave content hidden. */
.no-js .gl-reveal{opacity:1;transform:none}
.no-js .gl-underline{background-size:100% .3em}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
  .gl-reveal{opacity:1;transform:none}
  .gl-hero__bg{animation:none}
  .gl-underline{background-size:100% .3em}
  .gl-callbar{transform:none}
}

/* --- print --------------------------------------------------------------- */
@media print{
  .gl-header,.gl-callbar,.gl-footer__social,.gl-bc{display:none}
  body{color:#000}
  .gl-reveal{opacity:1;transform:none}
}

/* --- testimonials -------------------------------------------------------
   Recovered from the Strong Testimonials slider, which rendered every quote
   into the DOM and then showed one at a time via plugin JS. With the plugin
   gone they were invisible. Static grid: no JS, nothing to break. */
.gl-quotes{display:grid;gap:clamp(1rem,.7rem + 1.1vw,1.6rem);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,310px),1fr));margin-block:2rem}
.gl-quote{
  margin:0;background:#fff;border:1px solid var(--gl-line);border-radius:var(--gl-r);
  padding:1.6rem 1.5rem 1.35rem;box-shadow:var(--gl-shadow);position:relative;
  display:flex;flex-direction:column;
  transition:transform .3s var(--gl-ease),box-shadow .3s var(--gl-ease);
}
.gl-quote:hover{transform:translateY(-4px);box-shadow:var(--gl-shadow-lift)}
.gl-quote::before{
  content:'"';position:absolute;top:.15em;right:.35em;
  font-size:4.5rem;line-height:1;color:var(--gl-yellow);opacity:.5;
  font-family:Georgia,'Times New Roman',serif;pointer-events:none;
}
.gl-quote blockquote{margin:0;padding:0;border:0;background:none;font-size:1rem;
  line-height:1.62;color:var(--gl-ink)}
.gl-quote blockquote p:last-child{margin-bottom:0}
.gl-quote figcaption{
  margin-top:1rem;padding-top:.85rem;border-top:1px solid var(--gl-line);
  font-weight:700;font-size:.92rem;color:var(--gl-green);
}
.gl-quote figcaption::before{content:'— '}
.gl-section--wash .gl-quote,.gl-section--forest .gl-quote{background:#fff}
.gl-section--forest .gl-quote blockquote{color:var(--gl-ink)}

/* --- section with a background image ------------------------------------
   GenerateBlocks kept these in a --background-image custom property that only
   its own stylesheet read, so they rendered as tall EMPTY boxes here. */
.gl-block--bg{
  background-size:cover;background-position:center;background-repeat:no-repeat;
  border-radius:var(--gl-r);padding:clamp(1.75rem,1rem + 3vw,3.25rem);
  position:relative;color:#fff;overflow:hidden;
}
.gl-block--bg::before{content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
  background:linear-gradient(100deg,rgba(28,44,28,.86),rgba(28,44,28,.6))}
.gl-block--bg>*{position:relative;z-index:1}
.gl-block--bg h2,.gl-block--bg h3,.gl-block--bg h4{color:#fff}
.gl-block--bg a:not(.gl-btn){color:#CBEBCD}

/* Content blocks that carried builder-only layout: give them honest spacing
   instead of the collapsed/emptied boxes the stripped classes left behind. */
.gl-prose .gl-block{margin-block:0}
.gl-prose>.gl-block+.gl-block{margin-top:clamp(1.5rem,1rem + 1.6vw,2.75rem)}
/* Generic grid for converted content that is NOT a known component.
   ⚠ `.gl-prose .gl-grid` is (0,2,0) and outranks a component's own (0,1,0)
   class, so without the :not() list it shadows every component grid — today the
   two happen to compute the same column counts at every breakpoint, so nothing
   looks wrong, and a future change to a component's breakpoints would silently
   not apply. Third time this descendant selector has shadowed a component; see
   the `.gl-prose img` note above. Add new grid components here. */
.gl-prose .gl-grid:not(.gl-imgcards):not(.gl-cities):not(.gl-gal):not(.gl-svcgroups){
  display:grid;gap:clamp(1.1rem,.8rem + 1.2vw,2rem);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr));margin-block:1.6rem}
.gl-prose .gl-grid__col{min-width:0}
.gl-prose .gl-grid__col>*:first-child{margin-top:0}

/* Grid layouts whose display:grid lived in the (now absent) builder stylesheet.
   The inline style still carries grid-template-columns; this restores the rest. */
.gl-autogrid{display:grid;gap:clamp(1.2rem,.8rem + 1.6vw,2.5rem);align-items:center;
  margin-block:clamp(1.5rem,1rem + 1.5vw,2.5rem)}
.gl-autogrid>*{min-width:0}
.gl-autogrid>*:first-child{margin-top:0}
.gl-autogrid figure{margin:0}
.gl-autogrid img{border-radius:var(--gl-r);width:100%}
@media (max-width:760px){.gl-autogrid{grid-template-columns:1fr!important}}

/* --- media + text (34 of these sitewide) --------------------------------
   WordPress' media-text block: a two-cell grid, image left or right. The
   builder supplied display:grid from its own stylesheet; only the column
   template survived inline, so this restores the rest. */
.gl-mediatext{
  display:grid;gap:clamp(1.3rem,.9rem + 1.8vw,3rem);align-items:center;
  margin-block:clamp(1.75rem,1.2rem + 2vw,3.25rem);
}
.gl-mediatext__body>*:first-child{margin-top:0}
.gl-mediatext__body>*:last-child{margin-bottom:0}
.gl-mediatext__media{margin:0}
.gl-mediatext__media img{width:100%;border-radius:var(--gl-r);box-shadow:var(--gl-shadow)}
.gl-mediatext--media-right .gl-mediatext__media{order:2}
/* A trailing link in the body reads as a call to action, not stray underline. */
.gl-mediatext__body>a:last-child{
  display:inline-flex;align-items:center;gap:.45rem;margin-top:.3rem;
  font-weight:700;text-decoration:none;color:var(--gl-green);
}
.gl-mediatext__body>a:last-child::after{content:'→';transition:transform .25s var(--gl-ease)}
.gl-mediatext__body>a:last-child:hover::after{transform:translateX(4px)}
@media (max-width:760px){
  .gl-mediatext{grid-template-columns:1fr!important}
  .gl-mediatext--media-right .gl-mediatext__media{order:0}
}

/* --- column blocks ------------------------------------------------------- */
.gl-cols{display:grid;gap:clamp(1.1rem,.8rem + 1.4vw,2.2rem);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr));
  margin-block:clamp(1.5rem,1rem + 1.5vw,2.5rem)}
.gl-cols__col{min-width:0}
.gl-cols__col>*:first-child{margin-top:0}

/* --- embeds -------------------------------------------------------------- */
.gl-embed{margin-block:1.75rem}
.gl-embed__inner{position:relative;aspect-ratio:16/9;border-radius:var(--gl-r);
  overflow:hidden;background:#000}
.gl-embed__inner iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.gl-figure{margin:1.75rem 0}
.gl-figure img{border-radius:var(--gl-r)}
.gl-figure figcaption{font-size:.88rem;color:var(--gl-muted);margin-top:.55rem}

/* Links inside a dark background block need the light treatment. */
.gl-block--bg a:not(.gl-btn){color:#CBEBCD;font-weight:600}
.gl-block--bg p:last-child{margin-bottom:0}

/* Links in a dark banner render as ghost buttons.
   With its heading removed, this banner holds only its two links — as bare
   underlined text they read as an unfinished block rather than a deliberate
   one. Button treatment makes the band look intentional and gives each link a
   proper tap target. */
.gl-block--bg a:not(.gl-btn){
  display:inline-flex;align-items:center;gap:.5rem;
  margin:.4rem 1rem .4rem 0;padding:.72rem 1.35rem;
  border:2px solid rgba(255,255,255,.6);border-radius:999px;
  color:#fff;font-weight:700;font-size:.97rem;text-decoration:none;
  transition:background .22s var(--gl-ease),border-color .22s var(--gl-ease),
             transform .22s var(--gl-ease);
}
.gl-block--bg a:not(.gl-btn):hover{
  background:rgba(255,255,255,.15);border-color:#fff;color:#fff;transform:translateY(-2px)}
.gl-block--bg a:not(.gl-btn):last-child{margin-right:0}
/* A heading-less banner needs less vertical room than one carrying a headline. */
.gl-block--bg:not(:has(h2,h3,h4)){padding-block:clamp(1.5rem,1rem + 1.6vw,2.25rem)}
@media (prefers-reduced-motion:reduce){
  .gl-block--bg a:not(.gl-btn){transition:none;transform:none!important}}

/* --- form internals ------------------------------------------------------ */
.gl-subgrid{display:grid;gap:.9rem;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,170px),1fr))}
.gl-subgrid--4{grid-template-columns:repeat(auto-fit,minmax(min(100%,150px),1fr))}
.gl-formsection{
  font-size:1.12rem;font-weight:700;color:var(--gl-green-dk);
  margin-top:1.4rem;padding-bottom:.55rem;border-bottom:2px solid var(--gl-yellow);
}
.gl-formcopy{grid-column:1/-1;font-size:.95rem;color:var(--gl-muted);
  background:var(--gl-wash);border-radius:10px;padding:1rem 1.15rem}
.gl-formcopy>*:first-child{margin-top:0}
.gl-formcopy>*:last-child{margin-bottom:0}
.gl-formcopy p{margin-bottom:.6em}
.gl-form fieldset.gl-fieldset{grid-column:1/-1}
.gl-form button[type=submit]{margin-top:.4rem}

/* Hero text sits over a photograph whose luminance we do not control, so every
   text run on it carries a shadow as insurance beyond the computed contrast. */
.gl-hero__phones a,.gl-hero__eyebrow{text-shadow:none}
.gl-hero__phones a{text-shadow:0 1px 10px rgba(10,20,10,.7)}
/* A second, vertical scrim grounds the lower hero where CTAs and phones sit. */
.gl-hero::before{
  content:'';position:absolute;inset:auto 0 0 0;height:42%;z-index:1;pointer-events:none;
  background:linear-gradient(to top,rgba(16,29,16,.55),rgba(16,29,16,0));
}

/* Hero scrim on narrow viewports.
   The desktop scrim fades left-to-right because the text column occupies the
   left half. On mobile the text spans the FULL width, so it runs into the light
   end of that gradient and contrast drops. Go flat and stronger below 760px:
   at .70 over the lightest realistic photo pixel, white still clears 4.5:1. */
@media (max-width:760px){
  .gl-hero::after,.gl-phero::after{background:rgba(16,29,16,.70)}
  .gl-hero::before{display:none}
  .gl-hero h1,.gl-phero h1,.gl-hero__sub,.gl-phero p{max-width:none}
}

/* --- service-area city cards --------------------------------------------
   Replaces two columns of plain text links. Each card carries that town's own
   photograph from its own page, so the grid showcases the places rather than
   listing them. Whole card is one link — no nested interactive elements. */
.gl-cities{
  display:grid;gap:clamp(.9rem,.6rem + 1.1vw,1.5rem);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,255px),1fr));
  margin-block:clamp(1.6rem,1rem + 1.8vw,2.75rem);
}
.gl-city{
  display:flex;flex-direction:column;text-decoration:none;color:inherit;
  background:#fff;border:1px solid var(--gl-line);border-radius:var(--gl-r);
  overflow:hidden;box-shadow:var(--gl-shadow);position:relative;
  transition:transform .3s var(--gl-ease),box-shadow .3s var(--gl-ease),
             border-color .3s var(--gl-ease);
}
.gl-city:hover{transform:translateY(-5px);box-shadow:var(--gl-shadow-lift);
  border-color:#C3D9BF}
.gl-city:focus-visible{outline:3px solid var(--gl-green);outline-offset:3px}
.gl-city__media{display:block;position:relative;aspect-ratio:16/10;
  background:#EEEFEC;overflow:hidden;line-height:0}
.gl-city__media img{width:100%;height:100%;object-fit:cover;margin:0;
  border-radius:0;display:block;transition:transform .6s var(--gl-ease)}
.gl-city:hover .gl-city__media img{transform:scale(1.07)}
/* Yellow accent bar that grows on hover.
   ⚠ It lives on __body, NOT on __media. A pseudo-element on the SAME container
   as an <img> stops that image painting in this rendering path — the identical
   failure the hero hit (photo invisible, overlay visible). Keep image containers
   free of pseudo-elements and the <img> renders normally. */
.gl-city__body{position:relative}
.gl-city__body::before{
  content:'';position:absolute;left:0;right:0;top:0;height:4px;
  background:var(--gl-yellow);transform:scaleX(0);transform-origin:left;
  transition:transform .38s var(--gl-ease);
}
.gl-city:hover .gl-city__body::before{transform:scaleX(1)}
.gl-city__body{display:flex;flex-direction:column;flex:1;padding:1.05rem 1.15rem 1.15rem}
.gl-city__name{
  display:block;font-weight:800;font-size:1.22rem;line-height:1.2;
  letter-spacing:-.02em;color:var(--gl-ink);
}
.gl-city__name>span{font-weight:600;font-size:.82em;color:var(--gl-muted)}
.gl-city:hover .gl-city__name{color:var(--gl-green-dk)}
.gl-city__desc{display:block;margin-top:.35rem;font-size:.9rem;line-height:1.45;
  color:var(--gl-muted)}
.gl-city__more{
  display:inline-flex;align-items:center;gap:.4rem;margin-top:auto;padding-top:.85rem;
  font-weight:700;font-size:.92rem;color:var(--gl-green);
}
.gl-city__more span{transition:transform .25s var(--gl-ease)}
.gl-city:hover .gl-city__more span{transform:translateX(4px)}
@media (prefers-reduced-motion:reduce){
  .gl-city,.gl-city__media img,.gl-city__body::before,.gl-city__more span{
    transition:none!important;transform:none!important}
}

/* --- author box + byline -------------------------------------------------
   `wj-*` names on purpose: the STRUCTURE is the fleet's, generated by the
   shared /opt/aise/sa gen-author-box.php from _inc/site.md, so `sync-author`
   recognises it. The COLOURS are this site's — that CSS is deliberately NOT in
   the shared library ("shared structure, LOCAL brand"), so it lives here.
   Without this block the card renders unstyled and nothing reports it. */
.gl-byline{
  display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;
  margin:0 0 1.6rem;padding-bottom:1rem;border-bottom:1px solid var(--gl-line);
  font-size:.93rem;color:var(--gl-muted);
}
.gl-byline a{color:var(--gl-green);font-weight:700;text-decoration:none}
.gl-byline a:hover{text-decoration:underline}
.gl-byline time{color:var(--gl-muted)}

.wj-author-box{
  display:flex;gap:1.15rem;align-items:flex-start;
  margin:clamp(2.25rem,1.5rem + 2vw,3.25rem) 0 0;
  padding:clamp(1.25rem,1rem + 1vw,1.75rem);
  background:var(--gl-wash);border:1px solid var(--gl-line);
  border-left:5px solid var(--gl-green);
  border-radius:var(--gl-r);
}
/* Scoped to .gl-prose so it OUTRANKS `.gl-prose img` (0,1,1), which was giving
   the avatar the 14px content-image radius and a 1.6rem block margin. A bare
   `.wj-author-avatar` (0,1,0) loses that fight — the card is rendered inside
   .gl-prose on every post. */
.wj-author-avatar,
.gl-prose .wj-author-avatar{
  flex:0 0 auto;width:72px;height:72px;border-radius:50%;
  object-fit:cover;border:3px solid #fff;margin:0;
  box-shadow:0 2px 10px -4px rgba(39,50,39,.45);
}
.wj-author-text{min-width:0}
.wj-author-name{
  margin:0;font-family:var(--gl-font);font-weight:800;font-size:1.08rem;
  letter-spacing:-.01em;color:var(--gl-ink);
}
.wj-author-name a{color:var(--gl-green-dk);text-decoration:none}
.wj-author-name a:hover{text-decoration:underline}
.wj-author-role{
  margin:.15rem 0 .7rem;font-size:.86rem;font-weight:700;color:var(--gl-muted);
  text-transform:uppercase;letter-spacing:.05em;
}
.wj-author-bio{margin:0;font-size:.95rem;line-height:1.6;color:var(--gl-ink)}
.wj-author-highlights{
  margin:.9rem 0 0;padding:0;list-style:none;
  display:grid;gap:.35rem;font-size:.9rem;color:var(--gl-muted);
}
.wj-author-highlights li{margin:0;padding-left:1.4rem;position:relative}
.wj-author-highlights li::before{
  content:'';position:absolute;left:0;top:.52em;width:.5rem;height:.5rem;
  border-radius:50%;background:var(--gl-yellow);   /* decorative: never text */
}
.wj-author-social{display:flex;flex-wrap:wrap;gap:.9rem;margin-top:.9rem}
.wj-author-social a{
  font-size:.88rem;font-weight:700;color:var(--gl-green);
  text-decoration:none;padding:.2rem 0;
}
.wj-author-social a:hover{text-decoration:underline}
@media (max-width:560px){
  .wj-author-box{flex-direction:column;gap:.9rem}
  .wj-author-avatar{width:64px;height:64px}
}

/* --- grouped service links ("Services Include:") -------------------------
   The source marked each group's ITEMS as <h4> — seven headings in a row that
   were really a list. Rebuilt as a heading plus a real <ul>, presented as
   columns so the grouping reads at a glance instead of as three stacks of
   identical green underlined text. */
.gl-svcgroups{
  display:grid;gap:clamp(1rem,.7rem + 1.2vw,1.75rem);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));
  margin-block:clamp(1.5rem,1rem + 1.6vw,2.5rem);
}
.gl-svcgroup{
  background:#fff;border:1px solid var(--gl-line);border-radius:var(--gl-r);
  padding:1.35rem 1.4rem 1.4rem;box-shadow:var(--gl-shadow);
  transition:box-shadow .3s var(--gl-ease),border-color .3s var(--gl-ease);
}
.gl-svcgroup:hover{box-shadow:var(--gl-shadow-lift);border-color:#C8DCC4}
.gl-svcgroup__title{
  margin:0 0 .9rem;padding-bottom:.7rem;font-size:1.1rem;line-height:1.25;
  border-bottom:2px solid var(--gl-yellow);   /* decorative accent only */
}
.gl-svcgroup__title a{color:var(--gl-ink);text-decoration:none}
.gl-svcgroup__title a:hover{color:var(--gl-green-dk)}
.gl-svcgroup__list{list-style:none;margin:0;padding:0;display:grid;gap:.1rem}
.gl-svcgroup__list li{margin:0}
.gl-svcgroup__list a{
  display:flex;align-items:center;gap:.55rem;
  padding:.5rem .35rem;border-radius:8px;
  font-size:.95rem;font-weight:600;color:var(--gl-green);text-decoration:none;
  transition:background .18s var(--gl-ease),padding-left .18s var(--gl-ease);
}
.gl-svcgroup__list a::before{
  content:'';flex:0 0 auto;width:.4rem;height:.4rem;border-radius:50%;
  background:var(--gl-green);opacity:.55;
}
.gl-svcgroup__list a:hover{background:var(--gl-wash);color:var(--gl-green-dk);padding-left:.65rem}
.gl-svcgroup__list a:hover::before{opacity:1}
@media (prefers-reduced-motion:reduce){
  .gl-svcgroup,.gl-svcgroup__list a{transition:none}}

/* --- third-party embed fallback -----------------------------------------
   Shown only when a vendor embed's mount is still empty after it has had time
   to load (see site.js). Never appears when the embed works. */
.gl-embed-fallback{
  margin:1.25rem 0;padding:1.25rem 1.4rem;
  background:var(--gl-wash);border:1px solid var(--gl-line);
  border-left:5px solid var(--gl-yellow);border-radius:var(--gl-r);
}
.gl-embed-fallback p{margin:0 0 .6rem;font-size:.97rem}
.gl-embed-fallback p:last-child{margin-bottom:0}
.gl-embed-fallback__cta{display:flex;flex-wrap:wrap;gap:.7rem;margin-top:1rem}
.gl-embed-fallback__cta .gl-btn{padding:.7rem 1.25rem;font-size:.95rem}

/* ==========================================================================
   Gallery grid + lightbox
   Every tile is a REAL link to the image. The modal is layered on top by
   site.js, so with JS off the gallery still works — it just navigates.
   ========================================================================== */
/* THREE COLUMNS is the house standard for a converted gallery (Eric, 2026-08-20).
   Explicit counts, not auto-fill: auto-fill gave 4 columns at 1280 and a lone
   orphan tile on the last row. 3 -> 2 -> 1 as the viewport narrows. */
.gl-gal{
  display:grid;gap:clamp(.8rem,.6rem + 1vw,1.5rem);
  grid-template-columns:repeat(3,minmax(0,1fr));
  margin-block:clamp(1.5rem,1rem + 1.6vw,2.5rem);
}
@media (max-width:860px){.gl-gal{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.gl-gal{grid-template-columns:1fr}}
.gl-gal__item{margin:0;display:flex;flex-direction:column}
.gl-gal__link{
  position:relative;display:block;overflow:hidden;line-height:0;
  aspect-ratio:4/3;border-radius:var(--gl-r);background:#EEEFEC;
  box-shadow:var(--gl-shadow);
  transition:transform .3s var(--gl-ease),box-shadow .3s var(--gl-ease);
}
.gl-gal__link:hover{transform:translateY(-4px);box-shadow:var(--gl-shadow-lift)}
.gl-gal__link:focus-visible{outline:3px solid var(--gl-green);outline-offset:3px}
.gl-gal__link img{width:100%;height:100%;object-fit:cover;margin:0;border-radius:0;
  transition:transform .55s var(--gl-ease)}
.gl-gal__link:hover img{transform:scale(1.06)}
/* magnifier badge — pure CSS, no icon font */
.gl-gal__zoom{
  position:absolute;right:.6rem;bottom:.6rem;width:34px;height:34px;
  border-radius:50%;background:rgba(18,32,18,.62);backdrop-filter:blur(3px);
  opacity:0;transform:scale(.85);transition:opacity .25s var(--gl-ease),transform .25s var(--gl-ease);
}
.gl-gal__zoom::before{
  content:'';position:absolute;left:9px;top:9px;width:11px;height:11px;
  border:2px solid #fff;border-radius:50%;
}
.gl-gal__zoom::after{
  content:'';position:absolute;left:20px;top:20px;width:8px;height:2px;
  background:#fff;border-radius:2px;transform:rotate(45deg);
}
.gl-gal__link:hover .gl-gal__zoom,
.gl-gal__link:focus-visible .gl-gal__zoom{opacity:1;transform:scale(1)}
.gl-gal__item figcaption,.gl-gal__cap{
  font-size:.86rem;line-height:1.45;color:var(--gl-muted);
  padding:.6rem .15rem 0;
}
/* Caption galleries (a product catalogue, not just photos): the source caption
   carries a name, a price and a description, so the tile becomes a card. */
.gl-gal--cards .gl-gal__item{
  background:#fff;border:1px solid var(--gl-line);border-radius:var(--gl-r);
  overflow:hidden;box-shadow:var(--gl-shadow);
  transition:box-shadow .3s var(--gl-ease),border-color .3s var(--gl-ease);
}
.gl-gal--cards .gl-gal__item:hover{box-shadow:var(--gl-shadow-lift);border-color:#C8DCC4}
.gl-gal--cards .gl-gal__link{border-radius:0;box-shadow:none}
.gl-gal--cards .gl-gal__link:hover{transform:none}
.gl-gal--cards .gl-gal__cap{padding:1.05rem 1.15rem 1.25rem;color:var(--gl-ink)}
.gl-gal--cards .gl-gal__cap :is(h2,h3,h4){
  margin:0 0 .3rem;font-size:1.06rem;line-height:1.25;letter-spacing:-.01em;
}
/* the price line the source puts immediately after the name */
.gl-gal--cards .gl-gal__cap :is(h2,h3,h4) + p{
  margin:0 0 .55rem;font-weight:800;color:var(--gl-green);font-size:1rem;
}
.gl-gal--cards .gl-gal__cap p{margin:0 0 .5rem;font-size:.9rem;color:var(--gl-muted)}
.gl-gal--cards .gl-gal__cap p:last-child{margin-bottom:0}

/* --- lightbox ------------------------------------------------------------ */
body.gl-lb-open{overflow:hidden}          /* lock background scroll */
.gl-lb{position:fixed;inset:0;z-index:2000;display:flex;align-items:center;justify-content:center}
.gl-lb[hidden]{display:none}
.gl-lb__backdrop{position:absolute;inset:0;background:rgba(10,18,10,.88);
  animation:gl-lb-fade .22s var(--gl-ease)}
.gl-lb__panel{
  position:relative;z-index:1;display:flex;align-items:center;gap:.5rem;
  width:min(96vw,1180px);max-height:92vh;padding:0 .4rem;
}
.gl-lb__figure{
  margin:0;flex:1 1 auto;min-width:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;
}
.gl-lb__img{
  max-width:100%;max-height:78vh;width:auto;height:auto;margin:0;
  border-radius:var(--gl-r);background:#1a2a1a;
  box-shadow:0 24px 70px -20px rgba(0,0,0,.8);
  animation:gl-lb-in .28s var(--gl-ease);
}
.gl-lb__cap{
  margin:.9rem auto 0;max-width:70ch;text-align:center;
  color:#E8EFE7;font-size:.95rem;line-height:1.5;
}
.gl-lb__cap[hidden]{display:none}
.gl-lb__count{
  position:absolute;left:50%;bottom:-2.1rem;transform:translateX(-50%);
  margin:0;color:#B9C6B7;font-size:.85rem;letter-spacing:.04em;
}
.gl-lb__btn{
  flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  width:48px;height:48px;border:0;border-radius:50%;cursor:pointer;
  background:rgba(255,255,255,.14);color:#fff;font-size:1.9rem;line-height:1;
  transition:background .2s var(--gl-ease),transform .2s var(--gl-ease);
}
.gl-lb__btn:hover{background:rgba(255,255,255,.28)}
.gl-lb__btn:focus-visible{outline:3px solid var(--gl-yellow);outline-offset:2px}
.gl-lb__btn[hidden]{display:none}
.gl-lb__close{
  position:absolute;top:-3.1rem;right:0;width:44px;height:44px;font-size:1.7rem;
}
@keyframes gl-lb-fade{from{opacity:0}to{opacity:1}}
@keyframes gl-lb-in{from{opacity:0;transform:scale(.97)}to{opacity:1;transform:none}}

@media (max-width:640px){
  .gl-lb__panel{flex-direction:column;gap:.75rem;padding-top:3rem}
  .gl-lb__prev,.gl-lb__next{position:absolute;top:50%;transform:translateY(-50%)}
  .gl-lb__prev{left:.1rem}
  .gl-lb__next{right:.1rem}
  .gl-lb__close{top:.35rem;right:.35rem}
  .gl-lb__count{bottom:.2rem}
  .gl-lb__img{max-height:64vh}
}
@media (prefers-reduced-motion:reduce){
  .gl-gal__link,.gl-gal__link img,.gl-gal__zoom,.gl-lb__btn{transition:none!important}
  .gl-gal__link:hover{transform:none}
  .gl-gal__link:hover img{transform:none}
  .gl-lb__backdrop,.gl-lb__img{animation:none}
  .gl-gal__zoom{opacity:1;transform:none}
}

/* ==========================================================================
   Image card grids — a grid whose every column is image + heading + text.
   Four of these were rendering as bare columns: the 9 residential services,
   the 4-person team page, and two 3-up community-partner rows.
   ========================================================================== */
.gl-imgcards{
  display:grid;gap:clamp(1rem,.7rem + 1.2vw,1.6rem);
  grid-template-columns:repeat(3,minmax(0,1fr));
  margin-block:clamp(1.6rem,1rem + 1.8vw,2.75rem);
}
@media (max-width:900px){.gl-imgcards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.gl-imgcards{grid-template-columns:1fr}}

.gl-imgcard{
  display:flex;flex-direction:column;min-width:0;
  background:#fff;border:1px solid var(--gl-line);border-radius:var(--gl-r);
  overflow:hidden;box-shadow:var(--gl-shadow);
  transition:transform .3s var(--gl-ease),box-shadow .3s var(--gl-ease),
             border-color .3s var(--gl-ease);
}
.gl-imgcard:hover{transform:translateY(-4px);box-shadow:var(--gl-shadow-lift);
  border-color:#C8DCC4}
/* the source nests a spare wrapper inside each column; neutralise its spacing */
.gl-imgcard > *{min-width:0}
.gl-imgcard > div{display:flex;flex-direction:column;flex:1;min-width:0}

.gl-imgcard__media{
  margin:0;display:block;line-height:0;overflow:hidden;
  aspect-ratio:4/3;background:#EEEFEC;
}
.gl-imgcard__media img{
  width:100%;height:100%;object-fit:cover;margin:0;border-radius:0;
  transition:transform .55s var(--gl-ease);
}
.gl-imgcard:hover .gl-imgcard__media img{transform:scale(1.05)}
/* A partner's logo must never be cropped to fill the box. */
.gl-imgcard__media--logo{aspect-ratio:16/9;background:#fff;padding:1rem}
.gl-imgcard__media--logo img{object-fit:contain}
.gl-imgcard:hover .gl-imgcard__media--logo img{transform:none}

/* text inside the card */
.gl-imgcard :is(h2,h3,h4){
  margin:1.05rem 1.15rem .35rem;font-size:1.08rem;line-height:1.28;
  letter-spacing:-.01em;
}
.gl-imgcard p{margin:0 1.15rem .9rem;font-size:.93rem;line-height:1.55;
  color:var(--gl-muted)}
.gl-imgcard p:last-child{margin-bottom:1.15rem}
/* accordions live inside the team cards — keep them flush and working */
.gl-imgcard .gl-acc{margin:auto 1.15rem 1.15rem;border-radius:10px}
.gl-imgcard .gl-acc summary{padding:.75rem 2.4rem .75rem .9rem;font-size:.93rem}
.gl-imgcard .gl-acc summary::after{right:.9rem}
.gl-imgcard .gl-acc__body{padding:0 .9rem 1rem}

/* ==========================================================================
   Service cards — a heading-link plus its description. On
   /landscape-maintenance/ these had no shared parent, so they are styled
   individually rather than gathered into a grid.
   ========================================================================== */
.gl-svccard{
  background:var(--gl-wash);border:1px solid var(--gl-line);
  border-left:5px solid var(--gl-green);border-radius:var(--gl-r);
  padding:1.3rem 1.45rem;margin-block:clamp(1rem,.7rem + 1vw,1.5rem);
  transition:box-shadow .3s var(--gl-ease),transform .3s var(--gl-ease);
}
.gl-svccard:hover{box-shadow:var(--gl-shadow);transform:translateY(-2px)}
.gl-svccard :is(h2,h3,h4){margin:0 0 .45rem;font-size:1.16rem;line-height:1.25}
.gl-svccard :is(h2,h3,h4) a{
  color:var(--gl-green-dk);text-decoration:none;
  display:inline-flex;align-items:center;gap:.4rem;
}
.gl-svccard :is(h2,h3,h4) a::after{content:'→';transition:transform .25s var(--gl-ease)}
.gl-svccard:hover :is(h2,h3,h4) a::after{transform:translateX(4px)}
.gl-svccard :is(h2,h3,h4) a:hover{text-decoration:underline}
.gl-svccard p{margin:0 0 .6rem;font-size:.96rem}
.gl-svccard p:last-child{margin-bottom:0}

/* ==========================================================================
   Link chips — a run of bare heading-links was being used as a list. Headings
   with nothing under them are not sections.
   ========================================================================== */
.gl-chiprow{display:flex;flex-wrap:wrap;gap:.6rem;
  margin-block:clamp(1rem,.7rem + 1vw,1.6rem)}
.gl-chip{
  display:inline-flex;align-items:center;gap:.5rem;
  padding:.68rem 1.15rem;border-radius:999px;
  background:#fff;border:1.5px solid var(--gl-line);
  font-weight:700;font-size:.95rem;color:var(--gl-green-dk);text-decoration:none;
  transition:border-color .2s var(--gl-ease),background .2s var(--gl-ease),
             transform .2s var(--gl-ease);
}
.gl-chip::before{content:'';width:.4rem;height:.4rem;border-radius:50%;
  background:var(--gl-yellow)}         /* decorative accent only */
.gl-chip:hover{border-color:var(--gl-green);background:var(--gl-wash);
  color:var(--gl-green-dk);transform:translateY(-2px)}

@media (prefers-reduced-motion:reduce){
  .gl-imgcard,.gl-imgcard__media img,.gl-svccard,.gl-chip{
    transition:none!important;transform:none!important}
}
