`
- Renders WizardStepper above the card
- Card: `
`
- CardHeader: step title (heading 20px/600) + step description (body 14px/400 text-muted-foreground)
- CardContent: renders active step component based on `state.currentStep`
- Bottom nav: `flex justify-between items-center pt-4 border-t border-border`
- Left side: Go Back button (variant="ghost", hidden on step 1) + Skip Step button (variant="ghost" text-muted-foreground)
- Right side: Next Step button (variant="default")
- Step 1 Next: validates income > 0, shows error if invalid, otherwise advances to step 2
- Step 2 Next: no validation, advances to step 3
- Step 3: shows placeholder text "Review step coming in next plan" (will be replaced in Plan 02)
- Below card: "Skip setup" link: ``
- Skip step on step 1: advance to step 2. Skip step on step 2: advance to step 3.
- Clicking completed stepper steps calls `setStep(step)`
ls src/components/setup/WizardStepper.tsx src/components/setup/IncomeStep.tsx src/components/setup/AllocationBar.tsx src/components/setup/CategoryGroupHeader.tsx src/components/setup/PresetItemRow.tsx src/components/setup/RecurringItemsStep.tsx src/pages/SetupPage.tsx && npx tsc --noEmit 2>&1 | head -30
- src/pages/SetupPage.tsx contains `useWizardState` and `max-w-2xl`
- src/pages/SetupPage.tsx contains `currentStep` conditional rendering
- src/components/setup/WizardStepper.tsx contains `role="navigation"` and `aria-label`
- src/components/setup/WizardStepper.tsx contains `w-8 h-8`
- src/components/setup/IncomeStep.tsx contains `type="number"` and `text-lg`
- src/components/setup/AllocationBar.tsx contains `aria-live="polite"` and `sticky top-0`
- src/components/setup/CategoryGroupHeader.tsx contains `w-2.5 h-2.5 rounded-full`
- src/components/setup/PresetItemRow.tsx contains `Checkbox` import and `w-24`
- src/components/setup/RecurringItemsStep.tsx imports `PRESETS` from `@/data/presets`
- TypeScript compiles without errors (`npx tsc --noEmit` exits 0)
All 7 wizard UI components render correctly, TypeScript compiles without errors, wizard navigates between steps 1 and 2 with working state persistence
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| localStorage -> component | Persisted wizard data read back into React state |
| client -> Supabase (future Plan 02) | Category/template item creation on completion |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-07-01 | Tampering | useWizardState localStorage read | mitigate | Validate JSON shape on load: check currentStep is 1-3, income is number, selectedItems is object with expected structure. Fall back to defaults on invalid data. |
| T-07-02 | Information Disclosure | localStorage key | accept | Key includes userId, preventing cross-user data leakage. Data is non-sensitive (income amount, item selections). |
| T-07-03 | Spoofing | Preset data | accept | PRESETS are hardcoded source constants, not user input. i18n keys resolve from bundled JSON, no injection vector. |
- `npx tsc --noEmit` passes (no type errors)
- All 7 component files exist in src/components/setup/ and src/pages/
- useWizardState stores and retrieves state from localStorage
- i18n keys resolve for both "en" and "de" locales
- SetupPage renders with WizardStepper showing 3 steps
- Step 1 shows income input pre-filled with 3000 and currency suffix
- Step 2 shows all 19 PRESETS grouped by type with checkboxes and editable amounts
- Bills (4) and variable_expense (5) items are checked by default
- AllocationBar shows remaining = 3000 - sum(checked) and turns red when negative
- Navigating between steps preserves state
- Refreshing the page restores wizard at correct step (localStorage)