- Client-side buildHTML() replaces server-side Jinja loop rendering
- Greedy lane assignment algorithm (assignLanes) to prevent segment overlap
- assignEventLanes for detached events stacking
- Wheel zoom with cursor-position anchor; drag pan with user-select:none
- Bucket-based positioning: startOfBucket/nextBucket/bucketDelta for precision
- Events positioned on parent segment track lane; detached events in separate row
- resolveScale with explicit ?scale= URL param support
- Backend: add bucket_origin, track, parent_entry_id, parent_track to JSON data
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>