diff --git a/.planning/phases/05-live-show-execution/05-RESEARCH.md b/.planning/phases/05-live-show-execution/05-RESEARCH.md
new file mode 100644
index 0000000..6a1855c
--- /dev/null
+++ b/.planning/phases/05-live-show-execution/05-RESEARCH.md
@@ -0,0 +1,581 @@
+# Phase 5: Live Show Execution - Research
+
+**Researched:** 2026-04-07
+**Domain:** Real-time cue scheduling, canvas preview, show persistence, keyboard UX
+**Confidence:** HIGH — all findings verified against existing codebase; no external library discovery needed
+
+## Summary
+
+Phase 5 is almost entirely an integration and wiring task on top of already-built infrastructure. The server-side scheduler slots into the existing `ws.py` `tick` branch with ~30 lines of Python. The live preview panel is a new HTML `
` strip that receives `preview_update` WebSocket messages and paints colored rectangles via Canvas 2D or simple DOM elements. Show persistence already works at the API level — Phase 5 connects the show selector UI to `setCurrentShowId()` and wires up a `load` message to the WebSocket so the server can acquire the cue list per connection. Keyboard shortcuts are pure `document.addEventListener('keydown')` in `app.js`.
+
+The only non-trivial decision already made by the context session is the seek-safe cue reset: on a `seek` event the server must mark all cues with `timestamp < new_position` as already-fired, so they don't re-trigger after a backward seek. The 60ms look-ahead window eliminates missed cues at 10Hz tick rate — this is the timing contract the planner must implement faithfully.
+
+The frontend preview panel can be fully DOM-driven (one `
` per device, background-color CSS updated by JS) rather than requiring a `