/* ==========================================================================
   Honchar Remodeling — site stylesheet
   One accent colour, applied to one action. Everything else is neutral.
   ========================================================================== */

:root {
  /* --- colour ------------------------------------------------------------
     The brand is black and white. The trucks are wrapped that way and the
     logo has no colour in it, so neither does this site.

     V-05 of the review found the old site failed BECAUSE it was monochrome:
     seven identical white buttons, nothing telling the eye where to go. The
     answer isn't a hue, it's hierarchy. Here exactly one element per screen
     is a solid filled block -- the primary action -- secondary actions are
     outline only, and everything else is text. Fill carries the priority
     that colour normally would. Keep that rule and the palette works; break
     it by filling a second button and you are back to the old site. */
  --ink:        #0D0D0D;
  --ink-2:      #3A3A3A;
  --muted:      #6E6E6E;
  --bone:       #F4F4F4;
  --paper:      #FFFFFF;
  --sand:       #E7E7E7;
  --rule:       #D6D6D6;
  --rule-soft:  #E9E9E9;

  /* "Accent" is black. Named this way so the one-action rule stays legible
     in the CSS: anything using --accent is the primary action, nothing else. */
  --accent:      #0D0D0D;
  --accent-deep: #000000;
  --accent-tint: #ECECEC;

  --dark:       #121212;
  --dark-2:     #1E1E1E;
  --on-dark:    #F2F2F2;
  --on-dark-2:  #A8A8A8;

  --good:       #2F6B4F;
  --warn:       #8A6516;

  --sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Archivo echoes the heavy geometric wordmark in the logo. The logo and
     the H1 sit inches apart in the header, so they read as one voice. */
  --display: "Archivo", "Helvetica Neue", Arial, system-ui, sans-serif;

  --wrap: 1200px;
  --measure: 66ch;
  --radius: 4px;

  --shadow: 0 1px 2px rgba(20,23,26,.05), 0 8px 24px -12px rgba(20,23,26,.18);

  --step-1: clamp(.82rem, .8rem + .1vw, .88rem);
  --step-0: clamp(1rem, .97rem + .15vw, 1.06rem);
  --step-1u: clamp(1.16rem, 1.1rem + .3vw, 1.32rem);
  --step-2: clamp(1.4rem, 1.28rem + .6vw, 1.75rem);
  --step-3: clamp(1.75rem, 1.5rem + 1.1vw, 2.4rem);
  --step-4: clamp(2.2rem, 1.75rem + 2vw, 3.3rem);
  --step-5: clamp(2.7rem, 1.9rem + 3.4vw, 4.6rem);
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--sans);
  /* V-06: body was 300 weight on the old site. 400 minimum, 450 here. */
  font-weight: 400;
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

/* <figure> carries a UA default of margin: 1em 40px. Every card component
   here is a figure, so without this they each gained 80px of side margin --
   invisible inside a grid track (it just squeezed the card) but obvious in
   the flex rail, where it offset the first card by 40px and inflated
   scrollWidth by 560px across seven cards. */
figure { margin: 0; }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.028em;
  margin: 0;
  text-wrap: balance;
}
h1 { letter-spacing: -0.035em; }
h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1u); line-height: 1.25; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

a { color: var(--accent-deep); text-decoration: underline;
    text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--accent); }

:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
  border-radius: 2px;
}
/* A black ring vanishes on the dark sections -- invert it there. */
.on-dark :focus-visible, .hero :focus-visible, .page-head :focus-visible,
.cta-band :focus-visible, .site-footer :focus-visible, .announce :focus-visible {
  outline-color: var(--on-dark);
}

.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }
.wrap-narrow { width: min(100% - 2.5rem, 820px); margin-inline: auto; }
.prose { max-width: var(--measure); }
/* One body size and one heading size inside running copy, with the heading
   carrying real space on both sides. Previously the h2 had a top margin and
   no bottom one, so it sat directly on the paragraph beneath it. */
.prose > * + * { margin-top: 1.15em; }
.prose h2, .prose h3 {
  font-size: var(--step-3);
  margin-top: 2.75rem;
  margin-bottom: 1rem;
}
.prose h2 + p, .prose h3 + p { margin-top: 0; }
.prose p { margin-bottom: 0; }
.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; left: 1rem; top: -4rem; z-index: 200;
  background: var(--accent); color: #fff; padding: .75rem 1.15rem;
  border-radius: var(--radius); font-weight: 600; text-decoration: none;
  transition: top .18s ease;
}
.skip-link:focus { top: 1rem; color: #fff; }

section { padding-block: clamp(3.5rem, 7vw, 6.5rem); }
section.tight { padding-block: clamp(2.5rem, 4vw, 3.5rem); }

.eyebrow {
  font-family: var(--sans);
  font-size: var(--step-1);
  font-weight: 600;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 1rem;
}
.on-dark .eyebrow { color: var(--on-dark); }

.lede { font-size: var(--step-1u); color: var(--ink-2); line-height: 1.55; max-width: 58ch; }
.on-dark .lede { color: var(--on-dark-2); }

/* ==========================================================================
   Buttons — V-05: exactly one action wears the accent.
   ========================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  min-height: 52px; padding: .85rem 1.6rem;
  font-family: var(--sans); font-size: var(--step-0); font-weight: 600;
  line-height: 1.2; text-align: center; text-decoration: none;
  border: 1.5px solid transparent; border-radius: var(--radius);
  cursor: pointer; transition: background-color .18s ease, border-color .18s ease,
    color .18s ease, transform .18s ease;
}
.btn:active { transform: translateY(1px); }

/* THE primary action. Nothing else on the site is this colour. */
.btn-primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn-primary:hover { background: var(--accent-deep); border-color: var(--accent-deep); color: #fff; }

.btn-secondary { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn-secondary:hover { background: var(--ink); color: var(--bone); }

/* Dark grounds invert BOTH buttons. With a black accent the filled primary
   would otherwise be black-on-#121212 -- the same invisible-button bug the
   hero secondary had before. On dark, the primary becomes the white block:
   still exactly one filled element, still the only one. */
.on-dark .btn-primary,
.hero .btn-primary,
.page-head .btn-primary,
.guarantee .btn-primary { background: var(--on-dark); color: var(--ink); border-color: var(--on-dark); }
.on-dark .btn-primary:hover,
.hero .btn-primary:hover,
.page-head .btn-primary:hover,
.guarantee .btn-primary:hover { background: #fff; color: #000; border-color: #fff; }

/* .hero and .page-head are dark grounds without the .on-dark class, so the
   secondary button rendered ink-on-near-black — invisible. Any dark ground
   gets the light treatment. */
.on-dark .btn-secondary,
.hero .btn-secondary,
.page-head .btn-secondary,
.guarantee .btn-secondary { color: var(--on-dark); border-color: rgba(237,235,228,.5); }
.on-dark .btn-secondary:hover,
.hero .btn-secondary:hover,
.page-head .btn-secondary:hover,
.guarantee .btn-secondary:hover { background: var(--on-dark); color: var(--dark); }

.btn-block { width: 100%; }
.btn-lg { min-height: 58px; padding: 1rem 2rem; font-size: var(--step-1u); }

.btn-row { display: flex; flex-wrap: wrap; gap: .85rem; }

.cta-note {
  font-size: var(--step-1); color: var(--muted); margin: .9rem 0 0;
  display: flex; flex-wrap: wrap; gap: .4rem .85rem;
}
.on-dark .cta-note { color: var(--on-dark-2); }
.cta-note span { white-space: nowrap; }

/* ==========================================================================
   Header — V-02: tel: link, visible at every width, never behind a hamburger
   ========================================================================== */

.announce {
  background: var(--dark); color: var(--on-dark);
  font-size: var(--step-1); text-align: center;
  padding: .55rem 1rem; letter-spacing: .01em;
}
.announce strong { color: var(--on-dark); font-weight: 600; }

.site-header {
  position: sticky; top: 0; z-index: 100;
  /* Solid, deliberately. backdrop-filter here would make the header a
     containing block for position:fixed descendants, which collapses the
     off-canvas nav panel to the header's own box (120px tall) and leaves its
     links spilling over the page with nothing behind them. Not worth a blur. */
  background: var(--bone);
  border-bottom: 1px solid var(--rule);
}
.header-inner {
  display: flex; align-items: center; gap: 1rem;
  min-height: 74px; padding-block: .6rem;
}
.brand {
  display: flex; align-items: center;
  text-decoration: none; color: var(--ink); flex: none;
  /* On a narrow screen this pushes the phone and the menu button to the right
     edge. On a wide one the desktop rule below takes over, because a single
     auto margin piles ALL the free space into one 273px hole beside a 93px
     logo and leaves it looking stranded. */
  margin-right: auto;
}
.brand-logo {
  /* The client's full lockup: mark over wordmark, 1.6:1. Height is the whole
     game here -- "REMODELING" is letterspaced and about a twelfth of the
     lockup, so it turns to mush below roughly 50px. Which is why this is a
     height, never a width, and why the phone pill below gives up its icon on
     a narrow screen rather than the logo giving up the name. */
  height: 52px; width: auto; flex: none; display: block;
}

@media (min-width: 621px) {
  /* Tablet still hides the nav behind the hamburger, so the row is only the
     logo and the number -- there is room for the lockup to breathe. */
  .brand-logo { height: 58px; }
}
@media (min-width: 1121px) {
  /* Three zones, evenly spread: the logo, the number, then the nav and its
     CTA. Two auto margins split the free space between them instead of
     dumping it all after the logo. */
  .header-inner { padding-block: .5rem; }
  .brand-logo { height: 66px; }
  .brand { margin-right: 0; }
  .header-phone { margin-left: auto; }
  .nav { margin-left: auto; }
  .nav .btn-primary { margin-left: .85rem; }
}

.nav { display: flex; align-items: center; gap: .15rem; }
.nav a {
  padding: .6rem .62rem; border-radius: var(--radius);
  color: var(--ink); text-decoration: none; font-weight: 500; font-size: .93rem;
  /* Six links, a phone pill and a CTA share this row. Without nowrap,
     "Flooring & Tile" and "Our Work" break onto two lines and the header
     grows a ragged second row. */
  white-space: nowrap;
}
.nav a:hover, .nav a[aria-current="page"] { background: var(--sand); color: var(--ink); }

/* The nav CTA is an <a> inside .nav, so `.nav a { color: var(--ink) }` and the
   aria-current background both outrank .btn-primary and stripped the button
   back to ink-on-ink. It needs to win on specificity and sit after those
   rules. This was wrong before the palette change too -- it just read as
   near-black on dark teal instead of black on black, so nothing flagged it. */
.nav a.btn-primary,
.nav a.btn-primary:hover,
.nav a.btn-primary[aria-current="page"] {
  background: var(--accent); color: #fff; border-color: var(--accent);
  text-decoration: none;
}
.nav a.btn-primary:hover { background: var(--accent-deep); border-color: var(--accent-deep); }

.header-phone {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .6rem .95rem; min-height: 46px;
  border: 1.5px solid var(--ink); border-radius: var(--radius);
  color: var(--ink); text-decoration: none; font-weight: 700;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.header-phone:hover { background: var(--ink); color: var(--bone); }
.header-phone small {
  display: block; font-size: .6rem; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted); line-height: 1;
}
.header-phone:hover small { color: rgba(246,243,237,.75); }

.nav-toggle {
  display: none; width: 46px; height: 46px; flex: none;
  align-items: center; justify-content: center;
  background: transparent; border: 1.5px solid var(--ink);
  border-radius: var(--radius); cursor: pointer; color: var(--ink);
}

@media (max-width: 1120px) {
  .nav-toggle { display: inline-flex; }
  .header-phone small { display: none; }
  .header-phone { padding: .55rem .8rem; }
  /* The panel never leaves the viewport. Parking it off-canvas with
     translateX(100%) extends the document's scroll width by its own width —
     a phantom 328px horizontal scroll on every page that no amount of
     overflow-x:hidden on body or html will clip, because fixed elements
     aren't clipped by an ancestor's overflow. So it stays at right:0 and
     animates with opacity plus a short slide instead. */
  .nav {
    position: fixed; inset: 0 0 0 auto; width: min(84vw, 340px);
    flex-direction: column; align-items: stretch; gap: .2rem;
    background: var(--bone); border-left: 1px solid var(--rule);
    padding: 5.5rem 1.25rem 2rem; overflow-y: auto;
    opacity: 0; visibility: hidden; transform: translateX(14px);
    transition: opacity .22s ease, transform .22s cubic-bezier(.4,0,.2,1), visibility 0s linear .22s;
    box-shadow: -20px 0 50px -30px rgba(0,0,0,.5);
  }
  .nav[data-open="true"] {
    opacity: 1; visibility: visible; transform: none;
    transition: opacity .22s ease, transform .22s cubic-bezier(.4,0,.2,1), visibility 0s;
  }
  .nav a { padding: .9rem .75rem; font-size: 1.05rem; border-bottom: 1px solid var(--rule-soft); border-radius: 0; }
  .nav .btn { margin-top: 1rem; }
}
@media (prefers-reduced-motion: reduce) { .nav { transition: none; } }

/* The header carries three things that must all fit: the brand, the phone
   number (V-02 — it never goes behind the hamburger) and the menu button.
   Below ~560px they don't, so the brand gives up ground first. The number
   is the one element that must survive to the narrowest width. */
@media (max-width: 620px) {
  .header-inner { gap: .5rem; min-height: 0; padding-block: .5rem; }
  .header-phone { font-size: .95rem; padding: .5rem .7rem; min-height: 44px; }
}
@media (max-width: 430px) {
  /* The pill sheds its icon; the logo keeps the name. Both still fit, and the
     tap target stays 44px because the padding does the work the icon did. */
  .header-inner { gap: .4rem; }
  .header-phone { font-size: .88rem; padding: .5rem .6rem; gap: 0; }
  .header-phone svg { display: none; }
}

/* Mobile sticky call/text bar — C-02, the single highest-value element */
.sticky-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 99;
  display: none; gap: 1px;
  background: var(--rule); border-top: 1px solid var(--rule);
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.sticky-bar a {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 60px; text-decoration: none; font-weight: 700; font-size: 1rem;
  background: var(--paper); color: var(--ink);
}
.sticky-bar a.is-primary { background: var(--accent); color: #fff; }
.sticky-bar svg { width: 19px; height: 19px; flex: none; }
@media (max-width: 780px) {
  .sticky-bar { display: flex; }
  body { padding-bottom: 60px; }
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero { position: relative; background: var(--dark); color: var(--on-dark); overflow: hidden; }
.hero-media { position: absolute; inset: 0; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; opacity: .62; }
.hero-media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(10,10,10,.95) 0%, rgba(10,10,10,.82) 38%, rgba(10,10,10,.45) 72%, rgba(10,10,10,.30) 100%);
}
.hero-inner { position: relative; padding-block: clamp(3.5rem, 9vw, 7rem); }
.hero h1 { color: #fff; max-width: 15ch; }
.hero .lede { margin-top: 1.4rem; max-width: 52ch; color: rgba(237,235,228,.88); }
.hero .btn-row { margin-top: 2.1rem; }

.hero-sub {
  display: inline-flex; align-items: center; gap: .6rem;
  font-size: var(--step-1); font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--on-dark); margin-bottom: 1.2rem;
}
.hero-sub::before { content: ""; width: 28px; height: 2px; background: var(--on-dark); }

/* Trust bar — C-07 */
.trust {
  background: var(--dark-2); color: var(--on-dark);
  border-top: 1px solid rgba(237,235,228,.1);
}
.trust ul {
  list-style: none; margin: 0; padding: 1.5rem 0; display: grid; gap: 1.1rem 2rem;
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
}
.trust li { display: flex; align-items: flex-start; gap: .65rem; font-size: .95rem; line-height: 1.4; }
.trust svg { width: 20px; height: 20px; flex: none; color: var(--on-dark); margin-top: 1px; }
.trust strong { display: block; font-weight: 600; }
.trust span { color: var(--on-dark-2); font-size: .86rem; }

/* ==========================================================================
   Sections
   ========================================================================== */

.on-dark { background: var(--dark); color: var(--on-dark); }
.on-dark h1, .on-dark h2, .on-dark h3 { color: #fff; }
.on-sand { background: var(--sand); }
.on-paper { background: var(--paper); }

.sec-head { max-width: 62ch; margin-bottom: clamp(2rem, 4vw, 3rem); }
.sec-head.center { margin-inline: auto; text-align: center; }
.sec-head p { margin-top: 1rem; color: var(--ink-2); font-size: var(--step-1u); }
.on-dark .sec-head p { color: var(--on-dark-2); }

/* Service cards */
.cards { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fit, minmax(min(265px, 100%), 1fr)); }
.card {
  display: flex; flex-direction: column; background: var(--paper);
  border: 1px solid var(--rule); border-radius: var(--radius);
  overflow: hidden; text-decoration: none; color: var(--ink);
  transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.card:hover { border-color: var(--accent); transform: translateY(-3px); box-shadow: var(--shadow); color: var(--ink); }
.card-img { aspect-ratio: 4 / 3; overflow: hidden; background: var(--sand); }
.card-img img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.card:hover .card-img img { transform: scale(1.04); }
.card-body { padding: 1.4rem 1.4rem 1.5rem; display: flex; flex-direction: column; flex: 1; gap: .6rem; }
.card-body h3 { font-size: var(--step-1u); }
.card-body p { color: var(--ink-2); font-size: .95rem; margin: 0; }
.card-link {
  margin-top: auto; padding-top: .5rem; font-weight: 600; font-size: .93rem;
  color: var(--accent-deep); display: inline-flex; align-items: center; gap: .4rem;
}
.card:hover .card-link { gap: .7rem; }
.card-link svg { width: 15px; height: 15px; transition: transform .2s ease; }

@media (prefers-reduced-motion: reduce) {
  .card, .card-img img, .card-link, .card-link svg { transition: none !important; }
  .card:hover { transform: none; }
  .card:hover .card-img img { transform: none; }
}

/* ==========================================================================
   Before / after slider — I-01, I-02
   ========================================================================== */

/* minmax(min(Npx, 100%), 1fr) throughout rather than minmax(Npx, 1fr): a bare
   minimum larger than the viewport does not shrink, it overflows, and at 320px
   the before/after grid and the review cards pushed the whole page 20-40px
   sideways. min() lets the track collapse to the container. */
.ba-grid { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }

.ba {
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--radius); overflow: hidden;
}
.ba-stage {
  /* One ratio for every pair. process-uploads.py crops all halves to 3:2, so
     two sliders side by side in a grid are always the same height. Giving each
     pair its own aspect avoided cropping but made the grid look broken --
     a 0.8 tall card next to a 2.9 panorama. */
  position: relative; aspect-ratio: 3 / 2; overflow: hidden;
  background: var(--sand); touch-action: pan-y; user-select: none; cursor: ew-resize;
}
.ba-stage img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ba-after { clip-path: inset(0 0 0 var(--pos, 50%)); }
.ba-tag {
  position: absolute; bottom: .85rem; z-index: 3;
  font-size: .68rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  padding: .35rem .6rem; border-radius: 2px; pointer-events: none;
  background: rgba(20,23,26,.78); color: #fff; backdrop-filter: blur(4px);
}
.ba-tag.is-before { left: .85rem; }
.ba-tag.is-after { right: .85rem; background: rgba(13,13,13,.86); }

.ba-divider {
  position: absolute; top: 0; bottom: 0; left: var(--pos, 50%);
  width: 2px; background: #fff; z-index: 4; pointer-events: none;
  box-shadow: 0 0 0 1px rgba(20,23,26,.22);
}
.ba-handle {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 46px; height: 46px; border-radius: 50%;
  background: #fff; color: var(--ink);
  display: grid; place-items: center;
  box-shadow: 0 2px 10px rgba(20,23,26,.32);
}
.ba-handle svg { width: 22px; height: 22px; }

/* The real control: a range input laid over the stage. Keyboard + AT get it free. */
.ba-range {
  position: absolute; inset: 0; z-index: 5;
  width: 100%; height: 100%; margin: 0; opacity: 0; cursor: ew-resize;
  -webkit-appearance: none; appearance: none; background: transparent;
}
.ba-range::-webkit-slider-thumb { -webkit-appearance: none; width: 46px; height: 100%; }
.ba-range::-moz-range-thumb { width: 46px; height: 100%; border: 0; opacity: 0; }
.ba-range:focus-visible { opacity: 1; outline: 3px solid var(--accent); outline-offset: -3px; }
.ba-range:focus-visible + .ba-divider { background: var(--accent); }

.ba-meta { padding: 1.15rem 1.3rem 1.35rem; }
.ba-meta h3 { font-size: var(--step-1u); margin-bottom: .3rem; }
.ba-meta .ba-loc {
  font-size: .78rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent-deep); margin-bottom: .55rem;
}
.ba-meta p { font-size: .93rem; color: var(--ink-2); margin: 0; }
.ba-hint { font-size: .8rem; color: var(--muted); margin-top: .7rem; display: flex; align-items: center; gap: .4rem; }
.ba-hint svg { width: 14px; height: 14px; }

/* ==========================================================================
   Guarantee statement — P-02
   ========================================================================== */

.guarantee { position: relative; }
.guarantee-quote {
  font-family: var(--display); font-size: var(--step-4); font-weight: 700;
  line-height: 1.06; letter-spacing: -.03em; color: #fff; max-width: 18ch;
}
.guarantee-grid { display: grid; gap: clamp(2rem, 5vw, 4rem); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .guarantee-grid { grid-template-columns: 1fr 1fr; } }
.guarantee-points { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.35rem; }
.guarantee-points li { display: flex; gap: .9rem; align-items: flex-start; }
.guarantee-points svg { width: 22px; height: 22px; flex: none; color: var(--on-dark); margin-top: 3px; }
.guarantee-points strong { display: block; margin-bottom: .2rem; color: #fff; }
.guarantee-points span { color: var(--on-dark-2); font-size: .95rem; }

/* Process — a real sequence, so numbering carries meaning */
.steps { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); counter-reset: step; }
.step { border-top: 2px solid var(--ink); padding-top: 1.15rem; }
.step::before {
  counter-increment: step; content: "0" counter(step);
  display: block; font-family: var(--sans); font-size: .8rem; font-weight: 700;
  letter-spacing: .12em; color: var(--accent-deep); margin-bottom: .6rem;
}
.step h3 { font-size: var(--step-1u); margin-bottom: .45rem; }
.step p { font-size: .95rem; color: var(--ink-2); margin: 0; }

/* Reviews — C-09: name, service, source, and a way to check it's real */
.reviews { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }

/* ---------- review carousel ----------
   A scroll-snapping rail rather than a JS slider: touch, trackpad, keyboard
   and screen readers all get native behaviour, and with JS off it stays a
   plain scrollable row instead of collapsing to one frozen card. */
.rail-wrap { position: relative; }
.rail {
  display: flex; gap: 1.25rem; overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity; scroll-padding-inline: 2px;
  padding: 2px 2px 1.25rem; margin-inline: -2px;
  scrollbar-width: thin; scrollbar-color: var(--rule-strong) transparent;
}
.rail > * { flex: 0 0 clamp(270px, 78vw, 370px); scroll-snap-align: start; }
.rail::-webkit-scrollbar { height: 6px; }
.rail::-webkit-scrollbar-thumb { background: var(--rule-strong); border-radius: 3px; }
.rail::-webkit-scrollbar-track { background: transparent; }

/* ---------- continuously moving review marquee ----------
   The track holds the cards twice; translating it exactly -50% puts the copy
   where the original started, so the loop is seamless. Duration is set from
   the measured width in JS to keep the speed constant whatever the card count.

   WCAG 2.2.2: motion that starts on its own and runs past five seconds needs
   a way to stop it. There is an explicit pause button, and it also pauses on
   hover and on keyboard focus so nobody has to chase a moving link. */
.marquee { position: relative; overflow: hidden; }
.marquee-track {
  display: flex; gap: 1.25rem; width: max-content; padding: 2px 0 .25rem;
  animation: marquee var(--marquee-duration, 60s) linear infinite;
}
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.marquee-track > * { flex: 0 0 clamp(270px, 78vw, 370px); }
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track,
.marquee[data-paused="true"] .marquee-track { animation-play-state: paused; }

/* fade the edges so cards enter and leave rather than being cut off */
.marquee::before, .marquee::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: clamp(24px, 6vw, 72px);
  z-index: 2; pointer-events: none;
}
.marquee::before { left: 0; background: linear-gradient(90deg, var(--paper), transparent); }
.marquee::after { right: 0; background: linear-gradient(270deg, var(--paper), transparent); }
.on-sand .marquee::before { background: linear-gradient(90deg, var(--sand), transparent); }
.on-sand .marquee::after { background: linear-gradient(270deg, var(--sand), transparent); }

.marquee-pause {
  display: inline-flex; align-items: center; gap: .45rem;
  min-height: 40px; padding: .4rem .9rem; margin-bottom: 1rem;
  background: transparent; color: var(--ink);
  border: 1.5px solid var(--rule-strong); border-radius: 100px;
  font: inherit; font-size: .84rem; font-weight: 600; cursor: pointer;
}
.marquee-pause:hover { border-color: var(--ink); }
.marquee-pause svg { width: 13px; height: 13px; }
.no-js .marquee-pause { display: none; }

@media (prefers-reduced-motion: reduce) {
  /* no automatic motion at all -- becomes a plain scrollable rail */
  .marquee { overflow-x: auto; scroll-snap-type: x proximity; }
  .marquee-track { animation: none; width: auto; }
  .marquee-track > * { scroll-snap-align: start; }
  .marquee::before, .marquee::after { display: none; }
  .marquee-pause { display: none; }
}

.rail-nav { display: flex; gap: .6rem; justify-content: flex-end; margin-bottom: 1rem; }
.rail-btn {
  width: 46px; height: 46px; display: grid; place-items: center;
  background: transparent; color: var(--ink);
  border: 1.5px solid var(--ink); border-radius: 50%;
  cursor: pointer; transition: background-color .15s ease, color .15s ease, opacity .15s ease;
}
.rail-btn:hover:not(:disabled) { background: var(--ink); color: var(--bone); }
.rail-btn:disabled { opacity: .28; cursor: default; }
.rail-btn svg { width: 19px; height: 19px; }
.on-dark .rail-btn { color: var(--on-dark); border-color: rgba(242,242,242,.5); }
.on-dark .rail-btn:hover:not(:disabled) { background: var(--on-dark); color: var(--dark); }
.no-js .rail-nav { display: none; }

/* the source link that makes a quote checkable rather than decorative */
.review-src {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .82rem; font-weight: 600; color: var(--ink);
  text-decoration: none; margin-top: .2rem;
}
.review-src:hover { color: var(--ink); text-decoration: underline; }
.review-src svg { width: 13px; height: 13px; flex: none; }
.review-src .gmark {
  width: 15px; height: 15px; border-radius: 50%;
  border: 1.5px solid var(--ink); display: grid; place-items: center;
  font-size: .6rem; font-weight: 700; line-height: 1; font-family: var(--display);
}
/* The reviews page carries seven quotes, several of them long. At the default
   280px track that collapses to four columns of about four words per line. */
.reviews-full { grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr)); }
@media (min-width: 1100px) { .reviews-full { grid-template-columns: repeat(3, 1fr); } }
.review {
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 1.5rem 1.5rem 1.35rem; display: flex; flex-direction: column; gap: .9rem;
}
.stars { display: flex; gap: 2px; color: var(--ink); }
.stars svg { width: 17px; height: 17px; }
.review blockquote { margin: 0; font-size: 1rem; line-height: 1.6; color: var(--ink); }
.review figcaption { margin-top: auto; padding-top: .3rem; font-size: .86rem; color: var(--muted); line-height: 1.5; }
.review figcaption strong { display: block; color: var(--ink); font-size: .95rem; font-weight: 600; }

.rating-summary {
  display: inline-flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius);
  padding: .8rem 1.2rem; font-size: .92rem;
}
.rating-summary b { font-size: 1.3rem; font-family: var(--display); }

/* Service areas — P-04 */
.areas { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.area-group h3 { font-size: var(--step-1u); margin-bottom: .3rem; }
.area-group .county { font-size: .78rem; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted); margin-bottom: .9rem; }
.area-group ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .4rem; }
.area-group li a {
  display: inline-block; padding: .38rem .75rem; font-size: .88rem;
  background: var(--paper); border: 1px solid var(--rule); border-radius: 100px;
  text-decoration: none; color: var(--ink);
}
.area-group li a:hover { border-color: var(--accent); color: var(--accent-deep); }

/* Final CTA band */
.cta-band { background: var(--accent); color: #fff; }
.cta-band h2 { color: #fff; }
.cta-band .lede { color: rgba(255,255,255,.9); }
.cta-band .btn-secondary { color: #fff; border-color: rgba(255,255,255,.55); }
.cta-band .btn-secondary:hover { background: #fff; color: var(--accent-deep); }
.cta-band .btn-primary { background: #fff; color: var(--accent-deep); border-color: #fff; }
.cta-band .btn-primary:hover { background: var(--bone); color: var(--accent-deep); }
.cta-band .cta-note { color: rgba(255,255,255,.85); }

/* ==========================================================================
   Forms — C-06: five fields, photo upload, nothing else
   ========================================================================== */

.form-card {
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: clamp(1.5rem, 3vw, 2.25rem);
}
.field { margin-bottom: 1.15rem; }
.field label { display: block; font-weight: 600; font-size: .93rem; margin-bottom: .4rem; }
.field .opt { font-weight: 400; color: var(--muted); }
.field input[type="text"], .field input[type="tel"], .field input[type="email"],
.field textarea, .field input[type="file"] {
  width: 100%; min-height: 52px; padding: .8rem .95rem;
  font-family: inherit; font-size: 1rem; color: var(--ink);
  background: var(--bone); border: 1.5px solid var(--rule); border-radius: var(--radius);
}
.field textarea { min-height: 110px; resize: vertical; line-height: 1.55; }
.field input:focus, .field textarea:focus { border-color: var(--accent); outline: none;
  box-shadow: 0 0 0 3px var(--accent-tint); }
.field input::placeholder, .field textarea::placeholder { color: #9AA0A4; }

.chips { display: flex; flex-wrap: wrap; gap: .55rem; }
.chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.chip span {
  display: inline-flex; align-items: center; min-height: 46px; padding: .5rem 1rem;
  border: 1.5px solid var(--rule); border-radius: 100px; background: var(--bone);
  font-size: .93rem; font-weight: 500; cursor: pointer; transition: all .15s ease;
}
.chip input:checked + span { background: var(--accent); border-color: var(--accent); color: #fff; }
.chip input:focus-visible + span { outline: 3px solid var(--accent); outline-offset: 2px; }
.chip span:hover { border-color: var(--accent); }

.form-note { font-size: .86rem; color: var(--muted); margin-top: .9rem; text-align: center; }
.field-hint { font-size: .84rem; color: var(--muted); margin-top: .4rem; }

/* ==========================================================================
   Gallery — 09.5: case studies, filterable, lazy, captioned
   ========================================================================== */

.filters { display: flex; flex-wrap: wrap; gap: .55rem; margin-bottom: 2rem; }
.filter-btn {
  min-height: 44px; padding: .5rem 1.05rem; font-family: inherit; font-size: .92rem;
  font-weight: 600; background: var(--paper); color: var(--ink);
  border: 1.5px solid var(--rule); border-radius: 100px; cursor: pointer;
  transition: all .15s ease;
}
.filter-btn:hover { border-color: var(--accent); }
.filter-btn[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--bone); }

.gallery-grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fill, minmax(min(270px, 100%), 1fr)); }
.shot {
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--radius); overflow: hidden;
}
/* L-06 / 09.4: NOT square. 4:3 so tall composites aren't clipped. */
.shot-img { aspect-ratio: 4 / 3; background: var(--sand); }
.shot-img img { width: 100%; height: 100%; object-fit: cover; }
.shot figcaption { padding: .9rem 1.05rem 1.05rem; }
.shot figcaption strong { display: block; font-size: .96rem; font-weight: 600; margin-bottom: .2rem; }
.shot figcaption span { font-size: .84rem; color: var(--muted); }
.shot[hidden] { display: none; }

.gallery-count { font-size: .9rem; color: var(--muted); margin-bottom: 1.25rem; }
.load-more-wrap { text-align: center; margin-top: 2.5rem; }

/* ==========================================================================
   Footer — V-09: real NAP, real hours, real licence
   ========================================================================== */

.site-footer { background: var(--dark); color: var(--on-dark-2); padding-block: clamp(3rem, 6vw, 4.5rem) 2rem; font-size: .93rem; }
.footer-grid { display: grid; gap: 2.5rem; grid-template-columns: repeat(auto-fit, minmax(min(215px, 100%), 1fr)); }
.site-footer h4 {
  font-family: var(--sans); font-size: .74rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--on-dark); margin-bottom: 1rem;
}
.site-footer a { color: var(--on-dark); text-decoration: none; }
.site-footer a:hover { color: var(--on-dark); text-decoration: underline; }
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.site-footer address { font-style: normal; line-height: 1.75; }
.footer-phone { font-size: 1.22rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.footer-bottom {
  margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid rgba(237,235,228,.14);
  display: flex; flex-wrap: wrap; gap: .6rem 1.5rem; justify-content: space-between;
  font-size: .84rem; color: var(--on-dark-2);
}

/* ==========================================================================
   Scroll animation — opt-in, and fully disabled for reduced motion
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(22px); }
  .js .reveal { transition: opacity .7s cubic-bezier(.2,.6,.3,1), transform .7s cubic-bezier(.2,.6,.3,1); }
  .js .reveal.is-in { opacity: 1; transform: none; }
  .js .reveal-stagger > * { opacity: 0; transform: translateY(18px);
    transition: opacity .6s cubic-bezier(.2,.6,.3,1), transform .6s cubic-bezier(.2,.6,.3,1); }
  .js .reveal-stagger.is-in > * { opacity: 1; transform: none; }
  .js .reveal-stagger.is-in > *:nth-child(2) { transition-delay: .08s; }
  .js .reveal-stagger.is-in > *:nth-child(3) { transition-delay: .16s; }
  .js .reveal-stagger.is-in > *:nth-child(4) { transition-delay: .24s; }
  .js .reveal-stagger.is-in > *:nth-child(5) { transition-delay: .32s; }
  .js .reveal-stagger.is-in > *:nth-child(6) { transition-delay: .40s; }
}
/* No-JS and reduced-motion users see everything, always. */
.no-js .reveal, .no-js .reveal-stagger > * { opacity: 1; transform: none; }

/* ==========================================================================
   Page header (interior pages)
   ========================================================================== */

.page-head { background: var(--dark); color: var(--on-dark); position: relative; overflow: hidden; }
.page-head-media { position: absolute; inset: 0; }
.page-head-media img { width: 100%; height: 100%; object-fit: cover; opacity: .5; }
.page-head-media::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(10,10,10,.93), rgba(10,10,10,.6)); }
.page-head .wrap { position: relative; padding-block: clamp(2.75rem, 6vw, 4.5rem); }
.page-head h1 { color: #fff; font-size: var(--step-4); max-width: 18ch; }
.page-head .lede { margin-top: 1rem; color: rgba(237,235,228,.85); }

.crumbs { font-size: .84rem; color: var(--on-dark-2); margin-bottom: 1rem; }
.crumbs a { color: var(--on-dark-2); }
.crumbs a:hover { color: var(--on-dark); }

/* Two-column content layout */
.split { display: grid; gap: clamp(2rem, 5vw, 4rem); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .split { grid-template-columns: 1.15fr .85fr; } }
.split.reverse > *:first-child { order: 2; }
@media (max-width: 899px) { .split.reverse > *:first-child { order: 0; } }

.sticky-side { position: sticky; top: 100px; }

.spec-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .8rem; }
.spec-list li { display: flex; gap: .7rem; align-items: flex-start; font-size: .97rem; }
.spec-list svg { width: 19px; height: 19px; flex: none; color: var(--accent); margin-top: 4px; }

.price-box {
  background: var(--accent-tint); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.25rem 1.35rem; margin-block: 1.5rem;
}
.price-box .price-label { font-size: .76rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--accent-deep); margin-bottom: .35rem; }
.price-box .price { font-family: var(--display); font-size: var(--step-2); line-height: 1.1; }
.price-box p { font-size: .88rem; color: var(--ink-2); margin: .5rem 0 0; }

/* FAQ */
.faq { display: grid; gap: 0; border-top: 1px solid var(--rule); }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  padding: 1.15rem 2.5rem 1.15rem 0; cursor: pointer; position: relative;
  font-weight: 600; font-size: 1.03rem; list-style: none; line-height: 1.4;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; position: absolute; right: .4rem; top: 50%; transform: translateY(-50%);
  font-size: 1.5rem; font-weight: 400; color: var(--accent); line-height: 1;
}
.faq details[open] summary::after { content: "\2212"; }
.faq details > div { padding: 0 2.5rem 1.35rem 0; color: var(--ink-2); max-width: var(--measure); }

/* Utility */
.stack-sm > * + * { margin-top: .75rem; }
.stack > * + * { margin-top: 1.5rem; }
.stack-lg > * + * { margin-top: 2.5rem; }
.text-center { text-align: center; }
.mt-lg { margin-top: clamp(2rem, 4vw, 3rem); }
.divider { height: 1px; background: var(--rule); border: 0; margin-block: clamp(2.5rem,5vw,4rem); }

@media print {
  .site-header, .sticky-bar, .announce, .cta-band { display: none !important; }
  body { background: #fff; }
}
