var svg = document.getElementById('svg');
var NS = 'http://www.w3.org/2000/svg';
function se(t){ return document.createElementNS(NS,t); }
function sa(e,o){ for (var k in o) e.setAttribute(k,o[k]); }
function R(a,b){ return a + Math.random()*(b-a); }
var GX=30, GY=18;
var W=300, H=200;
var BLOBS_CUR = [
{ x:0.3, y:0.35, amp:1, s:0.22 },
{ x:0.68, y:0.4, amp:0.85, s:0.2 },
{ x:0.5, y:0.75, amp:0.7, s:0.18 }
];
function measure(){
var r = svg.getBoundingClientRect();
W = Math.max(r.width,10); H = Math.max(r.height,10);
sa(svg,{ viewBox: '0 0 ' + W + ' ' + H });
}
function fieldAt(x,y,blobs){
var v=0;
for (var i=0;i<blobs.length;i++){
var b=blobs[i], dx=x-b.x, dy=y-b.y;
v += b.amp*Math.exp(-(dx*dx+dy*dy)/(2*b.s*b.s));
}
return v;
}
function lerpPt(x0,y0,v0,x1,y1,v1,th){
var t = (v1===v0) ? 0.5 : (th-v0)/(v1-v0);
t = Math.max(0,Math.min(1,t));
return { x: x0+(x1-x0)*t, y: y0+(y1-y0)*t };
}
function marchingSquares(field, th, toPx){
var segs=[];
for (var j=0;j<GY;j++){
for (var i=0;i<GX;i++){
var v00=field[j][i], v10=field[j][i+1], v11=field[j+1][i+1], v01=field[j+1][i];
var c00=v00>=th, c10=v10>=th, c11=v11>=th, c01=v01>=th;
var p00=toPx(i,j), p10=toPx(i+1,j), p11=toPx(i+1,j+1), p01=toPx(i,j+1);
var edges=[];
if (c00!==c10) edges.push({ side:'t', pt: lerpPt(p00.x,p00.y,v00,p10.x,p10.y,v10,th) });
if (c10!==c11) edges.push({ side:'r', pt: lerpPt(p10.x,p10.y,v10,p11.x,p11.y,v11,th) });
if (c01!==c11) edges.push({ side:'b', pt: lerpPt(p01.x,p01.y,v01,p11.x,p11.y,v11,th) });
if (c00!==c01) edges.push({ side:'l', pt: lerpPt(p00.x,p00.y,v00,p01.x,p01.y,v01,th) });
if (edges.length===2){ segs.push([edges[0].pt, edges[1].pt]); }
else if (edges.length===4){
var center=(v00+v10+v11+v01)/4;
var bySide={}; edges.forEach(function(e){ bySide[e.side]=e.pt; });
if (center>=th){ segs.push([bySide.t,bySide.l]); segs.push([bySide.r,bySide.b]); }
else { segs.push([bySide.t,bySide.r]); segs.push([bySide.l,bySide.b]); }
}
}
}
return segs;
}
function draw(){
svg.innerHTML = '';
var padL=6,padT=6, pw=W-12, ph=H-12;
var field=[];
for (var j=0;j<=GY;j++){
var row=[];
for (var i=0;i<=GX;i++) row.push(fieldAt(i/GX, j/GY, BLOBS_CUR));
field.push(row);
}
function toPx(gx,gy){ return { x: padL+(gx/GX)*pw, y: padT+(gy/GY)*ph }; }
var LEVELS=[0.15,0.3,0.45,0.6,0.75,0.9];
LEVELS.forEach(function(th,li){
var segs = marchingSquares(field, th, toPx);
if (!segs.length) return;
var d='';
segs.forEach(function(s){ d += 'M'+s[0].x.toFixed(1)+','+s[0].y.toFixed(1)+'L'+s[1].x.toFixed(1)+','+s[1].y.toFixed(1)+' '; });
var p = se('path');
sa(p,{ d:d, stroke:'var(--accent)', 'stroke-width':1.4, fill:'none', 'stroke-opacity': 0.35+0.55*(li/(LEVELS.length-1)) });
svg.appendChild(p);
});
}
function animate(target){
var from = BLOBS_CUR.map(function(b){ return { x:b.x, y:b.y, amp:b.amp, s:b.s }; });
var t0 = performance.now();
function step(t){
var p = Math.min(1,(t-t0)/900);
var e = 1-Math.pow(1-p,3);
BLOBS_CUR = from.map(function(b,i){
return { x:b.x+(target[i].x-b.x)*e, y:b.y+(target[i].y-b.y)*e, amp:b.amp+(target[i].amp-b.amp)*e, s:b.s+(target[i].s-b.s)*e };
});
draw();
if (p<1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
function nextBlobs(){
return [
{ x:R(0.15,0.4), y:R(0.15,0.45), amp:R(0.7,1.1), s:R(0.16,0.24) },
{ x:R(0.55,0.85), y:R(0.2,0.55), amp:R(0.6,1), s:R(0.14,0.22) },
{ x:R(0.3,0.7), y:R(0.6,0.88), amp:R(0.5,0.95), s:R(0.14,0.22) }
];
}
new ResizeObserver(function(){ measure(); draw(); }).observe(svg);
measure();
draw();
animate(nextBlobs());
setInterval(function(){ animate(nextBlobs()); }, 3800);