Bring the Plotly canvas in line with opstool's visualisation recipes.
Camera / interaction:
- frame the camera in plotly's normalized scene units, using the model
bounds (grid excluded); a data-unit eye rendered the model as a speck
- use turntable dragmode so Z stays up and the horizon stays level
- align mouse bindings with the PyVista/VTK backend and document them in
Help → Mouse Controls
Visualisation:
- colour deformed / modal shapes by response with a shared colourbar
- scale load arrows by |F|, tint per load pattern, hover the magnitude,
and fix cones rendering as oversized fins (sizemode scaled, not absolute)
- draw DOF-accurate support glyphs (ported from opstool; see NOTICE)
- add an undeformed-reference overlay on both canvas backends
- play mode shapes with plotly frame animation in-page
Tests: builder unit tests plus GUI regression tests for gestures, the
deformed push, the undeformed reference and animation payloads.
Ports opstool's per-family element colours and its diverging response
scale; RenderStyle.response_scale_colors now also drives the PyVista
force-diagram colouring instead of a hard-coded "coolwarm".
The frame renderer drops the two-trace normal/selected workaround: my
earlier assumption that plotly cannot colour segments individually was
wrong. Scatter3d.line.color accepts an array mapped through a colorscale,
so one trace now carries per-element colours (family + selection) and is
ready to be coloured by response value later.
Attribution recorded in NOTICE per GPLv3 section 5(a)/(b).