/* Directstay.guru — suburb/area page bundle. GENERATED, do not hand-edit.
   Rebuild:  node scripts/build-area-css.mjs
   Source order is the exact <link> order the suburb template used to emit, so
   the cascade is unchanged:
     area-pages-base.css
     area-pages-shell.css
     area-pages-wa.css
     area-pages-hero-film.css
     area-pages-crm-ui.css
     area-pages-crm-spotlight.css
     area-pages-options.css
   Region overlay css/area-pages-au-east.css still loads separately (1KB, only
   on the 2,194 AU-east pages) so the big bundle stays one shared cache entry. */
@import url("https://api.fontshare.com/v2/css?f[]=switzer@400,500,600,700,800&display=swap");

/* ==== area-pages-base.css ======================================= */
/* Directstay.guru shared chapter system */


:root,
html{
  min-height:100dvh;
  background:var(--cloud);
}

:root{
  --navy:#4c1d95;
  --navy-2:#5b21b6;
  --teal:#7c3aed;
  --teal-dark:#6d28d9;
  --violet-mid:oklch(74% .12 294);
  --violet-bright:oklch(64% .2 294);
  --amber:oklch(80% .17 76);
  --amber-soft:oklch(90% .09 76);
  --signal-yellow:#f5ff63;
  --signal-blue:#01b2fd;
  --cloud:#f3f3f5;
  --white:oklch(100% 0 0);
  --mist:#f2f1f3;
  --ink:#19171c;
  --muted:#5d5962;
  --line:rgb(76 29 149 / .14);
  --ease:cubic-bezier(.22,1,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
  --sans:"Switzer",Avenir Next,Avenir,Helvetica Neue,sans-serif;
  --max:1344px;
  /* The widest the page canvas is ever allowed to get. The hero was tuned
     with clamps that all top out around a 1630px viewport, so past that it
     froze while the content column kept centring, and the two drifted apart.
     Stages cap here and centre instead. 1920 is the ceiling the site was
     designed to, so no stage moves at or below it. */
  --canvas:1920px;
  --gutter:48px;
  --header-h:92px;
  --z-header:100;
  --z-menu:110;
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;
  min-height:100dvh;
  color:var(--ink);
  background:var(--cloud);
  font-family:"Switzer",Avenir Next,Avenir,Helvetica Neue,sans-serif;
  font-size:17px;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
  transition:background-color .4s var(--ease),color .4s var(--ease);
}
body[data-theme="cloud"]{background:var(--cloud)}
body[data-theme="mist"]{background:var(--mist)}
body[data-theme="amber"]{background:var(--violet-mid)}
body[data-theme="navy"]{background:var(--navy);color:var(--cloud)}
body[data-theme="teal"]{background:var(--teal);color:var(--navy)}
body.menu-open{overflow:hidden}

img,svg,video{display:block;max-width:100%}
button,input{font:inherit}
button,a{-webkit-tap-highlight-color:transparent}
a{color:inherit}
p{margin:0}
h1,h2,h3,h4{
  margin:0;
  font-family:var(--sans);
  font-weight:700;
  letter-spacing:-.04em;
  line-height:.96;
  text-wrap:balance;
}
h1{font-size:clamp(3.5rem,7vw,6rem)}
h2{font-size:clamp(3.2rem,7vw,6rem)}
h3{font-size:clamp(1.6rem,2.4vw,2.2rem)}
p{max-width:70ch;text-wrap:pretty}

a:focus-visible,button:focus-visible,input:focus-visible,summary:focus-visible,.rail-viewport:focus-visible{
  outline:3px solid var(--amber);
  outline-offset:3px;
}

.btn{
  display:inline-flex;
  min-height:52px;
  align-items:center;
  justify-content:center;
  border:0;
  border-radius:999px;
  padding:13px 24px;
  font-size:15px;
  font-weight:700;
  text-decoration:none;
  transition:transform .4s var(--ease),background-color .4s var(--ease),color .4s var(--ease);
}
.btn:hover{transform:scale(.985)}
.btn-primary{background:var(--teal);color:var(--white)}
.btn-primary:hover{background:var(--teal-dark)}
.btn-brass{background:var(--teal);color:var(--white)}
.btn-brass:hover{background:var(--teal-dark)}
.btn-quiet{background:rgba(16,37,60,.07);color:var(--ink)}
.btn-quiet:hover{background:rgba(16,37,60,.12)}
.btn-outline{border:1px solid var(--navy);background:transparent;color:var(--navy)}
.btn-outline:hover{background:var(--navy);color:var(--white)}
.btn-dark{background:var(--navy);color:var(--white)}
.btn-light{background:var(--cloud);color:var(--navy)}
.btn-large{min-height:64px;padding-inline:34px;font-size:17px}

/* floating header */
.site-header{
  position:fixed;
  inset:0 0 auto;
  height:var(--header-h);
  z-index:var(--z-header);
  padding:24px 48px 8px;
  pointer-events:none;
}
.nav-shell{
  width:min(100%,var(--max));
  height:60px;
  margin:auto;
  padding:4px 6px 4px 16px;
  border-radius:999px;
  display:flex;
  align-items:center;
  gap:18px;
  color:var(--ink);
  background:rgba(255,255,255,.91);
  box-shadow:0 6px 8px rgba(14,31,46,.1);
  backdrop-filter:blur(24px);
  pointer-events:auto;
  transition:background-color .4s var(--ease),color .4s var(--ease),box-shadow .4s var(--ease);
}
body[data-theme="navy"] .nav-shell{
  color:var(--cloud);
  background:rgba(24,50,70,.92);
  box-shadow:0 6px 8px rgba(0,0,0,.16);
}
.brand{
  flex:0 0 auto;
  display:flex;
  align-items:center;
  gap:9px;
  color:inherit;
  text-decoration:none;
  font-family:var(--sans);
  font-size:20px;
  font-weight:800;
  letter-spacing:-.035em;
}
.brand img{width:34px;height:34px;border-radius:22%;object-fit:cover}
.brand .wordmark span{color:var(--teal)}
body[data-theme="navy"] .brand .wordmark span{color:var(--amber)}
.nav-center{
  flex:1;
  display:flex;
  justify-content:center;
  align-items:center;
  gap:4px;
}
.nav-center>a,.nav-group>summary{
  min-height:44px;
  padding:0 16px;
  border-radius:999px;
  display:flex;
  align-items:center;
  gap:7px;
  color:inherit;
  text-decoration:none;
  list-style:none;
  font-size:14px;
  font-weight:600;
  cursor:pointer;
  transition:background-color .35s var(--ease);
}
.nav-center>a:hover,.nav-group>summary:hover,.nav-group[open]>summary{background:var(--mist)}
body[data-theme="navy"] .nav-center>a:hover,
body[data-theme="navy"] .nav-group>summary:hover,
body[data-theme="navy"] .nav-group[open]>summary{background:rgba(255,255,255,.11)}
.nav-group{position:relative}
.nav-group>summary::-webkit-details-marker{display:none}
.nav-dropdown{
  position:absolute;
  top:60px;
  left:50%;
  width:270px;
  padding:10px;
  border-radius:16px;
  background:var(--white);
  color:var(--ink);
  box-shadow:0 8px 8px rgba(14,31,46,.12);
  transform:translateX(-50%);
}
.nav-dropdown::before{content:"";position:absolute;inset:-16px 0 auto;height:16px}
.nav-dropdown a{
  display:flex;
  flex-direction:column;
  padding:12px 14px;
  border-radius:10px;
  text-decoration:none;
  transition:background-color .3s var(--ease);
}
.nav-dropdown a:hover{background:var(--mist)}
.nav-dropdown strong{font-size:14px}
.nav-dropdown small{font-size:11px;color:var(--muted);margin-top:2px}
.nav-dropdown--locations{width:210px}
.nav-dropdown--locations a{font-size:14px;font-weight:600}
.nav-actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}
.nav-cta{
  min-height:48px;
  display:flex;
  align-items:center;
  padding:0 20px;
  border-radius:999px;
  background:var(--teal);
  color:var(--white);
  text-decoration:none;
  font-size:14px;
  font-weight:700;
  transition:transform .4s var(--ease),background-color .4s var(--ease);
}
.nav-cta:hover{transform:scale(.985);background:var(--teal-dark)}
body[data-theme="navy"] .nav-cta{background:var(--cloud);color:var(--navy)}
.nav-toggle{
  display:none;
  width:48px;
  height:48px;
  border:0;
  border-radius:50%;
  background:rgba(16,37,60,.07);
  position:relative;
  cursor:pointer;
}
.nav-toggle span{
  position:absolute;
  left:15px;
  width:18px;
  height:2px;
  border-radius:2px;
  background:currentColor;
  transition:transform .35s var(--ease),top .35s var(--ease);
}
.nav-toggle span:first-child{top:20px}
.nav-toggle span:last-child{top:27px}
.nav-toggle[aria-expanded="true"] span:first-child{top:24px;transform:rotate(45deg)}
.nav-toggle[aria-expanded="true"] span:last-child{top:24px;transform:rotate(-45deg)}
.mobile-menu,.nav-scrim{display:none}

/* hero level selection */
/* white, not cloud: the grey used to cut hard to the white section below, which
   made the illuminating headline read as its own section. One canvas from the
   hero through the showreel; grey is reserved for the places band. */
.story-hero{padding:94.14px var(--gutter) 74.88px;background:var(--white)}
.hero-levels{
  position:relative;
  width:min(100%,var(--max));
  margin:0 auto;
}
.level-track{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:14px;
  perspective:1400px;
}
.level-card{
  position:relative;
  height:clamp(360px,48vh,500px);
  max-height:500px;
  overflow:hidden;
  border-radius:14px;
  color:var(--white);
  text-decoration:none;
  background:oklch(12% 0 0);
  transform-origin:50% 100%;
  isolation:isolate;
  scroll-snap-align:start;
  will-change:transform,opacity;
}
.level-card>img,.level-card>video,.level-card>.level-card-art{
  width:100%;
  height:100%;
  object-fit:cover;
  transition:transform .8s var(--ease);
}
.level-card:hover>img,.level-card:hover>video,.level-card:focus-visible>img,.level-card:focus-visible>video{transform:scale(1.025)}
.level-card--elite>img{object-position:62% center}
.level-card>video{display:block}
.level-card-art{position:absolute;inset:0;display:block;overflow:hidden}
.growth-art{background:#e8edf0}
.mini-site{position:absolute;inset:24px 20px 152px;overflow:hidden;border-radius:9px;background:#fff;box-shadow:0 6px 8px rgb(18 28 36 / .12)}
.mini-browser-bar{height:30px;padding:0 9px;display:flex;align-items:center;gap:4px;background:#f0f2f3}
.mini-browser-bar i{width:5px;height:5px;border-radius:50%;background:#bdc6cb}
.mini-browser-bar b{margin-left:6px;color:#59676f;font-size:7px;font-style:normal;font-weight:600}
.mini-site-photo{height:calc(100% - 30px);padding:24px 18px;display:flex;flex-direction:column;justify-content:flex-end;background:linear-gradient(180deg,transparent,rgb(9 20 28 / .72)),url("../public/img/gallery-lakefront-living.jpg") center/cover;color:#fff}
.mini-site-photo small{font-size:8px;font-weight:700;letter-spacing:.08em}
.mini-site-photo strong{max-width:170px;margin:7px 0 12px;font-family:Georgia,serif;font-size:22px;line-height:.95}
.mini-site-photo em{align-self:flex-start;padding:6px 9px;border-radius:999px;background:#fff;color:#17242d;font-size:7px;font-style:normal;font-weight:700}
.mini-profile{position:absolute;right:18px;bottom:126px;width:calc(100% - 36px);padding:13px;display:flex;gap:10px;border-radius:9px;background:#fff;color:#17242d;box-shadow:0 6px 8px rgb(18 28 36 / .16)}
.mini-profile>b{width:25px;height:25px;display:grid;place-items:center;border-radius:50%;background:#4285f4;color:#fff;font-size:12px}
.mini-profile>span{min-width:0;display:flex;flex-direction:column}
.mini-profile strong{font-size:10px}
.mini-profile small{font-size:7px;color:#59676f}
.mini-profile em{margin-top:7px;color:#2868c7;font-size:7px;font-style:normal;font-weight:700}
.scale-art{padding:26px 20px;background:#14212a;color:#eaf0f3}
.scale-label{display:block;margin-bottom:18px;font-size:9px;font-weight:700;letter-spacing:.08em;text-transform:uppercase}
.scale-flow{display:flex;flex-direction:column;gap:8px}
.scale-flow i{padding:10px 11px;display:flex;justify-content:space-between;border-radius:8px;background:#22333e;font-style:normal;animation:workflow-step 6s var(--ease) infinite}
.scale-flow i:nth-child(2){animation-delay:1.2s}.scale-flow i:nth-child(3){animation-delay:2.4s}.scale-flow i:nth-child(4){animation-delay:3.6s}
.scale-flow b{font-size:9px}.scale-flow small{font-size:8px;color:#9fb0ba}
.scale-message{position:absolute;left:20px;right:20px;bottom:80px;padding:12px;border-radius:8px;background:#dff4e8;color:#155b38;font-size:8px;font-weight:700}
.elite-art{background:#101a21}
.elite-art::before{content:"";position:absolute;inset:12%;border:1px solid #3b4c56;border-radius:50%}
.elite-core{position:absolute;left:50%;top:42%;width:66px;height:66px;padding:8px;transform:translate(-50%,-50%);border-radius:14px;background:#fff;box-shadow:0 0 0 9px rgb(124 58 237 / .14)}
.elite-core img{width:100%;height:100%;border-radius:10px}
.elite-node{position:absolute;padding:8px 10px;border-radius:999px;background:#22313a;color:#eef2f4;font-size:8px;font-weight:700}
.elite-node--site{left:12%;top:20%}.elite-node--search{right:10%;top:21%}.elite-node--guests{left:10%;top:56%}.elite-node--automation{right:7%;top:57%}
.elite-path{position:absolute;left:50%;top:42%;width:5px;height:5px;border-radius:50%;background:#65c18c;box-shadow:0 0 0 6px rgb(101 193 140 / .15);animation:ecosystem-dot 4.8s linear infinite}
.elite-path--two{animation-delay:2.4s}
.level-card:focus-visible{outline-offset:-4px}
.level-card-shade{
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,oklch(12% 0 0 / 0) 58%,oklch(12% 0 0 / .36) 100%);
}
.level-card-copy{
  position:absolute;
  z-index:1;
  inset:0;
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  justify-content:flex-end;
  padding:clamp(22px,2.5vw,34px);
}
.service-pill{
  display:inline-flex;
  width:100%;
  max-width:100%;
  height:72px;
  align-items:center;
  justify-content:flex-start;
  padding:11px 17px 12px;
  border-radius:999px;
  background:var(--card-accent);
  color:var(--ink);
  font-family:var(--sans);
  font-size:clamp(17px,1.55vw,22px);
  font-weight:750;
  line-height:1.08;
  letter-spacing:-.025em;
  text-wrap:balance;
  transition:transform .3s var(--ease),background-color .3s var(--ease);
}
.level-card--entry{--card-accent:var(--white)}
.level-card--growth{--card-accent:var(--signal-blue)}
.level-card--scale{--card-accent:var(--teal)}
.level-card--elite{--card-accent:var(--signal-yellow)}
.level-card--scale .service-pill{color:var(--white)}
.level-card:hover .service-pill,.level-card:focus-visible .service-pill{transform:translateY(-3px)}
.level-swipe-cue{display:none}
.hero-copy{max-width:1280px;margin:0 auto;text-align:center;padding:0 24px 56px}
.hero-copy h1{color:var(--navy);font-size:clamp(3.5rem,5.6vw,5.25rem)}

/* level scroll story */
.level-story{padding:75.47px var(--gutter) 81.12px;background:var(--white);scroll-margin-top:var(--header-h)}
.level-story-intro{
  width:min(100%,var(--max));
  margin:0 auto 70.2px;
  display:grid;
  grid-template-columns:1.15fr .75fr;
  align-items:end;
  gap:80px;
}
.level-story-intro h2{max-width:800px;color:var(--navy);font-size:clamp(3.5rem,6vw,5.75rem)}
.level-story-intro p{max-width:540px;color:var(--muted);font-size:clamp(18px,2vw,23px);line-height:1.45}
.level-story-stage{width:min(100%,var(--max));margin:auto;display:grid;grid-template-columns:minmax(520px,1fr) minmax(360px,.78fr);gap:clamp(64px,7vw,118px)}
.story-visual-column{position:sticky;top:116px;align-self:start}
.story-visual-stack{position:relative;height:min(70vh,650px);min-height:560px}
.story-visual{
  position:absolute;
  inset:0;
  overflow:hidden;
  border-radius:14px;
  background:#111a20;
  opacity:0;
  transform:translateY(28px) scale(.965);
  transform-origin:center bottom;
  pointer-events:none;
  transition:opacity .42s var(--ease),transform .48s var(--ease);
  box-shadow:0 8px 8px rgb(25 18 40 / .1);
}
.story-visual.is-active{z-index:4;opacity:1;transform:none;pointer-events:auto}
.story-visual.is-before{z-index:2;opacity:.14;transform:translateY(-28px) scale(.94)}
.story-visual.is-after{z-index:3;opacity:.22;transform:translateY(20px) scale(.975)}
.story-visual--entry video{width:100%;height:100%;object-fit:cover}
.story-visual--entry::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 48%,rgb(8 16 22 / .88) 100%)}
.story-visual-caption{position:absolute;z-index:1;left:30px;right:30px;bottom:28px;color:#fff}
.story-visual-caption b{display:block;margin-bottom:8px;color:var(--amber);font-size:13px;text-transform:uppercase}
.story-visual-caption strong{font-family:var(--sans);font-size:clamp(30px,3vw,44px);font-weight:500}
.story-index{display:flex;justify-content:space-between;gap:10px;padding-top:18px}
.story-index span{color:#998eaa;font-size:12px;font-weight:700;transition:color .28s var(--ease)}
.story-index span.is-active{color:var(--teal)}
.story-step{min-height:78vh;padding:74.88px 0;display:flex;flex-direction:column;justify-content:center;opacity:.38;transform:translateY(18px);transition:opacity .35s var(--ease),transform .4s var(--ease);scroll-margin-top:calc(var(--header-h) + 28px)}
.story-step.is-active{opacity:1;transform:none}
.story-step>span{margin-bottom:18px;color:var(--teal);font-size:14px;font-weight:700}
.story-step h3{max-width:590px;color:var(--navy);font-size:clamp(2.6rem,4vw,4.8rem)}
.story-step>p{margin-top:24px;color:var(--muted);font-size:18px;line-height:1.55}
.story-step ul{margin:28px 0 0;padding:0;list-style:none}
.story-step li{padding:12px 0;border-bottom:1px solid var(--line);color:var(--ink);font-size:15px}
.story-link{align-self:flex-start;margin-top:24px;color:var(--teal-dark);font-weight:700;text-decoration:none}
.story-promise{width:min(100%,var(--max));margin:66.12px auto 0;padding:34px 0 0;display:flex;align-items:center;justify-content:space-between;gap:28px;border-top:1px solid var(--line)}
.story-promise p{color:var(--ink);font-size:18px;font-weight:600}
.story-visual--growth{background:#e7ecef}
.growth-browser{position:absolute;left:26px;top:28px;width:78%;height:82%;overflow:hidden;border-radius:12px;background:#fff;box-shadow:0 8px 8px rgb(25 36 44 / .14)}
.growth-browser-bar{height:38px;padding:0 12px;display:flex;align-items:center;gap:6px;background:#edf0f1}
.growth-browser-bar i{width:7px;height:7px;border-radius:50%;background:#bcc5c9}
.growth-browser-bar span{margin-left:8px;color:#66747c;font-size:10px;font-weight:600}
.growth-browser iframe{width:1200px;height:760px;border:0;transform:scale(.46);transform-origin:top left;pointer-events:none;animation:growth-page-pan 8s var(--ease) infinite}
.growth-profile{position:absolute;right:24px;bottom:26px;width:282px;padding:20px;border-radius:12px;background:#fff;color:#1a2730;box-shadow:0 8px 8px rgb(25 36 44 / .16);animation:growth-profile-in 8s var(--ease) infinite}
.growth-profile-head{display:flex;align-items:center;gap:12px}
.growth-profile-head>b{width:36px;height:36px;display:grid;place-items:center;border-radius:50%;background:#4285f4;color:#fff}
.growth-profile-head>span{display:flex;flex-direction:column}.growth-profile-head strong{font-size:14px}.growth-profile-head small{color:#6b777e;font-size:10px}
.growth-stars{margin:16px 0 12px;color:#e69a18;font-size:12px}.growth-stars span{color:#59676f}
.growth-actions{display:flex;gap:7px}.growth-actions span{padding:7px 9px;border-radius:999px;background:#edf4ff;color:#2868c7;font-size:9px;font-weight:700}
.growth-profile p{margin-top:15px;color:#53616a;font-size:10px}
.story-visual--scale{padding:32px;background:#14212a}
.automation-board{height:100%;padding:28px;border-radius:12px;background:#f4f6f7;color:#1b2830}
.automation-head{display:flex;align-items:center;justify-content:space-between;padding-bottom:20px;border-bottom:1px solid #d9dfe2}
.automation-head strong{font-family:var(--sans);font-size:21px}.automation-head>span{color:#276943;font-size:11px;font-weight:700}
.automation-head i{display:inline-block;width:7px;height:7px;margin-right:5px;border-radius:50%;background:#4caf75;animation:live-pulse 1.8s ease-out infinite}
.automation-guest{margin:22px 0;padding:18px;border-radius:10px;background:#fff;box-shadow:0 4px 8px rgb(18 31 40 / .07)}
.automation-guest span{display:block;color:#7c3aed;font-size:10px;font-weight:700;text-transform:uppercase}.automation-guest strong{display:block;margin:7px 0 3px;font-size:15px}.automation-guest small{color:#69777f}
.automation-flow{display:flex;flex-direction:column;gap:10px}
.automation-flow>span{padding:13px 14px;display:grid;grid-template-columns:30px 1fr auto;align-items:center;gap:10px;border-radius:9px;background:#e8ecee;animation:automation-row 8s var(--ease) infinite}
.automation-flow>span:nth-child(2){animation-delay:1.4s}.automation-flow>span:nth-child(3){animation-delay:2.8s}.automation-flow>span:nth-child(4){animation-delay:4.2s}
.automation-flow i{width:26px;height:26px;display:grid;place-items:center;border-radius:50%;background:#fff;color:#4f6069;font-size:10px;font-style:normal;font-weight:700}
.automation-flow b{font-size:12px}.automation-flow small{color:#708089;font-size:10px}
.story-visual--elite{padding:34px;background:#101a21}
.ecosystem-map{position:relative;width:100%;height:100%;overflow:hidden;border-radius:12px;background:radial-gradient(circle at center,#1e303a 0,#121e25 54%,#0d161b 100%)}
.ecosystem-map::before,.ecosystem-map::after{content:"";position:absolute;left:50%;top:50%;border:1px solid #344650;border-radius:50%;transform:translate(-50%,-50%)}
.ecosystem-map::before{width:68%;aspect-ratio:1}.ecosystem-map::after{width:42%;aspect-ratio:1}
.ecosystem-core{position:absolute;z-index:2;left:50%;top:50%;width:190px;padding:14px;display:flex;align-items:center;gap:12px;transform:translate(-50%,-50%);border-radius:12px;background:#fff;color:#26333b;box-shadow:0 0 0 12px rgb(124 58 237 / .12)}
.ecosystem-core img{width:44px;height:44px;border-radius:10px}.ecosystem-core span{display:flex;flex-direction:column}.ecosystem-core b{font-size:13px}.ecosystem-core small{color:#65737b;font-size:10px}
.ecosystem-node{position:absolute;z-index:1;min-width:105px;padding:11px 13px;border-radius:10px;background:#203039;color:#f0f4f5;box-shadow:0 4px 8px rgb(0 0 0 / .18)}
.ecosystem-node b,.ecosystem-node small{display:block}.ecosystem-node b{font-size:12px}.ecosystem-node small{margin-top:3px;color:#9fb0b8;font-size:9px}
.ecosystem-node--film{left:8%;top:12%}.ecosystem-node--site{right:7%;top:13%}.ecosystem-node--google{right:4%;bottom:14%}.ecosystem-node--guests{left:7%;bottom:13%}.ecosystem-node--auto{left:50%;bottom:5%;transform:translateX(-50%)}
.ecosystem-pulse{position:absolute;z-index:3;left:50%;top:50%;width:8px;height:8px;border-radius:50%;background:#5bc487;box-shadow:0 0 0 7px rgb(91 196 135 / .14);animation:ecosystem-orbit 7s linear infinite}
.pricing-section{padding:84px var(--gutter);background:var(--cloud);scroll-margin-top:var(--header-h)}
.pricing-section .pricing-heading>p{margin:20px auto 0;color:var(--muted);font-size:18px}
.pricing-section .price-card:not(.price-card--featured){background:var(--white)}

/* chapter system */
.chapter-theme{transition:background-color .4s var(--ease),color .4s var(--ease)}
.story-chapter{position:relative;padding:0 var(--gutter) 86.1px;overflow:hidden}
.story-chapter[data-chapter-theme="mist"]{background:var(--mist);color:var(--ink)}
.story-chapter[data-chapter-theme="amber"]{background:var(--violet-mid);color:var(--navy);margin-top:-62.64px;padding-top:62.64px;border-radius:48px 48px 0 0}
.story-chapter[data-chapter-theme="navy"]{background:var(--navy);color:var(--cloud);margin-top:-62.64px;padding-top:62.64px;border-radius:48px 48px 0 0}
.story-chapter[data-chapter-theme="teal"]{background:var(--teal);color:var(--navy);margin-top:-62.64px;padding-top:62.64px;border-radius:48px 48px 0 0}
.chapter-heading{
  min-height:74vh;
  max-width:1160px;
  margin:auto;
  padding:86.1px 0 84px;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  text-align:center;
}
.chapter-context{margin-bottom:24px;font-size:15px;font-weight:700}
.chapter-heading h2{max-width:1100px}
.chapter-heading>p:not(.chapter-context){font-size:clamp(18px,2vw,24px);line-height:1.4;margin:28px auto 24px;max-width:700px;color:color-mix(in srgb,currentColor 72%,transparent)}
.inline-guru{
  display:inline-block;
  width:.92em;
  height:.92em;
  border-radius:22%;
  object-fit:cover;
  vertical-align:-.12em;
  margin-inline:.05em;
}
.chapter-link{
  display:inline-flex;
  min-height:44px;
  align-items:center;
  padding:0 18px;
  border-radius:999px;
  background:rgba(16,37,60,.09);
  text-decoration:none;
  font-size:14px;
  font-weight:700;
  transition:transform .35s var(--ease),background-color .35s var(--ease);
}
.chapter-link:hover{transform:scale(.985);background:rgba(16,37,60,.15)}
.story-chapter--dark .chapter-link{background:rgba(255,255,255,.12)}
.story-chapter--dark .chapter-link:hover{background:rgba(255,255,255,.2)}
.rail-block{width:min(100%,var(--max));margin:auto}
.rail-meta{display:flex;align-items:center;justify-content:space-between;gap:20px;margin-bottom:18px;font-size:14px;font-weight:700}
.rail-controls{display:flex;padding:4px;border-radius:999px;background:rgba(255,255,255,.55)}
.story-chapter--dark .rail-controls{background:rgba(255,255,255,.1)}
.rail-controls button{
  width:40px;height:40px;border:0;border-radius:50%;
  background:transparent;color:inherit;cursor:pointer;
  transition:background-color .3s var(--ease),opacity .3s;
}
.rail-controls button:hover{background:rgba(255,255,255,.7)}
.story-chapter--dark .rail-controls button:hover{background:rgba(255,255,255,.15)}
.rail-controls button:disabled{opacity:.35;cursor:default}
.rail-viewport{overflow:hidden;cursor:ew-resize;touch-action:pan-y;padding-block:2px}
.rail-track{display:flex;gap:32px;width:max-content;will-change:transform}
.feature-card,.system-card,.escape-card{
  flex:0 0 394px;
  height:527px;
  border-radius:16px;
  overflow:hidden;
  position:relative;
}
.feature-card{background:var(--navy);color:var(--white)}
.feature-card>img,.feature-card>video{width:100%;height:100%;object-fit:cover;transition:transform 1.1s var(--ease)}
.feature-card::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(14,31,46,.02) 25%,rgba(14,31,46,.94) 92%)}
.feature-card-copy{position:absolute;z-index:2;left:0;right:0;bottom:0;padding:34px}
.feature-card-copy span{display:block;margin-bottom:14px;color:var(--amber);font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.1em}
.feature-card-copy h3{font-size:34px;margin-bottom:12px}
.feature-card-copy p{font-size:15px;line-height:1.45;color:rgba(255,255,255,.76)}
.feature-card.is-playing>img{animation:art-restart .9s var(--ease)}
@keyframes art-restart{0%{transform:scale(1.045)}100%{transform:scale(1)}}
@keyframes workflow-step{0%,12%,100%{background:#22333e;transform:none}24%,40%{background:#2d5646;transform:translateX(3px)}}
@keyframes ecosystem-dot{0%{transform:translate(-88px,-80px)}25%{transform:translate(78px,-76px)}50%{transform:translate(82px,58px)}75%{transform:translate(-82px,58px)}100%{transform:translate(-88px,-80px)}}
@keyframes growth-page-pan{0%,18%,100%{transform:translateY(0) scale(.46)}48%,76%{transform:translateY(-48px) scale(.46)}}
@keyframes growth-page-pan-mobile{0%,18%,100%{transform:translateY(0) scale(.34)}48%,76%{transform:translateY(-34px) scale(.34)}}
@keyframes growth-profile-in{0%,18%,100%{opacity:.5;transform:translateY(18px)}38%,82%{opacity:1;transform:none}}
@keyframes live-pulse{0%{box-shadow:0 0 0 0 rgb(76 175 117 / .4)}75%,100%{box-shadow:0 0 0 9px rgb(76 175 117 / 0)}}
@keyframes automation-row{0%,12%,100%{background:#e8ecee;transform:none}22%,36%{background:#dff2e7;transform:translateX(4px)}}
@keyframes ecosystem-orbit{0%{transform:translate(-175px,-170px)}25%{transform:translate(175px,-165px)}50%{transform:translate(188px,150px)}75%{transform:translate(-180px,145px)}100%{transform:translate(-175px,-170px)}}

.system-card{
  display:flex;
  flex-direction:column;
  justify-content:space-between;
  padding:32px;
  background:var(--cloud);
  color:var(--navy);
}
.system-card>div:last-child h3{margin-bottom:12px}
.system-card>div:last-child p{color:var(--muted);font-size:15px}
.system-art{
  min-height:285px;
  border-radius:12px;
  background:var(--mist);
  padding:26px;
  overflow:hidden;
}
.system-art--calendar{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;align-content:center}
.system-art--calendar span{grid-column:1/-1;font-family:var(--sans);font-size:84px;line-height:1;text-align:center;color:var(--teal)}
.system-art--calendar i{height:48px;border-radius:10px;background:var(--white)}
.system-art--message{display:flex;flex-direction:column;justify-content:center;gap:10px}
.system-art--message span{align-self:flex-start;border-radius:999px;background:var(--white);padding:12px 16px;font-size:13px;font-weight:600}
.system-art--message span:nth-child(2){align-self:flex-end;background:var(--teal);color:white}
.system-art--checkout{display:flex;flex-direction:column;justify-content:center;gap:14px}
.system-art--checkout span{font-size:14px;color:var(--muted)}
.system-art--checkout strong{font-family:var(--sans);font-size:56px;line-height:1}
.system-art--checkout button{border:0;border-radius:999px;background:var(--navy);color:white;padding:13px}
.system-art--repeat{display:flex;flex-direction:column;justify-content:center;gap:18px;background:var(--amber)}
.system-art--repeat span{font-size:14px}
.system-art--repeat strong{font-family:var(--sans);font-size:38px;line-height:1.05}

/* Escape */
.escape-metric{
  width:min(100%,1000px);
  margin:0 auto 62.64px;
  display:grid;
  grid-template-columns:.55fr 1fr;
  align-items:center;
  gap:40px;
  padding:38px 42px;
  border-radius:16px;
  background:var(--navy);
  color:var(--cloud);
}
.escape-metric strong{font-family:var(--sans);font-size:clamp(4rem,8vw,7rem);line-height:.85;color:var(--amber)}
.escape-metric p{font-size:17px;color:#c8d7df}
.escape-card{height:540px;background:var(--navy);color:var(--white)}
.escape-card img{width:100%;height:100%;object-fit:cover;transition:transform 1.1s var(--ease)}
.escape-card::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(14,31,46,0) 32%,rgba(14,31,46,.96) 88%)}
.escape-card>div{position:absolute;z-index:2;left:0;right:0;bottom:0;padding:30px}
.escape-card span{display:block;color:var(--amber);font-size:13px;font-weight:700;letter-spacing:.1em;margin-bottom:12px}
.escape-card h3{font-size:34px;margin-bottom:10px}
.escape-card p{font-size:14px;color:#cfdae1}
.escape-card.is-playing img{animation:art-restart .9s var(--ease)}
.dual-track{
  width:min(100%,var(--max));
  margin:86.1px auto 0;
  display:grid;
  grid-template-columns:.9fr 1.1fr;
  gap:80px;
  align-items:start;
  padding:72px;
  border-radius:16px;
  background:var(--cloud);
}
.dual-track h2{font-size:clamp(3rem,5vw,5rem)}
.dual-track ol{list-style:none;margin:0;padding:0}
.dual-track li{display:grid;grid-template-columns:48px 1fr;gap:18px;padding:24px 0;border-bottom:1px solid var(--line)}
.dual-track li:last-child{border:0}
.dual-track li>span{width:42px;height:42px;border-radius:50%;display:grid;place-items:center;background:var(--teal);color:white;font-weight:700}
.dual-track strong{font-family:var(--sans);font-size:24px}
.dual-track li p{color:var(--muted);font-size:15px;margin-top:4px}
.pricing-block{width:min(100%,var(--max));margin:86.1px auto 0}
#pricing{scroll-margin-top:calc(var(--header-h) + 28px)}
.pricing-heading{text-align:center;max-width:900px;margin:0 auto 54px}
.pricing-heading h2{font-size:clamp(3rem,6vw,5.5rem)}
.price-row{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.price-card{
  min-height:500px;
  padding:32px;
  border-radius:16px;
  display:flex;
  flex-direction:column;
  background:var(--cloud);
  color:var(--navy);
}
.price-card>span{font-size:14px;font-weight:700}
.price-card h3{font-size:52px;margin:30px 0 10px}
.price-card>p{min-height:72px;color:var(--muted);font-size:15px}
.price-card ul{margin:24px 0 30px;padding:0;list-style:none}
.price-card li{padding:12px 0;border-bottom:1px solid var(--line);font-size:14px}
.price-card .btn{margin-top:auto}
.price-card--featured{background:var(--navy);color:var(--cloud)}
.price-card--featured>p{color:#c9d7df}
.price-card--featured li{border-color:rgba(255,255,255,.14)}
.price-card.featured{background:var(--navy);color:var(--cloud)}
.price-card.featured>p{color:#c9d7df}
.price-card .amount{font-family:var(--sans);font-size:44px;line-height:1;margin:28px 0 12px}

/* regions, faq and final */
.region-section{
  padding:86.1px var(--gutter);
  background:var(--cloud);
  display:grid;
  grid-template-columns:.8fr 1.2fr;
  gap:80px;
}
.region-copy h2{font-size:clamp(3rem,5vw,5rem)}
.region-links{display:flex;flex-direction:column}
.region-links a{
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:26px 4px;border-bottom:1px solid var(--line);text-decoration:none;
  transition:color .3s var(--ease),transform .3s var(--ease);
}
.region-links a:hover{color:var(--teal);transform:translateX(6px)}
.region-links span{font-family:var(--sans);font-size:30px}
.region-links small{color:var(--muted)}
.faq-section{padding:86.1px var(--gutter);background:var(--cloud);display:grid;grid-template-columns:.7fr 1.3fr;gap:80px;align-items:start}
.faq-heading h2{font-size:clamp(3rem,5vw,5rem)}
/* The heading rides down beside a long answer set so the question group keeps its
   context on screen. 148px is measured clearance for the 129px resting header:
   --header-h holds its collapsed height, so binding to the token slides the h2 under. */
.faq-heading{position:sticky;top:148px}
/* The Questions nav panel deep-links to these rows. Without scroll-margin the anchor
   jump parks the row at viewport top 0, underneath the 129px fixed header. */
.faq-list details{border-bottom:1px solid var(--line);scroll-margin-top:170px}
.faq-list details:first-of-type{border-top:1px solid var(--line)}
.faq-list summary{
  list-style:none;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:28px;
  padding:30px 0;
  font-family:var(--sans);
  font-size:clamp(19px,1.6vw,26px);
  font-weight:600;
  letter-spacing:-.028em;
  line-height:1.22;
  text-wrap:balance;
  color:var(--ink);
  cursor:pointer;
  transition:color .25s var(--ease);
}
.faq-list summary::-webkit-details-marker{display:none}
.faq-list details[open] summary{color:var(--teal-dark)}
@media(hover:hover){.faq-list summary:hover{color:var(--teal-dark)}}
.faq-list summary:focus-visible{outline:2px solid var(--teal);outline-offset:6px;border-radius:4px}
/* The mark is drawn, never typed, the same rule the arrows follow: a typed glyph
   renders at whatever weight the reader's OS picked for it. 4,212 generated pages
   carry a literal "+" inside this span, so the character is zeroed out here and two
   bars are drawn over it instead, which needs no page regenerated. font-size:0 and
   not color:transparent, because the bars are currentColor and would go transparent
   with it. The span keeps aria-hidden, so neither version reaches a screen reader. */
.faq-list summary span{
  position:relative;
  flex:0 0 auto;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:34px;
  height:34px;
  border:1px solid var(--line);
  border-radius:50%;
  font-size:0;
  line-height:1;
  transition:background-color .25s var(--ease),color .25s var(--ease),border-color .25s var(--ease);
}
.faq-list summary span::before,
.faq-list summary span::after{
  content:"";
  position:absolute;
  top:50%;
  left:50%;
  width:14px;
  height:2px;
  background:currentColor;
  transform:translate(-50%,-50%);
}
/* Open reads as a minus, not a rotated cross. The row is being collapsed, and a
   cross is the site's word for dismiss. */
.faq-list summary span::after{transform:translate(-50%,-50%) rotate(90deg) scaleX(1);transition:transform .35s var(--ease)}
.faq-list details[open] summary span::after{transform:translate(-50%,-50%) rotate(90deg) scaleX(0)}
@media(hover:hover){.faq-list summary:hover span{border-color:var(--teal)}}
.faq-list details[open] summary span{background:var(--navy);border-color:var(--navy);color:var(--cloud)}
.faq-list details p{
  max-width:70ch;
  padding:0 62px 32px 0;
  color:var(--muted);
  font-size:17px;
  line-height:1.6;
}
.final-cta{
  min-height:58vh;
  padding:74.88px var(--gutter);
  background:var(--mist);
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  text-align:center;
}
.final-cta>p{font-size:clamp(24px,3vw,38px);color:var(--muted)}
.final-cta h2{max-width:1050px;margin:18px auto 40px}
.final-cta small{max-width:720px;margin-top:28px;color:rgba(16,37,60,.67)}

/* footer */
.site-footer{padding:32px 48px 24px;background:var(--cloud);color:var(--navy)}
.footer-panel{padding:40px;border-radius:16px;background:var(--white)}
.footer-top{display:grid;grid-template-columns:.8fr 1.2fr;gap:56px;align-items:start;padding-bottom:44px}
.footer-top>*{min-width:0}
.footer-identity{display:flex;align-items:center;gap:24px}
.footer-identity img{width:108px;height:108px;object-fit:contain}
.footer-identity strong{display:block;font-family:var(--sans);font-size:38px}
.footer-identity span{color:var(--muted)}
.newsletter{padding:26px;border-radius:16px;background:var(--mist)}
.newsletter>p{font-size:16px;color:var(--muted)}
.newsletter-form label{display:block;margin:24px 0 4px;font-size:13px;font-weight:700}
.newsletter-line{display:flex;align-items:end;gap:14px;border-bottom:2px solid var(--navy)}
.newsletter input{flex:1;min-width:0;padding:12px 0;border:0;background:transparent;color:var(--navy);font-family:var(--sans);font-size:clamp(28px,4vw,58px);line-height:1}
.newsletter input::placeholder{color:#6b7d89;opacity:1}
.newsletter input:focus{outline:0}
.newsletter button{flex:0 0 auto;margin-bottom:9px;border:0;border-radius:999px;background:var(--teal);color:white;padding:13px 20px;font-weight:700;cursor:pointer;transition:transform .35s var(--ease),background-color .35s var(--ease)}
.newsletter button:hover{transform:scale(.985);background:var(--navy)}
.newsletter button:disabled{opacity:.6;cursor:wait}
.form-status{display:block;margin-top:14px;color:var(--muted)}
.form-status:empty{display:none}
.form-status.is-error{color:#a12c2c}.form-status.is-success{color:#0c7560}
.footer-links{display:grid;grid-template-columns:1fr 1fr 1.2fr;gap:44px;padding-top:34px;border-top:1px solid var(--line)}
.footer-links h3{font-family:var(--sans);font-size:13px;letter-spacing:0;color:#71828d;margin-bottom:20px}
.footer-links a,.footer-links>div>span{display:block;width:max-content;max-width:100%;margin:11px 0;text-decoration:none;font-size:14px}
.footer-links a:hover{color:#75848d}
.status-pill{padding:8px 12px;border-radius:999px;background:#e9ece9}
.status-pill i{display:inline-block;width:6px;height:6px;margin-right:7px;border-radius:50%;background:#24a879}
.footer-legal{display:flex;justify-content:space-between;gap:28px;padding:24px 6px 0;font-size:12px;color:rgba(16,37,60,.7)}

/* shared inner pages */
.page-hero{padding:97.58px var(--gutter) 69.6px;text-align:center;background:var(--cloud)}
.page-hero .eyebrow,.section-head .eyebrow{margin:0 auto 20px;font-size:14px;font-weight:700;color:var(--teal)}
.page-hero h1{max-width:1050px;margin:auto}
.page-hero>p:not(.eyebrow){max-width:780px;margin:24px auto 0;font-size:20px;color:var(--muted)}
.page-hero .hero-actions{margin-top:30px}
.wrap{width:min(100%,var(--max));margin:auto;padding-inline:var(--gutter)}
main>section:not(.hero-film):not(.story-hero):not(.film-stage):not(.service-stack):not(.story-chapter):not(.region-section):not(.faq-section):not(.package-section):not(.level-story):not(.showreel-section):not(.pricing-section):not(.final-cta):not(.page-hero):not(.place-hero):not(.place-opportunity):not(.place-build):not(.place-pricing):not(.place-faq):not(.place-next):not(.places-hero):not(.places-directory):not(.service-ownership):not(.contact-hero):not(.ab-open):not(.ab-position):not(.ab-moves):not(.ab-people):not(.ab-practice):not(.ab-close):not(.inbox-converge):not(.price-flip):not(.crm-lede):not(.slabwall):not(.slab):not(.crm-closer){padding:78px 0;background:var(--cloud)}
.mini-hero-panel{width:min(100%,var(--max));margin:auto;height:min(60vh,620px);border-radius:16px;overflow:hidden;background:var(--navy)}
.mini-hero-panel video{width:100%;height:100%;object-fit:cover}
.band-muted{background:var(--mist)!important}
.band-dark{background:var(--navy)!important;color:var(--cloud)}
.section-head{text-align:center;max-width:900px;margin:0 auto 54px}
.section-head h2{font-size:clamp(3rem,5vw,5rem)}
.section-head>p:not(.eyebrow){max-width:720px;margin:22px auto 0;color:var(--muted)}
.band-dark .section-head>p:not(.eyebrow){color:#c6d4dc}
.card-grid,.price-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.card,.stat,.faq-item{
  border-radius:16px;
  padding:30px;
  background:var(--white);
}
.card .num,.stat .num{margin-bottom:18px;font-weight:700;color:var(--teal)}
.card h3,.faq-item h3{margin-bottom:12px}
.card p,.faq-item p,.stat small{color:var(--muted);font-size:15px}
.disclosure{max-width:800px;margin:30px auto 0;color:#c6d4dc;text-align:center;font-size:14px}
.cta-band{padding:72px;border-radius:16px;background:var(--violet-mid);text-align:center}
.cta-band h2{font-size:clamp(3rem,5vw,5rem)}
.cta-band p{margin:20px auto 28px;max-width:680px}
.loc-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.loc-chip{padding:22px;border-radius:12px;background:var(--white);text-align:center;text-decoration:none;font-weight:700}
.footer-brand{font-family:var(--sans);font-size:28px}

@media(max-width:1180px){
  :root{--gutter:32px}
  .site-header{padding-inline:32px}
  .nav-center{gap:0}
  .nav-center>a,.nav-group>summary{padding-inline:12px;font-size:17px}
  .nav-cta{padding-inline:16px}
  .rail-track{gap:24px}
  .feature-card,.system-card,.escape-card{flex-basis:360px}
}

@media(max-width:1050px){
  :root{--header-h:82px}
  .site-header{height:82px;padding:20px 20px 0}
  .nav-shell{height:62px;padding-left:10px}
  .brand .wordmark,.nav-center{display:none}
  .brand img{width:44px;height:44px}
  .nav-toggle{display:block}
  .nav-cta{min-height:48px}
  .mobile-menu{
    display:block;
    position:fixed;
    z-index:var(--z-menu);
    top:90px;
    right:16px;
    width:min(400px,calc(100vw - 32px));
    height:calc(100dvh - 116px);
    border-radius:16px;
    overflow:auto;
    background:var(--cloud);
    color:var(--navy);
    opacity:0;
    visibility:hidden;
    transform:translateY(16px) scale(.92);
    transform-origin:top right;
    pointer-events:none;
    transition:opacity .4s var(--ease),transform .4s var(--ease),visibility .4s;
  }
  .mobile-menu.is-open{opacity:1;visibility:visible;transform:none;pointer-events:auto}
  .mobile-menu-inner{padding:24px}
  .mobile-menu-label{padding:10px 12px 18px;color:var(--muted);font-size:13px}
  .mobile-menu-inner>a{display:flex;align-items:center;min-height:58px;padding:0 12px;border-bottom:1px solid var(--line);font-family:var(--sans);font-size:24px;text-decoration:none}
  .mobile-locations{display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:18px 0}
  .mobile-locations a{padding:10px 12px;border-radius:999px;background:var(--mist);text-align:center;text-decoration:none;font-size:12px;font-weight:700}
  .mobile-menu-inner .mobile-menu-cta{justify-content:center;border:0;border-radius:999px;background:var(--teal);color:white;font-family:var(--sans);font-size:15px;font-weight:700}
  .nav-scrim{
    display:block;
    position:fixed;
    z-index:calc(var(--z-menu) - 1);
    inset:0;
    border:0;
    background:rgba(7,23,37,.58);
    opacity:0;
    visibility:hidden;
    pointer-events:none;
    transition:opacity .4s var(--ease),visibility .4s;
  }
  .nav-scrim.is-open{opacity:1;visibility:visible;pointer-events:auto}
  .level-track{grid-template-columns:repeat(2,minmax(0,1fr))}
  .level-card{height:460px}
  .level-story{padding:71.76px 0}
  .level-story-intro{grid-template-columns:1fr;gap:24px;padding:0 32px;margin-bottom:52px}
  .level-story-stage{display:block}
  .story-visual-column{position:relative;top:auto}
  .story-visual-stack{
    min-height:0;
    height:auto;
    padding:0 32px 14px;
    display:flex;
    gap:16px;
    overflow-x:auto;
    scroll-snap-type:x mandatory;
    scroll-padding-inline:32px;
    scrollbar-width:none;
  }
  .story-visual-stack::-webkit-scrollbar{display:none}
  .story-visual{position:relative;inset:auto;flex:0 0 min(78vw,620px);height:560px;opacity:1;transform:none;pointer-events:auto;scroll-snap-align:start}
  .story-visual.is-before,.story-visual.is-after,.story-visual.is-active{opacity:1;transform:none}
  .story-index{display:none}
  .story-steps{padding:0 32px}
  .story-step{min-height:auto;padding:62.64px 0;opacity:1;transform:none;border-bottom:1px solid var(--line)}
  .story-step:last-child{border:0}
  .story-promise{margin:36px 32px 0;width:auto}
  .dual-track{grid-template-columns:1fr;gap:30px}
  .price-row{grid-template-columns:1fr}
  .price-card{min-height:auto}
  .price-card>p{min-height:0}
  .region-section,.faq-section{grid-template-columns:1fr;gap:54px}
  /* One column, so the heading has nothing to ride beside and would only sit
     on top of the first question. */
  .faq-heading{position:static}
  .footer-top{grid-template-columns:1fr;gap:34px}
  .footer-links{grid-template-columns:1fr 1fr}
  .card-grid,.price-grid{grid-template-columns:1fr 1fr}
}

@media(max-width:720px){
  :root{--gutter:20px}
  body{font-size:16px}
  .nav-cta{font-size:13px;padding-inline:16px}
  .story-hero{padding:79.56px 0 58px;overflow:hidden}
  .hero-levels{width:100%}
  .level-track{
    display:flex;
    gap:14px;
    width:100%;
    padding:0 20px 14px;
    overflow-x:auto;
    overscroll-behavior-inline:contain;
    scroll-snap-type:x mandatory;
    scroll-padding-inline:20px;
    scrollbar-width:none;
    -webkit-overflow-scrolling:touch;
  }
  .level-track::-webkit-scrollbar{display:none}
  .level-card{
    flex:0 0 min(78vw,330px);
    height:min(58vh,500px);
    min-height:420px;
  }
  .level-card-copy{padding:24px}
  .service-pill{height:72px;padding:10px 15px 11px;font-size:20px}
  .level-swipe-cue{
    display:flex;
    align-items:center;
    gap:9px;
    /* it was sitting 2px under the rail with 120px of dead air beneath it;
       the cue now breathes from the cards it belongs to */
    margin:18px 20px 0;
    color:var(--muted);
    font-size:12.5px;
    font-weight:600;
    letter-spacing:-.005em;
  }
  .level-swipe-cue span{font-size:inherit;color:inherit}
  .swipe-mark{
    display:block;
    flex:none;
    width:34px;
    height:16px;
    color:var(--teal);
    overflow:visible;
  }
  /* the heads drift outward and back, so the mark reads as "there is more either way"
     rather than sliding the whole glyph around */
  .swipe-mark-head{animation:swipe-mark-drift 2.6s var(--ease) infinite}
  .swipe-mark-head--r{animation-name:swipe-mark-drift-r}
  .hero-copy{padding:0 20px 38px}
  .hero-support{font-size:15px;margin-bottom:16px}
  .hero-copy h1{font-size:clamp(2.65rem,11.5vw,4rem)}
  .hero-copy>p:not(.hero-support){font-size:17px;margin-top:20px}
  .hero-actions{align-items:stretch;flex-direction:column}
  .proof-strip{padding:0 20px 55.68px;display:grid;grid-template-columns:1fr 1fr}
  .proof-strip span{padding:12px;border-right:0;border-bottom:1px solid var(--line);text-align:center;font-size:12px}
  .level-story{padding:67.86px 0}
  .level-story-intro{padding:0 20px;margin-bottom:38px}
  .level-story-intro h2{font-size:clamp(3rem,13vw,4.5rem)}
  .level-story-intro p{font-size:17px}
  .story-visual-stack{padding:0 20px 14px;scroll-padding-inline:20px}
  .story-visual{flex-basis:calc(100vw - 40px);height:480px}
  .story-visual--scale,.story-visual--elite{padding:20px}
  .growth-browser{left:16px;top:18px;width:82%;height:76%}
  .growth-browser iframe{transform:scale(.34);animation-name:growth-page-pan-mobile}
  .growth-profile{right:16px;bottom:18px;width:225px;padding:14px}
  .ecosystem-core{width:150px}.ecosystem-node{min-width:88px;padding:9px}.ecosystem-node--auto{bottom:3%}
  .story-steps{padding:0 20px}
  .story-step{padding:58px 0}
  .story-step h3{font-size:clamp(2.7rem,12vw,4rem)}
  .story-promise{margin:28px 20px 0;align-items:flex-start;flex-direction:column}
  .pricing-section{padding:73.08px 20px}
  .story-chapter{padding:0 20px 74.88px}
  .story-chapter[data-chapter-theme]{margin-top:-32px;padding-top:32px;border-radius:28px 28px 0 0}
  .story-chapter:first-of-type{margin-top:0}
  .chapter-heading{min-height:68vh;padding:87.36px 0 74.82px}
  .chapter-heading h2{font-size:clamp(2.8rem,13vw,4.6rem)}
  .chapter-heading>p:not(.chapter-context){font-size:17px;margin-top:22px}
  .chapter-context{margin-bottom:18px}
  .rail-track{gap:16px}
  .feature-card,.system-card,.escape-card{flex-basis:calc(100vw - 40px);height:468px}
  .feature-card-copy,.escape-card>div{padding:28px}
  .feature-card-copy h3,.escape-card h3{font-size:30px}
  .system-card{padding:26px}
  .system-art{min-height:240px}
  .escape-metric{grid-template-columns:1fr;gap:18px;padding:28px;margin-bottom:52px}
  .escape-metric strong{font-size:70px}
  .dual-track{margin-top:74.88px;padding:34px 24px}
  .dual-track h2{font-size:46px}
  .pricing-block{margin-top:74.88px}
  .pricing-heading h2{font-size:46px}
  .price-card{padding:28px}
  .price-card h3{font-size:44px;margin-top:30px}
  .region-section,.faq-section{padding:78px 20px}
  .region-copy h2,.faq-heading h2{font-size:46px}
  .region-links span{font-size:25px}
  .region-links small{display:none}
  .final-cta{min-height:55vh;padding:73.08px 20px}
  .final-cta h2{font-size:clamp(3rem,14vw,5rem)}
  .site-footer{padding:20px 20px 18px}
  .footer-panel{padding:28px 22px}
  .footer-identity{align-items:center;gap:14px;min-width:0}
  .footer-identity img{width:76px;height:76px;flex:0 0 auto}
  .footer-identity strong{font-size:28px}
  .footer-identity>div{min-width:0}
  .newsletter{min-width:0}
  .newsletter{padding:24px 18px}
  .newsletter-line{align-items:stretch;flex-direction:column;border:0}
  .newsletter input{font-size:32px;border-bottom:2px solid var(--navy);padding:12px 0}
  .newsletter button{margin:0;align-self:flex-start}
  .footer-links{grid-template-columns:1fr;gap:26px}
  .footer-legal{flex-direction:column;gap:8px}
  .page-hero{padding:74.62px 20px 52.2px}
  .page-hero h1{font-size:46px}
  .page-hero>p:not(.eyebrow){font-size:17px}
  main>section:not(.hero-film):not(.story-hero):not(.film-stage):not(.service-stack):not(.story-chapter):not(.region-section):not(.faq-section):not(.package-section):not(.level-story):not(.showreel-section):not(.pricing-section):not(.final-cta):not(.page-hero):not(.place-hero):not(.place-opportunity):not(.place-build):not(.place-pricing):not(.place-faq):not(.place-next):not(.places-hero):not(.places-directory):not(.service-ownership):not(.contact-hero):not(.ab-open):not(.ab-position):not(.ab-moves):not(.ab-people):not(.ab-practice):not(.ab-close):not(.inbox-converge):not(.price-flip):not(.crm-lede):not(.slabwall):not(.slab):not(.crm-closer){padding:62.64px 0}
  .wrap{padding-inline:20px}
  .mini-hero-panel{height:50vh;border-radius:12px}
  .card-grid,.price-grid,.loc-grid{grid-template-columns:1fr}
  .cta-band{padding:50px 24px}
}

@media(max-width:390px){
  .nav-cta{display:none}
  .nav-shell{justify-content:space-between}
  .proof-strip{grid-template-columns:1fr}
  .feature-card,.system-card,.escape-card{flex-basis:calc(100vw - 40px)}
}

@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
  .level-card{transform:none!important;opacity:1!important}
  .rail-track{will-change:auto}
}

/* Shared brand typography */
.brand,.level-card-copy strong,.story-visual-caption strong,
.story-step h3,.pricing-heading h2,.price-card h3{
  font-family:var(--sans);
}
.brand{letter-spacing:-.04em}

.hero-copy h1,.level-story-intro h2{color:var(--ink)}
.hero-highlight{
  display:inline-block;
  white-space:nowrap;
  text-decoration-line:underline;
  text-decoration-color:var(--teal);
  text-decoration-thickness:.09em;
  text-underline-offset:.11em;
  text-decoration-skip-ink:none;
}

.level-card--scale>img,.level-card--elite>img{filter:saturate(.92) contrast(1.04)}

/* Real-world media replaces premature Scale and Elite interfaces */
.story-visual--scale,.story-visual--elite{padding:0;background:#101216}
.story-visual--scale>img,.story-visual--elite>img{
  width:100%;
  height:100%;
  object-fit:cover;
  filter:saturate(.92) contrast(1.04);
  transition:transform 7s linear;
}
.story-visual--scale::after,.story-visual--elite::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,transparent 48%,rgb(8 12 16 / .84) 100%);
}
.story-visual--scale.is-active>img,.story-visual--elite.is-active>img{transform:scale(1.045)}
.story-visual--scale .story-visual-caption,.story-visual--elite .story-visual-caption{z-index:2}
.story-step>span{
  width:max-content;
  padding:6px 10px;
  border-radius:999px;
  color:var(--ink);
}
.story-step:nth-child(1)>span,.story-step:nth-child(4)>span{background:var(--signal-yellow)}
.story-step:nth-child(2)>span{background:var(--signal-blue)}
.story-step:nth-child(3)>span{background:var(--teal);color:#fff}
.story-index .is-active,.story-link{color:#236fe8}
.story-step h3{color:var(--ink)}

.level-card-copy{padding-bottom:24px}

/* Jitter-style continuous work reel */
.showreel-section{
  padding:97.58px 0 78.06px;
  overflow:hidden;
  background:var(--white);
  color:var(--ink);
}
.showreel-heading{
  width:min(100%,var(--max));
  margin:0 auto 52px;
  padding:0 var(--gutter);
  display:flex;
  align-items:end;
  justify-content:space-between;
  gap:48px;
}
.showreel-heading h2{
  max-width:960px;
  font-size:clamp(3.3rem,6vw,5.8rem);
  line-height:.92;
}
.showreel-heading p{
  max-width:430px;
  color:var(--muted);
  font-size:18px;
  line-height:1.45;
}
.showreel-window{overflow:hidden}
.showreel-track{
  display:flex;
  width:max-content;
  will-change:transform;
  animation:showreel-loop 54s linear infinite;
}
.showreel-window:hover .showreel-track,.showreel-window:focus-within .showreel-track{animation-play-state:paused}
.showreel-group{display:flex;gap:24px;padding-right:24px}
.showreel-item{
  flex:0 0 clamp(380px,31vw,520px);
  min-height:540px;
  padding:26px;
  display:grid;
  grid-template-rows:1fr auto;
  gap:24px;
  border-radius:16px;
  background:var(--mist);
  scroll-snap-align:start;
}
.showreel-media{
  min-height:390px;
  overflow:hidden;
  border-radius:10px;
  background:#d9d9de;
}
.showreel-media img,.showreel-media video{
  width:100%;
  height:100%;
  display:block;
  object-fit:cover;
}
.showreel-meta{display:flex;align-items:center;gap:12px}
.showreel-meta>img{width:44px;height:44px;border-radius:50%}
.showreel-meta>span{display:flex;flex-direction:column}
.showreel-meta strong{font-size:18px;line-height:1.05}
.showreel-meta small{margin-top:4px;color:var(--muted);font-size:13px}
@keyframes showreel-loop{to{transform:translateX(-50%)}}

/* Jitter-style simple pricing */
.pricing-section{
  padding:84.95px var(--gutter) 89.54px;
  background:var(--mist);
}
.pricing-section .pricing-heading{margin-bottom:55.68px}
.pricing-section .pricing-heading h2{color:var(--ink);font-size:clamp(4rem,7vw,6rem)}
.pricing-section .pricing-heading>p{max-width:620px;color:var(--ink);line-height:1.45}
.pricing-section .price-row{gap:12px}
.pricing-section .price-card,
.pricing-section .price-card--featured{
  min-height:570px;
  padding:30px;
  border:0;
  border-radius:14px;
  background:var(--white);
  color:var(--ink);
}
.price-plan-head{min-height:36px;display:flex;align-items:center;gap:10px}
.price-plan-pill{
  padding:8px 16px;
  border-radius:999px;
  color:var(--ink);
  font-size:14px;
  font-weight:700;
}
.price-plan-pill--blue{background:color-mix(in srgb,var(--signal-blue) 24%,white)}
.price-plan-pill--yellow{background:var(--signal-yellow)}
.price-plan-pill--purple{background:color-mix(in srgb,var(--teal) 22%,white)}
.price-popular{color:var(--teal);font-size:13px;font-weight:700}
.pricing-section .price-card h3{
  min-height:1em;
  margin:28px 0 24px;
  color:var(--ink);
  font-size:clamp(2.8rem,4.4vw,4.2rem);
  line-height:.92;
  letter-spacing:-.035em;
}
.pricing-section .price-card>p,
.pricing-section .price-card--featured>p{
  min-height:76px;
  margin:0;
  color:#56525b;
  font-size:15px;
  line-height:1.45;
}
.pricing-section .price-card>p strong{color:var(--ink)}
.price-cta{
  min-height:54px;
  margin-top:22px;
  padding:0 20px;
  display:flex;
  align-items:center;
  justify-content:center;
  border-radius:999px;
  color:var(--ink);
  text-decoration:none;
  font-weight:700;
  transition:transform .3s var(--ease),filter .3s var(--ease);
}
.price-cta:hover{transform:scale(.985);filter:saturate(1.12)}
.price-cta--blue{background:#68b9f5}
.price-cta--yellow{background:var(--signal-yellow)}
.price-cta--purple{background:#ab87f5}
.pricing-section .price-card ul{margin:30px 0 0}
.pricing-section .price-card li,
.pricing-section .price-card--featured li{
  padding:13px 0;
  border-color:var(--line);
  color:var(--ink);
}
.pricing-section .price-card li:first-child{font-weight:700}

/* Footer curtain reveal; the brand mark itself stays static. */
.site-footer{
  position:relative;
  isolation:isolate;
  padding:0;
  overflow:clip;
  background:#000;
  color:#fff;
}
.site-footer.footer-reveal-ready{
  padding-bottom:var(--footer-stage-size,100svh);
}
.footer-directory{
  position:relative;
  z-index:2;
  padding:clamp(66.12px,6.24vw,75.47px) var(--gutter) 64.38px;
  border-radius:0 0 80px 80px;
  background:var(--mist);
  color:var(--ink);
}
/* Hold the pinned newsletter behind a half-viewport directory cover. This
   preserves the delayed reveal without leaving a full screen of dead space. */
@media(min-width:901px){
  .footer-directory{height:50svh;min-height:0}
}
.footer-directory-grid{
  width:min(100%,var(--max));
  margin:auto;
  display:grid;
  grid-template-columns:1.25fr repeat(3,.75fr);
  gap:56px;
}
.footer-directory-brand{
  align-self:start;
  display:flex;
  align-items:center;
  gap:12px;
  color:var(--ink);
  text-decoration:none;
  font-size:25px;
  font-weight:800;
  letter-spacing:-.035em;
}
.footer-directory-brand img{width:52px;height:52px;border-radius:11px}
.footer-directory-brand>span>span{color:var(--teal)}
.footer-column{display:flex;flex-direction:column;align-items:flex-start}
.footer-column h3{margin-bottom:18px;font-size:16px}
.footer-column a{
  margin:7px 0;
  color:#47434b;
  text-decoration:none;
  font-size:15px;
}
.footer-column a:hover{color:var(--teal)}
.footer-directory-bottom{
  width:min(100%,var(--max));
  margin:66.12px auto 0;
  padding-top:28px;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:24px;
  border-top:1px solid #d4d1d8;
  color:#5d5962;
  font-size:13px;
}
.footer-legal{display:flex;flex-wrap:wrap;gap:8px 22px}
.footer-legal a{color:#5d5962;text-decoration:none;transition:color .25s var(--ease)}
.footer-legal a:hover{color:var(--teal)}
.footer-newsletter-stage{
  position:sticky;
  z-index:1;
  bottom:0;
  width:min(100%,var(--max));
  min-height:max(988px,100svh);
  margin:auto;
  padding:113.57px var(--gutter);
  display:grid;
  grid-template-columns:.85fr 1.15fr;
  align-items:center;
  gap:80px;
}
.footer-reveal-ready .footer-newsletter-stage{
  position:absolute;
  top:0;
  bottom:auto;
  left:50%;
  margin:0;
  transform:translate3d(-50%,var(--footer-reveal-y,0),0);
  will-change:transform;
}
/* Desktop now finishes as the same split reveal used on phones: the directory
   stays in the upper half and the newsletter occupies only the lower half. */
@media(min-width:901px){
  .site-footer.footer-reveal-ready{padding-bottom:0}
  .footer-newsletter-stage,
  .footer-reveal-ready .footer-newsletter-stage{
    position:sticky;
    top:auto;
    bottom:0;
    left:auto;
    height:65svh;
    min-height:0;
    margin:auto;
    padding:clamp(42px,6.5svh,73px) var(--gutter);
    transform:none;
    will-change:auto;
  }
  .footer-mark img,.footer-motion img{width:clamp(120px,20svh,200px)}
  .footer-newsletter h2{font-size:clamp(2.5rem,4.2vw,4rem)}
  .footer-newsletter .newsletter-form{margin-top:clamp(20px,3svh,32px)}
}
.footer-mark,.footer-motion{display:grid;place-items:center}
.footer-mark img,.footer-motion img{
  width:clamp(170px,19vw,260px);
  height:auto;
  border-radius:16px;
}
.footer-newsletter h2{
  max-width:650px;
  font-family:var(--sans);
  font-size:clamp(3rem,4.5vw,4.8rem);
  font-weight:750;
  letter-spacing:-.035em;
  line-height:.94;
}
.footer-newsletter .newsletter-form{margin-top:40px}
.footer-newsletter .newsletter-form label{
  position:absolute;
  width:1px;
  height:1px;
  padding:0;
  overflow:hidden;
  clip:rect(0,0,0,0);
  white-space:nowrap;
  border:0;
}
.footer-newsletter .newsletter-line{
  min-height:60px;
  display:flex;
  align-items:center;
  border:0;
  background:#2c2831;
  /* The submit button is a 52px pill inset 4px inside a 60px bar. If the bar
     keeps square corners its dark corner sits outside the pill's right cap and
     reads as a box bleeding past the button. Capping the bar at the same
     full radius makes the two concentric, so the cap is clean at both ends. */
  border-radius:999px;
}
.footer-newsletter .newsletter-line input{
  min-width:0;
  flex:1;
  /* clears the 30px left cap */
  padding:0 26px;
  border:0;
  background:transparent;
  color:#fff;
  font-family:var(--sans);
  font-size:16px;
}
.footer-newsletter .newsletter-line input::placeholder{color:#c5c1ca;opacity:1}
.footer-newsletter .newsletter-line input:focus,
.footer-newsletter .newsletter-line input:focus-visible{outline:0}
.footer-newsletter .newsletter-line:focus-within{
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.28);
}
/* the confirmation sweep is a child of the bar, so it has to be clipped to the
   same pill or it re-squares the corners for the length of the animation */
.footer-newsletter .newsletter-line::after{border-radius:inherit}
.footer-newsletter .newsletter-line button{
  min-width:190px;
  min-height:52px;
  margin-right:4px;
  border:0;
  border-radius:999px;
  background:var(--signal-yellow);
  color:var(--ink);
  font-weight:700;
}
.footer-newsletter .form-status{color:#aaa7af}

@media(max-width:1050px){
  .showreel-heading{padding:0 32px}
  .footer-directory-grid{grid-template-columns:1fr 1fr}
  .footer-directory-brand{grid-column:1/-1}
  .footer-newsletter-stage{grid-template-columns:.72fr 1.28fr;gap:44px}
}

@media(max-width:720px){
  .story-visual--scale,.story-visual--elite{padding:0}
  .showreel-section{padding:73.08px 0 74.88px}
  .showreel-heading{padding:0 20px;display:block}
  .showreel-heading h2{font-size:clamp(3.1rem,14vw,4.4rem)}
  .showreel-heading p{margin-top:20px}
  .showreel-item{flex-basis:82vw;min-height:440px;padding:18px;gap:18px}
  .showreel-media{min-height:320px}
  .showreel-window{overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none}
  .showreel-window::-webkit-scrollbar{display:none}
  .showreel-track{animation:none}
  .showreel-group[aria-hidden="true"]{display:none}
  .pricing-section{padding:71.76px 20px 78px}
  .pricing-section .pricing-heading h2{font-size:clamp(3.6rem,16vw,5rem)}
  .pricing-section .price-card,.pricing-section .price-card--featured{min-height:auto}
  .footer-directory{padding:62.64px 20px 54px;border-radius:0 0 40px 40px}
  .footer-directory-grid{grid-template-columns:1fr 1fr;gap:42px 24px}
  .footer-directory-brand{grid-column:1/-1}
  .footer-directory-bottom{margin-top:54px;align-items:flex-start;flex-direction:column}
  .footer-newsletter-stage{
    min-height:max(936px,100svh);
    padding:97.27px 20px;
    grid-template-columns:1fr;
    gap:52px;
  }
  .footer-mark img,.footer-motion img{width:138px}
  .footer-newsletter h2{font-size:clamp(2.8rem,12vw,3.8rem)}
  .footer-newsletter .newsletter-line button{min-width:122px}
}

@media(prefers-reduced-motion:reduce){
  .showreel-window{overflow-x:auto;scroll-snap-type:x mandatory}
  .showreel-track{animation:none}
  .showreel-group[aria-hidden="true"]{display:none}
  .site-footer.footer-reveal-ready{padding-bottom:0}
  .footer-reveal-ready .footer-newsletter-stage{
    position:relative;
    top:auto;
    left:auto;
    transform:none;
  }
}

/* Score-led New Zealand place pages */
.nav-dropdown--locations{width:520px;display:grid;grid-template-columns:1fr 1fr;gap:2px}
.nav-dropdown--locations .nav-all-places{grid-column:1/-1;margin-bottom:6px;background:var(--mist);color:var(--teal-dark)}
.footer-column--places{display:grid;grid-template-columns:1fr 1fr;align-content:start;column-gap:22px}
.footer-column--places h3{grid-column:1/-1}
.place-page,.places-page{overflow:clip}
.place-hero{
  min-height:100svh;
  padding:80.36px var(--gutter) 62.64px;
  display:grid;
  grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);
  align-items:center;
  gap:clamp(44px,6vw,92px);
  background:var(--cloud);
}
.place-hero-copy{max-width:680px}
.place-kicker{margin-bottom:26px;color:var(--teal-dark);font-size:15px;font-weight:700}
.place-hero h1{max-width:760px;font-size:clamp(3.8rem,6.4vw,6rem)}
.place-hero-copy>p:not(.place-kicker){max-width:630px;margin-top:30px;color:#514d56;font-size:clamp(18px,1.5vw,22px);line-height:1.55}
.place-hero-actions{margin-top:36px;display:flex;align-items:center;flex-wrap:wrap;gap:14px}
.place-text-link{color:var(--teal-dark);font-size:15px;font-weight:700;text-decoration:none}
.place-hero-media{position:relative;min-height:min(72vh,760px);margin:0;overflow:hidden;border-radius:16px;background:var(--navy)}
.place-hero-media img{width:100%;height:100%;min-height:inherit;object-fit:cover}
.place-hero-media::after{content:"";position:absolute;inset:auto 0 0;height:28%;background:linear-gradient(180deg,transparent,rgba(0,0,0,.64));pointer-events:none}
.place-hero-media figcaption{position:absolute;z-index:1;inset:auto 26px 24px;display:flex;align-items:flex-end;justify-content:space-between;gap:24px;color:#fff}
.place-hero-media figcaption strong{font-size:20px}
.place-hero-media figcaption span{max-width:290px;color:rgba(255,255,255,.78);font-size:12px;text-align:right}
.place-opportunity{padding:clamp(78px,6.888vw,97.58px) var(--gutter);display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);gap:clamp(60px,9vw,140px);background:var(--mist)}
.place-opportunity-copy{max-width:650px}
.place-opportunity h2,.place-build-heading h2{font-size:clamp(3.3rem,5vw,5.6rem)}
.place-opportunity-copy p{margin-top:28px;color:#514d56;font-size:18px}
.place-signal-list{margin:0;padding:0;list-style:none;border-top:1px solid var(--line)}
.place-signal-list li{padding:30px 0;display:grid;grid-template-columns:54px 1fr;gap:24px;border-bottom:1px solid var(--line)}
.place-signal-list li>span{color:var(--teal-dark);font-size:14px;font-weight:700}
.place-signal-list strong{display:block;font-size:clamp(22px,2vw,30px);line-height:1.1}
.place-signal-list p{margin-top:9px;color:var(--muted);font-size:15px}
.place-build{padding:clamp(78px,6.888vw,97.58px) var(--gutter);background:var(--cloud)}
.place-build-heading{max-width:960px;margin-bottom:60.9px}
.place-build-heading p{max-width:720px;margin-top:24px;color:var(--muted);font-size:19px}
.place-system-steps{display:grid;grid-template-columns:repeat(4,1fr);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.place-system-steps article{min-width:0;padding:36px clamp(20px,2.4vw,38px) 42px;border-right:1px solid var(--line)}
.place-system-steps article:first-child{padding-left:0}
.place-system-steps article:last-child{padding-right:0;border-right:0}
.place-system-steps span{color:var(--teal-dark);font-size:14px;font-weight:700}
.place-system-steps h3{margin-top:55.68px;font-size:clamp(28px,2.6vw,38px)}
.place-system-steps p{margin-top:16px;color:var(--muted);font-size:15px}
.place-fit{max-width:920px;margin-top:42px;color:#514d56}
.place-fit strong{color:var(--ink)}
.place-pricing{padding:clamp(78px,6.314vw,86.1px) var(--gutter);background:var(--mist)}
.place-pricing .price-row,.place-pricing .pricing-heading{width:min(100%,var(--max));margin-left:auto;margin-right:auto}
.place-faq{padding:clamp(78px,6.888vw,91.84px) var(--gutter);display:grid;grid-template-columns:minmax(0,.7fr) minmax(0,1.3fr);gap:clamp(54px,9vw,140px);align-items:start;background:var(--cloud)}
.place-faq .faq-heading h2{font-size:clamp(3.2rem,5vw,5.4rem)}
.place-faq .faq-heading p{margin-top:22px;color:var(--muted);font-size:18px}
.faq-page .place-faq{gap:clamp(54px,10vw,168px)}
.faq-page .place-faq .faq-heading p{margin-top:28px}
.faq-page .faq-list summary{padding:36px 0}
.faq-page .faq-list details p{padding:0 62px 38px 0}
.place-next{padding:44px var(--gutter);display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:32px;border-top:1px solid var(--line);background:var(--cloud)}
.place-next>a{display:flex;flex-direction:column;color:var(--ink);text-decoration:none}
.place-next>a:last-child{text-align:right}
.place-next>a small{color:var(--muted)}
.place-next>a strong{margin-top:4px;font-size:20px}
.place-next>div{text-align:center}
.place-next>div p{margin:0 auto 14px;color:var(--muted);font-size:13px}
.places-hero{padding:109.06px var(--gutter) 84px;background:var(--cloud)}
.places-hero>*{max-width:1050px;margin-left:auto;margin-right:auto;text-align:center}
.places-hero>p{margin-bottom:24px;color:var(--teal-dark);font-size:15px;font-weight:700}
.places-hero h1{font-size:clamp(4rem,7vw,6rem)}
.places-hero span{display:block;max-width:760px;margin-top:30px;color:var(--muted);font-size:20px}
.places-directory{padding:clamp(78px,6.314vw,86.1px) var(--gutter);background:var(--mist)}
.places-directory--established{background:var(--cloud)}
.places-directory-head{width:min(100%,var(--max));margin:0 auto 52px;display:grid;grid-template-columns:1fr 1fr;align-items:end;gap:48px}
.places-directory-head h2{font-size:clamp(3rem,4.5vw,5rem)}
.places-directory-head p{color:var(--muted);font-size:18px}
.places-directory-grid{width:min(100%,var(--max));margin:auto;display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.places-directory-grid--two{grid-template-columns:repeat(2,1fr)}
.place-directory-card--desktop{display:none}
@media(min-width:1051px){.place-directory-card--desktop{display:block}}
.places-directory--national .place-directory-card{min-height:350px}
.place-directory-card{position:relative;min-height:420px;overflow:hidden;border-radius:16px;background:var(--navy);color:#fff;text-decoration:none}
.place-directory-card img{width:100%;height:100%;object-fit:cover;transition:transform .7s var(--ease)}
.place-directory-card::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 42%,rgba(0,0,0,.08) 58%,rgba(0,0,0,.74) 100%)}
.place-directory-card:hover img{transform:scale(1.025)}
.place-directory-card>span{position:absolute;z-index:1;inset:auto 26px 25px;display:flex;flex-direction:column}
.place-directory-card small{color:rgba(255,255,255,.72)}
.place-directory-card strong{margin-top:4px;font-size:clamp(30px,3vw,44px);letter-spacing:-.035em;line-height:1}
.place-directory-card em{
  align-self:flex-start;
  display:inline-flex;
  align-items:center;
  gap:7px;
  margin-top:14px;
  color:#fff;
  font-size:14px;
  font-style:normal;
  font-weight:700;
  /* underline, not a pill: six yellow buttons stacked down the grid was the
     loudest thing on the page and it competed with the place names, which are
     what the card is actually selling. The arrow carries the affordance. */
  text-decoration:underline;
  text-decoration-thickness:1.5px;
  text-underline-offset:4px;
  text-decoration-color:rgb(255 255 255 / .5);
  transition:text-decoration-color .35s var(--ease);
}
.place-directory-card em .ds-arrow{
  width:13px;
  height:13px;
  flex:0 0 auto;
  transition:transform .35s var(--ease);
}
.place-directory-card:hover em{text-decoration-color:#fff}
.place-directory-card:hover em .ds-arrow{transform:translate(2px,-2px)}
.places-directory--home{background:var(--mist)}
.places-home-action{width:min(100%,var(--max));margin:36px auto 0;text-align:center}

@media(max-width:1180px){
  .place-system-steps{grid-template-columns:1fr 1fr}
  .place-system-steps article{border-bottom:1px solid var(--line)}
  .place-system-steps article:nth-child(2){border-right:0}
  .place-system-steps article:nth-child(3){padding-left:0;border-bottom:0}
  .place-system-steps article:last-child{border-bottom:0}
  .places-directory-grid{grid-template-columns:1fr 1fr}
}
@media(max-width:1050px){
  .place-hero{min-height:auto;padding-top:74.62px;grid-template-columns:1fr}
  .place-hero-copy{max-width:850px}
  .place-hero-media{min-height:62vw}
  .place-opportunity,.place-faq{grid-template-columns:1fr}
  .place-opportunity-copy{max-width:850px}
}
@media(max-width:720px){
  .place-hero{padding:86.8px 20px 52.2px;gap:42px}
  .place-hero h1{font-size:clamp(3.5rem,15vw,4.8rem)}
  .place-hero-copy>p:not(.place-kicker){font-size:18px}
  .place-hero-actions{align-items:flex-start;flex-direction:column}
  .place-hero-media{min-height:72vw;border-radius:12px}
  .place-hero-media figcaption{inset:auto 18px 16px;align-items:flex-start;flex-direction:column;gap:3px}
  .place-hero-media figcaption span{text-align:left}
  .place-opportunity,.place-build,.place-pricing,.place-faq{padding-left:20px;padding-right:20px}
  .place-signal-list li{grid-template-columns:38px 1fr;gap:14px}
  .place-system-steps{grid-template-columns:1fr}
  .place-system-steps article,.place-system-steps article:first-child,.place-system-steps article:nth-child(3),.place-system-steps article:last-child{padding:30px 0;border-right:0;border-bottom:1px solid var(--line)}
  .place-system-steps article:last-child{border-bottom:0}
  .place-system-steps h3{margin-top:32px}
  .place-next{padding:34px 20px;grid-template-columns:1fr 1fr}
  .place-next>div{grid-column:1/-1;grid-row:1}
  .places-hero{padding:86.1px 20px 73.08px}
  .places-hero span{font-size:18px}
  .places-directory{padding-left:20px;padding-right:20px}
  .places-directory-head{grid-template-columns:1fr}
  .places-directory-grid,.places-directory-grid--two{grid-template-columns:1fr}
  .place-directory-card{min-height:380px}
  .footer-column--places{grid-template-columns:1fr}
}

/* Jitter-measured global navigation */
:root{
  --nav-max:1440px;
  --jitter-expo:cubic-bezier(.19,1,.22,1);
  --jitter-spring:cubic-bezier(.16,1,.3,1);
  --jitter-soft:cubic-bezier(.25,.46,.45,.94);
  --jitter-card:cubic-bezier(.22,1,.36,1);
}
.site-header{
  inset:0 0 auto;
  height:129px;
  padding:0;
  isolation:isolate;
  transform:none;
  transition:transform 1.2s var(--jitter-expo);
}
.nav-shell{
  position:absolute;
  z-index:2;
  top:34px;
  left:50%;
  width:min(calc(100% - 96px),var(--nav-max));
  height:100px;
  margin:0;
  padding:0;
  display:flex;
  align-items:center;
  gap:28px;
  border-radius:0;
  background:transparent;
  color:var(--ink);
  box-shadow:none;
  backdrop-filter:none;
  transform:translateX(-50%);
  transition:none;
  isolation:isolate;
}
.nav-shell::before{
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  bottom:auto;
  left:calc(-1 * clamp(16px,2.4vw,40px));
  right:calc(-1 * clamp(16px,2.4vw,40px));
  height:100px;
  border:1px solid rgb(25 23 28 / .12);
  border-radius:20px;
  background:var(--white);
  box-shadow:0 4px 8px rgb(0 0 0 / .08);
  opacity:1;
  transform:none;
  transform-origin:top center;
  transition:
    top .5s var(--jitter-soft),
    left .7s var(--jitter-expo),
    right .7s var(--jitter-expo),
    width .7s var(--jitter-expo),
    height .7s var(--jitter-expo),
    border-radius .5s var(--jitter-soft),
    box-shadow .5s var(--jitter-soft),
    opacity .16s linear,
    transform .7s var(--jitter-expo);
}
.site-header.header-floating .nav-shell::before{opacity:1}
.site-header:not(.header-floating):not(.header-compact) .nav-shell::before{opacity:1}
body[data-theme="navy"] .nav-shell{
  color:var(--ink);
  background:transparent;
  box-shadow:none;
}
.brand{
  min-width:max-content;
  gap:9px;
  font-size:28px;
  transition:transform .8s var(--jitter-spring),opacity .16s linear;
}
.brand img{width:34px;height:34px}
.brand .wordmark span,
body[data-theme="navy"] .brand .wordmark span{color:var(--teal)}
.nav-center{
  flex:1;
  justify-content:flex-start;
  gap:0;
  min-width:0;
  transition:opacity .16s linear;
}
.nav-center>a,.nav-group>summary{
  min-height:48px;
  /* the nav is down to three links, so the room the dropdowns used to take
     goes into type size and breathing room instead */
  padding:0 20px;
  border-radius:999px;
  font-size:22.5px;
  font-weight:600;
  letter-spacing:-.022em;
  opacity:1;
  white-space:nowrap;
  transition:
    opacity .3s var(--jitter-soft),
    color .2s ease,
    background-color .3s var(--jitter-soft),
    transform .5s var(--jitter-spring);
}
.nav-center>a:hover,.nav-center>a:focus-visible,
body[data-theme="navy"] .nav-center>a:hover,
body[data-theme="navy"] .nav-center>a:focus-visible{
  background:transparent;
  color:inherit;
  transform:none;
}
.nav-group>summary:hover,.nav-group[open]>summary,
body[data-theme="navy"] .nav-group>summary:hover,
body[data-theme="navy"] .nav-group[open]>summary{background:transparent}
/* Complete package and Questions animate exactly like the Places and About menus:
   hovering any nav item dims its siblings to .35 and keeps itself lit. No pill, no
   lift. The body.nav-dropdown-open rules below outrank these, so an open panel keeps
   owning the dim state once the pointer crosses into it. */
@media(hover:hover){
  .nav-center:hover>a,
  .nav-center:hover>.nav-group>summary{opacity:.35}
  .nav-center>a:hover,
  .nav-center>a:focus-visible,
  .nav-center>.nav-group:hover>summary,
  .nav-center>.nav-group>summary:focus-visible{opacity:1}
}
.nav-center:has(>.nav-group--examples:hover)>a,
.nav-center:has(>.nav-group--examples:hover)>.nav-group>summary{opacity:1}
body.nav-dropdown-open .nav-center>a{opacity:.35}
body.nav-dropdown-open .nav-group:not([open])>summary{opacity:.35}
body.nav-dropdown-open .nav-group[open]>summary{opacity:1}
.nav-group{position:static}
.nav-dropdown{
  position:fixed;
  z-index:2;
  top:95px;
  left:50%;
  width:100vw;
  height:320px;
  padding:40px max(48px,calc((100vw - var(--nav-max))/2)) 54px;
  display:grid;
  grid-template-columns:repeat(5,minmax(0,1fr));
  gap:10px;
  border-radius:0;
  background:transparent;
  color:var(--ink);
  box-shadow:none;
  transform:translateX(-50%);
  pointer-events:auto;
}
.nav-dropdown::before{display:none}
.nav-dropdown a{
  position:relative;
  min-width:0;
  min-height:103px;
  padding:18px 18px 42px;
  justify-content:flex-end;
  border-radius:12px;
  background:var(--mist);
  color:var(--ink);
  font-size:15px;
  font-weight:700;
  line-height:1.15;
  opacity:0;
  transform:scale(1.15);
  transform-origin:center;
  transition:background-color .2s ease,color .2s ease;
}
.nav-dropdown a::after{
  content:"";
  display:inline-block;
  width:15px;height:15px;
  -webkit-mask:url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2014%2014%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.7%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M3.5%2010.55C5.85%208.45%208.15%206.1%2010.4%203.6%22%2F%3E%3Cpath%20d%3D%22M5.5%203.35%2010.65%203.25%2010.55%208.4%22%2F%3E%3C%2Fsvg%3E') no-repeat center/contain;
  mask:url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2014%2014%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.7%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M3.5%2010.55C5.85%208.45%208.15%206.1%2010.4%203.6%22%2F%3E%3Cpath%20d%3D%22M5.5%203.35%2010.65%203.25%2010.55%208.4%22%2F%3E%3C%2Fsvg%3E') no-repeat center/contain;
  background:currentColor;
  position:absolute;
  right:17px;
  bottom:15px;
  font-size:15px;
  transition:transform .3s var(--jitter-soft);
}
.nav-dropdown a:hover{background:var(--signal-blue)}
.nav-dropdown a:hover::after{transform:translate(25%,-25%)}
.nav-dropdown .nav-all-places{grid-column:auto;margin:0;background:var(--signal-yellow);color:var(--ink)}
.nav-dropdown strong{font-size:17px}
.nav-dropdown small{margin-top:6px;color:var(--muted);font-size:12px;font-weight:500}
.nav-dropdown--about .nav-about-intro{
  justify-content:space-between;
  background:var(--signal-yellow);
}
.nav-dropdown--about .nav-about-intro strong{
  font-size:clamp(20px,1.55vw,25px);
  line-height:1.02;
  letter-spacing:-.035em;
}
.nav-dropdown--about .nav-founder-card{
  isolation:isolate;
  overflow:hidden;
  background:var(--ink);
  color:var(--white);
}
.nav-dropdown--about .nav-founder-card::before{
  content:"";
  position:absolute;
  z-index:1;
  inset:38% 0 0;
  background:linear-gradient(180deg,transparent,rgb(0 0 0 / .78));
}
.nav-dropdown--about .nav-founder-card img{
  position:absolute;
  z-index:0;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
  filter:grayscale(1);
  transition:transform .7s var(--jitter-expo);
}
.nav-dropdown--about .nav-founder-card:not(.nav-founder-card--gray) img{object-position:center 30%}
.nav-dropdown--about .nav-founder-card--gray img{object-position:center 43%}
.nav-dropdown--about .nav-founder-card:hover img{transform:scale(1.035)}
.nav-dropdown--about .nav-founder-card span{
  position:relative;
  z-index:2;
  display:flex;
  flex-direction:column;
}
.nav-dropdown--about .nav-founder-card small{color:rgb(255 255 255 / .74)}
.nav-dropdown--about .nav-founder-card::after{z-index:2}
.nav-dropdown--about .nav-about-mission{
  background:var(--teal);
  color:var(--white);
}
.nav-dropdown--about .nav-about-mission small{color:rgb(255 255 255 / .72)}
.nav-dropdown--about .nav-about-link{background:var(--signal-blue)}
/* Complete package and Questions use the same five-card row as the About menu, so all
   four nav items open the identical panel with the identical staggered card animation.
   Only the lead card is styled here; every other card inherits .nav-dropdown a. */
.nav-dropdown--package .nav-panel-lead,
.nav-dropdown--questions .nav-panel-lead{
  justify-content:space-between;
  background:var(--signal-yellow);
  color:var(--ink);
}
.nav-dropdown--package .nav-panel-lead strong,
.nav-dropdown--questions .nav-panel-lead strong{
  font-size:clamp(20px,1.55vw,25px);
  line-height:1.02;
  letter-spacing:-.035em;
}
.nav-group[open] .nav-dropdown a{
  animation:nav-card-in .8s var(--jitter-card) both;
}
.nav-group[open] .nav-dropdown a:nth-child(1){animation-delay:.05s}
.nav-group[open] .nav-dropdown a:nth-child(2){animation-delay:.125s}
.nav-group[open] .nav-dropdown a:nth-child(3){animation-delay:.2s}
.nav-group[open] .nav-dropdown a:nth-child(4){animation-delay:.275s}
.nav-group[open] .nav-dropdown a:nth-child(5){animation-delay:.35s}
.nav-group[open] .nav-dropdown a:nth-child(6){animation-delay:.425s}
.nav-group[open] .nav-dropdown a:nth-child(7){animation-delay:.5s}
.nav-group[open] .nav-dropdown a:nth-child(8){animation-delay:.575s}
.nav-group[open] .nav-dropdown a:nth-child(9){animation-delay:.65s}
.nav-group[open] .nav-dropdown a:nth-child(10){animation-delay:.725s}
@keyframes nav-card-in{
  0%{opacity:0;transform:scale(1.15)}
  18%{opacity:1}
  100%{opacity:1;transform:scale(1)}
}
body.nav-dropdown-open .nav-shell::before{
  top:-34px;
  left:50%;
  right:auto;
  width:100vw;
  height:449px;
  border-radius:0 0 40px 40px;
  opacity:1;
  transform:translateX(-50%);
}
.nav-actions{
  position:relative;
  flex:0 0 auto;
  gap:0;
}
.nav-cta{
  min-height:52px;
  padding:0 22px;
  background:var(--signal-yellow);
  color:var(--ink);
  font-size:19.6px;
  transition:transform .6s var(--jitter-card),background-color .3s var(--jitter-soft),color .3s var(--jitter-soft);
}
.nav-cta:hover,
body[data-theme="navy"] .nav-cta:hover{
  background:var(--signal-blue);
  color:var(--ink);
  transform:scale(1.05);
}
.nav-cta:active{transform:scale(.9);transition-duration:.1s}
body[data-theme="navy"] .nav-cta{background:var(--signal-yellow);color:var(--ink)}
.nav-toggle{
  position:absolute;
  top:0;
  right:0;
  display:block;
  width:52px;
  height:52px;
  border-radius:50%;
  background:var(--ink);
  color:var(--white);
  opacity:0;
  pointer-events:none;
  transform:scale(0);
  transition:transform .8s var(--jitter-spring),background-color .16s linear,opacity .15s linear;
}
.nav-toggle span{left:17px;width:18px;background:currentColor}
.nav-toggle span:first-child{top:21px}
.nav-toggle span:last-child{top:28px}
/* The contracted desktop header hides the brand and the nav links outright.
   It used to fly them 130px up and back on a .8s spring, so a click on any nav
   item - See an example most of all - landed mid-flight and read as a lurch.
   Fade only, no travel. Focus still expands the header (focusin -> hold in
   site.js), so the links stay reachable by keyboard. The <=1024 rules below
   keep their own slide, where there are no nav links to lurch. */
.site-header.header-compact .brand,
.site-header.header-compact .nav-center{
  transform:none;
  opacity:0;
  pointer-events:none;
}
.site-header.header-compact .nav-cta{transform:translateX(-67px)}
.site-header.header-compact .nav-cta:hover{transform:translateX(-67px) scale(1.05)}
.site-header.header-compact .nav-toggle{opacity:1;pointer-events:auto;transform:scale(1)}
.site-header.header-compact .nav-shell::before{
  display:none;
}
.nav-scrim{
  display:block;
  position:fixed;
  z-index:1;
  inset:0;
  border:0;
  background:rgb(25 23 28 / .68);
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity .6s var(--jitter-soft),visibility .6s;
}
.nav-scrim.is-desktop-open{opacity:1;visibility:visible;pointer-events:auto}

@media(min-width:1025px){
  .mobile-menu{display:none!important}
  .brand .wordmark{display:inline}
  .nav-center{display:flex}
}

@media(min-width:1181px) and (max-width:1440px){
  .nav-shell{gap:20px}
  .nav-center>a,.nav-group>summary{padding-inline:16px;font-size:20.5px}
  .nav-cta{padding-inline:18px;font-size:16.5px}
}

@media(min-width:1025px) and (max-width:1180px){
  .nav-shell{gap:18px}
  .brand{font-size:20px}
  .nav-center>a,.nav-group>summary{padding-inline:12px;font-size:18px}
  .nav-cta{padding-inline:16px;font-size:14px}
}

@media(max-width:1024px){
  :root{--header-h:100px}
  .site-header{height:100px}
  .nav-shell{
    z-index:4;
    top:15px;
    width:calc(100% - 40px);
    height:70px;
    padding:0 10px;
    gap:10px;
  }
  body.menu-open .nav-shell{z-index:4}
  .nav-shell::before{
    inset:0 -10px auto;
    width:auto;
    height:70px;
    border-radius:10px;
  }
  .site-header.header-floating .nav-shell::before{opacity:1}
  .brand{min-width:0}
  .brand img{width:44px;height:44px}
  .brand .wordmark,.nav-center{display:none}
  .nav-actions{margin-left:auto;display:flex;align-items:center;gap:8px}
  .nav-cta{
    position:static;
    min-height:48px;
    padding:0 16px;
    font-size:18.2px;
    transform:none!important;
  }
  .nav-toggle{
    position:relative;
    top:auto;
    right:auto;
    flex:0 0 52px;
    opacity:1;
    pointer-events:auto;
    transform:scale(1);
  }
  .nav-toggle[aria-expanded="false"]{background:var(--white);color:var(--ink)}
  .nav-toggle[aria-expanded="true"]{background:var(--ink);color:var(--white)}
  .site-header.header-compact .brand{transform:translateY(-130px)}
  .site-header.header-compact .nav-cta{transform:translateY(-130px)!important}
  .site-header.header-compact .nav-toggle{transform:scale(1)}
  .site-header.header-compact .nav-shell::before{
    display:none;
  }
  .mobile-menu{
    display:block;
    position:fixed;
    z-index:3;
    inset:0;
    width:100%;
    height:100dvh;
    padding:78px 20px 24px;
    overflow:auto;
    border-radius:0;
    background:var(--mist);
    color:var(--ink);
    opacity:1;
    visibility:hidden;
    clip-path:inset(0 0 100% 0);
    transform:none;
    transform-origin:top;
    pointer-events:none;
    transition:clip-path .8s var(--jitter-spring),visibility .8s;
  }
  .mobile-menu.is-open{visibility:visible;clip-path:inset(0);transform:none;pointer-events:auto}
  /* Bare 100dvh can outgrow the real visible viewport on iOS Safari while the
     chrome is expanded (same bug js/viewport.js documents for the hero
     stage), which is why the actions row at the bottom was landing below the
     thumb instead of at it. --vvh is measured against the live viewport, so
     this keeps the panel's actual height honest in every chrome state. */
  @supports (height: 100lvh){
    .mobile-menu{height:max(100lvh, var(--vvh,0px))}
  }
  .mobile-menu-inner{
    width:min(100%,700px);
    min-height:calc(100dvh - 124px);
    margin:auto;
    padding:20px 0 0;
    display:flex;
    flex-direction:column;
  }
  .mobile-menu-label{
    padding:0 0 16px;
    color:var(--muted);
    font-size:13px;
  }
  .mobile-menu-inner>a{
    min-height:58px;
    padding:0;
    border-bottom:1px solid var(--line);
    font-family:"Switzer",Avenir Next,Avenir,Helvetica Neue,sans-serif;
    font-size:clamp(2rem,7vw,3rem);
    line-height:1;
    letter-spacing:-.04em;
    opacity:0;
    transform:translateY(-18px);
    transition:opacity .5s var(--jitter-expo),transform .8s var(--jitter-spring);
  }
  .mobile-menu.is-open .mobile-menu-inner>a{opacity:1;transform:none}
  .mobile-menu.is-open .mobile-menu-inner>a:nth-of-type(1){transition-delay:.08s}
  .mobile-menu.is-open .mobile-menu-inner>a:nth-of-type(2){transition-delay:.14s}
  .mobile-menu.is-open .mobile-menu-inner>a:nth-of-type(3){transition-delay:.2s}
  .mobile-menu.is-open .mobile-menu-inner>a:nth-of-type(4){transition-delay:.26s}
  .mobile-locations{
    margin:20px 0;
    padding:0;
    display:grid;
    grid-template-columns:repeat(3,minmax(0,1fr));
    gap:8px;
    opacity:0;
    transform:translateY(-18px);
    transition:opacity .5s var(--jitter-expo) .3s,transform .8s var(--jitter-spring) .3s;
  }
  .mobile-menu.is-open .mobile-locations{opacity:1;transform:none}
  .mobile-locations a{
    min-height:42px;
    padding:10px;
    display:flex;
    align-items:center;
    justify-content:center;
    border-radius:999px;
    background:var(--white);
    color:var(--ink);
    text-align:center;
    text-decoration:none;
    font-size:12px;
    font-weight:700;
  }
  .mobile-menu-actions{
    display:flex;
    gap:8px;
    margin-top:auto;
    padding-top:10px;
    position:sticky;
    bottom:0;
    background:var(--mist);
  }
  /* Wrapping these in .mobile-menu-actions took them out from under
     .mobile-menu-inner>a, which is where display:flex/align-items/padding/
     text-decoration used to come from - restated here directly so the pill
     still centers its label instead of rendering as a bare inline link. */
  .mobile-menu-actions .mobile-menu-cta,
  .mobile-menu-actions .mobile-menu-wa{
    flex:1;
    min-width:0;
    text-align:center;
    line-height:1.15;
  }
  .mobile-menu-actions .mobile-menu-wa{gap:6px;padding:0 10px;font-size:13.5px}
  .mobile-menu-actions .mobile-menu-wa svg{width:18px;height:18px}
  .mobile-menu-inner .mobile-menu-cta{
    display:flex;
    align-items:center;
    justify-content:center;
    min-height:54px;
    padding:0 10px;
    border:0;
    border-radius:999px;
    background:var(--signal-yellow);
    color:var(--ink);
    text-decoration:none;
    font-family:"Switzer",Avenir Next,Avenir,Helvetica Neue,sans-serif;
    font-size:13.5px;
    font-weight:750;
  }
  .nav-scrim,.nav-scrim.is-open,.nav-scrim.is-desktop-open{display:none}
}

/* Thin header below 900px, site-wide. Previously lived only in hero-film.css
   (loaded on index.html alone), so the homepage got this compact 68px header
   and every other page kept the 100px one from the block above - moved here
   so it's consistent everywhere. */
@media(max-width:900px){
  .site-header{height:68px!important}
  .nav-shell{
    top:max(6px,env(safe-area-inset-top))!important;
    width:calc(100% - 12px)!important;
    height:54px!important;
    padding:0 5px!important;
  }
  .nav-shell::before{height:54px!important}
  .brand{min-width:44px!important;min-height:44px!important}
  .brand img{width:34px!important;height:34px!important}
  .nav-cta{min-height:44px!important;padding-inline:11px!important;font-size:13px!important}
  .nav-toggle{flex-basis:44px!important;width:44px!important;height:44px!important}
  .nav-toggle span{left:13px!important}
}

@media(max-width:520px){
  /* brand + CTA + menu share one 350px row. At 16.8px the CTA measured 223px
     and pushed the menu button off a 390px screen. WhatsApp now floats
     bottom-right instead of competing for this row. */
  .site-header .nav-cta{display:flex;padding:0 13px;font-size:15px}
  .mobile-locations{grid-template-columns:1fr 1fr}
}

@media(max-width:360px){
  .site-header .nav-cta{display:none}
  .nav-shell{justify-content:space-between}
}

@media(prefers-reduced-motion:reduce){
  .site-header,.site-header *,.site-header *::before,.site-header *::after{
    animation:none!important;
    transition-duration:.01ms!important;
  }
  .site-header.header-compact .brand,
  .site-header.header-compact .nav-center,
  .site-header.header-compact .nav-cta{transform:none!important}
  .site-header.header-compact .brand,
  .site-header.header-compact .nav-center,
  .site-header.header-compact .nav-cta{visibility:hidden}
  .nav-group[open] .nav-dropdown a{opacity:1;transform:none}
}

/* Mobile field-guide pass */
@keyframes mobile-swipe-cue{
  0%,100%{transform:translateX(0)}
  50%{transform:translateX(3px)}
}

@keyframes swipe-mark-drift{
  0%,100%{transform:translateX(0)}
  50%{transform:translateX(-2.2px)}
}
@keyframes swipe-mark-drift-r{
  0%,100%{transform:translateX(0)}
  50%{transform:translateX(2.2px)}
}
@media(prefers-reduced-motion:reduce){
  .swipe-mark-head{animation:none}
}

@media(max-width:1024px){
  :root{--header-h:88px}
  .site-header{
    height:88px;
    padding-left:env(safe-area-inset-left);
    padding-right:env(safe-area-inset-right);
    transition:transform .34s var(--jitter-expo);
  }
  .nav-shell{
    top:max(12px,env(safe-area-inset-top));
    width:calc(100% - 24px);
    height:64px;
    padding:0 8px;
    gap:8px;
  }
  .nav-shell::before{
    inset:0 -6px auto;
    height:64px;
    border-radius:12px;
    transition:
      top .3s var(--jitter-expo),
      left .34s var(--jitter-expo),
      right .34s var(--jitter-expo),
      width .34s var(--jitter-expo),
      height .34s var(--jitter-expo),
      border-radius .3s var(--jitter-expo),
      box-shadow .3s var(--jitter-expo),
      opacity .12s linear,
      transform .34s var(--jitter-expo);
  }
  .brand{
    min-width:44px;
    min-height:44px;
    transition:transform .34s var(--jitter-expo);
  }
  .brand img{width:40px;height:40px}
  .nav-actions{gap:8px}
  .nav-cta{
    min-height:46px;
    padding:0 14px;
    font-size:16px;
    transition:transform .32s var(--jitter-expo),background-color .22s ease,color .22s ease;
  }
  .nav-toggle{
    flex-basis:48px;
    width:48px;
    height:48px;
    transition:transform .3s var(--jitter-expo),background-color .16s linear,opacity .12s linear;
  }
  .nav-toggle span{
    top:50%!important;
    left:15px;
    width:18px;
    transition:transform .26s var(--jitter-expo);
  }
  .nav-toggle span:first-child{transform:translateY(-4px)}
  .nav-toggle span:last-child{transform:translateY(3px)}
  .nav-toggle[aria-expanded="true"] span:first-child{transform:translateY(-1px) rotate(45deg)}
  .nav-toggle[aria-expanded="true"] span:last-child{transform:translateY(-1px) rotate(-45deg)}
  .site-header.header-compact .brand,
  .site-header.header-compact .nav-cta{transform:translateY(-92px)!important}
  .site-header.header-compact .nav-shell::before{
    display:none;
  }
  .mobile-menu{
    padding:max(76.56px,calc(env(safe-area-inset-top) + 69.6px)) 14px max(20px,env(safe-area-inset-bottom));
    overscroll-behavior:contain;
    opacity:0;
    transform:translateY(-8px);
    transition:opacity .24s var(--jitter-expo),transform .28s var(--jitter-expo),visibility .28s;
  }
  .mobile-menu.is-open{opacity:1;transform:none}
  .mobile-menu-inner{padding:18px 6px 12px}
  .mobile-menu-inner>a{min-height:54px;font-size:22px}
  .mobile-locations{margin:14px 0}
  .mobile-locations a{
    min-height:44px;
    display:flex;
    align-items:center;
    justify-content:center;
  }
  .mobile-locations .mobile-all-places{
    grid-column:1/-1;
    padding-inline:16px;
  }
}

@media(max-width:720px){
  .rail-controls button{width:44px;height:44px}
  .story-hero{padding:76.56px 0 44px}
  .level-track{
    gap:10px;
    padding:0 12px 9px;
    scroll-padding-inline:12px;
  }
  .level-card{
    flex-basis:min(84vw,344px);
    min-height:390px;
    height:min(60svh,460px);
    scroll-snap-stop:always;
  }
  .level-card-copy{padding:18px}
  .service-pill{height:58px;padding:8px 14px 9px;font-size:18px}
  .level-swipe-cue{
    gap:8px;
    /* the cue belongs to the cards above it, so it sits close to them and lets the
       section change below carry the separation */
    margin:16px 16px 0;
    font-size:11.5px;
  }
  /* the label is a plain span now; the drifting arrowheads live in .swipe-mark */
  .level-swipe-cue span{display:inline-block;font-size:inherit;animation:none}
  .swipe-mark{width:30px;height:14px}
  .hero-copy{padding:0 20px 30px}
  .hero-copy h1{font-size:clamp(2.55rem,11vw,3.6rem)}
  #how-it-works{scroll-margin-top:calc(var(--header-h) + 12px)}

  .level-story{padding:53.94px 0 64.38px}
  .level-story-intro{margin-bottom:26px}
  .level-story-intro h2{font-size:clamp(2.8rem,12vw,4rem)}
  .level-story-intro p{font-size:16px}
  .level-story-stage{
    display:grid;
    grid-template-columns:minmax(0,1fr);
  }
  .story-visual-column,.story-visual-stack,.story-steps{display:contents}
  .story-index{
    position:sticky;
    z-index:3;
    top:max(84px,calc(env(safe-area-inset-top) + 76px));
    grid-row:1;
    margin:0 20px 14px;
    padding:5px;
    display:grid;
    grid-template-columns:repeat(4,minmax(0,1fr));
    gap:3px;
    border:1px solid var(--line);
    border-radius:999px;
    background:rgba(255,255,255,.94);
    box-shadow:0 4px 8px rgba(0,0,0,.07);
    backdrop-filter:blur(12px);
  }
  .story-index span{
    min-width:0;
    height:34px;
    display:grid;
    place-items:center;
    overflow:hidden;
    border-radius:999px;
    color:var(--muted);
    font-size:10px;
    font-weight:750;
    white-space:nowrap;
    transition:background-color .24s ease,color .24s ease;
  }
  .story-index .is-active{background:var(--signal-yellow);color:var(--ink)}
  .story-visual{
    position:relative;
    inset:auto;
    width:auto;
    height:clamp(290px,84vw,360px);
    margin:0 20px;
    scroll-snap-align:none;
  }
  .story-visual:nth-child(1){grid-row:2}
  .story-visual:nth-child(2){grid-row:4}
  .story-visual:nth-child(3){grid-row:6}
  .story-visual:nth-child(4){grid-row:8}
  .story-step{
    min-height:0;
    margin:0 20px;
    padding:20px 0 54px;
    border-bottom:1px solid var(--line);
  }
  .story-step:nth-child(1){grid-row:3}
  .story-step:nth-child(2){grid-row:5}
  .story-step:nth-child(3){grid-row:7}
  .story-step:nth-child(4){grid-row:9;border-bottom:0}
  .story-step h3{font-size:clamp(2.25rem,10vw,3.25rem)}
  .story-step p{margin-top:16px;font-size:16px}
  .story-step ul{margin-top:18px}
  .story-step li{padding:10px 0;font-size:14px}
  .story-promise{margin-top:8px}

  .footer-directory{
    padding:52px 20px 38px;
    border-radius:0 0 24px 24px;
  }
  .footer-directory-grid{grid-template-columns:1fr 1fr;gap:32px 22px}
  .footer-directory-brand{grid-column:1/-1}
  .footer-directory-brand img{width:44px;height:44px}
  .footer-directory-brand>span{font-size:23px}
  .footer-column--places{
    grid-column:1/-1;
    display:grid;
    grid-template-columns:1fr 1fr;
    column-gap:18px;
  }
  .footer-column--places h3{grid-column:1/-1}
  .footer-column a{min-height:44px;margin:0;display:flex;align-items:center}
  .footer-column{min-width:0}
  .footer-column a{
    max-width:100%;
    overflow-wrap:anywhere;
  }
  .footer-directory-bottom{margin-top:38px;gap:12px}
  .footer-newsletter-stage{
    min-height:max(884px,100svh);
    padding:72.38px 20px max(72.38px,env(safe-area-inset-bottom));
    align-content:center;
    gap:38px;
  }
  .footer-mark img,.footer-motion img{width:96px}
  .footer-newsletter h2{font-size:clamp(2.55rem,11vw,3.35rem)}
  .footer-newsletter .newsletter-form{margin-top:28px}
  .footer-newsletter .newsletter-line{
    display:grid;
    grid-template-columns:1fr;
    gap:10px;
    background:transparent;
    /* stacked: the bar is no longer a bar, so the pill cap does not apply and
       the confirmation sweep must not round itself over two stacked rows */
    border-radius:0;
  }
  .footer-newsletter .newsletter-line input{
    width:100%;
    min-width:0;
    min-height:56px;
    padding:0 16px;
    border-radius:10px;
    background:#2c2831;
  }
  .footer-newsletter .newsletter-line button{
    width:100%;
    min-height:54px;
    margin:0;
  }

  .story-link,
  .place-text-link,
  .service-text-link,
  .place-next>a{
    min-height:44px;
    display:inline-flex;
    align-items:center;
  }

  .place-hero h1{font-size:clamp(2.85rem,14vw,4rem)}
  .place-opportunity h2,
  .place-build-heading h2,
  .place-faq .faq-heading h2{font-size:clamp(2.55rem,12vw,3.8rem)}
  .places-hero{padding:75.77px 20px 62.64px}
  .places-hero h1{font-size:clamp(2.75rem,13vw,3.8rem)}
  .places-directory{padding-top:73.08px;padding-bottom:73.08px}
  .places-directory-head{margin-bottom:36px;gap:20px}
  .places-directory-head h2{font-size:clamp(2.4rem,11vw,3.5rem)}
  .final-cta h2{font-size:clamp(2.5rem,12vw,4rem)}
  .page-hero h1,
  .section-head h2,
  .cta-band h2{font-size:clamp(2.5rem,12vw,3.8rem)}
}

@media(max-width:360px){
  .story-index span{font-size:9px}
  .footer-directory-grid{grid-template-columns:1fr}
  .footer-directory-brand,
  .footer-column--places{grid-column:1}
  .footer-column--places{grid-template-columns:1fr}
  .footer-newsletter h2{font-size:clamp(2.3rem,12vw,2.8rem)}
}

@media(prefers-reduced-motion:reduce){
  .level-swipe-cue span,
  .swipe-mark-head{animation:none}
}

/* 2026-07 stacked service story, connected portfolio and footer face */

.portfolio-ui{
  position:absolute;
  inset:0;
  overflow:hidden;
  display:flex;
  flex-direction:column;
  gap:14px;
  padding:24px;
  background:
    radial-gradient(circle at 84% 12%,rgb(124 58 237 / .2),transparent 30%),
    #19171c;
  color:#fff;
  font-family:var(--sans);
}
.portfolio-ui-bar{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:16px;
  font-size:14px;
}
.portfolio-ui-bar>i{
  display:flex;
  align-items:center;
  gap:6px;
  padding:6px 9px;
  border-radius:999px;
  background:rgb(245 255 99 / .12);
  color:var(--signal-yellow);
  font-size:10px;
  font-style:normal;
  font-weight:750;
}
.portfolio-ui-bar>i>em{
  width:7px;
  height:7px;
  border-radius:50%;
  background:var(--signal-yellow);
  box-shadow:0 0 8px rgb(245 255 99 / .7);
}
.portfolio-ui-metrics{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.portfolio-ui-metrics>b{
  min-width:0;
  padding:13px;
  border-radius:10px;
  background:#29262d;
  color:#fff;
  font-size:18px;
  line-height:1.05;
}
.portfolio-ui-metrics small{
  display:block;
  margin-bottom:7px;
  color:#aaa5af;
  font-size:9px;
  font-weight:600;
}
.portfolio-ui-properties{
  min-height:0;
  flex:1;
  display:flex;
  flex-direction:column;
  gap:7px;
}
.portfolio-ui-properties>span{
  min-height:0;
  flex:1;
  padding:8px 10px;
  display:grid;
  grid-template-columns:54px minmax(0,1fr) auto;
  align-items:center;
  gap:10px;
  border-radius:10px;
  background:#f3f3f5;
  color:var(--ink);
}
.portfolio-ui-properties b{min-width:0;font-size:12px;line-height:1.1}
.portfolio-ui-properties b small{display:block;margin-top:5px;color:var(--muted);font-size:9px;font-weight:500}
.portfolio-ui-properties>span>em{color:var(--teal-dark);font-size:9px;font-style:normal;font-weight:750}
.portfolio-thumb{width:54px;height:100%;min-height:42px;border-radius:7px;background:center/cover no-repeat}
.portfolio-thumb--lake{background-image:url("../public/img/gallery-lakefront-living.jpg")}
.portfolio-thumb--coast{background-image:url("../public/img/gallery-coastal-pool.jpg")}
.portfolio-thumb--alpine{background-image:url("../public/img/gallery-alpine-bedroom.jpg")}
.portfolio-ui-flow{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}
.portfolio-ui-flow i{
  position:relative;
  padding:8px 4px;
  overflow:hidden;
  border-radius:7px;
  background:#332e39;
  color:#cbc6d0;
  font-size:9px;
  font-style:normal;
  font-weight:700;
  text-align:center;
}
.portfolio-ui-flow i::after{
  content:"";
  position:absolute;
  inset:auto 0 0;
  height:2px;
  background:var(--signal-blue);
  transform:scaleX(.2);
  transform-origin:left;
}
.portfolio-ui-flow i:nth-child(2)::after{background:var(--signal-yellow)}
.portfolio-ui-flow i:nth-child(3)::after{background:var(--teal)}
.portfolio-ui-flow i:nth-child(4)::after{background:#fff}
.portfolio-ui--hero{padding:20px 18px 74.82px}
.portfolio-ui--hero .portfolio-ui-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}
.portfolio-ui--hero .portfolio-ui-properties>span{grid-template-columns:44px minmax(0,1fr) auto}
.portfolio-ui--hero .portfolio-thumb{width:44px}
.portfolio-ui--hero .portfolio-ui-flow{display:none}

@keyframes portfolio-connect{
  0%,16%{transform:scaleX(.12);opacity:.45}
  46%,82%{transform:scaleX(1);opacity:1}
  100%{transform:scaleX(.12);opacity:.45}
}
@keyframes portfolio-live{
  0%,100%{box-shadow:0 0 0 0 rgb(245 255 99 / .32)}
  50%{box-shadow:0 0 0 7px rgb(245 255 99 / 0)}
}
.story-step.is-active .portfolio-ui-flow i::after,
.level-card--elite:hover .portfolio-ui-flow i::after{
  animation:portfolio-connect 4.2s var(--ease-out) infinite;
}
.story-step.is-active .portfolio-ui-flow i:nth-child(2)::after{animation-delay:.22s}
.story-step.is-active .portfolio-ui-flow i:nth-child(3)::after{animation-delay:.44s}
.story-step.is-active .portfolio-ui-flow i:nth-child(4)::after{animation-delay:.66s}
.story-step.is-active .portfolio-ui-bar>i>em{animation:portfolio-live 1.8s ease-out infinite}

.level-story{padding:75.47px var(--gutter) 85.8px}
.level-story-stage{width:min(100%,var(--max));display:block;margin:auto}
.story-stack{position:relative}
.story-step{
  position:sticky;
  /* the floating header pill bottoms out ~42px below --header-h (24px of header
     padding plus the taller scrolled pill), so park the cards clear of it or
     they tuck under the nav with no breathing room */
  /* each card parks 14px lower than the one behind it, so the incoming card
     covers its predecessor completely while leaving a thin edge showing */
  top:calc(var(--header-h) + 64px + var(--stack-index) * 14px);
  z-index:calc(2 + var(--stack-index));
  min-height:0;
  margin:0 0 clamp(87.36px,10.332vh,101.02px);
  padding:0;
  display:block;
  opacity:1;
  /* NOTE: the last card gets margin-bottom:0 below - its trailing margin used to
     stack on the section padding and blow the gap to the showreel out to 373px */
  transform:none;
  border:0;
}
.story-stack .story-step:last-child{margin-bottom:0}
.story-stack-card{
  position:relative;
  top:auto;
  height:auto;
  /* every card in the stack must clear the tallest natural card, otherwise a
     shorter one pins on top and the card behind pokes out under it */
  min-height:clamp(680px,72vh,800px);
  overflow:clip;
  display:grid;
  grid-template-columns:minmax(0,.9fr) minmax(460px,1.1fr);
  border-radius:16px;
  background:var(--story-surface);
  box-shadow:0 8px 8px rgb(25 23 28 / .1);
}
.story-step--entry{--story-surface:#f1f1f3}
.story-step--growth{--story-surface:#e4f7ff}
.story-step--scale{--story-surface:#eee8fb}
.story-step--elite{--story-surface:#fbffd5}
.story-stack-card::before{display:none}
.story-card-copy{
  min-width:0;
  padding:clamp(42px,4.25vw,64px);
  display:flex;
  flex-direction:column;
  justify-content:center;
}
.story-card-level{
  width:max-content;
  margin-bottom:24px;
  padding:7px 11px;
  border-radius:999px;
  background:color-mix(in srgb,var(--story-surface) 65%,white);
  color:var(--ink);
  font-size:13px;
  font-weight:750;
}
.story-card-level b{margin-right:7px;color:color-mix(in srgb,var(--ink) 52%,transparent)}
.story-card-copy h3{max-width:560px;color:var(--ink);font-size:clamp(2.5rem,3.6vw,4.15rem)}
.story-card-copy>p{margin-top:22px;color:var(--muted);font-size:17px;line-height:1.52}
.story-card-copy ul{margin:24px 0 0;padding:0;list-style:none}
.story-card-copy li{padding:10px 0;border-bottom:1px solid rgb(25 23 28 / .12);font-size:14px}
.story-card-copy .story-link{margin-top:22px}
.story-stack .story-visual{
  position:relative;
  inset:auto;
  width:auto;
  height:auto;
  min-height:0;
  margin:0;
  border-radius:0;
  opacity:1;
  transform:none;
  box-shadow:none;
  border:0;
  pointer-events:auto;
}
.story-stack .story-visual--entry::after,
.story-stack .story-visual--scale::after,
.story-stack .story-visual--elite::after{display:none}
.story-stack .story-visual--entry video,
.story-stack .story-visual--scale>img{width:100%;height:100%;object-fit:cover}
.story-stack .story-visual--growth{background:#d8f3ff}
.story-stack .story-visual--elite{padding:0;background:#151218}
.story-stack .story-visual--elite>img{width:100%;height:100%;object-fit:cover}
.story-stack .story-visual--elite>img{object-position:60% center}
.story-stack .story-visual--elite .portfolio-ui{position:relative;width:100%;height:100%;border-radius:12px}
.story-stack .story-visual-caption{z-index:3}
.story-promise{margin-top:40px}

/* Pricing is intentionally paused for launch. Restore by removing this rule.
   Since 2 Sep 2026 the site publishes no prices at all, so un-hiding this
   brings back the plan cards reading "On request", not a price list.
   scripts/qa-pricing.mjs enforces that. */
.pricing-section,
.place-pricing{display:none}

.footer-newsletter .form-status.is-error{color:#ffb5ae}
.footer-newsletter .form-status.is-success{color:var(--signal-yellow)}
.footer-newsletter .newsletter-line button:disabled{opacity:.62;cursor:wait}

@media(max-width:1050px), (max-height:740px){
  .level-story{padding:71.76px 32px 74.88px}
  .level-story-intro{padding:0;margin-bottom:48px}
  .story-step,.story-step--elite{position:relative;top:auto;min-height:0;margin-bottom:18px}
  .story-stack-card{
    position:relative;
    top:auto;
    height:auto;
    min-height:620px;
    grid-template-columns:minmax(0,.95fr) minmax(360px,1.05fr);
  }
}

@media(max-width:720px){
  .portfolio-ui--hero{padding:17px 14px 67.86px;gap:10px}
  .portfolio-ui--hero .portfolio-ui-bar{font-size:11px}
  .portfolio-ui--hero .portfolio-ui-metrics>b{padding:10px;font-size:15px}
  .portfolio-ui--hero .portfolio-ui-properties>span{grid-template-columns:38px minmax(0,1fr) auto}
  .portfolio-ui--hero .portfolio-thumb{width:38px}
  .level-story{padding:59.16px 20px 67.86px}
  .level-story-intro{padding:0;margin-bottom:32px}
  .story-stack-card{display:flex;min-height:0;flex-direction:column;border-radius:14px}
  .story-card-copy{padding:44px 24px 30px}
  .story-card-level{margin-bottom:20px}
  .story-card-copy h3{font-size:clamp(2.35rem,10vw,3.2rem)}
  .story-card-copy>p{margin-top:17px;font-size:16px}
  .story-card-copy ul{margin-top:18px}
  .story-stack .story-visual{
    height:clamp(330px,88vw,430px);
    flex:0 0 auto;
    border-inline-start:0;
    border-top:1px solid rgb(25 23 28 / .18);
  }
  .story-step--scale .story-visual{border-top-color:rgb(255 255 255 / .22)}
  .story-stack .story-visual--growth{height:400px}
  .story-stack .story-visual--elite{height:500px;padding:0}
  .story-stack .story-visual--elite .portfolio-ui{padding:16px 14px 81.12px}
  .story-stack .story-visual--elite .portfolio-ui-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}
  .story-stack .story-visual--elite .portfolio-ui-metrics>b:last-child{display:none}
  .story-promise{margin-top:36px}
}

@media(prefers-reduced-motion:reduce){
  .story-step,.story-step--elite{position:relative;top:auto;min-height:0;margin-bottom:18px}
  .story-stack-card{position:relative;top:auto;height:auto;min-height:600px}
  .portfolio-ui-flow i::after{transform:scaleX(1)}
}

/* ------------------------------------------------------------------
   Drawn arrows.
   Never type an arrow character into the markup or into CSS `content`.
   U+2192 and friends are glyphs, so every operating system draws its own
   (Apple renders them at emoji weight, in its own colour), which is why the
   site read as stock iOS. These are drawn once, inherit currentColor, and
   look identical on every platform.
   ------------------------------------------------------------------ */
.ds-arrow{
  display:inline-block;
  width:.92em;
  height:.92em;
  flex:none;
  vertical-align:-.1em;
  overflow:visible;
  /* the shafts are gently bowed rather than ruler-straight, to sit with the
     hand-drawn brand marks instead of looking like a system icon set */
  fill:none;
  stroke:currentColor;
  stroke-width:1.7;
  stroke-linecap:round;
  stroke-linejoin:round;
}
.ds-arrow--lead{margin-right:.15em}
.ds-arrow--trail{margin-left:.12em}

/* pseudo-element arrows: masked so they still inherit colour and can animate */
.ds-mask{
  -webkit-mask-repeat:no-repeat;
  mask-repeat:no-repeat;
  -webkit-mask-position:center;
  mask-position:center;
  -webkit-mask-size:contain;
  mask-size:contain;
  background:currentColor;
}

/* ---------- newsletter signup confirmation ----------
   One driver: the .is-subscribed class on the form. Everything below derives
   its timing from that single flip so the sweep, the tick and the copy land as
   one gesture rather than three unrelated fades.
   Failure mode to avoid: the row visibly re-flowing when the label swaps to a
   tick - the button keeps its resting min-width so nothing jumps. */
.newsletter-line{position:relative;overflow:hidden}
.newsletter-line::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:0;
  transform:scaleX(0);
  transform-origin:left center;
  background:var(--signal-yellow);
  opacity:.16;
  pointer-events:none;
}
.newsletter-form.is-subscribed .newsletter-line::after{
  animation:ns-sweep 620ms cubic-bezier(.22,.8,.24,1) forwards;
}
@keyframes ns-sweep{
  0%  {transform:scaleX(0);opacity:.30}
  60% {transform:scaleX(1);opacity:.30}
  100%{transform:scaleX(1);opacity:0}
}

.newsletter-form.is-subscribed .newsletter-line input{
  opacity:0;
  transition:opacity 220ms ease 60ms;
}

.ns-tick{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px}
.ns-tick svg{width:100%;height:100%;overflow:visible}
.ns-tick path{
  fill:none;
  stroke:currentColor;
  stroke-width:2.6;
  stroke-linecap:round;
  stroke-linejoin:round;
  stroke-dasharray:32;
  stroke-dashoffset:32;
  animation:ns-draw 380ms cubic-bezier(.65,0,.35,1) 300ms forwards;
}
@keyframes ns-draw{to{stroke-dashoffset:0}}

/* The sweep is a wash behind the controls, never over them. */
.newsletter-line input,
.newsletter-line button{position:relative;z-index:1}

/* The .6 disabled dim is the "Subscribing…" wait cue and should stay for that.
   Once confirmed the button is disabled for behaviour only, so it holds full
   brand colour - otherwise the yellow reads as a dead olive. */
.newsletter-form.is-subscribed .newsletter-line button:disabled{opacity:1;cursor:default}
.newsletter-form.is-subscribed .newsletter-line button{
  background:var(--signal-yellow);
  color:var(--ink);
  animation:ns-settle 520ms cubic-bezier(.22,.8,.24,1) 240ms both;
}
@keyframes ns-settle{
  0%  {transform:scale(1)}
  38% {transform:scale(1.045)}
  100%{transform:scale(1)}
}

.newsletter-form.is-subscribed .form-status{
  animation:ns-rise 320ms cubic-bezier(.22,.8,.24,1) 420ms both;
}
@keyframes ns-rise{
  from{opacity:0;transform:translateY(7px)}
  to  {opacity:1;transform:none}
}

@media(prefers-reduced-motion:reduce){
  .newsletter-form.is-subscribed .newsletter-line::after,
  .newsletter-form.is-subscribed .newsletter-line button,
  .newsletter-form.is-subscribed .form-status,
  .ns-tick path{animation:none}
  .ns-tick path{stroke-dashoffset:0}
  .newsletter-form.is-subscribed .newsletter-line input{transition:none}
}

/* High-visibility in-page CTAs: these were previously easy to mistake for body links. */
.story-link,
.place-text-link{
  display:inline-flex;
  min-height:58px;
  align-items:center;
  justify-content:center;
  gap:8px;
  padding:15px 26px;
  border-radius:999px;
  background:rgba(124, 58, 237, 0.08);
  color:var(--navy);
  border:1.5px solid rgba(124, 58, 237, 0.24);
  font-size:16px;
  font-weight:750;
  line-height:1.1;
  text-decoration:none;
  transition:transform .4s var(--ease),background-color .4s var(--ease),border-color .4s var(--ease),color .4s var(--ease);
}
.story-link:hover,
.place-text-link:hover{
  background:rgba(124, 58, 237, 0.16);
  color:var(--navy-2);
  border-color:var(--teal);
  transform:translateY(-1px);
}
.story-link .ds-arrow,
.place-text-link .ds-arrow{width:16px;height:16px}

@media(max-width:720px){
  .place-hero-actions{align-items:stretch}
  .place-hero-actions>.btn,
  .place-hero-actions>.place-text-link{width:100%}
  .story-link{width:100%;min-height:62px}
}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ---- WhatsApp contact button ---- */
/* Desktop: a pill in the header row, where it has always lived.
   Phone/tablet: that row cannot carry brand + WhatsApp + CTA + menu inside
   350px (the hamburger shipped 31px off-screen), and a thumb reaches the
   bottom-right corner far more easily than the top bar, so it floats instead.
   The button is ONE node that js/site.js moves between the header and the body
   at the breakpoint - it cannot simply be positioned out of the header,
   because .nav-shell sets both a transform and a backdrop-filter and either
   one makes it the containing block for a position:fixed descendant. */
.nav-wa{
  flex:0 0 auto;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:52px;
  height:52px;
  margin-right:10px;
  border-radius:50%;
  background:var(--ink);
  color:var(--white);
  text-decoration:none;
  transition:transform .6s var(--jitter-card),background-color .3s var(--jitter-soft),color .3s var(--jitter-soft);
}
.nav-wa svg{width:24px;height:24px;fill:currentColor}
.nav-wa:hover{background:#25d366;color:var(--white);transform:scale(1.05)}
.nav-wa:active{transform:scale(.9);transition-duration:.1s}
.nav-wa:focus-visible{outline:2px solid var(--signal-blue);outline-offset:3px}
body[data-theme="navy"] .nav-wa{background:var(--cloud);color:var(--navy)}
body[data-theme="navy"] .nav-wa:hover{background:#25d366;color:var(--white)}
.site-header.header-compact .nav-wa{transform:translateX(-67px)}
.site-header.header-compact .nav-wa:hover{transform:translateX(-67px) scale(1.05)}

@media(max-width:1050px){
  .nav-wa{
    position:fixed;
    z-index:calc(var(--z-header) + 1);
    right:16px;
    bottom:16px;
    width:56px;
    height:56px;
    margin:0 0 env(safe-area-inset-bottom,0px);
    background:#25d366;
    color:var(--white);
    box-shadow:0 8px 22px rgb(9 22 14 / .3);
    transition:transform .45s var(--jitter-card),background-color .3s var(--jitter-soft);
  }
  .nav-wa svg{width:29px;height:29px}
  .nav-wa:hover{background:#1fbe5a}
  body[data-theme="navy"] .nav-wa{background:#25d366;color:var(--white)}
  /* a corner-anchored button must not ride the compact-header slide */
  .site-header.header-compact .nav-wa,
  .site-header.header-compact .nav-wa:hover{transform:none}
  /* the button is already on the page, so the duplicate in the menu is noise */
  .mobile-menu-wa{display:none}
}

.mobile-menu-wa{
  display:flex;
  flex:1;
  align-items:center;
  gap:12px;
  justify-content:center;
  min-height:58px;
  padding:0 12px;
  border:0;
  border-radius:999px;
  background:#25d366;
  color:var(--white);
  font-family:var(--sans);
  font-size:15px;
  font-weight:700;
  text-decoration:none;
}
.mobile-menu-wa svg{width:20px;height:20px;flex:none;fill:currentColor}

/* the button no longer lives in the header, so the compact-header slide and
   the small-screen hide that used to apply to it are gone: a corner-anchored
   contact button should stay put and stay reachable at every width */
@media(prefers-reduced-motion:reduce){
  .nav-wa{transition:none}
  .nav-wa:hover,.nav-wa:active{transform:none}
}

/* ---------- ANIM-06 footer coin flick ----------
   The approved badge stays a static image. The coin is a separate SVG layer
   sized to the MEASURED img box (the grid cell is wider than the badge, so
   inset:0 on the cell would desync the coin from the three img breakpoints).
   overflow:visible is load-bearing: the arc peaks above the badge circle. */
.footer-mark,.footer-motion{position:relative;overflow:visible}
.footer-mark img,.footer-motion img{will-change:transform}
.coin-layer{
  position:absolute;
  left:50%;
  top:50%;
  margin:0;
  overflow:visible;
  pointer-events:none;
  transform:translate(-50%,-50%);
}
.coin-layer text{
  font-family:var(--sans);
  font-weight:800;
  fill:#4C1D95;
  text-anchor:middle;
  dominant-baseline:central;
}
.footer-mark.is-coin-ready{cursor:pointer}

/* Compact mobile footer.
   The full-height newsletter stage and the 44px-per-row directory were adding
   the best part of two screens of footer on a phone. Below 720px the columns
   become wrapping chips and the newsletter drops to the same quiet weight as
   the copyright line, so the footer reads as a footer rather than a section.
   Every link stays in the DOM: this is a density change, not a cull. */
@media(max-width:720px){
  .footer-directory{padding:40px 20px 26px;border-radius:0 0 20px 20px}
  .footer-directory-grid{grid-template-columns:1fr;gap:26px}
  .footer-directory-brand{grid-column:1;gap:10px}
  .footer-directory-brand img{width:46px;height:46px}
  .footer-directory-brand>span{font-size:23px}

  .footer-column{display:flex;flex-flow:row wrap;align-items:flex-start;gap:8px}
  .footer-column h3{width:100%;margin-bottom:5px;font-size:14px;letter-spacing:.02em;opacity:.68}
  .footer-column--places{display:flex;flex-flow:row wrap;grid-column:1;grid-template-columns:none}
  .footer-column--places h3{grid-column:auto}
  /* 44px, not 36. This is a tap target, and 36 fails the 44 minimum on every
     platform guideline there is. The type comes up with it - 13px chips read
     as fine print next to the 17px newsletter heading beside them. */
  .footer-column a{
    min-height:44px;
    padding:0 15px;
    display:inline-flex;
    align-items:center;
    border:1px solid rgba(16,37,60,.12);
    border-radius:999px;
    font-size:15px;
    line-height:1;
    white-space:nowrap;
    overflow-wrap:normal;
  }
  .footer-column a .ds-arrow{display:none}

  .footer-directory-bottom{margin-top:28px;gap:10px;font-size:13px}

  .footer-newsletter-stage{
    min-height:0;
    padding:34px 20px max(34px,env(safe-area-inset-bottom));
    grid-template-columns:1fr;
    gap:14px;
    align-content:start;
  }
  /* Coin stays present (Reuben likes it live on every page) but shrinks hard
     so it doesn't reintroduce the "two screens of footer" problem this block
     was written to fix. justify-self:start keeps it left-aligned with the
     heading instead of the old centred desktop placement. */
  .footer-mark{justify-self:start}
  .footer-mark img,.footer-motion img{width:76px}
  .footer-newsletter h2{
    max-width:none;
    font-size:20px;
    font-weight:700;
    letter-spacing:-.01em;
    line-height:1.3;
  }
  .footer-newsletter .newsletter-form{margin-top:14px}
  .footer-newsletter .newsletter-line{gap:8px}
  .footer-newsletter .newsletter-line input{min-height:48px}
  .footer-newsletter .newsletter-line button{min-height:48px}
  .footer-newsletter .form-status,
  .footer-newsletter .form-privacy{font-size:13px}
}

@media(max-width:360px){
  .footer-column a{font-size:14px;padding:0 12px}
}

/* The Build and Talk columns are BACK on a phone, and this is load-bearing.
   They used to be hidden here because the mobile menu carried the same links.
   The menu has since been cut back to the four destinations the desktop header
   carries, so hiding these columns would leave Website + Google, Booking
   automation, Complete booking package, Answers, About and Contact with no
   mobile route at all. The menu is for choosing, the footer is the directory. */
@media(max-width:720px){
  .footer-directory-grid{gap:24px}
}

/* The menu now carries the links the footer used to. The panel already scrolls
   (.mobile-menu is overflow:auto), so the only thing missing was clearance for
   the home indicator under the last row. A nested scroller on the inner fights
   the panel's own and strands the last link, so do not add one. */
@media(max-width:900px){
  .mobile-menu{padding-bottom:max(24px,env(safe-area-inset-bottom))}
  .mobile-menu-inner{min-height:0}
}

/* The homepage compact footer is the shared site footer. These rules live in
   the area-page bundle as well as site.css so generated location pages render
   the same component without loading a second global stylesheet. */
.footer-directory--compact{
  padding-top:clamp(44px,4.5vw,58px);
  padding-bottom:44px;
}
.footer-directory-grid--compact{
  grid-template-columns:minmax(220px,.82fr) minmax(460px,1.6fr) minmax(250px,.83fr);
  align-items:start;
  gap:clamp(32px,4vw,64px);
}
.footer-link-columns{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(128px,1fr));
  gap:28px 32px;
}
.footer-link-col{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:9px;
}
.footer-link-heading{
  font-size:11px;
  font-weight:700;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:rgba(16,37,60,.5);
  margin-bottom:2px;
}
.footer-link-col a,
.footer-compact-email,
.footer-compact-cta{
  color:#47434b;
  text-decoration:none;
  font-size:15px;
  line-height:1.5;
  transition:color .25s var(--ease);
}
.footer-link-col a:hover,
.footer-compact-email:hover{color:var(--teal)}
.footer-compact-connect{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:10px;
}
.footer-compact-cta{
  display:inline-flex;
  min-height:48px;
  align-items:center;
  justify-content:center;
  gap:6px;
  padding:0 18px;
  border:1px solid var(--ink);
  border-radius:999px;
  background:var(--ink);
  color:var(--white);
  font-weight:700;
  transition:transform .25s var(--ease),background-color .25s var(--ease),border-color .25s var(--ease),color .25s var(--ease);
}
.footer-compact-cta:hover{border-color:var(--teal-dark);background:var(--teal-dark);color:var(--white);transform:translateY(-1px)}
.footer-socials{
  margin-top:10px;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:7px;
}
.footer-social-icon{
  width:38px;
  height:38px;
  display:grid;
  place-items:center;
  border:1px solid #d4d1d8;
  border-radius:50%;
  color:#6b6670;
  transition:background-color .25s var(--ease),border-color .25s var(--ease),color .25s var(--ease);
}
.footer-social-icon:hover{
  border-color:var(--teal);
  background:var(--teal);
  color:var(--white);
}
.footer-social-icon svg{
  width:19px;
  height:19px;
  display:block;
  fill:currentColor;
}
.footer-directory--compact .footer-directory-bottom{margin-top:36px}
/* The fixed 50svh .footer-directory height leaves the legal row only ~6px of
   air beneath it, so it reads as sitting on the footer's bottom edge. Lift the
   whole row so the text lands between roughly equal gaps. Desktop only: below
   901px the footer is auto-height and already has room to spare. This has to
   sit after the .footer-directory--compact and .footer-directory-bottom rules
   above, which match at equal specificity and would otherwise win on order. */
@media(min-width:901px){
  .footer-directory--compact .footer-directory-bottom{margin-top:20px}
  .footer-directory-bottom{padding-top:24px}
}
.footer-directory--compact .footer-legal{
  padding:0;
  flex-direction:row;
  justify-content:flex-end;
}

@media(max-width:1050px){
  .footer-directory-grid--compact{grid-template-columns:1fr 1fr}
  .footer-directory-grid--compact .footer-directory-brand{grid-column:1/-1}
}

@media(max-width:720px){
  .footer-directory-grid--compact{grid-template-columns:1fr;gap:24px}
  .footer-link-columns{display:flex;flex-wrap:wrap;gap:8px}
  .footer-link-col{display:contents}
  .footer-link-heading,
  .footer-link-col a.footer-city-link{display:none}
  .footer-link-col a,
  .footer-compact-email,
  .footer-compact-cta{
    min-height:44px;
    padding:0 14px;
    display:inline-flex;
    align-items:center;
    border:1px solid rgba(16,37,60,.12);
    border-radius:999px;
    font-size:15px;
    line-height:1;
  }
  .footer-compact-connect{gap:8px}
  .footer-compact-email,
  .footer-compact-cta{width:100%;justify-content:space-between}
  .footer-compact-cta{border-color:var(--ink)}
  .footer-socials{margin-top:8px}
  .footer-social-icon{width:42px;height:42px}
  .footer-social-icon svg{width:20px;height:20px}
  .footer-directory--compact .footer-directory-bottom{margin-top:24px}
}


/* ---------- keep-running: the phone-only build routes ----------
   Hidden on desktop by default, not shown by a max-width query, so a new
   breakpoint added above 720 cannot accidentally reveal it. */
.keep-running__build{display:none}

@media(max-width:720px){
  .keep-running__build{
    display:grid;
    gap:10px;
    width:100%;
    max-width:420px;
    margin:22px auto 0;
  }
  .keep-running__build-label{
    margin:0 0 2px;
    font-size:14px;
    letter-spacing:.02em;
    opacity:.66;
    text-align:center;
  }
  /* Full width and 52px tall: these sit directly under a btn-large, and three
     shrink-to-fit pills under one full-width button reads as an afterthought
     rather than a second choice. */
  .keep-running__build .btn{
    width:100%;
    min-height:52px;
    justify-content:center;
  }
}

/* ==== area-pages-shell.css ====================================== */
/*
 * layout-shell.css - the outer edges of the page, in one place.
 *
 * Loaded LAST on every page so it beats the per-page overrides.
 *
 * The problem it fixes: most bands sat on the --max (1344px) grid, but a
 * handful padded straight off var(--gutter), so on a wide monitor they ran
 * ~1632px and read as "that section is wider than the others". Here the
 * background band still goes full bleed; only the CONTENT is pulled back to
 * the same left and right edge as everything else.
 *
 * Below 1440px the max() collapses to var(--gutter), so mobile and laptop
 * are untouched.
 */

:root{
  --shell-pad:max(var(--gutter),calc((100% - var(--max)) / 2));
}

html{
  scroll-behavior:smooth;
  scroll-padding-top:clamp(100px, 14vh, 140px);
}

.page-hero,
.place-hero,
.place-opportunity,
.place-build,
.place-pricing,
.place-faq,
.place-next,
.faq-section{
  padding-inline:var(--shell-pad)!important;
}

/* photo-flick sets its own padding at .photo-flick.is-enhanced specificity,
   so drive it through its own token rather than fighting the cascade. */
.photo-flick{--flick-pad-x:var(--shell-pad)}

/* The four hero service cards were the loudest mismatch: 1632px wide with the
   1344px story section directly underneath them. */
.hero-levels{width:min(100%,var(--max))}
/* Deliberately NOT touching .hero-copy: service-vibrancy.css stretches it on
   purpose and centres the headline with justify-content. Capping its width
   left-aligns the whole hero headline. See the comment at service-vibrancy.css
   .hero-copy before changing this. */

/* Live-example strip removed from the hero, so close the gap it was holding
   open between the four cards and the section heading below. */
.story-hero{padding-bottom:40px}
.level-story{padding-top:44px}

/* ---------------------------------------------------------------------------
 * Header clearance.
 *
 * The floating nav pill sits 34px from the top and is 100px tall, so it bottoms
 * out at 134px. --header-h still reads 92px (the older pill), so any hero that
 * padded off --header-h - or off a hardcoded ~97px - had its eyebrow and the
 * top of its h1 sitting underneath the pill. contact.css already carries this
 * fix inline; these are the remaining heroes with the same bug.
 * ------------------------------------------------------------------------- */
.place-hero,
.service-page > .service-motion-hero,
.launch-hero,
.page-hero,
.places-hero{
  padding-top:clamp(140px, 16vh, 180px)!important;
}

@media(max-width:1024px){
  /* pill drops to top:12px, height:64px, so it bottoms out at 76px */
  .place-hero,
  .service-page > .service-motion-hero,
  .launch-hero,
  .page-hero,
  .places-hero{
    padding-top:clamp(100px, 13vh, 128px)!important;
  }
}

/* ---------------------------------------------------------------------------
 * The closing CTA on /faq.
 *
 * service-pages.css only centres this band under `.service-page > .service-cta`,
 * and /faq's main is `.faq-page`, so the band inherited the bare `.service-cta`
 * type rules: a 6.8rem headline, left aligned, with `padding:78px 0` and no
 * gutter at all. Give it the same centred treatment, at a headline size that
 * fits the measure.
 * ------------------------------------------------------------------------- */
.faq-page>.service-cta{
  min-height:0;
  padding:clamp(84px,10vh,118px) var(--shell-pad)!important;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  text-align:center;
}
.faq-page>.service-cta h2{
  max-width:900px;
  margin-inline:auto;
  font-size:clamp(2.6rem,5.2vw,4.4rem);
  line-height:1.02;
}
.faq-page>.service-cta p{max-width:620px;margin-inline:auto}

/* ---------------------------------------------------------------------------
 * Locality index.
 *
 * Parent-area pages can carry hundreds of child locations. Keep each letter
 * as one readable row instead of turning uneven groups into equal-height
 * cards. The links then reflow from four columns to one without changing the
 * alphabetical DOM or keyboard order.
 * ------------------------------------------------------------------------- */
.area-review .locations-index--local{
  padding:clamp(84px,8vw,120px) var(--shell-pad) clamp(96px,9vw,136px)!important;
  background:var(--cloud);
  color:var(--ink);
}

.area-review .locations-index--local .locations-index__head,
.area-review .locations-index--local .locations-index__grid{
  width:min(100%,var(--max));
  margin-inline:auto;
}

.area-review .locations-index--local .locations-index__head{
  display:grid;
  grid-template-columns:minmax(0,1.15fr) minmax(280px,.7fr);
  align-items:end;
  gap:clamp(28px,5vw,72px);
  margin-bottom:clamp(52px,6vw,80px);
}

.area-review .locations-index--local .locations-index__head h2{
  max-width:900px;
  font-size:clamp(2.75rem,5vw,5rem);
  line-height:.98;
  letter-spacing:-.04em;
  text-wrap:balance;
}

.area-review .locations-index--local .locations-index__head p{
  max-width:54ch;
  color:var(--muted);
  font-size:clamp(1rem,1.25vw,1.125rem);
  line-height:1.55;
}

.area-review .locations-index--local .locations-index__col{
  display:grid;
  grid-template-columns:56px minmax(0,1fr);
  gap:clamp(18px,2.5vw,34px);
  padding:clamp(24px,2.5vw,34px) 0;
  border-top:1px solid var(--line);
}

.area-review .locations-index--local .locations-index__col:last-child{
  border-bottom:1px solid var(--line);
}

.area-review .locations-index--local .locations-index__col h3{
  margin:0;
  padding-top:8px;
  color:var(--navy);
  font-size:1rem;
  font-weight:700;
  line-height:1;
  letter-spacing:.12em;
  text-transform:uppercase;
}

.area-review .locations-index--local .locations-index__links{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:0 clamp(12px,1.5vw,22px);
  min-width:0;
}

.area-review .locations-index--local .locations-index__links a{
  display:flex;
  min-width:0;
  min-height:48px;
  align-items:center;
  padding:10px 12px;
  border-bottom:1px solid rgb(76 29 149 / .1);
  border-radius:8px 8px 0 0;
  color:var(--ink);
  font-size:clamp(.94rem,1.05vw,1.0625rem);
  font-weight:500;
  line-height:1.3;
  text-decoration:none;
  overflow-wrap:anywhere;
  transition:background-color .2s var(--ease),color .2s var(--ease),padding-left .25s var(--ease-out);
}

@media(hover:hover){
  .area-review .locations-index--local .locations-index__links a:hover{
    padding-left:16px;
    background:rgb(1 178 253 / .1);
    color:var(--navy);
  }
}

.area-review .locations-index--local .locations-index__links a:focus-visible{
  position:relative;
  z-index:1;
  outline:3px solid var(--amber);
  outline-offset:2px;
  background:var(--white);
}

@media(max-width:1180px){
  .area-review .locations-index--local .locations-index__links{grid-template-columns:repeat(3,minmax(0,1fr))}
}

@media(max-width:900px){
  .area-review .locations-index--local .locations-index__head{grid-template-columns:1fr}
  .area-review .locations-index--local .locations-index__links{grid-template-columns:repeat(2,minmax(0,1fr))}
}

@media(max-width:600px){
  .area-review .locations-index--local{
    padding-top:72px!important;
    padding-bottom:88px!important;
  }
  .area-review .locations-index--local .locations-index__head{
    gap:18px;
    margin-bottom:42px;
  }
  .area-review .locations-index--local .locations-index__head h2{
    font-size:clamp(2.35rem,11vw,3.2rem);
  }
  .area-review .locations-index--local .locations-index__col{
    grid-template-columns:1fr;
    gap:10px;
    padding:26px 0;
  }
  .area-review .locations-index--local .locations-index__col h3{padding:0 0 4px}
  .area-review .locations-index--local .locations-index__links{grid-template-columns:1fr}
  .area-review .locations-index--local .locations-index__links a{
    min-height:44px;
    padding:9px 0;
    border-radius:0;
  }
}

/* ==== area-pages-wa.css ========================================= */
/* ------------------------------------------------------------------
   WhatsApp dock.

   Was a small icon buried in the header, competing with the CTA and
   invisible once the visitor scrolled. Now it sits bottom-right, always
   reachable, and asks the question that belongs to whatever section is
   being read.

   Motion constants (see js/wa-dock.js for the timing that pairs with
   these - they have to agree or the text swaps mid-fade):
     entry   560ms cubic-bezier(.22,1,.36,1) from x+18px, scale .94
     swap    170ms out to y-7px, then back in on the same entry curve
   ------------------------------------------------------------------ */

.wa-dock{
  position:fixed;
  z-index:60;
  right:clamp(16px,2.2vw,30px);
  bottom:calc(clamp(16px, 2.2vw, 30px) + env(safe-area-inset-bottom, 0px));
  display:flex;
  align-items:center;
  justify-content:flex-end;
  gap:12px;
  pointer-events:none; /* the gap between bubble and button must not eat clicks */
}

.wa-dock-bubble{
  max-width:min(62vw,290px);
  padding:13px 18px;
  border-radius:18px 18px 4px 18px;
  background:#fff;
  color:var(--ink,#19171c);
  font-family:var(--sans);
  font-size:14.5px;
  font-weight:650;
  line-height:1.32;
  letter-spacing:-.01em;
  text-wrap:balance;
  box-shadow:0 12px 34px rgb(25 23 28 / .18), 0 2px 6px rgb(25 23 28 / .1);
  pointer-events:auto;
  opacity:0;
  transform:translateX(18px) scale(.94);
  transform-origin:100% 100%;
  transition:
    opacity .56s cubic-bezier(.22,1,.36,1),
    transform .56s cubic-bezier(.22,1,.36,1);
}

.wa-dock.is-open .wa-dock-bubble{
  opacity:1;
  transform:none;
}

/* the outgoing state: lifts and fades rather than sliding back out, so a
   change of question reads as a change rather than as a dismissal */
.wa-dock.is-swapping .wa-dock-bubble{
  opacity:0;
  transform:translateY(-7px);
  transition:
    opacity .17s ease,
    transform .17s ease;
}

.wa-dock-btn{
  position:relative;
  width:60px;
  height:60px;
  flex:0 0 auto;
  display:grid;
  place-items:center;
  border-radius:50%;
  background:#25d366;
  color:#fff;
  text-decoration:none;
  pointer-events:auto;
  box-shadow:0 14px 32px rgb(20 90 50 / .34);
  transition:transform .4s cubic-bezier(.22,1,.36,1), box-shadow .4s ease;
}

.wa-dock-btn svg{width:31px;height:31px;fill:currentColor}
.wa-dock-btn:hover{transform:scale(1.06)}
.wa-dock-btn:active{transform:scale(.96)}
.wa-dock-btn:focus-visible{outline:3px solid var(--ink,#19171c);outline-offset:3px}

/* The marketing button: a second, equal-weight CTA that only shows up beside
   WhatsApp on mobile, where the corner is prime real estate and "message us"
   is not the only thing worth putting there. Off by default - only the pages
   that reach this markup (the homepage journey, the CRM tour) get it. */
.wa-dock-btn--marketing{display:none}

/* The visible words on each pill. Hidden everywhere except the mobile pill
   layout below - desktop and the pre-pill mobile state stay icon-only. */
.wa-dock-btn-label{display:none}

@media(max-width:600px){
  .wa-dock-bubble{display:none}

  /* Hidden over the hero - js/wa-dock.js adds .is-past-hero once the hero
     section (the cinematic film, or the CRM page's inbox-converge) scrolls
     out, which is also the moment there is a second CTA worth surfacing. */
  .wa-dock{
    left:16px;
    right:16px;
    justify-content:space-between;
    align-items:stretch;
    flex-wrap:nowrap;
    gap:10px;
    opacity:0;
    transform:translateY(10px);
    pointer-events:none;
    transition:opacity .4s cubic-bezier(.22,1,.36,1),transform .4s cubic-bezier(.22,1,.36,1);
  }

  .wa-dock.is-past-hero{
    opacity:1;
    transform:none;
    pointer-events:auto;
  }

  /* Two equal pills rather than the desktop circle - each takes the same
     share of the corner, per spec. */
  .wa-dock-btn{
    display:flex;
    align-items:center;
    justify-content:center;
    flex:1 1 0;
    width:auto;
    height:auto;
    min-height:54px;
    border-radius:999px;
    padding:8px 14px;
    gap:7px;
  }

  .wa-dock-btn svg{width:20px;height:20px;flex:none}

  .wa-dock-btn-label{
    display:block;
    font-family:var(--sans);
    font-weight:750;
    font-size:12.5px;
    line-height:1.22;
    text-align:center;
  }

  .wa-dock-btn--marketing{
    display:flex;
    background:var(--signal-yellow,#f5ff63);
    color:var(--ink,#19171c);
    box-shadow:0 14px 32px rgb(25 23 28 / .22);
  }
  /* Text-only, to match the reference: the icon would just compete with
     WhatsApp's for attention in a pill this narrow. */
  .wa-dock-btn--marketing svg{display:none}
  .wa-dock-btn--marketing:hover{transform:scale(1.03)}
  .wa-dock-btn--marketing:active{transform:scale(.97)}
  .wa-dock-btn--marketing:focus-visible{outline:3px solid var(--ink,#19171c);outline-offset:3px}
}

/* The dock is fixed over the page, so it will sit on top of the footer's
   newsletter field on short screens. Below this height the bubble is dropped
   and only the button remains. */
@media(max-height:520px){
  .wa-dock-bubble{display:none}
}

@media(prefers-reduced-motion:reduce){
  .wa-dock-bubble,
  .wa-dock.is-swapping .wa-dock-bubble{transition:none;transform:none}
  .wa-dock-btn{transition:none}
}

/* ------------------------------------------------------------------
   The expanded chat panel.

   Hover (or tap, or keyboard focus) grows the small prompt into a real
   conversation: who you are talking to, the message already drafted for
   you, and a few one-tap alternatives. The point is that nobody has to
   think of an opening line - the section they were reading wrote it.

   Motion, matched to the bubble so the two never fight:
     open   420ms cubic-bezier(.22,1,.36,1), from y+16px scale .96
     rows   staggered 40ms apart on the same curve, so the panel
            assembles rather than appearing all at once
   ------------------------------------------------------------------ */

.wa-dock{flex-wrap:wrap}

.wa-panel{
  position:absolute;
  right:0;
  bottom:76px;
  width:min(88vw,344px);
  padding:18px 18px 16px;
  border-radius:22px 22px 6px 22px;
  background:#fff;
  color:var(--ink,#19171c);
  box-shadow:0 26px 60px rgb(25 23 28 / .26), 0 2px 8px rgb(25 23 28 / .12);
  pointer-events:none;
  opacity:0;
  visibility:hidden;
  transform:translateY(16px) scale(.96);
  transform-origin:100% 100%;
  transition:
    opacity .42s cubic-bezier(.22,1,.36,1),
    transform .42s cubic-bezier(.22,1,.36,1),
    visibility 0s linear .42s;
}

.wa-dock.is-expanded .wa-panel{
  opacity:1;
  visibility:visible;
  transform:none;
  pointer-events:auto;
  transition:
    opacity .42s cubic-bezier(.22,1,.36,1),
    transform .42s cubic-bezier(.22,1,.36,1),
    visibility 0s;
}

/* the small prompt steps aside rather than sitting behind the panel */
.wa-dock.is-expanded .wa-dock-bubble{
  opacity:0;
  transform:translateX(10px) scale(.96);
  pointer-events:none;
}

.wa-panel-head{display:flex;align-items:center;gap:11px;padding-bottom:13px;border-bottom:1px solid rgb(25 23 28 / .1)}
.wa-panel-avatar{width:38px;height:38px;flex:0 0 auto;border-radius:50%;overflow:hidden;background:var(--service-scale,#7c3aed)}
.wa-panel-avatar img{width:100%;height:100%;display:block}
.wa-panel-who{display:flex;flex-direction:column;line-height:1.25}
.wa-panel-who strong{font-size:14.5px;font-weight:750}
.wa-panel-who small{color:#5d5a63;font-size:12px}
/* the little green dot is the only "we are here" signal, so it stays subtle */
.wa-panel-who small::before{content:"";display:inline-block;width:7px;height:7px;margin-right:6px;border-radius:50%;background:#25d366;vertical-align:middle}

.wa-panel-thread{padding:14px 0 4px;display:flex;flex-direction:column;gap:9px}
.wa-panel-greeting{
  align-self:flex-start;max-width:88%;margin:0;padding:9px 13px;
  border-radius:14px 14px 14px 4px;background:#f3f3f5;
  font-size:13.5px;line-height:1.4;
}
/* the draft is shown as the visitor's own outgoing message, because that is
   exactly what the link sends */
.wa-panel-draft{
  align-self:flex-end;max-width:92%;margin:0;padding:10px 14px;
  border-radius:14px 14px 4px 14px;background:#d9fdd3;
  font-size:13.5px;font-weight:600;line-height:1.4;
}

.wa-panel-chips{display:flex;flex-wrap:wrap;gap:7px;padding:12px 0 2px}
.wa-panel-chip{
  padding:7px 12px;border-radius:999px;border:1px solid rgb(25 23 28 / .16);
  background:#fff;color:var(--ink,#19171c);
  font-family:var(--sans);font-size:12.5px;font-weight:650;
  cursor:pointer;transition:border-color .25s ease,background-color .25s ease;
}
.wa-panel-chip:hover{border-color:#25d366;background:rgb(37 211 102 / .1)}
.wa-panel-chip[aria-pressed="true"]{border-color:#25d366;background:rgb(37 211 102 / .16)}

.wa-panel-send{
  margin-top:12px;
  display:flex;align-items:center;justify-content:center;gap:8px;
  padding:13px 18px;border-radius:14px;
  background:#25d366;color:#0b2a17;
  font-weight:750;font-size:14.5px;text-decoration:none;
  transition:transform .3s cubic-bezier(.22,1,.36,1),filter .3s ease;
}
.wa-panel-send:hover{transform:translateY(-2px);filter:brightness(1.05)}

/* Staggered assembly. Each row is 40ms behind the one above it, which is what
   makes the panel read as opening rather than as popping. */
.wa-panel-head,.wa-panel-thread,.wa-panel-chips,.wa-panel-send{
  opacity:0;transform:translateY(7px);
  transition:opacity .34s cubic-bezier(.22,1,.36,1),transform .34s cubic-bezier(.22,1,.36,1);
}
.wa-dock.is-expanded .wa-panel-head{opacity:1;transform:none;transition-delay:.06s}
.wa-dock.is-expanded .wa-panel-thread{opacity:1;transform:none;transition-delay:.1s}
.wa-dock.is-expanded .wa-panel-chips{opacity:1;transform:none;transition-delay:.14s}
.wa-dock.is-expanded .wa-panel-send{opacity:1;transform:none;transition-delay:.18s}

.wa-dock-btn{border:0;padding:0;cursor:pointer;font:inherit}
.wa-dock.is-expanded .wa-dock-btn{transform:rotate(-6deg) scale(1.04)}

@media(max-width:600px){
  .wa-panel{width:min(92vw,320px);bottom:70px;padding:16px 16px 14px}
  .wa-panel-greeting,.wa-panel-draft{font-size:13px}
}

/* A short screen cannot hold the panel above the button without covering the
   page, so below this the dock stays a plain link straight to WhatsApp. */
@media(max-height:620px){
  .wa-panel{display:none}
}

@media(prefers-reduced-motion:reduce){
  .wa-panel,
  .wa-panel-head,.wa-panel-thread,.wa-panel-chips,.wa-panel-send{transition:none;transform:none}
  .wa-dock.is-expanded .wa-dock-btn{transform:none}
}

/* ==== area-pages-hero-film.css ================================== */
/*
 * Current, compact homepage hero.
 *
 * One small, fixed-size Guru pulls the visible film into the page. The opening
 * pose is deliberately static. Motion begins only when the visitor scrolls.
 */

:root{
  --hero-guru-h:132px;
  --hero-guru-ratio:1.0714286;
  --hero-panel-edge:14px;
}

.hero-film{
  position:relative;
  min-height:100svh;
  background:var(--white);
}

/* svh is the viewport with the mobile browser chrome EXPANDED, lvh with it
   COLLAPSED. Both are STATIC - the browser resolves each one once and never
   revises it - so a sticky box locked to either is right in one chrome state
   and wrong in the other, while the position:fixed WhatsApp dock is always
   measured against the live visible viewport. That mismatch is the dead white
   band that opens under the grey panel once you start scrolling, with the dock
   sitting in it.

   max() of the static floor and the live --vvh (js/viewport.js) resolves it:
   lvh is the tallest the unit system claims the viewport gets, --vvh is the
   height it ACTUALLY is right now, and taking the larger means the panel can
   only ever be too tall, never too short. Because it only adds height, a
   mid-scroll update cannot shift the document or open a new gap, and with JS
   off every rule falls back to the plain lvh behaviour.

   Every child in here is positioned in % of the stage, so they scale with it. */
.hero-film-stage{
  position:sticky;
  top:0;
  height:100svh;
  overflow:hidden;
  background:var(--white);
}

@supports (height: 100lvh){
  .hero-film-stage{height:max(100lvh, var(--vvh, 0px))}
}

.hero-film-stage::before{
  content:"";
  position:absolute;
  z-index:0;
  inset:var(--hero-panel-edge);
  border-radius:30px;
  background:var(--cloud);
}

.hero-film-copy{
  position:absolute;
  z-index:4;
  /* Below ~1544px the clamp wins and nothing moves. Above it, this resolves to
     50% of the capped stage minus half the content column, which is exactly
     where every section below the hero starts, so the page keeps one spine. */
  left:max(clamp(56px,7.6vw,124px), calc(50% - var(--max) / 2));
  top:46%;
  width:min(672px,49vw);
  transform:translateY(-50%);
  will-change:opacity,transform;
}

.hero-film-copy h1{
  margin:0;
  font-size:clamp(3.18rem,4.92vw,5.04rem);
  line-height:1.01;
  letter-spacing:-.04em;
  font-weight:700;
}

.hero-film-copy h1 span{color:var(--teal)}

.hero-film-copy p{
  max-width:43ch;
  margin-top:20px;
  color:var(--muted);
  font-size:clamp(18px,1.62vw,20.4px);
  line-height:1.48;
}

.hero-film-guru-rig{
  position:absolute;
  z-index:8;
  left:0;
  top:0;
  width:calc(var(--hero-guru-h) * var(--hero-guru-ratio));
  height:var(--hero-guru-h);
  pointer-events:none;
  transform-origin:center bottom;
  will-change:transform;
  contain:layout style;
  overflow:visible;
}

.hero-film-guru-rig img{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:contain;
  object-position:center bottom;
  image-rendering:auto;
  backface-visibility:hidden;
  opacity:0;
}

.hero-film-guru-rig img[data-on]{opacity:1}

.hero-film-card{
  position:absolute;
  z-index:5;
  left:calc(57% - 14px);
  top:20%;
  width:43%;
  height:57%;
  margin:0;
  overflow:hidden;
  isolation:isolate;
  contain:paint;
  border-radius:24px;
  background:var(--ink);
  box-shadow:0 46px 95px -58px rgb(25 23 28 / .72);
  transform:translate3d(34vw,0,0);
  will-change:left,top,width,height,border-radius;
}

.hero-film-card video{
  position:absolute;
  inset:-2px;
  display:block;
  width:calc(100% + 4px);
  height:calc(100% + 4px);
  max-width:none;
  object-fit:cover;
  transform:translateZ(0);
}

.hero-film-overlay{
  position:absolute;
  z-index:2;
  inset:0;
  display:flex;
  align-items:flex-end;
  padding:clamp(34px,5vw,72px);
  color:var(--white);
  opacity:0;
  pointer-events:none;
  will-change:opacity;
}

.hero-film-overlay::before{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(to top,rgb(16 12 22 / .78),rgb(16 12 22 / .18) 48%,transparent 74%);
}

.hero-film-overlay>div{position:relative;z-index:1;max-width:min(780px,72vw)}

.hero-film-overlay h2{
  max-width:14ch;
  color:var(--white);
  font-size:clamp(2.7rem,5.2vw,5rem);
  line-height:.96;
  letter-spacing:-.04em;
}

.hero-film-overlay p{
  max-width:44ch;
  margin-top:18px;
  color:rgb(255 255 255 / .86);
  font-size:clamp(15px,1.35vw,18px);
  line-height:1.48;
}

.hero-film-link{
  display:inline-flex;
  align-items:center;
  gap:8px;
  margin-top:22px;
  color:var(--white);
  font-size:14px;
  font-weight:750;
  text-decoration:none;
}

.hero-film-link .ds-arrow{
  width:14px;
  height:14px;
  fill:none;
  stroke:currentColor;
  stroke-width:1.4;
  stroke-linecap:round;
  stroke-linejoin:round;
}

.hero-film-overlay:not([aria-hidden="true"]){pointer-events:auto}

.hero-film-badge{
  position:absolute;
  left:18px;
  bottom:17px;
  padding:8px 11px;
  border-radius:999px;
  background:rgb(255 255 255 / .9);
  color:var(--ink);
  font-size:10px;
  font-weight:800;
  letter-spacing:.08em;
  text-transform:uppercase;
}

/* The film resolves into the system: film first, booking website second. */
.system-journey{
  position:relative;
  z-index:10;
  min-height:100svh;
  background:var(--white);
}

.journey-sr-only{
  position:absolute;
  width:1px;
  height:1px;
  padding:0;
  margin:-1px;
  overflow:hidden;
  clip:rect(0,0,0,0);
  white-space:nowrap;
  border:0;
}

.system-journey-stage{
  position:relative;
  min-height:100svh;
  overflow:hidden;
  background:var(--white);
}

.system-journey-stage::before{
  content:"";
  position:absolute;
  inset:var(--hero-panel-edge);
  border-radius:30px;
  background:var(--cloud);
}

.system-journey[data-ready]{
  /* Each middle service gets a full-stage reveal and a readable hold before
     the final booking screen takes over. */
  height:760svh;
  margin-top:-100svh;
}

.system-journey[data-ready] .system-journey-stage{
  position:sticky;
  top:0;
  height:100svh;
}

/* Same collapsing-chrome fix as .hero-film-stage above. The overlap that
   pulls this section over the hero's last viewport has to move to the same
   unit, or the two stages no longer meet edge to edge.

   margin-top deliberately stays on plain lvh while the stage takes the live
   max(). margin-top is LAYOUT: re-writing it as the chrome collapses would
   move every section below this one and jump the scroll position under the
   reader. The stage's own height is paint plus a sticky release point, so
   growing it costs nothing. */
@supports (height: 100lvh){
  .system-journey[data-ready] .system-journey-stage{height:max(100lvh, var(--vvh, 0px))}
  .system-journey[data-ready]{margin-top:-100lvh}
}

.journey-gallery{
  position:absolute;
  z-index:1;
  inset:0;
  margin:0;
  padding:0;
  list-style:none;
  perspective:1800px;
  perspective-origin:50% 48%;
}

.journey-tile{
  position:absolute;
  z-index:1;
  inset:48px;
  margin:0;
  overflow:hidden;
  border-radius:28px;
  background:var(--ink);
  box-shadow:0 28px 72px -48px rgb(25 23 28 / calc(.3 + var(--card-focus,.7)*.32));
  filter:blur(var(--enter-blur,0)) saturate(calc(.84 + var(--card-focus,.7)*.16));
  transform-origin:center;
  backface-visibility:hidden;
  will-change:transform,clip-path,opacity,filter;
}

.journey-step{display:none}

.system-journey[data-ready] .journey-step{display:block}
.system-journey[data-ready] .journey-step--website,
.system-journey[data-ready] .journey-step--google{display:grid}

.journey-tile--film video{
  position:absolute;
  inset:-2px;
  width:calc(100% + 4px);
  height:calc(100% + 4px);
  max-width:none;
  object-fit:cover;
  transform:translateZ(0) scale(var(--media-scale,1.02));
  transform-origin:center;
}

.journey-tile--film{
  color:var(--white);
  text-decoration:none;
}

.journey-step-link{
  position:absolute;
  inset:0;
  display:block;
  color:inherit;
  text-decoration:none;
}

.journey-film-shade{
  position:absolute;
  inset:0;
  background:linear-gradient(to top,rgb(16 12 22 / .78),rgb(16 12 22 / .12) 56%,transparent 78%);
}

.journey-film-copy{
  position:absolute;
  z-index:1;
  left:clamp(34px,5vw,72px);
  bottom:clamp(34px,5vw,70px);
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  max-width:620px;
  color:var(--white);
  opacity:var(--film-copy-opacity,1);
}

.journey-film-copy strong{
  font-size:clamp(2.7rem,5.2vw,5rem);
  line-height:.96;
  letter-spacing:-.04em;
}

.journey-film-copy>span:not(.journey-film-go){
  margin-top:18px;
  color:rgb(255 255 255 / .86);
  font-size:clamp(15px,1.35vw,18px);
}

.journey-film-go{
  margin-top:22px;
  font-size:14px;
  font-weight:750;
}

.journey-step-face{
  position:absolute;
  z-index:6;
  inset:0;
  display:flex;
  flex-direction:column;
  justify-content:flex-end;
  padding:48px calc(34px + var(--face-inset,0px)) calc(76px + var(--face-inset-y,0px));
  color:var(--white);
  background:linear-gradient(to top,rgb(15 12 20 / calc(.84 - var(--stage-fill,0)*.48)),rgb(15 12 20 / calc(.04 - var(--stage-fill,0)*.04)) 70%);
  opacity:calc(var(--step-face-opacity,0)*var(--copy-opacity,1));
  transform:translate3d(0,var(--copy-shift,0),0);
  pointer-events:none;
}

.journey-step-copy{display:block}

.journey-step-copy strong{
  font-size:clamp(3.1rem,4.6vw,4.7rem);
  line-height:1;
  letter-spacing:-.04em;
}

/* Decorative full-bleed layers. They sit over the step-2 copy column, so without
   this they swallow the clicks on its two CTAs. */
/* The card face is the real scene, shrunk - a clone of .journey-browser or
   .journey-google-scene that hero-film.js drops in here and scales to the
   window the clip-path actually leaves visible. So the mini is bounded by
   --face-inset, not by the tile box: the tile is always full size and the card
   is a crop of it, so inset:0 here would centre the mini on a rectangle the
   viewer cannot see.
   It must be GONE before the full-size scene fades up, or the same page
   cross-fades against itself at two sizes and reads as a ghost. step-face-opacity
   alone decays across fill 0-0.9, far too slow for that; the multiplier below
   clears the mini by fill 0.25, and --scene-reveal only leaves 0 after that. */
.journey-step-mini{
  position:absolute;
  z-index:4;
  inset:var(--face-inset-y,0) var(--face-inset,0) calc(var(--face-inset-y,0px) + var(--mini-foot,80px));
  display:grid;
  place-items:center;
  opacity:calc(var(--step-face-opacity,0) * max(0,1 - var(--stage-fill,0)*4));
  pointer-events:none;
}

/* The clone keeps its expanded pixel size (JS writes it from the live scene's
   own offsetWidth/Height) and is scaled down whole, so the card is a true
   miniature rather than the same layout re-flowed at card width. */
.journey-step-mini-inner{
  transform:scale(var(--mini-scale,.3));
  transform-origin:center;
}

/* Undo the stage rules the clone inherits by sitting inside the tile: grid
   placement, the stretch, and the --scene-reveal opacity that keeps the real
   scene hidden while the tile is still a card. */
.journey-step-mini .journey-browser,
.journey-step-mini .journey-google-browser{
  position:relative;
  aspect-ratio:auto;
  box-shadow:0 30px 70px -42px rgb(25 23 28 / .55);
  z-index:auto;
  inset:auto;
  grid-column:auto;
  grid-row:auto;
  align-self:auto;
  justify-self:auto;
  min-height:0;
  width:100%;
  height:100%;
  opacity:1;
  transform:none;
}


.journey-google-scene{
  position:absolute;
  z-index:4;
  inset:0;
  display:grid;
  place-items:center;
  padding:clamp(28px,4vw,62px);
  background:#eef3fb;
  opacity:clamp(0,calc(var(--step-face-opacity,0) + var(--stage-fill,0)*1.6),1);
  pointer-events:none;
}

.journey-google-browser{
  width:min(100%,1120px);
  aspect-ratio:16/9;
  overflow:hidden;
  border-radius:16px;
  background:var(--white);
  color:#202124;
  box-shadow:0 34px 72px -48px rgb(14 11 18 / .48);
  transform:translateY(calc((1 - var(--scene-reveal,0))*18px)) scale(calc(.97 + var(--scene-reveal,0)*.03));
  transform-origin:center;
}

.journey-google-bar{
  height:15%;
  display:flex;
  align-items:center;
  gap:3%;
  padding:0 3%;
  border-bottom:1px solid #eceff1;
}

.journey-google-word{font-size:clamp(12px,1.55vw,22px);font-weight:700;letter-spacing:-.04em}
.journey-google-word i{font-style:normal}
.journey-google-word i:nth-child(1),.journey-google-word i:nth-child(4){color:#4285f4}
.journey-google-word i:nth-child(2),.journey-google-word i:nth-child(6){color:#ea4335}
.journey-google-word i:nth-child(3){color:#fbbc05}
.journey-google-word i:nth-child(5){color:#34a853}

.journey-google-search{
  width:55%;
  height:58%;
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding:0 2%;
  border:1px solid #dfe1e5;
  border-radius:999px;
  box-shadow:0 2px 7px rgb(60 64 67 / .12);
  font-size:clamp(7px,.95vw,14px);
}

.journey-google-search b{
  position:relative;
  width:clamp(8px,1.1vw,15px);
  height:clamp(8px,1.1vw,15px);
  border:2px solid #5f6368;
  border-radius:50%;
}

.journey-google-search b::after{
  content:"";
  position:absolute;
  right:-5px;
  bottom:-2px;
  width:6px;
  height:2px;
  background:#5f6368;
  transform:rotate(45deg);
}

.journey-google-result{
  height:85%;
  display:grid;
  grid-template-columns:1.18fr .82fr;
  gap:2.5%;
  padding:2.6% 3% 3%;
}

.journey-google-photos{
  min-width:0;
  display:grid;
  grid-template-columns:1.6fr .75fr;
  grid-template-rows:1fr 1fr;
  gap:3px;
  overflow:hidden;
  border-radius:12px;
}

.journey-google-photos img{width:100%;height:100%;object-fit:cover}
.journey-google-photos img:first-child{grid-row:1/3}

.journey-google-profile{
  min-width:0;
  padding:2% 1%;
}

.journey-google-profile>strong{
  display:block;
  font-size:clamp(14px,2.1vw,30px);
  font-weight:500;
  line-height:1;
  letter-spacing:-.025em;
}

.journey-google-rating{
  display:flex;
  align-items:center;
  gap:2%;
  margin-top:3%;
  font-size:clamp(6px,.8vw,12px);
}

.journey-google-rating i{color:#f9ab00;font-style:normal;letter-spacing:1px}
.journey-google-rating small{color:#5f6368;font-size:inherit}
.journey-google-type{display:block;margin-top:2%;color:#70757a;font-size:clamp(6px,.78vw,12px)}

.journey-google-actions{
  display:flex;
  gap:5%;
  margin:7% 0 6%;
}

.journey-google-actions>b{
  display:grid;
  justify-items:center;
  gap:5px;
  color:#1a73e8;
  font-size:clamp(5px,.65vw,10px);
  font-weight:500;
}

.journey-google-actions i{
  width:clamp(21px,2.8vw,38px);
  height:clamp(21px,2.8vw,38px);
  display:grid;
  place-items:center;
  border-radius:50%;
  background:#e8f0fe;
}

.journey-google-actions svg{width:45%;height:45%;fill:none;stroke:currentColor;stroke-width:1.8}

.journey-google-info{
  display:grid;
  gap:clamp(5px,.75vw,11px);
  padding-top:5%;
  border-top:1px solid #eceff1;
  font-size:clamp(6px,.75vw,11px);
}

.journey-google-info b{font-weight:500}
.journey-google-availability{
  display:block;
  margin-top:6%;
  padding:4% 5%;
  border-radius:9px;
  background:#f8fafd;
  color:#1a73e8;
  font-size:clamp(6px,.78vw,12px);
  font-weight:700;
}

.journey-step--bookings{
  background:var(--mist);
  color:var(--ink);
}

.journey-wave-guru{
  position:absolute;
  z-index:10;
  left:0;
  top:0;
  width:clamp(108px,9vw,138px);
  height:auto;
  opacity:0;
  transform:translate3d(-200px,0,0);
  transform-origin:55% 78%;
  pointer-events:none;
  will-change:transform,opacity;
}

/* Steps 2 and 3 share one stage and reveal contract. */
.journey-tile--website,
.journey-step--google{
  --website-reveal:var(--scene-reveal,0);
  z-index:2;
  display:grid;
  grid-template-columns:minmax(260px,.72fr) minmax(0,1.28fr);
  gap:clamp(30px,4vw,64px);
  align-items:center;
  padding:clamp(34px,5vw,72px);
  background:#fbfafe;
  color:var(--ink);
}

/* Step 3 leads with the Google proof, then lands on the explanation. The
   asymmetry distinguishes it from step 2 without changing the filled bounds. */
.journey-step--google{
  grid-template-columns:minmax(0,1.15fr) minmax(280px,.85fr);
}

.journey-step--google .journey-google-scene{
  grid-column:1;
  grid-row:1;
}

.journey-step--google .journey-marketing-copy{
  grid-column:2;
  grid-row:1;
  width:min(100%,34rem);
  justify-self:end;
}

.journey-website-copy,
.journey-marketing-copy{
  position:relative;
  z-index:calc(2 + var(--stage-fill,0)*5);
  /* Relay, not crossfade: the copy column is the LAST layer in. It waits until the
     browser scene is most of the way up, so the three text layers never share a beat.
     That 0.55 offset is the whole reason step 2 reads clean instead of washed out. */
  --copy-in:clamp(0,calc((var(--website-reveal,1) - .55) / .45),1);
  opacity:var(--copy-in);
  transform:translate3d(0,calc((1 - var(--copy-in)) * 18px),0);
}

.journey-website-copy h2,
.journey-marketing-copy h2{
  max-width:9ch;
  margin:0;
  color:var(--ink);
  font-size:clamp(2.6rem,4.5vw,4.7rem);
  line-height:.98;
  letter-spacing:-.04em;
}

.journey-website-copy p,
.journey-marketing-copy p{
  max-width:39ch;
  margin-top:22px;
  color:var(--muted);
  font-size:clamp(15px,1.35vw,18px);
  line-height:1.48;
}

.journey-website-actions{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:12px 22px;
  margin-top:28px;
}

.journey-website-actions a{
  display:inline-flex;
  align-items:center;
  gap:8px;
  color:var(--ink);
  font-size:14px;
  font-weight:750;
  text-decoration:none;
}

.journey-website-actions a:first-child{
  min-height:48px;
  padding:0 18px;
  border-radius:999px;
  background:var(--signal-yellow);
}

.journey-website-actions .ds-arrow{
  width:14px;
  height:14px;
  fill:none;
  stroke:currentColor;
  stroke-width:1.4;
  stroke-linecap:round;
  stroke-linejoin:round;
}

.journey-step--google .journey-google-scene{
  position:relative;
  z-index:1;
  inset:auto;
  align-self:stretch;
  min-height:420px;
  overflow:hidden;
  border-radius:calc(16px + var(--stage-fill,0)*10px);
  opacity:var(--scene-reveal,1);
  transform:translateZ(0) scale(calc(1 + (1 - var(--scene-reveal,1))*.04));
  transform-origin:center;
  contain:layout;
}

.journey-browser{
  --browser-bar-h:calc(42px + var(--stage-fill,0)*20px);
  pointer-events:none;
  position:relative;
  z-index:calc(1 + var(--stage-fill,0)*6);
  align-self:stretch;
  min-height:420px;
  overflow:hidden;
  border-radius:calc(16px + var(--stage-fill,0)*10px);
  background:var(--white);
  box-shadow:0 30px 70px -42px rgb(25 23 28 / .55);
  opacity:var(--scene-reveal,1);
  transform:translateZ(0) scale(calc(1 + (1 - var(--scene-reveal,1))*.04));
  transform-origin:center;
  contain:layout;
}

.journey-browser-bar{
  height:var(--browser-bar-h,42px);
  display:flex;
  align-items:center;
  gap:calc(7px + var(--stage-fill,0)*4px);
  padding:0 calc(14px + var(--stage-fill,0)*10px);
  background:var(--white);
}

.journey-browser-bar i{
  width:calc(8px + var(--stage-fill,0)*4px);
  height:calc(8px + var(--stage-fill,0)*4px);
  border-radius:50%;
  background:#d8d5de;
}

.journey-browser-bar span{
  margin-left:calc(7px + var(--stage-fill,0)*4px);
  color:#77727e;
  font-size:calc(11px + var(--stage-fill,0)*6px);
  font-weight:650;
}

.journey-browser-page{
  position:absolute;
  inset:var(--browser-bar-h,42px) 0 0;
  overflow:hidden;
  background:#17131e;
}

.journey-browser-page>img{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
}

.journey-browser-page::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(90deg,rgb(14 11 18 / .68),transparent 66%);
}

.journey-browser-nav,
.journey-browser-copy{
  position:absolute;
  z-index:2;
  left:calc(28px + var(--stage-fill,0)*22px);
  right:calc(28px + var(--stage-fill,0)*22px);
  color:var(--white);
}

.journey-browser-nav{
  top:calc(24px + var(--stage-fill,0)*16px);
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:calc(18px + var(--stage-fill,0)*16px);
  font-size:calc(11px + var(--stage-fill,0)*6px);
}

.journey-browser-nav strong{font-size:calc(15px + var(--stage-fill,0)*11px)}
.journey-browser-nav span{margin-left:auto;color:rgb(255 255 255 / .76)}
.journey-browser-nav b{padding:calc(9px + var(--stage-fill,0)*5px) calc(12px + var(--stage-fill,0)*8px);border-radius:999px;background:var(--signal-yellow);color:var(--ink)}

.journey-browser-copy{
  bottom:calc(34px + var(--stage-fill,0)*22px);
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  max-width:calc(360px + var(--stage-fill,0)*230px);
}

.journey-browser-copy small{font-size:calc(11px + var(--stage-fill,0)*5px);text-transform:uppercase;letter-spacing:.08em}
.journey-browser-copy strong{margin-top:calc(9px + var(--stage-fill,0)*6px);font-size:calc(clamp(1.7rem,2.7vw,3rem) + var(--stage-fill,0)*1.15rem);line-height:1;letter-spacing:-.035em}
.journey-browser-copy b{margin-top:calc(16px + var(--stage-fill,0)*8px);padding:calc(10px + var(--stage-fill,0)*5px) calc(13px + var(--stage-fill,0)*9px);border-radius:999px;background:var(--white);color:var(--ink);font-size:calc(11px + var(--stage-fill,0)*5px)}

@media(max-width:900px){
  :root{
    --hero-guru-h:94px;
    --hero-panel-edge:8px;
  }

  .hero-film{min-height:100svh}

  .hero-film-stage::before{border-radius:24px}

  .hero-film-copy{
    left:30px;
    right:30px;
    top:36%;
    width:auto;
  }

  .hero-film-copy h1{font-size:clamp(2.55rem,11.6vw,4rem)}
  .hero-film-copy p{max-width:36ch;font-size:15px}

  /* Home position is flush right (26% + 56% + the gutter = the screen), but
     the card starts pushed an EXTRA half of its own width past that, so only
     half of it is visible on first paint and the Guru hauls the rest into
     view. The numbers here are the static, pre-JS state of measure() in
     js/hero-film.js and are derived the same way:
       home left    = 26vw - 6
       flush travel = (100vw - 14 - width) - home left = 18vw - 8
       overflow     = width * .5 = 28vw
       travel       = 18vw - 8 + 28vw = 46vw - 8 */
  .hero-film-card{
    left:calc(26% - 6px);
    top:58%;
    width:56%;
    height:30%;
    min-height:196px;
    border-radius:20px;
    box-shadow:none;
    clip-path:inset(0 round 20px);
    transform:translate3d(calc(46vw - 8px),0,0);
  }

  /* 44px is the tap-target floor, not a target. The link's own text is 21px tall. */
  .hero-film-link{min-height:44px;align-items:center}

  .hero-film-overlay{padding:28px 26px 118px}
  .hero-film-overlay>div{max-width:none}
  .hero-film-overlay h2{font-size:clamp(2.45rem,11vw,3.7rem)}
  .hero-film-overlay p{font-size:15px}

  .system-journey-stage::before{border-radius:24px}
  /* The longer mobile track prevents normal touch scrolling from skipping the
     website and SEO holds. */
  .system-journey[data-ready]{height:680svh}

  .journey-tile{
    inset:14px;
    border-radius:20px;
    box-shadow:none;
  }

  /* Type here is sized for the CARD, not the screen. The card is ~80vw, so the
     desktop-scale 2.8rem headline was breaking "Direct-booking website" across
     three cramped lines. */
  .journey-step-face{
    inset:0;
    /* The bottom padding is NOT decoration: the tile is clip-masked 10.5% top and
       bottom in the row (85.7px of the 816px element), easing to 7.353% at full
       fill (60px), so 26px of that reserve stops being dead space as it fills. */
    padding:26px 22px calc(116px - var(--stage-fill,0)*26px);
  }

  /* Type is sized for the CARD: 275px wide in the row, 362px filled. Both ends
     get their own value rather than one compromise size. */
  .journey-step-copy strong{font-size:calc(2.08rem + var(--stage-fill,0)*.28rem);line-height:1.04;letter-spacing:-.02em}

  /* Step 3 is a portrait result on phones. Keeping the desktop 16:9 browser
     here left more than half the focal hold blank. */
  .journey-google-scene{padding:64px 12px 12px}
  .journey-google-browser{width:100%;height:100%;aspect-ratio:auto;border-radius:12px;box-shadow:none}
  .journey-google-bar{height:10%;padding-inline:14px;gap:12px}
  .journey-google-word{font-size:14px}
  .journey-google-search{width:auto;min-width:0;flex:1;height:36px;padding-inline:12px;font-size:10px}
  .journey-google-search b{width:10px;height:10px;border-width:1.5px}
  .journey-google-search b::after{right:-4px;bottom:-1px;width:5px;height:1.5px}
  /* The profile column now carries the whole listing (name through the
     availability line) in the lower half of a portrait frame, so it gets the
     larger of the two rows and the type steps down to match. */
  .journey-google-result{height:90%;grid-template-columns:1fr;grid-template-rows:minmax(0,.86fr) minmax(0,1.14fr);gap:10px;padding:10px 12px 12px}
  .journey-google-photos{border-radius:9px;gap:3px}
  .journey-google-profile{padding:4px 2px;overflow:hidden}
  .journey-google-profile>strong{font-size:19px}
  .journey-google-rating,.journey-google-type{font-size:9px}
  .journey-google-actions{margin:4% 0 3%}
  .journey-google-actions>b{font-size:7px}
  .journey-google-actions i{width:23px;height:23px}
  .journey-google-info{gap:6px;padding-top:4%;font-size:9px}
  .journey-google-availability{margin-top:3%;padding:8px 10px;border-radius:7px;font-size:9px}
  .journey-wave-guru{width:104px}

  .journey-film-copy{
    left:26px;
    right:26px;
    bottom:110px;
  }

  .journey-film-copy strong{font-size:clamp(2.45rem,11vw,3.7rem)}

  /* Portrait fill, arranged like the hero: copy first and hard left, the mock
     under it and pushed right. Both tiles take the SAME arrangement so they
     read as a pair rather than two unrelated compositions. The block padding
     matches the step face's clip reserve (85.7px in the row, 60px filled) so
     neither row ever lands outside the visible card. */
  .journey-tile--website,
  .journey-step--google{
    grid-template-columns:1fr;
    grid-template-rows:auto minmax(0,1fr);
    gap:calc(14px + var(--stage-fill,0)*6px);
    /* Bumped from 92px so the heading clears the floating mobile header with
       real breathing room instead of sitting flush under it. */
    padding:calc(140px - var(--stage-fill,0)*26px) 20px;
  }

  .journey-website-copy,
  .journey-marketing-copy{
    grid-column:1;
    grid-row:1;
    justify-self:start;
    width:100%;
    padding:0 4px;
  }

  /* The mock is the second beat: bottom of the card, inset from the left so the
     copy above it keeps the left edge to itself. */
  .journey-tile--website>.journey-browser,
  .journey-step--google>.journey-google-scene{
    grid-column:1;
    grid-row:2;
    justify-self:end;
    width:92%;
    min-height:0;
  }

  /* Beats the desktop `.journey-step--google .journey-marketing-copy` column
     rule on specificity. Without it the copy stays in column 2 and the scene
     lands in an implicit 0px column. */
  .journey-step--google .journey-marketing-copy{
    grid-column:1;
    grid-row:1;
    width:100%;
    justify-self:start;
  }

  .journey-website-copy h2,
  .journey-marketing-copy h2{max-width:15ch;font-size:clamp(1.85rem,7.4vw,2.6rem);line-height:1.02}
  .journey-website-copy p,
  .journey-marketing-copy p{max-width:34ch;margin-top:11px;font-size:13.5px;line-height:1.44}
  .journey-website-actions{margin-top:15px}
  /* Both links go live at fill now, not just the pill, so both need the 44px floor. */
  /* 46, not 44: the tile carries a live scale transform, so a rect measured
     mid-journey lands fractionally under whatever is declared here. */
  .journey-website-actions a{min-height:46px}
  .journey-website-actions a:first-child{padding:0 15px}
  .journey-browser-nav span{display:none}

  .journey-step--google>.journey-google-scene{padding:0}

  /* The browser mock is a landscape frame on desktop. Here it is ~322 x 330,
     so the chrome shrinks and the page scrim turns vertical: the desktop 90deg
     wash only darkens the left third, which on a near-square page leaves the
     bottom copy sitting on raw photo. */
  .journey-browser{--browser-bar-h:calc(30px + var(--stage-fill,0)*14px)}
  .journey-browser-bar{gap:calc(6px + var(--stage-fill,0)*3px);padding:0 calc(11px + var(--stage-fill,0)*5px)}
  .journey-browser-bar i{width:calc(7px + var(--stage-fill,0)*3px);height:calc(7px + var(--stage-fill,0)*3px)}
  .journey-browser-bar span{margin-left:calc(6px + var(--stage-fill,0)*3px);font-size:calc(10px + var(--stage-fill,0)*3px)}

  .journey-browser-page::after{
    background:linear-gradient(to top,rgb(14 11 18 / .8),rgb(14 11 18 / .3) 46%,rgb(14 11 18 / .34));
  }

  .journey-browser-nav,
  .journey-browser-copy{
    left:calc(14px + var(--stage-fill,0)*8px);
    right:calc(14px + var(--stage-fill,0)*8px);
  }

  .journey-browser-nav{
    top:calc(12px + var(--stage-fill,0)*8px);
    gap:calc(10px + var(--stage-fill,0)*8px);
    font-size:calc(10px + var(--stage-fill,0)*3px);
  }

  .journey-browser-nav strong{font-size:calc(13px + var(--stage-fill,0)*6px)}
  .journey-browser-nav b{padding:calc(7px + var(--stage-fill,0)*3px) calc(10px + var(--stage-fill,0)*4px)}

  .journey-browser-copy{
    bottom:calc(14px + var(--stage-fill,0)*10px);
    max-width:none;
  }

  .journey-browser-copy small{font-size:calc(9px + var(--stage-fill,0)*2px)}
  .journey-browser-copy strong{margin-top:calc(6px + var(--stage-fill,0)*4px);font-size:calc(1.35rem + var(--stage-fill,0)*.5rem)}
  .journey-browser-copy b{margin-top:calc(11px + var(--stage-fill,0)*5px);padding:calc(8px + var(--stage-fill,0)*3px) calc(12px + var(--stage-fill,0)*4px);font-size:calc(10px + var(--stage-fill,0)*3px)}

  /* Thin header rules moved to css/site.css so every page gets the same
     compact mobile header, not just this one. */
}

/* Phone hero headline. home-hero-pricing.css sets an unqualified
   width:min(760px,54vw) and a 4.65vw font, which on a phone leaves the h1 a
   210px column and shatters "Your place. Your guests." into four one-word
   lines. Re-qualify both through .hero-film so this wins on specificity, not
   source order, and size the type so each of the two spans holds ONE line:
   the lead measures 10.18em wide, so font-size = (viewport - gutters) / 10.4. */
@media(max-width:768px){
  .hero-film .hero-film-copy{
    left:24px;
    right:24px;
    width:auto;
  }

  .hero-film .hero-film-copy h1{
    font-size:clamp(1.6rem,calc(9.45vw - 4.4px),3.18rem);
    line-height:1.06;
    letter-spacing:-.035em;
  }
}


@media(prefers-reduced-motion:reduce){
  .hero-film-copy,
  .hero-film-card,
  .hero-film-guru-rig,
  .hero-film-overlay,
  .journey-tile{will-change:auto}

  .system-journey[data-ready]{height:auto;margin-top:0}
  .system-journey[data-ready] .system-journey-stage{position:relative;height:auto;min-height:100svh;padding:110px 48px}
  .system-journey[data-ready] .journey-gallery{position:relative;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:24px}
  .system-journey[data-ready] .journey-step{
    --step-face-opacity:1;
    --stage-fill:0;
    --scene-reveal:0;
    --website-reveal:0;
    position:relative;
    inset:auto;
    display:block!important;
    aspect-ratio:1.6;
    transform:none!important;
    clip-path:none!important;
    opacity:1!important;
  }
  .system-journey[data-ready] .journey-website-copy,
  .system-journey[data-ready] .journey-marketing-copy,
  .system-journey[data-ready] .journey-browser{display:none}
}

@media(max-width:900px) and (prefers-reduced-motion:reduce){
  .system-journey[data-ready] .system-journey-stage{padding:84px 20px 40px}
  .system-journey[data-ready] .journey-gallery{grid-template-columns:1fr;gap:20px}
  .system-journey[data-ready] .journey-step{width:min(78vw,320px);margin-inline:auto;aspect-ratio:9/16}
  /* Nothing is clip-masked here (clip-path:none above), so the clip reserve in
     the two padding rules is pure dead space. Reclaim it: the static end state
     is four legible cards, never a tile parked mid-fill. */
  .system-journey[data-ready] .journey-step-face{padding:22px 20px 26px}
  .system-journey[data-ready] .journey-tile--website,
  .system-journey[data-ready] .journey-step--google{padding:20px}
}

/* Phone only (<=768px). Measured at 390x844: every animated thing in the
   journey - tiles, the Step 4 push, and the "0% commission." payoff - has
   settled by raw progress .86, leaving ~685px (81svh) of scroll where nothing
   moves. Lowering the height on its own does NOT fix that: every window in
   renderJourney() is a FRACTION of the span, so a shorter section just replays
   the same sequence faster and keeps the same 14% dead tail. So the height cut
   here is paired with JOURNEY_PHONE_SCALE in js/hero-film.js, which multiplies
   the journey's raw progress by (new span / 580svh) and hands renderJourney the
   same absolute pacing it had at 680svh. Net: identical animation speed, the
   payoff still lands and then holds for ~31svh (~263px) before the section
   releases. Change one of the two numbers and you must change the other.
   Tablet (769-900px) is deliberately left on the 680svh rule above. */
@media(max-width:768px){
  .system-journey[data-ready]{height:630svh}
}

/* --- Tile 1 and tile 4 carry real captures, not coded mocks --------------- */

/* The screenshot already contains the site's own nav, hero and CTA, so the
   scrim and the overlaid copy that dressed the mock would double them up. */
.journey-browser--real .journey-browser-page{background:var(--cloud)}
.journey-browser--real .journey-browser-page::after{display:none}

.journey-browser--real .journey-browser-page>img{
  object-fit:cover;
  /* Anchored left and top. The tile frame is far taller than the 16:10 capture,
     so cover crops the sides hard; centring it cut the logo off one edge and
     the hero headline off the other. Left-anchored, the crop falls on the sky
     and the lake, which carry nothing. */
  object-position:left top;
}

/* The CRM shot replaces a 900px-wide coded replica that was scaled by
   --channel-scale. An image needs no scale factor: it fills the panel and
   crops the few percent of aspect-ratio difference off the bottom. */
.channels-shot{
  width:100%;
  height:100%;
  display:block;
  object-fit:cover;
  object-position:left top;
}

/* --- Mobile: the tiles state what they are, not everything they contain --- */
@media (max-width:700px){
  /* A 1600px-wide app screen inside a phone-width card renders 9px type that
     reads as noise. The shot stays, framed on the part that carries meaning:
     the rail and the conversation list. */
  .channels-shot{object-position:left top;object-fit:cover;transform:scale(1.35);transform-origin:left top}

  /* The browser tile keeps the capture unscaled. scale(1.18) with a centred
     origin pushed the site's own nav and hero headline past the left edge of
     the frame, so the shot's text read as broken words over the tile copy. */
  .journey-browser--real .journey-browser-page>img{transform:none}

  /* The chrome earns nothing at this size. */
  .journey-browser--real .journey-browser-bar span{max-width:52vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}

/* ---- Desktop canvas ceiling ------------------------------------------------
   The hero is positioned with clamps that all top out at roughly a 1630px
   viewport: left:clamp(56px,7.6vw,124px) plus the two font clamps. Past that
   the hero stopped responding while every content section kept centring in the
   1344px column, so the page lost its spine as the screen grew: measured on the
   homepage, the hero h1 sat 484px left of the sections below it at 2560, and
   924px left of them at 3440. The stages that size themselves off the viewport
   (%-based hero card, the journey gallery) kept growing at the same time.

   Cap the stages at one canvas and centre them. Nothing moves at or below
   1680px, which covers every laptop and most desktops. hero-film.js measures
   stage.clientWidth and crm-spotlight.js measures sticky.offsetWidth, so both
   recompute against the capped box rather than the window. */
.hero-film-stage,
.system-journey-stage{
  width:min(100%,var(--canvas));
  margin-inline:auto;
}

/* ==== area-pages-crm-ui.css ===================================== */
/* ============================================================
   The Direct Stay app, reproduced for the marketing site.

   A HAND PORT of the real product. Source of truth, all in
   ~/Code/web/directstay-app (read only from here, there is no build step
   joining the two repos and there should not be):

     components/app/Sidebar.tsx            + Sidebar.module.css
     components/app/AppShell.module.css    (the canvas / board / panel model)
     components/app/UserChip.module.css
     components/inbox/ConversationsPanel.tsx + .module.css
     components/inbox/InboxPanels.tsx        + .module.css
     components/icons/index.tsx            (nav glyphs, 24 box, 1.7 stroke)
     lib/inbox/preview-data.ts             (the conversations shown below)
     app/tokens.css                        (every value re-declared here)

   The point of the port is recognition: a visitor who signs up should land on
   the screen they were shown. So the structure is the app's structure, not a
   drawing of an app. In particular:

     - The sidebar is a WHITE FULLY ROUNDED CARD on a --mist board, not a
       column with a divider rule. Sidebar.module.css says in its own header
       that adding a hairline is what made it read as a table rather than a
       surface. The gap IS the division. Do not add a border-right here.
     - The board is the RECESS. It is mist, and the panels floating in it are
       the white cards.
     - The brand mark slot at the top of the sidebar is deliberately EMPTY.
       The flying badge in js/crm-spotlight.js parks in it and becomes the
       app's own logo. See .crm-ui__brand-mark.

   MEASURED DEVIATIONS from the app, all of them because a 1440px product is
   being shown inside a 980px illustration:
     - rail width 224px, not the app's --rail-expanded-w 248px
     - conversations panel 304px, not the app's 380px
     - board padding 10px is the app's; main padding is 10px, not the
       content well's 24px, which at this width would leave the conversation
       pane 340px and slice the bubbles
     - the row summary clamps to ONE line, not two, so four rows (one per
       channel, which is the whole claim) fit the 560px stage without the
       fourth being cut in half
   Type scale, radii, colours and every other value are the app's verbatim.

   Guest data is the app's own preview fixture. Never put real guest data here.
   ============================================================ */

.crm-ui {
  /* ---- app/tokens.css, verbatim ---- */
  --crm-violet-deep: #4c1d95;
  --crm-violet-bright: oklch(64% 0.2 294);
  --crm-accent: #7c3aed;
  --crm-accent-on: #fff;
  --crm-accent-text: #7c3aed;
  --crm-accent-subtle: rgb(124 58 237 / .10);
  --crm-accent-border: rgb(124 58 237 / .28);
  --crm-signal-yellow: #f5ff63;
  --crm-signal-blue: #01b2fd;
  --crm-success: #0b6b3a;
  --crm-cloud: #f3f3f5;
  --crm-mist: #f2f1f3;
  --crm-white: #fff;
  --crm-ink: #19171c;
  --crm-muted: #5d5962;
  --crm-line: rgb(76 29 149 / .14);

  --crm-radius: 16px;
  --crm-radius-sm: 10px;
  --crm-radius-xs: 6px;
  --crm-radius-pill: 999px;

  --crm-text-xs: 13px;
  --crm-text-sm: 15px;
  --crm-tracking-tight: -0.04em;
  --crm-leading-body: 1.5;
  --crm-tap: 44px;

  /* the app's board model */
  --crm-board-pad: 10px;
  --crm-rail-w: 224px;

  position: relative;
  width: min(980px, 100%);
  margin: 0 auto;
  border-radius: 28px;
  overflow: hidden;
  background: var(--crm-white);
  border: 1px solid var(--crm-line);
  /* Same lift as the site's own cards rather than a generic drop shadow. */
  box-shadow: 0 30px 80px -30px rgb(25 23 28 / .30), 0 2px 6px rgb(25 23 28 / .05);
  color: var(--crm-ink);
  font-family: var(--sans, "Switzer", "Avenir Next", Avenir, "Helvetica Neue", sans-serif);
  font-size: var(--crm-text-sm);
  line-height: var(--crm-leading-body);
  text-align: left;
}

.crm-ui *,
.crm-ui *::before,
.crm-ui *::after { box-sizing: border-box; }

/* ---------- browser chrome ---------- */
.crm-ui__chrome {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 38px;
  padding: 0 16px;
  background: var(--crm-cloud);
  border-bottom: 1px solid var(--crm-line);
}
.crm-ui__dots { display: flex; gap: 6px; }
.crm-ui__dots i { width: 9px; height: 9px; border-radius: 50%; background: rgb(76 29 149 / .18); }
.crm-ui__url { flex: 1; margin: 0; text-align: center; font-size: 11px; color: var(--crm-muted); }

/* ---------- the board (AppShell.module.css .board) ----------
   Mist ground, one radius, and the panels inside it are the white cards. No
   hairline anywhere inside: a gap between two rounded cards on a darker
   ground already reads as a division. */
.crm-ui__board {
  display: grid;
  /* minmax(0, rail) not a fixed track: below 1400px the window itself is
     narrower than 980, and a rigid 224px rail plus a rigid 304px conversations
     panel is what amputated the conversation pane. Measured before the fix:
     the pane fell to 210px at 1280 and 2px at 1024 while the copy beside it
     read "You answer from here". The rail now gives up width first, the
     conversations panel second, and the pane holds a 300px floor (see
     .crm-ui__main) at every width the section pins at. */
  grid-template-columns: minmax(0, var(--crm-rail-w)) minmax(0, 1fr);
  /* An auto row inside a fixed-height grid sizes to CONTENT and quietly
     overruns it: the sidebar was rendering 505.75px inside a 500px board and
     its bottom corner was being sliced off by .crm-ui's overflow:hidden.
     minmax(0, 1fr) pins the row to the board and hands the clipping back to
     each panel's own overflow, which is where it belongs. */
  grid-template-rows: minmax(0, 1fr);
  gap: var(--crm-board-pad);
  padding: var(--crm-board-pad);
  background: var(--crm-mist);
  height: var(--crm-board-h, 520px);
}

/* ---------- sidebar (Sidebar.module.css) ---------- */
/* Measured: at 14px/16px/32px the sidebar's content ran to 505.8px inside a
   482px content box, so the user chip's bottom corner was sliced flush against
   the board edge. 12px padding, 10px gap and a 30px nav row bring the content
   to 484px inside a 494px box at the 518px board height. overflow:hidden is
   the backstop, not the plan. */
.crm-ui__side {
  background: var(--crm-white);
  border-radius: var(--crm-radius);
  display: flex;
  flex-direction: column;
  padding: 12px;
  gap: 10px;
  min-width: 0;
  overflow: hidden;
}

.crm-ui__head-block { display: flex; flex-direction: column; gap: 4px; }

.crm-ui__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 8px;
}

/* The 32x32 slot the flying badge lands in. It stays empty on purpose: the
   badge IS the logo once it parks, and drawing a second one here would give
   the landing a double image. The box still holds its space so the wordmark
   beside it never shifts, and so the JS can measure the target while the
   badge is still out on the stage.

   The fallback (no JS, reduced motion, under the pin threshold) fills it with the real
   badge image instead, see .crm-ui__brand-mark img in crm-spotlight.css. */
.crm-ui__brand-mark {
  width: 32px;
  height: 32px;
  flex: none;
  display: block;
  border-radius: 8px;
}

.crm-ui__brand-name {
  font-weight: 700;
  font-size: var(--crm-text-sm);
  letter-spacing: var(--crm-tracking-tight);
  white-space: nowrap;
}

.crm-ui__tenant {
  margin: 0;
  padding: 0 8px;
  font-size: 11px;
  color: var(--crm-muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.crm-ui__nav { display: flex; flex-direction: column; gap: 2px; }

.crm-ui__nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 30px;
  padding: 0 10px;
  border-radius: var(--crm-radius-sm);
  font-size: var(--crm-text-xs);
  font-weight: 600;
  color: var(--crm-ink);
}
.crm-ui__nav-item svg { width: 18px; height: 18px; flex: none; }
.crm-ui__nav-item.is-active { background: var(--crm-accent-subtle); color: var(--crm-accent-text); }

.crm-ui__spacer { flex: 1; }

/* UserChip.module.css */
.crm-ui__chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px;
  border-radius: var(--crm-radius-sm);
  border: 1px solid var(--crm-line);
}
.crm-ui__chip-avatar {
  width: 28px;
  height: 28px;
  flex: none;
  border-radius: var(--crm-radius-pill);
  background: var(--crm-accent);
  color: var(--crm-accent-on);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 800;
}
.crm-ui__chip-meta { min-width: 0; }
.crm-ui__chip-meta strong { display: block; font-size: var(--crm-text-xs); font-weight: 700; }
.crm-ui__chip-meta span { display: block; font-size: 11px; color: var(--crm-muted); }

/* ---------- main panel ---------- */
.crm-ui__main {
  background: var(--crm-white);
  border-radius: var(--crm-radius);
  padding: var(--crm-board-pad);
  min-width: 0;
  display: grid;
  /* The pane's 300px minimum is the load-bearing number here: below it the
     bubbles, the composer and the Send control start getting clipped by the
     board's fixed height and overflow, and Step 04's whole payoff disappears.
     The conversations track is the one that yields. */
  grid-template-columns: minmax(0, var(--crm-convos-w, 304px)) minmax(300px, 1fr);
  grid-template-rows: minmax(0, 1fr);
  gap: 10px;
}

/* ---------- conversations panel (ConversationsPanel.module.css) ---------- */
.crm-ui__convos {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: var(--crm-white);
  border: 1px solid var(--crm-line);
  border-radius: var(--crm-radius);
  overflow: hidden;
}

.crm-ui__convos-head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 12px 12px 16px;
  border-bottom: 1px solid var(--crm-line);
  min-height: 52px;
}
.crm-ui__convos-head h3 {
  margin: 0;
  flex: 1;
  font-size: var(--crm-text-sm);
  font-weight: 700;
  letter-spacing: var(--crm-tracking-tight);
}
.crm-ui__convos-count { font-size: 11px; font-weight: 600; color: var(--crm-accent-text); }
.crm-ui__convos-toggle { width: 22px; height: 22px; color: var(--crm-muted); flex: none; }

/* the four channel tiles, laid across the top of the list */
.crm-ui__channel-bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--crm-line);
}
.crm-ui__tile {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: var(--crm-radius-sm);
  background: var(--crm-cloud);
}
.crm-ui__tile svg { width: 20px; height: 20px; display: block; }
.crm-ui__tile-badge {
  position: absolute;
  top: -3px;
  right: -3px;
  min-width: 17px;
  height: 17px;
  padding: 0 5px;
  border-radius: var(--crm-radius-pill);
  background: var(--crm-accent);
  color: var(--crm-accent-on);
  font-size: 10px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 2px var(--crm-white);
}

.crm-ui__rows {
  list-style: none;
  margin: 0;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 0;
  overflow: hidden;
}

/* Icon led: the app mark is the leading element, no initials avatar. With four
   inboxes pooled into one list the first question a host asks is which app
   this arrived in. Straight from ConversationsPanel.tsx's header. */
.crm-ui__row {
  display: flex;
  gap: 12px;
  padding: 11px 12px;
  border-radius: var(--crm-radius-sm);
  color: var(--crm-ink);
}
.crm-ui__row.is-selected { background: var(--crm-accent-subtle); }

/* A rounded tile rather than a circle: these are app icons, and all four ship
   as a squircle on the platforms the host knows them from. */
.crm-ui__row-mark {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--crm-radius-sm);
  background: var(--crm-cloud);
}
.crm-ui__row-mark svg { width: 20px; height: 20px; display: block; }

.crm-ui__row-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.crm-ui__row-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 0; }
.crm-ui__row-name {
  font-size: var(--crm-text-xs);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.crm-ui__row.is-unread .crm-ui__row-name { font-weight: 700; }
.crm-ui__row-time { flex: none; font-size: 11px; color: var(--crm-muted); }
.crm-ui__row-summary {
  margin: 0;
  font-size: 12px;
  line-height: 1.4;
  color: var(--crm-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.crm-ui__row-foot { display: flex; align-items: center; gap: 8px; margin: 2px 0 0; }
.crm-ui__row-channel { font-size: 10.5px; font-weight: 600; color: var(--crm-muted); }
.crm-ui__pip {
  padding: 1px 6px;
  border-radius: var(--crm-radius-pill);
  background: var(--crm-accent);
  color: var(--crm-accent-on);
  font-size: 10px;
  font-weight: 700;
}

/* ---------- the conversation (InboxPanels.module.css) ---------- */
.crm-ui__pane {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  background: var(--crm-white);
  border: 1px solid var(--crm-line);
  border-radius: var(--crm-radius);
  overflow: hidden;
}

.crm-ui__pane-head {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--crm-line);
  flex: none;
}
.crm-ui__back { flex: none; width: 26px; height: 26px; color: var(--crm-muted); transform: rotate(180deg); }
.crm-ui__pane-avatar {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--crm-accent);
  color: var(--crm-accent-on);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
}
.crm-ui__pane-identity { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.crm-ui__pane-name { font-size: var(--crm-text-xs); font-weight: 700; }
.crm-ui__pane-stay { font-size: 11px; color: var(--crm-muted); }
.crm-ui__pane-channel {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--crm-muted);
  background: var(--crm-cloud);
  border-radius: var(--crm-radius-pill);
  padding: 5px 10px;
}

/* Channel as a coloured dot plus its name in text, never a vendor logo. That
   is InboxPanels.tsx's rule and it is the one place in this replica where a
   brand mark would be wrong. */
.crm-ui__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--crm-muted); flex: none; display: inline-block; }
.crm-ui__dot[data-channel="whatsapp"] { background: var(--crm-success); }
.crm-ui__dot[data-channel="telegram"] { background: var(--crm-signal-blue); }
.crm-ui__dot[data-channel="email"] { background: var(--crm-violet-bright); }

/* justify-content:flex-end, so when the pane is short - and it is, at every
   width below 1440, because the board height is fixed and a narrower composer
   wraps the reply onto more lines - the message that gets clipped is the
   OLDEST one at the top, never the newest at the bottom. Measured at 1280
   before this: the third and most recent bubble, the one the reply is
   answering, was the one cut off. Which is also how a real thread behaves. */
.crm-ui__messages {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  padding: 16px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 14px;
}
.crm-ui__bubble-row { display: flex; flex-direction: column; gap: 5px; max-width: 76%; }
.crm-ui__bubble-row[data-direction="outbound"] { align-self: flex-end; align-items: flex-end; }
.crm-ui__bubble {
  margin: 0;
  padding: 10px 13px;
  border-radius: var(--crm-radius-sm);
  font-size: var(--crm-text-xs);
  line-height: var(--crm-leading-body);
}
.crm-ui__bubble[data-direction="inbound"] {
  background: var(--crm-cloud);
  color: var(--crm-ink);
  border-bottom-left-radius: var(--crm-radius-xs);
}
.crm-ui__bubble[data-direction="outbound"] {
  background: var(--crm-accent);
  color: var(--crm-accent-on);
  border-bottom-right-radius: var(--crm-radius-xs);
}
.crm-ui__bubble-meta { display: flex; align-items: center; gap: 6px; font-size: 10.5px; color: var(--crm-muted); padding: 0 2px; }

/* ---------- composer ---------- */
.crm-ui__composer { flex: none; border-top: 1px solid var(--crm-line); padding: 10px 14px 12px; background: var(--crm-white); }
.crm-ui__composer-field {
  border: 1px solid var(--crm-accent-border);
  border-radius: var(--crm-radius-sm);
  background: var(--crm-accent-subtle);
  padding: 9px 11px;
  min-height: 56px;
}
.crm-ui__composer-text {
  margin: 0;
  font-size: var(--crm-text-xs);
  line-height: var(--crm-leading-body);
  color: var(--crm-ink);
  min-height: 20px;
}
/* The placeholder belongs on the SPAN that gets typed into, not the
   paragraph: the paragraph also holds the caret, so it is never :empty and the
   composer sat as a blank box for the whole first half of the section. */
.crm-ui__composer-text > [data-crm-type]:empty::before { content: "Reply on WhatsApp\2026"; color: var(--crm-muted); }
.crm-ui__caret {
  display: inline-block;
  width: 1.5px;
  height: 14px;
  background: var(--crm-accent);
  vertical-align: -2px;
  margin-left: 1px;
  opacity: 0;
}
/* The caret only exists while the reply is being typed. Outside that it is a
   blinking bar in a finished message, which reads as a bug. */
.crm-ui--typing .crm-ui__caret { opacity: 1; animation: crm-caret 1s steps(1) infinite; }
@keyframes crm-caret { 50% { opacity: 0; } }

.crm-ui__composer-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 9px; }
.crm-ui__send-via { display: flex; align-items: center; gap: 7px; font-size: 11px; color: var(--crm-muted); }
.crm-ui__change { color: var(--crm-accent-text); font-weight: 600; }
.crm-ui__send {
  font-size: var(--crm-text-xs);
  font-weight: 600;
  padding: 7px 15px;
  border-radius: var(--crm-radius-sm);
  background: var(--crm-cloud);
  color: var(--crm-muted);
  transition: background .3s var(--ease, cubic-bezier(.22,1,.36,1)), color .3s var(--ease, cubic-bezier(.22,1,.36,1));
}
.crm-ui__send.is-lit { background: var(--crm-accent); color: var(--crm-accent-on); }


/* ---------- the pane's two states ----------
   The real app shows an EmptyState until a conversation is picked, so the
   walkthrough shows the same thing: the pane starts empty and the thread
   arrives in it. Both states are stacked in the same box rather than swapped,
   so the pane's own size never changes and the window cannot twitch when the
   thread opens. */
.crm-ui__pane { position: relative; }

.crm-ui__pane-empty {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 32px;
  text-align: center;
  background: var(--crm-white);
  border-radius: var(--crm-radius);
  pointer-events: none;
}
.crm-ui__pane-empty p:first-child { margin: 0; font-size: var(--crm-text-sm); font-weight: 700; }
.crm-ui__pane-empty p:last-child { margin: 0; max-width: 30ch; font-size: 12px; color: var(--crm-muted); }

.crm-ui__conv {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}

/* The visually hidden description that carries the aria-hidden replica. */
.crm-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------
   The replica is a 1440px product shown inside an illustration whose width is
   a function of the viewport. Every step below was picked by measuring the
   resulting conversation pane, which must stay above 300px so the thread, the
   composer and Send all survive the board's fixed height:

     viewport   window   rail   convos   pane
     1440       980      224    304      390
     1366       970      196    280      432
     1280       884      196    280      346
     1180       824       60    248      454
     1024       668       60    248      298

   Under 1280 the rail collapses to the icon rail the real app already uses at
   its own narrow breakpoint, rather than the sidebar being deleted: the flying
   badge parks on .crm-ui__brand-mark, so that slot has to exist and stay 32px
   at every width the section pins at.
   --------------------------------------------------------------- */
@media (max-width: 1399px) {
  .crm-ui { --crm-rail-w: 196px; --crm-convos-w: 280px; }
}

@media (min-width: 900px) and (max-width: 1279px) {
  .crm-ui { --crm-rail-w: 60px; --crm-convos-w: 248px; }
  .crm-ui__side { padding: 12px 8px; align-items: stretch; }
  .crm-ui__brand { padding: 4px 0; justify-content: center; gap: 0; }
  .crm-ui__brand-name,
  .crm-ui__tenant { display: none; }
  /* font-size:0 rather than a wrapper span: the label is a bare text node next
     to the glyph, and the glyph carries explicit width/height attributes so it
     is unaffected. */
  .crm-ui__nav-item { justify-content: center; padding: 0; gap: 0; font-size: 0; }
  .crm-ui__chip { justify-content: center; padding: 6px 2px; }
  .crm-ui__chip-meta { display: none; }
}

/* ---------------------------------------------------------------
   Narrow. The pinned section never runs under 1024px, so this is the stacked
   fallback's job: keep every one of the four channels identifiable, drop the
   two-panel inbox to one column, and never scroll sideways.
   --------------------------------------------------------------- */
@media (max-width: 899px) {
  .crm-ui { border-radius: 20px; }
  .crm-ui__board { grid-template-columns: 1fr; height: auto; }
  .crm-ui__side { overflow: visible; }
  /* The rail is the app's own <700px behaviour: MobileNavDrawer takes over and
     the sidebar is gone. Keeping the brand row is what carries the handoff. */
  /* .crm-ui__side > .crm-ui__nav-item catches the bare "How it works" row,
     which is a SIBLING of .crm-ui__nav rather than a child of it and so
     survived the rail being dropped, sitting alone under the brand row. */
  .crm-ui__nav,
  .crm-ui__side > .crm-ui__nav-item,
  .crm-ui__tenant,
  .crm-ui__spacer,
  .crm-ui__chip { display: none; }
  .crm-ui__side { padding: 10px; }
  .crm-ui__main { grid-template-columns: minmax(0, 1fr); }
  .crm-ui__rows { overflow: visible; }
  .crm-ui__messages { overflow: visible; justify-content: flex-start; }
  .crm-ui__bubble-row { max-width: 88%; }
}

/* ============================================================
   THE REPLICA IN PORTRAIT
   ============================================================

   Under 1024px the section does not shrink the desktop window, it renders a
   phone. Same DOM, same nodes, same data-crm hooks - so the badge still parks
   on the real brand mark, the rows are still the real rows, and there is no
   second replica to keep in sync with this one.

   The rules: nothing scales, nothing is hidden that the animation drives, and
   the brand slot stays on screen because the whole payoff of the section is
   the badge landing in it.
   ============================================================ */

.crm-spot--phone .crm-ui {
  --crm-screen-radius: calc(var(--crm-phone-w, 300px) * .13);
  width: var(--crm-phone-w);
  /* Match the supplied 809 x 1667 iPhone exactly. The original screenshot is
     the device surface; the live CRM DOM is inset over its screen so the
     scroll-driven rows, thread and reply remain code rather than a flattened
     screenshot. */
  height: calc(var(--crm-phone-w) * 2.06057);
  /* Flex, so the board takes exactly what the status bar leaves. As a grid
     child with height:100% it overran the shell by 18px and the composer's
     bottom edge was being sliced off by the shell's own overflow. */
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  /* These insets are measured from the supplied 809 x 1667 frame: the live
     screen begins at x=35 and y=29, and finishes 30px above the image edge. */
  padding: 3.55% 4.35% 3.75%;
  border: 0;
  border-radius: 0;
  background: transparent url("../public/brand/devices/iphone-frame.webp") center / 100% 100% no-repeat;
  box-shadow: none;
  filter: drop-shadow(0 22px 24px rgb(25 23 28 / .32)) drop-shadow(0 2px 4px rgb(25 23 28 / .10));
  overflow: visible;
}

/* The live interface covers the wallpaper inside the supplied frame, so the
   Dynamic Island is restored as the topmost physical part of the device. */
.crm-spot--phone .crm-ui::after {
  content: "";
  position: absolute;
  z-index: 20;
  top: 3.45%;
  left: 35.65%;
  width: 28.7%;
  height: 4.08%;
  border-radius: 999px;
  background: #000;
  pointer-events: none;
}

/* Cover the supplied frame's illustrated wallpaper beneath the live screen.
   Wherever the rounded interface cuts away, the reveal must be the iPhone's
   black inner bezel rather than a green corner from the source artwork. */
.crm-spot--phone .crm-ui::before {
  content: "";
  position: absolute;
  z-index: 0;
  /* Vertical inset percentages resolve against the device height, unlike the
     percentage padding above, which resolves against its width. Use the
     equivalent height ratios so this cover begins at the same measured
     29px/30px screen edges. Its radius follows the supplied screen curve,
     which is tighter than the live board, so it covers the blue corner
     cutouts without painting over the metal frame. */
  inset: 1.72% 4.35% 1.82%;
  border-radius: var(--crm-screen-radius);
  background: #000;
  pointer-events: none;
}

.crm-spot--phone .crm-ui > * {
  position: relative;
  z-index: 1;
}

/* The browser chrome becomes a status bar. The dots and the URL are desktop
   furniture and say the wrong thing on a device. */
.crm-spot--phone .crm-ui__chrome {
  position: absolute;
  z-index: 3;
  top: 3.55%;
  left: 4.35%;
  right: 4.35%;
  height: 26px;
  padding: 0 14px;
  background: transparent;
  border-bottom: 0;
  border-radius: 0;
  justify-content: stretch;
}
.crm-spot--phone .crm-ui__dots { display: none; }
.crm-spot--phone .crm-ui__url {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-width: 0;
  font-size: 0;
  font-weight: 700;
  letter-spacing: .02em;
  color: transparent;
}
.crm-spot--phone .crm-ui__url::before {
  content: "9:14";
  color: var(--crm-ink, #17151b);
  font-size: 9px;
}
.crm-spot--phone .crm-ui__url::after {
  content: "";
  width: 19px;
  height: 8px;
  background:
    radial-gradient(circle at 2px 4px, rgb(25 23 28 / .46) 0 1.6px, transparent 1.8px),
    radial-gradient(circle at 9.5px 4px, rgb(25 23 28 / .46) 0 1.6px, transparent 1.8px),
    radial-gradient(circle at 17px 4px, rgb(25 23 28 / .46) 0 1.6px, transparent 1.8px);
}

.crm-spot--phone .crm-ui__board {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  gap: 8px;
  /* The status bar is overlaid so this one surface can carry the full top and
     bottom screen curve. 34px preserves the old 26px + 8px content offset. */
  padding: 34px 8px 8px;
  background: linear-gradient(var(--crm-white) 0 34px, var(--crm-mist) 34px);
  /* The board carries a fixed desktop height. Left on, it rendered 498px of
     board inside a 616px phone and the bottom 87px was dead white. */
  flex: 1;
  min-height: 0;
  border-radius: var(--crm-screen-radius);
  overflow: hidden;
}

/* The sidebar becomes a header strip. Everything in it that is navigation
   goes; the brand block stays, because that is where the badge lands. */
.crm-spot--phone .crm-ui__side {
  flex-direction: row;
  align-items: center;
  padding: 8px 10px;
  gap: 8px;
}
.crm-spot--phone .crm-ui__nav,
.crm-spot--phone .crm-ui__spacer,
.crm-spot--phone .crm-ui__chip,
.crm-spot--phone .crm-ui__tenant { display: none; }
.crm-spot--phone .crm-ui__head-block { flex-direction: row; align-items: center; flex: 1; }

.crm-spot--phone .crm-ui__main {
  position: relative;
  grid-template-columns: minmax(0, 1fr);
  padding: 0;
  gap: 0;
}

/* The list owns the screen. */
.crm-spot--phone .crm-ui__convos { border-radius: 18px; }

/* And the thread rides OVER it, the way a phone app pushes a detail view
   rather than sitting beside a list it has no room for. It is the same
   opacity channel the desktop drives - no new actor, no new band. */
/* The pane is the CONTAINER, and on desktop it is an opaque white card
   sitting beside the list. Laid over the list on a phone it hid the rows for
   the whole 0.58 -> 0.70 band, so the inbox resolved as an empty box and the
   "it lands in one list" beat had nothing to show. The container goes
   transparent and the thread itself - which is the node the driver actually
   fades - carries the surface. */
.crm-spot--phone .crm-ui__pane {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: transparent;
  border: 0;
  pointer-events: none;
}
.crm-spot--phone .crm-ui__conv {
  height: 100%;
  background: var(--crm-white);
  border: 1px solid var(--crm-line);
  border-radius: 18px;
  overflow: hidden;
}
.crm-spot--phone .crm-ui__pane-empty { display: none; }
/* The back chevron is dead furniture on desktop and the one control that
   makes the pushed view legible on a phone. */
.crm-spot--phone .crm-ui__back { display: block; }
/* Three bubbles plus a composer are taller than the pane on a phone, and
   with overflow visible the last bubble rendered straight through the
   composer. Clipped, and anchored to the bottom, so what gets cut is the
   OLDEST message - which is what a real thread does. */
.crm-spot--phone .crm-ui__messages {
  padding: 10px 12px;
  overflow: hidden;
  justify-content: flex-end;
}
.crm-spot--phone .crm-ui__composer { padding: 8px 12px 10px; }

/* The pane head was eating 122px of a 411px pane - the guest name wrapped to
   two lines because the channel pill was holding a third of the row - and the
   thread underneath was down to one visible message. The pill goes: every
   bubble already carries its own channel dot and the section's whole claim is
   that the channel stops mattering once it is in here. */
.crm-spot--phone .crm-ui__pane-head { padding: 8px 10px; gap: 8px; }
.crm-spot--phone .crm-ui__pane-channel { display: none; }
.crm-spot--phone .crm-ui__pane-avatar { width: 30px; height: 30px; font-size: 11px; }
.crm-spot--phone .crm-ui__pane-name { font-size: 13px; }
.crm-spot--phone .crm-ui__pane-stay { font-size: 10.5px; }
.crm-spot--phone .crm-ui__composer-foot { padding-top: 6px; }
.crm-spot--phone .crm-ui__bubble { font-size: 12.5px; }
.crm-spot--phone .crm-ui__bubble-meta { font-size: 10px; }

/* ==== area-pages-crm-spotlight.css ============================== */
/* ============================================================
   The pinned CRM section: four notifications become one inbox.

   Layout and motion only. The app replica inside the stage is css/crm-ui.css.

   THE SPOTLIGHT IS GONE. No dim layer, no mask, no mask-composite, no zoom,
   no pan, no clamped camera. That machinery was deleted rather than disabled,
   because a disabled camera is a camera somebody turns back on. The window
   resolves once and then HOLDS COMPLETELY STILL while only its contents
   change. Everything that moves after that moves inside it.

   Motion rule for this file: transform and opacity only. Nothing here may
   transition a layout property.

   Default state is the fallback: no pin, four marks in a row, the app window
   full width with the thread open and the reply already written. The pin is
   opt-in, applied by js/crm-spotlight.js only once it has confirmed the
   viewport is at least MIN_WIDTH (1024px) wide and motion is welcome. So no-JS, reduced
   motion and phones all land on the same layout without a second
   implementation.
   ============================================================ */

.crm-spot__track { position: relative; }

.crm-spot__grid {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 var(--gutter, 32px);
  display: grid;
  gap: 32px;
}

/* ---------- the copy column ---------- */
.crm-spot__copy {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 20px;
}

.crm-spot__beat em {
  font-style: normal;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #7c3aed;
}
.crm-spot__beat h3 {
  margin: 10px 0 10px;
  font-size: clamp(22px, 2.4vw, 32px);
  line-height: 1.08;
  letter-spacing: -.02em;
}
.crm-spot__beat p {
  margin: 0;
  color: #5d5962;
  font-size: 15.5px;
  line-height: 1.6;
  max-width: 46ch;
}

/* The stage clips its actors. It is the one box here that is NEVER
   transformed, so it is the only clip a transformed child cannot escape. */
.crm-spot__stage { position: relative; }

/* ---------- fallback: the four marks as a static row ---------- */
.crm-spot__marks {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: clamp(14px, 5vw, 34px);
  margin: 0 0 22px;
  pointer-events: none;
}
.crm-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  flex: none;
}
.crm-mark svg { display: block; width: 100%; height: 100%; }

/* The notification cards and the flying badge are motion devices with nothing
   to say at rest, so unpinned they are not rendered at all. What the claim
   needs at rest is the four marks above and the badge sitting in the app's own
   brand slot below, and both of those survive. */
.crm-spot__notes,
.crm-badge { display: none; }

/* The end state has the thread open, so the pane's empty state has nothing to
   say at rest either. */
.crm-ui__pane-empty { opacity: 0; }

/* Unpinned, the sidebar's brand slot carries the real badge image. Pinned, the
   slot is empty and the flying badge lands in it. Same 32px box either way. */
.crm-ui__brand-mark img { width: 32px; height: 32px; display: block; }

/* ============================================================
   PINNED
   ============================================================ */

/* 420vh: four beats, and the notification stack needs its own runway before
   the inbox ever appears. */
.crm-spot--pinned .crm-spot__track { height: 420vh; }

.crm-spot--pinned .crm-spot__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
}

/* Pinned, the grid gives up the 1180px prose measure and takes the section's
   full gutter-to-gutter width. §5b wants the window at up to 980px and the
   copy column still needs 300px beside it, and 1180 cannot pay for both: at
   1440 it left the window 676px, which is the size the spec enlarged it FROM.
   The copy column is capped rather than proportional so the window keeps
   every pixel a wider viewport hands over, up to its own 980px ceiling. */
.crm-spot--pinned .crm-spot__grid {
  max-width: none;
  grid-template-columns: minmax(280px, 340px) minmax(0, 1fr);
  gap: 44px;
  align-items: center;
  width: 100%;
  /* The section's own clamp(82px, 8vw, 128px) block padding is what the head
     used to sit in. With the head gone that padding is dead space inside a
     100vh sticky, so the grid is optically centred against the viewport
     instead of inheriting the section's rhythm. */
  padding-block: 0;
}

.crm-spot--pinned .crm-spot__copy {
  position: relative;
  display: block;
  /* Tall enough to hold the longest beat, and no taller. Measured beat heights
     at the four pinning widths, tallest first:
       1280  293.8  (beat 0, the copy wraps hardest here)
       1440  273.1
       1024  269.1
       1366  262.4
     306px clears the worst of them by 12px, which is the gap the progress rule
     wants under the last line. At 340 the rule floated in dead space below the
     copy at every width, which is what made the whole column read bottom-heavy
     against the stage. At 260 - the value before that - the four-line first
     beat overran its own box and the rule drew THROUGH the last line. */
  min-height: 306px;
}

/* Stage scrubs continuously, copy STEPS. The beat index is discrete and its
   tweens are eased, because a beat caught half way between two states is
   saying nothing. The mismatch against the continuously driven stage is what
   stops the section reading as one flat slider. */
.crm-spot--pinned .crm-spot__beat {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .45s cubic-bezier(.22,.61,.36,1), transform .45s cubic-bezier(.22,.61,.36,1);
  pointer-events: none;
}
.crm-spot--pinned .crm-spot__beat.is-active {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Progress bar drawn from the active beat's index, so it cannot disagree with
   the copy. */
.crm-spot--pinned .crm-spot__copy::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -6px;
  width: 92px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(to right, #4c1d95 var(--crm-progress, 25%), rgb(76 29 149 / .14) var(--crm-progress, 25%));
}

/* §5b: 560px, and the window inside it is min(980px, 100%). Copy legibility at
   this size is the reason for enlarging it. The stage does NOT clip: the
   notification stack is deliberately taller than the window it collapses into,
   and clipping the top of the stack is what turned the clutter into a neat
   row. Nothing here ever leaves the grid column. */
.crm-spot--pinned .crm-spot__stage { height: 560px; }

/* ---------- the four notification cards ---------- */
/*
 * The opening is a phone's notification shade, not four floating icons. Each
 * card carries its app icon, a guest name and a line of what they wrote, and
 * they slide in one after another and pile up slightly overlapped and rotated.
 * That mess IS the problem statement, so the cards have to be readable: a
 * blurred stack of grey rectangles says nothing, four real messages say
 * "this is your morning".
 *
 * Geometry is shared with js/crm-spotlight.js and the two must agree:
 *   card       306 x 72
 *   icon slot  44px square, 12px in from the left edge
 *              so its centre sits at -(306/2) + 12 + 22 = -119 from the
 *              card's own centre. That is the constant the marks layer uses to
 *              ride the cards before it detaches from them.
 */
.crm-spot--pinned .crm-spot__notes {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

.crm-note {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 306px;
  height: 70px;
  margin: -35px 0 0 -153px;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 14px 0 12px;
  border-radius: 18px;
  background: rgb(255 255 255 / .94);
  border: 1px solid rgb(76 29 149 / .10);
  box-shadow: 0 18px 40px -16px rgb(25 23 28 / .32), 0 1px 3px rgb(25 23 28 / .06);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  will-change: transform, opacity;
}

/* The hole the icon leaves behind when it detaches. It is the same cloud tile
   the inbox rows use, so the card reads as a row that has lost its mark. */
.crm-note__slot {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: #f3f3f5;
}

.crm-note__body { flex: 1; min-width: 0; }
.crm-note__top {
  margin: 0 0 2px;
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: #5d5962;
}
.crm-note__top b { font-weight: 700; }
.crm-note__top span { margin-left: auto; font-weight: 600; letter-spacing: 0; text-transform: none; }
.crm-note__name { margin: 0; font-size: 13.5px; font-weight: 700; color: #19171c; line-height: 1.25; }
.crm-note__text {
  margin: 0;
  font-size: 12.5px;
  color: #5d5962;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- the marks, once they are actors ---------- */
/*
 * The marks live in the STAGE, never inside a card and never inside the
 * window. Riding the cards is done in JS by adding the card's own transform to
 * the icon-slot offset above, which is the only way an icon can leave a
 * rotating card without inheriting the rotation on the way out. A mark
 * parented to a card would tumble as it flew.
 */
.crm-spot--pinned .crm-spot__marks {
  display: block;
  position: absolute;
  inset: 0;
  margin: 0;
  z-index: 3;
  pointer-events: none;
}
.crm-spot--pinned .crm-mark {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  margin: -22px 0 0 -22px;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 6px 16px -4px rgb(25 23 28 / .28);
  will-change: transform, opacity;
}
.crm-spot--pinned .crm-mark svg { width: 26px; height: 26px; }

/* ---------- the badge ---------- */
/*
 * The payoff. Four apps resolve into this, it travels to the app's own brand
 * slot, and it BECOMES the sidebar logo with the wordmark fading in beside it.
 * It is a static image element and is never redrawn, recoloured or re-cropped.
 *
 * 120px base box, parked at scale 32/120 = 0.2667 so it lands at the app's
 * real 32px brand mark. The park point is measured off the replica's own DOM,
 * never hardcoded, so it survives a resize.
 */
.crm-spot--pinned .crm-badge {
  display: block;
  position: absolute;
  left: 50%;
  top: 50%;
  width: 120px;
  height: 120px;
  margin: -60px 0 0 -60px;
  /* z-index 2, UNDER the marks at 3, not over them. At 4 the four marks
     dissolved BEHIND the badge, which reads as vanishing; underneath it they
     dissolve in front of it, which reads as the badge emerging out of them.
     Still above the notes at 1 and above the window, which is positioned with
     z-index:auto and therefore paints at level 0. */
  z-index: 2;
  opacity: 0;
  will-change: transform, opacity;
}

/* Band B only. Once parked the badge is a 32px logo in a white card and a
   drop shadow under it would give the app's own sidebar a floating icon. */
.crm-spot--pinned .crm-badge.is-flying { filter: drop-shadow(0 14px 34px rgb(76 29 149 / .32)); }

/* Pinned, the wordmark is JS-driven: it fades in as the badge settles beside
   it. Unpinned it is simply there. */
.crm-spot--pinned .crm-ui__brand-name { opacity: 0; }
.crm-spot--pinned .crm-ui__brand-mark img { display: none; }

/* The window is what Band B resolves. It scales from 0.94 to 1 and then NEVER
   transforms again for the rest of the section. */
.crm-spot--pinned .crm-ui { will-change: transform, opacity; opacity: 0; }

/* ---------------------------------------------------------------
   Between 900 and 1080 the copy column and a 980px window will not both fit,
   so the window takes what is left rather than the grid overflowing.
   --------------------------------------------------------------- */
@media (max-width: 1399px) {
  .crm-spot--pinned .crm-spot__grid {
    grid-template-columns: minmax(260px, 300px) minmax(0, 1fr);
    gap: 32px;
  }
}
@media (max-width: 1279px) {
  .crm-spot--pinned .crm-spot__grid {
    grid-template-columns: minmax(236px, 268px) minmax(0, 1fr);
    gap: 24px;
  }
  .crm-spot--pinned .crm-spot__beat p { font-size: 15px; }
}

/* ============================================================
   PHONE - the same sequence, in portrait
   ============================================================

   The pin used to bail out under 1024px, and the reason was sound: a 980px
   desktop window on a 390px screen is either a 40% scale nobody can read or a
   horizontal scrollbar. What was wrong was the conclusion. The answer was
   never a second, lesser animation with its own driver, its own bands and its
   own set of bugs - it was to stop rendering a DESKTOP window down there.

   `.crm-spot--phone` is added by js/crm-spotlight.js alongside `--pinned`
   under 1024px. It reshapes the SAME replica into a portrait phone at 1:1
   type size: the sidebar becomes a top bar (the brand slot stays, so the badge
   still parks on a real measured target), the conversations list takes the
   screen, and the thread pane rides over it the way a phone app pushes a
   detail view. Every band, every constant and every actor is unchanged.

   Nothing is scaled. The phone is 1:1 or it is not shipped.
   ============================================================ */

/* ---------- interleaving the copy with the animation ----------
   Under 1024 the copy column and the stage are not two columns any more, they
   are one flow, and the <ol> stacked all four steps ABOVE the animation: a
   phone reader finished Steps 01-04 and only then scrolled into the four cards
   arriving, so the animation illustrated copy they had left a screen ago.

   Both wrappers go display:contents so their children become items of one flex
   column and can be ordered against each other. Nothing is duplicated: there
   is still exactly one copy of each beat in the document, in reading order for
   the fallback, and the DOM order the pin needs above 1024 is untouched.

   Scoped to the UNPINNED section. It was written when the pin bailed out
   under 1024 and the section arrived on a phone as one stacked flow; the
   pin now runs at every width, so with motion on there is no flow to
   interleave - the phone replica IS the animation and the copy steps beside
   it. What is left is exactly the case this was written for and the only one
   still reachable: JS off, or reduced motion, where the class never lands,
   the section is a stacked flow, and the ordering problem is identical.

   Each step now sits with the moment it describes:
     Step 01  the clutter          above the four marks and the pile
     Step 02  one list instead     between the pile and the inbox
     Step 03  the history is there
     Step 04  you answer from here below the inbox that shows both
   -------------------------------------------------------------- */
@media (max-width: 1023.98px) {
  .crm-section:not(.crm-spot--pinned) .crm-spot__grid { display: flex; flex-direction: column; }
  .crm-section:not(.crm-spot--pinned) .crm-spot__copy,
  .crm-section:not(.crm-spot--pinned) .crm-spot__stage { display: contents; }
  .crm-section:not(.crm-spot--pinned) .crm-spot__beat:nth-child(1) { order: 1; }
  .crm-section:not(.crm-spot--pinned) .crm-spot__marks { order: 2; }
  .crm-section:not(.crm-spot--pinned) .crm-spot__notes { order: 3; }
  .crm-section:not(.crm-spot--pinned) .crm-spot__beat:nth-child(2) { order: 4; }
  .crm-section:not(.crm-spot--pinned) .crm-ui { order: 5; }
  .crm-section:not(.crm-spot--pinned) .crm-spot__beat:nth-child(3) { order: 6; }
  .crm-section:not(.crm-spot--pinned) .crm-spot__beat:nth-child(4) { order: 7; }
}

/* The .crm-spot--mobile rules that stood here are gone with the class.
   That mode - the stacked, unpinned reveal under 1024 - no longer exists:
   the pin runs at every width and the replica becomes a phone instead.
   The measurements banked in them (the -6px bleed against the 14px
   gutter, the 520px card cap) belonged to full-width flowed cards, which
   the phone does not have - its cards are stage-positioned against a
   250px device. Kept in git, not here. */

.crm-spot--phone {
  /* ONE width, and the phone's height, the stage and the notification cards
     are all derived from it. The svh term is what stops the device growing
     taller than the viewport it has to share with the copy: at 33svh the
     phone is 66svh and the beat block keeps the rest. Measured against 844
     (iPhone 15) and 667 (SE) - at a flat 330px the copy's fourth line was
     rendering underneath the phone on both.

     30svh, not 33, and 70vw, not 84. At 33/84 the device measured 278 x 557
     inside a 390 x 844 screen: 71% of the width and 66% of the height, with
     the beat block taking most of what was left. Nothing overlapped, but
     there was no air anywhere in the frame and the whole section read heavy.
     At 30/70 it is 253 x 506 on the same screen, which leaves ~175px of
     unclaimed height once the beat and the gaps are paid for. That space IS
     the fix - the beat has not lost a word, it has been given a margin.

     The inner UI is stepped down with the device below, because a shell that
     shrinks while its type does not is exactly what "blown up" looks like. */
  --crm-phone-w: min(300px, 70vw, 30svh);
}

/* Shorter runway. Four beats still, but the reader is scrolling a phone and
   420vh of thumb is a section people leave. */
.crm-spot--phone .crm-spot__track { height: 360vh; }

/* Two units, two different jobs, and using only one of them is the bug.
   `100svh` is the viewport with the mobile browser chrome EXPANDED, `100lvh`
   is it with the chrome collapsed. The chrome is expanded on the first frame
   and collapses the moment you scroll - so a sticky locked to svh keeps its
   smaller height while the real viewport grows to lvh, and a dead white band
   opens at the bottom. That is exactly the "only appears once you start
   scrolling" white space.

   So: the BOX is lvh, which is the tallest the viewport ever gets, and there
   is never a band under it. The usable CONTENT area is pulled back to svh by
   padding out the difference, so on the first frame - chrome still expanded -
   the phone's composer is not sitting under the address bar. As the chrome
   collapses the inset goes to zero on its own and the content reclaims the
   space. Nothing is measured in JS and nothing has to be re-measured. */
.crm-spot--phone .crm-spot__sticky {
  --chrome-inset: 0px;
  height: 100svh;
  box-sizing: border-box;
}

@supports (height: 100lvh) {
  .crm-spot--phone .crm-spot__sticky {
    --chrome-inset: calc(100lvh - 100svh);
    height: 100lvh;
    padding-bottom: var(--chrome-inset);
  }
}

.crm-spot--phone .crm-spot__grid {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  gap: 18px;
  padding: 18px 16px 22px;
  align-content: center;
  justify-items: center;
}

/* One line of copy, not four. The beat block keeps stepping - the stepped copy
   is half the section - but it gets a phone's worth of room. */
.crm-spot--phone .crm-spot__copy {
  /* 132, not 92. The beats are absolutely positioned inside this box, so a
     box shorter than the tallest beat does not grow - it lets the last line
     render on top of whatever is underneath, which here is the phone. 148 is
     the measured height of the four-line beat at the type size below. */
  min-height: 148px;
  width: 100%;
  max-width: 420px;
}

/* One step down from 21/14/11. A 21px heading over a 14px paragraph is a
   desktop beat rendered on a phone: at 390 the first beat's heading ran two
   lines and its paragraph ran four, and between them they took 135px before
   the device had drawn a pixel. 18/12.75/10 says the same words in ~115px and
   reads as a caption on a step rather than a section header, which is what a
   numbered step IS. The copy is untouched - this is a type scale, not a cut. */
.crm-spot--phone .crm-spot__beat h3 { font-size: 18px; line-height: 1.16; margin: 5px 0 5px; }
.crm-spot--phone .crm-spot__beat p { font-size: 12.75px; line-height: 1.52; }
.crm-spot--phone .crm-spot__beat em { font-size: 10px; letter-spacing: .16em; }

/* The stage is the phone's own box, so the cards pile against the device
   rather than against the viewport. */
.crm-spot--phone .crm-spot__stage {
  height: auto;
  width: var(--crm-phone-w);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 268 x 66, down from 306 x 70. The margin is half of each, and both of these
   are READ BACK by measureGeometry() rather than duplicated in the JS. */
/* Opaque on the phone. At 94% the card below shows THROUGH the one on top of
   it, and on a 12px overlap that is a whole name line ghosting up through the
   card above - which reads as a rendering fault, not as a pile. */
.crm-spot--phone .crm-note {
  background: #fff;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* The cards follow the device. A 268px card on a 220px phone (an SE) hangs
   55px past the stage on each side once the jitter is on it, and that is a
   horizontal scrollbar. They are clipped at the sticky rather than at the
   stage, so the pile still spills past the phone's edges - which is the point
   of a pile - without ever reaching the document. */
.crm-spot--phone .crm-spot__sticky { overflow-x: clip; }

.crm-spot--phone .crm-note {
  width: min(268px, calc(var(--crm-phone-w) - 12px));
  height: 66px;
  margin: -33px 0 0 calc(min(268px, calc(var(--crm-phone-w) - 12px)) / -2);
  border-radius: 16px;
  /* Symmetrical 12px, not 12/10. measureGeometry() in js/crm-spotlight.js
     derives the icon-slot offset as -(cardWidth / 2) + 34, and 34 is
     12 + 44/2. At 10px of left padding the marks rode the cards 2px off
     centre for the whole opening band. */
  padding: 0 12px;
}
.crm-spot--phone .crm-note__name { font-size: 13.5px; }
.crm-spot--phone .crm-note__text { font-size: 12.5px; }
.crm-spot--phone .crm-note__top { font-size: 10px; }

/* The four brand glyphs sit over the phone, not beside it. */
.crm-spot--phone .crm-spot__marks { gap: 14px; }
.crm-spot--phone .crm-mark { width: 44px; height: 44px; }

/* ============================================================
   THE REPLICA'S OWN TYPE SCALE, ON THE PHONE
   ============================================================

   crm-ui.css builds the replica at desktop sizes and the phone rules there
   step down the handful of nodes that broke outright. Everything else was
   still drawn at 1:1 desktop inside a 253px device, which is why the shell
   read as a screenshot someone had zoomed: 13px names and 38px channel tiles
   are correct on a 980px window and enormous on a device a quarter that wide.

   So the whole interior is stepped down together here, in one place, at
   roughly 0.8 of the desktop figure. The rule is proportion: a real phone
   renders SMALLER type in a SMALLER frame, and any node left at its desktop
   size is the one that gives the trick away.

   These live in crm-spotlight.css rather than crm-ui.css on purpose. This
   file loads second, so equal-specificity `.crm-spot--phone` rules land on
   top of the ones there without a specificity arms race, and the replica
   keeps one owner for its desktop sizes.

   Nothing outside `.crm-spot--phone` is touched, so desktop is untouched by
   construction: the class is only ever added under 1024px.
   ------------------------------------------------------------ */

/* ---- the shell ---- */
.crm-spot--phone .crm-ui__chrome { height: 22px; padding: 0 12px; }
.crm-spot--phone .crm-ui__url { font-size: 9px; }
.crm-spot--phone .crm-ui__board {
  padding: 28px 6px 6px;
  background: linear-gradient(var(--crm-white) 0 28px, var(--crm-mist) 28px);
  gap: 6px;
}

/* ---- the header strip ---- */
.crm-spot--phone .crm-ui__side { padding: 6px 8px; gap: 7px; }
.crm-spot--phone .crm-ui__brand { padding: 2px 4px; gap: 8px; }
/* The badge's park point is MEASURED off this box every resize, so shrinking
   it moves the landing with it rather than desynchronising the payoff. */
.crm-spot--phone .crm-ui__brand-mark { width: 26px; height: 26px; border-radius: 7px; }
.crm-spot--phone .crm-ui__brand-mark img { width: 26px; height: 26px; }
.crm-spot--phone .crm-ui__brand-name { font-size: 12.5px; }

/* ---- the conversations list ---- */
.crm-spot--phone .crm-ui__convos { border-radius: 15px; }
.crm-spot--phone .crm-ui__convos-head { padding: 8px 10px; min-height: 0; gap: 8px; }
.crm-spot--phone .crm-ui__convos-head h3 { font-size: 12px; }
.crm-spot--phone .crm-ui__convos-count { font-size: 9.5px; }
.crm-spot--phone .crm-ui__channel-bar { padding: 6px 10px; gap: 5px; }
.crm-spot--phone .crm-ui__tile { width: 30px; height: 30px; border-radius: 8px; }
.crm-spot--phone .crm-ui__tile svg { width: 17px; height: 17px; }
.crm-spot--phone .crm-ui__tile-badge { min-width: 14px; height: 14px; padding: 0 4px; font-size: 8.5px; top: -2px; right: -2px; }

.crm-spot--phone .crm-ui__rows { padding: 5px; }
.crm-spot--phone .crm-ui__row { padding: 8px 9px; gap: 9px; border-radius: 9px; }
.crm-spot--phone .crm-ui__row-mark { width: 28px; height: 28px; border-radius: 8px; }
.crm-spot--phone .crm-ui__row-mark svg { width: 16px; height: 16px; }
.crm-spot--phone .crm-ui__row-name { font-size: 11.5px; }
.crm-spot--phone .crm-ui__row-time { font-size: 9.5px; }
.crm-spot--phone .crm-ui__row-summary { font-size: 10.5px; line-height: 1.35; }
.crm-spot--phone .crm-ui__row-channel { font-size: 9.5px; }
.crm-spot--phone .crm-ui__pip { font-size: 8.5px; padding: 1px 5px; }

/* ---- the thread ---- */
.crm-spot--phone .crm-ui__conv { border-radius: 15px; }
.crm-spot--phone .crm-ui__pane-head { padding: 7px 9px; gap: 7px; }
.crm-spot--phone .crm-ui__back { width: 20px; height: 20px; }
.crm-spot--phone .crm-ui__pane-avatar { width: 26px; height: 26px; font-size: 9.5px; }
/* Scaled off the device rather than fixed, for the reason set out over the
   composer below: --crm-phone-w carries an svh term, so a short phone gets a
   narrow device however wide its screen is, and a fixed 11.5px name plus a
   fixed 9.5px stay line wrapped the head onto three lines at 320 x 720. */
.crm-spot--phone .crm-ui__pane-name { font-size: clamp(10px, calc(var(--crm-phone-w) * .0455), 11.5px); }
.crm-spot--phone .crm-ui__pane-stay { font-size: clamp(8.2px, calc(var(--crm-phone-w) * .0375), 9.5px); }
.crm-spot--phone .crm-ui__messages { padding: 8px 10px; gap: 9px; }
.crm-spot--phone .crm-ui__bubble-row { gap: 3px; max-width: 84%; }
.crm-spot--phone .crm-ui__bubble { font-size: 11px; padding: 7px 9px; border-radius: 9px; }
.crm-spot--phone .crm-ui__bubble-meta { font-size: 8.5px; gap: 4px; }

/* ---- the composer, and the one collision this pass exists to kill ----
   At 11px "Sending on WhatsApp" plus a 13px Change plus a 13px Send needed
   more than the 239px of interior the device has, so the label wrapped onto
   two lines and pushed itself under the Change control it is supposed to sit
   beside. The label drops to 9px, Change with it, and the Send button loses
   6px of horizontal padding: measured, the row is ~150px wide inside the
   ~186px the narrowest phone this ships to (320) leaves it.

   flex:none on the label, NOT min-width:0. Shrinking was tried first and is
   worse: a nowrap label in a shrinking box does not get smaller, it overflows
   its own right edge, and at 360 that put "Change" 15px into the Send button
   with nothing in the box model to say so. Unshrinkable, the row either fits -
   which at these sizes it does at every width from 320 up - or it overflows
   the composer, which the QA overflow assertion catches. A layout that fails
   loudly beats one that silently draws two controls on top of each other.

   And the sizes are calc'd off --crm-phone-w rather than fixed, because the
   device width is NOT a function of the screen width alone: --crm-phone-w
   carries a 30svh term, so a 320 x 720 screen gets a 216px device and a
   390 x 844 screen gets a 253px one. Fixed 9px/10px fitted 253 and overflowed
   216 - Send was sliced in half by the thread card's own overflow:hidden,
   which is exactly the silent failure the flex:none above is meant to avoid.
   One number drives the device, its interior and this row, so they cannot
   disagree at a size nobody measured. The clamps are the floor: below them
   the label stops being type and starts being texture. */
.crm-spot--phone .crm-ui__composer { padding: 7px calc(var(--crm-phone-w) * .032) 9px; }
.crm-spot--phone .crm-ui__composer-field { padding: 7px 9px; min-height: 44px; border-radius: 9px; }
.crm-spot--phone .crm-ui__composer-text { font-size: 11px; min-height: 16px; }
.crm-spot--phone .crm-ui__caret { height: 11px; }
.crm-spot--phone .crm-ui__composer-foot { margin-top: 6px; padding-top: 0; gap: 6px; }
.crm-spot--phone .crm-ui__send-via {
  font-size: clamp(7.6px, calc(var(--crm-phone-w) * .0356), 9px);
  gap: 5px;
  flex: none;
  white-space: nowrap;
}
.crm-spot--phone .crm-ui__send-via .crm-ui__dot { width: 5px; height: 5px; }
.crm-spot--phone .crm-ui__change { flex: none; }
.crm-spot--phone .crm-ui__send {
  font-size: clamp(8.4px, calc(var(--crm-phone-w) * .0395), 10px);
  padding: 5px calc(var(--crm-phone-w) * .04);
  border-radius: 9px;
  flex: none;
}

@media (max-width: 768px) {
  .crm-spot__grid { padding: 0 14px; gap: 26px; }
  .crm-spot__marks { gap: 18px; margin-bottom: 18px; }
  .crm-mark { width: 46px; height: 46px; }
}


@media (prefers-reduced-motion: reduce) {
  .crm-spot__beat { transition: none; }
  .crm-ui__caret { animation: none; opacity: 0; }
}

/* ============================================================
   THE DESKTOP PHONE
   ============================================================

   The "and it is on your phone too" beat. A second, nearer device in front of
   the window - not a second animation. It reads the same `eased` as
   everything else, so it cannot arrive on its own schedule and cannot drift
   away from the window it is standing in front of.

   Depth is the whole trick. Across its band the window moves ZERO pixels: it
   resolved at 0.58 and holds still for the rest of the section. The phone
   moves 120, tilts, scales and deepens its shadow over the same frames. That
   difference in rate at a nearer plane is what makes it read as an object in
   the room rather than a rectangle pasted onto a screenshot.
   ============================================================ */

.crm-phone {
  position: absolute;
  right: 40px;
  bottom: -28px;
  z-index: 4;
  width: 232px;
  height: auto;
  aspect-ratio: 809 / 1667;
  /* Driven by js/crm-spotlight.js across the arrival band. */
  --crm-phone-shade: .26;
  --crm-screen-radius: 30px;
  pointer-events: none;
  /* The tilt has to rotate about the bottom edge or the phone pivots around
     its own middle and reads as a swinging sign rather than a device being
     stood up. */
  transform-origin: 50% 92%;
  will-change: transform, opacity;
}

/* Under 1024px the whole replica is already a phone, so a second one is just
   a duplicate claim. Removed from the layout, not faded. */
.crm-spot--phone .crm-phone { display: none; }

.crm-phone__shell {
  height: 100%;
  display: flex;
  flex-direction: column;
  position: relative;
  box-sizing: border-box;
  padding: 3.55% 4.35% 3.75%;
  border: 0;
  border-radius: 0;
  background: transparent url("../public/brand/devices/iphone-frame.webp") center / 100% 100% no-repeat;
  overflow: visible;
  box-shadow: none;
  filter:
    drop-shadow(0 24px 22px rgb(25 23 28 / var(--crm-phone-shade)))
    drop-shadow(0 2px 4px rgb(25 23 28 / .10));
}

/* The supplied iPhone is the real outer device. Its wallpaper sits behind
   the live CRM content, while this top layer preserves the Dynamic Island in
   front of the status bar exactly where it belongs. */
.crm-phone__shell::after {
  content: "";
  position: absolute;
  z-index: 20;
  top: 3.45%;
  left: 35.65%;
  width: 28.7%;
  height: 4.08%;
  border-radius: 999px;
  background: #000;
  pointer-events: none;
}

/* The live screen sits over an illustrated wallpaper in the supplied PNG.
   Black beneath the rounded surface keeps that wallpaper from peeking out at
   either end and reads as the real inner bezel. */
.crm-phone__shell::before {
  content: "";
  position: absolute;
  z-index: 0;
  /* Match the width-relative shell padding on this fixed-aspect device. The
     tighter screen radius fills the live UI's corner cutouts without covering
     the supplied metal frame. */
  inset: 1.72% 4.35% 1.82%;
  border-radius: var(--crm-screen-radius);
  background: #000;
  pointer-events: none;
}

.crm-phone__shell > * {
  position: relative;
  z-index: 1;
}

.crm-phone__status {
  position: absolute;
  z-index: 3;
  top: 3.55%;
  left: 4.35%;
  right: 4.35%;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 7px 14px 3px;
  font-size: 10px;
  font-weight: 700;
  color: #17151b;
  background: transparent;
  border-radius: 0;
}
.crm-phone__status-right { display: flex; gap: 3px; align-items: center; }
.crm-phone__status-right i { width: 4px; height: 4px; border-radius: 50%; background: rgb(25 23 28 / .34); }

.crm-phone__head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  /* The status row is overlaid above this padding. Making the header the
     first full-height surface lets the top radius curve through the screen
     instead of being squeezed into a 20px strip. */
  padding: 26px 12px 8px;
  border-bottom: 1px solid rgb(25 23 28 / .08);
  background: #fff;
  border-radius: var(--crm-screen-radius) var(--crm-screen-radius) 0 0;
}
.crm-phone__avatar {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgb(124 58 237 / .10);
  color: #7c3aed;
  font-size: 10px;
  font-weight: 800;
}
.crm-phone__identity { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.crm-phone__name { font-size: 12px; font-weight: 700; color: #17151b; }
.crm-phone__channel { display: flex; align-items: center; gap: 4px; font-size: 10px; color: #6b6672; }
.crm-phone__channel i { width: 6px; height: 6px; border-radius: 50%; background: #25d366; }

.crm-phone__messages {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 6px;
  padding: 10px;
  background: #f7f6f8;
}
.crm-phone__bubble {
  margin: 0;
  max-width: 84%;
  padding: 7px 10px;
  border-radius: 14px;
  font-size: 11px;
  line-height: 1.38;
  opacity: 0;
  will-change: transform, opacity;
}
.crm-phone__bubble[data-direction="outbound"] {
  align-self: flex-end;
  background: #7c3aed;
  color: #fff;
  border-bottom-right-radius: 5px;
}
.crm-phone__bubble[data-direction="inbound"] {
  align-self: flex-start;
  background: #fff;
  color: #17151b;
  border: 1px solid rgb(25 23 28 / .08);
  border-bottom-left-radius: 5px;
}

.crm-phone__composer {
  flex: none;
  display: flex;
  align-items: flex-end;
  gap: 6px;
  padding: 8px 10px 12px;
  border-top: 1px solid rgb(25 23 28 / .08);
  background: #fff;
  border-radius: 0 0 var(--crm-screen-radius) var(--crm-screen-radius);
  overflow: hidden;
}
.crm-phone__field {
  flex: 1;
  min-height: 30px;
  padding: 7px 10px;
  border-radius: 15px;
  background: #f3f3f5;
  font-size: 11px;
  line-height: 1.35;
  color: #17151b;
}
.crm-phone__send {
  flex: none;
  padding: 7px 11px;
  border-radius: 15px;
  font-size: 11px;
  font-weight: 700;
  background: rgb(124 58 237 / .12);
  color: rgb(124 58 237 / .5);
}
.crm-phone__send.is-lit { background: #7c3aed; color: #fff; }

/* Only the pin hides it. Without JS, and with reduced motion, the phone is
   simply there and finished - same rule as every other actor in the section. */
.crm-spot--pinned .crm-phone { opacity: 0; }


/* ---------------------------------------------------------------
   WHERE the phone parks, and why it is not where you would guess.

   Two positions were built and measured before this one.

   1. Bottom-right, over the window's corner. It covered the thread pane and
      the Send control - the exact thing Step 04's copy points at ("You answer
      from here"). A second device that hides the payoff it echoes is worse
      than no second device.

   2. Its own reserved lane, with the window sized narrower to leave room.
      Measured at 1440: the conversation pane fell to 282px, under the 300px
      floor this section was already fixed for once. The rail and the
      conversations panel are ALREADY yielding everything they have at 1440
      (210px and 156px against their 224/304 nominals), so there is no
      horizontal room on this layout to reserve. Not a tuning problem - the
      width is simply not there.

   So the phone overlaps, and it overlaps the one region that is inert at the
   end of the section: the lower half of the sidebar, which by 0.62 is empty
   space and an account chip. It hangs past the window's bottom edge, which is
   what makes it read as a device standing in FRONT of the screen rather than
   a panel inside it.

   The window still never moves or resizes after 0.58. Nothing about the
   window changed to make room; the phone went somewhere the window was not
   using.
   --------------------------------------------------------------- */
.crm-phone { left: 8px; right: auto; bottom: -34px; }

/* Under 1360 the sidebar itself is down to ~184px and the phone would cross
   into the conversations list, so it goes rather than degrading the replica
   it is supposed to be advertising. */
@media (max-width: 1359px) {
  .crm-phone { display: none; }
}

/* The section showed the product and then dead-ended. This is its way out. */
.crm-section__action{
  position:relative;
  z-index:2;
  width:min(100%,var(--max));
  margin:clamp(40px,4vw,64px) auto 0;
  display:flex;
  justify-content:center;
}

/* ============================================================
   The /crm clone
   Same section, same driver, same markup. Two differences, both because of
   where it sits on that page rather than because it is a different section.
   ============================================================ */

/* On the homepage this section is a chapter in a run of chapters and takes its
   ground from js/site.js's chapter theming. On /crm there is no such run, so
   it paints its own, and it paints the same colour the chapter theme would
   have given it. */
.crm-section--page { background: var(--mist); }

/* The arrival reveal. Opt-in via data-crm-reveal (see the block at the end of
   js/crm-spotlight.js).

   On the homepage this section is a chapter in a run of chapters and can be
   fully present on its first frame. On /crm it is the payoff to the black
   wipe, and copy already sitting there when the wipe lifts throws the arrival
   away. So the first beat and the CTA are held back until the section is
   actually on screen.

   This does NOT introduce a second opinion about beat opacity. The pinned
   rules above own that, and all this does is hold the ACTIVE beat back - one
   extra class deep, so it outranks .crm-spot--pinned .crm-spot__beat.is-active
   - and then let go. The fade you see on release is that same rule's own .45s
   transition. One owner, one transition, no cross-fade between two systems.

   The initial state comes from .crm-spot--reveal, which only the script adds,
   so with no JS nothing is ever hidden behind a class that never comes off. */
.crm-spot--reveal:not(.is-revealed) .crm-spot__beat.is-active { opacity: 0; }

.crm-spot--reveal .crm-section__action {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
}
.crm-spot--reveal.is-revealed .crm-section__action {
  opacity: 1;
  transform: none;
  /* Behind the copy, not with it: the CTA is the last thing the section says
     and it should not arrive before the first thing it says. */
  transition: opacity .62s var(--ease-out) .22s, transform .62s var(--ease-out) .22s;
}

@media (prefers-reduced-motion: reduce) {
  .crm-spot--reveal:not(.is-revealed) .crm-spot__beat.is-active { opacity: 1; }
  .crm-spot--reveal .crm-section__action { opacity: 1; transform: none; }
}

/* ---- Desktop canvas ceiling ------------------------------------------------
   The hero is positioned with clamps that all top out at roughly a 1630px
   viewport: left:clamp(56px,7.6vw,124px) plus the two font clamps. Past that
   the hero stopped responding while every content section kept centring in the
   1344px column, so the page lost its spine as the screen grew: measured on the
   homepage, the hero h1 sat 484px left of the sections below it at 2560, and
   924px left of them at 3440. The stages that size themselves off the viewport
   (%-based hero card, the journey gallery) kept growing at the same time.

   Cap the stages at one canvas and centre them. Nothing moves at or below
   1680px, which covers every laptop and most desktops. hero-film.js measures
   stage.clientWidth and crm-spotlight.js measures sticky.offsetWidth, so both
   recompute against the capped box rather than the window. */
.crm-spot__track{
  width:min(100%,var(--canvas));
  margin-inline:auto;
}

/* ==== area-pages-options.css ==================================== */
/* Isolated Auckland area-page review concepts. */

:root{
  --area-p:.12;
  --area-e:.04;
  --area-slide:22vw;
  --area-control-slide:2vw;
  --area-crm-opacity:.12;
  --area-video-opacity:1;
  --area-guru-h:132px;
}

.area-review{
  background:#f3f3f5;
}

.area-review .site-header{
  z-index:500;
}

.area-review .place-page{
  overflow:clip;
}

.area-review .place-hero{
  isolation:isolate;
}

.area-review .place-hero-copy,
.area-review .area-hero-scene{
  min-width:0;
}

.area-review .place-hero-copy{
  position:relative;
  z-index:5;
}

.area-review .place-hero-copy h1{
  text-wrap:balance;
}

.area-review .place-hero-actions{
  position:relative;
  z-index:10;
}

.area-review .place-text-link{
  display:inline-flex;
  align-items:center;
  gap:7px;
  min-height:48px;
  padding:0 12px;
  border-radius:999px;
}

.area-review .place-text-link:hover{
  background:rgb(124 58 237 / .08);
}

.area-arrow{
  display:inline-block;
  width:16px;
  height:16px;
  flex:none;
  fill:none;
  stroke:currentColor;
  stroke-width:1.5;
  stroke-linecap:round;
  stroke-linejoin:round;
}

.area-review .place-next strong{
  display:inline-flex;
  align-items:center;
  gap:8px;
}

.area-review .place-next>a:last-child strong{
  justify-content:flex-end;
}

.area-hero-scene{
  position:relative;
  min-height:min(72vh,760px);
}

.area-review .place-hero-media{
  position:absolute;
  inset:0;
  min-height:0;
  height:100%;
  box-shadow:0 36px 80px -48px rgb(25 23 28 / .62);
  will-change:transform;
}

.area-review .place-hero-media img{
  min-height:0;
  position:absolute;
  inset:0;
  z-index:0;
}

.area-review .place-hero-media .area-property-film{
  position:absolute;
  inset:0;
  z-index:1;
  width:100%;
  height:100%;
  max-width:none;
  object-fit:cover;
  opacity:var(--area-video-opacity);
  transform:translateZ(0);
}

.area-review .place-hero-media::after{
  z-index:2;
}

.area-review .place-hero-media figcaption{
  z-index:3;
}

.area-guru-rig{
  position:absolute;
  z-index:12;
  left:0;
  top:0;
  width:calc(var(--area-guru-h) * 1.142857);
  height:var(--area-guru-h);
  pointer-events:none;
  will-change:transform;
}

.area-guru-rig img{
  width:100%;
  height:100%;
  object-fit:contain;
  object-position:center bottom;
}

.area-review-label{
  position:fixed;
  z-index:480;
  left:18px;
  bottom:18px;
  display:flex;
  align-items:center;
  gap:8px;
  min-height:38px;
  padding:8px 13px;
  border:1px solid rgb(76 29 149 / .16);
  border-radius:999px;
  background:rgb(255 255 255 / .92);
  color:#4c1d95;
  font-size:12px;
  font-weight:800;
  letter-spacing:.02em;
  box-shadow:0 14px 34px rgb(25 23 28 / .13);
  backdrop-filter:blur(14px);
}

.area-review-label::before{
  content:"";
  width:8px;
  height:8px;
  border-radius:50%;
  background:#7c3aed;
  box-shadow:0 0 0 4px rgb(124 58 237 / .12);
}

.area-system-preview{
  position:relative;
  width:min(100%,1344px);
  min-height:430px;
  margin:0 auto 28px;
  overflow:hidden;
  border:1px solid rgb(76 29 149 / .13);
  border-radius:16px;
  background:#19171c;
  color:#fff;
  box-shadow:0 38px 90px -54px rgb(25 23 28 / .72);
}

.area-system-chrome{
  height:46px;
  display:flex;
  align-items:center;
  gap:7px;
  padding:0 16px;
  border-bottom:1px solid rgb(255 255 255 / .1);
  background:#28242d;
}

.area-system-chrome i{
  width:7px;
  height:7px;
  border-radius:50%;
  background:#726b7b;
}

.area-system-chrome span{
  margin-left:7px;
  color:rgb(255 255 255 / .6);
  font-size:11px;
  letter-spacing:.03em;
}

.area-system-screen{
  display:grid;
  grid-template-columns:180px 1fr;
  min-height:384px;
}

.area-system-nav{
  padding:22px 14px;
  border-right:1px solid rgb(255 255 255 / .08);
  background:#201d24;
}

.area-system-brand{
  display:flex;
  align-items:center;
  gap:9px;
  margin-bottom:28px;
  font-size:13px;
  font-weight:800;
}

.area-system-brand img{
  width:28px;
  height:28px;
}

.area-system-nav span:not(.area-system-brand){
  display:block;
  margin-top:8px;
  padding:9px 10px;
  border-radius:8px;
  color:rgb(255 255 255 / .55);
  font-size:11px;
}

.area-system-nav span.is-active{
  background:#7c3aed;
  color:#fff;
}

.area-system-main{
  padding:28px;
  background:#f6f5f7;
  color:#19171c;
}

.area-system-top{
  display:flex;
  justify-content:space-between;
  gap:18px;
  align-items:flex-end;
  padding-bottom:22px;
  border-bottom:1px solid rgb(25 23 28 / .1);
}

.area-system-top small{
  display:block;
  color:#77717e;
  font-size:10px;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.09em;
}

.area-system-top strong{
  display:block;
  margin-top:4px;
  font-size:clamp(24px,3vw,42px);
  letter-spacing:-.04em;
}

.area-system-state{
  padding:8px 12px;
  border-radius:999px;
  background:#efffc5;
  color:#4c1d95;
  font-size:11px;
  font-weight:800;
}

.area-system-cards{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:12px;
  margin-top:22px;
}

.area-system-card{
  min-height:160px;
  padding:16px;
  border:1px solid rgb(25 23 28 / .08);
  border-radius:12px;
  background:#fff;
}

.area-system-card b{
  display:block;
  color:#5b21b6;
  font-size:11px;
  text-transform:uppercase;
  letter-spacing:.08em;
}

.area-system-card span{
  display:block;
  margin-top:32px;
  font-size:18px;
  font-weight:750;
  line-height:1.08;
  letter-spacing:-.03em;
}

.area-system-card i{
  display:block;
  width:72%;
  height:6px;
  margin-top:16px;
  border-radius:999px;
  background:#e4d8fb;
  box-shadow:0 12px 0 #ece9ef,0 24px 0 #ece9ef;
}

.area-control-panel{
  position:absolute;
  z-index:1;
  inset:22px 44% 22px 22px;
  overflow:hidden;
  border:1px solid rgb(255 255 255 / .12);
  border-radius:14px;
  background:#201d24;
  color:#fff;
  opacity:var(--area-crm-opacity);
  transform:translateX(calc((1 - var(--area-p)) * -24px));
  transition:opacity .12s linear;
}

.area-control-panel__bar{
  height:38px;
  display:flex;
  align-items:center;
  gap:6px;
  padding:0 12px;
  background:#2b2730;
}

.area-control-panel__bar i{
  width:6px;
  height:6px;
  border-radius:50%;
  background:#756e7d;
}

.area-control-panel__bar span{
  margin-left:6px;
  color:rgb(255 255 255 / .58);
  font-size:9px;
}

.area-control-panel__body{
  padding:20px;
}

.area-control-panel__body small{
  color:#bca8ea;
  font-size:9px;
  font-weight:800;
  text-transform:uppercase;
  letter-spacing:.1em;
}

.area-control-panel__body strong{
  display:block;
  margin-top:7px;
  font-size:23px;
  line-height:1;
  letter-spacing:-.04em;
}

.area-control-panel__metric{
  display:grid;
  grid-template-columns:repeat(2,1fr);
  gap:8px;
  margin-top:18px;
}

.area-control-panel__metric span{
  min-height:72px;
  padding:11px;
  border-radius:9px;
  background:rgb(255 255 255 / .08);
  color:rgb(255 255 255 / .74);
  font-size:10px;
}

.area-control-panel__list{
  margin-top:10px;
  padding:13px;
  border-radius:9px;
  background:#f5ff63;
  color:#25173d;
  font-size:11px;
  font-weight:800;
}

/* Option 1: Cinematic Arrival */

.area-review--cinematic .place-hero{
  min-height:132svh;
  align-items:start;
  padding-top:clamp(168px,14vh,196px)!important;
  background:#fff;
}

.area-review--cinematic .place-hero::before{
  content:"";
  position:absolute;
  inset:18px;
  z-index:-1;
  border-radius:30px;
  background:#f3f3f5;
}

.area-review--cinematic .place-hero-copy,
.area-review--cinematic .area-hero-scene{
  position:sticky;
  top:clamp(156px,16vh,190px);
}

.area-review--cinematic .place-hero-media{
  transform:translate3d(var(--area-slide),0,0);
}

.area-review--cinematic .place-hero-media::before{
  content:"Your Auckland property film";
  position:absolute;
  z-index:2;
  top:18px;
  left:18px;
  padding:8px 11px;
  border-radius:999px;
  background:rgb(255 255 255 / .9);
  color:#19171c;
  font-size:10px;
  font-weight:800;
  letter-spacing:.08em;
  text-transform:uppercase;
}

.area-review--cinematic .place-opportunity{
  background:#f2f1f3;
}

.area-review--cinematic .place-build{
  background:#19171c;
  color:#fff;
}

.area-review--cinematic .place-build-heading p,
.area-review--cinematic .place-system-steps p,
.area-review--cinematic .place-fit{
  color:rgb(255 255 255 / .67);
}

.area-review--cinematic .place-system-steps{
  border-color:rgb(255 255 255 / .13);
}

.area-review--cinematic .place-system-steps article{
  border-color:rgb(255 255 255 / .13);
}

.area-review--cinematic .place-system-steps span{
  color:#c9aef7;
}

.area-review--cinematic .place-fit strong{
  color:#fff;
}

/* The area-page CRM beats use headings only. Keep the progress rule attached
   to the copy instead of reserving the paragraph height from the main site. */
.area-review--cinematic .crm-spot--pinned .crm-spot__copy{
  min-height:140px;
}

.area-review--cinematic .crm-spot__beat h3{
  margin-bottom:0;
}

.area-review--cinematic .crm-spot--phone .crm-spot__copy{
  min-height:76px;
}

/* Option 2: Local Search Field Guide */

.area-review--field .place-hero{
  min-height:112svh;
  display:block;
  padding-top:clamp(166px,14vh,194px)!important;
  background:#fff;
}

.area-review--field .place-hero-copy{
  width:min(100%,1344px);
  max-width:none;
  margin:0 auto 48px;
  display:grid;
  grid-template-columns:minmax(0,1.08fr) minmax(340px,.92fr);
  column-gap:clamp(64px,9vw,140px);
  align-items:start;
}

.area-review--field .place-kicker{
  grid-column:1 / -1;
}

.area-review--field .place-hero h1{
  grid-column:1;
  grid-row:2 / 4;
  font-size:clamp(4.5rem,7.2vw,7.2rem);
}

.area-review--field .place-hero-copy>p:not(.place-kicker){
  grid-column:2;
  margin-top:6px;
}

.area-review--field .place-hero-actions{
  grid-column:2;
  margin-top:28px;
}

.area-review--field .place-hero-actions .btn-primary{
  position:relative;
  z-index:1;
  color:#fff;
  -webkit-text-fill-color:#fff;
  isolation:isolate;
}

.area-review--field .area-hero-scene{
  width:min(100%,1344px);
  min-height:390px;
  margin:auto;
}

.area-review--field .place-hero-media{
  border-radius:16px;
  transform:translate3d(var(--area-slide),0,0);
}

.area-review--field .place-hero-media img{
  object-position:center 56%;
}

.area-review--field .place-opportunity-copy{
  position:sticky;
  top:160px;
  align-self:start;
}

.area-review--field .place-build{
  display:grid;
  grid-template-columns:minmax(320px,.72fr) minmax(0,1.28fr);
  gap:64px;
}

.area-review--field .place-build-heading{
  position:sticky;
  top:155px;
  align-self:start;
}

.area-review--field .area-system-preview,
.area-review--field .place-system-steps,
.area-review--field .place-fit{
  grid-column:2;
}

.area-review--field .area-system-preview{
  min-height:360px;
  margin:0;
}

.area-review--field .area-system-screen{
  min-height:314px;
}

.area-review--field .area-system-cards{
  grid-template-columns:repeat(2,1fr);
}

.area-review--field .area-system-card{
  min-height:112px;
}

.area-review--field .place-system-steps{
  display:block;
  border-bottom:0;
}

.area-review--field .place-system-steps article{
  padding:30px 0;
  display:grid;
  grid-template-columns:90px minmax(220px,.72fr) minmax(0,1fr);
  gap:24px;
  align-items:start;
  border-right:0;
  border-bottom:1px solid var(--line);
}

.area-review--field .place-system-steps h3{
  margin-top:0;
}

.area-review--field .place-system-steps p{
  margin-top:0;
}

/* Option 3: Host Control Room */

.area-review--control .place-hero{
  min-height:126svh;
  grid-template-columns:minmax(0,.72fr) minmax(0,1.28fr);
  align-items:start;
  padding-top:clamp(166px,14vh,194px)!important;
  background:#fff;
}

.area-review--control .place-hero-copy,
.area-review--control .area-hero-scene{
  position:sticky;
  top:clamp(156px,16vh,190px);
}

.area-review--control .area-hero-scene{
  min-height:min(72vh,720px);
  overflow:hidden;
  border-radius:20px;
  background:#19171c;
  box-shadow:0 44px 96px -58px rgb(25 23 28 / .78);
}

.area-review--control .place-hero-media{
  z-index:4;
  transform:translate3d(var(--area-control-slide),0,0);
  box-shadow:-20px 0 48px rgb(0 0 0 / .28);
}

.area-review--control .place-hero-media figcaption{
  right:calc(24px + var(--area-control-slide));
}

.area-review--control .place-build{
  position:relative;
  background:#fff;
}

.area-review--control .place-build::before{
  content:"";
  position:absolute;
  inset:36px max(18px,calc((100% - 1420px) / 2));
  border-radius:24px;
  background:#19171c;
}

.area-review--control .place-build>*{
  position:relative;
  z-index:1;
}

.area-review--control .place-build-heading{
  max-width:1120px;
  color:#fff;
}

.area-review--control .place-build-heading p,
.area-review--control .place-system-steps p,
.area-review--control .place-fit{
  color:rgb(255 255 255 / .65);
}

.area-review--control .area-system-preview{
  position:sticky;
  top:140px;
  width:58%;
  margin:0 0 30px auto;
}

.area-review--control .place-system-steps{
  width:38%;
  margin-top:-458px;
  display:block;
  border-color:rgb(255 255 255 / .12);
}

.area-review--control .place-system-steps article{
  padding:24px 0;
  border-right:0;
  border-bottom:1px solid rgb(255 255 255 / .12);
}

.area-review--control .place-system-steps span{
  color:#c9aef7;
}

.area-review--control .place-system-steps h3{
  margin-top:12px;
  color:#fff;
  font-size:clamp(24px,2.4vw,34px);
}

.area-review--control .place-fit{
  width:38%;
  margin-top:28px;
}

.area-review--control .place-fit strong{
  color:#fff;
}

.area-review--control .place-faq{
  background:#fff;
}

@media(max-width:1050px){
  :root{--area-guru-h:108px}

  .area-review .place-hero,
  .area-review--cinematic .place-hero,
  .area-review--control .place-hero{
    min-height:auto;
    grid-template-columns:1fr;
    padding-top:132px!important;
  }

  .area-review--cinematic .place-hero-copy,
  .area-review--cinematic .area-hero-scene,
  .area-review--control .place-hero-copy,
  .area-review--control .area-hero-scene{
    position:relative;
    top:auto;
  }

  .area-hero-scene{
    min-height:520px;
  }

  .area-review--field .place-hero{
    min-height:auto;
    padding-top:132px!important;
  }

  .area-review--field .place-hero-copy{
    grid-template-columns:1fr;
    gap:0;
  }

  .area-review--field .place-kicker,
  .area-review--field .place-hero h1,
  .area-review--field .place-hero-copy>p:not(.place-kicker),
  .area-review--field .place-hero-actions{
    grid-column:1;
    grid-row:auto;
  }

  .area-review--field .place-hero-copy>p:not(.place-kicker){
    margin-top:26px;
  }

  .area-review--field .area-hero-scene{
    min-height:460px;
  }

  .area-review--field .place-opportunity-copy,
  .area-review--field .place-build-heading{
    position:relative;
    top:auto;
  }

  .area-review--field .place-build{
    display:block;
  }

  .area-review--field .area-system-preview,
  .area-review--field .place-system-steps,
  .area-review--field .place-fit{
    width:100%;
  }

  .area-review--control .place-build::before{
    inset:22px 14px;
  }

  .area-review--control .area-system-preview{
    position:relative;
    top:auto;
    width:100%;
  }

  .area-review--control .place-system-steps{
    width:100%;
    margin-top:0;
  }

  .area-review--control .place-fit{
    width:100%;
  }
}

@media(max-width:720px){
  :root{--area-guru-h:86px}

  .area-review-label{
    left:12px;
    bottom:12px;
    min-height:32px;
    padding:6px 10px;
    font-size:10px;
  }

  .area-review .place-hero,
  .area-review--cinematic .place-hero,
  .area-review--field .place-hero,
  .area-review--control .place-hero{
    padding-top:112px!important;
    padding-bottom:54px!important;
  }

  .area-review--cinematic .place-hero::before{
    inset:8px;
    border-radius:22px;
  }

  .area-review .place-hero h1,
  .area-review--field .place-hero h1{
    font-size:clamp(3.2rem,15vw,4.8rem);
  }

  .area-review .place-hero-copy>p:not(.place-kicker){
    margin-top:20px;
    font-size:17px;
  }

  .area-review .place-hero-actions{
    margin-top:26px;
  }

  .area-hero-scene,
  .area-review--field .area-hero-scene,
  .area-review--control .area-hero-scene{
    min-height:420px;
  }

  .area-review .place-hero-media figcaption{
    inset:auto 16px 16px;
    display:block;
  }

  .area-review .place-hero-media figcaption span{
    display:block;
    margin-top:5px;
    text-align:left;
  }

  .area-review--field .place-hero-copy{
    margin-bottom:32px;
  }

  .area-review--field .area-hero-scene{
    width:100%;
  }

  .area-control-panel{
    inset:12px 34% 12px 12px;
  }

  .area-control-panel__body{
    padding:14px;
  }

  .area-control-panel__metric{
    grid-template-columns:1fr;
  }

  .area-control-panel__metric span:nth-child(2){
    display:none;
  }

  .area-system-preview{
    min-height:330px;
  }

  .area-system-screen{
    grid-template-columns:1fr;
    min-height:284px;
  }

  .area-system-nav{
    display:none;
  }

  .area-system-main{
    padding:18px;
  }

  .area-system-cards,
  .area-review--field .area-system-cards{
    grid-template-columns:repeat(2,1fr);
    gap:8px;
  }

  .area-system-card{
    min-height:94px;
    padding:12px;
  }

  .area-system-card span{
    margin-top:18px;
    font-size:15px;
  }

  .area-system-card i{
    margin-top:10px;
  }

  .area-review--field .place-system-steps article{
    grid-template-columns:1fr;
    gap:10px;
  }

  .area-review--control .place-build::before{
    inset:14px 8px;
  }
}

@media(prefers-reduced-motion:reduce){
  .area-review .place-hero-media{
    transition:none!important;
  }

  .area-guru-rig{
    display:none!important;
    transition:none!important;
  }

  .area-review .place-hero-media .area-property-film{
    display:none;
  }
}

/* Selected direction: the actual main-site hero and CRM, with only the
   location-page integration rules kept here. */

.area-review--cinematic .hero-film{
  isolation:isolate;
  background:#fff;
}

.area-review--cinematic .hero-film-copy{
  z-index:9;
}

.area-review--cinematic .hero-film-copy .place-kicker{
  max-width:none;
  margin:0 0 18px;
  color:var(--teal-dark);
  font-size:15px;
  font-weight:700;
  line-height:1.2;
}

.area-review--cinematic .hero-film-copy h1{
  max-width:none;
  text-wrap:balance;
}

.area-review--cinematic .hero-film-copy>p:not(.place-kicker){
  max-width:48ch;
}

.area-review--cinematic .hero-film-copy .place-hero-actions{
  margin-top:30px;
}

.area-review--cinematic .hero-film-copy .place-text-link{
  display:inline-flex;
  align-items:center;
  gap:7px;
  min-height:48px;
  padding:0 12px;
  border-radius:999px;
  color:var(--ink);
  font-size:14px;
  font-weight:700;
  text-decoration:none;
}

.area-review--cinematic .hero-film-copy .place-text-link:hover{
  background:rgb(124 58 237 / .08);
}

/* Two columns, not three. Left column (40%) carries the whole argument: the
   display heading, the body copy, then the numbered signal list under it.
   Right column (60%) is a single confident map panel. Source order on the
   pages is copy, map figure, signal list, so the columns are assembled with
   explicit grid placement rather than reordering four thousand pages. */
.area-review--cinematic .place-opportunity{
  grid-template-columns:minmax(0,40fr) minmax(0,60fr);
  align-items:start;
  column-gap:clamp(32px,3.4vw,64px);
  row-gap:clamp(38px,3.4vw,54px);
}

.area-review--cinematic .place-opportunity-copy{
  grid-column:1;
  grid-row:1;
  max-width:none;
}

.area-review--cinematic .place-signal-list{
  grid-column:1;
  grid-row:2;
}

/* Spans both rows and sticks, so on the long suburb pages the map stays with
   the copy that is describing it instead of scrolling away in the first
   screen. align-self:start keeps the figure at its content height, which is
   what gives sticky something to travel inside. */
.area-review--cinematic .place-location-map{
  grid-column:2;
  grid-row:1 / span 2;
  position:sticky;
  top:calc(var(--header-h) + 28px);
  align-self:start;
}

/* clamp(3.3rem,5vw,5.6rem) was sized for a full-width column and breaks into
   three-word lines at 40%. This keeps the display voice and the tight tracking
   while landing three comfortable lines at both 1440 and 1728. */
.area-review--cinematic .place-opportunity h2{
  font-size:clamp(2.5rem,3.1vw,3rem);
  line-height:.98;
  letter-spacing:-.035em;
  text-wrap:balance;
}

.place-location-map{
  min-width:0;
  margin:0;
}

.place-location-map__canvas{
  position:relative;
  min-height:clamp(560px,44vw,720px);
  overflow:hidden;
  border:1px solid rgb(76 29 149 / .12);
  border-radius:16px;
  background:#e8e5eb;
}

.place-location-map__canvas iframe{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  border:0;
}

.place-location-map figcaption{
  padding:16px 2px 0;
  color:var(--muted);
  font-size:13px;
  line-height:1.45;
}

.place-location-map figcaption strong,
.place-location-map figcaption span{
  display:block;
}

.place-location-map figcaption strong{
  margin-bottom:5px;
  color:var(--ink);
  font-size:14px;
}

.area-crm-intro{
  padding:clamp(78px,6.888vw,98px) var(--gutter) clamp(32px,3.5vw,54px);
  background:var(--mist);
  text-align:center;
}

/* The opportunity section now runs straight into the CRM. Both bands are mist,
   so the only thing separating them was two full section paddings stacked back
   to back. Halve the top one so the join reads as one continuous run. */
.place-opportunity + .area-crm-intro{
  padding-top:clamp(30px,3vw,48px);
}

.area-crm-intro>*{
  width:min(100%,900px);
  margin-inline:auto;
}

.area-crm-intro h2{
  max-width:13ch;
  font-size:clamp(3.3rem,5vw,5.6rem);
  line-height:.94;
  letter-spacing:-.04em;
  text-wrap:balance;
}

.area-crm-intro>p:not(.place-kicker){
  max-width:58ch;
  margin-top:24px;
  color:var(--muted);
  font-size:18px;
  line-height:1.55;
}

.area-review main>.crm-section{
  padding:0 var(--gutter) clamp(82px,8vw,128px)!important;
  background:var(--mist)!important;
  color:var(--ink);
  scroll-margin-top:var(--header-h);
}

@media(max-width:1180px){
  /* Under 1180 a 60% map is below 620px wide and the copy column below 420px,
     so both stack full width instead. Source order gives copy, then map, then
     the numbered signals: the map is the evidence for the geography argument
     the copy just made, and the signal list is the takeaway that should close
     the section rather than sit in the middle of it. */
  .area-review--cinematic .place-opportunity{
    grid-template-columns:minmax(0,1fr);
    row-gap:clamp(34px,4.4vw,52px);
  }

  .area-review--cinematic .place-opportunity-copy,
  .area-review--cinematic .place-signal-list,
  .area-review--cinematic .place-location-map{
    grid-column:1;
    grid-row:auto;
  }

  .area-review--cinematic .place-location-map{
    position:static;
    top:auto;
  }

  .area-review--cinematic .place-opportunity-copy{
    max-width:850px;
  }

  .area-review--cinematic .place-opportunity h2{
    font-size:clamp(2.9rem,5vw,4.2rem);
  }

  .place-location-map__canvas{
    min-height:clamp(420px,52vw,600px);
  }
}

@media(min-width:901px){
  .area-review--cinematic .hero-film-copy{
    top:53%;
  }
}

@media(max-width:900px){
  .area-review--cinematic .hero-film-copy .place-kicker{
    margin-bottom:13px;
    font-size:12px;
  }

  .area-review--cinematic .hero-film-copy h1{
    max-width:12ch;
  }

  .area-review--cinematic .hero-film-copy .place-hero-actions{
    display:none;
  }
}

@media(max-width:720px){
  .area-review--cinematic .place-opportunity{
    grid-template-columns:1fr;
    row-gap:clamp(30px,7vw,42px);
  }

  .area-review--cinematic .place-opportunity-copy{
    grid-column:auto;
  }

  .area-review--cinematic .place-opportunity h2{
    font-size:clamp(2.55rem,12vw,3.8rem);
    line-height:.96;
  }

  .place-location-map__canvas{
    min-height:clamp(340px,80vw,470px);
  }

  .area-crm-intro{
    padding-left:20px;
    padding-right:20px;
  }

  .area-review main>.crm-section{
    padding-left:20px!important;
    padding-right:20px!important;
  }
}

@media(prefers-reduced-motion:reduce){
  .area-review--cinematic .hero-film{
    min-height:auto!important;
  }

  .area-review--cinematic .hero-film-stage{
    position:relative;
    height:auto;
    min-height:100svh;
  }

  .area-review--cinematic .hero-film-copy{
    opacity:1!important;
    transform:translateY(-50%)!important;
  }
}
