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 LABELS = ['A','B','C','D','E','F','G'];
var COLORS = ['var(--accent)','var(--viz-4)','var(--accent-3)','var(--viz-5)'];
var vals = LABELS.map(function(){ return R(8,42); });
var W=300, H=200;
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 worstRatio(row, side){
var sum=0, max=-Infinity, min=Infinity;
row.forEach(function(v){ sum+=v; if (v>max) max=v; if (v<min) min=v; });
var s2=side*side, sum2=sum*sum;
return Math.max((s2*max)/sum2, sum2/(s2*min));
}
function squarify(list, x, y, w, h, out){
if (!list.length) return;
if (list.length===1){ out.push({ item:list[0], x:x, y:y, w:w, h:h }); return; }
var side = Math.min(w,h);
var row = [list[0].area];
var i = 1;
while (i<list.length){
var next = row.concat([list[i].area]);
if (worstRatio(next,side) <= worstRatio(row,side)) { row=next; i++; } else break;
}
var rowSum = row.reduce(function(a,b){ return a+b; },0);
if (w>=h){
var colW = rowSum/h, yy=y;
for (var k=0;k<row.length;k++){ var rh=row[k]/colW; out.push({item:list[k],x:x,y:yy,w:colW,h:rh}); yy+=rh; }
squarify(list.slice(row.length), x+colW, y, w-colW, h, out);
} else {
var rowH = rowSum/w, xx=x;
for (var k2=0;k2<row.length;k2++){ var rw=row[k2]/rowH; out.push({item:list[k2],x:xx,y:y,w:rw,h:rowH}); xx+=rw; }
squarify(list.slice(row.length), x, y+rowH, w, h-rowH, out);
}
}
function computeRects(valsArr){
var padL=6, padR=6, padT=6, padB=6;
var pw = W-padL-padR, ph = H-padT-padB;
var total = valsArr.reduce(function(a,b){ return a+b; },0);
var items = LABELS.map(function(l,i){ return { label:l, color:COLORS[i%4], area:(valsArr[i]/total)*pw*ph }; })
.sort(function(a,b){ return b.area-a.area; });
var out = [];
squarify(items, padL, padT, pw, ph, out);
var map = {};
out.forEach(function(rc){ map[rc.item.label] = { x:rc.x, y:rc.y, w:rc.w, h:rc.h, color:rc.item.color, label:rc.item.label }; });
return map;
}
function drawFrom(map){
svg.innerHTML = '';
var fs = Math.max(8, Math.min(13, W/70));
LABELS.forEach(function(l){
var rc = map[l];
var rect = se('rect');
sa(rect,{ x:rc.x+1, y:rc.y+1, width:Math.max(rc.w-2,0), height:Math.max(rc.h-2,0), rx:3, fill:rc.color });
svg.appendChild(rect);
if (rc.w>26 && rc.h>17){
var t = se('text');
sa(t,{ x:rc.x+6, y:rc.y+fs+4, fill:'#fff', 'font-size':fs, 'font-weight':700 });
t.textContent = l;
svg.appendChild(t);
}
});
}
var curMap = computeRects(vals);
function draw(){ curMap = computeRects(vals); drawFrom(curMap); }
function animateTo(target){
var fromMap = curMap;
var toMap = computeRects(target);
var t0 = performance.now();
function step(t){
var p = Math.min(1,(t-t0)/800);
var e = 1-Math.pow(1-p,3);
var mid = {};
LABELS.forEach(function(l){
var f=fromMap[l], to=toMap[l];
mid[l] = { x:f.x+(to.x-f.x)*e, y:f.y+(to.y-f.y)*e, w:f.w+(to.w-f.w)*e, h:f.h+(to.h-f.h)*e, color:to.color, label:l };
});
curMap = mid;
drawFrom(mid);
if (p<1) requestAnimationFrame(step); else { vals = target; curMap = toMap; }
}
requestAnimationFrame(step);
}
new ResizeObserver(function(){ measure(); draw(); }).observe(svg);
measure();
draw();
setInterval(function(){
animateTo(LABELS.map(function(){ return R(6,44); }));
}, 3800);