/* ============================================================
   OneVis 2.5D visual component (.v3d)
   Floating render with mouse tilt + inertia, depth layers, light
   sweep, glow, particles, orbital trail, scroll reveal + parallax.
   Tweak via CSS vars on the element or data-* attributes (see JS).
   ============================================================ */
.v3d{
  --speed:1;            /* float speed multiplier */
  --glow:.55;           /* 0..1 glow intensity */
  --depth:1;            /* parallax/tilt depth multiplier */
  --tilt:9deg;          /* max tilt */
  --radius:26px;
  position:relative;width:100%;aspect-ratio:4/3;perspective:1200px;
  isolation:isolate;
  opacity:0;transform:translateY(40px) scale(.94);
  transition:opacity .9s ease,transform 1.3s cubic-bezier(.16,1,.3,1);
}
.v3d.in{opacity:1;transform:none}
.v3d-stage{position:absolute;inset:0;transform-style:preserve-3d;will-change:transform;
  transform:rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg)) translate3d(0,var(--fy,0px),0);
  }
.v3d.settle .v3d-stage{transition:transform 1.1s cubic-bezier(.16,1,.3,1)}
/* glow bed */
.v3d-glow{position:absolute;inset:8% 4% -4%;border-radius:50%;z-index:0;pointer-events:none;
  background:radial-gradient(ellipse at 50% 60%,rgba(37,99,235,calc(.55*var(--glow))),rgba(37,99,235,calc(.18*var(--glow))) 40%,transparent 70%);
  filter:blur(18px);transform:translateZ(-80px) scale(var(--gs,1));animation:v3dGlow calc(6s/var(--speed)) ease-in-out infinite alternate}
@keyframes v3dGlow{from{opacity:.75;transform:translateZ(-80px) scale(.96)}to{opacity:1;transform:translateZ(-80px) scale(1.06)}}
/* the render */
.v3d-img{position:absolute;inset:0;z-index:2;border-radius:var(--radius);overflow:hidden;transform:translateZ(calc(40px*var(--depth)));
  box-shadow:0 40px 90px rgba(3,10,30,.55),0 0 0 1px rgba(119,179,255,.12) inset;background:#040B1B}
.v3d-img img,.v3d-img video{width:100%;height:100%;object-fit:cover;display:block;animation:v3dFloat calc(7s/var(--speed)) ease-in-out infinite;will-change:transform}
@keyframes v3dFloat{0%,100%{transform:translateY(0) scale(1.02)}50%{transform:translateY(-10px) scale(1.035)}}
/* moving reflection */
.v3d-sweep{position:absolute;inset:0;z-index:3;border-radius:var(--radius);pointer-events:none;overflow:hidden;transform:translateZ(calc(42px*var(--depth)))}
.v3d-sweep::before{content:'';position:absolute;top:-30%;bottom:-30%;left:-60%;width:45%;
  background:linear-gradient(105deg,transparent 0%,rgba(255,255,255,.0) 35%,rgba(170,210,255,.22) 50%,rgba(255,255,255,0) 65%,transparent 100%);
  transform:skewX(-18deg);animation:v3dSweep calc(9s/var(--speed)) cubic-bezier(.4,0,.2,1) infinite}
@keyframes v3dSweep{0%,55%{left:-60%}100%{left:140%}}
/* cursor-following specular highlight */
.v3d-spec{position:absolute;inset:0;z-index:4;border-radius:var(--radius);pointer-events:none;mix-blend-mode:screen;opacity:0;transition:opacity .4s;
  background:radial-gradient(360px circle at var(--mx,50%) var(--my,50%),rgba(119,179,255,calc(.35*var(--glow))),transparent 60%)}
.v3d:hover .v3d-spec{opacity:1}
/* particles */
.v3d-dust{position:absolute;inset:-6%;z-index:5;pointer-events:none;transform:translateZ(calc(90px*var(--depth)))}
.v3d-dust i{position:absolute;width:4px;height:4px;border-radius:50%;background:#9FD3FF;box-shadow:0 0 10px 2px rgba(119,179,255,.7);
  left:var(--x);top:var(--y);opacity:0;animation:v3dDust calc(var(--t)/var(--speed)) ease-in-out infinite;animation-delay:var(--dl)}
@keyframes v3dDust{0%{transform:translate3d(0,14px,0) scale(.6);opacity:0}25%{opacity:.9}75%{opacity:.6}100%{transform:translate3d(var(--dx),-50px,0) scale(1);opacity:0}}
/* orbital light trail */
.v3d-orbit{position:absolute;inset:6% -4% -2%;z-index:1;pointer-events:none;transform:translateZ(-20px) rotateX(70deg)}
.v3d-orbit::before,.v3d-orbit::after{content:'';position:absolute;inset:0;border-radius:50%;border:1.5px solid transparent;
  border-top-color:rgba(119,179,255,.0);border-right-color:rgba(119,179,255,.55);
  -webkit-mask:linear-gradient(90deg,transparent 20%,#000 60%,transparent 100%);mask:linear-gradient(90deg,transparent 20%,#000 60%,transparent 100%);
  animation:v3dOrbit calc(12s/var(--speed)) linear infinite}
.v3d-orbit::after{inset:12% 6% 6%;animation-duration:calc(17s/var(--speed));animation-direction:reverse;border-right-color:rgba(37,99,235,.5)}
@keyframes v3dOrbit{to{transform:rotate(360deg)}}
/* reduced motion + touch */
@media (hover:none){.v3d-spec{display:none}}
@media (prefers-reduced-motion:reduce){
  .v3d{opacity:1;transform:none}
  .v3d-img img,.v3d-img video,.v3d-glow,.v3d-sweep::before,.v3d-dust i,.v3d-orbit::before,.v3d-orbit::after{animation:none!important}
  .v3d-stage{transform:none!important}
  .v3d-dust{display:none}
}
/* Services page placement */
.svc-card .v3d{margin:0 0 8px}
.svc-card .card .v3d{aspect-ratio:4/3;margin:-6px 0 22px}
.svc-card .card{padding:22px}

/* pause everything while the component is offscreen */
.v3d:not(.in) .v3d-img img,.v3d:not(.in) .v3d-img video,.v3d:not(.in) .v3d-glow,.v3d:not(.in) .v3d-sweep::before,.v3d:not(.in) .v3d-dust i,.v3d:not(.in) .v3d-orbit::before,.v3d:not(.in) .v3d-orbit::after{animation-play-state:paused}
.v3d.offscreen .v3d-img img,.v3d.offscreen .v3d-img video,.v3d.offscreen .v3d-glow,.v3d.offscreen .v3d-sweep::before,.v3d.offscreen .v3d-dust i,.v3d.offscreen .v3d-orbit::before,.v3d.offscreen .v3d-orbit::after{animation-play-state:paused}
.v3d{contain:layout paint}
.v3d-img{contain:paint}
