/* Motion layer. Everything here is inert until motion.js marks the page as ready,
   so the page renders exactly as before without JavaScript or with reduced motion. */
:root {
  --m-io: cubic-bezier(.83, 0, .17, 1);
  --m-out: cubic-bezier(.16, 1, .3, 1);
}

/* Lenis smooth scrolling (desktop, fine pointer only). */
html.lenis, html.lenis body { height: auto; }
html.lenis { scroll-behavior: auto; }
.lenis:not(.lenis-autoToggle).lenis-stopped { overflow: clip; }
.lenis [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/* First paint while the intro is pending. A failsafe in the page head removes m-intro. */
.m-intro .hero-eyebrow,
.m-intro .hero h1,
.m-intro .hero-description,
.m-intro .hero-link,
.m-intro .hero-bottom,
.m-intro .art-caption { opacity: 0; }
.m-intro .hero-art { filter: blur(14px); scale: 1.08; }
@media (min-width: 801px) {
  .m-intro .site-header .wordmark,
  .m-intro .main-nav > a { opacity: 0; }
}

/* Split text: masks clip vertically only, with room for descenders and italic overhang. */
.m-line-mask, .m-char-mask {
  overflow: visible clip !important;
  padding-bottom: .16em;
  margin-bottom: -.16em;
}
.m-char-mask { padding-top: .08em; margin-top: -.08em; }

/* Logo assembly and image settling use individual transform properties,
   so they never fight the existing transform-based hover effects. */
.m-ready .wordmark .brand-mark path { translate: var(--m-tx, 0) var(--m-ty, 0); }
.m-ready .case-card-media img {
  scale: calc(var(--m-zoom, 1) * 1.07);
  translate: 0 var(--m-py, 0%);
}
.m-ready .person-image { scale: var(--m-zoom, 1); }
.m-ready .fold-seam { scale: var(--m-seam, 1); }
/* The unfold leaves a transform on both panels, which makes each a stacking context. Keep the
   brand panel above, so its slanted fold strip still overlaps the dark panel as designed. */
.m-ready .two-sides .creative-side { z-index: 2; }
.m-ready .contact-arrow { scale: var(--m-s, 1); rotate: var(--m-r, 0deg); }

/* Lines that draw themselves: the static border is replaced by an identical 1px gradient. */
.m-ready :is(.process-grid article, .engagement) {
  border-top-color: transparent;
  background-image: linear-gradient(var(--m-line-color), var(--m-line-color));
  background-repeat: no-repeat;
  background-origin: border-box;
  background-position: 0 0;
  background-size: var(--m-line, 100%) 1px;
}
.m-ready .process-grid article { --m-line-color: #bebebe; }
.m-ready .engagement { --m-line-color: #b6b6b6; }

/* Text swap on hover (twks): the label and the arrow slide out while a copy slides in. */
o-swap { display: inline; }
.m-swap-b { display: none; }
.m-ready .m-swap {
  display: inline-grid;
  overflow: hidden;
  padding: .14em .06em;
  margin: -.14em -.06em;
}
.m-ready .m-swap > * {
  grid-area: 1 / 1;
  display: inline-block;
  transition: transform .7s var(--m-io);
}
.m-ready .m-swap-b { transform: translateX(-112%); }
.m-ready .m-swap--diag > .m-swap-b { transform: translate(-112%, 112%); }
.m-ready .m-swap--up > .m-swap-b { transform: translateY(112%); }
.m-ready .m-swap--down > .m-swap-b { transform: translateY(-112%); }
.m-ready :is(a, button):is(:hover, :focus-visible) .m-swap > .m-swap-a { transform: translateX(112%); }
.m-ready :is(a, button):is(:hover, :focus-visible) .m-swap--diag > .m-swap-a { transform: translate(112%, -112%); }
.m-ready :is(a, button):is(:hover, :focus-visible) .m-swap--up > .m-swap-a { transform: translateY(-112%); }
.m-ready :is(a, button):is(:hover, :focus-visible) .m-swap--down > .m-swap-a { transform: translateY(112%); }
.m-ready :is(a, button):is(:hover, :focus-visible) .m-swap > .m-swap-b { transform: none; transition-delay: .08s; }
/* The swap replaces the small arrow nudge of the static design. */
.m-ready :is(.text-link, .side-link):hover span,
.m-ready .hero-bottom > a:hover > span:last-child,
.m-ready .contact-section .text-link:hover span { transform: none; }
.m-ready .contact-arrow:hover { transform: none; }

/* Underlines (twks): navigation sweeps in from the left and out to the right;
   text links run their line out and back in. */
.m-ready .main-nav > a:not(.nav-contact)::after {
  transform-origin: right;
  transition: transform .6s var(--m-io);
}
.m-ready .main-nav > a:not(.nav-contact):hover::after { transform-origin: left; }
.m-ready .text-link {
  border-bottom-color: transparent;
  background: linear-gradient(currentColor, currentColor) no-repeat 100% 100% / 100% 1px;
  background-origin: border-box;
}
.m-ready .text-link:is(:hover, :focus-visible) { animation: m-underline .95s var(--m-io); }
@keyframes m-underline {
  0% { background-size: 100% 1px; background-position: 100% 100%; }
  45% { background-size: 0 1px; background-position: 100% 100%; }
  55% { background-size: 0 1px; background-position: 0 100%; }
  100% { background-size: 100% 1px; background-position: 0 100%; }
}

/* Expertise: the plus turns as soon as a service starts closing. */
.m-ready .service.is-closing .plus::after { transform: rotate(90deg); }

/* Footer curtain (twks): the page slides up over the footer, which moves only by transform. */
.m-curtain main { position: relative; z-index: 1; background: var(--bg); }
.m-curtain .site-footer { position: relative; z-index: 0; }
