/* ============================================================
   East Cleaning LLC — "WHOLE PROPERTY"
   Registry-distinct: Outfit geometric display + Karla body.
   Palette is HIS OWN LOGO: steel blue #3a83a4 + sky blue #6bb5f6 + white.
   Square-ish 12px radius, diagonal section wedges, tick checklists.
   Signature components: the one-vendor comparison table, the
   service system orbit, spec rows, sticky trust bar.
   ============================================================ */
:root{
  --font-head:'Outfit',-apple-system,sans-serif;
  --font-body:'Karla',-apple-system,sans-serif;
  --cap-font:var(--font-body);
  --h1-min:38px;--h1-vw:5.2vw;--h1-max:70px;--h1-lh:1.06;--h1-ls:-1px;--h1-w:600;
  --h2-min:29px;--h2-vw:3.5vw;--h2-max:48px;--h2-lh:1.12;--h2-ls:-.6px;--h2-w:600;--h3-w:600;
  --maxw:1160px;--section-y:clamp(62px,8vw,112px);

  /* Palette sampled directly from his real logo:
     steel blue #3a83a4, sky blue #6bb5f6, white. The CTA blue is his steel blue
     deepened to #2e7a9c so white button text clears AA contrast. */
  --ink:#16323f;--body:#3a4f5c;--mut:#69838f;
  --bg:#f4f8fa;--bg-soft:#e7f0f5;--line:#cfe0e9;
  --brand:#3a83a4;--accent:#2e7a9c;--accent-2:#6bb5f6;
  --deep:#123243;--jade:#2e7a9c;--amber:#6bb5f6;

  --nav-fg:#ffffff;--nav-fg-scrolled:var(--ink);--nav-bg-scrolled:rgba(244,248,250,.97);
  --menu-bg:var(--deep);--menu-fg:#eaf3f8;
  --foot-bg:var(--deep);--foot-fg:#8fa9b8;--foot-rule:var(--jade);
  --foot-cols:1.7fr .9fr 1fr 1fr 1.2fr;
  --head-overlay-a:rgba(18,50,67,.7);--head-overlay-b:rgba(18,50,67,.92);
  --check-glyph:"✓";
  --hero-vh:86vh;--hero-cap:880px;

  --hero-scrim:linear-gradient(180deg,rgba(18,50,67,.84) 0%,rgba(18,50,67,.62) 45%,rgba(18,50,67,.92) 100%);
  --img-grade:saturate(1.02) contrast(1.03);
  --shadow:0 22px 50px rgba(18,50,67,.18);--shadow-sm:0 8px 24px rgba(18,50,67,.1);
  --radius:12px;--btn-radius:8px;
  --nav-h:82px;--nav-h-scrolled:62px;--ul-h:3px;
  --reveal-ease:cubic-bezier(.2,.9,.3,1);
}
h1,h2,h3{font-family:var(--font-head);letter-spacing:-.5px}
h1 em,h2 em{font-style:normal;color:var(--jade)}
body{background:var(--bg);color:var(--body)}
.btn{font-family:var(--font-head);font-weight:600;font-size:16px;letter-spacing:.2px;padding:15px 30px;border-radius:var(--btn-radius)}
.btn-primary{background:var(--jade);color:#fff;box-shadow:0 10px 24px rgba(46,122,156,.34)}
.btn-primary:hover{background:#26657f;transform:translateY(-2px)}
.btn-line{border:2px solid rgba(255,255,255,.7);color:#fff}
.section .btn-line{border-color:var(--jade);color:var(--ink)}
.eyebrow{font-weight:700;letter-spacing:3px;font-size:12px;color:var(--jade);text-transform:uppercase}

/* logo / wordmark */
.logo{display:flex;align-items:center;gap:11px}
.logo .mark{height:44px;width:auto}
.wordmark{display:flex;flex-direction:column;line-height:1}
.wm-name{font-family:var(--font-head);font-weight:600;font-size:21px;color:#fff;letter-spacing:-.3px}
.wm-sub{font-size:10px;font-weight:700;letter-spacing:2.6px;text-transform:uppercase;color:var(--jade);margin-top:4px}
.nav.scrolled .wm-name{color:var(--ink)}
.nav .cta{font-family:var(--font-head);font-weight:600;background:var(--jade);color:#fff}
.nav .links a{font-weight:600;font-size:15px}
@media(max-width:1240px){.wm-sub{display:none}.wm-name{font-size:19px}}

/* hero */
.hero{background:var(--deep)}
.hero .scrim{background:var(--hero-scrim)}
.hero .wrap{padding-bottom:clamp(56px,7vw,96px)}
.hero h1{color:#fff}
/* on the dark hero/page-head the deep CTA blue goes muddy over a photo;
   use the logo's bright sky blue so the emphasised words actually carry */
.hero h1 em,.page-head h1 em{color:var(--amber)}
.hero .lead{color:#d7e2e6;max-width:56ch;margin:18px 0 30px;font-size:clamp(16px,1.9vw,19px)}
.heroline{display:inline-flex;align-items:center;gap:12px;font-family:var(--font-head);font-weight:600;font-size:16px;color:var(--amber)}
.heroline::before{content:"";width:40px;height:3px;background:var(--amber)}

/* trust bar */
.trustbar{background:var(--deep);border-top:1px solid rgba(255,255,255,.1);padding:18px 0}
.trustbar .wrap{display:flex;flex-wrap:wrap;gap:14px 34px;justify-content:center;align-items:center}
.trustbar span{display:inline-flex;align-items:center;gap:9px;color:#cfdbe2;font-weight:600;font-size:14.5px}
.trustbar span::before{content:"✓";color:var(--jade);font-weight:800}

/* SIGNATURE 1 — diagonal wedge divider */
.wedge{display:block;width:100%;height:56px}
.wedge polygon{fill:currentColor}

/* SIGNATURE 2 — the one-vendor comparison (the whole strategy in one visual) */
.vsbox{background:#fff;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-sm)}
.vsbox table{width:100%;border-collapse:collapse}
.vsbox th{background:var(--deep);color:#fff;font-family:var(--font-head);font-weight:600;font-size:15.5px;padding:16px 18px;text-align:left}
.vsbox th:last-child{background:var(--jade)}
.vsbox td{padding:15px 18px;border-bottom:1px solid var(--line);font-size:15px;vertical-align:top}
.vsbox tr:last-child td{border-bottom:0}
.vsbox td:first-child{font-weight:700;color:var(--ink)}
.vsbox td.them{color:var(--mut)}
.vsbox td.us{color:var(--ink);font-weight:600;background:rgba(46,122,156,.07)}
.vsbox td.us::before{content:"✓ ";color:var(--jade);font-weight:800}
@media(max-width:720px){.vsbox th,.vsbox td{padding:12px 12px;font-size:14px}}

/* SIGNATURE 3 — service system cards with numbered spec rows */
.syscards{display:grid;grid-template-columns:repeat(auto-fit,minmax(270px,1fr));gap:clamp(16px,2.4vw,26px)}

/* home layout: Commercial (the lead service) featured tall, the other four in a 2x2.
   Five equal cards in a 3-col grid left a hole in the second row; this fills the
   canvas completely AND encodes the strategy: commercial first, everything else attached. */
.svcsplit{display:grid;grid-template-columns:1fr 1.55fr;gap:clamp(16px,2.4vw,26px);align-items:stretch}
.svcminor{display:grid;grid-template-columns:1fr 1fr;gap:clamp(16px,2.4vw,26px)}
@media(max-width:1020px){
  .svcsplit{grid-template-columns:1fr}
  .sys--feature img{min-height:230px;max-height:300px}
}
@media(max-width:560px){
  .svcminor{grid-template-columns:1fr}
  .svcminor .sys img{height:170px}
}
.sys{background:#fff;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;display:flex;flex-direction:column;transition:transform .35s var(--reveal-ease),box-shadow .35s}
.sys:hover{transform:translateY(-6px);box-shadow:var(--shadow)}
.sys img{width:100%;height:200px;object-fit:cover;filter:var(--img-grade)}
.sys .sc{padding:22px 22px 24px;display:flex;flex-direction:column;flex:1}
.sys .tag{font-size:11px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:var(--jade);margin-bottom:8px}
.sys h3{font-size:22px;color:var(--ink);margin-bottom:8px}
.sys p{font-size:14.8px;flex:1}
.sys .go{margin-top:14px;font-family:var(--font-head);font-weight:600;color:var(--jade)}

/* spec rows (service pages) */
.spec{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,4vw,60px);align-items:center;margin-bottom:clamp(40px,5.5vw,72px)}
.spec:nth-child(even){direction:rtl}
.spec>*{direction:ltr}
.spec figure{margin:0;border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-sm)}
.spec figure img{width:100%;height:360px;object-fit:cover;display:block;filter:var(--img-grade)}
.spec h3{font-size:clamp(23px,2.5vw,30px);color:var(--ink);margin-bottom:10px}
.spec .num{font-family:var(--font-head);font-weight:600;font-size:12.5px;letter-spacing:2.4px;text-transform:uppercase;color:var(--amber);display:block;margin-bottom:7px}
@media(max-width:860px){.spec{grid-template-columns:1fr}.spec:nth-child(even){direction:ltr}.spec figure img{height:280px}}

/* dark band */
.darkband{background:var(--deep);color:#d9e3e8;position:relative}
.darkband h2,.darkband h3{color:#fff}
.darkband .eyebrow{color:var(--amber)}
.darkband p{color:#bccbd4}

/* stats */
.statrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:24px;text-align:center;background:transparent;border-block:0}
.statrow .st b{font-family:var(--font-head);font-weight:600;font-size:clamp(38px,5vw,58px);color:var(--amber);display:block;line-height:1}
.statrow .st span{font-size:12px;font-weight:700;letter-spacing:2.2px;text-transform:uppercase;color:#8ea0ac}

/* process steps */
.steps3{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:clamp(16px,2.4vw,28px)}
.pstep{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:28px 24px;position:relative}
.pstep .pn{width:42px;height:42px;border-radius:10px;background:var(--jade);color:#fff;font-family:var(--font-head);font-weight:600;font-size:19px;display:flex;align-items:center;justify-content:center;margin-bottom:15px}
.pstep h3{font-size:20px;color:var(--ink);margin-bottom:7px}
.pstep p{font-size:14.8px}

/* checklist */
.ticks{list-style:none;padding:0;margin:0}
.ticks li{position:relative;padding:9px 0 9px 30px;border-bottom:1px solid var(--line);font-size:15.2px}
.ticks li::before{content:"✓";position:absolute;left:2px;top:9px;color:var(--jade);font-weight:800}
.darkband .ticks li{border-color:rgba(255,255,255,.12)}

/* who-we-serve pills */
.serve{display:flex;flex-wrap:wrap;gap:10px}
.serve span{background:#fff;border:1px solid var(--line);border-radius:99px;padding:9px 18px;font-weight:600;font-size:14.5px;color:var(--ink)}
.darkband .serve span{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.16);color:#e7eef1}

/* quote form + hours */
.hoursbox{background:#fff;border:1px solid var(--line);border-top:4px solid var(--jade);border-radius:var(--radius);padding:28px}
.hoursbox table{width:100%;border-collapse:collapse}
.hoursbox td{padding:9px 0;border-bottom:1px solid var(--line);font-size:15px}
.hoursbox td:last-child{text-align:right;font-weight:700;color:var(--ink)}

/* footer */
.footer .footlogo img{height:64px;width:auto}
.footer h4{font-family:var(--font-head);font-weight:600;font-size:16px;color:#fff}
.footer a:hover{color:var(--jade)}
.callbar a.primary{background:var(--jade)}
.callbar{font-family:var(--font-head);font-weight:600}

/* ============================================================
   THE DETAIL BAND + LOGO PRESENCE
   The house mark shows up in six places beyond the nav and the
   footer: the trust bar, a hairline section ornament, a faint
   wash in every dark band, the stat band, and the quote form.
   Every one of them is decorative, so each is aria-hidden or
   carries the company name as its alt.
   ============================================================ */

/* the mark, flanked by hairlines, as a section ornament */
.markrule{display:flex;align-items:center;justify-content:center;gap:20px;margin:0 auto 26px;max-width:420px}
.markrule span{flex:1;height:1px;background:linear-gradient(90deg,transparent,var(--line))}
.markrule span:last-child{background:linear-gradient(90deg,var(--line),transparent)}
.markrule img{height:36px;width:auto;opacity:.9;flex:none}

/* small mark leading the trust bar */
.trustbar .tb-mark{height:26px;width:auto;flex:none;opacity:.95;margin-right:2px}
@media(max-width:900px){.trustbar .tb-mark{display:none}}

/* faint wash in the corner of a dark band. The band needs position+clip
   or the wash escapes and creates a horizontal scrollbar on mobile. */
.darkband.has-wash{position:relative;overflow:hidden}
.darkband.has-wash>.wrap{position:relative;z-index:1}
.markwash{position:absolute;right:-46px;bottom:-56px;width:min(340px,42vw);height:auto;
  opacity:.055;pointer-events:none;user-select:none;z-index:0}
@media(max-width:760px){.markwash{right:-60px;bottom:-40px;width:56vw;opacity:.05}}

/* centred logo over the stat band */
.statmark{text-align:center;margin-bottom:26px}
.statmark img{height:58px;width:auto;opacity:.92}
@media(max-width:640px){.statmark img{height:46px}.statmark{margin-bottom:18px}}

/* mark on the quote form card */
.leadform .formmark{display:block;height:44px;width:auto;margin:0 0 14px}

/* ---- the detail grid ---- */
.detailband{background:var(--bg-soft)}
.dgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,2vw,26px)}
.dcard{margin:0;background:#fff;border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden;box-shadow:var(--shadow-sm);display:flex;flex-direction:column;
  transition:transform .45s var(--reveal-ease),box-shadow .45s var(--reveal-ease)}
.dcard:hover{transform:translateY(-4px);box-shadow:var(--shadow)}
.dcard img{width:100%;height:200px;object-fit:cover;display:block;filter:var(--img-grade)}
.dcard figcaption{padding:18px 20px 22px;display:flex;flex-direction:column;gap:6px}
.dcard b{font-family:var(--font-head);font-weight:600;font-size:17.5px;color:var(--ink);
  letter-spacing:-.3px;line-height:1.25;
  /* the jade tick ties these to the .ticks lists used everywhere else */
  padding-left:26px;position:relative}
.dcard b::before{content:var(--check-glyph);position:absolute;left:0;top:-1px;color:var(--jade);font-weight:700}
.dcard span{font-size:14.5px;line-height:1.55;color:var(--body);padding-left:26px}
@media(max-width:940px){
  .dgrid{grid-template-columns:repeat(2,1fr)}
  .dcard img{height:180px}
}
@media(max-width:620px){
  .dgrid{grid-template-columns:1fr;gap:14px}
  .dcard img{height:186px}
  .dcard figcaption{padding:16px 18px 20px}
  .dcard b{font-size:17px}
  .markrule{gap:14px;margin-bottom:20px}
  .markrule img{height:30px}
}

/* ============================================================
   THE CONVERSION BLOCK
   A form on every page instead of a button that sends people to
   another page to find one. Sits on the soft tint so it reads as
   a distinct "act now" band rather than more body content.
   ============================================================ */
.ctaband{background:var(--bg-soft);border-top:1px solid var(--line)}
.ctagrid{display:grid;grid-template-columns:1fr minmax(340px,470px);gap:clamp(28px,4vw,60px);align-items:start}
.ctacopy .ticks{margin-bottom:24px}
.ctacopy .ticks li{margin-bottom:9px}

/* the phone alternative: some people will never fill in a form */
.ctacall{display:inline-flex;flex-direction:column;gap:3px;background:#fff;border:1px solid var(--line);
  border-left:4px solid var(--jade);border-radius:var(--radius);padding:14px 22px 15px;text-decoration:none;
  transition:transform .3s var(--reveal-ease),box-shadow .3s var(--reveal-ease)}
.ctacall:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.ctacall span{font-size:12px;font-weight:700;letter-spacing:1.6px;text-transform:uppercase;color:var(--mut)}
.ctacall b{font-family:var(--font-head);font-weight:600;font-size:25px;color:var(--jade);letter-spacing:-.4px}

.ctaband .leadform{background:#fff;box-shadow:var(--shadow)}
.ctaband .leadform select{appearance:none;
  /* the chevron is inline so the select never depends on a separate asset */
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%2369838f' stroke-width='1.8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 15px center;background-size:12px;padding-right:40px}
.microtrust{margin:12px 0 0;font-size:12.5px;line-height:1.5;color:var(--mut);text-align:center}
.leadform .formnote{background:color-mix(in srgb,var(--jade) 12%,transparent);border:1.5px dashed var(--jade);
  color:var(--ink);border-radius:calc(var(--radius) * .6 + 2px);padding:13px 16px;font-weight:700;margin-top:14px}

@media(max-width:900px){
  .ctagrid{grid-template-columns:1fr;gap:26px}
  /* form first on a phone: the reason the visitor scrolled this far is to act */
  .ctacopy{order:2}
  .ctaband .leadform{order:1}
  .ctacall{width:100%;align-items:center;text-align:center;min-height:56px;justify-content:center}
}

/* ============================================================
   SPLIT HERO — headline left, quote form right, both above the fold.
   The single highest-leverage change on the page: the visitor can act
   without scrolling and without loading a second page.
   ============================================================ */
.hero--split{--hero-vh:auto;--hero-cap:none}
.hero--split .wrap{padding-top:clamp(122px,15vh,168px);padding-bottom:clamp(54px,7vw,86px)}
.herogrid{display:grid;grid-template-columns:1.08fr minmax(370px,452px);gap:clamp(30px,4.5vw,72px);align-items:center;width:100%}
.hero--split h1{font-size:clamp(34px,4.4vw,60px)}
.hero--split .lead{max-width:52ch;margin:18px 0 26px}
.hero--split .row{margin-top:0}

/* SOLID white, no transparency and no backdrop-filter. A lead form must never be
   see-through over a photo: the background bleeds into the labels and the whole
   thing reads as disabled. backdrop-filter also costs real frames on iOS while
   scrolling, which is precisely when this element is on screen. */
.heroform{background:#fff;border:1px solid rgba(255,255,255,.6);
  border-radius:var(--radius);padding:26px 26px 22px;box-shadow:0 30px 70px rgba(9,26,36,.42)}
.hf-flag{display:inline-block;background:color-mix(in srgb,var(--jade) 13%,transparent);color:var(--jade);
  font-family:var(--font-head);font-weight:700;font-size:11.5px;letter-spacing:1.7px;text-transform:uppercase;
  padding:6px 12px;border-radius:100px;margin-bottom:12px}
.hf-h{font-family:var(--font-head);font-weight:600;font-size:27px;color:var(--ink);margin:0 0 5px;letter-spacing:-.5px}
.hf-sub{margin:0 0 4px;color:var(--mut);font-size:14.5px;line-height:1.5}
.heroform label{margin-top:11px}
.hf-call{display:block;text-align:center;margin-top:13px;font-family:var(--font-head);font-weight:600;
  font-size:15px;color:var(--jade);text-decoration:none;min-height:26px}
.hf-call:hover{text-decoration:underline}

@media(max-width:1000px){
  /* copy first, then the form: the headline still has to earn the form fill */
  .herogrid{grid-template-columns:1fr;gap:26px}
  .hero--split .wrap{padding-top:clamp(104px,14vh,140px)}
  .hero--split h1{font-size:clamp(31px,7.6vw,44px);line-height:1.08}
  .hero--split .lead{font-size:16px;margin:16px 0 22px}
  .heroformwrap{max-width:470px;width:100%}
  .heroform{padding:22px 20px 20px}
  .hf-h{font-size:24px}
}

/* the three-option positioning table */
.vsbox--3 table{table-layout:fixed}
.vsbox--3 th:first-child,.vsbox--3 td:first-child{width:28%}
@media(max-width:820px){
  /* a 4-column table cannot survive a phone: scroll it rather than crush it */
  .vsbox--3{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .vsbox--3 table{min-width:660px}
}

/* ============================================================
   MOTION — everything here is inside body.motion, which
   site-motion.js only adds when the visitor has NOT asked for
   reduced motion. Nothing below is required to read the page.
   ============================================================ */
/* hero form entrance is defined in the MOTION block below (hf-slide) */

/* a slow light sweep across the primary button, once every few seconds */
body.motion .btn-primary{position:relative;overflow:hidden;isolation:isolate}
body.motion .btn-primary::after{content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(105deg,transparent 38%,rgba(255,255,255,.28) 50%,transparent 62%);
  transform:translateX(-120%);animation:sheen 5.5s ease-in-out 2s infinite}
@keyframes sheen{0%{transform:translateX(-120%)}22%,100%{transform:translateX(120%)}}

/* Ticks draw in one after another when their list scrolls into view.
   The hidden start state is scoped to ticks INSIDE a .reveal — a tick list with
   no .reveal ancestor would otherwise never get .in and would stay invisible. */
body.motion .reveal .ticks li{opacity:0;transform:translateX(-8px);transition:opacity .5s var(--reveal-ease),transform .5s var(--reveal-ease)}
body.motion .reveal.in .ticks li{opacity:1;transform:none}
body.motion .reveal.in .ticks li:nth-child(1){transition-delay:.06s}
body.motion .reveal.in .ticks li:nth-child(2){transition-delay:.13s}
body.motion .reveal.in .ticks li:nth-child(3){transition-delay:.2s}
body.motion .reveal.in .ticks li:nth-child(4){transition-delay:.27s}
body.motion .reveal.in .ticks li:nth-child(5){transition-delay:.34s}
body.motion .reveal.in .ticks li:nth-child(6){transition-delay:.41s}
body.motion .reveal.in .ticks li:nth-child(7){transition-delay:.48s}

/* the house mark breathes, very slightly */
body.motion .markrule img{animation:mark-float 6s ease-in-out infinite}
@keyframes mark-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
/* and its hairlines draw outward when the ornament arrives */
body.motion .markrule span{transform:scaleX(0);transition:transform .9s var(--reveal-ease) .1s}
body.motion .markrule span:first-child{transform-origin:right}
body.motion .markrule span:last-child{transform-origin:left}
body.motion .markrule.in span{transform:scaleX(1)}

/* photos ease in behind their own frame instead of popping */
body.motion .dcard img,body.motion .sys img,body.motion .spec figure img{transition:transform .7s var(--reveal-ease),filter .7s ease}
body.motion .spec figure:hover img{transform:scale(1.03)}
body.motion .sys:hover img{transform:scale(1.04)}
body.motion .sys img{will-change:transform}

/* comparison rows arrive one at a time so the argument reads in order */
body.motion .vsbox.in tr{animation:row-in .55s var(--reveal-ease) both}
body.motion .vsbox.in tr:nth-child(1){animation-delay:.04s}
body.motion .vsbox.in tr:nth-child(2){animation-delay:.11s}
body.motion .vsbox.in tr:nth-child(3){animation-delay:.18s}
body.motion .vsbox.in tr:nth-child(4){animation-delay:.25s}
body.motion .vsbox.in tr:nth-child(5){animation-delay:.32s}
body.motion .vsbox.in tr:nth-child(6){animation-delay:.39s}
body.motion .vsbox.in tr:nth-child(7){animation-delay:.46s}
@keyframes row-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* the trust bar marks its own arrival once, on load */
body.motion .trustbar .tb-mark{animation:mark-pop .7s cubic-bezier(.2,1.5,.4,1) .3s both}
@keyframes mark-pop{from{opacity:0;transform:scale(.6) rotate(-8deg)}to{opacity:1;transform:none}}

/* form focus gets a soft ring rather than a hard jump */
.leadform input,.leadform textarea,.leadform select{transition:border-color .25s ease,box-shadow .25s ease,background-color .25s ease}
.leadform input:focus,.leadform textarea:focus,.leadform select:focus{background:#fff;box-shadow:0 0 0 4px color-mix(in srgb,var(--jade) 15%,transparent)}
.leadform button{transition:transform .25s var(--reveal-ease),box-shadow .25s var(--reveal-ease)}
.leadform button:not(:disabled):hover{transform:translateY(-2px)}
.leadform button:disabled{opacity:.75;cursor:default}

/* ============================================================
   MOTION — SLIDE, DON'T FADE
   The base .reveal is a 24px lift with opacity and transform on the
   same 0.7s curve, which the eye reads as a dissolve. Here the opacity
   resolves in roughly a third of the time the transform takes, so what
   you see is TRAVEL that happens to become visible, not a fade.
   Distance is up from 24px to ~52px for the same reason.

   These live below the base rules so they win on source order, and the
   whole block is scoped to body.motion — a visitor who has asked their
   phone for reduced motion never gets any of it and the page is simply
   there, fully visible, instantly.
   ============================================================ */
body.motion .reveal{
  opacity:0;transform:translateY(52px);
  transition:opacity .32s linear, transform 1s var(--reveal-ease);
  will-change:transform,opacity;
}
body.motion .reveal.in{opacity:1;transform:none}
/* once it has arrived, drop the compositing hint so long pages stay light */
body.motion .reveal.in{will-change:auto}

/* --- DESKTOP ONLY: paired blocks slide in from their own side ---
   translateX is deliberately never applied below 1000px. An element
   sitting 60px off-screen to the right creates real horizontal scroll
   on a phone, and no animation is worth a page that shifts sideways. */
@media(min-width:1001px){
  body.motion .split2>.reveal:first-child{transform:translate3d(-64px,18px,0)}
  body.motion .split2>.reveal:last-child{transform:translate3d(64px,18px,0)}
  body.motion .split2>.reveal.in{transform:none}

  /* spec rows: photo in from the outside edge, copy in from the inside.
     .spec:nth-child(even) is flipped with direction:rtl, so its sides mirror. */
  body.motion .spec>figure.reveal{transform:translate3d(-70px,20px,0)}
  body.motion .spec>div.reveal{transform:translate3d(70px,20px,0)}
  body.motion .spec:nth-child(even)>figure.reveal{transform:translate3d(70px,20px,0)}
  body.motion .spec:nth-child(even)>div.reveal{transform:translate3d(-70px,20px,0)}

  /* EVERY landed state must out-specify its own start state.
     The nth-child start rules score one element higher than a plain
     `.spec>.reveal.in` reset, so the even rows stayed parked 70px
     off-position forever instead of sliding home. Each reset below is
     written to beat the exact rule it undoes — do not simplify these
     back into one selector. */
  body.motion .spec>.reveal.in,
  body.motion .spec:nth-child(even)>figure.reveal.in,
  body.motion .spec:nth-child(even)>div.reveal.in{transform:none}

  body.motion .ctagrid>.ctacopy.reveal{transform:translate3d(-58px,20px,0)}
  body.motion .ctagrid>.leadform.reveal{transform:translate3d(58px,24px,0)}
  body.motion .ctagrid>.ctacopy.reveal.in,
  body.motion .ctagrid>.leadform.reveal.in{transform:none}

  body.motion .split2>.reveal:first-child.in,
  body.motion .split2>.reveal:last-child.in{transform:none}
}

/* --- MOBILE: a longer, slower vertical slide ---
   On a phone every section is full width and stacked, so the only honest
   direction is up. More travel and a slower curve make it read as a
   deliberate slide rather than a twitch. */
@media(max-width:1000px){
  body.motion .reveal{transform:translateY(58px);transition:opacity .3s linear, transform 1.05s var(--reveal-ease)}
  body.motion .reveal.in{transform:none}
}

/* --- STAGGER: grids arrive one tile after another --- */
body.motion .dgrid>.reveal:nth-child(2),body.motion .svcminor>.reveal:nth-child(2){transition-delay:.09s}
body.motion .dgrid>.reveal:nth-child(3),body.motion .svcminor>.reveal:nth-child(3){transition-delay:.18s}
body.motion .dgrid>.reveal:nth-child(4),body.motion .svcminor>.reveal:nth-child(4){transition-delay:.27s}
body.motion .dgrid>.reveal:nth-child(5){transition-delay:.36s}
body.motion .dgrid>.reveal:nth-child(6){transition-delay:.45s}
body.motion .steps3>.reveal:nth-child(2){transition-delay:.1s}
body.motion .steps3>.reveal:nth-child(3){transition-delay:.2s}
body.motion .steps3>.reveal:nth-child(4){transition-delay:.3s}
body.motion .statrow>.reveal:nth-child(2){transition-delay:.08s}
body.motion .statrow>.reveal:nth-child(3){transition-delay:.16s}
body.motion .statrow>.reveal:nth-child(4){transition-delay:.24s}
body.motion .faq>.reveal:nth-child(2){transition-delay:.06s}
body.motion .faq>.reveal:nth-child(3){transition-delay:.12s}
body.motion .faq>.reveal:nth-child(4){transition-delay:.18s}
body.motion .faq>.reveal:nth-child(5){transition-delay:.24s}

/* the hero form slides up from below rather than materialising */
body.motion .heroform{animation:hf-slide 1s cubic-bezier(.16,1,.3,1) .4s both}
@keyframes hf-slide{from{opacity:0;transform:translateY(64px)}to{opacity:1;transform:none}}

/* ===== home service split — MUST STAY LAST IN THIS FILE =====
   .sys .sc / .sys p (defined above) carry flex:1; these overrides tie on
   specificity, so source order decides. At the end of the file, photos absorb
   ALL slack height and no card ever shows a void between copy and link. */
.svcsplit .sys--feature .sc{padding:26px 26px 28px;flex:0 0 auto}
.svcsplit .sys--feature h3{font-size:27px}
.svcsplit .sys--feature p{font-size:15.5px;flex:0 0 auto}
.svcsplit .sys--feature img{height:auto;flex:1 1 0;min-height:260px}
.svcsplit .svcminor .sys img{height:auto;flex:1 1 0;min-height:150px}
.svcsplit .svcminor .sys h3{font-size:19px}
.svcsplit .svcminor .sys p{font-size:14px;flex:0 0 auto}
.svcsplit .svcminor .sys .sc{padding:18px 18px 20px;flex:0 0 auto}
.svcsplit .sys .go{margin-top:12px}

/* first + last name side by side. Two full-width fields stacked reads as a
   longer form than it is, and form length is the main thing that kills a
   mobile submit. On a narrow phone they stack anyway rather than squeeze. */
.leadform .namerow{display:grid;grid-template-columns:1fr 1fr;gap:0 12px}
.leadform .namerow label{margin-top:14px}
@media(max-width:400px){.leadform .namerow{grid-template-columns:1fr;gap:0}}
