/* 23 Group · motion layer. Base styles are the finished, static frame:
   prefers-reduced-motion (style.css) switches every animation off and leaves exactly this. */
.art .draw>*{stroke-dasharray:1 1}
.hero .art .draw>*,.in .art .draw>*{animation:draw 1.6s var(--ease) calc(var(--i,0)*.18s + .25s) backwards}
@keyframes draw{from{stroke-dashoffset:1}}
@keyframes orbit{to{transform:rotate(360deg)}}

/* hero · idea -> possibility */
.hero-orbit{transform-origin:280px 200px;animation:orbit 28s linear infinite}
.hero-object{transform-origin:280px 200px;animation:object 12s ease-in-out infinite}
.hero-cross{transform-origin:280px 200px;animation:quarter 6s cubic-bezier(.7,0,.2,1) infinite}
.ox{animation:ox var(--t) cubic-bezier(.37,0,.63,1) infinite alternate}
.oy{animation:oy var(--t) cubic-bezier(.37,0,.63,1) calc(var(--t)/-2) infinite alternate}
.ping circle{transform-origin:280px 200px;opacity:0;animation:ping 4.4s cubic-bezier(.2,.6,.3,1) calc(var(--i,0)*-2.2s) infinite}
.vf path{animation:focus 6s ease-in-out 1.6s infinite}
@keyframes object{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(8deg)}}
@keyframes quarter{0%,65%{transform:rotate(0)}100%{transform:rotate(90deg)}}
@keyframes ox{from{transform:translateX(-145px)}to{transform:translateX(145px)}}
@keyframes oy{from{transform:translateY(-58px)}to{transform:translateY(58px)}}
@keyframes ping{0%{transform:scale(.3);opacity:.85}100%{transform:scale(1);opacity:0}}
@keyframes focus{0%,70%,100%{transform:none}80%{transform:translate(calc(var(--x)*9px),calc(var(--y)*9px))}90%{transform:translate(calc(var(--x)*-2px),calc(var(--y)*-2px))}}

/* 01 marketing · the signal spreads, people pick it up and pass it on */
.waves circle{transform-origin:280px 200px;opacity:0;animation:wave 4.8s linear var(--w,0s) infinite}
.aud{transform-box:fill-box;transform-origin:center;animation:aud 4.8s ease-out var(--d) infinite}
.link{stroke-dasharray:1 1;stroke-dashoffset:1;animation:link 4.8s ease-out var(--d) infinite}
.source{transform-origin:280px 200px;animation:emit 4.8s var(--ease) infinite}
.signal-orbit{transform-origin:280px 200px;animation:orbit 22s linear infinite}
@keyframes wave{0%{transform:scale(.139);opacity:0}4%{opacity:1}70%{transform:scale(1);opacity:0}100%{transform:scale(1);opacity:0}}
@keyframes aud{0%{fill:#2B3FF5;transform:scale(2)}12%{transform:scale(1.25)}45%{fill:#2B3FF5}60%,100%{fill:currentColor;transform:scale(1)}}
@keyframes link{0%{stroke-dashoffset:1;opacity:1}16%{stroke-dashoffset:0;opacity:1}45%,100%{stroke-dashoffset:0;opacity:0}}
@keyframes emit{0%{transform:scale(.84)}8%{transform:scale(1.08)}22%,100%{transform:scale(1)}}

/* 02 design · loose shapes snap onto the grid, get selected, let go */
.shape{transform-box:fill-box;transform-origin:center;animation:snap 8s infinite}
.s-sq{--tx:-95px;--ty:-40px;--r:-24deg;--s:.42}
.s-ci{--tx:112px;--ty:72px;--r:0deg;--s:.36;animation-delay:.14s}
.s-tr{--tx:78px;--ty:-82px;--r:34deg;--s:.4;animation-delay:.28s}
.guides path{opacity:0;animation:guide 8s calc(var(--i,0)*.06s) infinite}
.select{opacity:0;transform-origin:280px 200px;animation:select 8s infinite}
.design-dot{animation:corners 8s cubic-bezier(.7,0,.2,1) infinite}
@keyframes snap{0%,9%{transform:translate(var(--tx),var(--ty)) rotate(var(--r)) scale(var(--s));animation-timing-function:cubic-bezier(.3,1.45,.5,1)}24%,76%{transform:none;animation-timing-function:cubic-bezier(.6,0,.4,1)}90%,100%{transform:translate(var(--tx),var(--ty)) rotate(var(--r)) scale(var(--s))}}
@keyframes guide{0%,18%{opacity:0}21%{opacity:.9}34%,100%{opacity:0}}
@keyframes select{0%,27%{opacity:0;transform:scale(1.04)}32%,72%{opacity:1;transform:scale(1)}77%,100%{opacity:0;transform:scale(1)}}
@keyframes corners{0%,30%,92%,100%{transform:translate(0,0)}38%,46%{transform:translate(0,220px)}54%,62%{transform:translate(-220px,220px)}70%,82%{transform:translate(-220px,0)}}

/* 03 AI · inputs light up, data flows to the core, gets worked on, flows out */
.hexflow{stroke-dasharray:4 10;animation:flow 2.4s linear infinite}
.core-ring{transform-origin:280px 200px;animation:orbit 14s linear infinite}
.core{transform-origin:280px 200px;animation:core 5s var(--ease) infinite}
.core-cross{transform-origin:280px 200px;animation:core-cross 5s cubic-bezier(.7,0,.2,1) infinite}
.core-ripple{transform-origin:280px 200px;opacity:0;animation:ripple 5s ease-out infinite}
.pk{opacity:0}
.pk-in{animation:pk-in 5s cubic-bezier(.45,0,.55,1) var(--d) infinite}
.pk-out{animation:pk-out 5s cubic-bezier(.45,0,.55,1) var(--d) infinite}
.nd{fill:#F4F1EC}.nd-hi{fill:#2B3FF5;stroke:#2B3FF5}
.nd-in{animation:nd-in 5s var(--d) infinite}
.nd-out{animation:nd-out 5s var(--d) infinite}
@keyframes flow{to{stroke-dashoffset:-28}}
@keyframes core{0%,30%{transform:scale(1)}36%{transform:scale(1.14)}46%,100%{transform:scale(1)}}
@keyframes core-cross{0%,31%{transform:rotate(0)}42%,100%{transform:rotate(90deg)}}
@keyframes ripple{0%,31%{transform:scale(1);opacity:0}34%{opacity:.9}58%,100%{transform:scale(2.6);opacity:0}}
@keyframes pk-in{0%{transform:translate(var(--x),var(--y));opacity:0}5%{opacity:1}28%{transform:translate(0,0);opacity:1}31%,100%{transform:translate(0,0);opacity:0}}
@keyframes pk-out{0%,40%{transform:translate(0,0);opacity:0}43%,65%{opacity:1}68%,100%{transform:translate(var(--x),var(--y));opacity:0}}
@keyframes nd-in{0%,8%{fill:#2B3FF5;stroke:#2B3FF5}22%,100%{fill:#F4F1EC;stroke:currentColor}}
@keyframes nd-out{0%,64%{fill:#F4F1EC;stroke:currentColor}67%,90%{fill:#2B3FF5;stroke:#2B3FF5}100%{fill:#F4F1EC;stroke:currentColor}}

/* 04 web · the page builds itself, the visitor clicks, it converts, it resets */
.wb{animation-duration:10s;animation-iteration-count:infinite;animation-timing-function:var(--ease)}
.wb.sx{transform-box:fill-box;transform-origin:0 50%}
.wb.pop{transform-box:fill-box;transform-origin:center;animation-timing-function:cubic-bezier(.34,1.56,.64,1)}
.wb.dash{stroke-dasharray:1 1}
.cols{animation:cols 10s infinite}
.btn-press{transform-box:fill-box;transform-origin:center;animation:press 10s infinite}
.click-ring{transform-origin:141px 222px;opacity:0;animation:click 10s ease-out infinite}
.w-dot{transform-origin:371px 180px;animation:w-dot 10s var(--ease) infinite}
.web-pointer{transform:translate(399px,220px);animation:cursor 10s cubic-bezier(.65,0,.35,1) infinite}
@keyframes cols{0%,3%{opacity:0}8%,27%{opacity:1}34%,100%{opacity:0}}
@keyframes press{0%,45%{transform:scale(1)}47%{transform:scale(.88)}52%,100%{transform:scale(1)}}
@keyframes click{0%,46%{transform:scale(.6);opacity:0}48%{opacity:1}62%,100%{transform:scale(1.9);opacity:0}}
@keyframes w-dot{0%,50%{transform:scale(0)}56%,82%{transform:scale(1)}87%,100%{transform:scale(0)}}
@keyframes cursor{0%,30%{transform:translate(405px,282px)}42%{transform:translate(146px,226px)}46%{transform:translate(146px,226px) scale(.86)}50%,58%{transform:translate(146px,226px) scale(1)}72%,100%{transform:translate(405px,282px)}}

/* 05 social · the feed keeps moving, people react, someone is typing */
.feed{animation:feed 13s linear infinite}
.like{transform-box:fill-box;transform-origin:center;animation:like 13s infinite}
.burst{transform-box:fill-box;transform-origin:center;animation:burst 3s cubic-bezier(.7,0,.2,1) infinite}
.typing{animation:bob 4s ease-in-out infinite}
.td{animation:td 1.2s ease-in-out calc(var(--i,0)*.15s) infinite}
.float{transform-box:fill-box;transform-origin:center;opacity:0;animation:float 6s cubic-bezier(.2,.6,.3,1) var(--d) infinite}
@keyframes feed{to{transform:translateY(-326px)}}
@keyframes like{0%,2%{fill:none;stroke:currentColor;transform:scale(1)}4%{fill:#2B3FF5;stroke:#2B3FF5;transform:scale(1.55)}8%,40%{fill:#2B3FF5;stroke:#2B3FF5;transform:scale(1)}41%,100%{fill:none;stroke:currentColor;transform:scale(1)}}
@keyframes burst{0%,55%{transform:rotate(0)}85%,100%{transform:rotate(90deg)}}
@keyframes bob{50%{transform:translateY(-6px)}}
@keyframes td{0%,60%,100%{transform:translateY(0);opacity:.35}30%{transform:translateY(-5px);opacity:1}}
@keyframes float{0%{transform:translate(0,0) scale(.3);opacity:0}12%{transform:translate(calc(var(--dx)*.2),-40px) scale(1.15);opacity:1}25%{transform:translate(calc(var(--dx)*.4),-75px) scale(1)}75%{opacity:1}100%{transform:translate(var(--dx),-240px) scale(1);opacity:0}}

/* panel viewfinder corners (echo of the logo) */
.art-panel{position:relative}
.art-panel::before,.art-panel::after{content:"";position:absolute;width:22px;height:22px;border:0 solid currentColor;opacity:.5;transition:transform 1.1s var(--ease) .35s,opacity 1.1s var(--ease) .35s}
.art-panel::before{top:16px;left:16px;border-width:1.5px 0 0 1.5px}
.art-panel::after{right:16px;bottom:16px;border-width:0 1.5px 1.5px 0}

/* micro-interactions */
.status-dot{position:relative}
.status-dot::after{content:"";position:absolute;inset:0;border-radius:50%;border:1px solid var(--blue);animation:beacon 2.4s ease-out infinite}
@keyframes beacon{from{transform:scale(1);opacity:.9}to{transform:scale(3.4);opacity:0}}
.header nav a:not(.nav-contact),.service-index a{background:linear-gradient(currentColor,currentColor) 0 calc(100% - 6px)/0 1px no-repeat;transition:background-size .45s var(--ease),color .2s}
.service-index a{background-position:0 100%;padding-bottom:4px}
.header nav a:not(.nav-contact):hover,.service-index a:hover{background-size:100% 1px}
.service-index a:hover sup{color:var(--blue)}
.header nav a span,.text-link span,.email span{display:inline-block;transition:transform .4s var(--ease)}
.header nav a:hover span,.text-link:hover span{transform:translate(3px,3px)}
.header nav .nav-contact:hover span,.email:hover span{transform:translate(3px,-3px)}
.text-link{transition:gap .45s var(--ease),border-color .3s,color .2s}.text-link:hover{gap:54px;border-color:var(--blue)}
.capabilities li{cursor:default;transition:background-color .25s,color .25s,border-color .25s}
.capabilities li:hover{background:var(--blue);border-color:var(--blue);color:var(--bone)}
.contact-arrow{display:block;width:116px;height:116px;padding:0;margin-right:16px;flex:none}
.contact-arrow svg{width:100%;height:100%}
.ca-ring{stroke:var(--blue);stroke-width:2;stroke-dasharray:1 1;stroke-dashoffset:1;transition:stroke-dashoffset .8s var(--ease)}
.ca-arrow{animation:nudge 3.6s ease-in-out infinite}
.ca-arrow path{stroke-dasharray:1 1;transition:stroke-dashoffset 1.2s var(--ease) .45s}
.contact-link:hover .contact-arrow{transform:none;color:var(--blue)}
.contact-link:hover .ca-ring{stroke-dashoffset:0}
.contact-link:hover .ca-arrow{animation:shoot .75s var(--ease)}
@keyframes nudge{0%,72%,100%{transform:none}82%{transform:translate(7px,-7px)}}
@keyframes shoot{0%{transform:none;opacity:1}38%{transform:translate(46px,-46px);opacity:0}39%{transform:translate(-46px,46px);opacity:0}100%{transform:none;opacity:1}}
@media(max-width:700px){.contact-arrow{width:46px;height:46px;margin:6px 0 0}}

/* pause control: freeze everything, not just the svgs */
.motion-paused *,.motion-paused *::before,.motion-paused *::after{animation-play-state:paused!important}

/* scroll entrances. Only when scripting is on and motion is welcome; script.js adds .in per block. */
.ln{display:block}
@media (scripting:enabled) and (prefers-reduced-motion:no-preference){
 :is(.hero,.service-index,.service,.studio,.contact) :is(.hero-top,h1,.hero-description,.text-link,.hero-art,.hero-bottom,.service-index nav>*,.service-copy>.eyebrow,.service h2,.description,.art-panel,.studio-grid>.eyebrow,.studio h2,.studio-description p,.contact>.wrap>.eyebrow,.contact h2,.contact-bottom){transition:opacity .9s var(--ease) calc(var(--i,0)*85ms),transform 1.1s var(--ease) calc(var(--i,0)*85ms)}
 :is(.hero,.service-index,.service,.studio,.contact):not(.in) :is(.hero-top,h1,.hero-description,.text-link,.hero-art,.hero-bottom,.service-index nav>*,.service-copy>.eyebrow,.service h2,.description,.art-panel,.studio-grid>.eyebrow,.studio h2,.studio-description p,.contact>.wrap>.eyebrow,.contact h2,.contact-bottom){opacity:0;transform:translateY(26px)}
 .ln{overflow:hidden;padding-bottom:.12em;margin-bottom:-.12em}
 .ln>span{display:block;transition:transform 1.15s var(--ease) calc(var(--i,0)*85ms + var(--l,0)*110ms)}
 :is(.hero,.service,.studio,.contact):not(.in) .ln>span{transform:translateY(108%)}
 .in .ln>span{transform:none}
 .capabilities li{transition:opacity .6s var(--ease) calc(var(--j,0)*70ms + .45s),transform .7s var(--ease) calc(var(--j,0)*70ms + .45s),background-color .25s,color .25s,border-color .25s}
 .rv .service:not(.in) .capabilities li{opacity:0;transform:translateY(10px) scale(.92)}
 .rv .service:not(.in) .art-panel::before{transform:translate(-12px,-12px);opacity:0}
 .rv .service:not(.in) .art-panel::after{transform:translate(12px,12px);opacity:0}
 .in .art-panel::before,.in .art-panel::after{transform:none;opacity:.5}
 .rv .contact:not(.in) .ca-arrow path{stroke-dashoffset:1}
 .rv .service:not(.in) .art .draw>*{stroke-dashoffset:1}
 /* no-JS-ran failsafe: script.js tags <html class="rv"> at once; if it never runs, show everything */
 html:not(.rv) :is(.hero-top,h1,.hero-description,.text-link,.hero-art,.hero-bottom,.service-index nav>*,.service-copy>.eyebrow,.service h2,.description,.art-panel,.studio-grid>.eyebrow,.studio h2,.studio-description p,.contact>.wrap>.eyebrow,.contact h2,.contact-bottom){animation:rv-failsafe .5s 2.5s forwards}
}
@keyframes rv-failsafe{to{opacity:1;transform:none}}
/* generated by motion_upgrade.py */
@keyframes w-head{0%,5.00%{transform:scaleX(0)}10.50%,83.00%{transform:scaleX(1)}87.50%,100%{transform:scaleX(0)}}
@keyframes w-l1{0%,8.50%{transform:scaleX(0)}14.00%,83.00%{transform:scaleX(1)}87.50%,100%{transform:scaleX(0)}}
@keyframes w-l2{0%,10.00%{transform:scaleX(0)}15.50%,83.00%{transform:scaleX(1)}87.50%,100%{transform:scaleX(0)}}
@keyframes w-btn{0%,13.00%{transform:scale(0)}19.00%,83.00%{transform:scale(1)}87.50%,100%{transform:scale(0)}}
@keyframes w-img{0%,15.50%{stroke-dashoffset:1}23.50%,83.00%{stroke-dashoffset:0}87.50%,100%{stroke-dashoffset:1}}
@keyframes w-ci{0%,19.00%{stroke-dashoffset:1}27.00%,83.00%{stroke-dashoffset:0}87.50%,100%{stroke-dashoffset:1}}
@keyframes w-f1{0%,22.50%{transform:scaleX(0)}28.00%,83.00%{transform:scaleX(1)}87.50%,100%{transform:scaleX(0)}}
@keyframes w-f2{0%,24.00%{transform:scaleX(0)}29.50%,83.00%{transform:scaleX(1)}87.50%,100%{transform:scaleX(0)}}
@keyframes w-f3{0%,25.50%{transform:scaleX(0)}31.00%,83.00%{transform:scaleX(1)}87.50%,100%{transform:scaleX(0)}}
