/* ============================================================
   Catalyst: Page-specific styles
   Layered on top of styles.css (which contains the full design
   system extracted from web-components.html). This file only
   adds styles for production layout pieces NOT in the prototype:
   page hero, three-up service strips, systems grid, project
   feature, Step Code teaser, CTA bands, contact form, mobile
   drawer, page-hero subheaders, kv lists, etc.
   ============================================================ */

/* ----- Site nav as page chrome (the prototype's .nav-a is a
   demo inside .demo; here we make it the actual top of page) ----- */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 60;
  border-radius: 0;
  margin: 0;
  /* Override .nav-a's overflow:hidden so the burger dropdown can extend
     below the header without being clipped. We don't need the overflow
     clip here because border-radius is 0. */
  overflow: visible;
}
/* The util row carries its own background and bottom border, so capping it
   at 1240px made the coloured band STOP SHORT of the window while the hero
   and every section below ran edge to edge, 180px of bare nav gradient
   either side at 1600px wide. That seam is what made the page look like it
   had a boundary the fixed Step Code pill sat outside of (Mike, 12/09).

   The band is full width now, and the content inside it is held by padding
   to the SAME column the page body uses, .wrap is 1180px with 32px of its
   own padding, so 1116px of content. The nav was on its own 1240px grid
   before, which left the logo 38px outside the headline it sits above. */
.site-nav .util,
.site-nav .main {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
  padding-inline: max(32px, calc((100% - 1116px) / 2));
}
@media (max-width: 880px) {
  .site-nav .util,
  .site-nav .main { padding-inline: 16px; }
}
.site-nav .main { gap: 24px; }
.site-nav .util .pill { background: rgba(255,255,255,0.16); color: #F0F5F6; border: 1px solid rgba(255,255,255,0.18); }
[data-theme="dark"] .site-nav .util .pill { background: rgba(95,207,200,0.12); color: var(--accent); border-color: rgba(95,207,200,0.28); }

.site-nav .util-signin {
  display: inline-flex; align-items: center; gap: 6px;
  color: #F0F5F6;
  text-decoration: none;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.22);
  transition: background 200ms, border-color 200ms, color 200ms;
}
.site-nav .util-signin:hover {
  background: rgba(255,255,255,0.10);
  border-color: rgba(255,255,255,0.40);
}
[data-theme="dark"] .site-nav .util-signin {
  color: var(--accent);
  border-color: rgba(95,207,200,0.36);
}
[data-theme="dark"] .site-nav .util-signin:hover {
  background: rgba(95,207,200,0.10);
}

.site-nav .theme-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  background: transparent; border: 1px solid rgba(255,255,255,0.22);
  color: #F0F5F6;
  border-radius: 999px;
  padding: 4px 12px;
  font-family: var(--font-body); font-size: 12px; font-weight: 600;
  cursor: pointer;
  transition: background 200ms, border-color 200ms, color 200ms;
}
.site-nav .theme-toggle:hover { background: rgba(255,255,255,0.10); border-color: rgba(255,255,255,0.36); }
[data-theme="dark"] .site-nav .theme-toggle { color: var(--accent); border-color: rgba(95,207,200,0.36); }
[data-theme="dark"] .site-nav .theme-toggle:hover { background: rgba(95,207,200,0.10); }

/* Nav CTA: the existing .nav-a .cta .btn rules in styles.css use the
   Glass Pane gradient. Force it to a link element here too. */
.site-nav .cta .btn {
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none;
}
.site-nav .cta .btn .icon { transition: transform 220ms cubic-bezier(.2,.7,.2,1); }
.site-nav .cta .btn:hover .icon { transform: translateX(3px); }

/* ============================================================
   SITE NAV: burger-only nav on every screen size.
   Horizontal .primary nav is hidden. "Request a quote" CTA
   stays in the topbar (clustered with the brand on the left).
   Burger is pinned to the right and anchors a dropdown panel.
   ============================================================ */
.site-nav .main {
  /* Brand + CTA cluster on the left; burger pushed to the far right via margin-left:auto on the burger itself. */
  justify-content: flex-start;
  gap: 16px;
}
.site-nav .main .brand { flex: 0 0 auto; }
.site-nav .main .primary { display: none; }
/* Topbar CTA stays visible at every screen size, overrides the
   prototype's @media (max-width: 880px) rule from styles.css that
   collapses .nav-a .cta on mobile. Per Mike's locked exception
   (2026-05-17), the topbar CTA stays on the always-on pattern for
   prominence on every device. */
.site-nav .main .cta {
  flex: 0 0 auto;
  display: inline-flex !important;
  /* Group the CTA with the burger on the right, per Mike's artboard edit.
     The prototype nav gets this for free: .primary is visible there with
     flex:1 and centred, so brand / nav / cta+burger falls out naturally.
     The real site hides .primary at every width, so without this the auto
     margin on .mobile-burger swallows all the free space BEFORE the burger
     and strands the pill next to the logo. */
  margin-left: auto;
}
/* ...which means the burger must not claim that space a second time, or it
   reopens a gap between the pill and the burger. */
.site-nav .main .mobile-burger { margin-left: 0; }
@media (max-width: 880px) {
  .site-nav.nav-a .cta { display: inline-flex !important; }
}
/* On wider screens, keep some breathing room between the CTA and the burger. */
@media (min-width: 720px) {
  .site-nav .main { gap: 20px; }
}

/* Burger: locked Glass Pane gradient per the brand. Always visible. */
.mobile-burger {
  display: inline-flex;
  margin-left: auto;
  flex: 0 0 auto;
  width: 48px; height: 48px;
  flex-direction: column; justify-content: center; align-items: center;
  gap: 5px;
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
  color: #DCE6E7;
  border: none; border-radius: 12px;
  cursor: pointer;
  position: relative; overflow: hidden;
  box-shadow: 0 2px 4px rgba(16,34,34,0.08),
              0 6px 18px -6px color-mix(in srgb, var(--accent) 55%, transparent);
  transition: transform 220ms cubic-bezier(.2,.7,.2,1),
              box-shadow 280ms cubic-bezier(.2,.7,.2,1),
              filter 200ms;
}
/* Sheen sweep on hover: fires once via animation forwards so it doesn't reverse on un-hover. */
.mobile-burger::before {
  content: ""; position: absolute; top: 0; left: -120%; width: 60%; height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255,255,255,0.35), transparent);
  transform: skewX(-20deg);
  pointer-events: none;
}
.mobile-burger:hover {
  transform: translateY(-2px) scale(1.04);
  filter: saturate(1.1);
  box-shadow: 0 4px 8px rgba(16,34,34,0.10),
              0 14px 36px -10px color-mix(in srgb, var(--accent) 75%, transparent);
}
.mobile-burger:hover::before {
  animation: burgerSheen 700ms cubic-bezier(.2,.7,.2,1) forwards;
}
@keyframes burgerSheen {
  to { left: 130%; }
}
.mobile-burger:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.mobile-burger:active { transform: translateY(0) scale(1); }

.mobile-burger span {
  width: 22px; height: 2px; border-radius: 2px;
  background: #DCE6E7;
  z-index: 1;
  transition: transform 280ms cubic-bezier(.65,.05,.36,1),
              opacity 200ms, width 220ms cubic-bezier(.2,.7,.2,1);
}
/* Asymmetric line-shift hover: per brand burger spec */
.mobile-burger:hover span:nth-child(1) { width: 16px; transform: translateX(-3px); }
.mobile-burger:hover span:nth-child(3) { width: 16px; transform: translateX(3px); }
/* X snap on open */
.mobile-burger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); width: 22px; }
.mobile-burger.open span:nth-child(2) { opacity: 0; }
.mobile-burger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); width: 22px; }
.mobile-burger:hover.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.mobile-burger:hover.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Dropdown panel: anchored to the burger's lower-right.
   IMPORTANT: the .site-nav header is full-viewport-width, but the .main row
   inside it is constrained to max-width 1240px and centered. If we anchor
   the dropdown to the header (right: 24px from full viewport), it ends up
   way to the right of the burger on wide screens. The formula below pulls
   the dropdown back so its right edge tracks the burger's right edge, the
   right padding of the 1240px wrap, plus a fall-back of 24px on narrow screens. */
.mobile-drawer {
  position: absolute;
  top: calc(100% + 10px);
  right: max(24px, calc((100vw - 1240px) / 2 + 24px));
  width: 320px;
  max-width: calc(100vw - 32px);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow:
    0 12px 32px -16px rgba(16,34,34,0.18),
    0 24px 60px -20px rgba(16,34,34,0.22);
  padding: 12px;
  visibility: hidden;
  transform: translateY(-6px) scale(0.98);
  transform-origin: top right;
  transition: opacity 220ms cubic-bezier(.2,.7,.2,1),
              transform 240ms cubic-bezier(.2,.7,.2,1),
              visibility 240ms;
  z-index: 70;
  /* Flex column so cta-link can use `order: -1` to appear at the top
     regardless of where it sits in the HTML across all 13 pages. */
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.mobile-drawer.open {
  visibility: visible;
  transform: translateY(0) scale(1);
}
[data-theme="dark"] .mobile-drawer {
  background: var(--dark-surface, #1D3447);
  border-color: var(--dark-border, #2C4358);
  box-shadow:
    0 12px 32px -16px rgba(0,0,0,0.40),
    0 24px 60px -20px rgba(0,0,0,0.50);
}

.mobile-drawer a {
  display: flex; align-items: center;
  padding: 14px 14px 14px 16px;
  border-radius: 10px;
  text-decoration: none;
  color: var(--text);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 20px;
  letter-spacing: -0.005em;
  position: relative;
  transition: color 220ms cubic-bezier(.2,.7,.2,1),
              background 260ms cubic-bezier(.2,.7,.2,1),
              padding-left 280ms cubic-bezier(.2,.7,.2,1),
              letter-spacing 280ms cubic-bezier(.2,.7,.2,1),
              box-shadow 260ms cubic-bezier(.2,.7,.2,1);
}
/* Accent margin-mark animates in from the left on hover (dropdown-menu pattern).
   Bumped to 2 px tall × 14 px wide on hover so it reads as a clear margin tick. */
.mobile-drawer a::before {
  content: ""; position: absolute;
  left: 8px; top: 50%;
  width: 0; height: 2px;
  background: var(--accent);
  border-radius: 2px;
  transform: translateY(-50%);
  transition: width 280ms cubic-bezier(.2,.7,.2,1);
}
.mobile-drawer a:hover {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  padding-left: 32px;
  letter-spacing: 0.005em;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 24%, transparent);
}
.mobile-drawer a:hover::before { width: 14px; }

/* Current-page indicator: visually distinct from hover.
   Uses a small filled accent dot instead of the hover line-dash,
   no background tint, no indent: so it reads as "you are here"
   rather than "this is selected." Still hoverable; clicking just
   reloads the page. */
.mobile-drawer a.active {
  color: var(--accent);
  background: transparent;
  cursor: default;
}
.mobile-drawer a.active::before {
  /* Override the hover line-mark: filled dot, vertically centered */
  width: 6px;
  height: 6px;
  border-radius: 50%;
  left: 8px;
  background: var(--accent);
}
/* On hover of the active item, keep the dot but allow the rest of the
   hover treatment so it doesn't feel dead. */
.mobile-drawer a.active:hover::before {
  width: 6px;
  height: 6px;
  border-radius: 50%;
}

/* CTA at the top of the drawer.
   At DESKTOP (≥481px) the topbar CTA pill is visible, so the drawer's
   cta-link would be redundant: keep it hidden.
   At MOBILE (≤480px) the topbar CTA is hidden (see v5 layout above) and
   the drawer's cta-link becomes the primary conversion path. Styled as a
   prominent Glass Pane gradient pill anchored at the top of the drawer
   via `order: -1`. */
.mobile-drawer a.cta-link { display: none; }
@media (max-width: 480px) {
  .mobile-drawer a.cta-link {
    display: flex;
    align-items: center;
    justify-content: center;
    order: -1;
    margin-bottom: 8px;
    padding: 14px 18px;
    border-radius: 999px;
    background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
    color: #FFFFFF;
    font-family: var(--font-body);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-decoration: none;
    box-shadow:
      0 4px 10px rgba(16,34,34,0.10),
      0 14px 30px -10px color-mix(in srgb, var(--accent) 65%, transparent);
    transition: transform 240ms cubic-bezier(.2,.7,.2,1),
                box-shadow 280ms cubic-bezier(.2,.7,.2,1),
                filter 200ms;
  }
  .mobile-drawer a.cta-link::before { display: none; }
  /* :active stays unscoped: gives immediate press feedback on touch.
     :hover is scoped to non-touch via the media query below. */
  .mobile-drawer a.cta-link:active {
    color: #FFFFFF;
    background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
    transform: translateY(-1px);
    filter: saturate(1.08);
    padding-left: 18px;
    letter-spacing: 0.02em;
  }
}
@media (max-width: 480px) and (hover: hover) and (pointer: fine) {
  .mobile-drawer a.cta-link:hover {
    color: #FFFFFF;
    background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
    transform: translateY(-1px);
    filter: saturate(1.08);
    padding-left: 18px;
    letter-spacing: 0.02em;
  }
  .mobile-drawer a.cta-link:hover::before { width: 0; }
}

/* Phone link sits beneath everything else, smaller, separated by a rule. */
.mobile-drawer a.phone-link {
  font-family: var(--font-body);
  font-size: 13px; font-weight: 600;
  color: var(--muted);
  padding-top: 16px;
  margin-top: 8px;
  border-top: 1px solid var(--border);
}
.mobile-drawer a.phone-link::before { display: none; }
.mobile-drawer a.phone-link:hover { padding-left: 14px; color: var(--accent); }

/* Backdrop dim: soft.
   CRITICAL: must be BELOW .site-nav (z-index 60) so the dropdown inside
   the sticky header isn't covered. .site-nav's sticky position creates a
   stacking context, so its children (the drawer) inherit its z-order in
   the document. Backdrop at 50 sits below the chrome but above all
   normal-flow page content: clicks on body content still close the
   drawer, clicks on dropdown items reach them. */
.nav-backdrop {
  position: fixed; inset: 0;
  background: rgba(16, 34, 34, 0.15);
  visibility: hidden; opacity: 0;
  transition: opacity 220ms cubic-bezier(.2,.7,.2,1), visibility 220ms;
  z-index: 50;
}
.nav-backdrop.open { visibility: visible; opacity: 1; }
[data-theme="dark"] .nav-backdrop { background: rgba(0, 0, 0, 0.40); }

/* On very small screens, the drawer hugs the right edge with a small inset. */
@media (max-width: 480px) {
  .mobile-drawer {
    right: 12px;
    width: calc(100vw - 24px);
  }

  /* Topbar mobile layout v5 (locked 2026-05-18): two-element header.
     Brand cluster on the LEFT, burger on the RIGHT. The "Request a
     quote" CTA is removed from the header entirely on mobile, it
     lives at the top of the burger drawer instead (styled as a
     prominent pill, see .mobile-drawer a.cta-link rules below).
     Rationale (locked): on phones, the always-on Glass Pane gradient
     CTA was overpowering the brand wordmark. Moving the CTA into the
     drawer lets the brand own the header's visual hierarchy. */
  .site-nav .main {
    display: flex;
    align-items: center;
    padding: 12px 14px;
    gap: 12px;
  }
  .site-nav .main .brand {
    flex: 1 1 auto;
    min-width: 0;
    gap: 12px;
  }
  .site-nav .main .brand img { width: 48px; }
  .site-nav .main .brand .wm { font-size: 22px; line-height: 1.1; letter-spacing: -0.005em; }
  .site-nav .main .brand .sub { display: none; }
  /* CTA removed from mobile header (now lives in the drawer). Need
     `!important` to override the blanket `display: inline-flex
     !important` set higher in this file (which was added to keep the
     CTA visible at every width per the old locked rule, now superseded
     by Option C: CTA-in-drawer on mobile). */
  .site-nav .main .cta { display: none !important; }
  /* Burger on the right, slightly bigger than desktop for thumb target. */
  .mobile-burger {
    width: 48px;
    height: 48px;
    margin-left: auto;
    flex: 0 0 auto;
  }
}

/* Mid-phone widths: keep the wordmark visible but compact it so the
   topbar doesn't overflow at the in-between 480–620 range. */
@media (max-width: 620px) and (min-width: 481px) {
  .site-nav .main { padding: 14px 16px; gap: 12px; }
  .site-nav .main .brand img { width: 60px; }
  .site-nav .main .brand .wm { font-size: 18px; }
  /* Hide the lockup sub-line on phones (Mike, 30/09): it was cut off at this
     width. Header lockup only; the footer keeps it. <=480px is handled above. */
  .site-nav .main .brand .sub { display: none; }
  .site-nav .main .cta .btn { padding: 10px 16px; font-size: 13px; }
}

/* Tablet widths (Mike, 30/09/2026): the lockup sub-line still pushes the burger
   off screen above 620px. Measured in headless Chrome: with the sub-line shown
   the burger overflows the viewport up to ~949px and only clears the 32px
   gutter from ~981px, so hide it up to 980px. No existing breakpoint sits
   between 920 and 1100. Header lockup only; the footer keeps it. */
@media (max-width: 980px) {
  .site-nav .main .brand .sub { display: none; }
}

/* Belt-and-suspenders: prevent any element from forcing horizontal scroll
   beyond the viewport on phones. If something later sneaks in wider than
   the viewport, this clips it rather than letting the user pan sideways
   into broken layout. */
html, body { overflow-x: hidden; }

/* ============================================================
   PAGE HERO: large hero block at top of pages
   ============================================================ */
.page-hero {
  /* Top pulled in from 96px on Home (Mike 28/09/2026); every page matches. */
  padding: 56px 0 80px;
  background:
    radial-gradient(900px 360px at 18% -10%, color-mix(in srgb, var(--accent) 14%, transparent) 0%, transparent 70%),
    radial-gradient(700px 320px at 96% 10%, color-mix(in srgb, var(--accent) 8%, transparent) 0%, transparent 60%),
    var(--bg);
  border-bottom: 1px solid var(--border);
}
.page-hero .wrap { max-width: 1180px; margin: 0 auto; padding: 0 32px; }
.page-hero .tag {
  display: inline-block;
  font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 18px;
  padding: 6px 12px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-radius: 999px;
}
.page-hero h1 {
  font-family: var(--font-heading);
  font-size: clamp(40px, 6vw, 68px);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.02em;
  margin: 0 0 22px;
  max-width: 980px;
}
.page-hero .lede {
  font-size: 18px; line-height: 1.55;
  color: var(--text);
  margin: 0 0 32px;
  max-width: 780px;
}
/* Hero text set as several lede paragraphs (Careers): tighten the gap between them. */
.page-hero .lede:has(+ .lede) { margin-bottom: 14px; }
.page-hero .hero-actions {
  display: flex; gap: 14px; flex-wrap: wrap;
  margin-bottom: 36px;
}
.page-hero .hero-actions .btn-primary,
.page-hero .hero-actions .btn-ghost {
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none;
}
.page-hero .hero-meta {
  display: flex; gap: 12px; flex-wrap: wrap;
  font-size: 13px; color: var(--muted);
}
.page-hero .hero-meta strong { color: var(--text); font-weight: 600; }

/* Inner pages carry .compact, but Mike wants every hero the same size as
   Home (28/09/2026), so the padding, heading and lede all follow Home. Only
   the space under the buttons goes, since inner heroes have no meta row. */
.page-hero.compact .hero-actions { margin-bottom: 0; }

/* ============================================================
   STRIPS: section containers across pages
   ============================================================ */
.strip {
  padding: 88px 0;
  border-bottom: 1px solid var(--border);
}
.strip:last-of-type { border-bottom: none; }
.strip .wrap { max-width: 1180px; margin: 0 auto; padding: 0 32px; }

.strip-tint {
  background: color-mix(in srgb, var(--accent) 4%, var(--surface));
}
.strip-dark {
  background: linear-gradient(180deg, #14283A 0%, #182D40 100%);
  color: #DCE6E7;
  border-bottom: 1px solid #2C4358;
}
.strip-dark a { color: #5FCFC8; }
.strip-dark p { color: #B6C4CB; }

.strip-head {
  margin-bottom: 44px;
  max-width: 880px;
}
.strip-head .num {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}
.strip-head h2 {
  font-family: var(--font-heading);
  font-size: clamp(30px, 4vw, 42px);
  font-weight: 700;
  letter-spacing: -0.015em;
  margin: 0 0 14px;
  line-height: 1.1;
}
.strip-head p {
  font-size: 16px;
  color: var(--muted);
  margin: 0;
  max-width: 720px;
  line-height: 1.55;
}
/* Systems we spec: heading centred over its symmetric supplier-card grid
   (Mike 28/09/2026). Recent work stays left on purpose: it lines up with the
   photo-left / story-right layout under it. */
[data-section-id="systems-we-spec"] .strip-head { margin-left: auto; margin-right: auto; text-align: center; }
[data-section-id="systems-we-spec"] .strip-head p { margin-left: auto; margin-right: auto; }

/* Home: two blocks centred on Mike's canvas comments (30/09/2026, "center
   margined"). Both were capped (h1 980px, lede 780px, .strip-head 880px) but
   had no auto side margins, so they hugged the left edge of the 1180px .wrap
   while the photo band / project grid under them span the full width. Same
   mechanism as the systems-we-spec heading above. Home-only via .page-home:
   step-code.html also uses .hero-copy. */
.page-home .page-hero .hero-copy { max-width: 980px; margin-left: auto; margin-right: auto; text-align: center; }
.page-home .page-hero .hero-copy h1,
.page-home .page-hero .hero-copy .lede { margin-left: auto; margin-right: auto; }
.page-home .page-hero .hero-copy .hero-actions { justify-content: center; }
.page-home [data-section-id="featured-project"] .strip-head { margin-left: auto; margin-right: auto; text-align: center; }
.page-home [data-section-id="featured-project"] .strip-head p { margin-left: auto; margin-right: auto; }
/* Four-stages header (Mike, canvas comment 30/09/2026, "center margined"):
   same mechanism, header only; the four cards below are untouched. */
.page-home [data-section-id="how-we-work"] .strip-head { margin-left: auto; margin-right: auto; text-align: center; }

/* Rest of the Home page (Mike, canvas comment 30/09/2026, "center margin entire
   page"). Two leftovers, both measured at 1440px:
   1. The "Recent work" section's .wrap is also the slideshow host, and
      [data-slideshow].ss { margin: 0 } (specificity 0,2,0, later in the file)
      beat .strip .wrap { margin: 0 auto }, so the whole UBC MOA block sat
      flush left (0px left, 229px right). Restore the auto side margins.
   2. The hero slideshow project title and meta line (ss-head, built by
      slideshow.js) sat left under the hero. Centre them; the photo, caption
      and Previous/Next bar already span the full container. Home hero only,
      projects.html uses the same ss-head. */
.page-home .strip .wrap[data-slideshow].ss { margin-left: auto; margin-right: auto; }
.page-home .page-hero .ss-head { text-align: center; }

/* Every inner page (Mike, 01/10/2026, "all pages should be center margined to
   match the home page"). The Home rules above are scoped .page-home; inner
   pages carry .page-host, so the same treatment is generalised here once
   rather than per page. Measured at 1440px: every section's .wrap was already
   centred (130px each side), what hugged the left was what sits inside it -
   the capped h1 (980px), .lede (780px), .strip-head (880px) and the narrow
   .prose / photo columns. Centred: eyebrow, h1, lede, hero actions and meta,
   .strip-head blocks, and the .prose / photo blocks as blocks. Left on
   purpose: paragraph text, bullet lists, card internals, form labels and
   fields, and the legal body text. Home, header and footer are untouched. */
.page-host .page-hero .wrap { text-align: center; }
.page-host .page-hero h1,
.page-host .page-hero .lede { margin-left: auto; margin-right: auto; }
.page-host .page-hero .hero-actions,
.page-host .page-hero .hero-meta { justify-content: center; }
.page-host .strip-head { margin-left: auto; margin-right: auto; text-align: center; }
.page-host .strip-head p { margin-left: auto; margin-right: auto; }
/* Story and legal columns: the block sits centred, the text inside stays left. */
.page-host .strip > .wrap > .prose,
.page-host .about-body > .prose,
.page-host .about-body > .photo-band { margin-left: auto; margin-right: auto; }
/* Contact form card: heading and intro centre, labels and fields stay left. */
.page-host .contact-card > h2,
.page-host .contact-card > .sub { text-align: center; }

/* Sub-heads on inner pages (Mike, 01/10/2026, follow-up to the rule above).
   Centred: every slideshow title + meta line (.ss-head, built by slideshow.js;
   About, Projects, Contact, Careers, Step Code) and the h2 that heads a
   stand-alone prose block in the About story column ("A word from Mike",
   "Where we work"). Left on purpose: headings inside a card, a two-up or grid
   item (services detail rows, careers two-up, quote wizard steps, step-code
   panels) and the legal h2s on Privacy and Terms, which sit over left-aligned
   clauses. Body paragraphs stay left. Home, header and footer untouched. */
.page-host .ss-head { text-align: center; }
.page-host .about-body > .prose > h2 { text-align: center; }

/* Orthographic globe backdrop behind the heading (site/globe-backdrop, 28/09/2026).
   Atlantic-centred (25W, 45N) so western Europe and eastern North America share
   the visible face - the supply story (Spain/Belgium/Poland -> Canada), not
   decoration. Coastlines are Natural Earth 110m land polygons (public domain),
   projected and horizon-clipped at build time; the SVG in the page is static
   output - no runtime projection code ships. Colours ride the theme tokens via
   color-mix() so light/dark need no separate rule. */
[data-section-id="systems-we-spec"] { position: relative; overflow: hidden; }
.strip-head.has-globe { position: relative; }
.strip-head.has-globe .num,
.strip-head.has-globe h2 { position: relative; z-index: 1; }
.head-globe {
  position: absolute;
  top: 50%;
  left: 50%;
  width: clamp(280px, 34vw, 460px);
  height: auto;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 0;
}
/* Soft halo hugging the heading letters (replaces the old full-width SVG mask
   band, which knocked a strip out of the whole globe however short the sentence
   was). A text-shadow in the section's own tint rides the glyphs, so it follows
   the text at every width and when the heading wraps, and the globe stays
   visible everywhere else. */
.strip-head.has-globe {
  --globe-halo: color-mix(in srgb, var(--accent) 4%, var(--surface));
}
.strip-head.has-globe .num,
.strip-head.has-globe h2 {
  text-shadow:
    0 0 4px var(--globe-halo),
    0 0 4px var(--globe-halo),
    0 0 8px var(--globe-halo),
    0 0 8px var(--globe-halo),
    0 0 14px var(--globe-halo),
    0 0 14px var(--globe-halo),
    0 0 22px var(--globe-halo),
    0 0 30px var(--globe-halo);
}
.strip-head.has-globe .num {
  /* small eyebrow type sits closest to the globe's accent dots - extra tight layers */
  text-shadow:
    0 0 3px var(--globe-halo), 0 0 3px var(--globe-halo), 0 0 3px var(--globe-halo),
    0 0 6px var(--globe-halo), 0 0 6px var(--globe-halo), 0 0 6px var(--globe-halo),
    0 0 12px var(--globe-halo), 0 0 12px var(--globe-halo),
    0 0 20px var(--globe-halo), 0 0 28px var(--globe-halo);
}
.head-globe .globe-rim {
  fill: none;
  stroke: color-mix(in srgb, var(--text) 18%, transparent);
  stroke-width: 1.5;
}
.head-globe .globe-graticule {
  fill: none;
  stroke: color-mix(in srgb, var(--text) 11%, transparent);
  stroke-width: 0.75;
}
.head-globe .globe-land {
  fill: color-mix(in srgb, var(--text) 9%, transparent);
  stroke: color-mix(in srgb, var(--text) 15%, transparent);
  stroke-width: 0.6;
}
.head-globe .globe-dots circle { fill: var(--accent); }
@media (max-width: 640px) {
  .head-globe { display: none; }
}
.strip-head-dark .num { color: #5FCFC8; }
.strip-head-dark h2 { color: #DCE6E7; }
.strip-head-dark p { color: #B6C4CB; }

/* ============================================================
   THREE-UP: for service cards, value cards, etc.
   ============================================================ */
.three-up {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
}
@media (max-width: 920px) { .three-up { grid-template-columns: 1fr; } }

/* FOUR-UP: four cards; 2x2 at tablet so nothing orphans on a second row. */
.four-up { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }

/* ============================================================
   SUPPLIER CARD MARK
   Ported from the audit artboard 21/09/2026. The manufacturer logo
   replaces the text <h3>; the name survives as the logo's alt.
   Country flags removed 01/10/2026 (Mike, Home audit canvas).
   ============================================================ */
.system-card .card-mark {
  margin-bottom: 14px; min-height: 33px;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 10px 16px;
}
.system-card .card-mark > img {
  width: auto; height: 27px;
  filter: brightness(0); opacity: 0.6;
}
[data-theme="dark"] .system-card .card-mark > img { filter: brightness(0) invert(1); opacity: 0.85; }
.system-card .card-mark img.mark-cortizo  { height: 29px; }
.system-card .card-mark img.mark-reynaers { height: 33px; }
.system-card .card-mark img.mark-aluprof  { height: 27px; }
.system-card .card-mark img.mark-vinyltek { height: 25px; }
.system-card .card-mark img.mark-ventanas { height: 21px; }
.system-card .card-mark img.mark-catalyst { height: 44px; }

/* Visually hidden, still read aloud. */
.vh-label {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ============================================================
   BROCHURE DRAWER
   The artboard toggled a class from a click anywhere on the card.
   Here it is a real <button> with aria-expanded and the panel is
   [hidden] when closed, so it is keyboard reachable and absent from
   the accessibility tree rather than merely clipped to zero height.
   ============================================================ */
.system-card .tap-hint {
  font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--accent);
  margin-top: 14px; display: inline-flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 4px 0; cursor: pointer; font-family: inherit;
}
.system-card .tap-hint:hover { color: var(--accent-hover); }
/* Centre the label group in the card (the button is the full card width). */
.system-card .tap-hint { justify-content: center; }
/* Squared-off accent chip, echoing the frame around the Catalyst monogram -
   and deliberately not the round .dl-badge, so "expand" and "download" do not
   read as the same control. At 45 degrees the plus becomes a close cross. */
.system-card .tap-hint .hint-plus {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 6px;
  background: var(--accent); color: var(--accent-text);
  display: inline-flex; align-items: center; justify-content: center;
  transition: transform 260ms cubic-bezier(.2,.7,.2,1), background 180ms;
}
.system-card .tap-hint .hint-plus svg { width: 11px; height: 11px; }
.system-card .tap-hint:hover .hint-plus { background: var(--accent-hover); }
.system-card .tap-hint[aria-expanded="true"] .hint-plus { transform: rotate(45deg); }
@media (pointer: coarse) {
  .system-card .tap-hint { padding: 12px 0; margin-top: 6px; }
}
@media (prefers-reduced-motion: reduce) {
  .system-card .tap-hint .hint-plus { transition: background 180ms; }
}
.system-card .drawer { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.system-card .drawer[hidden] { display: none; }
.system-card .drawer:not([hidden]) { animation: drawerIn 220ms cubic-bezier(.2,.7,.2,1); }
@keyframes drawerIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .system-card .drawer:not([hidden]) { animation: none; }
}
.system-card .brochure-link,
.system-card .placeholder,
.system-card .drawer-ask {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 12px; font-weight: 600; color: var(--text); text-decoration: none;
  border: 1px solid var(--border); border-radius: 8px; padding: 9px 11px;
  background: var(--bg); transition: border-color 180ms, color 180ms;
}
.system-card .brochure-link:hover,
.system-card .drawer-ask:hover { border-color: var(--accent); color: var(--accent); }
.system-card .drawer-ask { border-style: dashed; color: var(--muted); justify-content: center; text-align: center; }
/* A system we have catalogued but have no brochure for yet: named, so the
   card still tells you what the line covers, but not a link and not
   hoverable. */
.system-card .placeholder { color: var(--muted); cursor: default; }
.system-card .soon-tag {
  flex: 0 0 auto;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted);
}
.system-card .dl-badge {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent); color: var(--accent-text);
  display: inline-flex; align-items: center; justify-content: center;
}
.system-card .dl-badge svg { width: 13px; height: 13px; }

/* ============================================================
   BROCHURE DRAWER: LINE PICKER
   One dropdown per drawer replaces the stack of per-line links,
   with a download control immediately to its right on the same
   row. The control stays genuinely inert (no href, out of the tab
   order, dimmed) until a line is picked - site.js wires the href.
   ============================================================ */
.system-card .drawer-picker { display: flex; align-items: center; gap: 8px; }
.system-card .brochure-select { flex: 1 1 auto; min-width: 0; min-height: 44px; }
.system-card .brochure-download {
  flex: 0 0 auto; width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  text-decoration: none; transition: opacity 180ms;
}
.system-card .brochure-download .dl-badge { width: 100%; height: 100%; }
.system-card .brochure-download .dl-badge svg { width: 18px; height: 18px; }
.system-card .brochure-download[aria-disabled="true"] {
  opacity: 0.45; cursor: not-allowed; pointer-events: none;
}
.system-card .brochure-download[aria-disabled="true"] .dl-badge {
  background: var(--surface-2); color: var(--muted);
}

/* The Home hero photo band sits between the copy and the section below it.
   The base .photo-band rules already live further down this file (they were
   written for the service pages) - this only supplies the spacing the hero
   needs. */
.page-hero .photo-band { margin: 36px 0 22px; }

/* ============================================================
   HOW-CARD ICON + SEPARATOR
   ============================================================ */
.how-card { position: relative; }
.how-card .how-icon {
  position: absolute; top: 22px; right: 22px;
  width: 48px; height: 48px; border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.how-card .how-icon svg { width: 26px; height: 26px; stroke-width: 1.3; } /* 1.5x box (32->48) and glyph (17->26); stroke 2->1.3 keeps the rendered line at ~1.4px, same weight as before */
/* The artboard set this at 16px and half opacity - a whisper beside a 26px
   heading. Cormorant's figures sit at x-height, so the number needs a bigger
   jump than a lining face would to read at the same weight; 32px matches the
   slash beside it and takes the accent. line-height:1 so the taller glyph
   does not open up the heading's line box. */
.how-card h3 .how-idx {
  font-size: 32px; font-weight: 700;
  color: var(--accent);
  line-height: 1;
  margin-right: 4px;
}
.how-card h3 .how-sep {
  font-size: 32px; font-weight: 700; color: var(--accent);
  line-height: 1; margin-right: 2px;
}



/* Home "How we work" runs two by two (Mike 29/09/2026): four across left each
   card too narrow, so the corner icon ran into the heading. The heading keeps
   clear of the icon, and minmax(0, 1fr) keeps the columns equal whatever the
   longest word is. */
.four-up { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.four-up.how-2x2 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
.how-card h3 { padding-right: 60px; }
@media (max-width: 1100px) { .four-up { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 920px)  { .four-up, .four-up.how-2x2 { grid-template-columns: 1fr; } }

.how-card {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 14px;
  padding: 28px;
  position: relative;
  transition: border-color 280ms cubic-bezier(.2,.7,.2,1),
              transform 280ms cubic-bezier(.2,.7,.2,1),
              box-shadow 360ms cubic-bezier(.2,.7,.2,1);
}
.how-card:hover {
  border-color: color-mix(in srgb, var(--accent) 60%, var(--border));
  transform: translateY(-2px);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 10%, transparent),
              0 16px 36px -16px color-mix(in srgb, var(--accent) 30%, transparent);
}
.how-card .how-num {
  font-family: var(--font-heading);
  font-size: 14px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.08em;
  margin-bottom: 12px;
}
.how-card h3 {
  font-family: var(--font-heading);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 12px;
}
.how-card p {
  font-size: 14px;
  color: var(--text);
  margin: 0 0 16px;
  line-height: 1.55;
}
.how-card .bullets {
  list-style: none; padding: 0; margin: 0;
  font-size: 13px;
  color: var(--muted);
}
.how-card .bullets li {
  padding: 6px 0 6px 18px;
  position: relative;
  line-height: 1.5;
}
.how-card .bullets li::before {
  content: ""; position: absolute;
  left: 0; top: 12px;
  width: 8px; height: 1.5px;
  background: var(--accent);
}

/* ============================================================
   SYSTEMS GRID: manufacturer cards on home
   ============================================================ */
.systems-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
@media (max-width: 920px) { .systems-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .systems-grid { grid-template-columns: 1fr; } }

.system-card {
  background: var(--bg);
  border: 1.5px solid var(--border);
  border-radius: 14px;
  padding: 24px;
  transition: border-color 280ms cubic-bezier(.2,.7,.2,1),
              transform 280ms cubic-bezier(.2,.7,.2,1),
              box-shadow 360ms cubic-bezier(.2,.7,.2,1);
}
/* The cards stretch to equal height as grid items, but their content did not
   flex, so the expand button landed wherever that card's copy happened to
   end: 21px of stagger across the first row, and a gap below the button that
   swung between 25px and 115px depending on which row a card sat in. Column
   flex with an auto top margin pins it to the bottom of every card, with the
   same breathing room above it whatever the copy does. */
.system-card { display: flex; flex-direction: column; }
.system-card .tap-hint { margin-top: auto; padding-top: 18px; }
@media (max-width: 600px) { .system-card .tap-hint { margin-top: auto; } }
/* The auto margin above still let the buttons drift once a drawer opened: the
   open card grows, its row neighbours stretch to match, and their buttons slide
   down with them, so a row showed three buttons at three heights. Where subgrid
   is supported, every card in a row shares the same row lines (logo, line, specs,
   button, drawer), so the buttons sit level whether drawers are open or shut.
   Browsers without subgrid keep the flex fallback above. */
@supports (grid-template-rows: subgrid) {
  .systems-grid { row-gap: 0; }
  .systems-grid > .system-card {
    display: grid;
    grid-row: span 5;
    grid-template-rows: subgrid;
    row-gap: 0;
    margin-bottom: 18px;
    align-content: start;
  }
  .systems-grid > .system-card .tap-hint { margin-top: 0; align-self: end; }
  .systems-grid > .system-card .drawer { align-self: start; }
}

.system-card:hover {
  border-color: color-mix(in srgb, var(--accent) 60%, var(--border));
  transform: translateY(-2px);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 10%, transparent),
              0 12px 28px -12px color-mix(in srgb, var(--accent) 30%, transparent);
}
.system-card .origin {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}
.system-card h3 {
  font-family: var(--font-heading);
  font-size: 24px;
  font-weight: 700;
  margin: 0 0 12px;
  letter-spacing: -0.01em;
}
.system-card .line {
  font-size: 13px;
  color: var(--text);
  line-height: 1.55;
  margin: 0 0 14px;
}
/* .meta kept as a class hook only (a second document's markup depends on it,
   site/globe-backdrop 28/09/2026) - the three facts now stack as a real <ul>
   and take their look entirely from .bullets below, so no layout of its own. */
.system-card .bullets {
  list-style: none; padding: 0; margin: 0;
  font-size: 13px;
  color: var(--muted);
}
.system-card .bullets li {
  padding: 6px 0 6px 18px;
  position: relative;
  line-height: 1.5;
}
.system-card .bullets li::before {
  content: ""; position: absolute;
  left: 0; top: 12px;
  width: 8px; height: 1.5px;
  background: var(--accent);
}
.system-card-cta {
  background: color-mix(in srgb, var(--accent) 6%, var(--bg));
  border-style: dashed;
  display: flex; flex-direction: column;
}
.system-card-cta .bullets { margin-bottom: 16px; }
.system-card-cta .inline-link {
  margin-top: auto;
  font-size: 13px; font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}
.system-card-cta .inline-link:hover { text-decoration: underline; }

/* ============================================================
   FEATURE PROJECT: left art + right body
   ============================================================ */
.feature-project {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 48px;
  align-items: center;
}
@media (max-width: 920px) { .feature-project { grid-template-columns: 1fr; } }

.proj-art {
  background: linear-gradient(135deg, var(--surface-2), color-mix(in srgb, var(--accent) 40%, var(--surface)));
  border-radius: 18px;
  padding: 32px;
  min-height: 440px;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border);
}
.proj-frame {
  position: absolute; inset: 32px;
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  grid-template-rows: 1.4fr 1fr;
  gap: 8px;
}
.proj-pane {
  background:
    linear-gradient(160deg,
      rgba(168, 239, 239, 0.3) 0%,
      rgba(168, 239, 239, 0.10) 40%,
      rgba(16, 34, 34, 0.10) 100%);
  border: 1px solid rgba(16, 34, 34, 0.18);
  position: relative;
  overflow: hidden;
}
.proj-pane::after {
  content: ""; position: absolute;
  top: -50%; left: -30%;
  width: 60%; height: 200%;
  background: linear-gradient(110deg, transparent 30%, rgba(255,255,255,0.18) 50%, transparent 70%);
  transform: skewX(-12deg);
}
.proj-pane-a { grid-column: 1; grid-row: 1 / span 2; }
.proj-pane-b { grid-column: 2; grid-row: 1; }
.proj-pane-c { grid-column: 2; grid-row: 2; }

.proj-body .proj-meta {
  display: flex; gap: 10px; flex-wrap: wrap;
  font-size: 12px; color: var(--muted);
  margin-bottom: 16px;
}
.proj-body h3, .proj-body h2 {
  font-family: var(--font-heading);
  font-size: clamp(26px, 3.5vw, 34px);
  font-weight: 700;
  letter-spacing: -0.015em;
  margin: 0 0 16px;
  line-height: 1.15;
}
.proj-body p {
  font-size: 16px;
  color: var(--text);
  line-height: 1.55;
  margin: 0 0 24px;
}
.kv {
  list-style: none; padding: 0; margin: 0 0 28px;
  display: grid; gap: 0;
}
.kv li {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.kv li:last-child { border-bottom: none; }
.kv li span {
  color: var(--muted);
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  padding-top: 3px;
}
.kv li strong { color: var(--text); font-weight: 600; }

/* ============================================================
   STEP CODE TEASER: on home
   ============================================================ */
.step-teaser {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 36px;
  align-items: center;
}
@media (max-width: 920px) { .step-teaser { grid-template-columns: 1fr; } }
.teaser-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
}
.teaser-tile {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(95, 207, 200, 0.20);
  border-radius: 12px;
  padding: 20px;
}
.teaser-tile .t-lbl {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: #5FCFC8;
  margin-bottom: 10px;
}
.teaser-tile .t-val {
  font-family: var(--font-heading);
  font-size: 30px;
  font-weight: 700;
  color: #DCE6E7;
  letter-spacing: -0.01em;
  line-height: 1;
  margin-bottom: 6px;
}
.teaser-tile .t-sub {
  font-size: 12px;
  color: var(--muted);
}
.teaser-cta {
  text-align: left;
}
.teaser-cta .btn-primary {
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none;
}
.teaser-cta .src {
  margin: 16px 0 0;
  font-size: 12px;
  color: var(--muted);
}
.teaser-cta .src strong { color: #B6C4CB; }
.teaser-cta .src a { color: #5FCFC8; }

/* A second paragraph in the hero that is deliberately NOT the lede: the
   confidentiality note is context, not the page's opening claim, so it takes
   the muted colour and a step down in size rather than competing. */
/* The size declaration is dropped rather than forced: at lede size in the muted
   colour this reads as context without shrinking to the quietest thing on
   the page, which would undercut the one line on Projects most likely to
   win the client. */
.page-hero .lede.lede-note {
  color: var(--muted);
  margin-top: 14px;
  max-width: 62ch;
}

/* ============================================================
   SERVICE BAND
   A bordered panel rather than an eighth .service-detail. The seven
   above are product lines; servicing is a different purchase, and a
   panel says that without a second axis in the same list.
   ============================================================ */
.service-band {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 44px;
  align-items: start;
  background: color-mix(in srgb, var(--accent) 5%, var(--surface));
  border: 1.5px solid color-mix(in srgb, var(--accent) 26%, var(--border));
  border-radius: 18px;
  padding: 44px 48px;
}
@media (max-width: 880px) {
  .service-band { grid-template-columns: 1fr; gap: 28px; padding: 32px; }
}
.service-band .label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}
.service-band h2 {
  font-family: var(--font-heading);
  font-size: clamp(26px, 3.5vw, 34px);
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 16px;
}
.service-band p {
  font-size: 16px; line-height: 1.6;
  color: var(--text);
  max-width: 56ch;
  margin: 0 0 14px;
}
/* The scope boundary and the response line are caveats, not the pitch. */
.service-band .service-band-note {
  font-size: 14px; color: var(--muted); line-height: 1.55;
}
.service-band-actions {
  display: flex; gap: 14px; flex-wrap: wrap; align-items: center;
  margin: 6px 0 14px;
}
.service-band-list .lbl {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 14px;
}
.service-band-list ul {
  list-style: none; padding: 0; margin: 0;
  font-size: 14px; color: var(--text);
}
.service-band-list li {
  padding: 8px 0 8px 18px;
  position: relative;
  line-height: 1.5;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
}
.service-band-list li:last-child { border-bottom: none; }
.service-band-list li::before {
  content: ""; position: absolute;
  left: 0; top: 16px;
  width: 8px; height: 1.5px;
  background: var(--accent);
}

/* ============================================================
   CTA BAND
   ============================================================ */
.cta-band {
  background: color-mix(in srgb, var(--accent) 6%, var(--surface));
}
/* ------------------------------------------------------------
   The band fills with the brand gradient and carries the mark
   behind it. Fixed hexes rather than var(--accent): the panel
   holds body copy in white, and letting the light theme swap the
   accent in would drop that text under contrast. #1F6E68 is the
   brand accent-dark and measures 5.25:1 for the paragraph at 90%
   white, against the 4.5 AA floor for 15.5px; a lighter stop was
   tried first and came in at 4.1.
   The contact icon buttons under [data-section-id="quote-cta"]
   were written white-on-accent for exactly this treatment and
   had been sitting on a dark card since.
   ------------------------------------------------------------ */
.cta-band .cta-band-inner {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, #1F6E68 0%, #16534E 100%);
  border-color: transparent;
}
.cta-band .cta-band-inner::before {
  content: "";
  position: absolute; right: -30px; top: 50%;
  width: 300px; height: 300px;
  transform: translateY(-50%);
  background: url("catalyst-logo-light.png") no-repeat center / contain;
  filter: brightness(0) invert(1);
  /* A watermark, not a second layer of copy: at full white the mark sat at
     1.0:1 against the paragraph that runs over it. 0.10 keeps the monogram
     legible as a mark while every line of text stays above AA contrast
     against the worst pixel behind it. */
  opacity: 0.10;
  pointer-events: none;
}
.cta-band .cta-band-inner > * { position: relative; z-index: 1; }
.cta-band .cta-band-inner h2 { color: #FFFFFF; }
.cta-band .cta-band-inner p { color: rgba(255,255,255,0.90); }

/* On teal the accent-gradient fill would be invisible, so the primary
   button inverts: white at rest, and the hover that normally slides the
   fill in instead lifts and warms it. */
.cta-band .btn-primary { color: #14453F !important; }
.cta-band .btn-primary::before,
.cta-band .btn-primary::after {
  background: #FFFFFF !important;
  transform: translateX(0) !important;
}
@media (hover: hover) and (pointer: fine) {
  .cta-band .btn-primary:hover:not(:disabled) {
    color: #14453F !important;
    transform: translateY(-1px) !important;
  }
  .cta-band .btn-primary:hover:not(:disabled)::before {
    background: #E8FBF9 !important;
  }
}
@media (max-width: 880px) {
  .cta-band .cta-band-inner::before { width: 220px; right: -70px; opacity: 0.08; }
}
/* One centred column rather than copy-left / actions-right: the band reads as
   a single invitation instead of two things sharing a card. */
.cta-band-inner {
  display: grid;
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
  gap: 24px;
  background: var(--bg);
  border: 1.5px solid var(--border);
  border-radius: 18px;
  padding: 48px;
}
/* the paragraph needs a measure, or centred text sprawls the full card */
.cta-band-inner > div:first-child { max-width: 58ch; }
@media (max-width: 880px) {
  .cta-band-inner { padding: 32px; }
}
.cta-band-inner h2 {
  font-family: var(--font-heading);
  font-size: clamp(28px, 4vw, 38px);
  font-weight: 700;
  letter-spacing: -0.015em;
  margin: 0 0 12px;
}
.cta-band-inner p {
  font-size: 16px;
  color: var(--muted);
  margin: 0;
  line-height: 1.55;
}
.cta-band-actions {
  display: flex; flex-direction: column; gap: 14px;
  align-items: center;
}
.cta-band-actions .btn-primary {
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none;
}
.phone-cta-inline {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  transition: color 180ms;
}
.phone-cta-inline:hover { color: var(--accent); }
.phone-cta-inline svg { width: 13px; height: 13px; }

/* ============================================================
   PAGE-LEVEL UTILS
   ============================================================ */
.two-up {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 48px;
  align-items: start;
}
@media (max-width: 920px) { .two-up { grid-template-columns: 1fr; gap: 28px; } }
/* About runs as one column. It used to be a .two-up with the stats in the
   side column, but the stats block is 467px against prose blocks of 341, 286
   and 162, so whichever grid row held it was inflated and the leftover
   appeared as a 185px gap before the first photograph, against 58 to 68px
   everywhere else. Putting the photos in the text column instead just moves
   the same emptiness into column 2. One column, stats as a full-width band,
   and neither failure mode exists. */
.about-body > .photo-band { max-width: 852px; margin: 10px 0 20px; }
.about-body > .prose + .photo-band { margin-top: 18px; }
.stat-band { margin: 26px 0 34px; }

.prose {
  /* Was 720px, which at 16px put Privacy and Terms between 88 and 95
     characters per line across 21 paragraphs - they are also the two longest
     pages on the site, so the measure had nowhere to hide. About is
     unaffected: its .prose sits in a narrower column and never reached the
     old cap either. */
  max-width: 56ch;
  font-size: 16px;
  line-height: 1.7;
  color: var(--text);
}
.prose p { margin: 0 0 16px; }
.prose p:last-child { margin-bottom: 0; }
.prose h3, .prose h2 {
  font-family: var(--font-heading);
  font-size: 24px;
  font-weight: 700;
  margin: 32px 0 12px;
  letter-spacing: -0.01em;
}
.prose h3:first-child, .prose h2:first-child { margin-top: 0; }

/* Service detail card (Services page) */
.service-detail {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 32px;
  padding: 36px 0;
  border-bottom: 1px solid var(--border);
}
.service-detail:first-of-type { padding-top: 16px; }
.service-detail:last-of-type { border-bottom: none; }
@media (max-width: 720px) { .service-detail { grid-template-columns: 1fr; gap: 16px; } }
/* The rail carries an operation symbol rather than a photograph. A photo shows
   one unit in one finish; the symbol is the drawing convention every European
   catalogue uses, and an architect reads the configuration off it without a
   caption - which is the point of the swap. Same accent-on-tint language as
   .how-icon, at rail scale. */
.service-detail .rail-icon {
  width: 100%;
  aspect-ratio: 1 / 1;
  /* fills the 220px rail: at 150 it floated in the column and left the
     rail looking unfinished against a body twice its height */
  max-width: 220px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--accent) 22%, var(--border));
  color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.service-detail .rail-icon svg { width: 58%; height: 58%; display: block; }
@media (max-width: 720px) {
  .service-detail .rail-icon { max-width: 108px; }
}

.service-detail > div:first-child { align-self: start; }
.service-detail .label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent);
}
.service-detail h2 .svc-idx {
  font-size: 34px; font-weight: 700;
  color: var(--accent);
  line-height: 1;
  margin-right: 4px;
}
.service-detail h2 .svc-sep {
  font-size: 34px; font-weight: 700; color: var(--accent);
  line-height: 1; margin-right: 6px;
}
.service-detail h3, .service-detail h2 {
  font-family: var(--font-heading);
  font-size: 26px; font-weight: 700;
  letter-spacing: -0.01em;
  margin: 8px 0 4px;
}
/* Sits under the heading now, not in the rail: a one-line credit that
   was wrapping at about 30 characters in a 220px column. */
.service-detail .meta {
  font-size: 13px;
  color: var(--muted);
  letter-spacing: 0.01em;
  margin: -6px 0 16px;
}
/* Measure cap. .no-photo blocks drop the 220px rail and ran the full 1116px
   wrap, which put three paragraphs at 147, 113 and 107 characters per line -
   past the width where the eye reliably finds the start of the next line.
   Home already caps its .lede at 780px and .strip-head at 720px on purpose;
   this block never got the same treatment. */
.service-detail .body { font-size: 16px; color: var(--text); line-height: 1.6; max-width: 56ch; }
.service-detail .body p { margin: 0 0 12px; }
.service-detail .body p:last-child { margin-bottom: 0; }
.service-detail .body ul {
  list-style: none; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px 18px;
  margin: 12px 0 0;
  font-size: 13px; color: var(--muted);
}
@media (max-width: 600px) { .service-detail .body ul { grid-template-columns: 1fr; } }
.service-detail .body ul li { padding-left: 16px; position: relative; }
.service-detail .body ul li::before {
  content: ""; position: absolute; left: 0; top: 9px;
  width: 7px; height: 1.5px; background: var(--accent);
}

/* Project gallery card (Projects page) */
.project-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}
@media (max-width: 720px) { .project-grid { grid-template-columns: 1fr; } }
.project-card {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 16px;
  overflow: hidden;
  display: flex; flex-direction: column;
  transition: transform 280ms cubic-bezier(.2,.7,.2,1),
              border-color 280ms,
              box-shadow 360ms cubic-bezier(.2,.7,.2,1);
}
.project-card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--accent) 60%, var(--border));
  box-shadow: 0 16px 36px -16px color-mix(in srgb, var(--accent) 25%, transparent);
}
.project-card .visual {
  height: 240px;
  background: linear-gradient(135deg, var(--surface-2), color-mix(in srgb, var(--accent) 50%, var(--surface)));
  position: relative;
  overflow: hidden;
}
.project-card .visual::after {
  content: ""; position: absolute;
  top: 14%; left: 20%; right: 20%; bottom: 14%;
  background:
    linear-gradient(160deg,
      rgba(168, 239, 239, 0.30) 0%,
      rgba(168, 239, 239, 0.10) 40%,
      rgba(16, 34, 34, 0.10) 100%);
  border: 1px solid rgba(16, 34, 34, 0.18);
}
.project-card .body { padding: 24px; }
.project-card .meta {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 10px;
}
.project-card h3, .project-card h2 {
  font-family: var(--font-heading);
  font-size: 22px; font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 8px;
}
.project-card p {
  font-size: 13px;
  color: var(--text);
  margin: 0 0 12px;
  line-height: 1.55;
}
.project-card .pills {
  display: flex; gap: 6px; flex-wrap: wrap;
  font-size: 11px;
  color: var(--accent);
}
.project-card .pills span {
  padding: 4px 10px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-radius: 999px;
}

/* Real project photography (09/09/2026). A card or feature with .has-photo
   drops the gradient stand-in and shows the image edge to edge. */
.project-card.has-photo .visual { background: var(--surface-2); }
.project-card.has-photo .visual::after { display: none; }
.project-card.has-photo .visual img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 600ms cubic-bezier(.2,.7,.2,1);
}
.project-card.has-photo:hover .visual img { transform: scale(1.03); }
.proj-art.has-photo { padding: 0; min-height: 0; aspect-ratio: 2 / 1; background: var(--surface-2); }
.proj-art.has-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Contact form */
.contact-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 48px;
}
@media (max-width: 880px) { .contact-grid { grid-template-columns: 1fr; gap: 28px; } }

.contact-card {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 14px;
  padding: 28px;
}
.contact-card h3, .contact-card h2 {
  font-family: var(--font-heading);
  font-size: 22px; font-weight: 700;
  margin: 0 0 6px;
  letter-spacing: -0.01em;
}
.contact-card .sub {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 22px;
  line-height: 1.5;
}
.contact-card .field { margin-bottom: 18px; }
.contact-card form .actions {
  display: flex; gap: 12px; align-items: center;
  margin-top: 6px;
}
.contact-card form .actions .btn-primary {
  display: inline-flex; align-items: center; gap: 8px;
}

.contact-info {
  display: flex; flex-direction: column; gap: 20px;
}
.contact-info-row {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 22px;
}
.contact-info-row .lbl {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}
.contact-info-row .val {
  font-size: 16px;
  color: var(--text);
  line-height: 1.55;
}
.contact-info-row .val a {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
}
.contact-info-row .val a:hover { text-decoration: underline; }

/* Quote page wrapper: gives the lifted qflow section breathing room
   inside a page hero instead of the prototype's .sec-head context. */
.page-host .demo {
  background: transparent;
  border: none;
  padding: 0;
  margin-bottom: 0;
}
.page-host .demo:hover, .page-host .demo:focus-within {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}
.page-host .demo-label { display: none; }

/* ============================================================
   Quote wizard: restrained hover + re-laid audience step
   (Mike, 05/10/2026). The tiles, project-type tiles and dropzones
   used to run a full white diagonal sweep plus a lift, a glyph spin
   and a big halo on every hover. One restrained highlight now:
   border to the accent, a 1px lift, a soft shadow. No sweep, no
   spin, no scale. Same rules at 390px and in the canvas phone frame.
   ============================================================ */
.qflow .audience-tile::before,
.qflow .ptype-tile::before,
.qflow .dropzone::before { display: none; }
.qflow .audience-tile,
.qflow .ptype-tile,
.qflow .dropzone {
  transition: border-color 160ms ease, background-color 160ms ease,
              box-shadow 160ms ease, transform 160ms ease;
}
.qflow .audience-tile:hover,
.qflow .ptype-tile:hover,
.qflow .dropzone:hover,
.qflow .dropzone.dragging {
  transform: translateY(-1px);
  box-shadow: 0 6px 16px -10px color-mix(in srgb, var(--accent) 45%, transparent);
}
.qflow .audience-tile:hover .glyph,
.qflow .ptype-tile:hover .icn {
  transform: none;
}
.qflow .audience-tile:hover .glyph {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  color: var(--accent);
}
.qflow .audience-tile:focus-visible,
.qflow .ptype-tile:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
@media (hover: none) {
  .qflow .audience-tile:hover,
  .qflow .ptype-tile:hover,
  .qflow .dropzone:hover { transform: none; }
}

/* Step 1 (audience), phone / narrow column (Mike, 19/10/2026: "very
   squished"). Each option is a full-width stacked card: glyph and title
   share the top row, the description runs the FULL card width beneath
   (it was squeezed into a ~190px column beside the glyph), then the
   small label. Roomier padding and gaps; every card is well over 44px. */
.qflow .audience-grid { grid-template-columns: 1fr; gap: 14px; }
.qflow .audience-tile.homeowner-wide { grid-column: auto; }
.qflow .audience-tile {
  display: grid;
  grid-template-columns: 48px 1fr;
  column-gap: 14px; row-gap: 10px;
  align-items: center;
  padding: 18px 18px 16px;
  min-height: 44px;
}
.qflow .audience-tile .glyph { grid-row: 1; grid-column: 1; width: 48px; height: 48px; margin: 0; }
.qflow .audience-tile h3 { grid-row: 1; grid-column: 2; font-size: 20px; line-height: 1.2; }
.qflow .audience-tile p { grid-column: 1 / -1; font-size: 14px; line-height: 1.55; }
.qflow .audience-tile .for { grid-column: 1 / -1; margin-top: 2px; font-size: 11px; }

@media (min-width: 1081px), (min-width: 761px) and (max-width: 880px) {
  .qflow .audience-grid { grid-template-columns: repeat(3, 1fr); gap: 14px; }
  .qflow .audience-tile {
    display: flex; flex-direction: column; gap: 8px;
    padding: 20px 18px 16px;
  }
  .qflow .audience-tile .glyph { margin: 0 0 4px; width: 44px; height: 44px; }
  .qflow .audience-tile h3, .qflow .audience-tile p, .qflow .audience-tile .for { grid-column: auto; grid-row: auto; }
  .qflow .audience-tile h3 { font-size: 19px; }
  .qflow .audience-tile p { font-size: 13px; }
  .qflow .audience-tile .for { margin-top: auto; padding-top: 6px; }
}

/* Phone: less chrome around the card, and the five-step stepper stays
   on ONE line (it wrapped to three) by labelling only the current step. */
@media (max-width: 620px) {
  /* 21/10/2026 (Mike, second comment: "way too squished"): the cards were only
     ~292px wide at 390 because page gutter + card border + .main padding each took a
     slice. The wizard card now bleeds 12px into the page gutter and .main trims its
     side padding to 14px, so the option cards gain ~34px of width. */
  .qflow { margin-left: -12px; margin-right: -12px; }
  .qflow .main { padding: 24px 14px 26px; min-height: 0; }
  .qflow .qhead h2, .qflow .qhead h3 { font-size: 26px; line-height: 1.2; text-wrap: balance; margin-bottom: 10px; }
  .qflow .qhead p { font-size: 14px; line-height: 1.55; margin-bottom: 22px; }
  .qflow .qsteps { flex-wrap: nowrap; gap: 6px; margin-bottom: 26px; }
  .qflow .qstep:not(.active) { font-size: 0; gap: 0; }
  .qflow .qstep:not(.active) .num { font-size: 11px; }
  .qflow .qstep { white-space: nowrap; }
  .qflow .qsteps .bar { flex: 1 1 4px; min-width: 3px; max-width: 28px; }
  .qflow .ptype-tile { padding: 14px 8px; }
  .qflow .qnav .btn-primary { min-height: 44px; }
}

/* ============================================================
   CTA family: Variant B "Slide Fill": LOCKED (2026-05-17)
   ============================================================
   At rest: transparent fill, accent-colored text, no border.
   On hover: a gradient fill + masked gradient outline ring slide
   in from the left over 360ms, like a door opening. Text flips
   to white. Icon nudges 3 px forward.

   This replaces the earlier "always-on Glass Pane gradient"
   pattern. The slide-fill is more elegant and reads as a more
   intentional CTA: restrained at rest, decisive on hover.

   Applies to: .btn-primary, .btn-secondary, .btn-ghost, and the
   topbar CTA pills (.nav-a .cta .btn, .site-nav .cta .btn).
   Lifted from brand/web-components.html section 01, Variant B.
   ============================================================ */

/* Anchors styled as buttons need no underline + inline-flex */
a.btn-primary, a.btn-secondary, a.btn-ghost {
  text-decoration: none;
  display: inline-flex; align-items: center; gap: 8px;
}

/* Reset: strip the always-on gradient + halo from styles.css.
   isolation: isolate creates a stacking context so the negative
   z-index pseudo-elements sit behind the text but in front of
   anything outside the button.
   NOTE: topbar CTA (.nav-a .cta .btn, .site-nav .cta .btn) is
   intentionally excluded: it stays on the always-on Glass Pane
   pattern for prominence per the locked exception (2026-05-17). */
.btn-primary,
.btn-secondary,
.btn-ghost {
  background: transparent !important;
  border: none !important;
  isolation: isolate;
  box-shadow: none !important;
  border-radius: 999px !important;
  transition: color 220ms cubic-bezier(.2,.7,.2,1),
              transform 220ms cubic-bezier(.2,.7,.2,1) !important;
  overflow: hidden;
  position: relative;
}

/* Primary CTA: accent color at rest */
.btn-primary {
  color: var(--accent) !important;
}

/* Slide-in gradient fill (sits behind the text) */
.btn-primary::before {
  content: "" !important;
  position: absolute !important;
  inset: 0 !important;
  top: 0 !important; left: 0 !important;
  width: 100% !important; height: 100% !important;
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%) !important;
  border-radius: 999px !important;
  transform: translateX(-101%) !important;
  transition: transform 360ms cubic-bezier(.65,.05,.36,1) !important;
  z-index: -2 !important;
  pointer-events: none !important;
}

/* Slide-in gradient outline ring (masked to a 1.5px stroke).
   Sits between the fill and the text: z-index -1. */
.btn-primary::after {
  content: ""; position: absolute; inset: 0;
  width: 100%; height: 100%;
  top: 0; left: 0;
  border-radius: 999px;
  padding: 1.5px;
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
  -webkit-mask:
    linear-gradient(#fff, #fff) content-box,
    linear-gradient(#fff, #fff);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#fff, #fff) content-box,
    linear-gradient(#fff, #fff);
  mask-composite: exclude;
  pointer-events: none;
  z-index: -1;
  transform: translateX(-101%);
  transition: transform 360ms cubic-bezier(.65,.05,.36,1);
}

/* Hover: pseudos slide in, text flips to white.
   Scoped to (hover: hover) and (pointer: fine) so touch devices
   don't fire phantom :hover during a tap, .tap-active owns the
   visual on touch instead. */
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover:not(:disabled) {
    color: #FFFFFF !important;
    transform: none !important;
    filter: none !important;
  }
  .btn-primary:hover:not(:disabled)::before,
  .btn-primary:hover:not(:disabled)::after {
    transform: translateX(0) !important;
  }
  .btn-primary:hover:not(:disabled) .icon {
    transform: translateX(3px) !important;
    transition: transform 220ms cubic-bezier(.2,.7,.2,1) !important;
  }
}

/* Press feedback: tight scale dip */
.btn-primary:active:not(:disabled) {
  transform: scale(0.98) !important;
  transition-duration: 80ms !important;
}

/* ============================================================
   Topbar CTA: locked exception (always-on Glass Pane gradient).
   The page-body CTAs use Variant B slide-fill, but the topbar
   "Request a quote" pill needs maximum prominence and stays on
   the always-on pattern. Locked 2026-05-17 per Mike.
   These rules undo the Variant B reset above and restore the
   always-on look from styles.css. Sweep stays at its brightened
   60% / 80% values for hover visibility.
   ============================================================ */
.nav-a .cta .btn,
.site-nav .cta .btn {
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%) !important;
  color: #FFFFFF !important;
  border-radius: 999px !important;
  padding: 12px 24px;
  font-weight: 600; font-size: 14px;
  letter-spacing: 0.01em;
  border: none !important;
  position: relative; overflow: hidden;
  box-shadow:
    0 2px 4px rgba(16, 34, 34, 0.08),
    0 6px 18px -6px color-mix(in srgb, var(--accent) 55%, transparent) !important;
  transition: transform 220ms cubic-bezier(.2, .7, .2, 1),
              box-shadow 280ms cubic-bezier(.2, .7, .2, 1),
              filter 200ms !important;
  isolation: auto;
}
.nav-a .cta .btn::before,
.site-nav .cta .btn::before {
  /* CASCADE ORDER MATTERS: `inset: auto` is a shorthand that resets
     top/right/bottom/left. It MUST come BEFORE the longhand top/left
     declarations below or the sweep ends up rendered in-flow (visible
     at rest, overlapping the button text). Bug fixed 2026-05-17. */
  content: "" !important;
  position: absolute !important;
  inset: auto !important;
  top: 0 !important;
  left: -120% !important;
  right: auto !important;
  bottom: auto !important;
  width: 80% !important;
  height: 100% !important;
  background: linear-gradient(120deg,
    transparent 20%,
    rgba(255, 255, 255, 0.60) 50%,
    transparent 80%) !important;
  transform: skewX(-20deg) !important;
  transition: left 700ms cubic-bezier(.2, .7, .2, 1) !important;
  z-index: auto !important;
  border-radius: 0 !important;
  pointer-events: none !important;
}
.nav-a .cta .btn::after,
.site-nav .cta .btn::after {
  display: none !important;
}
.nav-a .cta .btn:hover,
.site-nav .cta .btn:hover {
  transform: translateY(-2px) scale(1.015) !important;
  color: #FFFFFF !important;
  filter: saturate(1.1) !important;
  box-shadow:
    0 4px 8px rgba(16, 34, 34, 0.10),
    0 0 0 4px color-mix(in srgb, var(--accent) 14%, transparent),
    0 18px 40px -12px color-mix(in srgb, var(--accent) 85%, transparent) !important;
}
.nav-a .cta .btn:hover::before,
.site-nav .cta .btn:hover::before {
  left: 130% !important;
}
.nav-a .cta .btn:hover .icon,
.site-nav .cta .btn:hover .icon {
  transform: translateX(3px);
  transition: transform 220ms cubic-bezier(.2, .7, .2, 1);
}
.nav-a .cta .btn:active,
.site-nav .cta .btn:active {
  transform: translateY(0) scale(0.99) !important;
  transition-duration: 80ms !important;
}

/* === Secondary: borderless at rest, ink fill slides in === */
.btn-secondary {
  color: var(--text) !important;
}
.btn-secondary::before {
  content: ""; position: absolute; inset: 0;
  top: 0; left: 0; width: 100%; height: 100%;
  background: var(--text);
  border-radius: 999px;
  transform: translateX(-101%);
  transition: transform 360ms cubic-bezier(.65,.05,.36,1);
  z-index: -2;
  pointer-events: none;
}
.btn-secondary::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 999px;
  padding: 1.5px;
  background: var(--text);
  -webkit-mask:
    linear-gradient(#fff, #fff) content-box,
    linear-gradient(#fff, #fff);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#fff, #fff) content-box,
    linear-gradient(#fff, #fff);
  mask-composite: exclude;
  pointer-events: none;
  z-index: -1;
  transform: translateX(-101%);
  transition: transform 360ms cubic-bezier(.65,.05,.36,1);
}
@media (hover: hover) and (pointer: fine) {
  .btn-secondary:hover:not(:disabled) {
    color: var(--bg) !important;
  }
  .btn-secondary:hover:not(:disabled)::before,
  .btn-secondary:hover:not(:disabled)::after {
    transform: translateX(0) !important;
  }
}

/* === Ghost: muted at rest, surface fill slides in === */
.btn-ghost {
  color: var(--muted) !important;
}
.btn-ghost::before {
  content: ""; position: absolute; inset: 0;
  top: 0; left: 0; width: 100%; height: 100%;
  background: var(--surface-2);
  border-radius: 999px;
  transform: translateX(-101%);
  transition: transform 360ms cubic-bezier(.65,.05,.36,1);
  z-index: -2;
  pointer-events: none;
}
.btn-ghost::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 999px;
  padding: 1.5px;
  background: var(--border);
  -webkit-mask:
    linear-gradient(#fff, #fff) content-box,
    linear-gradient(#fff, #fff);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#fff, #fff) content-box,
    linear-gradient(#fff, #fff);
  mask-composite: exclude;
  pointer-events: none;
  z-index: -1;
  transform: translateX(-101%);
  transition: transform 360ms cubic-bezier(.65,.05,.36,1);
}
@media (hover: hover) and (pointer: fine) {
  .btn-ghost:hover:not(:disabled) {
    color: var(--text) !important;
  }
  .btn-ghost:hover:not(:disabled)::before,
  .btn-ghost:hover:not(:disabled)::after {
    transform: translateX(0) !important;
  }
}

/* ============================================================
   Tap-animation persistence: touch-device feature.
   ============================================================
   On touch devices the click handler holds the slide-fill animation
   through to completion before navigating (otherwise the page used to
   jump mid-animation and the click felt untracked). On back/forward
   nav the previously tapped button is restored to its animated state
   so the origin link is visually obvious. Cleared on next interaction.

   .tap-active: applied for ~380 ms while we wait for the
                     slide-fill to play out before navigating.
   .tap-persistent: applied on back/forward navigation to the
                     button matching the stored href. Cleared on
                     the next pointerdown / keydown / scroll.

   Both classes mirror the existing :hover end-state of each variant
   exactly so the visual is identical. JS lives in site.js. */
.btn-primary.tap-active,
.btn-primary.tap-persistent {
  color: #FFFFFF !important;
  transform: none !important;
  filter: none !important;
}
.btn-primary.tap-active::before,
.btn-primary.tap-active::after,
.btn-primary.tap-persistent::before,
.btn-primary.tap-persistent::after {
  transform: translateX(0) !important;
}
.btn-primary.tap-active .icon,
.btn-primary.tap-persistent .icon {
  transform: translateX(3px) !important;
}

.btn-secondary.tap-active,
.btn-secondary.tap-persistent {
  color: var(--bg) !important;
}
.btn-secondary.tap-active::before,
.btn-secondary.tap-active::after,
.btn-secondary.tap-persistent::before,
.btn-secondary.tap-persistent::after {
  transform: translateX(0) !important;
}

.btn-ghost.tap-active,
.btn-ghost.tap-persistent {
  color: var(--text) !important;
}
.btn-ghost.tap-active::before,
.btn-ghost.tap-active::after,
.btn-ghost.tap-persistent::before,
.btn-ghost.tap-persistent::after {
  transform: translateX(0) !important;
}

/* Drawer CTA pill: mobile-only. Mirrors the existing
   .mobile-drawer a.cta-link:hover state (lift + saturate). */
@media (max-width: 480px) {
  .mobile-drawer a.cta-link.tap-active,
  .mobile-drawer a.cta-link.tap-persistent {
    transform: translateY(-1px);
    filter: saturate(1.08);
  }
}

/* Disabled state */
.btn-primary:disabled,
.btn-secondary:disabled,
.btn-ghost:disabled {
  cursor: not-allowed;
}

/* Small adjustment: page-hero buttons need to be inline-flex anchors */
.page-hero .btn-primary,
.page-hero .btn-ghost {
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none;
}
.page-hero .btn-ghost {
  background: transparent;
  color: var(--text);
  border: 1.5px solid var(--border);
}
.page-hero .btn-ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}

/* Spacing: make sure footer separates from last strip */
footer.site { border-top: 1px solid var(--border); }

/* ============================================================
   ACCESSIBILITY
   ============================================================ */
/* Skip-to-content link: first focusable element on every page.
   Visually hidden until keyboard-focused, then visible top-left. */
.skip-link {
  position: absolute;
  top: -100px; left: 0;
  z-index: 9999;
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
  color: #FFFFFF;
  font-family: var(--font-body);
  font-size: 14px; font-weight: 600;
  padding: 12px 20px;
  text-decoration: none;
  border-radius: 0 0 12px 0;
  box-shadow: 0 4px 14px -4px rgba(16,34,34,0.30);
  transition: top 200ms cubic-bezier(.2,.7,.2,1);
}
.skip-link:focus {
  top: 0;
  outline: 2px solid #FFFFFF;
  outline-offset: -4px;
}

/* Reduced-motion preference: disable non-essential motion.
   Keeps transitions short and removes parallax/scaling/sliding. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Preserve open/close visibility transitions (still functional, just instant) */
  .mobile-drawer, .nav-backdrop, .dropdown-menu, .modal { transition: opacity 0.01ms !important; }
  /* Disable the pulse animation on active nav dot */
  .nav-a nav.primary > a.active::before { animation: none !important; }
  /* Disable sheen sweeps */
  .btn-primary::before, .nav-a .cta .btn::before, .mobile-burger::before, .switch .track::before, .dropdown-toggle::before { display: none !important; }
}

/* Visible focus rings: make every interactive element easy to spot
   in keyboard navigation. Per WCAG 2.4.7 (Focus Visible). */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}
.mobile-burger:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 4px;
}

/* ============================================================
   SOCIAL ICONS: brand-matched, dynamic-language hover
   ============================================================
   Icons inject automatically into every [data-social-icons]
   container via site.js. At rest: muted ink color, soft surface
   ring. Hover: lift -2 px, accent color shift, accent halo, ring
   thickens to accent. Per the dynamic-language conventions in
   brand-guide.md → Section 5. */

.social-icons-row {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.social-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  /* The accent is the RESTING state, not just the hover. These sat at
     var(--muted) and read as washed-out white against the dark footer - a
     contact control that looked disabled.
     --accent-hover rather than --accent: on a light theme card the lighter
     #2A8B83 measures 2.89:1, under the 3:1 a UI graphic needs, where the
     darker #1F6E68 gets 4.24. On dark grounds it resolves lighter anyway. */
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--accent) 38%, var(--border));
  color: var(--accent-hover);
  text-decoration: none;
  transition: transform 220ms cubic-bezier(.2, .7, .2, 1),
              color 220ms cubic-bezier(.2, .7, .2, 1),
              border-color 220ms cubic-bezier(.2, .7, .2, 1),
              background 220ms,
              box-shadow 280ms cubic-bezier(.2, .7, .2, 1);
}
.social-icon-glyph {
  display: inline-flex;
  width: 18px;
  height: 18px;
}
.social-icon-glyph svg {
  width: 100%;
  height: 100%;
  display: block;
}
/* Rest is already accent, so hover fills instead of colouring - the same
   accent/accent-text flip the brochure chip uses. */
/* .contact-info-row .val a (0,2,1) outranks .social-icon (0,1,0), so on the
   contact page the glyph was still taking the lighter --accent and measuring
   2.89:1 on that card. Matched here rather than reaching for !important. */
.contact-info-row .val a.social-icon { color: var(--accent-hover); }
.contact-info-row .val a.social-icon:hover { color: var(--accent-text); }

.social-icon:hover {
  transform: translateY(-2px);
  color: var(--accent-text);
  border-color: var(--accent);
  background: var(--accent);
  box-shadow:
    0 0 0 4px color-mix(in srgb, var(--accent) 14%, transparent),
    0 8px 22px -10px color-mix(in srgb, var(--accent) 70%, transparent);
}
.social-icon:active {
  transform: translateY(0) scale(0.96);
  transition-duration: 80ms;
}
.social-icon:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Variant with text labels (used on contact page) */
.social-icon-label {
  color: var(--text);
  margin-left: 8px;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.social-icons-row[data-social-labels] .social-icon {
  width: auto;
  padding: 8px 16px 8px 12px;
  gap: 4px;
}

/* Footer placement: every cluster stacks vertically on the same
   centered axis. Brand on top → menu → phone CTA → social → legal.
   Locked 2026-05-17 per Mike: footer everywhere is centered. */
footer.site .top-row {
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 22px;
  text-align: center;
}
footer.site .brand-cluster,
footer.site .menu,
footer.site .cta-cluster {
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 14px;
  text-align: center;
}
/* Call, text and the social links are all .social-icon now, so the contact
   pair and the social row read as one continuous row rather than two stacked
   groups. Same gap on both sides of the seam. */
footer.site .cta-cluster {
  flex-direction: row !important;
  flex-wrap: wrap;
  gap: 10px !important;
}
footer.site .contact-actions {
  display: flex; align-items: center; gap: 10px;
}

/* The service area sat under the wordmark in the header until it crowded the
   logo; it keeps the same relationship to the wordmark down here, in the same
   small-caps treatment the header strapline used. */
footer.site .brand-cluster .sub {
  font-family: var(--font-body);
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--muted);
  margin-top: -4px;
  line-height: 1.7;
  text-wrap: balance;
}
footer.site .menu {
  flex-direction: row !important;
  flex-wrap: wrap;
  gap: 18px;
}
footer.site .social-icons-row {
  align-items: center;
  justify-content: center;
}
/* Centre the bottom legal row too */
footer.site .bottom {
  text-align: center !important;
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  gap: 6px;
}
/* Footer icons on the Mist/Night chrome, adjust border + colors */
/* The footer used to grey these down off var(--text) - which is what made
   them read white and inert. It carries its own dark ground in BOTH themes,
   so they take the dark-theme accent here regardless of the page theme,
   rather than the light theme's darker #2A8B83 which would sink into it. */
footer.site .social-icon {
  border-color: color-mix(in srgb, #5FCFC8 40%, transparent);
  color: #5FCFC8;
  background: color-mix(in srgb, #5FCFC8 9%, transparent);
}
footer.site .social-icon:hover {
  border-color: #5FCFC8;
  background: #5FCFC8;
  color: #102222;
}

/* ============================================================
   EDIT MODE: in-browser content editing
   ============================================================
   Activated when ?edit=1 is in the URL. Click any heading or
   paragraph to edit it in place. Changes save to localStorage
   automatically. Export button downloads the current HTML with
   edits baked in. See site.js → editMode for details. */

/* Toolbar pinned to the bottom of the viewport */
.edit-bar {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 9998;
  background: #102222;
  color: #DCE6E7;
  border-top: 2px solid var(--accent);
  box-shadow: 0 -8px 24px -8px rgba(0,0,0,0.40);
  font-family: var(--font-body);
  padding: 14px 24px;
}
.edit-bar-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  max-width: 1240px; margin: 0 auto;
}
.edit-bar-status {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px;
}
.edit-bar-status strong { font-weight: 700; color: #5FCFC8; }
.edit-counter {
  font-size: 12px;
  color: #8395A0;
  margin-left: 8px;
}
.edit-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #5FCFC8;
  box-shadow: 0 0 0 0 #5FCFC8;
  animation: editPulse 1.8s ease-in-out infinite;
}
@keyframes editPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(95, 207, 200, 0.5); }
  50%      { box-shadow: 0 0 0 6px rgba(95, 207, 200, 0); }
}
.edit-bar-actions {
  display: flex; gap: 10px;
}
.edit-btn {
  font-family: var(--font-body);
  font-size: 12px; font-weight: 600;
  padding: 8px 16px;
  border-radius: 999px;
  border: none;
  cursor: pointer;
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
  color: #FFFFFF;
  transition: transform 200ms cubic-bezier(.2,.7,.2,1), filter 200ms;
}
.edit-btn:hover { transform: translateY(-1px); filter: saturate(1.1); }
.edit-btn.ghost {
  background: transparent;
  color: #8395A0;
  border: 1px solid #2C4358;
}
.edit-btn.ghost:hover {
  color: #5FCFC8;
  border-color: #5FCFC8;
}
.edit-bar-help {
  font-size: 11px;
  color: #8395A0;
  margin-top: 8px;
  max-width: 1240px;
  margin-left: auto; margin-right: auto;
  text-align: left;
}

/* Add body padding-bottom so the edit bar doesn't cover content */
html[data-edit-mode="on"] body { padding-bottom: 120px; }

/* Editable text: dashed outline at rest, solid accent on focus */
[data-edit-mode="on"] .edit-target {
  outline: 1px dashed color-mix(in srgb, var(--accent) 50%, transparent);
  outline-offset: 4px;
  cursor: text;
  transition: outline-color 180ms, background 180ms;
  border-radius: 3px;
}
[data-edit-mode="on"] .edit-target:hover {
  outline-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 4%, transparent);
}
[data-edit-mode="on"] .edit-target:focus {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}

/* ============================================================
   AUDIT MODE: placeholder visualization
   ============================================================
   Activated when:
     · URL has ?audit=1 (one-time check), OR
     · localStorage.catalyst-audit is set to "on" (persistent), OR
     · You toggle via the console: catalyst.audit()
   Every element with data-placeholder is highlighted with a
   dashed magenta outline and a floating badge that shows the
   reason. A fixed banner top-right shows the per-page count.
   PURPOSE: makes pre-launch sign-off impossible to miss.
   ============================================================ */
body.audit-mode [data-placeholder] {
  outline: 2px dashed #D946A8 !important;
  outline-offset: 2px;
  position: relative;
  background: color-mix(in srgb, #D946A8 6%, transparent) !important;
}
body.audit-mode [data-placeholder]::after {
  content: "PLACEHOLDER: " attr(data-placeholder);
  position: absolute;
  top: -22px; left: 0;
  background: #D946A8;
  color: #FFFFFF;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 4px;
  white-space: nowrap;
  z-index: 2000;
  pointer-events: none;
  max-width: 90vw;
  overflow: hidden;
  text-overflow: ellipsis;
  box-shadow: 0 2px 6px rgba(0,0,0,0.25);
}
body.audit-mode [data-mock="true"] {
  outline: 2px dashed #DBA763 !important;
  outline-offset: 2px;
  background: color-mix(in srgb, #DBA763 6%, transparent) !important;
  position: relative;
}
body.audit-mode [data-mock="true"]::after {
  content: "MOCK DATA: not wired to backend";
  position: absolute;
  top: -22px; left: 0;
  background: #DBA763;
  color: #102222;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 4px;
  white-space: nowrap;
  z-index: 2000;
  pointer-events: none;
  box-shadow: 0 2px 6px rgba(0,0,0,0.25);
}
.audit-banner {
  display: none;
  position: fixed;
  top: 12px; right: 12px;
  background: #D946A8;
  color: #FFFFFF;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 10px 16px;
  border-radius: 999px;
  box-shadow: 0 6px 18px -6px rgba(0,0,0,0.35);
  z-index: 9999;
  cursor: pointer;
}
body.audit-mode .audit-banner { display: inline-flex; align-items: center; gap: 8px; }
.audit-banner::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: #FFFFFF;
  box-shadow: 0 0 0 0 rgba(255,255,255,0.6);
  animation: auditPulse 1.6s ease-in-out infinite;
}
@keyframes auditPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,255,0.6); }
  50%      { box-shadow: 0 0 0 5px rgba(255,255,255,0); }
}

/* ============================================================
   LOGIN + PORTAL: auth-shell layouts
   ============================================================ */
.auth-shell {
  min-height: calc(100vh - 220px);
  display: grid;
  place-items: center;
  padding: 64px 24px;
  background:
    radial-gradient(700px 320px at 18% 0%, color-mix(in srgb, var(--accent) 12%, transparent) 0%, transparent 70%),
    radial-gradient(560px 280px at 92% 100%, color-mix(in srgb, var(--accent) 8%, transparent) 0%, transparent 60%),
    var(--bg);
}
.auth-card {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 18px;
  padding: 40px;
  max-width: 460px;
  width: 100%;
  box-shadow: 0 20px 60px -30px color-mix(in srgb, var(--accent) 30%, transparent);
}
.auth-card h1 {
  font-family: var(--font-heading);
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.015em;
  margin: 0 0 6px;
}
.auth-card .sub {
  font-size: 14px;
  color: var(--muted);
  margin: 0 0 24px;
  line-height: 1.5;
}
.auth-tabs {
  display: flex;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px;
  margin-bottom: 22px;
  gap: 4px;
}
.auth-tab {
  flex: 1;
  padding: 10px 14px;
  border: none;
  background: transparent;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  border-radius: 999px;
  cursor: pointer;
  transition: background 220ms, color 220ms;
}
.auth-tab.active {
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
  color: #FFFFFF;
  box-shadow: 0 4px 12px -4px color-mix(in srgb, var(--accent) 50%, transparent);
}
.auth-card .field { margin-bottom: 16px; }
.auth-card .actions {
  display: flex; align-items: center; gap: 12px;
  margin-top: 8px;
}
.auth-card .actions .btn-primary {
  flex: 1;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.auth-card .links {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  color: var(--muted);
  display: flex; justify-content: space-between; gap: 10px;
}
.auth-card .links a { color: var(--accent); text-decoration: none; font-weight: 600; }
.auth-card .links a:hover { text-decoration: underline; }
.auth-card .scaffolding-note {
  margin-top: 18px;
  padding: 12px 14px;
  background: color-mix(in srgb, #DBA763 14%, transparent);
  border: 1px solid color-mix(in srgb, #DBA763 50%, transparent);
  border-radius: 10px;
  font-size: 12px;
  color: var(--text);
  line-height: 1.5;
}
.auth-card .scaffolding-note strong { color: #A87B24; }

/* Portal layout: two-column with sidebar */
.portal-shell {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 0;
  min-height: calc(100vh - 220px);
  background: var(--bg);
}
@media (max-width: 920px) { .portal-shell { grid-template-columns: 1fr; } }

.portal-sidebar {
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: 32px 20px;
}
@media (max-width: 920px) { .portal-sidebar { border-right: none; border-bottom: 1px solid var(--border); padding: 24px; } }
.portal-sidebar .who {
  padding: 16px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  margin-bottom: 22px;
}
.portal-sidebar .who .nm {
  font-family: var(--font-heading);
  font-size: 18px;
  font-weight: 700;
  margin: 0 0 4px;
}
.portal-sidebar .who .role {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent);
}
.portal-sidebar .who .org {
  font-size: 12px; color: var(--muted);
  margin-top: 4px;
}
.portal-sidebar nav { display: flex; flex-direction: column; gap: 2px; }
.portal-sidebar nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  text-decoration: none;
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  transition: background 200ms, color 200ms, padding-left 220ms cubic-bezier(.2,.7,.2,1);
}
.portal-sidebar nav a:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--accent); padding-left: 16px; }
.portal-sidebar nav a.active {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  font-weight: 600;
}
.portal-sidebar nav a svg { width: 16px; height: 16px; flex: 0 0 16px; }
.portal-sidebar nav .group-label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--muted);
  padding: 14px 12px 6px;
}

.portal-main {
  padding: 36px 40px 64px;
  overflow-x: auto;
}
@media (max-width: 720px) { .portal-main { padding: 24px; } }
.portal-main > header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  margin-bottom: 28px;
}
.portal-main > header h1 {
  font-family: var(--font-heading);
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.015em;
  margin: 0;
}
.portal-main > header .sub {
  font-size: 13px;
  color: var(--muted);
  margin-top: 4px;
}

/* Portal cards & components */
.portal-grid-2 { display: grid; grid-template-columns: 1.4fr 1fr; gap: 22px; }
.portal-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 880px) {
  .portal-grid-2, .portal-grid-3 { grid-template-columns: 1fr; }
}

.portal-card {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 14px;
  padding: 24px;
}
.portal-card h3 {
  font-family: var(--font-heading);
  font-size: 20px;
  font-weight: 700;
  margin: 0 0 14px;
  letter-spacing: -0.01em;
}
.portal-card .meta {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 6px;
}
.portal-stat {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 20px;
}
.portal-stat .num {
  font-family: var(--font-heading);
  font-size: 32px;
  font-weight: 700;
  color: var(--accent);
  line-height: 1;
  margin-bottom: 6px;
}
.portal-stat .lbl {
  font-size: 12px;
  color: var(--muted);
}
.portal-stat .delta { font-size: 11px; font-weight: 600; color: var(--success); margin-top: 4px; }

.portal-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.portal-table th {
  text-align: left;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.portal-table td {
  padding: 14px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
}
.portal-table tr:last-child td { border-bottom: none; }
.portal-table tr:hover td { background: color-mix(in srgb, var(--accent) 4%, transparent); }
.portal-table .status-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 600;
  padding: 3px 10px;
  border-radius: 999px;
}
.portal-table .status-pill.in-flight { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent); }
.portal-table .status-pill.delivered { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success); }
.portal-table .status-pill.pending { background: color-mix(in srgb, var(--warning) 14%, transparent); color: var(--warning); }
.portal-table .status-pill.complete { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success); }
.portal-table .status-pill::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor;
}

/* Status timeline (client portal) */
.status-timeline {
  display: flex;
  align-items: center;
  gap: 0;
  margin: 16px 0;
}
.status-timeline .node {
  display: flex; flex-direction: column; align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}
.status-timeline .node .dot {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--border);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
  color: var(--muted);
}
.status-timeline .node.done .dot {
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
  border-color: transparent;
  color: #FFFFFF;
}
.status-timeline .node.current .dot {
  background: var(--bg);
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 40%, transparent);
  animation: pulseDot 2.4s ease-in-out infinite;
}
.status-timeline .node .lbl {
  font-size: 11px; font-weight: 600;
  color: var(--muted);
  text-align: center;
  max-width: 100px;
}
.status-timeline .node.done .lbl, .status-timeline .node.current .lbl { color: var(--text); }
.status-timeline .bar {
  flex: 1;
  height: 2px;
  background: var(--border);
  margin: 0 6px;
  margin-bottom: 22px;
  border-radius: 2px;
}
.status-timeline .bar.done {
  background: linear-gradient(90deg, #2A8B83, #5FCFC8);
}

/* Messages thread */
.msg-thread {
  display: flex; flex-direction: column; gap: 12px;
  margin-top: 14px;
}
.msg-bubble {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  max-width: 88%;
  font-size: 13px;
  line-height: 1.55;
}
.msg-bubble.from-staff {
  align-self: flex-start;
  background: var(--surface-2);
  border-color: var(--border);
}
.msg-bubble.from-client {
  align-self: flex-end;
  background: color-mix(in srgb, var(--accent) 10%, var(--bg));
  border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
}
.msg-meta {
  display: flex; gap: 6px;
  font-size: 11px; color: var(--muted);
  margin-bottom: 4px;
}
.msg-meta strong { color: var(--text); }
.msg-composer {
  display: flex; gap: 10px; align-items: flex-end;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.msg-composer textarea {
  flex: 1;
  min-height: 56px;
  background: var(--bg);
  border: 1.5px solid var(--border);
  border-radius: 12px;
  padding: 12px 16px;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text);
  resize: vertical;
}
.msg-composer textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent); }
.msg-composer .btn-primary {
  display: inline-flex; align-items: center; gap: 6px;
  white-space: nowrap;
}

/* ============================================================
   PHOTOGRAPHY: added 12/09/2026
   ------------------------------------------------------------
   Capability-sheet photos only (Mike's clearance 12/09: every
   photo used in the three capability PDFs is cleared for web,
   supplier marks included). Anything from the wider Dropbox
   library still needs his per-photo word, see the site review
   page. These rules reuse the .has-photo pattern above; no new
   visual language, no new tokens.
   ============================================================ */

/* Split hero: copy left, one photo right. Stacks under 920px so the
   headline is never competing with an image on a phone. */
.page-hero.hero-split .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  gap: 44px;
  align-items: center;
}
.page-hero.hero-split .hero-copy { min-width: 0; }
.page-hero.hero-split .hero-copy .hero-actions { margin-bottom: 0; }
.page-hero.hero-split .hero-meta { grid-column: 1 / -1; margin-bottom: 0; }
@media (max-width: 920px) {
  .page-hero.hero-split .wrap { grid-template-columns: 1fr; gap: 30px; }
}

.hero-photo {
  margin: 0; min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface-2);
  box-shadow: var(--shadow);
}
.hero-photo img { display: block; width: 100%; height: auto; }
.hero-photo figcaption {
  font-size: 11px; line-height: 1.45; color: var(--muted);
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  background: var(--surface);
}

/* Photo band: one wide image with a caption, sitting between sections. */
.photo-band { margin: 0; }
.photo-band .frame {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface-2);
}
.photo-band img { display: block; width: 100%; height: auto; }
.photo-band figcaption { font-size: 12px; line-height: 1.5; color: var(--muted); margin-top: 10px; }

/* The featured-project photo is whatever shape the project photo happens to
   be - the MOA shot is portrait 1100x1396 in a landscape slot - so crop it
   rather than letting the column stretch to the full height of the image. */
/* .proj-art.has-photo forces aspect-ratio 2/1, which is right for the Projects
   grid where every card must line up. Here it was cropping the MOA photo to
   48% of its height - and that photo is PORTRAIT, of a barrel-vault skylight,
   so the arch that makes the shot was the half being cut. The feature slot
   takes the photograph's own shape instead: height follows the image, so a
   portrait, square or landscape frame all land uncropped. */
.feature-project .proj-art.has-photo {
  aspect-ratio: auto;
  align-self: start;
}
.feature-project .proj-art.has-photo img {
  width: 100%; height: auto; min-height: 0;
  max-height: 680px;
  object-fit: contain;
  display: block;
}

/* Service-line photo: in the left rail, under the label. */
.service-detail .rail-photo {
  margin: 16px 0 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-2);
}
.service-detail .rail-photo img { display: block; width: 100%; height: auto; }
@media (max-width: 720px) { .service-detail .rail-photo { max-width: 440px; } }

/* Supplier marks. The mono artwork is one flat #102222, so it is forced
   to a single tone per theme instead of shipping two colour variants. */
.supplier-marks {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 26px 44px;
  padding: 24px 0 2px;
  margin-top: 30px;
  border-top: 1px solid var(--border);
}
.supplier-marks .marks-label {
  width: 100%;
  font-size: 11px; font-weight: 700; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--muted);
}
.supplier-marks img { width: auto; filter: brightness(0); opacity: 0.6; }
[data-theme="dark"] .supplier-marks img { filter: brightness(0) invert(1); opacity: 0.72; }

/* Set by eye, not by one height rule (Mike, 12/09). Every mark was pinned to
   26px, which is a box measurement, not an optical one, Ventanas is a single
   line of caps and carried about three times Cortizo's visual mass at the same
   height. Each file was rendered at a reference height and its ink measured;
   these are the heights that equalise it, to the nearest pixel. Reynaers is
   pulled a little under its measured 33px because saturated colour reads
   heavier than tone. Re-measure with catalyst-site/design/ if a mark changes. */
.supplier-marks img.mark-cortizo  { height: 29px; }
.supplier-marks img.mark-reynaers { height: 33px; }
.supplier-marks img.mark-aluprof  { height: 27px; }
.supplier-marks img.mark-vinyltek { height: 25px; }
.supplier-marks img.mark-ventanas { height: 21px; }

/* Copy with a portrait photo alongside (Step Code page). */
.aside-photo { display: grid; grid-template-columns: minmax(0,1fr) 280px; gap: 36px; align-items: start; }
.aside-photo figure { margin: 0; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--surface-2); }
.aside-photo figure img { display: block; width: 100%; height: auto; }
.aside-photo figcaption { font-size: 11px; line-height: 1.45; color: var(--muted); padding: 10px 12px; border-top: 1px solid var(--border); background: var(--surface); }
@media (max-width: 860px) { .aside-photo { grid-template-columns: 1fr; } .aside-photo figure { max-width: 360px; } }

/* ============================================================
   ACCESSIBILITY FIXES: 12/09/2026 (browser-verified, this pass)
   ------------------------------------------------------------
   1. Unclassed links in page content were falling through to the
      browser default blue (#0000EE), which measures 1.6:1 on the
      navy ground: effectively invisible. Seen live on
      step-code.html (energystepcode.ca), privacy.html and
      terms.html.
   2. Footer legal links measured 39x12 and 32x12 CSS px, under the
      24x24 minimum (WCAG 2.5.8). Padding grows the target without
      moving anything on the page.
   ============================================================ */
main a:not([class]) {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
main a:not([class]):hover { color: var(--accent-hover); }

footer.site .bottom .legal a { display: inline-block; padding: 6px 2px; }

/* --- a11y, second pass (12/09/2026, browser-measured) ------------------
   1. The "below target" pill on the Step Code calculator measured 4.31:1
      at 11px bold: under the 4.5 AA floor. A lighter red clears it at
      5.09:1 on the pill and 5.96:1 on the page ground, and still reads as
      the warning colour.
   2. `select` was already in the iOS 16px block, but `.sc-field select`
      (specificity 0,1,1) beat it, so the calculator's two dropdowns still
      zoomed the viewport on focus. Same for the file input.
   3. Tap targets under 24x24 (WCAG 2.5.8): the topbar phone/email links,
      the inline phone CTA and the card-footer link. Inline links
      inside a sentence are exempt and are left alone. */
[data-theme="dark"] .sc-metric .m-status.below { color: #E08D84; }

@media (max-width: 767px) {
  .sc-field select,
  .sc-field input,
  input[type="file"] { font-size: 16px; }
}

.site-nav .util .left a { display: inline-block; padding: 4px 0; }
.phone-cta-inline { display: inline-flex; align-items: center; min-height: 24px; padding: 2px 0; }
.system-card .inline-link { display: inline-flex; align-items: center; min-height: 24px; }

/* --- Edit mode: the panel and the "these are your words" notice ---------
   Added 12/09/2026 alongside the edit-mode rewrite. The toolbar styles
   above are unchanged; these cover the two new surfaces. */
.edit-panel {
  position: fixed; right: 16px; top: 84px; z-index: 9998;
  width: 330px; max-height: 70vh; overflow-y: auto;
  background: #1D3447; border: 1px solid #2C4358; border-radius: 12px;
  padding: 14px 16px; box-shadow: 0 10px 34px rgba(0,0,0,.4);
  font-family: var(--font-body); color: #DCE6E7;
}
.edit-panel h6 { margin: 0 0 4px; font-size: 13px; font-weight: 700; letter-spacing: .02em; }
.edit-panel-help { margin: 0 0 12px; font-size: 11px; line-height: 1.5; color: var(--muted); }
.edit-panel-row { display: block; margin-bottom: 11px; }
.edit-panel-row span {
  display: block; font-size: 11px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: #5FCFC8; margin-bottom: 4px;
}
.edit-panel-row textarea {
  width: 100%; font-family: var(--font-body); font-size: 12px; line-height: 1.45;
  color: #DCE6E7; background: #14283A; border: 1px solid #2C4358;
  border-radius: 7px; padding: 7px 9px; resize: vertical;
}
.edit-panel-row textarea:focus { outline: 2px solid #5FCFC8; outline-offset: 1px; }
@media (max-width: 900px) { .edit-panel { position: static; width: auto; max-height: none; margin: 20px 16px 90px; } }

.edit-notice {
  position: fixed; left: 16px; bottom: 16px; z-index: 9998; max-width: 460px;
  background: #1D3447; color: #DCE6E7; border: 1px solid var(--warning);
  border-left-width: 3px; border-radius: 10px; padding: 12px 14px;
  font-family: var(--font-body); font-size: 12px; line-height: 1.5;
  box-shadow: 0 10px 34px rgba(0,0,0,.4);
}
.edit-notice strong { color: var(--warning); }
.edit-notice em { display: block; margin-top: 4px; color: var(--muted); font-style: normal; }
.edit-notice button {
  margin: 9px 7px 0 0; padding: 5px 11px; font-size: 12px; font-weight: 600;
  font-family: inherit; cursor: pointer; border-radius: 6px;
  background: #5FCFC8; color: #102222; border: 1px solid #5FCFC8;
}
.edit-notice button + button { background: transparent; color: #DCE6E7; border-color: #2C4358; }

/* ============================================================
   STEP CODE LAUNCHER + DRAWER: 12/09/2026
   ------------------------------------------------------------
   Mike: the calculator should be reachable from anywhere, not
   parked near the bottom of the home page. A pill bottom-right,
   opening the real calculator in a drawer.

   Kept clear of everything else that owns a corner: the audit
   banner is top-right, the edit notice bottom-left, and the edit
   toolbar takes the whole bottom edge, the pill lifts above it
   when edit mode is on.
   ============================================================ */
.sc-launch {
  position: fixed;
  right: 20px; bottom: 20px; z-index: 9000;
  display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 18px 12px 15px;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(12px);
  color: var(--accent);
  font-family: var(--font-body);
  font-size: 13px; font-weight: 600; letter-spacing: .01em;
  cursor: pointer;
  box-shadow: 0 4px 10px rgba(0,0,0,.14), 0 14px 34px rgba(0,0,0,.18);
  transition: transform 200ms cubic-bezier(.2,.7,.2,1), box-shadow 200ms, background 200ms, color 200ms;
}
.sc-launch svg { width: 20px; height: 20px; flex: none; }
.sc-launch:hover {
  transform: translateY(-2px);
  background: var(--accent); color: var(--accent-text);
  border-color: var(--accent);
  box-shadow: 0 6px 14px rgba(0,0,0,.18), 0 18px 42px rgba(0,0,0,.24);
}
.sc-launch:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
[data-edit-mode="on"] .sc-launch { bottom: 112px; }
@media (max-width: 620px) {
  .sc-launch { right: 14px; bottom: 14px; padding: 12px; gap: 0; }
  .sc-launch .sc-launch-label { display: none; }
}
@media print { .sc-launch, .sc-drawer { display: none !important; } }

html.sc-drawer-open, html.sc-drawer-open body { overflow: hidden; }

.sc-drawer { position: fixed; inset: 0; z-index: 9500; }
.sc-drawer[hidden] { display: none; }
.sc-drawer-scrim { position: absolute; inset: 0; background: rgba(6,16,26,.55); backdrop-filter: blur(12px);
  opacity: 0.55; }
.sc-drawer-panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(860px, 100%);
  display: flex; flex-direction: column;
  background: var(--bg);
  border-left: 1px solid var(--border);
  box-shadow: -20px 0 60px rgba(0,0,0,.35);
  animation: sc-slide 260ms cubic-bezier(.2,.7,.2,1);
}
@keyframes sc-slide { from { transform: translateX(26px); opacity: .6; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .sc-drawer-panel { animation: none; } }

.sc-drawer-head {
  display: flex; align-items: flex-start; gap: 16px;
  padding: 22px 24px 16px;
  border-bottom: 1px solid var(--border);
}
.sc-drawer-eyebrow {
  font-size: 11px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--accent); margin-bottom: 6px;
}
.sc-drawer-title {
  font-family: var(--font-heading); font-size: 24px; font-weight: 700;
  line-height: 1.15; letter-spacing: -.01em; margin: 0; max-width: 34ch;
}
.sc-drawer-close {
  margin-left: auto; flex: none;
  width: 38px; height: 38px; border-radius: 9px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--muted);
  border: 1px solid var(--border); cursor: pointer;
}
.sc-drawer-close svg { width: 15px; height: 15px; }
.sc-drawer-close:hover { color: var(--accent); border-color: var(--accent); }

.sc-drawer-body { flex: 1; overflow-y: auto; padding: 20px 24px; }
.sc-drawer-body .stepcode-calc { margin: 0; }
.sc-drawer-loading { color: var(--muted); font-size: 14px; }

.sc-drawer-foot {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 14px 24px 18px;
  border-top: 1px solid var(--border);
  background: var(--surface);
}
@media (max-width: 620px) {
  .sc-drawer-head { padding: 16px 16px 12px; }
  .sc-drawer-title { font-size: 20px; }
  .sc-drawer-body { padding: 14px 16px; }
  .sc-drawer-foot { padding: 12px 16px 16px; gap: 12px; }
}

/* `.inline-link` existed only as `.system-card-cta .inline-link`, so the same
   class used anywhere else fell through to the browser's default blue, 1.6:1
   on the navy ground. Same failure as the unclassed links fixed above, one
   scope further in. Defined globally here; the scoped rule still wins where
   it applies. (12/09/2026, caught in the Step Code drawer footer.) */
.inline-link {
  font-size: 13px; font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}
.inline-link:hover { color: var(--accent-hover); text-decoration: underline; }

/* The email address in the footer menu's Contact panel had no colour rule of
   its own, so it rendered in the browser's default blue on the navy ground, 
   the same 1.6:1 failure, in the one place the earlier sweep could not see it
   because the panel is closed until you open the menu. (12/09/2026.) */
footer.site .popover .info a { color: var(--accent); text-decoration: none; }
footer.site .popover .info a:hover { color: var(--accent-hover); text-decoration: underline; }

/* ============================================================
   STEP CODE: live result bar (narrow screens only), 12/09/2026
   ------------------------------------------------------------
   Measured on a 390x844 screen: stacked, the Performance panel
   sits ~1000px below the inputs, so changing a chip produced no
   visible feedback at all. This bar sticks under the nav and
   carries the verdict while the controls are still under your
   thumb. It is redundant from 901px up, where both panels are on
   screen together, so it is hidden there.
   ============================================================ */
.sc-live { display: none; }

@media (max-width: 900px) {
  .sc-live {
    display: flex; flex-direction: column; gap: 6px;
    position: fixed; top: var(--sc-sticky-top, 0px); left: 12px; right: 12px;
    z-index: 45;
    opacity: 0; transform: translateY(-8px); pointer-events: none;
    transition: opacity 180ms ease, transform 180ms ease;
    margin: 0;
    padding: 10px 14px 11px;
    background: color-mix(in srgb, var(--surface) 94%, transparent);
    backdrop-filter: blur(12px);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 18px rgba(0,0,0,.18);
  }
  .sc-live.is-on { opacity: 1; transform: none; }
  @media (prefers-reduced-motion: reduce) { .sc-live { transition: none; } }
  .sc-live-top { display: flex; align-items: center; gap: 10px; }
  .sc-live-ctx {
    font-size: 11px; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted);
  }
  .sc-live-status {
    margin-left: auto; text-align: right;
    font-size: 11px; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase;
    padding: 3px 9px; border-radius: 999px;
    background: color-mix(in srgb, var(--muted) 14%, transparent);
    color: var(--muted);
  }
  .sc-live-status.ok {
    color: var(--success);
    background: color-mix(in srgb, var(--success) 15%, transparent);
  }
  .sc-live-status.bad {
    color: var(--error);
    background: color-mix(in srgb, var(--error) 15%, transparent);
  }
  .sc-live-bottom { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
  .sc-live-u {
    font-size: 12px; color: var(--muted);
    font-variant-numeric: tabular-nums;
  }
  .sc-live-u strong {
    font-family: var(--font-heading);
    font-size: 28px; font-weight: 700; color: var(--text);
    margin-right: 3px;
  }
  .sc-live-tgt { margin-left: 6px; }
  .sc-live-chip {
    font-size: 11px; font-weight: 600;
    font-variant-numeric: tabular-nums;
    padding: 3px 9px; border-radius: 999px;
    background: color-mix(in srgb, var(--muted) 12%, transparent);
    color: var(--muted);
  }
  .sc-live-chip.ok { color: var(--success); background: color-mix(in srgb, var(--success) 13%, transparent); }
  .sc-live-chip.bad { color: var(--error); background: color-mix(in srgb, var(--error) 13%, transparent); }
}

/* The calculator's own source has always described its model as an
   approximation for architect-side scoping; the page said nothing, and the
   only qualification a visitor got was buried in terms of service. Mike's
   call 12/09: say it where the numbers are. */
.sc-caveat {
  font-size: 12px; line-height: 1.55; color: var(--muted);
  margin: 4px 0 14px;
  padding: 10px 12px;
  border-left: 2px solid var(--border);
  background: color-mix(in srgb, var(--surface-2) 34%, transparent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

/* ============================================================
   SITE SURVEY: the true next step, 12/09/2026
   ------------------------------------------------------------
   Replaces the mock scheduler on the quote success screen: ten
   hardcoded day chips carrying no month, a "Lock it in" button
   with no handler, and copy promising a confirmation email the
   Worker cannot send while FROM_EMAIL is the Resend sandbox.
   Reuses .phone-cta and .hint, which the sidebar cards already
   define: this block only supplies the frame around them.
   ============================================================ */
.survey-next {
  margin-top: 34px;
  padding: 22px 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  text-align: left;
}
.survey-next h2 {
  font-family: var(--font-heading);
  font-size: 22px;
  line-height: 1.2;
  margin-bottom: 8px;
}
.survey-next p {
  font-size: 14px;
  line-height: 1.6;
  color: var(--muted);
  margin: 0 0 16px;
  max-width: 56ch;
}
.survey-next .phone-cta {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-heading);
  font-size: 22px; font-weight: 700;
  color: var(--accent);
  text-decoration: none;
  transition: color 200ms;
}
.survey-next .phone-cta svg { width: 16px; height: 16px; flex: none; }
.survey-next .phone-cta:hover { color: var(--accent-hover); }
.survey-next .hint {
  font-size: 12px; line-height: 1.5; color: var(--muted);
  margin-top: 8px; max-width: 52ch;
}

/* ==========================================================================
   PROJECT SLIDESHOW (28/09/2026). One block for every photo area on the site;
   behaviour lives in slideshow.js, photos in projects.js. Two control sets
   that must never be confused:
     photo level   small round glass arrows ON the photo, dots at its foot
     project level large labelled pill buttons UNDER the photo, with the
                   project name, place and count between them
   The stage has a fixed shape (--ss-ratio) so nothing below it moves when
   the photo or the caption changes.
   ========================================================================== */
[data-slideshow].ss { position: relative; container-type: inline-size; margin: 0; min-width: 0; }
.ss .ss-stage {
  position: relative; overflow: hidden; isolation: isolate;
  aspect-ratio: var(--ss-ratio, 2 / 1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface-2);
  touch-action: pan-y;
  outline: none;
}
.ss .ss-stage:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 55%, transparent); }
.ss.ss-fill .ss-stage { aspect-ratio: auto; height: 100%; border: 0; border-radius: 0; }
/* Hosts that used to size themselves to their photo take the stage's shape. */
.proj-art.has-photo.ss, .proj-art.has-photo:has(> .ss-stage) { aspect-ratio: auto; padding: 0; min-height: 0; border: 0; background: none; overflow: visible; border-radius: 0; }
.hero-photo.ss { border: 0; box-shadow: none; background: none; overflow: visible; }

.ss .ss-layers { position: absolute; inset: 0; }
/* Mike 28/09: never crop a photo. The photo sits whole (contain) and a
   blurred, darkened copy fills the rest of the fixed frame, so every slot
   is full at a fixed size whatever the photo's shape. */
.ss .ss-slide {
  position: absolute; inset: 0; overflow: hidden;
  opacity: 0; transition: opacity 650ms ease;
}
.ss .ss-slide.is-on { opacity: 1; }
.ss .ss-slide.ss-now { transition: none; }
.ss .ss-bg {
  position: absolute; inset: -30px;
  background-size: cover; background-repeat: no-repeat;
  filter: blur(26px) brightness(0.5) saturate(1.1);
}
.ss .ss-stage img.ss-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  max-width: none; max-height: none; min-height: 0;
  object-fit: contain; display: block;
  transform: scale(1.02);
  transition: transform 5600ms ease-out;
}
.ss .ss-stage .ss-slide.is-on img.ss-img { transform: scale(1); }
/* Video slides fill the same frame the same way, whole, never cropped. */
.ss .ss-stage video.ss-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; display: block; background: transparent;
}
.ss .ss-play {
  position: absolute; left: 50%; top: 50%; z-index: 3;
  width: 64px; height: 64px; margin: -32px 0 0 -32px; padding: 0;
  display: grid; place-items: center; border-radius: 50%;
  border: 1px solid rgba(95, 207, 200, 0.6);
  background: rgba(20, 40, 58, 0.62);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0.55; backdrop-filter: blur(12px);
  color: #FFFFFF; cursor: pointer;
}
.ss .ss-play svg { width: 22px; height: 22px; margin-left: 3px; }
.ss .ss-play:hover { background: #2A8B83; }
.ss .ss-play:focus-visible { outline: 2px solid #5FCFC8; outline-offset: 3px; }

/* Timer bar: fills over the five seconds so the slideshow reads as one. */
.ss .ss-progress {
  position: absolute; left: 0; right: 0; top: 0; height: 3px; z-index: 4;
  background: linear-gradient(90deg, #2A8B83, #5FCFC8);
  transform: scaleX(0); transform-origin: left center;
  pointer-events: none;
}
.ss.ss-paused .ss-progress { opacity: 0.45; }

/* Caption and credit, over a soft shade at the foot of the photo. */
.ss .ss-cap {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 44px 18px 16px;
  font-size: 12.5px; line-height: 1.45; color: #EEF4F4;
  background: linear-gradient(transparent, rgba(10, 20, 30, 0.7));
  pointer-events: none;
}
/* Clamp on the inner line box: clamping the padded outer box lets the
   extra line spill into the padding, on top of the dots. */
.ss .ss-cap-inner { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.ss .ss-cap.is-empty { display: none; }
.ss .ss-cap-credit { opacity: 0.85; font-style: italic; }
.ss .ss-cap-text:not(:empty) + .ss-cap-credit:not(:empty)::before { content: "  \00b7  "; font-style: normal; }
.ss .ss-stage:has(.ss-dots:not([hidden])) .ss-cap { padding-bottom: 44px; }

/* Photo arrows: small, round, glass, on the photo. */
.ss .ss-photo-btn, .ss .ss-pause {
  position: absolute; z-index: 3;
  display: grid; place-items: center;
  width: 38px; height: 38px; padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(95, 207, 200, 0.45);
  background: rgba(20, 40, 58, 0.58);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0.55; backdrop-filter: blur(12px);
  color: #DCE6E7; cursor: pointer;
  transition: opacity 220ms, background-color 200ms, color 200ms;
}
.ss .ss-photo-btn svg { width: 15px; height: 15px; }
.ss .ss-photo-prev { left: 12px; top: calc(50% - 19px); }
.ss .ss-photo-next { right: 12px; top: calc(50% - 19px); }
.ss .ss-pause { top: 12px; right: 12px; width: 30px; height: 30px; }
.ss .ss-pause svg { width: 12px; height: 12px; }
.ss .ss-stage:hover .ss-photo-btn, .ss .ss-stage:hover .ss-pause,
.ss .ss-stage:focus-within .ss-photo-btn, .ss .ss-stage:focus-within .ss-pause,
.ss.ss-user-paused .ss-pause { opacity: 1; }
.ss .ss-photo-btn:hover, .ss .ss-pause:hover { background: #2A8B83; color: #FFFFFF; }
.ss .ss-photo-btn:focus-visible, .ss .ss-pause:focus-visible { opacity: 1; outline: 2px solid #5FCFC8; outline-offset: 2px; }
.ss [hidden] { display: none !important; }
@media (hover: none) { .ss .ss-photo-btn, .ss .ss-pause { opacity: 1; } }

/* Photo dots (or "3 / 12" past eight photos). */
.ss .ss-dots {
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%); z-index: 3;
  display: flex; align-items: center; gap: 2px;
  padding: 2px 6px; border-radius: 999px;
  background: rgba(20, 40, 58, 0.55);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0.55; backdrop-filter: blur(12px);
}
.ss .ss-dot {
  width: 22px; height: 22px; padding: 0; border: 0; background: none; cursor: pointer;
  display: grid; place-items: center;
}
.ss .ss-dot::before {
  content: ""; width: 7px; height: 7px; border-radius: 4px;
  background: rgba(220, 230, 231, 0.5);
  transition: width 260ms, background-color 260ms;
}
.ss .ss-dot.is-on::before { width: 18px; background: #5FCFC8; }
.ss .ss-dot:hover::before { background: #DCE6E7; }
.ss .ss-dot:focus-visible { outline: 2px solid #5FCFC8; outline-offset: -2px; border-radius: 999px; }
.ss .ss-dots-count {
  padding: 4px 6px; color: #EEF4F4;
  font: 600 11px/1 var(--font-body); letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}

/* Project bar: large labelled buttons under the photo. */
.ss-bar {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 14px;
  margin-top: 14px;
}
.ss-proj-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 10px 18px;
  border-radius: 999px;
  border: 1.5px solid color-mix(in srgb, var(--accent) 55%, var(--border));
  background: transparent; color: var(--accent);
  font: 600 11.5px/1 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase;
  cursor: pointer;
  transition: border-color 200ms, color 200ms, background-color 200ms, transform 200ms, box-shadow 260ms;
}
.ss-proj-btn svg { width: 18px; height: 18px; flex: 0 0 18px; transition: transform 220ms cubic-bezier(.2,.7,.2,1); }
.ss-proj-btn:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  transform: translateY(-1px);
  box-shadow: 0 6px 18px -8px color-mix(in srgb, var(--accent) 60%, transparent);
}
.ss-proj-prev:hover svg { transform: translateX(-2px); }
.ss-proj-next:hover svg { transform: translateX(2px); }
.ss-proj-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Project heading above the photo (Mike 28/09): full width, never cut off. */
.ss-head { margin: 0 0 12px; min-width: 0; }
.ss-head .ss-proj-name { white-space: normal; overflow: visible; text-overflow: clip; font-size: 24px; }
.ss-head .ss-proj-sys {
  margin-top: 4px;
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
}
/* One record per job: tagline, then system, then role and supplier, the same
   under every photo of the job. A job with no tagline gets no line (Mike 19/10/2026: no tagline means no line, no gap). */
.ss-head .ss-proj-tag {
  margin-top: 4px;
  font-family: var(--font-heading); font-style: italic; font-size: 17px; line-height: 1.35; color: var(--text);
}
.ss-head .ss-proj-tag:empty { display: none; }
.ss-head .ss-proj-role {
  margin-top: 3px; min-height: 1.45em;
  font-size: 12px; letter-spacing: 0.06em; font-weight: 600; color: var(--accent);
}
.ss-head .ss-proj-role .ss-sup-label { font-weight: 400; color: var(--muted); }
.ss-ph:empty::before { content: attr(data-ph); font-style: italic; font-weight: 400; opacity: 0.55; }
.ss-bar .ss-proj-count { justify-self: center; font-size: 13px; letter-spacing: 0.12em; margin: 0; }
.ss-proj-name {
  font-family: var(--font-heading); font-weight: 700;
  font-size: 22px; line-height: 1.15; letter-spacing: -0.005em; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ss-proj-meta {
  margin-top: 4px;
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ss-proj-count { color: var(--accent); font-weight: 700; font-variant-numeric: tabular-nums; margin-right: 10px; }

/* Narrow slots (phones, half-width columns): icon-only project buttons. */
@container (max-width: 560px) {
  .ss-bar { gap: 10px; }
  .ss-proj-btn { width: 44px; padding: 0; }
  .ss-proj-word { display: none; }
  .ss-proj-name { font-size: 18px; }
  .ss-proj-meta { letter-spacing: 0.1em; }
  .ss .ss-cap { font-size: 12px; padding: 36px 14px 12px; }
  .ss .ss-cap-inner { -webkit-line-clamp: 2; }
  .ss .ss-stage:has(.ss-dots:not([hidden])) .ss-cap { padding-bottom: 40px; }
  .ss .ss-photo-btn { width: 34px; height: 34px; }
  .ss .ss-photo-prev { left: 8px; top: calc(50% - 17px); }
  .ss .ss-photo-next { right: 8px; top: calc(50% - 17px); }
}
/* A bar placed in a story panel (Recent work): count only between the
   buttons, since the headline beside it already names the project. */
[data-ss-nav] .ss-bar { margin-top: 0; justify-content: start; grid-template-columns: auto auto auto; }
.ss-bar-count-only .ss-proj-name, .ss-bar-count-only .ss-proj-sys { display: none; }
.ss-bar-count-only .ss-proj-meta { margin: 0; }
.ss-bar-count-only .ss-proj-count { margin: 0; font-size: 13px; letter-spacing: 0.12em; }
.ss-bar-count-only .ss-proj-btn { width: 44px; padding: 0; }
.ss-bar-count-only .ss-proj-word { display: none; }
.feature-project .proj-nav { margin: 22px 0 18px; }
/* Feature layout (photo left, story right): a fixed frame. Column widths are
   set by the grid, never by the length of the story or the shape of the
   photo, so every project lands in the same 4:3 window. */
.feature-project:has(> .proj-art > .ss-stage) { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: start; }
@media (max-width: 920px) { .feature-project:has(> .proj-art > .ss-stage) { grid-template-columns: minmax(0, 1fr); } }

/* Story scroll + smaller headline (Mike 28/09): the story column runs longer
   than the photo on some projects and shorter on others, so the two never
   line up. Cap and scroll .proj-story only - the meta line and headline
   stay put, since those are the column's own title, not the mismatch. Only
   above the same 920px breakpoint the grid itself already stacks on: below
   it there is no photo column to line up against, and a capped scroll box
   is a poor mobile pattern (steals the swipe, hides copy), so the story
   runs full length there instead. */
.feature-project .proj-body h3 {
  font-size: clamp(22px, 2.6vw, 28px);
}
@media (min-width: 921px) {
  .feature-project .proj-story {
    max-height: 320px;
    overflow-y: auto;
    padding-right: 14px;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
    /* Fade reads "more below" only when there is more: the cover layer is
       pinned to the CONTENT's own bottom edge (background-attachment:
       local, so it scrolls with the text) while the fade layer is pinned
       to the BOX's visible bottom edge (background-attachment: scroll).
       The two coincide - and the opaque cover erases the fade - exactly
       when there is nothing left to scroll to, so a short story never
       shows a fade over empty space. */
    background:
      linear-gradient(var(--bg), var(--bg)) bottom / 100% 36px no-repeat local,
      linear-gradient(to bottom, transparent, var(--bg)) bottom / 100% 36px no-repeat scroll;
  }
  .feature-project .proj-story::-webkit-scrollbar { width: 6px; }
  .feature-project .proj-story::-webkit-scrollbar-track { background: transparent; }
  .feature-project .proj-story::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
  .feature-project .proj-story::-webkit-scrollbar-thumb:hover { background: var(--muted); }
}

/* Text that changes with the project fades rather than jumps. */
[data-ss-field] { transition: opacity 280ms ease; }
[data-ss-field].ss-fade-out { opacity: 0; }

/* Projects page: one big slideshow with the project's story under it
   (Mike, 01/10/2026). Centred to match the .ss-head above the photo. */
.projects-ss .ss-story {
  max-width: 68ch; margin: 22px auto 0; text-align: center;
  font-size: 17px; line-height: 1.65; color: var(--text);
}
.projects-ss .ss-story p { margin: 0 0 12px; }
.projects-ss .ss-story p:last-child { margin-bottom: 0; }
.projects-ss .ss-bar { max-width: 100%; }
@media (max-width: 720px) {
  .projects-ss .ss-story { margin-top: 18px; font-size: 16px; text-align: left; }
}

/* ---- Photo controls vs project controls (Mike, 05/10/2026) ----------------
   "The arrows for projects and photos sit right on top of one another, it's
   hard to know which is which." So the two sets differ in place, shape and
   words. PHOTO: round glass arrows inside the photo's left and right edges,
   dots (a plain count on a phone). PROJECT: its own row under the photo,
   "Project 2 of 12" with labelled rounded-rectangle Previous / Next project
   buttons. On a phone every control is a 44px tap target. */
.ss-bar .ss-proj-btn {
  border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.ss-bar .ss-proj-count { text-transform: uppercase; font-size: 12px; letter-spacing: 0.14em; white-space: nowrap; }
.ss .ss-dots-count-narrow { display: none; }
@media (max-width: 720px) {
  .ss-bar:not(.ss-bar-count-only) {
    grid-template-columns: 1fr 1fr; grid-template-areas: "count count" "prev next";
    row-gap: 10px; column-gap: 10px;
  }
  .ss-bar:not(.ss-bar-count-only) .ss-proj-count { grid-area: count; justify-self: center; }
  .ss-bar:not(.ss-bar-count-only) .ss-proj-prev { grid-area: prev; }
  .ss-bar:not(.ss-bar-count-only) .ss-proj-next { grid-area: next; }
  .ss-bar:not(.ss-bar-count-only) .ss-proj-btn { width: auto; padding: 10px 10px; min-height: 48px; font-size: 10.5px; letter-spacing: 0.05em; gap: 6px; white-space: nowrap; }
  .ss-bar:not(.ss-bar-count-only) .ss-proj-btn svg { width: 16px; height: 16px; flex-basis: 16px; }
  .ss-bar:not(.ss-bar-count-only) .ss-proj-word { display: inline; }
  .ss.ss-ratio-auto .ss-stage { aspect-ratio: 3 / 2; }
  .ss .ss-photo-btn, .ss .ss-pause { width: 44px; height: 44px; }
  .ss .ss-photo-btn svg { width: 17px; height: 17px; }
  .ss .ss-pause svg { width: 14px; height: 14px; }
  .ss .ss-photo-prev { left: 8px; top: calc(50% - 22px); }
  .ss .ss-photo-next { right: 8px; top: calc(50% - 22px); }
  .ss .ss-pause { top: 8px; right: 8px; }
  .ss .ss-dots .ss-dot { display: none; }
  .ss .ss-dots .ss-dots-count-narrow { display: inline; }
  .ss .ss-dots { pointer-events: none; padding: 2px 4px; }
  .ss .ss-stage:has(.ss-dots:not([hidden])) .ss-cap { padding-bottom: 40px; }
}
@media (max-width: 380px) {
  .ss-bar:not(.ss-bar-count-only) .ss-proj-btn { letter-spacing: 0.02em; padding: 10px 6px; }
}

/* SERVICES > New projects: the globe fills the whole supplier section
   (Mike, 05/10/2026, "apply the globe art in the background here"). Same
   artwork and same markup as the Home heading globe (the section is a copy of
   Home's), so Home is untouched: every rule below is scoped to the Services
   panel. The globe is lifted out of the heading and centred on the section,
   larger, and kept on a phone too. It sits behind the heading halo and the
   cards; the strokes are the existing theme-token tints, so light and dark
   need no separate rule. */
[data-section-id="systems-we-spec"] .wrap,
[data-section-id="systems-we-spec"] .strip-head.has-globe { position: static; }
[data-section-id="systems-we-spec"] .systems-grid { position: relative; z-index: 1; }
[data-section-id="systems-we-spec"] .head-globe {
  display: block;
  width: clamp(560px, 78vw, 1040px);
  top: 50%; left: 50%;
}
[data-section-id="systems-we-spec"] .head-globe .globe-rim { stroke: color-mix(in srgb, var(--text) 22%, transparent); }
[data-section-id="systems-we-spec"] .head-globe .globe-graticule { stroke: color-mix(in srgb, var(--text) 14%, transparent); }
[data-section-id="systems-we-spec"] .head-globe .globe-land {
  fill: color-mix(in srgb, var(--text) 11%, transparent);
  stroke: color-mix(in srgb, var(--text) 19%, transparent);
}
@media (max-width: 640px) {
  [data-section-id="systems-we-spec"] .head-globe { display: block; width: 150vw; top: 42%; }
}

.ss .ss-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .ss .ss-slide, .ss .ss-stage img.ss-img { transition: none; transform: none; }
  .ss .ss-progress { display: none; }
  [data-ss-field] { transition: none; }
  .ss-proj-btn, .ss-proj-btn svg { transition: none; }
}

/* ==========================================================================
   INSTAGRAM FEED (28/09/2026, redesigned 28/09/2026). A branded profile
   header (avatar, bio, stats) plus a reel player: one post large on a
   stage, the rest in a scrollable playlist beside it. Proxied through
   catalyst-instagram-worker so the site never talks to Instagram directly.
   Behaviour lives in instagram.js. The section starts `hidden` in the HTML
   and instagram.js only reveals it once posts load, so there is no
   empty-state layout to style here.

   .ig-card/.ig-stage-frame get `isolation: isolate` and a translateZ(0)
   compositing layer, same for the <video> itself: a known Chrome bug
   paints nothing for some videos inside a rounded, clipped ancestor in a
   scroll container unless the video gets its own GPU layer.
   ========================================================================== */

/* ---- Profile header: a designed banner, not a thin strip. A mosaic of
   the visitor's own reel covers sits behind a fixed dark teal/navy wash
   (fixed hex, not theme tokens - the wash is always dark so the banner's
   text is always light-on-dark regardless of site theme) so the avatar,
   handle, bio, stats and capability chips all read on one on-brand
   surface instead of floating in an empty card. ---- */
[data-instagram-feed] .ig-profile-card {
  position: relative; overflow: hidden; isolation: isolate;
  margin-top: 28px; border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: #14283A; /* shows for an instant before the mosaic decodes */
}
[data-instagram-feed] .ig-banner-mosaic {
  position: absolute; inset: 0; z-index: 0;
  display: flex; width: 100%; height: 100%;
}
[data-instagram-feed] .ig-banner-mosaic img {
  flex: 1 1 0; min-width: 0; height: 100%;
  object-fit: cover; display: block;
  filter: blur(3px) brightness(0.5) saturate(1.05);
}
[data-instagram-feed] .ig-banner-wash {
  position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(0deg, rgba(9, 20, 28, 0.55) 0%, rgba(9, 20, 28, 0.32) 60%, rgba(9, 20, 28, 0.2) 100%),
    linear-gradient(115deg, rgba(20, 40, 58, 0.82) 0%, rgba(20, 62, 66, 0.7) 45%, rgba(42, 139, 131, 0.55) 100%);
}
[data-instagram-feed] .ig-profile-main {
  position: relative; z-index: 2;
  display: flex; align-items: flex-start; gap: 24px;
  padding: 30px 32px;
}
[data-instagram-feed] .ig-avatar { position: relative; flex: none; width: 104px; height: 104px; }
[data-instagram-feed] .ig-avatar-ring {
  position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from 0deg, #2A8B83, #5FCFC8, #2A8B83, #5FCFC8, #2A8B83);
  animation: ig-ring-spin 7s linear infinite;
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
}
@keyframes ig-ring-spin { to { transform: rotate(360deg); } }
[data-instagram-feed] .ig-avatar-inner {
  position: absolute; inset: 6px; border-radius: 50%; overflow: hidden;
  background: #1D3447; display: grid; place-items: center;
}
[data-instagram-feed] .ig-avatar-img { width: 100%; height: 100%; object-fit: cover; display: block; }
[data-instagram-feed] .ig-avatar-logo { display: block; width: 62%; height: 62%; position: relative; }
[data-instagram-feed] .ig-avatar-logo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; filter: brightness(0) invert(1); opacity: 0.92; }

[data-instagram-feed] .ig-profile-body { flex: 1 1 auto; min-width: 0; }
[data-instagram-feed] .ig-profile-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px 24px; flex-wrap: wrap; }
[data-instagram-feed] .ig-profile-names { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
[data-instagram-feed] .ig-profile-handle {
  font: 700 24px/1.2 var(--font-heading); color: #EAF3F1; letter-spacing: .01em;
  overflow-wrap: anywhere;
}
[data-instagram-feed] .ig-profile-handle .amp { font-style: italic; color: #5FCFC8; }
[data-instagram-feed] .ig-profile-name { font: 500 13.5px/1.3 var(--font-body); color: rgba(234, 243, 241, 0.72); }
[data-instagram-feed] .ig-profile-actions { display: flex; align-items: center; gap: 16px; flex: none; flex-wrap: wrap; }
[data-instagram-feed] .ig-viewall {
  display: inline-flex; align-items: center; gap: 5px;
  font: 600 12.5px/1 var(--font-body); letter-spacing: .01em;
  color: #5FCFC8; text-decoration: none; white-space: nowrap;
}
[data-instagram-feed] .ig-viewall svg { width: 13px; height: 13px; }
[data-instagram-feed] .ig-viewall:hover { text-decoration: underline; }
[data-instagram-feed] .ig-viewall:focus-visible { outline: 2px solid #5FCFC8; outline-offset: 3px; }
[data-instagram-feed] .ig-profile-bio { margin: 12px 0 0; font: 400 14.5px/1.55 var(--font-body); color: rgba(234, 243, 241, 0.92); max-width: 56ch; }
[data-instagram-feed] .ig-profile-stats { display: flex; gap: 28px; margin-top: 18px; flex-wrap: wrap; }
[data-instagram-feed] .ig-stat { display: flex; flex-direction: column; gap: 2px; }
[data-instagram-feed] .ig-stat-num { font: 700 21px/1 var(--font-heading); color: #5FCFC8; font-variant-numeric: tabular-nums; }
[data-instagram-feed] .ig-stat-label { font: 600 10.5px/1 var(--font-body); letter-spacing: .12em; text-transform: uppercase; color: rgba(234, 243, 241, 0.66); }
[data-instagram-feed] .ig-profile-chips { display: flex; gap: 8px; margin-top: 18px; flex-wrap: wrap; }
[data-instagram-feed] .ig-chip {
  padding: 6px 13px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.26);
  color: #EAF3F1; font: 600 11.5px/1 var(--font-body); letter-spacing: .02em;
}

/* Faint corner mark: logoMark() returns a <span> wrapping an <img>; the
   wrapper carries the position/size/opacity, the fallback chain inside it
   just needs to fill that box. */
[data-instagram-feed] .ig-profile-watermark {
  position: absolute; right: -18px; bottom: -26px; z-index: 1;
  width: 150px; height: 150px; opacity: 0.08; pointer-events: none;
}
[data-instagram-feed] .ig-profile-watermark img { width: 100%; height: 100%; object-fit: contain; filter: brightness(0) invert(1); }

@media (max-width: 640px) {
  [data-instagram-feed] .ig-profile-main { flex-direction: column; align-items: center; text-align: center; padding: 26px 22px; gap: 16px; }
  [data-instagram-feed] .ig-profile-top { flex-direction: column; align-items: center; }
  [data-instagram-feed] .ig-profile-names { align-items: center; }
  [data-instagram-feed] .ig-profile-stats,
  [data-instagram-feed] .ig-profile-chips { justify-content: center; }
}

[data-instagram-feed] .ig-follow {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  padding: 10px 20px; border-radius: 999px;
  border: 1.5px solid rgba(255, 255, 255, 0.55);
  color: #EAF3F1; text-decoration: none;
  font: 600 13.5px/1 var(--font-body); letter-spacing: .01em;
  transition: background 220ms, color 220ms, border-color 220ms, transform 220ms;
}
[data-instagram-feed] .ig-follow svg { width: 16px; height: 16px; }
[data-instagram-feed] .ig-follow:hover { background: linear-gradient(135deg, #2A8B83, #5FCFC8); color: #FFFFFF; border-color: transparent; transform: translateY(-1px); }
[data-instagram-feed] .ig-follow:focus-visible { outline: 2px solid #5FCFC8; outline-offset: 3px; }

/* ---- Subhead: "Latest reels" + updated stamp ---- */
[data-instagram-feed] .ig-subhead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px 20px; flex-wrap: wrap;
  margin-top: 22px;
}
[data-instagram-feed] .ig-eyebrow { font: 700 11px/1 var(--font-body); letter-spacing: .16em; text-transform: uppercase; color: var(--accent); }
[data-instagram-feed] .ig-updated { font: 500 12px/1 var(--font-body); color: var(--muted); }

/* ---- Stage: one post at a time, full width - the same visual family as
   the project photo slideshow (see PROJECT SLIDESHOW above: .ss-photo-btn,
   .ss-dots). Prev/next glass arrows on the frame, dots at its foot (or a
   "3 / 12" count past eight posts, same threshold as the slideshow). ---- */
[data-instagram-feed] .ig-stage { position: relative; margin-top: 12px; outline: none; border-radius: var(--radius-lg); }
[data-instagram-feed] .ig-stage:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 55%, transparent); }
[data-instagram-feed] .ig-stage-frame {
  position: relative; isolation: isolate; transform: translateZ(0);
  overflow: hidden; border-radius: var(--radius-lg);
  border: 1px solid var(--border); background: var(--surface-2);
  width: 100%; height: min(78vh, 780px);
}
[data-instagram-feed] .ig-stage-bg {
  position: absolute; inset: -40px; z-index: 0;
  background-size: cover; background-position: center; background-repeat: no-repeat;
  filter: blur(34px) brightness(0.5) saturate(1.1);
}
[data-instagram-feed] .ig-stage-cover,
[data-instagram-feed] .ig-stage-video {
  position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%;
  object-fit: contain; display: block; background: transparent;
}
[data-instagram-feed] .ig-stage-video { transform: translateZ(0); z-index: 2; }
[data-instagram-feed] .ig-stage-play {
  position: absolute; left: 50%; top: 50%; z-index: 3;
  width: 68px; height: 68px; margin: -34px 0 0 -34px; padding: 0;
  display: grid; place-items: center; border-radius: 50%;
  border: 1px solid rgba(95, 207, 200, 0.6);
  background: rgba(20, 40, 58, 0.62);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0.55; backdrop-filter: blur(12px);
  color: #FFFFFF; cursor: pointer;
  transition: background 200ms, transform 200ms;
}
[data-instagram-feed] .ig-stage-play svg { width: 26px; height: 26px; margin-left: 0; }
[data-instagram-feed] .ig-stage-play:hover { background: #2A8B83; transform: scale(1.06); }
[data-instagram-feed] .ig-stage-play:focus-visible { outline: 2px solid #5FCFC8; outline-offset: 3px; }
[data-instagram-feed] .ig-stage-watch {
  position: absolute; left: 50%; top: 50%; z-index: 3; transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: 8px;
  padding: 12px 20px; border-radius: 999px; white-space: nowrap;
  background: rgba(20, 40, 58, 0.72); color: #FFFFFF; text-decoration: none;
  border: 1px solid rgba(95, 207, 200, 0.55);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0.55; backdrop-filter: blur(12px);
  font: 600 13px/1 var(--font-body);
  transition: background 200ms, transform 200ms;
}
[data-instagram-feed] .ig-stage-watch svg { width: 15px; height: 15px; }
[data-instagram-feed] .ig-stage-watch:hover { background: #2A8B83; transform: translate(-50%, -50%) scale(1.04); }
[data-instagram-feed] .ig-stage-watch:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* instagram.js toggles these four via the `hidden` attribute; each one also
   sets its own `display` for layout, which otherwise out-specifies the
   browser's default `[hidden] { display: none }` rule and leaves a
   "hidden" element visible. Restate it here, scoped, so hidden always wins. */
[data-instagram-feed] .ig-stage-cover[hidden],
[data-instagram-feed] .ig-stage-video[hidden],
[data-instagram-feed] .ig-stage-play[hidden],
[data-instagram-feed] .ig-stage-watch[hidden] { display: none; }

[data-instagram-feed] .ig-stage-meta { padding: 14px 4px 0; }
[data-instagram-feed] .ig-stage-date { font: 700 10px/1 var(--font-body); letter-spacing: .16em; text-transform: uppercase; color: var(--accent); }
[data-instagram-feed] .ig-stage-caption { margin: 8px 0 0; font: 400 14px/1.6 var(--font-body); color: var(--text); max-width: 70ch; }
[data-instagram-feed] .ig-stage-link {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 10px;
  font: 600 12px/1 var(--font-body); letter-spacing: .02em;
  color: var(--accent); text-decoration: none;
}
[data-instagram-feed] .ig-stage-link svg { width: 13px; height: 13px; }
[data-instagram-feed] .ig-stage-link:hover { text-decoration: underline; }
[data-instagram-feed] .ig-stage-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Engagement row: Like, Comment, Share (Mike 28/09/2026). */
[data-instagram-feed] .ig-engage { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 12px 0 10px; }
[data-instagram-feed] .ig-engage-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border-radius: 999px; cursor: pointer;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  color: var(--text); text-decoration: none;
  font: 600 13px/1 var(--font-body);
  transition: background 200ms, border-color 200ms, color 200ms, transform 200ms;
}
[data-instagram-feed] .ig-engage-btn svg { width: 17px; height: 17px; color: var(--accent); transition: transform 260ms cubic-bezier(.2,.7,.2,1), color 200ms, fill 200ms; }
[data-instagram-feed] .ig-engage-btn:hover { background: linear-gradient(135deg, #2A8B83, #5FCFC8); border-color: transparent; color: #FFFFFF; transform: translateY(-1px); }
[data-instagram-feed] .ig-engage-btn:hover svg { color: #FFFFFF; }
[data-instagram-feed] .ig-engage-like:hover svg { transform: scale(1.18); }
[data-instagram-feed] .ig-engage-like.is-liked svg { fill: #E0556A; color: #E0556A; transform: scale(1.12); }
[data-instagram-feed] .ig-engage-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
[data-instagram-feed] .ig-engage-note { font: 600 12px/1 var(--font-body); color: var(--accent); }
[data-instagram-feed][data-variant="compact"] .ig-engage-btn { padding: 7px 12px; font-size: 12px; }
@media (prefers-reduced-motion: reduce) {
  [data-instagram-feed] .ig-engage-btn, [data-instagram-feed] .ig-engage-btn svg { transition: none; }
}

/* Prev/next: small round glass arrows on the frame, same recipe as the
   slideshow's .ss-photo-btn (size, colors, blur, hover-to-reveal). */
[data-instagram-feed] .ig-nav-btn {
  position: absolute; z-index: 3; top: calc(50% - 19px);
  display: grid; place-items: center;
  width: 38px; height: 38px; padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(95, 207, 200, 0.45);
  background: rgba(20, 40, 58, 0.58);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0.55; backdrop-filter: blur(12px);
  color: #DCE6E7; cursor: pointer;
  transition: opacity 220ms, background-color 200ms, color 200ms;
}
[data-instagram-feed] .ig-nav-btn svg { width: 15px; height: 15px; }
[data-instagram-feed] .ig-nav-prev { left: 12px; }
[data-instagram-feed] .ig-nav-next { right: 12px; }
[data-instagram-feed] .ig-stage:hover .ig-nav-btn,
[data-instagram-feed] .ig-stage:focus-within .ig-nav-btn { opacity: 1; }
[data-instagram-feed] .ig-nav-btn:hover { background: #2A8B83; color: #FFFFFF; }
[data-instagram-feed] .ig-nav-btn:focus-visible { opacity: 1; outline: 2px solid #5FCFC8; outline-offset: 2px; }
@media (hover: none) { [data-instagram-feed] .ig-nav-btn { opacity: 1; } }

/* Dots (or "3 / 12" past eight posts), same recipe as the slideshow's
   .ss-dots / .ss-dots-count. */
[data-instagram-feed] .ig-dots {
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%); z-index: 3;
  display: flex; align-items: center; gap: 2px;
  padding: 2px 6px; border-radius: 999px;
  background: rgba(20, 40, 58, 0.55);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0.55; backdrop-filter: blur(12px);
}
[data-instagram-feed] .ig-dot {
  width: 22px; height: 22px; padding: 0; border: 0; background: none; cursor: pointer;
  display: grid; place-items: center;
}
[data-instagram-feed] .ig-dot::before {
  content: ""; width: 7px; height: 7px; border-radius: 4px;
  background: rgba(220, 230, 231, 0.5);
  transition: width 260ms, background-color 260ms;
}
[data-instagram-feed] .ig-dot.is-on::before { width: 18px; background: #5FCFC8; }
[data-instagram-feed] .ig-dot:hover::before { background: #DCE6E7; }
[data-instagram-feed] .ig-dot:focus-visible { outline: 2px solid #5FCFC8; outline-offset: -2px; border-radius: 999px; }
[data-instagram-feed] .ig-dots-count {
  padding: 4px 6px; color: #EEF4F4;
  font: 600 11px/1 var(--font-body); letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 760px) {
  [data-instagram-feed] .ig-stage-frame { width: 100%; height: min(70vh, 620px); }
}

/* ---- Compact variant (Connect page): a tidy smaller version of the same
   banner - avatar, handle, Follow, still on the mosaic wash, without the
   bio/stats/chips a narrow column has no room for - and a shorter stage. ---- */
[data-instagram-feed][data-variant="compact"] .ig-viewall { display: none; }
/* Compact header (Connect), Mike 28/09/2026: one tight row that pops.
   Avatar, handle and Follow sit on one line at every width, the bio is a
   single line under the handle, and the card gets a teal edge glow and a
   solid Follow so it reads as the lead item on the page. These selectors
   outrank the max-width 640px stacking rule above. */
[data-instagram-feed][data-variant="compact"] .ig-profile-main { flex-direction: row; align-items: center; text-align: left; padding: 14px 16px; gap: 14px; }
[data-instagram-feed][data-variant="compact"] .ig-avatar { width: 56px; height: 56px; }
[data-instagram-feed][data-variant="compact"] .ig-avatar-inner { inset: 4px; }
[data-instagram-feed][data-variant="compact"] .ig-profile-top { flex-direction: row; align-items: center; justify-content: space-between; flex-wrap: nowrap; gap: 12px; }
[data-instagram-feed][data-variant="compact"] .ig-profile-names { align-items: flex-start; min-width: 0; }
[data-instagram-feed][data-variant="compact"] .ig-profile-handle { font-size: clamp(14.5px, 4.1vw, 17px); overflow-wrap: normal; white-space: nowrap; }
[data-instagram-feed][data-variant="compact"] .ig-profile-bio { margin-top: 5px; font-size: 13px; line-height: 1.4; color: rgba(234, 243, 241, 0.82); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
[data-instagram-feed][data-variant="compact"] .ig-follow { background: linear-gradient(135deg, #2A8B83, #5FCFC8); border-color: transparent; color: #FFFFFF; box-shadow: 0 6px 16px -6px rgba(95, 207, 200, 0.55); }
[data-instagram-feed][data-variant="compact"] .ig-follow:hover { filter: saturate(1.15); }
[data-instagram-feed][data-variant="compact"] .ig-profile-name { display: block; font: 600 10.5px/1.3 var(--font-body); letter-spacing: .12em; text-transform: uppercase; color: #5FCFC8; overflow-wrap: normal; margin-top: 2px; }
[data-instagram-feed] .ig-profile-name .amp { font-family: var(--font-heading); font-style: italic; font-weight: 500; font-size: 1.35em; line-height: 0; color: #5FCFC8; text-transform: none; padding: 0 1px; }
[data-instagram-feed][data-variant="compact"] .ig-avatar-ring { box-shadow: 0 0 0 3px rgba(95, 207, 200, 0.22), 0 0 18px rgba(95, 207, 200, 0.45); }
[data-instagram-feed][data-variant="compact"] .ig-profile-followers { display: block; margin-top: 3px; font: 500 12px/1.3 var(--font-body); color: rgba(234, 243, 241, 0.78); white-space: nowrap; }
[data-instagram-feed][data-variant="compact"] .ig-profile-followers strong { font-weight: 700; color: #FFFFFF; }
[data-instagram-feed][data-variant="compact"] .ig-profile-card { border-color: rgba(95, 207, 200, 0.45); box-shadow: 0 0 0 1px rgba(95, 207, 200, 0.12), 0 14px 34px -18px rgba(95, 207, 200, 0.55); }
@media (max-width: 380px) {
  [data-instagram-feed][data-variant="compact"] .ig-follow span, [data-instagram-feed][data-variant="compact"] .ig-follow-label { display: none; }
  [data-instagram-feed][data-variant="compact"] .ig-follow { padding: 8px; }
}
[data-instagram-feed][data-variant="compact"] .ig-stage-frame { height: min(56vh, 420px); }
[data-instagram-feed][data-variant="compact"] .ig-stage-meta { padding-top: 8px; }
[data-instagram-feed][data-variant="compact"] .ig-stage-caption { font-size: 12.5px; -webkit-line-clamp: 2; display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; }
[data-instagram-feed][data-variant="compact"] .ig-nav-btn { width: 32px; height: 32px; top: calc(50% - 16px); }
[data-instagram-feed][data-variant="compact"] .ig-nav-btn svg { width: 13px; height: 13px; }
@media (max-width: 760px) {
  [data-instagram-feed][data-variant="compact"] .ig-stage-frame { height: min(46vh, 360px); }
}

@media (prefers-reduced-motion: reduce) {
  [data-instagram-feed] .ig-avatar-ring { animation: none; }
  [data-instagram-feed] .ig-nav-btn,
  [data-instagram-feed] .ig-dot,
  [data-instagram-feed] .ig-follow,
  [data-instagram-feed] .ig-viewall,
  [data-instagram-feed] .ig-stage-play,
  [data-instagram-feed] .ig-stage-watch { transition: none; }
}


/* Aftercare plan cards under the service band (services.html). Reuses
   .three-up and .how-card; these rules only place them. */
.service-plans { margin-top: 36px; }
.service-plans > .label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
}
.service-plans .how-card .label {
  /* Tab straddling the card's top border, so it can never collide with the
     tagline or any card content. Solid surface fill hides the border line
     behind the text. */
  position: absolute; top: 0; right: 28px; margin: 0;
  transform: translateY(-50%);
  padding: 3px 10px;
  background: var(--surface);
  border-radius: 999px;
  font-size: 11px; font-weight: 700; line-height: 1.2;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent);
}
.service-plans .how-card.recommended {
  border-color: color-mix(in srgb, var(--accent) 60%, var(--border));
}
.service-plans .how-card h3 { padding-right: 0; }
.service-plans .plans-note {
  font-size: 14px; color: var(--muted); line-height: 1.55;
  max-width: 72ch; margin: 18px 0 0;
}
.service-plans .service-band-note {
  font-size: 14px; color: var(--muted); line-height: 1.55;
  max-width: 72ch; margin: 0 0 14px;
}

/* Wordmark ampersand: ONE treatment, every page, header and footer.
   Copied from the /connect lockup, where it was first set right. Italic
   accent teal, 1.5em, nudged onto the baseline. font-weight is pinned to 500
   because the header and footer wordmarks run at 700 and the italic face is
   500 (on /connect the wordmark itself is 500, so it inherited this). */
.wm .amp {
  font-style: italic;
  font-weight: 500;
  font-synthesis: none;
  color: var(--accent);
  font-size: 1.5em;
  line-height: 0;
  vertical-align: -.08em;
  padding: 0 3px;
}

/* ============================================================
   BROCHURE DRAWER: designed dropdown (the brand .dropdown.field)
   Replaces the native <select>, whose open list cannot be styled.
   Options are role=option (not <a>), so they restate the
   .dropdown-menu a item treatment from styles.css; the field
   toggle and menu panel come from styles.css unchanged.
   ============================================================ */
.system-card .drawer-picker .brochure-dd { flex: 1 1 auto; min-width: 0; width: auto; }
.system-card .brochure-dd .dropdown-toggle { min-height: 44px; }
.system-card .brochure-dd .dropdown-toggle [data-current-text] { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.system-card .brochure-dd .dropdown-menu { max-height: 240px; overflow-y: auto; outline: none; }
.system-card .brochure-dd .dd-option {
  display: block; padding: 10px 14px; min-height: 44px; box-sizing: border-box;
  font-size: 14px; color: var(--text); border-radius: 8px; cursor: pointer; position: relative;
  transition: color 200ms, background 220ms, padding-left 240ms cubic-bezier(.2,.7,.2,1);
}
.system-card .brochure-dd .dd-option::before {
  content: ""; position: absolute; left: 6px; top: 50%; width: 0; height: 1.5px;
  background: var(--accent); transform: translateY(-50%);
  transition: width 240ms cubic-bezier(.2,.7,.2,1);
}
.system-card .brochure-dd .dd-option:hover,
.system-card .brochure-dd .dd-option.active {
  color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); padding-left: 22px;
}
.system-card .brochure-dd .dd-option:hover::before,
.system-card .brochure-dd .dd-option.active::before { width: 10px; }
.system-card .brochure-dd .dd-option[aria-selected="true"] { font-weight: 600; }
.system-card .brochure-dd .dropdown-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The card is a transformed (stacking-context) box, so an open menu would paint
   under the next card; lift the card that owns the open menu. */
.system-card:has(.brochure-dd.open) { position: relative; z-index: 30; }

/* About hero: the Kawneer photo sits behind the headline and intro (Mike,
   01/10/2026, variant B). Scoped to .about-hero so the figure-style
   .hero-photo used by split heroes elsewhere is untouched. */
.page-hero.about-hero { position: relative; overflow: hidden; isolation: isolate; }
.about-hero .hero-photo {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  margin: 0; border: 0; border-radius: 0; box-shadow: none;
  background: url("img/about/hero-kawneer-1600.jpg") 55% 40% / cover no-repeat;
  opacity: .28;
  -webkit-mask-image: linear-gradient(to bottom, #000 38%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 38%, transparent 100%);
}
.about-hero h1 { margin-bottom: 22px; }
.about-hero .lede { margin-bottom: 0; }
/* Credit sits outside the masked photo layer, so it never dims with it. */
.about-hero .hero-credit {
  margin: 28px 0 0; max-width: 560px;
  font-size: 11px; line-height: 1.45; color: var(--muted);
}
@media (min-width: 921px) {
  .about-hero .hero-credit {
    position: absolute; right: 32px; bottom: 14px;
    margin: 0; text-align: right;
  }
}
/* ============================================================
   SERVICES TABS: "New projects" / "Service" (Mike, canvas comment 01/10/2026)
   No tab or segmented component existed in styles.css, site.css or
   brand/web-components.html, so this is built from existing tokens only:
   the pill radius (999px) and border/surface of .topbar .toggle, the
   .btn-primary gradient and 14px/600 type for the selected tab.
   The tablist ships `hidden` and site.js reveals it, so without JS both
   panels simply show stacked.
   ============================================================ */
.svc-tabs {
  display: inline-flex; gap: 4px; padding: 4px;
  margin-top: 4px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
}
.svc-tabs[hidden] { display: none; }
.svc-tab {
  appearance: none; cursor: pointer;
  min-height: 44px; padding: 0 28px;
  border: 0; border-radius: 999px; background: transparent;
  font-family: var(--font-body); font-size: 14px; font-weight: 600; letter-spacing: 0.01em;
  color: var(--text);
  transition: background 200ms, color 200ms, box-shadow 200ms;
}
.svc-tab:hover { background: var(--surface-2); }
.svc-tab[aria-selected="true"] {
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%);
  color: #FFFFFF;
  box-shadow: 0 2px 4px rgba(16,34,34,0.08),
              0 6px 18px -6px color-mix(in srgb, var(--accent) 55%, transparent);
}
.svc-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.svc-panel[hidden] { display: none; }
@media (max-width: 720px) {
  .svc-tabs { display: flex; width: 100%; }
  .svc-tab { flex: 1 1 0; padding: 0 12px; }
}


/* ============================================================
   Services page, Service tab (#panel-service). Design direction
   "A + B's failure strip", chosen by Mike 01/10/2026.
   Everything is scoped to #panel-service. The inverted card and the
   filled pill use panel-local tokens: --svc-inv-* is the opposite
   surface to the page (light card on the dark theme, dark card on
   the light theme); --svc-pane-* is the Glass Pane gradient.
   The solid filled pill (.svc-fill) is allowed on this tab only,
   for "Book the baseline assessment" (Mike, 01/10/2026). Everywhere
   else it stays reserved for the top bar's Request a quote.
   ============================================================ */
#panel-service {
  --svc-inv-bg: #1D3447; --svc-inv-text: #DCE6E7; --svc-inv-muted: #8A9CA7;
  --svc-inv-accent: #5FCFC8; --svc-inv-border: #2C4358;
  --svc-pane-1: #2A8B83; --svc-pane-2: #5FCFC8;
  --svc-lift: 0 2px 6px rgba(16,34,34,0.08), 0 28px 60px -22px rgba(16,34,34,0.4);
  --radius-band: 18px;
}
[data-theme="dark"] #panel-service {
  --svc-inv-bg: #D7E5E0; --svc-inv-text: #102222; --svc-inv-muted: #4F6361;
  --svc-inv-accent: #1F6E68; --svc-inv-border: #A6BCB5;
  --svc-lift: 0 2px 6px rgba(0,0,0,0.35), 0 28px 64px -22px color-mix(in srgb, var(--accent) 45%, transparent);
}
#panel-service h2,
#panel-service h3,
#panel-service .svc-amt { font-variant-numeric: lining-nums; }
#panel-service .svc-eyebrow {
  font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent); margin: 0 0 12px;
}
#panel-service .svc-intro h2 {
  font-family: var(--font-heading); font-weight: 700; font-size: 44px; line-height: 1.08;
  letter-spacing: -0.015em; margin: 0 0 16px; text-wrap: balance;
}
#panel-service .svc-lede { color: var(--muted); font-size: 17px; max-width: 56ch; margin: 0; }
#panel-service .svc-note { color: var(--muted); font-size: 14px; line-height: 1.55; max-width: 72ch; margin: 0 auto; text-align: center; }
#panel-service .svc-note a { color: var(--accent); }

/* Intro and assurance box */
#panel-service .svc-intro { display: grid; grid-template-columns: 1fr 1.15fr; gap: 48px; align-items: start; }
#panel-service .svc-assure {
  background: var(--surface); border: 1.5px solid var(--border); border-radius: var(--radius-lg);
  padding: 20px 22px; font-size: 15px;
}
#panel-service .svc-assure b {
  display: block; font-family: var(--font-heading); font-size: 22px; font-weight: 700;
  margin-bottom: 4px; color: var(--text);
}
#panel-service .svc-assure span { color: var(--muted); }

/* B's failure strip */
#panel-service .svc-wear { margin-top: 64px; }
#panel-service .svc-wear-h {
  font-family: var(--font-heading); font-weight: 700; font-size: 34px; line-height: 1.1;
  letter-spacing: -0.01em; margin: 0 0 8px; text-wrap: balance;
}
#panel-service .svc-fails { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: 32px; }
#panel-service .svc-fail {
  background: var(--surface); border: 1.5px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow); display: flex; flex-direction: column; overflow: hidden;
}
@supports (grid-template-rows: subgrid) {
  #panel-service .svc-fails { grid-template-rows: auto auto; }
  #panel-service .svc-fail { display: grid; grid-row: span 2; grid-template-rows: subgrid; row-gap: 0; }
  #panel-service .svc-fail .svc-fix { margin-top: 0; }
}
#panel-service .svc-fail-in { padding: 26px 26px 22px; display: grid; gap: 12px; align-content: start; text-align: center; }
#panel-service .svc-dg { width: 64px; height: 48px; justify-self: center; color: var(--accent); }
#panel-service .svc-fail h3 { font-family: var(--font-heading); font-weight: 700; font-size: 26px; line-height: 1.1; margin: 0; }
#panel-service .svc-fail p { margin: 0; font-size: 15px; color: var(--muted); }
#panel-service .svc-fix {
  margin-top: auto; padding: 16px 26px; font-size: 14px;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  border-top: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
}
#panel-service .svc-fix b {
  display: block; margin-bottom: 2px; color: var(--accent);
  font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase;
}
#panel-service .svc-warr {
  margin-top: 28px; background: var(--svc-inv-bg); color: var(--svc-inv-text);
  border-radius: var(--radius-band); padding: 40px 48px; box-shadow: var(--svc-lift);
  display: grid; grid-template-columns: 1fr auto; gap: 32px; align-items: center;
}
#panel-service .svc-warr q {
  display: block; max-width: 30ch; quotes: none; text-wrap: balance;
  font-family: var(--font-heading); font-size: 32px; line-height: 1.2; font-weight: 600;
}
#panel-service .svc-warr q em { color: var(--svc-inv-accent); font-style: italic; }
#panel-service .svc-src { margin: 0; font-size: 14px; color: var(--svc-inv-muted); max-width: 32ch; }

/* A's plan cards */
#panel-service .svc-plans {
  display: grid; grid-template-columns: 1fr 1.1fr 1fr; gap: 20px; align-items: stretch; margin-top: 64px;
}
/* Plan cards in direction C's membership-card styling (Mike, 01/10/2026):
   cut top-right corner, bottom-left chamfer, label row with the logo mark,
   tagline under the name, faint watermark. Colours are today's tokens:
   Estate/Essential on --surface, Signature on the inverted --svc-inv-* surface. */
#panel-service .svc-plan {
  --mtr: 34px; --mbl: 17px;
  --svc-ink: var(--text); --svc-soft: var(--muted); --svc-mark: var(--accent); --svc-line: var(--border);
  --svc-ds: drop-shadow(0 1px 2px rgba(16,34,34,0.10)) drop-shadow(0 10px 18px rgba(16,34,34,0.10));
  position: relative; display: flex; flex-direction: column;
  filter: var(--svc-ds);
}
[data-theme="dark"] #panel-service .svc-plan {
  --svc-ds: drop-shadow(0 2px 4px rgba(0,0,0,0.35)) drop-shadow(0 18px 30px color-mix(in srgb, var(--accent) 14%, transparent));
}
#panel-service .svc-frame {
  flex: 1; display: flex; padding: 1.5px;
  background: linear-gradient(160deg, color-mix(in srgb, var(--accent) 60%, var(--border)) 0%, var(--border) 60%, color-mix(in srgb, var(--accent) 35%, var(--border)) 100%);
  clip-path: polygon(0 0, calc(100% - var(--mtr)) 0, 100% var(--mtr), 100% 100%, var(--mbl) 100%, 0 calc(100% - var(--mbl)));
}
#panel-service .svc-card {
  --mtr: calc(var(--mtr-o, 34px) - 0.6px); --mbl: calc(var(--mbl-o, 17px) - 0.6px);
  position: relative; overflow: hidden; flex: 1; display: flex; flex-direction: column;
  padding: 30px 28px 26px; color: var(--svc-ink);
  background: radial-gradient(120% 80% at 100% 0%, color-mix(in srgb, var(--svc-mark) 12%, transparent) 0%, transparent 55%), var(--surface);
  clip-path: polygon(0 0, calc(100% - var(--mtr)) 0, 100% var(--mtr), 100% 100%, var(--mbl) 100%, 0 calc(100% - var(--mbl)));
}
#panel-service .svc-card::after {
  content: ""; position: absolute; right: -26px; bottom: -30px; width: 200px; height: 170px;
  background: var(--svc-mark); opacity: 0.07; pointer-events: none;
  -webkit-mask: url("catalyst-logo-light.png") center / contain no-repeat;
  mask: url("catalyst-logo-light.png") center / contain no-repeat;
}
#panel-service .svc-row { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding-right: 14px; }
#panel-service .svc-lbl { font-size: 11px; font-weight: 700; letter-spacing: 0.22em; text-transform: uppercase; color: var(--svc-mark); }
#panel-service .svc-mk {
  width: 36px; height: 31px; flex: none; background: var(--svc-mark);
  -webkit-mask: url("catalyst-logo-light.png") center / contain no-repeat;
  mask: url("catalyst-logo-light.png") center / contain no-repeat;
}
#panel-service .svc-card > div:not(.svc-row):not(.svc-price) { display: flex; flex-direction: column-reverse; margin: 20px 0 18px; }
#panel-service .svc-plan h3 {
  font-family: var(--font-heading); font-weight: 700; font-size: 46px; line-height: 1.05; letter-spacing: 0.02em;
  margin: 0 0 2px; font-variant-numeric: lining-nums;
}
#panel-service .svc-tl { font-family: var(--font-heading); font-style: italic; font-size: 19px; color: var(--svc-soft); margin: 0; }
#panel-service .svc-price {
  display: grid; gap: 2px; padding: 14px 0; margin-bottom: 20px;
  border-top: 1px solid var(--svc-line); border-bottom: 1px solid var(--svc-line);
}
#panel-service .svc-amt {
  font-family: var(--font-heading); font-weight: 700; font-size: 44px; line-height: 1;
  font-variant-numeric: lining-nums tabular-nums;
}
#panel-service .svc-per { font-size: 14px; color: var(--svc-soft); }
#panel-service .svc-ex {
  font-size: 11px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--svc-soft);
}
#panel-service .svc-checks { list-style: none; margin: 0 0 20px; padding: 0; display: grid; gap: 10px; font-size: 15px; }
#panel-service .svc-checks li { display: grid; grid-template-columns: 18px 1fr; gap: 10px; align-items: start; }
#panel-service .svc-checks svg { width: 16px; height: 16px; margin-top: 4px; color: var(--svc-mark); }
#panel-service .svc-perks { font-size: 14px; color: var(--svc-soft); margin: auto 0 0; }
#panel-service .svc-rec {
  --svc-ink: var(--svc-inv-text); --svc-soft: var(--svc-inv-muted); --svc-mark: var(--svc-inv-accent); --svc-line: var(--svc-inv-border);
  --svc-ds: drop-shadow(0 2px 4px rgba(16,34,34,0.12)) drop-shadow(0 24px 30px rgba(16,34,34,0.30));
  transform: translateY(-18px);
}
[data-theme="dark"] #panel-service .svc-rec {
  --svc-ds: drop-shadow(0 2px 4px rgba(0,0,0,0.35)) drop-shadow(0 24px 34px color-mix(in srgb, var(--accent) 38%, transparent));
}
#panel-service .svc-rec .svc-frame { background: var(--svc-inv-bg); }
#panel-service .svc-rec .svc-card { padding: 38px 32px 30px; background: var(--svc-inv-bg); --mtr-o: 34px; }
#panel-service .svc-rec .svc-amt { font-size: 54px; }
#panel-service .svc-rec h3 { font-size: 52px; }
#panel-service .svc-badge {
  position: absolute; z-index: 2; top: 0; left: 32px; transform: translateY(-50%);
  background: var(--accent); color: var(--accent-text);
  font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase;
  padding: 6px 14px; border-radius: 999px;
}

/* The one solid filled Glass Pane pill outside the top bar (this tab only) */
#panel-service .svc-fill {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 48px; margin-top: auto; padding: 14px 20px; border-radius: 999px;
  background: linear-gradient(135deg, var(--svc-pane-1) 0%, var(--svc-pane-2) 100%);
  color: #FFFFFF; font-weight: 600; font-size: 15px; letter-spacing: 0.01em;
  text-decoration: none; text-align: center; line-height: 1.25; max-width: 100%; box-sizing: border-box;
  box-shadow: 0 2px 4px rgba(16,34,34,0.08),
              0 6px 18px -6px color-mix(in srgb, var(--svc-pane-2) 55%, transparent);
  transition: transform 220ms cubic-bezier(.2,.7,.2,1), box-shadow 280ms cubic-bezier(.2,.7,.2,1);
}
#panel-service .svc-fill:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(16,34,34,0.10),
              0 14px 36px -10px color-mix(in srgb, var(--svc-pane-2) 75%, transparent);
}
#panel-service .svc-fill:focus-visible { outline: 2px solid var(--svc-inv-accent); outline-offset: 3px; }
#panel-service .svc-fill svg { width: 16px; height: 16px; flex: none; }
@media (max-width: 420px) { #panel-service .svc-fill { padding: 12px 16px; gap: 8px; } }
#panel-service .svc-base .svc-fill { align-self: center; margin-top: 0; }
@media (prefers-reduced-motion: reduce) {
  #panel-service .svc-fill { transition: none; }
  #panel-service .svc-fill:hover { transform: none; }
}

/* Baseline bar, notes, and what we service */
#panel-service .svc-base {
  margin-top: 36px; display: grid; grid-template-columns: auto 1fr auto; gap: 32px; align-items: center;
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  border: 1.5px solid color-mix(in srgb, var(--accent) 30%, var(--border));
  border-radius: var(--radius-band); padding: 30px 36px;
}
#panel-service .svc-base .svc-eyebrow { margin-bottom: 6px; }
#panel-service .svc-base h3 { font-family: var(--font-heading); font-weight: 700; font-size: 28px; line-height: 1.08; margin: 0; }
#panel-service .svc-base-lead { display: flex; align-items: center; gap: 20px; padding-right: 32px; max-width: 340px; border-right: 1px solid var(--border); }
#panel-service .svc-base-num { font-family: 'Inter', var(--font-body); font-weight: 600; font-size: 84px; line-height: 0.8; color: var(--accent); font-variant-numeric: lining-nums; }
#panel-service .svc-base-sub { font-family: var(--font-heading); font-style: italic; font-size: 20px; color: var(--muted); margin: 4px 0 0; }
#panel-service .svc-base-pairs { display: grid; grid-template-columns: 1fr; gap: 18px; }
#panel-service .svc-base-pair { display: grid; grid-template-columns: 34px 1fr; gap: 12px; align-items: start; }
#panel-service .svc-base-ico { width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
#panel-service .svc-base-ico svg { width: 18px; height: 18px; }
#panel-service .svc-base-pair b { display: block; font-size: 15px; line-height: 1.3; }
#panel-service .svc-base-pair div span { display: block; font-size: 14px; color: var(--muted); margin-top: 2px; }
#panel-service .svc-plans + .svc-base + .svc-note,
#panel-service .svc-base + .svc-note { margin-top: 18px; }
#panel-service .svc-assure .svc-list { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
#panel-service .svc-list-lbl {
  font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--accent); margin-bottom: 2px;
}
#panel-service .svc-list ul {
  list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0 24px; font-size: 14px; line-height: 1.35;
}
#panel-service .svc-list li {
  position: relative; padding: 7px 0 7px 16px; color: var(--text);
  border-bottom: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
}
#panel-service .svc-list li::before {
  content: ""; position: absolute; left: 0; top: 16px; width: 8px; height: 1.5px; background: var(--accent);
}

@media (min-width: 921px) and (max-width: 1180px) {
  #panel-service .svc-base { grid-template-columns: 1fr auto; row-gap: 24px; }
  #panel-service .svc-base .svc-fill { justify-self: end; align-self: center; grid-column: 2; grid-row: 1 / 3; }
  #panel-service .svc-base-lead { max-width: none; border-right: 0; padding-right: 0; }
  #panel-service .svc-base-pairs { grid-column: 1; grid-row: 2; grid-template-columns: 1fr 1fr; gap: 28px; padding-top: 22px; border-top: 1px solid var(--border); }
}

@media (max-width: 920px) {
  #panel-service .svc-intro,
  #panel-service .svc-fails,
  #panel-service .svc-plans,
  #panel-service .svc-base,
  #panel-service .svc-warr { grid-template-columns: 1fr; }
  #panel-service .svc-intro { gap: 24px; }
  #panel-service .svc-plans { gap: 28px; margin-top: 40px; }
  #panel-service .svc-rec { transform: none; order: -1; }
  #panel-service .svc-plans { gap: 34px; }
  #panel-service .svc-base { gap: 20px; padding: 26px 22px; }
  #panel-service .svc-base-lead { max-width: none; padding: 0 0 20px; border-right: 0; border-bottom: 1px solid var(--border); }
  #panel-service .svc-base .svc-fill { width: 100%; }
  #panel-service .svc-warr { gap: 14px; padding: 28px 22px; }
}
@media (max-width: 600px) {
  #panel-service .svc-intro h2 { font-size: 32px; }
  #panel-service .svc-wear-h { font-size: 28px; }
  #panel-service .svc-lede { font-size: 16px; }
  #panel-service .svc-warr q { font-size: 25px; }
  #panel-service .svc-list ul { grid-template-columns: 1fr; }
  #panel-service .svc-fill { width: 100%; }
  #panel-service .svc-plan { --mtr: 26px; --mbl: 13px; }
  #panel-service .svc-card { --mtr-o: 26px; --mbl-o: 13px; padding: 26px 22px 24px; }
  #panel-service .svc-rec .svc-card { --mtr-o: 26px; padding: 30px 22px 24px; }
  #panel-service .svc-plan h3 { font-size: 44px; }
  #panel-service .svc-rec h3 { font-size: 48px; }
  #panel-service .svc-card::after { width: 170px; height: 145px; }
}

/* ============================================================
   HOME, PHONE: CAROUSELS (Mike 01/10/2026, "to condense the mobile home
   page, lets put the supplier cards, and the four steps on respective
   carousels with themed scrolling arrows").
   600px and below only: the supplier grid is already one column there.
   Native scroll-snap does the swiping; site.js adds the arrows and the
   count, reusing the slideshow's round project buttons (.ss-proj-btn) and
   count (.ss-proj-count). Above 600px nothing here applies.
   ============================================================ */
.cx-bar { display: none; }
@media (max-width: 600px) {
  .four-up.how-2x2,
  .systems-grid {
    display: flex;
    grid-template-columns: none;
    flex-wrap: nowrap;
    align-items: flex-start;
    gap: 12px;
    position: relative;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    /* room so the hover lift and shadow are not clipped by the scroller */
    padding: 6px 7% 14px;
    margin: -6px 0 -14px;
    /* active card sits centred: equal 7% margins each side (Mike 05/10/2026) */
    scroll-padding-inline: 7%;
  }
  .four-up.how-2x2::-webkit-scrollbar,
  .systems-grid::-webkit-scrollbar { display: none; }
  .four-up.how-2x2 { align-items: stretch; }
  .four-up.how-2x2 > .how-card,
  .systems-grid > .system-card {
    flex: 0 0 100%; /* of the scroller's content box, which is 86% of its width */
    min-width: 0;
    scroll-snap-align: center;
    scroll-snap-stop: always;
  }
  /* undo the subgrid rows: each card is its own column of content */
  .systems-grid > .system-card {
    display: flex;
    flex-direction: column;
    grid-row: auto;
    margin-bottom: 0;
  }
  .systems-grid > .system-card .tap-hint { margin-top: auto; align-self: auto; }
  .systems-grid > .system-card .drawer { align-self: auto; }
  .systems-grid > .system-card:hover { transform: none; }
  /* The scroller clips anything that hangs outside it, so the open brochure
     list sits in the card instead of floating over it. */
  .systems-grid .brochure-dd .dropdown-menu {
    display: none;
    position: static;
    min-width: 0;
    width: 100%;
    margin-top: 8px;
    transform: none;
    transition: none;
  }
  .systems-grid .brochure-dd.open .dropdown-menu { display: block; visibility: visible; opacity: 1; }
  .systems-grid .drawer-picker { flex-wrap: wrap; }
  .systems-grid .drawer-picker .brochure-dd { flex: 1 1 100%; }

  .cx-bar {
    display: grid;
    grid-template-columns: auto auto auto;
    justify-content: center;
    align-items: center;
    gap: 14px;
    margin-top: 20px;
  }
  .cx-bar .ss-proj-btn[disabled] {
    opacity: 0.38;
    cursor: default;
    transform: none;
    box-shadow: none;
    background: transparent;
    border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  }
  .cx-bar .ss-proj-count { margin: 0; min-width: 4.5ch; text-align: center; }
}
@media (max-width: 600px) and (prefers-reduced-motion: no-preference) {
  .four-up.how-2x2, .systems-grid, #panel-service .svc-plans, #panel-service .svc-fails { scroll-behavior: smooth; }
}

/* ============================================================
   SERVICES, PHONE: aftercare plans and "what wears first" cards as the
   same swipe carousel as Home (Mike 21/10/2026, "turn these cards into a
   carousel with the recommended being the middle option default" and "same
   carousel treatment"). 600px and below only; site.js adds the arrows and
   count (.cx-bar) and opens on Signature (.svc-rec) or the first card.
   Desktop and tablet layouts are untouched.
   ============================================================ */
@media (max-width: 600px) {
  #panel-service .svc-plans,
  #panel-service .svc-fails {
    display: flex;
    grid-template-columns: none;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 12px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    position: relative;
    padding: 10px 7% 30px;
    scroll-padding-inline: 7%;
  }
  #panel-service .svc-plans { margin: 30px 0 -16px; }
  #panel-service .svc-fails { margin: 26px 0 -16px; }
  #panel-service .svc-plans::-webkit-scrollbar,
  #panel-service .svc-fails::-webkit-scrollbar { display: none; }
  #panel-service .svc-plans > .svc-plan,
  #panel-service .svc-fails > .svc-fail {
    flex: 0 0 100%;
    min-width: 0;
    scroll-snap-align: center;
    scroll-snap-stop: always;
  }
  /* DOM order is Essential, Signature, Estate: keep it, so Signature is the middle card */
  #panel-service .svc-plans > .svc-rec { order: 0; }
  #panel-service .svc-fails > .svc-fail { display: flex; grid-row: auto; }
  #panel-service .svc-fails > .svc-fail .svc-fail-in { flex: 1; }
}

/* ============================================================
   STEP CODE, PHONE: suggested-products list and the three "why the
   U-value matters" cards as the same swipe carousel as Home and Services
   (Mike 21/10/2026, canvas comments, "carousel"). 600px and below only;
   site.js adds the arrows and count (.cx-bar) and opens on the first card
   (for the products, the top-ranked suggestion; re-run after each
   calculation). Desktop and tablet layouts are untouched.
   ============================================================ */
.cx-bar[hidden] { display: none !important; }
@media (max-width: 600px) {
  .sc-three[data-cx-on],
  [data-recs][data-cx-on] {
    display: flex;
    grid-template-columns: none;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 12px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    position: relative;
    padding: 6px 7% 14px;
    margin-bottom: -14px;
    scroll-padding-inline: 7%;
  }
  .sc-three[data-cx-on]::-webkit-scrollbar,
  [data-recs][data-cx-on]::-webkit-scrollbar { display: none; }
  .sc-three[data-cx-on] > .sc-card,
  [data-recs][data-cx-on] > .sc-rec {
    flex: 0 0 100%;
    min-width: 0;
    margin-bottom: 0;
    scroll-snap-align: center;
    scroll-snap-stop: always;
  }
  [data-recs][data-cx-on] > .sc-rec:hover { transform: none; }
  /* the panel is a grid item; without this the scroller's full width props it open past the screen */
  .stepcode-calc > .sc-panel { min-width: 0; }
}
@media (max-width: 600px) and (prefers-reduced-motion: no-preference) {
  .sc-three[data-cx-on], [data-recs][data-cx-on] { scroll-behavior: smooth; }
}

/* ============================================================
   ABOUT: "A word from Mike" chat icon (Mike, canvas comment 01/10/2026).
   The old bottom-of-page prose block collapses into a round teal chat icon
   up by the intro paragraphs; the words open in a card anchored under it.
   Button look is .social-icon (round, accent tint, accent-hover glyph);
   card look is the footer .popover (12px radius, same shadow + top highlight,
   lift-and-fade) on theme tokens so it reads in light and dark.
   ============================================================ */
.about-body { position: relative; }
/* Mike, 01/10/2026: no text label, no shift. The wrapper takes no space; the icon
   and card are placed against .about-body. Desktop: icon in the gutter right of
   the 56ch column, level with the first paragraph. Phone: no gutter, so it floats
   at the top-right corner above the first line, over the strip's top padding. */
.mike-chat { position: static; }
.mike-chat-btn {
  position: absolute; top: 4px; left: calc(50% + 28ch + 20px); z-index: 24;
  display: inline-flex; align-items: center; gap: 0;
  padding: 0; background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 600; letter-spacing: 0.02em;
  color: var(--accent-hover);
}
.mike-chat-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--accent) 38%, var(--border));
  color: var(--accent-hover);
  transition: transform 220ms cubic-bezier(.2,.7,.2,1), background 220ms, border-color 220ms, color 220ms;
}
.mike-chat-btn:hover .mike-chat-ico,
.mike-chat-btn[aria-expanded="true"] .mike-chat-ico {
  background: var(--accent); border-color: var(--accent); color: var(--accent-text);
  transform: translateY(-2px);
}
.mike-chat-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 999px; }
.mike-chat-card {
  position: absolute; top: 60px; width: min(420px, 100%); right: calc(50% - 28ch - 64px); z-index: 25;
  box-sizing: border-box;
  background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--accent) 38%, var(--border));
  border-radius: 12px;
  padding: 22px 24px 20px;
  box-shadow:
    0 24px 48px -16px rgba(20, 40, 58, 0.45),
    inset 0 1px 0 0 color-mix(in srgb, var(--accent) 24%, transparent);
  animation: mike-chat-in 240ms cubic-bezier(.2,.7,.2,1);
}
.mike-chat-card[hidden] { display: none; }
.mike-chat-card::before {
  content: ""; position: absolute; top: -7px; right: 17px;
  width: 12px; height: 12px; transform: rotate(45deg);
  background: var(--surface);
  border-left: 1px solid color-mix(in srgb, var(--accent) 38%, var(--border));
  border-top: 1px solid color-mix(in srgb, var(--accent) 38%, var(--border));
}
.mike-chat-card h2 { margin: 0 0 12px; padding-right: 36px; text-align: left; }
.mike-chat-close {
  position: absolute; top: 10px; right: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 999px; cursor: pointer;
  background: transparent; border: 1.5px solid transparent; color: var(--accent-hover);
}
.mike-chat-close:hover { border-color: color-mix(in srgb, var(--accent) 38%, var(--border)); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.mike-chat-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@keyframes mike-chat-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes mike-chat-pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  100% { box-shadow: 0 0 0 16px color-mix(in srgb, var(--accent) 0%, transparent); }
}
@media (prefers-reduced-motion: no-preference) {
  .mike-chat-ico { animation: mike-chat-pulse 1.6s ease-out 0.8s 2; }
}
@media (prefers-reduced-motion: reduce) {
  .mike-chat-card { animation: none; }
  .mike-chat-ico { transition: none; }
}
@media (max-width: 860px) {
  .mike-chat-btn { top: -54px; left: auto; right: 0; }
  .mike-chat-card { top: -2px; left: 0; right: 0; width: auto; }
}
@media (max-width: 600px) {
  .mike-chat-card { padding: 20px 18px 18px; }
}

/* ABOUT body prose card (Mike, canvas comment 01/10/2026, "go with C, tighter
   padding"). The story column widens from 56ch to a 70ch measure and sits on a
   faint raised card; the closing line becomes a Cormorant sign-off under a
   hairline. Scoped to .about-story so Privacy, Terms and the other .prose
   blocks keep their 56ch measure. The chat icon below follows the card edge. */
.about-body > .prose.about-story {
  box-sizing: border-box;
  max-width: calc(70ch + 64px);
  padding: 24px 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow, 0 1px 2px rgba(0,0,0,.12));
}
.about-story p.signoff {
  margin-top: 22px; padding-top: 18px;
  border-top: 1px solid var(--border);
  font-family: var(--font-heading);
  font-size: 25px; line-height: 1.3; font-weight: 600; letter-spacing: -0.005em;
}
.about-story p.about-lead {
  font-family: var(--font-heading);
  font-size: 23px; line-height: 1.35; font-weight: 600; letter-spacing: -0.005em;
}
.about-body .mike-chat-btn { font-size: 16px; font-weight: 400; left: calc(50% + 35ch + 32px + 20px); top: 24px; }
.about-body .mike-chat-card { top: 80px; right: calc(50% - 35ch - 32px - 64px); }
@media (max-width: 980px) {
  .about-body .mike-chat-btn { top: -54px; left: auto; right: 0; }
  .about-body .mike-chat-card { top: -2px; left: 0; right: 0; }
}
@media (max-width: 600px) {
  /* Phones: the card bleeds to the screen edges (cancels the 32px page gutter),
     keeps its top and bottom hairlines, drops the side border and radius, and
     uses 16px side padding so the text keeps its full 326px+ measure. */
  .about-body > .prose.about-story {
    margin-left: -32px; margin-right: -32px;
    padding: 20px 16px;
    border-left: 0; border-right: 0; border-radius: 0;
  }
  .about-story p.signoff { font-size: 21px; margin-top: 18px; padding-top: 16px; }
  .about-story p.about-lead { font-size: 21px; }
}

/* ABOUT "Where we work": BC reach map (Mike, canvas comment 01/10/2026, "build it").
   Real BC outline (Natural Earth 1:50m admin-1, public domain, BC Albers),
   Maple Ridge as home, 36 arcs out to towns across the province, pulses of
   light travelling along them. The SVG in about.html is static output of
   scripts/bc-reach/build.mjs, no runtime projection or JS. Styled to match the
   globe backdrop: color-mix on --text for land and graticule, --accent for the
   dots and arcs, so light and dark need no separate rule. Decorative only
   (aria-hidden). The card matches the About story card above it. */
.about-body > .prose.bc-where {
  box-sizing: border-box;
  max-width: calc(70ch + 64px);
  margin-top: 28px;
  padding: 24px 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow, 0 1px 2px rgba(0,0,0,.12));
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 50%);
  column-gap: 32px;
  align-items: center;
}
.page-host .about-body > .prose.bc-where > h2 { text-align: left; grid-column: 1; grid-row: 1; align-self: end; }
.about-body > .prose.bc-where > p { grid-column: 1; grid-row: 2; align-self: start; margin-bottom: 0; }
.bc-reach-wrap { grid-column: 2; grid-row: 1 / span 2; }
.bc-reach { width: 100%; height: auto; display: block; }
.bc-reach .bc-land { fill: color-mix(in srgb, var(--text) 9%, transparent); stroke: color-mix(in srgb, var(--text) 18%, transparent); stroke-width: 1.5; stroke-linejoin: round; }
.bc-reach .bc-graticule { fill: none; stroke: color-mix(in srgb, var(--text) 11%, transparent); stroke-width: .75; }
.bc-reach .bc-dots circle { fill: var(--accent); }
.bc-reach .bc-arcs path { fill: none; stroke-width: 1; stroke-linecap: round; }
.bc-reach .ga { stop-color: var(--accent); stop-opacity: .55; }
.bc-reach .gb { stop-color: var(--accent); stop-opacity: .12; }
.bc-reach .bc-pulse { fill: none; stroke: var(--accent); stroke-width: 1.9; stroke-linecap: round; stroke-dasharray: 6 900; stroke-dashoffset: 7; opacity: .95; animation-name: bc-pulse; animation-timing-function: linear; animation-iteration-count: infinite; }
@keyframes bc-pulse { from { stroke-dashoffset: 7; } to { stroke-dashoffset: var(--end); } }
.bc-reach .bc-glow { fill: var(--accent); opacity: 0; transform-box: fill-box; transform-origin: center; animation-name: bc-glow; animation-timing-function: ease-out; animation-iteration-count: infinite; }
@keyframes bc-glow { 0% { opacity: .55; transform: scale(1); } 5% { opacity: 0; transform: scale(2.6); } 100% { opacity: 0; transform: scale(2.6); } }
.bc-reach .bc-home-ring { fill: none; stroke: var(--accent); stroke-width: 1.5; }
.bc-reach .bc-home-dot { fill: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .bc-reach .bc-pulse, .bc-reach .bc-glow { display: none; animation: none; }
}
@media (max-width: 700px) {
  .about-body > .prose.bc-where { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  .bc-reach-wrap { grid-column: 1; grid-row: 3; max-width: 300px; width: 100%; margin: 20px auto 0; }
}
@media (max-width: 600px) {
  .about-body > .prose.bc-where {
    margin-left: -32px; margin-right: -32px;
    padding: 20px 16px;
    border-left: 0; border-right: 0; border-radius: 0;
  }
}

/* ============================================================
   Services configurations viewer (Services > New projects, "01 . Configurations").
   Option E, "spec-sheet viewer", chosen by Mike 05/10/2026: one large looping stage icon
   with tag, name and a one-line description, previous / next and a counter, plus the grouped
   list of every configuration. At 700px and below the stage sits on top and the list becomes a
   one-row chip strip that keeps the active chip centred. Markup is generated by
   TOOLS/site-icons/gen_services_config.py; the behaviour is the "Services configurations viewer"
   block in site.js. Everything is scoped to .svc-config.
   ============================================================ */
.svc-config .strip-head { margin-left: auto; margin-right: auto; text-align: center; }
.svc-config .strip-head p { margin-left: auto; margin-right: auto; }

/* ---- the line icons: one 64 grid, 2 stroke, dashed operation lines, moving parts ---- */
.svc-config .ic { width: 100%; height: 100%; display: block; overflow: visible; }
.svc-config .ic .d { stroke-dasharray: 2.5 2.5; }
.svc-config .ic .pf { fill: var(--icbg); }
.svc-config .ic .sb { stroke-opacity: .5; }
.svc-config .ic .gs { fill: var(--accent); stroke: none; opacity: .24; }
.svc-config .ic .gs2 { opacity: .12; }
.svc-config .ic .clipg { clip-path: polygon(0px 0px, 40px 0px, 40px 64px, 0px 64px) view-box; }
.svc-config .ic .mv { transform-box: view-box; transform: var(--r, none); transition: transform .8s ease-in-out; }
.svc-config .ic .lift { transition: transform .3s ease-out .7s; }
.svc-config .ic .slide { transition: transform .7s ease-in-out 0s; }
.svc-config .ic .mvp { d: var(--dr); transition: d .8s ease-in-out; }
@keyframes cfgGlint { from { transform: translate(0px, 0px); } to { transform: translate(95px, 95px); } }
/* an icon operates while its chip is hovered or focused, and while the stage carries .go (the loop) */
.svc-config :is(.hv:is(:hover, :focus-within), .go) .ic .gs { animation: cfgGlint .85s ease-in-out 1; }
.svc-config :is(.hv:is(:hover, :focus-within), .go) .ic .lift { transition-delay: 0s; }
.svc-config :is(.hv:is(:hover, :focus-within), .go) .ic .slide { transition-delay: .3s; }
.svc-config :is(.hv:is(:hover, :focus-within), .go) .ic .mvp { d: var(--dh); }
.svc-config :is(.hv:is(:hover, :focus-within), .go) .ic .mv { transform: var(--t); }
/* Mirrored variants (Stack left of a drawn Stack right, and so on): the stage svg is flipped left to right; each glass mark
   flips back about its own centre so the marks keep the canon top-left to bottom-right direction. */
.svc-config .ic.mir { transform: scaleX(-1); }
.svc-config .ic.mir [stroke-width="0.65"] { transform-box: fill-box; transform-origin: 50% 50%; transform: scaleX(-1); }
/* Sequenced sliders (door_variants.py, rewritten 21/10/2026): one shared motion model for every sliding panel. The lead panel
   moves alone, engages the next panel through its interlock after one panel width less the overlap, and from then on they
   travel together at the same speed (linear, so no two moving panels ever run at different speeds); that pair engages the
   third, and so on. None overtakes its neighbour and nothing moves until it is picked up. --dl open delay, --dc close
   delay, --du duration, all derived from the final travels. Placed after the .lift and .slide rules so it wins. */
.svc-config .ic .sq { transition: transform var(--du, .75s) linear var(--dc, 0s); }
.svc-config .ic .sq.lift { transition-timing-function: ease-out; }
.svc-config :is(.hv:is(:hover, :focus-within), .go) .ic .sq { transition-delay: var(--dl, 0s); }
@media (prefers-reduced-motion: reduce) {
  .svc-config .ic .gs { animation: none !important; }
  .svc-config .ic .mv { transition: none !important; transform: none !important; }
  .svc-config .ic .mvp { transition: none !important; d: var(--dr) !important; }
}
/* the stage draws larger than the 64 grid was tuned for, so strokes are scaled down by --sf */
.svc-config .e-ic .ic { stroke-width: calc(2 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="0.65"] { stroke-width: calc(0.65 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="0.9"] { stroke-width: calc(0.9 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="1"] { stroke-width: calc(1 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="1.1"] { stroke-width: calc(1.1 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="1.2"] { stroke-width: calc(1.2 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="1.4"] { stroke-width: calc(1.4 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="1.6"] { stroke-width: calc(1.6 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="2"] { stroke-width: calc(2 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="2.6"] { stroke-width: calc(2.6 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="2.8"] { stroke-width: calc(2.8 * var(--sf)); }
.svc-config .e-ic .ic [stroke-width="3.2"] { stroke-width: calc(3.2 * var(--sf)); }

/* ---- the viewer ---- */
.svc-config .e-wrap { display: grid; grid-template-columns: 440px minmax(0, 1fr); gap: 48px; align-items: start; }
.svc-config .e-stage { position: sticky; top: 20px; }
.svc-config .e-box {
  --icbg: var(--surface);
  position: relative; aspect-ratio: 1 / 1; border-radius: 14px;
  border: 1.5px solid color-mix(in srgb, var(--accent) 28%, var(--border)); color: var(--accent);
  background: radial-gradient(circle at 50% 46%, color-mix(in srgb, var(--accent) 12%, var(--surface)) 0%, var(--surface) 62%);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.svc-config .e-box::before { content: ""; position: absolute; inset: 14px; border: 1px dashed color-mix(in srgb, var(--accent) 22%, transparent); border-radius: 8px; pointer-events: none; }
.svc-config .e-ic { --sf: .42; width: 320px; height: 320px; animation: drawerIn 320ms cubic-bezier(.2, .7, .2, 1); }
/* sliding doors (lift-and-slide, panoramic, pocketing) are drawn 25 percent larger in the same stage so each panel reads broader
   (Mike, 05/10/2026, zoom option c). site.js sets data-wide on the stage box. --sf drops to .336 so the stroke stays the same
   thickness in pixels; the width is capped to the box so a narrow phone never clips it. */
.svc-config .e-box[data-wide] .e-ic { --sf: .336; width: min(400px, calc(100% - 30px)); height: auto; aspect-ratio: 1 / 1; }
.svc-config .e-tagc { position: absolute; top: 26px; left: 28px; font-size: 12px; font-weight: 700; letter-spacing: .16em; color: var(--accent); }
.svc-config .e-loop { position: absolute; top: 26px; right: 28px; font-size: 11px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--muted); display: flex; align-items: center; gap: 7px; }
.svc-config .e-loop::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); animation: cfgPulse 2s ease-in-out infinite; }
@keyframes cfgPulse { 50% { opacity: .25; } }
.svc-config .e-meta { padding: 22px 4px 0; }
.svc-config .e-kick { display: block; font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--accent); }
.svc-config .e-name { font-family: var(--font-heading); font-size: 46px; line-height: 1.02; letter-spacing: -.02em; margin: 8px 0 10px; }
.svc-config .e-descs { margin: 0 0 18px; min-height: 50px; max-width: 400px; }
.svc-config .e-desc { margin: 0; color: var(--muted); font-size: 16px; }
.svc-config .e-desc[hidden] { display: none; }
.svc-config .e-nav { display: flex; align-items: center; gap: 14px; }
.svc-config .e-nav .ss-proj-btn { width: 44px; height: 44px; min-height: 44px; padding: 0; border-radius: 50%; border: 1.5px solid var(--border); background: transparent; color: var(--text); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: border-color 180ms, color 180ms; }
.svc-config .e-nav .ss-proj-btn svg { width: 18px; height: 18px; }
.svc-config .e-nav .ss-proj-btn:hover { border-color: var(--accent); color: var(--accent); background: transparent; box-shadow: none; transform: none; }
.svc-config .e-count { font-size: 13px; font-weight: 600; letter-spacing: .1em; font-variant-numeric: tabular-nums; color: var(--muted); }
.svc-config .e-list { display: flex; flex-direction: column; gap: 20px; }
.svc-config .e-grp h4 { font-family: var(--font-body); font-size: 11.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--muted); display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
.svc-config .e-grp h4::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.svc-config .e-grp h4 em { font-style: normal; color: var(--accent); order: 2; }
.svc-config .e-items { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.svc-config .e-it {
  --icbg: var(--bg);
  appearance: none; cursor: pointer; display: flex; align-items: center; gap: 10px; min-height: 54px; padding: 6px 10px 6px 6px;
  border-radius: 12px; border: 1.5px solid var(--border); background: var(--bg); color: var(--text);
  font: 600 13px/1.25 var(--font-body); text-align: left;
  transition: border-color 200ms, background 200ms, color 200ms;
}
.svc-config .e-it:hover { border-color: color-mix(in srgb, var(--accent) 60%, var(--border)); }
.svc-config .e-it:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.svc-config .e-it[aria-pressed="true"] { --icbg: color-mix(in srgb, var(--accent) 12%, var(--bg)); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--bg)); color: var(--accent); }
.svc-config .e-mini { flex: none; width: 40px; height: 40px; color: var(--accent); }
@media (max-width: 920px) {
  .svc-config .e-wrap { grid-template-columns: 340px minmax(0, 1fr); gap: 32px; }
  .svc-config .e-ic { width: 260px; height: 260px; }
  .svc-config .e-name { font-size: 38px; }
  .svc-config .e-items { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .svc-config.strip { padding: 56px 0; }
  .svc-config.strip .wrap { padding: 0 20px; }
  .svc-config .e-wrap { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .svc-config .e-stage { position: static; }
  .svc-config .e-ic { width: 250px; height: 250px; }
  .svc-config .e-name { font-size: 36px; }
  .svc-config .e-desc { font-size: 15px; }
  /* the list is one row of chips that bleeds to the screen edges; the side padding lets the first
     and last chip reach the centre, and every chip snaps to the centre like the other carousels */
  .svc-config .e-list {
    flex-direction: row; overflow-x: auto; gap: 8px;
    margin: 0 -20px; padding: 4px calc(50% - 40px) 10px;
    scroll-snap-type: x proximity; scrollbar-width: none;
  }
  .svc-config .e-list::-webkit-scrollbar { display: none; }
  .svc-config .e-grp { display: flex; gap: 8px; align-items: center; flex: none; }
  .svc-config .e-grp h4 { margin: 0; font-size: 10px; letter-spacing: .16em; color: var(--accent); padding: 0 2px 0 8px; white-space: nowrap; }
  .svc-config .e-grp h4::after, .svc-config .e-grp h4 em { display: none; }
  .svc-config .e-items { display: flex; gap: 8px; }
  .svc-config .e-it { flex: none; scroll-snap-align: center; min-height: 56px; white-space: nowrap; }
}

/* Services configurations viewer: note under the heading ("core types, not the full list") */
.svc-config .strip-head .e-note { max-width: 62ch; margin: 14px auto 0; font-size: .95em; opacity: .8; }

/* Services configurations viewer: door toggles (05/10/2026). Segmented pills under the stage description, only for
   door configurations. The pill is the Services tab pill (.svc-tab / .svc-tabs) scaled down; each option is a
   radio in a radiogroup, 44px tall. Every variant drawing is generated (TOOLS/site-icons/door_variants.py). */
.svc-config .e-dxs { margin: -8px 0 14px; max-width: 400px; }
.svc-config .e-dxs[hidden] { display: none; }
.svc-config .e-dx { margin: 0 0 4px; color: var(--muted); font-size: 14.5px; line-height: 1.45; }
.svc-config .e-dx[hidden] { display: none; }
.svc-config .e-optwrap { margin: 0 0 18px; }
.svc-config .e-optwrap:not(:has(.e-opts:not([hidden]))) { display: none; }
.svc-config .e-opts { display: flex; flex-wrap: wrap; gap: 12px 18px; }
.svc-config .e-opts[hidden] { display: none; }
.svc-config .e-og { display: flex; flex-direction: column; gap: 6px; min-width: 0; max-width: 100%; }
.svc-config .e-ol { font: 700 11px/1.2 var(--font-body); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.svc-config .e-seg {
  display: inline-flex; flex-wrap: wrap; gap: 4px; padding: 4px; max-width: 100%;
  background: var(--surface); border: 1px solid var(--border); border-radius: 27px;
  overflow-x: auto; scrollbar-width: none; scroll-snap-type: x proximity;
}
.svc-config .e-seg::-webkit-scrollbar { display: none; }
.svc-config .e-op {
  appearance: none; cursor: pointer; flex: none; scroll-snap-align: center;
  min-height: 44px; min-width: 44px; padding: 0 16px; white-space: nowrap;
  border: 0; border-radius: 999px; background: transparent; color: var(--text);
  font-family: var(--font-body); font-size: 13px; font-weight: 600; letter-spacing: 0.01em;
  transition: background 200ms, color 200ms, box-shadow 200ms;
}
.svc-config .e-op:hover { background: var(--surface-2); }
.svc-config .e-op[aria-checked="true"] {
  background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%); color: #FFFFFF;
  box-shadow: 0 2px 4px rgba(16,34,34,0.08), 0 6px 18px -6px color-mix(in srgb, var(--accent) 55%, transparent);
}
.svc-config .e-op:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 700px) {
  .svc-config .e-opts { gap: 12px 14px; }
  .svc-config .e-og { width: 100%; }
  .svc-config .e-seg { display: flex; }
  .svc-config .e-op { flex: 1 0 auto; padding: 0 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .svc-config .e-op { transition: none; }
}

/* Folding plan view: each leaf is a rotating group (rigid, nested). The timing curves are fitted so the plan angle
   stays in step with the elevation (TOOLS/site-icons/door_variants.py, FOLD_ALPHA). Base state = closing, hover/.go = opening. */
.svc-config .ic .pl { transition-timing-function: cubic-bezier(.376, -.035, .733, .703); }
.svc-config :is(.hv:is(:hover, :focus-within), .go) .ic .pl { transition-timing-function: cubic-bezier(.492, .631, .633, .989); }


/* ============================================================
   PHONE TAP TARGETS (05/10/2026 launch-ready pass)
   Anything a thumb has to hit gets a 44px box (WCAG 2.5.5 / Apple HIG)
   without moving the visual: padding or an invisible ::after adds the hit
   area, and an equal negative margin cancels padding in the layout, so
   nothing shifts. Desktop is untouched; phone width only.
   ============================================================ */
@media (max-width: 760px) {
  /* Header strip: phone, email, theme toggle */
  .site-nav .util .left a { padding-block: 13px; margin-block: -13px; position: relative; }
  .site-nav .theme-toggle { position: relative; }
  .site-nav .theme-toggle::after { content: ""; position: absolute; inset: -11px -4px; }
  /* Footer menu triggers (Services / Company / Reach us) */
  footer.site .menu .trigger { padding-block: 15px; margin-block: -6px; }
  /* Footer social / call / text icons: 40px circle, 44px hit area */
  .social-icon::after { content: ""; position: absolute; inset: -3.5px; }
  /* Footer legal row: email, Privacy, Terms */
  footer.site .bottom .legal a { display: inline-block; padding: 14px 8px; margin: -14px -8px; position: relative; }
  /* Step Code option chips and the email-me button */
  .sc-chip, .sc-actions .btn-ghost { min-height: 44px; }
  /* Step Code climate zone select: 16px (05/10/2026, Mike: "16px, shorter option
     labels"). 16px is the floor for iOS Safari, below it the page zooms when the
     select is focused. Native selects cannot wrap, so the option labels are kept
     short enough to fit at 390; padding is tight and the field bleeds 8px past
     the card padding each side. */
  .sc-field select { font-size: 16px; letter-spacing: -0.005em; padding: 12px 28px 12px 10px; text-align: left; text-align-last: left; width: calc(100% + 16px); max-width: none; margin-inline: -8px; background-position: right 10px center; min-height: 44px; }
  /* Quote hero strip phone link */
  .phone-link { position: relative; }
  .phone-link::after { content: ""; position: absolute; inset: -6px -4px; }
  /* Instagram widget (projects page) */
  [data-instagram-feed] .ig-follow, [data-instagram-feed] .ig-engage-btn, [data-instagram-feed] .ig-viewall, [data-instagram-feed] .ig-stage-link { position: relative; }
  [data-instagram-feed] .ig-follow::after, [data-instagram-feed] .ig-engage-btn::after { content: ""; position: absolute; inset: -6.5px 0; }
  [data-instagram-feed] .ig-viewall::after, [data-instagram-feed] .ig-stage-link::after { content: ""; position: absolute; inset: -16px -4px; }
  [data-instagram-feed] .ig-nav-btn::after { content: ""; position: absolute; inset: -4px; }
  [data-instagram-feed][data-variant="compact"] .ig-nav-btn::after { inset: -7px; }
  [data-instagram-feed] .ig-dot { position: relative; }
  [data-instagram-feed] .ig-dot::after { content: ""; position: absolute; inset: -11px; }
  .phone-cta { min-height: 44px; }
}

/* ============================================================
   STEP CODE: "What the Building Code requires, and what we'd spec."
   The ladder (Mike, 05/10/2026, variant A of the approved mockup).
   One ladder from the code ceiling down to Catalyst's Step 5 line:
   bar length is U-value, heat lost per square metre sits beside it.
   Globe behind the heading is the same artwork and the same
   .head-globe rules as Home and Services, kept on a phone here too.
   Tokens are the site's own; nothing in this block invents a colour.
   ============================================================ */
.sc-ladder-strip { position: relative; overflow: hidden; }
.sc-ladder-strip .strip-head { max-width: 880px; }
.sc-ladder-strip .strip-head.has-globe p {
  position: relative; z-index: 1;
  text-shadow:
    0 0 4px var(--globe-halo), 0 0 4px var(--globe-halo),
    0 0 8px var(--globe-halo), 0 0 8px var(--globe-halo),
    0 0 14px var(--globe-halo), 0 0 14px var(--globe-halo),
    0 0 22px var(--globe-halo), 0 0 30px var(--globe-halo);
}
.sc-ladder { margin: 0 0 36px; }
.sc-l-head, .sc-rung { display: grid; grid-template-columns: 270px 1fr 150px; gap: 24px; }
.sc-l-head {
  font-size: 11px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted); padding: 0 0 12px; border-bottom: 1px solid var(--border);
}
.sc-rung {
  align-items: center; padding: 16px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
}
.sc-who { display: flex; flex-direction: column; gap: 5px; align-items: flex-start; }
.sc-who b { font-family: var(--font-heading); font-size: 21px; line-height: 1.1; letter-spacing: -0.01em; }
.sc-who small { font-size: 12.5px; color: var(--muted); line-height: 1.4; }
.sc-badge {
  display: inline-block; padding: 4px 10px; font-size: 11px; font-weight: 600;
  border-radius: 999px; letter-spacing: 0.04em; white-space: nowrap;
}
.sc-badge.solid { background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%); color: #fff; }
.sc-badge.outline { background: transparent; color: var(--text); border: 1px solid var(--border); }
.sc-bar {
  position: relative; height: 46px; border-radius: 8px;
  background: color-mix(in srgb, var(--text) 5%, transparent);
}
.sc-bar i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 8px; display: block; }
.sc-rung.code .sc-bar i {
  background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--text) 22%, transparent) 0 6px, color-mix(in srgb, var(--text) 12%, transparent) 6px 12px);
}
.sc-rung.law .sc-bar i {
  background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--accent) 38%, transparent) 0 6px, color-mix(in srgb, var(--accent) 22%, transparent) 6px 12px);
}
.sc-rung.s3 .sc-bar i { background: color-mix(in srgb, var(--accent) 55%, var(--surface)); }
.sc-rung.s4 .sc-bar i { background: color-mix(in srgb, var(--accent) 78%, var(--surface)); }
.sc-rung.s5 .sc-bar i { background: linear-gradient(135deg, #2A8B83 0%, #5FCFC8 100%); }
.sc-val {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  display: flex; align-items: baseline; gap: 8px; white-space: nowrap; color: var(--text);
  font-family: var(--font-heading); font-size: 28px; font-weight: 700; line-height: 1;
  background: color-mix(in srgb, var(--surface) 82%, transparent); padding: 3px 8px; border-radius: 6px;
}
.sc-val em, .sc-val u { font: 500 11px var(--font-body); font-style: normal; text-decoration: none; color: var(--muted); }
.sc-side { font-size: 13px; line-height: 1.35; }
.sc-side b { font-family: var(--font-heading); font-size: 24px; }
.sc-side span { color: var(--muted); font-size: 12px; }
.sc-gap {
  margin: 22px 0 0; padding: 16px 20px; font-size: 15px;
  border-left: 3px solid var(--accent); border-radius: 0 10px 10px 0;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.sc-gap b { font-family: var(--font-heading); font-size: 20px; }
.sc-three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; margin: 36px 0 0; }
.sc-card {
  background: var(--surface); border: 1.5px solid var(--border); border-radius: 14px; padding: 28px;
}
.sc-card .k { font-family: var(--font-heading); font-size: 14px; font-weight: 700; color: var(--accent); letter-spacing: 0.08em; margin-bottom: 10px; }
.sc-card h3 { font-family: var(--font-heading); font-size: 26px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.1; margin: 0 0 12px; }
.sc-card p { font-size: 14.5px; margin: 0 0 12px; line-height: 1.55; }
.sc-card p:last-child { margin-bottom: 0; }
.sc-card .fine { font-size: 12.5px; color: var(--muted); }
.sc-how {
  margin-top: 30px; padding: 24px 28px; border: 1.5px dashed var(--border); border-radius: 14px;
  display: grid; grid-template-columns: 1fr auto; gap: 24px; align-items: center;
}
.sc-how p { margin: 0; font-size: 14.5px; }
.sc-how h4 { font-family: var(--font-heading); font-size: 22px; font-weight: 700; margin: 0 0 8px; }
.sc-src { font-size: 12.5px; color: var(--muted); margin: 28px 0 0; line-height: 1.6; max-width: 980px; }
.sc-src a { color: var(--accent); }
@media (max-width: 920px) {
  .sc-l-head { display: none; }
  .sc-rung { grid-template-columns: 1fr; gap: 10px; padding: 18px 0; }
  .sc-side { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; }
  .sc-three, .sc-how { grid-template-columns: 1fr; }
  .sc-bar { height: auto; min-height: 52px; display: flex; align-items: center; }
  .sc-bar i { z-index: 0; }
  .sc-val {
    position: relative; left: auto; top: auto; transform: none; z-index: 1;
    flex-wrap: wrap; gap: 2px 8px; white-space: normal; margin: 6px 0 6px 10px; max-width: calc(100% - 20px);
  }
  .sc-val u { flex-basis: 100%; }
}
@media (max-width: 700px) {
  .sc-ladder-strip { padding: 56px 0; }
  .sc-card { padding: 22px; }
  .sc-card h3 { font-size: 24px; }
  .sc-who b { font-size: 20px; }
  .sc-ladder-strip .head-globe { display: block; width: 340px; top: 46%; opacity: 0.8; }
}

/* Quote flow touch targets and wrap (final walk 21/10/2026) */
.qflow .qnav .back { min-height: 44px; padding: 0 14px; }
.qflow .file-row .remove { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
.qflow [data-ai-preview] h3 { text-wrap: balance; }
.qflow .is-failed a[href^="tel:"] { display: inline-block; padding: 14px 0; }
.qflow .field-error + .field-error { margin-top: 4px; }

/* Contact page art (site/contact-art, 21/10/2026): ringing handset behind the hero heading,
   globe behind the message form. Decorative only, aria-hidden, static (no motion). */
.page-hero.has-hero-art{position:relative;overflow:hidden}
.page-hero.has-hero-art .wrap{position:relative;z-index:1}
.hero-art{position:absolute;top:50%;left:84%;height:128%;width:auto;aspect-ratio:1;transform:translate(-50%,-50%);pointer-events:none;z-index:0}
.hero-art-phone{display:none}
.hero-art .art-line,.hero-art .art-rings,.hero-art-phone .art-line,.hero-art-phone .art-rings{stroke:color-mix(in srgb,var(--text) 20%,transparent);stroke-width:1.5;fill:none}
.hero-art .ring,.hero-art-phone .ring{stroke:color-mix(in srgb,var(--text) 16%,transparent);stroke-width:1.1}
.hero-art .ring1,.hero-art-phone .ring1{stroke:color-mix(in srgb,var(--accent) 55%,transparent);stroke-width:1.3}
.hero-art .art-dots circle,.hero-art-phone .art-dots circle{fill:var(--accent)}
.page-hero.has-hero-art{--halo:color-mix(in srgb,var(--accent) 4%,var(--bg))}
.page-hero.has-hero-art h1,.page-hero.has-hero-art .lede{text-shadow:0 0 4px var(--halo),0 0 4px var(--halo),0 0 8px var(--halo),0 0 8px var(--halo),0 0 14px var(--halo),0 0 14px var(--halo),0 0 22px var(--halo),0 0 30px var(--halo)}
@media (max-width:640px){
  .hero-art{display:none}
  .hero-art-phone{display:block;width:132px;height:auto;margin:0 auto 14px;pointer-events:none}
  .hero-art-phone .art-line,.hero-art-phone .art-rings{stroke:color-mix(in srgb,var(--text) 30%,transparent)}
}
.strip.has-globe-bg{position:relative;overflow:hidden}
.strip.has-globe-bg .wrap{position:relative;z-index:1}
.strip.has-globe-bg .head-globe{display:block;position:absolute;top:50%;left:50%;width:clamp(620px,86vw,1100px);height:auto;transform:translate(-50%,-50%);pointer-events:none;z-index:0}
.strip.has-globe-bg .head-globe .globe-rim{stroke:color-mix(in srgb,var(--text) 22%,transparent)}
.strip.has-globe-bg .head-globe .globe-graticule{stroke:color-mix(in srgb,var(--text) 14%,transparent)}
.strip.has-globe-bg .head-globe .globe-land{fill:color-mix(in srgb,var(--text) 11%,transparent);stroke:color-mix(in srgb,var(--text) 19%,transparent)}
@media (max-width:640px){.strip.has-globe-bg .head-globe{width:170vw;top:46%}}

/* --- Phone tap targets, second pass (22/10/2026) -------------------------
   Step Code hero "BCBC 2024 Table 9..." source link measured 16px tall at
   390px. Invisible hit area only; the text does not move. Prev/next circle
   buttons on the Instagram widget get a slightly larger invisible margin. */
@media (max-width: 760px) {
  .hero-meta a { position: relative; display: inline-block; }
  .hero-meta a::after { content: ""; position: absolute; inset: -14px -4px; }
  [data-instagram-feed] .ig-nav-btn::after { inset: -6px; }
  [data-instagram-feed][data-variant="compact"] .ig-nav-btn::after { inset: -8px; }
}

/* ============================================================
   TESTIMONIALS PAGE (22/10/2026, slice 1, canvas
   claude.ai/artifact/Nzqyw7W8Gi2x41wi8ywKqV). Everything else on the page
   (hero, strips, CTA band, slideshow) reuses existing rules above.
   New here: the testimonial card, the carousel and its controls, and the
   leave-a-testimonial form layout.
   ============================================================ */
.tcard {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 14px;
  padding: 28px;
}
.tcard.feature { padding: 32px; }
.tcard blockquote {
  margin: 0 0 24px;
  font-family: var(--font-heading); font-style: italic; font-weight: 500;
  font-size: 24px; line-height: 1.3; letter-spacing: -0.01em;
  color: var(--text);
}
.tcard .who { font-size: 15px; font-weight: 600; color: var(--text); margin: 0 0 2px; }
.tcard .role { font-size: 13.5px; color: var(--muted); line-height: 1.5; margin: 0; }
.tcard .co {
  font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent); margin-top: 10px;
}
/* Preview-only tag (?pending=1) on a quote Mike has not cleared yet. */
.tcard .tpending {
  display: inline-block; margin: 0 0 16px; padding: 4px 10px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text);
  border: 1.5px dashed var(--accent); border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

/* Empty state: a calm dashed card in the site's voice. */
.tcar .slot {
  background: color-mix(in srgb, var(--accent) 6%, var(--bg));
  border: 1.5px dashed var(--border);
  border-radius: 14px;
  padding: 28px;
  display: flex; flex-direction: column; justify-content: center;
  min-height: 160px;
}
.tcar .slot h3 { font-family: var(--font-heading); font-size: 20px; font-weight: 700; letter-spacing: -0.01em; margin: 0; }
.tcar .tslot-fill { min-height: 220px; }

.tcar { position: relative; }
.ttrack {
  display: flex; gap: 22px;
  overflow-x: auto; scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none; overscroll-behavior-x: contain;
}
.ttrack::-webkit-scrollbar { display: none; }
.ttrack:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 14px; }
.tslide { flex: 0 0 100%; min-width: 0; scroll-snap-align: start; display: flex; }
.tslide > .tcard, .tslide > .slot { flex: 1 1 auto; width: 100%; }
.tnav { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 20px; }
.tnav[hidden] { display: none; }
.tarrow {
  width: 44px; height: 44px; min-width: 44px; min-height: 44px; padding: 0;
  border-radius: 999px;
  border: 1.5px solid color-mix(in srgb, var(--accent) 40%, transparent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  color: var(--accent);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  transition: background-color 200ms, border-color 200ms;
}
.tarrow:hover { background: color-mix(in srgb, var(--accent) 18%, transparent); border-color: var(--accent); }
.tarrow:focus-visible, .tdot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tarrow svg { width: 16px; height: 16px; }
.tdot {
  width: 44px; height: 44px; min-width: 44px; min-height: 44px; padding: 0;
  border: none; background: transparent;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
}
.tdot span { display: block; width: 10px; height: 10px; border-radius: 999px; background: var(--border); border: 1.5px solid var(--accent); }
.tdot.on span { background: var(--accent); }

/* Iconic Projects: "See all projects" under the slideshow. */
.t-allprojects { margin-top: 28px; text-align: center; }

/* Leave-a-testimonial form (hidden in slice 1). */
[data-section-id="leave-testimonial"][hidden] { display: none !important; }
.tform .field { margin-bottom: 18px; }
.tform .textarea { min-height: 140px; resize: vertical; line-height: 1.55; }
.tform .input, .tform .textarea { min-height: 48px; }
.tform .check {
  display: flex; align-items: flex-start; gap: 12px;
  min-height: 44px; padding: 6px 0; margin-bottom: 18px;
  line-height: 1.5; position: relative;
}
.tform .check input { width: 44px; height: 44px; margin: 0; left: -8px; top: 0; pointer-events: auto; }
.tform .check .box { flex: 0 0 20px; margin-top: 2px; }
.tform .actions .btn-primary { min-height: 48px; }

@media (min-width: 721px) {
  .tcard.feature { padding: 44px 48px; }
  .tcard.feature blockquote { font-size: 34px; max-width: 900px; }
  .formrow { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .ttrack { scroll-behavior: auto; }
  .tarrow { transition: none; }
}
