` at `(x, y)` with `(w, h)` dimensions.
- Selection shows a CSS-outlined bounding box with 8 resize handles rendered as small squares.
- Drag-and-drop from the signal tree uses the HTML Drag-and-Drop API; on drop, the canvas coordinate is computed from the drop event offset.
- Undo/redo uses an array of past interface snapshots (max depth 50).
- Align/distribute operations compute target positions geometrically and generate a single undo entry.
- Multi-select via Ctrl+click or rubber-band area select.
### 4.4 Widget Rendering in View Mode (`Canvas.tsx`)
View mode renders widgets as absolutely positioned Preact components on a scrollable canvas div:
- Each widget subscribes to its signal store(s) in a `useEffect` and re-renders only when values change.
- uPlot (time series) and ECharts (histogram, bar, FFT, waterfall, logic analyser) manage their own canvas elements inside their widget component.
- Plot widgets maintain a rolling ring buffer of 200,000 samples per signal for smooth long-window display.
- Step-hold interpolation: when multiple signals at different update rates share a plot, the most recent value is carried forward to fill the shared time axis correctly.
### 4.5 Plot Panel (`PlotPanel.tsx`)
A live multi-signal plot panel accessible from the "Plot" tab in View mode:
- Signals are added by right-clicking any widget and choosing "Plot".
- Supports configurable time window (10s to 1h).
- Per-signal style editor: color picker, line width (0 = hidden), line dash (solid/dashed/dotted), marker size (none/S/M/L).
- Statistics table per signal: last, min, max, mean over the current time window.
- Uses a `requestAnimationFrame` loop limited to ≤1 redraw/second when data is not changing.
- Chart fills its container; `ResizeObserver` keeps the uPlot canvas sized correctly.
### 4.6 Resizable Panels
Both edit and view modes support mouse-drag panel resizing:
- **View mode**: drag handle between the interface list pane and the main content area.
- **Edit mode**: drag handles on both sides of the central canvas (signal tree ↔ canvas, canvas ↔ properties pane).
- Handle width: 5 px, cursor changes to `ew-resize` on hover.
- Minimum panel widths enforced to prevent collapse below usable size.
### 4.7 HiDPI / Zoom Support
- `html { font-size: clamp(13px, 1.5vh, 18px); }` — base font scales with viewport height, making the UI naturally larger on 4K screens where the browser zoom level is 100%.
- Key structural heights (toolbar, panel headers, tab bar, plot toolbar) are expressed in `rem` so they scale with the base font.
- **ZoomControl** (A− / % / A+) in the toolbar lets users manually override the zoom level in 11 steps from 50% to 250%. The preference is persisted in `localStorage` (`uopi:ui-zoom`) and applied by setting `document.documentElement.style.fontSize` on load.
- Canvas pixel rendering (uPlot, ECharts) reads `window.devicePixelRatio` and sizes canvases accordingly.
### 4.8 Lua Editor (`LuaEditor.tsx`)
A syntax-highlighted code editor for Lua scripts in the Synthetic signal wizard:
- Implemented as a `