/* web-fx: vanilla ports of MIT components from Magic UI (magicuidesign/magicui)
   and Motion Primitives (ibelick/motion-primitives). No dependencies.
   Licenses: MIT, (c) Magic UI and (c) 2024 ibelick. See LICENSES.md. */

/* border-beam: a light that runs around an element's border */
@property --fx-a{syntax:"<angle>";initial-value:0deg;inherits:false}
.fx-beam{position:relative;isolation:isolate}
.fx-beam::after{content:"";position:absolute;inset:0;border-radius:inherit;padding:var(--beam-w,1.5px);pointer-events:none;
  background:conic-gradient(from var(--fx-a),transparent 0 70%,var(--beam-from,#ffaa40) 82%,var(--beam-to,#9c40ff) 92%,transparent 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;
  animation:fx-spin var(--beam-dur,6s) linear infinite}
@keyframes fx-spin{to{--fx-a:360deg}}

/* marquee: <div class="fx-marquee"><div class="fx-track">items…</div></div> (fx.js duplicates the track) */
.fx-marquee{display:flex;overflow:hidden;gap:var(--gap,1rem);
  -webkit-mask:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);mask:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
.fx-track{display:flex;flex-shrink:0;gap:var(--gap,1rem);animation:fx-marq var(--dur,40s) linear infinite}
.fx-marquee.rev .fx-track{animation-direction:reverse}
.fx-marquee:hover .fx-track{animation-play-state:paused}
@keyframes fx-marq{to{transform:translateX(calc(-100% - var(--gap,1rem)))}}

/* progressive-blur: stacked backdrop blurs with staggered masks (fx.js builds layers) */
.fx-pblur{position:absolute;inset-inline:0;pointer-events:none;z-index:5}
.fx-pblur>i{position:absolute;inset:0}

/* magic-card: cursor-following glow on the border and surface */
.fx-card{position:relative;isolation:isolate;--mx:-999px;--my:-999px}
.fx-card::before{content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;pointer-events:none;z-index:2;
  background:radial-gradient(var(--glow-size,260px) circle at var(--mx) var(--my),var(--glow-from,#ff6a2b),var(--glow-to,#9c40ff),transparent 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude}
.fx-card::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:-1;
  background:radial-gradient(var(--glow-size,260px) circle at var(--mx) var(--my),var(--glow-fill,rgba(255,255,255,.06)),transparent 100%)}

/* orbit: children ride a circle. <div class="fx-orbit" style="--r:160px;--dur:30s"><span>…</span>…</div> */
.fx-orbit{position:absolute;inset:0;display:grid;place-items:center;pointer-events:none}
.fx-orbit>*{position:absolute;pointer-events:auto;animation:fx-orbit var(--dur,30s) linear infinite;
  transform:rotate(var(--ang,0deg)) translateY(calc(var(--r,160px) * -1)) rotate(calc(var(--ang,0deg) * -1))}
.fx-orbit.rev>*{animation-direction:reverse}
@keyframes fx-orbit{from{transform:rotate(var(--ang,0deg)) translateY(calc(var(--r,160px) * -1)) rotate(calc(var(--ang,0deg) * -1))}
  to{transform:rotate(calc(var(--ang,0deg) + 360deg)) translateY(calc(var(--r,160px) * -1)) rotate(calc((var(--ang,0deg) + 360deg) * -1))}}

/* spotlight: soft light under the cursor inside a container */
.fx-spot{position:relative;overflow:hidden}
.fx-spot>.fx-light{position:absolute;width:var(--spot,320px);aspect-ratio:1;border-radius:50%;pointer-events:none;opacity:0;transition:opacity .2s;
  background:radial-gradient(circle,var(--spot-c,rgba(255,255,255,.18)),transparent 70%);filter:blur(20px);transform:translate(-50%,-50%)}
.fx-spot:hover>.fx-light{opacity:1}

/* tilt: 3D tilt toward the cursor */
.fx-tilt{transform-style:preserve-3d;transition:transform .25s cubic-bezier(.2,.7,.2,1);will-change:transform}

/* shine: shimmer sweep across text */
.fx-shine{background:linear-gradient(110deg,currentColor 35%,var(--shine,#fff) 50%,currentColor 65%) 0 0/250% 100%;
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;animation:fx-shine 3.5s linear infinite}
@keyframes fx-shine{from{background-position:120% 0}to{background-position:-120% 0}}

/* blur-fade: reveal on scroll (fx.js adds .in) */
.fx-reveal{opacity:0;filter:blur(8px);transform:translateY(14px);transition:opacity .7s,filter .7s,transform .7s cubic-bezier(.2,.7,.2,1)}
.fx-reveal.in{opacity:1;filter:none;transform:none}

@media (prefers-reduced-motion:reduce){
  .fx-beam::after,.fx-track,.fx-orbit>*,.fx-shine{animation:none}
  .fx-reveal{opacity:1;filter:none;transform:none}
}
