/* Home page motion (motion.py). Loaded only on the home page, after minimal.css.
   Every rule sits under html.mo, which the head script sets only when motion is allowed.
   Set MOTION = False in minimal.py to remove all of it. */
:root{--mo:cubic-bezier(.16,1,.3,1)}
h1 .w,h2 .w{display:inline-block}

/* ---------------------------------------------------------------- headlines, word by word */
.mo .w{opacity:0;transform:translateY(.38em);filter:blur(10px);
  transition:opacity .9s var(--mo),transform 1.1s var(--mo),filter .9s var(--mo);
  transition-delay:calc(var(--wd,.08s) + var(--i) * 55ms)}
.mo .is-in .w{opacity:1;transform:none;filter:blur(0)}
.mo .hero{--wd:.18s}
.mo .me__txt{--wd:.2s}

/* ---------------------------------------------------------------- everything else rises a little
   The hidden state is plain CSS so it is in place before the first paint; the script only adds .is-in
   and sets each piece's delay (--up). */
.mo :is(.hero .label,.hero .intro,.hero .ctas,.stats,.logos,.shead .label,.svc > *,.projs .proj,.more--lg,
  .me__txt .label,.me__body,.me__txt .more,.end .label,.end__p,.end .ctas){
  opacity:0;transform:translateY(14px);transition:opacity .9s var(--mo),transform 1.1s var(--mo);transition-delay:var(--up,0s)}
.mo .is-in :is(.hero .label,.hero .intro,.hero .ctas,.stats,.logos,.shead .label,.svc > *,.me__txt .label,.me__body,.me__txt .more,.end .label,.end__p,.end .ctas),
.mo :is(.projs .proj,.more--lg).is-in{opacity:1;transform:none}
.mo .projs .proj{transition:opacity .9s var(--mo),transform 1.1s var(--mo),border-color .2s var(--ease);transition-delay:var(--up,0s),var(--up,0s),0s}

/* header settles in, and a hairline fills as you scroll (browsers with scroll-driven animations) */
.mo .hdr{animation:moHdr .9s var(--mo) both}
@keyframes moHdr{from{opacity:0;transform:translateY(-8px)}}
@supports (animation-timeline:scroll()){
  .mo .hdr::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;background:var(--ink);opacity:.7;
    transform-origin:left;transform:scaleX(0);animation:moProg linear both;animation-timeline:scroll(root)}
  @keyframes moProg{to{transform:scaleX(1)}}
}

/* ---------------------------------------------------------------- hero */
.mo .hero{position:relative;isolation:isolate}
/* a faint dot grid in the open space at the top right; a darker copy shows only around the pointer */
.mo .hero::before,.mo .hero::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:radial-gradient(circle,var(--dot) 1px,transparent 1.5px);background-size:22px 22px;background-position:11px 11px}
.mo .hero::before{--dot:#C9C9C9;opacity:0;transition:opacity 2.4s ease .5s;
  -webkit-mask-image:radial-gradient(ellipse 55% 60% at 82% 18%,#000,transparent 70%);
  mask-image:radial-gradient(ellipse 55% 60% at 82% 18%,#000,transparent 70%)}
.mo .hero.is-in::before{opacity:.8}
.mo .hero::after{--dot:#404040;opacity:0;transition:opacity .6s ease;
  -webkit-mask-image:radial-gradient(180px circle at var(--mx,50%) var(--my,50%),#000,transparent 72%);
  mask-image:radial-gradient(180px circle at var(--mx,50%) var(--my,50%),#000,transparent 72%)}
.mo .hero.is-spot::after{opacity:.6}
/* the hairline above the numbers draws in */
.mo .cred{position:relative;border-top-color:transparent}
.mo .cred::before{content:"";position:absolute;left:0;right:0;top:-1px;height:1px;background:var(--line);
  transform-origin:left;transform:scaleX(0);transition:transform 1.8s var(--mo) .9s}
.mo .hero.is-in .cred::before{transform:scaleX(1)}
.stats b{font-variant-numeric:tabular-nums}

/* ---------------------------------------------------------------- what we do */
.mo .svc{position:relative;border-top-color:transparent}
.mo .svc::before,.mo .svc::after{content:"";position:absolute;left:0;right:0;top:-1px;height:1px;transform:scaleX(0)}
.mo .svc::before{background:var(--line);transform-origin:left;transition:transform 1.4s var(--mo) var(--line-d,0s)}
.mo .svc.is-in::before{transform:scaleX(1)}
/* hover: an ink line draws over the gray one from the left and leaves to the right */
.mo .svc::after{background:var(--ink);transform-origin:right;transition:transform .7s var(--mo)}
.mo .svc:hover::after,.mo .svc:focus-within::after{transform:scaleX(1);transform-origin:left}

/* ---------------------------------------------------------------- selected work */
.mo .proj .frame{clip-path:inset(0 0 100% 0);transition:clip-path 1.3s var(--mo) var(--pic-d,.15s)}
.mo .proj .frame img{scale:1.14;transition:transform .6s var(--ease),scale 1.8s var(--mo) var(--pic-d,.15s)}
.mo .proj.is-in .frame{clip-path:inset(0)}
.mo .proj.is-in .frame img{scale:1}
@media (hover:hover) and (pointer:fine){
  /* the border lights up around the pointer (difference blend: light over the dark pictures, dark over white) */
  .mo .proj::before{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;border-radius:inherit;padding:1px;
    background:radial-gradient(240px circle at var(--mx,50%) var(--my,50%),rgba(255,255,255,.85),transparent 70%);mix-blend-mode:difference;
    -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;
    mask:linear-gradient(#000 0 0) content-box exclude,linear-gradient(#000 0 0);
    opacity:0;transition:opacity .4s ease}
  .mo .proj:hover::before{opacity:1}
}

/* ---------------------------------------------------------------- founder */
.mo .me__pic{clip-path:inset(100% 0 0 0 round var(--r));transition:clip-path 1.4s var(--mo) .05s}
.mo .me__pic img{scale:1.2;transition:scale 2s var(--mo) .05s}
.mo .me__in.is-in .me__pic{clip-path:inset(0 0 0 0 round var(--r))}
.mo .me__in.is-in .me__pic img{scale:1.1}

@media (prefers-reduced-motion:reduce){
  .mo .w{opacity:1;transform:none;filter:none}
}
