```
Task 1: Mobile responsive layout — card grid, button rows, step indicator collapsesrc/components/wizard/BackendSelectionStep.tsx, src/components/ui/BackendCard.tsx, src/components/wizard/RemoteConfigStep.tsx, src/components/wizard/DeploymentStep.tsx, src/components/wizard/ReviewStep.tsx, src/components/wizard/StepIndicator.tsx
POLISH-01: Make wizard layout mobile-responsive using Tailwind v4 mobile-first approach.
1. **BackendSelectionStep.tsx** — Change the `data-testid="backend-cards"` div from bare div to responsive grid:
- Add className `grid grid-cols-1 sm:grid-cols-2 gap-3 mt-4` to the `data-testid="backend-cards"` div
- Change button row from `flex gap-3 mt-6` to `flex flex-col sm:flex-row gap-3 mt-6`
- Add `w-full sm:w-auto` to the Next button className (append after MD3_BTN_FILLED)
2. **BackendCard.tsx** — Add `w-full` to the className array so the button fills its grid cell on all viewports. Insert at the start of the className string: `'w-full flex flex-col items-start...'`
3. **RemoteConfigStep.tsx** — Change button row div from `flex gap-3 mt-6` to `flex flex-col sm:flex-row gap-3 mt-6`. Add `w-full sm:w-auto` to both Back and Next button classNames (use template literal: `` `${MD3_BTN_OUTLINED} w-full sm:w-auto` ``).
4. **DeploymentStep.tsx** — Same button row changes as RemoteConfigStep: `flex flex-col sm:flex-row gap-3 mt-6` on the wrapper div, `w-full sm:w-auto` on both buttons.
5. **ReviewStep.tsx** — Change button row div from `flex gap-3 mt-6` to `flex flex-col sm:flex-row gap-3 mt-6`. Add `w-full sm:w-auto` to the Back button. The "Download All (ZIP)" button already has `w-full` — leave as-is.
6. **StepIndicator.tsx** — Add `hidden sm:block` to all three label `` elements:
- Completed step label: `className="text-xs text-primary hidden sm:block"`
- Active step label: `className="text-xs text-primary font-semibold hidden sm:block"`
- Future step label: `className="text-xs text-on-surface-container/40 hidden sm:block"`
Do NOT change any DOM structure beyond adding/modifying className strings. Do NOT add wrapper elements. The `data-testid="backend-cards"` div already exists — just add classes to it.
npx vitest runBackend cards use responsive grid (1-col mobile, 2-col desktop). All step button rows stack vertically on mobile and go horizontal on desktop. StepIndicator labels hidden on mobile, visible on desktop. All existing tests pass.Task 2: MD3 focus-visible indicators on all interactive elementssrc/styles/md3-buttons.ts, src/components/ui/BackendCard.tsx, src/components/wizard/StepIndicator.tsx, src/components/ui/ThemeToggle.tsx, src/components/ui/FieldRenderer.tsx
POLISH-02: Upgrade all interactive elements to 3px MD3 focus-visible rings for keyboard navigation.
1. **md3-buttons.ts** — In all three constants (MD3_BTN_FILLED, MD3_BTN_OUTLINED, MD3_BTN_TEXT), replace:
`focus-visible:ring-2 focus-visible:ring-primary/50`
with:
`focus-visible:ring-3 focus-visible:ring-primary`
Keep `focus-visible:outline-none` as-is.
2. **BackendCard.tsx** — Add focus-visible ring to the button className array. Add this string to the base classes (the first string before the ternary):
`'w-full flex flex-col items-start gap-1 rounded-xl border-2 p-4 text-left transition-all focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary'`
Do NOT add `ring-offset-2` (omit ring-offset to avoid dark mode surface color issues per research open question #2).
3. **StepIndicator.tsx** — On the completed-step circle ``, change:
`group-focus-visible:ring-2 group-focus-visible:ring-primary/50`
to:
`group-focus-visible:ring-3 group-focus-visible:ring-primary`
4. **ThemeToggle.tsx** — Add focus-visible ring to BOTH branches of the ternary className on each theme button:
- Selected: `'flex-1 px-3 py-1 bg-primary text-on-primary font-medium focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary focus-visible:ring-inset'`
- Unselected: `'flex-1 px-3 py-1 bg-surface-container text-on-surface-container hover:bg-surface focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-primary focus-visible:ring-inset'`
Use `ring-inset` because ThemeToggle buttons share a border (overflow-hidden) — outset ring would be clipped.
5. **FieldRenderer.tsx** — Two changes:
a. **Select element:** Change `focus:ring-2` to `focus-visible:ring-2` in the select className (keep ring-2 for form controls — inputs conventionally show focus on mouse too, but selects should match button behavior).
b. **Tooltip info buttons** (both the select-branch tooltip button and the text-branch tooltip button): Add `focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded` to both tooltip button classNames. These are small buttons so ring-2 is appropriate (not ring-3).
Note on TextFieldMD3: The input element uses `focus:ring-2` which is correct for text inputs (users expect visible focus on mouse click for inputs). Do NOT change TextFieldMD3.
npx vitest runMD3_BTN_FILLED/OUTLINED/TEXT contain focus-visible:ring-3. BackendCard has focus-visible ring. StepIndicator completed-step has upgraded group-focus-visible:ring-3. ThemeToggle buttons have focus-visible ring. FieldRenderer select uses focus-visible:ring-2, tooltip buttons have focus-visible ring. All tests pass.
- `npx vitest run` — all tests green
- Grep for `focus-visible:ring-3` in md3-buttons.ts, BackendCard.tsx, StepIndicator.tsx, ThemeToggle.tsx — all present
- Grep for `grid grid-cols-1 sm:grid-cols-2` in BackendSelectionStep.tsx — present
- Grep for `flex-col sm:flex-row` in all step components — present
- Grep for `hidden sm:block` in StepIndicator.tsx — 3 occurrences (one per label state)
- All step button rows use `flex-col sm:flex-row` (mobile stacks, desktop inline)
- Backend cards container uses `grid grid-cols-1 sm:grid-cols-2`
- BackendCard has `w-full` for grid cell fill
- StepIndicator labels have `hidden sm:block` (3 spans)
- All MD3 button constants use `focus-visible:ring-3 focus-visible:ring-primary`
- BackendCard, ThemeToggle, StepIndicator completed-step, FieldRenderer tooltip buttons all have focus-visible rings
- All existing tests pass (no regressions)