@keyframes driftA{0%{transform:translate(0,0)}50%{transform:translate(30px,-18px)}100%{transform:translate(0,0)}}
@keyframes driftB{0%{transform:translate(0,0)}50%{transform:translate(-24px,20px)}100%{transform:translate(0,0)}}
@keyframes driftC{0%{transform:translate(0,0)}50%{transform:translate(18px,24px)}100%{transform:translate(0,0)}}
@keyframes pulseLine{0%,100%{opacity:.15}50%{opacity:.4}}
.hero-net{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.hero-net .node{position:absolute;width:6px;height:6px;border-radius:50%;background:var(--cyan-400)}
.hero-net .node.n1{top:18%;left:12%;animation:driftA 14s ease-in-out infinite}
.hero-net .node.n2{top:62%;left:22%;animation:driftB 17s ease-in-out infinite}
.hero-net .node.n3{top:30%;left:78%;animation:driftC 15s ease-in-out infinite}
.hero-net .node.n4{top:75%;left:68%;animation:driftA 19s ease-in-out infinite}
.hero-net .node.n5{top:12%;left:55%;animation:driftB 13s ease-in-out infinite}
.hero-net .line{position:absolute;height:1px;background:var(--cyan-400);transform-origin:left center;animation:pulseLine 6s ease-in-out infinite}
@keyframes rainFall{0%{transform:translateY(-100%)}100%{transform:translateY(100%)}}
.data-rain{position:absolute;inset:0;overflow:hidden;pointer-events:none;opacity:.5}
.rain-col{position:absolute;top:0;width:1px;height:60%;background:linear-gradient(to bottom,transparent,var(--cyan-400) 30%,var(--cyan-200) 60%,transparent);animation-name:rainFall;animation-timing-function:linear;animation-iteration-count:infinite}
@keyframes slideUp{from{transform:translateY(18px)}to{transform:none}}
.fade-in{opacity:1;animation:slideUp .5s ease both}
.hover-lift{transition:transform .18s ease,box-shadow .18s ease}
.hover-lift:hover{transform:translateY(-3px);box-shadow:var(--shadow-lg)}
.site-nav a{transition:color .15s ease}
