Three defects in the view-preservation path could leave the plot frozen
(no updates, no orbit, stale colours):
1. The merge injected raw _fullLayout objects - including undefined when a
push landed before the previous react resolved - and plotly validates
layouts, so one bad value made every later react fail permanently.
currentView() now deep-copies and validates eye/center/up and each
range, and mergeView() is wrapped so it can never block an update.
2. Updates were not serialized: overlapping Plotly.react calls on one graph
div left it unresponsive. otkoUpdate now queues and coalesces (one react
at a time, latest payload wins), and logs instead of failing silently.
3. A style change re-framed the camera, so re-colouring yanked a view the
user had orbited. Colour/opacity ride the traces and background/outline
ride the layout, so set_style is now a non-framing push.
Verified in the browser: a user orbit survives colour changes, 30 rapid
preview updates land on the final value and stay responsive, and deleting
the live camera no longer wedges the plot.