/* ============================================================
   HEMNIX — 3D STYLE & MOTION LAYER
   Loaded after every other stylesheet so it can extend them.
   ------------------------------------------------------------
   • Shared 3D transform recipe (tilt + reveal + parallax vars)
   • Scroll reveal with stagger
   • Ambient stage: perspective grid floor, aurora, orbs
   • Hero 3D scene + rotating tech cube
   • 3D tech marquee, simple button hovers, glowing CTA border
   • Falls back gracefully when JS is off or motion is reduced
   ============================================================ */

:root{
    --fx-ease: cubic-bezier(.2,.7,.3,1);
    --fx-perspective: 1100px;
    --fx-glow: rgba(124,131,255,.45);
    --fx-depth: rgba(3,6,20,.78);
}

/* JS-GATE: only hide/animate content when the motion layer booted.
   If JS is off, .fx-active is never added and everything stays visible. */

/* ---------- SCROLL PROGRESS BAR ---------- */

.fx-scroll-progress{
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    z-index: 1200;
    pointer-events: none;
    background: transparent;
}

.fx-scroll-progress span{
    display: block;
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg,#7C83FF,#8B5CF6,#037f4c);
    box-shadow: 0 0 14px rgba(124,131,255,.85);
    transition: width .12s linear;
}

/* ---------- AMBIENT 3D STAGE (fixed background) ---------- */

.fx-stage{
    position: fixed;
    inset: 0;
    z-index: -1;
    overflow: hidden;
    pointer-events: none;
}

.fx-stage-grid{
    position: absolute;
    left: -40%;
    right: -40%;
    bottom: -12%;
    height: 70vh;
    background-image:
        linear-gradient(rgba(124,131,255,.16) 1px, transparent 1px),
        linear-gradient(90deg, rgba(124,131,255,.16) 1px, transparent 1px);
    background-size: 70px 70px;
    transform: rotateX(74deg);
    transform-origin: 50% 100%;
    -webkit-mask-image: linear-gradient(to top, rgba(0,0,0,.75), transparent 78%);
    mask-image: linear-gradient(to top, rgba(0,0,0,.75), transparent 78%);
    animation: fxGridScroll 9s linear infinite;
    opacity: .5;
}

.fx-stage-aurora{
    position: absolute;
    top: -28vh;
    left: 50%;
    width: 130vw;
    height: 95vh;
    transform: translateX(-50%);
    background:
        radial-gradient(45% 55% at 30% 40%, rgba(124,131,255,.30), transparent 70%),
        radial-gradient(40% 50% at 72% 32%, rgba(139,92,246,.24), transparent 70%),
        radial-gradient(35% 45% at 52% 62%, rgba(3,127,76,.16), transparent 70%);
    filter: blur(40px);
    animation: fxAuroraDrift 22s ease-in-out infinite alternate;
}

.fx-orb{
    position: absolute;
    border-radius: 50%;
    background: radial-gradient(circle at 32% 28%, rgba(255,255,255,.55), rgba(124,131,255,.35) 34%, rgba(124,131,255,0) 72%);
    box-shadow: 0 0 60px rgba(124,131,255,.35), inset 0 0 30px rgba(255,255,255,.14);
    opacity: .7;
}

.fx-orb-1{ width: 120px; height: 120px; top: 20%; left: 6%; animation: fxOrbFloat 11s ease-in-out infinite; }
.fx-orb-2{ width: 70px;  height: 70px;  top: 62%; right: 8%; animation: fxOrbFloat 14s ease-in-out infinite; animation-delay: -3s; }
.fx-orb-3{ width: 44px;  height: 44px;  top: 36%; right: 24%; animation: fxOrbFloat 9s  ease-in-out infinite; animation-delay: -5s; opacity: .55; }


/* ---------- SUBTLE ROCKET FLY-BYS: low contrast, decorative depth ---------- */

.fx-rocket{
    position: absolute;
    z-index: 0;
    top: 28%;
    left: -120px;
    width: 92px;
    height: 36px;
    opacity: .16;
    transform: rotate(18deg) scale(var(--rocket-scale, .85));
    transform-origin: center;
    animation: fxRocketFly var(--rocket-duration, 28s) linear var(--rocket-delay, 0s) infinite;
    will-change: transform, opacity;
    pointer-events: none;
}

.fx-rocket--1{
    top: 31%;
}

.fx-rocket--2{
    top: 68%;
    opacity: .11;
    transform: rotate(18deg) scale(calc(var(--rocket-scale, .85) * .82));
}

.fx-rocket-svg{
    position: relative;
    z-index: 1;
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
    filter: drop-shadow(0 0 5px rgba(124,131,255,.8));
}

.fx-rocket-body{
    fill: rgba(222,229,255,.82);
    stroke: rgba(255,255,255,.8);
    stroke-width: .8;
}

.fx-rocket-window{
    fill: #7c83ff;
    stroke: rgba(255,255,255,.8);
    stroke-width: 1;
}

.fx-rocket-fin{
    fill: rgba(139,92,246,.72);
}

.fx-rocket-flame{
    fill: #c8fff0;
    filter: drop-shadow(0 0 5px rgba(200,255,240,.95));
}

.fx-rocket-trail{
    position: absolute;
    z-index: 0;
    top: 50%;
    right: 76%;
    width: 54px;
    height: 2px;
    transform: translateY(-50%);
    border-radius: 50%;
    background: linear-gradient(90deg, transparent, rgba(124,131,255,.78));
    box-shadow: 0 0 9px rgba(124,131,255,.55);
    opacity: .75;
}



.fx-star{
    position: absolute;
    z-index: 0;
    display: block;
    width: var(--star-size, 2px);
    height: var(--star-size, 2px);
    left: var(--star-x, 50%);
    top: var(--star-y, 50%);
    border-radius: 50%;
    background: var(--star-color, #fff);
    box-shadow:
        0 0 6px 1px var(--star-glow, rgba(196,202,255,.75)),
        0 0 18px 4px var(--star-glow-soft, rgba(124,131,255,.22));
    opacity: var(--star-opacity, .65);
    animation: fxStarBlink var(--star-speed, 3.8s) ease-in-out var(--star-delay, 0s) infinite;
    will-change: opacity, transform;
}

.fx-star--bright{
    width: var(--star-size, 3px);
    height: var(--star-size, 3px);
    --star-opacity: .9;
    --star-glow: rgba(255,255,255,.95);
    --star-glow-soft: rgba(139,92,246,.42);
}

/* Sparse streaks add a sense of depth without competing with the content. */
.fx-shooting-star{
    position: absolute;
    z-index: 0;
    top: var(--streak-y, 20%);
    left: var(--streak-x, 10%);
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 8px 2px rgba(255,255,255,.9), 0 0 24px 8px rgba(124,131,255,.42);
    opacity: 0;
    transform: rotate(28deg) translate3d(0, 0, 0);
    animation: fxShootingStar var(--streak-speed, 11s) ease-in var(--streak-delay, 4s) infinite;
    will-change: transform, opacity;
}

.fx-shooting-star::after{
    content: '';
    position: absolute;
    right: 5px;
    top: 2px;
    width: 76px;
    height: 2px;
    border-radius: 999px;
    background: linear-gradient(90deg, rgba(255,255,255,.8), transparent);
    filter: blur(.4px);
}

/* ---------- MOUSE PARALLAX (generic, vars read by keyframes too) ---------- */

.fx-active [data-parallax]{
    transform: translate3d(var(--par-x,0px), var(--par-y,0px), var(--par-z,0px));
    transition: transform .7s var(--fx-ease);
}

/* ============ SHARED 3D RECIPE ============
   One transform chain for every enhanced element. The JS layer only
   writes custom properties:
     --rx/--ry        pointer tilt (deg)
     --gx/--gy        pointer drift for the shadow (unitless)
     --par-x/--par-y  mouse parallax (px)
     --rv-y/--rv-rx   reveal offset (px/deg)
     --reveal-delay   stagger (s) */

.fx-active .service-card,
.fx-active .blog-card,
.fx-active .why-card,
.fx-active .testimonial-card,
.fx-active .footer-contact-card,
.fx-active .portfolio-content,
.fx-active .faq-item,
.fx-active .cta-box,
.fx-active .dashboard-card,
.fx-active .section-title:not([data-aos]),
.fx-active .why-content,
.fx-active .faq-content{
    position: relative;
    transform:
        perspective(var(--fx-perspective))
        translate3d(var(--par-x,0px), calc(var(--par-y,0px) + var(--rv-y,0px)), 0)
        rotateX(calc(var(--rx,0deg) + var(--rv-rx,0deg)))
        rotateY(var(--ry,0deg))
        scale(var(--tilt-scale,1));
    transition:
        transform .85s var(--fx-ease) var(--reveal-delay,0s),
        opacity .85s var(--fx-ease) var(--reveal-delay,0s),
        box-shadow .5s ease,
        border-color .5s ease;
}

/* Hidden until IntersectionObserver adds .is-visible.
   Only while .fx-active exists (JS on) — no JS, nothing hidden. */

.fx-active .service-card:not(.is-visible),
.fx-active .blog-card:not(.is-visible),
.fx-active .why-card:not(.is-visible),
.fx-active .testimonial-card:not(.is-visible),
.fx-active .footer-contact-card:not(.is-visible),
.fx-active .portfolio-content:not(.is-visible),
.fx-active .faq-item:not(.is-visible),
.fx-active .cta-box:not(.is-visible),
.fx-active .section-title:not([data-aos]):not(.is-visible),
.fx-active .why-content:not(.is-visible),
.fx-active .faq-content:not(.is-visible){
    opacity: 0;
    --rv-y: 70px;
    --rv-rx: 9deg;
}

/* keeps the hero zoom through the shared recipe */
.fx-active .dashboard-card{
    --tilt-scale: 1.08;
}

/* fast tracking while the pointer is actively moving */
.fx-active .fx-tilting{
    transition:
        transform .12s linear,
        opacity .85s var(--fx-ease) var(--reveal-delay,0s),
        box-shadow .5s ease,
        border-color .5s ease;
  will-change: transform;
}

/* ============ DEPTH SHADOW (follows the pointer) ============ */

.fx-active .service-card,
.fx-active .blog-card,
.fx-active .why-card,
.fx-active .testimonial-card,
.fx-active .footer-contact-card,
.fx-active .cta-box,
.fx-active .faq-item,
.fx-active .dashboard-card{
    box-shadow:
        calc(var(--gx,0) * -20px) calc(26px + var(--gx,0) * -8px + var(--gy,0) * -14px) 46px -20px var(--fx-depth),
        calc(var(--gx,0) * -46px) calc(60px + var(--gx,0) * -14px + var(--gy,0) * -26px) 96px -44px rgba(3,6,20,.55);
}

/* ============ SPOTLIGHT GLARE (span injected by 3d.js) ============
   The recipe's transform gives every card its own stacking context, so
   a z-index:-1 child paints above the card background but below text. */

.fx-active .tilt-glare{
    position: absolute;
    inset: 0;
    border-radius: inherit;
    z-index: -1;
    pointer-events: none;
    opacity: 0;
    transition: opacity .4s ease;
    background: radial-gradient(440px circle at var(--mx,50%) var(--my,50%),
        rgba(255,255,255,.14), rgba(124,131,255,.07) 42%, transparent 66%);
}

.fx-active .service-card:hover .tilt-glare,
.fx-active .blog-card:hover .tilt-glare,
.fx-active .why-card:hover .tilt-glare,
.fx-active .testimonial-card:hover .tilt-glare,
.fx-active .footer-contact-card:hover .tilt-glare,
.fx-active .cta-box:hover .tilt-glare,
.fx-active .faq-item:hover .tilt-glare,
.fx-active .dashboard-card:hover .tilt-glare{
    opacity: 1;
}

/* ============ HOVER LIFTS (re-declared: the recipe overrides the
   old transform-based hovers in components.css) ============ */

.fx-active .service-card:hover,
.fx-active .blog-card:hover{
    --rv-y: -12px;
    border-color: rgba(124,131,255,.42);
}

.fx-active .why-card:hover,
.fx-active .testimonial-card:hover,
.fx-active .footer-contact-card:hover{
    --rv-y: -8px;
    border-color: rgba(124,131,255,.42);
}

.fx-active .cta-box:hover{
    --rv-y: -8px;
}

.fx-active .faq-item:hover{
    --rv-y: -6px;
    --rv-rx: -1.5deg;
    border-color: rgba(124,131,255,.4);
}

.fx-active .faq-item.active:hover{
    --rv-y: -4px;
    --rv-rx: 0deg;
}

/* the icon spin finally glides instead of snapping */
.fx-active .service-card .service-icon{
    transition: transform .7s var(--fx-ease), box-shadow .5s ease;
}

.fx-active .service-card:hover .service-icon{
    box-shadow: 0 14px 34px -14px var(--fx-glow);
}

/* ============ BUTTONS: SIMPLE HOVER ============
   No shadows, lifts, press scale, shine sweep, fill effect or
   magnetic pull — hover is only a quiet colour/background swap. */

.fx-active .btn-primary-custom,
.fx-active .btn-outline-custom{
    transform: none;
    box-shadow: none;
    transition:
        background .25s ease,
        color .25s ease,
        border-color .25s ease;
}

.fx-active .btn-primary-custom:active,
.fx-active .btn-outline-custom:active{
    transform: none;
    box-shadow: none;
}

/* strip the component-level motion as well */
.fx-active .btn-primary-custom::before{
    display: none;
}

.fx-active .btn-primary-custom i{
    transition: none;
}

.fx-active .btn-primary-custom:hover i{
    transform: none;
}

/* ============ NAVIGATION ============ */

.fx-active .navbar-custom{
    transition: background .4s ease, box-shadow .4s ease, border-color .4s ease;
    box-shadow: 0 18px 40px -32px rgba(3,6,20,.9);
}

.fx-active .main-header.scrolled .navbar-custom{
    box-shadow:
        0 24px 50px -30px rgba(3,6,20,.95),
        0 0 0 1px rgba(124,131,255,.16);
}

.fx-active .nav-menu li a{
    display: inline-block;
    transition: transform .35s var(--fx-ease), text-shadow .35s ease, color .3s ease;
}

.fx-active .nav-menu li a:hover{
    transform: translateY(-3px);
    text-shadow: 0 0 18px rgba(124,131,255,.9);
}

/* ============ SECTION BADGE + GRADIENT TEXT ============ */

.fx-active .section-subtitle{
    display: inline-block;
    position: relative;
    overflow: hidden;
    transition: box-shadow .4s ease, transform .4s var(--fx-ease);
    animation: fxBadgeBreathe 4.5s ease-in-out infinite;
}

.fx-active .section-subtitle::after{
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-image: linear-gradient(100deg,
        transparent 35%, rgba(255,255,255,.45) 50%, transparent 65%);
    background-size: 300% 100%;
    background-position: 140% 0;
    transition: background-position .8s var(--fx-ease);
    pointer-events: none;
}

.fx-active .section-title:hover .section-subtitle,
.fx-active .why-content:hover .section-subtitle,
.fx-active .faq-content:hover .section-subtitle,
.fx-active .cta-content:hover .section-subtitle{
    transform: translateY(-3px);
    box-shadow: 0 14px 30px -16px var(--fx-glow);
}

.fx-active .section-title:hover .section-subtitle::after,
.fx-active .why-content:hover .section-subtitle::after,
.fx-active .faq-content:hover .section-subtitle::after,
.fx-active .cta-content:hover .section-subtitle::after{
    background-position: -40% 0;
}

.fx-active .text-gradient{
    background-size: 220% 220%;
    animation: fxGradientShift 7s ease infinite;
}

/* ============ TECH MARQUEE: SEAMLESS 3D RAIL ============
   Components.css animates translateX(-50%) across a gap:80px flex row —
   the gaps after the last item make that hop land half a slot off, so
   the loop visibly jumps. Each gap becomes an in-slot margin instead:
   one image = one exact slot, -50% always lands on an identical slot. */

.fx-active .tech-slider{
    perspective: 1100px;
    perspective-origin: 50% 50%;
}

.fx-active .tech-track{
    gap: 0;
    transform-style: preserve-3d;
    animation: fxScrollTech3d 50s linear infinite;
}

.fx-active .tech-track img{
    margin-right: 80px;
    transition: transform .35s var(--fx-ease), filter .35s ease;
}

.fx-active .tech-track img:hover{
    transform: translateY(-8px) translateZ(48px) scale(1.08);
    filter: drop-shadow(0 14px 26px rgba(124,131,255,.5));
}

@media (max-width: 991px){
    .fx-active .tech-track img{ margin-right: 50px; }
}

/* ============ HERO 3D SCENE ============ */

.fx-active .hero-image-wrapper{
    perspective: 1500px;
    perspective-origin: 50% 45%;
}

/* float loops rewritten to read the JS parallax vars, so the CSS bob
   and the mouse depth compose on the same element */
.fx-active .floating-card-1{
    animation: fxFloatA 4.5s ease-in-out infinite;
    --par-z: 40px;
    box-shadow:
        0 24px 50px -24px rgba(3,6,20,.9),
        0 0 0 1px rgba(124,131,255,.14);
}

.fx-active .floating-card-2{
    animation: fxFloatB 5.5s ease-in-out infinite;
    --par-z: 80px;
    box-shadow:
        0 28px 56px -24px rgba(3,6,20,.9),
        0 0 0 1px rgba(124,131,255,.14);
}

/* ---------- rotating tech cube (markup added next to the hero art) ---------- */

.hero-cube-scene{
    position: absolute;
    top: -9%;
    right: -3%;
    width: 112px;
    height: 112px;
    perspective: 700px;
    z-index: 3;
}

.hero-cube{
    position: relative;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    animation: fxCubeSpin 20s linear infinite;
}

.cube-face{
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    border: 1px solid rgba(124,131,255,.4);
    border-radius: 18px;
    background: rgba(17,24,39,.75);
    backdrop-filter: blur(8px);
    box-shadow: inset 0 0 24px rgba(124,131,255,.25);
}

.cube-face img{
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    filter: drop-shadow(0 6px 14px rgba(0,0,0,.5));
}

.cube-face-front  { transform: rotateY(  0deg) translateZ(56px); }
.cube-face-back   { transform: rotateY(180deg) translateZ(56px); }
.cube-face-right  { transform: rotateY( 90deg) translateZ(56px); }
.cube-face-left   { transform: rotateY(-90deg) translateZ(56px); }
.cube-face-top    { transform: rotateX( 90deg) translateZ(56px); }
.cube-face-bottom { transform: rotateX(-90deg) translateZ(56px); }

/* ---------- hero slider: the missing slide-out / slide-in styles
   (the inline slider script toggles these classes but no CSS defined
   them before, so images snapped instantly) ---------- */

.fx-active #heroSliderImage{
    transform-origin: 50% 75%;
    backface-visibility: hidden;
    transition: opacity .5s var(--fx-ease), transform .5s var(--fx-ease), filter .5s ease;
}

.fx-active #heroSliderImage.slide-out{
    opacity: 0;
    transform: translate3d(0, -26px, -70px) rotateX(12deg);
    filter: blur(6px);
}

.fx-active #heroSliderImage.slide-in{
    animation: fxSlideIn .8s var(--fx-ease) both;
}

/* ============ PORTFOLIO FRAMES ============
   AOS owns the entrance transform on .portfolio-image (inline duration),
   so depth here comes from hover tilt + a floor shadow. */

.fx-active .portfolio-image{
    transition: transform .5s var(--fx-ease), box-shadow .5s ease;
    box-shadow: 0 30px 70px -40px rgba(3,6,20,.9);
}

.fx-active .portfolio-image:hover{
    transform: perspective(1400px) translateY(-10px) rotateY(-4deg) rotateX(2deg);
    box-shadow:
        -40px 44px 80px -40px rgba(3,6,20,.95),
        0 0 0 1px rgba(124,131,255,.25);
}

.fx-active .portfolio-image img{
    transition: transform .6s var(--fx-ease);
}

.fx-active .portfolio-image:hover img{
    transform: scale(1.05);
}

.fx-active .portfolio-features li{
    transition: transform .35s var(--fx-ease), color .35s ease;
}

.fx-active .portfolio-features li:hover{
    transform: translateX(6px);
    color: #fff;
}

/* ============ WHY SECTION DEPTH ============ */

.fx-active .why-feature{
    transition: transform .4s var(--fx-ease);
}

.fx-active .why-feature:hover{
    transform: translateX(8px);
}

.fx-active .why-icon{
    transition: box-shadow .4s ease, background .4s ease;
}

.fx-active .why-feature:hover .why-icon{
    box-shadow: 0 14px 32px -14px var(--fx-glow);
    background: rgba(124,131,255,.22);
}

/* ============ CTA: ROTATING CONIC RING + BREATHING GLOW ============ */

@property --cta-angle{
    syntax: '<angle>';
    inherits: false;
    initial-value: 0deg;
}

.fx-active .cta-box::after{
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    border-radius: inherit;
    padding: 1.5px;
    --cta-angle: 0deg;
    background: conic-gradient(from var(--cta-angle, 0deg),
        transparent 0 58%,
        rgba(124,131,255,.95) 74%,
        rgba(139,92,246,.95) 88%,
        transparent 97%);
    -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, linear-gradient(#000 0 0);
            mask-composite: exclude;
    animation: fxSpinAngle 6s linear infinite;
}

.fx-active .cta-glow{
    animation: fxBreathe 7s ease-in-out infinite;
}

/* ============ FAQ: DEPTH ACCORDION ============ */

.fx-active .faq-item{
    transform-origin: 50% 0%;
}

.fx-active .faq-item.active{
    border-color: rgba(124,131,255,.45);
    box-shadow: 0 28px 60px -34px rgba(3,6,20,.95);
}

.fx-active .faq-question h5{
    transition: transform .4s var(--fx-ease), color .35s ease;
}

.fx-active .faq-item:hover .faq-question h5{
    transform: translateX(6px);
    color: #C7D2FE;
}

/* the existing .faq-item.active span rotate(45deg) keeps ownership of
   the transform — only add the glide + glow */
.fx-active .faq-question span{
    transition: transform .45s var(--fx-ease), color .35s ease, text-shadow .35s ease;
}

.fx-active .faq-item.active .faq-question span{
    color: #7C83FF;
    text-shadow: 0 0 18px rgba(124,131,255,.9);
}

.fx-active .faq-answer{
    transition: max-height .5s var(--fx-ease), opacity .5s ease;
    opacity: 0;
}

.fx-active .faq-item.active .faq-answer{
    opacity: 1;
}

/* ============ BLOG: DEPTH HOVERS ============ */

.fx-active .blog-card img{
    transition: transform .6s var(--fx-ease), filter .6s ease;
}

.fx-active .blog-card:hover img{
    transform: scale(1.07);
    filter: saturate(1.15);
}

/* ============ FOOTER DEPTH ============ */

.fx-active .footer-socials{
    perspective: 800px;
}

.fx-active .footer-socials a{
    transition: transform .35s var(--fx-ease), background .35s ease, box-shadow .35s ease;
}

.fx-active .footer-socials a:hover{
    transform: translateY(-7px) rotateX(16deg);
    box-shadow: 0 16px 30px -16px var(--fx-glow);
}

.fx-active .footer-column ul li a{
    display: inline-block;
    transition: transform .3s var(--fx-ease), color .3s ease;
}

.fx-active .footer-column ul li a:hover{
    transform: translateX(6px);
    color: #fff;
}

/* children of the card (the slider image) get their own depth stage;
   independent of the card's own recipe transform */
.fx-active .dashboard-card{
    perspective: 1400px;
}

/* ============================================================
   KEYFRAMES
   ============================================================ */

@keyframes fxGridScroll{
    0%  { transform: rotateX(74deg) translate3d(0, 0, 0); }
    100%{ transform: rotateX(74deg) translate3d(0, 70px, 0); }
}

@keyframes fxAuroraDrift{
    0%  { transform: translateX(-50%) translateY(0) scale(1); }
    50% { transform: translateX(-53%) translateY(4vh) scale(1.06); }
    100%{ transform: translateX(-47%) translateY(-2vh) scale(1.03); }
}

@keyframes fxOrbFloat{
    0%, 100%{
        transform: translate3d(var(--par-x,0px), var(--par-y,0px), 0);
    }
    50%{
        transform: translate3d(var(--par-x,0px), calc(var(--par-y,0px) - 34px), 0);
    }
}

@keyframes fxFloatA{
    0%, 100%{
        transform: translate3d(var(--par-x,0px), var(--par-y,0px), var(--par-z,40px));
    }
    50%{
        transform: translate3d(var(--par-x,0px), calc(var(--par-y,0px) - 16px), var(--par-z,40px));
    }
}

@keyframes fxFloatB{
    0%, 100%{
        transform: translate3d(var(--par-x,0px), var(--par-y,0px), var(--par-z,80px));
    }
    50%{
        transform: translate3d(var(--par-x,0px), calc(var(--par-y,0px) - 14px), var(--par-z,80px));
    }
}

@keyframes fxCubeSpin{
    0%  { transform: rotateX(-18deg) rotateY(0deg); }
    100%{ transform: rotateX(-18deg) rotateY(360deg); }
}

/* rotateX runs first (local), then an exact -50% horizontal hop in
   parent space — with margin slots that lands on an identical slot */
@keyframes fxScrollTech3d{
    0%  { transform: translateX(0) rotateX(6deg); }
    100%{ transform: translateX(-50%) rotateX(6deg); }
}

@keyframes fxGradientShift{
    0%, 100%{ background-position: 0% 50%; }
    50%     { background-position: 100% 50%; }
}

@keyframes fxBadgeBreathe{
    0%, 100%{ transform: translateY(0); }
    50%     { transform: translateY(-4px); }
}

@keyframes fxSpinAngle{
    to{ --cta-angle: 360deg; }
}

@keyframes fxBreathe{
    0%, 100%{ transform: translate(-50%, -50%) scale(1);    opacity: .55; }
    50%     { transform: translate(-50%, -50%) scale(1.18); opacity: 1;   }
}

@keyframes fxSlideIn{
    0%  { opacity: 0; transform: translate3d(0, 44px, -110px) rotateX(18deg); filter: blur(8px); }
    100%{ opacity: 1; transform: translate3d(0, 0, 0) rotateX(0deg);          filter: blur(0);   }
}

@keyframes fxRocketFly{
    0%   { opacity: 0; transform: translate3d(0, 18px, 0) rotate(18deg) scale(var(--rocket-scale, .85)); }
    8%   { opacity: .16; }
    88%  { opacity: .12; }
    100% { opacity: 0; transform: translate3d(calc(100vw + 240px), -20px, 0) rotate(18deg) scale(var(--rocket-scale, .85)); }
}

@keyframes fxStarBlink{
    0%, 100%{ opacity: calc(var(--star-opacity, .65) * .42); transform: scale(.72); }
    42%     { opacity: var(--star-opacity, .65); transform: scale(1.08); }
    68%     { opacity: calc(var(--star-opacity, .65) * .58); transform: scale(.88); }
}

@keyframes fxShootingStar{
    0%, 72%{ opacity: 0; transform: rotate(28deg) translate3d(0, 0, 0); }
    74%    { opacity: .95; }
    82%    { opacity: .72; }
    91%, 100%{ opacity: 0; transform: rotate(28deg) translate3d(230px, 130px, 0); }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */

@media (max-width: 1199px){
    .hero-cube-scene{
        width: 92px;
        height: 92px;
        right: 0;
    }

    .cube-face-front  { transform: rotateY(  0deg) translateZ(46px); }
    .cube-face-back   { transform: rotateY(180deg) translateZ(46px); }
    .cube-face-right  { transform: rotateY( 90deg) translateZ(46px); }
    .cube-face-left   { transform: rotateY(-90deg) translateZ(46px); }
    .cube-face-top    { transform: rotateX( 90deg) translateZ(46px); }
    .cube-face-bottom { transform: rotateX(-90deg) translateZ(46px); }
}

@media (max-width: 991px){
    /* shallower reveal travel on small screens */
    .fx-active .service-card:not(.is-visible),
    .fx-active .blog-card:not(.is-visible),
    .fx-active .why-card:not(.is-visible),
    .fx-active .testimonial-card:not(.is-visible),
    .fx-active .footer-contact-card:not(.is-visible),
    .fx-active .portfolio-content:not(.is-visible),
    .fx-active .faq-item:not(.is-visible),
    .fx-active .cta-box:not(.is-visible),
    .fx-active .section-title:not([data-aos]):not(.is-visible),
    .fx-active .why-content:not(.is-visible),
    .fx-active .faq-content:not(.is-visible){
        --rv-y: 44px;
        --rv-rx: 6deg;
    }
}

@media (max-width: 767px){
    .hero-cube-scene{ display: none; }
    .fx-stage-grid{ display: none; }
    .fx-rocket{ display: none; }
    .fx-orb-1{ width: 80px; height: 80px; }
    .fx-orb-3{ display: none; }

    .fx-active .portfolio-image:hover{
        transform: perspective(1400px) translateY(-6px);
    }
}

@media (hover: none), (pointer: coarse){
    /* no spotlight glare without a real pointer */
    .fx-active .tilt-glare{
        display: none;
    }
}

/* ============================================================
   REDUCED MOTION — show everything, move nothing.
   The !important block neutralises hidden reveal states, hover lifts
   and pointer tilt in one place; JS also skips tilt/parallax
   and marks every reveal target visible on boot.
   ============================================================ */

@media (prefers-reduced-motion: reduce){

    .fx-active .service-card,
    .fx-active .blog-card,
    .fx-active .why-card,
    .fx-active .testimonial-card,
    .fx-active .footer-contact-card,
    .fx-active .portfolio-content,
    .fx-active .faq-item,
    .fx-active .cta-box,
    .fx-active .dashboard-card,
    .fx-active .section-title:not([data-aos]),
    .fx-active .why-content,
    .fx-active .faq-content{
        opacity: 1 !important;
        --rv-y: 0px !important;
        --rv-rx: 0deg !important;
        --rx: 0deg !important;
        --ry: 0deg !important;
        transition: none !important;
    }

    .fx-active .portfolio-image,
    .fx-active .btn-primary-custom,
    .fx-active .btn-outline-custom,
    .fx-active #heroSliderImage{
        transition: none !important;
    }

    .fx-active .portfolio-image:hover{
        transform: none !important;
    }

    .fx-active .btn-primary-custom,
    .fx-active .btn-outline-custom{
        transform: none !important;
        box-shadow: none;
    }

    .fx-stage,
    .hero-cube-scene{
        display: none;
    }

    .fx-active .tech-track,
    .fx-active .fx-rocket,
    .fx-active .section-subtitle,
    .fx-active .text-gradient,
    .fx-active .cta-glow,
    .fx-active .cta-box::after,
    .fx-active .floating-card-1,
    .fx-active .floating-card-2,
    #heroSliderImage.slide-in{
        animation: none !important;
    }
}