/* Hand-written overrides for this migration.
 *
 * DELIBERATELY OUTSIDE site/public/styles/ (gotcha 49): tools/port-css.mjs owns that
 * directory and clears its own hashed outputs on every run, so a hand-written sheet
 * placed there is deleted by the next port with no error anywhere — on one site that
 * silently removed the sheet that hides the inactive device bands, and all three
 * headers then rendered at every width.
 *
 * EVERY NUMBER BELOW MUST BE CENSUSED ON THIS SITE. That sentence is here because this
 * file has now arrived describing the wrong repo TWICE in this chain — once from two
 * generations back, whose structural section described the CLASSIC Duda template
 * (StandardLayoutMultiD / Hamburger / mobileHamburgerLayout) on a site that is FLEX, and
 * again into this repo carrying the previous FLEX site's own measurements. A number in a
 * hand-written sheet is exactly the residue gotcha 63 says survives a copy still looking
 * correct, so every figure below is re-derived here rather than inherited.
 * The RULES were sound and are kept; every measurement around them is re-taken.
 *
 * Population, RE-DERIVED 2026-09-29 — and the figures that stood here until then were the
 * PREVIOUS site's, which makes this the THIRD time this file has arrived describing the wrong
 * repo and the first time it happened underneath the paragraph warning about it. It read
 * "pages.txt holds 59 paths - 44 static plus the 15 blog posts ... so 177 captures (59 pages
 * x 3 bands) plus all 59 raw served documents". This site:
 *
 *   pages.txt                 25 paths
 *   generated/blog.rss        15 <item>s
 *   desktop captures          25 documents (75 across the three bands)
 *
 * The static/post split is deliberately NOT stated: deriving it wrongly is how the line above
 * got here. Count it from those two files when you need it.
 *
 * That the warning survived the copy while its own numbers did not is the whole lesson. A
 * reader who checks ONE figure and finds it right trusts the rest, so a partially re-censused
 * header is more dangerous than a wholly foreign one.
 *
 * Keep this file minimal. Anything that can come from the ported cascade should.
 */

/* The honeypot. Positioned off-screen rather than display:none — bots skip obviously
 * hidden fields, and taking it out of flow means it costs no layout, which the pixel
 * gate would otherwise measure. Live has NO honeypot on either of this site's two
 * forms, so this is ours and must cost nothing.
 *
 * /migration phase 8 specifies exactly this and one fleet repo shipped the spec
 * unimplemented — its honeypot rendered as an ordinary 40px text field and read as a
 * 46px layout defect. */
.mg-hp {
  position: absolute !important;
  left: -9999px !important;
  top: auto !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden !important;
}

/* SPECIFICITY NOTE — read before editing any rule below.
 *
 * Duda emits a per-widget rule for EVERY widget on the site, shaped
 *
 *     #dm .dmBody div.u_1213107879 { display: block !important }
 *
 * That is (1,2,1) and it is `!important`. A hide written as a plain
 * `.mg-only-t { display:none !important }` is (0,1,0), so with `!important` on both
 * sides SPECIFICITY decides and Duda's rule wins — the element stays visible and
 * nothing in the console says so.
 *
 * So every gate below repeats its class three times behind `#dm`, giving (1,3,0),
 * which outranks (1,2,1) on class count without relying on source order. Do not
 * "tidy" the repetition away.
 */

/* ---------------------------------------------------------------------------
 * BLOG PAGINATION — ONE REAL CONTROL, ON ONE PAGE.
 *
 * Censused on the raw served html of all 38 pages (the pages.txt population) and
 * confirmed by driving live's own control. The blog-widget record count is DERIVED,
 * not typed: generated/blog-widgets.json covers /blog plus the 15 posts
 * generated/blog.rss declares — 20 blog-list pages x 3 bands = 60 records:
 *
 *   /blog             declared 19, visible 10   NUMBERED PAGER, REPLACES
 *                     <nav class="pagination-nav"> x1,
 *                     more-posts-text-container x0 (zero on all 38 pages).
 *                     data-paginate-total-elements=19, page size 10; its links carry
 *                     data-page and data-action="paginate" and SWAP the visible set
 *                     rather than appending to it. It is the only page on which the
 *                     live driver finds a control at all, which is that run's own
 *                     positive control.
 *
 *   19 blog posts     declared 18, visible 15   NO CONTROL AT ALL
 *                     pagination-nav x0, more-posts-text-container x0. LIVE ITSELF
 *                     strands the other three — recorded per post in
 *                     blog-widgets.json as shape "none", steps [15]. So there is
 *                     nothing to reveal there and nothing to hide; the rule below
 *                     has no subject on those 19 pages.
 *
 * The numbered pagination-nav IS this site's shape and it is on /blog alone; the
 * "show more / appends" shape the inherited file described has no instance here.
 *
 * blog.rss independently declares 19 items, which is the cross-check that makes a
 * truncated /blog fail rather than ship quietly, and the alias set driven out of
 * /blog equals it exactly in both directions — 19 = 19, empty each way.
 *
 * A static build has no Duda backend, so every card ships and the ones past the
 * first page are stamped mg-blog-hidden with data-mg-blog-page; runtime.js reveals
 * them in live's own page size of 10, replacing the visible set rather than
 * appending to it. This rule is what hides them initially — 19 declared minus the 10
 * page one shows = 9 cards, on the one page that has a control.
 * ------------------------------------------------------------------------- */
#dm .mg-blog-hidden.mg-blog-hidden.mg-blog-hidden {
  display: none !important;
}

/* display:none DOES NOT CHANGE CHILD INDICES, so shipping the withheld cards
 * silently moves which card is :last-child — gotcha 69.
 *
 * Duda's own rule is `.postArticle:not(:last-child){padding-bottom:Npx}`. On live the
 * last VISIBLE card is genuinely :last-child and takes none of it. In our build it is
 * followed by hidden siblings, so it stops matching and GAINS that padding, pushing
 * the control and the whole footer down by a constant amount — the signature of one
 * shared element rather than a per-page fault.
 *
 * *** MEASURED ON THIS SITE, AND IT IS ARMED HERE — 30px, ON EXACTLY ONE CARD. ***
 * The comment this file arrived with said the rule was "currently inert here" because
 * every `:not(:last-child)` padding rule in THAT site's cascade was scoped
 * `[list-layout=recent_posts]` and its layouts did not match. That was a true
 * measurement of a previous client and is false here, which is exactly why an
 * inherited "this does not apply" is worth re-measuring: the matching rule on this
 * site is
 *
 *   #dm [blog-posts-feature-flag=true][list-layout=recent_posts][posts-padding="15"]
 *       .postArticle:not(:last-child){padding-bottom:30px}
 *
 * Every blog POST carries TWO related-posts widgets. Measured per widget with
 * EFFECTIVE visibility (tools/probe-blog-padding2.mjs — a per-element display test is
 * not enough, because a card can be display:block inside a display:none band copy):
 *
 *   live  widget0  5 cards  pad [30,30,30,30, 0]  sum 120
 *   build widget0  5 shown  pad [30,30,30,30,30]  sum 150   <- +30, the whole defect
 *   both  widget1 10 cards  pad [0 x10]           sum   0   (no padding rule matches)
 *
 * That +30 is the gate's dH on all 15 posts at 375 and 768, to the pixel.
 *
 * *** AND THE OVERRIDE BELOW WAS ALREADY PRESENT AND ALREADY MATCHING — IT LOST THE
 * SPECIFICITY FIGHT, WHICH IS THE FAILURE THAT LOOKS LIKE THE RULE NOT BEING THERE.
 * The selector matched (the last visible card's nextElementSibling really is
 * `.postArticle.mg-blog-hidden`), and the card still computed 30px. Counting:
 *
 *   ours   #dm + .postArticle + :not(.mg-blog-hidden) + :has(.postArticle.mg-blog-hidden)
 *          = (1,4,0)   — :has() takes the specificity of its most specific argument
 *   Duda's #dm + 3 attribute selectors + .postArticle + :not(:last-child)
 *          = (1,5,0)   — and it carries NO !important
 *
 * (1,5,0) beats (1,4,0), so the override was outranked and silently did nothing.
 * `!important` is what settles it, because Duda's rule here is not !important — this
 * is gotcha 70's specificity trap and the "a pixel count identical across runs means
 * the fix never took effect" rule arriving together.
 *
 * Keyed on `:has(+ .mg-blog-hidden)` rather than on a stamped class, because that
 * tracks the SEQUENCE as batches are revealed instead of pinning the initial state;
 * runtime.js does not have to re-stamp anything. */
#dm .postArticle:not(.mg-blog-hidden):has(+ .postArticle.mg-blog-hidden) {
  padding-bottom: 0 !important;
}

/* ---------------------------------------------------------------------------
 * PER-DEVICE WIDGET FORKS.
 *
 * THIS SITE IS DUDA **FLEX**, AND ON FLEX THE CHROME DOES NOT FORK — GOTCHA 5 IS
 * INVERTED. Measured over generated/served-by-device (177 documents, 59 paths x 3
 * device UAs, all 200):
 *
 *   dmtemplateid    FlexHeader on ALL THREE BANDS, all 59 pages
 *   <body> class    `dmRoot fix-mobile-scrolling flex-site dmResellerSite`,
 *                   BYTE-IDENTICAL on all three bands, all 59 pages
 *   data-flex-site  present on all three bands, all 59 pages
 *
 * So dmtemplateid CANNOT discriminate the fork here, and gotcha 48/88's
 * dmDesktopBody / dmTabletBody / dmMobileBody classes DO NOT EXIST on this platform.
 * The inherited header asserted three distinct dmtemplateid values across the bands;
 * that is the classic template and it is false here.
 *
 * THE CONTENT FORK IS STILL THREE-WAY, and it is measured on the served BYTES rather
 * than inferred from the template: desktop == tablet on 0 of 59, desktop == mobile on
 * 0 of 59, tablet == mobile on 0 of 59. Tag counts differ across bands on 34 of the 59.
 * generated/served-fork.json inspected 177 of 177 subjects with 0 missing, and its own
 * overlap check found the two independent desktop fetches 59 of 59 byte-identical.
 *
 * THE TABLET DECLARES ITS OWN CANVAS. <meta name="viewport" content="width=960px"> on
 * 59 of 59 tablet captures, against device-width on desktop and mobile. So gotcha 3's
 * 960 canvas DOES apply here — measured, not carried: gotcha 62 exists because that
 * value is a common default and not a platform constant.
 *
 * THE `mg-only-t` GATE THEREFORE CARRIES A CONTENT FORK, NOT A CHROME FORK. The header,
 * drawer and overlay are one shape on every band (#dmFlexHeaderContainer, #flex-header,
 * one #hamburger-drawer, one #layout-drawer-overlay); what differs per band is the page
 * content. THE OCCURRENCE COUNT IS NOT QUOTED because it is not yet measurable —
 * site/src/pages is empty and no page has been built — and an inherited figure here
 * would be a count of another client's build.
 *
 * THE BAND BOUNDARIES ARE DUDA'S OWN, RE-COUNTED ON THIS SITE. The media queries the
 * captured cascade actually contains, over all 383 sheets in generated/live/css:
 *
 *     max-width: 767px   x157      min-width: 768px   x106
 *     max-width: 1024px  x15       min-width: 1025px  x54
 *     min-width: 0px     x29
 *
 * 1025 is therefore the desktop edge on Duda's own declarations rather than by assuming
 * 1024+1. (The inherited counts were 136/92/65/64 over 202 sheets — a different site.)
 *
 * NOT TAKEN ON THIS SITE, AND RECORDED AS MISSING RATHER THAN INHERITED: a live drawer
 * ratio sweep across many widths. The inherited copy carried a 12-width sweep from
 * a previous client (40vw for #hamburger-drawer, 85vw for #mobile-hamburger-drawer
 * at 375). NOT ONE of those numbers is this site's — that site forked two ways with no
 * 960 tablet canvas and used two DIFFERENT drawer elements, while this site has ONE
 * #hamburger-drawer on every band — so they are deleted rather than renumbered. Re-take
 * before quoting a behavioural edge, and mind the UA trap (gotcha 66): Duda picks its
 * document by USER-AGENT, so a desktop UA at a narrow viewport gets the DESKTOP document
 * and reads the wrong element.
 *
 * So, on (a) alone: mobile <=767, tablet 768-1024, desktop >=1025.
 *
 * These hide rather than remove, deliberately — the elements stay in the document so
 * the runtime can still address them, and display:none costs no layout.
 *
 * Only the INACTIVE bands are hidden, inside the media queries. The active band is
 * never touched, so it keeps whatever `display` the ported cascade gives it — hiding
 * all three and restoring one with `display: revert` reverts past the author cascade
 * to the UA default and replaces the widget's real display value with a plain block.
 * ------------------------------------------------------------------------- */
@media (max-width: 767px) {
  #dm .mg-only-d.mg-only-d.mg-only-d,
  #dm .mg-only-t.mg-only-t.mg-only-t {
    display: none !important;
  }
}

@media (min-width: 768px) and (max-width: 1024px) {
  #dm .mg-only-d.mg-only-d.mg-only-d,
  #dm .mg-only-m.mg-only-m.mg-only-m {
    display: none !important;
  }
}

@media (min-width: 1025px) {
  #dm .mg-only-t.mg-only-t.mg-only-t,
  #dm .mg-only-m.mg-only-m.mg-only-m {
    display: none !important;
  }
}

/* ---------------------------------------------------------------------------
 * SLIDERS: TWO WIDGETS ON ONE PAGE, AND THEY DO MOVE. NO RULE IS NEEDED HERE.
 *
 * RE-CENSUSED ON THIS SITE, and the inherited section described the opposite site.
 * That copy asserted 9 single-slide roots across 9 pages with isAutoPlay:false and
 * isFade:true — "nothing to advance to, no arrows to bind" — which is
 * a previous client's shape, not this one.
 *
 * Measured over the 59 served documents: `ssrimageslider` occurs on exactly ONE page,
 * the home page, 6 occurrences. tools/derive-slider-config.mjs reads each widget's own
 * declared autoPagination config and finds TWO widgets, both:
 *
 *     autoPlay=true   interval=7s   pauseOnHover=false   animation=slide
 *
 * So this site's sliders DO auto-advance, on a 7-second interval, and the interval is
 * read from each widget's own payload rather than from runtime.js's inherited constant
 * (gotcha 90: every widget parameter comes from that page's own config, never from the
 * site the driver was written against).
 *
 * TWO CONSEQUENCES FOR THE GATE, both of them the reason this is written down:
 *
 *   (a) An auto-advancing slider can never diff to zero — the two captures land on
 *       different slides — so the home page's slider region is a legitimate --hide
 *       candidate, and whatever is hidden needs a per-element check that asserts
 *       MOTION, because motion is exactly what hiding removes.
 *   (b) The shared check-slider.mjs asserts on `.flexslider` roots, of which this site
 *       has ZERO. It will FATAL on an empty population. That refusal is honest about
 *       ITS subject and says nothing about this site's sliders — "no FlexSlider" must
 *       not be written up as "no sliders".
 *
 * NOT YET VERIFIED ON THE SERVED BUILD — nothing has been built yet (site/src/pages is
 * empty). The population any such run must cover is DERIVED from the census above and
 * not typed: 2 roots on 1 page, x 3 widths.
 * ------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
 * ACCORDION OPEN STATE — recovering a rule the live CSS read cannot see.
 *
 * RE-CENSUSED ON THIS SITE: 23 accordion widgets on 23 of 25 pages, exactly one per
 * page. The inherited section described 34 widgets on 33 of 38
 * pages from 15 distinct ids with a 19/15 firstExpanded split, and named /faq,
 * /request-a-quote and /service-areas — none of which exist here. All of it is
 * a previous client's and is deleted rather than renumbered.
 *
 * THIS SITE, from generated/accordion-config.json (derived from live's own
 * initiateWidget({"type":"SSR_ACCORDION"}) payloads, 0 failing to parse) and
 * corroborated against a `ssraccordion` census of the served html:
 *
 *     22 of 59 served documents carry an accordion
 *     8 DISTINCT widget ids
 *       7 unique per-page widgets — /, /bathrooms, /decks,
 *         /house-remodels-and-additions, /kitchens, /outdoor-spaces,
 *         /whole-house-renovations
 *       1 SHARED widget (1100007106) on all 15 blog posts
 *     EVERY widget: firstExpanded FALSE, closeOthers TRUE, 5 items
 *
 * BOTH FLAGS AGREE SITE-WIDE HERE, which is the opposite of the inherited site and is
 * worth stating rather than leaving implicit: a per-widget stamp is still used, because
 * a site-wide rule that happens to be right today is the shape that ships unnoticed the
 * day one widget differs.
 *
 * ONE PROPERTY DOES VARY, AND IT IS NOT BEHAVIOURAL. The shared blog widget declares
 * layout LAYOUT_1 on 12 posts and LAYOUT_5 on 3. That string is in each page's own
 * served markup, so the port reproduces the difference verbatim without any config
 * knowing about it — checked three ways: build-pages.py takes only closeOthers from the
 * config, runtime.js never reads a layout, and the LAYOUT_N token is present per page.
 *
 * THE REVEAL BEHAVIOUR IS NOT YET MEASURED HERE. The population to cover when it is
 * taken is the 22 pages above.
 *
 * THE CLOSED RULE IS IN THE PORT AND THE OPEN RULE IS NOT, AND THAT IS NOT A PORTING
 * MISTAKE. styled-components insert through the CSSOM, so a class exists in a
 * document's sheet only if that component actually RENDERED with it. Measured over all
 * 59 served documents: 24 <style data-styled> blocks, NONE empty, the CLOSED rule
 * served once per accordion instance, and NO open-state rule served anywhere — zero
 * non-zero max-height declarations in any of those blocks:
 *
 *     closed  .dygwmn  { overflow:hidden; transition:max-height .3s ease-out;
 *                        height:auto; max-height:0 }        served, x22
 *     open    minted per distinct pixel height at runtime   NOT SERVED, x0
 *
 * The inherited copy named three open classes and their heights (.eZPHSz 185px,
 * .eDGbXZ 211px, .crqarE 236px). Those were read off another site and are deleted
 * rather than renumbered; this site's open classes have not been read off live at all,
 * which is exactly why the rule below is keyed on OUR class.
 *
 * THE OPEN CLASS IS MINTED PER DISTINCT PIXEL HEIGHT, so items sharing a height share
 * a class. No open-state name can be hardcoded, and restoring the rule under OUR OWN
 * class is recovering a sheet the live read could not reach.
 * ------------------------------------------------------------------------- */
#dm .mg-acc-open.mg-acc-open.mg-acc-open {
  max-height: 2000px;
}

/* ---- Pre-launch review 2026-09-29 ------------------------------------------ */

/* Legal pages (tools/build-legal-pages.mjs). Duda's reset zeroes margin on p, ul
 * and h2, so the template text would otherwise render as one slab with every
 * heading pressed against the paragraph above it. */
#dm .gy-legal-row {
  max-width: 1200px;
  margin: 0 auto;
  padding: 60px 40px 80px;
  box-sizing: border-box;
}
#dm .gy-legal-row h2 {
  margin: 36px 0 12px;
}
#dm .gy-legal-row p {
  margin: 0 0 14px;
}
#dm .gy-legal-row ul {
  margin: 0 0 14px;
  padding-left: 1.4em;
  list-style: disc;
}
#dm .gy-legal-row li {
  margin: 0 0 4px;
}
@media (max-width: 767px) {
  #dm .gy-legal-row {
    padding: 40px 16px 60px;
  }
}

/* ---------------------------------------------------------------- flex popup --
 * THE TWO HOSTS DUDA'S RUNTIME CREATES FOR A CLICK-TRIGGERED FLEX POPUP (gotcha 105),
 * which runtime.js's flexPopup() creates on a click. They exist only after the click, so
 * no capture holds them and port-css has nothing to port; the <dialog> itself is in the
 * popup page's served markup and its rules come through the ported cascade.
 *
 * Read off a live original with a real hit-tested click (2026-10-01), identical at 1440,
 * 768 and 375:
 *   #flex-popup-overlay            position fixed  z-index 200  rgba(0, 0, 0, 0.533), full viewport
 *   #flex-runtime-popup-container  position fixed  z-index 201  display flex, centred, transparent
 * The dialog's place is CENTRING, not a coordinate. Scroll lock is on BODY. No subject on
 * this site (no trigger in the build): these match nothing here.
 */
#flex-popup-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  background-color: rgba(0, 0, 0, 0.533);
}
#flex-runtime-popup-container {
  position: fixed;
  inset: 0;
  z-index: 201;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: transparent;
}

/* ---- Pre-launch review 2026-10-09 ------------------------------------------ */

/* Tablet/phone drawer sub-menus ("About Us", "Services", "Resources", and "Purelight
 * Customer Support" inside Resources). runtime.js drawer() opens and closes each from
 * its caret; closed is the class gy-sub-closed. The closed state collapses height,
 * padding, border and opacity together (max-height alone clips only the content box),
 * and is !important at doubled id specificity so it outranks the ported cascade's own
 * :hover opener, which a tap leaves stuck on a touch screen. */
#hamburger-drawer#hamburger-drawer li.gy-sub > .unifiednav__container_sub-nav {
  overflow: hidden;
  transition: max-height .3s ease, opacity .2s ease;
}
#hamburger-drawer#hamburger-drawer li.gy-sub.gy-sub-closed > .unifiednav__container_sub-nav {
  max-height: 0 !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  margin-top: 0 !important;
  margin-bottom: 0 !important;
  border-width: 0 !important;
  opacity: 0 !important;
  pointer-events: none !important;
  visibility: hidden;
}
#hamburger-drawer#hamburger-drawer li.gy-sub:not(.gy-sub-closed) > .unifiednav__container_sub-nav {
  opacity: 1 !important;
  pointer-events: auto !important;
}
/* The close (X) follows the panel's scroll (runtime.js drawer()). Its row and the
 * menu's row can each be their own stacking context, and the later one, the menu,
 * would paint over the X once an open group scrolled up under it. */
#hamburger-drawer .hamburgerButton {
  position: relative;
  z-index: 5;
}
#hamburger-drawer div:has(> .hamburgerButton),
#hamburger-drawer div:has(.hamburgerButton) {
  z-index: 5;
}

/* Headings retagged to <h1> by tools/review-content-fixes.py (/blog-search, /partner,
 * /request had no <h1>). Pinned to the <h2> type they were set in, measured before the
 * change at 1440 / 768 / 390: 40px, 36px, 30px on a 1.2 line, weight 600; the
 * /blog-search heading carries its own size classes (32px desktop, 26px phone). */
#dm#dm h1.gy-h1 {
  font-size: 40px !important;
  line-height: 1.2;
  font-weight: 600;
  margin: 0;
  color: rgb(0, 0, 0);
}
#dm#dm h1.gy-h1 span {
  font-size: inherit !important;
  color: rgb(0, 0, 0);
}
#dm#dm h1.gy-h1.size-32,
#dm#dm h1.gy-h1.size-32 span { font-size: 32px !important; }
@media (min-width: 768px) and (max-width: 1024px) {
  #dm#dm h1.gy-h1,
  #dm#dm h1.gy-h1.size-32,
  #dm#dm h1.gy-h1.size-32 span { font-size: 36px !important; }
}
@media (max-width: 767px) {
  #dm#dm h1.gy-h1 { font-size: 30px !important; }
  #dm#dm h1.gy-h1.m-size-26,
  #dm#dm h1.gy-h1.m-size-26 span { font-size: 26px !important; }
}

/* The 404 page. Live's is styled by a Duda system sheet the port never captured, so
 * the page shipped as four lines of unstyled text with a default blue link at the
 * left edge. Every value below is live's own, measured at 1440 and 390: a white
 * centred block with 120px above it, a 130px Oswald "404" with the first 4 leaning
 * 15deg, a 22px message with 45px around it, and a 184x37 grey button. The message is
 * the page's <h1> now, pinned to that same type. */
#dm #error-container {
  padding: 120px 0 0;
  text-align: center;
  background-color: rgb(255, 255, 255);
}
#dm #error-container .four-o-four {
  font-family: Oswald, "Oswald Fallback", sans-serif;
  font-size: 130px;
  font-weight: 400;
  line-height: 193px;
  color: rgb(51, 51, 51);
}
#dm #error-container .four-o-four .lean {
  display: inline-block;
  transform: rotate(15deg);
}
#dm#dm #error-container .description,
#dm#dm #error-container h1.description {
  margin: 45px 0;
  padding: 0;
  font-size: 22px !important;
  font-weight: 400;
  line-height: 27px;
  letter-spacing: normal;
  text-transform: none;
  text-align: center;
  color: rgb(51, 51, 51);
}
#dm #error-container a.back-button {
  display: inline-block;
  box-sizing: border-box;
  width: 184px;
  height: 37px;
  margin: 0 0 20px;
  padding: 0;
  border-radius: 2px;
  background-color: rgb(137, 137, 137);
  color: rgb(255, 255, 255) !important;
  font-size: 16px;
  line-height: 37px;
  text-align: center;
  text-decoration: none !important;
}
#dm #error-container a.back-button:hover,
#dm #error-container a.back-button:focus-visible {
  background-color: rgb(33, 154, 225);
}

/* The call to action closing every blog post (and /faqs): the site's own "Request a
 * Free Quote" button, restated from its measured look (280x55 pill, rgb(33,154,225),
 * white 18px type, 16px on tablet and phone; rgb(77,153,219) on hover), since Duda
 * styles each button by a per-page id rule a new element cannot borrow. */
#dm .gy-post-cta {
  text-align: center;
  padding: 30px 16px 40px;
}
#dm .gy-post-cta.gy-page-cta {
  order: 999;
  width: 100%;
  box-sizing: border-box;
}
#dm#dm .gy-post-cta a.gy-cta {
  display: inline-block;
  box-sizing: border-box;
  width: 280px;
  max-width: 100%;
  height: 55px;
  line-height: 53px;
  padding: 0 16px;
  border: 1px solid transparent;
  border-radius: 50px;
  background-color: rgb(33, 154, 225);
  color: rgb(255, 255, 255) !important;
  font-size: 18px;
  font-weight: 400;
  text-decoration: none !important;
  white-space: nowrap;
  transition: background-color .2s, border-color .2s;
}
#dm#dm .gy-post-cta a.gy-cta:hover,
#dm#dm .gy-post-cta a.gy-cta:focus-visible {
  background-color: rgb(77, 153, 219);
}
@media (max-width: 1024px) {
  #dm#dm .gy-post-cta a.gy-cta { font-size: 16px; }
}

/* "Privacy Policy | Terms & Conditions" under every form's submit button, on one
 * line. clear:both puts it under the floated submit; the 15px above it is padding (a
 * margin collapses against the button's box); runtime.js legalLineAlign() lines it up
 * with the button and gives it the ink of the form's own labels. */
#dm .gy-legal-links--form {
  display: block;
  clear: both;
  width: 100%;
  box-sizing: border-box;
  padding-top: 15px;
  font-size: 13px;
  line-height: 1.6;
  text-align: left;
  white-space: nowrap;
}
#dm#dm .gy-legal-links--form a {
  color: inherit !important;
  text-decoration: underline !important;
}
#dm#dm .gy-legal-links--form a:hover {
  text-decoration: none !important;
}

/* The Google Business Profile map as a footer row, on the pages that do not already
 * close with it. Full width, 300px. */
#dm .gy-footer-map {
  width: 100%;
  height: 300px;
  max-height: 300px;
  overflow: hidden;
  line-height: 0;
}
#dm .gy-footer-map iframe {
  display: block;
  width: 100%;
  height: 300px;
  border: 0;
}

/* The business name linked to the home page in body copy (review-content-fixes.py):
 * the site's own link look, blue and underlined, whatever wrapper it sits in. */
#dm#dm .dmNewParagraph a.gy-home-link {
  color: rgb(33, 154, 225);
  text-decoration: underline;
  font-weight: inherit;
}

/* Desktop header at the narrow end of its range (on live too): below ~1090px the
 * fifth menu item, "Customer Portal", dropped to a second row and the header grew
 * from 97 to 111px; below ~1230px "Get a Quote" broke onto two lines inside its
 * pill. The menu gives up side padding there and the button's label stays on one
 * line in slightly smaller type; 1280 and wider are untouched. */
@media (min-width: 1025px) and (max-width: 1099px) {
  #dm#dm nav[id="1198691314"] > ul > li > a {
    padding-left: 8px !important;
    padding-right: 8px !important;
    font-size: 15px !important;
  }
  #dm#dm nav[id="1198691314"] > ul > li > a .nav-item-text {
    font-size: 15px !important;
  }
}
@media (min-width: 1025px) and (max-width: 1149px) {
  #dm#dm #flex-header [id="04886df1"] {
    padding-left: 6px !important;
    padding-right: 6px !important;
  }
}
@media (min-width: 1025px) and (max-width: 1279px) {
  #dm#dm #flex-header a[id="1540576542"] .text {
    white-space: nowrap;
    font-size: 14px !important;
  }
}

/* Home hero, "Create Energy. / Independence. / Home." (on live too): the rotating
 * word sits in a box wider than its half of the row, so the page scrolled sideways
 * (29px at 1280, 76px at 1100, 12px on a tablet), and below ~1250px the longest
 * word, "Independence.", ran off the right edge of the screen (634px of 90px type in
 * a 506px column at 1100). The hero section clips the spare box, and between 1025 and
 * 1279px both halves of the line scale with the window so the whole word shows;
 * 1280 and wider keep live's 96px / 90px. */
#dm#dm [id="63bd85219866cc362278151f"] {
  overflow-x: clip;
}
@media (min-width: 1025px) and (max-width: 1279px) {
  #dm#dm [id="1980418682"] [class*="d-ext-mediaSlider-content"],
  #dm#dm [id="1980418682"] [class*="d-ext-mediaSlider-content"] p {
    font-size: 7vw !important;
  }
  #dm#dm [id="1220362813"] p,
  #dm#dm [id="1220362813"] p span {
    font-size: 7.47vw !important;
  }
}

/* /about, the team's last row. Live added a third card to it after the capture (Aaron
 * Semliatschenko, Vice President, Field Operations; tools/review-content-fixes.py adds
 * the markup under live's own ids). These are live's rules for that row as served on
 * 2026-10-09, verbatim: the two existing cards went from 50% to 32% wide, and the new
 * group, its photo frame and its two text wrappers arrived with the values below. */
@media (min-width: 768px) {
  #dm [id="35124fff"],
  #dm #df1a9ec4 {
    width: 32%;
  }
}
#dm [id="837a860d"] {
  align-items: center;
  width: 32%;
  min-height: 160px;
  max-height: 100%;
  row-gap: 0px;
  column-gap: 4%;
  order: 1;
  padding: 0%;
  margin: 0%;
}
#dm #e9bd37bc {
  width: 100%;
  height: 500px;
  max-width: 100%;
}
#dm [id="16a0f6f0"] {
  width: 100%;
  height: auto;
  max-width: 100%;
  margin-top: 20px;
}
#dm #d117f201 {
  width: 100%;
  height: auto;
  max-width: 100%;
}
*#dm .dmInner div.u_1635034959 img {
  object-position: 50% 0% !important;
  object-fit: cover !important;
}
@media (min-width: 768px) and (max-width: 1024px) {
  #dm #e9bd37bc {
    height: 250px;
  }
}
@media (max-width: 767px) {
  #dm [id="837a860d"] {
    align-self: center;
    width: 100%;
    max-width: 100%;
    margin: 0px 0%;
  }
  #dm #e9bd37bc {
    height: 400px;
  }
}
