/* ==========================================================================
   Suite Home Renovations — components.css
   Buttons · Nav + mega-menu · Mobile drawer · Hero · Trust bar · Cards
   Stats · Pills · CTA band · Footer
   All components read the semantic tokens from main.css, so they recolour
   automatically inside any .section--* theme.
   ========================================================================== */

/* --------------------------------------------------------------------------
   BUTTONS
   -------------------------------------------------------------------------- */
.btn {
  --btn-bg: var(--c-brass);
  --btn-fg: var(--c-base);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 3rem;                 /* ≥44px touch target */
  padding: .85rem 1.6rem;
  font-family: var(--ff-body);
  font-weight: 600;
  font-size: var(--fs-small);
  letter-spacing: .04em;
  text-transform: uppercase;
  border-radius: var(--radius);
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              color var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out);
  touch-action: manipulation;
}
.btn:active { transform: translateY(1px) scale(.99); }

/* Inline icons (phone, etc.) inherit the button's text colour so they match the
   label instead of defaulting to black. The arrow is stroke-based (fill:none),
   so it's excluded — filling it would close its open path into a solid shape. */
.btn svg:not(.btn__arrow) { fill: currentColor; }

/* Primary — brass fill with a sweeping shine on hover */
.btn--primary { background: var(--btn-bg); color: var(--btn-fg); }
.btn--primary::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, .35) 50%, transparent 80%);
  transform: translateX(-120%);
  transition: transform var(--dur-slow) var(--ease-out);
}
.btn--primary:hover { box-shadow: var(--shadow-brass); transform: translateY(-2px); }
.btn--primary:hover::before { transform: translateX(120%); }

/* Ghost — outline that fills with brass on hover */
.btn--ghost {
  color: var(--heading);
  border: 1px solid var(--accent);
  background: transparent;
}
.btn--ghost::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: var(--c-brass);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform var(--dur) var(--ease-out);
}
.btn--ghost:hover { color: var(--c-base); border-color: var(--c-brass); }
.btn--ghost:hover::before { transform: scaleY(1); }

/* Text link button with animated underline + arrow */
.btn--text {
  min-height: auto;
  padding: .25rem 0;
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: var(--fs-overline);
  color: var(--accent);
  border-radius: 0;
}
.btn--text .btn__arrow { transition: transform var(--dur) var(--ease-out); }
.btn--text:hover .btn__arrow { transform: translateX(4px); }
.btn--text::after {
  content: ""; display: block; height: 1px; margin-top: 4px;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur) var(--ease-out);
}
.btn--text:hover::after { transform: scaleX(1); }

/* Ghost button: nudge the arrow on hover (parity with .btn--text) */
.btn--ghost .btn__arrow { transition: transform var(--dur) var(--ease-out); }
.btn--ghost:hover .btn__arrow { transform: translateX(4px); }

.btn-group { display: flex; flex-wrap: wrap; gap: var(--sp-4); }

/* --------------------------------------------------------------------------
   TRADE TAGS — "every trade in-house" proof strip for full-trade intros.
   Recolours per section theme via --accent / --heading / --line.
   -------------------------------------------------------------------------- */
.trade-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
  padding: 0;
  list-style: none;
}
.trade-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: .5rem 1rem;
  font-family: var(--ff-body);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--heading);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: 100px;
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
/* --------------------------------------------------------------------------
   INTRO MEDIA FRAME — holds a parallax-translated <img>. A transformed child
   stops a rounded `overflow:hidden` parent from clipping its corners, and GSAP
   clears the figure's own transform after the reveal (removing the compositing
   layer that would otherwise clip) — leaving the TOP corners square. clip-path
   clips the rounded rectangle reliably, transformed descendants included.
   -------------------------------------------------------------------------- */
.intro__media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  clip-path: inset(0 round var(--radius-lg));
  aspect-ratio: 4 / 5;            /* portrait crop while stacked on mobile */
}
/* Image is absolutely positioned so it never inflates the grid row — the copy
   column drives the row height and the photo stretches to match at md+ (below).
   width/height/object-fit (incl. the 112% parallax headroom) stay inline. */
.intro__media img { position: absolute; inset: 0; }

/* Brass check, drawn via mask so no sprite edit is needed on every page */
.trade-tag::before {
  content: "";
  flex: none;
  width: 1rem;
  height: 1rem;
  background: var(--accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round' d='M5 13l4 4L19 7'/%3E%3C/svg%3E") center/contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round' d='M5 13l4 4L19 7'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* --------------------------------------------------------------------------
   STAR RATING
   -------------------------------------------------------------------------- */
.stars { display: inline-flex; gap: 2px; color: var(--c-brass); flex-shrink: 0; }
.stars svg { width: 1.05em; height: 1.05em; fill: currentColor; }
.rating {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  font-size: var(--fs-small);
}
.rating__score {
  font-family: var(--ff-display); font-style: italic;
  font-size: 1.5rem; color: var(--accent); line-height: 1;
}

/* --------------------------------------------------------------------------
   REVIEW SUMMARY — the canonical Google-rating panel.
   Every number here is a data-review slot. To change a count or the rating,
   edit scripts/review-stats.json and run `python3 scripts/propagate_reviews.py`
   — never hardcode a number into this component.
   White surface + authentic Google star yellow is deliberate: the panel reads
   as Google's record, not our claim. CTAs stay brass to tie back to the brand.
   -------------------------------------------------------------------------- */
.review-summary {
  display: inline-flex; flex-direction: column; align-items: center;
  gap: var(--sp-3); text-align: center;
  background: #fff; border-radius: var(--radius-lg);
  padding: var(--sp-6) var(--sp-8);
  box-shadow: 0 2px 14px rgba(0, 0, 0, .12);
}
.review-summary__brand { display: flex; align-items: center; gap: .5rem; }
.review-summary__brand svg { width: 18px; height: 18px; flex-shrink: 0; }
.review-summary__label {
  font-size: .625rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: #5f6368; line-height: 1;
}
.review-summary__score { display: flex; align-items: center; gap: var(--sp-3); }
.review-summary__num {
  font-family: var(--ff-display); font-size: 2.5rem; line-height: 1; color: #202124;
}
.review-summary__stars { display: inline-flex; gap: 2px; color: #fbbc04; }
.review-summary__stars svg { width: 19px; height: 19px; fill: currentColor; }
.review-summary__meta { margin: 0; font-size: var(--fs-small); color: #5f6368; }
.review-summary__meta strong { color: #202124; font-weight: 600; }
.review-summary__cta {
  display: inline-flex; align-items: center; justify-content: center; gap: .35rem;
  min-height: 44px; padding: .5rem 1.15rem; box-sizing: border-box;
  font-size: var(--fs-small); font-weight: 600; text-decoration: none;
  color: var(--c-brass-deep); background: #fff;
  border: 1px solid #dadce0; border-radius: 999px;
  transition: background .2s ease, border-color .2s ease;
}
.review-summary__cta:hover, .review-summary__cta:focus-visible {
  background: var(--c-off-white); border-color: var(--c-brass);
}

/* --------------------------------------------------------------------------
   SITE NAV (fixed, transparent over hero → condenses to solid on scroll)
   -------------------------------------------------------------------------- */
.site-nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-nav);
  background: transparent;
  transition: background var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              backdrop-filter var(--dur) var(--ease-out);
}
.site-nav::after {            /* hairline that appears once condensed */
  content: ""; position: absolute; inset: auto 0 0 0; height: 1px;
  background: var(--c-line-dark); opacity: 0;
  transition: opacity var(--dur) var(--ease-out);
}
.nav--scrolled {
  background: rgba(20, 17, 15, .88);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 8px 30px rgba(0, 0, 0, .25);
}
.nav--scrolled::after { opacity: 1; }

.nav__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
  height: var(--nav-h, 4.75rem);
  transition: height var(--dur) var(--ease-out);
}
/* Full-bleed nav bar — span the viewport, keep gutters from .container */
.site-nav .nav__bar { max-width: none; }
.nav--scrolled .nav__bar { --nav-h: var(--nav-h-scrolled); }

.nav__logo { display: inline-flex; align-items: center; flex: 0 0 auto; }
.nav__logo img {
  height: 2.1rem; width: auto;
  transition: height var(--dur) var(--ease-out);
}
.nav--scrolled .nav__logo img { height: 1.85rem; }

/* Desktop link cluster — hidden on mobile (drawer takes over) */
.nav__links {
  display: none;
  align-items: center;
  gap: clamp(1rem, .4rem + 1.4vw, 2.25rem);
}
.nav__item { position: relative; }
.nav__link {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .5rem 0;
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--c-warm-white);
  letter-spacing: .02em;
}
.nav__link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
  background: var(--c-brass); transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur) var(--ease-out);
}
.nav__link:hover::after,
.nav__link[aria-current="page"]::after,
.nav__item:hover .nav__link::after { transform: scaleX(1); }
.nav__link[aria-current="page"] { color: var(--c-brass); }

.nav__caret { width: .7em; height: .7em; fill: currentColor; transition: transform var(--dur) var(--ease-out); }
.nav__trigger[aria-expanded="true"] .nav__caret { transform: rotate(180deg); }

/* 1024–1247px — six-item squeeze band (Home added 2026-07-29).
   The bar is `1fr auto 1fr`, so the logo and utility columns are peers: the
   utility cluster's 362px min-content wins the fr split and the LOGO column is
   what gets starved. Measured at 1024px with Home added, the logo column
   collapsed to 24px (rendered logo width 0) and "Areas We Serve" wrapped.
   Budget at 1024px (barInner 1009 incl. a 15px classic scrollbar):
     required = logo 119.2 (2rem) + links 494.8 (items 444.8 + 5×10px gaps)
              + utility 338.2 + bar's own 2 grid gaps 16 = 968.1
     inner    = 1009 − 2×12px gutter                    = 985  → ~17px slack
   Note `.nav__bar` carries `gap: var(--sp-6)` (24px) of its OWN grid gaps —
   2×24=48px that is easy to miss when budgeting this row.
   The band ends at 1248px, NOT 1200px. With default values the row needs
   1047.87 + 0.07w px against an inner width of 0.96w − 40.6, which only breaks
   even at w ≈ 1223px — so a 1200px cut-off would drop the overrides while the
   row still overflowed. ≥1248px keeps the fluid clamp, the 3rem gutter and the
   2.7rem logo untouched. Specificity (0,2,0) beats the 64rem block's (0,1,0),
   so source order cannot undo it. Re-measure if any nav label changes.
   `min-width: max-content` on the logo is load-bearing: without it the grid
   starves the logo track and SQUASHES the <img> horizontally (measured 88.03px
   against a 125.11px aspect-correct width) instead of shrinking whitespace —
   height:auto/width:auto does not protect a replaced element here. */
@media (min-width: 64rem) and (max-width: 77.99rem) {
  .site-nav .nav__bar { --gutter: .75rem; gap: .5rem; }
  .site-nav .nav__links { gap: .625rem; }
  .site-nav .nav__logo { min-width: max-content; }
  .site-nav .nav__logo img { height: 2rem; }
  .site-nav.nav--scrolled .nav__logo img { height: 1.85rem; }
  .site-nav .nav__utility { gap: .75rem; }
  .site-nav .nav__cta { padding-inline: 1.1rem; }
}

/* Right-hand utility cluster */
.nav__utility { display: flex; align-items: center; gap: var(--sp-4); }
/* The always-visible phone circle makes this cluster tight on small phones; the
   desktop gap is restored at lg, where the CTA button also appears. */
@media (max-width: 26rem) {
  .nav__utility { gap: var(--sp-2); }
}
/* Phone — icon-only brass circle, deliberately larger than .nav__portal (2.4rem)
   so the contact hierarchy reads. Visible at EVERY breakpoint: mobile users
   previously had to open the drawer to find a number. The number itself lives in
   the aria-label, the drawer, and the footer. */
.nav__phone {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.8rem; height: 2.8rem; flex: 0 0 auto;
  border: 1px solid var(--c-brass);
  border-radius: 50%;
  color: var(--c-brass);
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.nav__phone svg { width: 1.35rem; height: 1.35rem; fill: currentColor; }
.nav__phone:hover,
.nav__phone:focus-visible { background: var(--c-brass); color: var(--c-base); }
.nav__cta { display: none; white-space: nowrap; }   /* keep the label on one line */

/* Client-portal account icon — visible at every breakpoint (sits beside the
   hamburger on mobile, before the phone on desktop) */
.nav__portal {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; flex: 0 0 auto;
  color: var(--c-warm-white);
  transition: color var(--dur) var(--ease-out);
}
.nav__portal svg { width: 1.25rem; height: 1.25rem; stroke: currentColor; fill: none; }
.nav__portal:hover,
.nav__portal:focus-visible,
.nav__portal[aria-current="page"] { color: var(--c-brass); }

/* --------------------------------------------------------------------------
   MEGA-MENU (desktop) — opens below the bar
   -------------------------------------------------------------------------- */
.mega {
  position: absolute;
  top: 100%; left: 50%;
  transform: translateX(-50%) translateY(8px);
  width: min(46rem, 92vw);
  background: rgba(20, 17, 15, .97);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--c-line-dark);
  border-radius: var(--radius-lg);
  box-shadow: 0 30px 60px rgba(0, 0, 0, .45);
  padding: var(--sp-6);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out), visibility var(--dur);
}
.mega[data-open="true"] {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
.mega__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-2) var(--sp-8);
}

/* Per-dropdown panel widths. Services keeps descriptions and needs the room;
   Areas and Resources are compact. */
.mega--areas     { width: min(38rem, 92vw); }
.mega--resources { width: min(28rem, 92vw); }

/* Edge-anchored panels. .mega is centre-anchored by default, which was correct
   when Services was the 2nd of 7 items. It is now 1st of 5 (panel would clip the
   viewport on the left) and Resources is 4th of 5 (would clip on the right). */
.mega--start { left: 0; right: auto; transform: translateX(0) translateY(8px); }
.mega--end   { left: auto; right: 0;  transform: translateX(0) translateY(8px); }
.mega--start[data-open="true"],
.mega--end[data-open="true"] { transform: translateX(0) translateY(0); }

/* Compact rows — icon + title, no description line. Serves Areas and Resources. */
.mega--compact .mega__link { align-items: center; padding: var(--sp-2) var(--sp-3); }
.mega--compact .mega__icon { margin-top: 0; width: 1.15rem; height: 1.15rem; }

/* Areas — three columns of short town names. */
.mega__grid--3 { grid-template-columns: repeat(3, 1fr); gap: var(--sp-1) var(--sp-5); }

/* Resources — two labelled columns. The headings are what stop "About us" from
   reading oddly under a Resources tab. */
.mega__col { display: flex; flex-direction: column; }
.mega__col-title {
  margin: 0 0 var(--sp-2);
  padding: 0 var(--sp-3);
  font-size: .7rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--c-on-dark);
}
.mega__link {
  display: flex; flex-direction: row; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  color: var(--c-warm-white);
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.mega__link:hover, .mega__link:focus-visible { background: rgba(201, 163, 106, .12); color: var(--c-brass); }
.mega__icon {
  flex: 0 0 auto;
  width: 1.5rem; height: 1.5rem;
  display: flex; align-items: center; justify-content: center;
  color: var(--c-brass);
  margin-top: .15rem;
}
.mega__icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.mega__body { display: flex; flex-direction: column; gap: 2px; }
.mega__link span { font-weight: 600; font-size: var(--fs-small); }
.mega__link small { color: var(--c-on-dark); font-size: .8rem; }
.mega__footer {
  margin-top: var(--sp-5); padding-top: var(--sp-4);
  border-top: 1px solid var(--c-line-dark);
}

/* --------------------------------------------------------------------------
   HAMBURGER + MOBILE DRAWER
   -------------------------------------------------------------------------- */
.nav__toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 2.75rem; height: 2.75rem;     /* ≥44px touch target */
  margin-right: -.4rem;
}
.nav__toggle .bar {
  display: block; width: 24px; height: 2px; margin-inline: auto;
  background: var(--c-warm-white);
  transition: transform var(--dur) var(--ease-out), opacity var(--dur) var(--ease-out);
}
body.drawer-open .nav__toggle .bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
body.drawer-open .nav__toggle .bar:nth-child(2) { opacity: 0; }
body.drawer-open .nav__toggle .bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.drawer {
  position: fixed; inset: 0;
  z-index: var(--z-drawer);
  visibility: hidden;
}
body.drawer-open .drawer { visibility: visible; }

.drawer__backdrop {
  position: absolute; inset: 0;
  background: rgba(8, 7, 6, .6);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out);
}
body.drawer-open .drawer__backdrop { opacity: 1; }

.drawer__panel {
  position: absolute; inset: 0 0 0 auto;
  width: min(22rem, 88vw);
  background: var(--c-base-deep);
  border-left: 1px solid var(--c-line-dark);
  padding: 5.5rem var(--sp-6) var(--sp-8);
  overflow-y: auto;
  transform: translateX(100%);
  transition: transform var(--dur-slow) var(--ease-out);
  display: flex; flex-direction: column; gap: var(--sp-2);
}
body.drawer-open .drawer__panel { transform: translateX(0); }

.drawer__close {
  position: absolute; top: var(--sp-5); right: var(--sp-5);
  width: 2.75rem; height: 2.75rem;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--c-warm-white);
}
.drawer__close svg { width: 1.4rem; height: 1.4rem; stroke: currentColor; }

.drawer__link {
  display: block;
  padding: var(--sp-3) 0;
  font-family: var(--ff-display);
  font-size: 1.4rem;
  color: var(--c-warm-white);
  border-bottom: 1px solid var(--c-line-dark);
}
.drawer__link[aria-current="page"] { color: var(--c-brass); }

/* Services accordion inside drawer */
.drawer__acc-trigger {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%;
  padding: var(--sp-3) 0;
  font-family: var(--ff-display); font-size: 1.4rem;
  color: var(--c-warm-white);
  border-bottom: 1px solid var(--c-line-dark);
}
.drawer__acc-trigger svg { width: .8em; height: .8em; fill: var(--c-brass); transition: transform var(--dur) var(--ease-out); }
.drawer__acc-trigger[aria-expanded="true"] svg { transform: rotate(180deg); }
.drawer__acc-panel {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur) var(--ease-out);
}
.drawer__acc-panel[data-open="true"] { grid-template-rows: 1fr; }
.drawer__acc-panel > div { overflow: hidden; visibility: hidden; transition: visibility var(--dur); }
.drawer__acc-panel[data-open="true"] > div { visibility: visible; }
.drawer__sublink {
  display: block; padding: var(--sp-2) 0 var(--sp-2) var(--sp-4);
  font-size: var(--fs-small); color: var(--c-on-dark);
}
.drawer__sublink:hover { color: var(--c-brass); }
.drawer__cta { margin-top: var(--sp-5); }
.drawer__cta .btn { width: 100%; }
.drawer__phone {
  margin-top: var(--sp-4); display: inline-flex; align-items: center; gap: .5rem;
  color: var(--c-brass); font-weight: 600;
}
.drawer__phone svg { fill: currentColor; }
.drawer__portal {
  margin-top: var(--sp-4); display: inline-flex; align-items: center; gap: .5rem;
  color: var(--c-warm-white); font-weight: 600;
  transition: color var(--dur) var(--ease-out);
}
.drawer__portal svg { stroke: var(--c-brass); fill: none; }
.drawer__portal:hover { color: var(--c-brass); }

/* --------------------------------------------------------------------------
   AUTH CARD + FORM (client-login placeholder; first form styles in the build)
   -------------------------------------------------------------------------- */
.auth {
  min-height: 100svh;
  display: flex; align-items: flex-start; justify-content: center;
  /* clamp ensures nav (4.75rem) is always cleared; grows with vw for visual balance */
  padding: clamp(5.75rem, 4.75rem + 3vw, 9rem) var(--sp-5) var(--sp-12);
  background: var(--c-base);
}
.auth-card {
  width: 100%; max-width: 28rem;
  background: var(--c-base-deep);
  border: 1px solid var(--c-brass);
  border-radius: var(--radius-lg);
  padding: var(--sp-10) var(--sp-8);
  box-shadow: 0 30px 60px rgba(0, 0, 0, .45);
}
.auth-card .overline { color: var(--c-brass); }
.auth-card h1 { margin: var(--sp-2) 0 var(--sp-3); }
.auth-card .lead { color: var(--c-on-dark); margin-bottom: var(--sp-6); }

.auth-form { display: flex; flex-direction: column; gap: var(--sp-4); }
.field { display: flex; flex-direction: column; gap: var(--sp-2); }
.field label {
  font-size: var(--fs-overline); letter-spacing: .12em; text-transform: uppercase;
  font-weight: 600; color: var(--c-on-dark);
}
.auth-form input {
  width: 100%;
  padding: .75rem 1rem;
  font: inherit; font-size: var(--fs-small);
  color: var(--c-warm-white);
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--c-line-dark);
  border-radius: var(--radius);
  transition: border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
.auth-form input::placeholder { color: var(--c-muted); }
.auth-form input:focus-visible {
  outline: none;
  border-color: var(--c-brass);
  box-shadow: 0 0 0 3px rgba(201, 163, 106, .25);
}
.auth-form .btn { width: 100%; margin-top: var(--sp-2); }
.auth-forgot {
  align-self: flex-end;
  font-size: var(--fs-small); color: var(--c-on-dark);
}
.auth-forgot:hover { color: var(--c-brass); }
.auth-note {
  margin-top: var(--sp-6); padding-top: var(--sp-5);
  border-top: 1px solid var(--c-line-dark);
  font-size: var(--fs-small); color: var(--c-muted); text-align: center;
}
.auth-note.is-active { color: var(--c-brass); }

/* --------------------------------------------------------------------------
   HERO
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  /* Room reserved for .hero__scroll-cue, which is absolutely positioned INSIDE
     the bottom padding band — if the band is shorter than the cue, the cue lands
     on top of the hook card. 0 by default (the cue is desktop-only); the lg
     query below sets the real figure. */
  --cue-space: 0rem;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-top: 6rem;
  padding-bottom: max(var(--cue-space), clamp(3rem, 2rem + 5vw, 6rem));
  overflow: hidden;
  isolation: isolate;
}
/* Extra vertical room (top:-6%; height:112%) so the parallax scrub never
   exposes an edge gap. Decorative layer, sits behind the content + wash. */
.hero__media { position: absolute; inset: -6% 0 auto 0; height: 112%; z-index: -2; }
.hero__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 40%;
}
/* Cinematic dark wash so white type stays legible (left-weighted) */
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(20, 17, 15, .55) 0%, rgba(20, 17, 15, .25) 35%, rgba(20, 17, 15, .85) 100%),
    linear-gradient(90deg, rgba(20, 17, 15, .8) 0%, rgba(20, 17, 15, .25) 60%, transparent 100%);
}
.hero__inner { max-width: 44rem; }
.hero h1 { color: var(--c-white); margin-top: var(--sp-4); }
.hero h1 em { color: var(--c-brass); font-style: italic; }
.hero__sub {
  margin-top: var(--sp-5);
  max-width: 36rem;
  color: var(--c-warm-white);
  font-size: var(--fs-lead);
  line-height: 1.55;
}
.hero__rating {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3);
  margin-top: var(--sp-6);
}
.hero__rating .rating__score { font-size: clamp(2rem, 1.4rem + 2vw, 3rem); }
.hero__rating .meta { color: var(--c-warm-white); font-size: var(--fs-small); }
.hero__rating .meta strong { color: var(--c-white); }
.hero .btn-group { margin-top: var(--sp-8); }

/* Hero layout: single column on mobile (hook card stacks under the copy),
   two columns from lg up (see the lg media query below). */
.hero__grid { display: grid; gap: var(--sp-8); width: 100%; }

/* --------------------------------------------------------------------------
   HERO HOOK FORM — minimal lead capture. Dark-glass + brass card that mirrors
   the contact quiz so the hand-off feels like one continuous flow.
   -------------------------------------------------------------------------- */
.hook {
  background: rgba(20, 17, 15, .58);
  border: 1px solid rgba(201, 163, 106, .28);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 1rem + 2vw, 2.25rem);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, .6);
}
.hook__title {
  font-family: var(--ff-display);
  color: var(--c-white);
  font-size: var(--fs-h3);
  line-height: 1.15;
}
.hook__sub {
  margin-top: var(--sp-2);
  color: var(--c-on-dark);
  font-size: var(--fs-small);
  line-height: 1.5;
}
.hook__field { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-4); }
.hook__field label { font-size: var(--fs-small); font-weight: 600; color: var(--c-on-dark); }
.hook__field label .req { color: var(--c-brass); }
.hook__field input,
.hook__field select {
  width: 100%;
  min-height: 48px;
  padding: var(--sp-3) var(--sp-4);
  background: rgba(255, 255, 255, .06);
  border: 1px solid rgba(201, 163, 106, .22);
  border-radius: var(--radius);
  color: #fff;
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  transition: border-color .2s, background .2s;
}
/* Custom brass caret on the select; native option list renders dark-on-light */
.hook__field select {
  appearance: none; -webkit-appearance: none;
  padding-right: 2.75rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23C9A36A'%3E%3Cpath d='M6 9l6 6 6-6z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-4) center;
  background-size: 18px;
  cursor: pointer;
}
.hook__field select option { color: #14110F; }
.hook__field input:focus,
.hook__field select:focus { outline: none; border-color: var(--c-brass); background: rgba(255, 255, 255, .09); }
.hook__submit {
  width: 100%;
  margin-top: var(--sp-6);
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
}
.hook__submit svg { width: 18px; height: 18px; }
.hook__trust {
  margin-top: var(--sp-4);
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: .4rem;
  font-size: var(--fs-overline);
  color: var(--c-on-dark);
  text-align: center;
}
.hook__stars { display: inline-flex; gap: 2px; color: var(--c-brass); }
.hook__stars svg { width: 13px; height: 13px; fill: currentColor; }

/* Desktop only. Below lg the hero stacks (copy + hook card) and runs well past
   one screen, so a "scroll" affordance signals nothing the user hasn't already
   done — and the bottom of the viewport there belongs to the sticky mobile CTA
   bar, which the cue's 38px dot would sit behind. */
.hero__scroll-cue { display: none; }
@media (min-width: 64rem) {
  .hero__scroll-cue {
    position: absolute; left: 50%; bottom: var(--sp-6);
    transform: translateX(-50%);
    display: inline-flex; flex-direction: column; align-items: center; gap: var(--sp-2);
    color: var(--c-warm-white); font-size: var(--fs-overline); letter-spacing: .14em; text-transform: uppercase;
  }
}
.hero__scroll-cue .dot {
  width: 2px; height: 38px; border-radius: 2px;
  background: linear-gradient(var(--c-brass), transparent);
}

/* --------------------------------------------------------------------------
   TRUST BAR
   -------------------------------------------------------------------------- */
/* The bar carries its own themed surface. Without this it inherited the page
   ground while its type stayed on-dark — light text on warm-white, invisible. */
.trust-bar {
  padding-block: clamp(1.75rem, 1rem + 2vw, 2.75rem);
  background: var(--bg);
  color: var(--fg);
}
.trust-bar .container {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: center;
  gap: var(--sp-6) clamp(1.5rem, .5rem + 3vw, 4rem);
}
.trust-item {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  color: var(--c-on-dark); font-size: var(--fs-small);
}
.trust-item .trust-item__mark {
  font-family: var(--ff-display); font-size: 1.5rem; line-height: 1;
  color: var(--c-brass);
}
.trust-item strong { color: var(--c-warm-white); display: block; font-weight: 600; }
.trust-item small { color: var(--c-on-dark); }
.trust-sep { width: 1px; height: 2rem; background: var(--c-line-dark); display: none; }

/* Four chips: 1 → 2 → 4 across, never 3 + 1 orphan. The vertical rules become
   column borders so the grid keeps whole cells. Used by every trust bar
   (homepage, locations hub) — the markup is identical on both, so the chips sit
   directly in .container with no wrapper. */
.trust-bar > .container {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-5) 0;
  justify-items: start;
}
@media (min-width: 30rem) {
  .trust-bar > .container { grid-template-columns: 1fr 1fr; }
  .trust-bar > .container > .trust-item:nth-child(3),
  .trust-bar > .container > .trust-item:nth-child(7) {
    border-left: 1px solid var(--line);
    padding-left: clamp(1.25rem, .5rem + 2vw, 2.5rem);
  }
}
/* md 768px — all four chips on ONE line. Equal fractions, each chip wrapping
   its own label, so the row can never fall back to a 3 + 1 orphan. */
@media (min-width: 48rem) {
  .trust-bar > .container { grid-template-columns: repeat(4, 1fr); }
  .trust-bar > .container > .trust-item:not(:first-child) {
    border-left: 1px solid var(--line);
    padding-left: clamp(1rem, .25rem + 1.5vw, 2.5rem);
  }
}
.trust-bar > .container > .trust-sep { display: none; }

/* --------------------------------------------------------------------------
   CARDS (shared base + variants)
   -------------------------------------------------------------------------- */
.card {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--card-bg, rgba(255, 255, 255, .03));
  border: 1px solid var(--line);
  transition: transform var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out);
}
.card__body { padding: var(--sp-6); }

/* Service card — image top, content below; hover lift + brass border */
.card--service { display: flex; flex-direction: column; }
.card--service .card__media { aspect-ratio: 3 / 2; overflow: hidden; }
.card--service .card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease-out); }
.card--service .card__body { padding: var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-3); flex: 1; }
.card--service .card__icon { width: 2rem; height: 2rem; color: var(--accent); }
.card--service .card__icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; }
.card--service h3 { color: var(--heading); }
.card--service p { color: var(--fg); font-size: var(--fs-small); }
.card--service .card__link { margin-top: auto; }
.card--service:hover { transform: translateY(-6px); border-color: var(--accent); box-shadow: var(--shadow-md); }
.card--service:hover .card__media img { transform: scale(1.05); }
/* whole-card click affordance: stretch the title link over the card */
.card__stretch::after { content: ""; position: absolute; inset: 0; }

/* "All services" router card — no photo; a quiet brass-tinted panel that
   centres its content and fills the same height as its photo-topped siblings. */
.card--service-all {
  justify-content: center;
  background:
    radial-gradient(120% 90% at 100% 0%, rgba(201,163,106,.14), transparent 55%),
    linear-gradient(180deg, rgba(201,163,106,.06), rgba(201,163,106,.02));
  border-color: rgba(201,163,106,.35);
}
.card--service-all .card__body { gap: var(--sp-4); }
.card--service-all .card__icon { width: 2.5rem; height: 2.5rem; }
.card--service-all h3 { font-size: var(--fs-lead); }
.card--service-all:hover { transform: translateY(-6px); border-color: var(--accent); box-shadow: var(--shadow-md); }

/* Project / case-study card */
.card--project { display: block; }
.card--project .card__media { aspect-ratio: 4 / 3; overflow: hidden; }
.card--project .card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease-out); }
.card--project:hover .card__media img { transform: scale(1.06); }
.card--project:hover { transform: translateY(-6px); border-color: var(--accent); box-shadow: var(--shadow-md); }
.card--project .card__body { padding: var(--sp-5) var(--sp-5) var(--sp-6); }
.card--project .card__meta {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
  margin-top: var(--sp-3); font-size: var(--fs-overline);
  text-transform: uppercase; letter-spacing: .1em; color: var(--accent);
}
.card--project .card__meta span { display: inline-flex; align-items: center; gap: .35rem; }
.card--project h3 { color: var(--heading); }
.card--project .card__client { color: var(--fg); font-size: var(--fs-small); margin-top: var(--sp-2); }

/* Testimonial card */
.card--testimonial {
  display: flex; flex-direction: column; gap: var(--sp-4);
  padding: var(--sp-6);
  background: var(--c-off-white);
  border-color: var(--c-line-light);
}
.card--testimonial .quote { color: var(--c-base); font-size: var(--fs-body); line-height: 1.6; }
.card--testimonial .quote::before { content: "\201C"; color: var(--c-brass-deep); font-family: var(--ff-display); font-size: 2.5rem; line-height: 0; vertical-align: -.35em; margin-right: .1em; }
.card--testimonial .attrib { display: flex; align-items: center; gap: var(--sp-3); margin-top: auto; }
.card--testimonial .avatar {
  width: 2.75rem; height: 2.75rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--c-base); color: var(--c-brass);
  font-family: var(--ff-display); font-size: 1.1rem; flex: 0 0 auto;
}
.card--testimonial .attrib b { color: var(--c-base); display: block; font-weight: 600; font-size: var(--fs-small); }
.card--testimonial .attrib small { color: var(--c-muted); }

/* Reviews link inside a review attribution / rating meta line ("… · Read more reviews →").
   Underlined rather than recoloured: the global rule is `a { color: inherit; text-decoration: none }`,
   so without this the link is byte-for-byte indistinguishable from the text around it (verified in
   Chrome on /portfolio: link and parent both rgb(197,189,179), decoration none). Brass-deep is not
   the fix — on the card's --c-off-white surface it measures 2.7:1, below AA; the muted meta colour
   it inherits already passes at 5.1:1, so the underline carries the affordance and colour is left
   alone. Covers all three markup families that host this link. */
.card--testimonial .attrib small a,
.ex-quote figcaption small a,
.rating .meta a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  white-space: nowrap;   /* .ex-quote's caption column is 256px: without this the → orphans on its own line */
}
.card--testimonial .attrib small a:hover { color: var(--c-base); }
.ex-quote figcaption small a:hover,
.rating .meta a:hover { color: var(--accent); }

/* Suite Guarantee card — dark with brass border accent (class name .card--promise kept: renaming
   the selector would touch every page for no user-visible gain) */
.card--promise {
  padding: var(--sp-8) var(--sp-6);
  background: rgba(255, 255, 255, .02);
  border: 1px solid var(--c-line-dark);
  display: flex; flex-direction: column; gap: var(--sp-3);
}
.card--promise::before {            /* top brass accent rule */
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--c-brass), var(--c-brass-deep));
  transform: scaleX(1); transform-origin: left;
  transition: transform var(--dur-slow) var(--ease-out);
}
.card--promise:hover {
  transform: translateY(-4px);
  border-color: var(--c-brass-deep);
  box-shadow: var(--shadow-md);
}
.card--promise .card__num {
  font-family: var(--ff-display); font-style: italic;
  font-size: 1.5rem; color: var(--c-brass);
}
.card--promise .card__icon { width: 2.25rem; height: 2.25rem; color: var(--c-brass); }
.card--promise .card__icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; }
.card--promise h3 { color: var(--c-warm-white); }
.card--promise p { color: var(--c-on-dark); font-size: var(--fs-small); }

/* --------------------------------------------------------------------------
   STATS
   -------------------------------------------------------------------------- */
.stat { text-align: center; }
.stat__num {
  font-family: var(--ff-display); font-style: italic;
  font-size: var(--fs-display); line-height: 1; color: var(--accent);
}
.stat__label {
  margin-top: var(--sp-2);
  font-size: var(--fs-overline); letter-spacing: .12em; text-transform: uppercase; color: var(--fg);
}

/* --------------------------------------------------------------------------
   PILLS (service areas)
   -------------------------------------------------------------------------- */
.pill-group { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.pill {
  display: inline-flex; align-items: center; gap: .4rem;
  min-height: 2.75rem;
  padding: .6rem 1.15rem;
  border: 1px solid var(--accent);
  border-radius: 999px;
  color: var(--heading);
  font-size: var(--fs-small); font-weight: 500;
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.pill:hover, .pill:focus-visible { background: var(--c-brass); color: var(--c-base); transform: translateY(-2px); }

/* --------------------------------------------------------------------------
   CTA BAND
   -------------------------------------------------------------------------- */
.cta-band { text-align: center; }
.cta-band .container { max-width: 48rem; }
.cta-band h2 { font-size: var(--fs-h1); }
.cta-band p { margin-top: var(--sp-4); color: var(--fg); font-size: var(--fs-lead); }
.cta-band .btn-group { margin-top: var(--sp-8); justify-content: center; }

/* Kitchen page — unique split CTA: editorial left + start-a-project form right */
.cta2a { display: grid; grid-template-columns: 1fr; gap: clamp(2rem,1rem + 4vw,4.5rem); align-items: center; }
@media (min-width: 62rem) { .cta2a { grid-template-columns: 1.1fr .9fr; } }
.cta2a h2 { font-size: var(--fs-h1); }
.cta2a > div > p { margin-top: var(--sp-4); color: var(--fg); font-size: var(--fs-lead); }
.cta2a .cta2-phone { margin-top: var(--sp-6); font-size: var(--fs-small); color: var(--c-on-dark); }
.cta2a .cta2-phone a { color: var(--c-brass); }
.cta2a-cross { margin-top: var(--sp-10); padding-top: var(--sp-6); border-top: 1px solid var(--line); text-align: center; font-size: var(--fs-small); color: var(--c-on-dark); }
.cta2a-cross a { color: var(--c-brass); }

/* ---- CTA cinematic band: tinted-image bg, centred, 1·2·3 steps ---- */
.cta2c-inner { text-align: center; max-width: 46rem; margin-inline: auto; }
.cta2c-inner h2 { font-size: var(--fs-h1); }
.cta2c-inner > p { margin-top: var(--sp-4); color: var(--fg); font-size: var(--fs-lead); }
.cta2c-rule { width: 3rem; height: 1px; background: var(--accent); margin: 0 auto var(--sp-5); }
.cta-steps { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-4) 0; margin: var(--sp-8) 0; }
.cta-step { display: flex; align-items: center; gap: var(--sp-3); padding: 0 clamp(1rem,.5rem + 1.5vw,2rem); }
.cta-step + .cta-step { border-left: 1px solid var(--line); }
.cta-step__n { width: 2rem; height: 2rem; border-radius: 50%; border: 1px solid var(--accent); color: var(--accent); display: grid; place-items: center; font-family: var(--ff-display); font-variant-numeric: tabular-nums; flex: none; }
.cta-step__t { color: var(--heading); font-size: var(--fs-small); text-align: left; }
.cta2c-cross { margin-top: var(--sp-8); font-size: var(--fs-small); color: var(--c-on-dark); text-align: center; }
.cta2c-cross a { color: var(--c-brass); }

/* --------------------------------------------------------------------------
   FOOTER
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--c-base-deep);
  color: var(--c-on-dark);
  padding-block: clamp(3rem, 2rem + 4vw, 5rem) var(--sp-8);
  border-top: 1px solid var(--c-line-dark);
}
/* Mobile is two columns: the brand block and the NAP block each span the full
   width, and the two link lists (Services / Company) sit side by side. That
   roughly halves the footer's height on a phone (~1090px -> ~600px) without
   hiding any link. The 40rem/48rem/64rem media queries below take over from there. */
.footer__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-10) var(--sp-6);
}
.footer__grid > .footer__brand { grid-column: 1 / -1; }
.footer__grid > .footer__col:last-child { grid-column: 1 / -1; }
.footer__brand img { height: 2.1rem; width: auto; margin-bottom: var(--sp-4); }
.footer__brand p { color: var(--c-on-dark); font-size: var(--fs-small); max-width: 22rem; }
.footer__social { display: flex; gap: var(--sp-3); margin-top: var(--sp-5); }
.footer__social a {
  width: 2.5rem; height: 2.5rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--c-line-dark); color: var(--c-warm-white);
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
.footer__social a:hover { background: rgba(201, 163, 106, .16); color: var(--c-brass); border-color: var(--c-brass); }
.footer__social svg { width: 1.1rem; height: 1.1rem; fill: currentColor; }

.footer__col .footer__h {
  font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-overline);
  letter-spacing: .14em; text-transform: uppercase; color: var(--c-brass);
  margin-bottom: var(--sp-4);
}
.footer__col ul { display: flex; flex-direction: column; gap: var(--sp-3); }
.footer__col a { font-size: var(--fs-small); color: var(--c-on-dark); transition: color var(--dur) var(--ease-out); }
.footer__col a:hover { color: var(--c-brass); }

.footer__nap { font-style: normal; font-size: var(--fs-small); line-height: 1.8; }
.footer__nap a { color: var(--c-on-dark); }
.footer__nap a:hover { color: var(--c-brass); }
.footer__nap .label { color: var(--c-warm-white); font-weight: 600; }

.footer__bottom {
  margin-top: var(--sp-12);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--c-line-dark);
  display: flex; flex-wrap: wrap; gap: var(--sp-4);
  align-items: center; justify-content: space-between;
  font-size: var(--fs-overline); color: var(--c-on-dark);
}
.footer__bottom nav { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.footer__bottom a:hover { color: var(--c-brass); }

/* Agency credit — groups with the legal links on the right of the bottom bar.
   Colour is inherited (a{color:inherit}), so at rest it matches Privacy/Terms.
   The "·" separator lives in the 40rem block below, not here: it must not render
   at the widths where the credit wraps onto its own line under the legal nav. */
.footer__legal { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4); }
.footer__credit a { transition: color var(--dur) var(--ease-out); }
.footer__bottom a[href*="bigfox"]:hover { color: #FE701F; }   /* Big Fox brand orange */

/* --------------------------------------------------------------------------
   INTERIOR PAGE HEADER (.page-hero) + BREADCRUMB
   Compact dark header for every non-home page. Reuses the cinematic wash so
   transparent nav links stay legible over the background photo.
   -------------------------------------------------------------------------- */
.page-hero {
  position: relative;
  padding-top: clamp(7.5rem, 5rem + 9vw, 11rem);
  padding-bottom: clamp(3rem, 2rem + 5vw, 5.5rem);
  overflow: hidden;
  isolation: isolate;
  background: var(--c-base);
}
.page-hero__media { position: absolute; inset: 0; z-index: -2; }
.page-hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: center 35%; }
.page-hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(20, 17, 15, .72) 0%, rgba(20, 17, 15, .55) 45%, rgba(20, 17, 15, .92) 100%),
    linear-gradient(90deg, rgba(20, 17, 15, .85) 0%, rgba(20, 17, 15, .4) 70%, transparent 100%);
}
.page-hero__inner { max-width: 50rem; }
.page-hero h1 { color: var(--c-white); margin-top: var(--sp-4); }
.page-hero h1 em { color: var(--c-brass); font-style: italic; }
.page-hero .lead { margin-top: var(--sp-5); max-width: 42rem; color: var(--c-warm-white); }
.page-hero .btn-group { margin-top: var(--sp-8); }

.breadcrumb { font-size: var(--fs-overline); }
.breadcrumb ol {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  letter-spacing: .12em; text-transform: uppercase; color: var(--c-on-dark);
}
.breadcrumb li { display: inline-flex; align-items: center; gap: .5rem; }
.breadcrumb li + li::before { content: "/"; color: var(--c-brass); opacity: .6; }
.breadcrumb a { color: var(--c-on-dark); transition: color var(--dur) var(--ease-out); }
.breadcrumb a:hover { color: var(--c-brass); }
.breadcrumb [aria-current="page"] { color: var(--c-warm-white); }

/* --------------------------------------------------------------------------
   SCROLL-HERO (.scroll-hero) — cinematic scroll-driven canvas hero.
   A tall scroll-driver wrapping a sticky full-viewport stage. The dark stage
   keeps the white wordmark + nav links legible; the transformation frames sit
   on a warm-white "plate" (matching the renders' white background) inset to the
   side, realising the right-hand asset slot the homepage reserved (.hero__3d).
   Logic in js/scroll-hero.js scrubs frames + reveals captions; this degrades to
   the static poster <img> with no JS / reduced-motion. Reuses brand tokens.
   -------------------------------------------------------------------------- */
.scroll-hero {
  position: relative;
  height: var(--hero-h, 550svh);   /* scroll distance: ~360svh scrub + ~90svh end-hold (see SCRUB_END in scroll-hero.js) */
  background: var(--c-base);
}
.scroll-hero__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  isolation: isolate;
  display: flex;
  align-items: center;
  padding-top: clamp(6rem, 4rem + 6vw, 8rem);
  padding-bottom: clamp(2.5rem, 1.5rem + 4vw, 4rem);
  background:
    radial-gradient(120% 90% at 72% 38%, rgba(201, 163, 106, .07), transparent 62%),
    var(--c-base);
}
/* Copy floats above the full-stage backdrop + scrim. */
.scroll-hero .container { position: relative; z-index: 2; }
.scroll-hero__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 1rem + 3vw, 3rem);
  align-items: center;
  width: 100%;
}
.scroll-hero__inner { max-width: 38rem; }
.scroll-hero__inner .overline { margin-bottom: var(--sp-3); }
.scroll-hero h1 { color: var(--c-white); margin-top: var(--sp-2); }
.scroll-hero h1 em { color: var(--c-brass); font-style: italic; }
/* Lead is hidden on phones (it would push the sticky stage past 100svh; the
   intro section restates it). It returns at md where there's room. */
.scroll-hero .lead { display: none; margin-top: var(--sp-4); max-width: 34rem; color: var(--c-warm-white); }
.scroll-hero__actions {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-5) var(--sp-6);
  margin-top: var(--sp-6);
}
.scroll-hero__actions .rating__score { font-size: 2rem; }
.scroll-hero__actions .meta { color: var(--c-warm-white); font-size: var(--fs-small); }
.scroll-hero__actions .meta strong { color: var(--c-white); }

/* Full-stage backdrop the transformation frames are drawn onto — the kitchen
   fills the whole sticky stage and the copy floats over it (see .container z-index). */
.scroll-hero__viewport {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: var(--c-base);
}
/* Scrim for legible copy over the photo. Phones/tablets: top+bottom darkening
   (copy is centred over the image). Paints above the canvas, below the captions.
   The first (top) layer darkens behind the fixed nav (~5rem tall) so the white
   nav links stay legible while the nav itself remains transparent. */
.scroll-hero__viewport::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(14, 12, 11, .82) 0, rgba(14, 12, 11, .58) 5rem, rgba(14, 12, 11, 0) 9rem),
    linear-gradient(180deg, rgba(14, 12, 11, .55) 0%, rgba(14, 12, 11, .30) 40%, rgba(14, 12, 11, .72) 100%);
}
.scroll-hero__poster,
.scroll-hero__canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.scroll-hero__canvas {
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
  z-index: 1;
}
.scroll-hero[data-shf-ready="true"] .scroll-hero__canvas { opacity: 1; }
.scroll-hero[data-shf-ready="true"] .scroll-hero__poster { opacity: 0; transition: opacity var(--dur-slow) var(--ease-out); }

/* Caption cards — dark glass over the kitchen backdrop; revealed by scroll progress. */
.scroll-hero__cap {
  position: absolute;
  left: clamp(.75rem, .3rem + 2vw, 1.5rem);
  bottom: clamp(.75rem, .3rem + 2vw, 1.5rem);
  z-index: 2;
  max-width: min(22rem, 78%);
  margin: 0;
  padding: var(--sp-4) var(--sp-5);
  background: rgba(14, 12, 11, .82);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid var(--c-line-dark);
  border-left: 3px solid var(--c-brass);
  border-radius: var(--radius);
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
  pointer-events: none;
}
.scroll-hero__cap.is-visible { opacity: 1; transform: translateY(0); }
.scroll-hero__cap .scroll-hero__cap-tag {
  display: block;
  font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-overline);
  letter-spacing: .14em; text-transform: uppercase; color: var(--c-brass);
  margin-bottom: var(--sp-2);
}
.scroll-hero__cap p { color: var(--c-warm-white); font-size: var(--fs-small); line-height: 1.5; }

/* Scroll cue — fades out once the scrub begins. */
.scroll-hero__cue {
  position: absolute; left: 50%; bottom: var(--sp-5);
  transform: translateX(-50%);
  z-index: 2;
  display: inline-flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  color: var(--c-warm-white); font-size: var(--fs-overline);
  letter-spacing: .14em; text-transform: uppercase;
  transition: opacity var(--dur) var(--ease-out);
}
.scroll-hero__cue .dot { width: 2px; height: 38px; border-radius: 2px; background: linear-gradient(var(--c-brass), transparent); }
.scroll-hero[data-shf-cue="hidden"] .scroll-hero__cue { opacity: 0; }

/* Short viewports (landscape phones) — drop the secondary bits so the H1 +
   CTA still fit the sticky stage without clipping. */
@media (max-height: 34rem) {
  .scroll-hero__stage { padding-top: 4.25rem; padding-bottom: var(--sp-3); }
  .scroll-hero .breadcrumb,
  .scroll-hero__inner .overline { display: none; }
}

/* Show the lead only when there's room on BOTH axes (keeps short landscape
   windows from overflowing the sticky 100svh stage). */
@media (min-width: 48rem) and (min-height: 46rem) {
  .scroll-hero .lead { display: block; }
}

/* lg 1024 — copy floats over the left of the backdrop; the kitchen reads clear
   on the right, and captions annotate it from the bottom-right. */
@media (min-width: 64rem) {
  /* Left-weighted scrim: dark behind the copy, fully clear over the kitchen at
     right, plus a soft bottom vignette to ground the captions. */
  .scroll-hero__viewport::after {
    background:
      linear-gradient(180deg, rgba(14, 12, 11, .82) 0, rgba(14, 12, 11, .58) 5rem, rgba(14, 12, 11, 0) 9rem),
      linear-gradient(90deg,
        rgba(14, 12, 11, .94) 0%, rgba(14, 12, 11, .74) 24%,
        rgba(14, 12, 11, .34) 50%, rgba(14, 12, 11, 0) 76%),
      linear-gradient(0deg, rgba(14, 12, 11, .45), rgba(14, 12, 11, 0) 42%);
  }
  .scroll-hero__cap { left: auto; right: clamp(1.5rem, -1rem + 5vw, 4rem); max-width: min(26rem, 40%); }
  /* cue stays bottom-centred (default left:50% / translateX(-50%)) — clear of the corner cards */
}

/* --------------------------------------------------------------------------
   BIO CARD (team members) — portrait + narrative
   -------------------------------------------------------------------------- */
.bio-card {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-6);
  padding: var(--sp-6);
  background: var(--card-bg, rgba(255, 255, 255, .03));
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}
.bio-card__portrait {
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: linear-gradient(160deg, rgba(201, 163, 106, .12), rgba(201, 163, 106, .02));
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-2); text-align: center; padding: var(--sp-4);
}
/* Photo variant — image fills the frame (monogram styling above stays a fallback) */
.bio-card__portrait--photo { padding: 0; background: none; }
.bio-card__portrait img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
.bio-card__mono {
  font-family: var(--ff-display);
  font-size: clamp(2.5rem, 2rem + 2vw, 3.25rem);
  line-height: 1; color: var(--accent);
}
.bio-card__portrait small {
  font-size: var(--fs-overline); letter-spacing: .14em; text-transform: uppercase; color: var(--fg);
}
.bio-card__role {
  display: block;
  font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-overline);
  letter-spacing: .14em; text-transform: uppercase; color: var(--accent);
  margin-bottom: var(--sp-2);
}
.bio-card h3 { color: var(--heading); }
.bio-card__body > * + * { margin-top: var(--sp-3); }
.bio-card__body p { color: var(--fg); font-size: var(--fs-small); }
.bio-card__cite { display: flex; align-items: center; gap: var(--sp-2); }
.bio-card__cite .stars svg { width: .9em; height: .9em; }
.bio-card__cite cite { font-style: normal; color: var(--c-muted); font-size: var(--fs-small); }

/* --------------------------------------------------------------------------
   FOUNDER CARDS (home team section) — portrait beside a short bio, footer-aligned link
   -------------------------------------------------------------------------- */
.tm5a-grid { display: grid; grid-template-columns: 1fr; gap: var(--sp-6); max-width: 60rem; margin-inline: auto; }
.tm5a-card { display: grid; grid-template-columns: 1fr; border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; }
.tm5a-card__pic { aspect-ratio: 4 / 5; overflow: hidden; }
.tm5a-card__pic img { width: 100%; height: 100%; object-fit: cover; }
.tm5a-card__body { display: flex; flex-direction: column; padding: var(--sp-6); }
.tm5a-card__role { font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-overline); letter-spacing: .14em; text-transform: uppercase; color: var(--accent); }
.tm5a-card h3 { color: var(--heading); margin-top: var(--sp-2); }
.tm5a-card__q { color: var(--fg); font-size: var(--fs-small); margin-top: var(--sp-3); line-height: 1.6; }
.tm5a-card__q em { color: var(--heading); }
.tm5a-foot { margin-top: auto; padding-top: var(--sp-5); }
.tm5a-foot .btn { margin-top: 0; }
@media (min-width: 34rem) {
  .tm5a-card { grid-template-columns: 10rem 1fr; }
  .tm5a-card__pic { aspect-ratio: auto; }
}
@media (min-width: 52rem) {
  .tm5a-grid { grid-template-columns: 1fr 1fr; }
}

/* --------------------------------------------------------------------------
   FEATURE (icon + heading + text) — values, why-us, service highlights
   -------------------------------------------------------------------------- */
.feature { display: flex; flex-direction: column; gap: var(--sp-3); }
.feature__icon { width: 2.25rem; height: 2.25rem; color: var(--accent); }
.feature__icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; }
.feature h3 { color: var(--heading); font-size: var(--fs-h3); }
.feature p { color: var(--fg); font-size: var(--fs-small); }

/* --------------------------------------------------------------------------
   PROCESS TIMELINE (.process) — numbered steps on a vertical brass rail.
   Mobile-first single rail; recolours per section theme (marker bg = --bg so
   the connecting line never shows through). Put data-anim="stagger" on
   .process to reveal steps in sequence.
   -------------------------------------------------------------------------- */
.process { display: grid; gap: 0; }
.process__step {
  position: relative;
  display: grid;
  grid-template-columns: 3rem 1fr;
  gap: var(--sp-5);
  padding-bottom: var(--sp-10);
}
.process__step:last-child { padding-bottom: 0; }
/* connecting rail — runs from below this marker to the next step */
.process__step::before {
  content: "";
  position: absolute;
  left: 1.5rem;
  top: 3.25rem;
  bottom: 0;
  width: 2px;
  background: var(--line);
  transform: translateX(-1px);
}
.process__step:last-child::before { display: none; }
.process__marker {
  position: relative;
  z-index: 1;
  width: 3rem; height: 3rem;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--ff-display); font-style: italic; font-size: 1.25rem;
  color: var(--accent);
  border: 1px solid var(--accent);
  background: var(--bg);
  transition: background var(--dur) var(--ease-out),
              color var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out);
}

/* Scroll-driven progress rail — opt-in via [data-process-rail] on .process.
   js/animations.js scrubs --seg (0→1) per step as it travels up; the connector
   below each marker fills brass, and the reached marker lights up. Degrades to
   the static rail when JS/motion is off (--seg defaults to 0 = no fill). */
@property --seg { syntax: "<number>"; inherits: false; initial-value: 0; }
.process[data-process-rail] .process__step::before {
  background: linear-gradient(
    var(--accent) calc(var(--seg, 0) * 100%),
    var(--line)   calc(var(--seg, 0) * 100%));
}
.process[data-process-rail] .process__marker.is-active {
  background: var(--accent);
  color: var(--c-base);
  border-color: var(--accent);
  box-shadow: 0 0 0 5px rgba(201, 163, 106, .14);
}
.process__body { padding-top: .35rem; }
.process__tag {
  display: inline-block;
  font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-overline);
  letter-spacing: .14em; text-transform: uppercase; color: var(--accent);
  margin-bottom: var(--sp-2);
}
.process__body h3 { color: var(--heading); }
.process__body p { color: var(--fg); font-size: var(--fs-small); margin-top: var(--sp-3); }

/* sm 640px — give the step content a comfortable measure beside the rail */
@media (min-width: 40rem) {
  .process__step { grid-template-columns: 3.5rem 1fr; gap: var(--sp-8); }
  .process__step::before { left: 1.75rem; }
  .process__body { max-width: 44rem; }
}

/* --------------------------------------------------------------------------
   BACK-TO-TOP — fixed brass disc, fades in after the first viewport.
   Toggled by [data-visible] from main.js (§6). Reuses the brand arrow icon
   rotated upward. Hidden from tab order until visible (visibility:hidden).
   -------------------------------------------------------------------------- */
.to-top {
  position: fixed;
  right: clamp(1rem, .4rem + 2vw, 2rem);
  bottom: clamp(1rem, .4rem + 2vw, 2rem);
  z-index: var(--z-sticky);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  background: var(--c-brass);
  color: var(--c-base);
  border-radius: 50%;
  box-shadow: var(--shadow-md);
  opacity: 0;
  visibility: hidden;
  transform: translateY(1rem);
  transition: opacity var(--dur) var(--ease-out),
              transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              visibility var(--dur);
}
.to-top[data-visible="true"] { opacity: 1; visibility: visible; transform: translateY(0); }
.to-top:hover { background: var(--c-brass-deep); box-shadow: var(--shadow-brass); }
.to-top[data-visible="true"]:hover { transform: translateY(-2px); }
.to-top:active { transform: translateY(0) scale(.96); }
.to-top__icon { width: 1.25rem; height: 1.25rem; transform: rotate(-90deg); }

@media (prefers-reduced-motion: reduce) {
  .to-top,
  .to-top[data-visible="true"],
  .to-top[data-visible="true"]:hover,
  .to-top:active { transform: none; }
}

/* --------------------------------------------------------------------------
   CASE STUDY — shared components for the /work/ project case-study template.
   Reads the section theme tokens (--bg/--fg/--heading/--accent/--line) so each
   block recolours inside any .section--* theme. Promoted out of the old inline
   <style> block so all four case studies share one source of truth.
   -------------------------------------------------------------------------- */

/* Project spec grid — Location · Type · Investment · Duration */
.case-meta { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); }
@media (min-width: 40rem) { .case-meta { grid-template-columns: repeat(4, 1fr); } }
.case-meta__item {
  display: flex; flex-direction: column;
  background: rgba(255, 255, 255, .04);
  border: 1px solid rgba(201, 163, 106, .2);
  border-radius: var(--radius-lg);
  padding: var(--sp-4);
}
.case-meta__item .label {
  font-size: var(--fs-overline); text-transform: uppercase;
  letter-spacing: .1em; color: var(--c-brass); margin-bottom: var(--sp-3);
}
.case-meta__item strong {
  margin-top: auto; display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-body); color: #fff; line-height: 1.25;
}
.case-meta__item svg { flex: none; width: 16px; height: 16px; color: var(--c-brass); }

/* Brass-accented "promise" chips under the meta grid — three balanced cards,
   each proof point in a brass badge, sized to span the row like the meta grid. */
.case-highlight {
  margin-top: var(--sp-5);
  display: grid; grid-template-columns: 1fr; gap: var(--sp-3);
}
@media (min-width: 40rem) { .case-highlight { grid-template-columns: repeat(3, 1fr); } }
.case-highlight span {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  background: rgba(255, 255, 255, .04);
  border: 1px solid rgba(201, 163, 106, .2);
  border-radius: var(--radius-lg);
  color: var(--c-warm-white); font-size: var(--fs-small); font-weight: 500;
  text-align: center;
}
.case-highlight svg {
  flex: 0 0 auto; width: 1.7rem; height: 1.7rem; padding: .42rem;
  border-radius: 50%; background: rgba(201, 163, 106, .14);
  color: var(--c-brass); stroke: currentColor; fill: none; box-sizing: border-box;
}

/* Story photos */
.case-photo { width: 100%; border-radius: var(--radius-lg); overflow: hidden; margin-bottom: var(--sp-6); }
.case-photo img { width: 100%; display: block; }
.case-photo-grid { display: grid; grid-template-columns: 1fr; gap: var(--sp-4); }
@media (min-width: 40rem) { .case-photo-grid { grid-template-columns: 1fr 1fr; } }
/* Grid photos crop to a uniform 3:2 so paired cells always match height,
   regardless of each source image's native aspect ratio. */
.case-photo-grid .case-photo { margin-bottom: 0; aspect-ratio: 3 / 2; }
.case-photo-grid .case-photo img { height: 100%; object-fit: cover; }

/* Captioned photo — capture-date line under a documentary case-study photo.
   Colour inherits from the section so it reads on both dark and light bands. */
.case-figure { margin: 0 0 var(--sp-6); }
.case-figure .case-photo { margin-bottom: 0; }
.case-caption { margin-top: var(--sp-3); font-size: var(--fs-small); color: inherit; opacity: .66; text-align: center; }

/* Author byline — real named person under a case-study hero (sits on the dark hero) */
.case-byline { margin-top: var(--sp-5); font-size: var(--fs-small); color: var(--c-on-dark); line-height: 1.6; }
.case-byline strong { color: var(--c-warm-white); font-weight: 600; }
.case-byline a { color: var(--c-brass); text-decoration: underline; text-underline-offset: 2px; }
.case-byline a:hover { color: var(--c-brass-deep); }

/* --- BEFORE / AFTER comparison slider ----------------------------------------
   Accessible range-input drives --pos (0–100); the "before" layer is clipped to
   that width over the full "after" layer. No JS / reduced-motion → the inline
   --pos:50 still renders a valid static 50/50 split. Keyboard-operable via the
   native range thumb. */
.case-ba {
  position: relative;
  aspect-ratio: 3 / 2;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid rgba(201, 163, 106, .25);
  --pos: 50;
  touch-action: pan-y;
}
.case-ba img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.case-ba__before { clip-path: inset(0 calc((100 - var(--pos)) * 1%) 0 0); z-index: 1; }
.case-ba__tag {
  position: absolute; top: var(--sp-4); z-index: 2;
  font-size: var(--fs-overline); letter-spacing: .14em; text-transform: uppercase;
  padding: .35rem .7rem; border-radius: var(--radius);
  background: rgba(14, 12, 11, .78); color: var(--c-warm-white);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.case-ba__tag--before { left: var(--sp-4); z-index: 2; }
.case-ba__tag--after { right: var(--sp-4); }
/* Vertical divider + grabbable handle, tracking --pos */
.case-ba__line {
  position: absolute; top: 0; bottom: 0; z-index: 2;
  left: calc(var(--pos) * 1%); transform: translateX(-50%);
  width: 2px; background: var(--c-brass); pointer-events: none;
}
.case-ba__handle {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 2.75rem; height: 2.75rem; border-radius: 50%;
  background: var(--c-brass); color: var(--c-base);
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-md);
}
.case-ba__handle svg { width: 1.4rem; height: 1.4rem; fill: currentColor; }
/* The real control — transparent range on top, full-bleed, ew-resize cursor */
.case-ba__range {
  position: absolute; inset: 0; z-index: 3;
  width: 100%; height: 100%; margin: 0;
  background: transparent; cursor: ew-resize; opacity: 0;
  -webkit-appearance: none; appearance: none;
}
.case-ba__range::-webkit-slider-thumb { -webkit-appearance: none; width: 3rem; height: 100%; cursor: ew-resize; }
.case-ba__range::-moz-range-thumb { width: 3rem; height: 100%; border: 0; background: transparent; cursor: ew-resize; }
.case-ba__range:focus-visible { outline: none; }
.case-ba__range:focus-visible ~ .case-ba__handle { box-shadow: 0 0 0 4px rgba(201, 163, 106, .4), var(--shadow-md); }

/* Note shown when the image is a placeholder mock-up (swap-in pending) */
.case-ba__note {
  margin-top: var(--sp-3); font-size: var(--fs-overline); letter-spacing: .06em;
  color: var(--fg, var(--c-muted)); text-align: center;
}

/* --- Scope checklist — distinct cards, each anchored by a brass check chip ---*/
.case-scope { display: grid; gap: var(--sp-4); list-style: none; margin: 0; padding: 0; }
@media (min-width: 40rem) { .case-scope { grid-template-columns: 1fr 1fr; } }
.case-scope li {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-6);
  background: var(--c-white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  color: var(--heading);
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: 1.45;
  transition: transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out);
}
.case-scope li:hover {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  box-shadow: var(--shadow-md);
}
/* Brass check chip — a tinted disc that separates each point and fills on hover */
.case-scope svg {
  flex: 0 0 auto;
  box-sizing: border-box;
  width: 2.5rem;
  height: 2.5rem;
  padding: .6rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  stroke: currentColor;
  fill: none;
  transition: background var(--dur) var(--ease-out),
              color var(--dur) var(--ease-out),
              transform var(--dur) var(--ease-out);
}
.case-scope li:hover svg {
  background: var(--accent);
  color: var(--c-white);
  transform: scale(1.05);
}

/* --- Mini-FAQ (native <details> accordion) ----------------------------------*/
.case-faq { max-width: 48rem; margin-inline: auto; }
.case-faq details { border-bottom: 1px solid var(--line); }
.case-faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  padding: var(--sp-5) 0; cursor: pointer; list-style: none;
  font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--heading);
}
.case-faq summary::-webkit-details-marker { display: none; }
.case-faq summary svg { flex: 0 0 auto; width: 1rem; height: 1rem; fill: var(--accent); transition: transform var(--dur) var(--ease-out); }
.case-faq details[open] summary svg { transform: rotate(180deg); }
.case-faq details p { padding-bottom: var(--sp-5); margin: 0; color: var(--fg); font-size: var(--fs-small); line-height: 1.6; }

/* --- Sticky mobile conversion bar -------------------------------------------
   Persistent call/quote actions on phones; hidden once the desktop nav (with its
   own phone + CTA) appears at lg. Body gets .has-sticky-cta to reserve space and
   lift the back-to-top disc clear of the bar. */
.case-sticky {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sticky);
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--c-line-dark); border-top: 1px solid var(--c-brass);
}
.case-sticky a {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 3.5rem; font-weight: 600; font-size: var(--fs-small); letter-spacing: .04em;
}
.case-sticky svg { width: 1.05em; height: 1.05em; }
.case-sticky .is-call { background: var(--c-base-deep); color: var(--c-warm-white); }
.case-sticky .is-call svg { fill: var(--c-brass); }
.case-sticky .is-quote { background: var(--c-brass); color: var(--c-base); text-transform: uppercase; }
body.has-sticky-cta { padding-bottom: 3.5rem; }
body.has-sticky-cta .to-top { bottom: 4.25rem; }
@media (min-width: 64rem) {
  .case-sticky { display: none; }
  body.has-sticky-cta { padding-bottom: 0; }
  body.has-sticky-cta .to-top { bottom: clamp(1rem, .4rem + 2vw, 2rem); }
}

/* --------------------------------------------------------------------------
   RESPONSIVE
   -------------------------------------------------------------------------- */

/* xs 480px — trust bar separators appear */
@media (min-width: 30rem) {
  .trust-sep { display: block; }
}

/* sm 640px — footer columns split; bio cards go portrait-beside-text */
@media (min-width: 40rem) {
  .footer__grid { grid-template-columns: repeat(2, 1fr); }
  /* Legal links + agency credit share a line from here up (measured: they need
     446px and have 128px of headroom at 640px), so separate them with a dot.
     Below 40rem the credit wraps under the nav and a leading dot would orphan. */
  .footer__credit::before {
    content: "·";           /* fallback: browsers without content alt-text support */
    content: "·" / "";      /* empty alt text — decorative, not announced by AT */
    margin-right: var(--sp-4);
  }
  .bio-card { grid-template-columns: 12rem 1fr; align-items: start; gap: var(--sp-8); padding: var(--sp-8); }
}

/* md 768px — footer 3-col; nav stays in drawer mode */
@media (min-width: 48rem) {
  .footer__grid { grid-template-columns: 1.6fr 1fr 1fr; }
  .footer__grid > .footer__brand,
  .footer__grid > .footer__col:last-child { grid-column: auto; }
}

/* lg 1024px — desktop nav replaces drawer; footer four columns.
   Breakpoint kept at 1024px (not 768px): the 7-item link row + phone + CTA
   totals ~1050px of content, which overflows any tablet viewport below 1024px. */
@media (min-width: 64rem) {
  .nav__links { display: flex; }
  .nav__cta { display: inline-flex; }
  .nav__toggle { display: none; }
  /* True-centered link cluster: logo left · links center · utility right */
  .site-nav .nav__bar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
  }
  .nav__logo    { justify-self: start; }
  .nav__links   { justify-self: center; }
  .nav__utility { justify-self: end; }
  .footer__grid { grid-template-columns: 2fr 1fr 1fr 1.3fr; }
  .footer__grid > .footer__brand,
  .footer__grid > .footer__col:last-child { grid-column: auto; }
  /* Larger logo on real desktops; links stay viewport-centered via the 1fr/auto/1fr grid. */
  .nav__logo img { height: 2.7rem; }
  .nav--scrolled .nav__logo img { height: 2.2rem; }
  /* Hero splits: copy left, hook card right */
  .hero__grid {
    grid-template-columns: minmax(0, 1.05fr) minmax(20rem, .92fr);
    gap: clamp(2.5rem, 1rem + 4vw, 5rem);
    align-items: center;
  }
  /* The scroll cue appears here: 66px (label + gap + 38px dot) + its own 1.5rem
     bottom offset = 90px. The hero's own clamp only reaches that at ~1280px, so
     without this floor the cue overlapped the hook card's trust line from
     1024–1279px. Re-measure if the cue's label size or dot height changes. */
  .hero { --cue-space: 6rem; }
}

/* 2xl 1440px+ — slightly larger nav presence */
@media (min-width: 90rem) {
  .nav__bar { --nav-h: 5.25rem; }
}

/* --------------------------------------------------------------------------
   SHORT-VIEWPORT HERO FIT (height-only queries)
   The fluid type + spacing scale is tuned to viewport WIDTH, so a wide-but-
   short display (e.g. 1440×772 laptop) got full desktop-size copy/form with no
   vertical room — the full-height heroes overflowed past one screen. These
   queries compress only the vertical rhythm so .hero / .scroll-hero /
   .page-hero / .auth fit within the viewport. Tall displays are unaffected.
   -------------------------------------------------------------------------- */
@media (max-height: 50rem) {
  /* Homepage hero — the two-column copy + hook-form layout is the tallest hero.
     Trim padding (still clears the ≤5.25rem nav) + inter-element rhythm. */
  .hero { padding-top: 5.75rem; padding-bottom: var(--sp-6); }
  /* This block reclaims the bottom padding to fit the hero in one screen, which
     leaves no band for the scroll cue to sit in. Drop the cue rather than give
     back the 90px — on a short viewport the hero visibly overflows anyway, so
     the affordance it signals is already self-evident. */
  .hero__scroll-cue { display: none; }
  .hero h1 { margin-top: var(--sp-3); }
  .hero__sub { margin-top: var(--sp-4); }
  .hero__rating { margin-top: var(--sp-4); }
  .hero .btn-group { margin-top: var(--sp-5); }

  /* Hook form — tighten card padding + field rhythm; inputs stay ≥44px (a11y). */
  .hook { padding: clamp(1.1rem, .8rem + 1.5vw, 1.6rem); }
  .hook__sub { margin-top: var(--sp-1); }
  .hook__field { margin-top: var(--sp-3); }
  .hook__field input,
  .hook__field select { min-height: 44px; padding-top: var(--sp-2); padding-bottom: var(--sp-2); }
  .hook__submit { margin-top: var(--sp-4); }
  .hook__trust { margin-top: var(--sp-3); }

  /* Service scroll-hero sticky stage. */
  .scroll-hero__stage { padding-top: 5.75rem; padding-bottom: var(--sp-5); }

  /* Interior page headers — tame the tall top padding so content sits higher. */
  .page-hero {
    padding-top: clamp(6rem, 4.5rem + 4vw, 8rem);
    padding-bottom: clamp(2.5rem, 2rem + 3vw, 4rem);
  }

  /* Client-login card. */
  .auth { padding-top: 5.75rem; padding-bottom: var(--sp-10); }
}

/* Very short displays (landscape phones / small laptops, ≤640px). Even a
   trimmed two-column hero can't fit here, so let the homepage hero size to its
   content (never clip) and drop the secondary copy. */
@media (max-height: 40rem) {
  .hero { min-height: 0; padding-top: 5.5rem; }
  .hero__sub,
  .hook__sub { display: none; }
  .hook__field { margin-top: var(--sp-2); }
  .scroll-hero__stage { padding-top: 5.25rem; }
}

/* Nav bar is intentionally full-bleed at every width — logo anchored left, utility
   anchored right, links viewport-centered. (No ultra-wide max-width cap; the gutter
   grows at 3xl/4K via --gutter, so the bar never crowds the screen edges.) */

/* --------------------------------------------------------------------------
   PROMISE ROW (/suite-guarantee — the named commitments + the written terms)
   Alternating photo + editorial copy. The copy column drives the row height
   and the photo stretches to match it (no fixed aspect ratio at md+), so the
   short copy never floats in a sea of dead space beside an over-tall portrait.
   The lead statement gets a brass rule accent to mark it as the headline
   promise, distinct from the supporting body copy.
   -------------------------------------------------------------------------- */
.promise { display: grid; gap: clamp(2rem, 1rem + 4vw, 5rem); }
.promise + .promise { margin-top: var(--sp-20); }

.promise__copy {
  display: flex; flex-direction: column; justify-content: center;
  gap: var(--sp-6);
}
.promise__copy .overline { color: var(--c-brass); }
.promise__copy h2 { font-size: var(--fs-h1); margin: 0; }

.promise__head { display: flex; flex-direction: column; gap: var(--sp-3); }
.promise__body { display: flex; flex-direction: column; gap: var(--sp-4); }
.promise__body p { color: var(--c-on-dark); margin: 0; }

/* Lead accent — brass rule + brighter, larger type sets the commitment apart. */
.promise__lead {
  margin: 0;
  padding: var(--sp-1) 0 var(--sp-1) var(--sp-5);
  border-left: 3px solid var(--c-brass);
  color: var(--c-warm-white);
  font-size: var(--fs-lead);
  line-height: 1.55;
}

.promise__media {
  overflow: hidden; border-radius: var(--radius-lg);
  aspect-ratio: 4 / 5;          /* portrait crop while stacked on mobile */
}
.promise__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* md 768px — two columns; the photo stretches to the copy's height. */
@media (min-width: 48rem) {
  .promise { grid-template-columns: 1fr 1fr; align-items: stretch; }
  .promise__media { aspect-ratio: auto; height: 100%; min-height: 26rem; }
  .promise--reverse .promise__media { order: -1; }
}

/* --------------------------------------------------------------------------
   INTRO / STORY ROW — same treatment applied site-wide (homepage, About, Our
   Process, services hub + pages, locations). The copy column drives the row
   height; the .intro__media photo stretches to match it (align-self:stretch,
   image absolute) instead of floating beside an over-tall portrait. The lead
   inside an intro grid gets the brass rule accent — matched to .promise — via
   :has() so no per-page lead markup is needed (graceful no-op if unsupported).
   -------------------------------------------------------------------------- */
.grid:has(.intro__media) .lead {
  border-left: 3px solid var(--c-brass);
  padding-left: var(--sp-5);
}

@media (min-width: 48rem) {
  /* Top-anchor both columns and give the photo a FIXED portrait ratio. Its
     height no longer tracks the copy column, so it ends around the body copy
     instead of stretching down to the trade-tags / CTA — and it never grows
     with the amount of text. The text simply flows on below it. */
  .grid:has(.intro__media) > * { align-self: start; }
  .intro__media { aspect-ratio: 5 / 6; }
}

/* ==========================================================================
   BLOG POST / COST GUIDE  (long-form editorial article)
   Dark hero → light reading surface → sticky TOC rail (lg+) → dark CTA.
   Structure ported from the Diamond Bright article template; restyled to
   Dark Editorial Luxe tokens. Used by /blog/*-cost-*.html cost guides.
   ========================================================================== */

/* ---- Hero (dark section): breadcrumb, eyebrow, H1, dek, byline ---- */
.post-hero__inner { max-width: 54rem; }
.post-hero .breadcrumb { margin-bottom: var(--sp-6); }
.post-hero h1 { margin-top: var(--sp-4); }
.post-hero__dek {
  margin-top: var(--sp-5);
  max-width: 44rem;
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: var(--c-warm-white);
}
.post-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3);
  margin-top: var(--sp-6);
  font-size: var(--fs-small);
  color: var(--c-on-dark);
}
.post-meta a { color: var(--c-brass); }
.post-meta a:hover { color: var(--c-brass-deep); text-decoration: underline; }
.post-meta .post-meta__sep { opacity: .5; }
.post-meta__avatar {
  width: 1.75rem; height: 1.75rem; border-radius: 50%;
  object-fit: cover; border: 1px solid var(--c-line-dark);
}

/* ---- Reading-progress bar (blog posts only; stamped by propagate_post_nav.py) ----
   Pinned to the BOTTOM edge of the nav (Paul, 2026-07-29), so it grows along the
   nav's own hairline rather than across the top of the screen. It is NOT a child
   of .site-nav — the nav is propagated chrome shared by 51 pages, and this is a
   blog-post component — so it pins itself with --nav-h-scrolled (main.css).
   That is the CONDENSED nav height, which is the right one at every moment the
   bar is visible: progress only leaves 0 once the reader is ~700px into the
   article, by which point .nav--scrolled has long since applied. At scrollY 0
   the nav is taller, but the bar is at scaleX(0) and invisible, so the gap can
   never be seen.
   The fill is driven by --p (0–1), set on the container by js/post.js, and the
   bar SCALES rather than resizing so the fill stays compositor-only. With no JS
   --p is never set, the bar sits at scaleX(0) and nothing renders — which is also
   why there is no track.
   Deliberately no transition: the bar must track scroll 1:1, so it has no motion
   of its own for prefers-reduced-motion to reduce.
   Range is the article top → the bottom of #faq, NOT the whole document — see
   the standing-rule block in CLAUDE.md. */
.read-progress {
  position: fixed; inset: var(--nav-h-scrolled) 0 auto 0; height: 3px;
  z-index: calc(var(--z-nav) + 1);   /* over the nav, under --z-drawer */
  pointer-events: none;              /* never eat clicks under the nav edge */
}
.read-progress__bar {
  display: block; height: 100%;
  background: var(--c-brass);
  transform: scaleX(var(--p, 0));
  transform-origin: left center;
  will-change: transform;
}

/* ---- Article layout: single column → body + sticky rail at lg ---- */
.post-layout { display: grid; gap: var(--sp-10); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 64rem) {
  /* Default `align-items: stretch` is required, not `start`: the aside column
     must stretch to the full row height so its `position: sticky` child has
     room to travel. With `start` the column collapses to the TOC's height and
     the sticky rail scrolls away with the page. */
  .post-layout { grid-template-columns: minmax(0, 1fr) 15rem; gap: var(--sp-16); }
}
.post-body { min-width: 0; max-width: 44rem; }

/* ---- Desktop sticky TOC + share rail (hidden below lg) ---- */
.post-aside { display: none; }
@media (min-width: 64rem) {
  .post-aside { display: block; }
  .post-aside__sticky { position: sticky; top: 6rem; }
}
.post-toc__title {
  font-family: var(--ff-body); font-weight: 600;
  font-size: var(--fs-overline); letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); margin-bottom: var(--sp-3);
}
.post-toc ol { display: flex; flex-direction: column; gap: 1px; }
.post-toc a {
  display: block; padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-small); line-height: 1.35; color: var(--c-muted);
  border-left: 2px solid var(--c-line-light);
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
.post-toc a:hover, .post-toc a[aria-current="true"] {
  color: var(--c-base); border-color: var(--c-brass-deep);
}

/* ---- Mobile TOC (native <details>, hidden at lg+) ---- */
.post-toc-m {
  margin-bottom: var(--sp-8);
  border: 1px solid var(--c-line-light); border-radius: var(--radius-lg);
  background: var(--c-white);
}
@media (min-width: 64rem) { .post-toc-m { display: none; } }
.post-toc-m > summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5); cursor: pointer; list-style: none;
  font-family: var(--ff-body); font-weight: 600;
  font-size: var(--fs-overline); letter-spacing: .12em; text-transform: uppercase;
  color: var(--c-base);
}
.post-toc-m > summary::-webkit-details-marker { display: none; }
.post-toc-m > summary::after {
  content: ""; width: .6rem; height: .6rem; flex: none;
  border-right: 2px solid var(--c-brass-deep); border-bottom: 2px solid var(--c-brass-deep);
  transform: rotate(45deg); transition: transform var(--dur) var(--ease-out);
}
.post-toc-m[open] > summary::after { transform: rotate(-135deg); }
.post-toc-m .post-toc { padding: 0 var(--sp-3) var(--sp-4); }

/* ---- Short-answer AEO callout ---- */
.short-answer {
  margin-bottom: var(--sp-8);
  padding: var(--sp-5) var(--sp-6);
  background: rgba(201, 163, 106, .10);
  border: 1px solid rgba(201, 163, 106, .30);
  border-left: 3px solid var(--c-brass-deep);
  border-radius: var(--radius-lg);
}
.short-answer__label {
  font-family: var(--ff-body); font-weight: 600;
  font-size: var(--fs-overline); letter-spacing: .12em; text-transform: uppercase;
  color: var(--c-brass-deep); margin-bottom: var(--sp-2);
}
.short-answer__body { font-size: var(--fs-lead); line-height: 1.5; color: var(--c-base); }

/* ---- Article prose ---- */
.article-body { color: var(--c-muted); }
/* Prose keeps the same 46rem measure as the .section-head above it. A body column
   wider than its own h2 reads as oversized type — .container--narrow is 813px of
   content, .section-head is 736px, so unconstrained prose out-ran its heading. */
.container--narrow .article-body { max-width: 46rem; }
.article-body > * + * { margin-top: var(--sp-5); }
.article-body h2 {
  margin-top: var(--sp-12); color: var(--c-base);
  font-size: var(--fs-h2); line-height: 1.14; scroll-margin-top: 6rem;
}
.article-body h2 + p { margin-top: var(--sp-5); }
.article-body h3 { margin-top: var(--sp-8); color: var(--c-base); }
.article-body p { line-height: var(--lh-body); }
.article-body strong, .article-body b { color: var(--c-base); font-weight: 600; }
.article-body a {
  color: var(--c-brass-deep); text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: 2px;
}
.article-body a:hover { color: var(--c-base); }
.article-body ul, .article-body ol { padding-left: var(--sp-6); }
.article-body ul > li { list-style: disc; }
.article-body ol > li { list-style: decimal; }
.article-body li { margin-top: var(--sp-3); padding-left: var(--sp-2); }
.article-body li::marker { color: var(--c-brass-deep); }
.article-hr { height: 1px; border: 0; background: var(--c-line-light); margin: var(--sp-10) 0; }

/* ---- Cost tables (scroll on small screens) ---- */
.cost-table { overflow-x: auto; -webkit-overflow-scrolling: touch; margin-top: var(--sp-6); }
/* Prose resuming after a table needs the same step a heading gets (was 0) */
.cost-table + .article-body { margin-top: var(--sp-8); }
.cost-table table {
  width: 100%; border-collapse: collapse; min-width: 30rem;
  font-size: var(--fs-small); background: var(--c-white); border-radius: var(--radius-lg);
  overflow: hidden;
}
.cost-table thead th {
  background: var(--c-base); color: var(--c-warm-white);
  font-family: var(--ff-body); font-weight: 600; letter-spacing: .04em;
  text-align: left; padding: var(--sp-3) var(--sp-4); vertical-align: bottom;
}
.cost-table tbody th, .cost-table tbody td {
  padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--c-line-light);
  text-align: left; vertical-align: top; color: var(--c-muted);
}
.cost-table tbody th { color: var(--c-base); font-weight: 600; }
.cost-table tbody tr:nth-child(even) { background: var(--c-off-white); }
.cost-table .price { color: var(--c-brass-deep); font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.table-note { margin-top: var(--sp-3); font-size: var(--fs-small); color: var(--c-muted); font-style: italic; }

/* ---- Criteria table: 4 prose columns at lg, stacked labelled rows below ----
   Promoted out of blog/renovation-contractor-calgary-how-to-choose 2026-07-29,
   where it lived in a scoped <style> as `.compare-table` — a name left over from
   the named-competitor grid that was cut (D0.3). That version set no padding, no
   border-collapse and no vertical-align, so every cell fell back to the UA
   defaults (~1px padding, middle-aligned numbers), and its `min-width: 46rem`
   was WIDER than the 44rem `.post-body` prose cap, so it scrolled sideways at
   EVERY viewport, 4K included.
   Four prose columns do not fit a 44rem measure, so below lg each row reflows to
   one stacked block per row instead of scrolling. `.criteria-table__k` carries
   the stacked-view labels as REAL text rather than ::before generated content,
   which screen readers announce inconsistently; it is display:none at lg, where
   the <th scope="col"> headers do that job. The row header is the criterion, not
   the number — a bare numeral is useless as a row label. */
.criteria-table { margin: var(--sp-6) 0; }
.criteria-table table {
  width: 100%; border-collapse: collapse; font-size: var(--fs-small);
  background: var(--c-white); border-radius: var(--radius-lg); overflow: hidden;
}
.criteria-table__n {
  font-family: var(--ff-display); color: var(--c-brass-deep);
  font-variant-numeric: tabular-nums; line-height: 1.2;
}
.criteria-table small { color: var(--c-muted); font-weight: 400; }

/* Stacked view (below 72rem): one block per row, each cell labelled.
   The switch is 72rem, NOT the lg 64rem breakpoint, and the number is measured:
   64rem is also where `.post-aside` appears and takes 240px + a 4rem gap out of
   the row, so at 1024px the body column is only 638px and the 4-column table ran
   to 5-line rows (138px each). The column first clears ~776px at 72rem. Same
   reasoning as `.usp-b` holding single-column until 72rem. */
@media (max-width: 71.999rem) {
  .criteria-table table, .criteria-table tbody, .criteria-table tr,
  .criteria-table tbody th, .criteria-table tbody td { display: block; }
  .criteria-table thead { display: none; }
  .criteria-table tbody tr {
    position: relative;
    padding: var(--sp-5) var(--sp-5) var(--sp-5) calc(var(--sp-5) + 2rem);
    border-top: 1px solid var(--c-line-light);
  }
  .criteria-table tbody tr:first-child { border-top: 0; }
  .criteria-table tbody tr:nth-child(even) { background: var(--c-off-white); }
  .criteria-table__n {
    position: absolute; left: var(--sp-5); top: var(--sp-5);
    font-size: 1.125rem;
  }
  .criteria-table tbody th[scope="row"] {
    text-align: left; color: var(--c-base); font-weight: 600;
    font-size: var(--fs-body); line-height: 1.35;
  }
  .criteria-table tbody td { color: var(--c-muted); line-height: var(--lh-body); }
  .criteria-table th[scope="row"] + td, .criteria-table td + td { margin-top: var(--sp-4); }
  .criteria-table__k {
    display: block; margin-bottom: var(--sp-1);
    font-size: var(--fs-overline); font-weight: 600; letter-spacing: .12em;
    text-transform: uppercase; color: var(--c-brass-deep);
  }
}

/* Table view (72rem+): the body column finally has room for all four columns. */
@media (min-width: 72rem) {
  .criteria-table__k { display: none; }

  /* Breakout: let the table use the FULL .post-layout body column instead of the
     44rem prose measure. At 1440px the column is 925px while .post-body caps at
     704px, so 221px sat empty beside a table wrapping to 4 lines per row.
     Done by moving the cap off .post-body and onto its descendants rather than
     by a negative margin: the slack is not a constant (≈0px at 1024px, 221px at
     1440px, 208px at 1920px), so any hardcoded offset would overflow the page at
     some widths. This way the table simply inherits the grid column's real width,
     whatever it is, and needs no recomputing if the container tokens change.
     `:has()` scopes it to posts that actually carry the table — every other blog
     post keeps the plain 44rem cap. The intermediate max-widths reproduce the
     inherited 44rem exactly, so prose is pixel-identical. */
  .post-body:has(.criteria-table) { max-width: none; }
  .post-body:has(.criteria-table) > *,
  .post-body:has(.criteria-table) > .article-body > * { max-width: 44rem; }
  .post-body:has(.criteria-table) > .article-body { max-width: none; }
  /* 72rem ceiling so the breakout can't run away on big screens: `--maxw` steps
     up at 160rem and 240rem, which would take this table to 1232px at 2560px and
     1488px at 3840px — a ~85-character line in the widest column. 72rem holds
     that column near 480px (~65 characters) and leaves 1440px untouched, where
     the column is 925px anyway. */
  .post-body:has(.criteria-table) > .article-body > .criteria-table { max-width: 72rem; }
  /* Fixed layout so the long "how to check" column can't starve the others. */
  .criteria-table table { table-layout: fixed; }
  .criteria-table thead th {
    background: var(--c-base); color: var(--c-warm-white);
    font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-overline);
    letter-spacing: .06em; text-align: left; vertical-align: bottom;
    padding: var(--sp-3) var(--sp-4);
  }
  .criteria-table thead th:first-child { padding-right: 0; }
  .criteria-table thead th:nth-child(1) { width: 2.25rem; }
  .criteria-table thead th:nth-child(2) { width: 25%; }
  .criteria-table thead th:nth-child(3) { width: 31%; }
  .criteria-table tbody th, .criteria-table tbody td {
    padding: var(--sp-4); border-top: 1px solid var(--c-line-light);
    /* vertical-align:top — the UA default `middle` floated the row numbers into
       the vertical centre of tall rows. Numbers sit with the row's first line. */
    text-align: left; vertical-align: top;
    color: var(--c-muted); line-height: 1.5;
  }
  .criteria-table tbody th[scope="row"] { color: var(--c-base); font-weight: 600; }
  .criteria-table tbody tr:nth-child(even) { background: var(--c-off-white); }
  .criteria-table__n { padding-right: 0; font-size: 1rem; }
}

/* ---- Timeline: full-width heading, two-col paragraph, horizontal numbered rail ---- */
.timeline-cols { display: grid; grid-template-columns: 1fr; gap: var(--sp-4) clamp(2rem,1rem + 3vw,3.5rem); margin-top: var(--sp-6); }
@media (min-width: 62rem) { .timeline-cols { grid-template-columns: 1fr 1fr; } }
.timeline-cols p { color: var(--fg); }
.timeline-rail { position: relative; display: grid; grid-template-columns: 1fr; gap: var(--sp-8) var(--sp-6); margin-top: var(--sp-12); }
@media (min-width: 40rem) { .timeline-rail { grid-template-columns: repeat(2,1fr); } }
@media (min-width: 62rem) {
  .timeline-rail { grid-template-columns: repeat(4,1fr); }
  .timeline-rail::before { content: ""; position: absolute; top: 1.3rem; left: 1.3rem; right: 1.3rem; height: 1px; background: var(--line); }
}
.timeline-step__n { width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 1px solid var(--accent); color: var(--accent); display: grid; place-items: center; background: var(--bg); position: relative; z-index: 1; font-family: var(--ff-display); font-variant-numeric: tabular-nums; }
.timeline-step__phase { font-family: var(--ff-display); font-size: var(--fs-lead); color: var(--heading); margin-top: var(--sp-4); }
.timeline-step__win { color: var(--accent); font-weight: 600; font-variant-numeric: tabular-nums; margin-top: var(--sp-1); }
.timeline-step__win small { color: var(--c-muted); font-weight: 400; }

/* ---- Cost: full-width heading, answer left, price-tier cards right ---- */
.cost-split__grid { display: grid; grid-template-columns: 1fr; gap: clamp(2rem,1rem + 4vw,4rem); align-items: start; margin-top: var(--sp-8); }
@media (min-width: 62rem) { .cost-split__grid { grid-template-columns: 1fr 1.05fr; } .cost-split__intro { position: sticky; top: var(--sp-8); } }
.cost-tiers { display: grid; gap: var(--sp-4); }
.cost-tier { display: grid; grid-template-columns: 1fr auto; gap: var(--sp-2) var(--sp-5); align-items: baseline; background: var(--c-white); border: 1px solid var(--c-line-light); border-radius: var(--radius-lg); padding: var(--sp-6); }
.cost-tier__name { font-family: var(--ff-display); font-size: var(--fs-lead); color: var(--c-base); }
.cost-tier__name small { display: block; font-family: var(--ff-body); font-size: .8rem; color: var(--c-muted); font-weight: 400; margin-top: 2px; }
.cost-tier__price { color: var(--c-brass-deep); font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; font-size: 1.05rem; }
.cost-tier__covers { grid-column: 1 / -1; color: var(--c-muted); font-size: var(--fs-small); border-top: 1px solid var(--c-line-light); padding-top: var(--sp-4); margin-top: var(--sp-1); }

/* ---- Process: vertical numbered stepper on a single centered spine ---- */
.proc-list { position: relative; max-width: 52rem; margin: var(--sp-10) auto 0; }
.proc-list::before { content: ""; position: absolute; left: 1.3rem; top: 1.3rem; bottom: 1.3rem; width: 1px; background: var(--line); }
.proc-row { position: relative; display: grid; grid-template-columns: 2.6rem 1fr; gap: var(--sp-6); padding-block: var(--sp-5); align-items: center; }
.proc-mark { width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 1px solid var(--accent); color: var(--accent); display: grid; place-items: center; background: var(--bg); z-index: 1; font-family: var(--ff-display); font-variant-numeric: tabular-nums; }
.proc-row h3 { font-family: var(--ff-display); font-size: var(--fs-lead); color: var(--heading); }
.proc-row p { color: var(--fg); margin-top: var(--sp-2); max-width: 60ch; }

/* ---- Living in your home: framing left, protections checklist right, tinted bg ---- */
.lv-hasbg { position: relative; overflow: hidden; }
.lv-bg { position: absolute; inset: 0; z-index: 0; }
.lv-bg img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(.25); }
.lv-bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(20,17,15,.96) 0%, rgba(20,17,15,.9) 48%, rgba(20,17,15,.82) 100%); }
.lv-hasbg > .container { position: relative; z-index: 1; }
.lv-split { display: grid; grid-template-columns: 1fr; gap: clamp(2rem,1rem + 4vw,4rem); align-items: start; }
@media (min-width: 62rem) { .lv-split { grid-template-columns: .9fr 1.1fr; } .lv-split__intro { position: sticky; top: var(--sp-8); } }
.lv-ic { width: 2.75rem; height: 2.75rem; border: 1px solid var(--accent); border-radius: 50%; display: grid; place-items: center; color: var(--accent); flex: none; }
.lv-ic svg { width: 1.4rem; height: 1.4rem; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.lv-title { font-family: var(--ff-display); font-size: var(--fs-lead); color: var(--heading); }
.lv-detail { color: var(--fg); }
.lv-caveat { color: var(--c-on-dark); font-style: italic; }
.lv-rows { border-top: 1px solid var(--line); }
.lv-row { display: grid; grid-template-columns: 2.75rem 1fr; gap: var(--sp-5); align-items: center; padding: var(--sp-6) 0; border-bottom: 1px solid var(--line); }
.lv-row .lv-detail { font-size: var(--fs-small); margin-top: 2px; }

/* ---- Small kitchens / layout changes: heading, image band, two sub-topics ---- */
.sk-band { position: relative; overflow: hidden; border-radius: var(--radius-lg); aspect-ratio: 24 / 8; margin-top: var(--sp-8); }
.sk-band img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 40%; }
.sk-two { display: grid; grid-template-columns: 1fr; gap: clamp(1.75rem,1rem + 3vw,3.5rem); margin-top: var(--sp-10); }
@media (min-width: 52rem) { .sk-two { grid-template-columns: 1fr 1fr; } }
.sk-two h3 { font-family: var(--ff-display); font-size: var(--fs-lead); color: var(--heading); margin-top: var(--sp-3); }
.sk-two p { margin-top: var(--sp-3); color: var(--fg); }

/* Intro (1a) — editorial bullets + byline */
.bi-body { margin-top: var(--sp-12); padding-top: var(--sp-10); border-top: 1px solid var(--line); }
.bi-para { max-width: 68ch; font-size: var(--fs-lead); color: var(--fg); margin-bottom: var(--sp-8); }
.bi-bullets { display: grid; grid-template-columns: 1fr; gap: var(--sp-6) clamp(2rem,1rem + 3vw,3.5rem); }
@media (min-width: 52rem) { .bi-bullets { grid-template-columns: 1fr 1fr; } }
.bi-bullet { border-top: 2px solid var(--accent); padding-top: var(--sp-4); }
.bi-bullet p { color: var(--fg); }
.bi-bullet strong { color: var(--heading); }
.bi-bullet a { color: var(--accent); }
.byline { color: var(--c-muted); font-size: var(--fs-small); margin: 0; }
.byline a { color: var(--c-brass-deep); }

/* What's included — checklist */
.inc-list { list-style: none; display: grid; grid-template-columns: 1fr; gap: var(--sp-4) clamp(2rem,1rem + 3vw,3.5rem); margin-top: var(--sp-8); }
@media (min-width: 52rem) { .inc-list { grid-template-columns: 1fr 1fr; } }
.inc-item { display: grid; grid-template-columns: 1.6rem 1fr; gap: var(--sp-4); align-items: start; padding: var(--sp-4) 0; border-bottom: 1px solid var(--line); color: var(--fg); }
.inc-check { width: 1.6rem; height: 1.6rem; border: 1px solid var(--accent); border-radius: 50%; display: grid; place-items: center; color: var(--accent); flex: none; margin-top: 2px; }
.inc-check svg { width: 1rem; height: 1rem; fill: none; stroke: currentColor; stroke-width: 2; }

/* ---- Pull-stat ---- */
.pull-stat {
  margin: var(--sp-8) 0; padding: var(--sp-5) 0;
  border-top: 1px solid var(--c-line-light); border-bottom: 1px solid var(--c-line-light);
  display: flex; align-items: baseline; gap: var(--sp-4); flex-wrap: wrap;
}
.pull-stat__num {
  font-family: var(--ff-display); font-size: clamp(2.25rem, 1.5rem + 3vw, 3.25rem);
  line-height: 1; color: var(--c-brass-deep); font-variant-numeric: tabular-nums;
}
.pull-stat__lbl { font-size: var(--fs-small); color: var(--c-muted); max-width: 22rem; }

/* ---- Figures ---- */
.article-figure { margin: var(--sp-8) 0; }
.article-figure img { width: 100%; border-radius: var(--radius-lg); }
.article-figure figcaption {
  margin-top: var(--sp-3); font-size: var(--fs-small); font-style: italic; color: var(--c-muted);
}

/* ---- Provenance / disclaimer note ---- */
.article-note {
  margin-top: var(--sp-6); padding: var(--sp-4) var(--sp-5);
  background: var(--c-off-white); border: 1px solid var(--c-line-light);
  border-radius: var(--radius); font-size: var(--fs-small); color: var(--c-muted);
}

/* ---- Inline "read more" link row ---- */
.article-more { margin-top: var(--sp-5); }
.article-more a {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-overline); letter-spacing: .1em; text-transform: uppercase;
  font-weight: 600; color: var(--c-brass-deep); text-decoration: none;
}
.article-more a svg { width: 1.1em; height: 1.1em; fill: none; stroke: currentColor; stroke-width: 2; }
.article-more a:hover svg { transform: translateX(3px); }
.article-more a svg { transition: transform var(--dur) var(--ease-out); }

/* ---- End-of-post author card ---- */
.author-card {
  display: flex; gap: var(--sp-4); align-items: flex-start;
  margin-top: var(--sp-12); padding-top: var(--sp-8);
  border-top: 1px solid var(--c-line-light);
}
.author-card__avatar {
  width: 3.25rem; height: 3.25rem; border-radius: 50%; flex: none;
  object-fit: cover; border: 1px solid var(--c-line-light); background: var(--c-off-white);
}
.author-card__name { font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--c-base); }
.author-card__role { font-size: var(--fs-small); color: var(--c-muted); margin-top: var(--sp-1); }

/* ---- Share row ---- */
.post-share { margin-top: var(--sp-8); }
.post-toc + .post-share { margin-top: var(--sp-8); padding-top: var(--sp-6); border-top: 1px solid var(--c-line-light); }
.post-share__label {
  font-family: var(--ff-body); font-weight: 600;
  font-size: var(--fs-overline); letter-spacing: .12em; text-transform: uppercase;
  color: var(--c-muted); margin-bottom: var(--sp-3);
}
.post-share__row { display: flex; gap: var(--sp-3); }
.post-share__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem; border-radius: 50%;
  border: 1px solid var(--c-line-light); color: var(--c-muted); background: var(--c-white);
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.post-share__btn svg { width: 1.05rem; height: 1.05rem; }
.post-share__btn:hover { color: var(--c-brass-deep); border-color: var(--c-brass-deep); transform: translateY(-2px); }

/* ---- FAQ (native <details> accordion) ---- */
.post-faq { max-width: 48rem; margin-inline: auto; }
.post-faq details {
  border-bottom: 1px solid var(--line);
}
.post-faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  padding: var(--sp-5) 0; cursor: pointer; list-style: none;
  font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--heading);
}
.post-faq summary::-webkit-details-marker { display: none; }
.post-faq summary::after {
  content: ""; width: .7rem; height: .7rem; flex: none; margin-top: .35rem;
  border-right: 2px solid var(--accent); border-bottom: 2px solid var(--accent);
  transform: rotate(45deg); transition: transform var(--dur) var(--ease-out);
}
.post-faq details[open] summary::after { transform: rotate(-135deg); }
.post-faq details > p { padding: 0 0 var(--sp-5); color: var(--fg); line-height: var(--lh-body); max-width: 44rem; }
.post-faq details > p + p { margin-top: var(--sp-4); }
.post-faq a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

/* ---- Related guides ---- */
.related-card {
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-6); background: var(--c-off-white);
  border: 1px solid var(--c-line-light); border-radius: var(--radius-lg);
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
.related-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.related-card__tag {
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--c-brass-deep);
}
.related-card h3 { color: var(--c-base); font-size: var(--fs-h3); }
.related-card p { color: var(--c-muted); font-size: var(--fs-small); line-height: 1.55; }
.related-card__more { margin-top: auto; font-size: var(--fs-overline); letter-spacing: .1em; text-transform: uppercase; font-weight: 600; color: var(--c-brass-deep); }

/* ==========================================================================
   HOMEPAGE v2 ADDITIONS
   Reusable across page types: floating photo annotation, credential badge
   slots, and a stats band. All read section tokens so they recolour per theme.
   ========================================================================== */

/* Floating editorial annotation over an .intro__media / .promise__media photo */
.usp-annot {
  position: absolute;
  left: clamp(.75rem, .3rem + 2vw, 1.5rem);
  right: clamp(.75rem, .3rem + 2vw, 1.5rem);
  bottom: clamp(.75rem, .3rem + 2vw, 1.5rem);
  z-index: 2;
  max-width: 24rem;
  padding: var(--sp-4) var(--sp-5);
  background: rgba(14, 12, 11, .82);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid var(--c-line-dark);
  border-left: 3px solid var(--c-brass);
  border-radius: var(--radius);
}
.usp-annot .overline { color: var(--c-brass); }
.usp-annot p { color: var(--c-warm-white); font-size: var(--fs-small); line-height: 1.5; margin-top: var(--sp-2); }

/* Credential badge slots (trust bar) — A+ Rated · BBB, Houzz, etc. */
.cred-row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--sp-3) var(--sp-4);
  margin-top: var(--sp-6); padding-top: var(--sp-6);
  border-top: 1px solid var(--c-line-dark);
}
.cred-row__label {
  font-size: var(--fs-overline); letter-spacing: .14em; text-transform: uppercase;
  color: var(--c-on-dark);
}
.cred-badge {
  display: inline-flex; align-items: center; gap: .55rem;
  padding: .55rem 1rem; min-height: 2.75rem;
  border: 1px solid rgba(201, 163, 106, .4);
  border-radius: var(--radius);
  background: rgba(201, 163, 106, .06);
  color: var(--c-warm-white); font-size: var(--fs-small); font-weight: 600;
  transition: border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.cred-badge:hover { border-color: var(--c-brass); background: rgba(201, 163, 106, .12); transform: translateY(-2px); }
.cred-badge svg { width: 1.15rem; height: 1.15rem; fill: var(--c-brass); flex: none; }
.cred-badge .cred-badge__grade { color: var(--c-brass); font-family: var(--ff-display); font-style: italic; font-size: 1.15rem; line-height: 1; }
.cred-badge small { color: var(--c-on-dark); font-weight: 500; font-size: var(--fs-overline); letter-spacing: .08em; text-transform: uppercase; }

/* Stats band — count-up figures on a dividing rail */
.stats-band {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-8) var(--sp-4);
}
.stats-band .stat { position: relative; }
@media (min-width: 40rem) {
  .stats-band { grid-template-columns: repeat(4, 1fr); }
  .stats-band .stat + .stat::before {
    content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
    height: 3.5rem; width: 1px; background: var(--c-line-dark);
  }
}

/* Suite Promise — photo-anchored (plate left, hairline pillar rows right) */
.pr-split { display: grid; grid-template-columns: 1fr; gap: var(--sp-8); align-items: stretch; }
.pr-plate { position: relative; border-radius: var(--radius-lg); overflow: hidden; min-height: 22rem; }
.pr-plate img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.pr-plate__cap { position: absolute; left: 1.5rem; right: 1.5rem; bottom: 1.5rem; background: rgba(14,12,11,.82); border-left: 3px solid var(--c-brass); border-radius: 4px; padding: 1rem 1.25rem; backdrop-filter: blur(8px); }
.pr-rows { display: flex; flex-direction: column; justify-content: center; }
.pr-row { display: grid; grid-template-columns: 3rem 1fr; gap: var(--sp-5); padding: var(--sp-6) 0; border-top: 1px solid var(--c-line-dark); }
.pr-row:first-child { border-top: 0; padding-top: 0; }
.pr-row__ic { width: 2.4rem; height: 2.4rem; color: var(--c-brass); }
.pr-row__ic svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.pr-row h3 { color: var(--c-warm-white); display: flex; align-items: baseline; gap: .6rem; }
.pr-row h3 .n { font-family: var(--ff-display); font-style: italic; font-size: 1rem; color: var(--c-brass); }
.pr-row p { color: var(--c-on-dark); font-size: var(--fs-small); margin-top: var(--sp-2); line-height: 1.55; }
@media (min-width: 60rem) { .pr-split { grid-template-columns: .9fr 1.1fr; } }

/* One accountable team — coordination diagram (hub + four icon nodes on a ring) */
.usp-b { display: grid; grid-template-columns: 1fr; gap: clamp(2rem,1rem + 4vw,4.5rem); align-items: center; }
/* The orbit's side nodes overhang the ring by ~70px each, so the two-column form
   needs a column of >=503px before the east node clears the viewport. That means a
   ~1120px viewport; 72rem gives comfortable margin. Below this the section stacks,
   which gives the ring the full container width. Was 62rem, which overflowed by
   ~11px in the 992-1010px band. */
@media (min-width: 72rem) { .usp-b { grid-template-columns: 1fr 1fr; } }
.hub { position: relative; aspect-ratio: 1/1; max-width: 27rem; margin-inline: auto; width: 100%; }
.hub__ring { position: absolute; inset: 8%; border: 1px solid rgba(201,163,106,.4); border-radius: 50%; }
.hub__ring::after { content: ""; position: absolute; inset: 14%; border: 1px solid rgba(201,163,106,.16); border-radius: 50%; }
.hub__center { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); width: 44%; aspect-ratio: 1/1; border-radius: 50%; border: 1px solid var(--c-brass); background: var(--c-base-deep); box-shadow: 0 0 0 8px rgba(201,163,106,.06), inset 0 0 30px rgba(0,0,0,.6), var(--shadow-md); display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 1.1rem; }
.hub__center img { width: 66%; height: auto; }
.hub__center span { font-size: var(--fs-overline); letter-spacing: .16em; text-transform: uppercase; color: var(--c-warm-white); margin-top: .75rem; padding-top: .7rem; line-height: 1.35; border-top: 1px solid rgba(201,163,106,.5); }
.node { position: absolute; width: 8.5rem; transform: translate(-50%,-50%); display: flex; flex-direction: column; align-items: center; text-align: center; gap: .5rem; }
.node__badge { width: 4.25rem; height: 4.25rem; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: var(--c-base-deep); border: 1px solid rgba(201,163,106,.5); box-shadow: 0 0 0 6px var(--bg), var(--shadow-md); transition: border-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out); }
.node__badge svg { width: 2.1rem; height: 2.1rem; fill: none; stroke: var(--c-brass); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.node:hover .node__badge { border-color: var(--c-brass); transform: translateY(-3px); box-shadow: 0 0 0 6px var(--bg), 0 0 0 10px rgba(201,163,106,.12), var(--shadow-md); }
/* Recolours per section theme — on a warm/offwhite band --c-warm-white was
   invisible against the identical background. */
.node__label { font-family: var(--ff-display); font-style: italic; color: var(--heading); font-size: 1.05rem; line-height: 1.2; }
.node--n { left: 50%; top: 8%; }
.node--e { left: 92%; top: 50%; }
.node--s { left: 50%; top: 92%; }
.node--w { left: 8%; top: 50%; }

/* Below lg the ring cannot hold these label lengths — the side nodes overhang the
   ring by half their own width, and shrinking the ring to compensate drives the
   labels into the centre disc. On phones and small tablets the orbit becomes a
   2x2 grid under the centre badge instead: nothing overlaps, nothing shrinks
   below readable size. The ring is unchanged at >=48rem. */
@media (max-width: 47.99rem) {
  .hub {
    aspect-ratio: auto;
    max-width: 100%;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-8) var(--sp-5);
    justify-items: center;
    align-items: start;
  }
  .hub__ring { display: none; }
  .hub__center {
    position: static;
    transform: none;
    grid-column: 1 / -1;
    width: min(15rem, 58vw);
    margin-inline: auto;
    margin-bottom: var(--sp-4);
  }
  .node {
    position: static;
    transform: none;
    width: 100%;
    left: auto; top: auto;
  }
}

/* FAQ — two-column (sticky ask-us aside) + native accordion */
.faq-2 { display: grid; grid-template-columns: 1fr; gap: clamp(2rem,1rem + 4vw,4rem); align-items: start; }
@media (min-width: 60rem) { .faq-2 { grid-template-columns: 20rem 1fr; } }
.faq-aside { border: 1px solid var(--c-line-light); border-radius: var(--radius-lg); padding: var(--sp-8); background: rgba(201,163,106,.04); }
@media (min-width: 60rem) { .faq-aside { position: sticky; top: var(--sp-8); } }
.faq-aside h2 { color: var(--heading); font-size: var(--fs-h2); overflow-wrap: normal; }
.faq-aside p { color: var(--fg); font-size: var(--fs-small); margin-top: var(--sp-3); }
.faq-acc { min-width: 0; }
/* Scoped to details.faq-item: /faq uses <li class="faq-item"> with its own page-level
   border styling, and an unscoped .faq-item border-top doubled its separator rules. */
details.faq-item { border-top: 1px solid var(--c-line-light); }
details.faq-item:last-of-type { border-bottom: 1px solid var(--c-line-light); }
.faq-item summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-5); padding: var(--sp-6) 0; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary h3 { font-size: var(--fs-lead); color: var(--heading); }
.faq-item summary:hover h3 { color: var(--c-brass-deep); }
.faq-ic { flex: none; width: 1.6rem; height: 1.6rem; position: relative; }
.faq-ic::before, .faq-ic::after { content: ""; position: absolute; background: var(--c-brass-deep); transition: transform var(--dur) var(--ease-out), opacity var(--dur) var(--ease-out); }
.faq-ic::before { left: 0; right: 0; top: 50%; height: 2px; transform: translateY(-50%); }
.faq-ic::after { top: 0; bottom: 0; left: 50%; width: 2px; transform: translateX(-50%); }
.faq-item[open] .faq-ic::after { opacity: 0; transform: translateX(-50%) rotate(90deg); }
.faq-a { padding: 0 0 var(--sp-6); max-width: 62ch; }
.faq-a p { color: var(--fg); }
.faq-item:focus-visible { outline: 2px solid var(--c-brass); outline-offset: 2px; }


/* Intro row, fill variant — media stretches to the (taller) copy column height
   instead of sitting in a fixed 5/6 box, so long-copy intros have no void beside
   the photo. Opt in per section with .intro-row--fill on the grid. */
.intro-row--fill:has(.intro__media) > * { align-self: stretch; }
.intro-row--fill .intro__media { aspect-ratio: auto; min-height: 22rem; }

/* Service intro — editorial opener: heading + image paired at the top (balanced
   heights), then the dense prose in magazine columns full-width beneath, with a
   byline + CTA footer rule. Handles long service copy without a wall-of-text row. */
.svc-intro__top { display: grid; grid-template-columns: 1fr; gap: clamp(1.75rem,1rem + 3vw,3.25rem); align-items: center; }
.svc-intro__hook h2 { margin-top: var(--sp-5); }
.svc-intro__hook .lead { margin-top: var(--sp-6); border-left: 3px solid var(--c-brass); padding-left: var(--sp-5); }
.svc-intro__fig { position: relative; overflow: hidden; border-radius: var(--radius-lg); aspect-ratio: 4 / 3; }
.svc-intro__fig img { position: absolute; inset: 0; width: 100%; height: 112%; object-fit: cover; }
.svc-intro__body { margin-top: var(--sp-12); padding-top: var(--sp-10); border-top: 1px solid var(--c-line-light); display: grid; grid-template-columns: 1fr; gap: var(--sp-6); }
.svc-intro__foot { margin-top: var(--sp-8); display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-5) var(--sp-8); }
.svc-intro__foot .byline { margin: 0; }
@media (min-width: 52rem) {
  .svc-intro__top { grid-template-columns: 1.05fr .95fr; align-items: start; }
  .svc-intro__fig { aspect-ratio: 4 / 3; }
  .svc-intro__body { grid-template-columns: 1fr 1fr; column-gap: clamp(2rem,1rem + 3vw,3.5rem); }
}


/* --------------------------------------------------------------------------
   PORTFOLIO — two-axis filter (kind of project × category) + photo grid
   --------------------------------------------------------------------------
   The filter asks two questions that combine, so a visitor can ask for
   "kitchen case studies". Category counts are re-read from the tiles by the
   page script whenever the kind of project changes.
   -------------------------------------------------------------------------- */
.f2 { display: grid; gap: var(--sp-5); justify-items: center; margin-top: var(--sp-8); }
.f2__row { width: 100%; }

/* Control plate — groups both filter rows into one hairline panel so the header
   prose ends and the browsing tool begins. Same card treatment used on dark. */
.f2--plate {
  margin-top: clamp(2.75rem, 2rem + 2.5vw, 4rem);
  gap: var(--sp-6);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, .03);
  padding: clamp(1.5rem, 1rem + 1.5vw, 2.25rem) clamp(1.25rem, .8rem + 2vw, 2.5rem);
}
.f2__cap {
  display: block; text-align: center; margin-bottom: var(--sp-3);
  font-size: var(--fs-overline); letter-spacing: .16em; text-transform: uppercase;
  color: var(--fg); opacity: .7;
}
.f2__pills { display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: center; }

/* Category pills — outlined, brass fill when pressed. */
.fpill {
  padding: .55rem 1.1rem; border: 1px solid var(--c-brass); background: transparent; color: var(--c-brass);
  font-family: var(--ff-body); font-size: var(--fs-small); font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; border-radius: 999px; cursor: pointer;
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.fpill:hover, .fpill[aria-pressed="true"] { background: var(--c-brass); color: var(--c-base); }
.fpill__n { font-variant-numeric: tabular-nums; opacity: .65; margin-left: .45rem; font-weight: 400; }
.fpill[aria-pressed="true"] .fpill__n { opacity: .8; }

/* Kind of project — serif tabs on a hairline: a change of view, not a filter. */
.ttabs {
  display: flex; justify-content: center; gap: clamp(1.5rem, .5rem + 3vw, 3.5rem);
  border-bottom: 1px solid var(--line);
}
.ttab {
  background: transparent; border: 0; cursor: pointer; padding: 0 0 var(--sp-4);
  margin-bottom: -1px; border-bottom: 2px solid transparent;
  font-family: var(--ff-display); font-size: var(--fs-lead); color: var(--fg);
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
.ttab:hover { color: var(--heading); }
.ttab[aria-pressed="true"] { color: var(--c-brass); border-bottom-color: var(--c-brass); }
.ttab .fpill__n { font-family: var(--ff-body); font-size: var(--fs-small); }

/* Kind of project — one capsule, hairline-divided. */
.seg2 { display: inline-flex; border: 1px solid var(--c-brass); border-radius: 999px; overflow: hidden; }
.seg2__opt {
  background: transparent; border: 0;
  border-left: 1px solid color-mix(in srgb, var(--c-brass) 45%, transparent);
  padding: .6rem 1.3rem; color: var(--c-brass); cursor: pointer;
  font-family: var(--ff-body); font-size: var(--fs-small); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.seg2__opt:first-child { border-left: 0; }
.seg2__opt:hover { background: color-mix(in srgb, var(--c-brass) 16%, transparent); }
.seg2__opt[aria-pressed="true"] { background: var(--c-brass); color: var(--c-base); }

/* Photo grid — 1 / 2 / 3 across. */
.pgrid { display: grid; grid-template-columns: 1fr; gap: var(--sp-5); margin-top: var(--sp-8); }
@media (min-width: 40rem) { .pgrid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .pgrid { grid-template-columns: repeat(3, 1fr); } }

.ptile {
  display: block; position: relative; overflow: hidden; border-radius: var(--radius-lg);
  background: var(--c-base-deep); color: inherit; text-decoration: none; cursor: zoom-in;
}
/* The class sets display, so the attribute needs the weight to win. */
.ptile[hidden] { display: none; }
.ptile--link { cursor: pointer; }
.ptile img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; transition: transform .6s var(--ease-out); }
.ptile:hover img { transform: scale(1.04); }
.ptile__veil {
  position: absolute; inset: 0; display: flex; align-items: flex-end; padding: var(--sp-5);
  background: linear-gradient(to top, rgba(14,12,11,.88) 0%, rgba(14,12,11,.15) 55%, transparent 100%);
  opacity: 0; transition: opacity var(--dur) var(--ease-out);
}
.ptile:hover .ptile__veil, .ptile:focus-within .ptile__veil { opacity: 1; }
.ptile__veil h3 { color: #fff; font-size: var(--fs-body); margin: 0 0 var(--sp-1); }
.ptile__veil p { color: var(--c-on-dark); font-size: var(--fs-small); margin: 0; }
.ptile__flag {
  position: absolute; top: var(--sp-3); left: var(--sp-3); z-index: 2;
  background: rgba(201,163,106,.94); color: var(--c-base);
  font-size: var(--fs-overline); letter-spacing: .1em; text-transform: uppercase; font-weight: 600;
  padding: .25rem .6rem; border-radius: 999px;
}

/* Under the grid: how much is on show, then the three actions. */
.pmore { display: grid; justify-items: center; gap: var(--sp-5); margin-top: var(--sp-10); }
.pmore__count {
  font-size: var(--fs-overline); letter-spacing: .14em; text-transform: uppercase;
  color: var(--fg); font-variant-numeric: tabular-nums;
}
.pmore .btn-group { justify-content: center; }
.pmore .btn[hidden] { display: none; }

/* --------------------------------------------------------------------------
   LIGHTBOX — full-size viewer for gallery photographs
   --------------------------------------------------------------------------
   Case-study tiles are links and navigate instead; only plain tiles open this.
   Prev/next cycle the currently-visible tiles, so it follows the filter.
   -------------------------------------------------------------------------- */
body.lb-open { overflow: hidden; }
.lightbox {
  position: fixed; inset: 0; z-index: 1200;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(1rem, 3vw, 3rem); background: rgba(8,7,6,.95);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.lightbox[hidden] { display: none; }
.lightbox__stage {
  position: relative; display: flex; flex-direction: column;
  margin: 0; max-width: min(94vw, 1200px); width: 100%;
}
.lightbox__img {
  display: block; width: 100%; max-height: 78vh; object-fit: contain;
  border-radius: var(--radius-lg); background: var(--c-base-deep);
}
.lightbox__cap {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-4); margin-top: var(--sp-5);
}
.lightbox__title { color: #fff; font-size: var(--fs-h3); margin: 0; }
.lightbox__meta { color: var(--c-on-dark); font-size: var(--fs-small); margin: var(--sp-1) 0 0; }
.lightbox__count {
  position: absolute; left: 50%; bottom: clamp(.5rem, 2vw, 1.25rem); transform: translateX(-50%);
  color: var(--c-on-dark); font-size: var(--fs-overline); letter-spacing: .14em;
  font-variant-numeric: tabular-nums;
}
.lightbox__close, .lightbox__nav {
  position: absolute; z-index: 2; border: 0; cursor: pointer;
  border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  color: #fff; background: rgba(255,255,255,.08);
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.lightbox__close:hover, .lightbox__nav:hover { background: var(--c-brass); color: var(--c-base); }
.lightbox__close {
  top: clamp(.75rem, 2.5vw, 1.75rem); right: clamp(.75rem, 2.5vw, 1.75rem);
  width: 3rem; height: 3rem;
}
.lightbox__close svg { width: 1.4rem; height: 1.4rem; stroke: currentColor; fill: none; stroke-width: 2; }
.lightbox__nav { top: 50%; transform: translateY(-50%); width: 3.25rem; height: 3.25rem; }
.lightbox__nav svg { width: 1.5rem; height: 1.5rem; stroke: currentColor; fill: none; stroke-width: 2; }
.lightbox__nav--prev { left: clamp(.5rem, 2vw, 1.5rem); }
.lightbox__nav--prev svg { transform: rotate(180deg); }
.lightbox__nav--next { right: clamp(.5rem, 2vw, 1.5rem); }
@media (max-width: 40rem) {
  .lightbox__nav { width: 2.75rem; height: 2.75rem; background: rgba(8,7,6,.6); }
  .lightbox__nav--prev { left: var(--sp-2); }
  .lightbox__nav--next { right: var(--sp-2); }
}
@media (prefers-reduced-motion: reduce) {
  .lightbox__close, .lightbox__nav { transition: none; }
}

/* --------------------------------------------------------------------------
   OUR PROCESS — the Suite Home Approach pillars, and the protection quadrant
   --------------------------------------------------------------------------
   Both hold long prose (90–130 words an item), so they're drawn with hairlines
   at a full measure rather than squeezed into narrow columns.
   -------------------------------------------------------------------------- */
.pillars { border-top: 1px solid var(--line); margin-top: var(--sp-10); }
.pillar {
  display: grid; grid-template-columns: 1fr; gap: var(--sp-3);
  padding-block: var(--sp-8); border-bottom: 1px solid var(--line);
}
@media (min-width: 52rem) {
  .pillar { grid-template-columns: 16rem 1fr; gap: clamp(2rem, 1rem + 4vw, 5rem); }
}
.pillar h3 { font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--heading); }
.pillar__n {
  display: block; font-size: var(--fs-overline); letter-spacing: .16em; text-transform: uppercase;
  color: var(--accent); font-variant-numeric: tabular-nums; margin-bottom: var(--sp-2);
}
.pillar p { margin: 0; color: var(--fg); max-width: 66ch; }

.quad { display: grid; grid-template-columns: 1fr; margin-top: var(--sp-10); border-top: 1px solid var(--line); }
@media (min-width: 52rem) { .quad { grid-template-columns: 1fr 1fr; } }
.quad > * { padding: var(--sp-8) 0; border-bottom: 1px solid var(--line); }
@media (min-width: 52rem) {
  .quad > * { padding: var(--sp-8) clamp(1.5rem, 1rem + 2vw, 3rem); }
  .quad > *:nth-child(odd) { padding-left: 0; border-right: 1px solid var(--line); }
  .quad > *:nth-child(even) { padding-right: 0; }
}

/* Header over a darkened plate of the work (Our Process). */
.ph-media { position: absolute; inset: 0; overflow: hidden; }
.ph-media img { width: 100%; height: 100%; object-fit: cover; }
.ph-media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(20,17,15,.82) 0%, rgba(20,17,15,.92) 55%, var(--c-base) 100%);
}

/* --------------------------------------------------------------------------
   AREAS WE SERVE — community cards, the service-area map, its list
   --------------------------------------------------------------------------
   Twelve communities fill 4 × 3 and 2 × 6 exactly, so there is no orphan cell
   at any width. The map is real geography (Leaflet + OpenStreetMap), graded
   down to the page's ground so it reads as a plan rather than a screenshot.
   -------------------------------------------------------------------------- */
    /* 3a — twelve equal cards: 12 fills 4 × 3 and 2 × 6 exactly */
    .loc-tiles { display: grid; grid-template-columns: 1fr; gap: 0; margin-top: var(--sp-10); border-top: 1px solid var(--line); }
    @media (min-width: 40rem) { .loc-tiles { grid-template-columns: repeat(2, 1fr); } }
    @media (min-width: 68rem) { .loc-tiles { grid-template-columns: repeat(4, 1fr); } }
    .loc-tile {
      display: flex; flex-direction: column; gap: var(--sp-2);
      padding: var(--sp-6) 0; border-bottom: 1px solid var(--line);
      text-decoration: none; color: inherit;
    }
    @media (min-width: 40rem) {
      .loc-tile { padding-inline: clamp(1rem, .5rem + 1.5vw, 2rem); border-right: 1px solid var(--line); }
      .loc-tile:nth-child(2n) { border-right: 0; padding-right: 0; }
      .loc-tile:nth-child(2n+1) { padding-left: 0; }
    }
    @media (min-width: 68rem) {
      .loc-tile { border-right: 1px solid var(--line); padding-inline: clamp(1rem, .5rem + 1.5vw, 2rem); }
      .loc-tile:nth-child(2n) { border-right: 1px solid var(--line); padding-right: clamp(1rem, .5rem + 1.5vw, 2rem); }
      .loc-tile:nth-child(2n+1) { padding-left: clamp(1rem, .5rem + 1.5vw, 2rem); }
      .loc-tile:nth-child(4n) { border-right: 0; padding-right: 0; }
      .loc-tile:nth-child(4n+1) { padding-left: 0; }
    }
    .loc-tile__h { font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--heading); transition: color var(--dur) var(--ease-out); }
    .loc-tile:hover .loc-tile__h { color: var(--accent); }
    .loc-tile__meta { font-size: var(--fs-overline); letter-spacing: .1em; text-transform: uppercase; color: var(--accent); }
    .loc-tile p { margin: 0; font-size: var(--fs-small); color: var(--fg); }
    .loc-tile__go { margin-top: auto; padding-top: var(--sp-3); font-size: var(--fs-small); font-weight: 600; color: var(--accent); }
    .loc-tiles__note { margin-top: var(--sp-6); font-size: var(--fs-small); color: var(--fg); max-width: 66ch; }
    .loc-tiles__note a { color: var(--accent); }

    /* 3b — hairline list: name + distance, the line, then the link */
    .loc-list { margin-top: var(--sp-10); border-top: 1px solid var(--line); }
    .loc-row {
      display: grid; grid-template-columns: 1fr; gap: var(--sp-2);
      padding-block: var(--sp-6); border-bottom: 1px solid var(--line);
      text-decoration: none; color: inherit; align-items: baseline;
    }
    @media (min-width: 62rem) {
      .loc-row { grid-template-columns: 14rem 1fr 12rem; gap: clamp(1.5rem, 1rem + 2vw, 3rem); }
    }
    .loc-row__name { font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--heading); transition: color var(--dur) var(--ease-out); }
    .loc-row:hover .loc-row__name { color: var(--accent); }
    .loc-row__dist { display: block; font-size: var(--fs-overline); letter-spacing: .1em; text-transform: uppercase; color: var(--accent); margin-bottom: var(--sp-1); }
    .loc-row p { margin: 0; color: var(--fg); }
    .loc-row__go { font-size: var(--fs-small); font-weight: 600; color: var(--accent); }
    @media (min-width: 62rem) { .loc-row__go { text-align: right; } }

    /* 3c — two across, photograph beside the copy: 10 fills 2 × 5 */
    .loc-pairs { display: grid; grid-template-columns: 1fr; gap: var(--sp-6) clamp(2rem, 1rem + 3vw, 4rem); margin-top: var(--sp-10); }
    @media (min-width: 62rem) { .loc-pairs { grid-template-columns: 1fr 1fr; } }
    .loc-pair {
      display: grid; grid-template-columns: 9rem 1fr; gap: var(--sp-5);
      padding-block: var(--sp-5); border-top: 1px solid var(--line);
      text-decoration: none; color: inherit; align-items: start;
    }
    .loc-pair img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-lg); display: block; }
    .loc-pair h3 { font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--heading); transition: color var(--dur) var(--ease-out); }
    .loc-pair:hover h3 { color: var(--accent); }
    .loc-pair p { margin: var(--sp-2) 0 0; font-size: var(--fs-small); color: var(--fg); }
    .loc-pair__go { display: inline-block; margin-top: var(--sp-3); font-size: var(--fs-small); font-weight: 600; color: var(--accent); }

    /* Crossfield and Nanton carry no canonical line and no page of their own, so
       they read as rows in the same form, minus the link behaviour. */
    .loc-mrow--static { cursor: default; }
    .loc-mrow--static:hover { background: none; }
    .loc-mrow--static:hover .loc-mrow__name { color: var(--heading); }
    .loc-map__note { margin-top: var(--sp-5); font-size: var(--fs-small); color: var(--fg); max-width: 66ch; }
    .loc-map__note a { color: var(--accent); }

    /* "Also serving" — the last row of the same hairline system, not a card */
    .loc-also {
      display: grid; grid-template-columns: 1fr; gap: var(--sp-3);
      padding-block: var(--sp-6); border-bottom: 1px solid var(--line);
    }
    @media (min-width: 62rem) {
      .loc-also { grid-template-columns: 14rem 1fr; gap: clamp(1.5rem, 1rem + 2vw, 3rem); }
    }
    .loc-also__label {
      font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--heading);
    }
    .loc-also__chips { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
    .loc-also p { margin: var(--sp-4) 0 0; font-size: var(--fs-small); color: var(--fg); max-width: 66ch; }
    .loc-also p a { color: var(--accent); }

    /* 3d — the service area as a real map, list beside it */
    .loc-map { display: grid; grid-template-columns: 1fr; gap: clamp(2rem, 1rem + 3vw, 3.5rem); margin-top: var(--sp-10); align-items: start; }
    @media (min-width: 68rem) { .loc-map { grid-template-columns: 1.05fr .95fr; } }
    .loc-map__canvas {
      position: relative; height: clamp(24rem, 20rem + 22vw, 34rem);
      border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden;
      background: var(--c-base-deep);
    }
    @media (min-width: 68rem) { .loc-map__canvas { position: sticky; top: var(--sp-8); } }
    .loc-bandmap {
      position: relative; margin-top: var(--sp-8);
      height: clamp(17rem, 12rem + 20vw, 26rem);
      border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden;
      background: var(--c-base-deep);
    }
    .loc-bandmap__cap { margin-top: var(--sp-3); font-size: var(--fs-small); color: var(--fg); }
    .loc-map__canvas .leaflet-container, .loc-bandmap .leaflet-container { width: 100%; height: 100%; background: var(--c-base-deep); font-family: var(--ff-body); }
    /* OpenStreetMap tiles, graded down to the page's ground so the map reads as
       a plan rather than a screenshot. Attribution sits outside this pane. */
    .map-plate .leaflet-tile-pane, .loc-map__canvas .leaflet-tile-pane { filter: grayscale(1) brightness(.42) contrast(1.15) sepia(.35); }
    .loc-bandmap .leaflet-control-attribution,
    .loc-map__canvas .leaflet-control-attribution {
      background: rgba(14,12,11,.72); color: var(--c-on-dark); font-size: 10px;
    }
    .loc-bandmap .leaflet-control-attribution a,
    .loc-map__canvas .leaflet-control-attribution a { color: var(--c-brass); }
    .loc-map__lbl {
      background: none; border: 0; box-shadow: none; padding: 0 0 0 .45rem;
      color: var(--c-warm-white); font-family: var(--ff-body); font-size: .72rem;
      font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
      text-shadow: 0 1px 3px rgba(8,7,6,.9);
    }
    .loc-map__lbl::before { display: none; }
    .loc-map__lbl--home { color: var(--c-brass); font-size: .82rem; }
    .loc-map__list { border-top: 1px solid var(--line); }
    .loc-mrow {
      display: grid; grid-template-columns: 1fr; gap: var(--sp-1);
      padding-block: var(--sp-4); border-bottom: 1px solid var(--line);
      text-decoration: none; color: inherit;
    }
    .loc-mrow:hover, .loc-mrow[data-active] { background: rgba(201,163,106,.06); }
    .loc-mrow__name { font-family: var(--ff-display); font-size: var(--fs-lead); color: var(--heading); }
    .loc-mrow:hover .loc-mrow__name, .loc-mrow[data-active] .loc-mrow__name { color: var(--accent); }
    /* The drive time sits above the name at a full measure — as a right-aligned
       column it wrapped to two lines and crushed the place name it labels. */
    .loc-mrow__dist { order: -1; font-size: var(--fs-overline); letter-spacing: .1em; text-transform: uppercase; color: var(--accent); }
    .loc-mrow p { margin: 0; font-size: var(--fs-small); color: var(--fg); }

    /* "Also serving" — chips + the travel note */
    .also {
      margin-top: var(--sp-12); padding: var(--sp-8);
      background: rgba(255,255,255,.03); border: 1px solid rgba(201,163,106,.15);
      border-radius: var(--radius-lg);
    }
    .also__chips { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-4); }
    .also__chip {
      padding: var(--sp-2) var(--sp-4); border: 1px solid rgba(201,163,106,.3);
      border-radius: 999px; font-size: var(--fs-small); color: var(--c-on-dark);
    }
    .also p { margin-top: var(--sp-4); font-size: var(--fs-small); color: var(--fg); }
    .also p a { color: var(--c-brass); }
.also__chip {
  padding: var(--sp-2) var(--sp-4); border: 1px solid rgba(201,163,106,.3);
  border-radius: 999px; font-size: var(--fs-small); color: var(--c-on-dark);
}

/* The map plate on a light ground: tiles graded up instead of down, and the
   place labels flip to the near-black/deep-brass pair so they stay legible. */
.map-plate--light .leaflet-tile-pane { filter: grayscale(1) brightness(1.04) contrast(.9) sepia(.22); }
.map-plate--light .loc-map__lbl { color: var(--c-base); text-shadow: 0 1px 3px rgba(243,241,237,.95); }
.map-plate--light .loc-map__lbl--home { color: var(--c-brass-deep); }
.map-plate--light .leaflet-control-attribution { background: rgba(243,241,237,.82); color: var(--c-muted); }
.map-plate--light .leaflet-control-attribution a { color: var(--c-brass-deep); }


/* --------------------------------------------------------------------------
   STANDFIRST BAND (location pages) — the opening statement set as display
   prose against a brass rule, the credential marks as a hairline panel beside
   it, and the byline on the closing hairline. Replaces the flat lead + pill
   row: same copy, real hierarchy.
   -------------------------------------------------------------------------- */
.stf { display: grid; grid-template-columns: 1fr; gap: clamp(2rem,1rem + 3vw,4rem); align-items: start; }
@media (min-width: 62rem) { .stf { grid-template-columns: 1.45fr .55fr; } }
.stf__lead {
  font-family: var(--ff-display); font-weight: 400;
  font-size: clamp(1.3rem, 1.05rem + .8vw, 1.9rem); line-height: 1.42;
  color: var(--heading); text-wrap: pretty;
  border-left: 3px solid var(--c-brass); padding-left: clamp(1.25rem, .75rem + 1.5vw, 2rem);
  max-width: 56ch; margin: 0;
}
/* Credential marks: a drawn line icon in a hairline brass disc per row, the
   label beside it — the generic tick row read as a to-do list. */
.stf__marks { list-style: none; margin: 0; border-top: 1px solid var(--line); }
.stf__mark {
  display: grid; grid-template-columns: 2.75rem 1fr; gap: var(--sp-4);
  align-items: center; padding-block: var(--sp-5);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-body); line-height: 1.35; color: var(--heading);
}
.stf__ic {
  width: 2.75rem; height: 2.75rem; border-radius: 50%;
  border: 1px solid var(--accent); background: transparent;
  display: grid; place-items: center; color: var(--accent); flex: none;
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.stf__ic svg {
  width: 1.4rem; height: 1.4rem;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.stf__mark:hover .stf__ic { background: rgba(201,163,106,.1); }
.stf__foot {
  margin-top: clamp(2rem,1rem + 3vw,3.25rem); padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
}


/* --------------------------------------------------------------------------
   PLATE BAND (location pages, "the local picture") — heading + lead full
   width, a wide photographic plate, and the closing statement in a bordered
   card inset over the plate's bottom edge. Replaces a half-empty prose row.
   -------------------------------------------------------------------------- */
.lp-plate { position: relative; margin-top: var(--sp-8); }
.lp-plate__img { position: relative; overflow: hidden; border-radius: var(--radius-lg); aspect-ratio: 21 / 9; }
.lp-plate__img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 45%; }
.lp-plate__card {
  position: relative; max-width: 46rem;
  margin: calc(-1 * clamp(2rem,1rem + 4vw,5rem)) auto 0;
  background: var(--c-white); border: 1px solid var(--c-line-light);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-md);
  padding: clamp(1.5rem,1rem + 2vw,2.5rem);
}
.lp-plate__card p { margin: 0; color: var(--c-muted); }
.lp-plate__card .btn { margin-top: var(--sp-6); }
@media (min-width: 62rem) { .lp-plate__card { margin-left: 0; margin-right: auto; } }
@media (max-width: 40rem) { .lp-plate__img { aspect-ratio: 4 / 3; } }

/* --------------------------------------------------------------------------
   CHECKABLE CLAIM (location pages, "why homeowners choose us") — heading
   beside the claim paragraph, with the live links surfaced as a hairline rail
   so the "you can check this" promise is one click, not a hunt through prose.
   -------------------------------------------------------------------------- */
.chk { display: grid; grid-template-columns: 1fr; gap: clamp(1.5rem,1rem + 3vw,3.5rem); align-items: start; }
@media (min-width: 62rem) {
  .chk { grid-template-columns: .8fr 1.2fr; }
  /* Second column starts BELOW the heading block, never level with the eyebrow */
  .chk > *:nth-child(2) { margin-top: var(--sp-10); }
}
.chk > p { margin: 0; color: var(--fg); max-width: 66ch; }
.chk > p a { color: var(--accent); }
.chk-rail { display: grid; grid-template-columns: 1fr; margin-top: var(--sp-10); border-top: 1px solid var(--line); }
@media (min-width: 52rem) { .chk-rail { grid-template-columns: repeat(4, 1fr); } }
.chk-link {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  padding: var(--sp-5) 0; border-bottom: 1px solid var(--line);
  font-size: var(--fs-small); font-weight: 600; letter-spacing: .02em;
  color: var(--heading); text-decoration: none;
  transition: color var(--dur) var(--ease-out);
}
@media (min-width: 52rem) {
  .chk-link { padding-inline: var(--sp-5); border-right: 1px solid var(--line); }
  .chk-link:first-child { padding-left: 0; }
  .chk-link:last-child { border-right: 0; padding-right: 0; }
}
.chk-link svg { width: 1.1rem; height: 1.1rem; flex: none; fill: none; stroke: var(--accent); stroke-width: 1.8; transition: transform var(--dur) var(--ease-out); }
.chk-link:hover { color: var(--accent); }
.chk-link:hover svg { transform: translateX(4px); }


/* --------------------------------------------------------------------------
   COST LEDGER (location pages) — the price tiers as a full-width hairline
   ledger under the heading, with the answer prose flowing beneath in two
   columns. Used where a narrow prose column beside short tier cards left a
   void; the numbers lead, the caveats follow.
   -------------------------------------------------------------------------- */
.cost-ledger { margin-top: var(--sp-8); border-top: 1px solid var(--line); }
.cost-ledger__row {
  display: grid; grid-template-columns: 1fr auto; gap: var(--sp-4) var(--sp-8);
  align-items: baseline; padding-block: var(--sp-6);
  border-bottom: 1px solid var(--line);
}
.cost-ledger__name { font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--heading); }
.cost-ledger__price {
  font-family: var(--ff-display); font-size: clamp(1.5rem,1.2rem + 1vw,2.15rem); line-height: 1;
  color: var(--accent); font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Prose flowing in two columns (long single-paragraph answers) */
.prose-cols { color: var(--fg); }
.prose-cols strong { color: var(--heading); }
.prose-cols a { color: var(--accent); }
@media (min-width: 62rem) { .prose-cols { columns: 2; column-gap: clamp(2rem,1rem + 4vw,4.5rem); } }

/* Closing rule footer: a supporting line and the section's action */
.sec-foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-5) var(--sp-8); margin-top: var(--sp-8);
  padding-top: var(--sp-6); border-top: 1px solid var(--line);
}
.sec-foot p { margin: 0; max-width: 56ch; color: var(--fg); }
.sec-foot p a { color: var(--c-brass-deep); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }
.sec-foot p a:hover { color: var(--heading); }


/* --------------------------------------------------------------------------
   COST — two more shipped compositions of the same tier data, kept for reuse
   on the remaining location pages. Reference markup lives in
   locations/_airdrie-cost-options.html (CO-B, CO-C).

   .cost-stack (CO-B) — answer prose left, tier cards with a brass left rule
   stacked right, and the "what moves the number" note as a panel beneath them
   so the right column reaches the full height of the prose.
   .cost-cards (CO-C) — three equal cards across the top with the ranges as the
   visual hero, then the answer beneath in .prose-cols.
   -------------------------------------------------------------------------- */
.cost-stack { display: grid; grid-template-columns: 1fr; gap: clamp(2rem,1rem + 4vw,4rem); align-items: start; margin-top: var(--sp-8); }
@media (min-width: 62rem) { .cost-stack { grid-template-columns: 1.1fr .9fr; } }
.cost-stack__tiers { display: grid; gap: var(--sp-4); }
.cost-stack__tier {
  display: grid; grid-template-columns: 1fr; gap: var(--sp-2);
  background: var(--c-white); border: 1px solid var(--c-line-light);
  border-left: 2px solid var(--c-brass); border-radius: var(--radius-lg);
  padding: var(--sp-6);
}
.cost-stack__tier b { font-family: var(--ff-display); font-weight: 400; font-size: var(--fs-lead); color: var(--heading); }
.cost-stack__tier span {
  font-family: var(--ff-display); font-size: clamp(1.5rem,1.2rem + 1vw,2rem); line-height: 1;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
.cost-stack__note { margin-top: var(--sp-5); padding-top: var(--sp-5); border-top: 1px solid var(--line); }

.cost-cards { display: grid; grid-template-columns: 1fr; gap: var(--sp-5); margin-top: var(--sp-8); }
@media (min-width: 52rem) { .cost-cards { grid-template-columns: repeat(3, 1fr); } }
.cost-cards__card {
  display: flex; flex-direction: column; gap: var(--sp-4);
  background: var(--c-white); border: 1px solid var(--c-line-light);
  border-top: 2px solid var(--c-brass); border-radius: var(--radius-lg);
  padding: clamp(1.25rem,1rem + 1.5vw,2rem);
}
.cost-cards__name { font-size: var(--fs-overline); letter-spacing: .1em; text-transform: uppercase; color: var(--c-muted); }
.cost-cards__covers { font-size: var(--fs-small); color: var(--fg); margin: 0; }
.cost-cards__price {
  font-family: var(--ff-display); font-size: clamp(1.45rem,1.1rem + 1.2vw,2.15rem); line-height: 1.1;
  color: var(--accent); font-variant-numeric: tabular-nums; margin-top: auto; text-wrap: balance;
}

/* Shared note line for any cost composition */
.cost-note { font-size: var(--fs-small); color: var(--c-muted); margin: 0; max-width: 74ch; }
.cost-note strong { color: var(--heading); }

/* ---- Cost-expectation card (the standing block on all 12 /work pages) ----
   Scoped via :has(.cost-note) so the blog pages' plain .article-note keeps its
   footnote styling. The band is a compact utility strip, not an editorial
   section, so it runs at half rhythm; when it directly follows another warm
   section (most /work pages) the shared background already provides the gap,
   so its top padding collapses entirely. Falls back to the old spacing in
   any browser without :has() — worse spacing, nothing broken. */
.section:has(> .container > .article-note > .cost-note) { padding-block: calc(var(--section-y) / 2); }
.section--warm + .section--warm:has(> .container > .article-note > .cost-note) { padding-top: 0; }

.article-note:has(> .cost-note) {
  margin-top: 0; margin-inline: auto;
  padding: clamp(1.75rem, 1.25rem + 2vw, 2.75rem);
  border: 1px solid var(--line); border-top: 2px solid var(--accent);
  border-radius: var(--radius-lg);
}
.article-note > .cost-note { font-size: var(--fs-body); line-height: var(--lh-body); max-width: none; }
.article-note > .cost-note strong {
  display: block;
  font-family: var(--ff-display); font-weight: 400;
  font-size: var(--fs-h3); line-height: 1.2; letter-spacing: -.01em;
  margin-bottom: var(--sp-3);
}


/* --------------------------------------------------------------------------
   PAPERWORK SPLIT (location pages) — the situation as prose on the left, the
   "we handle it" answer lifted into a bordered card on the right. Used to keep
   two prose-heavy sections in a row from reading as the same layout twice.
   -------------------------------------------------------------------------- */
.pw-split { display: grid; grid-template-columns: 1fr; gap: clamp(2rem,1rem + 4vw,4rem); align-items: start; margin-top: var(--sp-8); }
@media (min-width: 62rem) { .pw-split { grid-template-columns: 1.15fr .85fr; } }
.pw-split__prose { color: var(--fg); max-width: 62ch; }
.pw-split__prose p { margin: 0; }
.pw-split__card {
  border: 1px solid var(--line); border-top: 2px solid var(--accent);
  border-radius: var(--radius-lg); padding: clamp(1.5rem,1rem + 2vw,2.5rem);
  background: rgba(201,163,106,.05);
}
.pw-split__card .overline { display: block; margin-bottom: var(--sp-4); }
.pw-split__card p { margin: 0; color: var(--fg); }
/* Second column starts BELOW the heading block, never level with the eyebrow */
@media (min-width: 62rem) { .pw-split__card { margin-top: var(--sp-12); position: sticky; top: var(--sp-8); } }
/* Mirrored: the card sits left of the heading + prose, for alternating rhythm
   when several prose sections run in a row. Source order stays heading-first. */
@media (min-width: 62rem) {
  .pw-split--flip { grid-template-columns: .85fr 1.15fr; }
  .pw-split--flip > :first-child { order: 2; }
  .pw-split--flip > .pw-split__card { order: 1; }
}


/* --------------------------------------------------------------------------
   LOCATION-PAGE TYPE RULES (one system across every town page)
   • --fs-lead is for SHORT intro/standfirst lines only (about three lines max).
     Long narrative paragraphs sit at --fs-body in .prose-cols / .prose-stack —
     a 120-word paragraph set at lead size reads as a mistake.
   • A heading block always gets the same step down to whatever follows it.
   -------------------------------------------------------------------------- */
.section-head:not(.section-head--center) + .article-body,
.section-head:not(.section-head--center) + .timeline-cols,
.section-head:not(.section-head--center) + .prose-cols,
.section-head:not(.section-head--center) + .prose-stack,
.section-head:not(.section-head--center) + .cost-ledger,
.section-head:not(.section-head--center) + .cost-cards,
.section-head:not(.section-head--center) + .inc-list,
.section-head:not(.section-head--center) + .bi-bullets,
.section-head:not(.section-head--center) + .grid,
.section-head:not(.section-head--center) + .lp-plate { margin-top: var(--sp-8); }

/* Even paragraph rhythm in multi-column prose (matches .prose-stack + .section-head) */
.prose-cols p + p { margin-top: var(--sp-5); }
/* The closing-rule line is supporting text, a clear step below body prose */
.sec-foot p { font-size: var(--fs-small); }

/* Single-column narrative prose: body size, even paragraph rhythm, one measure */
.prose-stack { display: grid; gap: var(--sp-5); color: var(--fg); max-width: 66ch; }
.prose-stack p { margin: 0; font-size: var(--fs-body); }
.prose-stack a { color: var(--accent); }

/* ---- Basement page: development-vs-renovation comparison split ---- */
.cmp-split { position: relative; display: grid; grid-template-columns: 1fr; gap: var(--sp-6); max-width: 64rem; margin-inline: auto; }
@media (min-width: 40rem) { .cmp-split { grid-template-columns: 1fr 1fr; gap: clamp(2rem,1rem + 3vw,3.5rem); } }
.cmp-vs { display: none; }
@media (min-width: 40rem) {
  .cmp-vs {
    display: flex; align-items: center; justify-content: center;
    position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
    width: 2.75rem; height: 2.75rem; border-radius: 50%;
    background: var(--bg); border: 1px solid var(--accent); color: var(--accent);
    font-family: var(--ff-display); font-size: .85rem; letter-spacing: .04em; z-index: 2;
  }
}

/* ---- Cost tier icon + featured accent ---- */
.cost-tier__icon { grid-column: 1 / -1; width: 2.5rem; height: 2.5rem; border: 1px solid var(--accent); border-radius: 50%; display: grid; place-items: center; color: var(--accent); margin-bottom: var(--sp-1); }
.cost-tier__icon svg { width: 1.3rem; height: 1.3rem; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.cost-tier--featured { border-color: var(--accent); position: relative; }
.cost-tier--featured::before {
  content: "Most Common"; position: absolute; top: -.65rem; left: var(--sp-5);
  background: var(--accent); color: var(--c-base); font-size: .68rem; letter-spacing: .06em;
  text-transform: uppercase; padding: .2rem .6rem; border-radius: 999px; font-family: var(--ff-body); font-weight: 600;
}


/* Enumerated variant: a real <ol>, so "here's the range …" is announced as a
   list. Scoped to --items so the step-sequence .proc-list stays untouched. */
.proc-list--items { list-style: none; padding-left: 0; }
.proc-list--items > .proc-row { list-style: none; }

/* Scope-range stepper on the town pages: the row holds one verbatim item
   ("<strong>Label</strong> — detail"), so the paragraph carries the type. */
.proc-row > p { margin: 0; color: var(--fg); }
.proc-row > p strong { color: var(--heading); }


/* --------------------------------------------------------------------------
   CASE-STUDY CHAPTER KIT (v2) — "dossier ledger"
   Ships with work/mount-royal-full-home-renovation. The unit is a CHAPTER, so a
   single-room study (Dover) uses one .cs-chap and a whole-home study uses five.
   .cs-fact  — merged meta + proof band (replaces .case-meta + .case-highlight)
   .cs-jump  — "On this page" pill rail
   .cs-chap  — hairline ledger row: sticky numeral + title left, prose/photo right
   .cs-fig   — 3:2 captioned figure inside a chapter body
   .cs-bleed — full-bleed frame with a lapped caption plate (closes a chapter)
   .cs-quote — brass-ruled pull quote with stars
   .cs-pn / .post-pn — previous / next rail. SHARED: .cs-pn on the 12 /work case
             studies (portfolio order), .post-pn on the blog posts (blog index
             order, stamped by scripts/propagate_post_nav.py). One rule set, so
             restyling one restyles both.
   -------------------------------------------------------------------------- */
.cs-fact { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.cs-fact__grid { display: grid; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 52rem) { .cs-fact__grid { grid-template-columns: repeat(4, 1fr); } }
.cs-fact__cell { padding: var(--sp-6) var(--sp-5) var(--sp-6) 0; border-bottom: 1px solid var(--line); }
.cs-fact__cell:nth-child(2) { border-left: 1px solid var(--line); padding-left: var(--sp-6); }
@media (min-width: 52rem) {
  .cs-fact__cell { border-bottom: 0; }
  .cs-fact__cell + .cs-fact__cell { border-left: 1px solid var(--line); padding-left: var(--sp-6); }
}
.cs-fact__label {
  display: block; font-size: var(--fs-overline); letter-spacing: .16em;
  text-transform: uppercase; color: var(--accent); margin-bottom: var(--sp-3);
}
.cs-fact__val {
  display: flex; align-items: center; gap: .55rem;
  font-family: var(--ff-display); font-size: var(--fs-lead);
  line-height: 1.25; color: var(--heading);
}
.cs-fact__val svg { flex: none; width: 1.05rem; height: 1.05rem; color: var(--accent); }
.cs-fact__checks {
  display: flex; flex-wrap: wrap; gap: var(--sp-4) clamp(1.5rem, 1rem + 3vw, 3.5rem);
  padding: var(--sp-5) 0; border-top: 1px solid var(--line);
  font-size: var(--fs-small); color: var(--fg);
}
.cs-fact__checks span { display: inline-flex; align-items: center; gap: var(--sp-3); }
.cs-fact__checks svg {
  flex: none; width: 1.6rem; height: 1.6rem; padding: .35rem; box-sizing: border-box;
  border-radius: 50%; background: rgba(201, 163, 106, .14); color: var(--accent);
  fill: none; stroke: currentColor; stroke-width: 2;
}

/* Numbered index row — typography, not capsules: capsules read as a filter
   affordance in this system (portfolio chips, quiz choices). */
.cs-jump { display: flex; flex-wrap: wrap; gap: var(--sp-3) clamp(1.5rem, 1rem + 2.5vw, 3rem); padding-top: var(--sp-6); }
.cs-jump__cap {
  flex: 0 0 100%; font-size: var(--fs-overline); letter-spacing: .16em;
  text-transform: uppercase; color: var(--fg); opacity: .7;
}
.cs-jump a {
  position: relative; display: inline-flex; align-items: baseline; gap: .5rem;
  font-size: var(--fs-body); color: var(--fg); text-decoration: none;
  transition: color var(--dur) var(--ease-out);
}
.cs-jump a i { font-family: var(--ff-display); font-style: italic; font-size: .95em; color: var(--accent); }
.cs-jump a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -4px; height: 1px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur) var(--ease-out);
}
.cs-jump a:hover { color: var(--heading); }
.cs-jump a:hover::after { transform: scaleX(1); }

.cs-chap {
  display: grid; grid-template-columns: 1fr; gap: var(--sp-5);
  padding-block: clamp(2.5rem, 1.5rem + 3vw, 4rem);
  border-top: 1px solid var(--line);
  scroll-margin-top: calc(6rem + var(--cs-rail-h));
}
.cs-chap--last { border-bottom: 1px solid var(--line); }
/* #cs-scope / #cs-how are the standard case-study template's "what was
   included" / "how we work" sections — plain .section blocks, not .cs-chap,
   but on mount-royal-full-home-renovation.html they're two of the seven
   .cs-jump targets, so they need the same rail-aware offset. The ids repeat
   across every /work page, so this is scoped to body.has-cs-rail: on the two
   pilot pages it applies; everywhere else it doesn't match at all, and the
   sitewide `html { scroll-padding-top: 5.5rem }` default keeps governing
   those ids unchanged. */
body.has-cs-rail #cs-scope, body.has-cs-rail #cs-how { scroll-margin-top: calc(6rem + var(--cs-rail-h)); }
@media (min-width: 62rem) {
  .cs-chap { grid-template-columns: 18rem 1fr; gap: clamp(2.5rem, 1rem + 4vw, 5rem); }
  .cs-chap__label { position: sticky; top: calc(7rem + var(--cs-rail-h)); align-self: start; }
}
.cs-chap__n {
  display: block; font-family: var(--ff-display); font-style: italic;
  font-size: 1.5rem; color: var(--accent); line-height: 1; margin-bottom: var(--sp-3);
}
.cs-chap__label h2 {
  font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.25rem);
  line-height: 1.12; color: var(--heading); margin: 0;
}
.cs-chap__body > * + * { margin-top: var(--sp-5); }
/* Media inside a chapter gets its own breathing room, not paragraph spacing */
.cs-chap__body > * + .cs-fig,
.cs-chap__body > * + .case-ba { margin-top: clamp(2rem, 1.25rem + 2.5vw, 3.5rem); }
/* One type size through the whole chapter body — the eye steps down once, H2 → body.
   Deliberately sets no margin: the global `* { margin: 0 }` reset already zeroes it,
   and a `margin: 0` here (0,1,1) would out-specify the `> * + *` flow rule above
   (0,1,0) and collapse the gap between consecutive chapter paragraphs. */
.cs-chap__body p { color: var(--fg); }
.cs-chap__body .lead { font-size: var(--fs-body); line-height: 1.65; color: var(--heading); }

.cs-fig { margin: 0; }
.cs-fig img {
  width: 100%; height: auto; display: block;
  border-radius: var(--radius-lg); aspect-ratio: 3 / 2; object-fit: cover;
}
.cs-fig figcaption { margin-top: var(--sp-3); font-size: var(--fs-small); color: var(--fg); opacity: .8; }

.cs-bleed { position: relative; margin-top: clamp(2rem, 1rem + 3vw, 3.5rem); }
.cs-bleed__img { position: relative; overflow: hidden; aspect-ratio: 21 / 9; }
.cs-bleed__img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 48rem) { .cs-bleed__img { aspect-ratio: 4 / 3; } }
.cs-cap {
  position: relative; max-width: 34rem;
  margin: calc(-1 * clamp(2rem, 1rem + 4vw, 4.5rem)) 0 0 var(--gutter);
  background: rgba(14, 12, 11, .86);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border: 1px solid rgba(201, 163, 106, .22); border-radius: var(--radius-lg);
  padding: clamp(1.25rem, 1rem + 1.5vw, 2rem);
}
.cs-cap .overline { color: var(--c-brass); }
.cs-cap p { margin-top: var(--sp-3); color: var(--c-on-dark); font-size: var(--fs-small); }
.cs-cap h2 { color: var(--c-warm-white); font-size: var(--fs-h3); margin-top: var(--sp-2); }

.cs-quote {
  border-left: 3px solid var(--c-brass);
  padding-left: clamp(1.25rem, 1rem + 1.5vw, 2rem); max-width: 46rem;
}
.cs-quote blockquote {
  font-family: var(--ff-display); font-size: clamp(1.15rem, 1rem + .6vw, 1.5rem);
  line-height: 1.5; color: var(--heading); margin: 0;
}
.cs-quote figcaption { margin-top: var(--sp-5); font-size: var(--fs-small); color: var(--fg); }
.cs-quote figcaption strong { color: var(--heading); }
.cs-quote .stars { display: inline-flex; gap: .15rem; color: var(--c-brass); margin-bottom: var(--sp-3); }
.cs-quote .stars svg { width: 1rem; height: 1rem; fill: currentColor; }

.cs-pn, .post-pn {
  display: grid; grid-template-columns: 1fr; gap: 1px;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  background: var(--line);
}
@media (min-width: 48rem) { .cs-pn, .post-pn { grid-template-columns: 1fr 1fr; } }
.cs-pn a, .post-pn a {
  background: var(--bg); padding: clamp(1.5rem, 1rem + 2vw, 2.5rem) var(--sp-5);
  display: grid; gap: var(--sp-2); text-decoration: none;
  transition: background var(--dur) var(--ease-out);
}
.cs-pn a:hover, .post-pn a:hover { background: rgba(201, 163, 106, .07); }
.cs-pn .dir, .post-pn .dir { font-size: var(--fs-overline); letter-spacing: .16em; text-transform: uppercase; color: var(--accent); }
.cs-pn .name, .post-pn .name { font-family: var(--ff-display); font-size: var(--fs-h3); color: var(--heading); }
.cs-pn .is-next, .post-pn .is-next { text-align: right; }

/* --------------------------------------------------------------------------
   .cs-rail — sticky case-study rail (spec section 11)
   Reveals once the hero clears, retires when .cs-pn arrives. Height is a token
   so the two offsets below stay correct; it is 0rem everywhere the rail is not
   used, which makes those calc() edits inert on every non-/work page.
   -------------------------------------------------------------------------- */
:root { --cs-rail-h: 0rem; }
body.has-cs-rail { --cs-rail-h: 3rem; }

.cs-rail {
  /* The rail sits outside every .section--* scope, so it must set its own
     light-theme tokens: :root defaults --line to the DARK-section brass
     hairline, which would read wrong on this cream ground. */
  --line: var(--c-line-light);
  /* top = the condensed nav height, shared token (main.css) — not a literal 4rem,
     so this rail and .read-progress can never drift from the nav. */
  position: fixed; top: var(--nav-h-scrolled); left: 0; right: 0; z-index: var(--z-rail);
  height: var(--cs-rail-h);
  background: var(--c-warm-white);
  border-bottom: 1px solid var(--line);
  transform: translateY(-100%); visibility: hidden;
  transition: transform .28s var(--ease-out), visibility .28s;
}
.cs-rail.is-on { transform: none; visibility: visible; }
.cs-rail__inner {
  height: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4);
}
.cs-rail a {
  display: inline-flex; align-items: center; gap: .55rem;
  min-height: 2.75rem; padding-block: .25rem;
  font-size: var(--fs-small); color: var(--c-base); text-decoration: none;
}
/* The hub label is a fixed, known-length navigation string ("All case studies",
   CSS-swapped to "All work" below 30rem), so the hub does NOT shrink. Without
   flex: none the flexbox squeezes it to its min-content width (the longest word)
   and the label wraps to two lines, which overflows the fixed-height band top
   and bottom — the same IMPORTANT-1 failure already fixed for .cs-rail__next,
   and what shipped on all 8 rail pages at <=375px / at ~480-515px with a large
   browser root font. The variable-length side is .cs-rail__next, and it absorbs
   the squeeze by ellipsising instead. nowrap on the label spans holds the
   no-wrap guarantee even where flex sizing is not the binding constraint. */
.cs-rail__hub { font-weight: 600; flex: none; }
.cs-rail__hub span { white-space: nowrap; }
/* min-width: 0 on both the flex child and its label span lets the item
   shrink below its content's intrinsic (nowrap) width whenever the hub side
   leaves it less room than it needs — e.g. longer wave labels, a narrow
   viewport, or a larger browser root font size. Without it the flexbox
   default (min-width: auto) pins the item at full content width and the
   label wraps instead, which is IMPORTANT-1: a wrapped 2-line label
   overflowed the fixed-height band top and bottom. The label's own
   max-width is 100% of that (now shrinkable) box rather than a fixed
   ch/vw guess, so it renders unclipped whenever there is room — matching
   the already-reviewed Dover/Mount Royal pilot — and only ellipsises when
   there truly isn't. */
.cs-rail__next { color: var(--c-muted); min-width: 0; }
.cs-rail__next span {
  display: block; min-width: 0; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cs-rail a:hover { color: var(--c-brass-deep); }
.cs-rail svg { width: 1rem; height: 1rem; flex: none; }
.cs-rail__back { transform: scaleX(-1); }
.cs-rail__grid { color: var(--c-brass); }
.cs-rail__short { display: inline; }
.cs-rail__full { display: none; }
@media (min-width: 30rem) {
  .cs-rail__short { display: none; }
  .cs-rail__full { display: inline; }
}
@media (prefers-reduced-motion: reduce) {
  .cs-rail { transition: none; }
}

/* ─────────────────────────────────────────────────────────────────────────────
   The Suite Home Approach — SHARED BLOCK (added 2026-07-24)
   Build-once component, same treatment tier as the CTA band. The canonical
   markup + the allow/deny placement list live in site/README.md; the authored
   copy is services/seo/03-execution/content/component-suite-home-approach-block.md
   in the marketing repo. Never reword it per page — identical text everywhere is
   the point. One instance per page, maximum, and NEVER on /our-process (that page
   carries the full three-pillar version).
   ───────────────────────────────────────────────────────────────────────────── */
.approach-block { border-block: 1px solid var(--c-line-light); }
.approach-block .container { max-width: 52rem; }
.approach-block__lead { margin-bottom: var(--sp-6); }
.approach-block__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4); }
.approach-block__list li { padding-left: var(--sp-5); position: relative; }
.approach-block__list li::before {
  content: ""; position: absolute; left: 0; top: 0.6em;
  width: 8px; height: 8px; border-radius: 50%; background: var(--c-brass);
}
.approach-block__cta { margin-top: var(--sp-6); }
