/* ==========================================================================
   Sierra Lights — colour only.

   Loaded AFTER roofex.webflow.shared.css. It repoints the template's own CSS
   variables and does nothing else, so every layout, breakpoint, hover state and
   Webflow IX2 interaction stays exactly as the template ships it.

   Palette: _brief/SierraLights_Website_Brief.docx §6
   ========================================================================== */

/* Both selectors matter. The template re-declares its whole variable set on
   `body` inside @media (max-width: 991px / 767px / 479px), which beats an
   override that only sits on :root, so below 991px every colour reverted to
   the template's. Declaring on body too, later in the cascade, wins. */
:root,
body {
  --sl-navy: #001733;
  --sl-deep-navy: #001126;
  --sl-navy-blue: #082B4F;
  --sl-gold: #E1A64A;
  --sl-champagne: #CFA24A;
  --sl-champagne-lt: #E8C875;
  --sl-soft-white: #F5F4EF;

  /* the template's variables, repointed to the brand palette */
  /* theme-color-01 is the accent: buttons, icons, small highlights. Gold. */
  --_colors---colors--theme-color-01: var(--sl-gold);      /* was #ffa12e */

  /* theme-color-02 paints the full-bleed bands (who-we-are, reviews, CTA,
     interior page banners). The brand runs 70% navy and uses gold sparingly,
     so those large surfaces are navy, not gold. */
  --_colors---colors--theme-color-02: var(--sl-navy-blue); /* was #ba8a51 */

  --_colors---colors--neutral-04: var(--sl-navy);          /* was #171714 */
  --_colors---colors--neutral-03: #45566B;                 /* was #434338 */
  --_colors---colors--neutral-02: var(--sl-soft-white);    /* was #f4f4eb */
}

/* Brand guide §6: the primary CTA is gold with navy text, not white text. */
.button:not(.w-variant-9e1b8176-7447-c0a7-4874-e1f3ac536888):not(.w-variant-2745f118-32d3-df23-5f91-c489a31ce1f6) .button-text {
  color: var(--sl-navy);
}
/* ⚠ No blanket .button:hover rule. Measured against roofex.webflow.io, the
   template changes NOTHING on hover for the solid and link buttons: the label
   slides up 24px and, on a service card, the image scales to 1.1. A background
   or text-colour change here also hit the "Learn More" link variant, which is
   meant to stay a plain text link.
   The only hover the template does recolour is the bordered secondary, which
   fills with theme-color-01. Its label goes navy because on our gold, white
   text does not carry (brand guide §6). */
.button.w-variant-9e1b8176-7447-c0a7-4874-e1f3ac536888:hover .button-text {
  color: var(--sl-navy);
}

/* The hero scrim is tinted #002a3d in the template; bring it to Sierra navy. */
.hero-bg-left {
  background-image: linear-gradient(89.33deg, rgba(0, 17, 51, 0) 0.58%, rgba(0, 17, 51, 0.95) 99.44%);
}

/* Match the template logo's footprint exactly. Roofex renders 140x39 in both
   the header and the footer. Ours is a much wider wordmark, so it is sized on
   WIDTH, not height, or it reads far heavier than the template's mark. */
.navbar-brand-header-logo { width: 228px; height: auto; }
.footer-logo { width: 219px; height: auto; }

@media screen and (max-width: 767px) {
  .navbar-brand-header-logo { width: 175px; }
}

/* Trust badges: the first three (100% Guaranteed, Best Service, Certified
   Professional) are shown, per Jay. Badges four and five read "Extended
   Warranty" and "Best Sales Ever", which are claims Sierra Lights has not
   made, so those two stay hidden.
   Hidden rather than deleted: the images carry data-w-id, and removing them
   from the markup breaks the page's IX2 timeline, which leaves every other
   reveal on the page stuck at opacity 0. */
.badge-wrapper .badge-icon-wrapper:nth-child(n + 4) { display: none; }

/* The review cards carry logos for invented companies (Netdot, Pulse, ZenZap).
   Hidden rather than removed, for the same IX2 reason as the badges above. */
.brand-icon-wrapper { display: none; }

/* The template title-cases every footer contact line, and that is kept, because
   it is how Roofex looks. The one exception is the email: capitalise turns a
   real address into "Sales@sierraservices.ca". Scoped to the mailto link only,
   so the address line above it still renders exactly like the template's. */
a.contact-info-text[href^="mailto:"] { text-transform: none; }

/* The who-we-are block is a Webflow background video. Its sources are stripped
   (the template's footage is roofers on a roof), so the play button and the
   "watch the video" label promise something that cannot happen. Both go, and
   the block reads as a still. Hidden rather than deleted, because the play
   button carries data-w-id and removing it breaks the page's IX2 timeline. */
.video-button-area { display: none !important; }

/* With the <source> tags gone the element is an empty <video>, so its poster
   has to be painted as a proper cover background rather than a tiled one. */
.who-we-are-section video,
.about-video video,
video[data-object-fit="cover"] {
  background-size: cover;
  background-position: 50% 50%;
  background-repeat: no-repeat;
}

/* --------------------------------------------------------------------------
   Packages (brief §3).

   The template ships no pricing component, so the cards ARE the template's
   .service-card. Everything below is only the parts a service card has no
   equivalent for: a price line, an inclusions list and a "Most Popular" tag.
   All of it is sized and coloured from the template's own variables so it
   inherits the type scale, spacing and every breakpoint.
   -------------------------------------------------------------------------- */

/* the page alternates white / soft / navy; this drops in on the navy beat */
.sl-packages-section { background-color: var(--_colors---colors--theme-color-02); }


.sl-price {
  display: flex;
  align-items: baseline;
  gap: var(--_sizes---spacing--03);
  gap: 8px;
  flex-wrap: wrap;
}
.sl-price-from,
.sl-price-tax {
  font-family: var(--font--body-font);
  font-size: var(--font-sizes--body-04);
  font-weight: var(--font-weight--medium);
  color: var(--_colors---colors--neutral-03);
}
.sl-price-value {
  font-family: var(--font--heading-font);
  font-size: var(--font-sizes--h3);
  line-height: var(--line-height--xs);
  font-weight: var(--font-weight--bold);
  letter-spacing: var(--letter-spacing--md);
  color: var(--_colors---colors--neutral-04);
}

.sl-includes {
  display: flex;
  flex-direction: column;
  gap: var(--_sizes---spacing--03);
  gap: 8px;
  margin: 0;
  padding: 0;
  width: 100%;
}
.sl-includes li {
  position: relative;
  padding-left: 26px;
  font-family: var(--font--body-font);
  font-size: var(--font-sizes--body-04);
  line-height: var(--line-height--lg);
  color: var(--_colors---colors--neutral-03);
}
.sl-includes li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 8px;
  width: 8px;
  height: 8px;
  border-radius: 100px;
  background-color: var(--_colors---colors--theme-color-01);
}

.sl-price-note {
  width: 100%;
  max-width: 720px;
  margin: var(--_sizes---spacing--15) auto 0;
  text-align: center;
  font-family: var(--font--body-font);
  font-size: var(--font-sizes--body-04);
  line-height: var(--line-height--xl);
  color: rgba(255, 255, 255, 0.62);
}

/* the taller of the three cards sets the row height, so the button stays put */
.sl-package-card .service-text-block { flex: 1 1 auto; }
.sl-package-card .sl-includes { flex: 1 1 auto; }

/* "Most Popular" reads as gold text on the title's own line, so it costs no
   vertical space and the three card titles stay level. The card it belongs to
   is picked out with a gold outline drawn as an inset shadow, which does not
   change the box size and so cannot nudge the grid. */
.sl-title-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
  width: 100%;
}
.sl-popular {
  font-family: var(--font--body-font);
  font-size: var(--font-sizes--body-04);
  font-weight: var(--font-weight--bold);
  line-height: var(--line-height--lg);
  letter-spacing: 0.7px;
  text-transform: uppercase;
  color: var(--_colors---colors--theme-color-01);
  white-space: nowrap;
}
.sl-package-card.sl-featured {
  box-shadow: inset 0 0 0 1.5px var(--_colors---colors--theme-color-01);
}


/* ==========================================================================
   The 17 September 2026 meeting changes (Scott / Alex / James).
   Spec: "Granola Generated Changes", marketing Drive, section 2.
   Colour and layout only. No template component is restyled beyond the band
   it sits in, and nothing carrying data-w-id is removed from the markup.
   ========================================================================== */

/* --- 2.3 The Google rating strip. Alex: "I get rid of that."
   Hidden, not deleted: .google-rating-left-block carries data-w-id, and
   pulling an animated node strands every other reveal at opacity 0. */
.google-rating-section { display: none !important; }

/* --- 2.1 Header: phone number beside the CTA, top right. */
.sl-header-phone {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-right: var(--_sizes---spacing--06, 16px);
  font-family: var(--font--body-font);
  font-size: var(--font-sizes--body-04);
  font-weight: var(--font-weight--medium);
  /* the header sits over a dark hero on every page, and .nav-link measures
     white on all of them, so the phone matches the links it sits beside */
  color: var(--_colors---colors--neutral-01);
  white-space: nowrap;
  text-decoration: none;
}
.sl-header-phone:hover { color: var(--_colors---colors--theme-color-01); }
/* the template's phone glyph is a dark navy SVG, drawn for a light bar. Setting
   `color` on the link cannot reach inside an <img>, so it is inverted to white
   to match the nav links it sits beside. */
.sl-header-phone-icon {
  width: 18px;
  height: 18px;
  filter: brightness(0) invert(1);
  transition: opacity .2s ease;
}
.sl-header-phone:hover .sl-header-phone-icon { opacity: .75; }

/* ⛔ Measured, not assumed: making .navigation-button a flex row unconditionally
   squeezed the CTA on a phone and wrapped "Get Your Free Quote" onto four lines,
   which ballooned the gold pill over the hero headline. The row only applies
   where the header actually has room for two things. */
@media screen and (min-width: 768px) {
  /* ⭐ Alex agreed this in round 2 ("the phone number moves to sit directly
     under that button") and had to ask again in round 3 ("Just the phone
     number under the button please") because it shipped BESIDE the button.

     ⛔⛔ THE NUMBER HANGS OFF THE BUTTON, IT IS NOT STACKED WITH IT. A flex
     column was the obvious build and it was wrong: .navbar-wrapper centres its
     children, so a 100px-tall column instead of a 67px button dragged the
     CTA 16px UP and the whole bar from 99px to 128px. Jay, 18 Sep: "the button
     should have been in the same place as it was before, vertically compared to
     the things on the left. Just the phone number underneath it."
     ⭐⭐⭐ Taking the number OUT OF FLOW is what keeps that promise. The block is
     the button's 67px again, so the logo, the nav links and the CTA all sit on
     the same 65.5px midline they did before this was ever asked for, and the
     bar is back to 99px. The header is transparent, position:absolute over the
     hero and every ancestor is overflow:visible, so the number simply sits on
     the photo below the button. Asserted by _qa/r12hdr3.js.
     ⭐ left:0/right:0 spans the BUTTON's width, so `justify-content:center`
     centres the number under the button rather than under the bar.
     ⭐ It also gives the nav ~145px back. .navigation-button was 364px wide
     with the number beside the button and is 217px with it underneath, which is
     what was squeezing the four nav links onto two lines between 992 and 1194. */
  .navigation-button { position: relative; display: flex; align-items: center; }
  .sl-header-phone {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    justify-content: center;
    margin-right: 0;
  }
}
@media screen and (max-width: 767px) {
  /* Below the burger breakpoint the template hides the CTA entirely, so the bar
     is logo + burger and there is no room for a number written out. Alex's
     campaign is a text campaign, so this page is mostly read on a phone and a
     tap-to-call is the highest-intent thing in the bar. The number becomes an
     icon-sized tap target beside the burger; the CTA stays hidden, as the
     template intends, and the hero's two buttons are immediately below it. */
  .navigation-button { display: flex !important; align-items: center; }
  .navigation-button > .button { display: none !important; }
  /* 24px of icon inside 44x44 of tap target: a 24px hit area fails the minimum
     and this is the one control a phone user is most likely to reach for */
  .sl-header-phone {
    display: inline-flex;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin-right: 6px;
    padding: 10px;
    touch-action: manipulation;
  }
  .sl-header-phone span { display: none; }
  .sl-header-phone-icon { width: 24px; height: 24px; }
}
/* the label is a fixed single line in this template; letting it wrap is what
   made the pill grow rather than the text shrink */
.navigation-button .button .button-text { white-space: nowrap; }

/* ⛔ MEASURED: between 992px and ~1050px the bar wants 1003px (logo 228 + nav
   486 + CTA 217 + two 36px gaps) and has 944-1002px, so "What We Do", "How It
   Works" and "Who We Are" each wrapped onto TWO lines and the header grew to
   122px. Nobody reported it because it only happens on a narrow desktop window,
   and neither Alex nor Jay works at that width. Stacking the phone under the
   CTA gave 147px back and cleared 1100-1194 on its own; this closes the rest.
   22px + 24px brings the requirement to ~925px, so there is real slack rather
   than a hairline fit. The wrap is asserted at 21 widths by _qa/r12resp.js. */
@media screen and (min-width: 992px) and (max-width: 1090px) {
  .nav-menu { column-gap: 22px; }
  .navbar-wrapper { column-gap: 24px; }
}

/* --- 2.2 Hero: the location line under the headline. The strip that used to
   carry "Whistler & the Sea to Sky, BC" has gone, so it reappears here. */
.sl-hero-location {
  margin-top: var(--_sizes---spacing--05, 12px);
  font-family: var(--font--body-font);
  font-size: var(--font-sizes--body-02);
  font-weight: var(--font-weight--medium);
  line-height: var(--line-height--lg);
  letter-spacing: 0.4px;
  color: rgba(255, 255, 255, 0.86);
}

/* --------------------------------------------------------------------------
   2.4 Band colours. The running order changed, so the light / dark rhythm had
   to be rebuilt: packages and the slider section are now light where they were
   navy, and the services grid and Why Sierra are navy where they were light.
   Each flip carries its own text colours, because the template colours text by
   the band it was designed for, not by a utility class.
   -------------------------------------------------------------------------- */

/* Packages: navy -> light. Its cards were always white, so only the section
   heading and the footnote needed moving. */
.sl-packages-section { background-color: var(--_colors---colors--neutral-02); }
.sl-price-note { color: var(--_colors---colors--neutral-03); }

/* Everything We Light Up: light -> navy. */
#what-we-do { background-color: var(--_colors---colors--theme-color-02); }
#what-we-do .section-title,
#what-we-do .section-subtitle { color: var(--_colors---colors--neutral-01); }

/* Nothing To Buy / the slider: navy -> light. */
#see-the-lights { background-color: var(--_colors---colors--neutral-02); }
#see-the-lights .section-title,
#see-the-lights .section-subtitle,
#see-the-lights .stat-title,
#see-the-lights .counter-title { color: var(--_colors---colors--neutral-04); }
#see-the-lights .about-paragraph,
#see-the-lights .counter-subtitle { color: var(--_colors---colors--neutral-03); }

/* Why Sierra: light -> navy. */
#who-we-are { background-color: var(--_colors---colors--theme-color-02); }
#who-we-are .section-title,
#who-we-are .section-subtitle,
#who-we-are .choose-us-title,
#who-we-are .core-value-widget-title { color: var(--_colors---colors--neutral-01); }
#who-we-are .choose-us-subtitle,
#who-we-are .core-value-widget-subtitle { color: rgba(255, 255, 255, 0.74); }

/* --------------------------------------------------------------------------
   2.5 "Most Popular". Alex: "make it in a bubble... there's a circle around
   gold so you can see it more", "and a bit bigger", "it looks like a button,
   although it's not a button".
   The row gets a min-height so the gold pill cannot make the Signature card's
   title row taller than the other two and knock the three cards out of level.
   A stacked pill did exactly that once and was rejected.
   -------------------------------------------------------------------------- */
.sl-title-row { align-items: center; min-height: 38px; }
.sl-popular {
  display: inline-flex;
  align-items: center;
  padding: 7px 18px;
  border-radius: 999px;
  background-color: var(--_colors---colors--theme-color-01);
  border: 2px solid var(--_colors---colors--theme-color-01);
  box-shadow: 0 0 0 3px rgba(225, 166, 74, 0.22);
  color: var(--sl-navy);
  font-size: var(--font-sizes--body-03);
  letter-spacing: 0.9px;
  cursor: default;
}
/* the gold outline on the card itself gets heavier to match the badge */
.sl-package-card.sl-featured {
  box-shadow: inset 0 0 0 2.5px var(--_colors---colors--theme-color-01);
}

/* --------------------------------------------------------------------------
   2.6 The six service-detail pages are hidden, so "Learn More" promises a page
   that is not there. The card keeps its image and title links, repointed to
   the on-page section, because the template scales the card image on hover
   through that anchor.
   -------------------------------------------------------------------------- */
#what-we-do .service-text-block > .button { display: none; }

/* --------------------------------------------------------------------------
   2.7 The before / after slider. Alex: divider starts centred, dragged by
   hand, daytime with no lights on one side and dusk with the lights on on the
   other. It replaces the block that was a background video, which stays in the
   DOM (its play button carries data-w-id) and is hidden here.
   Built on a native range input, so mouse, touch and keyboard all work with no
   custom drag handling, and it still functions if the script never runs.
   -------------------------------------------------------------------------- */
#see-the-lights .background-video > video,
#see-the-lights .video-gradient { display: none !important; }

.sl-ba {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 2;
  --sl-ba-pos: 50%;
}
.sl-ba-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}
/* clip-path rather than a wrapper, so the two frames stay pixel-aligned at
   every width and nothing has to be re-measured on resize */
.sl-ba-before { clip-path: inset(0 calc(100% - var(--sl-ba-pos)) 0 0); }

.sl-ba-line {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--sl-ba-pos);
  width: 2px;
  margin-left: -1px;
  background: var(--_colors---colors--theme-color-01);
  pointer-events: none;
  z-index: 3;
}
/* The handle. It was a plain ring, which did not say "drag me": two chevrons
   in a larger circle do, and the ring behind it pulses once a second until the
   reader touches it, then stops. */
.sl-ba-handle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 64px;
  height: 64px;
  margin: -32px 0 0 -32px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1px;
  border-radius: 999px;
  border: 2px solid var(--_colors---colors--theme-color-01);
  background: rgba(0, 17, 51, .62);
  backdrop-filter: blur(2px);
  color: #fff;
  box-shadow: 0 6px 20px -8px rgba(0, 0, 0, .7);
}
.sl-ba-handle::before {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 999px;
  border: 2px solid var(--_colors---colors--theme-color-01);
  animation: sl-ba-pulse 2s ease-out infinite;
}
.sl-ba[data-touched] .sl-ba-handle::before { animation: none; opacity: 0; }
@keyframes sl-ba-pulse {
  0%   { transform: scale(1);    opacity: .85; }
  70%  { transform: scale(1.55); opacity: 0; }
  100% { transform: scale(1.55); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .sl-ba-handle::before { animation: none; opacity: .5; }
}
.sl-ba-tag {
  position: absolute;
  bottom: 18px;
  z-index: 3;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(0, 17, 51, 0.62);
  color: #fff;
  font-family: var(--font--body-font);
  font-size: var(--font-sizes--body-04);
  letter-spacing: 0.6px;
  text-transform: uppercase;
  pointer-events: none;
}
.sl-ba-tag-before { left: 18px; }
.sl-ba-tag-after { right: 18px; }

/* the control itself: full-bleed and invisible, so the whole image is the
   drag target and the gold line is what the eye follows */
.sl-ba-range {
  position: absolute;
  inset: 0;
  z-index: 4;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: ew-resize;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
}
.sl-ba-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 56px;
  height: 100%;
  cursor: ew-resize;
}
.sl-ba-range::-moz-range-thumb {
  width: 56px;
  height: 100%;
  border: 0;
  background: transparent;
  cursor: ew-resize;
}
/* keyboard users get the focus ring back on the line, since the input is
   transparent and would otherwise show nothing at all */
.sl-ba-range:focus-visible ~ .sl-ba-line::after {
  box-shadow: 0 0 0 4px rgba(225, 166, 74, 0.45);
}

/* --------------------------------------------------------------------------
   2.9 The proof row. The About page's four icon blocks, lifted onto the
   homepage under the Why Sierra promises and relabelled with the facts Alex
   asked for. One row of four, per James: "they probably should be on one line,
   right, because otherwise it will look weird over on the right-hand side."
   -------------------------------------------------------------------------- */
.sl-proof-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--_sizes---spacing--10, 32px);
  align-items: start;
  margin-top: var(--_sizes---spacing--15, 56px);
  padding-top: var(--_sizes---spacing--12, 40px);
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}
.sl-proof-row .core-values-widget-item { max-width: none; }
@media screen and (max-width: 991px) {
  .sl-proof-row { grid-template-columns: repeat(2, 1fr); }
}
@media screen and (max-width: 479px) {
  .sl-proof-row { grid-template-columns: 1fr; }
}

/* --- Corrections found by measuring the rebuilt page ------------------------ */

/* The Why Sierra list is a Webflow tab set, and the gold fill belongs to
   whichever tab link carries w--current, so it MOVES as the reader clicks.
   On the template's light background the label was dark and read fine on that
   gold. The section is navy now, so labels had to go white, and white on solid
   gold measures 2.15:1. Measured, not assumed: only .w--current is gold, and it
   follows the click.
   ⛔ AND MEASURING IT FOUND A REAL BUG, NOT A CONTRAST NIGGLE. Clicking a tab
   makes IX2 write the DEACTIVATED tab's colours inline: color:rgb(0,23,51) on
   the title and rgb(69,86,107) on the subtitle, both chosen for the light band
   this section used to sit on. On navy that is navy on navy, so the first item
   vanishes the moment the reader clicks any other one. An inline style beats
   every stylesheet rule, so !important is the only route, and it is scoped to
   :not(.w--current) so the active gold tab keeps the template's own white
   label rather than being second-guessed. */
#who-we-are .choose-us-tab-link:not(.w--current) .choose-us-title {
  color: var(--_colors---colors--neutral-01) !important;
}
#who-we-are .choose-us-tab-link:not(.w--current) .choose-us-subtitle {
  color: rgba(255, 255, 255, 0.74) !important;
}

/* The "+" eyebrow marks are white SVGs, which the template only ever put on
   navy. Two of the bands flipped to light, so theirs are recoloured to the gold
   the other light bands already use. */
#see-the-lights .subtitle-icon,
.benefit-section .subtitle-icon {
  filter: none;
}
#see-the-lights .section-subtitle { color: var(--_colors---colors--neutral-04); }

/* 2.10 Reviews. The avatar keeps the template's circle and its exact size; only
   the source changed, so it needs a plate behind it and room to breathe. */
.review-image {
  background-color: #fff;
  border-radius: 999px;
  object-fit: contain;
  padding: 6px;
  box-shadow: inset 0 0 0 1px rgba(0, 23, 51, 0.10);
}

/* The two large "Sierra client" cards are stock photographs of people who are
   not Sierra clients, with a play button over a video that is not of them.
   James, 17 Sep: "remove the two people images, the Sierra clients."
   Hidden, not deleted: each wraps a Webflow background video whose play button
   carries data-w-id. */
.review-image-card { display: none !important; }

/* ⛔ THE SLIDER EXISTED ONLY ON DESKTOP. Measured, not assumed: the template
   collapses .background-area to height 0 below 991px, because there it was a
   decorative background video it did not want on a phone. Our slider lives in
   that box, so on a phone it was 361x0: present in the DOM, zero pixels tall,
   and a naive "is it there" check passes. Alex is driving a TEXT campaign to
   this page, so mobile is where most of it will be seen.
   The box is given its height back and the slider now sets its own, from an
   aspect ratio, so it is the same component at every width. */
#see-the-lights .background-area,
#see-the-lights .background-area > .w-layout-blockcontainer,
#see-the-lights .background-video {
  height: auto !important;
  min-height: 0;
}
.sl-ba {
  position: relative;
  inset: auto;
  width: 100%;
  /* Alex round 3: "Maybe make the picture smaller as well?", asked alongside
     moving the stats cards below it. 16:9 takes it from 898px to 729px tall at
     desktop, 169px back, which pays for about half of what the cards add.
     ⚠️ The photographs are 1507x1044 and .sl-ba-img is object-fit:cover, so this
     crops rather than squashes: 9.4% off the top and 9.4% off the bottom of the
     source. That is sky and driveway. The roofline lights, which are the whole
     point of the shot, start about 15% down and are untouched. Checked on the
     rendered frames, not calculated.
     ⚠️ BOTH frames are the same size in the same box, so they crop identically
     and the wipe still reveals the same house. */
  aspect-ratio: 16 / 9;
}
@media screen and (max-width: 767px) {
  .sl-ba-tag { bottom: 12px; font-size: 12px; padding: 5px 10px; }
  .sl-ba-tag-before { left: 12px; }
  .sl-ba-tag-after { right: 12px; }
  .sl-ba-handle { width: 52px; height: 52px; margin: -26px 0 0 -26px; }
  .sl-ba-handle svg { width: 14px; height: 14px; }
}

/* ==========================================================================
   Round 2, James's review of the rebuilt page, 17 September.
   ========================================================================== */

/* --- 1. The white band above the hero.
   The template gave .hero-section a 56px top margin, which used to sit behind
   the announcement strip. With the strip deleted the margin became a bare white
   stripe above the photograph. The header is transparent and the hero has 250px
   of its own top padding, so the image can start at the very top and the header
   simply sits over it, which is how the template composes it. */
.hero-section { margin-top: 0 !important; }

/* --- 2. Cards on the light bands.
   Flipping these two bands from navy to light left every card the same colour
   as the band it sits on: the packages cards were soft white on soft white with
   no shadow, and the stats cards were a 10% white fill drawn for navy. Both
   read as loose text on a page.
   The fix is to darken the BAND rather than lighten the cards, so the card
   surface stays the same soft white used on the navy band elsewhere: one card
   colour across the whole page, and neither white nor dark, as asked. */
:root, body { --sl-band: #E9E4D9; --sl-card: #F7F5F0; --sl-card-line: rgba(0, 23, 51, .07); }

#packages, #see-the-lights { background-color: var(--sl-band); }

#packages .sl-package-card,
#see-the-lights .stats-card {
  background-color: var(--sl-card);
  border: 1px solid var(--sl-card-line);
  box-shadow: 0 1px 2px rgba(10, 26, 47, .05), 0 14px 30px -20px rgba(10, 26, 47, .45);
}

/* --- 3. The Signature card stands taller than the two beside it.
   A percentage margin would resolve against the card's WIDTH, not its height,
   so this is set in pixels: 44px top and bottom on a ~680px card is about 6.5%
   each way, inside the 5 to 10% asked for. The grid row is set by the other two
   cards, so negative margins let this one grow past it in both directions
   without moving them. */
@media screen and (min-width: 992px) {
  /* ⛔ The margin has to go on the GRID ITEM, not on the card inside it.
     Measured: putting it on .sl-package-card moved the card up 44px and left
     its height at 650, because the card's height is set by its content, not by
     the row. On the item, the row still sizes from the other two cards and this
     one stretches 44px past it in each direction, so it genuinely grows. */
  #packages .sl-featured-item { margin-block: -44px; }
  #packages .sl-featured-item .sl-package-card {
    height: 100%;
    box-shadow: inset 0 0 0 2px var(--_colors---colors--theme-color-01),
                0 2px 4px rgba(10, 26, 47, .07), 0 26px 50px -24px rgba(10, 26, 47, .6);
  }
  /* room for it to grow into, so it cannot collide with the heading above or
     the leasing note below */
  #packages .service-collection-list { margin-block: 44px; }
}
#packages .sl-package-card.sl-featured {
  box-shadow: inset 0 0 0 2px var(--_colors---colors--theme-color-01),
              0 2px 4px rgba(10, 26, 47, .07), 0 26px 50px -24px rgba(10, 26, 47, .6);
}

/* --- 4. Space under the before/after slider.
   It was flush against the bottom edge of its section, with the next band
   starting on the same pixel. */
#see-the-lights .about-wrapper-1 { padding-bottom: clamp(56px, 6vw, 96px); }

/* --- 5. Why Sierra: the icons and the progress rail.
   Measured: the template filters only the ACTIVE tab's icon, because on its
   light background the others were meant to read dark. On navy they are black
   on navy. The rail behind the gold progress bar is rgba(23,23,20,.1), a near
   black at 10%, which is invisible on navy for the same reason. */
#who-we-are .choose-us-tab-link:not(.w--current) .choose-us-icon {
  filter: brightness(0) invert(1);
}
#who-we-are .choose-tab-divider { background-color: rgba(255, 255, 255, .22); }

/* --- 6. The proof row sits inside the container now (see restructure.py), so
   it lines up with the rest of the section. Sized down a step: these are a
   supporting row of facts under the four promises, not a second headline. */
.sl-proof-row { gap: clamp(20px, 2.4vw, 34px); }
.sl-proof-row .core-values-icon { width: 46px; height: 46px; }
.sl-proof-row .core-value-widget-title {
  font-size: var(--font-sizes--body-01);
  line-height: var(--line-height--sm);
}
.sl-proof-row .core-value-widget-subtitle { font-size: var(--font-sizes--body-04); }

/* Two more things drawn for the navy this band used to be:
   .video-bg is the template's half-height decorative band behind the video
   block, painted soft white so it would read against navy. On a light band it
   split the section into two tones across the slider.
   .stat-title and .stat-icon-wrapper are 10% white pills, which on a light card
   are all but invisible. */
#see-the-lights .video-bg { background-color: var(--sl-band); }
#see-the-lights .stat-title,
#see-the-lights .stat-icon-wrapper { background-color: rgba(0, 23, 51, .055); }

/* ==========================================================================
   Round 3, James's review, 17 September.
   ========================================================================== */

/* --- The gold outline stopped 1px short of the card edge, because the inset
   shadow is drawn inside the 1px hairline every card carries. On the featured
   card the gold IS the edge, so it becomes the border instead. */
#packages .sl-package-card.sl-featured {
  border: 2px solid var(--_colors---colors--theme-color-01);
  box-shadow: 0 2px 4px rgba(10, 26, 47, .07), 0 26px 50px -24px rgba(10, 26, 47, .6);
}
@media screen and (min-width: 992px) {
  #packages .sl-featured-item .sl-package-card {
    border: 2px solid var(--_colors---colors--theme-color-01);
    box-shadow: 0 2px 4px rgba(10, 26, 47, .07), 0 26px 50px -24px rgba(10, 26, 47, .6);
  }
}

/* --- The hero trust line lost the three faces and read as a stranded sentence.
   A five-star row takes their place, in the template's own star, so the line is
   still an object rather than loose text. */
.sl-star-row { display: flex; align-items: center; gap: 3px; margin-bottom: 10px; }
.sl-star-row .star-icon { width: 17px; height: 16px; }

/* --- The Stays-Lit card is a rating card, so where the faces were it takes the
   same Google mark the reviews carry, which also says where the rating is from. */
.sl-google-badge {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 14px 7px 8px;
  margin: 4px 0 2px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .10);
  border: 1px solid rgba(255, 255, 255, .16);
  font-family: var(--font--body-font);
  font-size: var(--font-sizes--body-04);
  font-weight: var(--font-weight--medium);
  color: #fff;
  white-space: nowrap;
}
.sl-google-badge-mark {
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: #fff;
  padding: 4px;
}

/* --- The ticker's circles are the same stock faces as the reviews grid and now
   carry the same Google mark, so they need the same plate behind them. */
.testimonial-image {
  background-color: #fff;
  border-radius: 999px;
  object-fit: contain;
  padding: 6px;
  box-shadow: inset 0 0 0 1px rgba(0, 23, 51, .10);
}

/* --- Why Sierra runs straight into the reviews on the same navy, so 100px of
   padding each side read as one 240px void between the proof row and the next
   heading. Tightened, and the boundary is drawn with the same hairline the
   proof row uses, at container width so the two rules line up. */
#who-we-are { padding-bottom: 64px; }
#reviews { padding-top: 0; }
#reviews > .w-layout-blockcontainer {
  border-top: 1px solid rgba(255, 255, 255, .16);
  padding-top: clamp(44px, 4.5vw, 64px);
}

/* The template caps .review-stats at 334px, a width sized for three overlapping
   faces and a short line. Ours is a star row and a longer sentence, which left
   the text on three lines in a 190px column. Widened so it sets on two. */
/* Round 4: stars above the line rather than beside it, and three times the
   size. Beside it, the sentence could only ever be a narrow two-line column;
   stacked, it sets on one line at every width above a phone.
   Both the row and the paragraph carry their own max-width in the template
   (334px and 190px, sized for three overlapping faces and a short label), and
   both have to go or the line wraps regardless. */
.review-stats {
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  max-width: none;
}
.review-stats .review-text { max-width: none; }
.sl-star-row { flex: none; gap: 6px; }
.sl-star-row .star-icon { width: 51px; height: 48px; }

@media screen and (max-width: 767px) {
  /* the sentence cannot hold one line on a phone, so the stars come down a
     little and it wraps to two rather than running to a third */
  .sl-star-row .star-icon { width: 38px; height: 36px; }
  .sl-star-row { gap: 5px; }
}

/* --- Round 4, corrected in round 13 after Alex: "header banner isnt centered
   anymore after you moved the phone number".

   ⛔⛔⛔ HE IS RIGHT AND IT WAS OUR DOING, WITH EXACT ARITHMETIC. Round 4 gave
   the links `margin-left:auto`, which hands them ALL the free space on their
   left and pins them to whatever sits on the right. That looked centred only
   because the CTA happened to be 364px wide. Round 12 stacked the phone under
   the button, the button became 217px, and the links slid right by the 147px
   difference: measured 158px right of the bar's centre at 1512, against 11px
   before the change.
   ⭐⭐⭐ THE LESSON IS THE SHAPE, NOT THE NUMBER: `margin-left:auto` is a
   position expressed as "hard against my neighbour", so it silently inherits
   every future change to that neighbour's width. It was never centring, it
   only agreed with centring at one button width.
   ⭐ `margin-inline:auto` splits the free space evenly instead, which is the
   optical centre Jay asked for, equal gap to the logo and equal gap to the
   button. It lands at 761.6 against a bar centre of 756, so it satisfies the
   true centre too: the two readings differ by 5.6px, under a hairline.
   ⚠️ Auto margins collapse to 0 when there is no free space, so the tight
   992-1090 band behaves exactly as it did. Asserted at 14 widths by
   _qa/r13hdr.js, which carries a negative control. */
@media screen and (min-width: 992px) {
  .navbar-wrapper .nav-menu-2 { margin-left: auto; margin-right: auto; }
}

/* ==========================================================================
   ROUND 5 — Alex's second pass, 17 September 2026
   Every colour below resolves to a token already declared at the top of this
   file, so nothing here can drift away from the rest of the site.
   ========================================================================== */

/* --- 1. Hero: the headline block centred in the photo, clear of the logo.
   Alex: "Big tittle centered left of the page (too close to logo)".
   MEASURED, not guessed. The template gives .hero-section height:100vh with a
   fixed 250px/168px padding pair. On a 1280x800 laptop that leaves the content
   only 41px of free space, so the headline started 20px under the logo, and on
   a 1440x900 it sat 82px below true centre. Padding-top now equals the header's
   own measured height (99px) so the content centres in the photo BELOW the
   header, and a floor on the section height keeps that gap honest on short
   screens. Below 992px the template already sets height:auto and the content
   clears the logo by 65-71px, so this deliberately does not apply there. */
@media screen and (min-width: 992px) {
  .hero-section {
    height: auto;
    min-height: max(100vh, 880px);
    padding-top: 99px;
    padding-bottom: 0;
  }
}

/* --- 2. The header CTA loses its icon.
   Alex agreed a phone icon on a button that opens a form reads as click to
   call, so the symbol stays on the number and the button is left clean. The
   icon is hidden rather than removed: it is half of the template's normal/hover
   pair and pulling it strands the button's own timeline. */
/* ⚠️ MEASURED: the wrapper is .button-icon-LEFT on this button. A rule
   written against .button-icon-right matched nothing and the template's phone
   icon was still sitting on the button. Both sides are covered now. */
.sl-cta-clean .button-icon-left,
.sl-cta-clean .button-icon-right { display: none; }

/* --- 3. Three headings out, their eyebrows promoted to the same size.
   "Can we make Our Packages, What We Do and How It Works same size as what we
   deleted?" Taking the h2's OWN custom properties rather than hard numbers
   means the promoted label tracks the heading at every breakpoint on its own
   (64px desktop, 55px tablet, 36px phone). */
.sl-promoted .section-title { display: none; }

.sl-promoted .section-subtitle {
  font-family: var(--font--heading-font);
  font-size: var(--font-sizes--h2);
  line-height: var(--line-height--sm);
  font-weight: var(--font-weight--bold);
  letter-spacing: var(--letter-spacing--lg);
  color: var(--_colors---colors--neutral-04);
}
/* the gold "+" is sized for 14px text and looks lost beside 64px, so it grows
   with it and sits on the cap height rather than the middle of the line */
.sl-promoted .subtitle-icon { width: 26px; height: 26px; align-self: center; }
.sl-promoted .section-subtitle-wrapper { gap: 14px; }

/* the dark band inverts, exactly as the h2 it replaces does */
#what-we-do .sl-promoted .section-subtitle { color: var(--_colors---colors--neutral-01); }

@media screen and (max-width: 991px) {
  .sl-promoted .subtitle-icon { width: 22px; height: 22px; }
}
@media screen and (max-width: 479px) {
  .sl-promoted .subtitle-icon { width: 18px; height: 18px; }
  .sl-promoted .section-subtitle-wrapper { gap: 10px; }
}

/* --- 4. Why Sierra: the four stats move beside the picture.
   "consolidate exactly the banner under that picture and move it to the right
   of that same picture." The tabs that used to fill this column are hidden,
   not deleted: every one carries a data-w-id and removing an animated node
   stranded every other reveal on this page at opacity 0 once already. */
#who-we-are .choose-us-tabs,
#who-we-are .choose-us-list,
#who-we-are .choose-tab-divider { display: none; }

.sl-proof-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: var(--_sizes---spacing--space-10, 48px);
  row-gap: var(--_sizes---spacing--space-12, 56px);
  width: 100%;
}
.sl-proof-col .core-value-widget-subtitle { max-width: none; }

@media screen and (max-width: 991px) {
  .sl-proof-col { column-gap: 32px; row-gap: 36px; }
}
@media screen and (max-width: 479px) {
  /* two columns of stat text on a phone leaves four cramped words per line */
  .sl-proof-col { grid-template-columns: 1fr; row-gap: 28px; }
}

/* --- 5. The FAQ.
   Alex asked whether an FAQ should replace the reviews. It goes in as well:
   the reviews are real Google reviews and they are the strongest trust signal
   a brand nobody has heard of has. The template ships no usable accordion
   (.faq-tab-link is an empty five-rule shell no page uses), so this is built
   from the template's own surfaces and tokens.
   Band colour is neutral-02, the same soft white as Why Sierra, which keeps
   the page's navy/light alternation intact between the navy reviews band and
   the light CTA that follows. */
.sl-faq-section { background-color: var(--_colors---colors--neutral-02); }

.sl-faq-list {
  width: 100%;
  max-width: 860px;
  margin: 0 auto;
  border-top: 1px solid rgba(0, 23, 51, 0.12);
}
.sl-faq-item { border-bottom: 1px solid rgba(0, 23, 51, 0.12); }

/* h3 wrapper keeps the document outline honest without adding its own type */
.sl-faq-h { margin: 0; font: inherit; }

.sl-faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 26px 4px;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
  font-family: var(--font--heading-font);
  font-size: var(--font-sizes--h5, 22px);
  line-height: var(--line-height--lg, 1.4);
  font-weight: var(--font-weight--bold);
  letter-spacing: var(--letter-spacing--xs);
  color: var(--_colors---colors--neutral-04);
  /* a fast second tap on a control zooms iOS otherwise */
  touch-action: manipulation;
  transition: color .22s ease;
}
.sl-faq-q:hover { color: var(--sl-gold); }
.sl-faq-q:focus-visible { outline: 2px solid var(--sl-gold); outline-offset: 3px; }

.sl-faq-icon {
  flex: none;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  transition: transform .38s cubic-bezier(.4, 0, .2, 1);
}
.sl-faq-icon img { width: 100%; height: 100%; display: block; }
.sl-faq-item.is-open .sl-faq-icon { transform: rotate(45deg); }

/* The smooth part. Animating max-height needs a magic number that is always
   either too small (clipped) or too large (a lazy tail on the way open).
   0fr -> 1fr on a grid row animates the CONTENT's own height exactly, so every
   answer opens at the same speed whatever its length. */
/* ⛔⛔ NO LAYOUT ANIMATION. Jay reported the FAQ as slow and sticky twice.
   Measured on the live page: the worst frame is ~115ms and the MEDIAN is 32ms
   with nothing happening at all, and removing the testimonials ticker or the
   background-video nodes changed none of it. The page simply has no spare
   frame budget, so animating grid-template-rows, which re-sizes tracks and
   relays out everything below on EVERY frame, was competing for time that was
   never there.
   The row now snaps open and only the answer's opacity and transform animate,
   and both of those are compositor properties that cost no layout at all. */
.sl-faq-a {
  display: grid;
  grid-template-rows: 0fr;
}
.sl-faq-item.is-open .sl-faq-a { grid-template-rows: 1fr; }
.sl-faq-a-inner { overflow: hidden; }

.sl-faq-a-text {
  margin: 0;
  padding: 0 46px 28px 4px;
  color: var(--_colors---colors--neutral-03);
  font-size: var(--font-sizes--body-03, 16px);
  line-height: var(--line-height--xl, 1.7);
  opacity: 0;
  transform: translateY(-6px);
  /* opacity and transform only: no layout, no paint of anything above it */
  transition: opacity .19s ease, transform .19s ease;
}
.sl-faq-item.is-open .sl-faq-a-text { opacity: 1; transform: none; }

@media screen and (max-width: 767px) {
  .sl-faq-q { padding: 20px 2px; gap: 16px; }
  .sl-faq-a-text { padding: 0 34px 22px 2px; }
  .sl-faq-icon { width: 18px; height: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .sl-faq-a,
  .sl-faq-a-text,
  .sl-faq-icon { transition: none; }
}

/* --- 6. The quote pop-up. Alex's "IMPORTANT ONE".
   Every Get Your Free Quote / Book a Consultation / package button opens this
   instead of walking the visitor off to the contact page. */
.sl-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.sl-modal[hidden] { display: none; }

.sl-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 17, 51, 0.72);
  backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity .28s ease;
}
.sl-modal.is-open .sl-modal-backdrop { opacity: 1; }

.sl-modal-dialog {
  position: relative;
  width: 100%;
  max-width: 560px;
  /* dvh, so the dialog is measured against the visible viewport rather than
     the device: iOS lays out between its toolbars and a vh-sized panel runs
     under them */
  max-height: 88vh;
  max-height: 88dvh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--_colors---colors--neutral-01, #fff);
  border-radius: 14px;
  padding: 40px 40px 34px;
  box-shadow: 0 30px 80px rgba(0, 17, 51, .45);
  opacity: 0;
  transform: translateY(14px) scale(.985);
  transition: opacity .3s ease, transform .3s cubic-bezier(.4, 0, .2, 1);
}
.sl-modal.is-open .sl-modal-dialog { opacity: 1; transform: none; }

.sl-modal-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 38px;
  height: 38px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  touch-action: manipulation;
  transition: background-color .2s ease;
}
.sl-modal-close:hover { background: rgba(0, 23, 51, .07); }
.sl-modal-close:focus-visible { outline: 2px solid var(--sl-gold); outline-offset: 2px; }
.sl-modal-close span {
  position: absolute;
  width: 16px;
  height: 2px;
  background: var(--sl-navy);
  border-radius: 2px;
}
.sl-modal-close span:first-child { transform: rotate(45deg); }
.sl-modal-close span:last-child { transform: rotate(-45deg); }

.sl-modal-head { margin-bottom: 26px; padding-right: 34px; }
.sl-modal-head .section-subtitle-wrapper { margin-bottom: 10px; }
.sl-modal-title {
  margin: 0 0 8px;
  font-family: var(--font--heading-font);
  font-size: var(--font-sizes--h4, 30px);
  line-height: var(--line-height--sm, 1.15);
  font-weight: var(--font-weight--bold);
  letter-spacing: var(--letter-spacing--xs);
  color: var(--_colors---colors--neutral-04);
}
.sl-modal-sub {
  margin: 0;
  color: var(--_colors---colors--neutral-03);
  font-size: var(--font-sizes--body-04, 14px);
  line-height: var(--line-height--xl, 1.7);
}

.sl-form { display: flex; flex-direction: column; gap: 16px; }
.sl-field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.sl-field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }

.sl-field label {
  font-family: var(--font--body-font);
  font-size: 13px;
  font-weight: var(--font-weight--medium, 500);
  letter-spacing: .01em;
  color: var(--_colors---colors--neutral-04);
}
.sl-req { color: var(--sl-gold); }

.sl-field input,
.sl-field textarea,
.sl-field select {
  width: 100%;
  font-family: var(--font--body-font);
  /* ⛔ never below 16px: iOS zooms the whole page on focus of a smaller field */
  font-size: 16px;
  line-height: 1.4;
  color: var(--_colors---colors--neutral-04);
  background: #fff;
  border: 1px solid rgba(0, 23, 51, .18);
  border-radius: 9px;
  padding: 12px 14px;
  transition: border-color .18s ease, box-shadow .18s ease;
  -webkit-appearance: none;
  appearance: none;
}
.sl-field textarea { resize: vertical; min-height: 84px; }
.sl-field input::placeholder,
.sl-field textarea::placeholder { color: rgba(0, 23, 51, .38); }

.sl-field input:focus,
.sl-field textarea:focus,
.sl-field select:focus {
  outline: none;
  border-color: var(--sl-gold);
  box-shadow: 0 0 0 3px rgba(225, 166, 74, .2);
}
.sl-field input.is-bad,
.sl-field select.is-bad { border-color: #C0392B; }
.sl-err { display: none; font-size: 12px; color: #C0392B; }
.sl-err.is-on { display: block; }

/* the select keeps a chevron, drawn rather than shipped, so it needs no asset */
.sl-select-wrap { position: relative; }
.sl-select-wrap::after {
  content: "";
  position: absolute;
  right: 16px;
  top: 50%;
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--sl-navy);
  border-bottom: 2px solid var(--sl-navy);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

/* Brand guide §6: the primary CTA is gold with navy text, the same rule the
   rest of this stylesheet applies to the template's own buttons. */
.sl-submit {
  margin-top: 4px;
  padding: 15px 22px;
  border: 0;
  border-radius: 9px;
  background: var(--sl-gold);
  color: var(--sl-navy);
  font-family: var(--font--body-font);
  font-size: 15px;
  font-weight: var(--font-weight--bold, 700);
  letter-spacing: .01em;
  cursor: pointer;
  touch-action: manipulation;
  transition: filter .2s ease, transform .12s ease;
}
.sl-submit:hover { filter: brightness(1.06); }
.sl-submit:active { transform: translateY(1px); }
.sl-submit:focus-visible { outline: 2px solid var(--sl-navy); outline-offset: 2px; }
.sl-submit[disabled] { opacity: .6; cursor: default; }

.sl-form-note {
  margin: 0;
  text-align: center;
  font-size: 12px;
  color: var(--_colors---colors--neutral-03);
}

/* ⛔⛔⛔ THE HONEYPOT ATE A REAL ENQUIRY ON 19 SEP. Off-screen is still
   RENDERED, and a rendered field named "company" labelled "Company" is exactly
   what Chrome, Edge and every password manager fill from an address profile.
   Alex autofilled the form, this field filled itself, the page classified him
   as a bot and thanked him for a lead it never sent.
   ⭐⭐⭐ `display:none` is the fix, and it is not a weakening: autofill SKIPS a
   display:none field, while the scripted bots this exists to stop parse the DOM
   and fill everything in it. The trap gets stronger against bots and blind to
   humans at the same time. Field renamed to "website" to match Pika and
   Mongolie, which have never had this happen. */
.sl-hp { display: none; }

/* ⛔⛔⛔ `form.hidden = true` DID NOTHING, AND THAT IS WHAT ALEX SAW.
   An author-stylesheet `display:flex` beats the user agent's `[hidden]` rule
   no matter how specific the selector looks, so the form stayed on screen and
   the confirmation was appended UNDERNEATH it: measured, form still 668px
   tall, panel starting at y=910 with the dialog ending at 846, so the
   checkmark was below the fold and the live Send button was still sitting
   above it. His words: "it pops bellow and its hard to see the checkmark and
   I want to avoid double submissions."
   ⭐⭐⭐ The tell was already in this file: `.sl-form-done[hidden]` was written
   defensively one line below, for the same reason, on the same night. The
   author of that line knew the rule and did not apply it to the form. Any
   element this file gives a `display` to needs its own `[hidden]`. */
.sl-form[hidden] { display: none; }

.sl-form-done { text-align: center; padding: 18px 0 8px; }
.sl-form-done[hidden] { display: none; }
.sl-done-mark {
  width: 56px;
  height: 56px;
  margin: 0 auto 18px;
  border-radius: 50%;
  background: rgba(225, 166, 74, .16);
  position: relative;
}
.sl-done-mark::after {
  content: "";
  position: absolute;
  left: 20px;
  top: 15px;
  width: 13px;
  height: 24px;
  border-right: 3px solid var(--sl-gold);
  border-bottom: 3px solid var(--sl-gold);
  transform: rotate(42deg);
}
.sl-form-done h3 {
  margin: 0 0 8px;
  font-family: var(--font--heading-font);
  font-size: var(--font-sizes--h5, 22px);
  font-weight: var(--font-weight--bold);
  color: var(--_colors---colors--neutral-04);
}
.sl-form-done p {
  margin: 0;
  color: var(--_colors---colors--neutral-03);
  font-size: var(--font-sizes--body-04, 14px);
  line-height: var(--line-height--xl, 1.7);
}

/* --- Round 13: the confirmation REPLACES the form rather than hanging under
   it. Jay: "once one is submitted, it replaces the content of the form with
   the success message ... visible and centered on the screen, so that it's
   clear that it's been submitted and they can close it afterwards."
   The heading goes with the fields, so what is left is a small card holding
   the checkmark and two lines. .sl-modal is a centring flex container, so a
   shorter dialog re-centres itself with nothing measured. The close button is
   a sibling of the head, not a child, so it survives the swap. */
.sl-modal-dialog.is-done {
  max-width: 440px;
  padding: 44px 40px 40px;
  overflow-y: visible;          /* nothing left that can scroll */
}
.sl-modal-dialog.is-done .sl-modal-head { display: none; }

/* ⭐ The swap is a fade of the WHOLE box, deliberately, not a height
   animation. The two panels are different heights, so animating height means
   measuring both, at every width, on a box that is already max-height capped
   against a phone's shifting viewport. Fading out, swapping while nothing is
   readable, and fading back has no measurement in it and cannot be wrong at
   any size. ⚠️ Must stay AFTER `.sl-modal.is-open .sl-modal-dialog`: same
   specificity, so source order is what decides the winner. */
.sl-modal-dialog.is-swapping { opacity: 0; transition: opacity .16s ease; }

.sl-form-done { animation: sl-done-in .34s cubic-bezier(.2, .7, .3, 1) both; }
@keyframes sl-done-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.sl-done-mark { animation: sl-mark-pop .42s cubic-bezier(.2, 1.3, .4, 1) .06s both; }
@keyframes sl-mark-pop {
  from { opacity: 0; transform: scale(.7); }
  to   { opacity: 1; transform: none; }
}

@media screen and (max-width: 560px) {
  .sl-modal-dialog.is-done { padding: 34px 22px 30px; }
}
@media (prefers-reduced-motion: reduce) {
  .sl-form-done,
  .sl-done-mark { animation: none; }
  .sl-modal-dialog.is-swapping { transition: none; }
}

/* Pinned, not just overflow:hidden. iOS happily keeps scrolling the page
   behind a dialog when only overflow is set; the JS stores the offset and puts
   it back on close, so the page does not jump to the top either. */
body.sl-modal-open { overflow: hidden; position: fixed; width: 100%; }

@media screen and (max-width: 560px) {
  .sl-modal { padding: 12px; }
  .sl-modal-dialog { padding: 30px 22px 26px; border-radius: 12px; }
  .sl-field-row { grid-template-columns: 1fr; }
  .sl-modal-head { margin-bottom: 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .sl-modal-backdrop,
  .sl-modal-dialog { transition: none; }
  .sl-modal-dialog { transform: none; }
}

/* The stats sat at the top of the right column while the photo opposite ran
   ~490px, leaving a dead half-column under them. Measured, not eyeballed:
   photo 358-845, stats 100-490. The block now takes the column's full height
   and centres its two rows against the picture. */
/* ⚠️ MEASURED: .choose-us-right-block computes to display:BLOCK at this
   breakpoint, despite the flex-flow:column in the template sheet, so flex:1
   on the child was inert and the stats kept sitting at 393px against a 746px
   column. The block does have a definite height, so a percentage height is
   the lever that actually works here. */
#who-we-are .sl-proof-col { min-height: 100%; align-content: center; }

/* ⛔⛔ AND THAT WAS STILL NOT THE PHOTO. Alex round 3: "Can we align/center the
   4 paragraphs to the photo please?"
   `min-height:100%` is 100% of .choose-us-right-block, whose height is the
   WHOLE left column, heading and photo together. So the stats centred on the
   column and sat exactly half the heading block above the photo: measured
   -128px at 1152, 1280, 1440, 1600, 1920 and 2560, and -165px between 992 and
   1100 where the heading wraps to three lines. The rule computed as `center`
   the whole time, which is why it passed its own check twice.
   The padding below is written by initWhyAlign() in js/sierra-lights.js from
   the measured distance between the top of the left column and the top of the
   photo. With it applied, this block's CONTENT box is exactly the photo's
   span, so the `min-height:100%` above finally resolves against the picture.
   Defaults to 0px, so with no JS the section renders as it does today. */
@media screen and (min-width: 992px) {
  #who-we-are .choose-us-right-block { padding-top: var(--sl-why-offset, 0px); }
}

/* The submit stays on screen however short the window is. The dialog is the
   scroller, so a sticky footer inside it pins the button to the bottom edge
   while the fields scroll underneath. The negative bottom closes the 1px
   sub-pixel gap that otherwise lets a field show through on some zoom levels. */
.sl-form-foot {
  position: sticky;
  bottom: -1px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 0 2px;
  margin-top: 2px;
  background: var(--_colors---colors--neutral-01, #fff);
}
.sl-form-foot::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: -18px;
  height: 18px;
  background: linear-gradient(to top, var(--_colors---colors--neutral-01, #fff), rgba(255,255,255,0));
  pointer-events: none;
}
.sl-submit { margin-top: 0; }

/* ==========================================================================
   ROUND 6 — Alex 18 Sep + Jay 18 Sep
   ========================================================================== */

/* --- A1. The pop-up has to clear the header.
   Alex: "In the form, you can't click on the X because the who we are is
   highlighted." MEASURED: .header-section carries the template's own
   z-index:999999, so at the X's coordinates the top element was
   .navbar-wrapper and the close button was genuinely unclickable, not just
   visually covered. Anything that sits over a modal has to lose to it. */
.sl-modal { z-index: 1000001; }

/* --- A2. Hero: the stars come up to the buttons so the whole block fits.
   Alex: "Make the stars closer to the buttons so everything fits on te
   landing page." MEASURED: .hero-wrapper had a 100px row gap, which put the
   trust line 731px down a 900px screen and pushed it under the fold on
   anything shorter. 40px keeps them as one group and takes 60px out of the
   hero, which also lets the section floor come down. */
@media screen and (min-width: 992px) {
  .hero-wrapper { row-gap: 40px; }
  /* floor lowered with the content: 880 was sized for the taller block */
  .hero-section { min-height: max(100vh, 820px); }
}
@media screen and (max-width: 991px) {
  .hero-wrapper { row-gap: 32px; }
}

/* --- J1. The FAQ, after Jay reported it as glitchy and slow.
   The jump he felt is fixed in JS (questions no longer close each other, so
   the row under the cursor never moves). These two sit alongside it:
   faster, and scoped so the browser repaints the answer rather than the band.
   ⚠️ Measured first: animated, instant and opacity-only opens all cost the
   same per frame, and an idle page cost more than any of them, so the
   duration was never the real problem. It is shortened because 380ms on top
   of a page this heavy reads as hesitation. */
/* ⚠️ `contain: layout paint` went with the height animation. It was there to
   scope the relayout that no longer happens, and on a snap-open it only adds
   another containment boundary for the compositor to manage. */
.sl-faq-icon { transition-duration: .22s; }

/* --- J2. The bottom of the page becomes ONE blue block.
   Jay: "it needs to be a whole blue section, like the footer. The background
   of the footer gets extended up to include Book a free consultation with a
   little bit of spacing above it."
   The template shipped a 247px navy half-band with a cream card lapping over
   it onto white. Leaving the card cream would have given cream FAQ, a navy
   sliver, a cream card, then navy footer: worse, not better. So the card
   takes the footer's exact navy and its text inverts, and the CTA band and
   the footer read as one surface. */
.cta-section {
  background-color: var(--sl-navy);
  padding-top: 90px;           /* Jay's "little bit of spacing above it" */
}
.cta-bg,
.cta-bg.w-variant-39927133-be85-a162-636b-018 { background-color: var(--sl-navy); }

/* ⛔ Jay, 18 Sep: "you've also got rid of the card... I still wanted that. I
   just wanted the blue background to be behind it." So the card KEEPS its own
   beige surface and its navy text exactly as the template drew them; only the
   band behind it changed. The previous version painted the card navy too,
   which dissolved it into the footer and lost the panel entirely. */

@media screen and (max-width: 767px) {
  .cta-section { padding-top: 60px; }
}

/* --- A6. The multi-year discounts. Option A of four, chosen by Jay 18 Sep:
   one hairline strip rather than a block of cards, sitting close under the
   package cards, with the figures in gold.
   ⛔ Two earlier attempts are recorded in the README: an invented tile that
   did not animate, and a 292px row of stats-cards that Jay called "too big
   and just plugged into the page". */
.sl-terms {
  width: 100%;
  /* ⚠️ MEASURED: at +25% the label and the four figures need 862px plus 56px
     of padding. At 900px the label was pushed onto its own line and the strip
     doubled to 152px tall, which reads as the block growing rather than the
     type growing. 1020px keeps it on one line with headroom. */
  max-width: 1020px;
  /* Jay: "bring it up a little bit closer". MEASURED: the gap was 150px, made
     of the section's own 72px row gap PLUS the 44px bottom margin on the card
     list (added so The Signature can grow past its row) PLUS this margin.
     Cancelling exactly the 44px puts the strip on the section's natural 72px
     rhythm, the same gap the heading has above the cards, rather than on an
     arbitrary number. */
  /* Jay asked for more room above it again on 18 Sep, so the pull-up is
     eased off from -44px. */
  margin: -12px auto 0;
}
.sl-strip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 42px;
  flex-wrap: wrap;
  padding: 23px 28px;
  border-top: 1px solid rgba(0, 23, 51, .1);
  border-bottom: 1px solid rgba(0, 23, 51, .1);
}
.sl-strip-label {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  font-family: var(--font--body-font);
  font-size: 17px;
  font-weight: var(--font-weight--medium, 500);
  color: var(--_colors---colors--neutral-03);
}
.sl-strip-label img { width: 17px; height: 17px; }

.sl-strip-items {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 38px;
  flex-wrap: wrap;
}
.sl-strip-item { display: flex; align-items: baseline; gap: 10px; }

.sl-strip-pct {
  font-family: var(--font--heading-font);
  font-size: 33px;              /* 26px +25%, Jay 18 Sep */
  font-weight: var(--font-weight--bold);
  letter-spacing: -.02em;
  color: var(--sl-gold);        /* Jay, 18 Sep */
}
.sl-strip-yrs {
  font-family: var(--font--body-font);
  font-size: 16px;
  color: var(--_colors---colors--neutral-03);
}

/* Jay, 18 Sep: centre it rather than running to the left edge.
   ⚠️ text-align alone did nothing visible. The paragraph carries max-width:720px
   inside a 1344px flex container with margin-left:0, so the text was centred
   within a box that itself sat hard left. The margins are what move it. */
.sl-price-note {
  text-align: center;
  margin-left: auto;
  margin-right: auto;
}

@media screen and (max-width: 767px) {
  .sl-strip { gap: 14px; padding: 16px 10px; }
  .sl-strip-items { gap: 18px; }
  .sl-strip-pct { font-size: 22px; }
}
@media screen and (max-width: 479px) {
  .sl-strip-items { gap: 14px; }
  .sl-strip-pct { font-size: 20px; }
  .sl-strip-yrs { font-size: 12px; }
}


@media screen and (max-width: 767px) {
  .cta-section { padding-top: 60px; }
}


@media screen and (max-width: 767px) {
  .cta-section { padding-top: 60px; }
}



/* ==========================================================================
   ROUND 13 — the mobile pass, 19 September 2026

   Jay: "a real detailed pass on mobile to make sure that everything looks
   correct, adapts to different screen sizes, and animates (all the sort of
   stuff that the regular template would have done)."

   Alex is emailing his whole client base, so this page is about to be opened
   on phones far more than on desktops. Everything below is a MEASURED finding
   from _qa/r13mob.js across nine layout sizes from 360x600 to 768x1024, not a
   guess about what phones like.

   ⛔⛔ THE VIEWPORT HEIGHTS IN THAT SWEEP ARE LAID-OUT HEIGHTS, NOT DEVICE
   HEIGHTS. iOS Safari lays out between its toolbars: a 390x844 handset gets
   390x664. Sizing to the device number is how a hero block lands on top of
   its own buttons, and it is worst on the biggest phones.
   ========================================================================== */

/* --- M1. iOS ZOOMS THE WHOLE PAGE when you tap a text field smaller than
   16px, then leaves the page zoomed in and scrolled sideways. The four fields
   in the bottom consultation band are 15px, so every phone user who filled
   that form got thrown into a zoomed viewport on the first tap. 16px is the
   threshold exactly, not a rounding: 15.99 zooms.
   ⚠️ Mobile only. The desktop form keeps the template's 15px, so nothing a
   client has already signed off changes. The pop-up's own fields were already
   16px, which is why they never did this. */
@media screen and (max-width: 991px) {
  .text-field.w-input,
  .text-field.w-select,
  textarea.text-field { font-size: 16px; }
}

/* --- M2. Tap targets. Every one of these is a control somebody aims a thumb
   at, and every one measured under the 44px minimum on every phone tested.
   ⭐ The pattern throughout is min-height plus centring, NOT extra margin:
   the target grows around the text, the type does not move and nothing in the
   layout shifts. The visual size of every icon is unchanged. */
@media screen and (max-width: 991px) {
  /* the burger was 25x15. It is the only way to reach the menu on a phone. */
  .menu-button.w-nav-button {
    width: 44px;
    height: 44px;
    min-width: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    top: 0;
    touch-action: manipulation;
  }

  /* 30x30 pills. The dot stays 30px, the tappable area becomes 44. */
  .social-icon-wrapper { gap: 6px; }
  .social-icon-item {
    width: 44px;
    min-width: 44px;
    height: 44px;
    /* the visible disc is drawn by a background inset rather than by the box,
       so the circle looks identical and only the hit area grows */
    background-color: #0000;
    position: relative;
  }
  .social-icon-item::before {
    content: "";
    position: absolute;
    inset: 7px;
    border-radius: var(--_sizes---radius--radius-full, 999px);
    background-color: #ffffff1a;
    transition: background-color .2s ease;
  }
  .social-icon-item:hover::before { background-color: var(--_colors---colors--theme-color-01); }
  .social-icon-item img { position: relative; z-index: 1; }

  /* 27px text links in the footer, the CTA band's phone number, and the
     contact rows. The footer's own column gap comes down by the amount the
     links grow, so the block ends up the same height it was. */
  .footer-widget-link-block { gap: 0; }
  .footer-widget-link {
    display: flex;
    align-items: center;
    min-height: 44px;
    touch-action: manipulation;
  }
  .cta-button-number,
  a.contact-info-text,
  .sl-header-phone {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    touch-action: manipulation;
  }
  .contact-info-item { align-items: center; }

  /* ⭐⭐ The most important one. This is the "Get Your Free Quote" link on
     each package card, which is the conversion control the whole section
     exists to deliver, and it measured 179x26 on every phone. */
  .service-card .button,
  .services-card .button,
  a.button[data-sl-open] {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    touch-action: manipulation;
  }
  .service-title {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* --- M3. The multi-year strip broke 3 + 1, leaving "20% 5 years" alone and
   centred on its own row, which reads as a mistake rather than as a set of
   four. A 2x2 grid gives four equal cells and the same block reads as one
   thing. ⚠️ grid, not flex-wrap: wrapping is what produced the orphan. */
@media screen and (max-width: 767px) {
  .sl-strip-items {
    display: grid;
    grid-template-columns: repeat(2, auto);
    justify-content: center;
    column-gap: 26px;
    row-gap: 14px;
  }
  .sl-strip-item { justify-content: center; }
}

/* --- M4. Double-tapping a control must not zoom the page. Applied at section
   level so anything injected later is covered too, rather than an allowlist of
   selectors that somebody has to maintain.
   ⛔⛔⛔ NEVER user-scalable=no to achieve this: it kills pinch zoom, fails
   WCAG 1.4.4 and iOS ignores it anyway. */
@media screen and (max-width: 991px) {
  .navbar,
  .hero-section,
  .cta-section,
  .footer-section,
  .sl-modal { touch-action: manipulation; }
}

/* ==========================================================================
   ROUND 14 — Jay's mobile pass, 19 September 2026

   Round 13 made the page FIT a phone. This one makes it look designed for one.
   Everything here is scoped to the burger breakpoint or below, so the desktop
   Alex has already signed off is untouched.
   ========================================================================== */

/* --- N1. The phone icon comes OUT of the header bar, and the burger goes back
   to the size the template drew it.
   ⛔⛔ ROUND 13 INFLATED THE BURGER WITHOUT REALISING. `.menu-button` is not an
   icon, it is the CONTAINER OF A LOTTIE, and a Lottie scales to fill its box.
   Setting the box to 44x44 for the tap target scaled the artwork with it, from
   the template's 25x15 to 44x44, which is why Jay said it "looked a little bit
   big". ⭐⭐⭐ Grow the HIT AREA, never the box: a transparent ::after centred
   on the button gives 44x44 to a thumb while the drawn icon keeps the exact
   dimensions the template gave it. */
@media screen and (max-width: 991px) {
  .sl-header-phone { display: none !important; }

  .menu-button.w-nav-button {
    width: 25px;
    height: 15px;
    min-width: 0;
    padding: 0;
    display: block;
    position: relative;
    top: -5px;
    touch-action: manipulation;
  }
  .menu-button.w-nav-button::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* --- N2. The dropdown carries the quote button and the number instead.
   Jay: "put the button that appears on desktop in the header in that dropdown
   as well, and the phone number as well."
   ⛔ Desktop must never see it: `.nav-menu-2` is the inline nav bar up there,
   not a panel. */
.sl-nav-actions { display: none; }

@media screen and (max-width: 991px) {
  .sl-nav-actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
    margin-top: 18px;
    padding-top: 18px;
    border-top: 1px solid rgba(0, 23, 51, .12);
  }
  /* full width inside the panel, so it reads as the panel's action rather than
     as a stray pill */
  .sl-nav-actions .button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 52px;
    text-align: center;
  }
  .sl-nav-actions .button .button-text-wrapper { justify-content: center; }
  .sl-nav-phone {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    min-height: 44px;
    font-family: var(--font--body-font);
    font-size: 17px;
    font-weight: var(--font-weight--medium, 500);
    /* ⚠️ the panel is WHITE, unlike the header, which sits on the dark hero.
       The header's phone colour is near-white and would vanish here. */
    color: var(--_colors---colors--neutral-04);
    touch-action: manipulation;
  }
  .sl-nav-phone-icon { width: 18px; height: 18px; }
}

/* --- N3. The hero fills the screen.
   Jay: "should fill the screen and adapt to whatever screen or browser it's
   on ... it shouldn't overlap the screen."
   ⛔⛔⛔ `100vh` IS THE WRONG UNIT AND IT IS THE ONE EVERYBODY REACHES FOR. On
   iOS Safari `vh` is the LARGE viewport, measured with the toolbars hidden, so
   a 100vh hero is taller than the screen you are actually looking at and its
   buttons sit under the browser furniture. `svh` is the SMALL viewport, the
   one with the toolbars showing, so it always fits. ⭐ `dvh` is not the answer
   either: it changes AS YOU SCROLL, so the hero would resize under the reader.
   The cascade is deliberate: vh for anything ancient, svh wins where supported.
   ⚠️ Worst on the biggest phones, because the furniture is a fixed height and
   the free space grows. */
@media screen and (max-width: 991px) {
  .hero-section {
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    align-items: center;
    /* the bar is absolute over the hero, so the content clears it by hand */
    padding-top: 96px;
    padding-bottom: 40px;
  }
  .hero-section .container.hero { width: 100%; }
  /* the block now owns the space rather than being pushed down by padding,
     so the gaps can breathe on a tall phone and tighten on a short one */
  .hero-wrapper {
    row-gap: clamp(20px, 4.5vh, 44px);
    justify-content: center;
  }
  /* Jay: "center the text and the buttons". Everything in the hero centres on
     mobile, which is what makes a full-bleed photo read as a poster rather
     than as a page with a picture behind it. The stars and the trust line come
     with it, or the block looks like two different decisions. */
  .hero-text-block {
    display: flex;
    flex-direction: column;
    gap: clamp(14px, 3vh, 30px);
    text-align: center;
    align-items: center;
  }
  .hero-section .display-heading-1 { text-align: center; }
  .hero-section .sl-hero-location { text-align: center; }
  .button-group { display: flex; flex-direction: column; gap: 12px; width: 100%; }
  .hero-section .button-group .button { width: 100%; min-height: 56px; }
  .hero-section .button-group .button .button-text-wrapper { justify-content: center; }
  .hero-section .review-stats { display: flex; flex-direction: column; align-items: center; text-align: center; }
  .hero-section .sl-star-row { justify-content: center; }
  /* ⭐ Centred text makes a one-word last line look like a mistake rather than
     like a wrap. `balance` lets the browser even out the lines itself, which
     survives any future copy change; a hand-placed <br> would not. Ignored by
     anything that does not support it, so it can only improve. */
  .hero-section .display-heading-1,
  .hero-section .sl-hero-location,
  .hero-section .review-text { text-wrap: balance; }
  .hero-section .review-text { max-width: 22ch; }
}

/* --- N4. Multi-year savings: wider and bigger.
   Jay: "it's okay that you stack them, but maybe just spread them out a little
   bit widthways and make them a little bit bigger."
   The round 13 grid was `repeat(2, auto)` centred, which shrink-wrapped both
   columns into the middle of the screen. `1fr 1fr` across the full strip is
   what actually spreads them. */
@media screen and (max-width: 767px) {
  .sl-strip { padding: 22px 6px; gap: 18px; }
  .sl-strip-items {
    display: grid;
    grid-template-columns: 1fr 1fr;
    justify-content: stretch;
    column-gap: 10px;
    row-gap: 22px;
    width: 100%;
  }
  .sl-strip-item {
    justify-content: center;
    align-items: baseline;
    gap: 8px;
  }
  .sl-strip-pct { font-size: 30px; }
  .sl-strip-yrs { font-size: 15px; }
  .sl-strip-label { font-size: 16px; }
}
@media screen and (max-width: 479px) {
  .sl-strip-items { column-gap: 6px; }
  .sl-strip-pct { font-size: 27px; }
  .sl-strip-yrs { font-size: 14px; }
}

/* --- N5. "Nothing To Buy. Nothing To Store." — the slider gets height back.
   Jay: "some way of making that image bigger vertically on mobile without
   taking away too much of the width."
   Width stays 100%; the frame goes from 16:9 to 4:3, which at 393px is 203px
   -> 271px, a third more house for the same width. ⚠️ The images are
   object-fit:cover, so this crops the sides rather than stretching anything. */
@media screen and (max-width: 767px) {
  .sl-ba { aspect-ratio: 4 / 3; }
}
@media screen and (max-width: 479px) {
  .sl-ba { aspect-ratio: 5 / 4; }
}

/* --- N6. THE SLIDER YOU COULD NOT USE ON A PHONE.
   Jay: "I can't use the slider on mobile, so that needs to be fixed."

   ⛔⛔⛔ AND MY ROUND 13 GUARD SAID IT WORKED, BECAUSE IT ONLY EVER TAPPED IT.
   The control is an `<input type=range>` stretched invisibly over the photos.
   Chrome moves a range when you tap or drag anywhere on its track, which is
   what the guard measured and what a desktop mouse does. **iOS Safari does
   not.** There, a range only responds to a drag that BEGINS ON THE THUMB, and
   this thumb is transparent and 56px wide, so unless your finger landed on the
   exact divider line, nothing happened at all. Working on every browser I
   could automate, dead on the one the client uses.
   ⭐⭐⭐ The fix is to stop depending on the range's touch behaviour: the
   container handles pointer events itself (see sierra-lights.js), and the
   input stays purely for the keyboard, which is why it keeps its focus ring.
   `touch-action: pan-y` is the other half: it tells the browser vertical
   scrolling is still the page's, while horizontal movement is ours, so a drag
   never gets stolen and the page never stops scrolling. */
.sl-ba { touch-action: pan-y; }
.sl-ba-range { pointer-events: none; }

@media (hover: none) {
  /* a thumb needs a bigger target than a cursor does */
  .sl-ba-handle { width: 58px; height: 58px; margin: -29px 0 0 -29px; }
  .sl-ba-handle svg { width: 16px; height: 16px; }
}

/* --- N7. Experience / Reviews / Insured / Covered, as a designed 2x2.
   Jay: "perhaps two side by side and then two underneath, and then designed in
   a way that looks proper and good on mobile."
   The template stacks all four full width, which is four near-identical tall
   cards in a column. As a 2x2 the four read as one set, which is what they
   are. The internals get rebuilt rather than just squeezed: the icon row sits
   above, the figure is the loudest thing in the cell, and the caption wraps
   under it instead of fighting the number for the same line. */
@media screen and (max-width: 767px) {
  .sl-stats-row .stats-card-list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }
  .sl-stats-row .stats-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 18px 14px 16px;
    min-height: 0;
    height: 100%;
    /* ⛔⛔ A GRID ITEM'S DEFAULT min-width IS auto, WHICH MEANS "never shrink
       below my contents". Without this the card refuses to fit its own column
       and pushes the whole page sideways instead: measured 189px of card in a
       174.5px column, so the page scrolled horizontally on every phone at
       393px and below. The overflow is the symptom; this is the cause. */
    min-width: 0;
  }
  .sl-stats-row .stat-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-width: 0;
  }
  /* ⚠️ These two are PILLS, and the template pads them for a card that is the
     full width of the screen: 24px each side on the label, 16px on the icon.
     At half width that is 181px of furniture inside 161px of room. Measured,
     not guessed. The pill shape is kept, the air inside it is not. */
  .sl-stats-row .stat-title {
    font-size: 13px;
    letter-spacing: .01em;
    padding: 6px 12px;
    min-width: 0;
  }
  /* ⛔ An ellipsis was here as a safety net and it became the bug: at 360px it
     clipped "Experience" to "Experien...". A truncated one-word label is worse
     than a smaller one, so the narrow breakpoint below makes it FIT instead.
     Nothing on this page is allowed to be cut off. */
  .sl-stats-row .stat-icon-wrapper { flex: 0 0 auto; padding: 6px 9px; }
  .sl-stats-row .stat-icon { width: 20px; height: 20px; }
  .sl-stats-row .stat-value { display: flex; flex-direction: column; gap: 2px; }
  .sl-stats-row .counter-title.large { font-size: 30px; line-height: 1.1; }
  /* ⚠️ the WCB cell wraps its figure in .counter-number-wrap, which the
     template gives a fixed 49px height. Left alone it makes that one card
     taller than its three neighbours, which is the exact thing a grid is
     supposed to stop. */
  .sl-stats-row .counter-number-wrap,
  .sl-stats-row .counter-number-wrap.lg { height: auto; width: auto; }
  .sl-stats-row .counter-subtitle { font-size: 13px; line-height: 1.45; }
}
@media screen and (max-width: 389px) {
  .sl-stats-row .counter-title.large { font-size: 26px; }
  .sl-stats-row .stats-card { padding: 15px 12px 14px; }
  /* MEASURED at 360px: card 158, content 134, icon pill 32, gap 8, so the
     label has 94 to live in and needs 65 of it for "Experience" at 12px. */
  .sl-stats-row .stat-title { font-size: 12px; padding: 5px 10px; }
  .sl-stats-row .stat-icon-wrapper { padding: 5px 7px; }
  .sl-stats-row .stat-icon { width: 18px; height: 18px; }
  .sl-stats-row .counter-subtitle { font-size: 12px; }
}

/* --- N8. The pop-up's submit stops being a sticky footer on a phone.
   Jay: "it's keeping Send my request kind of stuck there towards the bottom
   ... I can see things scrolling beneath it at the bottom of the form ... Maybe
   just remove that entirely so that it's at the bottom of the form on mobile
   and it all scrolls together."
   The sticky footer earns its place on a short desktop window, where the
   dialog scrolls and the button would otherwise be out of reach. On a phone
   the dialog is nearly full height already, so all it does is cover the field
   you are typing into and show content sliding underneath it. */
@media screen and (max-width: 767px) {
  .sl-form-foot {
    position: static;
    background: none;
    padding-top: 6px;
  }
  .sl-form-foot::before { display: none; }
}

/* --- N9. Card images fade in rather than snapping in.
   The measurement, and why the images are NOT simply loaded eagerly, are in
   sierra-lights.js above `initImageFade()`. Short version: eager cost 1.5MB
   and 8 seconds of LCP on a throttled link, so they stay lazy.
   ⛔ `.sl-img-pending` is added by JS and ONLY to an image that has not loaded
   yet, so with no JavaScript, or on an image already in cache, none of this
   applies and nothing is ever hidden waiting for a script.
   ⚠️ `transition:none` on the pending state is load-bearing: without it,
   applying the class fades the image OUT, which is a flash in the other
   direction. The transition belongs to the REMOVAL only. */
img.service-image.sl-img-pending { opacity: 0; transition: none; }
img.service-image { transition: opacity .4s ease; }

@media (prefers-reduced-motion: reduce) {
  img.service-image { transition: none; }
}
