With 100+ IPs in fixed INNER_HEIGHT=780, vertical step shrinks to ~5px. Labels (8px font) need ~12-14px and overlap badly.
Enforce a minimum vertical spacing per IP. When the required height exceeds INNER_HEIGHT, expand the SVG. The #chart-container already has overflow: auto so scrolling works automatically.
MIN_IP_SPACING = 14 (px) — added to src/config/constants.js
Add MIN_IP_SPACING = 14 export.
Add MIN_IP_SPACING to the constants import.
Current:
const step = Math.min((INNER_HEIGHT - 25) / (sortedIps.length + 1), 15);Change to:
const step = Math.max(MIN_IP_SPACING, Math.min((INNER_HEIGHT - 25) / (sortedIps.length + 1), 15));
const dynamicInnerHeight = Math.max(INNER_HEIGHT, 12 + sortedIps.length * step + 25);Then update SVG height:
const dynamicHeight = MARGIN.top + dynamicInnerHeight + MARGIN.bottom;
svg.attr('height', dynamicHeight);Single component path (line 3019):
// Current:
const step = Math.min((INNER_HEIGHT - 25) / (ipArray.length + 1), 15);
// Change to:
const step = Math.max(MIN_IP_SPACING, Math.min((INNER_HEIGHT - 25) / (ipArray.length + 1), 15));Multi-component path (line 3074-3077):
Change absolute minimum from 8 to MIN_IP_SPACING:
const ipStep = Math.max(
Math.min(spaceForIPs / (numIPs + 1), minIPSpacing),
MIN_IP_SPACING // was 8
);The brush extent uses MARGIN.top + INNER_HEIGHT. Since setupDragToBrush runs before final positioning computes dynamicInnerHeight, store it at module scope and update brush extent after height is known. Alternatively, reconfigure brush extent after final height is calculated:
if (brushGroup && brush) {
brush.extent([[MARGIN.left, MARGIN.top], [width + MARGIN.left, dynamicHeight]]);
brushGroup.call(brush);
}Pass dynamicHeight instead of height + MARGIN.top + MARGIN.bottom to createBifocalHandles.
- Force simulation and IP order
- Arc rendering
- Bifocal/lens behavior
- Label font size (8px)
- Row line rendering
python -m http.server 8000, openattack_timearcs.html- Load CSV with 100+ IPs — labels readable, container scrolls
- Load CSV with <50 IPs — stays compact, no unnecessary expansion
- Brush selection works across full dynamic height
- Bifocal handles span full chart height
- Window resize re-renders correctly