/* ----- Typefaces -----
   DM Sans and Outfit, served from this site (they used to be fetched from
   Google's font service on every first visit, a second website to wait on
   before text took its final shape). Same files, same weights, same character
   ranges as that service handed out; both are under the SIL Open Font Licence.
   The file names carry the version, because /fonts/* is cached for a year. */
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url('/fonts/dm-sans-v17-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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url('/fonts/dm-sans-v17-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: 'DM Sans';
  font-style: italic;
  font-weight: 300 500;
  font-display: swap;
  src: url('/fonts/dm-sans-v17-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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'DM Sans';
  font-style: italic;
  font-weight: 300 500;
  font-display: swap;
  src: url('/fonts/dm-sans-v17-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: 'Outfit';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('/fonts/outfit-v15-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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('/fonts/outfit-v15-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;
}

/* =============================================================================
   Premium Roofing — shared site styles
   This file is the canonical source for any rule that should be the same on
   every page (nav, footer, common interactions, accessibility safety nets).
   Loaded BEFORE per-page <style> so per-page rules can still override.
   ============================================================================= */

/* ----- Brand tokens ----- */
:root {
  --black: #0a0a0a;
  --dark: #111111;
  --dark-mid: #1a1a1a;
  --mid: #2a2a2a;
  --light-mid: #999;
  --light: #e8e8e8;
  --white: #ffffff;
  --accent: #ff5d00;
  --accent-dim: #e05400;
  --accent-glow: rgba(255, 93, 0, 0.15);
}

/* ----- Reduced-motion safety net (also injected per-page; kept here for rigour) ----- */
@media (prefers-reduced-motion: reduce) {
  .reveal,
  .stagger-reveal > *,
  .hero-tag,
  .hero-title .word,
  .hero-subtitle,
  .hero-buttons,
  .scroll-indicator {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    animation: none !important;
  }
}

/* ----- Custom cursor: explicitly disabled site-wide -----
   The custom SVG cursor was inconsistent across pages and a usability tax
   on slow hardware / accessibility tools. Use system cursors. */
html, body, a, button, [role="button"], input, textarea, select, .nav-link,
.btn, .card, .service-card, .mega-card, .mega-link {
  cursor: auto;
}
a, button, [role="button"], .nav-link, .btn, .mega-card, .mega-link,
input[type="submit"], input[type="button"], summary {
  cursor: pointer;
}
input[type="text"], input[type="email"], input[type="tel"], input[type="search"],
input[type="number"], textarea {
  cursor: text;
}

/* ----- Footer (canonical) -----
   Site-wide footer styling. Kept here so a single edit updates every page. */
.footer-canonical {
  background: var(--black);
  color: var(--light-mid);
  padding: 4.5rem 3rem 2rem;
  /* no line above the footer: dark sections run into each other with no border */
  font-family: 'DM Sans', sans-serif;
  font-size: 0.92rem;
  line-height: 1.7;
}
.footer-canonical-grid {
  max-width: 1280px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.3fr repeat(5, 1fr);
  gap: 3rem;
  padding-bottom: 3rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.footer-canonical-brand img {
  height: 56px;
  width: auto;
  margin-bottom: 1.25rem;
}
.footer-canonical-tagline {
  color: var(--light-mid);
  font-size: 0.92rem;
  line-height: 1.7;
  max-width: 320px;
}
/* h2: the footer's three lists are sections of the page, not sub-sub-headings
   of whatever came last (they were h4, which skipped levels on every page) */
.footer-canonical-col h2,
.footer-canonical-col h4 {
  font-family: 'Outfit', sans-serif;
  font-size: 0.78rem;
  line-height: normal;
  margin-top: 0;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--white);
  margin-bottom: 1.1rem;
}
.footer-canonical-col ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.footer-canonical-col a,
.footer-canonical-contact a {
  color: var(--light-mid);
  text-decoration: none;
  transition: color 0.2s ease;
}
.footer-canonical-col a:hover,
.footer-canonical-contact a:hover {
  color: var(--accent);
}
.footer-canonical-contact {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  font-style: normal;
}
.footer-canonical-contact strong {
  color: var(--white);
  font-weight: 600;
}
.footer-canonical-bottom {
  max-width: 1280px;
  margin: 0 auto;
  padding-top: 1.5rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  font-size: 0.82rem;
  color: var(--light-mid);
}
.footer-canonical-badges {
  display: flex;
  gap: 1.5rem;
  align-items: center;
  flex-wrap: wrap;
}
.footer-canonical-badge {
  font-family: 'Outfit', sans-serif;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.58);
  padding: 0.35rem 0.7rem;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 3px;
}
/* The BBB badge opens the company's BBB profile. */
a.footer-canonical-badge {
  text-decoration: none;
  transition: color 0.2s ease, border-color 0.2s ease;
}
a.footer-canonical-badge:hover,
a.footer-canonical-badge:focus-visible {
  color: var(--white);
  border-color: rgba(255, 255, 255, 0.3);
}
@media (max-width: 900px) {
  .footer-canonical-grid {
    grid-template-columns: 1fr 1fr;
    gap: 2.25rem;
  }
  .footer-canonical-brand {
    grid-column: 1 / -1;
  }
}
@media (max-width: 540px) {
  .footer-canonical {
    padding: 3rem 1.5rem 1.5rem;
  }
  .footer-canonical-grid {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  .footer-canonical-bottom {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* skip-to-content */
.skip-to-content {
  position: absolute;
  top: -100px;
  left: 1rem;
  z-index: 100000;
  padding: 0.75rem 1.25rem;
  background: var(--accent);
  color: #111;
  font-family: 'Outfit', sans-serif;
  font-weight: 700;
  font-size: 0.85rem;
  text-decoration: none;
  border-radius: 4px;
  transition: top 0.2s ease;
}
.skip-to-content:focus {
  top: 1rem;
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* scroll-progress disabled site-wide
   The 3px orange progress bar at the top of every page reads as a "page loading"
   indicator and consistently scores as confusing in usability tests.
   Hidden globally; element kept in markup for any dependent JS. */
.scroll-progress {
  display: none !important;
}

/* ----- Keyboard focus (canonical) -----
   Visible focus ring for keyboard users only; mouse clicks stay clean. */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ----- Media placeholders -----
   All photo/video assets are disconnected pending the media redo.
   Each slot is marked with data-media describing the intended asset.
   The label is rendered from data-media so the slot documents itself. */
.media-ph {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    repeating-linear-gradient(
      -45deg,
      rgba(255, 255, 255, 0.025) 0px,
      rgba(255, 255, 255, 0.025) 1px,
      transparent 1px,
      transparent 12px
    ),
    var(--dark-mid);
  border: 1px dashed rgba(255, 93, 0, 0.35);
  overflow: hidden;
}
.media-ph::before {
  content: attr(data-ph-type);
  position: absolute;
  top: 0.6rem;
  left: 0.75rem;
  font-family: 'Outfit', sans-serif;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  opacity: 0.85;
}
.media-ph::after {
  content: attr(data-media);
  display: block;
  padding: 1.5rem;
  max-width: 90%;
  text-align: center;
  font-family: 'Outfit', sans-serif;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.45);
}
.media-ph--bg {
  position: absolute;
  inset: 0;
  min-height: 0;
  border-left: none;
  border-right: none;
  border-top: none;
}
.media-ph--bg::after {
  font-size: 0.85rem;
}
/* compact labels inside small nav mega-menu thumbnails */
.mega-card-img .media-ph::after {
  font-size: 0.58rem;
  padding: 0.5rem;
  line-height: 1.45;
}
.mega-card-img .media-ph::before {
  font-size: 0.52rem;
  top: 0.4rem;
  left: 0.5rem;
}

/* ----- Cross-document page transitions (decision D11) -----
   Branded sweep: old page dims and drifts up, new page reveals top-down.
   Progressive enhancement — browsers without View Transitions just navigate. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
  ::view-transition-old(root) {
    animation: vt-out 0.22s ease both;
  }
  ::view-transition-new(root) {
    animation: vt-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
  }
  @keyframes vt-out {
    to {
      opacity: 0.25;
      transform: translateY(-14px);
    }
  }
  @keyframes vt-in {
    from {
      clip-path: inset(0 0 100% 0);
    }
    to {
      clip-path: inset(0 0 0% 0);
    }
  }
}

/* ----- Motion-layer handoff -----
   When the GSAP motion module boots it sets .has-motion on <html> and takes
   ownership of all entrance animation via inline styles. These overrides
   neutralise the legacy CSS reveal/keyframe system so the two never fight. */
html.has-motion .reveal,
html.has-motion .stagger-reveal > * {
  opacity: 1;
  transform: none;
  transition: none !important;
}
/* Attribute selectors cover every page's hero prefix
   (.hero-*, .port-hero-*, .sp-hero-*, .fn-hero-*, ...) */
html.has-motion [class$="hero-tag"],
html.has-motion [class$="hero-title"],
html.has-motion [class$="hero-title"] .word,
html.has-motion [class$="hero-sub"],
html.has-motion [class$="hero-subtitle"],
html.has-motion [class$="hero-buttons"],
html.has-motion [class$="hero-phone"],
html.has-motion .scroll-indicator {
  opacity: 1;
  transform: none;
  animation: none !important;
}

/* =============================================================================
   Shared motion-system components (canonical; used across multiple pages)
   ============================================================================= */

/* ===== ROOF SYSTEM ASSEMBLY ===== */
.roof-assembly {
  position: relative;
  /* the dark band fades to black at both edges — no seam against the sections
     above and below; the orange glow rides on top of it */
  background:
    radial-gradient(ellipse 70% 55% at 70% 45%, rgba(255, 93, 0, 0.05), transparent 65%),
    var(--black);
}
.roof-assembly-pin {
  min-height: 100vh;
  display: flex;
  align-items: center;
}
.roof-assembly-inner {
  display: grid;
  grid-template-columns: minmax(320px, 460px) 1fr;
  gap: 3.5rem;
  align-items: center;
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  padding: 5rem 3rem;
}
.roof-assembly-copy .interstitial-tag {
  justify-content: flex-start;
}
.roof-assembly-title {
  font-family: 'Outfit', sans-serif;
  font-weight: 800;
  font-size: clamp(2.4rem, 4.5vw, 4rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--white);
  margin: 1.25rem 0;
}
.roof-assembly-title .word-thin {
  font-weight: 300;
  color: var(--light-mid);
}
.roof-assembly-subtitle {
  font-size: 1rem;
  line-height: 1.65;
  color: var(--light-mid);
  max-width: 420px;
}
.roof-layers {
  list-style: none;
  margin-top: 2.25rem;
  padding: 0;
}
.roof-layer {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  /* Steps the film has not reached yet stay readable ahead of it. */
  opacity: 0.58;
  transition: opacity 0.4s ease;
}
.roof-layer.is-active {
  opacity: 1;
}
/* No motion module (reduced motion, or no JS) means nothing will ever light the
   list: show it whole beside the still. */
html:not(.has-motion) .roof-layer {
  opacity: 1;
}
.roof-layer-num {
  font-family: 'Outfit', sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--accent);
  min-width: 1.6rem;
}
.roof-layer strong {
  display: block;
  font-family: 'Outfit', sans-serif;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--white);
}
.roof-layer div span {
  font-size: 0.82rem;
  color: var(--light-mid);
}
.roof-assembly-stage {
  position: relative;
  height: min(72vh, 640px);
}
/* ----- rendered assembly loop -----
   A system with a Blender render plays as a looping video in the stage instead
   of the WebGL scene (src/motion/assemblyVideo.ts). It must read as if there
   were no frame at all, so: the clip is rendered 5:4 for this stage with every
   piece held clear of its edges at every frame (blender/tpo `--framing site`,
   verified by `--framecheck`); it is shown whole, never cropped; and `lighten`
   lets the section's orange glow read through the clip's black, so there is no
   box. The poster is the same frame, shown before the video starts and when
   motion is off. */
.roof-video,
.roof-stage-poster {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  max-height: 100%;
  aspect-ratio: 5 / 4;
  transform: translate(-50%, -50%);
  mix-blend-mode: lighten;
  pointer-events: none;
}
.roof-video video,
.roof-stage-poster img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* The bar under the picture: pause, a slider to drag through the build, and
   enlarge. It sits on the stage's bottom edge, below the clip's own frame. */
.roof-video-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.roof-video-toggle,
.roof-video-expand,
.roof-video-zoom,
.roof-theatre-close {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  color: var(--light-mid);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 50%;
  cursor: pointer;
  transition: color 0.25s ease, border-color 0.25s ease;
}
.roof-video-toggle:hover,
.roof-video-toggle:focus-visible,
.roof-video-expand:hover,
.roof-video-expand:focus-visible,
.roof-video-zoom:hover,
.roof-video-zoom:focus-visible,
.roof-theatre-close:hover,
.roof-theatre-close:focus-visible {
  color: var(--white);
  border-color: rgba(255, 255, 255, 0.28);
}
.roof-video-toggle svg,
.roof-video-expand svg,
.roof-video-zoom svg,
.roof-theatre-close svg {
  width: 0.8rem;
  height: 0.8rem;
  fill: currentColor;
}
.roof-video-toggle .icon-play,
.roof-video-toggle[aria-pressed='true'] .icon-pause,
.roof-video-expand .icon-shrink,
.roof-video-expand[aria-pressed='true'] .icon-expand {
  display: none;
}
.roof-video-toggle[aria-pressed='true'] .icon-play,
.roof-video-expand[aria-pressed='true'] .icon-shrink {
  display: block;
}

/* the slider: a hairline that fills in orange as the build goes on, with a
   mark where each layer starts. The input itself is the whole 2.25rem band, so
   a thumb has plenty to land on. */
.roof-video-track {
  --p: 0;
  position: relative;
  flex: 1;
  min-width: 0;
  height: 2.25rem;
  cursor: grab;
  touch-action: pan-y; /* a sideways drag is ours; an up-and-down one still scrolls the page */
}
.roof-video-track.is-dragging {
  cursor: grabbing;
}
.roof-video-track::before,
.roof-video-track::after {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  height: 2px;
  margin-top: -1px;
  border-radius: 1px;
  pointer-events: none;
}
.roof-video-track::before {
  right: 0;
  background: rgba(255, 255, 255, 0.16);
}
.roof-video-track::after {
  width: calc(var(--p) * 100%);
  background: var(--accent);
}
.roof-video-ticks i {
  position: absolute;
  top: 50%;
  width: 1px;
  height: 8px;
  margin-top: -4px;
  background: rgba(255, 255, 255, 0.34);
  pointer-events: none;
}
.roof-video-scrub {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: none;
  pointer-events: none; /* the band takes the pointer; the input keeps the keyboard and the thumb */
  -webkit-appearance: none;
  appearance: none;
}
.roof-video-scrub:focus {
  outline: none;
}
.roof-video-scrub::-webkit-slider-runnable-track {
  height: 100%;
  background: none;
}
.roof-video-scrub::-moz-range-track {
  height: 100%;
  background: none;
}
.roof-video-scrub::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  margin-top: calc(1.125rem - 7px);
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(255, 93, 0, 0.18);
  transition: transform 0.2s ease;
}
.roof-video-scrub::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(255, 93, 0, 0.18);
}
.roof-video-track:hover .roof-video-scrub::-webkit-slider-thumb,
.roof-video-track.is-dragging .roof-video-scrub::-webkit-slider-thumb {
  transform: scale(1.25);
}
.roof-video-scrub:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 2px var(--black), 0 0 0 4px var(--white);
}
.roof-video-scrub:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 2px var(--black), 0 0 0 4px var(--white);
}

/* ----- enlarged: the picture and its bar in a layer over the whole window ----- */
html.roof-theatre-open {
  overflow: hidden;
}
.roof-theatre {
  position: fixed;
  inset: 0;
  z-index: 100001; /* over the nav, the call bar and the chat button */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  padding: max(1rem, env(safe-area-inset-top)) max(1.25rem, env(safe-area-inset-right))
    max(1.25rem, env(safe-area-inset-bottom)) max(1.25rem, env(safe-area-inset-left));
  background: var(--black);
}
/* as large as the window allows: the clip is 5:4, and the caption and bar
   need about 8.5rem of the height between them */
.roof-theatre .roof-video {
  position: relative;
  left: auto;
  top: auto;
  flex: none;
  width: min(100%, calc((100vh - 8.5rem) * 1.25));
  width: min(100%, calc((100dvh - 8.5rem) * 1.25));
  max-height: none;
  transform: none;
  mix-blend-mode: normal;
}
/* zoom lives in the enlarged view only: the picture takes the pointer there, and
   is clipped to its box as it grows */
.roof-video-zoom {
  display: none;
}
.roof-theatre .roof-video-zoom {
  display: grid;
}
.roof-video-zoom[aria-pressed='true'] {
  color: var(--accent);
  border-color: rgba(255, 93, 0, 0.55);
}
.roof-theatre .roof-video {
  overflow: hidden;
  pointer-events: auto;
  touch-action: none;
  cursor: zoom-in;
}
.roof-theatre .roof-video.is-zoomed {
  cursor: grab;
}
.roof-theatre .roof-video video {
  will-change: transform;
}
.roof-theatre .roof-video-bar {
  position: static;
  flex: none;
  width: min(100%, 56rem);
}
.roof-theatre-step {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 0.2rem 0.7rem;
  min-height: 1.5rem;
  max-width: 56rem;
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.4;
  text-align: center;
  color: var(--light-mid);
}
.roof-theatre-step span {
  font-family: 'Outfit', sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--accent);
}
.roof-theatre-step strong {
  font-family: 'Outfit', sans-serif;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--white);
}
.roof-theatre-close {
  position: absolute;
  top: max(1rem, env(safe-area-inset-top));
  right: max(1rem, env(safe-area-inset-right));
}
/* A phone held upright: the clip is nearly square, so it cannot get any wider.
   Give the picture all the height instead — at 1× it sits in the middle as
   before, and zoomed in it has a tall window to move around in. The caption
   and the bar stay at the bottom, under the thumb. */
@media (orientation: portrait) and (max-width: 899px) {
  .roof-theatre .roof-video {
    flex: 1 1 auto;
    width: 100%;
    min-height: 0;
    margin-top: 3rem; /* clear of the close button */
    aspect-ratio: auto;
  }
}
/* A phone on its side: too little height for a caption, so the picture takes it */
@media (max-height: 520px) {
  .roof-theatre {
    gap: 0.4rem;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
  }
  .roof-theatre-step {
    display: none;
  }
  .roof-theatre .roof-video {
    width: min(100%, calc((100vh - 3.6rem) * 1.25));
    width: min(100%, calc((100dvh - 3.6rem) * 1.25));
  }
}
@media (max-width: 899px) {
  .roof-assembly-pin {
    min-height: 0;
  }
  .roof-assembly-inner {
    grid-template-columns: 1fr;
    gap: 1.5rem;
    padding: 4rem 1.5rem;
  }
  /* One column: the label, the heading and the picker of builds come first,
     then the film, then the list of steps. (The film used to come first, so a
     page with more than one build showed no sign of the others until the
     visitor had scrolled past it.) The text block gives up its own box so its
     parts can be ordered around the film. */
  .roof-assembly-inner {
    gap: 0;
  }
  .roof-assembly-copy {
    display: contents;
  }
  .roof-assembly-copy > * {
    order: 1;
  }
  .roof-assembly-stage {
    order: 2;
    height: 46vh;
    margin: 1.75rem 0 0.5rem;
  }
  .roof-assembly-copy > .roof-layers {
    order: 3;
    margin-top: 1rem;
  }
  /* On a phone the list sits under the film, and the film stops once it has
     scrolled away: a list that waits for it would stay dim. Show it whole. */
  .roof-layer {
    opacity: 1;
  }
}

/* system switcher */
.roof-switcher {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 2rem;
}
.roof-switch {
  font-family: 'Outfit', sans-serif;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--light-mid);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 100px;
  padding: 0.45rem 0.8rem;
  cursor: pointer;
  transition: color 0.25s ease, background 0.25s ease, border-color 0.25s ease;
}
.roof-switch:hover {
  color: var(--white);
  border-color: rgba(255, 255, 255, 0.28);
}
.roof-switch.is-active {
  color: var(--accent);
  background: rgba(255, 93, 0, 0.12);
  border-color: rgba(255, 93, 0, 0.55);
}
/* a system rendered more than one way: which build to watch */
.roof-versions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 1.1rem;
}
/* slick swap: fade the stage + layer list while the new system rebuilds */
.roof-assembly-stage,
.roof-layers {
  transition: opacity 0.28s ease;
}
.roof-assembly.is-switching .roof-assembly-stage,
.roof-assembly.is-switching .roof-layers {
  opacity: 0;
}

/* ===== EMERGENCY REPAIRS STRIP ===== */
.emergency-strip {
  /* fades to black at both edges so the strip floats in the page instead of
     being a boxed band with visible seams */
  background: var(--black);
}

/* On phones the sticky call bar (call-bar.js) is pinned to the bottom of every
   screen with the same number and the same "we answer emergency calls" line —
   so this strip is a second copy of that message, 150px tall, one scroll below
   the hero. Drop it on mobile: the pinned bar already does the job, and better,
   because it never scrolls away. */
@media (max-width: 900px) {
  .emergency-strip { display: none; }
}
.emergency-strip-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 1.1rem 3rem;
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
}
.emergency-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 12px rgba(255, 93, 0, 0.8);
  animation: emergencyPulse 1.8s ease-in-out infinite;
  flex-shrink: 0;
}
@keyframes emergencyPulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.55; transform: scale(0.8); }
}
.emergency-strip p {
  color: var(--light-mid);
  font-size: 0.95rem;
  flex: 1;
  min-width: 240px;
}
.emergency-strip p strong {
  color: var(--white);
  font-family: 'Outfit', sans-serif;
}
.emergency-strip-call {
  font-family: 'Outfit', sans-serif;
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.04em;
  color: var(--accent);
  white-space: nowrap;
  border: 1px solid rgba(255, 93, 0, 0.4);
  padding: 0.55rem 1.2rem;
  border-radius: 4px;
  transition: background 0.25s ease, color 0.25s ease;
}
.emergency-strip-call:hover {
  background: var(--accent);
  color: var(--black);
}
@media (max-width: 540px) {
  .emergency-strip-inner { padding: 1rem 1.5rem; }
}
@media (prefers-reduced-motion: reduce) {
  .emergency-dot { animation: none; }
}

/* ----- System-page hero 3D showcase ----- */
.system-showcase {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* ----- Hero call line (paired CTA, decision D2) ----- */
.hero-call-line {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1.5rem;
  font-family: 'Outfit', sans-serif;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
  color: var(--light-mid);
  transition: color 0.2s ease;
}
.hero-call-line strong {
  color: var(--white);
  font-weight: 700;
  letter-spacing: 0.04em;
}
.hero-call-line:hover,
.hero-call-line:hover strong {
  color: var(--accent);
}

/* ----- Interactive material swatch section ----- */
.material-strip {
  background: var(--black);
  position: relative;
  isolation: isolate;
}

/* A full-bleed photograph carries its own edge — a hairline across the top of
   one just draws a line through the picture. The masked fade below is the
   separator. */
.material-strip.is-photo {
  border-top: none;
}

/* Optional photo backdrop for the close-up strip. Masked to transparent at the
   top and bottom edges so the section melts into the black on either side
   rather than stacking another hard band into the scroll. */
.material-strip-photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.material-strip-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.34;
  -webkit-mask-image: var(--strip-fade);
  mask-image: var(--strip-fade);
}

/* One vertical falloff shared by the photograph AND the scrim over it. The
   scrim used to sit at inset:0 with no vertical ramp, so it switched on hard at
   the section edge and stepped the page from 10/255 down to 2/255 in a single
   row — a visible line, even though the image itself was fading correctly. */
.material-strip {
  --strip-fade: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(0, 0, 0, 0.05) 7%,
    rgba(0, 0, 0, 0.13) 13%,
    rgba(0, 0, 0, 0.25) 19%,
    rgba(0, 0, 0, 0.40) 25%,
    rgba(0, 0, 0, 0.57) 30%,
    rgba(0, 0, 0, 0.74) 35%,
    rgba(0, 0, 0, 0.89) 39%,
    #000 44%,
    #000 56%,
    rgba(0, 0, 0, 0.89) 61%,
    rgba(0, 0, 0, 0.74) 65%,
    rgba(0, 0, 0, 0.57) 70%,
    rgba(0, 0, 0, 0.40) 75%,
    rgba(0, 0, 0, 0.25) 81%,
    rgba(0, 0, 0, 0.13) 87%,
    rgba(0, 0, 0, 0.05) 93%,
    transparent 100%
  );
}

.material-strip-inner {
  position: relative;
  z-index: 1;
}

/* Photo-led variant: no interactive swatch, so the copy sits in a single
   readable column and the photograph carries the section. A left-weighted
   scrim keeps the text legible while the right side stays open image. */
.material-strip.is-photo .material-strip-inner {
  grid-template-columns: minmax(0, 620px);
  padding: 14rem 3rem;
  z-index: 2;
}

.material-strip.is-photo .material-strip-text {
  max-width: 560px; /* the global 420px was set for the narrow swatch column */
}

.material-strip.is-photo .material-strip-photo img {
  opacity: 0.6;
}

.material-strip.is-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  -webkit-mask-image: var(--strip-fade);
  mask-image: var(--strip-fade);
  background: linear-gradient(
    to right,
    rgba(0, 0, 0, 0.86) 0%,
    rgba(0, 0, 0, 0.68) 38%,
    rgba(0, 0, 0, 0.25) 68%,
    rgba(0, 0, 0, 0.1) 100%
  );
}

@media (max-width: 900px) {
  .material-strip.is-photo .material-strip-inner {
    padding: 5rem 1.5rem;
  }
  .material-strip.is-photo::after {
    background: rgba(0, 0, 0, 0.72);
  }
}

/* ----- Photo band: a job photo behind a section's own words -----
   Silas, 2026-10-16: "photos aren't just for galleries... that's boring. They are
   to bring life to the site. A background. Then a photo to show something to make
   a point." Add .photo-band to any section and put a picture.photo-band-img first
   inside it. Same falloff as the close-up strip above, so the picture melts into
   the black on either side; the scrim sits on the text side (left by default,
   --right or --center to move it) and goes even on phones. */
section.photo-band {
  position: relative;
  isolation: isolate;
  padding-top: 13rem;
  padding-bottom: 13rem;
  --band-fade: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(0, 0, 0, 0.05) 7%,
    rgba(0, 0, 0, 0.13) 13%,
    rgba(0, 0, 0, 0.25) 19%,
    rgba(0, 0, 0, 0.40) 25%,
    rgba(0, 0, 0, 0.57) 30%,
    rgba(0, 0, 0, 0.74) 35%,
    rgba(0, 0, 0, 0.89) 39%,
    #000 44%,
    #000 56%,
    rgba(0, 0, 0, 0.89) 61%,
    rgba(0, 0, 0, 0.74) 65%,
    rgba(0, 0, 0, 0.57) 70%,
    rgba(0, 0, 0, 0.40) 75%,
    rgba(0, 0, 0, 0.25) 81%,
    rgba(0, 0, 0, 0.13) 87%,
    rgba(0, 0, 0, 0.05) 93%,
    transparent 100%
  );
}

/* the mask sits on the frame, not the picture, so a picture scaled or shifted
   inside it still fades out at the section's own edges */
.photo-band-img {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: var(--band-fade);
  mask-image: var(--band-fade);
}

.photo-band-img img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.8;
}

section.photo-band::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  -webkit-mask-image: var(--band-fade);
  mask-image: var(--band-fade);
  background: linear-gradient(
    to right,
    rgba(0, 0, 0, 0.84) 0%,
    rgba(0, 0, 0, 0.6) 36%,
    rgba(0, 0, 0, 0.14) 64%,
    rgba(0, 0, 0, 0) 100%
  );
}

section.photo-band--right::after {
  background: linear-gradient(
    to left,
    rgba(0, 0, 0, 0.84) 0%,
    rgba(0, 0, 0, 0.6) 36%,
    rgba(0, 0, 0, 0.14) 64%,
    rgba(0, 0, 0, 0) 100%
  );
}

section.photo-band--center::after {
  background: rgba(0, 0, 0, 0.58);
}

section.photo-band > :not(.photo-band-img) {
  position: relative;
  z-index: 2;
}

@media (max-width: 900px) {
  section.photo-band {
    padding-top: 7rem;
    padding-bottom: 7rem;
  }
  section.photo-band::after {
    background: rgba(0, 0, 0, 0.66);
  }
}
.material-strip-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 7rem 3rem;
  display: grid;
  grid-template-columns: minmax(320px, 440px) 1fr;
  gap: 3.5rem;
  align-items: center;
}
.material-strip-text {
  font-size: 1rem;
  line-height: 1.65;
  color: var(--light-mid);
  max-width: 420px;
  margin: 1.25rem 0 2rem;
}
.material-specs {
  list-style: none;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.1rem 1.5rem;
}
.material-specs li {
  border-left: 2px solid rgba(255, 93, 0, 0.5);
  padding-left: 0.9rem;
}
.material-specs strong {
  display: block;
  font-family: 'Outfit', sans-serif;
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--white);
  letter-spacing: -0.01em;
}
.material-specs span {
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--light-mid);
}
.material-strip-hint {
  margin-top: 2rem;
  font-family: 'Outfit', sans-serif;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--light-mid);
}
.material-strip-stage {
  position: relative;
  height: min(56vh, 480px);
}
@media (max-width: 899px) {
  .material-strip-inner {
    grid-template-columns: 1fr;
    gap: 2rem;
    padding: 4rem 1.5rem;
  }
  /* smart-lite (D12): no orbiter on mobile — specs carry the section */
  .material-strip-stage,
  .material-strip-hint {
    display: none;
  }
}

/* =============================================================================
   Anatomy of an Ice Dam — scroll-driven cross-section (ice-damming.html)
   ============================================================================= */
.icedam {
  position: relative;
  background:
    radial-gradient(ellipse 80% 60% at 50% 40%, rgba(91, 141, 239, 0.06), transparent 65%),
    var(--black);
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.icedam-pin {
  min-height: 100vh;
  display: flex;
  align-items: center;
}
.icedam-inner {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 4.5rem 3rem;
}
.icedam-copy {
  text-align: center;
  max-width: 660px;
  margin: 0 auto 1.5rem;
}
.icedam-title {
  font-family: 'Outfit', sans-serif;
  font-weight: 800;
  font-size: clamp(2rem, 4vw, 3.2rem);
  letter-spacing: -0.02em;
  color: var(--white);
  margin: 0.75rem 0 0.75rem;
}
.icedam-lead {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--light-mid);
  max-width: 520px;
  margin: 0 auto;
}
.icedam-stage {
  position: relative;
  height: min(62vh, 580px);
  width: 100%;
}

/* badge (BEFORE / AFTER) */
.icedam-badge {
  position: absolute;
  top: 8px;
  left: 8px;
  font-family: 'Outfit', sans-serif;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #ff7a3c;
  border: 1px solid rgba(255, 93, 0, 0.4);
  background: rgba(255, 93, 0, 0.08);
  padding: 0.4rem 0.8rem;
  border-radius: 999px;
  transition: color 0.4s ease, border-color 0.4s ease, background 0.4s ease;
  pointer-events: none;
}
.icedam-badge.after {
  color: #7fd0ff;
  border-color: rgba(127, 208, 255, 0.45);
  background: rgba(127, 208, 255, 0.08);
}

/* caption */
.icedam-caption {
  position: absolute;
  bottom: 6px;
  left: 50%;
  transform: translateX(-50%);
  max-width: 90%;
  text-align: center;
  font-family: 'DM Sans', sans-serif;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--light);
  pointer-events: none;
}
.icedam-caption.flip {
  animation: icedamCaptionIn 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes icedamCaptionIn {
  from { opacity: 0; transform: translateX(-50%) translateY(8px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* static fallback (motion off / reduced-motion) */
.icedam-stage.icedam-live .icedam-fallback {
  display: none;
}
.icedam-fallback {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  max-width: 820px;
  margin: 0 auto;
  height: 100%;
  align-content: center;
}
.icedam-fb-col {
  background: var(--dark-mid);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 10px;
  padding: 1.5rem 1.5rem 1.75rem;
}
.icedam-fb-tag {
  display: inline-block;
  font-family: 'Outfit', sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  margin-bottom: 1rem;
}
.icedam-fb-tag.before {
  color: #ff7a3c;
  background: rgba(255, 93, 0, 0.1);
  border: 1px solid rgba(255, 93, 0, 0.3);
}
.icedam-fb-tag.after {
  color: #7fd0ff;
  background: rgba(127, 208, 255, 0.1);
  border: 1px solid rgba(127, 208, 255, 0.3);
}
.icedam-fb-col ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}
.icedam-fb-col li {
  position: relative;
  padding-left: 1.1rem;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--light-mid);
}
.icedam-fb-col li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}
@media (max-width: 899px) {
  .icedam-pin { min-height: 0; }
  .icedam-inner { padding: 3.5rem 1.25rem; }
  .icedam-stage { height: 56vh; }
  .icedam-fallback { grid-template-columns: 1fr; }
}

/* ice-dam hyper-real story: caption entrance */
@keyframes idsCaptionIn {
  from { opacity: 0; transform: translateX(-50%) translateY(8px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* ---------------------------------------------------------------------------
   Real media replacing the old dashed placeholders. The containers
   (.mega-card-img, portfolio tiles, section backgrounds) already set their own
   aspect ratio and clip overflow, so the image just fills them.
   --------------------------------------------------------------------------- */
.media-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Nothing here is a hero; a short fade avoids a hard pop on lazy load.
     fill-mode BACKWARDS + a from-only keyframe: the fade starts at 0 and ends
     at whatever opacity the cascade gives the element. (fill-mode:both pinned
     every image to opacity:1 forever, overriding container rules like the
     mission section's dimmed background — animations beat the cascade.) */
  animation: media-in .35s ease backwards;
}
picture:has(> .media-img) { display: contents; }

@keyframes media-in { from { opacity: 0 } }
@media (prefers-reduced-motion: reduce) {
  .media-img { animation: none }
}

/* Hero background loops. index.html and the material pages each define their
   own rule inline; this covers the pages that define neither, and keeps the
   behaviour identical everywhere. Page-level rules still win by cascade order. */
.hero-video,
.sp-hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  pointer-events: none;
}
/* Reduced motion: the film does not play (site.js stops it), but it stays on the
   page showing its opening still. Until 2026-10-13 it was hidden outright, and on
   the pages with no separate still (Systems, Services, the system pages) the
   first screen was black. */
@media (prefers-reduced-motion: reduce) {
  .hero-poster { display: block; }
}


/* =============================================================================
   CHAT IS OFF until the office's Chat Portal is ready (2026-10-13).
   /chat-widget.js holds the switch (CHAT_LIVE) and adds .pr-chat-live to <html>
   when it is on. Until then every link to the Chat page, and the divider beside
   the one in the header, stays out of sight. Nothing was removed from any page.
   ============================================================================= */
html:not(.pr-chat-live) a[href="/chat.html"],
html:not(.pr-chat-live) a[href="/chat"],
html:not(.pr-chat-live) .nav-right-sep { display: none !important; }

/* Phone header logo: the file is the artwork alone (lion + two-line name), so
   its height here is the height of the mark itself. The old file was a square
   with the mark a third of its height, which left it about 15 px tall. */
img.nav-lion-icon.stacked {
  height: 36px;
  width: auto;
}

/* Climate cards on the system pages: line icons in the brand orange (they were
   keyboard emoji, which every phone draws in its own colours). */
.sp-climate-icon svg,
.sp-climate-point-icon svg {
  display: block;
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.sp-climate-icon svg { width: 2rem; height: 2rem; }
.sp-climate-point-icon svg { width: 15px; height: 15px; stroke-width: 1.75; }

/* ----- Keyboard and touch -----
   The Services and Systems panels open for the keyboard as they do for the
   mouse: Tab to the menu name and its panel opens, Tab on through its links,
   and it closes when the keyboard moves past (or on Escape, see site.js). */
.nav-item:has(:focus-visible) > .mega-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: all;
}
/* The phone menu button keeps its look and gets a thumb-sized touch area. */
.nav-hamburger {
  position: relative;
}
.nav-hamburger::after {
  content: '';
  position: absolute;
  inset: -11px;
}

/* A link inside a sentence is underlined, so it is not told apart from the
   words around it by colour alone (20 links on 12 pages). Buttons, cards and
   menu links are not sentences and are left as they are. */
main p a:not([class]),
main .svc-card-desc a:not([class]),
main .insp-check-note a:not([class]),
main .svc-faq-a-inner a:not([class]),
main .ss-faq-answer-inner a:not([class]),
main .fx-a-in a:not([class]),
main .ht-proof-cap a:not([class]),
main .nf-cta a:not([class]) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

/* The faint grid behind the plain-page headings (not-found, Privacy, Careers,
   FAQ, Terms) fades out toward the bottom of its hero instead of stopping in a
   straight line with its squares cut off. */
.pp-hero-grid,
.fn-hero-grid,
.terms-hero-grid {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 96%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 96%);
}

/* Two headings marked an accent word that no rule coloured (every other
   heading on their pages has an orange phrase). Both sit on black. */
.ht-proof-title .accent,
.ida-title .accent {
  color: var(--accent);
}

/* A heading that wraps shares its words between its lines, so none ends with
   one word alone on the last line ("Not Sure Which System Is" / "Right?"). */
h2,
h3 {
  text-wrap: balance;
}

/* On a phone the bottom bar carries the number on every screen, so the hero's
   own "Or call directly 250-258-8600" line, a thumb's width above it, is the
   same number twice. The line stays on laptops, where there is no bar. */
@media (max-width: 900px) {
  .hero-call-line {
    display: none;
  }
}

/* the Services menu: a heading over the protection pages, a hairline before Inspections / Financing */
.mega-label{display:block;font-family:'Outfit',sans-serif;font-size:.66rem;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--accent);margin:0 0 .35rem}
.mega-rule{display:block;height:1px;background:rgba(255,255,255,.12);margin:.6rem 0}

/* six footer columns need a wide screen: three across between tablet and full desktop */
@media (min-width: 901px) and (max-width: 1240px) {
  .footer-canonical-grid { grid-template-columns: repeat(3, 1fr); }
  .footer-canonical-brand { grid-column: 1 / -1; }
}

/* =============================================================================
   PHONE MENU: the desktop menu, unfolded (Silas, 2026-10-16: "Why is mobile
   version not consistent with the web version?" He picked B.)
   Same top level as the desktop bar; Services and Systems open to the same pages
   as its drop-downs, the six service photo cards included. Only the section you
   are in is orange, taken from the desktop bar's active item. The markup is each
   page's #mobileNav.mn, the unfolding is in /scripts/site.js. These rules outrank
   each page's older .mobile-nav styles, which still open and close the panel.
   ============================================================================= */
.mobile-nav.mn {
  justify-content: flex-start;
  align-items: stretch;
  gap: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 6.2rem 1.75rem 8rem;
}

.mobile-nav.mn .mn-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  margin: 0;
  padding: 1.15rem 0;
  background: none;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 0;
  font-family: 'Outfit', sans-serif;
  font-size: 1.45rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--light-mid);
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.mobile-nav.mn .mn-top.mn-end {
  border-bottom: 0;
}

.mobile-nav.mn .mn-top.is-current {
  color: var(--accent);
}

.mobile-nav.mn .mn-chev {
  width: 11px;
  height: 11px;
  margin-right: 4px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  opacity: 0.7;
  transform: translateY(-3px) rotate(45deg);
  transition: transform 0.25s ease;
}

.mobile-nav.mn .mn-group.open > .mn-top .mn-chev {
  transform: translateY(3px) rotate(-135deg);
}

.mobile-nav.mn .mn-sub {
  display: none;
  padding: 0.9rem 0 1.4rem;
}

.mobile-nav.mn .mn-group.open > .mn-sub {
  display: block;
}

.mobile-nav.mn .mn-sub a {
  display: block;
  padding: 0.55rem 0;
  font-family: 'DM Sans', sans-serif;
  font-size: 1.02rem;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--light);
}

.mobile-nav.mn .mn-sub a:hover,
.mobile-nav.mn .mn-sub a:focus-visible,
.mobile-nav.mn .mn-sub a.mn-accent,
.mobile-nav.mn .mn-sub a.mn-all {
  color: var(--accent);
}

.mobile-nav.mn .mn-all {
  margin-top: 0.6rem;
}

.mobile-nav.mn .mn-label {
  display: block;
  margin: 1.1rem 0 0.2rem;
  font-family: 'Outfit', sans-serif;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

.mobile-nav.mn .mn-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 1rem;
}

.mobile-nav.mn .mn-rule {
  display: block;
  height: 1px;
  margin: 0.9rem 0 0.4rem;
  background: rgba(255, 255, 255, 0.07);
}

.mobile-nav.mn .mn-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 0.4rem 0;
}

.mobile-nav.mn .mn-sub a.mn-card {
  padding: 0;
  font-size: 0.86rem;
}

.mobile-nav.mn .mn-card-img {
  display: block;
  aspect-ratio: 3 / 2;
  border-radius: 5px;
  overflow: hidden;
  background: #141416;
}

.mobile-nav.mn .mn-card-img img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.mobile-nav.mn .mn-card-label {
  display: block;
  margin-top: 0.45rem;
}

/* ----- Roof-system pages: a real job of that system beside "Ideal For", and the
   "... in the Okanagan" section over one (Silas, 2026-10-16, batch two of the
   photos-in-the-page pass). The climate cards let a little of it through. */
.sp-ideal-photo {
  margin: 2.4rem 0 0;
  border-radius: 6px;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: #141416;
}

.sp-ideal-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

section.photo-band .sp-climate-card {
  background: rgba(14, 14, 16, 0.82);
}

/* ===== Google rating line =====
   One quiet line under the hero buttons and in the closing section of every
   customer page: orange stars filled to the real rating (4.8 of 5 = 96%), the
   rating and a review count that stays true as it grows ("120+"). It links to
   the Business Profile so a visitor can check it. Raise the count at each
   milestone and re-check the stars at each deploy (his picks, 2026-10-17). */
.g-rating-row {
  display: block;
  width: 100%;
}
.g-rating {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  margin-top: 1.1rem;
  font-family: 'Outfit', sans-serif;
  font-size: 0.86rem;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.82);
  text-decoration: none;
}
.g-rating strong {
  color: #fff;
  font-weight: 600;
}
.g-rating:hover span:not(.g-stars) {
  color: #fff;
}
.g-stars {
  font-size: 1rem;
  letter-spacing: 0.08em;
  background: linear-gradient(90deg, var(--accent) 96%, rgba(255, 255, 255, 0.28) 96%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.g-rating .g-sep {
  opacity: 0.45;
}
/* the homepage's closing phone number sits right under it */
.cta-buttons + .g-rating-row {
  margin-bottom: 1.5rem;
}
/* in the hero it arrives just after the buttons */
.g-rating-row--hero {
  animation: g-rating-in 0.8s cubic-bezier(0.16, 1, 0.3, 1) 1.15s both;
}
@keyframes g-rating-in {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .g-rating-row--hero { animation: none; }
}

/* ----- Footer: the town pages, under Contact (his pick A, 2026-10-17) ----- */
.footer-canonical-areas { margin-top: 1.8rem; }
/* one line per footer link: "Commercial & Industrial" is the longest and still clears the gap to the next column */
.footer-canonical-col li { white-space: nowrap; }

/* ----- Project stories (his Q41 "A", 2026-10-18) -----
   "The story" link: placed where a page already shows one of the ten jobs, it goes to that job's story page.
   The "Projects." row: the jobs a page does not show, as photo cards, above the page's questions. */
.story-link {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: 'Outfit', sans-serif;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--white);
  padding-bottom: 0.35rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.28);
  text-decoration: none;
  transition: color 0.25s ease, border-color 0.25s ease, gap 0.25s ease;
}
.story-link span[aria-hidden] { color: var(--accent); }
.story-link:hover { color: var(--accent); border-color: var(--accent); gap: 0.85rem; }
.story-link-row { margin: 1.6rem 0 0; }
/* on a phone a long "The story: ..." wraps: as plain inline text the underline follows each line and the arrow stays with the words */
@media (max-width: 900px) { .story-link { display: inline; line-height: 2; } }
figcaption .story-cap { color: inherit; text-decoration: none; border-bottom: 1px solid rgba(255, 255, 255, 0.22); }
figcaption .story-cap span[aria-hidden] { color: var(--accent); }
figcaption .story-cap:hover { color: var(--accent); border-color: var(--accent); }

.proj-row { background: var(--black); padding: 7rem 3rem; }
.proj-row-inner { max-width: 1280px; margin: 0 auto; }
.proj-row-title {
  font-family: 'Outfit', sans-serif;
  font-weight: 800;
  font-size: clamp(2.2rem, 4.4vw, 3.6rem);
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--white);
  margin: 0.6rem 0 2.4rem;
}
.proj-row-title .accent { color: var(--accent); }  /* the system pages don't colour .accent on their own */
.proj-row-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.proj-row-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.proj-row-grid--1 { grid-template-columns: minmax(0, 1fr); }
.proj-card {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 4px;
  color: var(--white);
  text-decoration: none;
  background: var(--dark);
}
.proj-row-grid--2 .proj-card { aspect-ratio: 16 / 10; }
.proj-row-grid--1 .proj-card { aspect-ratio: 21 / 9; }
.proj-card picture, .proj-card img { position: absolute; inset: 0; width: 100%; height: 100%; }
.proj-card img { object-fit: cover; transition: transform 0.8s cubic-bezier(0.2, 0.7, 0.2, 1); }
.proj-card:hover img { transform: scale(1.04); }
.proj-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.88) 0%, rgba(0, 0, 0, 0.5) 38%, rgba(0, 0, 0, 0) 70%);
}
.proj-card-text { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; padding: 1.6rem 1.6rem 1.5rem; display: block; }
.proj-card-meta { display: block; font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(255, 255, 255, 0.72); margin-bottom: 0.5rem; }
.proj-card-name { display: block; font-family: 'Outfit', sans-serif; font-weight: 700; font-size: 1.3rem; line-height: 1.15; margin-bottom: 0.9rem; }
.proj-row-grid--1 .proj-card-name { font-size: clamp(1.5rem, 3vw, 2.4rem); }
.proj-card-go { font-family: 'Outfit', sans-serif; font-size: 0.74rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.proj-card-go span[aria-hidden] { color: var(--accent); }
.proj-row-all { margin-top: 2rem; }
@media (max-width: 900px) {
  .proj-row { padding: 5rem 1.5rem; }
  .proj-row-grid, .proj-row-grid--2 { grid-template-columns: minmax(0, 1fr); }
  .proj-row-grid--2 .proj-card, .proj-row-grid--1 .proj-card { aspect-ratio: 4 / 3; }
}

/* ----- Main heading = the small line + the big words (his #17, approved 2026-10-18) -----
   <h1 class="h1-wrap"> holds the small line and the big words, each still styled by its own class, so the page looks
   the same and the heading names the service and the place. Zero specificity: any page rule wins over these. */
:where(.h1-wrap) {
  display: block;
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  text-align: inherit;
}
:where(.h1-wrap > .h1-blk) { display: block; }

/* ----- "Related": a page's neighbouring pages, above its questions (his #19 / Q50 "A", 2026-10-18) ----- */
.related-row { padding: 3.5rem 3rem; }
.related-row-inner { max-width: 1280px; margin: 0 auto; display: flex; flex-wrap: wrap; align-items: baseline; gap: 1.2rem 2.4rem; }
.related-row .section-tag { margin: 0; }
.related-links { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 1.1rem 2rem; }
@media (max-width: 900px) {
  .related-row { padding: 3rem 1.5rem; }
  .related-row-inner { flex-direction: column; gap: 1.2rem; }
}
