:root {
  color-scheme: light;
  font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  background: #f7f7f5;
  color: #1d1d1d;
  font-size: 16px;
  line-height: 1.6;
  --brand: #35771a;
  --brand-dark: #2c6615;
  --brand-darker: #1f4a0f;
  /* the two stops of the header backdrop, and the ink that sits on them */
  --lime-bright: #63c92c;
  --lime: #9ae03f;
  --lime-dark: #7ccb3a;
  --ink: #102309;
  --ink-soft: #17380d;
  /* review stars only: the one warm colour on the page, so it reads as a
     rating rather than as brand furniture */
  --gold: #f2b307;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 3px solid var(--brand-dark);
  outline-offset: 2px;
}

.site-header a:focus-visible,
.site-header button:focus-visible {
  outline-color: var(--ink);
}

.skip-link {
  position: absolute;
  left: 1rem;
  top: -10rem;
  z-index: 100;
  background: #fff;
  color: var(--brand-darker);
  padding: 0.75rem 1.25rem;
  border-radius: 0 0 14px 14px;
  font-weight: 700;
  text-decoration: none;
}

.skip-link:focus {
  top: 0;
}

body {
  min-height: 100vh;
}

img {
  max-width: 100%;
  display: block;
}

.container {
  width: min(1120px, calc(100% - 2rem));
  margin: 0 auto;
}

.site-header {
  min-height: 84vh;
  padding: 2.5rem 0 4rem;
  display: grid;
  gap: 6rem;
  background: linear-gradient(135deg, var(--lime-bright) 0%, var(--lime) 55%);
  color: var(--ink);
  position: relative;
  overflow: hidden;
}

.site-header::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at top center, rgba(255, 255, 255, 0.18), transparent 28%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(31, 74, 15, 0.14));
  pointer-events: none;
  z-index: 0;
}

/* full-bleed white band behind the logo/nav that melts into the green hero */
.site-header::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 600px;
  background: linear-gradient(
    180deg,
    #ffffff 0%,
    #ffffff 64%,
    rgba(255, 255, 255, 0.9) 74%,
    rgba(255, 255, 255, 0.65) 83%,
    rgba(255, 255, 255, 0.35) 91%,
    rgba(255, 255, 255, 0.12) 96%,
    rgba(255, 255, 255, 0) 100%
  );
  pointer-events: none;
  z-index: 2;
}

.header-inner,
.site-header .hero-content {
  position: relative;
  z-index: 1;
}

.header-inner {
  display: grid;
  place-items: center;
  gap: 1.25rem;
  text-align: center;
  z-index: 3;
}

.brand {
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

.brand-logo {
  width: auto;
  height: 300px;
  object-fit: contain;
  object-position: center;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.main-nav {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
}

.main-nav a {
  color: var(--brand-darker);
  text-decoration: none;
  font-weight: 600;
}

.main-nav a:hover {
  color: var(--brand);
}

.mobile-nav-toggle {
  display: none;
  position: fixed;
  /* respect the notch / status-bar safe area, and sit higher up */
  top: calc(env(safe-area-inset-top, 0px) + 0.5rem);
  left: calc(env(safe-area-inset-left, 0px) + 0.85rem);
  z-index: 60;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 0;
  background: linear-gradient(145deg, #9ae03f, #6cbf33);
  color: var(--ink);
  border-radius: 999px;
  box-shadow: 0 8px 20px rgba(20, 46, 10, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.25);
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.mobile-nav-toggle:hover {
  box-shadow: 0 10px 24px rgba(20, 46, 10, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.mobile-nav-toggle:active {
  transform: scale(0.94);
}

/* crisp hamburger drawn from three bars; morphs into an X when the menu is open */
.nav-toggle-icon {
  position: relative;
  display: block;
  width: 20px;
  height: 2.5px;
  border-radius: 2px;
  background: var(--ink);
  transition: background 0.2s ease;
}

.nav-toggle-icon::before,
.nav-toggle-icon::after {
  content: "";
  position: absolute;
  left: 0;
  width: 20px;
  height: 2.5px;
  border-radius: 2px;
  background: var(--ink);
  transition: transform 0.2s ease, top 0.2s ease;
}

.nav-toggle-icon::before {
  top: -6.5px;
}

.nav-toggle-icon::after {
  top: 6.5px;
}

.site-header.nav-open .nav-toggle-icon {
  background: transparent;
}

.site-header.nav-open .nav-toggle-icon::before {
  top: 0;
  transform: rotate(45deg);
}

.site-header.nav-open .nav-toggle-icon::after {
  top: 0;
  transform: rotate(-45deg);
}

.site-header .hero-content {
  display: grid;
  grid-template-columns: 1.2fr 0.8fr;
  gap: 2rem;
  align-items: center;
}

/* Shop opening strip: sits between the logo and the hero copy. Nothing here is
   boxed — the photos are feathered at every edge with a mask so they dissolve
   into the header gradient, and the text sits straight on the background. */
.shop-opening {
  position: relative;
  z-index: 3;
  display: grid;
  justify-items: center;
  gap: 1.75rem;
  /* trim the header's 6rem row gap so the strip hugs the logo and the hero */
  margin-top: -3rem;
  margin-bottom: -2rem;
}

.open-now {
  /* inline dot rather than a flex row, so it stays with the first word when
     the line wraps on narrow screens instead of floating beside both lines */
  display: block;
  margin: 0;
  /* the deepest lime that still holds 3:1 on the white band — a full-strength
     lime here would be all but unreadable */
  color: #4aa826;
  font-weight: 800;
  font-size: clamp(1.2rem, 2.4vw, 1.85rem);
  line-height: 1.25;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-align: center;
  text-wrap: balance;
}

.open-now-dot {
  display: inline-block;
  width: 0.7rem;
  height: 0.7rem;
  margin-right: 0.7rem;
  vertical-align: 0.05em;
  border-radius: 50%;
  background: #5cb32b;
  box-shadow: 0 0 0 0.35rem rgba(92, 179, 43, 0.2);
}

@media (prefers-reduced-motion: no-preference) {
  .open-now-dot {
    animation: open-now-pulse 2.6s ease-in-out infinite;
  }
}

@keyframes open-now-pulse {
  0%, 100% { box-shadow: 0 0 0 0.3rem rgba(92, 179, 43, 0.18); }
  50% { box-shadow: 0 0 0 0.55rem rgba(92, 179, 43, 0.04); }
}

.shop-opening-photos {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
  width: 100%;
}

/* The opening photo and the showroom clip no longer sit side by side: the hero
   copy runs between them. Each takes the row on its own, held to about the
   width it had as half of the pair rather than stretching to the container. */
.shop-opening-photos-single {
  grid-template-columns: minmax(0, 1fr);
}

.shop-opening-photos-single .shop-photo,
.shop-opening-photos-single figcaption {
  max-width: 36rem;
  margin-inline: auto;
}

/* the clip sits under the hero copy rather than up beside the logo, so it
   trims the header's 6rem row gap instead of the photo's -3rem pull.

   It also drops the -2rem bottom margin: the clip is the last thing in the
   header, and the header hides its overflow, so pulling the block up cut the
   tail off the flooring description on narrow screens. */
.shop-opening-clip {
  margin-top: -2.75rem;
  margin-bottom: 0;
}

.shop-opening-photos figure {
  margin: 0;
}

.shop-opening-photos .shop-photo {
  display: block;
}

/* A hairline edge and a soft shadow give the photos a defined frame; the
   feathering that came before left them dissolving into the lime. */
.shop-opening-photos img {
  display: block;
  width: 100%;
  height: clamp(24rem, 32vw, 30rem);
  object-fit: cover;
  object-position: center 35%;
  border: 1px solid rgba(14, 36, 6, 0.22);
  box-shadow: 0 2px 12px rgba(20, 46, 10, 0.16),
    0 22px 48px rgba(20, 46, 10, 0.22);
}

.shop-opening-photos figcaption {
  margin-top: 0.75rem;
  color: var(--ink-soft);
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  text-align: center;
}

/* the range summary under the showroom clip: sentence case, so it reads as
   copy rather than another uppercase label */
.shop-photo-note {
  margin: 0.6rem auto 0;
  max-width: 34ch;
  color: var(--ink-soft);
  font-size: 0.85rem;
  line-height: 1.5;
  text-align: center;
  text-wrap: pretty;
}

.eyebrow {
  display: inline-block;
  margin-bottom: 1rem;
  font-size: 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--ink-soft);
}

.site-header .hero-content h1 {
  font-size: clamp(2rem, 4vw, 3.5rem);
  margin: 0 0 1.2rem;
  max-width: 20ch;
  color: var(--ink);
}

.site-header .hero-content p {
  max-width: 45rem;
  margin: 0 0 1.75rem;
  color: var(--ink-soft);
}

.site-header .hero-box {
  border-radius: 24px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.75);
  box-shadow: 0 24px 60px rgba(20, 46, 10, 0.14);
  color: var(--ink);
  padding: 2rem;
}

/* the call to action closes the box, sitting under the reasons rather than
   floating on the lime beside them, where a lime button had little to hold it */
.site-header .hero-box .button {
  display: flex;
  margin-top: 1.5rem;
}

.site-header .hero-box h2 {
  margin: 0 0 1rem;
  font-size: 1.35rem;
}

.site-header .hero-box ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.85rem;
}

.site-header .hero-box li {
  padding-left: 1.2rem;
  position: relative;
}

.site-header .hero-box li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.65rem;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--brand);
}

.section {
  padding: 4rem 0;
}

/* the eyebrow specifically, not any span that lands in a section header — the
   stars and their label sit in one too, and were being styled as eyebrows */
.section-header .eyebrow {
  display: inline-block;
  margin-bottom: 0.75rem;
  color: var(--brand);
  text-transform: uppercase;
  letter-spacing: 0.15em;
  font-size: 0.8rem;
  font-weight: 700;
}

.section-header h2 {
  margin: 0;
  font-size: clamp(2rem, 3vw, 2.7rem);
}

.services-grid,
.contact-grid,
.slideshow-controls {
  display: grid;
  gap: 1.5rem;
}

.services-grid {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

/* Before/after sliders sitting inside a service card. They reuse the .ba-*
   component; only the card chrome is stripped, since these already sit
   inside a card. */
.service-ba {
  display: grid;
  gap: 1.25rem;
  margin-top: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
}

.service-ba .ba-card {
  background: none;
  box-shadow: none;
}

/* one frame for both the sliders and the still shots beside them */
.service-ba .ba-compare,
.service-ba .ba-still {
  border-radius: 0;
  border: 1px solid rgba(14, 36, 6, 0.18);
}

.service-ba .ba-card figcaption {
  padding: 0.75rem 0 0;
  font-size: 0.92rem;
}

/* a card carrying comparisons or a slideshow takes the whole grid row, so the
   sliders are big enough to actually drag */
@media (min-width: 760px) {
  .service-card-wide {
    grid-column: 1 / -1;
  }

  .service-ba {
    gap: 1.5rem;
  }
}

.slideshow {
  position: relative;
  background: #fff;
  border-radius: 24px;
  overflow: hidden;
  box-shadow: 0 18px 45px rgba(15, 15, 15, 0.06);
  min-height: 28rem;
}

/* visibility rides along with opacity so inactive slides drop out of
   hit-testing instead of sitting invisibly on top of the active slide.
   NOTE: no decoding="async" on the slide <img>s — Chrome can rasterise the
   layer before the async decode lands and never repaint (white slideshow). */
.slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.6s ease, visibility 0.6s;
  display: grid;
  place-items: center;
}

.slide.active {
  opacity: 1;
  visibility: visible;
}

.slide img {
  width: 100%;
  height: auto;
  max-height: 540px;
  object-fit: cover;
  border: none;
  border-radius: 0;
}

.slideshow-controls {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 1rem;
  margin-top: 1rem;
}

/* keep Previous and Next the same width so the row is balanced */
.slideshow-controls .prev,
.slideshow-controls .next {
  min-width: 7rem;
}

.slide-btn {
  background: var(--lime);
  border: none;
  color: var(--ink);
  border-radius: 999px;
  padding: 0.9rem 1.4rem;
  cursor: pointer;
  font-weight: 700;
}

.slide-btn:hover {
  background: var(--lime-dark);
}

.slide-counter {
  font-weight: 700;
  color: #54504b;
  min-width: 4.5rem;
  text-align: center;
}

/* Fullscreen slideshow styling.
   .fullscreen is set via the Fullscreen API; .fullscreen-fallback is the
   fixed-position stand-in for browsers without it (iPhone Safari). */
.slideshow.fullscreen,
.slideshow.fullscreen-fallback {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
  border-radius: 0;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100vw;
  height: 100vh;
  min-height: 100vh;
  overflow: hidden;
}

.slideshow.fullscreen .slide,
.slideshow.fullscreen-fallback .slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.slideshow.fullscreen .slide.active,
.slideshow.fullscreen-fallback .slide.active {
  opacity: 1;
}

.slideshow.fullscreen-fallback .close-fullscreen {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 1;
  display: inline-flex;
}

.close-fullscreen {
  display: none;
}

body.slideshow-fullscreen-open {
  overflow: hidden;
}

.slideshow.fullscreen .slide img,
.slideshow.fullscreen-fallback .slide img {
  width: auto;
  height: auto;
  max-width: 95vw;
  max-height: 95vh;
  object-fit: contain;
}

/* Pause + fullscreen as compact icon buttons overlaid on the image's
   bottom-right corner, instead of full pill buttons in the controls row. */
.slide-actions {
  position: absolute;
  right: 0.75rem;
  bottom: 0.75rem;
  z-index: 3;
  display: flex;
  gap: 0.5rem;
}

.slide-icon-btn {
  display: inline-grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(17, 30, 22, 0.55);
  color: #fff;
  cursor: pointer;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.28);
  transition: background 0.15s ease, transform 0.15s ease;
}

.slide-icon-btn:hover {
  background: var(--lime);
  color: var(--ink);
}

.slide-icon-btn:active {
  transform: scale(0.94);
}

.slide-icon-btn .icon {
  width: 1.15rem;
  height: 1.15rem;
  display: block;
}

.icon-pause,
.icon-play {
  fill: currentColor;
}

.icon-expand,
.icon-compress {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* swap icons based on the button's state (aria-pressed toggled in JS) */
.slide-icon-btn .icon-play,
.slide-icon-btn .icon-compress {
  display: none;
}

.slide-icon-btn.pause[aria-pressed="true"] .icon-pause,
.slide-icon-btn.fullscreen[aria-pressed="true"] .icon-expand {
  display: none;
}

.slide-icon-btn.pause[aria-pressed="true"] .icon-play,
.slide-icon-btn.fullscreen[aria-pressed="true"] .icon-compress {
  display: block;
}

/* Before & after comparisons. The two photos sit on top of one another and the
   "after" fades in and out over the "before" on a slow loop, with the chips
   fading in step so the one on show is always named. Each card carries its own
   --ba-delay so they are not all turning over together. */
.section-intro {
  margin: 0.75rem 0 0;
  color: #54504b;
  max-width: 45rem;
}

.ba-card {
  margin: 0;
  background: #fff;
  border-radius: 24px;
  box-shadow: 0 18px 45px rgba(15, 15, 15, 0.06);
}

.ba-card figcaption {
  padding: 1rem 1.5rem 1.25rem;
  font-weight: 600;
  color: #54504b;
}

.ba-compare {
  --ba-delay: 0s;
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: #e8e6e1;
  border-radius: 24px 24px 0 0;
}

/* clips the photos (and their rounded top corners) without clipping the
   handle, which lives outside this layer */
.ba-media {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
}

.ba-compare-portrait {
  aspect-ratio: 3 / 4;
}

/* for pairs shot at different orientations, squared off to a common frame */
.ba-compare-square {
  aspect-ratio: 1 / 1;
}

/* Icon above a service heading, sized to the type rather than the card */
.service-icon {
  display: block;
  width: 2.4rem;
  height: 2.4rem;
  margin-bottom: 0.6rem;
  color: var(--brand-darker);
}

/* Compact slideshow for a service card: one 16:9 stage, arrows either side and
   dots beneath. Independent of the portfolio slideshow further down the page. */
.mini-slideshow {
  position: relative;
  margin-top: 1.25rem;
  max-width: 52rem;
}

.mini-stage {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 1px solid rgba(14, 36, 6, 0.22);
  box-shadow: 0 2px 12px rgba(20, 46, 10, 0.16),
    0 22px 48px rgba(20, 46, 10, 0.22);
  background: #e8e6e1;
}

.mini-slide {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  transition: opacity 0.5s ease;
}

@media (prefers-reduced-motion: reduce) {
  .mini-slide {
    transition: none;
  }
}

.mini-slide.is-active {
  opacity: 1;
}

.mini-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.mini-slide figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 2.5rem 1rem 0.9rem;
  color: #f4f7f0;
  font-size: 0.9rem;
  font-weight: 600;
  background: linear-gradient(180deg, rgba(16, 35, 9, 0), rgba(16, 35, 9, 0.78));
}

.mini-nav {
  position: absolute;
  top: calc(50% - 1.5rem);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  background: rgba(16, 35, 9, 0.55);
  color: #f4f7f0;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background 0.15s ease;
}

.mini-nav:hover {
  background: var(--lime);
  color: var(--ink);
}

.mini-prev {
  left: 0.75rem;
}

.mini-next {
  right: 0.75rem;
}

.mini-dots {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 0.9rem;
}

.mini-dot {
  width: 0.55rem;
  height: 0.55rem;
  padding: 0;
  border: 1px solid rgba(14, 36, 6, 0.35);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background 0.15s ease;
}

.mini-dot[aria-selected="true"] {
  background: var(--lime);
  border-color: rgba(14, 36, 6, 0.35);
}

/* a pair of tall comparisons: hold them to a sensible width rather than let
   two portrait frames stretch across the whole row */
.service-ba-tall {
  max-width: 46rem;
}

/* landscape pairs — gardens read better wide than square */
.ba-compare-landscape {
  aspect-ratio: 3 / 2;
}

/* a finished shot with no matching before: same frame as its slider siblings,
   minus the wipe */
.ba-still {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
}

.ba-still img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ba-still-landscape {
  aspect-ratio: 3 / 2;
}

.ba-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Nine seconds a turn: a long hold on each photo so it can be looked at, and
   a slow dissolve between them. The chips run the same cycle inverted. */
@keyframes ba-reveal {
  0%, 38% { opacity: 0; }
  50%, 88% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes ba-label-before {
  0%, 38% { opacity: 1; }
  50%, 88% { opacity: 0; }
  100% { opacity: 1; }
}

/* the after layer starts hidden; the animation (or, without motion, the
   override below) brings it up. Declared here, ahead of both media blocks. */
.ba-img-after,
.ba-tag-after {
  opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
  .ba-img-after,
  .ba-tag-after {
    animation: ba-reveal 9s ease-in-out var(--ba-delay) infinite;
  }

  .ba-tag-before {
    animation: ba-label-before 9s ease-in-out var(--ba-delay) infinite;
  }
}

/* Nothing moves for readers who ask for less motion: the finished work is held
   on screen, labelled, rather than cycling. */
@media (prefers-reduced-motion: reduce) {
  .ba-img-after,
  .ba-tag-after {
    opacity: 1;
  }

  .ba-tag-before {
    opacity: 0;
  }
}

/* Small squared chips rather than shouty pills: matched weight and size on
   both sides, frosted so they sit on any photo without a hard slab. */
.ba-tag {
  position: absolute;
  top: 0.75rem;
  padding: 0.28rem 0.6rem;
  border-radius: 4px;
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  line-height: 1;
  color: #f2f6ec;
  background: rgba(16, 35, 9, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.22);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  box-shadow: 0 2px 8px rgba(16, 35, 9, 0.25);
  pointer-events: none;
  transition: opacity 0.15s ease;
}

.ba-tag-before {
  left: 0.75rem;
}

.ba-tag-after {
  right: 0.75rem;
  background: var(--lime);
  color: var(--ink);
  border-color: rgba(16, 35, 9, 0.28);
}

.service-card {
  background: #fff;
  border-radius: 24px;
  padding: 1.75rem;
  box-shadow: 0 18px 45px rgba(15, 15, 15, 0.06);
}

.service-card h3 {
  margin-top: 0;
}

.service-card p {
  margin: 0.75rem 0 0;
  color: #54504b;
}

.contact-grid {
  grid-template-columns: 1.2fr 0.8fr;
  align-items: start;
}

.contact-form {
  display: grid;
  gap: 1rem;
  background: #fff;
  padding: 2rem 2rem 1.25rem;
  border-radius: 24px;
  box-shadow: 0 18px 45px rgba(15, 15, 15, 0.05);
}

.contact-form label {
  font-weight: 600;
}

.contact-form input,
.contact-form textarea {
  width: 100%;
  border: 1px solid #d8d4ce;
  border-radius: 14px;
  padding: 0.95rem 1rem;
  font: inherit;
  color: #1f1d19;
  background: #fff;
}

.contact-details p {
  margin: 0 0 0.75rem;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 1rem 1.6rem;
  color: var(--ink);
  background: var(--lime);
  border: none;
  border-radius: 999px;
  text-decoration: none;
  font-weight: 700;
  font-size: 1.1rem;
  cursor: pointer;
}

.button:hover {
  background: var(--lime-dark);
}

/* Section eyebrow on light backgrounds */
.eyebrow-dark {
  display: inline-block;
  margin-bottom: 0.75rem;
  color: var(--brand);
  text-transform: uppercase;
  letter-spacing: 0.15em;
  font-size: 0.8rem;
  font-weight: 700;
}

.about-inner {
  max-width: 60rem;
}

/* The shop's own before/after, sitting under the About copy. It is the one
   comparison on the page that is about AGG rather than a client's property,
   so it gets a heading and a little air above it rather than dropping
   straight out of the paragraph. */
.about-origin {
  margin-top: 3rem;
  display: grid;
  gap: 1rem;
}

.about-origin h3 {
  margin: 0;
  font-size: 1.35rem;
}

.about-origin p {
  margin: 0;
}

.about-origin .ba-card {
  margin-top: 0.75rem;
}

.contact-details a {
  color: var(--brand-dark);
  text-decoration: none;
  font-weight: 600;
}

.contact-details a:hover {
  text-decoration: underline;
}

.form-status {
  margin: 0;
  color: var(--brand-dark);
  font-weight: 600;
}

/* don't reserve empty space (and grid gap) below the button until there's a message */
.form-status:empty {
  display: none;
}

.site-footer {
  background: #111110;
  color: #c3c0b8;
  padding: 2rem 0;
}

.footer-inner {
  text-align: center;
}

@media (max-width: 900px) {
  .site-header {
    min-height: auto;
    padding: 2rem 0 3rem;
  }

  .header-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  .mobile-nav-toggle {
    display: flex;
  }

  .main-nav {
    display: none;
    position: fixed;
    top: 4.75rem;
    left: 1rem;
    z-index: 59;
    width: min(15rem, calc(100% - 2rem));
    flex-direction: column;
    gap: 0;
    padding: 0.25rem 1rem;
    background: #ffffff;
    border: 1px solid rgba(43, 101, 20, 0.15);
    box-shadow: 0 18px 40px rgba(20, 46, 10, 0.18);
    border-radius: 20px;
  }

  .site-header.nav-open .main-nav {
    display: flex;
  }

  .main-nav a {
    padding: 0.85rem 0;
    border-bottom: 1px solid rgba(43, 101, 20, 0.12);
  }

  .main-nav a:last-child {
    border-bottom: none;
  }

  .brand {
    justify-content: center;
    width: 100%;
  }

  .brand-logo {
    max-height: 220px;
    width: auto;
  }

  /* Solid white just past the logo, then a short fade that finishes ABOVE
     the "Craftsmanship…" eyebrow so the pale text lands on solid green. */
  .site-header::before {
    height: 440px;
    background: linear-gradient(
      180deg,
      #ffffff 0%,
      #ffffff 350px,
      rgba(255, 255, 255, 0.7) 390px,
      rgba(255, 255, 255, 0.3) 420px,
      rgba(255, 255, 255, 0) 440px
    );
  }

  .site-header .hero-content,
  .contact-grid {
    grid-template-columns: 1fr;
  }

  .site-header .hero-content {
    align-items: flex-start;
    gap: 1.75rem;
  }
}

@media (max-width: 600px) {
  .site-header,
  .section,
  .site-footer {
    padding-left: 1rem;
    padding-right: 1rem;
  }

  .site-header {
    padding-top: 1.5rem;
    padding-bottom: 2rem;
  }

  .site-header .hero-content h1 {
    font-size: clamp(2rem, 6vw, 2.5rem);
    max-width: 100%;
  }

  .site-header .hero-content p {
    max-width: 100%;
    margin-bottom: 1.5rem;
  }

  .site-header .hero-box {
    padding: 1.5rem;
  }

  .brand-logo {
    max-height: 180px;
  }

  /* small stage: shrink the controls and keep the caption clear of them */
  .mini-nav {
    top: calc(50% - 2.4rem);
    width: 2rem;
    height: 2rem;
    font-size: 1.1rem;
  }

  .mini-prev {
    left: 0.5rem;
  }

  .mini-next {
    right: 0.5rem;
  }

  .mini-slide figcaption {
    padding: 1.75rem 0.75rem 0.7rem;
    font-size: 0.78rem;
  }

  .shop-opening {
    gap: 1.35rem;
    margin-top: -3.5rem;
    margin-bottom: -2.5rem;
  }

  /* same as above: the last block in the header keeps its bottom edge inside
     the green, or the header's hidden overflow trims the description */
  .shop-opening-clip {
    margin-bottom: 0;
  }

  .shop-opening-photos {
    grid-template-columns: 1fr;
    gap: 0.5rem;
  }

  .shop-opening-photos img {
    height: 15rem;
  }

  .site-header::before {
    height: 400px;
    background: linear-gradient(
      180deg,
      #ffffff 0%,
      #ffffff 310px,
      rgba(255, 255, 255, 0.7) 350px,
      rgba(255, 255, 255, 0.3) 380px,
      rgba(255, 255, 255, 0) 400px
    );
  }

  .main-nav {
    gap: 0.8rem;
  }

  .container {
    width: min(100%, calc(100% - 1rem));
  }

  .slideshow-controls {
    gap: 0.6rem;
  }

  .slide-btn {
    padding: 0.75rem 1.1rem;
    font-size: 0.9rem;
  }

  .slideshow {
    min-height: 18rem;
  }
}

/* The stars are the heading: the rating is the claim, and spelling it out
   beside them said the same thing twice. The wording survives for screen
   readers, which cannot see gold. */
.review-heading {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.15rem 0.6rem;
  margin: 0.75rem 0 0;
  line-height: 1;
}

/* set below the heading scale: the stars are the headline, this names where
   they come from */
.review-heading-label {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
}

.review-stars {
  display: inline-flex;
  gap: 0.2rem;
}

.review-star {
  width: 1.9rem;
  height: 1.9rem;
  fill: var(--gold);
}

/* Customer reviews, as left on Google, on the same card as the services grid
   so the quotes read as part of the site rather than a bolted-on widget.
   One row, always. Four quotes fit side by side on a desktop; on a narrower
   screen the row scrolls sideways a card at a time rather than stacking into a
   column, which buried the last of them a screen and a half down. */
.review-list {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0 0 0.75rem;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(15rem, 1fr);
  gap: 1.5rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  overscroll-behavior-x: contain;
}

.review-card {
  scroll-snap-align: start;
  background: #fff;
  border-radius: 24px;
  padding: 1.75rem;
  box-shadow: 0 18px 45px rgba(15, 15, 15, 0.06);
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.review-card .review-star {
  width: 1.1rem;
  height: 1.1rem;
}

.review-card blockquote {
  margin: 0;
  color: #33302c;
}

/* quotes run to different lengths; the names line up along the bottom of the
   row rather than trailing each quote at a different height */
.review-card cite {
  margin-top: auto;
  font-style: normal;
  font-weight: 700;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--brand-dark);
}

.review-cta {
  margin: 1.5rem 0 0;
}

.review-cta a {
  color: var(--brand-dark);
  font-weight: 600;
}

/* Showroom gallery in the header: the clip and three shop photos, one large
   with the rest small beside it. The pictures run to different shapes, so each
   is sized by height and keeps its own width rather than being cropped to a
   shared frame; the stage is wide enough for the widest of them, and the
   others simply sit narrower in the middle of it. */
.showroom {
  width: 100%;
  display: grid;
  justify-items: center;
}

.showroom-viewer {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 1rem;
  width: 100%;
  max-width: 48rem;
}

.showroom-stage {
  position: relative;
  display: grid;
  /* a definite row, or the slides' height: 100% resolves against an auto row
     and they spill past the stage instead of being held by it */
  grid-template-rows: minmax(0, 1fr);
  place-items: center;
  height: clamp(22rem, 30vw, 28rem);
  overflow: hidden;
}

/* The stage is a fixed frame at every width, so nothing below it moves as the
   pictures change. Each slide fills its height and keeps its own width, except
   the two landscape shots, which cover the frame — they are wide enough to lose
   a little off the top and bottom, and it stops green banding above and below
   them. The clip and the portrait seating shot are not, so those keep their
   shape. Inactive slides stay in place and are faded out rather than removed,
   which is what lets one picture dissolve into the next. */
.showroom-slide {
  grid-area: 1 / 1;
  width: auto;
  height: 100%;
  max-width: 100%;
  border: 1px solid rgba(14, 36, 6, 0.22);
  box-shadow: 0 2px 12px rgba(20, 46, 10, 0.16),
    0 22px 48px rgba(20, 46, 10, 0.22);
  opacity: 0;
  transform: scale(0.94);
  pointer-events: none;
  transition: opacity 0.45s ease, transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* the one on show settles up to full size as it fades in */
.showroom-slide.is-active {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.showroom-slide-fill {
  width: 100%;
  object-fit: cover;
}

.showroom-nav {
  position: absolute;
  top: calc(50% - 1.25rem);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  background: rgba(16, 35, 9, 0.55);
  color: #f4f7f0;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background 0.15s ease;
}

.showroom-nav:hover {
  background: var(--lime);
  color: var(--ink);
}

.showroom-prev {
  left: 0.5rem;
}

.showroom-next {
  right: 0.5rem;
}

.showroom-thumbs {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.showroom-thumb {
  display: block;
  padding: 0;
  width: 5rem;
  height: 3.9rem;
  border: 1px solid rgba(14, 36, 6, 0.22);
  border-radius: 4px;
  background: none;
  overflow: hidden;
  cursor: pointer;
  opacity: 0.72;
  transition: opacity 0.15s ease, box-shadow 0.15s ease;
}

.showroom-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.showroom-thumb:hover {
  opacity: 1;
}

/* the one currently large: full strength and ringed in ink */
.showroom-thumb[aria-pressed="true"] {
  opacity: 1;
  box-shadow: 0 0 0 2px var(--ink);
}

/* the four captions share one cell, so the block is as tall as the longest and
   holds its height as they swap */
.showroom-text {
  display: grid;
  width: 100%;
}

.showroom-copy {
  grid-area: 1 / 1;
  opacity: 0;
  transition: opacity 0.45s ease;
}

.showroom-copy.is-active {
  opacity: 1;
}

.showroom-caption {
  margin: 1rem 0 0;
  color: var(--ink-soft);
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  text-align: center;
}

.showroom-note {
  max-width: 40ch;
}

@media (max-width: 640px) {
  /* thumbnails drop under the stage, since there is no room beside it */
  .showroom-viewer {
    grid-template-columns: minmax(0, 1fr);
  }

  .showroom-thumbs {
    grid-auto-flow: column;
    justify-content: center;
  }

  .showroom-thumb {
    width: 4.2rem;
    height: 3.3rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .showroom-slide,
  .showroom-copy {
    transition: none;
  }

  .showroom-slide {
    transform: none;
  }
}
