/* ============================================================
   device-switch.css — THE ONLY HAND-WRITTEN CSS IN THIS BUILD.

   Duda serves three separate documents (desktop / tablet / mobile),
   each with its own header markup and its own stylesheet. This
   rebuild is one responsive document, so all three header blocks
   are present and gated by the same breakpoints Duda itself uses:

     mobile   <= 767px
     tablet   768px - 1024px   (laid out on a 960px canvas, as the
                                original's <meta viewport> dictates)
     desktop  >= 1025px

   Everything else on the page is Duda's own CSS, ported unchanged.
   ============================================================ */

@media (max-width: 767px) {
  .tbc-dev-desktop,
  .tbc-dev-tablet {
    display: none !important;
  }
}

@media (min-width: 768px) and (max-width: 1024px) {
  .tbc-dev-desktop,
  .tbc-dev-mobile {
    display: none !important;
  }
}

@media (min-width: 1025px) {
  .tbc-dev-tablet,
  .tbc-dev-mobile {
    display: none !important;
  }
}

/* Duda's runtime injects the drawer's open/closed state. Without its JS the
   drawer must start closed; the layout's script drives it from here. */
.tbc-drawer-closed {
  display: none !important;
}

/* The tablet and mobile documents have no #iscrollBody — only the desktop one
   does. Our single document keeps it (desktop rules need it), so below 1025px
   its inherited `.dmBodyNoIscroll #iscrollBody { overflow-y: auto }` has to be
   neutralised. Left as-is it becomes an inner scroll container and the page
   paints offset from its own layout in a full-page screenshot. */
@media (max-width: 1024px) {
  #iscrollBody {
    overflow: visible !important;
    height: auto !important;
  }
}

/* Duda runs skrollr parallax on the DESKTOP document only — the tablet and
   mobile documents load a runtime that never initialises it, so their parallax
   rows keep the CSS default. The markup here was captured from the desktop DOM
   after skrollr had run, so it carries that frozen state inline
   (`class="… skrollable skrollable-between"` + `style="background-position:
   50% -25.5426px"`). Inline styles beat any normal rule, so below 1025px the
   desktop offset has to be undone explicitly. Where Duda's own mobile sheet
   already pins one of these rows (it does for u_1325247579), its id-level
   selector outranks this and still wins. */
@media (max-width: 1024px) {
  .skrollable[style*="background-position"] {
    background-position: 0% 0% !important;
  }
}

/* Duda gates its scroll-in animations from CSS:

     .dmDesktopBody:not(.editGrid) [data-anim-desktop]:not([data-anim-desktop="none"])
       { visibility: hidden }

   and its runtime clears that once the widget scrolls into view. This build has
   no animation runtime, so without an override the widget stays hidden forever.
   One element on the site is affected — the green panel on
   /basement-finishing-west-boxbury — and the end state a visitor sees is
   visible, so that is what ships. */
[data-anim-desktop]:not([data-anim-desktop="none"]),
[data-anim-tablet]:not([data-anim-tablet="none"]),
[data-anim-mobile]:not([data-anim-mobile="none"]) {
  visibility: visible !important;
}

/* Photo galleries are the other widget Duda lays out in JavaScript rather than
   CSS: it reads data-desktop-columns / data-mobile-columns and builds a grid of
   .photogallery-row > .photogallery-column.column-N at runtime. A static copy
   can only carry one grid, so each gallery ships both — the one Duda builds at
   >= 768px and the one it builds at <= 767px — and the breakpoint picks. */
@media (max-width: 767px) {
  .dmPhotoGallery > .layout-container.tbc-gal-large {
    display: none !important;
  }
}

@media (min-width: 768px) {
  .dmPhotoGallery > .layout-container.tbc-gal-small {
    display: none !important;
  }
}

/* The forms carry no reCAPTCHA. Duda's site key belongs to Duda's own account
   and is registered to Duda-hosted domains, so it cannot validate here — it
   would either fail closed and swallow real leads or render nothing at all.
   The widget is removed outright rather than left as a reserved gap, and this
   honeypot is the spam protection: a field no human sees, which the handler
   uses to drop bots. It must stay empty and stay out of the tab order. */
.dmform-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---------------------------------------------------------------------------
   Google Business Profile map — a deliberate addition to the footer, not a
   ported Duda element. Full-bleed band across the top of the footer, capped at
   300px tall so it reads as a banner rather than taking over the page.
   --------------------------------------------------------------------------- */
.tbc-footer-map {
  width: 100%;
  max-height: 300px;
  overflow: hidden;
  line-height: 0; /* kill the inline-element descender gap under the iframe */
}
.tbc-footer-map iframe {
  display: block;
  width: 100%;
  height: 300px;
  max-height: 300px;
  border: 0;
}
@media (max-width: 767px) {
  .tbc-footer-map,
  .tbc-footer-map iframe { height: 220px; max-height: 220px; }
}

/* Privacy Policy / Terms links in the footer copyright block. Inherits the
   copyright block's own colour; only the underline is added so they read as
   links against the surrounding plain text. */
.tbc-legal-links { margin-top: 4px; }
.tbc-legal-links a { text-decoration: underline; color: inherit; }
.tbc-legal-links span { opacity: 0.55; }

/* Privacy / Terms note under the contact form, after all fields. */
.tbc-form-legal { clear: both; padding: 14px 2px 0; }
.tbc-form-legal p { margin: 0; font-size: 13px; line-height: 1.5; opacity: 0.8; }
.tbc-form-legal a { text-decoration: underline; color: inherit; }

/* ------------------------------------------------------------------
   Drawer stacking.

   The hamburger panel and its scrim each sit in their own wrapper div,
   so Duda's z-index values (drawer 13, scrim 6) never get compared —
   the wrappers themselves paint in DOM order. The scrim is a
   full-viewport box with pointer-events:all, so it was covering the
   open panel: clicks on a nav link hit the scrim, which closed the
   menu instead of following the link. These give the wrappers the same
   order Duda's own values intend.
   ------------------------------------------------------------------ */
.tbc-overlay-layer { position: relative; z-index: 6; }
.tbc-drawer-layer  { position: relative; z-index: 13; }

/* Duda's scrim is a full-viewport box with `pointer-events: all`, and it wins
   hit-testing over the open panel even though the panel's z-index is higher —
   the two sit in sibling wrappers, so their own z-indexes never get compared.
   The visible result was that every click inside the open menu landed on the
   scrim: the menu closed and the link was never followed.

   Rather than keep fighting the stacking, the scrim stops taking pointer
   events at all. It still dims the page exactly as before, and closing by
   clicking outside the panel is handled in Layout.astro's drawer script,
   which now closes on any click that is not inside the drawer or on the
   trigger — so the behaviour is unchanged and links work. */
.layout-drawer-overlay { pointer-events: none !important; }

/* ------------------------------------------------------------------
   Tablet header — clear the hamburger.

   `hamburger-reverse` pins the trigger to the right edge (right: 18px,
   52x52), and the tablet header puts both phone numbers in the right
   column, so the button sat on top of the mobile number. Pull that
   column in far enough to clear the button and leave a gap. Scoped to
   the tablet band and to the tablet header block, so the desktop and
   mobile headers are untouched.
   ------------------------------------------------------------------ */
@media (min-width: 768px) and (max-width: 1024px) {
  /* The phone block sits in a medium-4 column (a third of the 960 canvas).
     Reserving 68px of it for the button leaves "Office: 508-541-9159" too
     little room and it breaks onto a second line, which makes the header
     taller. So the two columns are re-proportioned instead: the logo has room
     to spare, the phone block gets what it needs, and the numbers move left
     off the button while staying one line each.

     Duda already sets `div.u_1500309195 { padding: 0 0 0 18px !important }`,
     so the padding override needs the extra specificity and !important. */
  #hamburger-header div.u_1451116217 {
    width: 54% !important;
  }
  #hamburger-header div.u_1500309195 {
    width: 46% !important;
    padding-left: 0 !important;
    padding-right: 68px !important;
  }

}

/* ------------------------------------------------------------------
   Drawer open transform.

   Duda opens the panel with
     .runtime-module-container:not(.layout-drawer_push-content)
       .layout-drawer[open] { transform: translate(0) }
   but in this single responsive document that rule loses to the
   closed `translateX(100%)` that `data-origin="side-reverse"` carries,
   so setting the `open` attribute left the panel parked off-screen:
   the menu looked like it did nothing, and the click that opened it
   landed on the page behind. State it explicitly, keyed off the same
   two things Duda keys off — the `open` attribute on the panel and
   `layout-drawer_open` on the wrapper — and keep Duda's own easing.
   ------------------------------------------------------------------ */
#dm-outer-wrapper.layout-drawer_open .layout-drawer[open] {
  transform: translateX(0) !important;
}

/* ------------------------------------------------------------------
   Mobile spacing corrections on the home page.

   Three fixes from the pre-launch review, all scoped to the mobile
   band and to specific Duda widget ids, so tablet and desktop keep the
   spacing they were captured with. Each overrides an `!important`
   value in mobile/s096.css, which is why they carry !important too.
   ------------------------------------------------------------------ */
@media (max-width: 767px) {
  /* "Update Your Property's Look…" is pulled up by -200px. That overlap
     is deliberate on desktop, where the paragraph above is short enough
     to sit clear of it, but at 375px the same copy runs several lines
     longer and the green panel cut straight through the end of it —
     the sentence was unreadable. The pull is dropped on mobile so the
     panel starts below the text; tablet and desktop keep it. */
  #dm .dmBody div.u_1840769613 {
    margin-top: 0 !important;
  }

  /* "Trust a Skilled Home Remodeling Contractor…" was padded
     15px top / 200px bottom, leaving a large gap under it that
     matched nothing. Bottom now matches the top. */
  #dm .dmBody div.u_1683540992 {
    padding-bottom: 15px !important;
  }

  /* The photo beside "Your One and Only Solution for Exterior Home
     Remodeling" is a column background. Mobile set `contain`, so it
     letterboxed inside its column instead of filling it; desktop uses
     `cover`, which is what makes it sit flush. */
  #dm .dmBody div.u_1403522319 {
    background-size: cover !important;
  }
}
