/* ===================== TOKENS ===================== */
:root{
  --bg:#0b0c0c;
  --bg-panel:#131414;
  --bg-panel-2:#171818;
  --line:#292b2b;
  --line-soft:#1c1d1d;
  --ink:#edecea;
  --ink-mute:#9a9c9b;
  --ink-faint:#67696a;
  --steel:#7c8386;
  --primer:#4a5254;
  --primer-bright:#a7afb1;
  --primer-dim:#262d2e;
  --logo-bg:#e1e1e1;

  --f-display:'Manrope',sans-serif;
  --f-body:'Inter',sans-serif;
  --f-mono:'IBM Plex Mono',monospace;

  --container:1440px;
  --pad:clamp(20px,5vw,64px);
  --ease:cubic-bezier(.16,.8,.24,1);
  --nav-h:96px;
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
html{scroll-behavior:smooth;}
html,body{overflow-x:hidden;background:var(--bg);}
body{
  font-family:var(--f-body);
  color:var(--ink);
  background-color:var(--bg);
  background-image:linear-gradient(rgba(11,12,12,.90),rgba(11,12,12,.94)), url('img/vision.webp');
  background-size:cover;
  background-position:center top;
  background-repeat:no-repeat;
  background-attachment:fixed;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
  font-size:16px;
}
@media (max-width:900px){
  body{background-attachment:scroll;}
}
img{max-width:100%;display:block;}
a{color:inherit;text-decoration:none;}
button{font-family:inherit;background:none;border:none;color:inherit;cursor:pointer;}
ul{list-style:none;}
h1,h2,h3,h4{font-family:var(--f-display);font-weight:700;line-height:1.05;letter-spacing:-.01em;}
.container{max-width:var(--container);margin:0 auto;padding-left:var(--pad);padding-right:var(--pad);}
section{position:relative;}

:focus-visible{outline:2px solid var(--primer-bright);outline-offset:4px;}

.eyebrow{
  font-family:var(--f-mono);
  font-size:.72rem;
  letter-spacing:.28em;
  text-transform:uppercase;
  color:var(--primer-bright);
  display:flex;align-items:center;gap:14px;
  margin-bottom:22px;
}
.eyebrow::before{content:'';width:28px;height:1px;background:var(--primer-bright);}

.hairline{border:none;border-top:1px solid var(--line);}

/* reveal system */
.reveal{opacity:0;transform:translateY(28px);transition:opacity .9s var(--ease),transform .9s var(--ease);}
.reveal.in{opacity:1;transform:translateY(0);}

@media (prefers-reduced-motion: reduce){
  *{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;transition-delay:0ms !important;scroll-behavior:auto !important;}
  .btn:hover,.nav-cta:hover,.portfolio-card,.project-card{transform:none !important;}
}

/* ===================== SIGNATURE: DRAFTING FRAME ===================== */
.frame-corner{position:fixed;width:22px;height:22px;border-color:var(--ink-faint);z-index:60;pointer-events:none;opacity:.55;}
.frame-corner.tl{top:18px;left:18px;border-top:1px solid var(--ink-faint);border-left:1px solid var(--ink-faint);}
.frame-corner.tr{top:18px;right:18px;border-top:1px solid var(--ink-faint);border-right:1px solid var(--ink-faint);}
.frame-corner.bl{bottom:18px;left:18px;border-bottom:1px solid var(--ink-faint);border-left:1px solid var(--ink-faint);}
.frame-corner.br{bottom:18px;right:18px;border-bottom:1px solid var(--ink-faint);border-right:1px solid var(--ink-faint);}
.frame-readout{
  position:fixed;left:50px;bottom:24px;z-index:60;
  font-family:var(--f-mono);font-size:.68rem;letter-spacing:.12em;
  color:var(--ink-faint);pointer-events:none;text-transform:uppercase;
  display:flex;gap:10px;align-items:center;
}
.frame-readout .dot{width:5px;height:5px;border-radius:50%;background:var(--primer-bright);}
@media (max-width:900px){.frame-corner,.frame-readout{display:none;}}

.scroll-progress{position:fixed;top:0;left:0;height:2px;width:0%;background:var(--primer-bright);z-index:80;pointer-events:none;transition:width .12s linear;}

/* ===================== NAV ===================== */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:70;
  padding:22px var(--pad);
  display:flex;align-items:center;justify-content:space-between;
  transition:padding .5s var(--ease),background .5s var(--ease),border-color .5s var(--ease);
  border-bottom:1px solid transparent;
}
.nav.scrolled{
  padding:14px var(--pad);
  background:rgba(11,12,12,.86);
  backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line);
}
.nav-logo-link{display:flex;align-items:center;}
.nav-logo-img{
  height:65px;width:65px;object-fit:cover;border-radius:10px;background:var(--logo-bg);
  box-shadow:0 0 0 1px rgba(242,237,226,.08);transition:height .5s var(--ease),width .5s var(--ease);
}
.nav.scrolled .nav-logo-img{height:52px;width:52px;}
.nav-links{display:flex;align-items:center;gap:32px;}
.nav-links a{
  font-size:.8rem;letter-spacing:.07em;text-transform:uppercase;
  color:var(--ink-mute);position:relative;padding-bottom:4px;
  transition:color .3s;white-space:nowrap;
}
.nav-links a::after{content:'';position:absolute;left:0;bottom:0;width:0;height:1px;background:var(--primer-bright);transition:width .35s var(--ease);}
.nav-links a:hover{color:var(--ink);}
.nav-links a:hover::after{width:100%;}
.nav-links a.active{color:var(--ink);}
.nav-links a.active::after{width:100%;background:var(--primer-bright);}
.nav-cta{
  border:1px solid var(--ink-faint);padding:11px 20px;font-size:.74rem;
  letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;
  transition:border-color .3s,color .3s,background .3s,transform .3s var(--ease);
}
.nav-cta:hover{border-color:var(--primer-bright);color:var(--primer-bright);transform:translateY(-2px);}
.nav-mobile-projects{display:none;}
.nav-right{display:flex;align-items:center;gap:28px;}
.nav-toggle{display:none;flex-direction:column;gap:6px;width:28px;z-index:70;}
.nav-toggle span{display:block;height:1px;background:var(--ink);transition:transform .4s var(--ease),opacity .4s var(--ease);}
.nav-toggle.open span:nth-child(1){transform:translateY(7px) rotate(45deg);}
.nav-toggle.open span:nth-child(2){opacity:0;}
.nav-toggle.open span:nth-child(3){transform:translateY(-7px) rotate(-45deg);}

.mobile-menu{
  position:fixed;inset:0;background:var(--bg);z-index:65;
  display:flex;flex-direction:column;justify-content:flex-start;
  padding:calc(var(--nav-h) + 26px) 32px 48px;
  overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  opacity:0;pointer-events:none;transition:opacity .4s var(--ease);
}
.mobile-menu.open{opacity:1;pointer-events:auto;}
.mobile-menu a,
.mobile-menu button.m-cta{
  font-family:var(--f-display);font-size:clamp(1.35rem,5vw,1.85rem);font-weight:700;
  padding:11px 0;border-bottom:1px solid var(--line-soft);color:var(--ink-mute);
  opacity:0;transform:translateY(14px);transition:opacity .4s var(--ease),transform .4s var(--ease),color .3s;
}
.mobile-menu.open a,
.mobile-menu.open button.m-cta{opacity:1;transform:translateY(0);}
.mobile-menu a:hover{color:var(--ink);}
.mobile-menu .m-cta{
  margin-top:16px;color:var(--primer-bright);font-size:.92rem;font-family:var(--f-mono);
  letter-spacing:.08em;padding:12px 16px;border:1px solid rgba(94,162,239,.3);
  background:rgba(94,162,239,.05);border-radius:2px;
}
.mobile-menu .m-cta:hover{border-color:var(--primer-bright);background:rgba(94,162,239,.12);color:#fff;}

@media (max-width:1080px){
  :root{--nav-h:68px;}
  .nav{padding:12px var(--pad);}
  .nav.scrolled{padding:10px var(--pad);}
  .nav-logo-img{height:44px;width:44px;}
  .nav.scrolled .nav-logo-img{height:38px;width:38px;}
  .nav-links{display:none;}
  .nav-toggle{display:flex;}
  .nav-auth-btn{display:none;}
  .nav-cta-desktop{display:none;}
  .nav-mobile-projects{
    display:inline-flex;align-items:center;justify-content:center;
    padding:8px 16px;font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;
    font-family:var(--f-body);font-weight:500;
    color:var(--ink);border:1px solid var(--line);border-radius:2px;
    background:rgba(242,237,226,.03);text-decoration:none;white-space:nowrap;
    transition:border-color .3s,color .3s,background .3s;
  }
  .nav-mobile-projects:hover{
    border-color:var(--primer-bright);color:var(--primer-bright);
    background:rgba(94,162,239,.08);
  }
  .nav-mobile-projects.current{
    border-color:var(--primer-bright);color:var(--ink);
    background:rgba(94,162,239,.14);
  }
  .nav-right{gap:14px;}
  .nav.menu-open{background:rgba(11,12,12,.98);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);border-bottom:1px solid var(--line);}
}
@media (max-width:640px){
  .nav-right > .nav-cta{display:none;}
  .mobile-menu{padding:calc(var(--nav-h) + 20px) 24px 44px;}
}
@media (max-width:480px){
  .nav-mobile-projects{padding:6px 12px;font-size:.68rem;letter-spacing:.07em;}
}

/* ===================== HERO ===================== */
.hero{
  min-height:100vh;display:flex;flex-direction:column;justify-content:flex-end;
  position:relative;overflow:hidden;padding-bottom:92px;
}
.hero-media{position:absolute;inset:0;z-index:0;overflow:hidden;}
.hero-zoom{position:absolute;inset:0;animation:heroZoom 30s ease-in-out infinite alternate;}
.hero-media img{width:100%;height:103%;object-fit:cover;object-position:center center;position:absolute;top:-1.5%;left:0;}
@keyframes heroZoom{from{transform:scale(1);}to{transform:scale(1.03);}}
.hero-media::after{
  content:'';position:absolute;inset:0;
  background:
    linear-gradient(180deg, rgba(11,12,12,.50) 0%, rgba(11,12,12,.06) 16%, rgba(11,12,12,.04) 52%, rgba(11,12,12,.20) 80%, rgba(11,12,12,.52) 100%),
    linear-gradient(90deg, rgba(11,12,12,.95) 0%, rgba(11,12,12,.82) 28%, rgba(11,12,12,.44) 42%, rgba(11,12,12,.16) 58%, rgba(11,12,12,.10) 74%, rgba(11,12,12,.40) 100%);
}
.hero-content{position:relative;z-index:2;padding:0 var(--pad);width:100%;max-width:min(660px,45vw);}
.hero-eyebrow{
  font-family:var(--f-mono);font-size:.78rem;letter-spacing:.32em;text-transform:uppercase;
  color:var(--ink-mute);margin-bottom:26px;
}
.hero-eyebrow strong{color:var(--ink);font-weight:500;}
.hero-title{
  font-size:clamp(2rem,4.2vw,3.6rem);
  font-weight:800;text-transform:uppercase;letter-spacing:-.015em;
  color:var(--ink);max-width:100%;
}
.hero-title .line{overflow:hidden;display:block;}
.hero-title .line span{display:block;transform:translateY(110%);transition:transform 1.1s var(--ease);}
.hero.loaded .hero-title .line span{transform:translateY(0);}
.hero-title .line:nth-child(1) span{transition-delay:.15s;}
.hero-title .line:nth-child(2) span{transition-delay:.32s;}

.hero-sub{
  margin-top:34px;max-width:560px;color:var(--ink-mute);font-size:1.05rem;line-height:1.65;
  opacity:0;transform:translateY(16px);transition:opacity 1s var(--ease) .7s,transform 1s var(--ease) .7s;
}
.hero.loaded .hero-sub{opacity:1;transform:translateY(0);}

.hero-actions{
  margin-top:44px;display:flex;gap:18px;flex-wrap:wrap;
  opacity:0;transform:translateY(16px);transition:opacity 1s var(--ease) .9s,transform 1s var(--ease) .9s;
}
.hero.loaded .hero-actions{opacity:1;transform:translateY(0);}

.btn{
  display:inline-flex;align-items:center;gap:10px;
  padding:16px 30px;font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;
  font-family:var(--f-body);font-weight:500;
  transition:all .4s var(--ease);white-space:nowrap;
}
.btn-primary{background:var(--ink);color:var(--bg);}
.btn-primary:hover{background:var(--primer-bright);color:var(--ink);transform:translateY(-3px);box-shadow:0 16px 30px -12px rgba(0,0,0,.55);}
.btn-outline{border:1px solid var(--ink-faint);color:var(--ink);}
.btn-outline:hover{border-color:var(--ink);background:rgba(242,237,226,.06);transform:translateY(-3px);box-shadow:0 16px 30px -12px rgba(0,0,0,.4);}
.btn:active{transform:translateY(-1px);}
.btn svg{width:14px;height:14px;transition:transform .4s var(--ease);}
.btn:hover svg{transform:translateX(4px);}

.scroll-indicator{
  position:absolute;bottom:36px;left:var(--pad);z-index:2;
  display:flex;align-items:center;gap:14px;
  font-family:var(--f-mono);font-size:.68rem;letter-spacing:.24em;text-transform:uppercase;color:var(--ink-mute);
}
.scroll-line{width:1px;height:46px;background:linear-gradient(var(--ink-mute),transparent);position:relative;overflow:hidden;}
.scroll-line::after{content:'';position:absolute;top:-100%;left:0;width:100%;height:100%;background:var(--primer-bright);animation:scrollDrop 2.6s ease-in-out infinite;}
@keyframes scrollDrop{0%{top:-100%;}60%{top:100%;}100%{top:100%;}}

@media (max-width:640px){
  .hero{min-height:100svh;display:flex;flex-direction:column;justify-content:flex-end;padding-top:calc(var(--nav-h) + 24px);padding-bottom:clamp(36px,8vw,56px);overflow:hidden;}
  .hero-media{position:absolute;inset:0;}
  .hero-content{
    position:relative;max-width:100%;z-index:2;
    background:transparent;padding:0 var(--pad);margin-top:auto;
  }
  .hero-title{font-size:clamp(1.65rem,7vw,2.5rem);max-width:100%;line-height:1.15;}
  .hero-eyebrow{font-size:.7rem;letter-spacing:.2em;margin-bottom:14px;}
  .hero-sub{margin-top:16px;font-size:.92rem;line-height:1.55;}
  .hero-actions{margin-top:22px;gap:12px;}
  .scroll-indicator{display:flex;}
  .hero-media::after{
    background:linear-gradient(180deg,
      rgba(11,12,12,.60) 0%,
      rgba(11,12,12,.12) 16%,
      rgba(11,12,12,.16) 30%,
      rgba(11,12,12,.52) 46%,
      rgba(11,12,12,.80) 62%,
      rgba(11,12,12,.93) 78%,
      rgba(11,12,12,.97) 100%);
  }
}
@media (max-height:760px) and (min-width:641px){
  .hero-eyebrow{margin-bottom:12px;}
  .hero-sub{margin-top:14px;}
  .hero-actions{margin-top:18px;}
}

/* ===================== ABOUT ===================== */
.about{padding:180px 0 140px;border-top:1px solid var(--line);}
.about-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:80px;align-items:start;}
.about-head h2{font-size:clamp(2.1rem,4vw,3.4rem);text-transform:uppercase;max-width:13ch;}
.about-body{margin-top:30px;color:var(--ink-mute);font-size:1.05rem;line-height:1.75;max-width:48ch;}
.about-body p + p{margin-top:20px;}
.about-caps{display:grid;grid-template-columns:1fr 1fr;gap:40px 30px;margin-top:64px;max-width:480px;}
.cap-block{border-top:1px solid var(--line);padding-top:18px;}
.cap-block.reveal:nth-child(1){transition-delay:.05s;}
.cap-block.reveal:nth-child(2){transition-delay:.16s;}
.cap-block.reveal:nth-child(3){transition-delay:.27s;}
.cap-block.reveal:nth-child(4){transition-delay:.38s;}
.cap-block .cap-title{font-family:var(--f-display);font-weight:800;font-size:1.6rem;color:var(--ink);letter-spacing:-.01em;line-height:1.2;}
.cap-block .cap-label{margin-top:8px;font-size:.78rem;letter-spacing:.03em;color:var(--ink-faint);text-transform:uppercase;}
.about-media{position:relative;aspect-ratio:4/5.1;overflow:hidden;}
.about-media img{width:100%;height:100%;object-fit:cover;filter:grayscale(35%) contrast(1.05);transform:scale(1.08);transition:transform 1.4s var(--ease);}
.about-media.in img{transform:scale(1);}
.about-media::after{content:'';position:absolute;inset:0;box-shadow:inset 0 0 0 1px rgba(242,237,226,.08);}
.about-tag{
  position:absolute;left:24px;bottom:24px;background:rgba(11,12,12,.82);backdrop-filter:blur(6px);
  padding:12px 16px;font-family:var(--f-mono);font-size:.7rem;letter-spacing:.1em;color:var(--ink-mute);
  border-left:2px solid var(--primer-bright);text-transform:uppercase;
}

@media (max-width:960px){
  .about-grid{grid-template-columns:1fr;gap:56px;}
  .about-media{order:-1;aspect-ratio:16/11;}
}

/* ===================== VISION BAND (featured, uses provided background) ===================== */
.vision-band{min-height:64vh;position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;padding:100px 20px;}
.vision-media{position:absolute;inset:0;}
.vision-media img{width:100%;height:130%;object-fit:cover;position:absolute;top:-15%;}
.vision-media::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg, rgba(11,12,12,.35) 0%, rgba(11,12,12,.55) 55%, rgba(11,12,12,.88) 100%);}
.vision-content{position:relative;z-index:1;max-width:920px;text-align:center;}
.vision-content .eyebrow{justify-content:center;}
.vision-content h2{font-size:clamp(1.7rem,4.2vw,3.2rem);text-transform:uppercase;line-height:1.28;color:var(--ink);}
.vision-content p{margin-top:26px;color:var(--ink-mute);font-size:1.05rem;font-style:italic;}

/* ===================== WHO WE ARE (mission + values) ===================== */
.who{padding:150px 0;border-top:1px solid var(--line);}
.who-banner{position:relative;height:260px;overflow:hidden;margin-bottom:80px;}
.who-banner img{width:100%;height:100%;object-fit:cover;filter:grayscale(40%);}
.who-banner::after{content:'';position:absolute;inset:0;z-index:1;background:linear-gradient(90deg, rgba(11,12,12,.94) 25%, rgba(11,12,12,.65) 100%);}
.who-banner-content{position:absolute;inset:0;z-index:2;display:flex;flex-direction:column;justify-content:center;padding:0 var(--pad);max-width:var(--container);margin:0 auto;}
.mission-text{max-width:640px;color:var(--ink-mute);font-size:1.15rem;line-height:1.6;}
.values-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin-top:0;}
.value-block{padding:0 30px;border-right:1px solid var(--line);}
.value-block:first-child{padding-left:0;}
.value-block:last-child{border-right:none;padding-right:0;}
.value-block.reveal:nth-child(1){transition-delay:.03s;}
.value-block.reveal:nth-child(2){transition-delay:.12s;}
.value-block.reveal:nth-child(3){transition-delay:.21s;}
.value-block.reveal:nth-child(4){transition-delay:.3s;}
.value-num{font-family:var(--f-mono);font-size:.7rem;color:var(--primer-bright);letter-spacing:.15em;margin-bottom:16px;}
.value-block h4{font-size:1.15rem;text-transform:uppercase;margin-bottom:12px;}
.value-block p{color:var(--ink-mute);font-size:.9rem;line-height:1.55;}

@media (max-width:900px){
  .values-grid{grid-template-columns:1fr 1fr;row-gap:40px;}
  .value-block{border-right:none;padding:0 0 0 20px;border-left:1px solid var(--line);}
  .value-block:nth-child(odd){padding-left:0;border-left:none;}
  .who-banner{height:340px;}
}

/* ===================== SERVICES ===================== */
.services{padding:150px 0;border-top:1px solid var(--line);background:var(--bg-panel);}
.services-banner{position:relative;height:180px;overflow:hidden;margin-bottom:70px;}
.services-banner img{width:100%;height:100%;object-fit:cover;filter:grayscale(45%);}
.services-banner::after{content:'';position:absolute;inset:0;z-index:1;background:linear-gradient(90deg, rgba(19,20,20,.94) 20%, rgba(19,20,20,.6) 100%);}
.services-banner-content{position:absolute;inset:0;z-index:2;display:flex;flex-direction:column;justify-content:center;padding:0 var(--pad);max-width:var(--container);margin:0 auto;}
.section-head{display:flex;justify-content:space-between;align-items:flex-end;gap:30px;flex-wrap:wrap;}
.section-head h2{font-size:clamp(2.1rem,4vw,3.4rem);text-transform:uppercase;max-width:16ch;}
.section-head p{color:var(--ink-mute);max-width:36ch;font-size:.98rem;line-height:1.6;}

.services-note{margin:0 0 50px;color:var(--ink-mute);font-size:.98rem;max-width:70ch;line-height:1.6;border-top:1px solid var(--line);padding-top:30px;}

.service-row{
  display:grid;grid-template-columns:70px 1fr 340px 44px;align-items:center;gap:30px;
  padding:32px 0;border-top:1px solid var(--line);position:relative;overflow:hidden;cursor:default;
}
.service-row:last-child{border-bottom:1px solid var(--line);}
.service-row.reveal:nth-of-type(1){transition-delay:.02s;}
.service-row.reveal:nth-of-type(2){transition-delay:.08s;}
.service-row.reveal:nth-of-type(3){transition-delay:.14s;}
.service-row.reveal:nth-of-type(4){transition-delay:.2s;}
.service-row.reveal:nth-of-type(5){transition-delay:.26s;}
.service-row.reveal:nth-of-type(6){transition-delay:.32s;}
.service-bg{position:absolute;inset:0;z-index:0;opacity:0;transition:opacity .6s var(--ease);}
.service-bg img{width:100%;height:100%;object-fit:cover;filter:grayscale(60%) brightness(.5);}
.service-bg::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,var(--bg-panel) 15%,rgba(19,20,20,.55) 100%);}
.service-row:hover .service-bg{opacity:1;}
.service-num{font-family:var(--f-mono);font-size:.95rem;color:var(--ink-faint);position:relative;z-index:1;transition:transform .5s var(--ease),color .5s;}
.service-row:hover .service-num{transform:translateX(8px);color:var(--primer-bright);}
.service-title{font-family:var(--f-display);font-weight:700;font-size:clamp(1.1rem,1.8vw,1.55rem);text-transform:uppercase;position:relative;z-index:1;letter-spacing:-.01em;transition:transform .5s var(--ease);}
.service-row:hover .service-title{transform:translateX(8px);}
.service-desc{color:var(--ink-mute);font-size:.9rem;line-height:1.5;position:relative;z-index:1;}
.service-arrow{
  width:38px;height:38px;border:1px solid var(--ink-faint);border-radius:50%;
  display:flex;align-items:center;justify-content:center;position:relative;z-index:1;
  transition:all .5s var(--ease);flex-shrink:0;
}
.service-arrow svg{width:14px;height:14px;transition:transform .5s var(--ease);}
.service-row:hover .service-arrow{border-color:var(--primer-bright);background:var(--primer-bright);}
.service-row:hover .service-arrow svg{transform:rotate(45deg);}

.systems-block{margin-top:70px;}
.systems-block .sb-label{font-family:var(--f-mono);font-size:.72rem;letter-spacing:.15em;text-transform:uppercase;color:var(--ink-faint);margin-bottom:20px;}
.systems-chips{display:flex;flex-wrap:wrap;gap:12px;}
.systems-chips span{
  border:1px solid var(--line);padding:9px 16px;border-radius:20px;font-size:.82rem;color:var(--ink-mute);
  font-family:var(--f-mono);letter-spacing:.01em;
}
.systems-chips span b{color:var(--ink);font-weight:500;}

@media (max-width:900px){
  .service-row{grid-template-columns:40px 1fr;grid-template-areas:"num title" "desc desc" "arrow arrow";row-gap:12px;padding:26px 0;}
  .service-num{grid-area:num;}
  .service-title{grid-area:title;font-size:1.15rem;}
  .service-desc{grid-area:desc;}
  .service-arrow{grid-area:arrow;}
}

/* ===================== PROCESS (differentiator) ===================== */
.process{padding:150px 0;border-top:1px solid var(--line);}
.process-intro{max-width:640px;}
.process-flow-label{
  margin-top:16px;font-family:var(--f-mono);font-size:.82rem;color:var(--ink-mute);letter-spacing:.03em;
  display:flex;flex-wrap:wrap;gap:8px 10px;align-items:center;
}
.process-flow-label span{color:var(--ink);}
.process-flow-label .sep{color:var(--primer-bright);}
.process-flow-label span:not(.sep){opacity:0;transform:translateY(6px);transition:opacity .5s var(--ease),transform .5s var(--ease);}
.process-intro.in .process-flow-label span:not(.sep){opacity:1;transform:translateY(0);}
.process-intro.in .process-flow-label span:nth-of-type(1){transition-delay:.5s;}
.process-intro.in .process-flow-label span:nth-of-type(3){transition-delay:.6s;}
.process-intro.in .process-flow-label span:nth-of-type(5){transition-delay:.7s;}
.process-intro.in .process-flow-label span:nth-of-type(7){transition-delay:.8s;}
.process-intro.in .process-flow-label span:nth-of-type(9){transition-delay:.9s;}
.process-intro.in .process-flow-label span:nth-of-type(11){transition-delay:1s;}
.process-intro.in .process-flow-label span:nth-of-type(13){transition-delay:1.1s;}
.process-timeline{display:grid;grid-template-columns:repeat(7,1fr);gap:0;margin-top:80px;position:relative;}
.timeline-track{position:absolute;top:11px;left:0;right:0;height:1px;background:var(--line);}
.timeline-track-fill{position:absolute;top:0;left:0;height:1px;width:0;background:var(--primer-bright);transition:width 1.6s var(--ease);}
.process-step{padding-right:20px;position:relative;}
.process-step.reveal:nth-child(1){transition-delay:0s;}
.process-step.reveal:nth-child(2){transition-delay:.06s;}
.process-step.reveal:nth-child(3){transition-delay:.12s;}
.process-step.reveal:nth-child(4){transition-delay:.18s;}
.process-step.reveal:nth-child(5){transition-delay:.24s;}
.process-step.reveal:nth-child(6){transition-delay:.3s;}
.process-step.reveal:nth-child(7){transition-delay:.36s;}
.process-step .dot{width:23px;height:23px;border-radius:50%;border:1px solid var(--ink-faint);background:var(--bg);position:relative;z-index:2;margin-bottom:28px;display:flex;align-items:center;justify-content:center;transition:border-color .5s,background .5s;}
.process-step .dot::after{content:'';width:7px;height:7px;border-radius:50%;background:var(--ink-faint);transition:background .5s;}
.process-step.in .dot{border-color:var(--primer-bright);}
.process-step.in .dot::after{background:var(--primer-bright);}
.process-step .p-num{font-family:var(--f-mono);font-size:.68rem;color:var(--primer-bright);letter-spacing:.1em;margin-bottom:8px;}
.process-step h3{font-size:1.02rem;text-transform:uppercase;margin-bottom:10px;letter-spacing:-.005em;}
.process-step p{color:var(--ink-mute);font-size:.82rem;line-height:1.5;max-width:20ch;}

@media (max-width:1100px){
  .process-timeline{grid-template-columns:repeat(4,1fr);row-gap:50px;}
  .timeline-track{display:none;}
}
@media (max-width:640px){
  .process-timeline{grid-template-columns:1fr;gap:40px;}
  .process-step{padding-right:0;padding-left:30px;border-left:1px solid var(--line);}
  .process-step .dot{position:absolute;left:-12px;top:0;}
}

/* ===================== PROJECTS / PORTFOLIO ===================== */
.projects{padding:150px 0;border-top:1px solid var(--line);background:var(--bg-panel);}
.filter-row{display:flex;flex-wrap:wrap;gap:10px;margin:50px 0 56px;}
.filter-chip{
  border:1px solid var(--line);padding:9px 18px;border-radius:20px;font-size:.78rem;
  letter-spacing:.03em;color:var(--ink-mute);transition:all .3s var(--ease);white-space:nowrap;
}
.filter-chip:hover{border-color:var(--ink-faint);color:var(--ink);}
.filter-chip.active{background:var(--ink);border-color:var(--ink);color:var(--bg);}

.portfolio-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;}
.portfolio-card{
  position:relative;overflow:hidden;cursor:pointer;aspect-ratio:5/4;background:var(--bg-panel-2);
  transition:opacity .4s var(--ease),transform .4s var(--ease);
}
.portfolio-card.filtered-out{display:none;}
.portfolio-card.reveal:nth-child(3n+1){transition-delay:0s;}
.portfolio-card.reveal:nth-child(3n+2){transition-delay:.09s;}
.portfolio-card.reveal:nth-child(3n+3){transition-delay:.18s;}
.portfolio-card img{width:100%;height:100%;object-fit:cover;transform:scale(1.06);transition:transform 1.1s var(--ease);filter:saturate(.85) grayscale(15%);}
.portfolio-card:hover img{transform:scale(1.14);}
.portfolio-card::before{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(11,12,12,0) 35%,rgba(11,12,12,.94) 100%);z-index:1;}
.portfolio-card.no-photo{display:flex;align-items:center;justify-content:center;
  background-image:linear-gradient(var(--line-soft) 1px, transparent 1px),linear-gradient(90deg, var(--line-soft) 1px, transparent 1px);
  background-size:26px 26px;
}
.no-photo-note{position:relative;z-index:1;text-align:center;font-family:var(--f-mono);font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-faint);}
.portfolio-info{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:22px;}
.portfolio-info .p-num{font-family:var(--f-mono);font-size:.68rem;color:var(--primer-bright);letter-spacing:.12em;margin-bottom:8px;}
.portfolio-name{font-family:var(--f-display);font-weight:700;font-size:1.08rem;text-transform:uppercase;transition:transform .5s var(--ease);letter-spacing:-.005em;}
.portfolio-card:hover .portfolio-name{transform:translateX(4px);}
.portfolio-meta{margin-top:6px;font-size:.76rem;color:var(--ink-mute);letter-spacing:.02em;}
.portfolio-expand{
  position:absolute;top:16px;right:16px;z-index:2;width:36px;height:36px;border:1px solid rgba(242,237,226,.3);
  border-radius:50%;display:flex;align-items:center;justify-content:center;transition:all .5s var(--ease);
}
.portfolio-card:hover .portfolio-expand{background:var(--primer-bright);border-color:var(--primer-bright);transform:rotate(90deg);}
.portfolio-expand svg{width:14px;height:14px;}

.projects-note{margin-top:44px;font-family:var(--f-mono);font-size:.78rem;color:var(--ink-faint);display:flex;gap:12px;align-items:flex-start;}
.projects-note svg{width:16px;height:16px;flex-shrink:0;margin-top:2px;color:var(--primer-bright);}

@media (max-width:1100px){.portfolio-grid{grid-template-columns:repeat(2,1fr);}}
@media (max-width:640px){.portfolio-grid{grid-template-columns:1fr;} .portfolio-card{aspect-ratio:4/3.2;}}

/* ===================== PROJECT MODAL ===================== */
.modal-overlay{
  position:fixed;inset:0;background:var(--bg);z-index:100;
  opacity:0;pointer-events:none;transition:opacity .5s var(--ease);
  overflow-y:auto;
}
.modal-overlay.open{opacity:1;pointer-events:auto;}
.modal-hero-content{opacity:0;transform:translateY(18px);transition:opacity .6s var(--ease) .1s,transform .6s var(--ease) .1s;}
.modal-overlay.open .modal-hero-content{opacity:1;transform:translateY(0);}
.modal-info-grid{opacity:0;transform:translateY(14px);transition:opacity .6s var(--ease) .2s,transform .6s var(--ease) .2s;}
.modal-overlay.open .modal-info-grid{opacity:1;transform:translateY(0);}
.modal-gallery img{opacity:0;transform:translateY(14px);transition:opacity .55s var(--ease),transform .55s var(--ease);}
.modal-overlay.open .modal-gallery img{opacity:1;transform:translateY(0);}
.modal-overlay.open .modal-gallery img:nth-child(1){transition-delay:.28s;}
.modal-overlay.open .modal-gallery img:nth-child(2){transition-delay:.34s;}
.modal-overlay.open .modal-gallery img:nth-child(3){transition-delay:.4s;}
.modal-overlay.open .modal-gallery img:nth-child(4){transition-delay:.46s;}
.modal-close{
  position:fixed;top:28px;right:var(--pad);z-index:110;width:48px;height:48px;border:1px solid var(--line);
  border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--bg);transition:border-color .3s,transform .4s var(--ease);
}
.modal-close:hover{border-color:var(--primer-bright);transform:rotate(90deg);}
.modal-close svg{width:16px;height:16px;}
.modal-hero{position:relative;height:60vh;min-height:380px;overflow:hidden;
  background-image:linear-gradient(var(--line-soft) 1px, transparent 1px),linear-gradient(90deg, var(--line-soft) 1px, transparent 1px);
  background-size:32px 32px;background-color:var(--bg-panel-2);
}
.modal-hero img{width:100%;height:100%;object-fit:cover;filter:saturate(.85) grayscale(10%);position:relative;z-index:1;}
.modal-hero::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(11,12,12,.15),rgba(11,12,12,.95));z-index:1;}
.modal-hero-content{position:absolute;left:0;right:0;bottom:0;padding:0 var(--pad) 50px;z-index:2;}
.modal-cat{font-family:var(--f-mono);font-size:.75rem;letter-spacing:.2em;text-transform:uppercase;color:var(--primer-bright);margin-bottom:16px;}
.modal-title{font-size:clamp(2rem,5vw,3.6rem);text-transform:uppercase;color:var(--ink);}
.modal-body{max-width:var(--container);margin:0 auto;padding:60px var(--pad) 120px;}
.modal-info-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:30px;padding-bottom:50px;border-bottom:1px solid var(--line);margin-bottom:60px;}
.modal-info-item .mi-label{font-family:var(--f-mono);font-size:.68rem;letter-spacing:.15em;text-transform:uppercase;color:var(--ink-faint);margin-bottom:10px;}
.modal-info-item .mi-value{font-family:var(--f-display);font-weight:700;font-size:1.05rem;color:var(--ink);}
.modal-gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:20px;}
.modal-gallery img{width:100%;height:100%;object-fit:cover;aspect-ratio:1/1;filter:saturate(.85) grayscale(10%);}
.modal-no-gallery{color:var(--ink-faint);font-family:var(--f-mono);font-size:.85rem;padding:20px 0;}

@media (max-width:900px){
  .modal-info-grid{grid-template-columns:1fr 1fr;}
}

/* ===================== WHY ELRAEEY ===================== */
.why{padding:150px 0;border-top:1px solid var(--line);}
.why-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 60px;margin-top:70px;}
.why-item{padding:30px 0;border-top:1px solid var(--line);display:flex;gap:26px;align-items:flex-start;}
.why-item.reveal:nth-child(6n+1){transition-delay:.02s;}
.why-item.reveal:nth-child(6n+2){transition-delay:.08s;}
.why-item.reveal:nth-child(6n+3){transition-delay:.14s;}
.why-item.reveal:nth-child(6n+4){transition-delay:.02s;}
.why-item.reveal:nth-child(6n+5){transition-delay:.08s;}
.why-item.reveal:nth-child(6n+6){transition-delay:.14s;}
.why-mark{font-family:var(--f-mono);color:var(--primer-bright);font-size:1.1rem;flex-shrink:0;margin-top:2px;}
.why-item h4{font-size:1.1rem;text-transform:uppercase;letter-spacing:-.005em;margin-bottom:8px;}
.why-item p{color:var(--ink-mute);font-size:.92rem;line-height:1.55;max-width:40ch;}

@media (max-width:900px){.why-grid{grid-template-columns:1fr;gap:0;}}

/* ===================== CONTACT / CTA ===================== */
.cta{padding:180px 0 100px;border-top:1px solid var(--line);position:relative;overflow:hidden;text-align:center;}
.cta-lines{position:absolute;inset:0;opacity:.35;pointer-events:none;}
.cta h2{font-size:clamp(2.2rem,6.4vw,5rem);text-transform:uppercase;max-width:16ch;margin:0 auto;}
.cta p{margin:26px auto 0;color:var(--ink-mute);font-size:1.1rem;max-width:42ch;}
.cta .btn{margin-top:48px;}

.contact-grid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:0;margin-top:120px;position:relative;z-index:1;
}
.contact-block{padding:0 40px;border-right:1px solid var(--line);text-align:left;}
.contact-block:first-child{padding-left:0;}
.contact-block:last-child{border-right:none;padding-right:0;}
.contact-block .cb-label{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-faint);margin-bottom:18px;}
.contact-block a, .contact-block p{display:block;color:var(--ink-mute);font-size:1rem;margin-bottom:10px;transition:color .3s;}
.contact-block a:hover{color:var(--primer-bright);}
.contact-block .social-row{display:flex;gap:20px;margin-top:2px;}
.contact-block .social-row a{margin-bottom:0;font-size:.9rem;text-transform:uppercase;letter-spacing:.04em;}

.map-placeholder{
  margin-top:60px;border:1px solid var(--line);aspect-ratio:21/6;position:relative;z-index:1;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  background-image:linear-gradient(var(--line-soft) 1px, transparent 1px),linear-gradient(90deg, var(--line-soft) 1px, transparent 1px);
  background-size:40px 40px;color:var(--ink-faint);text-align:center;
}
.map-placeholder svg{width:26px;height:26px;color:var(--primer-bright);}
.map-placeholder span{font-family:var(--f-mono);font-size:.74rem;letter-spacing:.12em;text-transform:uppercase;}

@media (max-width:900px){
  .contact-grid{grid-template-columns:1fr;gap:40px;}
  .contact-block{border-right:none !important;padding:0 !important;}
  .map-placeholder{aspect-ratio:16/10;}
}

/* ===================== FOOTER ===================== */
footer{border-top:1px solid var(--line);padding:80px 0 40px;}
.footer-grid{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:50px;padding-bottom:70px;}
.footer-logo-img{height:84px;width:84px;object-fit:cover;border-radius:14px;background:var(--logo-bg);margin-bottom:18px;}
.footer-brand p{color:var(--ink-faint);font-size:.88rem;letter-spacing:.03em;}
.footer-col h5{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-faint);margin-bottom:22px;}
.footer-col a,.footer-col p{display:block;color:var(--ink-mute);font-size:.92rem;margin-bottom:12px;transition:color .3s;}
.footer-col a:hover{color:var(--primer-bright);}
.footer-bottom{display:flex;justify-content:space-between;align-items:center;padding-top:32px;border-top:1px solid var(--line);flex-wrap:wrap;gap:16px;}
.footer-bottom p{color:var(--ink-faint);font-size:.8rem;}
.footer-social{display:flex;gap:22px;}
.footer-social a{font-size:.8rem;color:var(--ink-mute);text-transform:uppercase;letter-spacing:.06em;transition:color .3s;}
.footer-social a:hover{color:var(--primer-bright);}

@media (max-width:900px){
  .footer-grid{grid-template-columns:1fr 1fr;gap:40px;}
  .footer-brand{grid-column:span 2;}
}
@media (max-width:560px){
  .footer-grid{grid-template-columns:1fr;}
  .footer-brand{grid-column:span 1;}
}

/* ===================================================================
   REFINEMENT LAYER — typography, rhythm, materials, micro-interactions
   =================================================================== */
:root{
  --e-out:cubic-bezier(.16,.8,.24,1);
  --e-in-out:cubic-bezier(.65,.05,.36,1);
  --shadow-1:0 1px 2px rgba(0,0,0,.30), 0 10px 28px -14px rgba(0,0,0,.5);
  --shadow-2:0 30px 70px -28px rgba(0,0,0,.72);
  --hairline:rgba(255,255,255,.07);
  --s-sec:clamp(96px,9.5vw,176px);
}
html{-webkit-text-size-adjust:100%;}
body{text-rendering:optimizeLegibility;font-feature-settings:"kern" 1,"liga" 1,"calt" 1;}
::selection{background:var(--primer-bright);color:#0b0c0c;}

/* --- type scale: tighter optical tracking as size increases --- */
h1,h2,h3,h4{letter-spacing:-.018em;text-wrap:balance;}
.hero-title{letter-spacing:-.03em;line-height:.97;}
.section-head h2,.about-head h2,.cta h2,.vision-content h2{letter-spacing:-.024em;line-height:1.03;}
.process-intro h2{letter-spacing:-.024em;}
.hero-sub,.about-body,.section-head p,.why-item p,.service-desc{text-wrap:pretty;}
.eyebrow,.hero-eyebrow,.cb-label,.sb-label,.footer-col h5,.mi-label,.modal-cat{font-variant-numeric:tabular-nums;}

/* --- vertical rhythm --- */
.about{padding-top:var(--s-sec);padding-bottom:calc(var(--s-sec)*.85);}
.services,.process,.projects,.why{padding-top:var(--s-sec);padding-bottom:var(--s-sec);}
.cta{padding-top:var(--s-sec);}
.section-head{position:relative;padding-bottom:34px;margin-bottom:56px;}
.section-head::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--line);}
.services .section-head::after{opacity:.85;}

/* --- architectural grid: fine blueprint ruling on panel sections --- */
.services::before,.projects::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:0;opacity:.55;
  background-image:linear-gradient(var(--line-soft) 1px,transparent 1px),
                   linear-gradient(90deg,var(--line-soft) 1px,transparent 1px);
  background-size:128px 128px;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 18%,#000 82%,transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,#000 18%,#000 82%,transparent 100%);
}
.services > .container,.projects > .container,.services-banner{position:relative;z-index:1;}

/* --- buttons --- */
.btn{position:relative;border:1px solid transparent;transition:background-color .32s var(--e-out),color .32s var(--e-out),border-color .32s var(--e-out),transform .32s var(--e-out),box-shadow .32s var(--e-out);}
.btn-primary{box-shadow:var(--shadow-1);}
.btn-primary:hover{transform:translateY(-2px);box-shadow:var(--shadow-2);}
.btn-outline:hover{transform:translateY(-2px);}
.btn:active{transform:translateY(0);}
.btn:focus-visible,.nav-cta:focus-visible,.filter-chip:focus-visible,.portfolio-card:focus-visible{
  outline:1px solid var(--primer-bright);outline-offset:3px;
}

/* --- navigation --- */
.nav{transition:padding .55s var(--e-out),background-color .55s var(--e-out),border-color .55s var(--e-out),backdrop-filter .55s var(--e-out);}
.nav.scrolled{box-shadow:0 1px 0 var(--hairline),0 18px 40px -32px rgba(0,0,0,.9);}
.nav-links a{transition:color .28s var(--e-out);}
.nav-links a::after{height:1px;transition:width .42s var(--e-out);}
.nav-logo-img{box-shadow:0 0 0 1px var(--hairline),var(--shadow-1);}

/* --- service rows --- */
.service-row{transition:background-color .45s var(--e-out);}
.service-row:hover{background-color:rgba(255,255,255,.014);}
.service-arrow{transition:background-color .35s var(--e-out),border-color .35s var(--e-out),transform .45s var(--e-out);}
.service-row:hover .service-arrow{transform:translateX(3px);}

/* --- project cards --- */
.portfolio-card{
  border:1px solid transparent;
  transition:transform .55s var(--e-out),box-shadow .55s var(--e-out),border-color .45s var(--e-out);
}
.portfolio-card:hover{transform:translateY(-5px);box-shadow:var(--shadow-2);border-color:var(--hairline);}
.portfolio-card img{transition:transform 1.25s var(--e-out),filter .6s var(--e-out);}
.portfolio-card:hover img{transform:scale(1.10);}
.portfolio-info{transition:transform .55s var(--e-out);}
.portfolio-card::after{ /* corner registration tick */
  content:"";position:absolute;top:14px;left:14px;width:14px;height:14px;z-index:2;
  border-top:1px solid rgba(255,255,255,.34);border-left:1px solid rgba(255,255,255,.34);
  opacity:0;transform:translate(4px,4px);transition:opacity .45s var(--e-out),transform .45s var(--e-out);
}
.portfolio-card:hover::after{opacity:1;transform:translate(0,0);}

/* --- filter chips --- */
.filter-chip{transition:background-color .3s var(--e-out),border-color .3s var(--e-out),color .3s var(--e-out),transform .3s var(--e-out);}
.filter-chip:hover{transform:translateY(-1px);}

/* --- capability + why blocks --- */
.cap-block{transition:border-color .45s var(--e-out);}
.cap-block:hover{border-color:var(--ink-faint);}
.why-item{transition:border-color .45s var(--e-out);}
.why-item:hover{border-color:var(--ink-faint);}

/* --- modal --- */
.modal-gallery img{box-shadow:var(--shadow-1);}
.modal-close{box-shadow:var(--shadow-1);}
.modal-info-item{position:relative;}

/* --- imagery: keep photographic assets crisp --- */
/* keep photographic assets crisp; avoid layer promotion on large decoded bitmaps */
.hero-media img,.portfolio-card img,.modal-hero img,.modal-gallery img,
.about-media img,.vision-media img,.who-banner img,.services-banner img{
  image-rendering:auto;transform-origin:center;
}
/* let real colour through — the heavy desaturation was flattening the photography */
.portfolio-card img,.modal-hero img,.modal-gallery img{filter:saturate(.94) grayscale(.05);}
.about-media img{filter:none;}

/* --- links in footer/contact --- */
.footer-col a,.contact-block a{position:relative;transition:color .28s var(--e-out);}
.footer-col a::after,.contact-block a::after{
  content:"";position:absolute;left:0;bottom:-2px;width:0;height:1px;background:var(--primer-bright);
  transition:width .38s var(--e-out);
}
.footer-col a:hover::after,.contact-block a:hover::after{width:100%;}

@media (max-width:900px){
  :root{--s-sec:clamp(96px,16vw,140px);}
  .services, .process, .projects, .why, .cta{
    padding-top:calc(var(--nav-h) + clamp(36px,8vw,64px));
  }
  .services-banner{height:140px;margin-bottom:36px;}
  .section-head{padding-bottom:26px;margin-bottom:40px;}
  .portfolio-card:hover{transform:none;box-shadow:none;}
}
@media (prefers-reduced-motion:reduce){
  .portfolio-card,.portfolio-card img,.btn,.nav{transition:none !important;}
  .portfolio-card:hover{transform:none;}
}


/* ============================================================
   HERO — DEPTH PARALLAX
   The hero render is displaced by its own AI-estimated depth map
   and approached by a real camera. Additive only: if WebGL is
   unavailable or anything below fails, the <img> stays visible
   and the hero is exactly as it was.
   ============================================================ */
.hero-gl{position:absolute;inset:0;width:100%;height:100%;display:block}
.hero-media.gl-active img{opacity:0}

/* ============================================================
   SECTION MOTION
   One vocabulary per section, not one effect everywhere.

   The site already ships an IntersectionObserver that adds .in to
   every .reveal. Rather than add observers, this layer redefines
   what .reveal -> .in *means* per section, so the existing
   infrastructure drives entirely different behaviour in each one.

   The hero is untouched: no rule below matches .hero*.
   ============================================================ */

/* Neutralise the generic fade-up only where a section defines its
   own language. Anything not listed keeps the original behaviour. */
.about .about-head.reveal,
.about .about-media.reveal,
.about .cap-block.reveal,
.vision-band .vision-content.reveal,
.who .value-block.reveal,
.services .section-head.reveal,
.services .service-row.reveal,
.process .process-step.reveal,
.projects .section-head.reveal,
.projects .filter-row.reveal,
.projects .portfolio-card.reveal,
.why .why-item.reveal,
.cta .container.reveal{
  opacity:1;transform:none;transition:none;
}

/* ============================================================
   1. ABOUT — editorial
   The statement is set line by line behind a mask, the way a
   printed page is read. The plate wipes up and settles from a
   slight overscale. Body copy arrives last and quietly.
   ============================================================ */
.about-head h2 .ln{display:block;overflow:hidden;}
.about-head h2 .ln > i{
  display:block;font-style:inherit;
  transform:translateY(105%);
  transition:transform 1.05s var(--ease);
  transition-delay:calc(var(--i,0) * 90ms);
}
.about-head.in h2 .ln > i{transform:translateY(0);}

.about-head .about-body{
  opacity:0;transition:opacity .9s var(--ease) .5s;
}
.about-head.in .about-body{opacity:1;}

.about .about-media{
  clip-path:inset(0 0 100% 0);
  transition:clip-path 1.15s var(--ease);
}
.about .about-media.in{clip-path:inset(0 0 0 0);}
.about .about-media img{
  transform:scale(1.14);
  transition:transform 1.7s var(--ease);
}
.about .about-media.in img{transform:scale(1);}
.about .about-tag{
  opacity:0;transform:translateY(8px);
  transition:opacity .6s var(--ease) .75s,transform .6s var(--ease) .75s;
}
.about .about-media.in .about-tag{opacity:1;transform:none;}

/* ============================================================
   2. STATISTICS — number, then rule, then label
   A measured read: the figure counts, a hairline is struck
   alongside it, the caption follows. Fast, no bounce.
   ============================================================ */
.about .cap-block{position:relative;}
.about .cap-block::after{
  content:'';position:absolute;left:0;top:0;height:1px;width:100%;
  background:var(--primer-bright);
  transform:scaleX(0);transform-origin:left center;
  transition:transform .85s var(--ease);
  transition-delay:calc(var(--i,0) * 110ms);
}
.about .cap-block.in::after{transform:scaleX(1);}

.about .cap-block .cap-title{
  opacity:0;transform:translateY(12px);
  transition:opacity .55s var(--ease),transform .55s var(--ease);
  transition-delay:calc(var(--i,0) * 110ms + 120ms);
}
.about .cap-block.in .cap-title{opacity:1;transform:none;}
.about .cap-block .cap-label{
  opacity:0;
  transition:opacity .5s var(--ease);
  transition-delay:calc(var(--i,0) * 110ms + 420ms);
}
.about .cap-block.in .cap-label{opacity:1;}

/* ============================================================
   3. VISION — letterbox
   The quote opens from the centre like a frame being pulled
   apart, against the image already drifting on scroll.
   ============================================================ */
.vision-band .vision-content{
  clip-path:inset(48% 0 48% 0);
  transition:clip-path 1.25s var(--ease);
}
.vision-band .vision-content.in{clip-path:inset(0 0 0 0);}

/* ============================================================
   4. WHO / VALUES — constructed in order
   Numeral, then rule, then the words: each principle is built
   rather than faded.
   ============================================================ */
.who .value-block{position:relative;padding-top:20px;}
.who .value-block::before{
  content:'';position:absolute;left:0;top:0;height:1px;width:100%;
  background:var(--line);
  transform:scaleX(0);transform-origin:left center;
  transition:transform .8s var(--ease);
  transition-delay:calc(var(--i,0) * 130ms);
}
.who .value-block.in::before{transform:scaleX(1);}
.who .value-block .value-num{
  opacity:0;transform:translateY(8px);
  transition:opacity .5s var(--ease),transform .5s var(--ease);
  transition-delay:calc(var(--i,0) * 130ms + 90ms);
}
.who .value-block h4,
.who .value-block p{
  opacity:0;transform:translateY(10px);
  transition:opacity .6s var(--ease),transform .6s var(--ease);
}
.who .value-block h4{transition-delay:calc(var(--i,0) * 130ms + 240ms);}
.who .value-block p{transition-delay:calc(var(--i,0) * 130ms + 340ms);}
.who .value-block.in .value-num,
.who .value-block.in h4,
.who .value-block.in p{opacity:1;transform:none;}

/* ============================================================
   5. SERVICES — drawn, like a technical sheet
   A setting-out grid fades up behind the list once, then each
   scope is drawn: rule, number, title from behind a mask, arrow.
   ============================================================ */
.services .container{position:relative;}
.services .container::before{
  content:'';position:absolute;inset:-2% -4% 6% -4%;pointer-events:none;z-index:0;
  background-image:
    repeating-linear-gradient(90deg, var(--line-soft) 0 1px, transparent 1px 84px),
    repeating-linear-gradient(0deg,  var(--line-soft) 0 1px, transparent 1px 84px);
  opacity:0;
  transition:opacity 1.4s var(--ease);
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 22%,#000 70%,transparent);
          mask-image:linear-gradient(180deg,transparent,#000 22%,#000 70%,transparent);
}
.services .container.grid-in::before{opacity:.5;}
.services .container > *{position:relative;z-index:1;}

.services .section-head h2{
  clip-path:inset(0 0 105% 0);
  transition:clip-path 1s var(--ease);
}
.services .section-head.in h2{clip-path:inset(0 0 -10% 0);}
.services .section-head p{
  opacity:0;transition:opacity .8s var(--ease) .35s;
}
.services .section-head.in p{opacity:1;}

.services .service-row{position:relative;}
.services .service-row::before{
  content:'';position:absolute;left:0;top:0;height:1px;width:100%;
  background:var(--primer-bright);opacity:.55;
  transform:scaleX(0);transform-origin:left center;
  transition:transform 1s var(--ease);
  transition-delay:calc(var(--i,0) * 90ms);
  z-index:2;
}
.services .service-row.in::before{transform:scaleX(1);}

.services .service-row .service-num{
  opacity:0;
  transition:opacity .5s var(--ease),transform .5s var(--ease),color .5s;
  transition-delay:calc(var(--i,0) * 90ms + 140ms);
}
.services .service-row.in .service-num{opacity:1;}

.services .service-row .service-title{
  clip-path:inset(0 100% 0 0);
  transition:clip-path .95s var(--ease),transform .5s var(--ease);
  transition-delay:calc(var(--i,0) * 90ms + 200ms);
}
.services .service-row.in .service-title{clip-path:inset(0 0 0 0);}

.services .service-row .service-desc{
  opacity:0;
  transition:opacity .6s var(--ease);
  transition-delay:calc(var(--i,0) * 90ms + 360ms);
}
.services .service-row.in .service-desc{opacity:1;}

.services .service-row .service-arrow{
  opacity:0;transform:scale(.8);
  transition:opacity .5s var(--ease),transform .5s var(--e-out),
             background-color .35s var(--e-out),border-color .35s var(--e-out);
  transition-delay:calc(var(--i,0) * 90ms + 440ms);
}
.services .service-row.in .service-arrow{opacity:1;transform:scale(1);}
/* hover must still win over the entry transform */
.services .service-row:hover .service-arrow{transform:translateX(3px) scale(1);transition-delay:0s;}

/* ============================================================
   6. PROCESS — a line being walked
   The existing track fill carries the sequence; each station
   marks itself as the line reaches it.
   ============================================================ */
.process .process-step .dot{
  transform:scale(.35);opacity:0;
  transition:transform .5s var(--e-out),opacity .4s var(--ease),border-color .5s,background .5s;
  transition-delay:calc(var(--i,0) * 70ms);
}
.process .process-step.in .dot{transform:scale(1);opacity:1;}
.process .process-step .p-num,
.process .process-step h3,
.process .process-step p{
  opacity:0;transform:translateX(-10px);
  transition:opacity .55s var(--ease),transform .55s var(--ease);
}
.process .process-step .p-num{transition-delay:calc(var(--i,0) * 70ms + 120ms);}
.process .process-step h3{transition-delay:calc(var(--i,0) * 70ms + 200ms);}
.process .process-step p{transition-delay:calc(var(--i,0) * 70ms + 280ms);}
.process .process-step.in .p-num,
.process .process-step.in h3,
.process .process-step.in p{opacity:1;transform:none;}

/* ============================================================
   7. PROJECTS — the presentation board
   Each plate is uncovered from the bottom edge while its
   photograph settles back from overscale, so the image appears
   to come to rest rather than fade in. The grid opens on a
   diagonal, which reads as one board being laid out.
   ============================================================ */
.projects .section-head h2{
  clip-path:inset(0 0 105% 0);
  transition:clip-path 1s var(--ease);
}
.projects .section-head.in h2{clip-path:inset(0 0 -10% 0);}
.projects .section-head p{opacity:0;transition:opacity .8s var(--ease) .3s;}
.projects .section-head.in p{opacity:1;}

.projects .filter-row .filter-chip{
  opacity:0;transform:translateY(8px);
  transition:opacity .45s var(--ease),transform .45s var(--ease),
             border-color .3s,color .3s,background-color .3s;
  transition-delay:calc(var(--i,0) * 45ms);
}
.projects .filter-row.in .filter-chip{opacity:1;transform:none;}

.projects .portfolio-card{
  --imgScale:1.20;
  clip-path:inset(0 0 100% 0);
  transition:clip-path 1.05s var(--ease),
             transform .55s var(--e-out),box-shadow .55s var(--e-out),border-color .45s var(--e-out);
  transition-delay:calc(var(--i,0) * 55ms);
}
.projects .portfolio-card.in{clip-path:inset(0 0 0 0);--imgScale:1.06;}
.projects .portfolio-card img{
  transform:scale(var(--imgScale));
  transition:transform 1.5s var(--ease),filter .6s var(--e-out);
}
.projects .portfolio-card:hover{--imgScale:1.10;}
.projects .portfolio-card:hover img{transition:transform 1.25s var(--e-out),filter .6s var(--e-out);}

/* a hairline is struck across the plate on approach */
.projects .portfolio-card::after{
  content:'';position:absolute;left:0;top:0;height:1px;width:100%;z-index:3;
  background:var(--primer-bright);
  transform:scaleX(0);transform-origin:left center;
  transition:transform .6s var(--e-out);
  pointer-events:none;
}
.projects .portfolio-card:hover::after,
.projects .portfolio-card:focus-visible::after{transform:scaleX(1);}

.projects .portfolio-card .portfolio-info{
  transition:transform .55s var(--e-out);
}
.projects .portfolio-card:hover .portfolio-info{transform:translateY(-4px);}

/* filtering should re-lay the board, not blink */
.projects .portfolio-card.filtered-out{
  clip-path:inset(0 0 100% 0);opacity:0;pointer-events:none;
  transition:clip-path .5s var(--ease),opacity .35s var(--ease);
}

/* ============================================================
   8. WHY — deliberately quiet
   Six assurances after a dense section. Only the marks move;
   the copy simply arrives. Restraint is the point.
   ============================================================ */
.why .why-item .why-mark{
  display:inline-block;
  opacity:0;transform:rotate(-90deg) scale(.6);
  transition:opacity .5s var(--ease),transform .6s var(--e-out);
  transition-delay:calc(var(--i,0) * 70ms);
}
.why .why-item.in .why-mark{opacity:1;transform:rotate(0) scale(1);}
.why .why-item > div{
  opacity:0;
  transition:opacity .7s var(--ease);
  transition-delay:calc(var(--i,0) * 70ms + 90ms);
}
.why .why-item.in > div{opacity:1;}

/* ============================================================
   9. CONTACT — one gesture
   A closing section should not perform. A single rule is drawn
   under the invitation and nothing else moves.
   ============================================================ */
.cta .container{position:relative;}
.cta .container h2{
  opacity:0;transform:translateY(14px);
  transition:opacity .8s var(--ease),transform .8s var(--ease);
}
.cta .container.in h2{opacity:1;transform:none;}
.cta .container > .eyebrow{
  opacity:0;transition:opacity .6s var(--ease);
}
.cta .container.in > .eyebrow{opacity:1;}

/* ============================================================
   10. PROJECT DETAIL — the case study opens
   The overlay is a room being entered: the plate uncovers from
   the centre, the title rises behind it, the schedule and the
   gallery follow in order.
   ============================================================ */
.modal-overlay .modal-hero{clip-path:inset(0 0 100% 0);}
.modal-overlay.open .modal-hero{
  clip-path:inset(0 0 0 0);
  transition:clip-path 1s var(--ease) .05s;
}
.modal-overlay .modal-hero img{transform:scale(1.16);}
.modal-overlay.open .modal-hero img{
  transform:scale(1);
  transition:transform 1.8s var(--ease);
}
.modal-overlay .modal-info-item{
  opacity:0;transform:translateY(12px);
  transition:opacity .5s var(--ease),transform .5s var(--ease);
}
.modal-overlay.open .modal-info-item{opacity:1;transform:none;}
.modal-overlay.open .modal-info-item:nth-child(1){transition-delay:.34s;}
.modal-overlay.open .modal-info-item:nth-child(2){transition-delay:.42s;}
.modal-overlay.open .modal-info-item:nth-child(3){transition-delay:.50s;}
.modal-overlay.open .modal-info-item:nth-child(4){transition-delay:.58s;}
.modal-overlay .modal-gallery img{
  clip-path:inset(0 0 100% 0);
  transition:clip-path .8s var(--ease),transform 1.2s var(--ease);
  transform:scale(1.08);
}
.modal-overlay.open .modal-gallery img.shown{clip-path:inset(0 0 0 0);transform:scale(1);}

/* ============================================================
   11. NAVIGATION — a panel, not a hamburger
   The menu arrives as a surface sliding in from the edge, with
   the links set out in sequence behind it. Closing reverses.
   ============================================================ */
.mobile-menu{
  transform:translateX(8%);
  transition:opacity .45s var(--ease),transform .55s var(--ease);
}
.mobile-menu.open{transform:translateX(0);}
.mobile-menu a{
  transform:translateY(22px);
  transition:opacity .55s var(--ease),transform .55s var(--ease),color .3s;
}
.mobile-menu.open a{transform:translateY(0);}
.mobile-menu.open a:nth-child(1){transition-delay:.14s;}
.mobile-menu.open a:nth-child(2){transition-delay:.20s;}
.mobile-menu.open a:nth-child(3){transition-delay:.26s;}
.mobile-menu.open a:nth-child(4){transition-delay:.32s;}
.mobile-menu.open a:nth-child(5){transition-delay:.38s;}
.mobile-menu.open a:nth-child(6){transition-delay:.44s;}
.mobile-menu.open a:nth-child(7){transition-delay:.50s;}
.mobile-menu.open a:nth-child(8){transition-delay:.56s;}
/* closing: no stagger, everything leaves together */
.mobile-menu:not(.open) a{transition-delay:0s;}

/* ============================================================
   12. MICRO-INTERACTIONS
   Fast, small, and only where a hand is already going.
   ============================================================ */
.nav-links a::after{transform-origin:left center;}
.service-row:hover .service-arrow svg{transform:translateX(2px);}
.btn svg{transition:transform .32s var(--e-out);}
.btn:hover svg{transform:translateX(5px);}
.portfolio-card .portfolio-expand{transition:transform .45s var(--e-out),background-color .35s,border-color .35s;}

/* ============================================================
   13. REDUCED MOTION
   Everything above resolves to its finished state.
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  .about-head h2 .ln > i{transform:none!important;}
  .about .about-media,
  .vision-band .vision-content,
  .services .section-head h2,
  .projects .section-head h2,
  .projects .portfolio-card,
  .modal-overlay .modal-hero,
  .modal-overlay .modal-gallery img{clip-path:none!important;}
  .services .service-row .service-title{clip-path:none!important;}
  .about .about-media img,
  .projects .portfolio-card img,
  .modal-overlay .modal-hero img,
  .modal-overlay .modal-gallery img{transform:none!important;}
  .about .cap-block::after,
  .who .value-block::before,
  .services .service-row::before{transform:scaleX(1)!important;}
  .about-head .about-body,
  .about .about-tag,
  .about .cap-block .cap-title,
  .about .cap-block .cap-label,
  .who .value-block .value-num,
  .who .value-block h4,
  .who .value-block p,
  .services .section-head p,
  .services .service-row .service-num,
  .services .service-row .service-desc,
  .services .service-row .service-arrow,
  .process .process-step .dot,
  .process .process-step .p-num,
  .process .process-step h3,
  .process .process-step p,
  .projects .section-head p,
  .projects .filter-row .filter-chip,
  .why .why-item .why-mark,
  .why .why-item > div,
  .cta .container h2,
  .cta .container > .eyebrow,
  .modal-overlay .modal-info-item{
    opacity:1!important;transform:none!important;transition:none!important;
  }
  .services .container::before{opacity:.5!important;}
}

/* ============================================================
   FAIL-OPEN
   Every hidden state above applies only once the motion script has
   run and marked the document. Until then — a slow connection, a
   download that never finishes, scripting disabled — the page
   renders as ordinary HTML with nothing concealed. A site that has
   not animated yet is fine; a site that is blank is not.
   ============================================================ */
html:not(.js-anim) .about-head h2 .ln > i,
html:not(.js-anim) .about-head .about-body,
html:not(.js-anim) .about .about-media,
html:not(.js-anim) .about .about-tag,
html:not(.js-anim) .about .cap-block .cap-title,
html:not(.js-anim) .about .cap-block .cap-label,
html:not(.js-anim) .vision-band .vision-content,
html:not(.js-anim) .who .value-block .value-num,
html:not(.js-anim) .who .value-block h4,
html:not(.js-anim) .who .value-block p,
html:not(.js-anim) .services .section-head h2,
html:not(.js-anim) .services .section-head p,
html:not(.js-anim) .services .service-row .service-num,
html:not(.js-anim) .services .service-row .service-title,
html:not(.js-anim) .services .service-row .service-desc,
html:not(.js-anim) .services .service-row .service-arrow,
html:not(.js-anim) .process .process-step .dot,
html:not(.js-anim) .process .process-step .p-num,
html:not(.js-anim) .process .process-step h3,
html:not(.js-anim) .process .process-step p,
html:not(.js-anim) .projects .section-head h2,
html:not(.js-anim) .projects .section-head p,
html:not(.js-anim) .projects .filter-row .filter-chip,
html:not(.js-anim) .projects .portfolio-card,
html:not(.js-anim) .why .why-item .why-mark,
html:not(.js-anim) .why .why-item > div,
html:not(.js-anim) .cta .container h2,
html:not(.js-anim) .cta .container > .eyebrow,
html:not(.js-anim) .reveal{
  opacity:1 !important;
  transform:none !important;
  clip-path:none !important;
  -webkit-clip-path:none !important;
  transition:none !important;
}
html:not(.js-anim) .about .cap-block::after,
html:not(.js-anim) .who .value-block::before,
html:not(.js-anim) .services .service-row::before{ transform:scaleX(1) !important; }

/* ============================================================
   MOBILE / SAFARI COMPATIBILITY
   Compatibility and performance only. No layout, colour, type or
   spacing decision is changed; every rule here either restores an
   intended behaviour on Safari or removes work that costs battery
   without being seen.
   ============================================================ */

/* ---- 1. Safari needs the prefix for backdrop blur ---- */
.nav,
.nav.scrolled,
.modal-overlay,
.mobile-menu{ -webkit-backdrop-filter:inherit; }
.nav{ -webkit-backdrop-filter:blur(14px); }
.modal-overlay{ -webkit-backdrop-filter:blur(6px); }

/* ---- 2. iOS viewport units ----
   100vh on iOS measures the viewport with the address bar hidden, so
   a 100vh hero is taller than what is actually on screen and the copy
   sits under the browser chrome. svh is the small-viewport unit, which
   is what 100vh was always meant to be here. Declared after, so
   browsers that do not know it keep the original value. */
.hero{ min-height:100svh; }
/* dvh is deliberately not used: it tracks the address bar, which would
   change the pinned hero's height mid-scroll and make the pin jump. svh
   is the stable choice — the hero is sized to the viewport with the bar
   showing, and simply reveals a little of the next section when it hides. */

/* ---- 3. clip-path needs the prefix on iOS 13-14 ----
   Where it is unsupported the declaration is simply dropped and the
   element stays visible, so this is about restoring the animation,
   not about preventing a blank page. */
.about .about-media{ -webkit-clip-path:inset(0 0 100% 0); }
.about .about-media.in{ -webkit-clip-path:inset(0 0 0 0); }
.vision-band .vision-content{ -webkit-clip-path:inset(48% 0 48% 0); }
.vision-band .vision-content.in{ -webkit-clip-path:inset(0 0 0 0); }
.services .section-head h2{ -webkit-clip-path:inset(0 0 105% 0); }
.services .section-head.in h2{ -webkit-clip-path:inset(0 0 -10% 0); }
.services .service-row .service-title{ -webkit-clip-path:inset(0 100% 0 0); }
.services .service-row.in .service-title{ -webkit-clip-path:inset(0 0 0 0); }
.projects .section-head h2{ -webkit-clip-path:inset(0 0 105% 0); }
.projects .section-head.in h2{ -webkit-clip-path:inset(0 0 -10% 0); }
.projects .portfolio-card{ -webkit-clip-path:inset(0 0 100% 0); }
.projects .portfolio-card.in{ -webkit-clip-path:inset(0 0 0 0); }
.projects .portfolio-card.filtered-out{ -webkit-clip-path:inset(0 0 100% 0); }
.modal-overlay .modal-hero{ -webkit-clip-path:inset(0 0 100% 0); }
.modal-overlay.open .modal-hero{ -webkit-clip-path:inset(0 0 0 0); }
.modal-overlay .modal-gallery img{ -webkit-clip-path:inset(0 0 100% 0); }
.modal-overlay.open .modal-gallery img.shown{ -webkit-clip-path:inset(0 0 0 0); }

/* ---- 4. no horizontal scroll, on any device ----
   overflow-x:hidden on <body> alone does not always hold on iOS.
   Pinning the width and clipping at the root does. */
html{ overflow-x:clip; max-width:100%; }
body{ overflow-x:clip; max-width:100%; position:relative; }
img,svg,video,canvas{ max-width:100%; }

/* ---- 5. touch behaviour ---- */
a,button,.portfolio-card,.filter-chip,.nav-toggle,.modal-close{
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;
}
/* Safari shrinks type in landscape unless told not to */
html{ -webkit-text-size-adjust:100%; text-size-adjust:100%; }

/* ---- 6. the mobile hero, when WebGL is not running ----
   The depth effect now runs on handhelds too, but it can still bow
   out: no WebGL, reduced-motion, a lost context, a low-memory
   device. In those cases the photograph is the hero, and these
   rules are what make that state look deliberate. The scroll-linked
   translate the page applies to the <img> is dropped: the stacked
   hero has only ~3% of overscan, so after a couple of hundred
   pixels that transform drags a visible gap in at the top edge.
   Removing it also takes a per-scroll style write off the main
   thread. When the canvas is live, rule 10 below stands these down. */
@media (max-width:900px){
  .hero-media img{ transform:none !important; }
}
@media (max-width:640px){
  /* a touch more overscan so the slow zoom never reaches an edge */
  .hero-media img{ height:108%; top:-4%; }
  /* the zoom is the whole motion budget on a handset: make it slower
     and shallower than desktop so it reads as a held shot */
  .hero-zoom{ animation-duration:44s; }
}
@media (max-width:640px) and (prefers-reduced-motion: reduce){
  .hero-zoom{ animation:none; }
}

/* ---- 7. hover effects must not stick on touch ----
   A tapped card on iOS keeps its :hover state until the next tap
   elsewhere, which leaves a project looking selected. Scope the
   hover work to devices that actually have a pointer. */
@media (hover: none){
  .portfolio-card:hover{ transform:none; box-shadow:none; }
  .portfolio-card:hover img{ transform:scale(1.06); }
  .portfolio-card:hover::after{ transform:scaleX(0); }
  .service-row:hover .service-num,
  .service-row:hover .service-title{ transform:none; }
  .btn:hover,.nav-cta:hover,.filter-chip:hover{ transform:none; box-shadow:none; }
}

/* ---- 8. iOS scroll-lock for the project overlay ----
   body{overflow:hidden} does not hold the page still on iOS; the
   class below is applied by script alongside it and does. */
body.modal-locked{
  position:fixed;
  left:0; right:0; width:100%;
  overflow:hidden;
}

/* ---- 9. the overlay must be able to scroll under a finger ---- */
.modal-overlay{ -webkit-overflow-scrolling:touch; }

/* ---- 10. when WebGL takes the hero, stop the CSS work ----
   The slow keyframe zoom exists for the plain-image hero. With the
   depth effect running it is invisible under an opaque canvas and
   would only keep a compositor layer alive on the phone. */
.hero-media.gl-active .hero-zoom{ animation:none; }
.hero-media.gl-active img{ opacity:0; }

/* ============================================================
   11. THE PHONE HERO IS FULL-VIEWPORT AGAIN
   The site restacked the hero below 640px: the media became a
   50vh block with the copy underneath on solid ground. That is a
   perfectly good editorial layout, but it is also the reason the
   depth effect had nowhere to go — a camera cannot push through a
   half-height box that scrolls away in one flick.

   So the phone gets the same overlay hero as the desktop: image
   full-bleed behind, copy over it, pinned while the camera moves.
   The rest of the page keeps every one of its own breakpoints.
   ============================================================ */
@media (max-width:640px){
  .hero{
    min-height:100svh;
    display:flex; flex-direction:column; justify-content:flex-end;
    overflow:hidden;
    padding-top:calc(var(--nav-h) + 24px);
    padding-bottom:clamp(36px, 8vw, 56px);
  }

  .hero-media{
    position:absolute; inset:0;
    height:auto; min-height:0;
  }
  .hero-media img{ height:103%; top:-1.5%; }

  .hero-content{
    position:relative; z-index:2;
    max-width:100%;
    background:transparent;
    padding:0 var(--pad);
    margin-top:auto;
  }
  .hero-eyebrow{
    margin-bottom:14px;
    font-size:0.7rem;
    letter-spacing:.2em;
  }
  .hero-title{
    font-size:clamp(1.65rem, 7vw, 2.5rem);
    line-height:1.15;
  }
  .hero-sub{
    margin-top:16px;
    font-size:0.92rem;
    line-height:1.55;
    max-width:100%;
  }
  .hero-actions{
    margin-top:22px;
    gap:12px;
  }

  /* Portrait puts the copy across the full width at the bottom, so the
     legibility gradient has to be vertical and land hard at the base —
     the desktop's left-edge wash does nothing here. The building stays
     clear through the upper two thirds. */
  .hero-media::after{
    background:linear-gradient(180deg,
      rgba(11,12,12,.60) 0%,
      rgba(11,12,12,.12) 16%,
      rgba(11,12,12,.16) 30%,
      rgba(11,12,12,.52) 46%,
      rgba(11,12,12,.80) 62%,
      rgba(11,12,12,.93) 78%,
      rgba(11,12,12,.97) 100%);
  }

  /* A pinned hero needs to say that scrolling does something. */
  .scroll-indicator{ display:flex; }
}

/* Short landscape phones: the copy will not fit under a 100svh hero,
   so let the hero size to its content instead of the viewport. */
@media (max-width:900px) and (max-height:460px) and (orientation:landscape){
  .hero{ min-height:0; padding-top:88px; padding-bottom:36px; }
  .hero-title{ font-size:clamp(1.5rem,4.6vw,2.2rem); }
  .hero-sub{ margin-top:10px; font-size:.86rem; }
  .hero-actions{ margin-top:14px; }
  .scroll-indicator{ display:none; }
}

/* The canvas is scenery: every touch on it belongs to the page. */
.hero-gl{ pointer-events:none; touch-action:pan-y; }

/* ============================================================
   PAGE TRANSITION
   One page dissolving into the next. Nothing is overlaid.

   There is no panel, no cover, no label, no shape. The only
   things that move are the page's own content layers, and the
   body background underneath them never moves or fades at all.
   That is the whole trick: both documents paint the same
   background, so the surface the reader is looking at is
   continuous across the navigation and only its contents
   change. There is no moment that presents an empty screen
   because the screen is never emptied.

       content fades back  ->  documents swap  ->  content fades in

   The swap is timed to land while the outgoing content is
   almost gone rather than after it has gone, so the two halves
   overlap instead of meeting at a hard edge.

   The page's own entrance animations are a separate system and
   are deliberately held until this has substantially finished,
   so the two never animate over each other.
   ============================================================ */

:root{
  --ch-exit:  440ms;
  --ch-enter: 620ms;
  /* out fast then long, slow settle; no hard stop at either end */
  --ch-ease:    cubic-bezier(.22, .61, .36, 1);
  --ch-ease-in: cubic-bezier(.45, .05, .55, .95);
}

/* ---------- leaving ---------- */
/* The scale is there for depth, not for zoom: 1.5% is below the
   threshold at which it reads as movement and above the one at
   which it reads as nothing. Home is exempt - its hero is pinned
   by ScrollTrigger against the viewport, and a transform on an
   ancestor would redefine what that pin is measured against. So
   Home fades without the scale, which looks the same and leaves
   the depth effect untouched. */
html.ch-leave #page{
  opacity:0;
  transition:opacity var(--ch-exit) var(--ch-ease-in);
  /* opacity only. will-change:transform would make this element a
     containing block for its fixed-position descendants, which is what
     the pinned hero on Home is - the same reason the scale is withheld
     there. It is promised only on .ch-move, which Home never gets. */
  will-change:opacity;
}
html.ch-leave #page.ch-move{
  transform:scale(.985);
  transition:opacity var(--ch-exit) var(--ch-ease-in),
             transform var(--ch-exit) var(--ch-ease-in);
  will-change:opacity, transform;
}
html.ch-leave .nav,
html.ch-leave footer{
  opacity:0;
  transition:opacity calc(var(--ch-exit) * .78) var(--ch-ease-in);
}

/* ---------- arriving ---------- */
/* The incoming document paints already faded back. There is no
   transition on this state - it is simply where the page starts. */
html.ch-enter #page{ opacity:0; will-change:opacity; }
html.ch-enter #page.ch-move{ transform:scale(1.015); will-change:opacity, transform; }
html.ch-enter .nav,
html.ch-enter footer{ opacity:0; }

/* Failsafe, and the only reason this is an animation rather than a
   transition. The faded start state above is applied by a tiny inline
   script in the head, and the class that releases it is added by the
   main script - which means a script that never arrives, or a phone
   that has stopped servicing timers and frames, could leave the page
   sitting at zero opacity. CSS animations are driven by the rendering
   engine rather than by script, so this one lands even then: two
   seconds in, it snaps the page visible. In the normal case the
   transition has long finished and the classes are already gone, so
   this never fires at all. */
@keyframes ch-failsafe{ to{ opacity:1; transform:none; } }
html.ch-enter #page{ animation:ch-failsafe 1ms linear 2s forwards; }

html.ch-enter-run #page{
  opacity:1;
  transition:opacity var(--ch-enter) var(--ch-ease);
}
html.ch-enter-run #page.ch-move{
  transform:none;
  transition:opacity var(--ch-enter) var(--ch-ease),
             transform var(--ch-enter) var(--ch-ease);
}
html.ch-enter-run .nav,
html.ch-enter-run footer{
  opacity:1;
  transition:opacity calc(var(--ch-enter) * .85) var(--ch-ease) 70ms;
}

/* ---------- active tab ---------- */
.nav-links a.current{ color:var(--ink); }
.nav-links a.current::after{ width:100%; }
.mobile-menu a.current{ color:var(--ink); }

/* A service detail page belongs to the Services chapter but is not the
   Services page, so its tab is marked as the section rather than the
   destination: same underline, drawn lighter, and still a live link.
   Only `.current` is treated as "already here" by the click handler. */
.nav-links a.current-section{ color:var(--ink-mute); }
.nav-links a.current-section::after{ width:100%; opacity:.45; }
.mobile-menu a.current-section{ color:var(--ink-mute); }

/* ---------- mobile: same gesture, a little quicker ---------- */
@media (max-width:900px){
  :root{
    --ch-exit:  380ms;
    --ch-enter: 540ms;
  }
  /* less travel on a small viewport, where the same percentage of
     the screen is a larger proportion of what is being looked at */
  html.ch-leave #page.ch-move{ transform:scale(.99); }
  html.ch-enter #page.ch-move{ transform:scale(1.01); }
}

/* ---------- reduced motion: no transition at all ---------- */
@media (prefers-reduced-motion: reduce){
  html.ch-leave #page, html.ch-enter #page,
  html.ch-leave #page.ch-move, html.ch-enter #page.ch-move,
  html.ch-enter-run #page, html.ch-enter-run #page.ch-move{
    opacity:1 !important; transform:none !important; transition:none !important;
  }
  html.ch-leave .nav, html.ch-leave footer,
  html.ch-enter .nav, html.ch-enter footer{
    opacity:1 !important; transition:none !important;
  }
}


/* ---------- services listing: the rows are links ----------
   They always looked clickable - arrow, hover, the lot - and were not.
   Nothing about the appearance changes here; only the element does. */
a.service-row{
  display:grid; text-decoration:none; color:inherit; cursor:pointer;
}
a.service-row:focus-visible{ outline:1px solid var(--primer-bright); outline-offset:-2px; }


/* ---------- contact details ---------- */
.contact-block .cb-tel{ font-variant-numeric:tabular-nums; letter-spacing:.02em; }
.contact-block a .ext, .map-link .ext{
  display:inline-block; width:11px; height:11px; margin-left:8px; vertical-align:0;
  opacity:.7; transition:transform .35s var(--e-out), opacity .35s var(--e-out);
}
.contact-block a:hover .ext, .map-link:hover .ext{ transform:translate(2px,-2px); opacity:1; }
.contact-block a:focus-visible, .footer-col a:focus-visible, .footer-social a:focus-visible{
  outline:1px solid var(--primer-bright); outline-offset:4px;
}

a.map-link{ color:var(--ink-mute); transition:border-color .45s var(--e-out), color .45s var(--e-out); }
a.map-link:hover{ border-color:var(--primer-bright); color:var(--ink); }
a.map-link:focus-visible{ outline:1px solid var(--primer-bright); outline-offset:4px; }
.map-link svg:first-child{ transition:transform .45s var(--e-out); }
a.map-link:hover svg:first-child{ transform:translateY(-3px); }
.map-link .map-cta{
  display:inline-flex; align-items:center; margin-top:4px;
  border:1px solid var(--ink-faint); padding:12px 20px; color:var(--ink);
  transition:border-color .35s var(--e-out), color .35s var(--e-out);
}
.map-link .map-cta svg{ width:11px; height:11px; color:currentColor; }
a.map-link:hover .map-cta{ border-color:var(--primer-bright); color:var(--primer-bright); }

/* on a phone every line is a comfortable target for a thumb */
@media (max-width:900px){
  .contact-block a{ padding:9px 0; margin-bottom:0; }
  .contact-block .social-row a{ padding:9px 0; }
  .footer-col a{ padding:7px 0; margin-bottom:2px; }
  .footer-social a{ padding:8px 0; }
}
