/* ==========================================================================
   mobile-conversion.css
   Mobile-focused layout + conversion layer. Everything here is inside a
   max-width:767px query, so desktop is untouched.

   MUST LOAD LAST. On 131 pages that means after formatting-audit-fixes.css;
   on index.html after home-fire-rebuilds.css, on fire-rebuild.html after
   hero-scroll-build.css, on careers.html after careers.css.

   Two jobs:
     A. Turn desktop grids that collapse to one tall column into horizontal
        swipe rows, matching the fire-rebuild carousel already on the homepage.
     B. Sticky Call/Inquire bar + 3-field quick form (styles for the elements
        injected by js/mobile-conversion.js).

   Brand tokens used here (from style.css :root and hero-rebuild.css):
     navy    #1c3f60   dark navy #12283f
     gold    #b5894e   gold hover #c39a60   gold light #c99f62
     radius  2px buttons / 10px cards
   ========================================================================== */

@media (max-width: 767px) {

  /* ------------------------------------------------------------------
     Shared swipe-row primitive.
     Generalized from .home-fire-rebuilds__track. Full-bleed track that
     scroll-snaps, with the next card peeking so it's obvious there's more.
     ------------------------------------------------------------------ */
  .mcv-row {
    display: flex;
    gap: 14px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scroll-behavior: smooth;
    scrollbar-width: none;
    /* full-bleed out of the section's 5% padding, with matching inset
       padding so the first card still aligns to the text above it */
    margin-left: -20px;
    margin-right: -20px;
    padding: 4px 20px 8px;
    /* contain scroll chaining so a horizontal swipe never yanks the page */
    overscroll-behavior-x: contain;
  }
  .mcv-row::-webkit-scrollbar { display: none; }

  .mcv-row > * {
    flex: 0 0 auto;
    scroll-snap-align: start;
  }

  /* Numbered carousel counter, e.g. "01 / 06". Blue Label's pattern: reads
     as deliberate at any item count, where a dot row gets noisy past ~4. */
  .mcv-dots {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-top: 14px;
    margin-bottom: 0;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.8rem;
    letter-spacing: 0.1em;
  }
  /* The What We Do row is the last child of .wwd-container, so its counter
     lands at the very bottom of that section, visually adjacent to the next
     section's heading. Pull it back inside its own section. */
  .wwd-container .mcv-dots {
    margin-bottom: 4px;
  }
  .mcv-count__current {
    color: #b5894e;
    font-weight: 700;
  }
  .mcv-count__total {
    color: rgba(28, 63, 96, 0.45);
    font-weight: 500;
  }
  /* Light treatment on the dark testimonials panel */
  .testimonials-section .mcv-count__current { color: #c99f62; }
  .testimonials-section .mcv-count__total { color: rgba(255, 255, 255, 0.45); }

  /* Hide the desktop prev/next arrows on mobile; swipe is the interaction */
  .home-fire-rebuilds__nav { display: none; }

  /* home-fire-rebuilds.css:222 bleeds this track -20px on both sides, so its
     first card started at x=0 while every other row starts at 20px. Align it
     with the rest: left flush to the gutter, bleed right only. */
  .home-fire-rebuilds__carousel {
    margin-left: 0 !important;
    margin-right: -20px !important;
  }
  .home-fire-rebuilds__track {
    padding-left: 0 !important;
    padding-right: 20px !important;
  }


  /* ==================================================================
     1. TESTIMONIALS  (was 2.1 screens: 3 stacked cards)
     testimonials.css:188 only sets grid-template-columns:1fr, so the
     cards stack full-height. Override to a swipe row.
     ================================================================== */
  .testimonials-section .testimonials-grid {
    /* was: grid + 1fr. display must beat the grid rule at same specificity,
       which source order handles since this file loads last. */
    display: flex;
    gap: 14px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
    /* section supplies the left gutter; bleed right only so the next card peeks */
    margin-left: 0;
    margin-right: -20px;
    padding: 4px 20px 8px 0;
  }
  .testimonials-section .testimonials-grid::-webkit-scrollbar { display: none; }

  .testimonials-section .testimonial-card {
    flex: 0 0 auto;
    scroll-snap-align: start;
    /* 86vw leaves ~14vw of the next card visible as the swipe affordance */
    width: 86vw;
    max-width: 420px;
    /* equal heights so the row doesn't look ragged mid-swipe */
    display: flex;
    flex-direction: column;
  }
  .testimonials-section .testimonial-card__quote {
    /* fill available space so the author block sits at the card bottom */
    flex: 1 1 auto;
    font-size: 1rem;   /* was 15.2px, under the 16px mobile minimum */
    line-height: 1.6;
  }


  /* ==================================================================
     2. WHAT WE DO  (was 2.9 screens: 7 stacked cards)
     Fire Rebuilds stays a full-width hero card because it is the priority
     service. The other six are ONE swipe row beneath it.

     The markup used to have two separate .wwd-featured-secondary containers
     (3 cards each), which on mobile produced a hero plus two independent
     carousels: three different layout ideas in one section. They are now
     merged into a single container in index.html, which also reflows
     cleanly on desktop as two rows of a 3-column grid.

     The section already provides the 20px gutter and .wwd-container is
     zeroed, so this row must NOT also pull -20px or the cards bleed off
     the left edge. Bleed right only, so the next card peeks past the edge.
     ================================================================== */
  .wwd-section .wwd-featured-secondary {
    /* was: grid-template-columns:1fr */
    display: flex;
    gap: 14px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
    margin-left: 0;
    margin-right: -20px;
    padding: 4px 20px 8px 0;
    margin-bottom: 0;
  }
  .wwd-section .wwd-featured-secondary::-webkit-scrollbar { display: none; }

  .wwd-section .wwd-featured-secondary .wwd-featured-card {
    flex: 0 0 auto;
    scroll-snap-align: start;
    width: 78vw;
    max-width: 340px;
    min-height: 260px;
  }

  /* Blue Label's project cards are photo + name only, no badge and no
     paragraph. Ours carried badge + title + paragraph + link on every card,
     which at 375px is four text layers over a photo. Hide the badge and the
     paragraph on the SECONDARY cards only; the Fire Rebuilds hero keeps its
     full copy because it is the priority service. Desktop keeps everything.
     Text stays in the DOM, so nothing is lost for SEO or for desktop. */
  .wwd-section .wwd-featured-secondary .wwd-featured-card__badge,
  .wwd-section .wwd-featured-secondary .wwd-featured-card__content p {
    display: none;
  }
  .wwd-section .wwd-featured-secondary .wwd-featured-card__content {
    /* copy block is now title + link, so let it sit at the bottom */
    padding-top: 0 !important;
  }

  /* Hero card: tall and prominent, but aligned to the same 20px gutter as
     the row below it. what-we-do-v2.css pulls it -5% (-16.875px) on each
     side, which left it at x=2 while the carousel started at x=19.

     440px because the content block alone is ~322px (badge 28 + title 26 +
     paragraph 120 + link 41, plus 64px vertical padding). At 340px the text
     filled the whole card, hiding the photo and cramming the CTA against
     the bottom edge. */
  .wwd-section .wwd-featured-card--hero {
    min-height: 440px;
    margin-left: 0 !important;
    margin-right: 0 !important;
    width: 100% !important;
  }
  /* Keep the CTA on one line; at 375px it was wrapping the arrow onto a
     second row, which read as a rendering glitch. */
  .wwd-section .wwd-featured-card--hero .wwd-featured-card__link {
    font-size: 0.8rem !important;
    letter-spacing: 0.08em !important;
    white-space: nowrap;
  }

  /* Card copy sits directly on photography, so mobile needs a stronger
     bottom scrim than desktop or the text disappears into the image. */
  .wwd-section .wwd-featured-card__overlay {
    background: linear-gradient(
      to top,
      rgba(15, 30, 48, 0.94) 0%,
      rgba(15, 30, 48, 0.82) 45%,
      rgba(15, 30, 48, 0.45) 75%,
      rgba(15, 30, 48, 0.15) 100%
    ) !important;
  }
  /* The hero card's copy runs over the bright mountain ridge, which the
     gradient alone doesn't cover. Give it a slightly heavier wash. */
  .wwd-section .wwd-featured-card--hero .wwd-featured-card__overlay {
    background: linear-gradient(
      to top,
      rgba(15, 30, 48, 0.95) 0%,
      rgba(15, 30, 48, 0.88) 55%,
      rgba(15, 30, 48, 0.6) 82%,
      rgba(15, 30, 48, 0.3) 100%
    ) !important;
  }
  .wwd-section .wwd-featured-card__content p {
    font-size: 1rem;   /* was 15.2px, under the mobile body-copy floor */
    line-height: 1.5;
  }


  /* ==================================================================
     3. WHERE WE WORK  (was 1.9 screens: 6 stacked city photos)
     The gallery is already horizontal on desktop. simple-services-center.css
     :125-135 forces flex-direction:column + full-width items on mobile.
     Undo that and let it scroll horizontally.
     Those rules use !important, so these must too.
     ================================================================== */
  .cities-gallery {
    flex-direction: row !important;   /* undoes simple-services-center.css:127 */
    align-items: stretch !important;
    gap: 14px !important;
    /* 20px inset matches the section's text gutter so the first card lines
       up with the heading instead of bleeding off the left edge */
    padding: 4px 20px 8px 0 !important; /* undoes its 20px all-round */
    overflow-x: auto !important;      /* undoes overflow-x:visible */
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
    margin-left: 0 !important;
    margin-right: -20px !important;   /* bleed right so the next card peeks */
    /* width:auto let this flex row expand to fit all six cards (clientWidth
       came out 1755px), so scrollWidth equalled clientWidth and there was
       nothing to scroll. Constrain it to the container and the overflow
       becomes real. min-width:0 is needed because a flex item's default
       min-width:auto refuses to shrink below its content. */
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
  }
  .cities-gallery::-webkit-scrollbar { display: none; }

  /* The container was also sized by its content; cap it too. */
  .cities-gallery-container {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    overflow: hidden !important;
  }

  .city-item {
    /* undoes simple-services-center.css:138-140 (width:90%, max 350, h 180) */
    width: 74vw !important;
    max-width: 320px !important;
    height: 200px !important;
    scroll-snap-align: start;
  }

  /* The "View More Cities" button sits above the gallery it describes.
     Push it below so the reading order is heading, photos, then action. */
  .where-we-work-section .where-we-work-button-container {
    order: 3;
    margin-top: 20px;
  }
  .where-we-work-section .where-we-work-container {
    display: flex;
    flex-direction: column;
  }
  .where-we-work-section .where-we-work-header { order: 1; }
  .where-we-work-section .cities-gallery-container { order: 2; }


  /* ==================================================================
     4. DESIGN / MANAGE / BUILD  (was 1.5 screens for three words)
     simple-services-center.css:11-23 pins these at 250px each plus
     padding; style.css gives them near-viewport height. Cap the whole
     tile so all three read in roughly half a screen.
     ================================================================== */
  /* Hidden on mobile. The three tiles cost ~1.3 screens to deliver three
     words, and every service is covered properly in What We Do further
     down. Desktop keeps them: there they are an instant side-by-side row
     that reads in one glance, which is the layout they were designed for. */
  .services {
    display: none !important;
  }


  /* ==================================================================
     MOBILE SECTION ORDER
     Fire Rebuilds moves directly below the hero, since it is the priority
     service and the strongest proof we have. Done with flex `order` so the
     HTML (and therefore desktop) source order is untouched.

     Every child of <main> needs an explicit order once the container is a
     flex column, otherwise unset items all default to 0 and collapse to
     source order.
     ================================================================== */
  /* !important because mobile-homepage.css:494 sets display:block !important
     on main, which silently made every `order` below inert. */
  main {
    display: flex !important;
    flex-direction: column !important;
  }
  #home                        { order: 1; }  /* hero */
  #fire-rebuilds-feature       { order: 2; }  /* moved up from 4th */
  #about                       { order: 3; }
  #portfolio                   { order: 4; }
  #testimonials                { order: 5; }
  .partners-bar                { order: 6; }
  #what-we-do                  { order: 7; }
  #where-we-work               { order: 8; }
  .additional-photo-section    { order: 9; }
  #instagram                   { order: 10; }


  /* ==================================================================
     5. FEATURED PROJECTS  (was 1.4 screens of cropped countertop)
     The showcase image crops to an unreadable slice at 375px. Give it a
     portrait-ish ratio so it reads as a room, and kill the trailing gap.
     ================================================================== */
  .portfolio-section {
    padding-bottom: 32px;
  }
  /* homepage-updates.css:259-265 sets height:90vh + width:100vw with a
     -50vw pull. Keep the full-bleed trick but cap the height, otherwise
     this single image costs 1.3 screens. */
  .portfolio-showcase {
    height: 280px !important;
    margin-bottom: 0;
  }
  .portfolio-image {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover;
    /* bias toward the upper part of the frame, where the room reads
       rather than the countertop edge */
    object-position: center 38%;
  }


  /* ==================================================================
     6. ADDITIONAL PHOTO  (was 0.9 screens, unlabeled)
     It's a visual breather, not a feature. Halve it.
     ================================================================== */
  /* Hidden on mobile. It is an unlabeled portrait photo with no heading,
     caption, or link, and cropping it to a landscape band cut the subject in
     half. As a wide full-bleed breather on desktop it works; at 375px it just
     reads as a stray image between two real sections. Desktop keeps it. */
  .additional-photo-section {
    display: none !important;
  }


  /* ==================================================================
     7. OUR STORY  (was 2.1 screens)
     Left-align the prose. Centered is fine for a short intro but hard to
     track across three stacked paragraphs ragged on both edges.
     ================================================================== */
  /* simple-services-center.css:37-39 pads #about 10% left / 7% right, which
     was tuned to the old 8%/9% service tiles. With tiles now at 5% it leaves
     a 78px left and 66px right gutter and only 231px of usable width, so the
     whole section reads off-centre and cramped. Normalize to 20px like every
     other section. */
  #about.about {
    padding-left: 20px !important;
    padding-right: 20px !important;
  }
  #about .process-image {
    justify-content: center !important;   /* was flex-start */
    margin-left: 0 !important;            /* was -5% */
    margin-right: 0 !important;
  }
  #about .process-photos-grid {
    padding-left: 0 !important;           /* was 3% / 7% */
    padding-right: 0 !important;
    width: 100% !important;
  }
  #about .process-photo-item {
    width: 100% !important;               /* was a fixed 280px */
    max-width: none !important;
    height: 200px !important;
  }

  #about .process-text {
    text-align: left !important;   /* mobile-homepage.css:245 sets center */
  }
  #about .process-title {
    text-align: center !important; /* heading stays centered */
  }
  #about .process-lead,
  #about .process-text p {
    text-align: left !important;
    font-size: 1rem !important;
    line-height: 1.65 !important;
  }
  #about .process-text .cta-button {
    display: block;
    width: fit-content;
    margin-left: auto;
    margin-right: auto;
  }
  #about .process-photos-grid {
    margin-top: 24px !important;
    margin-bottom: 0 !important;
  }


  /* ==================================================================
     8a. ONE GUTTER, ONE ALIGNMENT
     Measured gutters were 19/20/22/25/60px depending on section, and 8 of
     9 headings were centre-aligned. Varying gutters read as sloppy, and
     wall-to-wall centred text in a 375px column is the main thing that
     reads amateur next to Blue Label or Forma, which left-align on mobile.

     Left-align headings and body; keep the section eyebrow labels centred
     so sections still announce themselves.
     ================================================================== */
  #about .process-hero-section,
  .home-fire-rebuilds__header,
  .portfolio-header,
  .testimonials-header,
  .wwd-header,
  .where-we-work-header {
    text-align: left !important;
  }

  .home-fire-rebuilds__title,
  .portfolio-title,
  .testimonials-header h2,
  .wwd-header h2,
  .where-we-work-title,
  #about .process-title {
    text-align: left !important;
  }
  .home-fire-rebuilds__lede,
  .wwd-subtitle {
    text-align: left !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    max-width: none !important;
  }

  /* ------------------------------------------------------------------
     ONE TYPE SCALE
     Our section headings measured 40, 32, 28.8, 26.4, 25.6, 25.6 and
     18.4px. Blue Label uses a single 25px for every section heading, and
     that consistency is a large part of why theirs reads composed and
     ours reads improvised. One size, one weight, tight leading.
     ------------------------------------------------------------------ */
  #about .process-title,
  .home-fire-rebuilds__title,
  .portfolio-title,
  .testimonials-header h2,
  .wwd-header h2,
  .where-we-work-title,
  .ig-feed-title h2 {
    font-size: 1.65rem !important;   /* 26.4px */
    line-height: 1.15 !important;
    font-weight: 700 !important;
    letter-spacing: -0.01em !important;
    margin-bottom: 14px !important;
  }

  /* Card titles are one step down, also uniform. */
  .wwd-featured-card__content h3,
  .home-fire-rebuilds__card-name {
    font-size: 1.25rem !important;
    line-height: 1.2 !important;
  }

  /* Uniform 20px gutter. The section provides it; inner containers are
     zeroed so the two don't stack (testimonials and What We Do were
     section 19px + container 20px = 39px, Our Story was 20 + 40 = 60px). */
  .testimonials-section,
  .wwd-section,
  .portfolio-section,
  .where-we-work-section,
  .partners-bar,
  .home-fire-rebuilds {
    padding-left: 20px !important;
    padding-right: 20px !important;
  }
  .portfolio-container,
  .testimonials-container,
  .wwd-container,
  .where-we-work-container,
  .partners-bar__container,
  #about .about-container {
    padding-left: 0 !important;
    padding-right: 0 !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    max-width: none !important;
  }
  /* home-fire-rebuilds.css:197 pads the inner 20px and the section itself is
     0-padded (its carousel bleeds full width by design), so this one keeps
     its own gutter rather than inheriting from the section. */
  .home-fire-rebuilds {
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  .home-fire-rebuilds__inner {
    padding-left: 20px !important;
    padding-right: 20px !important;
  }
  /* city-gallery.css:66-68 makes this header a flex row with
     justify-content:center, so text-align could not move the heading. The
     flex alignment itself has to change. */
  .where-we-work-section .where-we-work-header {
    display: flex !important;
    justify-content: flex-start !important;
    text-align: left !important;
  }
  .where-we-work-section h2.where-we-work-title {
    text-align: left !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    padding-left: 0 !important;
  }
  /* Same flex-centering on the button container below the gallery. */
  .where-we-work-section .where-we-work-button-container {
    justify-content: flex-start !important;
  }

  /* Section eyebrows: one consistent treatment, gold accent so each section
     announces itself. Previously they varied in size, colour and opacity and
     were easy to miss, which made sections bleed into each other. */
  .section-label,
  .portfolio-subtitle,
  .wwd-label,
  .partners-bar__label {
    text-align: left !important;
    font-size: 0.7rem !important;
    font-weight: 600 !important;
    letter-spacing: 0.2em !important;
    color: #b5894e !important;
    margin-bottom: 8px !important;
  }
  /* On the dark testimonials panel the gold needs to be the lighter tint */
  .testimonials-section .section-label {
    color: #c99f62 !important;
  }

  /* Adjacent white sections had no visible boundary, so the page read as one
     long undifferentiated column. A hairline rule separates them without
     adding the heaviness of alternating background blocks. */
  #about,
  .portfolio-section,
  .wwd-section,
  .where-we-work-section {
    border-top: 1px solid rgba(28, 63, 96, 0.1);
  }


  /* ==================================================================
     8. SECTION PADDING PASS
     Sections range 56px to 100px vertical. Standardize so the rhythm
     reads deliberate instead of gappy.
     ================================================================== */
  #about { padding-top: 48px !important; padding-bottom: 48px !important; }
  .home-fire-rebuilds { padding: 48px 0 !important; }
  .portfolio-section { padding-top: 48px; }
  .testimonials-section { padding: 48px 5% !important; }
  .partners-bar { padding-top: 32px; padding-bottom: 32px; }
  .wwd-section { padding: 48px 5% !important; }
  .where-we-work-section { padding-top: 48px; padding-bottom: 48px; }
  .ig-feed-section { padding-top: 40px; padding-bottom: 40px; }

  /* Body copy floor: nothing below 16px. Under 16px also triggers
     iOS auto-zoom on any adjacent form field. */
  .home-fire-rebuilds__lede { font-size: 1rem !important; }
  .wwd-subtitle { font-size: 1rem !important; }


  /* ==================================================================
     HERO
     The hero is a full-height video with the copy at the top and the CTAs
     pinned to the base. Scale the copy up so it carries that top third
     rather than floating as a small block over the footage — the type is
     the main event here, and a bigger scrim-backed block also reads more
     legibly over the moving frame.
     ================================================================== */
  .hero-rebuild__kicker {
    font-size: 0.7rem !important;
    letter-spacing: 0.2em !important;
    margin-bottom: 10px !important;
  }
  .hero-rebuild__title {
    /* Scales with the viewport: ~35px at 360px wide, ~44px at 430px. */
    font-size: clamp(2.1rem, 9.6vw, 2.75rem) !important;
    line-height: 1.05 !important;
    letter-spacing: -0.02em !important;
    margin-bottom: 14px !important;
  }
  .hero-rebuild__sub {
    font-size: 1rem !important;
    line-height: 1.5 !important;
    margin-bottom: 22px !important;
    /* Full measure + balanced breaking: at the larger size this wrapped to
       four lines and orphaned "home." on the last one. */
    max-width: none !important;
    text-wrap: pretty;
  }
  /* Side by side rather than two stacked full-width blocks, which ate
     ~150px of a 680px hero. */
  /* One primary button + one subordinate text link, not two equal buttons.
     Two equal-weight CTAs split attention and cause choice paralysis; a solid
     primary with a quieter secondary is the documented hierarchy. It also
     reclaims ~60px of height versus two stacked buttons. */
  .hero-rebuild__ctas {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    gap: 4px !important;
    width: 100% !important;
    margin: 0 !important;
  }
  /* 56px sits in the conversion-optimal 56-64px band (WCAG floor is 48px). */
  .hero-rebuild__btn--primary {
    flex: 0 0 auto !important;
    width: 100% !important;
    min-width: 0 !important;
    min-height: 56px !important;
    padding: 18px 20px !important;
    font-size: 0.9rem !important;
    letter-spacing: 0.1em !important;
    border-radius: 3px !important;
    white-space: nowrap;
    text-align: center;
    box-shadow: 0 10px 26px -12px rgba(0, 0, 0, 0.7);
  }
  /* Demote "Call Now" from a ghost button to a text link. */
  .hero-rebuild__btn--ghost {
    background: transparent !important;
    border: 0 !important;
    backdrop-filter: none !important;
    width: auto !important;
    min-height: 48px !important;   /* keeps the tap target legal */
    padding: 12px 16px !important;
    font-size: 0.82rem !important;
    letter-spacing: 0.12em !important;
    color: rgba(255, 255, 255, 0.92) !important;
    text-decoration: underline !important;
    text-underline-offset: 5px !important;
    text-decoration-color: rgba(201, 159, 98, 0.8) !important;
    text-decoration-thickness: 1px !important;
    box-shadow: none !important;
  }
  /* ---- Hero height ------------------------------------------------------
     Deliberately SHORTER than the viewport. A full-height hero with copy at
     the top and CTAs at the base guarantees dead space in the middle, and it
     grows with screen height (we measured a 412px hole at 430x932).

     NN/g calls the result the "illusion of completeness": on Maple.com 6 of 8
     test users never scrolled past a full-screen autoplaying hero video. The
     documented fix is to let the next section peek above the fold — which is
     exactly what subtracting from the viewport buys us.

     Every major builder does this rather than a bare 100vh:
       Pella          calc(100svh - 59px)
       Pulte          calc(100vh  - 59px)
       Toll Brothers  calc(100vh  - 190px)
       David Weekley  min-height: 90vh

     svh not dvh: dvh re-triggers layout on every toolbar slide and can't
     animate smoothly. svh is the small-viewport (toolbars visible) value, so
     the hero is stable and never taller than the visible area. vh first as
     the fallback for browsers without svh.
     --------------------------------------------------------------------- */
  .hero-rebuild {
    display: flex !important;
    flex-direction: column !important;
    position: relative;
    /* 70px navbar + ~62px of the next section showing through. */
    min-height: calc(100vh - 132px) !important;
    min-height: calc(100svh - 132px) !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
  }

  /* Bottom-weighted scrim, matching the pattern every builder site uses
     (Lennar: rgba(0,0,0,.5) -> transparent, bottom-to-top). The copy now
     lives in one group at the base, so the darkness belongs there and the
     top two-thirds of the footage stays clear.

     0.0001 rather than 0 at the light end dodges Safari's
     gradient-to-transparent grey-shift bug — the trick Pulte uses. */
  .hero-rebuild__scrim {
    background: linear-gradient(
      to top,
      rgba(12, 26, 42, 0.92) 0%,
      rgba(12, 26, 42, 0.86) 22%,
      rgba(12, 26, 42, 0.62) 42%,
      rgba(12, 26, 42, 0.32) 60%,
      rgba(12, 26, 42, 0.12) 78%,
      rgba(12, 26, 42, 0.0001) 100%
    ) !important;
  }

  /* Belt-and-braces legibility for the frames where the sky blows out. */
  .hero-rebuild__title,
  .hero-rebuild__sub {
    text-shadow: 0 2px 14px rgba(10, 20, 34, 0.55) !important;
  }

  /* ONE bottom-anchored group: kicker, headline, sub and CTAs travel together
     over the dark end of the scrim. Previously the text was pinned top and the
     buttons pinned bottom, which is what opened the hole between them.

     align-items:flex-end is the mobile half of Ahmad Shadeed's pattern
     (`place-content: end start` on mobile, `center start` on desktop) — one
     alignment flip, no duplicated markup. */
  .hero-rebuild__inner {
    flex: 1 1 auto;
    display: flex;
    align-items: flex-end !important;
    min-height: 0;
    /* 24px each side left only 342px of measure, which pushed the larger
       subhead to four lines. */
    padding-left: 16px !important;
    padding-right: 16px !important;
  }
  .hero-rebuild__content {
    /* No top padding needed now that the group sits at the base — the video
       occupies the space the navbar used to overlap. */
    padding-top: 20px !important;
    padding-bottom: 20px !important;
    width: 100%;
    max-width: none !important;
  }

  /* Trust bar over the video at the very bottom of the hero. It was already
     the last child; the flex column plus the transparent-to-dark gradient
     makes it read as part of the footage rather than a separate band. */
  .hero-rebuild__trust {
    margin-top: auto;
    border-top: 1px solid rgba(201, 159, 98, 0.28) !important;
    background: linear-gradient(
      to bottom,
      rgba(15, 30, 48, 0.55) 0%,
      rgba(15, 30, 48, 0.85) 100%
    ) !important;
    padding-bottom: env(safe-area-inset-bottom);
  }
  /* Keep it to ONE line over the video. All four items wrapped to three
     rows at 375px, which made an 81px band across the footage and left no
     room for the scroll hint. The two longest items are hidden here; the
     hero sub already names the cities, and "Fire Rebuilds Underway" is the
     entire next section. Desktop still shows all four. */
  .hero-rebuild__trust-inner {
    padding: 11px 20px !important;
    font-size: 9.5px !important;
    gap: 0 16px !important;
    flex-wrap: nowrap !important;
    white-space: nowrap;
  }
  .hero-rebuild__trust-wide {
    display: none !important;
  }

  /* ---- Scroll indicator -------------------------------------------------
     The .hero-scroll__hint element is already in the markup but
     hero-scroll-build.css:11-13 sets display:none, and only re-enables it
     under html.hero-scroll-on, which is desktop-only (min-width 768px).
     Show it on mobile, positioned just above the trust bar.
     --------------------------------------------------------------------- */
  /* Hidden now that the CTAs occupy the base of the hero — the hint's slot at
     bottom:58px printed "SCROLL" straight through the Call Now button. The
     buttons sitting on the fold are a stronger scroll affordance anyway. */
  .hero-scroll__hint {
    display: none !important;
  }
  /* "Scroll to build" is the desktop label, where the scroll-scrub actually
     builds the house frame by frame. On mobile the video just autoplays, so
     that copy would be describing something that doesn't happen. */
  .hero-scroll__hint-desktop { display: none !important; }
  .hero-scroll__hint-mobile { display: inline !important; }

  .hero-scroll__hint span {
    font-family: 'Montserrat', sans-serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.75);
  }
  /* Chevron built from two borders on the existing empty <i>. */
  .hero-scroll__hint i {
    width: 9px;
    height: 9px;
    border-right: 2px solid rgba(201, 159, 98, 0.95);
    border-bottom: 2px solid rgba(201, 159, 98, 0.95);
    transform: rotate(45deg);
    animation: mcv-hint 1.8s ease-in-out infinite;
  }
  /* Fade the hint out once the visitor starts scrolling; JS adds the class. */
  .hero-scroll--started .hero-scroll__hint,
  body.mcv-scrolled .hero-scroll__hint {
    opacity: 0;
    transition: opacity 300ms ease;
  }

  /* Hero trust bar: original four items, unchanged. */


  /* ==================================================================
     9. STICKY CALL + INQUIRE BAR
     Injected by js/mobile-conversion.js. Class is .mcv-* deliberately:
     mobile-enhancements.js:22 writes inline transform on .cta-button,
     and an inline transform on a fixed ancestor creates a containing
     block, which would break position:fixed.
     ================================================================== */
  /* mobile-optimizations.css:14-16 applies `transform: translateZ(0)` to
     EVERY element under 768px as a GPU-acceleration hack. A transform on
     <body> makes body the containing block for fixed descendants, which
     breaks position:fixed entirely. Exempt body and html so the sticky bar
     and sheet resolve against the viewport.
     Also exempts the carousel tracks, whose scroll containers misbehave
     with a forced transform. */
  html, body {
    transform: none !important;
  }

  .mcv-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    /* above navbar(1000) and nav overlay(999); below sidenav(1002)
       and all modals(9000+) */
    z-index: 1001;
    display: flex;
    gap: 10px;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
    background: rgba(18, 40, 63, 0.97);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-top: 1px solid rgba(201, 159, 98, 0.35);
    /* start hidden; JS adds .is-visible once the hero scrolls away */
    transform: translateY(110%);
    transition: transform 260ms ease;
  }
  .mcv-bar.is-visible { transform: translateY(0); }

  /* Hide while the hamburger menu is open. body.nav-open is set by
     main.js:23, so this is a free existing hook. */
  body.nav-open .mcv-bar { transform: translateY(110%); }

  .mcv-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 50px;           /* >=48px touch target */
    border-radius: 2px;         /* matches hero-rebuild.css buttons */
    font-family: 'Montserrat', sans-serif;
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-decoration: none;
    border: 1px solid transparent;
    cursor: pointer;
  }
  /* 60/40 split favoring Call: phone leads convert far better */
  .mcv-btn--call {
    flex: 1.5 1 0;
    background: #b5894e;
    color: #12283f;
  }
  .mcv-btn--call:active { background: #c39a60; }
  .mcv-btn--inquire {
    flex: 1 1 0;
    background: transparent;
    color: #fff;
    border-color: rgba(255, 255, 255, 0.45);
  }
  .mcv-btn--inquire:active { background: rgba(255, 255, 255, 0.1); }
  .mcv-btn svg { width: 16px; height: 16px; flex: 0 0 auto; }
  .mcv-btn:focus-visible { outline: 2px solid #c99f62; outline-offset: 2px; }

  /* Reserve the bar's height so it never covers the footer and its
     appearance costs no layout shift (CLS). */
  body.mcv-has-bar {
    padding-bottom: calc(70px + env(safe-area-inset-bottom));
  }


  /* ==================================================================
     10. QUICK FORM SHEET
     Bottom sheet, 3 fields, one screen. Posts to the same Netlify
     "contact" form so existing notifications keep working.
     ================================================================== */
  .mcv-sheet {
    position: fixed;
    inset: 0;
    z-index: 1003;             /* above the bar, below modals */
    display: flex;
    align-items: flex-end;
    /* hidden by default without display:none, so the transition runs */
    visibility: hidden;
    opacity: 0;
    transition: opacity 220ms ease, visibility 220ms ease;
  }
  .mcv-sheet.is-open { visibility: visible; opacity: 1; }

  .mcv-sheet__scrim {
    position: absolute;
    inset: 0;
    background: rgba(15, 30, 48, 0.55);
  }
  .mcv-sheet__panel {
    position: relative;
    width: 100%;
    max-height: 92vh;
    overflow-y: auto;
    background: #fff;
    /* !important because several files carry blanket `border-radius:0
       !important` rules for mobile (21 instances across the CSS). */
    border-radius: 14px 14px 0 0 !important;
    padding: 22px 20px calc(22px + env(safe-area-inset-bottom));
    transform: translateY(16px);
    transition: transform 260ms ease;
  }
  .mcv-sheet.is-open .mcv-sheet__panel { transform: translateY(0); }

  .mcv-sheet__close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 40px;
    height: 40px;
    border: 0;
    background: transparent;
    color: #666;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
  }
  .mcv-sheet__title {
    font-family: 'Montserrat', sans-serif;
    font-size: 1.3rem;
    font-weight: 700;
    color: #1c3f60;
    margin: 0 34px 6px 0;
  }
  .mcv-sheet__sub {
    font-size: 0.95rem;
    line-height: 1.5;
    color: #666;
    margin: 0 0 18px;
  }
  .mcv-field { margin-bottom: 14px; }
  .mcv-field label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #1c3f60;
    margin-bottom: 6px;
  }
  /* Project-type chips. Replaces a <select>, which on iOS opens a wheel
     picker docked to the bottom of the screen and collides with the sheet.
     Two columns so all eight options are visible without scrolling. */
  .mcv-chips {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }
  .mcv-chip {
    min-height: 44px;            /* touch target */
    padding: 10px 8px;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.85rem;
    font-weight: 500;
    color: #1c3f60;
    background: #fff;
    border: 1px solid #d8dde3;
    border-radius: 2px;
    cursor: pointer;
    text-align: center;
    line-height: 1.25;
  }
  .mcv-chip.is-selected {
    background: #1c3f60;
    border-color: #1c3f60;
    color: #fff;
    font-weight: 600;
  }
  .mcv-chip:focus-visible {
    outline: 2px solid #b5894e;
    outline-offset: 2px;
  }

  .mcv-field input,
  .mcv-field select {
    width: 100%;
    /* 16px exactly: anything smaller makes iOS Safari zoom on focus */
    font-size: 16px;
    font-family: 'Montserrat', sans-serif;
    padding: 13px 14px;
    border: 1px solid #d8dde3;
    border-radius: 2px;
    background: #fff;
    color: #333;
  }
  .mcv-field input:focus,
  .mcv-field select:focus {
    outline: none;
    border-color: #b5894e;
    box-shadow: 0 0 0 3px rgba(181, 137, 78, 0.15);
  }
  .mcv-sheet__submit {
    width: 100%;
    min-height: 52px;
    margin-top: 4px;
    background: #b5894e;
    color: #12283f;
    border: 0;
    border-radius: 2px;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
  }
  .mcv-sheet__submit:disabled { opacity: 0.6; }
  .mcv-sheet__note {
    font-size: 0.82rem;
    line-height: 1.5;
    color: #777;
    text-align: center;
    margin: 12px 0 0;
  }
  .mcv-sheet__note a { color: #1c3f60; }
  .mcv-sheet__error {
    display: none;
    background: #fdf2f2;
    border: 1px solid #f5c6c6;
    color: #a33;
    font-size: 0.88rem;
    line-height: 1.5;
    padding: 10px 12px;
    border-radius: 2px;
    margin-bottom: 12px;
  }
  .mcv-sheet__error.is-shown { display: block; }
}

/* Scroll-hint chevron nudge. Outside the media query because keyframes are
   not scoped by it, but only referenced by the mobile rule above. */
@keyframes mcv-hint {
  0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: 0.9; }
  50%      { transform: rotate(45deg) translate(3px, 3px); opacity: 0.5; }
}

/* Reduced motion: keep everything functional, drop the sliding. */
@media (max-width: 767px) and (prefers-reduced-motion: reduce) {
  .hero-scroll__hint i { animation: none; }
  .mcv-bar,
  .mcv-sheet,
  .mcv-sheet__panel,
  .mcv-dot { transition: none; }
  .mcv-row,
  .testimonials-section .testimonials-grid,
  .wwd-section .wwd-featured-secondary,
  .cities-gallery { scroll-behavior: auto; }
}
