Sorry, totally missed your reply!
At first we had normal text and then we switched them for hand-drawn sprites. The text animation consists of 2D transformations (translation, rotation, scale) interpolated over time. It's all animated in code. NanoVG helps by having a transformation stack like OpenGL. In Zig I can open a block like this:
{
vg.save();
defer vg.restore(); // undo all transformations at the end of the block
{ vg.save(); defer vg.restore(); // undo all transformations at the end of the block
} // continue to draw the rest of the scene