/* Barlow Semi Condensed 700 — latin subset, self-hosted (no font CDN) */
@font-face{font-family:'Barlow Semi Condensed';font-style:normal;font-weight:700;font-display:swap;
  src:url('fonts/barlow-semi-condensed-700.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}

/* ══════════════════════════════════════════════════════════════
   GrimeBusters Commercial Cleaning · Adam Gurski Creative
   Direction: "Clean room, bright spirit."
   White foundation carries the credibility their audience needs
   (medical / dental / financial, after hours, unsupervised).
   Rainbow is a SIGNATURE DEVICE — heading rules, top border,
   button gradients — never a field behind text.
   Bubbles are CSS-only atmosphere, confined to hero + CTA bands.
   ══════════════════════════════════════════════════════════════ */

:root{
  /* brand — sampled from the client's logo */
  --blue-deep:#10396f;
  --blue:#1e5aa8;
  --blue-br:#2f86d8;
  --green:#63b81f;          /* GRAPHIC ONLY — 2.5:1 on white, never text */
  --green-br:#8ad63f;
  --green-ink:#3f7a12;      /* text-safe green, 5.4:1 on white */

  /* rainbow ramp — the shield edge. Bright set is for GRAPHICS only. */
  --rb-1:#7ac943; --rb-2:#f7d117; --rb-3:#f89a1c; --rb-4:#ef4a6b; --rb-5:#a15cc9; --rb-6:#2f86d8;
  --rainbow:linear-gradient(90deg,var(--rb-1),var(--rb-2),var(--rb-3),var(--rb-4),var(--rb-5),var(--rb-6));

  /* TEXT-SAFE rainbow — every stop measured >=4.5:1 on white, so headings can
     carry the full spectrum and still pass AA. The bright ramp above cannot:
     its yellow is ~1.5:1. Verified 2026-07-31. */
  --rbd-1:#2d7a1a; --rbd-2:#9a6b06; --rbd-3:#b34a00;
  --rbd-4:#c2185b; --rbd-5:#6a2c9c; --rbd-6:#14549e;
  --rainbow-text:linear-gradient(96deg,var(--rbd-1),var(--rbd-2),var(--rbd-3),var(--rbd-4),var(--rbd-5),var(--rbd-6));

  /* saturated band hues — all >=7:1 against white text */
  --bd-1:#10396f; --bd-2:#3b1f6e; --bd-3:#5b2080; --bd-4:#8e1a5e; --bd-5:#0d5a68;
  --bd-p:#7a1f78;           /* extra purple-magenta stop, added 2026-08-05 */

  /* DEEP BANDS — the client named this treatment as their favourite part of the
     page ("the purple at the bottom"). So purple gets the largest share of the
     ramp, and the treatment now runs across How-it-works, the estimate and the
     footer as one continuous mass rather than appearing once.
     Every stop is >=7:1 against white text; that is the whole reason these
     sections can be this saturated and still be readable. */
  --band-a:linear-gradient(134deg,var(--bd-1) 0%,var(--bd-2) 17%,var(--bd-3) 40%,var(--bd-p) 58%,var(--bd-4) 79%,var(--bd-5) 100%);
  --band-b:linear-gradient(206deg,var(--bd-2) 0%,var(--bd-3) 26%,var(--bd-p) 48%,var(--bd-4) 72%,var(--bd-1) 100%);

  /* ink + surface */
  --ink:#1b2430;            /* 14.2:1 on white */
  --ink-2:#5a6675;          /* 5.4:1 on white  */
  --line:#e3eaf2;
  --white:#ffffff;
  --paper:#fdfdfd;          /* matches the logo's baked background */
  --tint:#f2f7fc;

  /* type */
  --display:'Barlow Semi Condensed',"Segoe UI Semibold",system-ui,sans-serif;
  --sans:system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --t-hero:clamp(2.5rem,1.4rem + 4.6vw,4.75rem);
  --t-h2:clamp(1.9rem,1.2rem + 2.6vw,3rem);
  --t-h3:clamp(1.15rem,1.05rem + .4vw,1.35rem);
  --t-body:clamp(1rem,.96rem + .2vw,1.1rem);
  --t-small:.875rem;
  --t-eyebrow:.75rem;

  /* rhythm + motion */
  --sp:clamp(56px,7vw,104px);
  --wrap:1120px;
  --r:14px;
  --ease:cubic-bezier(.16,1,.3,1);
  --dur:.45s;
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;scroll-padding-top:84px;-webkit-text-size-adjust:100%}
body{font-family:var(--sans);font-size:var(--t-body);line-height:1.62;color:var(--ink);
  background:var(--white);-webkit-font-smoothing:antialiased;overflow-x:hidden}
img{max-width:100%;display:block;height:auto}
a{color:var(--blue);text-underline-offset:3px}
h1,h2,h3{font-family:var(--display);font-weight:700;line-height:1.04;letter-spacing:-.01em;text-wrap:balance}
p{text-wrap:pretty}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 clamp(20px,5vw,44px)}

/* the rainbow hairline that runs across the top of the whole page */
body::before{content:"";position:fixed;inset:0 0 auto 0;height:7px;background:var(--rainbow);z-index:100}

.skip{position:absolute;left:-9999px;top:0;background:var(--blue-deep);color:#fff;padding:12px 20px;z-index:200;border-radius:0 0 8px 0}
.skip:focus{left:0}

.eyebrow{font-family:var(--display);font-size:var(--t-eyebrow);letter-spacing:.2em;
  text-transform:uppercase;color:var(--blue);display:block;margin-bottom:.6rem}

/* ── bubbles: decorative, aria-hidden ──
   Built as real soap bubbles — a CLEAR centre with the iridescence confined to
   the rim by a radial mask. That is what lets them be bold and numerous without
   dropping contrast on the text they drift behind. A tinted disc would not. */
.bubbles{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
.bubbles i{position:absolute;bottom:-180px;border-radius:50%;opacity:.9;
  background:radial-gradient(circle at 50% 50%,rgba(255,255,255,.14),rgba(255,255,255,.03) 62%,transparent 74%);
  box-shadow:inset 0 0 20px rgba(255,255,255,.45),0 6px 20px rgba(70,110,190,.10);
  animation:rise var(--bd,26s) linear var(--bdel,0s) infinite}
/* specular highlight, layered ABOVE the film — otherwise the film covers it
   and the bubble reads as a flat coloured ring */
.bubbles i::before{content:"";position:absolute;left:20%;top:16%;width:28%;height:21%;
  border-radius:50%;z-index:2;transform:rotate(-24deg);
  background:radial-gradient(circle,rgba(255,255,255,.95),rgba(255,255,255,0) 72%)}
/* No will-change here on purpose: transform/opacity animations are already
   compositor-promoted, and forcing a layer per bubble costs phone memory. */
/* The iridescent film. The mask keeps the very centre clear (so text behind
   stays readable) but the band is wide — a thin ring reads as a pale outline
   rather than a soap bubble. */
.bubbles i::after{content:"";position:absolute;inset:0;border-radius:50%;opacity:.72;
  background:conic-gradient(from 200deg,#5fc016,#ffd400,#ff9012,#ff3d6b,#b44ae0,#1f7fe0,#12d8bd,#5fc016);
  -webkit-mask:radial-gradient(circle,transparent 44%,rgba(0,0,0,.30) 58%,rgba(0,0,0,.75) 74%,#000 88%,transparent 100%);
          mask:radial-gradient(circle,transparent 44%,rgba(0,0,0,.30) 58%,rgba(0,0,0,.75) 74%,#000 88%,transparent 100%);
  mix-blend-mode:multiply}
/* Travel is a custom property so the mobile hero — which is far taller than one
   viewport once the layout stacks — gets a longer path. With a fixed vh value
   the bubbles never climbed past the lower third of the hero on a phone.
   Delays in the markup are NEGATIVE, which starts every bubble already in
   flight instead of parked below the fold waiting its turn. */
.bubbles i{--travel:-115vh}
@media (max-width:900px){.hero .bubbles i{--travel:-165vh}}
@keyframes rise{
  0%{transform:translateY(0) translateX(0) scale(.78);opacity:0}
  8%{opacity:.95}
  88%{opacity:.8}
  100%{transform:translateY(var(--travel,-115vh)) translateX(var(--bx,20px)) scale(1.12);opacity:0}
}

/* ── header ── */
.hdr{position:sticky;top:0;z-index:50;background:rgba(255,255,255,.94);
  backdrop-filter:saturate(160%) blur(9px);border-bottom:1px solid var(--line)}
.hdr .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:74px;padding-top:8px;padding-bottom:8px}
/* The client's master logo is square once trimmed (533x510 of a 1050x600 canvas
   — 57% was whitespace). At header height a square mark alone is too small to
   read, so the text lockup stays; it just steps aside under 430px. */
.brand{display:flex;align-items:center;gap:11px;text-decoration:none;color:inherit}
.brand img{width:56px;height:auto}
.brand b{font-family:var(--display);font-size:1.18rem;line-height:1.02;display:block;color:var(--blue-deep);white-space:nowrap}
.brand > span > span{display:block;font-size:.68rem;letter-spacing:.15em;text-transform:uppercase;color:var(--ink-2);font-weight:600;white-space:nowrap}

/* ── buttons ── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-family:var(--display);font-size:1.02rem;letter-spacing:.02em;text-decoration:none;white-space:nowrap;
  padding:14px 30px;border:0;border-radius:999px;cursor:pointer;
  transition:transform var(--dur) var(--ease),box-shadow var(--dur) var(--ease),filter .25s}
/* Buttons carry the band hues rather than the old blue->green, so the primary
   action matches the deep purple treatment the client liked. Every stop is a
   >=7:1 band hue, so white label text is safe across the whole sweep. */
.btn-main{color:#fff;background:linear-gradient(102deg,var(--bd-1),var(--bd-3) 52%,var(--bd-4));
  box-shadow:0 10px 26px rgba(91,32,128,.40)}
.btn-main:hover{transform:translateY(-2px);box-shadow:0 16px 36px rgba(91,32,128,.50)}
.btn-ghost{color:var(--blue-deep);background:transparent;box-shadow:inset 0 0 0 2px var(--blue)}
.btn-ghost:hover{background:var(--tint);transform:translateY(-2px)}
.btn:active{transform:translateY(0)}
:where(a,button,input,select,textarea):focus-visible{outline:3px solid var(--blue-br);outline-offset:3px;border-radius:6px}

/* ── hero ── */
/* Brand-colour washes, intensified 2026-08-05 at the client's request ("more
   vibrant"). Every stop here is a LIGHT hue laid over near-white, so raising
   alpha adds chroma without dropping luminance much — that is what keeps body
   copy AA. The saturated dark hues stay confined to .est and .spotlight, where
   the text is white. Text sitting over these washes is darkened to #414d5c
   (7.2:1 on white) rather than left at --ink-2. Contrast re-measured after. */
/* The hero is a DEEP BAND as of 2026-08-05 (round 3). The client's favourite
   part of the page was the purple, and it previously sat below the fold — she
   had to scroll to reach the thing she'd asked for. Sections now alternate
   deep / light / deep / light from the very top.
   The overlay washes are all DARK hues, so they can only push the surface
   darker than the band stops; white text keeps its headroom either way. */
.hero{position:relative;overflow:hidden;isolation:isolate;color:#fff;
  padding:clamp(48px,7vw,86px) 0 clamp(56px,8vw,96px);
  background:
    radial-gradient(760px 540px at 86% 10%,rgba(122,31,120,.55),transparent 62%),
    radial-gradient(700px 500px at 6% 86%,rgba(13,90,104,.42),transparent 62%),
    radial-gradient(640px 460px at 30% 8%,rgba(16,57,111,.45),transparent 60%),
    var(--band-a)}
.hero .wrap{position:relative;z-index:2;display:grid;grid-template-columns:1.15fr .85fr;
  gap:clamp(28px,5vw,64px);align-items:center}
.hero .eyebrow{color:#9fe0ff}
.hero h1{font-size:var(--t-hero);color:#fff;margin-bottom:1rem}
/* The second line uses the BRIGHT ramp, deliberately skipping its blue stop —
   #2f86d8 against a navy band is far too close in luminance to read. Green,
   yellow, orange and pink all clear 3:1 (large text) on every band stop. */
.hero h1 em{font-style:normal;display:block;
  background:linear-gradient(96deg,var(--rb-1),var(--rb-2) 38%,var(--rb-3) 64%,#ff9ec4);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.hero .lede{font-size:clamp(1.06rem,1rem + .42vw,1.3rem);color:#e4edfb;max-width:54ch;margin-bottom:1.6rem}
.hero-cta{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:1.4rem}
.hero-note{font-size:var(--t-small);color:#cbdaef}
/* The primary CTA cannot use the band hues here — it would be the same palette
   as the surface behind it and disappear. Solid white with deep purple text is
   ~10.7:1 and makes the estimate button the loudest thing on the screen. */
.hero .btn-main{background:#fff;color:var(--bd-3);box-shadow:0 12px 30px rgba(0,0,0,.32)}
.hero .btn-main:hover{background:#fff;color:var(--bd-2);box-shadow:0 18px 42px rgba(0,0,0,.40)}
.hero .btn-ghost{color:#fff;background:transparent;box-shadow:inset 0 0 0 2px rgba(255,255,255,.62)}
.hero .btn-ghost:hover{background:rgba(255,255,255,.15)}
/* The client's master logo is a landscape PNG on PURE white, so the card is
   pure white too and the seam disappears entirely. (The earlier Facebook-scraped
   JPG sat on #fdfdfd and needed the card colour matched to it.) */
.hero-art{justify-self:center;position:relative;background:var(--white);
  border:0;border-radius:24px;padding:clamp(16px,2.2vw,30px);
  box-shadow:0 26px 64px rgba(16,57,111,.18)}
/* Rainbow halo behind the logo card. Blurred and sitting behind an opaque white
   surface, so it is pure atmosphere — no text ever sits on it. */
.hero-art::after{content:"";position:absolute;inset:-9px;border-radius:32px;z-index:-1;
  background:var(--rainbow);filter:blur(13px);opacity:.75}
.hero-art img{width:min(320px,64vw);position:relative;z-index:1}

/* ── section furniture ── */
.sec{padding:var(--sp) 0;position:relative}
.sec-head{max-width:62ch;margin-bottom:clamp(28px,4vw,48px)}
/* Headings carry the full spectrum via the TEXT-SAFE ramp. A fallback colour is
   declared first so browsers without background-clip still get readable navy. */
.sec-head h2{font-size:var(--t-h2);color:var(--blue-deep);margin-bottom:.7rem}
@supports (-webkit-background-clip:text) or (background-clip:text){
  .sec-head h2{background:var(--rainbow-text);-webkit-background-clip:text;
    background-clip:text;color:transparent}
}
.sec-head h2::after{content:"";display:block;width:110px;height:6px;border-radius:99px;
  background:var(--rainbow);margin-top:.85rem}
.sec-head p{color:var(--ink-2)}

/* Services band: a soft full-spectrum wash rather than a flat blue tint.
   Alphas stay low so the white cards keep their contrast. */
/* Services is the second deep band in the alternation. Its own angle and stop
   order so it doesn't read as a repeat of the hero or How-it-works. The white
   service cards sitting on it are what make this section work. */
.alt{position:relative;color:#fff;
  background:linear-gradient(158deg,var(--bd-3) 0%,var(--bd-p) 26%,var(--bd-4) 52%,var(--bd-2) 78%,var(--bd-1) 100%)}
/* Two more washed sections. Why and Before-&-After were previously bare white,
   which made them the flattest part of the page. Each wash is positioned
   differently so the three light sections don't read as one repeated texture. */
.tint-a{background:
  radial-gradient(660px 460px at 92% 4%,rgba(161,92,201,.34),transparent 62%),
  radial-gradient(600px 420px at 8% 34%,rgba(47,134,216,.26),transparent 62%),
  radial-gradient(580px 400px at 50% 104%,rgba(239,74,107,.28),transparent 62%),
  radial-gradient(520px 380px at 74% 70%,rgba(122,201,67,.26),transparent 62%),
  var(--white)}
.tint-b{background:
  radial-gradient(640px 440px at 4% 8%,rgba(247,209,23,.32),transparent 62%),
  radial-gradient(620px 430px at 96% 22%,rgba(161,92,201,.32),transparent 62%),
  radial-gradient(600px 420px at 30% 98%,rgba(47,134,216,.26),transparent 62%),
  radial-gradient(560px 400px at 80% 92%,rgba(239,74,107,.26),transparent 62%),
  var(--white)}

/* Intro copy on the LIGHT washed sections is darkened — --ink-2 is only 5.4:1
   on pure white and has no headroom left once a wash lands behind it. */
.tint-a .sec-head p,.tint-b .sec-head p{color:#414d5c}

/* ── DEEP BAND ──
   Shared treatment for the saturated sections. Headings go SOLID WHITE here
   rather than keeping the rainbow background-clip: the text-safe ramp was
   tuned for >=4.5:1 on WHITE, and those same dark stops disappear against a
   dark band. The rainbow stays as the underline rule, where it is purely
   decorative and contrast does not apply. */
.band{position:relative;overflow:hidden;isolation:isolate;color:#fff;background:var(--band-b)}
.band::before,.alt::before{content:"";position:absolute;inset:0 0 auto 0;height:6px;background:var(--rainbow);z-index:3}
.band .wrap,.alt .wrap{position:relative;z-index:2}
/* .est included: its eyebrow used to carry an inline colour, which was removed
   last round — without this it falls back to --blue (#1e5aa8) and fails on the
   dark band. */
.band .eyebrow,.alt .eyebrow,.est .eyebrow{color:#9fe0ff}
.band .sec-head h2,.alt .sec-head h2{background:none;-webkit-background-clip:border-box;background-clip:border-box;
  color:#fff;-webkit-text-fill-color:#fff}
.band .sec-head p,.alt .sec-head p{color:#d9e4f5}
.band .step h3{color:#fff}
.band .step p{color:#d9e4f5}
/* On dark, the BRIGHT ramp is the readable one — the numerals are decorative
   scale, and the bright stops glow here where the darkened ramp would sink. */
.band .step::before{background:var(--rainbow);-webkit-background-clip:text;background-clip:text;
  color:transparent;opacity:1}

/* ── trust / why ── */
/* Both card grids hold exactly 4 items, so column counts are pinned rather than
   auto-fit — auto-fit lands on 3 at the 1120px wrap and orphans the 4th.
   .why cards carry 2-3 sentence paragraphs: 4-up gives ~22 characters per line,
   which is unreadable, so they stay 2x2. .svc cards carry short list items and
   take 4-up comfortably. */
.why{display:grid;grid-template-columns:1fr;gap:clamp(16px,2.4vw,26px)}
@media (min-width:620px){
  .why{grid-template-columns:repeat(2,1fr)}
  /* Five cards into a two-column grid orphans the last one. Spanning it full
     width instead turns the leftover into a deliberate capstone — the family
     story closes the section rather than dangling beside empty space. */
  .why .is-capstone{grid-column:1/-1;background:var(--tint)}
}
.card{background:var(--white);border:1px solid var(--line);border-radius:var(--r);padding:clamp(22px,2.6vw,30px);
  position:relative;overflow:hidden;transition:transform var(--dur) var(--ease),box-shadow var(--dur) var(--ease),border-color var(--dur)}
.card::before{content:"";position:absolute;inset:0 0 auto 0;height:4px;background:var(--rainbow);
  transform:scaleX(0);transform-origin:left;transition:transform var(--dur) var(--ease)}
.card:hover{transform:translateY(-4px);box-shadow:0 18px 40px rgba(16,57,111,.10);border-color:transparent}
.card:hover::before{transform:scaleX(1)}
.card h3{font-size:var(--t-h3);color:var(--blue-deep);margin-bottom:.5rem}
.card p{font-size:.98rem;color:var(--ink-2)}
.ico{width:44px;height:44px;border-radius:12px;display:grid;place-items:center;margin-bottom:1rem;
  background:linear-gradient(135deg,var(--blue),var(--blue-br));color:#fff}
.ico svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.card:nth-child(2) .ico{background:linear-gradient(135deg,var(--green-ink),var(--green))}
.card:nth-child(3) .ico{background:linear-gradient(135deg,var(--rb-4),var(--rb-5))}
.card:nth-child(4) .ico{background:linear-gradient(135deg,var(--rb-3),var(--rb-2))}
/* The capstone keeps the full rainbow bar it inherits from .card::before, so its
   icon uses the deep band hues rather than competing with it. */
.card:nth-child(5) .ico{background:linear-gradient(135deg,var(--bd-1),var(--bd-3))}

/* ── services ── */
.svc{display:grid;grid-template-columns:1fr;gap:clamp(16px,2.4vw,26px)}
@media (min-width:620px){.svc{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1040px){.svc{grid-template-columns:repeat(4,1fr)}}
.svc-col{background:var(--white);border:1px solid var(--line);border-radius:var(--r);padding:clamp(22px,2.6vw,30px)}
.svc-col h3{font-size:var(--t-h3);color:var(--blue-deep);margin-bottom:.9rem;padding-bottom:.7rem;border-bottom:2px solid var(--line)}
.svc-col ul{list-style:none;display:grid;gap:.55rem}
.svc-col li{position:relative;padding-left:1.6rem;font-size:.97rem;color:var(--ink-2)}
.svc-col li::before{content:"";position:absolute;left:0;top:.52em;width:9px;height:9px;border-radius:50%;
  background:linear-gradient(135deg,var(--green-br),var(--green))}
.svc-note{margin-top:clamp(22px,3vw,34px);padding:18px 22px;border-left:5px solid transparent;
  border-image:var(--rainbow) 1;background:var(--tint);border-radius:0 var(--r) var(--r) 0;color:var(--ink-2);font-size:.97rem}
.svc-note strong{color:var(--blue-deep)}

/* ── food-service spotlight ──
   The client asked for a restaurant/bar/coffee-shop angle AND for more of the
   saturated colour they liked in the estimate band. This block does both: it
   reuses the same >=7:1 deep-hue gradient, so the section gains a second strong
   colour moment without adding a sixth page section or putting body copy on a
   light wash. */
/* INVERTED 2026-08-05: Services became a deep band, and a dark spotlight on a
   dark section would have disappeared. As a white card it now pops off the
   purple instead — the section behind it already supplies the saturation. */
.spotlight{margin-top:clamp(26px,3.4vw,40px);position:relative;overflow:hidden;isolation:isolate;
  border-radius:var(--r);color:var(--ink);background:var(--white);
  box-shadow:0 24px 54px rgba(0,0,0,.30)}
.spotlight::before{content:"";position:absolute;inset:0 0 auto 0;height:6px;background:var(--rainbow);z-index:2}
.spotlight-body{padding:clamp(26px,3.6vw,46px);max-width:76ch}
.spotlight .eyebrow{color:var(--blue)}
.spotlight h3{font-family:var(--display);font-weight:700;line-height:1.08;letter-spacing:-.01em;
  font-size:clamp(1.42rem,1.1rem + 1.3vw,2.05rem);color:var(--blue-deep);margin-bottom:.75rem}
.spotlight p{color:var(--ink-2);font-size:.99rem}
.spotlight p + p{margin-top:.85rem}
/* Type selector included deliberately: `.spotlight p` is (0,1,1) and would
   otherwise out-specify a bare `.spotlight-kicker` (0,1,0), silently leaving
   the kicker the same colour as the body copy. */
.spotlight p.spotlight-kicker{color:var(--blue-deep);font-weight:600}

/* ── before & after ── */
.ba{display:grid;gap:clamp(26px,3.4vw,44px)}
.ba-pair{background:var(--white);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;box-shadow:0 14px 36px rgba(16,57,111,.07)}
.ba-imgs{display:grid;grid-template-columns:1fr 1fr;gap:3px;background:var(--line)}
.ba-shot{position:relative;margin:0;background:var(--tint)}
.ba-shot img{width:100%;height:100%;object-fit:cover;display:block;aspect-ratio:5/3}
/* Label pills sit ON the image, so they carry their own solid background rather
   than relying on whatever pixels happen to be underneath. */
.ba-shot figcaption{position:absolute;top:12px;left:12px;font-family:var(--display);
  font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;color:#fff;
  padding:6px 13px;border-radius:99px;backdrop-filter:blur(3px)}
.ba-shot.is-before figcaption{background:rgba(140,26,60,.92)}
.ba-shot.is-after  figcaption{background:rgba(45,109,26,.94)}
.ba-cap{padding:16px clamp(18px,2.2vw,26px);display:flex;flex-wrap:wrap;gap:6px 14px;
  align-items:baseline;border-top:4px solid transparent;border-image:var(--rainbow) 1}
.ba-cap b{font-family:var(--display);font-size:1.08rem;color:var(--blue-deep)}
.ba-cap span{font-size:.94rem;color:var(--ink-2)}
@media (max-width:620px){
  .ba-imgs{grid-template-columns:1fr}
  .ba-shot figcaption{font-size:.72rem;padding:5px 11px}
}

/* ── testimonials ── */
.quotes{display:grid;gap:clamp(18px,2.4vw,26px);margin-top:clamp(30px,4vw,52px);align-items:start}
@media (min-width:820px){.quotes{grid-template-columns:1.25fr .75fr}}
.quote{background:var(--white);
  border:1px solid var(--line);border-radius:var(--r);padding:clamp(26px,3.4vw,42px);
  position:relative;overflow:hidden;box-shadow:0 14px 36px rgba(16,57,111,.07)}
.quote::before{content:"";position:absolute;inset:0 0 auto 0;height:5px;background:var(--rainbow)}
.quote blockquote{font-size:clamp(1.06rem,1rem + .4vw,1.28rem);line-height:1.62;color:var(--ink);margin-bottom:1.2rem}
.quote.sm blockquote{font-size:clamp(1rem,.96rem + .28vw,1.12rem)}
.quote figcaption{font-family:var(--display);font-size:1rem;color:var(--blue-deep)}
.quote figcaption span{display:block;font-family:var(--sans);font-size:.88rem;
  font-weight:400;color:var(--ink-2);margin-top:.2rem}

/* ── how it works ── */
.steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:clamp(18px,2.6vw,30px);counter-reset:s}
.step{position:relative;padding-top:14px}
.step::before{counter-increment:s;content:counter(s);font-family:var(--display);font-size:2.6rem;line-height:1;
  color:var(--blue);opacity:.26;display:block;margin-bottom:.4rem}
.step h3{font-size:var(--t-h3);color:var(--blue-deep);margin-bottom:.45rem}
.step p{font-size:.97rem;color:var(--ink-2)}

/* ── estimate form ── */
/* Full-spectrum band. Every stop is a saturated hue measured >=7:1 against
   white text, so the section can be genuinely rainbow and still be readable —
   the bright ramp would have made this unusable. */
.est{position:relative;color:#fff;overflow:hidden;isolation:isolate;background:var(--band-a)}
.est::before{content:"";position:absolute;inset:0 0 auto 0;height:6px;background:var(--rainbow);z-index:3}
.est .wrap{position:relative;z-index:2}
/* Over navy the white core reads as a solid grey sphere, so on the dark band
   the fill is dropped almost entirely and the iridescent rim does the work. */
/* Against a saturated dark band a strong iridescent film composites into muddy
   dark spheres. Real bubbles over dark read as LIGHT — bright rim, faint colour.
   So here the white rim does the work and the film drops right back. */
.est .bubbles i,.band .bubbles i,.hero .bubbles i{opacity:.92;
  box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.72),inset -12px -14px 30px rgba(255,255,255,.30),0 0 26px rgba(255,255,255,.16);
  background:radial-gradient(circle at 32% 28%,rgba(255,255,255,.95) 0 7%,rgba(255,255,255,.34) 26%,rgba(255,255,255,.10) 52%,transparent 70%)}
.est .bubbles i::after,.band .bubbles i::after,.hero .bubbles i::after{opacity:.75;mix-blend-mode:screen}
.est .sec-head h2{color:#fff}
.est .sec-head p{color:#cfe0f4}
.est-grid{display:grid;grid-template-columns:.85fr 1.15fr;gap:clamp(28px,4vw,56px);align-items:start}
.est-side p{color:#cfe0f4;margin-bottom:1.1rem}
.est-side .direct{display:grid;gap:.7rem;margin-top:1.4rem}
/* The email address is a single unbreakable token wider than a 320px column,
   so it must be allowed to break or it pushes the card out of the viewport. */
.est-side .direct a{display:flex;align-items:center;gap:10px;color:#fff;text-decoration:none;font-weight:600;
  padding:13px 18px;border-radius:12px;background:rgba(255,255,255,.09);min-width:0;overflow-wrap:anywhere;
  border:1px solid rgba(255,255,255,.18);transition:background var(--dur),transform var(--dur) var(--ease)}
@media (max-width:360px){.est-side .direct a{font-size:.9rem;padding:12px 14px}}
.est-side .direct a:hover{background:rgba(255,255,255,.17);transform:translateX(3px)}
.est-side .direct svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;flex:0 0 auto}

/* The client's own business card, shown as a physical card — tilted, white
   border, dropped shadow. It is their existing brand artwork, which is why the
   rainbow direction on this page is theirs rather than imposed. */
.card-shot{margin-top:1.7rem;border-radius:14px;overflow:hidden;transform:rotate(-1.8deg);
  border:4px solid rgba(255,255,255,.7);box-shadow:0 24px 54px rgba(0,0,0,.34);
  transition:transform var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}
.card-shot:hover{transform:rotate(0) translateY(-4px);box-shadow:0 30px 64px rgba(0,0,0,.4)}
.card-shot img{width:100%;display:block}
.card-cap{font-size:var(--t-small);color:#dfe8f8;margin-top:.75rem;text-align:center}

form{background:var(--white);border-radius:var(--r);padding:clamp(22px,3vw,34px);color:var(--ink)}
.fgrid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.f{display:flex;flex-direction:column;gap:6px}
.f.full{grid-column:1/-1}
.f label{font-size:var(--t-small);font-weight:600;color:var(--ink)}
.f input,.f select,.f textarea{font-family:inherit;font-size:1rem;padding:12px 14px;
  border:1.5px solid var(--line);border-radius:10px;background:var(--white);color:var(--ink);width:100%}
.f textarea{resize:vertical;min-height:96px}
.f input:focus,.f select:focus,.f textarea:focus{border-color:var(--blue-br);outline:none;box-shadow:0 0 0 3px rgba(47,134,216,.22)}
.req{color:var(--rb-4)}
form .btn{width:100%;margin-top:6px}
.hp{position:absolute;left:-9999px}
.fineprint{font-size:.8rem;color:var(--ink-2);margin-top:12px;text-align:center}

/* ── footer ── */
/* The footer CONTINUES the estimate band rather than reverting to paper, so the
   whole bottom of the page reads as one deep purple mass — the part the client
   named as their favourite. */
.ftr{padding:clamp(38px,5vw,58px) 0 26px;color:#fff;background:var(--band-a)}
.ftr-grid{display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:clamp(22px,3vw,40px);margin-bottom:28px}
/* h3 not h4: the document went h2 -> h4 here, which is a heading-level skip for
   screen-reader navigation. Visual size is unchanged. */
.ftr h3{font-family:var(--display);font-size:1rem;letter-spacing:.06em;text-transform:uppercase;color:#fff;margin-bottom:.8rem}
.ftr p,.ftr li{font-size:.93rem;color:#dbe6f7}
.ftr ul{list-style:none;display:grid;gap:.42rem}
.ftr a{color:#dbe6f7;text-decoration:none}
.ftr a:hover{color:#fff;text-decoration:underline}
/* The logo file has a light background baked in (no alpha), so on a dark band it
   would read as a stray white rectangle. A real white card makes it deliberate. */
.ftr-brand img{width:104px;margin-bottom:.9rem;background:#fff;border-radius:12px;
  padding:8px 10px;box-shadow:0 12px 28px rgba(0,0,0,.26)}
.ftr-btm{border-top:1px solid rgba(255,255,255,.20);padding-top:20px;display:flex;flex-wrap:wrap;gap:10px;
  justify-content:space-between;font-size:.82rem;color:#c9d8ee}
.ftr-btm a{color:#c9d8ee}
.ftr-btm a:hover{color:#fff}

/* ── reveal on scroll ── */
.rv{opacity:0;transform:translateY(18px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.rv.in{opacity:1;transform:none}

/* ══ colour accents ══
   Each card/column/step carries its own hue drawn from the logo's rainbow
   shield, so colour is present at rest rather than only on hover. Colour is
   always decorative here — never the sole carrier of meaning. */
.card::before{transform:scaleX(1);height:6px}
.card:hover::before{height:9px}
.card:nth-child(1)::before{background:linear-gradient(90deg,var(--blue),var(--blue-br))}
.card:nth-child(2)::before{background:linear-gradient(90deg,var(--green-ink),var(--green-br))}
.card:nth-child(3)::before{background:linear-gradient(90deg,var(--rb-4),var(--rb-5))}
.card:nth-child(4)::before{background:linear-gradient(90deg,var(--rb-3),var(--rb-2))}

.svc-col{border-top:5px solid transparent}
.svc-col:nth-child(1){border-top-color:var(--green)}
.svc-col:nth-child(2){border-top-color:var(--blue-br)}
.svc-col:nth-child(3){border-top-color:var(--rb-5)}
.svc-col:nth-child(4){border-top-color:var(--rb-3)}
.svc-col:nth-child(1) li::before{background:linear-gradient(135deg,var(--green-br),var(--green))}
.svc-col:nth-child(2) li::before{background:linear-gradient(135deg,var(--blue-br),var(--blue))}
.svc-col:nth-child(3) li::before{background:linear-gradient(135deg,var(--rb-5),#7d4bb0)}
.svc-col:nth-child(4) li::before{background:linear-gradient(135deg,var(--rb-2),var(--rb-3))}

/* Step numerals get the full rainbow so the process reads as one sequence. */
.step::before{background:var(--rainbow);-webkit-background-clip:text;background-clip:text;
  color:transparent;opacity:1;font-size:3.1rem}

.ftr{border-top:0;position:relative}
.ftr::before{content:"";position:absolute;inset:0 0 auto 0;height:5px;background:var(--rainbow)}

/* ── responsive ── */
@media (max-width:900px){
  .hero .wrap{grid-template-columns:1fr;text-align:center}
  .hero .lede{margin-inline:auto}
  .hero-cta{justify-content:center}
  .hero-art{order:-1}
  .hero-art img{width:min(230px,58vw)}
  .est-grid{grid-template-columns:1fr}
  .ftr-grid{grid-template-columns:1fr 1fr}
}
@media (max-width:560px){
  /* Thin the bubble field on phones — still lively, but 9 animated layers
     instead of 14 keeps scrolling smooth on mid-range hardware. */
  .hero .bubbles i:nth-child(n+10){display:none}
  .hdr .wrap{min-height:64px}
  .hdr .btn{padding:11px 18px;font-size:.92rem;width:auto}
  .fgrid{grid-template-columns:1fr}
  .ftr-grid{grid-template-columns:1fr}
  .btn{width:100%}
  .hero-cta .btn{width:100%}
}

/* Under ~430px there isn't room for mark + wordmark + CTA without collision.
   The mark carries the name, so the text lockup steps aside and it grows. */
@media (max-width:430px){
  .brand > span{display:none}
  .brand img{width:62px}
}

/* ── motion + contrast preferences ── */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  .bubbles{display:none}
  .rv{opacity:1;transform:none}
}
@media (prefers-contrast:more){
  :root{--ink-2:#3d4854;--line:#9fb2c6}
  .bubbles{display:none}
}
@media print{
  .bubbles,.hdr .btn,form{display:none}
  body{background:#fff}
  /* Every saturated surface flattens to white for print — otherwise the deep
     bands burn a page of toner and the light text vanishes. */
  .est,.band,.ftr,.spotlight,.hero,.alt{background:#fff!important;color:#000!important}
  .est *,.band *,.ftr *,.spotlight *,.hero *,.alt *{color:#000!important;-webkit-text-fill-color:#000!important}
  .tint-a,.tint-b{background:#fff!important}
  .hero-art::after{display:none}
}

