/* ===== RESET & BASE ===== */
*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    --bg: #FFFFFF;
    --bg-alt: #F7F5F2;
    --dark: #14161A;
    --dark-alt: #1B1E25;
    --dark-card: #232833;
    --text: #16181D;
    --muted: #5F6672;
    /* ===== BRAND COLOR SYSTEM =====
       The ONLY brand inputs are the four injected colors below. Every tint, glow,
       ring, and soft background is derived from them with color-mix, and all
       neutrals are untinted greys - so any client palette (warm, cool, muted,
       saturated) re-themes the entire template with no other edits. Never
       hardcode an accent-derived color; add a derived token here instead. */
    --accent: #103a7f;
    --accent-dark: #000c51;
    --accent-2: ##b4b5c0;
    --accent-2-dark: ##b4b5c0;
    --on-accent: #FFFFFF;                                               /* text/icons on accent surfaces */
    --accent-soft: color-mix(in srgb, var(--accent) 9%, transparent);   /* icon chips, subtle fills */
    --accent-ring: color-mix(in srgb, var(--accent) 15%, transparent);  /* focus rings */
    --accent-glow: color-mix(in srgb, var(--accent) 30%, transparent);  /* button glow shadows */
    --accent-line: color-mix(in srgb, var(--accent) 35%, transparent);  /* hover borders */
    --accent-on-dark: color-mix(in srgb, var(--accent) 55%, #ffffff);    /* accent legible on dark sections, any hue */
    --white: #FFFFFF;
    --card: #F1F1F1;   /* neutral surface for stat + form cards */
    --hero-overlay: linear-gradient(105deg, rgba(9,12,16,0.74) 0%, rgba(9,12,16,0.46) 44%, rgba(9,12,16,0.14) 76%, rgba(9,12,16,0.05) 100%),
                    linear-gradient(180deg, rgba(9,12,16,0.30) 0%, rgba(9,12,16,0) 26%, rgba(9,12,16,0.42) 100%);
    /* Dropdown glass while the nav is still transparent over the hero. Same family as the hero
       overlay and the proof bar, so a menu opened at the top of the page belongs to the photo
       behind it instead of punching a pale rectangle through it. */
    /* SOLID, not glass. The open menus can't actually blur the page behind them - the nav bar's own
       backdrop-filter becomes the child's backdrop root, so a translucent panel just lets the hero
       headline ghost through crisp under the menu labels. Opaque is the only readable option. */
    --menu-dark: #0f141b;
    --border: rgba(16, 20, 28, 0.08);
    --shadow-xs: 0 1px 2px rgba(16,20,28,0.05), 0 2px 8px rgba(16,20,28,0.04);
    --shadow-sm: 0 2px 4px rgba(16,20,28,0.04), 0 10px 28px rgba(16,20,28,0.08);
    --shadow-md: 0 4px 10px rgba(16,20,28,0.05), 0 20px 48px rgba(16,20,28,0.12);
    --shadow-lg: 0 10px 24px rgba(16,20,28,0.10), 0 36px 90px rgba(16,20,28,0.20);
    --radius: 20px;
    --radius-sm: 14px;
    --ease: cubic-bezier(0.4, 0, 0.2, 1);
    --transition: all 0.35s var(--ease);

    /* Georgia for headers, Arial for body + UI. Both are system fonts present on every Mac and
       Windows machine, so there's no webfont request at all - the pages used to block on a Google
       Fonts stylesheet for Noto Serif Display + Lato, and that <link> is gone from every page.
       No -apple-system ahead of Arial on purpose: it would quietly render San Francisco on a Mac,
       which is not what was asked for.
       Weight note: as system fonts these ship regular + bold only, so the 500/600 requests dotted
       through this file resolve to Georgia Bold / Arial Bold rather than a true mid-weight. That's
       the intended look here - headings stay sturdy over a photo. Two-font system, fully tokenized. */
    --font-display: Georgia, 'Times New Roman', serif;
    --font-sans: Arial, Helvetica, sans-serif;
    --font-body: Arial, Helvetica, sans-serif;
    --font-serif: Georgia, 'Times New Roman', serif;
}

html {
    scroll-behavior: smooth;
    scroll-padding-top: 84px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

body {
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.7;
    color: var(--text);
    background: var(--bg);
    overflow-x: hidden;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; transition: var(--transition); }
ul { list-style: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
::selection { background: var(--accent); color: var(--on-accent); }

.container { max-width: 1240px; margin: 0 auto; padding: 0 32px; }

h1, h2, h3 {
    font-family: var(--font-display);
    font-weight: 600;
    letter-spacing: -0.005em;
    line-height: 1.12;
}

.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    font-family: var(--font-body);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--accent);
    font-size: 12px;
    margin-bottom: 12px;
}
.eyebrow::before {
    content: "";
    width: 30px;
    height: 2px;
    background: var(--accent);
    flex-shrink: 0;
}
/* On dark/photo sections the accent may not have enough contrast - use a neutral. */
.hero .eyebrow, .page-hero .eyebrow, .final-cta .eyebrow,
.faq .eyebrow, .cta-band .eyebrow, .why .eyebrow, .services .eyebrow, .reviews .eyebrow { color: rgba(255,255,255,0.75); }

/* Lucide icon defaults - one library, one stroke weight everywhere */
[data-lucide], svg.lucide {
    width: 1em;
    height: 1em;
    stroke-width: 1.75;
    flex-shrink: 0;
}

.anim-fade-up {
    opacity: 0;
    transform: translateY(30px);
    transition: opacity 0.55s var(--ease), transform 0.55s var(--ease);
}
.anim-fade-up.visible { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .anim-fade-up { opacity: 1; transform: none; transition: none; }
    *, *::before, *::after { animation-duration: 0.001s !important; transition-duration: 0.001s !important; }
}

/* ===== BUTTONS ===== */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 15px 32px;
    border-radius: 999px;
    font-family: var(--font-sans);
    font-weight: 600;
    letter-spacing: 0.01em;
    font-size: 15.5px;
    line-height: 1.2;
    white-space: nowrap;
    transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease), background-color 0.35s var(--ease), border-color 0.35s var(--ease), color 0.35s var(--ease);
}
.btn--lg { padding: 17px 36px; font-size: 16.5px; }
.btn--primary {
    background: var(--accent);
    color: var(--on-accent);
    box-shadow: 0 2px 8px var(--accent-glow), var(--shadow-xs);
}
.btn--primary:hover {
    background: var(--accent-dark);
    transform: translateY(-2px);
    box-shadow: 0 12px 28px var(--accent-glow), var(--shadow-sm);
}
.btn--white { background: var(--white); color: var(--dark); box-shadow: var(--shadow-sm); }
.btn--white:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.btn--dark { background: var(--dark); color: var(--white); }
.btn--dark:hover { background: #000; transform: translateY(-2px); box-shadow: var(--shadow-md); }
.btn--outline-white {
    background: rgba(255,255,255,0.04);
    color: var(--white);
    border: 1.5px solid rgba(255,255,255,0.55);
    backdrop-filter: blur(4px);
}
.btn--outline-white:hover { background: rgba(255,255,255,0.14); border-color: var(--white); transform: translateY(-2px); }
.btn--outline-dark {
    background: var(--white);
    color: var(--dark);
    border: 1.5px solid var(--border);
    box-shadow: var(--shadow-xs);
}
.btn--outline-dark:hover { border-color: var(--dark); transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.btn--block { width: 100%; }
/* On photo/dark backgrounds the primary CTA stays SOLID brand color (the elite-contractor
   convention: the reference sites all run solid CTAs on the hero photo). A frosted button
   reads as disabled against a busy image. */
.hero__actions .btn--primary,
.page-hero__actions .btn--primary,
.cta-band__actions .btn--primary {
    background: var(--accent);
    color: var(--on-accent);
    box-shadow: 0 10px 30px rgba(0,0,0,0.28), 0 2px 10px var(--accent-glow);
}
.hero__actions .btn--primary:hover,
.page-hero__actions .btn--primary:hover,
.cta-band__actions .btn--primary:hover {
    background: var(--accent-dark);
    box-shadow: 0 16px 40px rgba(0,0,0,0.32), 0 0 0 4px var(--accent-glow);
    transform: translateY(-2px);
}

/* ===== HERO ENTRANCE (load-time, staggered; the rule draws in) ===== */
@keyframes heroRise { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: translateY(0); } }
@keyframes heroRule { from { transform: scaleX(0); opacity: 0; } to { transform: scaleX(1); opacity: 1; } }
.hero__social-proof, .hero__eyebrow, .hero__headline, .hero__sub, .hero__actions {
    animation: heroRise 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.hero__rule { animation: heroRule 0.8s cubic-bezier(0.22, 1, 0.36, 1) 0.55s both; }
.hero__social-proof { animation-delay: 0.05s; }
.hero__eyebrow { animation-delay: 0.15s; }
.hero__headline { animation-delay: 0.28s; }
.hero__sub { animation-delay: 0.62s; }
.hero__actions { animation-delay: 0.75s; }
@media (prefers-reduced-motion: reduce) {
    .hero__social-proof, .hero__eyebrow, .hero__headline, .hero__sub, .hero__actions, .hero__rule { animation: none; }
}

/* ===== NAVIGATION ===== */
.nav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
    background: transparent;
    height: 84px;
    /* Keep the bar clear of the notch / Dynamic Island on edge-to-edge iOS */
    height: calc(84px + env(safe-area-inset-top, 0px));
    padding-top: env(safe-area-inset-top, 0px);
    transition: background-color 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.nav.is-scrolled {
    background: rgba(255,255,255,0.94);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow: 0 1px 0 var(--border), 0 8px 30px rgba(16,20,28,0.08);
}
/* While the full-width services sheet is open the bar takes the sheet's tone and drops its lower
   edge, so the two are a single continuous surface. Which tone depends on where the page is: over
   the hero both are the dark glass the bar already sits in, and once scrolled both are pale. */
.nav.has-mega-open {
    box-shadow: none;
}
.nav.has-mega-open:not(.is-scrolled) {
    background: var(--menu-dark);
}
.nav.has-mega-open.is-scrolled {
    background: var(--bg-alt);
}
.nav__inner {
    max-width: 1320px;
    margin: 0 auto;
    height: 100%;
    padding: 0 32px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
}
.nav__logo {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.01em;
    font-size: clamp(16px, 3.6vw, 21px);
    color: var(--white);
    text-shadow: 0 1px 4px rgba(0,0,0,0.35);
    transition: color 0.35s var(--ease), text-shadow 0.35s var(--ease);
}
.nav.is-scrolled .nav__logo { color: var(--dark); text-shadow: none; }
.nav__logo-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav__logo.has-image-logo .nav__logo-text { display: none; }
.nav__logo-badge {
    /* Per-site logo size (set in the factory). The bar's height is fixed independently, and the
       76px cap guarantees the logo can never overflow it - so the nav bar never changes size. */
    height: 68px;
    max-height: 76px;
    max-width: 250px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.nav__logo-badge img { height: 100%; width: auto; max-width: 100%; object-fit: contain; filter: drop-shadow(0 1px 3px rgba(0,0,0,0.3)); }
.nav__logo-badge span {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    color: var(--on-accent);
    font-size: 16px;
    background: var(--accent);
    box-shadow: 0 2px 10px rgba(0,0,0,0.25);
    transition: box-shadow 0.35s var(--ease);
}
.nav.is-scrolled .nav__logo-badge span { box-shadow: none; }

.nav__links {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 1;
    justify-content: center;
}
.nav__links > li { position: relative; }
.nav__links a,
.nav__links button.nav__link {
    font-size: 15px;
    font-family: var(--font-body);
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--white);
    font-weight: 500;
    font-size: 15px;
    padding: 10px 16px;
    border-radius: 0;
    text-shadow: 0 1px 4px rgba(0,0,0,0.35);
    transition: color 0.3s var(--ease), text-shadow 0.3s var(--ease), background-color 0.3s var(--ease);
}
.nav.is-scrolled .nav__links a,
.nav.is-scrolled .nav__links button.nav__link { color: var(--text); text-shadow: none; }
/* Hover = accent underline only; text keeps its color so it stays readable
   over both the transparent-dark and scrolled-white nav states. */
.nav__links > li > a,
.nav__links > li > button.nav__link { position: relative; }
.nav__links > li > a::after,
.nav__links > li > button.nav__link::after {
    content: '';
    position: absolute;
    left: 16px;
    right: 16px;
    bottom: 5px;
    height: 2px;
    /* white over the transparent-dark hero state; accent once the nav turns white -
       a dark client accent would vanish against the hero photo */
    background: rgba(255,255,255,0.9);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.3s var(--ease);
}
.nav.is-scrolled .nav__links > li > a::after,
.nav.is-scrolled .nav__links > li > button.nav__link::after { background: var(--accent); }
.nav__links > li > a:hover::after,
.nav__links > li > button.nav__link:hover::after { transform: scaleX(1); }

.nav__chevron { transition: transform 0.3s var(--ease); }
.has-dropdown.is-open .nav__chevron,
.has-dropdown:hover .nav__chevron { transform: rotate(180deg); }

/* Dropdown - fade + slide down, soft shadow, accent bar per item */
.dropdown {
    position: absolute;
    top: calc(100% + 10px);
    left: 50%;
    min-width: 230px;
    /* Warm off-white rather than flat #FFF - matches the paper tone the rest of the template uses.
       Fully opaque: the scrolled nav bar's backdrop-filter makes it this panel's backdrop root, so
       any translucency here lets page content ghost through with no blur to soften it. */
    background: var(--bg-alt);
    border-radius: 0;
    border: 1px solid var(--border);
    box-shadow: var(--shadow-md);
    padding: 8px;
    opacity: 0;
    visibility: hidden;
    transform: translateX(-50%) translateY(-8px);
    transition: opacity 0.28s var(--ease), transform 0.28s var(--ease), visibility 0.28s;
}
.dropdown::before {
    /* invisible hover bridge so the pointer can travel from trigger to panel */
    content: '';
    position: absolute;
    top: -12px;
    left: 0;
    right: 0;
    height: 12px;
}
.has-dropdown.is-open .dropdown {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}
.dropdown li a,
.nav.is-scrolled .dropdown li a {
    display: block;
    padding: 11px 16px;
    border-radius: 0;
    border-left: 2px solid transparent;
    color: var(--text);
    font-weight: 500;
    font-size: 14.5px;
    text-shadow: none;
}
.dropdown li a:hover,
.nav.is-scrolled .dropdown li a:hover {
    /* An accent tint, not --bg-alt: the panel itself is now that tone, so a grey hover would be
       invisible. */
    background: var(--accent-soft);
    border-left-color: var(--accent);
    color: var(--text);
}

/* ---- Mega menu ------------------------------------------------------------------------------
   A remodeler with a dozen services produced a single column tall enough to run off the bottom of
   the screen. Past a handful of services the generator promotes the panel to a full-bleed sheet
   under the bar - a grid of photo cards reading left-to-right, the way the big builder sites do it.
   The `is-mega` flag is set by the generator on BOTH the <li> and the <ul>: the li needs
   position:static so the panel can size itself against the fixed nav (i.e. the whole viewport)
   instead of against the narrow Services trigger. */
.nav__links > li.is-mega { position: static; }

.dropdown.is-mega {
    left: 0;
    right: 0;
    width: 100%;
    /* Pale by default (the scrolled state, where the page behind is white). The dark-glass variant
       for an unscrolled hero is further down, keyed off the nav. */
    background: var(--bg-alt);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    /* Flush under the bar - no gap for the pointer to fall through, so no hover bridge needed. */
    top: 100%;
    display: grid;
    /* Six across keeps even a 15-service list to three shallow rows, so the sheet never eats the
       whole screen the way five larger cards did. */
    grid-template-columns: repeat(6, 1fr);
    gap: 14px 16px;
    /* Full-bleed panel, content held to the same 1320px rhythm as the nav bar above it. */
    padding: 22px max(32px, calc((100% - 1320px) / 2)) 18px;
    /* No side or top edges: the bar above is the same surface, so a top hairline would draw a line
       through the middle of it. */
    border-left: 0;
    border-right: 0;
    border-top: 0;
    /* Two rows, never more - the generator caps how many cards it renders, this is the backstop. */
    grid-auto-rows: minmax(0, auto);
    overflow: hidden;
    /* Smoother than the small dropdown: longer, and on a decelerating curve so it settles rather
       than snapping. */
    transform: translateY(-10px);
    transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.46s cubic-bezier(0.16, 1, 0.3, 1),
                visibility 0.46s;
}
.has-dropdown.is-open .dropdown.is-mega { transform: translateY(0); }

.dropdown.is-mega > li { display: block; }
.dropdown.is-mega > li > a {
    display: block;
    padding: 0;
    border-left: 0;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: transparent;
    /* Each card lifts slightly on hover - the same easing as the panel. */
    transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1), background-color 0.3s var(--ease);
}
.dropdown.is-mega > li > a:hover {
    background: var(--accent-soft);
    border-left: 0;
    transform: translateY(-3px);
}
.dropdown__thumb {
    display: block;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--radius-sm);
    background: var(--card);
}
.dropdown__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.6s var(--ease);
}
.dropdown.is-mega > li > a:hover .dropdown__thumb img { transform: scale(1.05); }
.dropdown__label { display: block; padding: 9px 10px 10px; font-size: 14px; line-height: 1.3; }

/* The small (few-services) dropdown keeps its plain text list - same markup, no photos. */
.dropdown:not(.is-mega) .dropdown__thumb { display: none; }
.dropdown:not(.is-mega) .dropdown__label { padding: 0; }

/* The last cell closes the grid. It mirrors a service card exactly - same thumb-sized block on top,
   same label underneath - so it sits in the rhythm rather than interrupting it as a dashed box did. */
.dropdown.is-mega .dropdown__all-tile > a {
    display: block;
    padding: 0;
    background: transparent;
}
.dropdown__all-art {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 16 / 9;
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--accent) 10%, var(--bg-alt));
    color: var(--accent);
    transition: background-color 0.35s var(--ease), color 0.35s var(--ease);
}
.dropdown__all-art svg { width: 26px; height: 26px; }
.dropdown.is-mega .dropdown__all-tile > a:hover .dropdown__all-art {
    background: var(--accent);
    color: var(--on-accent);
}
.dropdown.is-mega .dropdown__all-tile .dropdown__label { font-weight: 700; padding-bottom: 0; }
.dropdown.is-mega .dropdown__all-count {
    display: block;
    padding: 0 10px;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--muted);
}

/* In the small (few-services) dropdown the tile collapses back to a plain text link. */
.dropdown:not(.is-mega) .dropdown__all-count,
.dropdown:not(.is-mega) .dropdown__all-art { display: none; }

@media (max-width: 1240px) { .dropdown.is-mega { grid-template-columns: repeat(5, 1fr); } }
@media (max-width: 1024px) { .dropdown.is-mega { grid-template-columns: repeat(4, 1fr); } }

/* ---- Dark skin: menus opened while the bar is still transparent over the hero ----------------
   A pale panel dropped out of a transparent bar was the jarring part: the bar read as part of the
   photo and the menu read as a separate white box stapled underneath. Over the hero both are now
   the same dark glass; the moment the page scrolls and the bar turns pale, so does the menu. */
.nav:not(.is-scrolled) .dropdown {
    background: var(--menu-dark);
    border-color: rgba(255, 255, 255, 0.10);
    box-shadow: 0 24px 60px rgba(6, 9, 13, 0.45);
}
.nav:not(.is-scrolled) .dropdown li a,
.nav:not(.is-scrolled) .dropdown .dropdown__label { color: var(--white); }
.nav:not(.is-scrolled) .dropdown li a:hover {
    background: rgba(255, 255, 255, 0.08);
    border-left-color: var(--accent-on-dark);
    color: var(--white);
}
.nav:not(.is-scrolled) .dropdown.is-mega > li > a:hover { background: rgba(255, 255, 255, 0.08); }
.nav:not(.is-scrolled) .dropdown .dropdown__all-count { color: rgba(255, 255, 255, 0.55); }
.nav:not(.is-scrolled) .dropdown .dropdown__all-art {
    background: rgba(255, 255, 255, 0.09);
    color: var(--accent-on-dark);
}
.nav:not(.is-scrolled) .dropdown.is-mega .dropdown__all-tile > a:hover .dropdown__all-art {
    background: var(--accent);
    color: var(--on-accent);
}
.nav:not(.is-scrolled) .dropdown:not(.is-mega) .dropdown__all { border-top-color: rgba(255, 255, 255, 0.14); }
.nav:not(.is-scrolled) .dropdown__thumb { background: rgba(255, 255, 255, 0.06); }

.nav__actions { display: flex; align-items: center; gap: 14px; flex-shrink: 0; }
.nav__phone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1.2;
    background: transparent;
    color: var(--white);
    font-family: var(--font-sans);
    font-weight: 700;
    padding: 11px 6px;
    font-size: 15.5px;
    letter-spacing: 0.01em;
    text-shadow: 0 1px 4px rgba(0,0,0,0.35);
    border-bottom: 2px solid transparent;
    transition: color 0.35s var(--ease), border-color 0.25s var(--ease), text-shadow 0.35s var(--ease);
}
.nav__phone:hover { border-bottom-color: currentColor; }
.nav.is-scrolled .nav__phone { color: var(--dark); text-shadow: none; }
.nav__cta { padding: 11px 18px; font-size: 15px; }

.nav__toggle {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 40px;
    height: 40px;
    flex-shrink: 0;
}
.nav__toggle span { display: block; width: 22px; height: 2px; border-radius: 2px; background: var(--white); transition: var(--transition), background-color 0.3s var(--ease); }
.nav.is-scrolled .nav__toggle span,
.nav__toggle.is-active span { background: var(--dark); }
.nav__toggle.is-active span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav__toggle.is-active span:nth-child(2) { opacity: 0; }
.nav__toggle.is-active span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.nav__mobile {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-width: 400px;
    background: var(--white);
    z-index: 99;
    padding: 108px 30px 40px;
    overflow-y: auto;
    box-shadow: var(--shadow-lg);
    transform: translateX(100%);
    transition: transform 0.45s var(--ease);
}
.nav__mobile.is-open { transform: translateX(0); }
.nav__mobile-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(10,12,16,0.5);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    z-index: 98;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.35s var(--ease), visibility 0.35s;
}
.nav__mobile-backdrop.is-open { opacity: 1; visibility: visible; }
.nav__mobile ul { display: flex; flex-direction: column; margin-bottom: 30px; }
.nav__mobile ul li {
    opacity: 0;
    transform: translateX(24px);
    transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}
.nav__mobile.is-open ul li { opacity: 1; transform: translateX(0); }
.nav__mobile.is-open ul li:nth-child(1) { transition-delay: 0.06s; }
.nav__mobile.is-open ul li:nth-child(2) { transition-delay: 0.11s; }
.nav__mobile.is-open ul li:nth-child(3) { transition-delay: 0.16s; }
.nav__mobile.is-open ul li:nth-child(4) { transition-delay: 0.21s; }
.nav__mobile.is-open ul li:nth-child(5) { transition-delay: 0.26s; }
.nav__mobile.is-open ul li:nth-child(6) { transition-delay: 0.31s; }
.nav__mobile.is-open ul li:nth-child(n+7) { transition-delay: 0.36s; }
.nav__mobile ul li a {
    display: block;
    padding: 15px 4px;
    font-family: var(--font-display);
    font-weight: 600;
    letter-spacing: -0.01em;
    font-size: 21px;
    color: var(--text);
    border-bottom: 1px solid var(--border);
}
.nav__mobile ul li a:hover { padding-left: 10px; }
.nav__mobile .btn { width: 100%; }

/* ===== HERO ===== */
.hero {
    position: relative;
    min-height: 100vh;
    min-height: 100dvh; /* fill the visible viewport on mobile without the URL-bar jump */
    display: flex;
    align-items: center;
    background: var(--dark);
    /* The Ken Burns pan scales .hero__bg up to 1.13, which without this spills the photo ~55px past
       the section on every side. The bottom spill was the visible one: it ran on underneath the
       trust bar, so the bar read as floating in the photo instead of sitting at its base. The
       closing scenic section clips its scaled background for the same reason. */
    overflow: hidden;
}
.hero__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero__overlay { position: absolute; inset: 0; background: var(--hero-overlay); }
.hero__inner {
    position: relative;
    z-index: 2;
    width: 100%;
    max-width: 940px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding-top: 168px;
    padding-bottom: 176px;
}
.hero__content { display: flex; flex-direction: column; align-items: center; }

/* Social proof: stars + a single legible rating line, centered. */
.hero__social-proof {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 26px;
    padding: 8px 18px 8px 10px;
    border-radius: 999px;
    background: rgba(255,255,255,0.10);
    border: 1px solid rgba(255,255,255,0.18);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.hero__avatars { display: inline-flex; }
.hero__avatar {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    margin-left: -9px;
    /* Stack front-to-back left-to-right: Google on top, then Facebook, Thumbtack at the back.
       Source order alone would paint it the other way round (later siblings win), burying Google -
       the badge that carries the rating - under the other two. */
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--white);
    border: 2px solid rgba(20,22,26,0.85);
    box-shadow: 0 2px 6px rgba(0,0,0,0.25);
}
.hero__avatars .hero__avatar:first-child { margin-left: 0; }
.hero__avatars .hero__avatar:nth-child(1) { z-index: 3; }
.hero__avatars .hero__avatar:nth-child(2) { z-index: 2; }
.hero__avatars .hero__avatar:nth-child(3) { z-index: 1; }
.hero__avatar--fb { background: #1877F2; }
.hero__avatar--tt { background: #009FD9; }
.hero__rating-block { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.hero__rating-top { display: inline-flex; align-items: center; gap: 6px; }
.hero__rating-stars { color: #FBBC05; font-size: 13px; letter-spacing: 1.5px; line-height: 1; }
.hero__rating-num { color: var(--white); font-weight: 700; font-size: 13.5px; line-height: 1; font-family: var(--font-sans); }
.hero__rating-meta { font-size: 12px; color: rgba(255,255,255,0.82); line-height: 1; }

.hero__eyebrow {
    display: block;
    font-family: var(--font-body);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.22em;
    font-size: 13px;
    color: rgba(255,255,255,0.82);
    margin-bottom: 18px;
}
.hero__headline {
    color: var(--white);
    font-weight: 600;
    font-size: clamp(40px, 5.6vw, 70px);
    letter-spacing: -0.01em;
    line-height: 1.08;
    margin-bottom: 0;
    max-width: 16ch;
    text-wrap: balance;
    text-shadow: 0 2px 28px rgba(0,0,0,0.32);
}
/* The thin rule under the headline (the CGN signature) - centered, draws itself in from the middle. */
.hero__rule {
    width: 128px;
    height: 2px;
    background: rgba(255,255,255,0.7);
    margin: 28px auto 24px;
    transform-origin: center;
}
.hero__sub {
    color: rgba(255,255,255,0.94);
    font-family: var(--font-body);
    font-weight: 400;
    font-size: clamp(17px, 1.9vw, 21px);
    max-width: 620px;
    margin: 0 auto 40px;
}
.hero__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; }

/* ===== PROOF BAR - full-width auto-sliding marquee, seated in the base of the hero ===== */
.proof-stats {
    --proof-h: 90px;
    position: relative;
    z-index: 20;
    /* The band is seated in the base of the hero: pulled up by its full height so its bottom edge
       lands exactly on the hero's, and no negative bottom margin so it never floats over the section
       below. Same on every screen size - the hero is a plain full-viewport block, so its bottom edge
       is the photo's bottom edge on mobile too. */
    margin-top: calc(var(--proof-h) * -1);
    margin-bottom: 0;
}
.proof-bar {
    height: var(--proof-h);
    width: 100%;
    overflow: hidden;
    display: flex;
    align-items: center;
    background: rgba(16, 20, 26, 0.82);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-top: 1px solid rgba(255,255,255,0.14);
    /* No bottom border and the shadow casts upward: the band ends where the hero ends, so it sits ON
       the seam rather than over the section below - a lower hairline and a downward shadow would
       both read as it floating. */
    box-shadow: 0 -18px 46px rgba(10,14,20,0.28);
}
.proof-bar__track {
    display: flex;
    width: max-content;
    animation: proofSlide 48s linear infinite;
}
.proof-bar:hover .proof-bar__track { animation-play-state: paused; }
@keyframes proofSlide { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }
@media (prefers-reduced-motion: reduce) {
    .proof-bar__track { animation: none; }
}
.proof-bar__set { display: flex; align-items: center; flex-shrink: 0; }
.proof-bar__item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 0 34px;
    font-family: var(--font-sans);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.01em;
    color: rgba(255,255,255,0.82);
    white-space: nowrap;
}
.proof-bar__item strong { color: var(--white); font-weight: 700; }
.proof-bar__stars { color: #FBBC05; font-size: 12px; letter-spacing: 1px; }
.proof-bar__g { flex-shrink: 0; }
/* Diamond divider between items */
.proof-bar__sep {
    width: 5px;
    height: 5px;
    flex-shrink: 0;
    transform: rotate(45deg);
    background: rgba(255,255,255,0.28);
}

/* ===== INTRO + MAP ===== */
.intro { padding: 100px 0; background: var(--bg); }
.intro__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: center; }
.intro__content h2 {
    font-size: clamp(28px, 3.6vw, 42px);
    margin-bottom: 18px;
    color: var(--text);
}
.intro__content p { color: var(--muted); font-size: 16.5px; margin-bottom: 28px; }
.intro__content p strong { color: var(--text); }
.intro__actions { display: flex; flex-wrap: wrap; gap: 14px; }
.intro__photo { border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-md); aspect-ratio: 4/3; }
.intro__photo img { width: 100%; height: 100%; object-fit: cover; }

/* ===== SERVICES ===== */
.services { padding: 110px 0; background: var(--dark-alt); }
.section-header { text-align: center; max-width: 680px; margin: 0 auto 60px; }
.section-header h2 { font-size: clamp(30px, 4vw, 46px); margin-bottom: 14px; color: var(--text); text-wrap: balance; }
.section-header p { color: var(--muted); font-size: 16.5px; }
.services__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 44px; }
.services__header h2 { font-size: clamp(30px, 4vw, 42px); color: var(--white); }
.services__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; }
.service-card {
    position: relative;
    aspect-ratio: 4/3;
    border-radius: var(--radius);
    overflow: hidden;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.service-card:hover { transform: translateY(-6px); box-shadow: var(--shadow-md); }
.service-card img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.6s var(--ease);
}
.service-card:hover img { transform: scale(1.06); }
.service-card__face {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    padding: 22px;
    background: linear-gradient(to top, rgba(10,12,16,0.8) 0%, rgba(10,12,16,0.25) 45%, transparent 65%);
    color: var(--white);
    font-family: var(--font-display);
    font-weight: 600;
    letter-spacing: -0.01em;
    font-size: 19px;
    transition: opacity 0.35s var(--ease);
}
.service-card__back {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 28px;
    background: linear-gradient(160deg, rgba(17,19,24,0.96) 0%, rgba(17,19,24,0.86) 100%);
    color: var(--white);
    opacity: 0;
    transition: opacity 0.35s var(--ease);
}
.service-card:hover .service-card__face,
.service-card.is-flipped .service-card__face { opacity: 0; }
.service-card:hover .service-card__back,
.service-card.is-flipped .service-card__back { opacity: 1; }
.service-card__back h3 {
    font-size: 22px;
    font-weight: 700;
    margin-bottom: 10px;
}
.service-card__back p { font-size: 14.5px; line-height: 1.55; opacity: 0.94; }
.service-card__arrow {
    width: 38px;
    height: 38px;
    border-radius: 0;
    background: var(--accent);
    color: var(--white);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    box-shadow: var(--shadow-sm);
    transition: transform 0.35s var(--ease);
}
.service-card:hover .service-card__arrow { transform: translateX(3px); }
.service-card__back .service-card__arrow { background: var(--accent); box-shadow: none; }
.service-card__cta {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    align-self: flex-start;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 15px;
    color: var(--white);
}

/* ===== ABOUT / BEFORE-AFTER ===== */
.about { padding: 130px 0 110px; background: var(--bg); }
/* stretch, not center: the photo column matches the height of the text beside it so the two halves
   of the section square off instead of the image floating in the middle of a taller column. */
.about__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 64px; align-items: stretch; }
.about__content { display: flex; flex-direction: column; }
.about__content h2 { font-size: clamp(30px, 3.8vw, 46px); margin-bottom: 18px; color: var(--text); text-wrap: balance; }
.about__content p { color: var(--muted); font-size: 16.5px; margin-bottom: 30px; }
.about__content p strong { color: var(--text); }
/* Side by side, always. At full width these two labels total just over the half-column they sit in,
   so the default flex-wrap dropped the second button onto its own line. Equal flex shares with
   tighter padding keeps them on one row without shortening the copy. */
.about__content .intro__actions { margin-top: auto; flex-wrap: nowrap; }
.about__content .intro__actions .btn {
    flex: 1 1 0;
    min-width: 0;
    justify-content: center;
    padding-left: 18px;
    padding-right: 18px;
    white-space: nowrap;
}
.about__media { display: flex; }

/* Stats as one quiet inline strip divided by hairlines - no boxes. Smaller and calmer than four
   cards, which competed with the before/after image next to them. */
.about__stats {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 0;
    margin-bottom: 32px;
    padding: 18px 0;
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
}
.about-stat {
    /* min-width:0 so four stats stay on ONE line in a half-width column - the labels wrap inside
       their own cell instead of pushing a stat onto an orphan second row. */
    flex: 1 1 0;
    min-width: 0;
    padding: 2px 14px;
    border-left: 1px solid var(--border);
    display: flex;
    flex-direction: column;
}
.about-stat:first-child { border-left: 0; padding-left: 0; }
.about-stat__value {
    display: block;
    font-family: var(--font-sans);
    font-weight: 800;
    letter-spacing: -0.02em;
    /* Every stat renders at exactly this size and line box, so "12+", "347+" and "4.9*" read as one
       set rather than three differently-weighted numbers. */
    font-size: 22px;
    color: var(--text);
    line-height: 1.2;
    height: 1.2em;
    margin-bottom: 6px;
}
.about-stat__label {
    color: var(--muted);
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    line-height: 1.3;
    /* Two lines reserved whether the label needs them or not - otherwise "GOOGLE RATING" sits on one
       line beside two-line neighbours and the strip reads ragged. */
    min-height: 2.6em;
}

.ba-slider {
    position: relative;
    width: 100%;
    /* Fills the column so it matches the text height (see .about__grid); the ratio is the floor for
       pages where it isn't in a two-column grid. */
    flex: 1;
    min-height: 100%;
    aspect-ratio: 4/3;
    border-radius: var(--radius);
    overflow: hidden;
    cursor: ew-resize;
    user-select: none;
    box-shadow: var(--shadow-lg);
}
.ba-slider img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.ba-slider__before { z-index: 1; }
.ba-slider__after { z-index: 2; clip-path: inset(0 50% 0 0); }
.ba-slider__handle {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 50%;
    width: 2px;
    background: var(--white);
    box-shadow: 0 0 12px rgba(0,0,0,0.35);
    z-index: 3;
    transform: translateX(-50%);
}
.ba-slider__knob {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 50px;
    height: 50px;
    border-radius: 50%;
    background: var(--white);
    border: 2px solid rgba(16,20,28,0.06);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--accent);
    box-shadow: var(--shadow-md);
    transition: transform 0.25s var(--ease);
}
.ba-slider:active .ba-slider__knob { transform: translate(-50%, -50%) scale(1.08); }
.ba-slider__label {
    position: absolute;
    top: 18px;
    z-index: 3;
    background: rgba(20,22,26,0.72);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    color: var(--white);
    font-family: var(--font-body);
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    padding: 7px 16px;
    border-radius: 0;
}
.ba-slider__label--before { right: 18px; }
.ba-slider__label--after { left: 18px; }

/* ===== WHY CHOOSE US ===== */
.why { padding: 110px 0; background: var(--dark); }
.why .section-header h2 { color: var(--white); }
.why .section-header p { color: rgba(255,255,255,0.65); }
.why__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.why-card {
    text-align: center;
    background: var(--dark-card);
    border: 1px solid rgba(255,255,255,0.07);
    border-radius: var(--radius);
    padding: 34px 28px;
    transition: var(--transition);
}
.why-card:hover { transform: translateY(-5px); border-color: rgba(255,255,255,0.14); }
.why-icon {
    width: 60px;
    height: 60px;
    border-radius: 0;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.1);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--accent);
    font-size: 26px;
    margin: 0 auto 18px;
}
.why-card h3 {
    color: var(--white);
    font-size: 19px;
    font-weight: 700;
    margin-bottom: 10px;
}
.why-card p { color: rgba(255,255,255,0.62); font-size: 15px; }

/* ===== PROJECTS CAROUSEL (home) ===== */
.projects__track-wrap { overflow: hidden; padding: 8px 4px 20px; margin: -8px -4px -8px; }
.projects__track { display: flex; gap: 26px; transition: transform 0.55s var(--ease); }
.projects__track .project-card { flex: 0 0 calc(33.333% - 17.34px); }
.projects__dots { display: flex; justify-content: center; gap: 8px; margin-top: 28px; }
.projects__dots:empty { display: none; }
.projects__dot { width: 8px; height: 8px; background: rgba(16,20,28,0.16); transition: var(--transition); }
.projects__dot.is-active { background: var(--accent); width: 24px; }

/* ===== PROJECTS GALLERY ===== */
.projects { padding: 110px 0; background: var(--bg-alt); }
.projects__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; }
.project-card {
    position: relative;
    border-radius: var(--radius);
    overflow: hidden;
    aspect-ratio: 4/3;
    box-shadow: var(--shadow-sm);
    transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.project-card:hover { transform: translateY(-6px); box-shadow: var(--shadow-md); }
.project-card img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
.project-card:hover img { transform: scale(1.07); }
.project-card__overlay {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(10,12,16,0.85) 0%, rgba(10,12,16,0.2) 45%, transparent 62%);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 24px;
}
.project-card__overlay h3 {
    color: var(--white);
    font-size: 20px;
    font-weight: 700;
    margin-bottom: 4px;
    transform: translateY(0);
    transition: transform 0.4s var(--ease);
}
.project-card:hover .project-card__overlay h3 { transform: translateY(-2px); }
.project-card__overlay span { color: rgba(255,255,255,0.75); font-size: 13.5px; }

/* ===== PROCESS ===== */
.process { padding: 110px 0; background: var(--bg-alt); }
/* Wider than the default 680px header so the trade name doesn't push the headline to three lines. */
.process .section-header { max-width: 860px; }
/* auto-fit, so a four-step trade and a six-step one both lay out on one clean line rather than
   leaving an orphan card on a second row. */
.process__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 26px; }
.process-step {
    position: relative;
    padding: 26px 20px 22px 0;
    /* A rule across the top of each step reads as one continuous track through the sequence -
       lighter and more "steps" than four separate boxes. */
    border-top: 2px solid var(--border);
    transition: border-color 0.35s var(--ease);
}
.process-step:hover { border-top-color: var(--accent); }

/* ---- Four-step connected-track variant (home page) ----------------------------------------- */
/* No cards. One rule runs behind the whole row and each step's icon sits ON it, so the four read as
   one sequence rather than four separate boxes. The line is a pseudo-element on the grid (not a
   per-step border) so the grid gaps don't chop it into segments. */
.process__grid--simple {
    position: relative;
    --step-gap: 34px;
    --step-icon: 68px;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--step-gap);
}
.process__grid--simple::before {
    content: '';
    position: absolute;
    /* Sits on the icons' centre line. It starts at the first icon (which is flush with the
       container's left edge) and stops at the centre of the LAST icon - one column width minus half
       an icon - rather than dangling off to the right of the final step. */
    top: calc(var(--step-icon) / 2);
    left: 0;
    right: calc((100% - 3 * var(--step-gap)) / 4 - var(--step-icon) / 2);
    height: 2px;
    background: var(--border);
}
.process-step--line {
    position: relative;
    border-top: 0;
    padding: 0;
    text-align: left;
}
/* Icon disc - stroke inherits currentColor, so it re-tints with the client's accent automatically.
   Opaque fill (the same tone --accent-soft resolves to over this section) so it masks the track
   running behind it instead of letting the line cut through the icon. */
.process-step__icon {
    position: relative;
    width: var(--step-icon, 68px);
    height: var(--step-icon, 68px);
    border-radius: 50%;
    background: color-mix(in srgb, var(--accent) 9%, var(--bg-alt));
    color: var(--accent);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 22px;
    box-shadow: 0 0 0 6px var(--bg-alt);
    transition: background-color 0.35s var(--ease), color 0.35s var(--ease);
}
.process-step__icon svg { width: 32px; height: 32px; }
.process-step--line:hover .process-step__icon { background: var(--accent); color: var(--on-accent); }
.process-step--line .process-step__num { font-size: 26px; margin-bottom: 8px; }
.process-step--line h3 { font-size: 18.5px; margin-bottom: 8px; }
.process-step--line p { font-size: 15px; line-height: 1.65; }

@media (max-width: 1024px) {
    .process__grid--simple { grid-template-columns: repeat(2, 1fr); gap: 40px 34px; }
    /* Two rows means only the first would sit on the track - drop it rather than half-draw it. */
    .process__grid--simple::before { display: none; }
}
@media (max-width: 640px) { .process__grid--simple { grid-template-columns: 1fr; } }
.process-step__num {
    font-family: var(--font-display);
    font-weight: 800;
    letter-spacing: -0.02em;
    font-size: 30px;
    line-height: 1;
    color: var(--accent);
    margin-bottom: 12px;
}
.process-step h3 {
    font-size: 19px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 8px;
}
.process-step p { color: var(--muted); font-size: 15px; }

/* ===== REVIEWS ===== */
.reviews { padding: 110px 0; background: var(--dark-alt); overflow: hidden; }
.reviews__track-wrap { overflow: hidden; padding: 8px 4px 24px; margin: -8px -4px -8px; }
.reviews__track { display: flex; gap: 28px; transition: transform 0.55s var(--ease); }
.review-card {
    flex: 0 0 calc(33.333% - 19px);
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 28px;
    position: relative;
    box-shadow: var(--shadow-xs);
    transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.review-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-sm); }
.review-card__google { position: absolute; top: 26px; right: 26px; }
.review-card__head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.review-card__avatar {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: linear-gradient(150deg, var(--accent) 0%, var(--accent-dark) 100%);
    color: var(--white);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-display);
    font-weight: 700;
    flex-shrink: 0;
}
.review-card__name { font-weight: 600; font-size: 15px; }
.review-card__sub { color: var(--muted); font-size: 13px; }
.review-card__rating { margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }
.stars { color: #FBBC05; letter-spacing: 2px; }
.review-text { color: var(--muted); font-size: 15px; line-height: 1.65; }
.review-card.is-expanded .review-text { -webkit-line-clamp: unset; }
.review-text {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.review-card__more { color: var(--accent); font-weight: 600; font-size: 13.5px; margin-top: 10px; }
.review-card__more:hover { color: var(--accent-dark); }
.reviews__dots { display: none; justify-content: center; gap: 8px; margin-top: 32px; }
.reviews__dot { width: 8px; height: 8px; background: rgba(16,20,28,0.16); transition: var(--transition); }
.reviews__dot.is-active { background: var(--accent); width: 24px; }

/* Reviews on dark: cards, text, dots, and link recolored for the dark section.
   Scoped to .reviews (home) so the light .reviews-page grid is unaffected. */
.reviews .section-header h2 { color: var(--white); }
.reviews .review-card { background: var(--dark-card); border-color: rgba(255,255,255,0.08); box-shadow: none; }
.reviews .review-card:hover { border-color: rgba(255,255,255,0.16); box-shadow: none; }
.reviews .review-card__name { color: var(--white); }
.reviews .review-card__sub { color: rgba(255,255,255,0.55); }
.reviews .review-text { color: rgba(255,255,255,0.72); }
.reviews .review-card__more { color: var(--accent-on-dark); }
.reviews .review-card__more:hover { color: var(--white); }
.reviews .reviews__dot { background: rgba(255,255,255,0.25); }
.reviews .reviews__dot.is-active { background: var(--accent-on-dark); }

/* ===== RESOURCES ===== */
/* ===== FAQ ===== */
.faq { position: relative; padding: 120px 0 110px; background: var(--dark-alt); }
/* The diagonal lead-in this section used to draw was removed with the rest of the section
   wedges - see the surfaces note. Edges are square; the hero owns the only angle. */
.faq .section-header h2 { color: var(--white); }
.faq .section-header p { color: rgba(255,255,255,0.65); }
.faq__list { max-width: 780px; margin: 0 auto; display: flex; flex-direction: column; gap: 12px; }
.faq-item {
    background: var(--dark-card);
    border: 1px solid rgba(255,255,255,0.07);
    border-radius: var(--radius-sm);
    overflow: hidden;
    transition: border-color 0.3s var(--ease);
}
.faq-item.is-open { border-color: rgba(255,255,255,0.16); }
.faq-q {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 24px;
    text-align: left;
    color: var(--white);
    font-weight: 500;
    font-size: 16.5px;
    transition: color 0.3s var(--ease);
}
.faq-q:hover { color: rgba(255,255,255,0.85); }
.faq-q__icon {
    width: 30px;
    height: 30px;
    border-radius: 0;
    border: 1px solid rgba(255,255,255,0.18);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--accent-on-dark);
    font-size: 18px;
    line-height: 1;
    flex-shrink: 0;
    margin-left: 16px;
    transition: transform 0.35s var(--ease), background-color 0.35s var(--ease), color 0.35s var(--ease);
}
.faq-item.is-open .faq-q__icon { transform: rotate(45deg); background: var(--accent); color: var(--white); border-color: transparent; }
.faq-a { max-height: 0; overflow: hidden; transition: max-height 0.4s var(--ease); }
.faq-a p { color: rgba(255,255,255,0.62); padding: 0 24px 22px; font-size: 15px; }

/* ===== SERVICE AREAS ===== */
.areas { padding: 90px 0; background: var(--bg); }
.areas__grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
.area-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 20px;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 0;
    font-weight: 500;
    font-size: 14.5px;
    color: var(--text);
    box-shadow: var(--shadow-xs);
    transition: var(--transition);
}
.area-pill:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); border-color: var(--accent-line); }
.area-pill [data-lucide],
.area-pill svg.lucide { color: var(--accent); font-size: 15px; }
.areas__map {
    margin-top: 40px;
    border-radius: var(--radius);
    overflow: hidden;
    border: 1px solid var(--border);
    box-shadow: var(--shadow-md);
}
.areas__map iframe { width: 100%; height: 100%; min-height: 460px; border: none; display: block; filter: saturate(0.9); }

/* Map + "how to reach us" side by side, the pair centered under a centered header. The map takes
   the larger share - it is the thing people actually scan for their own town. */
.areas__panel {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(300px, 1fr);
    gap: 28px;
    align-items: stretch;
    margin-top: 40px;
}
.areas__panel .areas__map { margin: 0; height: 100%; }
.areas__contact {
    background: var(--bg-alt);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 32px 30px;
    display: flex;
    flex-direction: column;
    text-align: left;
}
.areas__contact h3 { font-size: 23px; font-weight: 700; margin-bottom: 8px; }
.areas__contact > p { color: var(--muted); font-size: 15px; margin-bottom: 22px; }
.areas__contact-list { list-style: none; display: flex; flex-direction: column; gap: 16px; margin-bottom: 26px; }
.areas__contact-list li { display: flex; align-items: flex-start; gap: 12px; font-size: 15.5px; color: var(--text); }
.areas__contact-icon {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--accent-soft);
    color: var(--accent);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 17px;
}
.areas__contact-label {
    display: block;
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--muted);
    margin-bottom: 1px;
}
.areas__contact-list a { color: var(--text); font-weight: 600; }
.areas__contact-list a:hover { color: var(--accent); }
.areas__contact-actions { display: flex; flex-direction: column; gap: 10px; margin-top: auto; }
.areas__contact-actions .btn { width: 100%; }

@media (max-width: 900px) {
    .areas__panel { grid-template-columns: 1fr; }
    .areas__map iframe { min-height: 340px; }
}

/* ===== SCENIC CTA ===== */
.final-cta {
    position: relative;
    padding: 120px 0;
    background: var(--dark);
    overflow: hidden;
}
.final-cta__bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.final-cta__overlay {
    position: absolute;
    inset: 0;
    background: linear-gradient(105deg, rgba(16,18,23,0.9) 0%, rgba(16,18,23,0.68) 52%, rgba(16,18,23,0.82) 100%);
}
.final-cta .container { position: relative; z-index: 1; }
.final-cta__grid {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(340px, 0.55fr);
    gap: 56px;
    align-items: center;
}
.final-cta__copy { text-align: left; }
.final-cta h2 { color: var(--white); font-weight: 800; font-size: clamp(32px, 4.5vw, 56px); letter-spacing: -0.025em; margin-bottom: 16px; }
.final-cta p { color: rgba(255,255,255,0.88); font-size: 17px; margin-bottom: 30px; max-width: 540px; }
.contact-form {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: 30px;
    display: grid;
    gap: 16px;
}
.contact-form label { display: grid; gap: 7px; }
/* `label span` and not `span`: this is the field-label treatment, and as a bare descendant selector
   it also hit the <span class="hl"> inside the form's own heading - which is why the highlighted
   word rendered at 11.5px in the middle of a 26px title. */
.contact-form label span {
    color: var(--muted);
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
}
.contact-form input,
.contact-form textarea {
    width: 100%;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 13px 15px;
    font: inherit;
    font-size: 15px;
    background: var(--white);
    color: var(--text);
    transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease), background-color 0.25s var(--ease);
}
.contact-form textarea { resize: vertical; min-height: 116px; }
.contact-form input:focus,
.contact-form textarea:focus {
    border-color: var(--accent);
    background: var(--white);
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-ring);
}

/* ===== FOOTER ===== */
.footer { background: var(--dark); padding: 76px 0 0; }
.footer__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 44px; padding-bottom: 54px; }
.footer__col { display: flex; flex-direction: column; gap: 10px; }
.footer__col h4 {
    color: var(--white);
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 12.5px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    margin-bottom: 8px;
}
.footer__col a { color: rgba(255,255,255,0.62); font-size: 14.5px; }
.footer__col a:hover { color: var(--white); padding-left: 3px; }
.footer__col ul { display: flex; flex-direction: column; gap: 10px; }
/* Closes the truncated services list - see FOOTER_SERVICE_CAP in the generator. */
.footer__col a.footer__all-services { color: var(--accent-on-dark); font-weight: 600; }
.footer__col a.footer__all-services:hover { color: var(--white); }
/* Footer logo: mirrors the nav - client logo image when present, otherwise an
   initial badge + company name text (fallback driven by onerror in the markup). */
.footer__logo {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.01em;
    font-size: 24px;
    color: var(--white);
    margin-bottom: 12px;
}
.footer__logo:hover { opacity: 0.85; }
.footer__logo-badge {
    /* Deliberately larger than the nav badge: the footer has the room, and the mark is the last
       thing on the page - it should read as a sign-off, not a repeat of the header at half size. */
    height: 78px;
    max-width: 280px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.footer__logo-badge img { height: 100%; width: auto; max-width: 100%; object-fit: contain; }
.footer__logo-badge > span {
    width: 62px;
    height: 62px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 24px;
    color: var(--accent);
    background: rgba(255,255,255,0.1);
}
.footer__logo.has-image-logo .footer__logo-text { display: none; }
.footer__logo-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.footer__tagline { color: rgba(255,255,255,0.55); font-size: 14.5px; max-width: 300px; }
.footer__note { color: rgba(255,255,255,0.55); font-size: 14.5px; padding: 4px 0; }
.footer__bottom { border-top: 1px solid rgba(255,255,255,0.08); padding: 24px 0; }
.footer__bottom-inner { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px 24px; color: rgba(255,255,255,0.45); font-size: 13.5px; }
.footer__powered a { color: rgba(255,255,255,0.7); font-weight: 600; }
.footer__powered a:hover { color: var(--white); }


/* =====================================================================
   INTERIOR PAGES (page-hero, hubs, detail pages, contact, CTA band)
   ===================================================================== */

/* ===== SECTION "VIEW MORE" ROW ===== */
.section-more { display: flex; justify-content: center; margin-top: 48px; }
.section-more--left { justify-content: flex-start; margin-top: 28px; }
.services__header-link { flex-shrink: 0; }

/* ===== PAGE HERO (interior pages) ===== */
.page-hero {
    position: relative;
    display: flex;
    align-items: center;
    min-height: 440px;
    padding: 170px 0 100px;
    background: var(--dark);
}
.page-hero__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.page-hero__overlay { position: absolute; inset: 0; background: var(--hero-overlay); }
.page-hero__content {
    position: relative;
    z-index: 2;
    max-width: 800px;
    margin: 0 auto;
    text-align: center;
}
.page-hero__content h1 {
    color: var(--white);
    font-weight: 800;
    font-size: clamp(34px, 5vw, 58px);
    letter-spacing: -0.025em;
    margin-bottom: 16px;
    text-wrap: balance;
}
.page-hero__content p {
    color: rgba(255,255,255,0.88);
    font-size: clamp(16px, 1.8vw, 18px);
    max-width: 620px;
    margin: 0 auto;
}
.page-hero__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; margin-top: 30px; }

/* ===== CTA BAND (dark strip used on interior pages) ===== */
.cta-band { background: var(--dark-alt); padding: 90px 0; }
.cta-band__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 40px;
    flex-wrap: wrap;
}
.cta-band h2 { color: var(--white); font-weight: 800; font-size: clamp(28px, 3.6vw, 44px); letter-spacing: -0.02em; margin-bottom: 10px; }
.cta-band p { color: rgba(255,255,255,0.65); font-size: 16.5px; max-width: 520px; }
.cta-band__actions { display: flex; flex-wrap: wrap; gap: 14px; flex-shrink: 0; }

/* ===== CHECK LIST (about / area pages) ===== */
.check-list { display: grid; gap: 12px; margin-bottom: 32px; }
.check-list li { display: flex; align-items: center; gap: 12px; font-weight: 500; font-size: 15.5px; }
.check-list [data-lucide], .check-list svg.lucide {
    color: var(--accent);
    background: var(--accent-soft);
    border-radius: 0;
    padding: 4px;
    width: 24px;
    height: 24px;
}

/* ===== OWNER BIO (about page) ===== */
.owner-bio { padding: 120px 0 110px; background: var(--bg); }
.owner-bio__grid {
    display: grid;
    grid-template-columns: minmax(280px, 0.72fr) 1.28fr;
    gap: 64px;
    align-items: center;
}
.owner-bio__media { border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-md); aspect-ratio: 4/5; }
.owner-bio__media img { width: 100%; height: 100%; object-fit: cover; }
.owner-bio__content h2 { font-size: clamp(30px, 3.8vw, 46px); margin-bottom: 18px; }
.owner-bio__content p { color: var(--muted); font-size: 16.5px; margin-bottom: 30px; }

/* ===== CREDENTIALS ===== */
.credentials { padding: 0 0 40px; background: var(--bg); }
.credentials__list { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
.credentials__list--left { justify-content: flex-start; margin-bottom: 28px; }
.credential-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 20px;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 0;
    font-weight: 500;
    font-size: 14px;
    color: var(--text);
    box-shadow: var(--shadow-xs);
}
.credential-badge [data-lucide], .credential-badge svg.lucide { color: var(--accent); font-size: 16px; }

/* ===== ACCEPTED PAYMENTS ===== */
.payments { padding: 40px 0; background: var(--bg-alt); border-top: 1px solid var(--border); }
.payments__inner {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 14px 26px;
}
.payments__label {
    font-family: var(--font-display);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-size: 12px;
    color: var(--muted);
}
.payments__list { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px; }
.payment-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 0;
    font-weight: 500;
    font-size: 13.5px;
    color: var(--text);
    box-shadow: var(--shadow-xs);
}
/* ===== PROMO POPUP ===== */
.promo-popup { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; padding: 20px; }
.promo-popup[hidden] { display: none; }
.promo-popup__backdrop { position: absolute; inset: 0; background: rgba(10,12,16,0.55); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); opacity: 0; transition: opacity 0.3s var(--ease); }
.promo-popup.is-open .promo-popup__backdrop { opacity: 1; }
.promo-popup__card {
    position: relative;
    z-index: 1;
    background: var(--white);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
    max-width: 420px;
    width: 100%;
    padding: 40px 34px 34px;
    text-align: center;
    transform: translateY(16px) scale(0.98);
    opacity: 0;
    transition: transform 0.32s var(--ease), opacity 0.32s var(--ease);
}
.promo-popup.is-open .promo-popup__card { transform: none; opacity: 1; }
.promo-popup__close {
    position: absolute; top: 12px; right: 12px;
    width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
    color: var(--muted); background: none; border: none; cursor: pointer;
}
.promo-popup__close:hover { color: var(--dark); }
.promo-popup__eyebrow { display: inline-block; font-family: var(--font-display); font-weight: 700; text-transform: uppercase; letter-spacing: 0.14em; font-size: 12px; color: var(--accent); margin-bottom: 12px; }
.promo-popup__title { font-family: var(--font-display); font-size: clamp(24px, 5vw, 30px); line-height: 1.1; margin-bottom: 12px; }
.promo-popup__message { color: var(--muted); font-size: 15px; line-height: 1.6; margin-bottom: 22px; }

.form-success {
    padding: 28px 24px;
    text-align: center;
    background: var(--bg-alt);
    border: 1px solid var(--border);
    color: var(--text);
    font-size: 15px;
    line-height: 1.6;
}
.form-success strong { font-family: var(--font-display); font-size: 18px; }

.payment-badge__icon { display: inline-flex; width: 22px; height: 22px; flex-shrink: 0; }
.payment-badge__icon svg { width: 100%; height: 100%; display: block; }

/* ===== SERVICES HUB ===== */
.svc-hub { padding: 130px 0 110px; background: var(--bg); }
.svc-hub__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; }
.svc-card {
    display: flex;
    flex-direction: column;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    color: var(--text);
    box-shadow: var(--shadow-xs);
    transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease), border-color 0.4s var(--ease);
}
.svc-card:hover { transform: translateY(-6px); box-shadow: var(--shadow-md); border-color: transparent; }
.svc-card__media { aspect-ratio: 16/10; overflow: hidden; }
.svc-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
.svc-card:hover .svc-card__media img { transform: scale(1.06); }
.svc-card__content { padding: 26px 28px 28px; display: flex; flex-direction: column; flex: 1; }
.svc-card__content h3 { font-size: 21px; font-weight: 700; margin-bottom: 8px; }
.svc-card__content p { color: var(--muted); font-size: 14.5px; line-height: 1.65; margin-bottom: 20px; }
.svc-card__link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: auto;
    color: var(--accent);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 15px;
    transition: gap 0.3s var(--ease);
}
.svc-card:hover .svc-card__link { gap: 12px; }

/* ===== WHAT'S INCLUDED (service detail) ===== */
.whats-included { padding: 120px 0 110px; background: var(--bg); }
.whats-included__list {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 14px;
    max-width: 880px;
    margin: 0 auto;
}
.whats-included__item {
    display: flex;
    align-items: center;
    gap: 14px;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 18px 22px;
    font-weight: 500;
    font-size: 15.5px;
    box-shadow: var(--shadow-xs);
    transition: var(--transition);
}
.whats-included__item:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.whats-included__check {
    width: 30px;
    height: 30px;
    border-radius: 0;
    background: var(--accent-soft);
    color: var(--accent);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    flex-shrink: 0;
}

/* ===== DETAIL BEFORE/AFTER ===== */
/* ===== SERVICE INTRO (copy left, framed photo right) ===== */
.service-intro { padding: 100px 0; background: var(--bg-alt); }
.service-intro__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 64px;
    align-items: center;
}
.service-intro__content h2 {
    font-size: clamp(28px, 3.6vw, 44px);
    line-height: 1.12;
    margin-top: 4px;
}
.service-intro__rule {
    display: block;
    width: 64px;
    height: 3px;
    background: var(--accent);
    margin: 22px 0 26px;
}
.service-intro__content p { color: var(--muted); font-size: 16.5px; margin-bottom: 20px; }
.service-intro__content p:last-of-type { margin-bottom: 30px; }
.service-intro__media img {
    width: 100%;
    aspect-ratio: 4/3;
    object-fit: cover;
    box-shadow: var(--shadow-md);
}

.detail-ba { padding: 110px 0; background: var(--bg); }
.detail-ba__grid { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 64px; align-items: center; }
.detail-ba__content h2 { font-size: clamp(28px, 3.6vw, 42px); margin-bottom: 16px; }
.detail-ba__content p { color: var(--muted); font-size: 16.5px; margin-bottom: 28px; }

/* ===== LEAD FORM (detail + contact pages) ===== */
.detail-form { padding: 110px 0; background: var(--bg-alt); }
.detail-form__inner { max-width: 680px; }
.lead-form {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    padding: 34px;
    display: grid;
    gap: 16px;
}
.lead-form label { display: grid; gap: 7px; }
.lead-form label > span {
    color: var(--muted);
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
}
.lead-form input,
.lead-form select,
.lead-form textarea {
    width: 100%;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 13px 15px;
    font: inherit;
    font-size: 15px;
    background: var(--white);
    color: var(--text);
    transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease), background-color 0.25s var(--ease);
}
.lead-form textarea { resize: vertical; min-height: 110px; }
.lead-form select {
    appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%235F6672' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 15px center;
    padding-right: 42px;
}
.lead-form input:focus,
.lead-form select:focus,
.lead-form textarea:focus {
    border-color: var(--accent);
    background: var(--white);
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.lead-form input[readonly] { color: var(--muted); }

/* ===== LOCAL INTRO (area detail) ===== */
.local-intro { padding: 120px 0 40px; background: var(--bg); }
.local-intro .section-header { margin-bottom: 0; max-width: 780px; }

/* ===== WHY CHOOSE US (area detail) ===== */
.why-local { padding: 90px 0 110px; background: var(--bg); }
.why-local__grid { display: grid; grid-template-columns: 0.95fr 1.05fr; gap: 64px; align-items: center; }
.why-local__media { position: relative; }
.why-local__media > img {
    width: 100%;
    aspect-ratio: 4/3;
    object-fit: cover;
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
}
.why-local__badge {
    position: absolute;
    bottom: -24px;
    right: -18px;
    background: var(--accent);
    color: var(--on-accent);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: 20px 26px;
    text-align: center;
}
.why-local__badge-num {
    display: block;
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 34px;
    line-height: 1.1;
    letter-spacing: -0.02em;
}
.why-local__badge-label {
    display: block;
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    opacity: 0.9;
}
.why-local__content h2 { font-size: clamp(28px, 3.6vw, 42px); margin-bottom: 16px; }
.why-local__content > p { color: var(--muted); font-size: 16.5px; margin-bottom: 28px; }

/* ===== AREAS HUB ===== */
.areas-hub { padding: 130px 0 110px; background: var(--bg); }
.areas-hub__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 16px;
    margin-bottom: 56px;
}
.area-hub-card {
    display: flex;
    align-items: center;
    gap: 14px;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 18px 20px;
    color: var(--text);
    font-weight: 600;
    font-size: 15.5px;
    box-shadow: var(--shadow-xs);
    transition: var(--transition);
}
.area-hub-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-sm); border-color: var(--accent-line); }
.area-hub-card__city { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.area-hub-card__arrow { color: var(--muted); transition: var(--transition); }
.area-hub-card:hover .area-hub-card__arrow { color: var(--accent); transform: translateX(3px); }

/* Onyx uses short town names here; five compact columns keep a five-town list on one balanced row
   instead of stretching four cards wide and leaving one oversized orphan underneath. */
.onyx .areas-hub__grid {
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 12px;
}
.onyx .area-hub-card { gap: 10px; padding: 14px 16px; }

/* ===== PROJECTS HUB ===== */
.projects-hub { padding: 120px 0 110px; background: var(--bg); }
.project-filters { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-bottom: 44px; }
.project-filter {
    padding: 10px 22px;
    border-radius: 0;
    border: 1px solid var(--border);
    background: var(--white);
    color: var(--muted);
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 14px;
    box-shadow: var(--shadow-xs);
    transition: var(--transition);
}
.project-filter:hover { color: var(--text); border-color: var(--accent-line); transform: translateY(-1px); }
.project-filter.is-active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
    box-shadow: 0 6px 18px var(--accent-glow);
}
.project-card.is-filtered-out { display: none; }

/* ===== REVIEWS PAGE ===== */
.reviews-page { padding: 60px 0 110px; background: var(--bg); }
.reviews-page__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; }
.review-card__service {
    display: inline-block;
    margin-top: 4px;
    padding: 3px 10px;
    border-radius: 0;
    background: var(--accent-soft);
    color: var(--accent);
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.review-card__service:empty { display: none; }

/* ===== CONTACT PAGE ===== */
.contact-section { padding: 120px 0 110px; background: var(--bg); }
.contact-grid { display: grid; grid-template-columns: 1fr 1.05fr; gap: 64px; align-items: start; }
.contact-info h2 { font-size: clamp(28px, 3.6vw, 42px); margin-bottom: 14px; }
.contact-info__lede { color: var(--muted); font-size: 16.5px; margin-bottom: 32px; }
.contact-info__rows { display: grid; gap: 14px; }
.contact-info__row {
    display: flex;
    align-items: center;
    gap: 16px;
    background: var(--bg-alt);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 16px 20px;
    color: var(--text);
    transition: var(--transition);
}
a.contact-info__row:hover { background: var(--white); box-shadow: var(--shadow-sm); transform: translateY(-2px); border-color: var(--accent-line); }
.contact-info__icon {
    width: 44px;
    height: 44px;
    border-radius: 0;
    background: var(--accent-soft);
    color: var(--accent);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    flex-shrink: 0;
}
.contact-info__row-label {
    display: block;
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
}
.contact-info__row-value { display: block; font-weight: 600; font-size: 15.5px; overflow-wrap: anywhere; }
.areas--contact { padding-top: 0; }

/* ===== FAQ PAGE VARIANT (light page-flow spacing) ===== */
.faq--page { padding-top: 130px; }

/* ===== NAV: MOBILE SUBMENUS + PHONE ===== */
.nav__mobile-parent { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.nav__mobile-parent svg { transition: transform 0.3s var(--ease); }
.nav__mobile-sub {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.4s var(--ease);
    margin: 0 !important;
}
.nav__mobile-sub.is-open { max-height: 600px; }
.nav__mobile li:has(.nav__mobile-sub.is-open) .nav__mobile-parent svg { transform: rotate(180deg); }
.nav__mobile-sub li a {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 15.5px !important;
    color: var(--muted);
    padding: 12px 4px 12px 18px !important;
    border-bottom: none !important;
}
.nav__mobile-sub li:last-child a { border-bottom: none; }
.nav__mobile-phone {
    display: block;
    text-align: center;
    margin-top: 14px;
    color: var(--muted);
    font-weight: 500;
    font-size: 14.5px;
}
.nav__mobile-phone:hover { color: var(--text); }
/* Only in the small text dropdown, where it separates "All Services" from the list above it. In the
   mega sheet the link is a card of its own and a rule would cut across the grid. */
.dropdown:not(.is-mega) .dropdown__all { font-weight: 600; border-top: 1px solid var(--border); }
/* ===== RESPONSIVE ===== */
@media (max-width: 1024px) {
    .services__grid, .why__grid, .projects__grid, .process__grid,
    .svc-hub__grid, .reviews-page__grid, .whats-included__list { grid-template-columns: repeat(2, 1fr); }
    .final-cta__grid { grid-template-columns: 1fr; }
    .projects__track .project-card { flex-basis: calc(50% - 13px); }
    .review-card { flex-basis: calc(50% - 14px); }
    .footer__grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 900px) {
    .nav__links, .nav__phone { display: none; }
    .owner-bio__grid, .detail-ba__grid, .why-local__grid, .contact-grid,
    .service-intro__grid { grid-template-columns: 1fr; gap: 44px; }
    .service-intro__media { order: -1; }
    .owner-bio__media { max-width: 420px; }
    .why-local__badge { right: 12px; bottom: -18px; }
    .cta-band__inner { flex-direction: column; align-items: flex-start; }
    .page-hero { padding: 150px 0 90px; min-height: 0; }
    .nav__toggle { display: flex; }
    /* Let the logo shrink so the CTA + hamburger never push off-screen */
    .nav__logo { flex-shrink: 1; min-width: 0; }
    .nav__logo-badge { max-width: 150px; }
    .nav__inner { gap: 12px; }
    .intro__grid, .about__grid { grid-template-columns: 1fr; }
    .about__media { order: -1; }
    .hero__inner { padding-top: 138px; padding-bottom: 138px; }
}

@media (max-width: 720px) {
    .container { padding: 0 20px; }
    .nav__inner { padding: 0 20px; }
    /* Small phones: the slide-in menu already carries the quote CTA */
    .nav__cta { display: none; }
    .services__grid, .why__grid, .projects__grid, .process__grid,
    .svc-hub__grid, .reviews-page__grid, .whats-included__list { grid-template-columns: 1fr; }
    .areas-hub__grid { grid-template-columns: 1fr 1fr; }
    .page-hero { padding: 140px 0 80px; }
    .page-hero__actions .btn { width: 100%; }
    .cta-band__actions { width: 100%; }
    .cta-band__actions .btn { width: 100%; }
    .lead-form { padding: 26px; }
    .detail-form, .contact-section, .svc-hub, .areas-hub, .projects-hub, .whats-included, .owner-bio { padding-top: 90px; padding-bottom: 90px; }
    /* Stats stay a compact 2x2 card on phones (not a tall single stack) */

    .review-card { flex-basis: 100%; }
    .reviews__dots { display: flex; }
    .footer__grid { grid-template-columns: 1fr; }
    /* Hero: tighter vertical rhythm, headline scales with the viewport, form full-width */
    .hero__inner { padding-top: 116px; padding-bottom: 108px; gap: 34px; }
    .hero__eyebrow { font-size: 12px; letter-spacing: 0.16em; margin-bottom: 12px; }
    .hero__headline { font-size: clamp(34px, 8.6vw, 46px); margin-bottom: 16px; }
    .hero__sub { font-size: 16px; margin-bottom: 28px; }
    .hero__social-proof { margin-bottom: 22px; }
    .projects__track .project-card { flex-basis: 100%; }
    .hero__actions, .intro__actions { flex-direction: column; }
    .hero__actions .btn, .intro__actions .btn { width: 100%; }
    .faq::before { top: -36px; height: 37px; }
    .final-cta { padding: 90px 0; }
    .contact-form { padding: 24px; }
}

/* ============================================================================
   PREMIUM POLISH LAYER - cinematic depth + micro-interactions.
   Additive, accent-driven (uses the per-site --accent vars), reduced-motion
   aware. Layered over the base so it enhances components without changing their
   structure or the generator's placeholder markup.
   ============================================================================ */

html { scroll-behavior: smooth; }

/* 1 · Scroll progress bar (element injected by main.js) --------------------- */
.scroll-progress {
    position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 200;
    background: transparent; pointer-events: none;
}
.scroll-progress > span {
    display: block; height: 100%; width: 0;
    background: linear-gradient(90deg, var(--accent), var(--accent-2, var(--accent)));
    box-shadow: 0 0 12px var(--accent-glow);
    transition: width 0.08s linear;
}

/* 2 · Hero Ken Burns - slow cinematic push-in ------------------------------ */
@keyframes heroKenBurns { from { transform: scale(1.03); } to { transform: scale(1.13); } }
.hero__bg { animation: heroKenBurns 22s ease-out both; will-change: transform; }

/* 3 · Aurora accent glow on the dark sections (depth) ---------------------- */
.services {
    position: relative;
    background:
        radial-gradient(1100px 540px at 84% -12%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 60%),
        var(--dark-alt);
}
.reviews {
    background:
        radial-gradient(1000px 520px at 12% 0%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 58%),
        var(--dark-alt);
}

/* 4 · Primary button shine sweep ------------------------------------------- */
.btn--primary { position: relative; overflow: hidden; }
.btn--primary::after {
    content: ""; position: absolute; top: 0; left: -125%; width: 55%; height: 100%;
    background: linear-gradient(100deg, transparent, rgba(255,255,255,0.30), transparent);
    transform: skewX(-18deg); transition: left 0.6s var(--ease); pointer-events: none;
}
.btn--primary:hover::after { left: 135%; }

/* 5 · Accent-tinted hover glow on cards ------------------------------------ */
.service-card:hover, .project-card:hover {
    box-shadow: 0 20px 46px -22px color-mix(in srgb, var(--accent) 55%, rgba(16,20,28,0.55));
}

/* 6 · Subtle parallax on the scenic closing image -------------------------- */
.final-cta__bg {
    transform: translate3d(0, var(--parallax, 0px), 0) scale(1.14);
    transition: transform 0.15s ease-out; will-change: transform;
}

/* 7 · Sticky mobile action bar (injected by main.js) ----------------------- */
.mobile-cta {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 150;
    display: none; gap: 10px; padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
    background: rgba(18, 20, 24, 0.92); backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px); border-top: 1px solid rgba(255,255,255,0.10);
    transform: translateY(110%); transition: transform 0.38s var(--ease);
}
.mobile-cta.is-visible { transform: translateY(0); }
.mobile-cta .btn { flex: 1; justify-content: center; padding: 13px 14px; }
@media (max-width: 768px) {
    .mobile-cta { display: flex; }
    body.has-mobile-cta { padding-bottom: 70px; }
}

/* Reduced motion: drop the cinematic movement, keep everything legible. */
@media (prefers-reduced-motion: reduce) {
    .hero__bg { animation: none; }
    .final-cta__bg { transform: scale(1.14); }
    html { scroll-behavior: auto; }
}

/* ===== FLOATING REVIEWS WIDGET ==============================================
   Bottom-left pill -> popup of review cards. Styled entirely from the tokens
   at the top of this file so any client palette re-themes it for free. */

.rw { font-family: var(--font-body); }

/* -- Pill ------------------------------------------------------------------ */
.rw-pill {
    position: fixed;
    left: 18px;
    bottom: 18px;
    z-index: 1200;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px 10px 12px;
    background: var(--white);
    border-radius: 999px;
    box-shadow: var(--shadow-md);
    border: 1px solid var(--border);
    text-align: left;
    transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.rw-pill:hover,
.rw-pill:focus-visible { transform: scale(1.045); box-shadow: var(--shadow-lg); }
/* On preview sites the claim bar owns the bottom edge - main.js adds this class to hop above it. */
.rw--raised .rw-pill { bottom: 86px; }

.rw-pill__logos { display: flex; align-items: center; }
.rw-pill__logo {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--white);
    border: 2px solid var(--white);
    box-shadow: 0 1px 4px rgba(16,20,28,0.18);
}
.rw-pill__logo svg { width: 16px; height: 16px; }
.rw-pill__logo + .rw-pill__logo { margin-left: -9px; }
.rw-pill__logo--fb { background: #1877F2; }
.rw-pill__logo--yelp { background: #FF1A1A; }

.rw-pill__body { display: grid; line-height: 1.25; }
.rw-pill__top { display: inline-flex; align-items: center; gap: 6px; font-size: 14.5px; color: var(--text); }
.rw-pill__meta { font-size: 11.5px; color: var(--muted); }

.rw-stars { display: inline-flex; gap: 1px; }
.rw-stars svg { width: 13px; height: 13px; }

/* Dismiss X - hidden until the pill is hovered, then fades in at its top-right corner. */
.rw-pill__x {
    position: absolute;
    top: -7px;
    right: -7px;
    display: grid;
    place-items: center;
    width: 21px;
    height: 21px;
    font-size: 11px;
    line-height: 1;
    color: var(--muted);
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 50%;
    box-shadow: var(--shadow-xs);
    opacity: 0;
    transition: opacity 0.2s var(--ease), color 0.2s var(--ease);
}
.rw-pill:hover .rw-pill__x,
.rw-pill__x:focus-visible { opacity: 1; }
.rw-pill__x:hover { color: var(--dark); }

/* -- Modal ----------------------------------------------------------------- */
.rw-modal { position: fixed; inset: 0; z-index: 1300; display: grid; place-items: center; padding: 24px; }
/* Explicit display beats the hidden attribute's UA display:none - restore it, or the closed
   modal's invisible backdrop sits over the page eating every click. Same for the root. */
.rw-modal[hidden], .rw[hidden] { display: none; }
.rw-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(9, 12, 16, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity 0.28s var(--ease);
}
.rw-modal__card {
    position: relative;
    width: min(720px, 100%);
    max-height: min(78vh, 720px);
    display: flex;
    flex-direction: column;
    background: var(--bg);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    transform: translateY(18px) scale(0.97);
    transition: opacity 0.28s var(--ease), transform 0.28s var(--ease);
}
.rw-modal.is-open .rw-modal__backdrop { opacity: 1; }
.rw-modal.is-open .rw-modal__card { opacity: 1; transform: none; }

.rw-modal__head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 18px 20px;
    border-bottom: 1px solid var(--border);
}
.rw-modal__g svg { width: 26px; height: 26px; display: block; }
.rw-modal__title { display: grid; gap: 2px; min-width: 0; }
.rw-modal__title strong { font-family: var(--font-display); font-size: 17px; color: var(--text); }
.rw-modal__sub { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--muted); }
.rw-modal__sub b { color: var(--text); }
.rw-modal__x {
    margin-left: auto;
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    color: var(--muted);
    border-radius: 50%;
    transition: var(--transition);
}
.rw-modal__x:hover { background: var(--bg-alt); color: var(--text); }
.rw-modal__x svg { width: 17px; height: 17px; }

.rw-modal__body {
    overflow-y: auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    padding: 18px 20px;
    background: var(--bg-alt);
}

.rw-card {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 16px;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-xs);
}
.rw-card__g { position: absolute; top: 12px; right: 12px; opacity: 0.35; }
.rw-card__g svg { width: 16px; height: 16px; }
.rw-card__head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.rw-card__avatar {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--accent-soft);
    color: var(--accent-dark);
    font-weight: 700;
    font-size: 15px;
    flex-shrink: 0;
}
.rw-card__name { font-weight: 700; font-size: 13.5px; color: var(--text); }
.rw-card__time { font-size: 11.5px; color: var(--muted); }
.rw-card__rating { display: inline-flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.rw-card__check { width: 13px; height: 13px; }
.rw-card__text {
    font-size: 13px;
    line-height: 1.6;
    color: var(--text);
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.rw-card.is-expanded .rw-card__text { display: block; -webkit-line-clamp: unset; }
.rw-card__more {
    align-self: flex-start;
    margin-top: 6px;
    padding: 0;
    font-size: 12px;
    font-weight: 700;
    color: var(--accent);
}
.rw-card__more:hover { text-decoration: underline; }

.rw-modal__foot {
    display: flex;
    justify-content: center;
    padding: 14px 20px;
    border-top: 1px solid var(--border);
}

/* -- Mobile: pill shrinks, popup becomes a bottom sheet -------------------- */
@media (max-width: 640px) {
    .rw-pill { left: 12px; bottom: 12px; padding: 8px 13px 8px 10px; gap: 9px; }
    .rw--raised .rw-pill { bottom: 96px; }
    .rw-pill__logo { width: 26px; height: 26px; }
    .rw-pill__logo svg { width: 14px; height: 14px; }
    .rw-modal { padding: 0; align-items: end; }
    .rw-modal__card {
        width: 100%;
        max-height: 86vh;
        border-radius: var(--radius) var(--radius) 0 0;
        transform: translateY(100%);
    }
    .rw-modal.is-open .rw-modal__card { transform: none; }
    .rw-modal__body { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
    .rw-pill, .rw-pill__x, .rw-modal__backdrop, .rw-modal__card { transition: none; }
}

/* ===== SERVICE PAGE GALLERY ================================================
   Every photo the client placed in this service's slot. Editorial grid: large
   leading image, then a tight masonry-free grid - reads curated, not dumped. */
.svc-gallery { padding: 96px 0; background: var(--bg-alt); }
.svc-gallery__grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 14px;
}
.svc-gallery__item {
    position: relative;
    margin: 0;
    border-radius: var(--radius-sm);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    cursor: zoom-in;
    transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
/* The first photo leads at double size - a gallery with a hero reads designed. */
.svc-gallery__item:first-child { grid-column: span 2; grid-row: span 2; }
.svc-gallery__item img {
    width: 100%;
    height: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    display: block;
    transition: transform 0.45s var(--ease);
}
.svc-gallery__item:first-child img { aspect-ratio: auto; min-height: 100%; }
.svc-gallery__item:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.svc-gallery__item:hover img { transform: scale(1.04); }
.svc-gallery__item figcaption {
    position: absolute;
    inset: auto 0 0 0;
    padding: 26px 14px 12px;
    font-size: 13px;
    font-weight: 600;
    color: #fff;
    background: linear-gradient(180deg, transparent, rgba(9, 12, 16, 0.72));
}
.svc-gallery__item figcaption:empty { display: none; }

@media (max-width: 800px) {
    .svc-gallery { padding: 64px 0; }
    .svc-gallery__grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .svc-gallery__item:first-child { grid-column: span 2; grid-row: auto; }
}

/* ===== LIGHTBOX ============================================================ */
.rs-lightbox {
    position: fixed;
    inset: 0;
    z-index: 4000;
    display: grid;
    place-items: center;
    padding: 28px;
    background: rgba(9, 12, 16, 0.9);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    opacity: 0;
    transition: opacity 0.25s var(--ease);
}
.rs-lightbox.is-open { opacity: 1; }
.rs-lightbox img {
    max-width: min(1100px, 100%);
    max-height: 88vh;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
    transform: scale(0.96);
    transition: transform 0.25s var(--ease);
}
.rs-lightbox.is-open img { transform: none; }
.rs-lightbox__x {
    position: absolute;
    top: 18px;
    right: 18px;
    width: 42px;
    height: 42px;
    display: grid;
    place-items: center;
    font-size: 26px;
    line-height: 1;
    color: #fff;
    background: rgba(255, 255, 255, 0.12);
    border-radius: 50%;
    cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
    .svc-gallery__item, .svc-gallery__item img, .rs-lightbox, .rs-lightbox img { transition: none; }
}

/* ============================================================================
   ONYX / NG SKIN - high-energy exteriors look. White/black bands with hard
   diagonal cuts, squared uppercase display type, one vivid accent, inline lead
   strip under the hero, accordion trust sections, giant-year footer.
   Appended last so it wins the cascade over the inherited Elite styles.
   ========================================================================== */

/* ---- Surfaces -----------------------------------------------------------------------------------
   Four surfaces, and every section is one of them. Nothing gets a one-off background.

     --surface-1  #FFFFFF   the default light ground
     --surface-2  #F5F6F8   the recessed light ground - used when a section's own content is white
                            cards, so the cards have something to sit on
     --band       #17191E   the dark block. Deliberately an off-black, not #000: a true black forces
                            every accent hue to sit at maximum contrast against it, which turns warm
                            accents muddy and cool ones neon. This is a desaturated near-neutral one
                            step off black, so any client palette reads as intended on it.
     accent                 punctuation only - never a content ground

   Dark is an ACCENT here, not the page's default. It marks two moments - the services grid and the
   closing contact block. Light sections are grouped by purpose instead of zebra-striping every time
   the visitor crosses a heading:

     hero (photo) > reviews + about S1 > services BAND > ticker ACCENT >
     why + projects + process + faq S2 > contact BAND > footer BAND

   Hairlines separate sections inside a shared surface. White cards then rise from S2 where the
   content needs containment, so the page has rhythm without looking like alternating swatches.

   The contact block and the footer are both dark on purpose: they read as one closing slab.

   Section edges are all square. The only angle in the template is the hero's diagonal, which is the
   signature; section-to-section wedges at other angles were fighting it. */
.onyx {
    --ink: #101114;
    --copy: #464D57;
    --band: #17191E;
    --band-card: #202329;   /* raised surface on the band */
    --surface-1: #FFFFFF;
    --surface-2: #F5F6F8;
    /* Brand colors are editable. Mixing display accents toward ink keeps highlighted words and
       small controls readable even when a client chooses a very bright brand color. */
    --accent-ink: color-mix(in srgb, var(--accent) 58%, var(--ink));
}

/* ---- Type: everything display goes uppercase ----------------------------- */
.onyx h1, .onyx h2, .onyx h3 { text-transform: uppercase; letter-spacing: 0.01em; }
.ng-h2 { font-size: clamp(26px, 3.4vw, 42px); line-height: 1.12; font-weight: 700; letter-spacing: -0.012em; }
.ng-h2 .hl, .onyx .contact-form__title .hl { color: var(--accent-ink); }
.onyx .hero__headline .hl { color: var(--accent-on-dark); }
.onyx .btn { text-transform: uppercase; letter-spacing: 0.06em; font-weight: 700; border-radius: 8px; }

/* Onyx reveals should feel like weight settling into place, not content climbing in from below. */
.onyx .anim-fade-up {
    transform: translateY(18px);
    transition: opacity 0.62s cubic-bezier(0.22, 1, 0.36, 1),
                transform 0.62s cubic-bezier(0.22, 1, 0.36, 1);
}
.onyx .anim-fade-up.visible { transform: translateY(0); }

/* ---- Top utility bar ------------------------------------------------------ */
.ng-topbar { background: var(--accent-ink); color: rgba(255,255,255,0.92); font-size: 13.5px; }
.ng-topbar__inner { display: flex; align-items: center; gap: 22px; padding: 9px 32px; }
.ng-topbar__note { font-weight: 600; color: #fff; }
.ng-topbar__spacer { flex: 1; }
.ng-topbar__item { display: inline-flex; align-items: center; gap: 7px; color: inherit; }
.ng-topbar__item [data-lucide] { color: #fff; }
.ng-topbar__item--strong { color: #fff; font-weight: 700; }
@media (max-width: 760px) {
    .ng-topbar__inner { padding: 8px 16px; gap: 14px; }
    .ng-topbar__note, .ng-topbar__item:not(.ng-topbar__item--strong) { display: none; }
    .ng-topbar__spacer { display: none; }
    .ng-topbar__inner { justify-content: center; }
}

/* ---- Nav: solid white, sticky under the topbar --------------------------- */
.onyx .nav {
    position: sticky;
    top: 0;
    background: #fff;
    box-shadow: 0 6px 24px -14px rgba(10, 10, 12, 0.35);
}
.onyx .nav .nav__logo, .onyx .nav .nav__phone { color: var(--ink); text-shadow: none; }
.onyx .nav .nav__links a, .onyx .nav .nav__links button.nav__link { color: #22262c; text-shadow: none; text-transform: uppercase; font-size: 13.5px; letter-spacing: 0.05em; font-weight: 700; }
.onyx .nav .nav__links a:hover, .onyx .nav .nav__links button.nav__link:hover { color: var(--accent); }
.onyx .nav .nav__toggle { color: var(--ink); }

/* ---- Menus: light, always ---------------------------------------------------------------------
   The base template fades its bar from transparent to white on scroll and swaps the bar AND the menus
   between a dark and a light skin to match. Onyx's bar is solid white from the very top, so both
   halves of that machinery fired backwards: opening a menu above the fold turned the bar to
   #0f141b while its own labels stayed the dark ink chosen for a white bar - dark on dark. Pin both
   surfaces light in every state instead.
   The bar first - `.nav.has-mega-open:not(.is-scrolled)` out-ranks the plain `.onyx .nav`. */
.onyx .nav.has-mega-open:not(.is-scrolled),
.onyx .nav.has-mega-open.is-scrolled,
.onyx .nav.is-scrolled {
    background: #fff;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}
/* Open sheet and bar are one surface, so the bar drops its lower edge while the sheet is down. */
.onyx .nav.has-mega-open { box-shadow: none; }
/* Now the menus. */
.onyx .nav:not(.is-scrolled) .dropdown {
    background: #fff;
    border-color: rgba(16, 17, 20, 0.09);
    box-shadow: 0 22px 54px -26px rgba(10, 10, 12, 0.45);
}
.onyx .nav:not(.is-scrolled) .dropdown li a,
.onyx .nav:not(.is-scrolled) .dropdown .dropdown__label { color: #22262c; }
.onyx .nav:not(.is-scrolled) .dropdown li a:hover,
.onyx .nav:not(.is-scrolled) .dropdown.is-mega > li > a:hover {
    background: var(--accent-soft);
    border-left-color: var(--accent);
    color: var(--ink);
}
.onyx .nav:not(.is-scrolled) .dropdown .dropdown__all-count { color: #6a7078; }
.onyx .nav:not(.is-scrolled) .dropdown .dropdown__all-art {
    background: color-mix(in srgb, var(--accent) 10%, #F4F6F8);
    color: var(--accent);
}
.onyx .nav:not(.is-scrolled) .dropdown.is-mega .dropdown__all-tile > a:hover .dropdown__all-art {
    background: var(--accent);
    color: var(--on-accent);
}
.onyx .nav:not(.is-scrolled) .dropdown:not(.is-mega) .dropdown__all { border-top-color: rgba(16, 17, 20, 0.1); }
.onyx .nav:not(.is-scrolled) .dropdown__thumb { background: #F4F6F8; }
/* The mega sheet is the same white as the bar it hangs from, so a hairline is what separates them. */
.onyx .dropdown.is-mega { background: #fff; border-bottom: 1px solid rgba(16, 17, 20, 0.09); }
.onyx .dropdown li a { transition: background-color 0.25s var(--ease), color 0.25s var(--ease), border-color 0.25s var(--ease); }
/* The bar's labels are uppercase chrome; the menu items are content (service names), so they inherit
   that treatment from `.nav__links a` and come out shouty. Reset them - needs the full nav__links
   path to out-rank it. */
.onyx .nav .nav__links .dropdown li a,
.onyx .nav .nav__links .dropdown .dropdown__label {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
    font-size: 14.5px;
}

/* ---- Hero: full-bleed photo, dark shade, accent diagonals on the right ---- */
.onyx .ng-hero {
    position: relative;
    min-height: 0;
    height: auto;
    padding: clamp(40px, 5vw, 70px) 0 clamp(36px, 4vw, 56px);
    overflow: visible;
    background: #0B0D11;
    display: block;
}
.onyx .ng-hero .hero__bg, .onyx .ng-hero .hero__overlay { display: none; }
.ng-hero__bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* The generic polish layer animates .hero__bg, but Onyx uses its own image element. Keep this
   deliberately restrained so the stationary diagonal still feels architectural. */
@keyframes onyxHeroDrift {
    from { transform: scale(1.01); }
    to { transform: scale(1.065); }
}
.onyx .ng-hero__bg {
    animation: onyxHeroDrift 20s cubic-bezier(0.22, 1, 0.36, 1) both;
    transform-origin: 68% center;
    will-change: transform;
}
.ng-hero__shade {
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(7, 9, 12, 0.92) 0%, rgba(7, 9, 12, 0.82) 55%, rgba(7, 9, 12, 0.66) 100%);
    /* The tint lives ONLY left of the diagonal - the photo stays clean on the right. */
    clip-path: polygon(0 0, 64% 0, 42% 100%, 0 100%);
}
/* One accent line riding the shade's diagonal edge exactly. */
.ng-hero__diag {
    position: absolute;
    inset: 0;
    background: var(--accent);
    clip-path: polygon(64% 0, calc(64% + 14px) 0, calc(42% + 14px) 100%, 42% 100%);
}
/* The Elite .hero is a flex container - un-shrink our containers or they collapse to fit-content. */
.onyx .ng-hero > .container { width: 100%; }
.ng-hero__inner { position: relative; }
.ng-hero__content { padding-bottom: clamp(64px, 6.5vw, 86px); }
.onyx .ng-hero .hero__headline {
    color: #fff;
    font-weight: 800;
    font-size: clamp(32px, 3.1vw, 44px);
    line-height: 1.12;
    margin: 0 0 14px;
    text-shadow: 0 3px 24px rgba(0, 0, 0, 0.45);
}
.onyx .ng-hero .hero__headline .hl { color: var(--accent-on-dark, var(--accent)); }
.onyx .ng-hero .hero__sub { color: rgba(255, 255, 255, 0.92); font-size: clamp(16px, 1.5vw, 20px); font-weight: 600; max-width: 52ch; margin: 0 0 22px; }
.onyx .ng-hero .hero__actions { justify-content: flex-start; margin-top: 22px; }
.onyx .ng-hero .btn--outline-white { border-color: rgba(255,255,255,0.6); color: #fff; }

/* The white review pill (G + FB, rating, count, gold stars). */
.ng-ratingpill {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    padding: 12px 22px 12px 12px;
    background: #fff;
    border-radius: 999px;
    box-shadow: 0 16px 40px -18px rgba(0, 0, 0, 0.6);
}
.ng-ratingpill__logos { display: flex; }
.ng-ratingpill__logo {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: #fff;
    border: 2px solid #fff;
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.25);
}
.ng-ratingpill__logo--fb { background: #1877F2; margin-left: -10px; }
.ng-ratingpill__body { display: grid; line-height: 1.3; }
/* Score first, then the stars it refers to, then the volume behind it - the stars have to sit
   against the number or the row reads as two unrelated facts. */
.ng-ratingpill__top { display: flex; align-items: center; gap: 7px; font-size: 15.5px; font-weight: 700; color: #14161C; }
.ng-ratingpill__top strong { font-size: 18px; line-height: 1; }
.ng-ratingpill__stars { color: #E8A33D; letter-spacing: 1px; }
.ng-ratingpill__count { font-weight: 600; color: #3d434b; }
.ng-ratingpill__count::before { content: ''; display: inline-block; width: 1px; height: 12px; margin-right: 8px; vertical-align: -1px; background: rgba(16, 17, 20, 0.18); }
.ng-ratingpill__sub { font-size: 12.5px; color: #5F6672; font-weight: 600; }

/* ---- Inline lead bar: white card riding the hero's bottom edge ------------ */
.ng-strip__wrap {
    position: absolute;
    left: 50%;
    bottom: 0;
    transform: translateX(-50%);
    z-index: 3;
}
.ng-strip__form {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    padding: 18px;
    background: #fff;
    border-radius: 6px;
    box-shadow: 0 26px 60px -24px rgba(0, 0, 0, 0.55);
    transform: translateY(50%);
}
/* Content column: hero text block on the left like the reference. */
.ng-hero__content { max-width: 760px; }
/* This is the headline of the whole lead bar, not a field label - it carries the offer, so it is
   sized like a heading. "Free" is the word doing the work and must not be the smallest thing in it. */
.ng-strip__head {
    flex: 1 1 100%;
    font-family: var(--font-display);
    font-size: clamp(20px, 2vw, 26px);
    line-height: 1.15;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: #14161C;
    margin: 0;
}
.ng-strip__head .hl { color: var(--accent); }
.ng-strip__sub {
    flex: 1 1 100%;
    margin: -4px 0 2px;
    font-size: 13.5px;
    font-weight: 600;
    color: #5F6672;
}
.ng-field { position: relative; flex: 1; min-width: 0; }
.ng-field input {
    width: 100%;
    padding: 14px 40px 14px 14px;
    font: inherit;
    font-size: 14px;
    color: #14161C;
    background: #fff;
    border: 1.5px solid #14161C;
    border-radius: 4px;
}
.ng-field input::placeholder { color: #6a7078; }
.ng-field input:focus { outline: none; border-color: var(--accent); }
.ng-field [data-lucide] {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    width: 17px;
    height: 17px;
    color: #14161C;
    pointer-events: none;
}
.ng-strip__form .btn { flex-shrink: 0; align-self: stretch; }
/* The bar hangs below the hero - give the next section room for the overlap. */
.onyx .ng-reviews { padding-top: clamp(110px, 11vw, 150px); }
@media (max-width: 980px) {
    .ng-strip__wrap { position: relative; left: auto; bottom: auto; transform: none; margin-top: 20px; }
    .ng-strip__form { flex-wrap: wrap; transform: none; margin-bottom: -70px; }
    .ng-field { flex: 1 1 46%; }
    .ng-field--wide, .ng-strip__form .btn { flex: 1 1 100%; }
    .onyx .ng-reviews { padding-top: 150px; }
}

/* ---- Reviews: white section, carded ---------------------------------------- */
.onyx .ng-reviews { background: var(--surface-1); }
.onyx .ng-reviews .section-header h2 { color: var(--ink); }
.onyx .ng-reviews .section-header p { color: var(--copy); }
.onyx .ng-reviews .review-card { border: 1px solid rgba(16,17,20,0.1); box-shadow: 0 16px 40px -24px rgba(16,17,20,0.35); }
/* The Elite base styles .reviews as a dark section (dark cards, light text) - this section is
   white, so out-rank those scoped selectors card by card. */
.onyx .ng-reviews .review-card { background: #fff; }
.onyx .ng-reviews .review-card:hover { box-shadow: 0 20px 48px -24px rgba(16,17,20,0.4); }
.onyx .ng-reviews .review-card__name, .onyx .ng-reviews .review-text { color: var(--ink); }
.onyx .ng-reviews .review-card__sub { color: var(--copy); }
.onyx .ng-reviews .review-card__more { color: var(--accent-ink); }
.onyx .ng-reviews .review-card__more:hover { color: var(--ink); }

/* ---- Black band ------------------------------------------------------------ */
.ng-dark, .ng-dark-cont { background: var(--band); }
.onyx .ng-soft { background: var(--surface-2); }
.onyx .ng-dark h2, .onyx .ng-dark-cont h2,
.onyx .ng-dark h3, .onyx .ng-dark-cont h3 { color: #fff; }
.onyx .ng-dark p, .onyx .ng-dark-cont p { color: #b9bfc8; }
.onyx .ng-dark p strong, .onyx .ng-dark-cont p strong { color: #fff; }
.onyx .ng-dark .about-stat__value { color: var(--accent); }
.onyx .ng-dark .about-stat__label { color: #8d939c; }
.onyx .ng-dark .btn--outline-dark, .onyx .ng-dark .btn--outline-white,
.onyx .ng-dark-cont .btn--outline-dark, .onyx .ng-dark-cont .btn--outline-white {
    border-color: rgba(255,255,255,0.35); color: #fff; background: transparent;
}
.onyx .about__media { display: block; position: relative; }
.onyx .about__media .ba-slider { width: 100%; aspect-ratio: 4 / 3; height: auto; }

/* ---- About: keep the column's contents inside the column --------------------------------------
   Three separate things were pushing content past the grid track on desktop, which read as the whole
   section bleeding off the sides:
   - the two buttons are `nowrap` + `flex-wrap: nowrap`, and Onyx sets every button uppercase with
     extra letter-spacing, so the pair no longer fits the half-width column and simply overflowed;
   - the licence stat renders a full licence number at the same 22px as "20+", with nothing telling
     it it may break;
   - the stat strip's hairlines are the light-theme --border, invisible on black, so the numbers
     looked like they were floating loose rather than sitting in a ruled strip. */
.onyx .about__grid { align-items: center; }
.onyx .about__content { min-width: 0; }
.onyx .about__content .intro__actions { flex-wrap: wrap; gap: 12px; }
.onyx .about__content .intro__actions .btn {
    flex: 1 1 auto;
    white-space: normal;
    text-align: center;
    padding-left: 20px;
    padding-right: 20px;
}
.onyx .ng-dark .about__stats {
    border-top-color: rgba(255, 255, 255, 0.14);
    border-bottom-color: rgba(255, 255, 255, 0.14);
}
.onyx .ng-dark .about-stat { border-left-color: rgba(255, 255, 255, 0.14); }
.onyx .about-stat__value {
    /* Auto height, not a locked 1.2em line box - a licence number needs two lines and the fixed
       height clipped it. Two lines are then RESERVED for every stat so all four labels sit on the
       same baseline whether their value wrapped or not. */
    font-size: clamp(16px, 1.5vw, 20px);
    height: auto;
    min-height: 2.4em;
    overflow-wrap: anywhere;
}
/* The licence stat is the only one whose value is a long string rather than a short number. At the
   shared size it ran to three lines and made the strip ragged. */
.onyx .about-stat:nth-child(4) .about-stat__value { font-size: 15px; line-height: 1.25; }
/* 46px of uppercase Georgia ran the heading to four lines beside the photo. */
.onyx .about__content h2 { font-size: clamp(28px, 2.9vw, 38px); margin-bottom: 16px; }
.onyx .about__content p { font-size: 16px; margin-bottom: 26px; }
/* The 64px gutter is what tips the columns too narrow between the base breakpoint and full width. */
@media (max-width: 1180px) { .onyx .about__grid { gap: 40px; } }
.ng-photo-tag {
    position: absolute;
    bottom: 12px;
    left: 12px;
    z-index: 5;
    padding: 6px 14px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #fff;
    background: var(--accent-ink);
    border-radius: 6px;
    box-shadow: 0 6px 18px -6px rgba(0,0,0,0.5);
    pointer-events: none;
}

/* ---- Ticker: skewed accent marquee ---------------------------------------- */
.ng-ticker {
    /* --proof-h normally comes from .proof-stats, the hero wrapper this bar was written for. Dropped
       straight into the ticker the variable was unset, `height: var(--proof-h)` was invalid, and the
       bar collapsed to its 24px line box. Set it here.
       The band used to be skewed with its contents counter-skewed back to horizontal, which is what
       put two mismatched diagonals across it. It is a straight bar now. */
    --proof-h: 64px;
    position: relative;
    z-index: 2;
    background: var(--accent-ink);
    overflow: hidden;
}
/* The proof bar ships with a top hairline, a blur, and an upward-casting shadow because in its home
   position it is seated in the base of the hero photo. Here it is counter-skewed inside the accent
   band, so that shadow rendered as a soft dark edge at the OPPOSITE angle to the band - a second
   diagonal crossing the first. Strip the seam treatment entirely; the band supplies its own edges. */
.ng-ticker .proof-bar {
    background: transparent;
    border: none;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}
.ng-ticker .proof-bar__item { color: #fff; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }
.ng-ticker .proof-bar__item strong { color: #fff; }
.ng-ticker .proof-bar__stars { color: #FFD666; }
/* separator becomes a bolt-ish notch */
.ng-ticker .proof-bar__sep { width: 14px; height: 16px; background: rgba(255,255,255,0.85); clip-path: polygon(58% 0, 22% 55%, 46% 55%, 36% 100%, 82% 40%, 55% 40%); border-radius: 0; }

/* ---- Why us: accordion, light ------------------------------------------------------------------
   Moved off the dark band, so the rows invert: pale card, ink text, accent spine on the left. */
.ng-why { padding: 100px 0; background: var(--surface-2); }
.ng-why__grid { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 48px; align-items: start; }
.onyx .ng-why h2 { color: var(--ink); }
.onyx .ng-why__head p { color: var(--copy); margin: 12px 0 22px; }
.onyx .ng-why .faq-item {
    background: var(--surface-1);
    border: 1px solid rgba(16, 17, 20, 0.08);
    border-left: 3px solid var(--accent);
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 10px;
    transition: box-shadow 0.35s var(--ease), border-color 0.35s var(--ease);
}
.onyx .ng-why .faq-item.is-open {
    background: var(--surface-1);
    box-shadow: 0 18px 40px -30px rgba(16, 17, 20, 0.55);
    border-color: rgba(16, 17, 20, 0.12);
    border-left-color: var(--accent);
}
.onyx .ng-why .faq-q { color: var(--ink); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; }
.onyx .ng-why .faq-q__icon { color: var(--accent-ink); border-color: rgba(16, 17, 20, 0.14); background: transparent; }
.onyx .ng-why .faq-item.is-open .faq-q__icon { background: var(--accent); color: var(--on-accent); border-color: transparent; }
.onyx .ng-why .faq-a p { color: var(--copy); }
@media (max-width: 900px) { .ng-why__grid { grid-template-columns: 1fr; } }

/* ---- Projects: light ---------------------------------------------------------------------------- */
.onyx .projects.ng-soft {
    background: var(--surface-2);
    border-top: 1px solid rgba(16, 17, 20, 0.07);
}
.onyx .projects .section-header h2 { color: var(--ink); }
.onyx .projects .projects__dot { background: rgba(16, 17, 20, 0.16); }
.onyx .projects .projects__dot.is-active { background: var(--accent-ink); }

/* ---- About: light --------------------------------------------------------------------------------
   The stat strip's hairlines and the heading colour both key off the section being light now, which
   is what the base .about styles already assume - so this only needs the surface itself. */
.onyx .about.ng-soft {
    background: var(--surface-1);
    border-top: 1px solid rgba(16, 17, 20, 0.07);
}

/* ---- Process: numbered cards ------------------------------------------------------------------
   The base template's home-page variant is a connected track: no cards, `padding: 0`, and the icons
   sit ON a rule running behind the row. Onyx was pinning a card border and shadow onto that same
   zero-padded step, so every box hugged its own text with no inset. Cards here mean real cards - the
   track is dropped, each step gets its own surface, and the step number becomes a watermark rather
   than another line of text competing with the heading. */
.onyx .process {
    background: var(--surface-2);
    border-top: 1px solid rgba(16, 17, 20, 0.07);
}
.onyx .process .section-header h2 { color: var(--ink); }
.onyx .process .section-header p { color: var(--copy); }
.onyx .process__grid--simple::before { display: none; }
.onyx .process__grid--simple { gap: 22px; }

.onyx .process .process-step--line {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: 32px 26px 30px;
    background: var(--surface-1);
    border: 1px solid rgba(16, 17, 20, 0.08);
    border-radius: 14px;
    box-shadow: 0 18px 40px -30px rgba(16, 17, 20, 0.5);
    transition: transform 0.45s var(--ease), box-shadow 0.45s var(--ease), border-color 0.45s var(--ease);
}
/* Accent wash rising from the base on hover - reads as the step "activating" without moving text. */
.onyx .process .process-step--line::before {
    content: '';
    position: absolute;
    inset: auto 0 0 0;
    height: 100%;
    z-index: -1;
    background: linear-gradient(0deg, color-mix(in srgb, var(--accent) 9%, transparent), transparent 62%);
    opacity: 0;
    transition: opacity 0.45s var(--ease);
}
/* Accent rule that draws across the bottom edge. */
.onyx .process .process-step--line::after {
    content: '';
    position: absolute;
    inset: auto 0 0 0;
    height: 3px;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.5s var(--ease);
}
.onyx .process .process-step--line:hover {
    transform: translateY(-6px);
    border-color: color-mix(in srgb, var(--accent) 28%, transparent);
    box-shadow: 0 30px 60px -34px rgba(16, 17, 20, 0.6);
}
.onyx .process .process-step--line:hover::before { opacity: 1; }
.onyx .process .process-step--line:hover::after { transform: scaleX(1); }

/* The number as a ghosted watermark in the corner. It keeps the ordering legible at a glance while
   leaving the heading as the only real line of type at the top of the card. */
.onyx .process .process-step--line .process-step__num {
    position: absolute;
    top: 6px;
    right: 18px;
    margin: 0;
    font-size: 82px;
    line-height: 1;
    font-weight: 800;
    color: rgba(16, 17, 20, 0.055);
    pointer-events: none;
    transition: color 0.45s var(--ease);
}
.onyx .process .process-step--line:hover .process-step__num { color: color-mix(in srgb, var(--accent) 16%, transparent); }

.onyx .process .process-step__icon {
    width: 56px;
    height: 56px;
    border-radius: 14px;
    margin-bottom: 20px;
    /* No ring: the ring existed to mask the connector track, and there is no track here. */
    box-shadow: none;
    background: color-mix(in srgb, var(--accent) 12%, #fff);
    border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
    transition: background-color 0.45s var(--ease), color 0.45s var(--ease), transform 0.45s var(--ease), border-color 0.45s var(--ease);
}
.onyx .process .process-step__icon svg { width: 26px; height: 26px; }
.onyx .process .process-step--line:hover .process-step__icon {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
    transform: translateY(-2px) rotate(-4deg);
}
/* Two lines reserved: "Construction & Installation" wraps and "Free Consultation" doesn't, and
   without this the body copy started at a different height in each card. */
.onyx .process .process-step--line h3 { position: relative; font-size: 18px; margin-bottom: 10px; min-height: 2.2em; }
.onyx .process .process-step--line p { color: var(--copy); }

@media (prefers-reduced-motion: reduce) {
    .onyx .process .process-step--line,
    .onyx .process .process-step__icon { transition: none; }
    .onyx .process .process-step--line:hover { transform: none; }
    .onyx .process .process-step--line:hover .process-step__icon { transform: none; }
}

/* ---- FAQ: editable interior photo ---------------------------------------------------------------
   The image is a real photo slot, not a CSS URL, so the portal/runtime loader can replace it. The
   dark scrim keeps the heading readable while the near-opaque question cards preserve scanning. */
.onyx .ng-faq {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    background: var(--band);
    padding: 100px 0;
    border-top: 1px solid rgba(16, 17, 20, 0.07);
}
.onyx .ng-faq::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(110deg, rgba(10, 12, 16, 0.88), rgba(10, 12, 16, 0.66));
}
.onyx .ng-faq__bg {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}
.onyx .ng-faq > .container { position: relative; }
.onyx .ng-faq .section-header h2 { color: #fff; text-shadow: 0 2px 22px rgba(0, 0, 0, 0.34); }
.onyx .ng-faq .section-header .hl { color: var(--accent-on-dark); }
.onyx .ng-faq .faq-item {
    background: rgba(255, 255, 255, 0.95);
    border: 1px solid rgba(255, 255, 255, 0.48);
    border-radius: 10px;
    margin-bottom: 10px;
    box-shadow: 0 18px 42px -28px rgba(0, 0, 0, 0.68);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.onyx .ng-faq .faq-q { color: var(--ink); font-weight: 700; }
.onyx .ng-faq .faq-q__icon { color: var(--accent-ink); border-color: rgba(16, 17, 20, 0.14); background: transparent; }
.onyx .ng-faq .faq-item.is-open .faq-q__icon { background: var(--accent); color: var(--on-accent); border-color: transparent; }
.onyx .ng-faq .faq-a p { color: var(--copy); }

/* ---- Contact + service areas: one closing block --------------------------------------------------
   Previously two sections doing overlapping jobs - a "schedule an estimate" panel and, further down,
   a "proudly serving" panel with the same city list the contact copy already named. Merged: where we
   work and how to reach us are one answer, and the form sits beside them instead of a screen away.
   Dark, and running straight into the dark footer, so the page closes on a single slab. */
.onyx .ng-contact { background: var(--band); padding: 100px 0 90px; }
.ng-contact__grid { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 56px; align-items: start; }
.onyx .ng-contact h2 { color: #fff; }
.onyx .ng-contact .ng-h2 .hl { color: var(--accent-on-dark); }
.onyx .ng-contact__lede { color: rgba(255, 255, 255, 0.72); margin: 14px 0 26px; max-width: 46ch; }

.ng-contact__facts { display: grid; gap: 12px; padding-bottom: 26px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); }
.ng-contact__facts li { display: flex; gap: 12px; align-items: baseline; color: #fff; font-size: 15px; }
.ng-contact__facts a { color: #fff; font-weight: 700; }
.ng-contact__facts a:hover { color: var(--accent-on-dark); }
.ng-fact__label {
    flex-shrink: 0;
    min-width: 74px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.5);
}

.ng-contact__areas { padding: 26px 0 0; }
.onyx .ng-contact__sub {
    font-size: 15px;
    line-height: 1.45;
    font-weight: 700;
    color: #fff;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 16px;
}
.onyx .ng-contact__sub .hl { color: var(--accent-on-dark); }
/* Left-aligned, not the centred chip cloud the standalone section used - it now sits in a column
   beside the form and has to share that column's alignment. */
.onyx .ng-contact .areas__grid { justify-content: flex-start; gap: 8px; }
.onyx .ng-contact .area-pill {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.88);
    border-radius: 8px;
    padding: 8px 14px;
    font-size: 13.5px;
    box-shadow: none;
}
.onyx .ng-contact .area-pill:hover { background: rgba(255, 255, 255, 0.11); border-color: var(--accent); transform: none; }
.onyx .ng-contact .area-pill [data-lucide] { color: var(--accent-on-dark); width: 14px; height: 14px; }
.ng-contact__arealink {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-top: 16px;
    font-size: 13.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--accent-on-dark);
}
.ng-contact__arealink:hover { color: #fff; }
.onyx .ng-contact .ng-map { margin: 26px 0 0; max-width: none; border-color: rgba(255, 255, 255, 0.12); box-shadow: none; }
.onyx .ng-contact .ng-map iframe { height: 260px; }

/* Form card: the one white surface on the slab, which is where the eye should land. */
.onyx .ng-contact .contact-form {
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.6);
    padding: 30px;
    position: sticky;
    top: 104px;
}
.onyx .ng-contact .contact-form label span { color: var(--muted); }
.onyx .ng-contact .contact-form input, .onyx .ng-contact .contact-form textarea {
    background: var(--surface-2); color: var(--ink); border: 1px solid rgba(16, 17, 20, 0.12);
}
.contact-form__note { font-size: 13px; color: #6a7078; margin: -8px 0 18px; }
@media (max-width: 980px) {
    .ng-contact__grid { grid-template-columns: 1fr; gap: 40px; }
    .onyx .ng-contact .contact-form { position: static; }
}

/* ---- Footer: clean black, standard layout ---------------------------------- */
.onyx .footer { background: #0A0A0B; }
.onyx .footer__bottom { border-top: 1px solid rgba(255,255,255,0.08); }
.onyx .footer__bottom-inner { display: flex; align-items: center; justify-content: center; gap: 18px; flex-wrap: wrap; font-size: 13px; }
.footer__legal a { color: inherit; text-decoration: none; }
.footer__legal a:hover { color: var(--accent-on-dark, #fff); }



/* ---- Service-area map card -------------------------------------------------- */
.ng-map {
    margin: 34px auto 26px;
    max-width: 980px;
    border-radius: 14px;
    overflow: hidden;
    border: 1px solid rgba(16, 17, 20, 0.1);
    box-shadow: 0 22px 50px -28px rgba(16, 17, 20, 0.45);
}
.ng-map iframe { display: block; width: 100%; height: 380px; border: 0; }
@media (max-width: 640px) { .ng-map iframe { height: 260px; } }

/* ---- Before/after: smooth, contained, no drag side-effects ------------------ */
.onyx .ba-slider {
    border-radius: 14px;
    overflow: hidden;
    box-shadow: 0 26px 60px -26px rgba(0, 0, 0, 0.65);
    user-select: none;
    -webkit-user-select: none;
    touch-action: pan-y;    /* vertical page scroll stays free; horizontal drags drive the slider */
    cursor: ew-resize;
}
/* The clip position snaps instantly under the pointer - easing here would make it lag the hand. */
.onyx .ba-slider__after { transition: none; }

/* Legal pages */
.legal { padding: 140px 0 90px; background: #fff; }
.legal h1 { font-size: clamp(26px, 3vw, 38px); color: var(--ink, #14161C); margin-bottom: 6px; }
.legal__updated { color: #6a7078; font-size: 13.5px; margin-bottom: 30px; }
.legal h2 { font-size: 19px; margin: 30px 0 10px; color: var(--ink, #14161C); }
.legal p, .legal li { font-size: 15px; line-height: 1.75; color: #3d434b; }
.legal ul { padding-left: 22px; margin: 10px 0; list-style: disc; }
.legal .container { max-width: 820px; }
.legal a { color: var(--accent); }


/* ===== SERVICE BEFORE & AFTER ============================================== */
.svc-ba { padding: 90px 0; }
.svc-ba__wrap { max-width: 880px; margin: 0 auto; }
.svc-ba .ba-slider { width: 100%; aspect-ratio: 16 / 10; height: auto; border-radius: 14px; overflow: hidden; box-shadow: var(--shadow-md); user-select: none; -webkit-user-select: none; touch-action: pan-y; cursor: ew-resize; }
@media (max-width: 640px) { .svc-ba { padding: 60px 0; } .svc-ba .ba-slider { aspect-ratio: 4 / 3; } }


/* ===== QUOTE MODAL =========================================================================
   The stepped estimate form behind every CTA. Markup is built in main.js (initQuoteModal) so it
   exists on every page from one source. Three short steps beat one long form: each screen asks for
   one kind of thing, and the cheap question (what do you need) comes before the expensive one
   (your phone number).
   ============================================================================================ */
.qm {
    position: fixed;
    inset: 0;
    /* Above the floating reviews pill (1200) and the reviews modal (1300), below the photo
       lightbox (4000) which is the template's true top layer. */
    z-index: 1400;
    display: grid;
    place-items: center;
    padding: 20px;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s var(--ease), visibility 0.3s;
}
.qm.is-open { opacity: 1; visibility: visible; }
body.qm-locked { overflow: hidden; }

.qm__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(8, 9, 12, 0.62);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.qm__dialog {
    position: relative;
    width: 100%;
    max-width: 520px;
    max-height: calc(100vh - 40px);
    overflow-y: auto;
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 40px 100px -30px rgba(0, 0, 0, 0.6);
    padding: 30px;
    transform: translateY(14px) scale(0.98);
    transition: transform 0.36s cubic-bezier(0.16, 1, 0.3, 1);
}
.qm.is-open .qm__dialog { transform: none; }

.qm__x {
    position: absolute;
    top: 14px;
    right: 16px;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    font-size: 22px;
    line-height: 1;
    color: #6a7078;
    background: var(--surface-2);
    transition: background-color 0.25s var(--ease), color 0.25s var(--ease);
}
.qm__x:hover { background: #e6e8ec; color: var(--ink); }

.qm__title { font-size: clamp(21px, 2.4vw, 27px); line-height: 1.15; color: var(--ink); margin: 0 34px 6px 0; }
.qm__title .hl { color: var(--accent); }
.qm__sub { font-size: 13.5px; color: #6a7078; margin-bottom: 18px; }
.qm__meter { height: 4px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.qm__meter-fill {
    display: block;
    height: 100%;
    width: 33.333%;
    border-radius: 999px;
    background: var(--accent);
    transition: width 0.4s var(--ease);
}
.qm__count { font-size: 12px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: #6a7078; margin: 10px 0 20px; }
.qm__count strong { color: var(--accent); }

/* Steps are display:none rather than visually hidden - a hidden-but-rendered fieldset would still
   be reachable by Tab from the visible one. */
/* min-width:0 defeats the <fieldset> quirk of refusing to shrink below its content's intrinsic
   width - without it the chip row could not wrap and pushed the dialog off-screen on mobile. */
.qm__step { display: none; border: 0; padding: 0; margin: 0; min-width: 0; }
.qm__step.is-active { display: block; }
.qm__legend { font-size: 16px; font-weight: 700; color: var(--ink); margin-bottom: 14px; padding: 0; }

.qm__field { display: grid; gap: 7px; margin-bottom: 14px; }
.qm__field > span {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
}
.qm__field > span em { font-style: normal; opacity: 0.65; letter-spacing: 0.06em; }
.qm__field input,
.qm__field textarea {
    width: 100%;
    padding: 12px 14px;
    font: inherit;
    font-size: 15px;
    color: var(--ink);
    background: var(--surface-2);
    border: 1px solid rgba(16, 17, 20, 0.12);
    border-radius: 8px;
    transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease), background-color 0.25s var(--ease);
}
.qm__field textarea { resize: vertical; min-height: 96px; }
.qm__field input:focus,
.qm__field textarea:focus {
    outline: none;
    background: #fff;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

/* Service picker: real radios, visually a chip set. The input stays in the layout (opacity:0, not
   display:none) so it keeps its focus ring and remains reachable by keyboard. */
.qm-chips { display: flex; flex-wrap: wrap; gap: 9px; }
.qm-chip { position: relative; }
.qm-chip input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}
.qm-chip span {
    display: block;
    padding: 10px 16px;
    font-size: 14px;
    font-weight: 600;
    color: #3d434b;
    background: var(--surface-2);
    border: 1px solid rgba(16, 17, 20, 0.1);
    border-radius: 999px;
    transition: var(--transition);
}
.qm-chip input:hover + span { border-color: var(--accent-line); }
.qm-chip input:checked + span {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
}
.qm-chip input:focus-visible + span { box-shadow: 0 0 0 3px var(--accent-ring); }

.qm__actions { display: flex; gap: 10px; margin-top: 24px; }
.qm__actions .btn { flex: 1 1 auto; justify-content: center; }
.qm__actions .qm__back { flex: 0 0 auto; }
/* Honeypot - off-screen rather than display:none, which some bots skip. */
.qm__hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

.qm .form-success { padding: 24px 0; font-size: 16px; line-height: 1.7; color: var(--ink); text-align: center; }
.form-error { margin-top: 12px; color: #A5271D; font-size: 14px; line-height: 1.5; font-weight: 600; }

@media (max-width: 560px) {
    /* Centred, not docked to the bottom edge: as a bottom sheet the dialog sat under the thumb and
       right on top of the sticky mobile CTA bar, and a short first step left a large dead gap
       above it. Centred it reads as a dialog at any step height. */
    .qm { padding: 12px; align-items: center; }
    .qm__dialog { padding: 24px 20px; border-radius: 14px; max-height: calc(100vh - 24px); }
    .qm__actions { flex-wrap: wrap; }
}

@media (max-width: 560px) {
    .onyx .areas-hub__grid { grid-template-columns: 1fr; gap: 10px; }
}
@media (prefers-reduced-motion: reduce) {
    .qm, .qm__dialog, .qm__meter-fill { transition: none; }
    .qm__dialog { transform: none; }
}

/* The contact block carries .ng-dark, whose `h2, h3 { color:#fff }` and `p { color:#b9bfc8 }` are
   meant for copy sitting directly on the band. The form is a white card inside it, so its own
   heading and note have to opt back out. */
.onyx .ng-contact .contact-form__title { color: var(--ink); }
.onyx .ng-contact .contact-form__title .hl { color: var(--accent); }
.onyx .ng-contact .contact-form__note { color: #6a7078; }

/* .btn sets display:inline-flex, which out-ranks the UA's `[hidden] { display:none }` - so the
   step buttons stayed on screen when the script hid them. */
.qm__actions .btn[hidden] { display: none; }

/* Stat values keep the accent now the strip sits on a light ground - they read as figures rather
   than another line of body copy. */
.onyx .about-stat__value { color: var(--accent); }

/* Floating furniture is noise behind a modal, and on a phone the sticky CTA bar sits exactly where
   the wizard's own buttons are. Both step aside while the quote modal is open. */
body.qm-locked .rw-pill,
body.qm-locked .mobile-cta { opacity: 0; pointer-events: none; }
.rw-pill, .mobile-cta { transition: opacity 0.25s var(--ease), transform 0.38s var(--ease); }

/* ---- Onyx homepage responsive finish ------------------------------------- */
@media (max-width: 720px) {
    /* The shade and the diagonal are handled by the 900px block further down - phones get a flat
       scrim and no wedge at all. Only the type scale is tuned here. */
    .onyx .ng-hero .hero__headline { font-size: clamp(32px, 9vw, 38px); }
    .onyx .ng-hero .hero__sub { line-height: 1.55; }
    .onyx .ng-ratingpill { max-width: 100%; padding-right: 16px; gap: 10px; }
    .onyx .ng-ratingpill__top { flex-wrap: wrap; row-gap: 2px; }
    .onyx .ng-ratingpill__sub { line-height: 1.35; }

    .onyx .ng-reviews { padding-bottom: 72px; }
    .onyx .about,
    .onyx .services,
    .onyx .ng-why,
    .onyx .projects,
    .onyx .process,
    .onyx .ng-faq,
    .onyx .ng-contact { padding-top: 72px; padding-bottom: 72px; }

    .onyx .section-header { margin-bottom: 40px; }
    .onyx .ng-h2 { font-size: clamp(26px, 7.2vw, 32px); line-height: 1.16; }
    .onyx .faq-q { min-height: 56px; line-height: 1.35; }
    .onyx .faq-a p,
    .onyx .process .process-step--line p,
    .onyx .about__content p { font-size: 15.5px; line-height: 1.7; }
}

@media (prefers-reduced-motion: reduce) {
    .onyx .ng-hero__bg { animation: none; transform: none; will-change: auto; }
}

/* ===== LIGHT-LOGO NAV SKIN ===================================================================
   Applied by main.js (initLogoLuminance) when the logo's own pixels come back mostly light - a
   white wordmark, a knocked-out mark. Onyx's bar is pale by default, which makes exactly that kind
   of logo disappear, so those sites get the inverse treatment instead: transparent over the dark
   hero on load, and a solid dark bar once scrolled. The logo is legible in both states, which is
   the whole point.

   Scoped to <html class="has-light-logo"> so it can be set before <body> is styled, and every rule
   below is a straight inversion of the pale skin further up rather than a new design.
   ============================================================================================= */
.onyx .nav { transition: background-color 0.35s var(--ease), box-shadow 0.35s var(--ease); }

/* Solid dark at every scroll position, deliberately NOT transparent. Onyx's bar is `position:
   sticky`, so it occupies its own band in the flow rather than floating over the hero - making it
   transparent reveals the white page behind it, not the photo, and a white logo on white is the
   exact failure this skin exists to fix. Solid dark also reads as continuous with the accent
   topbar above and the dark hero below. */
.has-light-logo .onyx .nav,
.has-light-logo .onyx .nav.is-scrolled,
.has-light-logo .onyx .nav.has-mega-open,
.has-light-logo .onyx .nav.has-mega-open:not(.is-scrolled),
.has-light-logo .onyx .nav.has-mega-open.is-scrolled {
    background: var(--band);
}
.has-light-logo .onyx .nav { box-shadow: none; }
.has-light-logo .onyx .nav.is-scrolled { box-shadow: 0 6px 24px -14px rgba(0, 0, 0, 0.7); }
.has-light-logo .onyx .nav.has-mega-open { box-shadow: none; }

/* Bar contents invert with it. */
.has-light-logo .onyx .nav .nav__logo,
.has-light-logo .onyx .nav .nav__phone { color: #fff; }
.has-light-logo .onyx .nav .nav__links a,
.has-light-logo .onyx .nav .nav__links button.nav__link { color: rgba(255, 255, 255, 0.92); }
.has-light-logo .onyx .nav .nav__links a:hover,
.has-light-logo .onyx .nav .nav__links button.nav__link:hover { color: var(--accent-on-dark); }
.has-light-logo .onyx .nav .nav__links > li > a::after,
.has-light-logo .onyx .nav .nav__links > li > button.nav__link::after { background: var(--accent-on-dark); }
/* The badge's letter fallback and its plate both sit on dark now. */
.has-light-logo .onyx .nav .nav__logo-badge span { background: rgba(255, 255, 255, 0.1); color: #fff; }
/* Hamburger bars are set dark for the pale skin; put them back to white - except while the mobile
   panel (which is light) is open, where the toggle sits on that panel instead of on the bar. */
.has-light-logo .onyx .nav .nav__toggle span { background: #fff; }
.has-light-logo .onyx .nav .nav__toggle.is-active span { background: var(--ink); }

/* Menus follow the bar down. These mirror the pale-skin overrides one for one, so a menu opened on
   a dark bar is dark rather than a white sheet stapled underneath it. */
.has-light-logo .onyx .nav .dropdown,
.has-light-logo .onyx .nav:not(.is-scrolled) .dropdown {
    background: var(--menu-dark);
    border-color: rgba(255, 255, 255, 0.1);
    box-shadow: 0 24px 60px rgba(6, 9, 13, 0.5);
}
.has-light-logo .onyx .dropdown.is-mega { background: var(--menu-dark); border-bottom-color: rgba(255, 255, 255, 0.1); }
.has-light-logo .onyx .nav .nav__links .dropdown li a,
.has-light-logo .onyx .nav .nav__links .dropdown .dropdown__label { color: rgba(255, 255, 255, 0.92); }
.has-light-logo .onyx .nav .nav__links .dropdown li a:hover,
.has-light-logo .onyx .nav .nav__links .dropdown.is-mega > li > a:hover {
    background: rgba(255, 255, 255, 0.08);
    border-left-color: var(--accent-on-dark);
    color: #fff;
}
.has-light-logo .onyx .nav .dropdown .dropdown__all-count { color: rgba(255, 255, 255, 0.55); }
.has-light-logo .onyx .nav .dropdown .dropdown__all-art { background: rgba(255, 255, 255, 0.09); color: var(--accent-on-dark); }
.has-light-logo .onyx .nav .dropdown__thumb { background: rgba(255, 255, 255, 0.06); }
.has-light-logo .onyx .nav .dropdown:not(.is-mega) .dropdown__all { border-top-color: rgba(255, 255, 255, 0.14); }

/* A transparent bar only works when something dark sits behind it - the home page's .ng-hero or an
   interior page's .page-hero. The legal pages have neither and start on white, where a transparent
   bar would put white labels on a white page. Those get the solid dark bar from the very top.
   (.onyx is the <body> element itself, so this is body.onyx, not a descendant of it.) */
.has-light-logo body.onyx:not(:has(.ng-hero)):not(:has(.page-hero)) .nav {
    background: var(--band);
}

/* ===== ONYX: NAV + HERO RESPONSIVE ===========================================================
   Three problems this fixes, all only visible below desktop width:

   1. The hamburger was invisible. The base template's bars are `background: var(--white)` because
      its bar is transparent over a photo; Onyx's bar is solid white, so white bars sat on white.
      `.onyx .nav .nav__toggle { color: var(--ink) }` set the icon colour, which the bars - being
      background, not currentColor - never read.
   2. The desktop nav ran out of room long before it collapsed. Onyx sets its links uppercase with
      extra letter-spacing, so the row needs noticeably more width than the base template it
      inherits the 900px breakpoint from; between roughly 900 and 1150 the phone number clipped and
      the CTA fell off the bar entirely.
   3. Hero copy crossed the accent diagonal. The diagonal is positioned in percentages of the
      viewport while the copy sits in a fixed-max-width container, so the two converge as the
      window narrows and the buttons ended up on the bright side of the photo.
   ============================================================================================= */

/* ---- 1. Hamburger: dark on the pale bar, light on the dark one ---- */
.onyx .nav .nav__toggle span { background: var(--ink); }
/* Open, the toggle sits on the light mobile panel, so it stays dark there in both skins. */
.onyx .nav .nav__toggle.is-active span { background: var(--ink); }
.has-light-logo .onyx .nav .nav__toggle span { background: #fff; }
.has-light-logo .onyx .nav .nav__toggle.is-active span { background: var(--ink); }

/* ---- 2. Collapse the nav earlier than the base template ---- */
@media (max-width: 1150px) {
    .onyx .nav__links,
    .onyx .nav__phone { display: none; }
    .onyx .nav__toggle { display: flex; }
    .onyx .nav__logo { flex-shrink: 1; min-width: 0; }
    .onyx .nav__inner { gap: 12px; }
}

/* ---- 3. Hero: keep the copy clear of the diagonal ----
   The diagonal's two x-positions become variables so the shade, the accent line and the copy
   column all derive from one source. As the viewport narrows the wedge swings right, giving the
   text more dark ground instead of letting the photo creep under it. */
.onyx .ng-hero {
    /* Measured, not eyeballed: the copy column's widest element is the button row, and its bottom
       edge is where the slanted scrim is narrowest, so that is the pair these values are checked
       against. The wedge is deliberately well left of centre - it reads as a design element rather
       than a background split - and --copy-max is pulled in to match so the two never meet. */
    --diag-top: 60%;
    --diag-bot: 44%;
    --copy-max: 500px;
}
.onyx .ng-hero__shade {
    clip-path: polygon(0 0, var(--diag-top) 0, var(--diag-bot) 100%, 0 100%);
}
.onyx .ng-hero__diag {
    clip-path: polygon(
        var(--diag-top) 0,
        calc(var(--diag-top) + 14px) 0,
        calc(var(--diag-bot) + 14px) 100%,
        var(--diag-bot) 100%
    );
}
.onyx .ng-hero__content { max-width: var(--copy-max); }

@media (max-width: 1280px) { .onyx .ng-hero { --diag-top: 66%; --diag-bot: 50%; --copy-max: 460px; } }
@media (max-width: 1080px) { .onyx .ng-hero { --diag-top: 76%; --diag-bot: 62%; --copy-max: 430px; } }

/* Below 900 the page is single-column and the copy needs the full width, which leaves no room for
   a diagonal to cut across. The wedge becomes a slim edge signature and the copy gets a continuous
   scrim instead - the same treatment the phone breakpoint already used, just starting earlier,
   because the collision begins well before phone width. */
@media (max-width: 900px) {
    .onyx .ng-hero { --copy-max: 100%; }
    .onyx .ng-hero__shade {
        clip-path: none;
        background: linear-gradient(90deg, rgba(7, 9, 12, 0.94), rgba(7, 9, 12, 0.78));
    }
    /* No diagonal on a phone. There is no room for it to mean anything next to full-width copy,
       and the sliver version it used to shrink to just read as a stray line down the edge. */
    .onyx .ng-hero__diag { display: none; }
}

/* ---- Headline: unambiguously bold at every size ----
   Georgia ships regular and bold only, so 800 resolves to the same face as 700 - state 700 so the
   weight is honest, and let the browser synthesise nothing. */
.onyx .ng-hero .hero__headline {
    font-weight: 700;
    text-wrap: balance;
}

/* ===== ONYX: MOBILE OPTIMISATION =============================================================
   Measured fixes, not guesses - each one came out of auditing the rendered page at 390px.
   ============================================================================================= */

/* ---- Tap targets ----
   iOS and Android both want ~44px; these were 8-15px. The visuals are already right, so the hit
   area is expanded with a pseudo-element rather than by resizing anything the eye can see. */
.reviews__dot,
.projects__dot { position: relative; }
.reviews__dot::after,
.projects__dot::after {
    content: '';
    position: absolute;
    /* 8px dot + 13px each side = a 34px target, without moving the dots apart. */
    inset: -13px;
}
.review-card__more {
    min-height: 34px;
    padding: 8px 0;
    /* The card's own padding already spaces it; only the touch box grows. */
    margin: -8px 0;
}

@media (max-width: 900px) {
    /* Every topbar link, not just the phone: at tablet width the email is still shown and was a
       23px line of text. These are the highest-intent controls on the page. */
    .onyx .ng-topbar__item {
        padding: 6px 4px;
        min-height: 36px;
        align-items: center;
    }
    /* Inline text links that act as navigation get the same treatment. */
    .onyx .ng-contact__arealink,
    .onyx .ng-contact__facts a,
    .onyx .footer a {
        min-height: 34px;
        display: inline-flex;
        align-items: center;
    }
}

/* ---- iOS input zoom ----
   Safari zooms the viewport whenever a focused field's text is under 16px, which on these forms
   yanked the page sideways mid-typing and left it zoomed. 16px is the threshold, so every input
   the client can tap into gets exactly that at phone width. Desktop keeps its tighter sizes. */
@media (max-width: 640px) {
    .onyx .ng-field input,
    .onyx .contact-form input,
    .onyx .contact-form textarea,
    .qm__field input,
    .qm__field textarea {
        font-size: 16px;
    }
}

/* ---- Hero: breathing room on a phone ---- */
@media (max-width: 640px) {
    .onyx .ng-hero .hero__actions { gap: 10px; }
    /* Both hero buttons full width and stacked: side by side at this width they were each too
       narrow for their label and the text wrapped inside the button. */
    .onyx .ng-hero .hero__actions .btn { flex: 1 1 100%; justify-content: center; }
}

/* ---- Section rhythm ----
   The desktop 90-110px section padding is a lot of dead scrolling on a phone. */
@media (max-width: 640px) {
    .onyx .about,
    .onyx .services,
    .onyx .projects,
    .onyx .process,
    .onyx .ng-why,
    .onyx .ng-faq,
    .onyx .ng-contact { padding-top: 56px; padding-bottom: 56px; }
    .onyx .ng-reviews { padding-bottom: 56px; }
    .onyx .section-header { margin-bottom: 28px; }
}

/* The mobile panel starts below the bar, wherever the bar actually ends. --nav-bottom is measured
   and republished by main.js on load, scroll and resize; the fallback matches the base template's
   original fixed value for the case where the script never runs. */
.onyx .nav__mobile { padding-top: calc(var(--nav-bottom, 108px) + 18px); }

/* ===== ONYX: SMALL-SCREEN SWEEP ==============================================================
   Everything here came from measuring the rendered pages at 320/360/390/414/430px - the real
   spread of phones in use, including the 320px floor that a small iPhone in landscape-zoom or an
   older Android still reports.
   ============================================================================================= */

/* The section header is a `space-between` row: heading on the left, "All Services" on the right.
   The link carries `flex-shrink: 0` so it cannot give way, and on a phone it was pushed clean off
   the screen - 116px past the edge at 320px. Stack the two instead of asking them to share a line
   that isn't wide enough for either. */
@media (max-width: 720px) {
    .onyx .services__header {
        flex-direction: column;
        align-items: flex-start;
        gap: 16px;
    }
    .onyx .services__header-link {
        flex-shrink: 1;
        max-width: 100%;
    }
}

@media (max-width: 640px) {
    /* Buttons default to their intrinsic width, which overflows once a label is long enough.
       Full-width is also simply a better phone target. */
    .onyx .section-more .btn,
    .onyx .services__header-link,
    .onyx .about__content .intro__actions .btn { width: 100%; justify-content: center; }
    .onyx .section-more { display: flex; }

    /* Long unbroken strings - an email address, a licence number - are the usual cause of a
       stubborn 20px of horizontal overflow on a narrow screen. */
    .onyx .ng-contact__facts a,
    .onyx .footer a,
    .onyx .about-stat__value { overflow-wrap: anywhere; }
}

/* At 320-360 the container's 32px side padding costs a fifth of the screen. */
@media (max-width: 380px) {
    .onyx .container { padding-left: 20px; padding-right: 20px; }
    .onyx .ng-hero .hero__headline { font-size: clamp(28px, 8.6vw, 34px); }
    .onyx .ng-ratingpill { padding: 10px 14px 10px 10px; gap: 10px; }
    .onyx .ng-ratingpill__logo { width: 34px; height: 34px; }
    .onyx .process .process-step--line { padding: 26px 20px 24px; }
    .onyx .process .process-step--line .process-step__num { font-size: 64px; right: 14px; }
}

/* ===== ONYX: MOBILE TOPBAR ROTATOR ===========================================================
   One item at a time, crossfading, driven by initTopbarRotator in main.js. The items are stacked
   on top of each other in a fixed-height box so the bar never changes height as the content
   changes - a bar that grew and shrank would shift the whole page under the reader's thumb.
   ============================================================================================= */
@media (max-width: 760px) {
    .onyx .ng-topbar__inner.is-rotating {
        position: relative;
        display: block;
        height: 36px;
        padding: 0 16px;
    }
    .onyx .ng-topbar__inner.is-rotating .ng-topbar__spacer { display: none; }
    /* Out-ranks the display:none that hides everything but the phone on small screens. */
    .onyx .ng-topbar__inner.is-rotating > .ng-topbar__note,
    .onyx .ng-topbar__inner.is-rotating > .ng-topbar__item {
        display: inline-flex;
        position: absolute;
        inset: 0;
        align-items: center;
        justify-content: center;
        gap: 7px;
        opacity: 0;
        transform: translateY(5px);
        transition: opacity 0.45s var(--ease), transform 0.45s var(--ease);
        /* Only the item on screen is tappable - the stack underneath must not swallow the tap. */
        pointer-events: none;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .onyx .ng-topbar__inner.is-rotating > .is-active {
        opacity: 1;
        transform: none;
        pointer-events: auto;
    }
}
@media (prefers-reduced-motion: reduce) {
    .onyx .ng-topbar__inner.is-rotating > .ng-topbar__note,
    .onyx .ng-topbar__inner.is-rotating > .ng-topbar__item {
        transition: none;
        transform: none;
    }
}

/* ===== ONYX: MOBILE MENU PANEL ===============================================================
   The panel was `top: 0` with enough top padding to clear the bar, which meant a white sheet slid
   up over the accent topbar and cut it in half lengthwise - the bar stayed visible only in the
   strip beside the panel. Anchor it under the bar instead, using the same measured --nav-bottom
   the padding used to approximate. The topbar and nav stay whole, and the panel reads as a drawer
   hanging off the bar rather than a sheet pasted over it.
   ============================================================================================= */
.onyx .nav__mobile {
    top: var(--nav-bottom, 108px);
    padding-top: 22px;
    border-top: 1px solid var(--line, rgba(16, 17, 20, 0.08));
}
/* The backdrop still covers everything below the bar, so the page behind reads as inert. */
.onyx .nav__mobile-backdrop { top: var(--nav-bottom, 108px); }

/* ===== Font theme: Tech (tech) - injected by the generator ===== */
@font-face{font-family:'Michroma';font-style:normal;font-weight:400;font-display:swap;src:url('https://client.remodelersites.com/fonts/michroma-400.woff2') format('woff2');}
@font-face{font-family:'Michroma';font-style:normal;font-weight:600;font-display:swap;src:url('https://client.remodelersites.com/fonts/michroma-400.woff2') format('woff2');}
@font-face{font-family:'Michroma';font-style:normal;font-weight:700;font-display:swap;src:url('https://client.remodelersites.com/fonts/michroma-400.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('https://client.remodelersites.com/fonts/inter-400.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('https://client.remodelersites.com/fonts/inter-600.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url('https://client.remodelersites.com/fonts/inter-700.woff2') format('woff2');}
:root{--font-display:'Michroma', 'Arial Black', Arial, sans-serif;--font-serif:'Michroma', 'Arial Black', Arial, sans-serif;--font-body:'Inter', -apple-system, 'Segoe UI', sans-serif;--font-sans:'Inter', -apple-system, 'Segoe UI', sans-serif;}
