/* ============================================================================
   Home Improvements USA — tokens, fonts, and the rules that are ours.

   This is the last stylesheet in the chain. The three before it are:

     vendor/bootstrap.min.css   Bootstrap 4.5.3, vendored byte-for-byte from the
                                harvest. The markup is written against this grid.
     theme.css                  The theme's own declarations, transcribed from
                                the harvested style.css and main.css.
     lead-form.css              The lead form's stylesheet, from the harvest.

   What belongs here: the token block, the @font-face declarations, and the
   handful of rules the original does not have because it does not have the
   corresponding markup — the skip link, the inline SVG glyphs that replace an
   icon font, and the carousel behaviour that replaces Swiper.

   What does not belong here: anything the theme already declares. If a rule
   exists in style.css or main.css it goes in theme.css, verbatim, with its
   source noted. Prompt 1 rebuilt those rules by hand because the stylesheets
   had not come back in the capture; they have now, and the reconstructions are
   gone.

   No inline <style> and no style= attribute anywhere in the markup: the CSP is
   style-src 'self'.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   Fonts

   Self-hosted, from wwwroot/static/fonts. The original loads these from the
   Google Fonts CDN; that link is deliberately not reproduced. Weights are
   exactly the ones the original's CSS2 request asks for and no others —
   Play 400/700, Roboto 400/700/900 upright and italic.

   Roboto now ships as a variable font, so one file per subset and style covers
   all three weights; the three weights are still declared separately, which is
   the shape the Google CSS uses, so only those three are nameable.

   font-display swap on every face. The alternative is up to three seconds of
   invisible text while a font that is already on this origin loads.

   See fonts/README.md for provenance and licences.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Play";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/play-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Play";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/play-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Play";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/play-700-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Play";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/play-700-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/roboto-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/roboto-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("/static/fonts/roboto-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/roboto-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/roboto-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("/static/fonts/roboto-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Roboto";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/roboto-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Roboto";
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/roboto-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Roboto";
  font-style: italic;
  font-weight: 900;
  font-display: swap;
  src: url("/static/fonts/roboto-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Roboto";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/roboto-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Roboto";
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/roboto-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Roboto";
  font-style: italic;
  font-weight: 900;
  font-display: swap;
  src: url("/static/fonts/roboto-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------------------
   Tokens

   Verbatim from the harvested inline override block, which the page serves as
   <style id="wp-bootstrap-starter-overrides-inline-css"> immediately after the
   main.css link. Names included, so a rule copied from main.css keeps working
   without translation.

   The two font stacks are the one place this block departs from the harvest,
   and only by putting the real families in front. The theme's own values are
   Arial sans-serif and Arial serif, which is what the site falls back to before
   the woff2 arrives — and what it rendered in until this phase, because no font
   binary came back in the capture. main.css itself names Play and Roboto
   directly in a dozen rules, so those families were always the intent; the
   tokens simply did not say so.
   -------------------------------------------------------------------------- */

:root {
  --primary-text: #222222;
  --white: #ffffff;
  --offwhite: #f0f0f0;

  --primary: #1b93d2;
  --primary-alt: #147BA6;
  --secondary: #d80022;
  --secondary-alt: #AA0018;
  --accent: #4AA9E0;
  --accent-alt: #3194BC;
  --cta: rgb(74, 169, 224);
  --cta-alt: rgb(49, 148, 188);
  --dark: #333333;
  --darker: #111111;

  --header-font: "Play", Arial, sans-serif;
  --prehead-font: "Play", Arial, sans-serif;
  --copy-font: "Roboto", Arial, serif;

  /* Named by main.css's .quote-form and .about-section gradients and never
     defined in the harvested token block — the theme ships those two rules
     broken. Declared here at the value the name states: --secondary at 90%
     alpha. Neither rule is ported yet; this is so the next phase that needs
     one does not have to rediscover the gap. */
  --secondary-90: rgba(216, 0, 34, 0.9);

  /* footer.site-footer .bottom-footer names this and the harvest never defines
     it either, so the bottom bar's text colour falls back to inherit. Seashell
     is a named CSS colour; this is that colour. */
  --seashell: #fff5ee;

  /* ---- Type scale, from the harvested WordPress global-styles block ---- */
  --font-size-small: 13px;
  --font-size-normal: 16px;
  --font-size-medium: 20px;
  --font-size-large: 36px;
  --font-size-x-large: 42px;
  --font-size-huge: 42px;

  --font-weight-normal: 400;
  --font-weight-bold: 700;
  --font-weight-black: 900;

  --line-height-body: 1.5;
  --line-height-heading: 1.2;

  /* ---- Spacing scale, from the same block ---- */
  --space-20: 0.44rem;
  --space-30: 0.67rem;
  --space-40: 1rem;
  --space-50: 1.5rem;
  --space-60: 2.25rem;
  --space-70: 3.38rem;
  --space-80: 5.06rem;

  /* ---- Shadows, from the same block ---- */
  --shadow-natural: 6px 6px 9px rgba(0, 0, 0, 0.2);
  --shadow-deep: 12px 12px 50px rgba(0, 0, 0, 0.4);
  --shadow-sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);

  /* ---- Breakpoints (documentation: a custom property cannot be used in a
          media query, so the numbers are repeated literally and these exist to
          name them) ---- */
  --bp-sm: 576px;
  --bp-md: 768px;
  --bp-lg: 992px;
  --bp-xl: 1200px;
  --bp-xxl: 1400px;
  --bp-theme-wide: 1280px;

  --radius: 6px;
}

/* ---------------------------------------------------------------------------
   Accessibility primitives the theme does not have
   -------------------------------------------------------------------------- */

/* One visible focus ring for anything the theme does not already style. The
   theme's own .btn:focus-visible rule in main.css handles buttons and CTAs; it
   exists because box-shadow:none !important on .btn had beaten Bootstrap's
   focus ring and left every control on the site with no focus state at all.
   Same colour as that rule, so the site has one ring rather than two. */
:focus-visible {
  outline: 3px solid #0b5c86;
  outline-offset: 2px;
}

/* Bootstrap 4 ships .sr-only; this is Bootstrap 5's clip-path form of it,
   which is the one that does not collapse text into a single character column
   in some screen-reader and browser pairs. Same class name, so the harvested
   markup's .sr-only spans keep working. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The first focusable element on every page. The original has no skip link at
   all — it ships the underscores .screen-reader-text rule and a
   skip-link-focus-fix script, but no link to focus. */
.skip-link {
  position: absolute;
  top: -100px;
  left: 15px;
  z-index: 400;
  padding: var(--space-30) var(--space-50);
  background: var(--white);
  color: var(--primary-text);
  font-family: var(--header-font);
  font-weight: var(--font-weight-bold);
  text-decoration: none;
  border-radius: var(--radius);
  box-shadow: var(--shadow-natural);
  transition: top 0.15s ease-in-out;
}

.skip-link:focus {
  top: var(--space-30);
}

/* Takes the slack on a short page, so the footer sits at the bottom of the
   viewport instead of partway up it. The harvested #page wrapper does this with
   Bootstrap's d-flex flex-column min-vh-100; the layout keeps that wrapper, and
   this states the two rules rather than spelling them as four utility classes. */
#page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

#content {
  flex: 1 0 auto;
}

/* ---------------------------------------------------------------------------
   Inline SVG glyphs

   The original draws its stars, social marks, phone handset and footer
   separators with Font Awesome 5.15.1. This project has no icon font: the
   harvest carries fontawesome.min.css and none of the six webfont binaries it
   @font-faces, and a glyph that fails to load leaves a screen reader reading a
   private-use codepoint. See the README.
   -------------------------------------------------------------------------- */

/* svg.icon, not .icon: the theme's own markup uses class="icon" on container
   DIVs too — the four-steps icon column and the city-grid pin box — and the
   bare selector was sizing those to 1em (measured: a 50px step icon inside a
   17px float, and the step text 33px wide of the capture). Every glyph this
   project draws is an inline <svg class="icon">, so the element type is the
   precise scope. */
svg.icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  fill: currentColor;
  vertical-align: -0.125em;
}

/* CSP-FORCED RELOCATION, not a design change.

   The harvested footer writes its logo as
   <img style="max-height: 40px;" ... class="img-fluid site-logo">. That
   max-height never reached any stylesheet — it exists only as an inline
   style attribute, which this project's CSP drops (no style-src
   'unsafe-inline'). Without it the 300x200 source renders ~200px wide
   against the capture's ~60px. Same declaration, same element, moved to
   the one place the CSP allows it to live. Logged in
   ORIGINAL-SITE-DEFECTS.md.

   width: auto is part of the same relocation, not an addition. The harvested
   footer <img> has no width/height attributes, so max-height alone scales it
   to 60x40. Ours keeps width="300" height="200" (the house rule for every
   image), and the attribute width would otherwise win over the height clamp
   and render 200x40. auto hands the width back to the 3:2 intrinsic ratio —
   measured against the capture: 60x40 both. */
.site-footer .site-logo {
  max-height: 40px;
  width: auto;
}

/* footer.site-footer .social-menu div a in theme.css sizes the circle and sets
   the colour; the glyph inside it is ours. */
.social-menu .icon {
  width: 16px;
  height: 16px;
  vertical-align: middle;
}

/* The stars themselves are coloured in theme.css, by the selectors the theme
   already had — .review-stars .stars there, .footer-stars here. This is only
   the geometry. */
.stars {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  line-height: 1;
}

.stars .icon {
  width: 1em;
  height: 1em;
}

/* WHITE, and taken from the capture rather than chosen.

   The harvested footer writes the star row as
   <div class="flex space-x-1 text-accent mr-1">. Three Tailwind-shaped class
   names, and not one of them is defined in anything the page loads —
   `grep -r text-accent` over style.css, main.css, bootstrap.min.css,
   fontawesome.min.css and lead-form.css returns nothing. So .text-accent sets
   no colour, the <i class="fas fa-star"> elements inherit from the nearest
   ancestor that does, and that is the column's own .text-white. The stars
   render #fff. Confirmed against the capture: computed colour on the footer
   star is rgb(255, 255, 255).

   This said var(--accent) before, which is #4AA9E0 — it read the class name
   rather than the cascade, and put a blue star row on a page that has a white
   one. The variable is right about what "accent" means and wrong about what
   the footer does with it.

   Deliberately on .footer-stars — the wrapper — and not on .stars, which is
   the partial's own element. Colour reaches the star row by inheritance from
   whatever context it is dropped into, so each context sets its own and the
   partial sets none: white here, and rgb(241, 146, 73) on the testimonial
   cards through `.review-stars .stars` in theme.css. Put either colour on
   .stars itself and the two rows stop being independent — the next context
   that wants a third colour is then fighting a rule inside the component
   rather than writing one beside it. */
.footer-stars {
  color: var(--white);
}

/* ---------------------------------------------------------------------------
   Navigation deltas

   Two rules, both consequences of decisions the original did not make.
   -------------------------------------------------------------------------- */

/* The gallery tab pills are <button>s here, not the original's
   <a data-toggle="tab">, because they switch panes rather than going anywhere
   (see _GallerySection). Everything the theme says about a pill reaches the
   button through the same class selectors — except that a button brings a
   2px default border the anchor never had, which is 4px on each box
   dimension and moves every wrap point in the centred row. Measured against
   the capture: with the border off, the pill boxes match. */
.accordion .nav-pills button.nav-link {
  border: 0;
}

/* The "Company" dropdown heading is a <button> here, not the original's
   <a href="#">, because it opens a menu rather than going anywhere. A button
   needs the chrome taken off it before it can look like the links beside it;
   theme.css supplies the colour, padding and size through the selector it
   already had, widened to reach a button. */
#masthead .navbar-nav > li > button.nav-link {
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  font-weight: inherit;

  /* line-height explicitly, and NOT `font: inherit` or `font-size: inherit`.
     Bootstrap's reboot gives every button `line-height: inherit`, and the
     `inherit` keyword takes the parent's *computed* value — 25.5px, from body's
     17px x 1.5 — rather than the unitless 1.5 that an <a> inherits and
     recomputes. The links beside this button are 16px with a 24px line box; the
     button came out 25.5px, and because .navbar-nav is a stretch flex row every
     item in the bar grew to match. The whole nav bar was 45.5px against the
     original's 44px.

     Stating 1.5 here recomputes it against the 16px theme.css sets, which is
     24px, which is the links. Setting font-size: inherit instead would be worse
     than useless: it has the same specificity as the theme's own rule and loads
     after it, so it would silently take the button back to 17px. */
  line-height: 1.5;
}

/* The section the current page belongs to. The theme marks it with opacity .7
   alone — on a red bar that is a contrast change and nothing else, which is
   colour as the only means of conveying information. The underline is the
   addition; aria-current="page" in the markup is what actually answers the
   question for a screen reader. */
#masthead .navbar-nav > li.current_page_item > a,
#masthead .navbar-nav > li.current_page_item > button.nav-link,
#masthead .navbar-nav .current_page_item > .dropdown-item {
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 2px;
}

/* ---------------------------------------------------------------------------
   Testimonials carousel

   The original runs Swiper: a container, a flex track, and nothing that works
   from a keyboard — the slides are divs, the pagination bullets are divs, and
   "Read more" is a span with a click handler. This is the same layout built on
   scroll-snap, which needs no library, degrades to a plain scrollable row with
   JavaScript off, and is operable with Tab and the arrow keys.

   The class names are the harvest's, so the .swiper-container, .swiper-slide,
   .review-card and .swiper-pagination-bullet declarations transcribed into
   theme.css apply unchanged.
   -------------------------------------------------------------------------- */

.swiper-container {
  display: flex;
  gap: 30px;
  scroll-snap-type: x mandatory;
  /* theme.css carries the original's overflow:hidden, which is right for Swiper
     — it translates the track itself — and wrong here, where the container is
     the scroller. */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}

.swiper-container:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: -3px;
}

.swiper-slide {
  scroll-snap-align: start;
  flex: 0 0 100%;
  min-width: 0;
}

/* The bullets are real buttons rather than the original's divs, so they need
   the button reset; theme.css gives them their size and colour. */
.swiper-pagination-bullet {
  padding: 0;
  border: 0;
  cursor: pointer;
}

.swiper-pagination-bullet:focus-visible {
  outline: 3px solid var(--secondary);
  outline-offset: 3px;
}

/* The clamp lives on a class JavaScript adds, not on .review-text itself. The
   original clamps in CSS and reveals its "Read more" from JavaScript, so with
   scripting off the tail of every long review is unreachable. This way the
   untrimmed review is what a scriptless page shows. */
.review-text.is-clamped {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.review-text.is-expanded {
  -webkit-line-clamp: unset;
}

/* theme.css carries the original's display:none, which JavaScript flips on the
   cards whose text actually overflows. */
.read-more {
  padding: 0;
  background: none;
  border: 0;
  text-align: left;
}

.read-more.is-available {
  display: inline-block;
}

/* ---------------------------------------------------------------------------
   Offer bar

   No rules. The band is .bg-secondary, .border-radius and .p-5 from the theme
   and the grid, and its label is a bare <p class="prehead font-weight-bold
   txt-white mb-0"> — .prehead is not a class the theme declares at all, so the
   label simply renders as bold body text, which is what the original does.

   There was a rule here, and it was wrong in four ways at once: it set the
   label in Play at 16px, uppercased it and tracked it out. Measured against the
   harvest the label is Roboto at 17px, mixed case, normal tracking. It is noted
   rather than silently deleted because "the theme does not declare .prehead" is
   exactly the observation that invites someone to invent one again.
   -------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   Lead form additions

   Everything structural is in lead-form.css, from the harvest. These are the
   pieces that stylesheet does not have, because the original solves them in
   JavaScript and WebAssembly rather than in markup.
   -------------------------------------------------------------------------- */

/* The form is multi-step and JavaScript-driven: every step but the first is
   display:none, and nothing reveals them without script. So the form starts
   hidden and the script that can drive it is what reveals it — otherwise a
   scriptless visitor gets step 1, a dead "Continue" button and no way to
   finish. The notice below is what they get instead.

   The original uses <noscript> for this, which covers scripting switched off
   and not the script failing to load, timing out or throwing. A notice that is
   visible until the script hides it covers both, and needs no second element
   for the second case. */
.hiusa-lead-form {
  display: none;
}

.hiusa-lead.is-ready .hiusa-lead-form {
  display: flex;
}

.hiusa-lead .hiusa-lead-nojs {
  margin: 0;
  padding: 0.75rem 1rem;
  border: 1.5px solid currentColor;
  border-radius: 6px;
  font-weight: 700;
}

/* Shown only while the form is not ready — that is, until the script runs.
   Once it does, the form itself is the answer. */
.hiusa-lead.is-ready .hiusa-lead-nojs {
  display: none;
}

/* ---------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------------------------------------------------------------------------
   Carousel breakpoints — the slidesPerView the original hands to Swiper:
   1 below 768, 2 from 768, 3 from 992.

   The 2-up rule starts at 768.02, not 768, because at exactly 768 the
   original shows ONE slide: its Swiper config says 2-up from 768, but its
   own `@media (max-width: 768px) { .swiper-slide { width: 100% !important } }`
   still applies at that width and !important beats Swiper's inline widths.
   Measured against the capture at 768 — slide 650px (full row), not 310.
   .02 is the same epsilon WordPress uses in the hero breakpoints (767.98).
   -------------------------------------------------------------------------- */

@media (min-width: 768.02px) {
  .swiper-slide {
    flex-basis: calc((100% - 30px) / 2);
  }
}

@media (min-width: 992px) {
  .swiper-slide {
    flex-basis: calc((100% - 60px) / 3);
  }
}

/* ===========================================================================
   CSP-FORCED RELOCATIONS -- page markup styles the original writes inline.

   The harvested pages carry two kinds of inline CSS this project's
   Content-Security-Policy drops: a <style> block WordPress prints at the top
   of <main> for the hero's responsive background images, and style=""
   attributes on individual elements. None of it ever reached a stylesheet on
   the original. Every declaration below is the original's, moved to the one
   place the CSP allows it to live. Logged in ORIGINAL-SITE-DEFECTS.md; the
   rendering was verified against the capture, not assumed.
   ======================================================================== */

/* The Google Tag Manager <noscript> iframe. The harvested tag writes
     style="display:none;visibility:hidden"
   on it; with style-src 'self' that attribute is stripped, and a 0x0 iframe
   that is not display:none still takes part in layout. Both declarations, as
   the original writes them. */
.gtm-noscript {
  display: none;
  visibility: hidden;
}

/* Every hero section carries
     style="background-position: 5% center; background-size: cover;"
   on every harvested page. One rule instead of fifty-one copies. */
.hero-wrap.homepage-hero {
  background-position: 5% center;
  background-size: cover;
}

/* The per-page hero backgrounds, from the <style> block at the top of each
   harvested <main>. Ids are the original's own (WordPress post ids); the
   breakpoints are copied as written -- note the .98s. 3-tab and four window
   children have no responsive variants because the original serves each a
   single default image. */

/* /projects/ */
#gr-hero-2315 { background-image: url('/static/media/uploads/2024/04/IMG_0028-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-2315 { background-image: url('/static/media/uploads/2024/04/IMG_0028-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-2315 { background-image: url('/static/media/uploads/2024/04/IMG_0028-1024x683.webp'); } }

/* / */
#gr-hero-2 { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1701989695_20240301131407-1-1536x976.webp'); }
@media (max-width: 767.98px) { #gr-hero-2 { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1701989695_20240301131407-1-768x488.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-2 { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1701989695_20240301131407-1-1024x651.webp'); } }

/* /roof/ */
#gr-hero-543 { background-image: url('/static/media/uploads/2024/04/4FFC2D6BDC5833DF7D24E9CEC958DC3D1684255139-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-543 { background-image: url('/static/media/uploads/2024/04/4FFC2D6BDC5833DF7D24E9CEC958DC3D1684255139-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-543 { background-image: url('/static/media/uploads/2024/04/4FFC2D6BDC5833DF7D24E9CEC958DC3D1684255139-1024x683.webp'); } }

/* /roof/3-tab/ */
#gr-hero-1020 { background-image: url('/static/media/uploads/2024/04/default-1.webp'); }

/* /roof/asphalt/ */
#gr-hero-1002 { background-image: url('/static/media/uploads/2024/04/IMG_0027-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1002 { background-image: url('/static/media/uploads/2024/04/IMG_0027-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1002 { background-image: url('/static/media/uploads/2024/04/IMG_0027-1024x683.webp'); } }

/* /roof/cedar/ */
#gr-hero-1026 { background-image: url('/static/media/uploads/2024/04/cedar-roof-1-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1026 { background-image: url('/static/media/uploads/2024/04/cedar-roof-1-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1026 { background-image: url('/static/media/uploads/2024/04/cedar-roof-1-1-1024x683.webp'); } }

/* /roof/commercial/ */
#gr-hero-990 { background-image: url('/static/media/uploads/2024/04/gallery_roof-commercial-company-1_20240301131349-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-990 { background-image: url('/static/media/uploads/2024/04/gallery_roof-commercial-company-1_20240301131349-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-990 { background-image: url('/static/media/uploads/2024/04/gallery_roof-commercial-company-1_20240301131349-1024x683.webp'); } }

/* /roof/impact/ */
#gr-hero-1014 { background-image: url('/static/media/uploads/2024/04/IMG_0203-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1014 { background-image: url('/static/media/uploads/2024/04/IMG_0203-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1014 { background-image: url('/static/media/uploads/2024/04/IMG_0203-1024x683.webp'); } }

/* /roof/metal/ */
#gr-hero-1008 { background-image: url('/static/media/uploads/2024/04/IMG_0001-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1008 { background-image: url('/static/media/uploads/2024/04/IMG_0001-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1008 { background-image: url('/static/media/uploads/2024/04/IMG_0001-1024x683.webp'); } }

/* /roof/multi-family/ */
#gr-hero-996 { background-image: url('/static/media/uploads/2024/04/gallery_roof-multi-family-1_20240301131428-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-996 { background-image: url('/static/media/uploads/2024/04/gallery_roof-multi-family-1_20240301131428-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-996 { background-image: url('/static/media/uploads/2024/04/gallery_roof-multi-family-1_20240301131428-1-1024x683.webp'); } }

/* /roof/repair/ */
#gr-hero-972 { background-image: url('/static/media/uploads/2024/04/gallery_roof-repair-leak-1_20240301131308-2-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-972 { background-image: url('/static/media/uploads/2024/04/gallery_roof-repair-leak-1_20240301131308-2-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-972 { background-image: url('/static/media/uploads/2024/04/gallery_roof-repair-leak-1_20240301131308-2-1024x683.webp'); } }

/* /roof/replace/ */
#gr-hero-966 { background-image: url('/static/media/uploads/2024/04/IMG_0222-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-966 { background-image: url('/static/media/uploads/2024/04/IMG_0222-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-966 { background-image: url('/static/media/uploads/2024/04/IMG_0222-1024x683.webp'); } }

/* /roof/residential/ */
#gr-hero-984 { background-image: url('/static/media/uploads/2024/04/IMG_0124-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-984 { background-image: url('/static/media/uploads/2024/04/IMG_0124-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-984 { background-image: url('/static/media/uploads/2024/04/IMG_0124-1024x683.webp'); } }

/* /roof/storm-damage/ */
#gr-hero-978 { background-image: url('/static/media/uploads/2024/04/gallery_roof-storm-wind-1_20240301131222-1536x1026.webp'); }
@media (max-width: 767.98px) { #gr-hero-978 { background-image: url('/static/media/uploads/2024/04/gallery_roof-storm-wind-1_20240301131222-768x513.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-978 { background-image: url('/static/media/uploads/2024/04/gallery_roof-storm-wind-1_20240301131222-1024x684.webp'); } }

/* /gutter/ */
#gr-hero-555 { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1698152248_20240301130925-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-555 { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1698152248_20240301130925-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-555 { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1698152248_20240301130925-1024x683.webp'); } }

/* /gutter/aluminum/ */
#gr-hero-1242 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_426002563_20240301130922-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1242 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_426002563_20240301130922-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1242 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_426002563_20240301130922-1024x683.webp'); } }

/* /gutter/commercial/ */
#gr-hero-1230 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1392761393_20240301130939-2-1536x853.webp'); }
@media (max-width: 767.98px) { #gr-hero-1230 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1392761393_20240301130939-2-768x427.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1230 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1392761393_20240301130939-2-1024x569.webp'); } }

/* /gutter/copper/ */
#gr-hero-1254 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_269004965_20240301130919-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1254 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_269004965_20240301130919-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1254 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_269004965_20240301130919-1-1024x683.webp'); } }

/* /gutter/guards/ */
#gr-hero-1248 { background-image: url('/static/media/uploads/2024/04/gutter-cap-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1248 { background-image: url('/static/media/uploads/2024/04/gutter-cap-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1248 { background-image: url('/static/media/uploads/2024/04/gutter-cap-1-1024x683.webp'); } }

/* /gutter/heater-cap/ */
#gr-hero-1260 { background-image: url('/static/media/uploads/2024/04/gutters-heater-cap-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1260 { background-image: url('/static/media/uploads/2024/04/gutters-heater-cap-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1260 { background-image: url('/static/media/uploads/2024/04/gutters-heater-cap-1-1024x683.webp'); } }

/* /gutter/install/ */
#gr-hero-1212 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1954393924_20240301130901-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1212 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1954393924_20240301130901-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1212 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1954393924_20240301130901-1024x683.webp'); } }

/* /gutter/multi-family/ */
#gr-hero-1236 { background-image: url('/static/media/uploads/2024/04/shutterstock_103239599-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1236 { background-image: url('/static/media/uploads/2024/04/shutterstock_103239599-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1236 { background-image: url('/static/media/uploads/2024/04/shutterstock_103239599-1024x683.webp'); } }

/* /gutter/replace/ */
#gr-hero-1206 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1781719613_20240301130905-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1206 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1781719613_20240301130905-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1206 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1781719613_20240301130905-1024x683.webp'); } }

/* /gutter/residential/ */
#gr-hero-1224 { background-image: url('/static/media/uploads/2024/04/gutter-cap-2-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1224 { background-image: url('/static/media/uploads/2024/04/gutter-cap-2-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1224 { background-image: url('/static/media/uploads/2024/04/gutter-cap-2-1024x683.webp'); } }

/* /gutter/storm-damage/ */
#gr-hero-1218 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_202075513_20240301130903-1-1536x1025.webp'); }
@media (max-width: 767.98px) { #gr-hero-1218 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_202075513_20240301130903-1-768x513.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1218 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_202075513_20240301130903-1-1024x684.webp'); } }

/* /gutter-cap/ */
#gr-hero-2276 { background-image: url('/static/media/uploads/2024/04/IMG_0005-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-2276 { background-image: url('/static/media/uploads/2024/04/IMG_0005-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-2276 { background-image: url('/static/media/uploads/2024/04/IMG_0005-1024x683.webp'); } }

/* /siding/ */
#gr-hero-546 { background-image: url('/static/media/uploads/2024/04/IMG_1886-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-546 { background-image: url('/static/media/uploads/2024/04/IMG_1886-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-546 { background-image: url('/static/media/uploads/2024/04/IMG_1886-1024x683.webp'); } }

/* /siding/aluminum/ */
#gr-hero-1074 { background-image: url('/static/media/uploads/2024/04/aluminum-siding-3-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1074 { background-image: url('/static/media/uploads/2024/04/aluminum-siding-3-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1074 { background-image: url('/static/media/uploads/2024/04/aluminum-siding-3-1024x683.webp'); } }

/* /siding/board-and-batten/ */
#gr-hero-1068 { background-image: url('/static/media/uploads/2024/04/siding-board-batten-2-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1068 { background-image: url('/static/media/uploads/2024/04/siding-board-batten-2-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1068 { background-image: url('/static/media/uploads/2024/04/siding-board-batten-2-1024x683.webp'); } }

/* /siding/fiber-cement/ */
#gr-hero-1062 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1849512127_20240301131107-1-1536x978.webp'); }
@media (max-width: 767.98px) { #gr-hero-1062 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1849512127_20240301131107-1-768x489.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1062 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1849512127_20240301131107-1-1024x652.webp'); } }

/* /siding/multi-family/ */
#gr-hero-1050 { background-image: url('/static/media/uploads/2024/04/shutterstock_144767806-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1050 { background-image: url('/static/media/uploads/2024/04/shutterstock_144767806-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1050 { background-image: url('/static/media/uploads/2024/04/shutterstock_144767806-1-1024x683.webp'); } }

/* /siding/replace/ */
#gr-hero-1032 { background-image: url('/static/media/uploads/2024/04/IMG_5617-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1032 { background-image: url('/static/media/uploads/2024/04/IMG_5617-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1032 { background-image: url('/static/media/uploads/2024/04/IMG_5617-1024x683.webp'); } }

/* /siding/residential/ */
#gr-hero-1044 { background-image: url('/static/media/uploads/2024/04/IMG_1886-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1044 { background-image: url('/static/media/uploads/2024/04/IMG_1886-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1044 { background-image: url('/static/media/uploads/2024/04/IMG_1886-1024x683.webp'); } }

/* /siding/scallop/ */
#gr-hero-1086 { background-image: url('/static/media/uploads/2024/04/siding-scallop-1-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1086 { background-image: url('/static/media/uploads/2024/04/siding-scallop-1-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1086 { background-image: url('/static/media/uploads/2024/04/siding-scallop-1-1-1024x683.webp'); } }

/* /siding/shake/ */
#gr-hero-1080 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1672515259_20240301131105-1536x1025.webp'); }
@media (max-width: 767.98px) { #gr-hero-1080 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1672515259_20240301131105-768x513.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1080 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1672515259_20240301131105-1024x684.webp'); } }

/* /siding/storm-damage/ */
#gr-hero-1038 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1308850942_20240301131054-2-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1038 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1308850942_20240301131054-2-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1038 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1308850942_20240301131054-2-1024x683.webp'); } }

/* /siding/vinyl/ */
#gr-hero-1056 { background-image: url('/static/media/uploads/2024/04/IMG_2583-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1056 { background-image: url('/static/media/uploads/2024/04/IMG_2583-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1056 { background-image: url('/static/media/uploads/2024/04/IMG_2583-1-1024x683.webp'); } }

/* /window/ */
#gr-hero-549 { background-image: url('/static/media/uploads/2024/04/shutterstock_84162844-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-549 { background-image: url('/static/media/uploads/2024/04/shutterstock_84162844-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-549 { background-image: url('/static/media/uploads/2024/04/shutterstock_84162844-1024x683.webp'); } }

/* /window/architectural/ */
#gr-hero-1170 { background-image: url('/static/media/uploads/2024/04/default-12.webp'); }

/* /window/awning/ */
#gr-hero-1140 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2149792505_20240301131152-2-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1140 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2149792505_20240301131152-2-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1140 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2149792505_20240301131152-2-1024x683.webp'); } }

/* /window/bay/ */
#gr-hero-1128 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2232003673_20240301131144-1536x1152.webp'); }
@media (max-width: 767.98px) { #gr-hero-1128 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2232003673_20240301131144-768x576.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1128 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2232003673_20240301131144-1024x768.webp'); } }

/* /window/bow/ */
#gr-hero-1134 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2232003673_20240301131144-1-1536x1152.webp'); }
@media (max-width: 767.98px) { #gr-hero-1134 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2232003673_20240301131144-1-768x576.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1134 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2232003673_20240301131144-1-1024x768.webp'); } }

/* /window/casement/ */
#gr-hero-1122 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1021367125_20240301131202-1536x1536.webp'); }
@media (max-width: 767.98px) { #gr-hero-1122 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1021367125_20240301131202-768x768.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1122 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1021367125_20240301131202-1024x1024.webp'); } }

/* /window/double-hung/ */
#gr-hero-1116 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2044497857_20240301131154-1536x1025.webp'); }
@media (max-width: 767.98px) { #gr-hero-1116 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2044497857_20240301131154-768x513.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1116 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2044497857_20240301131154-1024x684.webp'); } }

/* /window/garden/ */
#gr-hero-1164 { background-image: url('/static/media/uploads/2024/04/default-11.webp'); }

/* /window/multi-family/ */
#gr-hero-1110 { background-image: url('/static/media/uploads/2024/04/shutterstock_144767806-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1110 { background-image: url('/static/media/uploads/2024/04/shutterstock_144767806-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1110 { background-image: url('/static/media/uploads/2024/04/shutterstock_144767806-1-1024x683.webp'); } }

/* /window/picture/ */
#gr-hero-1152 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2260761383_20240301131140-2-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1152 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2260761383_20240301131140-2-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1152 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2260761383_20240301131140-2-1024x683.webp'); } }

/* /window/replace/ */
#gr-hero-1092 { background-image: url('/static/media/uploads/2024/04/shutterstock_748728976-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1092 { background-image: url('/static/media/uploads/2024/04/shutterstock_748728976-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1092 { background-image: url('/static/media/uploads/2024/04/shutterstock_748728976-1024x683.webp'); } }

/* /window/residential/ */
#gr-hero-1104 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2281303735_20240301131205-1536x1130.webp'); }
@media (max-width: 767.98px) { #gr-hero-1104 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2281303735_20240301131205-768x565.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1104 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_2281303735_20240301131205-1024x753.webp'); } }

/* /window/single-hung/ */
#gr-hero-1146 { background-image: url('/static/media/uploads/2024/04/default-9.webp'); }

/* /window/sliding/ */
#gr-hero-1158 { background-image: url('/static/media/uploads/2024/04/default-10.webp'); }

/* /window/storm-damage/ */
#gr-hero-1098 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1546674134_20240301131131-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1098 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1546674134_20240301131131-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1098 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1546674134_20240301131131-1-1024x683.webp'); } }

/* /company/ */
#gr-hero-535 { background-image: url('/static/media/uploads/2024/04/gutter-cap-1-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-535 { background-image: url('/static/media/uploads/2024/04/gutter-cap-1-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-535 { background-image: url('/static/media/uploads/2024/04/gutter-cap-1-1024x683.webp'); } }

/* /gallery/ */
#gr-hero-539 { background-image: url('/static/media/uploads/2024/04/IMG_0011-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-539 { background-image: url('/static/media/uploads/2024/04/IMG_0011-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-539 { background-image: url('/static/media/uploads/2024/04/IMG_0011-1024x683.webp'); } }

/* /reviews/ */
#gr-hero-537 { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_2383731163_20240301131256-1536x1152.webp'); }
@media (max-width: 767.98px) { #gr-hero-537 { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_2383731163_20240301131256-768x576.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-537 { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_2383731163_20240301131256-1024x768.webp'); } }

/* /project-received/ */
#gr-hero-1303 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1954804633_20240301131536-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-1303 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1954804633_20240301131536-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-1303 { background-image: url('/static/media/uploads/2024/04/gallery_shutterstock_1954804633_20240301131536-1024x683.webp'); } }

/* /instant-roof-estimate/ */
#gr-hero-2347 { background-image: url('/static/media/uploads/2024/04/IMG_0203-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-2347 { background-image: url('/static/media/uploads/2024/04/IMG_0203-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-2347 { background-image: url('/static/media/uploads/2024/04/IMG_0203-1024x683.webp'); } }

/* /roof-quote/ — the same photo as the /roof/ hub's hero */
#gr-hero-2515 { background-image: url('/static/media/uploads/2024/04/4FFC2D6BDC5833DF7D24E9CEC958DC3D1684255139-1536x1024.webp'); }
@media (max-width: 767.98px) { #gr-hero-2515 { background-image: url('/static/media/uploads/2024/04/4FFC2D6BDC5833DF7D24E9CEC958DC3D1684255139-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gr-hero-2515 { background-image: url('/static/media/uploads/2024/04/4FFC2D6BDC5833DF7D24E9CEC958DC3D1684255139-1024x683.webp'); } }

/* Two harvested heroes have NO rule here on purpose, both logged in
   ORIGINAL-SITE-DEFECTS.md: /privacy-policy/'s inline style points at
   .../images/heros/ — a directory, which 404s on the live site — and
   /referral/thank-you/'s points at https://home-improvements-usa.local/…,
   the author's local dev host. Both render with no background on the
   original, and reproduce that state by having no rule. */

/* /referral/'s closing hero: an inline background shorthand naming the
   image below at center center / cover, plus height: 300px. The section has
   no id in the harvest, so the rule keys off its position after the intro.
   Position and height are this hero's own; the shared .hero-wrap
   .homepage-hero rule above would say 5% center. */
.referral-intro + .hero-wrap.homepage-hero {
  background: url('/static/media/uploads/2024/03/gallery_shutterstock_1701989695_20240301131407-1.webp') center center;
  background-size: cover;
  height: 300px;
}

/* /referral/'s intro section carries
     style="padding: 40px 0; background-color: #f0f0f0;"
   — #f0f0f0 is the theme's own --offwhite, but the attribute writes the
   literal and so does this. */
.referral-intro {
  padding: 40px 0;
  background-color: #f0f0f0;
}

/* Every gallery thumbnail carries
     style="object-fit: cover; object-position: center; width: 100%; height: 180px;"
   The selector reaches exactly the elements the attribute sat on. */
.gallery-container .expand-link img {
  object-fit: cover;
  object-position: center;
  width: 100%;
  height: 180px;
}

/* /reviews/'s pagination row carries
     style="margin-bottom: 0; margin-top: auto;"
   (the .mb-0 beside it already repeats the first declaration). */
.review-list + .pagination {
  margin-bottom: 0;
  margin-top: auto;
}


/* The photo in every two-column content block carries
     style="max-height: 100%; object-fit: cover;"
   The selector reaches exactly the elements the attribute sat on: the
   .img-fluid.border-radius image inside a .block section's column. */
section.block .col-lg-6 img.img-fluid.border-radius {
  max-height: 100%;
  object-fit: cover;
}

/* The four-steps photo panel:
     <div class="bg-image"> with an inline background-image style
   Page-scoped like the heroes; only the home page has the section today. */
.four-steps .home-process-bg {
  background-image: url('/static/media/uploads/2024/03/company-process.webp');
}

/* The service-hub variant of the service cards writes its equal-height flex
   plumbing inline on every card:

     .card          style="display: flex; flex-direction: column; height: 100%"
     .card-body     style="display: flex; flex-direction: column; flex-grow: 1"
     .card-content  style="flex-grow: 1"
     hr             style="width: 100%; margin-top: auto"
     a.btn          style="margin-top: auto; align-self: flex-end"
     img            style="width: 100%"

   The card and image declarations are no-ops -- Bootstrap's .card is already
   display:flex column, .h-100 is height:100%, and .card-img-top is
   width:100% -- so only the ones that changed anything move here. Scoped with
   :has(> .card-content) because only the hub cards have the .card-content
   wrapper; the home page's service cards share every class but carry none of
   these inline styles, and must not catch the rules (flex suppresses margin
   collapsing, which would change their spacing). */
.services-section .card-body:has(> .card-content) {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
}

.services-section .card-body > .card-content {
  flex-grow: 1;
}

.services-section .card-body:has(> .card-content) hr {
  width: 100%;
  margin-top: auto;
}

.services-section .card-body:has(> .card-content) > a.btn {
  margin-top: auto;
  align-self: flex-end;
}

/* ===========================================================================
   GALLERY LIGHTBOX -- ours, not the theme's.

   The original opens gallery images in Magnific Popup (jQuery). gallery.js
   opens them in a native <dialog> instead; these are the only rules the
   dialog needs, and they exist on no harvested page -- the original's
   equivalent chrome is script-injected markup styled by magnific-popup.css,
   which stays unvendored until something needs the real thing.
   ======================================================================== */

.gallery-lightbox {
  padding: 0;
  border: 0;
  background: transparent;
  max-width: min(92vw, 1200px);
  max-height: 92vh;
}

.gallery-lightbox::backdrop {
  background: rgba(0, 0, 0, 0.8);
}

.gallery-lightbox img {
  display: block;
  max-width: 100%;
  max-height: 92vh;
}

.gallery-lightbox-close {
  position: absolute;
  top: 0;
  right: 0;
  width: 44px;
  height: 44px;
  border: 0;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
}

/* ==========================================================================
   SERVICE CITY PAGES (ours)

   The city pages are deliberately not replicas (see _ServiceCityPage), so
   these rules are this project's own. Each service's hero photo is the one
   the original used on that service's own city pages, in the same three
   renditions at the same breakpoints as every relocated hero rule above;
   one id per service covers all 183 of its cities, because every city page
   of a service shares the photo.

   Roof, gutter, siding and window take the photo from the harvested
   /roof/lisle-il/, /gutter/naperville-il/, /siding/naperville-il/ and
   /window/naperville-il/ heroes. Gutter Cap takes /gutter-cap/'s, and
   heated gutters take /gutter/heater-cap/chicago-il/'s - the two families
   whose city pages the original barely built, so their section's own hero
   is the closest thing to a harvested answer.
   ========================================================================== */

/* /roof/{city-slug}/ */
#roof-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_2124694193_20240301131238-1536x1152.webp'); }
@media (max-width: 767.98px) { #roof-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_2124694193_20240301131238-768x576.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #roof-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_2124694193_20240301131238-1024x768.webp'); } }

/* /gutter/{city-slug}/ */
#gutter-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1698152248_20240301130925-1536x1024.webp'); }
@media (max-width: 767.98px) { #gutter-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1698152248_20240301130925-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gutter-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1698152248_20240301130925-1024x683.webp'); } }

/* /gutter-cap/{city-slug}/ */
#gutter-cap-city-hero { background-image: url('/static/media/uploads/2024/04/IMG_0005-1536x1024.webp'); }
@media (max-width: 767.98px) { #gutter-cap-city-hero { background-image: url('/static/media/uploads/2024/04/IMG_0005-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #gutter-cap-city-hero { background-image: url('/static/media/uploads/2024/04/IMG_0005-1024x683.webp'); } }

/* /siding/{city-slug}/ */
#siding-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_2105916530-1_20240301131117-1536x1024.webp'); }
@media (max-width: 767.98px) { #siding-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_2105916530-1_20240301131117-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #siding-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_2105916530-1_20240301131117-1024x683.webp'); } }

/* /window/{city-slug}/ */
#window-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1524860069-2_20240301131159-1536x1024.webp'); }
@media (max-width: 767.98px) { #window-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1524860069-2_20240301131159-768x512.webp'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #window-city-hero { background-image: url('/static/media/uploads/2024/03/gallery_shutterstock_1524860069-2_20240301131159-1024x683.webp'); } }

/* /heater-cap/{city-slug}/ - the one hero on the site whose renditions are
   PNG, because that is what the original uploaded for it. */
#heater-cap-city-hero { background-image: url('/static/media/uploads/2025/12/heated-gutters.png'); }
@media (max-width: 767.98px) { #heater-cap-city-hero { background-image: url('/static/media/uploads/2025/12/heated-gutters-768x478.png'); } }
@media (min-width: 768px) and (max-width: 1279.98px) { #heater-cap-city-hero { background-image: url('/static/media/uploads/2025/12/heated-gutters-1024x638.png'); } }

/* ============================================================================
   BIRDEYE — the home page's "What our customers say" card, in the left column
   of the Why-homeowners-choose band where the original loads Birdeye's widget
   script. Ours is server-rendered HTML; see Reviews/BirdeyeClient.cs and
   _BirdeyeReviews.cshtml. Not transcribed from the widget's stylesheet — the
   shapes are the widget's (white card, bordered summary strip, three-column
   grid, circular arrows), the type and spacing are this site's.

   The two colours that are not tokens are the widget's own, read from its
   configuration payload rather than guessed: #1976d2 is its configured button
   blue, #ff9800 the star orange.
   ========================================================================== */

.birdeye {
  width: 100%;
  background: var(--white);
  color: var(--primary-text);
  border-radius: 8px;
  padding: 1.25rem;
  margin: 2rem 0;
}

.birdeye-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.birdeye-title { color: var(--primary-text); }

.birdeye-nav { display: flex; gap: 0.5rem; }

.birdeye-arrow {
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--offwhite);
  border-radius: 50%;
  background: var(--white);
  color: var(--dark);
  cursor: pointer;
  padding: 0;
}

.birdeye-arrow .icon { width: 18px; height: 18px; fill: currentColor; }
.birdeye-arrow:hover { border-color: var(--dark); }
.birdeye-arrow:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* ---- The summary strip --------------------------------------------------- */

.birdeye-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  border: 1px solid var(--offwhite);
  border-radius: 8px;
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
}

.birdeye-score { display: inline-flex; align-items: center; gap: 0.5rem; }

.birdeye-average {
  font-family: var(--header-font);
  font-size: 2rem;
  font-weight: var(--font-weight-bold);
  line-height: 1;
}

.birdeye .stars { display: inline-flex; gap: 1px; }
.birdeye .stars .icon { width: 16px; height: 16px; fill: #ff9800; }

.birdeye-caption {
  flex: 1 1 12rem;
  font-size: var(--font-size-small);
  color: var(--dark);
}

/* ---- Write a review: a <details> styled as the widget's blue button ------ */

.birdeye-write { position: relative; }

.birdeye-write-button {
  display: inline-block;
  list-style: none;
  cursor: pointer;
  background: #1976d2;
  color: var(--white);
  border-radius: 4px;
  padding: 0.5rem 1.1rem;
  font-weight: var(--font-weight-bold);
  font-size: var(--font-size-small);
  white-space: nowrap;
}

/* The disclosure triangle, both engines. The element reads as a button. */
.birdeye-write-button::-webkit-details-marker { display: none; }
.birdeye-write-button::marker { content: ""; }

.birdeye-write-button:hover { background: #145ea8; }
.birdeye-write-button:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

.birdeye-write-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 5;
  min-width: 220px;
  background: var(--white);
  border: 1px solid var(--offwhite);
  border-radius: 4px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);
  padding: 0.25rem 0;
}

.birdeye-write-menu a {
  display: block;
  padding: 0.5rem 0.9rem;
  color: var(--primary-text);
  font-size: var(--font-size-small);
  text-decoration: none;
}

.birdeye-write-menu a:hover { background: var(--offwhite); }

/* The empty-state strip keeps the menu reachable without numbers to show. */
.birdeye-summary-empty { border-style: dashed; }

/* ---- The rotation: pages in a scroll-snap track -------------------------- */

.birdeye-track {
  display: flex;
  gap: 0.75rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* The original widget hides the bar too; arrows, snap and touch remain. */
  scrollbar-width: none;
}

.birdeye-track::-webkit-scrollbar { display: none; }

.birdeye-track:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

.birdeye-page {
  flex: 0 0 100%;
  scroll-snap-align: start;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
  align-content: start;
}

/* ---- One review card ------------------------------------------------------ */

.birdeye-review {
  border: 1px solid var(--offwhite);
  border-radius: 8px;
  padding: 0.75rem;
  min-width: 0;
}

.birdeye-review-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}

.birdeye-avatar {
  flex: 0 0 36px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--white);
  font-weight: var(--font-weight-bold);
}

/* The avatar palette BirdeyeReviewsModel hashes names into. */
.birdeye-avatar-a { background: #e57373; }
.birdeye-avatar-b { background: #64b5f6; }
.birdeye-avatar-c { background: #81c784; }
.birdeye-avatar-d { background: #ffb74d; }
.birdeye-avatar-e { background: #ba68c8; }
.birdeye-avatar-f { background: #4db6ac; }

.birdeye-review-who { min-width: 0; }

.birdeye-reviewer {
  font-weight: var(--font-weight-bold);
  font-size: var(--font-size-small);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.birdeye-source {
  font-size: 12px;
  color: var(--primary);
}

.birdeye-review-rating {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}

.birdeye-review-rating .stars .icon { width: 13px; height: 13px; }

.birdeye-age {
  font-size: 12px;
  color: var(--dark);
  opacity: 0.7;
  white-space: nowrap;
}

.birdeye-text {
  font-size: var(--font-size-small);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.birdeye-powered {
  margin-top: 0.75rem;
  font-family: var(--prehead-font);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--dark);
  opacity: 0.7;
}

@media (max-width: 767.98px) {
  .birdeye-page { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 479.98px) {
  .birdeye-page { grid-template-columns: 1fr; }
}

/* ============================================================================
   PROJECTS — /projects/, the detail page, and the city pages' nearby-work
   section.

   None of this is transcribed. The original renders its whole portfolio from
   CompanyCam's Showcase widget, so the harvest holds a hero and an empty div;
   everything below is written to the brief in the site's own tokens.

   .city-projects-stage and .city-projects-status are GONE with the placeholder
   they framed. A city with no nearby work now renders no section at all rather
   than a dashed box holding a sentence, so there is no height to reserve.
   ========================================================================== */

/* ---- The listing panel ---------------------------------------------------

   THE SHAPE IS THE SHOWCASE WIDGET'S, measured from its own stylesheet
   (showcase.companycam.com/bundle.js) rather than guessed: a centred panel
   capped at 1200px, a three-column grid at a 32px gap, fixed 4:3 covers,
   pill filters (#cbd1d4 border, 30px radius, 12x20 padding, 13px), a
   five-cell thumbnail strip, and one bordered pager strip (#e6e8eb, radius
   4px) whose "1 of N" is 105px wide at 14px/600. Colour and type otherwise
   come from this site's tokens. */

.projects-panel {
  max-width: 1200px;
  margin: 0 auto;
  background: var(--white);
  border-radius: 8px;
  padding: 24px;
}

.projects-panel-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin-bottom: 1rem;
}

/* The CompanyCam attribution. It stays: these are their photographs, served
   from their servers. */
.projects-powered {
  font-family: var(--prehead-font);
  font-size: var(--font-size-small);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--dark);
  opacity: 0.7;
}

/* ---- Filters: two pills in a row -----------------------------------------

   The original's row is three: Project Type, Products Used, City & State.
   Products Used is gone (ORIGINAL-SITE-DEFECTS.md 22), so this is two live
   <select>s and the Apply the original does not need.

   THE TWO SHARE ONE WIDTH, and that is what keeps the proportions right with
   one pill fewer. Three pills filled the 1200px panel's left half on their
   own; two of their old width would have left the row looking like something
   had fallen off it. They are flex items with an equal basis instead, so the
   pair spans what the trio did and neither is the odd size — the reason the
   width lives on .projects-pill-live rather than on the select inside it. */

.projects-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-bottom: 1.5rem;
}

.projects-filters .projects-pill-live {
  flex: 1 1 0;
  /* Not below the 13rem the select asked for on its own, and not so wide that
     two of them push Apply onto a second line before the panel is narrow. */
  min-width: 13rem;
  max-width: 22rem;
  /* A pill is a <label>, and Bootstrap's reboot gives every label
     margin-bottom: .5rem. That made this row 52px tall around 44px controls,
     and align-items:center then dropped Apply — which has no such margin — 4px
     below the pills it sits beside. Measured in Chrome at 1440 and 768; with
     this the row is 44px and all three centres agree. */
  margin-bottom: 0;
}

.projects-pill {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 20px;
  background: var(--white);
  border: 1px solid #cbd1d4;
  border-radius: 30px;
  color: var(--primary-text);
  font-family: var(--copy-font);
  font-size: 13px;
  line-height: 1;
}

/* A live pill is a <select> wearing the same shape; the wrapping label carries
   the border so the control can stay borderless inside it. Both pills on this
   row are one of these now — the disabled-button rule that used to sit here
   went with Products Used, and there is no disabled pill anywhere on the page. */
.projects-pill-live { padding: 0; }

.projects-pill-select {
  min-height: 42px;
  width: 100%;
  padding: 0 20px;
  border: 0;
  border-radius: 30px;
  background: transparent;
  color: var(--primary-text);
  font-family: var(--copy-font);
  font-size: 13px;
}

.projects-pill-select:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

.projects-filter-apply {
  min-height: 44px;
  cursor: pointer;
  font-weight: var(--font-weight-bold);
  color: var(--primary);
}

.projects-filter-apply:hover { border-color: var(--primary); }
.projects-filter-apply:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

.projects-filter-clear {
  align-self: center;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  color: var(--primary);
}

.projects-empty {
  padding: 2rem 0;
  text-align: center;
  color: var(--dark);
}

/* ---- Cards ----------------------------------------------------------------

   Uniform by construction: the grid fixes the columns, the cover fixes its
   own height from the 4:3 ratio, and the thumbnail strip is pinned to the
   card's bottom, so every row lines up whatever the photographs are. */

.projects-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
  margin-bottom: 1.5rem;
}

.project-card {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--offwhite);
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 1px 8px rgba(58, 75, 86, 0.2);
}

/* THE FIXED-RATIO COVER. The image is absolutely positioned, and that is the
   fix rather than a flourish: a replaced element flowing inside an
   aspect-ratio box contributes its own content size to the box's automatic
   minimum, so a portrait photograph quietly stretched its card to 540px
   where a landscape one stopped at 304px — the broken rows this section had.
   Taken out of flow, the image can only fill the box the ratio computed. */
.project-card-cover {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  background: var(--offwhite);
  overflow: hidden;
}

.project-card-cover img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The date chip bottom-left, the city/ZIP chip bottom-right. */
.project-chip {
  position: absolute;
  bottom: 0.5rem;
  padding: 0.2rem 0.55rem;
  border-radius: 4px;
  background: rgba(17, 17, 17, 0.78);
  color: var(--white);
  font-family: var(--prehead-font);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.6;
}

.project-chip-date { left: 0.5rem; }
.project-chip-place { right: 0.5rem; }

.project-card-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1rem;
}

.project-card-title {
  margin: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.project-card-title a { color: var(--primary-text); }

/* Label over value, side by side — the anatomy the original's PROJECT TYPE and
   PRODUCTS USED blocks have. Project Type is a real value here as of the
   project-types phase; the photo and visit counts occupy the slot Products
   Used had, which is not coming back.

   It wraps, and the type item is the one allowed to be wide: "Siding, Windows"
   is two labels and a job can carry more, where the two counts are single
   digits and should never be pushed onto a second line by one. */
.project-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  margin: 0;
}

.project-card-meta-type {
  flex: 1 1 100%;
  min-width: 0;
}

.project-card-meta dt {
  font-family: var(--prehead-font);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--dark);
  opacity: 0.75;
  font-weight: var(--font-weight-normal);
}

.project-card-meta dd {
  margin: 0;
  font-weight: var(--font-weight-bold);
}

/* The four thumbnails and the +N cell, five equal squares like the original's
   preview strip; pinned to the bottom so short titles do not unalign rows. */
.project-card-thumbs {
  margin-top: auto;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  align-items: center;
}

.project-card-thumbs img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 4px;
  display: block;
}

.project-card-overflow {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--prehead-font);
  font-size: var(--font-size-small);
  color: var(--dark);
  white-space: nowrap;
}

/* ---- Pager: one bordered strip -------------------------------------------- */

.projects-pager {
  display: flex;
  align-items: center;
  width: fit-content;
  margin: 0 auto;
  padding: 0 8px;
  border: 1px solid #e6e8eb;
  border-radius: 4px;
}

.projects-pager-arrow {
  min-width: 44px;
  min-height: 50px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--primary-text);
  text-decoration: none;
}

.projects-pager-arrow .icon { width: 18px; height: 18px; fill: currentColor; }

a.projects-pager-arrow:hover { color: var(--primary); }

.projects-pager-arrow.is-disabled { opacity: 0.3; }
.projects-pager-arrow:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

.projects-pager-count {
  min-width: 105px;
  padding: 16px;
  text-align: center;
  font-size: 14px;
  font-weight: var(--font-weight-bold);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 991.98px) {
  .projects-grid { grid-template-columns: repeat(2, 1fr); gap: 24px; }
}

@media (max-width: 767.98px) {
  .projects-grid { grid-template-columns: 1fr; }
}


/* ---- The detail page ----------------------------------------------------- */

.project-back { margin-bottom: 1rem; }

.project-header { margin-bottom: 2.5rem; }

.project-cover {
  width: 100%;
  height: auto;
  border-radius: 8px;
  display: block;
}

.project-meta {
  font-family: var(--prehead-font);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--dark);
}

.project-description { max-width: 60ch; }

.project-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin-top: 1.5rem;
}

.project-fact-label {
  margin: 0 0 0.25rem;
  font-family: var(--prehead-font);
  font-size: var(--font-size-small);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--dark);
  font-weight: var(--font-weight-bold);
}

.project-fact-value { margin: 0; }

/* ---- The visit timeline -------------------------------------------------- */

.project-timeline {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The dot and the vertical rule. The rule is a border on the item and the dot
   sits on top of it, so a visit's photographs push the rule down with them and
   the last visit's rule stops at its own content. */
.project-visit {
  position: relative;
  padding: 0 0 2.5rem 2rem;
  border-left: 2px solid var(--offwhite);
}

.project-visit:last-child { border-left-color: transparent; padding-bottom: 0; }

.project-visit::before {
  content: "";
  position: absolute;
  left: -9px;
  top: 0.35rem;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--primary);
  border: 3px solid var(--white);
}

.project-visit-date {
  margin: 0;
  font-size: var(--font-size-medium);
}

.project-visit-count {
  margin: 0 0 0.75rem;
  font-size: var(--font-size-small);
  color: var(--dark);
}

.project-visit-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 0.5rem;
}

.project-visit-photo img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 4px;
  display: block;
}

.project-visit-photo:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* ---- Nearby work on a city page ------------------------------------------ */

.city-project-card {
  height: 100%;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--offwhite);
  border-radius: 8px;
  overflow: hidden;
  color: var(--primary-text);
  text-decoration: none;
  text-align: left;
}

.city-project-cover { display: block; aspect-ratio: 4 / 3; background: var(--offwhite); }

.city-project-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.city-project-body { display: block; padding: 0.85rem 1rem; }

.city-project-title {
  display: block;
  font-family: var(--header-font);
  font-weight: var(--font-weight-bold);
}

.city-project-meta {
  display: block;
  margin-top: 0.2rem;
  font-size: var(--font-size-small);
  color: var(--dark);
}

@media (max-width: 767.98px) {
  .projects-panel { padding: 16px; }
  /* Each pill on its own line on a phone — the equal-basis pair above would
     otherwise put two 13rem controls side by side in a 345px panel. */
  .projects-filters .projects-pill-live { flex-basis: 100%; max-width: none; min-width: 0; }
}
