.wrap{position:relative;width:100%;height:100%}
#cv{position:absolute;inset:0;width:100%;height:100%}
.panel{position:absolute;left:10px;right:10px;bottom:10px;z-index:2;padding:7px 10px;border-radius:10px;
background:rgba(13,13,18,0.55);backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,0.15);
display:flex;align-items:center;gap:8px;font-size:11px;font-weight:700;color:#f1f0ec;flex-wrap:wrap}
.bar{flex:1;min-width:60px;height:5px;border-radius:99px;background:rgba(255,255,255,0.15);overflow:hidden}
.fill{height:100%;width:0;background:var(--accent);transition:width .08s linear}
const cv = document.getElementById('cv'), ctx = cv.getContext('2d');
const val = document.getElementById('val'), fill = document.getElementById('fill');
function fit() { const dpr = Math.min(devicePixelRatio || 1, 2); cv.width = innerWidth * dpr; cv.height = innerHeight * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); }
addEventListener('resize', fit); fit();
function mulberry32(a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }
function lerp(a, b, t) { return a + (b - a) * t; }
function render(s) {
const w = innerWidth, h = innerHeight;
ctx.clearRect(0, 0, w, h);
const hue = lerp(200, 15, s);
const g = ctx.createLinearGradient(0, 0, 0, h);
g.addColorStop(0, 'hsl(' + hue + ' 55% ' + lerp(60, 45, s) + '%)'); g.addColorStop(1, 'hsl(' + (hue + 30) + ' 40% 30%)');
ctx.fillStyle = g; ctx.fillRect(0, 0, w, h);
const r = mulberry32(4);
for (let l = 0; l < 2; l++) {
ctx.beginPath(); ctx.moveTo(0, h);
const jitter = r() * 0.12 * s;
for (let i = 0; i <= 6; i++) { const x = w * i / 6; const y = h * (0.55 + l * 0.15) - h * (0.06 + jitter) * (1 + Math.sin(i + s * 6)); ctx.lineTo(x, y); }
ctx.lineTo(w, h); ctx.closePath();
ctx.fillStyle = 'hsl(' + lerp(150, 340, s) + ' 40% ' + (20 + l * 12) + '%)'; ctx.fill();
}
ctx.beginPath(); ctx.arc(lerp(w * 0.75, w * 0.3, s), lerp(h * 0.22, h * 0.35, s), Math.min(w, h) * 0.07, 0, Math.PI * 2);
ctx.fillStyle = 'hsl(50 90% 75%)'; ctx.fill();
}
let s = 0, dir = 1;
setInterval(() => {
render(s); val.textContent = s.toFixed(2); fill.style.width = (s * 100) + '%';
s += dir * 0.01;
if (s >= 1) { s = 1; dir = -1; } if (s <= 0) { s = 0; dir = 1; }
}, 60);
render(0);