/* Reflow the schematic while keeping the mapped candidate region at its true area share. */ (function () { const svg = document.getElementById('melon-variants'); if (!svg) return; const dots = Array.from(svg.querySelectorAll('.snp-dot')); const candidateRegion = svg.querySelector('.candidate-region'); const callout = svg.querySelector('.causal-callout'); let previous; const layout = () => { const columns = svg.clientWidth < 480 ? 43 : 86; if (columns === previous) return; previous = columns; const rows = Math.ceil(dots.length / columns); const gridWidth = columns * 12, gridHeight = rows * 8; const width = gridWidth + 24, height = gridHeight + 24; const area = gridWidth * gridHeight * 3061 / 47492; const regionWidth = Math.sqrt(area * 5), regionHeight = area / regionWidth; const rx = (width - regionWidth) / 2, ry = (height - regionHeight) / 2; svg.setAttribute('viewBox', `0 0 ${width} ${height}`); Object.entries({ x: rx, y: ry, width: regionWidth, height: regionHeight }).forEach(([key, value]) => candidateRegion.setAttribute(key, value)); dots.forEach((dot, i) => { const x = 18 + i % columns * 12, y = 16 + Math.floor(i / columns) * 8; dot.setAttribute('cx', x); dot.setAttribute('cy', y); dot.classList.toggle('is-candidate', x >= rx && x <= rx + regionWidth && y >= ry && y <= ry + regionHeight); }); const x = 18 + Math.floor(columns / 2) * 12, y = 16 + Math.floor(rows / 2) * 8; callout.querySelectorAll('circle').forEach(circle => { circle.setAttribute('cx', x); circle.setAttribute('cy', y); }); }; new ResizeObserver(layout).observe(svg); layout(); })();