diff --git a/.planning/phases/12-dark-mode-visibility-fixes/12-RESEARCH.md b/.planning/phases/12-dark-mode-visibility-fixes/12-RESEARCH.md
new file mode 100644
index 0000000..0541380
--- /dev/null
+++ b/.planning/phases/12-dark-mode-visibility-fixes/12-RESEARCH.md
@@ -0,0 +1,328 @@
+# Phase 12: Dark Mode Visibility Fixes - Research
+
+**Researched:** 2026-04-01
+**Domain:** CSS dark mode theming — Tailwind v4 CSS custom properties, native form control styling
+**Confidence:** HIGH (all findings based on direct source code audit of the live codebase)
+
+## Summary
+
+Phase 12 addresses a specific set of dark-mode visibility regressions introduced during the v1.2 UI overhaul. The project uses a robust two-layer CSS token system (raw `--r2b-*` custom properties overridden per `.dark` class, wired to Tailwind utility classes via `@theme`). The architecture is sound. The problem is that several components were incompletely migrated: their structural/container elements received semantic tokens but their text elements, headings, and native form controls were left unstyled, rendering them invisible or unreadable in dark mode.
+
+The issues fall into three categories: (1) bare `
` headings with no className in four wizard steps, (2) DeploymentStep using completely unstyled native form controls (fieldset, legend, labels, checkbox, radio), and (3) a `` element in FieldRenderer with no background or text color class, causing browsers to apply a white system background in dark mode.
+
+The fix approach is purely additive: apply existing semantic token classes (`text-on-surface`, `bg-surface-container`, etc.) to the affected elements. Zero new CSS variables, zero new design decisions, zero new dependencies. The existing `.dark` token overrides in `index.css` already define the correct dark-mode values — the work is connecting those tokens to the elements that currently bypass them.
+
+**Primary recommendation:** Audit each component's rendered elements and add semantic token classes to every text and interactive element that currently has none. Do not introduce hardcoded colors.
+
+## Standard Stack
+
+### Core (already in project — no changes needed)
+
+| Library | Version | Purpose | Notes |
+|---------|---------|---------|-------|
+| Tailwind v4 | ^4.2.2 | Utility classes via `@theme` + CSS custom properties | Already wired; all needed tokens exist |
+| `@tailwindcss/vite` | ^4.2.2 | Tailwind v4 Vite integration | No postcss config needed |
+
+### CSS Token System (already complete in `src/index.css`)
+
+All required tokens exist. Dark variants are already correct in `.dark` block:
+
+| Token | Light value | Dark value | Use |
+|-------|------------|-----------|-----|
+| `--r2b-on-surface` | `#111827` (gray-900) | `#F9FAFB` (gray-50) | Primary text, headings |
+| `--r2b-on-surface-container` | `#374151` (gray-700) | `#D1D5DB` (gray-300) | Labels, secondary text |
+| `--r2b-surface-container` | `#FFFFFF` | `#1F2937` (gray-800) | Input/select backgrounds |
+| `--r2b-outline` | `#D1D5DB` | `#4B5563` (gray-600) | Borders |
+| `--r2b-warning` | `#D97706` | `#FCD34D` | Warning text |
+| `--r2b-success` | `#15803D` | `#86EFAC` | Success text |
+
+No installation needed. No new dependencies.
+
+## Architecture Patterns
+
+### Two-Layer Token Pattern (established, Phase 08-01)
+
+```css
+/* Layer 1: raw values, overridden per theme */
+@layer base {
+ :root { --r2b-on-surface: #111827; }
+ .dark { --r2b-on-surface: #F9FAFB; }
+}
+
+/* Layer 2: wire to Tailwind utility classes */
+@theme {
+ --color-on-surface: var(--r2b-on-surface);
+}
+```
+
+This means `text-on-surface` already works correctly in both themes. The fix is always "add the right class", never "add a new CSS variable".
+
+### Semantic Class Application Pattern
+
+**What:** Apply semantic Tailwind utility classes to elements that currently have no className or only structural classes.
+
+**Key classes for this phase:**
+- `text-on-surface` — primary text, headings (h1, h2, h3)
+- `text-on-surface-container` — labels, secondary text, legend elements
+- `bg-surface-container` — input/select backgrounds
+- `text-on-surface-container/60` — placeholder-like text, muted elements
+- `border-outline` — form control borders
+
+### Anti-Patterns to Avoid
+
+- **Hardcoded color classes** (`text-gray-900`, `text-black`, `bg-white`): These ignore the `.dark` cascade — they were the root cause of v1.1 tech debt that THEME-01 fixed.
+- **Adding `dark:` variants**: The project uses `.dark` class toggle (not `prefers-color-scheme`); the `@custom-variant dark (&:where(.dark, .dark *))` declaration in `index.css` means semantic tokens already handle dark automatically. Never add explicit `dark:` prefixes.
+- **Styling `` elements**: Browser-native ` ` elements cannot be reliably styled cross-browser via CSS. Accept system rendering for options; only style the `` container itself.
+
+## Don't Hand-Roll
+
+| Problem | Don't Build | Use Instead | Why |
+|---------|-------------|-------------|-----|
+| Dark select styling | Custom `` component | Add `bg-surface-container text-on-surface` classes to existing `` | `` can't be styled cross-browser; native select with container styling is sufficient |
+| Checkbox/radio dark mode | Custom checkboxes | Accept native rendering + add `accent-primary` Tailwind class | Already in project out-of-scope (REQUIREMENTS.md: "Custom checkbox/radio styling: High effort for few toggles") |
+
+**Key insight:** All tokens already exist and resolve correctly in dark mode. The fix is application of existing classes, not new infrastructure.
+
+## Specific Issues Found (Source Code Audit)
+
+### Issue 1: Bare `` headings — CRITICAL (invisible in dark mode)
+
+**Files affected:**
+- `src/components/wizard/BackendSelectionStep.tsx` line 65: `Step 1: Select Backend `
+- `src/components/wizard/RemoteConfigStep.tsx` line 65: `Step 2: Configure {backendLabel[backendType]} `
+- `src/components/wizard/DeploymentStep.tsx` line 24: `Step 3: Deployment Options `
+- `src/components/wizard/ReviewStep.tsx` line 75: `Step 4: Review & Download `
+
+**Root cause:** No `className` at all — browser renders `` in its default black color, which is invisible on the dark `bg-surface` (#111827) background.
+
+**Fix:** Add `className="text-2xl font-bold text-on-surface mb-2"` (matching the pattern used by IntroSection's `` in App.tsx line 19).
+
+**Reference pattern (correct, from App.tsx line 19):**
+```tsx
+
+```
+
+### Issue 2: DeploymentStep — completely unstyled (CRITICAL)
+
+**File:** `src/components/wizard/DeploymentStep.tsx`
+
+**Elements with no dark-mode styling:**
+- Container `