/* Evolve site — ONE shared stylesheet (#85, extracted 2026-07-18 from the
   two inline copies that had drifted). Page-specific rules stay inline in
   each page AFTER this link so they win ties. */

@font-face{font-family:'General Sans';src:url('fonts/GeneralSans-Regular.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'General Sans';src:url('fonts/GeneralSans-Medium.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'General Sans';src:url('fonts/GeneralSans-Semibold.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'General Sans';src:url('fonts/GeneralSans-Bold.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap}

:root{--bg:#f1e4c6;--surface:#fff;--ink:#14110d;--ink-soft:#463d31;--ink-mute:#807358;
--border:#e8e1cf;--hairline:#d8cfb6;--brand:#2c4634;--deep:#1a2a1f;--brand-soft:#d6e0d2;--tint:#ebf0e8;
--cream:#f4ead2;--accent:#b07d49;--accent-deep:#7a5326;
--serif:'Fraunces',Georgia,serif;--sans:'General Sans',ui-sans-serif,system-ui,-apple-system,sans-serif;--mono:'Geist Mono',ui-monospace,monospace;
--ease:cubic-bezier(.2,0,0,1)}
*{box-sizing:border-box;margin:0}
html{scroll-behavior:smooth}
/* html carries the ground too — during a cross-document view transition the
   canvas behind the snapshots is the ROOT's background; unset, it flashed a
   WHITE box mid-navigation (Eshaan 2026-07-30 4:32pm). */
html{background:var(--bg)}
body{background:var(--bg);color:var(--ink);font-family:var(--sans);font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
img{max-width:100%;display:block}
.mono{font-family:var(--mono)}
/* nav — ONE centered floating capsule, never a full-bleed band. LIGHT SAGE
   glass (Eshaan 2026-07-30 3:14pm — the dark forest pill "doesn't look very
   good"; revert-or-lighter → the lighter shade: the old cream pill's body and
   shadows with a soft green cast via brand-soft, dark type + the original
   deep-green CTA back on top). Over a photo it needs more body (72%) or dark
   type loses contrast on a dark frame; over the flat cream page it thins. */
.nav{position:fixed;top:22px;left:0;right:0;z-index:97;display:flex;justify-content:center;padding:0 14px;pointer-events:none;transition:top .4s var(--ease)}
.nav.solid{top:12px}
/* max-width + no shrink: children keep their natural size so the pill genuinely
   overflows when it can't fit — which is what layoutNav() measures against.
   Without these the flex items just squash and every width reports "fits". */
.navpill{max-width:100%}
.navpill>*,.navright>*{flex-shrink:0}
.navpill{pointer-events:auto;display:flex;align-items:center;gap:16px;padding:6px 6px 6px 20px;border-radius:999px;
background:color-mix(in srgb,var(--brand-soft) 72%,transparent);backdrop-filter:blur(26px) saturate(200%);-webkit-backdrop-filter:blur(26px) saturate(200%);
border:1px solid color-mix(in srgb,#fff 55%,transparent);
box-shadow:0 14px 40px rgba(20,17,13,.22),inset 0 1px 0 rgba(255,255,255,.75),inset 0 -1px 0 rgba(20,17,13,.06);
transition:background .4s var(--ease),border-color .4s var(--ease),box-shadow .4s var(--ease)}
/* One light material, top to bottom — sage glass over the hero photo AND the
   page. Over a photo it needs the 72% body or dark type loses contrast on a
   dark frame; over the flat cream page it thins to 58%. */
.nav.solid .navpill{background:color-mix(in srgb,var(--brand-soft) 58%,transparent);
box-shadow:0 10px 32px rgba(20,17,13,.13),inset 0 1px 0 rgba(255,255,255,.75),inset 0 -1px 0 rgba(20,17,13,.06)}
/* Evolve's real logo, as an ALPHA MASK painted with currentColor — so it
   inherits the nav's colour transition instead of needing two image files.
   The roof+script only: the full lockup's "STAGE & DESIGN" is 10% of its height
   and would render ~5px tall here. */
.wordmark{display:block;width:97px;height:44px;flex-shrink:0;color:var(--deep);text-decoration:none;
background:currentColor;transition:color .4s var(--ease);
-webkit-mask:url(evolve-logo.png) left center/contain no-repeat;mask:url(evolve-logo.png) left center/contain no-repeat}

.navdiv{width:1px;height:28px;background:var(--hairline)}

.navlinks{position:relative;display:flex;gap:20px;font-size:13.5px;font-weight:600;color:var(--ink-soft)}

.navlinks a{color:inherit;text-decoration:none;position:relative;z-index:1;padding:7px 0}
/* the section pill — a soft deep tint that glides along the links to whichever
   section is crossing the viewport's middle (the dashboard rail's sliding-pill
   gesture, brought to the site). Built by the nav script, so no-JS never sees
   it; the global reduced-motion kill makes it jump instead of glide. */
.nav-ind{position:absolute;top:50%;left:0;height:34px;border-radius:999px;
background:color-mix(in srgb,var(--deep) 16%,transparent);border:1px solid color-mix(in srgb,var(--deep) 38%,transparent);
box-shadow:inset 0 1px 0 rgba(255,255,255,.4),0 2px 8px rgba(26,42,31,.18);opacity:0;pointer-events:none;
transform:translate(var(--x,0px),-50%);
transition:transform .45s var(--ease),width .45s var(--ease),opacity .3s var(--ease)}
.nav-ind.on{opacity:1}
/* the link the pill is parked on goes full deep so the pair reads as one
   clear "you are here" (Eshaan 3:31pm — "more clear to see") */
.navlinks a.cur{color:var(--deep)}
.navlinks a:focus-visible,.burger:focus-visible{outline:2px solid var(--accent-deep);outline-offset:3px;border-radius:8px}
/* the rule wipes in from the left, out to the right — same gesture as the gallery */
.navlinks a::after{content:'';position:absolute;left:0;right:0;bottom:2px;height:1px;background:currentColor;opacity:.55;transform:scaleX(0);transform-origin:right;transition:transform .32s var(--ease)}
.navlinks a:hover::after{transform:scaleX(1);transform-origin:left}
/* display:grid is the BASE — layoutNav() hides it with .off when nothing
   overflows. (It used to be display:none switched on by a media query; that
   query is gone, so a `none` base would keep it hidden forever.) */
/* a proper THREE-line hamburger, 2px weight so it actually reads.
   44px target, morphs to an X when the overlay is up. */
.burger{display:grid;width:44px;height:44px;padding:0;border:0;background:none;cursor:pointer;
place-content:center;gap:4px;color:var(--deep)}

.burger i{display:block;width:19px;height:2px;background:currentColor;border-radius:2px;
transition:transform .35s var(--ease),opacity .2s var(--ease)}
.burger[aria-expanded="true"] i:nth-child(1){transform:translateY(6px) rotate(45deg)}
.burger[aria-expanded="true"] i:nth-child(2){opacity:0}
.burger[aria-expanded="true"] i:nth-child(3){transform:translateY(-6px) rotate(-45deg)}
/* ACTIONS GROUP — Book + hamburger read as one cluster on the right, tight to
   each other, clearly separate from the links. Previously every child shared the
   pill's single gap, so nothing grouped and the spacing looked arbitrary. */
.navright{display:flex;align-items:center;gap:6px;margin-left:auto}
/* a small dropdown anchored to the button — it only ever holds the 1-3 links
   that didn't fit, so a full-screen takeover was wildly out of proportion */
.navright{position:relative}
.menu{position:absolute;top:calc(100% + 12px);right:0;z-index:98;min-width:172px;
background:color-mix(in srgb,var(--brand-soft) 78%,transparent);backdrop-filter:blur(24px) saturate(200%);-webkit-backdrop-filter:blur(24px) saturate(200%);
border:1px solid color-mix(in srgb,#fff 55%,transparent);border-radius:16px;padding:6px;
box-shadow:0 18px 44px rgba(20,17,13,.20),inset 0 1px 0 rgba(255,255,255,.75),inset 0 -1px 0 rgba(20,17,13,.05);
opacity:0;transform:translateY(-6px) scale(.97);transform-origin:top right;pointer-events:none;
transition:opacity .22s var(--ease),transform .22s var(--ease)}
.menu.open{opacity:1;transform:none;pointer-events:auto}
.menu-links{display:flex;flex-direction:column}
.menu-links a{display:flex;align-items:center;min-height:44px;padding:0 14px;border-radius:11px;
font-size:14.5px;font-weight:600;color:var(--ink-soft);text-decoration:none;white-space:nowrap;
transition:background .18s var(--ease),color .18s var(--ease)}
.menu-links a:hover{background:var(--tint);color:var(--deep)}
/* the green CTA — deep glass on the light sage pill (the original, back by
   request: the cream-on-dark inversion left with the dark pill). */
.navcta{background:color-mix(in srgb,var(--deep) 88%,transparent);color:var(--cream);padding:10px 19px;font-size:13px;
backdrop-filter:blur(20px) saturate(190%);-webkit-backdrop-filter:blur(20px) saturate(190%);
border:1px solid rgba(244,234,210,.18);
box-shadow:0 4px 16px rgba(26,42,31,.26),inset 0 1px 0 rgba(255,255,255,.20),inset 0 -1px 0 rgba(0,0,0,.25)}
.navcta:hover{background:color-mix(in srgb,#24382c 94%,transparent);box-shadow:0 6px 20px rgba(26,42,31,.38),inset 0 1px 0 rgba(255,255,255,.24)}

.btn{display:inline-block;border-radius:999px;padding:12px 24px;font-weight:700;font-size:14px;text-decoration:none;cursor:pointer;transition:transform .15s var(--ease),box-shadow .2s var(--ease),background .2s var(--ease)}
/* every button clears the 44px tap minimum on touch, not just the nav CTA */
@media(pointer:coarse){.btn{padding:14px 24px}}
.btn:active{transform:scale(.97)}
.btn-deep{background:color-mix(in srgb,var(--deep) 88%,transparent);color:#fff;
backdrop-filter:blur(20px) saturate(190%);-webkit-backdrop-filter:blur(20px) saturate(190%);
border:1px solid rgba(244,234,210,.18);
box-shadow:0 6px 20px rgba(26,42,31,.28),inset 0 1px 0 rgba(255,255,255,.20),inset 0 -1px 0 rgba(0,0,0,.25)}
.btn-deep:hover{background:color-mix(in srgb,#24382c 94%,transparent);box-shadow:0 8px 26px rgba(26,42,31,.38),inset 0 1px 0 rgba(255,255,255,.24)}
.btn-cream{background:color-mix(in srgb,var(--cream) 82%,transparent);color:var(--deep);
backdrop-filter:blur(20px) saturate(190%);-webkit-backdrop-filter:blur(20px) saturate(190%);
border:1px solid rgba(255,255,255,.5);box-shadow:0 6px 20px rgba(20,17,13,.22),inset 0 1px 0 rgba(255,255,255,.8)}
.btn-cream:hover{background:color-mix(in srgb,var(--cream) 94%,transparent);box-shadow:0 8px 26px rgba(20,17,13,.3),inset 0 1px 0 rgba(255,255,255,.8)}
.btn-ghost{border:1px solid rgba(244,234,210,.5);color:var(--cream);
background:color-mix(in srgb,var(--deep) 30%,transparent);backdrop-filter:blur(18px) saturate(180%);-webkit-backdrop-filter:blur(18px) saturate(180%);
box-shadow:inset 0 1px 0 rgba(255,255,255,.2)}
.btn-ghost:hover{background:color-mix(in srgb,var(--deep) 42%,transparent)}
.btn-outline{border:1px solid color-mix(in srgb,#fff 70%,transparent);color:var(--deep);
background:color-mix(in srgb,var(--surface) 55%,transparent);backdrop-filter:blur(18px) saturate(190%);-webkit-backdrop-filter:blur(18px) saturate(190%);
box-shadow:inset 0 1px 0 rgba(255,255,255,.8)}
.btn-outline:hover{background:color-mix(in srgb,var(--surface) 78%,transparent);border-color:var(--brand-soft)}
.eyebrow{font-family:var(--mono);font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--accent-deep);font-weight:600}
/* margin-inline, NOT `margin:0 auto` — the shorthand would zero margin-top and
   silently cancel section{margin-top} on every <section class="wrap"> */
.wrap{max-width:1160px;margin-inline:auto;padding:0 38px}
section{margin-top:52px}
/* testimonials — serif pull-quotes on white cards, mono attribution */

.quote-card{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:22px;
box-shadow:inset 0 1px 0 rgba(255,255,255,.45),0 6px 22px rgba(28,24,16,.08)}
.quote-card p{font-family:var(--serif);font-size:19px;line-height:1.45;letter-spacing:-.01em;color:var(--deep)}
.quote-card .attr{margin-top:14px;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-mute)}
.quote-card .attr b{color:var(--accent-deep);font-weight:600}
/* hero */
.hero{position:relative;min-height:100vh;display:flex;align-items:flex-end;overflow:hidden}
/* No static will-change: the kenburns animation promotes its own layer while
   running; a permanent hint pinned five full-viewport backing stores for the
   page's life (run-4 P3, MDN caution). */
.hero .ph{position:absolute;inset:-6% 0;transform:translate3d(0,0,0);backface-visibility:hidden}
/* Parallax on the COMPOSITOR where supported. The JS version wrote transform
   from a scroll handler; iOS coalesces scroll events during momentum scrolling,
   so it caught up in jumps — that's the jitter. A scroll timeline never touches
   the main thread. JS stays as the fallback, desktop-only. */
@supports (animation-timeline:scroll()){
  .hero .ph{animation:parallax linear both;animation-timeline:scroll();animation-range:0 100vh}
  @keyframes parallax{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,14vh,0)}}
}
/* stacked, cross-fading. only the active frame Ken Burnses, so the scale
   restarts with each photo instead of every image animating at once. */
/* long, linear cross-fade — an eased fade front-loads the change and reads as a
   blink; linear over 3s is what makes it feel like a dissolve rather than a cut */
.hero .ph img{position:absolute;inset:0;width:100%;height:112%;object-fit:cover;opacity:0;transition:opacity 3s linear}
/* Ken Burns runs the full dwell so the frame is always drifting, never parked */
.hero .ph img.on{opacity:1;animation:kenburns 13s linear both}
@keyframes kenburns{from{transform:scale(1.06)}to{transform:scale(1)}}
.hero::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(20,17,13,.32) 0%,rgba(20,17,13,.12) 30%,rgba(26,42,31,.55) 62%,rgba(26,42,31,.88) 100%)}
.hero-inner{position:relative;z-index:2;max-width:1160px;margin:0 auto;width:100%;padding:0 38px 74px;color:var(--cream)}
.hero h1{font-family:var(--serif);font-weight:300;font-size:clamp(42px,6.4vw,80px);line-height:1.02;letter-spacing:-.022em;max-width:13ch}
.hero h1 .ln{display:block;overflow:hidden}
.hero h1 .ln span{display:block;transform:translateY(112%);animation:riseln .8s var(--ease) forwards}
.hero h1 .ln:nth-child(2) span{animation-delay:.09s}.hero h1 .ln:nth-child(3) span{animation-delay:.18s}
@keyframes riseln{to{transform:translateY(0)}}
.hero .sub{margin-top:18px;font-size:17px;max-width:46ch;text-shadow:0 1px 16px rgba(20,17,13,.45);opacity:0;animation:fadeup .7s var(--ease) .45s forwards}
.hero .cta{margin-top:30px;display:flex;gap:12px;flex-wrap:wrap;opacity:0;animation:fadeup .7s var(--ease) .6s forwards}
.hero .eyebrow{display:inline-block;background:color-mix(in srgb,var(--deep) 52%,transparent);backdrop-filter:blur(18px) saturate(180%);-webkit-backdrop-filter:blur(18px) saturate(180%);border:1px solid rgba(244,234,210,.26);box-shadow:inset 0 1px 0 rgba(255,255,255,.18);border-radius:999px;padding:7px 14px;color:var(--cream);opacity:0;animation:fadeup .6s var(--ease) .05s forwards}
@keyframes fadeup{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
/* No glass pill here — the cue sits on the hero photo, which the type reads
   against on its own. A capsule around two words is a box for its own sake. */
.scrollcue{position:absolute;bottom:26px;right:40px;z-index:3;font-family:var(--mono);font-size:9px;letter-spacing:.22em;text-transform:uppercase;color:rgba(244,234,210,.95);writing-mode:vertical-rl;display:flex;align-items:center;gap:8px;
text-shadow:0 1px 8px rgba(20,17,13,.55)}
.scrollcue::after{content:'';width:1px;height:44px;background:linear-gradient(180deg,rgba(244,234,210,.8),transparent);animation:cue 1.8s var(--ease) infinite}
@keyframes cue{0%{transform:scaleY(0);transform-origin:top}55%{transform:scaleY(1);transform-origin:top}56%{transform-origin:bottom}100%{transform:scaleY(0);transform-origin:bottom}}
/* reveal system */
/* visible by DEFAULT; the hidden pre-reveal state applies only once JS has
   stamped html.js — no-JS / failed-JS / unfurl renders show everything */
[data-reveal]{transition:opacity .7s var(--ease),transform .7s var(--ease)}
html.js [data-reveal]:not(.in){opacity:0;transform:translateY(26px)}
[data-reveal].in{opacity:1;transform:none}
/* transformation — THE signature (in-flow; each frame auto-sweeps once on reveal) */
/* before/after slider — each one lives in the service card it proves. 3:2 matches
   the source photos exactly, so cover crops nothing and the layers stay registered */
.xf .frame{position:relative;aspect-ratio:3/2;overflow:hidden;
box-shadow:inset 0 1px 0 rgba(255,255,255,.5),inset 0 0 0 1px rgba(255,255,255,.14),inset 0 -20px 40px -24px rgba(20,17,13,.5)}
.xf .frame img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.xf .after{clip-path:inset(0 0 0 var(--split,8%))}
.xf .line{position:absolute;top:0;bottom:0;left:var(--split,8%);width:2px;background:var(--cream);box-shadow:0 0 0 1px rgba(20,17,13,.3)}
.xf .knob{position:absolute;top:50%;left:var(--split,8%);transform:translate(-50%,-50%);width:34px;height:34px;border-radius:999px;background:color-mix(in srgb,var(--cream) 78%,transparent);backdrop-filter:blur(14px) saturate(180%);-webkit-backdrop-filter:blur(14px) saturate(180%);border:1px solid rgba(255,255,255,.5);color:var(--deep);display:grid;place-items:center;font-weight:800;font-size:12px;box-shadow:0 4px 16px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.7);cursor:ew-resize}
/* touch: the handle is the whole point of this section — it has to be tappable.
   44px is the minimum target; the visual stays small via the inset ring. */
@media(pointer:coarse){.xf .knob{width:44px;height:44px;font-size:15px}}
.xf .knob:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.xf .tag{position:absolute;top:12px;font-family:var(--mono);font-size:8.5px;letter-spacing:.18em;text-transform:uppercase;background:color-mix(in srgb,var(--ink) 45%,transparent);backdrop-filter:blur(14px) saturate(170%);-webkit-backdrop-filter:blur(14px) saturate(170%);border:1px solid rgba(255,255,255,.18);box-shadow:inset 0 1px 0 rgba(255,255,255,.2);color:var(--cream);border-radius:999px;padding:4px 9px}
.xf.sweep .after,.xf.sweep .line,.xf.sweep .knob{transition:clip-path 1.5s var(--ease),left 1.5s var(--ease)}
/* services */
/* about — their own words, set against one of their own rooms */
.about{display:grid;grid-template-columns:1fr 1fr;gap:52px;align-items:center}
.about-im{border-radius:20px;overflow:hidden;aspect-ratio:4/3;position:relative;
box-shadow:inset 0 1px 0 rgba(255,255,255,.45),inset 0 0 0 1px rgba(255,255,255,.16),0 8px 28px rgba(28,24,16,.12)}
.about-im img{width:100%;height:100%;object-fit:cover}
.about-body h2{font-family:var(--serif);font-weight:300;font-size:clamp(30px,3.6vw,44px);letter-spacing:-.02em;color:var(--deep);margin:10px 0 16px}
.about-body p{color:var(--ink-soft);font-size:15.5px;max-width:46ch}
.about-body p+p{margin-top:12px}
/* this is Evolve's own sentence, not a label — set it as body text.
   uppercase mono is for short eyebrows; it makes a sentence unreadable. */
.gal-more{display:flex;justify-content:center;margin-top:26px}
.gal-note{font-size:14.5px;color:var(--ink-soft);margin:-16px 0 26px;max-width:60ch}
.sec-head{display:flex;align-items:baseline;justify-content:space-between;gap:20px;margin-bottom:30px}
/* h1 too — the subpages put their page title in this slot (gallery.html has
   carried an inline copy of this rule since its redesign; it now matches). */
.sec-head h1,.sec-head h2{font-family:var(--serif);font-weight:400;font-size:36px;letter-spacing:-.015em;color:var(--deep)}
.svc{display:grid;grid-template-columns:1fr 1fr;gap:26px}
.svc-card{background:color-mix(in srgb,var(--surface) 62%,transparent);backdrop-filter:blur(26px) saturate(200%);-webkit-backdrop-filter:blur(26px) saturate(200%);
border:1px solid color-mix(in srgb,#fff 65%,transparent);border-radius:20px;overflow:hidden;
box-shadow:0 8px 30px rgba(28,24,16,.09),inset 0 1px 0 rgba(255,255,255,.85),inset 0 -1px 0 rgba(20,17,13,.05);transition:transform .35s var(--ease),box-shadow .35s var(--ease)}
.svc-card:hover{transform:translateY(-5px);box-shadow:0 18px 44px rgba(28,24,16,.13)}

.svc-body{padding:26px 28px 30px}
.svc-body h3{font-family:var(--serif);font-weight:500;font-size:24px;color:var(--deep)}
.svc-body p{margin-top:9px;color:var(--ink-soft);font-size:14.5px}
.svc-meta{margin-top:18px;display:flex;justify-content:space-between;align-items:center;gap:10px}
.svc-meta .mono{font-size:10.5px;letter-spacing:.08em;color:var(--ink-soft);text-transform:uppercase}
/* gallery */
.gal{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.gal figure{position:relative;border-radius:16px;overflow:hidden;
box-shadow:inset 0 1px 0 rgba(255,255,255,.45),inset 0 0 0 1px rgba(255,255,255,.16),0 6px 22px rgba(28,24,16,.10)}
.gal img{height:240px;width:100%;object-fit:cover;transition:transform .5s var(--ease)}
.gal figure:hover img{transform:scale(1.04)}
.gal figcaption{position:absolute;inset-inline:8px;bottom:8px;padding:9px 12px;border-radius:10px;
background:color-mix(in srgb,var(--ink) 42%,transparent);backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);
border:1px solid rgba(255,255,255,.18);box-shadow:inset 0 1px 0 rgba(255,255,255,.2);
color:var(--cream);font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;opacity:0;transition:opacity .35s}
.gal figure:hover figcaption{opacity:1}
.btn:focus-visible{outline:2px solid var(--accent-deep);outline-offset:3px}
@media(pointer:coarse){.navlinks a{min-height:44px;display:inline-flex;align-items:center}}
@media (hover:none){.gal figcaption{opacity:1;backdrop-filter:none;-webkit-backdrop-filter:none;background:color-mix(in srgb,var(--ink) 68%,transparent)}}
/* quote */








/* book */
.book{background:linear-gradient(165deg,color-mix(in srgb,var(--brand) 88%,transparent) 0%,color-mix(in srgb,var(--deep) 92%,transparent) 82%);
backdrop-filter:blur(26px) saturate(190%);-webkit-backdrop-filter:blur(26px) saturate(190%);
border:1px solid rgba(244,234,210,.16);
box-shadow:0 14px 40px rgba(20,17,13,.18),inset 0 1px 0 rgba(255,255,255,.16),inset 0 -1px 0 rgba(0,0,0,.22);border-radius:26px;color:var(--cream);padding:56px 60px;display:grid;grid-template-columns:1fr minmax(0,440px);align-items:center;gap:48px;position:relative;overflow:hidden}
.book::after{content:'';position:absolute;right:-70px;top:-70px;width:280px;height:280px;border-radius:999px;background:radial-gradient(circle,rgba(244,234,210,.12),transparent 65%)}
.book h2{font-family:var(--serif);font-weight:400;font-size:36px;max-width:18ch;letter-spacing:-.015em}
.book-say{margin-top:16px;font-size:14.5px;opacity:.82;max-width:34ch;line-height:1.6}
.book-call{margin-top:22px;display:inline-flex;align-items:center;gap:9px;font-family:var(--mono);font-size:12px;letter-spacing:.06em;color:var(--cream);text-decoration:none;opacity:.9;border-bottom:1px solid rgba(244,234,210,.3);padding-bottom:3px}
.book-call:hover{opacity:1;border-bottom-color:var(--cream)}

/* ---- quote form ---------------------------------------------------------
   Replaces the mailto stopgap. Posts JSON to the dashboard's /api/lead so a
   submission lands as a triageable lead instead of an email nobody structures.
   Field set mirrors what the old Wix form collected (incl. the Home Owner /
   Broker split, which maps onto the realtor-vs-owner model the app already
   has) MINUS its "Today's date" input — the server stamps submittedAt. */
.qf{position:relative;z-index:2;display:grid;gap:13px}
.qf-row{display:grid;grid-template-columns:1fr 1fr;gap:13px}
.qf-f{display:flex;flex-direction:column;gap:6px;min-width:0}
.qf label{font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:rgba(244,234,210,.72)}
.qf input,.qf select,.qf textarea{
  /* 16px min — anything smaller makes iOS Safari zoom the viewport on focus */
  font:400 16px/1.4 var(--sans);color:var(--cream);width:100%;
  background:rgba(244,234,210,.07);border:1px solid rgba(244,234,210,.22);
  border-radius:10px;padding:11px 13px;min-height:44px;
  transition:border-color .18s var(--ease),background .18s var(--ease)}
.qf textarea{min-height:74px;resize:vertical}
.qf select{appearance:none;-webkit-appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'><path d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23f4ead2' stroke-width='1.5' stroke-linecap='round'/></svg>");
  background-repeat:no-repeat;background-position:right 13px center;background-size:11px;padding-right:34px}
.qf select option{background:var(--deep);color:var(--cream)}
/* .64 ≈ 4.6:1 over the evergreen book panel — .38 sat at ~2.85:1 and the
   textarea hint is the field's only cue (run-4 P2). */
.qf input::placeholder,.qf textarea::placeholder{color:rgba(244,234,210,.64)}
.qf input:hover,.qf select:hover,.qf textarea:hover{border-color:rgba(244,234,210,.38)}
.qf input:focus-visible,.qf select:focus-visible,.qf textarea:focus-visible{
  outline:2px solid var(--cream);outline-offset:2px;border-color:transparent;background:rgba(244,234,210,.12)}
.qf-hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0;pointer-events:none}
.qf-submit{margin-top:5px;justify-self:start;border:0;cursor:pointer;font:500 14px var(--sans)}
.qf-submit[disabled]{opacity:.55;cursor:progress}
.qf-note{font-size:11.5px;opacity:.62;line-height:1.5}
.qf-msg{font-size:13.5px;line-height:1.55;padding:11px 13px;border-radius:10px;display:none}
.qf-msg.show{display:block}
.qf-msg.ok{background:rgba(244,234,210,.12);border:1px solid rgba(244,234,210,.3);color:var(--cream)}
.qf-msg.bad{background:rgba(176,125,73,.18);border:1px solid rgba(214,160,100,.5);color:#f0d9bd}
.qf-err{font-size:11.5px;color:#f0c9a0;display:none}
.qf-err.show{display:block}
.qf input[aria-invalid="true"],.qf select[aria-invalid="true"]{border-color:#d6a064}
footer{background:var(--deep);color:var(--cream);margin-top:52px;box-shadow:inset 0 1px 0 rgba(255,255,255,.10)}
/* TWO children (brand+blurb · contact) — the old `2fr 1fr 1fr` declared a third
   track that nothing ever filled, stranding contact mid-footer beside a hole.
   `auto` sizes the contact column to its longest line (the email) so it sets
   flush to the right rule instead of floating. */
.foot{max-width:1160px;margin:0 auto;padding:54px 38px 42px;display:grid;grid-template-columns:1fr auto;gap:40px}
/* The contact column is NOT a card. Glass needs something behind it to bend;
   on the flat forest footer it only drew a border around three lines of text
   and made one of three equal columns look like a separate object. */
.foot-h{font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:#ddd0ab;font-weight:600;margin:0 0 12px}
.foot a{color:var(--cream);text-decoration:none;opacity:.85}.foot a:hover{opacity:1}
/* the UL keeps a browser-default 40px padding-inline-start — list-style:none on
   the LI doesn't touch it, which is what was indenting the contact lines */
.foot ul{list-style:none;padding:0;margin:0}
.foot p,.foot li{font-size:13.5px;opacity:.95;margin-bottom:6px}
.copyright{border-top:1px solid rgba(244,234,210,.18);padding:18px 38px;text-align:center;font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:rgba(244,234,210,.75)}
@media(max-width:880px){.svc{grid-template-columns:1fr}.gal{grid-template-columns:1fr 1fr}
/* the form can't hold a 440px track next to a headline on a phone — stack it,
   and drop the 60px padding that would leave the inputs ~200px wide */
.book{grid-template-columns:1fr;gap:28px;padding:34px 24px}
.book h2{font-size:27px;max-width:none}
/* stacked, a 40px column gap reads as a hole between the blurb and the contacts */
.foot{grid-template-columns:1fr;gap:30px;padding:44px 22px 34px}
/* about MUST collapse — two columns on a phone crushes the photo and wraps the text every few words */
.about{grid-template-columns:1fr;gap:26px}.about-im{aspect-ratio:16/10}
.sec-head{flex-wrap:wrap;gap:14px}.wrap{padding:0 22px}section{margin-top:44px}footer{margin-top:44px}
/* links collapse away — the divider has nothing left to divide */
.navdiv{display:none}}
.navcta .sm{display:none}
/* No link breakpoint. layoutNav() measures and keeps every link that fits,
   pushing only the overflow into the menu — so the bar is as full as the
   width allows at any size, rather than all-or-nothing at a guessed px. */
.navlinks a.off,.navdiv.off,.burger.off{display:none}
/* Stretched bar, final form (Eshaan 2026-07-30 4:32pm — "you didn't fix the
   spacing": 56px still read too airy): EQUAL, genuinely reduced voids — a
   26px margin each side of the links (+ the pill's 16px beat ≈ 42px visual),
   divider→Services exactly matching Contact→Book. Links keep the 40px spread.
   Scoped ≥881px so the measured priority+ overflow math below is untouched. */
@media(min-width:881px){
.navlinks{margin-inline:26px;gap:40px}
.navright{margin-left:0}
}
@media(max-width:880px){
.nav{padding:0 12px}
.navpill{gap:13px;padding:6px 6px 6px 17px}
.navlinks{gap:16px;font-size:13px}
.navcta{padding:12px 17px}.navcta .lg{display:none}.navcta .sm{display:inline}}
/* narrow: the bar spans the width so it reads as a bar, not a floating lozenge */
@media(max-width:560px){
.nav{top:12px;padding:0 12px}
.navpill{width:100%;padding:8px 8px 8px 16px;border-radius:22px}
.wordmark{width:88px;height:40px}
/* paired fields go single-file — at this width a 2-col row leaves each input
   too narrow to show a typed address or a full email */
.qf-row{grid-template-columns:1fr}
}
/* The selector list was `*,{*::before,*::after}` — a stray brace made it
   malformed, and CSS's tolerant parser DROPS a bad rule silently rather than
   erroring, so this looked correct while doing nothing: reduced-motion visitors
   were still getting the 13s kenburns pan and the 1.8s scroll cue. */
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}
[data-reveal]{opacity:1!important;transform:none!important}
.hero h1 .ln span{transform:none}.hero .sub,.hero .cta,.hero .eyebrow{opacity:1}
/* no sweep — the sliders just rest at the midpoint (belt and braces; the JS does this too) */
.xf .after{clip-path:inset(0 0 0 50%)!important}.xf .line,.xf .knob{left:50%!important}}

/* #78 — dashboard-controlled announcement bar (hydration-only: no baked
   markup; the script inserts it when site_content turns it on). */
.announcebar{position:fixed;top:0;left:0;right:0;z-index:98;background:var(--cream);color:var(--ink);font:500 12.5px/1.4 var(--mono,monospace);text-align:center;padding:9px 14px;border-bottom:1px solid rgba(0,0,0,.08);letter-spacing:.02em}
.skiplink{position:fixed;top:8px;left:8px;z-index:200;transform:translateY(-200%);background:var(--deep);color:var(--cream);padding:10px 16px;border-radius:999px;font-family:var(--mono);font-size:12px;letter-spacing:.06em;transition:transform .2s}
.skiplink:focus{transform:none;outline:2px solid var(--accent-deep);outline-offset:3px}
/* #89 v3 (2026-07-30 4:32pm — Eshaan: "that green transition is fully gone,
   why, i only said improve the performance, not remove it") — the GREEN VEIL
   IS BACK, rebuilt fast: the sweep-up is 300ms (was 340), the destination is
   already prerendered (speculation rules in each page's head) so the swap
   behind it is instant, and the cross-document view transition then dissolves
   green→new page — same drama, zero stall. The fixed nav pill keeps its own
   group so it holds steady; the bfcache pageshow guard in site-motion.js
   drops a stuck veil on back-restore. */
@view-transition{navigation:auto}
::view-transition-old(root),::view-transition-new(root){animation-duration:.28s}
.nav{view-transition-name:site-nav}
@media(prefers-reduced-motion:reduce){
@view-transition{navigation:none}
}
.pt-veil{position:fixed;inset:0;z-index:300;pointer-events:none;background:var(--deep);transform:translateY(101%)}
html.pt-exit .pt-veil{transition:transform .3s cubic-bezier(.22,.61,.36,1);transform:translateY(0)}
html.pt-exit main{transition:opacity .26s ease,transform .26s ease;opacity:0;transform:translateY(-12px)}

/* ── #92 premium effects pack ──────────────────────────────────────────────
   Everything below is PROGRESSIVE: html.fx is stamped by site-effects.js only
   when motion is allowed, WebGL bits self-disable without support, and the
   global prefers-reduced-motion kill above already zeroes every animation/
   transition these rules declare. No-JS renders never see a changed page. */

/* A — shader hero crossfade. The canvas sits INSIDE .ph (under the scrim and
   the type), fades in once textures are warm, and .gl freezes the img stack's
   own kenburns/fade so the shader is the only thing moving. */
.ph canvas.hero-gl{position:absolute;inset:0;width:100%;height:100%;opacity:0;transition:opacity .6s var(--ease)}
.ph.gl canvas.hero-gl{opacity:1}
.ph.gl img{animation:none!important;transition:none!important}

/* D — hero mouse reveal: a warm light that trails the cursor and thins the
   scrim locally. z1 puts it above the scrim (::after, z-auto) and under the
   type (z2). Hidden until the first pointermove so touch never sees it. */
.hero-glow{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:0;transition:opacity .8s var(--ease);
mix-blend-mode:soft-light;
background:radial-gradient(520px circle at var(--mx,50%) var(--my,42%),rgba(244,234,210,.14),rgba(244,234,210,.03) 48%,transparent 75%)}
.hero-glow.live{opacity:1}

/* B — living CTA gradient. Two soft auroras drift behind the book panel's
   glass; transform-only, so the compositor owns them. The existing ::after
   radial keeps its place — these ride under the content (z1 < the text's z2). */
.book::before{content:'';position:absolute;z-index:1;left:-120px;bottom:-160px;width:420px;height:420px;border-radius:999px;
background:radial-gradient(circle,rgba(176,125,73,.34),transparent 62%);
animation:aurora-a 19s var(--ease) infinite alternate;pointer-events:none}
.book::after{animation:aurora-b 23s var(--ease) infinite alternate}
@keyframes aurora-a{from{transform:translate3d(0,0,0) scale(1)}to{transform:translate3d(120px,-90px,0) scale(1.25)}}
@keyframes aurora-b{from{transform:translate3d(0,0,0) scale(1)}to{transform:translate3d(-110px,70px,0) scale(1.18)}}

/* B — specular sheen that sweeps solid buttons once per hover. Gated to real
   hover devices; overflow:hidden only where the sheen exists. */
@media(hover:hover) and (pointer:fine){
.btn-cream,.btn-deep,.navcta{position:relative;overflow:hidden}
.btn-cream::after,.btn-deep::after,.navcta::after{content:'';position:absolute;top:0;bottom:0;left:-40%;width:36%;
background:linear-gradient(105deg,transparent,rgba(255,255,255,.32),transparent);
transform:translateX(-120%) skewX(-14deg);pointer-events:none}
.btn-cream:hover::after,.btn-deep:hover::after,.navcta:hover::after{transition:transform .7s var(--ease);transform:translateX(480%) skewX(-14deg)}
}

/* E — gooey caption melt. site-effects.js injects the #ev-goo SVG filter and
   a .gooify shape layer per figure; on hover a droplet falls out of the photo
   and MERGES into the caption's ground while the label text (kept OUTSIDE the
   filter, so it stays crisp) fades in above it. Hover-capable devices only —
   touch keeps today's always-visible caption. */
@media(hover:hover) and (pointer:fine){
html.fx .gal figure .gooify{position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity .3s var(--ease);filter:url(#ev-goo)}
html.fx .gal figure:hover .gooify{opacity:1}
html.fx .gal .gooify i{position:absolute;background:color-mix(in srgb,var(--ink) 62%,transparent)}
html.fx .gal .gooify .g-pill{inset-inline:8px;bottom:8px;height:34px;border-radius:10px}
html.fx .gal .gooify .g-dot{left:50%;bottom:96px;width:18px;height:18px;margin-left:-9px;border-radius:999px;
transform:translateY(-8px) scale(.4);transition:transform .55s var(--ease)}
html.fx .gal figure:hover .gooify .g-dot{transform:translateY(74px) scale(1)}
/* the real caption floats above the goo ground: no double backdrop, and an
   explicit z so the appended .gooify (later in DOM) can never paint over it */
html.fx .gal figure .gooify{z-index:1}
html.fx .gal figure figcaption{z-index:2;background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;border-color:transparent;box-shadow:none}
}

/* ── service areas (#39, 2026-08-08) ───────────────────────────────────────
   The hub (service-areas.html) + the seven city pages. ONE shared block
   rather than eight inline copies — same reasoning as #85, which pulled the
   two drifted inline stylesheets into this file. Everything below reuses the
   existing tokens and glass recipes; .gal, .svc/.svc-card and .book are
   borrowed as-is so a service-area page is built from the same parts the
   homepage is. */

/* the subpage head sits where gallery.html's does (below the floating pill) */
.pagehead{margin-top:118px}
.lede{font-size:17px;line-height:1.6;color:var(--ink-soft);max-width:62ch;margin:-14px 0 0}

/* an inline link inside body copy. The site had no prose-link style because
   until now every link was a button, a nav item or a footer line. */
.tlink{color:var(--accent-deep);text-decoration:none;
border-bottom:1px solid color-mix(in srgb,var(--accent-deep) 38%,transparent);padding-bottom:1px;
transition:border-color .25s var(--ease),color .25s var(--ease)}
.tlink:hover{border-bottom-color:var(--accent-deep);color:var(--deep)}
.tlink:focus-visible{outline:2px solid var(--accent-deep);outline-offset:3px;border-radius:4px}

/* contained, rounded lead photo — the gallery chapters' hero treatment */
.sa-hero{margin-top:26px;border-radius:20px;overflow:hidden;aspect-ratio:16/7;
box-shadow:inset 0 1px 0 rgba(255,255,255,.45),inset 0 0 0 1px rgba(255,255,255,.16),0 14px 38px rgba(28,24,16,.16)}
.sa-hero img{width:100%;height:100%;object-fit:cover}

/* fact strip — mono label over a serif value, on the same sage glass as the
   pill. GRID, not flex: three equal columns fill the strip's width instead of
   bunching the facts against the left edge with a void beside them. */
.sa-facts{display:grid;grid-template-columns:repeat(3,1fr);gap:16px 32px;margin-top:26px;padding:18px 22px;border-radius:18px;
background:color-mix(in srgb,var(--brand-soft) 48%,transparent);backdrop-filter:blur(20px) saturate(190%);-webkit-backdrop-filter:blur(20px) saturate(190%);
border:1px solid color-mix(in srgb,#fff 55%,transparent);box-shadow:inset 0 1px 0 rgba(255,255,255,.55),0 8px 26px rgba(20,17,13,.07)}
.sa-fact span{display:block;font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--accent-deep);font-weight:600}
.sa-fact b{display:block;margin-top:5px;font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;color:var(--deep)}
.sa-fact i{display:block;margin-top:2px;font-style:normal;font-size:11.5px;color:var(--ink-mute)}

/* city cards — the .svc-card material at index-card scale, whole card linked */
.sa-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.sa-card{display:flex;flex-direction:column;gap:8px;padding:24px 24px 20px;border-radius:20px;text-decoration:none;color:inherit;
background:color-mix(in srgb,var(--surface) 62%,transparent);backdrop-filter:blur(26px) saturate(200%);-webkit-backdrop-filter:blur(26px) saturate(200%);
border:1px solid color-mix(in srgb,#fff 65%,transparent);
box-shadow:0 8px 30px rgba(28,24,16,.09),inset 0 1px 0 rgba(255,255,255,.85),inset 0 -1px 0 rgba(20,17,13,.05);
transition:transform .35s var(--ease),box-shadow .35s var(--ease)}
.sa-card:hover{transform:translateY(-5px);box-shadow:0 18px 44px rgba(28,24,16,.13)}
.sa-card:focus-visible{outline:2px solid var(--accent-deep);outline-offset:3px}
.sa-card h3{font-family:var(--serif);font-weight:500;font-size:23px;letter-spacing:-.01em;color:var(--deep)}
.sa-card p{font-size:14px;color:var(--ink-soft)}
.sa-card .sa-count{margin-top:auto;padding-top:14px;font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--accent-deep)}
.sa-card .sa-count em{font-style:normal;display:inline-block;transition:transform .3s var(--ease)}
.sa-card:hover .sa-count em{transform:translateX(4px)}
/* Seven cities in a 3-col grid leaves a lone tile in the last row. The eighth
   tile isn't filler — it's the "your city isn't listed" route — and spanning it
   across the two free cells makes the grid land exactly (3+3+1+2 = 9 cells). */
.sa-card.sa-ask{background:color-mix(in srgb,var(--brand-soft) 50%,transparent)}
.sa-card.sa-ask h3{font-size:21px}
@media(min-width:881px){.sa-card.sa-ask{grid-column:span 2}}

/* body copy blocks */
.prose{max-width:68ch}
.prose h2{font-family:var(--serif);font-weight:400;font-size:clamp(26px,2.6vw,33px);letter-spacing:-.015em;color:var(--deep);margin-bottom:13px}
.prose p{color:var(--ink-soft);font-size:15.5px}
.prose p+p{margin-top:13px}
.prose em{font-style:italic}

/* the four-step engagement — Fraunces numerals, the gallery rail's language */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:22px;margin-top:26px}
.step{padding-top:16px;border-top:1px solid color-mix(in srgb,var(--deep) 18%,transparent)}
.step b{display:block;font-family:var(--serif);font-weight:300;font-size:38px;line-height:.95;letter-spacing:-.02em;color:color-mix(in srgb,var(--deep) 26%,transparent)}
.step h3{font-family:var(--serif);font-weight:500;font-size:19px;color:var(--deep);margin:10px 0 6px}
.step p{font-size:14px;color:var(--ink-soft)}

/* adjacent communities — named, but never given a page of their own */
.sa-tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
.sa-tag{font-family:var(--mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-soft);
background:color-mix(in srgb,var(--surface) 55%,transparent);border:1px solid color-mix(in srgb,#fff 60%,var(--hairline));
border-radius:999px;padding:7px 13px;box-shadow:inset 0 1px 0 rgba(255,255,255,.7)}

/* three photos read as one row on desktop; 2+1 on a phone leaves a hole, so
   the strip goes single-file where the 9-up homepage grid goes two-up */
@media(max-width:880px){.sa-gal{grid-template-columns:1fr}}

/* the book panel without the form — one column, CTAs instead of inputs */
.book.solo{grid-template-columns:1fr}
.book.solo .book-say{max-width:54ch}
.book-cta{margin-top:24px;display:flex;gap:12px;flex-wrap:wrap}

/* the quiet footer nav line (service areas / gallery) */
.foot-nav{margin-top:14px}
.foot-nav a{border-bottom:1px solid rgba(244,234,210,.3);padding-bottom:2px}
.foot-nav a:hover{border-bottom-color:var(--cream)}

@media(max-width:880px){
.pagehead{margin-top:104px}
.sa-grid{grid-template-columns:1fr 1fr}
.steps{grid-template-columns:1fr 1fr;gap:20px}
.sa-hero{aspect-ratio:16/10}
.sa-facts{grid-template-columns:repeat(2,1fr);gap:14px 24px;padding:16px 18px}
.lede{font-size:16px}
}
@media(max-width:560px){
.sa-grid,.steps{grid-template-columns:1fr}
}
