diff --git a/.planning/phases/01-esp32-firmware/01-CONTEXT.md b/.planning/phases/01-esp32-firmware/01-CONTEXT.md
new file mode 100644
index 0000000..24245cb
--- /dev/null
+++ b/.planning/phases/01-esp32-firmware/01-CONTEXT.md
@@ -0,0 +1,97 @@
+# Phase 1: ESP32 Firmware - Context
+
+**Gathered:** 2026-04-03
+**Status:** Ready for planning
+
+
+## Phase Boundary
+
+ESP32-C3 SuperMini firmware that drives two LED strips (WS2801 160 LEDs via SPI, SK6812 300 LEDs via RMT/RGBW) and accepts named animation commands over UDP/JSON from a Raspberry Pi. The ESP32 executes animations autonomously — no frame streaming.
+
+
+
+
+## Implementation Decisions
+
+### Animation Design
+- **D-01:** Animations use a palette-based color system with full RGBW support. Each animation accepts a color palette (1-N colors as RGBW arrays) plus effect-specific parameters (speed, intensity, direction).
+- **D-02:** White channel (W) on SK6812 is auto-derived from RGB when not explicitly specified in the command. User can override W directly for warm/cool white effects.
+- **D-03:** 8 initial animations: Chase, Pulse, Rainbow, Strobe, Color Wash, Breathe, Sparkle, Gradient Sweep. All must work on both strip types.
+- **D-04:** Animation tick rate: 50fps (20ms per frame) as a FreeRTOS task. This is the animation engine update rate, not the LED refresh rate.
+
+### JSON Protocol
+- **D-05:** Flat JSON command structure: `{"zone":"schrank"|"wand"|"all", "animation":"chase", "params":{"speed":0.5, "intensity":1.0, "colors":[[255,0,128,0]]}}`. Zone field is mandatory.
+- **D-06:** Additional commands: `{"cmd":"stop","zone":"all"}`, `{"cmd":"brightness","zone":"all","value":100}`, `{"cmd":"status"}` (returns JSON via UDP response).
+- **D-07:** Unknown commands are ignored silently; errors logged to serial console for debugging.
+- **D-08:** Protocol includes a `"v":1` version field in every command for future compatibility.
+
+### Power & Safety
+- **D-09:** Firmware-enforced brightness cap at 40% (configurable via JSON command, max 60%). Research flagged 27A peak at full brightness — dedicated 5V supplies per strip required.
+- **D-10:** On WiFi disconnect: continue running the last animation. On reconnect: accept new commands immediately. No auto-off timeout.
+- **D-11:** Startup behavior: boot with a subtle breathing animation (low brightness) to indicate firmware is alive and WiFi is connecting.
+
+### Development Setup
+- **D-12:** PlatformIO with Arduino framework. NeoPixelBus (RMT) for SK6812, hardware SPI for WS2801.
+- **D-13:** ArduinoJson v7 for JSON parsing, AsyncUDP for WiFi command reception.
+- **D-14:** Serial debug output for development. No OTA in Phase 1 — flash via USB.
+
+### Claude's Discretion
+- FreeRTOS task priorities and stack sizes
+- Exact GPIO pin assignments (validate on hardware — ESP32-C3 SuperMini pinout constraints)
+- DMA buffer sizing for RMT to mitigate WiFi interrupt interference
+- WiFi reconnection strategy and timing
+
+
+
+
+## Canonical References
+
+**Downstream agents MUST read these before planning or implementing.**
+
+### Project Context
+- `.planning/PROJECT.md` — Project vision, hardware specs (WS2801 160 LEDs Schrank, SK6812 300 LEDs Wand, ESP32-C3 SuperMini)
+- `.planning/REQUIREMENTS.md` — FW-01 through FW-05 requirements
+
+### Research
+- `.planning/research/STACK.md` — NeoPixelBus RMT, ArduinoJson, PlatformIO recommendations
+- `.planning/research/ARCHITECTURE.md` — Component boundaries, FreeRTOS task structure, data flow
+- `.planning/research/PITFALLS.md` — WiFi+RMT coexistence on single-core C3, SK6812 RGBW 4-byte framing, power budget
+
+
+
+
+## Existing Code Insights
+
+### Reusable Assets
+- None — greenfield project, no existing code
+
+### Established Patterns
+- None — first phase establishes firmware patterns
+
+### Integration Points
+- UDP port (to be defined) for Pi-to-ESP communication
+- JSON protocol schema must be documented for Phase 2 (Pi-side transport client)
+
+
+
+
+## Specific Ideas
+
+- Hardware: ESP32-C3 SuperMini with WS2801 5m/160 LEDs (U-turn around Schrank) and SK6812 5m/300 LEDs (along wall)
+- Both strips on one ESP32-C3 via different GPIO pins (SPI for WS2801, RMT for SK6812)
+- Research warns: WiFi interrupts can corrupt SK6812 RMT timing on single-core C3 — must validate with `WIFI_PS_NONE` and proper DMA buffer sizing on day 1
+- 1000uF capacitor at each strip input recommended
+
+
+
+
+## Deferred Ideas
+
+None — discussion stayed within phase scope (auto mode)
+
+
+
+---
+
+*Phase: 01-esp32-firmware*
+*Context gathered: 2026-04-03*
diff --git a/.planning/phases/01-esp32-firmware/01-DISCUSSION-LOG.md b/.planning/phases/01-esp32-firmware/01-DISCUSSION-LOG.md
new file mode 100644
index 0000000..f8d8768
--- /dev/null
+++ b/.planning/phases/01-esp32-firmware/01-DISCUSSION-LOG.md
@@ -0,0 +1,74 @@
+# Phase 1: ESP32 Firmware - Discussion Log
+
+> **Audit trail only.** Do not use as input to planning, research, or execution agents.
+> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
+
+**Date:** 2026-04-03
+**Phase:** 01-esp32-firmware
+**Areas discussed:** Animation design, JSON protocol, Power & safety, Development setup
+**Mode:** auto (all areas auto-selected, recommended defaults chosen)
+
+---
+
+## Animation Design
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Palette-based with RGBW | Each animation accepts color palette + params | [auto] |
+| Single color per animation | Simpler but limiting | |
+| HSV color space | Alternative representation | |
+
+**User's choice:** [auto] Palette-based with RGBW support (recommended default)
+**Notes:** SK6812 is RGBW — palette approach keeps JSON commands simple while supporting rich effects. W channel auto-derived from RGB when not specified.
+
+---
+
+## JSON Protocol
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Flat JSON | `{"zone":"wall","animation":"chase","params":{}}` | [auto] |
+| Nested/hierarchical | More structured but complex | |
+| Binary protocol | Lower overhead but harder to debug | |
+
+**User's choice:** [auto] Flat JSON with zone, animation, and params fields (recommended default)
+**Notes:** Matches research recommendation. Simple, debuggable with netcat.
+
+---
+
+## Power & Safety
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 40% brightness cap | Safe for power budget | [auto] |
+| No cap (user responsibility) | Full brightness available | |
+| Dynamic cap based on animation | Complex but optimal | |
+
+**User's choice:** [auto] 40% firmware-enforced cap, adjustable to max 60% (recommended default)
+**Notes:** Research flagged 27A peak at full brightness across 460 LEDs.
+
+---
+
+## Development Setup
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| PlatformIO + Arduino | NeoPixelBus + ArduinoJson ecosystem | [auto] |
+| ESP-IDF native | More control, steeper learning curve | |
+| Arduino IDE | Simpler but no dependency management | |
+
+**User's choice:** [auto] PlatformIO + Arduino framework (recommended default)
+**Notes:** Research validated NeoPixelBus RMT + ArduinoJson work well on ESP32-C3.
+
+---
+
+## Claude's Discretion
+
+- FreeRTOS task priorities and stack sizes
+- GPIO pin assignments (hardware validation needed)
+- DMA buffer sizing for RMT
+- WiFi reconnection strategy
+
+## Deferred Ideas
+
+None — auto mode, discussion stayed within phase scope