/* Digital Perception — motion layer. Every section owns a distinct motion identity.
   Reveal/hidden states apply ONLY under html.dp-motion so content is always visible without JS/GSAP. */

/* Hero entrance (CSS keyframes: works before any library loads) */
html{--introDelay:0s}
html.is-intro{--introDelay:.66s}
html.js .hero-title .ln>span{animation:lnrise 1.15s var(--ease-out) calc(var(--introDelay) + .05s + var(--i,0)*.12s) both}
html.js .hero-title .ln:nth-child(2)>span{--i:1}
html.js .hero-lead{animation:heroin 1s var(--ease-out) calc(var(--introDelay) + .34s) both}
html.js .hero-actions{animation:heroin 1s var(--ease-out) calc(var(--introDelay) + .48s) both}
html.js .hero-cue{animation:heroin 1s var(--ease-out) calc(var(--introDelay) + .9s) both}
html.js .hero-core-static{animation:corein 1.6s var(--ease-out) calc(var(--introDelay) + .1s) backwards}
@keyframes lnrise{from{transform:translateY(108%) rotateX(-38deg);transform-origin:0 100%}to{transform:none}}
@keyframes heroin{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
@keyframes corein{from{opacity:0;scale:.86}to{opacity:1;scale:1}}

/* Heading mask reveals (perspective + layered lines) */
html.dp-motion .rv .ln>span{transform:translateY(108%) rotateX(-38deg);transform-origin:0 100%;transition:transform 1.1s var(--ease-out) calc(var(--i,0)*.11s + var(--rd,0s))}
html.dp-motion .rv .ln:nth-child(2)>span{--i:1}
html.dp-motion .rv.is-in .ln>span{transform:none}
html.dp-motion .rv.hero-title .ln>span{transform:none;transition:none}

/* 03 stream: line ignites from the centre, then track powers up */
html.dp-motion .stream-ignite{transform:scaleX(0);transition:transform 1.4s var(--ease-io)}
html.dp-motion .stream.is-in .stream-ignite{transform:scaleX(1)}
html.dp-motion .stream-head>*,html.dp-motion .stream-window{opacity:0;transition:opacity 1s .2s}
html.dp-motion .stream.is-in .stream-head>*,html.dp-motion .stream.is-in .stream-window{opacity:1}

/* 04 system: labels tint when their stage activates */
html.dp-pin .engine .tlink,html.dp-pin .engine>p,html.dp-pin .engine h3{transition:opacity .5s}

/* 05 services: instruments power on from their centre */
html.dp-motion .control .inst{opacity:0;clip-path:inset(46% 46% 46% 46% round 18px);transition:clip-path 1s var(--ease-out) var(--rd,0s),opacity .6s var(--rd,0s),border-color .5s,box-shadow .6s}
html.dp-motion .control .inst.is-in{opacity:1;clip-path:inset(0 round 18px)}
html.dp-motion .control .inst.is-done{clip-path:none}
.inst:not(.is-live) .viz *,.inst:not(.is-live) .viz *::before{animation-play-state:paused!important}

/* instrument loops */
.sweep{animation:spin 6s linear infinite}
.radar b{animation:blip 6s linear infinite;animation-delay:calc(var(--a)/360*6s)}
@keyframes spin{to{rotate:360deg}}
@keyframes blip{0%{opacity:1;scale:1.7}35%{opacity:.4;scale:1}100%{opacity:0;scale:.9}}
.sn-edges path{stroke-dasharray:3 8;animation:dashflow 2.6s linear infinite}
.sn-nodes circle{transform-box:fill-box;transform-origin:center;animation:npulse 3.2s ease-in-out infinite}
.sn-nodes circle:nth-child(2){animation-delay:-.4s}.sn-nodes circle:nth-child(3){animation-delay:-.9s}.sn-nodes circle:nth-child(4){animation-delay:-1.4s}.sn-nodes circle:nth-child(5){animation-delay:-1.9s}.sn-nodes circle:nth-child(6){animation-delay:-2.3s}.sn-nodes circle:nth-child(7){animation-delay:-2.8s}
.inst-social:hover .sn-edges path{animation-duration:.9s}
.inst-social:hover .sn-nodes circle{animation-duration:1.4s}
@keyframes dashflow{to{stroke-dashoffset:-22}}
@keyframes npulse{0%,100%{scale:1}50%{scale:1.32;stroke:var(--gold)}}
.strip::before{animation:strip 9s linear infinite}
.strip.s2::before{animation-duration:14s;animation-direction:reverse}.strip.s3::before{animation-duration:11s}
.inst-content:hover .strip::before{animation-duration:4s}
@keyframes strip{to{transform:translateX(calc(var(--p)*-1))}}
.viz-web .ui{animation:wipe 8s var(--ease-io) infinite}
.viz-web .wf{animation:wfade 8s var(--ease-io) infinite}
@keyframes wipe{0%,14%{clip-path:inset(0 100% 0 0)}46%,84%{clip-path:inset(0 0 0 0)}100%{clip-path:inset(0 100% 0 0)}}
@keyframes wfade{0%,14%{opacity:1}46%,84%{opacity:.25}100%{opacity:1}}
.inst-web:hover .ui{animation-duration:4s}
.tf i{animation:tforg 9s var(--ease-io) infinite}
.tf em{animation:tflink 9s var(--ease-io) infinite}
@keyframes tforg{0%,10%{transform:translate(var(--sx),var(--sy)) rotate(var(--sr));border-style:dashed}38%,84%{transform:none;border-style:solid;border-color:rgba(255,148,31,.55)}100%{transform:translate(var(--sx),var(--sy)) rotate(var(--sr));border-style:dashed}}
@keyframes tflink{0%,36%{opacity:0}48%,82%{opacity:.75}94%,100%{opacity:0}}
.inst-transform:hover .tf i,.inst-transform:hover .tf em{animation-duration:4.5s}
.tg{animation:tgbg 9s var(--ease-io) infinite}.tg::after{animation:tgkn 9s var(--ease-io) infinite}
.ac-row:nth-child(2) .tg,.ac-row:nth-child(2) .tg::after{animation-delay:1.6s}.ac-row:nth-child(3) .tg,.ac-row:nth-child(3) .tg::after{animation-delay:3.2s}
@keyframes tgbg{0%,8%{background:var(--steel-2)}16%,80%{background:rgba(var(--energy),.85)}92%,100%{background:var(--steel-2)}}
@keyframes tgkn{0%,8%{translate:0 0;background:var(--mute)}16%,80%{translate:16px 0;background:#fff}92%,100%{translate:0 0;background:var(--mute)}}
.ac-cur{animation:accur 9s var(--ease-io) infinite}
@keyframes accur{0%{translate:0 0}12%,28%{translate:0 0}36%,48%{translate:0 50px}56%,72%{translate:0 100px}84%,100%{translate:0 0}}

/* 06 products: unfocused windows are inert; focused window animates its internals */
.pw-flow i{animation:nodeon 3s ease-in-out infinite}.pw-flow i:nth-child(2){animation-delay:.5s}.pw-flow i:nth-child(3){animation-delay:1s}
@keyframes nodeon{0%,100%{background:var(--steel-2)}40%,60%{background:var(--amber-hot);box-shadow:0 0 10px rgba(var(--energy),.9)}}
.rt{animation:dashflow 3s linear infinite}.rt2{animation-duration:5s}
.veh{animation:npulse 2.6s ease-in-out infinite;transform-box:fill-box;transform-origin:center}
.pw-gantt i{animation:ganttgrow 5s var(--ease) infinite alternate}
@keyframes ganttgrow{from{scale:.7 1;transform-origin:left}to{scale:1 1;transform-origin:left}}
.an{animation:anom 2.2s ease-in-out infinite;transform-box:fill-box;transform-origin:center}
@keyframes anom{0%,100%{scale:1;opacity:1}50%{scale:1.7;opacity:.35}}
.u1f{animation:dashflow 2.4s linear infinite}
.pwin:not(.is-focus) *,.pwin:not(.is-focus) *::before{animation-play-state:paused!important}
.p-scene .pw-bars i{transform-origin:bottom;animation:barbeat 4s ease-in-out infinite alternate}
.p-scene .pw-bars i:nth-child(even){animation-delay:-1.4s}
@keyframes barbeat{from{scale:1 .82}to{scale:1 1}}

/* 07 marketplace: hub emits, nodes answer */
html.dp-motion .net .nn{opacity:0;scale:.6;transition:opacity .7s var(--ease-out),scale .8s var(--ease-out),border-color .4s,box-shadow .4s;transition-delay:calc(var(--n,0)*90ms + .2s)}
html.dp-motion .net.is-in .nn{opacity:1;scale:1}
html.dp-motion .net .net-paths path{stroke-dasharray:1;stroke-dashoffset:1;transition:stroke-dashoffset 1.5s var(--ease-io) .2s;stroke:rgba(255,148,31,.35)}
html.dp-motion .net.is-in .net-paths path{stroke-dashoffset:0;animation:dashflow 2.6s linear 1.8s infinite;stroke-dasharray:3 6}
@keyframes nnpulse{0%,100%{box-shadow:0 0 0 0 rgba(var(--energy),0)}50%{box-shadow:0 0 22px -4px rgba(var(--energy),.45)}}
.net-hub{animation:hubbeat 3.6s ease-in-out infinite}
@keyframes hubbeat{0%,100%{box-shadow:0 0 50px -10px rgba(var(--energy),.45)}50%{box-shadow:0 0 80px -6px rgba(var(--energy),.75)}}
.net-orbit{transform-origin:300px 280px;animation:spin 60s linear infinite}
.net-orbit.o2{animation-duration:90s;animation-direction:reverse}
.flow li.on::after{height:calc(100% - 22px)}
.net:not(.is-live) .net-orbit,.net:not(.is-live) .net-hub{animation-play-state:paused}

/* 08 work: hint only; portal depth is scroll-linked (JS custom props) */
.pt-ring{transition:border-color .8s}

/* 09 process micro-systems */
@keyframes ping{0%{scale:.4;opacity:1}100%{scale:1.9;opacity:0}}
@keyframes scanx{0%{translate:-46% 0;opacity:0}20%,80%{opacity:1}100%{translate:46% 0;opacity:0}}
@keyframes wire{from{clip-path:inset(0 100% 0 0);opacity:.4}to{clip-path:inset(0);opacity:1;border-color:rgba(255,148,31,.55)}}
@keyframes drop{from{translate:0 -34px;opacity:0}to{translate:0 0;opacity:1}}
@keyframes draw{to{stroke-dashoffset:0}}
@keyframes angspin{to{--ang:360deg}}

/* 10 plans: matrix boots row by row like a scan */
html.dp-motion .matrix .mx-table tbody tr{clip-path:inset(0 100% 0 0);transition:clip-path 1s var(--ease-out) calc(var(--r,0)*80ms + .1s)}
html.dp-motion .matrix.is-in .mx-table tbody tr{clip-path:inset(0)}
html.dp-motion .matrix.is-done .mx-table tbody tr{clip-path:none}
.mx-summary [data-mx-price],.mx-summary h3,.mx-summary>p{transition:opacity .25s,translate .4s var(--ease)}
.mx-summary.is-swap [data-mx-price],.mx-summary.is-swap h3,.mx-summary.is-swap>p{opacity:0;translate:0 8px}

/* 11 insights: slow editorial curtain (minimal motion) */
html.dp-motion .ed-img{clip-path:inset(0 0 100% 0 round 14px);transition:clip-path 1.3s var(--ease-out) var(--rd,0s)}
html.dp-motion .ed.is-in .ed-img{clip-path:inset(0 round 14px)}
html.dp-motion .ed-copy{opacity:0;transition:opacity 1.2s ease var(--rd,0s)}
html.dp-motion .ed.is-in .ed-copy{opacity:1}

/* 12 CTA: aperture idle + headline emerges after convergence */
.cta-aperture i:nth-child(1){animation:spin 120s linear infinite}
.cta-aperture i:nth-child(2){animation:spin 80s linear infinite reverse}
html.dp-motion .cta .cta-actions,html.dp-motion .cta .cta-contact{opacity:0;translate:0 14px;transition:opacity .9s var(--ease) .5s,translate .9s var(--ease) .5s}
html.dp-motion .cta.is-in .cta-actions,html.dp-motion .cta.is-in .cta-contact{opacity:1;translate:0 0}
html.dp-motion .cta.is-in .cta-contact{transition-delay:.7s}
html.dp-motion .cta-aperture{opacity:calc(var(--cv,0)*.9)}

/* Reduced motion: keep all information, drop scrubbing, parallax, loops, magnetic movement */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;animation-delay:0s!important;transition-duration:.001ms!important;transition-delay:0s!important;scroll-behavior:auto!important}
  .hero-cue,.sweep,.dp-intro,.dp-cursor,.dp-route{display:none!important}
  html.js .hero-title .ln>span,html.js .hero-lead,html.js .hero-actions,html.js .hero-cue,html.js .hero-core-static{animation:none}
  .radar b{opacity:.85}
  .btn{translate:none!important}
}

/* Hero scroll-linked state (--copy is written by hero-motion.js on the stage) */
html.dp-pin .hero-copy{opacity:calc(1 - var(--copy,0)*1.35);translate:-50% calc(var(--copy,0)*-9vh)}
html.dp-pin .hero-title .ln>span{translate:0 calc(var(--copy,0)*-112%)}
.hero-stage.is-scrolled .hero-cue{animation:none;opacity:0;transition:opacity .4s}

/* Phone hero: copy lifts away as the story starts (--copy written by hero-motion.js) */
html.dp-mpin .hero-copy{opacity:calc(1 - var(--copy,0)*1.35);translate:-50% calc(var(--copy,0)*-6svh)}
html.dp-mpin .hero-title .ln>span{translate:0 calc(var(--copy,0)*-112%)}
