/* ============================================================
   Carpet Pro - v5+ (Deep Teal & Bronze)
   Your existing identity, modernised. Slim header, left slide-out
   services menu, slider hero with your photos, Spectral/Inter
   typography, smooth scrolling, subtle modern motion. HTML/CSS/JS only.
   ============================================================ */

:root {
  --teal: #80a8af;
  --teal-dark: #71949a;
  --teal-deep: #405458;
  --teal-soft: #afc8cd;
  --bronze: #bf9972;
  --bronze-dark: #ab784e;
  --gold: #e9e768;
  --ink: #020101;
  --ink-soft: #1d1a17;
  --paper: #f7f5f1;
  --white: #ffffff;
  --slate: #6f675c;
  --line: #e4ddd2;

  --font-display: "Spectral", Georgia, "Times New Roman", serif;
  --font-body: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;

  --sp-1: 0.5rem; --sp-2: 1rem; --sp-3: 1.5rem; --sp-4: 2rem; --sp-5: 3rem; --sp-6: 4rem;
  --maxw: 1160px;
  --header-h: 64px;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: calc(var(--header-h) + 12px); -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1.05rem;
  line-height: 1.7;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img { max-width: 100%; height: auto; display: block; }
a { color: var(--teal); }
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0 0 var(--sp-2);
  text-wrap: balance;
}
h1 { font-size: clamp(2.3rem, 5.2vw, 3.9rem); }
h2 { font-size: clamp(1.8rem, 3.8vw, 2.9rem); letter-spacing: -0.015em; }
h3 { font-size: 1.4rem; }
p { margin: 0 0 var(--sp-2); }
.container { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--sp-3); }
.btn, a, button { cursor: pointer; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-block; padding: 0.9rem 1.9rem; border-radius: 999px;
  font-weight: 700; font-size: 0.97rem; text-decoration: none; text-align: center;
  border: 1.5px solid transparent;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, transform 0.1s ease;
}
.btn:active { transform: translateY(1px); }
.btn-teal { background: var(--teal); color: #fff; }
.btn-teal:hover { background: var(--teal-dark); color: #fff; }
.btn-bronze { background: var(--bronze); color: var(--ink); }
.btn-bronze:hover { background: var(--bronze-dark); color: #fff; }
.btn-ghost-light { border-color: rgba(255,255,255,0.55); color: #fff; }
.btn-ghost-light:hover { background: rgba(255,255,255,0.12); color: #fff; }
.btn-ghost-ink { border-color: var(--ink); color: var(--ink); background: transparent; }
.btn-ghost-ink:hover { background: var(--ink); color: var(--cream); }
.btn-lg { padding: 1.05rem 2.3rem; font-size: 1.02rem; }

/* ---------- Slim header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 60;
  background: #f7f5f1;
  border-bottom: 1px solid var(--line);
  height: var(--header-h);
  transition: background 0.25s ease, border-color 0.25s ease;
}
/* CP 2026-10-05 (user spec): the overlay state is 90% opaque white (was a
   nearly-invisible 10% tint) with ink text from the start; on scroll the JS adds
   .fade-solid and it completes to 100% opaque over 1 second */
.site-header.overlay { position: fixed; top: 0; left: 0; right: 0; background: rgba(255, 255, 255, 0.9); border-bottom-color: transparent; transition: transform 2.6s cubic-bezier(0.19, 1, 0.22, 1), background 1s ease, border-color 0.25s ease; }
.site-header.overlay.fade-solid { background: rgba(255, 255, 255, 1); border-bottom-color: var(--line); }
.site-header.overlay .brand-name { color: var(--ink); }
.site-header.overlay .header-nav a { color: var(--ink); }
.site-header.overlay .header-nav a:hover { color: var(--teal); border-bottom-color: var(--teal); }
.site-header.overlay .header-phone { color: var(--ink); }
.site-header.overlay .menu-btn { background: rgba(191, 153, 114, 0.5); border: 0; color: var(--ink); }
.site-header.overlay .menu-btn:hover { background: rgba(191, 153, 114, 0.8); color: var(--ink); }
/* Text flips to dark with the background: the class is added at the same
   moment as .fade-solid and the 1s color transition below makes the text
   crossfade white -> ink over the same second as the background */
.site-header.overlay.solid .brand-name { color: var(--ink); }
.site-header.overlay.solid .header-nav a { color: var(--ink); }
.site-header.overlay.solid .header-nav a:hover { color: var(--teal); border-bottom-color: var(--teal); }
.site-header.overlay.solid .header-phone { color: var(--ink); }
.site-header.overlay.solid .menu-btn { background: rgba(191, 153, 114, 0.5); color: var(--ink); }
.site-header.overlay.solid .menu-btn:hover { background: rgba(191, 153, 114, 0.8); color: var(--ink); }
/* Book / Quote keeps its white-on-teal look in every header state
   (explicitly excluded from the text darkening) */
.site-header.overlay .header-book,
.site-header.overlay.solid .header-book { color: #fff; background: var(--teal); }
/* Text color crossfades in sync with the background fade */
.site-header.overlay .brand-name,
.site-header.overlay .header-nav a,
.site-header.overlay .header-phone { transition: color 1s ease, border-bottom-color 0.25s ease; }
.site-header.overlay .menu-btn { transition: color 1s ease, background 0.2s ease; }
.header-inner { display: flex; align-items: center; gap: var(--sp-2); height: var(--header-h); max-width: 1680px; }
.brand { display: flex; align-items: center; gap: 0.65rem; text-decoration: none; color: var(--ink); }
.brand img { height: 38px; width: auto; opacity: 0.7; transition: opacity 0.2s ease; }
.brand:hover img { opacity: 1; }
.brand-name { font-family: var(--font-display); font-weight: 700; font-size: 1.08rem; line-height: 1; letter-spacing: 0.22em; text-transform: uppercase; color: var(--ink); white-space: nowrap; }
.header-nav { display: flex; align-items: center; gap: 2.5rem; margin-left: auto; margin-right: auto; }
.header-nav a { text-decoration: none; color: var(--ink); font-weight: 600; font-size: 0.74rem; letter-spacing: 0.14em; text-transform: uppercase; white-space: nowrap; border-bottom: 2px solid transparent; padding: 0.3rem 0; }
.header-nav a:hover { color: var(--teal); border-bottom-color: var(--teal); }
@media (max-width: 1360px) { .header-nav { display: none; } }
.header-actions { display: flex; align-items: center; gap: 0.5rem; margin-left: auto; }  /* CP 2026-10-05 (user spec): the actions pin to the right edge of the
   container, so their right margin equals the container padding that sets the logo's left margin - identical
   margins both sides at every width, including when .header-nav is hidden below 1360px. Buttons keep their tight gap. */
/* CP 2026-10-05 (user spec): triple the space between the phone number and the
   booking button (0.5rem flex gap + 1rem margin = 1.5rem = 3 x 0.5rem), so the
   number sits further left. Only this gap changes - the tight gap between the
   two buttons stays 0.5rem. */
.header-phone { font-weight: 600; color: var(--ink); text-decoration: none; font-size: 0.95rem; white-space: nowrap; margin-right: 1rem; }
.header-phone:hover { color: var(--teal); }
.hp-short { display: none; }

/* Fixed bottom phone bar - replaces the phone line that used to drop below the header
   at <=720px. body reserves the same height so the page footer is never covered. */
.phone-bar { display: none; }
@media (max-width: 720px) {
  :root { --phone-bar-h: 44px; }
  .phone-bar {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 70;
    align-items: center;
    justify-content: center;
    height: var(--phone-bar-h);
    background: #4f6165;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
    color: #ffffff;
    font-weight: 600;
    font-size: 0.95rem;
    line-height: 1.4;
    text-decoration: none;
    text-align: center;
  }
  body { padding-bottom: var(--phone-bar-h); }
}
.menu-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
  background: rgba(191, 153, 114, 0.5); border: 0; color: var(--ink);
  padding: 0.55rem 1.3rem; font-weight: 600; font-size: 0.9rem;
  line-height: 1.4; min-width: 8.5rem;
  cursor: pointer; font-family: var(--font-body);
  white-space: nowrap;
  border-radius: 999px;
  transition: color 0.2s ease, background 0.2s ease;
}
.menu-btn::after { content: "\25BE"; font-size: 0.7em; line-height: 1; }
/* The hamburger artwork lives in the button as a real <img> (content:url() on ::before did not
   paint); hidden above the breakpoint, where the label pill shows instead. The supplied PNG is
   pale cream, so brightness(0) normalises it to black first and invert(1) then paints the bars
   white inside the tan pill (user spec 2026-10-06). */
.menu-btn .menu-icon { display: none; }
.menu-btn:hover { background: rgba(191, 153, 114, 0.8); color: var(--ink); }
.header-book { display: inline-flex; align-items: center; justify-content: center; background: var(--teal); color: #fff; border-radius: 999px; padding: 0.55rem 1.3rem; font-weight: 600; font-size: 0.9rem; line-height: 1.4; min-width: 8.5rem; white-space: nowrap; text-decoration: none; transition: background 0.2s ease; }
.header-book:hover { background: var(--teal-dark); color: #fff; }
/* CP 2026-10-03 (user spec): the phone number leaves the header row entirely and lives in
   the fixed bar pinned to the bottom of the viewport (.phone-bar, below), so it stays reachable
   while scrolling. The header keeps a single row - brand plus both buttons, sized to their labels
   (min-width: 0) so the row can never wrap, with a small gap after CARPET PRO. */
@media (max-width: 720px) {
  .header-phone { display: none; }
  .header-book { padding: 0.55rem 1rem; font-size: 0.85rem; min-width: 0; }
}
/* CP 2026-10-06 (user spec): the hamburger graphic replaces the Services button's label + caret
   ONLY at the small widths (<=767, the widget's single breakpoint) - above that the tan pill with
   its label stays. The artwork is kept small (16px, under the 24px brand mark) so it sits inside
   the 64px header; 6px of padding is the tap target, so the whole button is 28px square. The
   overlay states (more specific and earlier) are re-stated here so no pill shows behind it. */
@media (max-width: 767px) {
  .menu-btn .menu-label { display: none; }
  .menu-btn::after { content: none; }
  /* The supplied artwork is pale cream (#DAC6B1), so on the light header it renders as
     nothing at all unless it is darkened - brightness(0) makes it ink-black. The pill
     itself is NOT overridden here: the base and overlay rules already paint the tan
     capsule, so the full button simply swaps its words for the icon. */
  .menu-btn .menu-icon { display: block; width: 16px; height: 16px; filter: brightness(0) invert(1); }
  .menu-btn,
  .site-header.overlay .menu-btn,
  .site-header.overlay.solid .menu-btn { min-width: 0; padding: 0.5rem 0.75rem; }
}
@media (max-width: 900px) {
  .brand img { height: 32px; }
  .brand-name { font-size: 1.06rem; }
  .header-inner { gap: 0.6rem; }
}
@media (max-width: 480px) {
  .container { padding-left: 16px; padding-right: 16px; }
  .brand img { height: 24px; }
  .brand { gap: 0.4rem; }
  .brand-name { font-size: 0.8rem; letter-spacing: 0.12em; }
  .header-book { font-size: 0.72rem; padding: 0.45rem 0.7rem; min-width: 0; }
}
@media (max-width: 360px) {
  .container { padding-left: 14px; padding-right: 14px; }
  .brand-name { font-size: 0.78rem; letter-spacing: 0.1em; }
  .header-book { font-size: 0.66rem; padding: 0.4rem 0.55rem; }
  .header-inner { gap: 0.5rem; }
}
@media (max-width: 335px) {
  .brand img { display: none; }
}

/* The booking button now stays level with the wordmark and shrinks its own font when it
   would crowd it (user spec 2026-10-06, replacing the stack-below-Services layout). The
   fitting test lives in main.js: cpHdFit measures the gap and reduces the font just far
   enough to keep a 16px margin, floor 0.6rem. No layout switch, nothing moves vertically. */

/* ---------- Left slide-out services panel ---------- */
.panel-overlay {
  position: fixed; inset: 0; z-index: 80; background: rgba(2, 1, 1, 0.45);
  opacity: 0; pointer-events: none; transition: opacity 0.3s ease;
}
.panel-overlay.show { opacity: 1; pointer-events: auto; }
.services-panel {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 90;
  width: min(400px, 92vw); background: var(--white);
  transform: translateX(-105%); transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  display: flex; flex-direction: column; box-shadow: 12px 0 40px rgba(2, 1, 1, 0.18);
  overflow-y: auto;
}
.services-panel.open { transform: translateX(0); }
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.1rem 1.5rem; border-bottom: 1px solid var(--line);
}
.panel-head h2 { margin: 0; font-size: 1.15rem; color: var(--teal); }
.panel-close {
  width: 38px; height: 38px; border-radius: 50%; border: 0; background: var(--paper);
  font-size: 1.2rem; line-height: 1; color: var(--ink); display: flex; align-items: center; justify-content: center;
  transition: background 0.2s ease, color 0.2s ease;
}
.panel-close:hover { background: var(--teal); color: #fff; }
.panel-section { padding: 1.2rem 1.5rem 0.4rem; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.22em; text-transform: uppercase; color: var(--bronze-dark); }
.panel-list { list-style: none; margin: 0; padding: 0.2rem 1.5rem 1rem; }
.panel-list li { border-bottom: 1px solid var(--line); }
.panel-list a {
  display: flex; align-items: center; gap: 0.9rem; padding: 0.85rem 0.2rem;
  text-decoration: none; color: var(--ink); transition: color 0.15s ease;
}
.panel-list a:hover { color: var(--teal); }
.panel-list .num { font-family: var(--font-display); font-size: 0.8rem; color: var(--bronze); font-weight: 700; width: 1.6rem; }
.panel-list .name { font-family: var(--font-display); font-size: 1.02rem; font-weight: 600; flex: 1; }
.panel-list .arr { color: var(--bronze); font-weight: 700; }
.panel-foot { margin-top: auto; padding: 1.2rem 1.5rem 1.5rem; border-top: 1px solid var(--line); background: var(--paper); }
.panel-foot .btn { width: 100%; margin-bottom: 0.7rem; }
.panel-foot p { margin: 0.15rem 0; font-size: 0.88rem; color: var(--slate); }
/* Scoped to text links only: this rule used to win over .btn-teal (higher specificity) and
   painted the panel's green button teal-on-teal. Buttons keep their own colours in every state. */
.panel-foot a:not(.btn) { color: var(--teal); font-weight: 600; text-decoration: none; }

/* ---------- Hero slider ---------- */
.hero-slider { position: relative; height: min(87vh, 960px); min-height: 560px; overflow: hidden; background: #020101; }
.hero-slider::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 140px; z-index: 3; pointer-events: none;
  background: linear-gradient(180deg, rgba(2, 1, 1, 0.45) 0%, rgba(2, 1, 1, 0.12) 70px, rgba(2, 1, 1, 0) 140px);
}
.hero-slider::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 120px; z-index: 4; pointer-events: none;
  background: linear-gradient(180deg, rgba(247, 245, 241, 0) 0%, rgba(247, 245, 241, 0.16) 65%, rgba(247, 245, 241, 0.24) 100%);
}
.slide { position: absolute; inset: 0; opacity: 0; transition: opacity 2.2s ease; pointer-events: none; }
.slide.active { opacity: 1; pointer-events: auto; }
.slide-bg { position: absolute; inset: 0; will-change: transform; backface-visibility: hidden; }
.slide-bg img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
/* 2026-08-14: slider images are pre-cropped to the banner shape (1600x300)
   at build time, so cover has (almost) nothing left to crop. */
.hero-slider .slide-bg img { object-position: 50% 50%; }
/* CP 2026-10-06 (user spec): slide 01 keeps its right edge anchored to the window's right
   edge at every width, so as the window narrows the crop eats the LEFT of the picture
   (the van stays in frame on mobile). Slides without a data-frame keep the centred
   framing above; slide 02's two-stage rule is measured in main.js (cpSlideFrame). */
.hero-slider .slide[data-frame="right"] .slide-bg img { object-position: 100% 50%; }

.slide-content .inner { opacity: 0; transform: translateY(18px); transition: opacity 1.2s cubic-bezier(0.16, 1, 0.3, 1) 0.6s, transform 1.2s cubic-bezier(0.16, 1, 0.3, 1) 0.6s; }
.slide.active .inner { opacity: 1; transform: none; }
.slide-content { position: relative; z-index: 2; height: 100%; display: flex; align-items: center; }
@media (max-height: 620px) {
  .slide-content { align-items: flex-start; padding-top: calc(var(--header-h) + 1rem); padding-bottom: 5.5rem; }
}
.slide-content .inner {
  margin-left: 21rem;
  max-width: 660px;
}
@media (max-width: 1100px) { .slide-content .inner { margin-left: 10rem; } }
@media (max-width: 640px) { .slide-content .inner { margin-left: var(--sp-3); } }
.slide-content::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 58%;
  background: linear-gradient(90deg, rgba(2, 1, 1, 0.55) 0%, rgba(2, 1, 1, 0.3) 45%, rgba(2, 1, 1, 0.05) 75%, transparent 100%);
  pointer-events: none; z-index: 0;
}
.slide-content .inner { position: relative; z-index: 1; }
.hero-eyebrow {
  display: inline-flex; align-items: center; gap: 0.9rem; margin-bottom: 1.1rem;
  color: var(--bronze); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.3em; text-transform: uppercase;
  text-shadow: 0 1px 8px rgba(2, 1, 1, 0.6);
}
.hero-eyebrow .ln { width: 44px; height: 2px; background: var(--bronze); box-shadow: 0 1px 6px rgba(2, 1, 1, 0.5); }
.slide h1 { color: #fff; max-width: 18ch; text-shadow: 0 2px 6px rgba(0, 0, 0, 0.9), 0 8px 30px rgba(0, 0, 0, 0.8), 0 1px 2px rgba(0, 0, 0, 0.95); }
.slide p.lede { color: rgba(255, 255, 255, 0.97); max-width: 46ch; font-size: 1.12rem; text-shadow: 0 2px 6px rgba(0, 0, 0, 0.9), 0 6px 24px rgba(0, 0, 0, 0.8), 0 1px 2px rgba(0, 0, 0, 0.95); }
/* CP 2026-10-06 (user spec): a solid black glow behind every word on a slide, so the
   copy stays readable over the whitest part of a photo. Layered shadows: a tight black
   halo for contrast at any size, plus a wide one for the soft falloff. */
.slide .hero-eyebrow { text-shadow: 0 2px 6px rgba(0, 0, 0, 0.9), 0 1px 2px rgba(0, 0, 0, 0.95); }
.slide .btns { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: var(--sp-2); }
/* CP 2026-10-05 (user spec): the slider's transparent (ghost) buttons take the
   same light teal that sits behind the header's booking button, instead of a
   white outline. Scoped to the slider so the ghost buttons in the cta-bands and
   footer keep their transparent look. Declared after .btn-ghost-light, and the
   hover rule is more specific than .btn-ghost-light:hover, so both win cleanly. */
.hero-slider .btn-ghost-light { background: var(--teal); border-color: var(--teal); color: #fff; }
.hero-slider .btn-ghost-light:hover { background: var(--teal-dark); border-color: var(--teal-dark); color: #fff; }
.slider-nav { position: absolute; bottom: 1.4rem; left: 0; right: 0; z-index: 5; display: flex; justify-content: center; align-items: center; gap: 1.1rem; }
.slider-dots { display: flex; gap: 0.5rem; }
.slider-dots button {
  width: 9px; height: 9px; border-radius: 50%; border: 0; padding: 0;
  background: rgba(255,255,255,0.4); transition: background 0.25s ease, transform 0.25s ease;
}
.slider-dots button.active { background: var(--bronze); transform: scale(1.25); }
.slider-arrows { display: flex; gap: 0.5rem; }
.slider-arrows button {
  width: 40px; height: 40px; border-radius: 50%; border: 1.5px solid rgba(255,255,255,0.5);
  background: rgba(2,1,1,0.25); color: #fff; font-size: 1.05rem; line-height: 1;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.slider-arrows button:hover { background: var(--bronze); border-color: var(--bronze); color: var(--ink); }
/* "Current special" pill on the hero (user spec 2026-10-06): the same teal the buttons use
   (var(--teal), .btn-teal) as a solid background so it no longer picks up the photo behind it -
   the original was a pale yellow at 16% alpha, which blended to green over grass. */
.special-badge {
  display: inline-block; margin-top: 1.1rem; padding: 0.4rem 1rem; border-radius: 999px;
  background: var(--teal); border: 1px solid var(--teal);
  color: #fff; font-size: 0.82rem; font-weight: 600;
}

/* ---------- Trust band ---------- */
/* The band background runs edge to edge like every other section, but its cards sit on the
   page's normal gutters: max(var(--sp-3), (100% - var(--maxw)) / 2 + var(--sp-3)) is exactly
   where .container's content starts, computed from the same containing block so a scrollbar
   cannot shift one without the other. */
.trust-band { display: grid; grid-template-columns: repeat(4, 1fr); background: var(--white); border-bottom: 1px solid var(--line); padding-inline: max(var(--sp-3), calc((100% - var(--maxw)) / 2 + var(--sp-3))); }
.trust-item { padding: 2rem var(--sp-3); border-right: 1px solid var(--line); }
.trust-item:last-child { border-right: 0; }
.trust-item h3 { font-family: var(--font-body); font-size: 0.76rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.16em; color: var(--teal); margin-bottom: 0.4rem; }
.trust-item h3 .tnum { font-family: var(--font-display); color: var(--bronze); font-size: 0.95rem; margin-right: 0.5rem; }
.trust-item p { font-size: 0.92rem; color: var(--slate); margin: 0; }
/* .container drops to 16px then 14px side padding at these widths, so the band follows it. */
@media (max-width: 480px) { .trust-band { padding-inline: 16px; } }
@media (max-width: 360px) { .trust-band { padding-inline: 14px; } }
@media (max-width: 900px) { .trust-band { grid-template-columns: 1fr 1fr; } .trust-item:nth-child(2) { border-right: 0; } .trust-item { border-bottom: 1px solid var(--line); } }
@media (max-width: 540px) { .trust-band { grid-template-columns: 1fr; } .trust-item { border-right: 0; } }

/* ---------- Audience strip (who we work with) ---------- */
.audience-strip { border-bottom: 1px solid var(--line); background: var(--white); padding: 0.95rem 0; text-align: center; }
.audience-strip .container { display: flex; flex-wrap: wrap; gap: 0.55rem 0.9rem; align-items: center; justify-content: center; font-size: 0.88rem; color: var(--slate); }
.audience-strip .label { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.2em; color: var(--teal); }
.audience-strip em { font-style: normal; color: var(--bronze); }

/* ---------- Services grid (dark section imagery) ---------- */
.section { padding: var(--sp-6) 0; }
.section-head { max-width: 52ch; margin-bottom: var(--sp-3); }
.section-head .eyebrow {
  text-transform: uppercase; letter-spacing: 0.22em; font-size: 0.72rem; font-weight: 700;
  color: var(--bronze-dark); margin-bottom: var(--sp-2);
}
.services-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); }
.service-tile { background: var(--white); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; text-decoration: none; color: var(--ink); display: flex; flex-direction: column; transition: transform 0.2s ease, box-shadow 0.2s ease; }
.service-tile:hover { transform: translateY(-3px); box-shadow: 0 14px 34px rgba(2, 1, 1, 0.12); }
.service-tile .media { overflow: hidden; aspect-ratio: 16 / 9; }
.service-tile .media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.45s ease; }
.service-tile:hover .media img { transform: scale(1.06); }
.service-tile .body { padding: 1.1rem 1.2rem 1.2rem; display: flex; flex-direction: column; flex: 1; }
.service-tile h3 { font-size: 1.12rem; margin-bottom: 0.35rem; }
.service-tile p { font-size: 0.9rem; color: var(--slate); margin: 0 0 0.6rem; flex: 1; }
.service-tile .link { font-weight: 700; font-size: 0.88rem; color: var(--teal); }
@media (max-width: 960px) { .services-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 580px) { .services-grid { grid-template-columns: 1fr; } }

/* ---------- Quote band (dark) ---------- */
.quote-band { background: var(--ink); color: #d8d2c8; padding: var(--sp-5) 0; }
.quote-band .stars { color: var(--bronze); letter-spacing: 0.3em; margin-bottom: var(--sp-2); }
.quote-band blockquote {
  margin: 0; max-width: 38rem;
  font-family: var(--font-display); font-size: clamp(1.4rem, 3vw, 2rem);
  font-weight: 500; font-style: italic; line-height: 1.4; color: #fff;
}
.quote-band cite { display: block; margin-top: var(--sp-2); font-style: normal; font-size: 0.85rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--bronze); }
.quote-band cite a { color: var(--bronze); }

/* ---------- Trusted by ---------- */
.trusted-row { padding: var(--sp-3) 0; text-align: center; }
.trusted-eyebrow { font-family: var(--font-display); font-weight: 700; font-size: 0.72rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--bronze); margin: 0 0 1rem; }
.trusted-sub { margin: -0.7rem 0 1.1rem; font: 400 0.85rem/1.5 var(--font-body); color: var(--slate); }
.trusted-links { display: flex; flex-wrap: wrap; gap: 0.8rem 1.6rem; align-items: center; justify-content: center; }
.trusted-links a { color: var(--slate); font-weight: 700; font-size: 0.9rem; letter-spacing: 0.06em; text-decoration: none; transition: color 0.25s ease; }
.trusted-links a:hover { color: var(--teal); }
.trusted-links .trusted-plain { color: var(--slate); font-weight: 700; font-size: 0.9rem; letter-spacing: 0.06em; }
.trusted-links .trusted-more { color: var(--teal); }
@media (min-width: 1100px) { .trusted-links { flex-wrap: nowrap; } }
.trusted-links .trusted-item { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; }
.trusted-links .trusted-item small { font: 600 0.6rem/1.2 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--bronze); }
/* CP 2026-10-06 (user spec): this strip keeps the SAME left/right margins as the header
   (header-inner: max-width 1680px + the 24px padding) instead of the narrower 1160px page
   container, and the names shrink to fit the wider run rather than wrapping. Declared
   last so it wins over the base .trusted-links rules above. */
.trusted-row { max-width: 1680px; padding-left: var(--sp-3); padding-right: var(--sp-3); }
.trusted-links { gap: 0.8rem clamp(1rem, 1.7vw, 1.6rem); }
.trusted-links a, .trusted-links .trusted-plain { font-size: clamp(0.7rem, 1.02vw, 0.9rem); }

/* Places we love page: linked partner groups by category */
.partner-group { border-top: 1px solid var(--line); padding: var(--sp-3) 0; }
.partner-group h2 { font-size: 1.3rem; margin: 0 0 1rem; }
.partner-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.7rem 2rem; }
.partner-list a { color: var(--slate); text-decoration: none; font-weight: 600; transition: color 0.25s ease; }
.partner-list a:hover { color: var(--teal); }

/* ---------- CTA band ---------- */
.cta-band { background: var(--teal); color: #fff; padding: var(--sp-5) 0; text-align: center; }
.cta-band h2 { color: #fff; }
.cta-band p { color: rgba(255, 255, 255, 0.92); max-width: 46rem; margin: 0 auto var(--sp-3); }
.cta-actions { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }

/* ---------- Footer ---------- */
/* CP 2026-10-06 (user spec): the logo blown up behind the footer at 70% transparency
   (opacity .3), sized in viewport units so it grows and shrinks with the window and part
   of the fern always sits behind the writing. The content column is lifted above it. */
.site-footer { position: relative; overflow: hidden; background: var(--ink); color: #b3aca1; padding: var(--sp-5) 0 0; font-size: 0.94rem; }
.site-footer::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  /* 5x the previous clamp(300px, 46vw, 760px), and the fern's CENTRE is pinned to 75% of the
     viewable screen: left edge = 75vw - half the image, so the centre stays at 75% at every
     window size, at every breakpoint, and after any resize (user spec 2026-10-06). */
  --fern: clamp(1500px, 230vw, 3800px);
  background: url("/assets/img/logo.png") no-repeat;
  background-size: var(--fern) auto;
  background-position: calc(75vw - var(--fern) / 2) 45%;
  opacity: 0.25;   /* 75% transparent (user spec 2026-10-06) */
}
.site-footer > .container { position: relative; z-index: 1; }
/* The big title Carpet Pro goes white (user spec 2026-10-06), as does the footer's own
   "Carpet Pro" heading; the Services/Company/Trusted By headings keep the bronze. */
.footer-wordmark { font-family: var(--font-display); font-weight: 700; font-size: clamp(2.6rem, 9vw, 7.5rem); line-height: 1; color: #fff; letter-spacing: -0.01em; margin-bottom: var(--sp-3); user-select: none; }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1.4fr; gap: var(--sp-4); padding: var(--sp-3) 0 var(--sp-4); border-top: 1px solid rgba(255,255,255,0.1); }
.footer-grid h3 { color: var(--bronze); font-family: var(--font-body); font-size: 0.74rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.2em; margin-bottom: var(--sp-2); }
.footer-grid a { color: #b3aca1; text-decoration: none; display: block; padding: 0.22rem 0; }
.footer-grid a:hover { color: #fff; }
.footer-contact p { margin: 0 0 0.35rem; }
.footer-contact h3 { color: #fff; }
.footer-bottom { border-top: 1px solid rgba(255,255,255,0.1); padding: var(--sp-2) 0 var(--sp-3); font-size: 0.8rem; color: #6e675e; display: flex; flex-wrap: wrap; gap: 0.4rem 1.5rem; justify-content: space-between; }
@media (max-width: 800px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .footer-grid { grid-template-columns: 1fr; } }

/* ---------- Page hero: full-area photo, bronze panel half-width, vertically centered ---------- */
/* The header is fixed over this hero (main.js adds .overlay wherever a .page-hero or the
   slider exists), so the picture starts at y=0 behind it. Top padding is therefore the
   header height + the old 32px, bottom keeps its 32px: the difference (64px) is exactly
   the header, which puts the panel's centre on the middle of the band between the
   header's bottom edge and the bottom of the picture, at any hero height. */
.page-hero { position: relative; min-height: 390px; display: flex; align-items: center; justify-content: flex-start; background: var(--teal-deep); border-bottom: 1px solid var(--line); overflow: hidden; padding: calc(var(--header-h) + var(--sp-4)) var(--sp-3) var(--sp-4); }
.ph-bg { position: absolute; inset: 0; }
.ph-bg img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ph-panel { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 0.55rem; background: var(--bronze); padding: var(--sp-3) var(--sp-3); width: 25%; max-width: none; text-align: left; box-shadow: 0 24px 60px rgba(2, 1, 1, 0.28); }
.ph-panel h1 { margin: 0; color: #fff; font-size: clamp(1.7rem, 3.4vw, 2.5rem); text-shadow: 0 1px 10px rgba(2, 1, 1, 0.28); }
.ph-panel p { margin: 0; color: rgba(255, 255, 255, 0.95); font-size: 0.97rem; max-width: 46ch; }
.ph-crumb { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.18em; color: rgba(255, 255, 255, 0.88); }
.ph-crumb a { color: rgba(255, 255, 255, 0.88); text-decoration: none; }
.ph-crumb a:hover { text-decoration: underline; }
.ph-crumb span { color: #fff; }
@media (max-width: 860px) {
  .page-hero { min-height: 340px; }
  .ph-panel { width: 58vw; }
}
@media (max-width: 620px) {
  .page-hero { min-height: 300px; }
  .ph-panel { width: 76vw; }
}
@media (max-width: 440px) {
  .page-hero { min-height: 280px; }
  /* full run of the hero's content box: 24px margins either side, and the box grows
     sideways instead of taller, so the panel keeps its top and bottom air */
  .ph-panel { width: 100%; }
}

/* ---------- Before/after marquee gallery (for-living style scroller) ---------- */
.ba-strip { overflow: hidden; padding: 1.5rem 0 2.2rem; }
.ba-track { display: flex; width: max-content; animation: baScroll 220s linear infinite; will-change: transform; }
.ba-strip:hover .ba-track { animation-play-state: paused; }
.ba-card { flex: 0 0 auto; width: clamp(480px, 54vw, 780px); margin: 0 var(--sp-3) 0 0; background: var(--white); border: 1px solid #4f6165; border-radius: 2px; padding: 8px 8px 0.65rem; transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.5s ease, border-color 0.5s ease; }
.ba-card img { display: block; width: 100%; height: auto; }
.ba-card figcaption { margin-top: 0.55rem; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.14em; color: #4f6165; text-align: center; }
.ba-card:hover { transform: scale(1.05); border-color: var(--bronze); box-shadow: 0 20px 44px rgba(2, 1, 1, 0.16); }
@keyframes baScroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .ba-track { animation: none; }
  .ba-strip { overflow-x: auto; }
}

/* ---------- Preloader (homepage landing reveal) ---------- */
.cp-preloader { position: fixed; inset: 0; z-index: 20000; display: flex; align-items: center; justify-content: center; background: var(--paper); opacity: 1; transition: opacity 0.55s ease 0.1s, visibility 0s 0.75s; }
.cp-preloader.done { opacity: 0; visibility: hidden; }
.cp-pre-mark { font-family: var(--font-display); font-size: 1.02rem; letter-spacing: 0.34em; text-indent: 0.34em; text-transform: uppercase; color: var(--ink); }
.cp-pre-mark::after { content: ""; display: block; margin: 0.85rem auto 0; width: 100%; height: 1px; background: var(--bronze); transform: scaleX(0); transform-origin: center; animation: cpline 1.5s cubic-bezier(0.16, 1, 0.3, 1) 0.25s forwards; }
@keyframes cpline { 0% { transform: scaleX(0); opacity: 0.5; } 100% { transform: scaleX(1); opacity: 1; } }

/* ---------- Hero intro stagger (homepage landing reveal, JS-gated) ---------- */
html.js .hero-intro { opacity: 0; transform: translateY(16px); transition: opacity 1.35s cubic-bezier(0.19, 1, 0.22, 1), transform 1.35s cubic-bezier(0.19, 1, 0.22, 1); transition-delay: var(--hd, 0s); }
html.js .hero-intro.in { opacity: 1; transform: none; }
/* Hero image fades in as the splash lifts: JS adds .intro on load and
   removes it when the text stagger starts, so the active slide glides
   from black to full over its 1.4s crossfade transition. */
html.js .hero-slider.intro .slide.active { opacity: 0; }

/* Header slides in from the top at half the intro speed (for-living style) */
html.js .site-header { transform: translateY(-110%); transition: transform 2.6s cubic-bezier(0.19, 1, 0.22, 1), background 0.25s ease, border-color 0.25s ease; }
html.js .site-header.in { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .cp-preloader { display: none; }
  html.js .hero-intro { opacity: 1; transform: none; transition: none; }
  html.js .hero-slider.intro .slide.active { opacity: 1; }
  html.js .site-header { transform: none; transition: none; }
}

/* ---------- Booking embed ---------- */
.booking-frame-wrap { width: 70vw; max-width: none; margin-left: calc(50% - 35vw); background: var(--white); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.booking-frame-header { display: none; }
.booking-frame-wrap iframe { display: block; width: 100%; height: 950px; border: 0; overscroll-behavior: contain; }
.booking-fallback { margin-top: var(--sp-3); text-align: center; color: var(--slate); font-size: 0.95rem; }
@media (max-width: 1100px) {
  /* CP 2026-10-05 (user spec): ONE disappearance point for the widget cart sidebar.
     Above 1100 the frame is 70vw (>= 770.7px) and here it fills the container but is
     never under 770px - 768 for the widget plus the wrap's 1px borders - so the iframe
     inner width stays >= 768 while the viewport is >= 768. Without this the sidebar
     dipped under 768 at ~1097 (0.7 * width) and reappeared at <=1024. Final cut
     stays <=767 like the widget. */
  .booking-frame-wrap { width: max(100%, 770px); margin-left: calc((100% - max(100%, 770px)) / 2); margin-right: 0; }
}
.booking-top { padding-top: 2rem; }
.booking-top h1 { text-align: center; margin-bottom: 1.5rem; }
.booking-tabs {
  width: 90vw; max-width: none; margin-left: calc(50% - 45vw);
  display: flex; flex-wrap: nowrap; align-items: center; justify-content: center;
  gap: clamp(3px, 0.45vw, 7px); margin-bottom: 1rem;
  counter-reset: bookingtab;
}
.booking-tab {
  appearance: none;
  display: inline-flex; align-items: baseline;
  padding: 8px clamp(5px, 0.7vw, 11px);
  background: transparent;
  border: 1px solid #4f6165;
  border-radius: 2px;
  color: #4f6165;
  font: 600 0.8rem/1.2 "Inter", system-ui, sans-serif;
  font-size: clamp(0.36rem, 0.75vw, 0.9rem);
  letter-spacing: 0.01em;
  white-space: nowrap;
  flex-shrink: 0;
  cursor: pointer;
  counter-increment: bookingtab;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.booking-tab::before {
  content: counter(bookingtab, decimal-leading-zero);
  color: var(--bronze);
  font-weight: 700;
  font-size: 0.82em;
  letter-spacing: 0.16em;
  margin-right: 0.45em;
}
.booking-tab:hover, .booking-tab:focus-visible {
  background: #4f6165; color: #ffffff; outline: none;
}
.booking-tab:hover::before, .booking-tab:focus-visible::before { color: #e3c5a3; }
.booking-tab:active { background: #405458; border-color: #405458; color: #ffffff; }
/* Selected tab keeps the hover fill while the widget is on that service's extras. */
.booking-tab.selected, .booking-tab.selected:hover { background: #4f6165; color: #ffffff; }
.booking-tab.selected::before { color: #e3c5a3; }
/* Mobile service dropdown (replaces the tab chips under 768px). */
.booking-select-wrap { display: none; margin-bottom: 1rem; }
.booking-select-label {
  display: block;
  font: 700 0.66rem/1 "Spectral", Georgia, serif;
  /* scales down with the viewport so the label reaches the 10px floor and rule 3
     (dropdown alone) can fire below ~625px instead of overflowing the row */
  font-size: clamp(0.5rem, 1.6vw, 0.66rem);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bronze);
  margin-bottom: 0.55rem;
}
.booking-select {
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background: #ffffff;
  border: 1px solid #4f6165;
  border-radius: 2px;
  color: #24333a;
  font: 600 1rem/1.4 "Inter", system-ui, sans-serif;
  letter-spacing: 0.01em;
  padding: 0.85rem 2.6rem 0.85rem 1rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%234f6165' stroke-width='1.5' stroke-linecap='square'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
}
.booking-select:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }

/* CP 2026-10-03 (user spec): the service control follows the RENDERED font size,
   not the viewport width - the tab chips scale with clamp(0.36rem, 0.75vw, 0.9rem),
   so 10px of tab text is the readable floor. The inline sync script on the booking
   page measures the computed sizes and sets these two classes on <html>:
     tab text >= 10px -> tab chips as they are now
     tab text <  10px -> "Choose your service:" + dropdown, the pair centred
     label    <  10px -> dropdown alone, centred */
html.cp-tabs-tiny .booking-tabs { display: none; }
html.cp-tabs-tiny .booking-select-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
}
html.cp-tabs-tiny .booking-select-label {
  display: inline;
  margin-bottom: 0;
  white-space: nowrap;
}
html.cp-tabs-tiny .booking-select { width: auto; min-width: min(20rem, 100%); }
html.cp-label-tiny .booking-select-label { display: none; }
@media (max-width: 767px) {
  .booking-top .container { padding-left: 0.75rem; padding-right: 0.75rem; }
  .booking-top { padding-top: 1.25rem; }
  .booking-top h1 { font-size: clamp(1.5rem, 6.2vw, 1.9rem); margin-bottom: 1rem; }
  /* tabs -> dropdown used to be switched here by viewport width; it now follows
     the rendered font size via cp-tabs-tiny / cp-label-tiny (see below). */
  .booking-frame-header {
    display: flex;
    width: 100%;
    max-width: 42rem;
    margin: 0 auto;
    border: 1px solid var(--line);
    border-bottom: 0;
    border-radius: 6px 6px 0 0;
    overflow: hidden;
    background: var(--white);
  }
  .booking-mode-button {
    flex: 1;
    /* CP 2026-10-03 (user spec): 1/3 shorter on mobile */
    min-height: calc(44px * 2 / 3);
    border: 0;
    border-right: 1px solid var(--line);
    background: var(--white);
    color: var(--slate);
    font: 700 0.82rem/1 "Inter", system-ui, sans-serif;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
  }
  .booking-mode-button:last-child { border-right: 0; }
  .booking-mode-button.is-active { background: var(--teal); color: #fff; }
  .booking-mode-button:focus-visible { outline: 2px solid var(--bronze); outline-offset: -2px; }
  .booking-frame-wrap {
    width: 100%;
    max-width: 42rem;
    margin: 0 auto;
    border-radius: 0 0 6px 6px;
  }
}
@media (max-width: 480px) {
  .booking-top { padding-top: 1rem; }
  .booking-top h1 { font-size: 1.5rem; margin-bottom: 0.9rem; }
}

/* Booking page: title + supporting line (user spec 2026-10-05). Declared after the
   booking media queries above so the tighter title-to-line spacing holds at every
   width instead of being reset by the mobile h1 rules. */
.booking-top h1 { margin-bottom: 0.55rem; }
.booking-lede { text-align: center; color: var(--slate); font-size: 1rem; line-height: 1.55; max-width: 44rem; margin: 0 auto var(--sp-3); }

/* Contact page: lightbox that hosts the widget's contact-form popup. */
.contact-form-lightbox { position: fixed; inset: 0; z-index: 2000; background: rgba(15, 23, 42, 0.55); display: flex; align-items: center; justify-content: center; padding: 20px; }
.contact-form-lightbox[hidden] { display: none; }
.contact-form-lightbox iframe { width: min(620px, 94vw); height: min(760px, 88vh); background: #fff; border: 0; border-radius: 12px; box-shadow: 0 18px 50px rgba(2, 1, 1, 0.35); }
.contact-form-lightbox .cfl-close { position: absolute; top: 14px; right: 18px; background: #405458; color: #fff; border: 0; border-radius: 50%; width: 36px; height: 36px; font-size: 1.15rem; line-height: 1; cursor: pointer; z-index: 1; }
.contact-card-btn { font: inherit; text-align: left; width: 100%; cursor: pointer; }

/* ---------- Content pages ---------- */
.page-lead { font-size: 1.18rem; color: var(--slate); max-width: 60ch; }
/* Services intro list (user spec 2026-10-05): the three ways to start, as a real
   bulleted list. Every other list on the site is list-style:none, so the markers
   are styled here - bronze discs to stay in the palette, block layout (grid/flex
   on the ul would swallow the markers in Chrome). */
.lead-list { list-style: disc; padding-left: 1.35rem; margin: 0 0 var(--sp-2); font-size: 1.05rem; color: var(--slate); }
.lead-list li { margin-bottom: 0.45rem; }
.lead-list li:last-child { margin-bottom: 0; }
.lead-list li::marker { color: var(--bronze); }
.lead-list strong { color: var(--ink); }
/* Services intro (user spec 2026-10-06): heading + blurb on the left, photo on the right.
   The grid column sets the measure, so the section-head's 52ch cap is lifted here. */
.intro-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 38%); gap: var(--sp-4); align-items: center; }
.intro-split .section-head { max-width: none; margin-bottom: 0; }
.intro-media img { display: block; width: 100%; height: auto; box-shadow: 16px 20px 44px rgba(2, 1, 1, 0.16); }
@media (max-width: 900px) { .intro-split { grid-template-columns: 1fr; gap: var(--sp-3); } }
/* Case studies intro (user spec 2026-10-06): centred and wider than the default 52ch
   section head, so the lede sits in two lines on desktop; the 46rem cap is what keeps it
   at two, and below that the column itself narrows and it simply re-wraps. */
.case-intro .section-head { max-width: 46rem; margin-left: auto; margin-right: auto; text-align: center; }
.case-intro .lede { max-width: none; }
.rule { border: 0; border-top: 1px solid var(--line); margin: var(--sp-4) 0; }

/* ---------- Reveal (subtle) ---------- */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity 1.2s cubic-bezier(0.16, 1, 0.3, 1), transform 1.2s cubic-bezier(0.16, 1, 0.3, 1); }
.reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .slide, .slide-content .inner { transition: none; }
  .slide-content .inner { opacity: 1; transform: none; }
}

/* ---------- Focus & a11y ---------- */
a:focus-visible, button:focus-visible { outline: 3px solid var(--bronze); outline-offset: 2px; }
.skip-link { position: absolute; left: -9999px; top: 0; background: var(--ink); color: #fff; padding: 0.6rem 1rem; z-index: 100; }
.skip-link:focus { left: 0; }

/* ============================================================
   Page components (v29): split/blob, stats, process, faq,
   compare sliders, reviews, gallery, chips, cta, reveal variants
   ============================================================ */

/* Uniform vertical rhythm (2026-08-17 user spec): every content band
   between hero and footer gets the same top/bottom padding, so headings
   and blocks never sit flush against a neighbouring section. */
.certs-band, .values-band, .rug-notes, .rating-band, .review-cta,
.repair-gallery, .fibre-care, section.faq, .expect-band,
.contact-note, .contact-grid, .compare-band { padding: var(--sp-5) 0; }

/* Split sections + blob image shapes */
/* These sections must stay plain blocks: the grid rule they used to carry made their only
   child (.container) a grid item in the first column, pinning the picture and the blurb to the
   window's left edge (x=24) while every other section sits inside the centred container
   (x=164 at 1440px). The container now centres itself, so picture and blurb share the page's
   left alignment at every width. The 66ch cap keeps the stacked copy readable. */
.split { padding: var(--sp-6) 0; }
.split .copy { max-width: 66ch; }
/* The seven-step blurb keeps HALF the usual section rhythm above and below it (user spec):
   .section gives 64px top/bottom (var(--sp-6)) and .section-head 24px (var(--sp-3)). */
/* The seven-step blurb: the gap to the cards above is half what it was (64px of .section
   padding below the cards + 32px here = 96px -> 16px + 32px = 48px), and the text runs the
   full container width - the same left and right edges as the note cards (52ch cap lifted). */
.qa-band { padding-bottom: calc(var(--sp-6) / 4); }
.step-note { padding-top: calc(var(--sp-6) / 2); padding-bottom: calc(var(--sp-6) / 2); }
.step-note .section-head { max-width: none; margin-bottom: calc(var(--sp-3) / 2); }
/* The "once per year" calendar is a small illustration, not a photo: the PNG is 976px across,
   so the column is capped well below that, the image scales inside the cap (never stretches)
   and drops the photo shadow. The CTA button sits directly beneath the graphic (user spec). */
.split.schedule .media { max-width: 240px; }
.split.schedule .media img { display: block; width: 100%; height: auto; box-shadow: none; }
/* The two timing graphics sit side by side and stack once the columns get too narrow. */
.stat-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; }
.stat-pair img { display: block; width: 100%; height: auto; }
@media (max-width: 620px) { .stat-pair { grid-template-columns: 1fr; } }
/* Full-bleed tan band behind the schedule block, 50% transparent (user spec). */
.split.schedule { background: rgba(191, 153, 114, 0.5); }
/* Two-up variant: text BESIDE the picture. The base .split stays a plain block so the service
   pages keep their left alignment (see above); this class only re-introduces the row where a
   two-column layout is actually wanted, and reverts to the stacked, left-aligned flow under
   1000px exactly like every other split. */
.split.two-col > .container { display: grid; grid-template-columns: 1fr 1fr; gap: 2.5rem; align-items: center; }
/* The CTA is a direct child of the container so CSS decides where it lands: in the grid it
   auto-places into column 1, row 2 (straight under the heading); once the <=1000px rule turns
   the container into a stacked column, order 3 puts it last - i.e. under the graphic, which is
   only then below the heading (user spec 2026-10-06). */
.split.schedule > .container { row-gap: 1rem; }
.split.schedule > .container > .btn { order: 3; justify-self: start; align-self: start; }
@media (max-width: 1000px) { .split.two-col > .container { display: flex; flex-direction: column; gap: var(--sp-4); align-items: stretch; } }
.split .media { max-width: 420px; }
.split .media { position: relative; }
.split .media img { box-shadow: 16px 20px 44px rgba(2, 1, 1, 0.16); }
.blob { border-radius: 58% 42% 55% 45% / 45% 58% 42% 55%; overflow: hidden; box-shadow: 0 24px 60px rgba(2, 1, 1, 0.16); }
.blob img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.8s ease; }
.blob:hover img { transform: scale(1.05); }
.blob-ghost::after { content: ""; position: absolute; inset: 7% -4% -4% 7%; border-radius: 62% 38% 48% 52% / 52% 44% 56% 48%; background: var(--bronze); opacity: 0.22; z-index: -1; animation: blobMorph 14s ease-in-out infinite alternate; }
@keyframes blobMorph { from { border-radius: 62% 38% 48% 52% / 52% 44% 56% 48%; } to { border-radius: 45% 55% 60% 40% / 45% 60% 40% 55%; } }
.split .copy h2 { margin-top: var(--sp-1); }
.split .copy p { color: var(--slate); }
@media (max-width: 1000px) {
  .split { grid-template-columns: 1fr; gap: var(--sp-4); padding: var(--sp-5) 0; }
  .split .container { display: flex; flex-direction: column; gap: var(--sp-4); }
  .split .media { max-width: 560px; }
  /* mobile consistency: title+description above, photo below, for every split row */
  .split .copy { order: 1; }
  .split .media { order: 2; margin: 0; }
}

/* Value ticks */
.value-tick { list-style: none; margin: var(--sp-3) 0 0; padding: 0; display: grid; gap: 0.7rem; }
.value-tick li { position: relative; padding-left: 2rem; color: var(--ink-soft); }
.value-tick li::before { content: ""; position: absolute; left: 0; top: 0.28em; width: 1.1rem; height: 1.1rem; border-radius: 50%; background: var(--teal); }
.value-tick li::after { content: "\2713"; position: absolute; left: 0.18rem; top: 0.2em; color: #fff; font-size: 0.68rem; font-weight: 700; }

/* Stats band */
.stats-band { padding: var(--sp-5) 0; }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.1rem; }
.stat { text-align: center; padding: 2rem 1rem; background: var(--white); border: 1px solid var(--line); border-radius: 18px; }
.stat b { display: block; font-family: var(--font-display); font-size: 2.7rem; line-height: 1.05; color: var(--teal); font-weight: 600; }
.stat span { color: var(--slate); font-size: 0.86rem; }
@media (max-width: 1000px) { .stats { grid-template-columns: 1fr 1fr; } }

/* Steps / process */
.steps-band { padding: var(--sp-5) 0; }
.process { display: grid; gap: 1rem; }
.process.two { grid-template-columns: 1fr 1fr; }
.step { display: flex; gap: 1.2rem; background: var(--white); border: 1px solid var(--line); border-radius: 16px; padding: 1.4rem 1.6rem; transition: transform 0.25s ease, box-shadow 0.25s ease; }
.step:hover { transform: translateY(-4px); box-shadow: 0 14px 34px rgba(2, 1, 1, 0.08); }
.step .n { font-family: var(--font-display); font-size: 1.7rem; color: var(--bronze); font-weight: 700; line-height: 1; min-width: 2.4rem; }
.step h3 { margin: 0 0 0.4rem; font-size: 1.12rem; }
.step p { margin: 0; color: var(--slate); font-size: 0.95rem; }
@media (max-width: 800px) { .process.two { grid-template-columns: 1fr; } }

/* Fibre cards / notes / who grids */
.fibre-grid, .notes-grid, .who-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; margin-top: var(--sp-3); }
.fibre-card, .note, .who { background: var(--white); border: 1px solid var(--line); border-radius: 16px; padding: 1.5rem; transition: transform 0.25s ease, box-shadow 0.25s ease; }
.fibre-card:hover, .note:hover, .who:hover { transform: translateY(-4px); box-shadow: 0 14px 34px rgba(2, 1, 1, 0.08); }
.note .ic-badge { display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; border-radius: 50%; background: var(--teal); color: #fff; font-size: 1.05rem; line-height: 1; margin-bottom: 0.7rem; }
.fibre-card h3, .note h3, .who h3 { margin: 0 0 0.4rem; font-size: 1.08rem; }
.fibre-card p, .note p, .who p { margin: 0; color: var(--slate); font-size: 0.95rem; }
@media (max-width: 1000px) { .fibre-grid, .notes-grid, .who-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 620px) { .fibre-grid, .notes-grid, .who-grid { grid-template-columns: 1fr; } }

/* Guarantee band */
.guarantee-band { padding: var(--sp-5) 0; }
/* CP 2026-10-06 (user spec): solid palette colour, no gradient and no animated blobs. */
.guarantee { display: flex; gap: 1.2rem; align-items: flex-start; background: var(--teal); color: #fff; border-radius: 20px; padding: 2.2rem 2.4rem; position: relative; overflow: hidden; }
.guarantee > * { position: relative; }
.guarantee .g-ic { font-size: 1.6rem; color: var(--bronze); line-height: 1.2; }
.guarantee h2 { color: #fff; margin: 0 0 0.4rem; font-size: 1.5rem; }
.guarantee p { color: #fff; margin: 0; }   /* #cfe0e8 all but vanished against the lighter teal */

/* FAQ accordion */
.faq { max-width: 780px; margin: 0 auto; }
.qa { border: 1px solid var(--line); border-radius: 14px; background: var(--white); margin-bottom: 0.8rem; overflow: hidden; }
.qa > button { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 1.15rem 1.4rem; background: none; border: 0; font: inherit; font-weight: 700; color: var(--ink); text-align: left; cursor: pointer; }
.qa > button:hover { color: var(--teal); }
.qa .ic { color: var(--bronze); font-weight: 700; font-size: 1.3rem; transition: transform 0.3s ease; flex: none; }
.qa.open .ic { transform: rotate(45deg); }
.qa .a { max-height: 0; overflow: hidden; transition: max-height 0.4s ease; }
.qa .a > div { padding: 0 1.4rem 1.2rem; color: var(--slate); font-size: 0.97rem; }

/* Before/after compare sliders */
.compare-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; margin-top: var(--sp-3); }
.compare-grid.three { grid-template-columns: repeat(3, 1fr); }
.compare { position: relative; border-radius: 18px; overflow: hidden; aspect-ratio: 4 / 3; cursor: ew-resize; touch-action: pan-y; user-select: none; box-shadow: 0 20px 50px rgba(2, 1, 1, 0.14); background: var(--teal-deep); }
.compare img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.compare .after { clip-path: inset(0 0 0 var(--pos, 90%)); }
.compare .divider { position: absolute; top: 0; bottom: 0; left: var(--pos, 90%); width: 3px; background: #fff; transform: translateX(-50%); box-shadow: 0 0 12px rgba(2, 1, 1, 0.5); pointer-events: none; }
.compare .handle { position: absolute; top: 50%; left: var(--pos, 90%); transform: translate(-50%, -50%); width: 46px; height: 46px; border-radius: 50%; background: #fff; color: var(--teal); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 1.15rem; box-shadow: 0 4px 16px rgba(2, 1, 1, 0.35); pointer-events: none; }
.compare .tag { position: absolute; top: 12px; padding: 4px 12px; border-radius: 999px; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; background: rgba(2, 1, 1, 0.55); color: #fff; pointer-events: none; }
.compare .tag.b { left: 12px; }
.compare .tag.a { right: 12px; }
@media (max-width: 1000px) { .compare-grid.three { grid-template-columns: 1fr 1fr; } }
@media (max-width: 700px) { .compare-grid, .compare-grid.three { grid-template-columns: 1fr; } }
.compare-more { text-align: center; margin-top: var(--sp-4); }

/* Reviews */
.reviews-band { padding: var(--sp-5) 0; }
.review-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.3rem; }
.review-card { background: var(--white); border: 1px solid var(--line); border-radius: 18px; padding: 1.5rem; display: flex; flex-direction: column; gap: 0.75rem; transition: transform 0.25s ease, box-shadow 0.25s ease; }
.review-card:hover { transform: translateY(-5px); box-shadow: 0 18px 40px rgba(2, 1, 1, 0.09); }
.review-card .stars { color: var(--bronze); letter-spacing: 0.18em; font-size: 0.95rem; }
.review-card blockquote { margin: 0; color: var(--ink-soft); font-size: 0.95rem; line-height: 1.6; }
.review-card cite { font-style: normal; font-weight: 700; color: var(--teal); font-size: 0.85rem; margin-top: auto; }
@media (max-width: 1000px) { .review-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 620px) { .review-grid { grid-template-columns: 1fr; } }

/* Case gallery */
.gallery-band { padding: var(--sp-5) 0; }
.case-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.3rem; }
.case-card { position: relative; border-radius: 16px; overflow: hidden; aspect-ratio: 4 / 3; box-shadow: 0 10px 30px rgba(2, 1, 1, 0.1); }
.case-card img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s ease; }
.case-card:hover img { transform: scale(1.06); }
.case-card .cap { position: absolute; left: 0; right: 0; bottom: 0; padding: 1.4rem 1rem 0.8rem; background: linear-gradient(transparent, rgba(2, 1, 1, 0.75)); color: #fff; font-size: 0.82rem; font-weight: 600; }
@media (max-width: 1000px) { .case-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 620px) { .case-grid { grid-template-columns: 1fr; } }

/* Chips */
.chips { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.chip { padding: 0.45rem 1.05rem; border-radius: 999px; border: 1px solid var(--teal); color: var(--teal); font-size: 0.85rem; font-weight: 600; transition: background 0.2s ease, color 0.2s ease; }
.chip:hover { background: var(--teal); color: #fff; }

/* Contact cards */
.contact-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.2rem; margin: var(--sp-3) 0; }
.contact-card { display: block; background: var(--white); border: 1px solid var(--line); border-radius: 18px; padding: 1.6rem 1.4rem; text-align: center; text-decoration: none; color: var(--ink); transition: transform 0.25s ease, box-shadow 0.25s ease; }
.contact-card:hover { transform: translateY(-5px); box-shadow: 0 18px 40px rgba(2, 1, 1, 0.09); }
.contact-card .c-ic { font-size: 1.5rem; color: var(--bronze); }
.contact-card h3 { margin: 0.6rem 0 0.25rem; font-size: 1.05rem; }
.contact-card p { margin: 0; color: var(--slate); font-size: 0.92rem; }
.contact-areas { margin-top: var(--sp-4); }
@media (max-width: 1000px) { .contact-cards { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .contact-cards { grid-template-columns: 1fr; } }

/* Intro blocks (promise/faq/reviews) */
.promise-intro { max-width: 56ch; margin: 0 auto; text-align: center; padding: var(--sp-5) 0 var(--sp-2); }
.promise-intro h2 { margin-top: var(--sp-1); }
.promise-intro p { color: var(--slate); }

/* CTA band: dark teal, fully opaque, no moving light */
.cta-band { position: relative; overflow: hidden; background: var(--teal-deep); }
.cta-band .container { position: relative; }

/* Reveal variants (stagger via --rd) */
[data-reveal] { opacity: 0; transform: translateY(28px); transition: opacity 1.35s cubic-bezier(0.16, 1, 0.3, 1), transform 1.35s cubic-bezier(0.16, 1, 0.3, 1); transition-delay: var(--rd, 0s); }
[data-reveal].in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
  .blob-ghost::after { animation: none; }
}

/* ============================================================
   Architect style (v30): arches, drawing markers, index rows
   ============================================================ */

/* Section markers (drawing notation) */
.sec-mark { display: flex; align-items: center; gap: 1rem; margin-bottom: var(--sp-2); }
.sec-mark .num { font-family: var(--font-display); color: var(--bronze); font-weight: 700; font-size: 0.9rem; letter-spacing: 0.08em; }
.sec-mark .line { flex: 0 0 3rem; height: 1px; background: var(--bronze); opacity: 0.6; }
.sec-mark .label { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.22em; color: var(--teal); }

/* Featured service rows (architect elevation style) */
.feat { display: grid; grid-template-columns: 320px 1fr; gap: var(--sp-5); align-items: center; padding: var(--sp-4) 0; }
.feat.copy-first { grid-template-columns: 1fr 320px; }
.feat .media { width: min(100%, 320px); }
/* Each row already carries 32px of padding top and bottom (64px of visible air between two
   rows); 1.5x that is 96px, so half again is added BETWEEN rows only. The space above 01 is
   deliberately left alone (user spec 2026-10-06). Under 1000px the rows carry 24px each, so
   the same 1.5x rule adds 24px there. */
.feat + .feat { margin-top: var(--sp-4); }
.feat .copy h3 { font-size: 1.9rem; margin-bottom: 0.6rem; }
.feat .copy p { color: var(--slate); }
.feat .copy .eyebrow { margin-bottom: var(--sp-2); }
.feat .link { display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 700; color: var(--teal); text-decoration: none; margin-top: 0.8rem; transition: gap 0.25s ease, color 0.25s ease; }
.feat .link:hover { color: var(--bronze-dark); gap: 0.9rem; }

/* Photos: clean rectangles with a soft bottom-right shadow (matching the
   about-page treatment; the old arch/squircle shapes are retired) */
.feat .media img { box-shadow: 16px 20px 44px rgba(2, 1, 1, 0.16); }
@media (max-width: 1000px) {
  .feat, .feat.copy-first { grid-template-columns: 1fr; gap: var(--sp-3); padding: var(--sp-3) 0; }
  .feat + .feat { margin-top: var(--sp-3); }
  .feat .media, .feat.copy-first .media { margin: 0 auto; }
  /* mobile consistency: title+description above, photo below, for every feature row */
  .feat .copy, .feat.copy-first .copy { order: 1; }
  .feat .media, .feat.copy-first .media { order: 2; }
}

/* Services index (drawing index rows) */
.svc-index { border-top: 1px solid var(--line); margin-top: var(--sp-4); }
.svc-index a { display: flex; align-items: center; gap: 1.4rem; padding: 1.3rem 0.4rem; border-bottom: 1px solid var(--line); text-decoration: none; color: var(--ink); transition: padding 0.25s ease, color 0.25s ease, background 0.25s ease; }
.svc-index a:hover { padding-left: 1.1rem; color: var(--teal); background: var(--white); }
.svc-index .n { font-family: var(--font-display); color: var(--bronze); font-weight: 700; font-size: 0.85rem; min-width: 2.2rem; }
.svc-index h3 { margin: 0; font-size: 1.15rem; flex: 1; }
.svc-index p { margin: 0; color: var(--slate); font-size: 0.9rem; flex: 1.6; }
.svc-index .arr { color: var(--bronze); font-size: 1.2rem; transition: transform 0.25s ease; }
.svc-index a:hover .arr { transform: translateX(4px); }
@media (max-width: 700px) { .svc-index p { display: none; } }

/* Full-width bleed (v31) */
/* Full-bleed feature photos, repaired 2026-10-06 (user report: "pictures only show when
   the window is narrowed"). The old calc(50% - 50vw) resolves its 50% against the photo's
   320px GRID AREA, not the centred 1160px container, so above 1000px it produced
   margin-left:-800px at 1920 and the photo sat at x=-396 to -76 - entirely outside the
   window, hidden by body{overflow-x:hidden}. It only reappeared below 1001px, where the
   media query zeroes the margin. The distance from the container's content edge to the
   window edge is now written out: max(0, (100vw - 1160px) / 2) + the 24px container
   padding. A relative offset rather than a margin, so no grid track changes size; 100vw
   includes the scrollbar, leaving ~7px of the photo past the edge, which overflow-x:hidden
   clips without allowing a sideways scroll. Below 1000px the offset is cancelled. */
.feat.bleed-left .media { position: relative; left: calc(-1 * (max(0px, (100vw - 1160px) / 2) + var(--sp-3))); }
.feat.bleed-right .media { position: relative; left: calc(max(0px, (100vw - 1160px) / 2) + var(--sp-3)); }
@media (max-width: 1000px) {
  .feat.bleed-left .media, .feat.bleed-right .media { margin: 0; left: 0; }
}

/* Rating summary band (reviews page) */
.rating-summary { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; gap: 0.6rem 1rem; background: var(--white); border: 1px solid var(--line); border-radius: 18px; padding: 1.4rem 1.8rem; margin: 0 auto var(--sp-4); max-width: 720px; text-align: center; }
.rating-summary .stars { color: var(--bronze); letter-spacing: 0.2em; font-size: 1.3rem; }
.rating-summary b { font-family: var(--font-display); font-size: 1.5rem; color: var(--teal); }
.rating-summary .rb-sub { color: var(--slate); font-size: 0.92rem; width: 100%; }

/* ---- Booking maintenance page ---- */
.cp-maint { padding: clamp(4.5rem, 12vh, 7.5rem) 0 clamp(4.5rem, 10vh, 6rem); }
.cp-maint-card { max-width: 660px; margin: 0 auto; text-align: center; }
.cp-maint-card .cp-eyebrow {
  text-transform: uppercase; letter-spacing: 0.22em; font-size: 0.72rem; font-weight: 700;
  color: var(--bronze-dark); margin-bottom: 1rem;
}
.cp-maint-card h1 { font-size: clamp(1.9rem, 4.2vw, 2.8rem); line-height: 1.15; margin: 0 0 1.1rem; }
.cp-maint-card .lede { font-size: 1.15rem; margin: 0; }
.cp-maint-actions { display: flex; gap: 0.9rem; justify-content: center; flex-wrap: wrap; margin-top: 1.9rem; }
.cp-restore-wrap { margin-top: 2.75rem; }
.cp-hairline { height: 1px; background: var(--line); margin: 0 auto 1.4rem; }
.cp-restore-note { font-size: 0.92rem; max-width: 46ch; margin: 0 auto 1rem; }
.cp-restore-wrap .btn[disabled] { opacity: 0.55; cursor: default; }

/* ---------- Calm motion (2026-08-17): slow, relaxing pacing site-wide.
   Smooth scrolling, slow soft reveals, gentle hover transitions. ---------- */
html { scroll-behavior: smooth; }
html.js .hero-intro { transition-duration: 2.4s; }
.reveal, [data-reveal] { transition-duration: 1.6s; }
.slide-content .inner { transition-duration: 1.1s; }
a, button, .btn, .header-book, .menu-btn, .ba-card, .qa, .compare, .case-card { transition-duration: 0.45s; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }


/* CP 2026-10-06 (user): on small widths (neither side panel in the widget) the
   blurb under "Select Your Date & Service" folds away and the dropdown slides
   up beneath the heading with a small top margin; the Quote/Book bar and the
   frame follow in flow, so fitFrame re-fits the widget taller. The class is
   toggled by the booking page controller: 7s after load, or immediately once
   the dropdown is used - customer view only, fresh on every page load. */
.booking-lede {
  max-height: 10rem;
  overflow: hidden;
  transition: max-height .6s ease, opacity .4s ease, margin-bottom .6s ease;
}
html.cp-intro-collapsed .booking-lede {
  max-height: 0;
  opacity: 0;
  margin-bottom: 0;
}
.booking-select-wrap,
html.cp-tabs-tiny .booking-select-wrap {
  transition: margin-top .6s ease;
}
html.cp-intro-collapsed .booking-select-wrap { margin-top: .55rem; }


/* CP 2026-10-06 (user): admin mode ONLY - hide the booking intro (heading,
   blurb, quick tabs and dropdown) so the Quote/Book bar sits just under the
   header and the frame extends up to fill the space (booknetic fills the
   frame's height). Toggled by the booking controller on the widget's
   carpetpro-admin-mode-enabled message. */
html.cp-admin-intro-hidden .booking-top h1,
html.cp-admin-intro-hidden .booking-lede { display: none !important; }
/* CP 2026-10-06 revision (user): the dropdown stays visible in admin; the
   quick tabs are already hidden at phone width by the tabs-tiny rule. The
   class itself is only applied at phone size or smaller (controller). */
