Using millis() instead of delay

I think it only works as expected because you are using each of the "timer()" functions only once.

If you took the '5' out of timer(500, blinking, 5); the blink would never get executed. Every 30 mSec the second call to timer() would trigger and reset 'prev'. The fading would happen but "millis() - prev" would never reach 500 so the blink would never happen.

You could create a timer object that keeps a separate "prev" for each timer.