/* ==========================================================================
   Upstate KC Builders, design system.

   Identity: the logo, enlarged. The mark is a KC monogram cut from an
   excavator arm and a tape measure in exactly three values, and the site uses
   the same three and nothing else. Corners are near-square and edges are
   ruled rather than shadowed, because this is a company whose work is
   measured in seams, joints and reveals. The recurring motif is the standing
   seam: thin vertical rules at a fixed rhythm, on section caps and hero edges.

   THE ONE STRUCTURAL PROBLEM, and how it is solved.
   The brand palette is three neutrals with no accent hue, so nothing is
   naturally louder than anything else and a call to action has nothing to pop
   against. Rather than invent a colour the brand does not own, BLACK IS THE
   ACTION COLOUR and is reserved for it. On light ground a CTA is black with a
   white label (21:1). On dark ground it inverts to white with a black label
   (21:1). Either way the CTA is the highest-contrast element on the page, and
   no other element is allowed pure black as a fill.

   Every pair below is computed against WCAG 2.1 AA. The ratios are real, not
   aspirational. Two rules follow and must not be broken:
     1. --grey-500 (#726F78) is 4.93:1 on white. That clears AA for normal
        text but only just, so it carries rules, icons and eyebrows. Body-size
        muted text uses --grey-700 (6.63:1).
     2. --grey-500 is only 4.26:1 on black and MUST NOT carry text on a dark
        ground. Use --grey-300 (5.00:1 on --slate-800) there.
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  /* --- THE BRAND, exactly as supplied. These three are the logo. --- */
  --black:     #000000;   /* the tape measure and every outline in the mark */
  --slate-800: #4B4851;   /* the excavator bucket */
  --grey-500:  #726F78;   /* the K and the C */

  /* --- Derived, and only where the three above cannot meet AA ---
     Each is a tint or shade on the same desaturated violet axis as
     --grey-500, so nothing here introduces a new hue. */
  --ink-950:   #000000;
  --ink-900:   #17161A;   /* footer and mobile bar ground, a hair off pure
                             black so pure black CTAs still separate from it */
  --slate-700: #2A282F;
  --slate-600: #3B3843;
  --grey-700:  #5E5B66;   /* 6.63:1 on white. Body-size muted text. */
  --grey-600:  #6E6B76;
  --grey-400:  #A3A0A9;   /* 5.66:1 on --slate-700 */
  --grey-300:  #C4C0C9;   /* 5.00:1 on --slate-800. Muted text on dark. */
  --grey-200:  #DDDBE1;   /* borders */
  --grey-100:  #EBEAEE;
  --grey-050:  #F4F3F5;   /* tinted panels, quick-answer blocks */

  --surface-alt: #F4F3F5; /* alternating section background */
  --white: #FFFFFF;
  --ink: #17161A;         /* body copy. Softened from pure black to stop
                             halation on long-form text; headings and CTAs
                             still take the pure brand black. */

  /* --- ACTION. Black, and nothing else on the page gets a black fill. ---
     white on --action        = 21.0:1
     black on --action-invert = 21.0:1
     Both are the maximum contrast available, which is the point: the CTA
     wins on a palette that has no accent hue to give it. */
  --action: #000000;
  --action-hover: #2A282F;
  --action-invert: #FFFFFF;        /* the CTA fill on dark grounds */
  --action-invert-hover: #DDDBE1;
  --action-deep: #000000;

  /* Google review star gold. Deliberately outside the brand palette:
     gold stars are a universal rating convention, and this is the one
     place where borrowing another brand mark increases trust rather
     than diluting ours. */
  --star: #FBBC04;

  /* --- Semantic --- */
  --bg: var(--white);
  --bg-alt: var(--surface-alt);
  --bg-dark: var(--slate-800);
  --text: var(--ink);
  --text-muted: var(--grey-700);       /* 6.63:1 on white */
  --text-on-dark: #F2F1F4;             /* 14.6:1 on --slate-800 */
  --text-muted-on-dark: var(--grey-300);
  --border: var(--grey-200);
  --border-strong: #C7C4CC;
  --border-on-dark: rgba(255, 255, 255, .18);

  /* --- Type ---
     Display: Bricolage Grotesque. A grotesk with deliberately irregular
     joints and a variable width axis, so headings read cut rather than set.
     Body: Nunito Sans. Round, humanist, plain. Two genuinely different
     skeletons, which is what makes the pairing hold up at every size. */
  --font-display: 'Bricolage Grotesque', 'Helvetica Neue', Helvetica, sans-serif;
  --font-body: 'Nunito Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* --- Scale, fluid between 380px and 1280px --- */
  --fs-eyebrow: .875rem;
  --fs-sm: .9375rem;
  --fs-body: clamp(1rem, .97rem + .14vw, 1.0625rem);
  --fs-lead: clamp(1.0625rem, 1rem + .3vw, 1.1875rem);
  --fs-h4: clamp(1.0625rem, 1rem + .3vw, 1.1875rem);
  --fs-h3: clamp(1.25rem, 1.15rem + .45vw, 1.5rem);
  --fs-h2: clamp(1.75rem, 1.45rem + 1.4vw, 2.625rem);
  --fs-h1: clamp(2.125rem, 1.6rem + 2.35vw, 3.75rem);
  --fs-display: clamp(2.5rem, 1.7rem + 3.4vw, 4.5rem);

  /* --- Space --- */
  --container: 1220px;
  --container-narrow: 820px;
  --gutter: clamp(1.15rem, 4vw, 2.5rem);
  --sp-1: .25rem;  --sp-2: .5rem;   --sp-3: .75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;  --sp-6: 2rem;    --sp-7: 3rem;    --sp-8: 4rem;
  --sp-9: 5.5rem;
  --section-y: clamp(3.5rem, 2rem + 6vw, 6.5rem);

  /* --- Edges. Near-square on purpose. --- */
  --radius: 2px;
  --radius-lg: 4px;

  /* --- Depth. Rules first, shadow only where an element genuinely floats. --- */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .07);
  --shadow-md: 0 6px 18px -6px rgba(0, 0, 0, .16);
  --shadow-lg: 0 24px 60px -20px rgba(0, 0, 0, .34);

  /* --- Motion --- */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --dur: .22s;

  /* --- Layered UI --- */
  --z-header: 900;
  --z-rail: 940;
  --z-bar: 950;
  --z-drawer: 980;
  --z-popup: 1000;

  --header-h: 74px;
}

@media (max-width: 1023px) { :root { --header-h: 64px; } }

/* The standing seam motif. A repeating hairline used as a section cap and on
   the hero edge. Vertical rules at a 22px rhythm, the way panels run. */
.seam-cap {
  height: 5px;
  background:
    repeating-linear-gradient(90deg,
      var(--grey-500) 0 1px,
      transparent 1px 22px);
  opacity: .5;
}

/* ==========================================================================
   2. RESET
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video, iframe { display: block; max-width: 100%; }
img { height: auto; }

h1, h2, h3, h4, h5 {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.021em;
  text-wrap: balance;
}

h1 { font-size: var(--fs-h1); font-weight: 800; }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); line-height: 1.2; }
h4 { font-size: var(--fs-h4); line-height: 1.3; letter-spacing: -.012em; }

p { margin: 0 0 var(--sp-4); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: var(--grey-700); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--grey-500); }

ul, ol { margin: 0 0 var(--sp-4); padding-left: 1.15rem; }
li { margin-bottom: var(--sp-2); }
li:last-child { margin-bottom: 0; }

button { font: inherit; color: inherit; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--action);
  outline-offset: 2px;
  border-radius: var(--radius);
}
.bg-dark :focus-visible, .header :focus-visible { outline-color: var(--action-hover); }

::selection { background: var(--grey-500); color: var(--white); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ==========================================================================
   3. LAYOUT
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container-narrow { max-width: var(--container-narrow); }

.section { padding-block: var(--section-y); }
.section-alt { background: var(--bg-alt); }
.section-dark { background: var(--ink-900); color: var(--text-on-dark); }
.section-dark h1, .section-dark h2, .section-dark h3, .section-dark h4 { color: var(--white); }
.section-dark p { color: var(--text-on-dark); }
.section-tight { padding-block: clamp(2.5rem, 1.5rem + 4vw, 4rem); }

.section-head { max-width: 46rem; margin-bottom: var(--sp-7); }
.section-head.center { margin-inline: auto; text-align: center; }
.section-head p { font-size: var(--fs-lead); color: var(--text-muted); margin-bottom: 0; }
.section-dark .section-head p { color: var(--text-muted-on-dark); }

/* Eyebrow. Small, uppercase, tracked, copper. Labels every section. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--grey-700);
}
.eyebrow::before {
  content: '';
  width: 26px;
  height: 2px;
  background: var(--grey-500);
  flex: none;
}
.center .eyebrow { justify-content: center; }
.section-dark .eyebrow { color: var(--grey-300); }

.lead { font-size: var(--fs-lead); color: var(--text-muted); }
.section-dark .lead { color: var(--text-on-dark); }

.grid { display: grid; gap: var(--sp-5); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(275px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

.split {
  display: grid;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) { .split { grid-template-columns: 1fr 1fr; } }
.split-media img { width: 100%; border-radius: var(--radius-lg); }

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

.skip-link {
  position: absolute; top: -100px; left: var(--sp-4); z-index: 1100;
  padding: var(--sp-3) var(--sp-4);
  background: var(--action); color: var(--ink);
  font-weight: 800; text-decoration: none; border-radius: var(--radius);
}
.skip-link:focus { top: var(--sp-3); }

/* ==========================================================================
   4. BUTTONS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: .95rem 1.6rem;
  min-height: 50px;
  border: 2px solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: .015em;
  line-height: 1.15;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn svg { flex: none; }

/* The primary action. Black field, white label, 21:1.
   Nothing else on a light surface is allowed a pure black fill, so the CTA is
   unambiguously the loudest element even without an accent hue. */
.btn-primary { background: var(--action); border-color: var(--action); color: var(--white); }
.btn-primary:hover { background: var(--action-hover); border-color: var(--action-hover); color: var(--white); }

/* Inverted on every dark ground, because a black button on a near-black
   surface is invisible. White field, black label, also 21:1. */
.hero .btn-primary,
.page-hero .btn-primary,
.cta-band .btn-primary,
.section-dark .btn-primary,
.mobile-drawer .btn-primary {
  background: var(--action-invert); border-color: var(--action-invert); color: var(--black);
}
.hero .btn-primary:hover,
.page-hero .btn-primary:hover,
.cta-band .btn-primary:hover,
.section-dark .btn-primary:hover,
.mobile-drawer .btn-primary:hover {
  background: var(--action-invert-hover); border-color: var(--action-invert-hover); color: var(--black);
}

/* Secondary on light grounds. */
.btn-outline { background: transparent; border-color: var(--ink-900); color: var(--ink-900); }
.btn-outline:hover { background: var(--ink-900); color: var(--white); }

/* Secondary on dark grounds, e.g. the hero. */
.btn-ghost { background: transparent; border-color: rgba(255,255,255,.42); color: var(--white); }
.btn-ghost:hover { background: rgba(255,255,255,.1); border-color: var(--white); color: var(--white); }

.btn-solid { background: var(--ink-900); border-color: var(--ink-900); color: var(--white); }
.btn-solid:hover { background: var(--slate-800); border-color: var(--slate-800); color: var(--white); }

.btn-sm { padding: .6rem 1.05rem; min-height: 42px; font-size: .9375rem; }
.btn-lg { padding: 1.1rem 2rem; min-height: 58px; font-size: 1.0625rem; }
.btn-block { width: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.center .btn-row, .btn-row.center { justify-content: center; }

/* Text link with a moving arrow. Used on every card. */
.link-arrow {
  display: inline-flex; align-items: center; gap: .45rem;
  font-weight: 800; font-size: var(--fs-sm);
  letter-spacing: .02em; text-transform: uppercase;
  color: var(--grey-700); text-decoration: none;
}
.link-arrow svg { transition: transform var(--dur) var(--ease); }
.link-arrow:hover svg { transform: translateX(4px); }
.section-dark .link-arrow { color: var(--grey-300); }

/* ==========================================================================
   5. TOP TRUST BAR
   ========================================================================== */

.top-bar {
  background: var(--ink-950);
  color: var(--text-muted-on-dark);
  font-size: .8125rem;
  border-bottom: 1px solid rgba(255,255,255,.06);
}
.top-bar-inner {
  display: flex; align-items: center; gap: var(--sp-5);
  min-height: 40px; flex-wrap: wrap;
}
.top-bar-item {
  display: inline-flex; align-items: center; gap: .4rem;
  color: inherit; text-decoration: none;
}
a.top-bar-item:hover { color: var(--grey-300); }
.top-bar-item svg { color: var(--grey-500); flex: none; }
.top-bar-rating { display: inline-flex; align-items: center; gap: .4rem; }
.top-bar-rating .tb-stars { display: inline-flex; gap: 1px; color: var(--star); }
/* The colour has to be set on the svg itself, not just on .tb-stars.
   `.top-bar-item svg` above targets the element directly at (0,1,1), which
   beats colour inherited from the parent span however specific that parent
   rule is. This selector is (0,2,1) and wins. That specificity trap is why
   these stars rendered grey. */
.top-bar-rating .tb-stars svg { width: 12px; height: 12px; color: var(--star); }
.top-bar-rating strong { color: var(--white); }
.top-bar-spacer { margin-left: auto; }
.top-bar-cta { color: var(--white); font-weight: 800; text-decoration: none; }
.top-bar-cta:hover { color: var(--grey-300); }
@media (max-width: 900px) { .top-bar { display: none; } }

/* ==========================================================================
   6. HEADER
   ========================================================================== */

.header {
  position: sticky; top: 0; z-index: var(--z-header);
  background: var(--white);
  border-bottom: 1px solid var(--border);
  transition: box-shadow var(--dur) var(--ease);
}
.header-scrolled { box-shadow: var(--shadow-md); }
.header > .container {
  display: flex; align-items: center; gap: var(--sp-5);
  min-height: var(--header-h);
}

/* The mark is a near-square monogram (1.15:1) with no lettering in it, so the
   header pairs it with a typeset wordmark. A square emblem alone at header
   height reads as an orphaned icon and never tells a first-time visitor the
   company name. */
.header-logo {
  flex: none;
  display: inline-flex; align-items: center; gap: .6rem;
  text-decoration: none; line-height: 1;
}
.header-logo img { width: auto; height: clamp(36px, 3vw, 46px); }

.header-wordmark {
  display: flex; flex-direction: column; gap: .1rem;
  font-family: var(--font-display); line-height: 1;
}
.header-wordmark strong {
  font-size: clamp(.95rem, .82rem + .4vw, 1.18rem);
  font-weight: 800; letter-spacing: -.022em; color: var(--black);
}
.header-wordmark > span {
  font-family: var(--font-body);
  font-size: clamp(.62rem, .56rem + .18vw, .72rem);
  font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--grey-700);
}
@media (max-width: 400px) { .header-wordmark { display: none; } }

.header-nav { display: flex; align-items: center; gap: var(--sp-5); margin-left: auto; }

.nav-links { display: flex; align-items: center; gap: clamp(.4rem, 1vw, 1.05rem); }
.nav-links > a, .nav-dropdown > a {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .5rem .25rem;
  font-size: .9375rem; font-weight: 700; letter-spacing: .005em;
  color: var(--ink-900); text-decoration: none;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.nav-links > a:hover, .nav-dropdown > a:hover { color: var(--grey-700); }
.nav-links > a.active, .nav-dropdown > a.active {
  color: var(--grey-700); border-bottom-color: var(--grey-500);
}
.nav-dropdown { position: relative; }
.nav-dropdown .chevron { transition: transform var(--dur) var(--ease); }
.nav-dropdown:hover .chevron, .nav-dropdown:focus-within .chevron { transform: rotate(180deg); }

/* VISIBILITY TIMING, applies to this menu, the drawer, the drawer overlay
   and the popup overlay.

   `transition: visibility var(--dur)` looks harmless and is a real bug: the
   computed value stays `hidden` for the whole duration, so at the instant the
   class flips the element is not yet focusable. Scripted focus lands on
   <body> and keyboard users tab straight past the panel.

   The fix is to transition visibility with a zero duration and move the
   DELAY instead: 0s when showing, so it flips immediately, and the full
   duration when hiding, so the element stays visible until the fade finishes.
   Everything below uses this pattern. */
.dropdown-menu {
  position: absolute; top: 100%; left: -.75rem;
  min-width: 250px; padding: var(--sp-2);
  background: var(--white);
  border: 1px solid var(--border);
  border-top: 3px solid var(--grey-500);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  box-shadow: var(--shadow-lg);
  opacity: 0; visibility: hidden; transform: translateY(6px);
  transition: opacity var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              visibility 0s linear var(--dur);
}
.nav-dropdown:hover .dropdown-menu,
.nav-dropdown:focus-within .dropdown-menu {
  opacity: 1; visibility: visible; transform: translateY(0);
  transition: opacity var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              visibility 0s linear 0s;
}
.dropdown-menu a {
  display: block; padding: .55rem .75rem;
  font-size: .9375rem; font-weight: 600;
  color: var(--slate-800); text-decoration: none;
  border-radius: var(--radius);
  border-left: 2px solid transparent;
}
.dropdown-menu a:hover { background: var(--surface-alt); color: var(--grey-700); border-left-color: var(--grey-500); }
.dropdown-menu a.active { background: var(--surface-alt); color: var(--grey-700); border-left-color: var(--grey-500); }
.dropdown-wide { min-width: 430px; columns: 2; column-gap: var(--sp-2); }
.dropdown-wide a { break-inside: avoid; }

.header-cta { display: flex; align-items: center; gap: var(--sp-3); }
.header-phone {
  display: inline-flex; align-items: center; gap: .4rem;
  font-family: var(--font-display); font-size: 1.0625rem; font-weight: 700;
  color: var(--ink-900); text-decoration: none; white-space: nowrap;
}
.header-phone:hover { color: var(--grey-700); }
.header-phone svg { color: var(--grey-500); }

.header-mobile-trust { display: none; }

.hamburger {
  display: none; flex: none;
  width: 46px; height: 46px; padding: 11px;
  background: var(--ink-900); border: 0; border-radius: var(--radius);
  margin-left: auto;
}
.hamburger span {
  display: block; height: 2px; width: 100%; background: var(--white);
  border-radius: 2px; transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.hamburger span + span { margin-top: 5px; }
.hamburger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hamburger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.hamburger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 1150px) { .header-phone span { display: none; } }
@media (max-width: 1023px) {
  .header-nav { display: none; }
  .hamburger { display: block; }
  /* The gap between the logo and the hamburger was dead space on every
     phone, because this block used to be hidden below 420px. It now carries
     the Google rating, which is the single most persuasive thing we can put
     in front of someone before they scroll. Tappable, straight to /reviews/. */
  .header-mobile-trust {
    display: flex; flex-direction: column; align-items: flex-end; gap: 3px;
    margin-left: auto; margin-right: var(--sp-3);
    max-width: 48vw;
    line-height: 1.15; text-decoration: none;
  }
  .hmt-stars { display: flex; gap: 1px; color: var(--star); }
  .hmt-stars svg { width: 13px; height: 13px; }
  .hmt-count {
    font-size: .625rem; font-weight: 800; letter-spacing: .02em;
    text-transform: uppercase; color: var(--text-muted); text-align: right;
  }
  .header-mobile-trust:hover .hmt-count { color: var(--text); }
}

/* Very narrow phones. Shrink rather than hide, so the rating always shows. */
@media (max-width: 359px) {
  .hmt-stars svg { width: 11px; height: 11px; }
  .hmt-count { font-size: .5625rem; }
}

/* ==========================================================================
   7. MOBILE DRAWER
   ========================================================================== */

.drawer-overlay {
  position: fixed; inset: 0; z-index: calc(var(--z-drawer) - 1);
  background: rgba(0, 0, 0, .62);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
}
.drawer-overlay.active {
  opacity: 1; visibility: visible;
  transition: opacity var(--dur) var(--ease), visibility 0s linear 0s;
}

/* visibility:hidden here is doing accessibility work, not decoration. Without
   it the drawer is merely translated off-screen, which leaves all 25 of its
   links in the tab order on every page at every viewport width. */
.mobile-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: var(--z-drawer);
  width: min(400px, 90vw);
  display: flex; flex-direction: column;
  background: var(--ink-900); color: var(--text-on-dark);
  visibility: hidden;
  transform: translateX(100%);
  transition: transform .28s var(--ease), visibility 0s linear .28s;
  overflow-y: auto; overscroll-behavior: contain;
}
.mobile-drawer.active {
  visibility: visible;
  transform: translateX(0);
  transition: transform .28s var(--ease), visibility 0s linear 0s;
}

.drawer-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border-on-dark);
}
.drawer-header img { height: 40px; width: auto; }
.drawer-close {
  flex: none; width: 44px; height: 44px;
  display: grid; place-items: center;
  background: transparent; border: 1px solid var(--border-on-dark);
  border-radius: var(--radius); color: var(--white);
}
.drawer-close:hover { background: rgba(255,255,255,.08); }

.drawer-nav { padding: var(--sp-4) var(--sp-5); flex: 1; }
.drawer-nav > a, .drawer-services-toggle {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; padding: .85rem 0;
  background: transparent; border: 0; border-bottom: 1px solid var(--border-on-dark);
  font-family: var(--font-display); font-size: 1.0625rem; font-weight: 700;
  color: var(--white); text-align: left; text-decoration: none;
}
.drawer-nav > a.active, .drawer-services-toggle.active { color: var(--grey-300); }
.drawer-services-toggle .chevron { transition: transform var(--dur) var(--ease); color: var(--grey-300); }
.drawer-services-toggle[aria-expanded="true"] .chevron { transform: rotate(180deg); }

.drawer-services-list {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .26s var(--ease);
}
.drawer-services-list.open { grid-template-rows: 1fr; }
.drawer-services-list > div { overflow: hidden; }
.drawer-services-list a {
  display: block; padding: .6rem 0 .6rem var(--sp-4);
  font-size: .9375rem; font-weight: 600;
  color: var(--text-muted-on-dark); text-decoration: none;
  border-left: 2px solid var(--border-on-dark);
}
.drawer-services-list a:hover, .drawer-services-list a.active {
  color: var(--grey-300); border-left-color: var(--grey-500);
}

.drawer-cta { display: grid; gap: var(--sp-3); padding: var(--sp-5); border-top: 1px solid var(--border-on-dark); }
.drawer-info {
  padding: 0 var(--sp-5) var(--sp-6);
  font-size: .875rem; color: var(--text-muted-on-dark);
}
.drawer-info p { margin-bottom: var(--sp-1); }

/* ==========================================================================
   8. HERO
   ========================================================================== */

.hero {
  position: relative;
  display: grid; align-items: center;
  min-height: clamp(520px, 74vh, 720px);
  padding-block: var(--sp-9) var(--sp-8);
  background: var(--ink-900);
  color: var(--white);
  overflow: hidden;
}
.hero-media { position: absolute; inset: 0; z-index: 0; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; }
/* Scrim. Heavier at the left where the copy sits, so the photo still reads. */
.hero-media::after {
  content: '';
  position: absolute; inset: 0;
  background:
    linear-gradient(100deg, rgba(0,0,0,.90) 0%, rgba(0,0,0,.76) 42%, rgba(0,0,0,.40) 78%, rgba(0,0,0,.30) 100%);
}
.hero > .container { position: relative; z-index: 1; }
.hero-inner { max-width: 46rem; }
.hero .eyebrow { color: var(--grey-300); }
.hero .eyebrow::before { background: var(--grey-300); }
.hero h1 { color: var(--white); margin-bottom: var(--sp-5); }
.hero-sub {
  font-size: clamp(1.0625rem, 1rem + .4vw, 1.25rem);
  color: var(--text-on-dark);
  max-width: 40rem;
  margin-bottom: var(--sp-6);
}
.hero .btn-row { margin-bottom: var(--sp-7); }

.hero-trust {
  display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-5);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border-on-dark);
}
.hero-trust li {
  display: flex; align-items: center; gap: .5rem;
  margin: 0; font-size: var(--fs-sm); font-weight: 700; color: var(--text-on-dark);
}
.hero-trust svg { color: var(--grey-300); flex: none; }
.hero-trust { list-style: none; padding-left: 0; margin: 0; }

/* Standing seam rule along the bottom edge of the hero */
.hero::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: 6px; z-index: 2;
  background: repeating-linear-gradient(90deg, var(--grey-500) 0 1px, transparent 1px 22px);
  opacity: .55;
}

/* Compact hero for inner pages */
.page-hero {
  position: relative;
  padding-block: clamp(3rem, 2rem + 5vw, 5.5rem);
  background: var(--ink-900); color: var(--white);
  overflow: hidden;
}
.page-hero .hero-media::after {
  background: linear-gradient(100deg, rgba(0,0,0,.90) 0%, rgba(0,0,0,.78) 50%, rgba(0,0,0,.50) 100%);
}
.page-hero > .container { position: relative; z-index: 1; }
.page-hero h1 { color: var(--white); max-width: 22ch; }
.page-hero .hero-sub { margin-bottom: var(--sp-5); }
.page-hero::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: 5px;
  background: repeating-linear-gradient(90deg, var(--grey-500) 0 1px, transparent 1px 22px);
  opacity: .5;
}

/* ==========================================================================
   9. BREADCRUMBS
   ========================================================================== */

.breadcrumbs {
  padding-block: var(--sp-3);
  font-size: .8125rem;
  background: var(--surface-alt);
  border-bottom: 1px solid var(--border);
}
.breadcrumbs ol {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
  list-style: none; margin: 0; padding: 0;
}
.breadcrumbs li { display: flex; align-items: center; gap: .4rem; margin: 0; }
.breadcrumbs li + li::before { content: '›'; color: var(--grey-300); }
.breadcrumbs a { color: var(--text-muted); text-decoration: none; font-weight: 600; }
.breadcrumbs a:hover { color: var(--grey-700); text-decoration: underline; }
.breadcrumbs [aria-current] { color: var(--ink-900); font-weight: 700; }

/* ==========================================================================
   10. CARDS
   ========================================================================== */

/* Service card. Image, then a ruled body. The top copper rule appears on
   hover, which is the only motion on the card. */
.card {
  display: flex; flex-direction: column;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.card:hover { border-color: var(--grey-500); box-shadow: var(--shadow-md); transform: translateY(-3px); }
.card-media { position: relative; aspect-ratio: 16 / 10; background: var(--grey-100); overflow: hidden; }
.card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s var(--ease); }
.card:hover .card-media img { transform: scale(1.04); }
.card-body { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-5); flex: 1; }
.card-body h3 { margin: 0; }
.card-body p { color: var(--text-muted); font-size: var(--fs-sm); margin: 0; flex: 1; }
.card-body .link-arrow { margin-top: var(--sp-1); }
.card a.card-link::after { content: ''; position: absolute; inset: 0; }
.card { position: relative; }

/* Feature card. Icon, no image. Used for "why choose us". */
.feature {
  padding: var(--sp-5);
  background: var(--white);
  border: 1px solid var(--border);
  border-top: 3px solid var(--grey-500);
  border-radius: var(--radius-lg);
}
.feature-icon {
  display: grid; place-items: center;
  width: 46px; height: 46px; margin-bottom: var(--sp-4);
  background: var(--grey-050); color: var(--grey-700);
  border-radius: var(--radius);
}
.feature h3 { font-size: var(--fs-h4); margin-bottom: var(--sp-2); }
.feature p { color: var(--text-muted); font-size: var(--fs-sm); margin: 0; }
.section-dark .feature {
  background: var(--slate-800); border-color: rgba(255,255,255,.08); border-top-color: var(--grey-500);
}
.section-dark .feature-icon { background: rgba(114,111,120,.28); color: var(--grey-300); }
.section-dark .feature p { color: var(--text-muted-on-dark); }

/* County card. Photograph led. These previously rendered as text on a grey
   ground and read as a directory listing rather than as places. */
.area-card {
  position: relative;
  display: flex; flex-direction: column;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.area-card:hover { border-color: var(--grey-500); box-shadow: var(--shadow-md); transform: translateY(-3px); }

.area-card-media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; background: var(--grey-100); }
.area-card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .45s var(--ease); }
.area-card:hover .area-card-media img { transform: scale(1.05); }
/* Scrim so the state badge stays legible over any photograph */
.area-card-media::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.55) 0%, rgba(0,0,0,0) 45%);
}

.area-card .area-state {
  position: absolute; left: var(--sp-4); bottom: var(--sp-3); z-index: 1;
  display: inline-block; padding: .2rem .55rem;
  background: var(--white); color: var(--black);
  font-size: .6875rem; font-weight: 800; letter-spacing: .1em;
  border-radius: var(--radius);
}

.area-card-body { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-5); flex: 1; }
.area-card-body h3 { margin: 0; font-size: var(--fs-h4); }
.area-card-body p { font-size: var(--fs-sm); color: var(--text-muted); margin: 0; }
.area-card-body .area-towns { font-size: .8125rem; color: var(--grey-600); flex: 1; }
.area-card-body .link-arrow { margin-top: var(--sp-1); }

/* Plain text link card, used for the service grid on the areas hub. */
.link-card {
  position: relative;
  display: flex; flex-direction: column; gap: var(--sp-2);
  padding: var(--sp-5);
  background: var(--white);
  border: 1px solid var(--border);
  border-left: 3px solid var(--grey-500);
  border-radius: var(--radius-lg);
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.link-card:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); border-left-color: var(--black); }
.link-card h3 { margin: 0; font-size: var(--fs-h4); color: var(--text); }
.link-card p { margin: 0; font-size: var(--fs-sm); color: var(--text-muted); }

/* Numbered step. Used for every process section. */
.steps { counter-reset: step; display: grid; gap: var(--sp-5); }
.step { position: relative; padding-left: 4.25rem; }
.step::before {
  counter-increment: step;
  content: counter(step, decimal-leading-zero);
  position: absolute; left: 0; top: -.1em;
  font-family: var(--font-display); font-size: 2rem; font-weight: 800;
  color: var(--grey-500); line-height: 1;
}
.step h3 { font-size: var(--fs-h4); margin-bottom: var(--sp-2); }
.step p { color: var(--text-muted); font-size: var(--fs-sm); margin: 0; }
.section-dark .step p { color: var(--text-muted-on-dark); }

/* Checklist */
.checklist { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-3); }
.checklist li { display: flex; gap: var(--sp-3); margin: 0; font-size: var(--fs-sm); }
.checklist svg { flex: none; color: var(--grey-500); margin-top: .2rem; }

/* Stat band */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--sp-5); }
.stat { text-align: center; }
.stat-num {
  display: block;
  font-family: var(--font-display); font-size: clamp(2.25rem, 1.6rem + 2.4vw, 3.25rem);
  font-weight: 800; line-height: 1; color: var(--grey-300);
}
.stat-label { font-size: var(--fs-sm); font-weight: 700; color: var(--text-on-dark); letter-spacing: .02em; }

/* Gallery */
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--sp-3); }
.gallery figure { margin: 0; position: relative; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius-lg); background: var(--grey-100); }
.gallery img { width: 100%; height: 100%; object-fit: cover; transition: transform .45s var(--ease); }
.gallery figure:hover img { transform: scale(1.05); }

/* Answer-first block for AEO. One short paragraph that directly answers the
   page's primary question, placed above the long-form body copy. */
.quick-answer {
  padding: var(--sp-5);
  background: var(--grey-050);
  border-left: 3px solid var(--grey-500);
  border-radius: var(--radius-lg);
}
.quick-answer h2, .quick-answer h3 {
  font-family: var(--font-body); font-size: var(--fs-eyebrow); font-weight: 800;
  letter-spacing: .13em; text-transform: uppercase; color: var(--grey-700);
  margin-bottom: var(--sp-2);
}
.quick-answer p { margin: 0; font-size: var(--fs-lead); }

/* Callout for pending client assets, dev only, stripped at launch by qc.js.
   Inside a container that already fixes its own aspect ratio, the placeholder
   fills instead of imposing a second ratio, which otherwise pushes the hero
   and the cards taller than the real photograph will. */
.hero-media .asset-pending,
.card-media .asset-pending,
.gallery figure .asset-pending {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  min-height: 0; border-radius: 0;
  aspect-ratio: auto !important;
}
.asset-pending {
  display: grid; place-items: center; gap: var(--sp-2);
  min-height: 180px; padding: var(--sp-5);
  background: repeating-linear-gradient(45deg, var(--grey-100) 0 10px, var(--surface-alt) 10px 20px);
  border: 1px dashed var(--border-strong); border-radius: var(--radius-lg);
  color: var(--grey-600); font-size: .8125rem; font-weight: 700;
  text-align: center; letter-spacing: .04em; text-transform: uppercase;
}

/* ==========================================================================
   11. REVIEWS

   These are real Google reviews and the design says so. The star colour is
   Google's own #FBBC04 rather than a brand value: gold stars are a universal
   rating convention, and this is the one place where borrowing another brand
   mark increases trust instead of diluting ours. Black stars, which is what
   the palette change briefly produced, read as a decorative glyph rather than
   as a rating.
   ========================================================================== */

.review {
  display: flex; flex-direction: column; gap: var(--sp-4);
  padding: var(--sp-5);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.review:hover { border-color: var(--grey-500); box-shadow: var(--shadow-md); transform: translateY(-2px); }

.review-top { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.review-stars { display: flex; gap: 2px; color: var(--star); }

.review-source {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .75rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted);
}

.review-body { font-size: var(--fs-sm); line-height: 1.7; color: var(--text); flex: 1; margin: 0; }

.review-foot {
  display: flex; align-items: center; gap: var(--sp-3);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
}
.review-avatar {
  flex: none; width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--slate-800); color: var(--white);
  font-family: var(--font-display); font-size: 1.0625rem; font-weight: 800;
}
.review-author { font-weight: 800; font-size: var(--fs-sm); color: var(--text); margin: 0; }
.review-meta { font-size: .75rem; color: var(--text-muted); margin: 0; }

/* Names inside review bodies. The palette has no accent hue, so emphasis is
   made with weight and a ruled underline rather than with colour. */
.hl-owner { font-weight: 800; color: var(--text); box-shadow: inset 0 -2px 0 var(--grey-500); }
.hl-crew  { font-weight: 800; color: var(--grey-700); }
.hl-brand { font-weight: 800; color: var(--text); }

/* On dark grounds */
.section-dark .review { background: var(--slate-700); border-color: rgba(255,255,255,.10); }
.section-dark .review:hover { border-color: var(--grey-400); }
.section-dark .review-body { color: var(--text-on-dark); }
.section-dark .review-author { color: var(--white); }
.section-dark .review-meta,
.section-dark .review-source { color: var(--grey-300); }
.section-dark .review-foot { border-top-color: rgba(255,255,255,.12); }
.section-dark .review-avatar { background: var(--white); color: var(--slate-800); }
.section-dark .hl-owner { color: var(--white); box-shadow: inset 0 -2px 0 var(--grey-300); }
.section-dark .hl-crew,
.section-dark .hl-brand { color: var(--white); }

/* Rating summary, the block that leads the reviews section */
.rating-summary {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4) var(--sp-6);
  padding: var(--sp-5) var(--sp-6);
  margin-bottom: var(--sp-7);
  background: var(--white);
  border: 1px solid var(--border);
  border-left: 4px solid var(--star);
  border-radius: var(--radius-lg);
}
.section-dark .rating-summary { background: var(--slate-700); border-color: rgba(255,255,255,.12); }
.rating-score { display: flex; flex-direction: column; gap: .35rem; }
.rating-number { font-family: var(--font-display); font-size: 3rem; font-weight: 800; line-height: 1; color: var(--text); }
.section-dark .rating-number { color: var(--white); }
.rating-score .review-stars svg { width: 18px; height: 18px; }
.rating-meta { display: flex; flex-direction: column; gap: .25rem; }
.rating-count { display: inline-flex; align-items: center; gap: .45rem; font-size: var(--fs-lead); color: var(--text-muted); }
.rating-count strong { color: var(--text); }
.section-dark .rating-count { color: var(--text-on-dark); }
.section-dark .rating-count strong { color: var(--white); }
.rating-note { font-size: .8125rem; color: var(--text-muted); }
.section-dark .rating-note { color: var(--grey-300); }

/* Shown when the client has not supplied reviews yet. Never fake cards. */
.reviews-empty {
  padding: var(--sp-7) var(--sp-5);
  text-align: center;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

/* ==========================================================================
   12. FAQ ACCORDION
   ========================================================================== */

.faq { display: grid; gap: var(--sp-3); max-width: 52rem; }
.faq-item { border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--white); overflow: hidden; }
.faq-item.open { border-color: var(--grey-500); }
.faq-q {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4);
  width: 100%; padding: var(--sp-4) var(--sp-5);
  background: transparent; border: 0; text-align: left;
  font-family: var(--font-display); font-size: var(--fs-h4); font-weight: 700;
  color: var(--ink-900); line-height: 1.3;
}
.faq-q:hover { color: var(--grey-700); }
.faq-q .chevron { flex: none; margin-top: .2rem; color: var(--grey-500); transition: transform var(--dur) var(--ease); }
.faq-item.open .faq-q .chevron { transform: rotate(180deg); }
.faq-a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .26s var(--ease); }
.faq-item.open .faq-a { grid-template-rows: 1fr; }
.faq-a > div { overflow: hidden; }
.faq-a p { padding: 0 var(--sp-5) var(--sp-5); color: var(--text-muted); margin: 0; }
.faq-a p + p { padding-top: var(--sp-3); }

/* ==========================================================================
   13. CTA BAND
   ========================================================================== */

.cta-band { position: relative; background: var(--ink-900); color: var(--white); overflow: hidden; }
.cta-band::before {
  content: '';
  position: absolute; inset: 0;
  background: repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 1px, transparent 1px 22px);
}
.cta-band > .container { position: relative; }
.cta-band-inner {
  display: grid; gap: var(--sp-5); align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) { .cta-band-inner { grid-template-columns: 1.4fr auto; gap: var(--sp-7); } }
.cta-band h2 { color: var(--white); margin-bottom: var(--sp-3); }
.cta-band p { color: var(--text-on-dark); margin: 0; font-size: var(--fs-lead); }

/* ==========================================================================
   14. FOOTER
   ========================================================================== */

.footer { background: var(--ink-950); color: var(--text-muted-on-dark); font-size: var(--fs-sm); }
.footer-grid {
  display: grid; gap: var(--sp-6) var(--sp-5);
  padding-block: var(--sp-8) var(--sp-7);
  grid-template-columns: 1fr;
}
@media (min-width: 620px) { .footer-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .footer-grid { grid-template-columns: 1.5fr 1fr 1.2fr 1.4fr; } }

.footer h4 {
  font-family: var(--font-body); font-size: var(--fs-eyebrow); font-weight: 800;
  letter-spacing: .13em; text-transform: uppercase; color: var(--white);
  margin-bottom: var(--sp-4); padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border-on-dark);
}
.footer-brand img { height: 46px; width: auto; margin-bottom: var(--sp-4); }
.footer-brand p { margin-bottom: var(--sp-4); }
.footer-social { display: flex; gap: var(--sp-2); }
.footer-social a {
  display: grid; place-items: center; width: 40px; height: 40px;
  border: 1px solid var(--border-on-dark); border-radius: var(--radius);
  color: var(--grey-300);
}
.footer-social a:hover { background: var(--grey-500); border-color: var(--grey-500); color: var(--ink-950); }

.footer-links { display: grid; gap: .55rem; }
.footer-links a { color: var(--text-muted-on-dark); text-decoration: none; }
.footer-links a:hover { color: var(--grey-300); }

.footer-contact-item { display: flex; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.footer-contact-item svg { flex: none; margin-top: .2rem; color: var(--grey-500); }
.footer-contact-item a { color: var(--text-on-dark); text-decoration: none; font-weight: 700; }
.footer-contact-item a:hover { color: var(--grey-300); }

.footer-map { margin-top: var(--sp-4); border: 1px solid var(--border-on-dark); border-radius: var(--radius-lg); overflow: hidden; }
.footer-map iframe { width: 100%; height: 170px; border: 0; filter: grayscale(1) contrast(.9) brightness(.85); }

.footer-bottom {
  border-top: 1px solid var(--border-on-dark);
  padding-block: var(--sp-4);
  font-size: .8125rem;
}
.footer-bottom .container { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); align-items: center; }
.footer-bottom a { color: var(--text-muted-on-dark); text-decoration: none; }
.footer-bottom a:hover { color: var(--grey-300); }
.footer-legal { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-left: auto; }

/* ==========================================================================
   15. STICKY CTAs
   ========================================================================== */

/* Desktop, right edge, vertically centred. */
.sticky-rail {
  position: fixed; right: 0; top: 50%; transform: translateY(-50%);
  z-index: var(--z-rail);
  display: none; flex-direction: column; gap: 1px;
}
.sticky-rail a {
  display: flex; align-items: center; gap: .5rem;
  padding: .85rem 1rem;
  font-size: .875rem; font-weight: 800; text-decoration: none;
  writing-mode: vertical-rl;
  border-radius: var(--radius) 0 0 var(--radius);
}
.sticky-rail a svg { transform: rotate(90deg); }
/* The rail sits over light page content, so the CTA stays black. The phone
   button uses the brand slate so the two are distinguishable from each other
   as well as from the page. */
.rail-phone { background: var(--slate-800); color: var(--white); }
.rail-phone:hover { background: var(--slate-700); color: var(--white); }
.rail-cta { background: var(--action); color: var(--white); }
.rail-cta:hover { background: var(--action-hover); color: var(--white); }
@media (min-width: 1100px) and (min-height: 620px) { .sticky-rail { display: flex; } }

/* Mobile, bottom bar, visible on load with no scroll trigger. */
.mobile-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-bar);
  display: none; gap: 1px;
  background: var(--ink-900);
  box-shadow: 0 -4px 18px rgba(0,0,0,.32);
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.mobile-bar a {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: .45rem;
  min-height: 56px; padding: .6rem;
  font-size: .9375rem; font-weight: 800; text-decoration: none;
}
/* The bar itself is near-black, so the CTA inverts to white here. */
.bar-phone { background: var(--ink-900); color: var(--white); }
.bar-cta { background: var(--action-invert); color: var(--black); }
@media (max-width: 767px) {
  .mobile-bar { display: flex; }
  body { padding-bottom: 56px; }
}

/* ==========================================================================
   16. POPUP FORM
   ========================================================================== */

.popup-overlay {
  position: fixed; inset: 0; z-index: var(--z-popup);
  display: grid; place-items: center;
  padding: var(--sp-4);
  background: rgba(0, 0, 0, .74);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
  overflow-y: auto;
}
.popup-overlay.active {
  opacity: 1; visibility: visible;
  transition: opacity var(--dur) var(--ease), visibility 0s linear 0s;
}

.popup-form {
  position: relative;
  width: min(520px, 100%);
  margin: auto;
  padding: var(--sp-6) clamp(1.25rem, 4vw, 2.25rem) var(--sp-6);
  background: var(--white);
  border-top: 4px solid var(--grey-500);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  transform: translateY(12px) scale(.99);
  transition: transform .26s var(--ease);
}
.popup-overlay.active .popup-form { transform: none; }

.popup-close {
  position: absolute; top: var(--sp-3); right: var(--sp-3);
  width: 44px; height: 44px; display: grid; place-items: center;
  background: transparent; border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--ink-900);
}
.popup-close:hover { background: var(--surface-alt); border-color: var(--grey-500); }

.popup-logo { height: 44px; width: auto; margin-bottom: var(--sp-4); }
.popup-form h3 { margin-bottom: var(--sp-2); font-size: var(--fs-h3); }
.popup-subtitle { font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: var(--sp-5); }

.popup-form form, .inline-form { display: grid; gap: var(--sp-3); }
.form-row { display: grid; gap: var(--sp-3); grid-template-columns: 1fr 1fr; }
@media (max-width: 440px) { .form-row { grid-template-columns: 1fr; } }

/* The contact page renders the same fields inline rather than in a dialog,
   so the two share every input style. Field names are identical in both, so
   CallRail's External Form matcher treats them as one form. */
.inline-form {
  padding: var(--sp-5);
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-left: 3px solid var(--grey-500);
  border-radius: var(--radius-lg);
}
.inline-form input, .inline-form select, .inline-form textarea,
.popup-form input, .popup-form select, .popup-form textarea {
  width: 100%; padding: .8rem .9rem;
  font-family: var(--font-body); font-size: 1rem; color: var(--text);
  background: var(--white);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.inline-form input:focus, .inline-form select:focus, .inline-form textarea:focus,
.popup-form input:focus, .popup-form select:focus, .popup-form textarea:focus {
  outline: none; border-color: var(--grey-500);
  box-shadow: 0 0 0 3px rgba(114, 111, 120, .22);
}
.inline-form textarea, .popup-form textarea { resize: vertical; min-height: 84px; }
.inline-form select, .popup-form select { appearance: none; padding-right: 2.25rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2355606C' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .9rem center; }

/* Honeypot. Off-screen, not display:none, so bots still fill it. */
.hp-field { position: absolute; left: -9999px; opacity: 0; height: 0; overflow: hidden; }

.btn-submit {
  width: 100%; min-height: 54px; margin-top: var(--sp-2);
  background: var(--action); color: var(--white);
  border: 0; border-radius: var(--radius);
  font-family: var(--font-body); font-size: 1.0625rem; font-weight: 800; letter-spacing: .015em;
  transition: background-color var(--dur) var(--ease);
}
.btn-submit:hover { background: var(--action-hover); }

.privacy-note {
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  margin: var(--sp-2) 0 0;
  font-size: .8125rem; color: var(--text-muted);
}
.privacy-note svg { flex: none; color: var(--grey-500); }

/* ==========================================================================
   17. LONG-FORM PROSE
   ========================================================================== */

.prose { max-width: 44rem; }
.prose h2 { margin-top: var(--sp-7); }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: var(--sp-6); }
.prose ul, .prose ol { margin-bottom: var(--sp-5); }
.prose li::marker { color: var(--grey-500); }

/* Town list on county pages. Reads as a set, not a directory dump. */
.town-list {
  display: flex; flex-wrap: wrap; gap: var(--sp-2);
  list-style: none; padding: 0; margin: 0;
}
.town-list li {
  margin: 0; padding: .35rem .7rem;
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: .8125rem; font-weight: 600; color: var(--text-muted);
}

/* ==========================================================================
   17a. VIDEO WALL

   Reels are 9:16, so the cards are too. Forcing vertical video into a
   landscape card either letterboxes it or crops the subject out, and on a
   roofing clip the subject is usually the top third of the frame.
   ========================================================================== */

/* Social-proof header: headline on the left, the big number on the right.
   The figure is the whole argument, so it is set at display size and pulled
   out of the running copy. Real number from the API, never rounded up. */
.social-proof-head {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: var(--sp-4) var(--sp-6);
  margin-bottom: var(--sp-6);
}
.social-proof-head > div:first-child { max-width: 44ch; }
.social-proof-head h2 { margin-bottom: var(--sp-2); }
.social-proof-head p { color: var(--text-muted-on-dark); margin: 0; }

.social-proof-stat {
  display: flex; flex-direction: column; gap: .2rem;
  padding-left: var(--sp-5);
  border-left: 4px solid var(--star);
  flex: none;
}
.social-proof-figure {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 1.8rem + 3vw, 3.75rem);
  font-weight: 800; line-height: 1; color: var(--white);
  font-variant-numeric: tabular-nums;
}
.social-proof-label { font-size: var(--fs-sm); color: var(--grey-300); }

@media (max-width: 640px) {
  .social-proof-head { align-items: flex-start; }
  .social-proof-stat { padding-left: var(--sp-4); }
  .social-proof-figure { font-size: 2.5rem; }
}

/* FEATURE VIDEO. The single most-watched clip, pulled out of the carousel and
   given a split hero: the vertical thumbnail on one side, the big number and a
   call to action on the other. This is where the standout figure earns its
   prominence, separate from the row of everything else. */
.feature-video {
  display: grid;
  grid-template-columns: clamp(220px, 26vw, 300px) 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  margin-bottom: var(--sp-7);
  padding: var(--sp-5);
  background:
    linear-gradient(120deg, rgba(114,111,120,.18), rgba(114,111,120,0) 60%),
    var(--slate-700);
  border: 1px solid rgba(255,255,255,.10);
  border-left: 4px solid var(--star);
  border-radius: var(--radius-lg);
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.feature-video:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: rgba(255,255,255,.2); }

.feature-video-media {
  position: relative; display: block;
  aspect-ratio: 9 / 16;
  background: var(--ink-900);
  border-radius: var(--radius);
  overflow: hidden;
}
.feature-video-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .45s var(--ease); }
.feature-video:hover .feature-video-media img { transform: scale(1.04); }
.feature-video-media::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.5) 0%, rgba(0,0,0,0) 45%);
}
.feature-play { width: 64px; height: 64px; }

.feature-video-body { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-3); }
.feature-label {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .3rem .7rem;
  background: var(--star); color: var(--black);
  font-size: .6875rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  border-radius: var(--radius);
}
.feature-figure {
  font-family: var(--font-display);
  font-size: clamp(3rem, 2rem + 5vw, 5rem);
  font-weight: 800; line-height: .95; color: var(--white);
  font-variant-numeric: tabular-nums;
}
.feature-figure span {
  display: block;
  font-family: var(--font-body); font-size: 1rem; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; color: var(--grey-300);
  margin-top: .35rem;
}
.feature-caption { font-size: var(--fs-lead); color: var(--text-on-dark); max-width: 42ch; }
.feature-cta { margin-top: var(--sp-2); pointer-events: none; }

@media (max-width: 640px) {
  .feature-video {
    grid-template-columns: 1fr;
    justify-items: center; text-align: center;
    padding: var(--sp-4);
  }
  .feature-video-media { width: min(260px, 68vw); }
  .feature-video-body { align-items: center; }
  .feature-caption { text-align: center; }
}

.carousel-heading {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-body); font-size: var(--fs-eyebrow); font-weight: 800;
  letter-spacing: .13em; text-transform: uppercase; color: var(--grey-300);
}

/* CAROUSEL. Native horizontal scroll with snap, so touch swipe is free and
   works without JavaScript. The arrows are a JS enhancement for pointer
   users; the track scrolls fine on its own if the script never runs. */
.carousel { position: relative; }

.carousel-track {
  display: flex; gap: var(--sp-4);
  margin: 0; padding: 0 0 var(--sp-3); list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: thin;
  scrollbar-color: var(--grey-500) transparent;
  -webkit-overflow-scrolling: touch;
}
.carousel-track::-webkit-scrollbar { height: 6px; }
.carousel-track::-webkit-scrollbar-thumb { background: var(--grey-500); border-radius: 3px; }

.carousel-slide {
  flex: 0 0 clamp(180px, 62vw, 232px);
  scroll-snap-align: start;
  margin: 0;
}

.carousel-arrow {
  position: absolute; top: calc(50% - var(--sp-5)); z-index: 2;
  width: 48px; height: 48px;
  display: grid; place-items: center;
  background: var(--white); color: var(--black);
  border: 0; border-radius: 50%;
  box-shadow: var(--shadow-lg);
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.carousel-arrow:hover { transform: scale(1.08); }
.carousel-arrow[hidden] { display: none; }
.carousel-prev { left: -14px; }
.carousel-next { right: -14px; }
@media (max-width: 900px) { .carousel-arrow { display: none; } }

/* One video card. In the carousel each slide is exactly the card width, so
   there is no dead whitespace inside the link, which was the complaint about
   the old full-width grid card. */
.video-card {
  display: flex; flex-direction: column;
  height: 100%;
  background: var(--slate-700);
  border: 1px solid rgba(255,255,255,.10);
  border-radius: var(--radius-lg);
  overflow: hidden;
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.video-card:hover { border-color: var(--grey-400); transform: translateY(-3px); box-shadow: var(--shadow-lg); }

.video-card-media {
  position: relative; display: block;
  aspect-ratio: 9 / 16;
  background: var(--ink-900);
  overflow: hidden;
}
.video-card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .45s var(--ease); }
.video-card:hover .video-card-media img { transform: scale(1.04); }
/* Scrim only at the bottom, where the view count sits. The play badge has its
   own backing, and darkening the whole frame would flatten the photography. */
.video-card-media::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.72) 0%, rgba(0,0,0,0) 38%);
}

.video-play {
  position: absolute; top: 50%; left: 50%; z-index: 1;
  transform: translate(-50%, -50%);
  width: 54px; height: 54px;
  display: grid; place-items: center;
  background: rgba(0, 0, 0, .55);
  border: 2px solid rgba(255,255,255,.9);
  border-radius: 50%;
  color: var(--white);
  /* Nudged right: an equilateral triangle centred on its bounding box reads
     as sitting left of centre inside a circle. */
  padding-left: 4px;
  transition: background-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.video-card:hover .video-play { background: rgba(0,0,0,.8); transform: translate(-50%, -50%) scale(1.08); }

.video-views {
  position: absolute; left: var(--sp-3); bottom: var(--sp-3); z-index: 1;
  font-size: .75rem; font-weight: 800; letter-spacing: .03em;
  color: var(--white);
  text-shadow: 0 1px 3px rgba(0,0,0,.6);
}

/* The card lives on a dark section, so its body is dark-on-dark by default. */
.video-card-body { display: flex; flex-direction: column; gap: .3rem; padding: var(--sp-4); flex: 1; }
.video-caption {
  font-size: var(--fs-sm); font-weight: 700; line-height: 1.35; color: var(--white);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.video-meta {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .6875rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  color: var(--grey-300); margin-top: auto;
}
.video-card:hover .video-meta { color: var(--white); }

@media (max-width: 520px) {
  .video-card-body { padding: var(--sp-3); }
  .video-play { width: 44px; height: 44px; }
}

/* ==========================================================================
   17b. LIGHTBOX

   Every gallery figure on the site opens here. The markup is untouched: the
   script promotes existing <figure> elements to buttons, so this works on the
   homepage, the projects page and all ten service galleries without any of
   them knowing about it, and a crawler still sees plain images.

   Sizing uses dvh rather than vh. On mobile Safari, vh is the height of the
   viewport WITHOUT the browser chrome, so a 100vh lightbox puts its close
   button underneath the address bar, which is precisely the control someone
   needs when a photo has taken over their screen.
   ========================================================================== */

.lightbox {
  position: fixed; inset: 0; z-index: 1200;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: rgba(0, 0, 0, .94);
  opacity: 0; visibility: hidden;
  transition: opacity .2s var(--ease), visibility 0s linear .2s;
}
.lightbox.active {
  opacity: 1; visibility: visible;
  transition: opacity .2s var(--ease), visibility 0s linear 0s;
}

.lightbox-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  color: var(--grey-300);
  font-size: .8125rem; font-weight: 700; letter-spacing: .04em;
}

.lightbox-close {
  width: 46px; height: 46px; flex: none;
  display: grid; place-items: center;
  background: transparent; border: 1px solid rgba(255,255,255,.28);
  border-radius: var(--radius); color: var(--white);
}
.lightbox-close:hover { background: rgba(255,255,255,.12); border-color: var(--white); }

.lightbox-stage {
  position: relative;
  display: grid; place-items: center;
  min-height: 0;                 /* lets the image shrink inside the grid row */
  padding: 0 var(--sp-3);
}
.lightbox-stage img {
  max-width: 100%;
  max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
  border-radius: var(--radius);
  /* No transition on opacity here: swapping src mid-fade shows the old image
     briefly at the new one's size, which reads as a glitch. */
}

.lightbox-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 52px; height: 52px;
  display: grid; place-items: center;
  background: rgba(0,0,0,.55); color: var(--white);
  border: 1px solid rgba(255,255,255,.24);
  border-radius: 50%;
}
.lightbox-nav:hover { background: rgba(0,0,0,.85); border-color: var(--white); }
.lightbox-nav[hidden] { display: none; }
.lightbox-prev { left: var(--sp-3); }
.lightbox-next { right: var(--sp-3); }

.lightbox-caption {
  padding: var(--sp-4) var(--sp-5) var(--sp-6);
  text-align: center;
  color: var(--text-on-dark);
  font-size: var(--fs-sm); line-height: 1.5;
  max-width: 70ch; margin-inline: auto;
}

/* Gallery figures become interactive. Cursor and hover state say so before
   the click, which the inert version did not. */
.gallery figure[role="button"],
.gallery-item figure[role="button"] { cursor: zoom-in; }
.gallery figure[role="button"]:focus-visible {
  outline: 3px solid var(--star); outline-offset: 3px;
}

@media (max-width: 640px) {
  .lightbox-nav { width: 44px; height: 44px; }
  .lightbox-prev { left: 4px; }
  .lightbox-next { right: 4px; }
  .lightbox-caption { padding: var(--sp-3) var(--sp-4) var(--sp-5); font-size: .8125rem; }
}

/* Modern viewport unit where supported. Declared second so it simply wins,
   and older browsers keep the vh fallback above. */
@supports (height: 100dvh) {
  .lightbox { height: 100dvh; }
}

/* ==========================================================================
   18. TOUCH TARGETS

   Card links look small when measured, but each card carries a full-bleed
   ::after overlay so the real hit area is the whole card. The links that
   genuinely need help are the dense text lists: the footer columns, the
   breadcrumb trail and the town chips. Padding rather than font size, so the
   footer keeps its density on desktop and only opens up on touch.
   ========================================================================== */

@media (hover: none) and (pointer: coarse) {
  .footer-links { gap: 0; }
  .footer-links a { padding-block: .6rem; }
  .footer-bottom a { display: inline-block; padding-block: .5rem; }
  .breadcrumbs a, .breadcrumbs li { padding-block: .35rem; }
  .town-list li { padding: .55rem .8rem; }
  .header-logo { padding-block: .3rem; }
  .footer-social a { width: 46px; height: 46px; }
}

/* ==========================================================================
   19. PRINT
   ========================================================================== */

@media print {
  .top-bar, .header, .mobile-drawer, .drawer-overlay, .sticky-rail,
  .mobile-bar, .popup-overlay, .footer-map, .cta-band { display: none !important; }
  body { padding-bottom: 0; color: #000; }
  a[href^="http"]::after { content: ' (' attr(href) ')'; font-size: .75em; }
}

/* ---------- Footer credit signature (RBR Growth Consulting) ---------- */
.foot__credit {
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid rgba(128,128,128,.25);
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: inherit;
  text-align: center;
}
.foot__credit a {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  color: inherit;
  opacity: 0.75;
  text-decoration: none;
  transition: opacity 180ms ease;
}
.foot__credit a:hover,
.foot__credit a:focus-visible { opacity: 1; }
.foot__credit img {
  height: 26px;
  width: auto;
  display: block;
  filter: opacity(0.95) contrast(1.08) saturate(1.05);
  transition: filter 420ms ease, transform 420ms ease;
}
.foot__credit a:hover img {
  filter: opacity(1) contrast(1.1) saturate(1.15)
          drop-shadow(0 2px 8px rgba(220, 170, 90, 0.45));
  transform: translateY(-1px);
}
.foot__credit strong { font-weight: 600; color: inherit; }
@media (prefers-reduced-motion: reduce) {
  .foot__credit a, .foot__credit img { transition: none; }
}
/* ---------- end RBR footer credit ---------- */
