Megalomaniak duane thanks - not sure why it expired, sorry about that. Updated it with a new one.
I've played around with it a bit more and looked at various performance metrics in the debugger. I think the issue is how inefficient the logic for detecting overlap is inside the _draw() function since every circle needs to check every other circle before it expands which i think makes its O(n2). Even without the update() to refresh the screen, the latency in _process() is spiking like crazy when the number of circles goes above 300.
Not sure how P5.js and Processing handles this so well in that video... but I'm going to try implementing a quadtree later today to see if this will help. I'm pretty new to Godot / coding so just making this up as I go! Any other ideas would be appreciated!