.fx-dot{position:absolute;left:0;top:0;width:12px;height:12px;margin:-6px 0 0 -6px;border-radius:50%;
background:var(--accent);box-shadow:0 0 0 5px color-mix(in srgb,var(--accent) 18%,transparent),0 2px 6px rgba(0,0,0,.3);
pointer-events:none;z-index:9999;transition:opacity .25s}
.snap{position:absolute;inset:0;display:flex;gap:12px;overflow-x:auto;overflow-y:hidden;
scroll-snap-type:x mandatory;padding:0 40%;align-items:center;cursor:grab;scrollbar-width:none}
.snap::-webkit-scrollbar{display:none}
.scard{flex:0 0 auto;width:min(46%,120px);aspect-ratio:1/1;border-radius:16px;scroll-snap-align:center;
display:grid;place-items:center;font-size:clamp(16px,5vmin,22px);font-weight:800;color:#fff;
background:linear-gradient(135deg,var(--accent),var(--accent-2))}
.scard:nth-child(even){background:linear-gradient(135deg,var(--accent-3),var(--accent))}
const fxDot=document.createElement('div');fxDot.className='fx-dot';document.body.appendChild(fxDot);
let fxAuto=true,fxX=innerWidth/2,fxY=innerHeight/2;
function fxHide(){fxDot.style.opacity='0';}
addEventListener('pointerdown',()=>{fxAuto=false;fxHide();},{capture:true});
addEventListener('pointermove',e=>{fxAuto=false;fxHide();fxX=e.clientX;fxY=e.clientY;},{capture:true});
function fxWalk(x,y,ms){
return new Promise(res=>{
const sx=fxX,sy=fxY,start=performance.now();
function step(now){
if(!fxAuto)return res();
const p=Math.min(1,(now-start)/ms),e=1-Math.pow(1-p,3);
fxX=sx+(x-sx)*e;fxY=sy+(y-sy)*e;
fxDot.style.transform='translate('+fxX+'px,'+fxY+'px)';
if(p<1)requestAnimationFrame(step);else res();
}
requestAnimationFrame(step);
});
}
function fxWait(ms){
return new Promise(res=>{
const start=performance.now();
function step(now){ if(!fxAuto)return res(); if(now-start<ms)requestAnimationFrame(step);else res(); }
requestAnimationFrame(step);
});
}
const snap=document.getElementById('snap');
addEventListener('wheel',()=>{fxAuto=false;fxHide();},{capture:true,passive:true});
addEventListener('touchstart',()=>{fxAuto=false;fxHide();},{capture:true,passive:true});
let dragging=false, dragStartX=0, dragStartScroll=0;
snap.addEventListener('pointerdown',e=>{
fxAuto=false; fxHide();
dragging=true; dragStartX=e.clientX; dragStartScroll=snap.scrollLeft;
snap.setPointerCapture(e.pointerId); snap.style.cursor='grabbing';
});
addEventListener('pointermove',e=>{ if(!dragging) return; snap.scrollLeft=dragStartScroll-(e.clientX-dragStartX); });
addEventListener('pointerup',()=>{ if(!dragging) return; dragging=false; snap.style.cursor='grab'; });
const cards=[...snap.querySelectorAll('.scard')];
async function autoSeq(){
let i=0;
while(fxAuto){
await fxWait(1500); if(!fxAuto) break;
i=(i+1)%cards.length;
cards[i].scrollIntoView({behavior:'smooth', inline:'center', block:'nearest'});
const r=snap.getBoundingClientRect();
fxY=r.top+r.height/2;
const steps=16;
for(let s=0;s<=steps;s++){
if(!fxAuto) break;
fxX=r.left+r.width*(0.7-0.4*(s/steps));
fxDot.style.transform='translate('+fxX+'px,'+fxY+'px)';
await new Promise(res=>requestAnimationFrame(res));
}
}
}
autoSeq();