.lane-label{position:absolute;left:6%;font:700 clamp(10px,2.8vmin,13px)/1 ui-monospace,monospace;color:var(--muted);z-index:2}
.l1{top:12%}
.l2{top:56%}
#sc{position:absolute;inset:0;width:100%;height:100%;display:block}
const canvas = document.getElementById('sc');
const ctx = canvas.getContext('2d');
const cs = getComputedStyle(document.documentElement);
function col(name, fb) { const v = cs.getPropertyValue(name).trim(); return v || fb; }
const MUTED = col('--muted', '#6b6b76');
const ACCENT = col('--accent', '#5b5bf7');
const ACCENT2 = col('--accent-2', '#f25c8a');
let w = 0, h = 0;
function resize() {
const dpr = Math.min(devicePixelRatio || 1, 2);
w = innerWidth; h = innerHeight;
canvas.width = w * dpr; canvas.height = h * dpr;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
addEventListener('resize', resize);
resize();
function ball(x, y, r, color, alpha) {
ctx.globalAlpha = alpha === undefined ? 1 : alpha;
ctx.beginPath(); ctx.arc(x, y, Math.max(r, 1), 0, Math.PI * 2);
ctx.fillStyle = color; ctx.fill(); ctx.globalAlpha = 1;
}
const DUR = 3200;
const startT = performance.now();
function loop(now) {
const t = ((now - startT) % DUR) / DUR;
ctx.clearRect(0, 0, w, h);
const y1 = h * 0.38, y2 = h * 0.78;
const r = h * 0.05;
for (let k = 6; k >= 1; k--) {
const tt = ((t - k * 0.025) + 1) % 1;
const ex = w * 0.1 + tt * w * 0.75;
const ey = y1 + Math.sin(tt * 16) * h * 0.09;
ball(ex, ey, r * 0.8, ACCENT, 0.08 * (7 - k));
}
const x1 = w * 0.1 + t * w * 0.75;
ball(x1, y1 + Math.sin(t * 16) * h * 0.09, r, ACCENT);
const poses = [0.14, 0.4, 0.62, 0.86];
for (let i = 0; i < poses.length; i++) {
ctx.fillStyle = MUTED; ctx.globalAlpha = 0.4;
ctx.fillRect(w * poses[i] - 3, y2 - 3, 6, 6);
ctx.globalAlpha = 1;
}
const idx = Math.min(Math.floor(t * poses.length), poses.length - 1);
ball(w * poses[idx], y2, r * 1.05, ACCENT2);
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);