Paint one series. Same contract as RendererEntry.draw minus the context:
priceToY and items[].x are media px, and the renderer snaps to device
pixels with dpr itself.
Take the pane's base data canvas. ctx2d is the 2D context the pane
already holds on it, when it holds one: the canvas-2D backend draws on
exactly that object, so a frame is one context's op stream and not two
contexts' interleaved. A backend that owns the canvas outright ignores it.
Paints one pane's series. One instance per pane: a backend holds a context on that pane's base canvas, and contexts do not travel between canvases.