Thanks so much for the quick reply.
That put me on the right track and worked for the codepen(now updated).
For some reason in my real project the bg tween was not resetting - I fixed it by explicitly setting as below after playing around with repeatRefresh and yoyo params. There must still be some external forces working on my real project but it got me rolling for now!
const reddening = () =>
gsap
.timeline()
.set(ball1, { backgroundPosition: "0% 0%" })
.to(ball1, {
backgroundPosition: "100% 0",
ease: `steps(${numStepsInCycle})`
})
.yoyo(true);