I tried the suggestions made but I could not get them to work properly. I think that's due to the very fluid nature of the DOM in this scenario.
However, I sort of have this working fairly well by using two separate Timelines - one for the class of elements that have not been dynamically removed/re-added, and another Timeline for those that have been. Whenever I remove an element, and then it gets re-added, I give it a class different from what the static elements have, and animate these new elements with the 2nd Timeline. This works pretty well except for one issue. It looks like my two Timelines are not running simultaneously, but rather sequentially with respect to each other. The animations in the first Timeline will run, then those in the second Timeline run, instead of both groups of animations running at the same time. The longer the duration I set for each Timeline, the more noticeable this issue is, of course. I have them defined separately, like this:
<script>
var tl = gsap.timeline({repeat: 0});
tl.eventCallback("onComplete", triaRefresh);
var tl2 = gsap.timeline({repeat: 0});
tl2.eventCallback("onComplete", trianewRefresh);
</script>
And in my two separate onComplete callbacks I simply do tl.restart() and tl2.restart() respectively so that the animations appear to run continuously for each group of elements.
I start each Timeline like this, for example:
gsap.set(".tria", {transformOrigin: "50% 65%", scale: 0.9});
tl.to(".tria", {duration: .5, rotation: 360, ease: "bounce"});
So except for the issue I mentioned above where the two Timelines seem to run sequentially to each other rather than simultaneously with each other, this is working. I don't know if there's a better, cleaner way to do this - perhaps nested Timelines? I'm a newbie to gsap so I'm still feeling my way thru this.