diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 2d5f077..716c2f8 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -31,8 +31,8 @@ Decimal phases appear between their surrounding integers in numeric order.
5. A single `lib/palette.ts` file exists as the source of truth for all category-to-color mappings; `InlineEditCell.tsx` is extracted as a shared component replacing three duplicated local definitions
**Plans:** 2/2 plans complete
Plans:
-- [ ] 01-01-PLAN.md — CSS token foundation, palette.ts module, and test infrastructure
-- [ ] 01-02-PLAN.md — Component wiring, InlineEditCell extraction, and visual verification
+- [x] 01-01-PLAN.md — CSS token foundation, palette.ts module, and test infrastructure
+- [x] 01-02-PLAN.md — Component wiring, InlineEditCell extraction, and visual verification
### Phase 2: Layout and Brand Identity
**Goal**: Users encounter a visually branded, polished experience on every high-visibility surface — login page, sidebar, and dashboard layout — establishing the perceptual quality bar for the entire app
@@ -44,7 +44,10 @@ Plans:
3. The sidebar has a pastel background visually distinct from the main content area, with a branded typographic treatment for the app name
4. The active navigation item has a clearly visible color indicator — clicking a nav item produces a visible selected state
5. The sidebar can be collapsed via a toggle button, reducing screen space usage on smaller layouts
-**Plans**: TBD
+**Plans:** 2 plans
+Plans:
+- [ ] 02-01-PLAN.md — Auth screen branding (gradient background, wordmark, alert errors)
+- [ ] 02-02-PLAN.md — Sidebar polish (wordmark, active indicator, collapse trigger)
### Phase 3: Interaction Quality and Completeness
**Goal**: Every user action and app state has appropriate visual feedback — loading states, empty states, edit affordances, and delete confirmations — so the app feels complete and trustworthy
@@ -76,6 +79,6 @@ Phases execute in numeric order: 1 → 2 → 3 → 4
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 1. Design Token Foundation | 2/2 | Complete | 2026-03-11 |
-| 2. Layout and Brand Identity | 0/TBD | Not started | - |
+| 2. Layout and Brand Identity | 0/2 | In progress | - |
| 3. Interaction Quality and Completeness | 0/TBD | Not started | - |
| 4. Chart Polish and Bug Fixes | 0/TBD | Not started | - |
diff --git a/.planning/phases/02-layout-and-brand-identity/02-01-PLAN.md b/.planning/phases/02-layout-and-brand-identity/02-01-PLAN.md
new file mode 100644
index 0000000..a7d284b
--- /dev/null
+++ b/.planning/phases/02-layout-and-brand-identity/02-01-PLAN.md
@@ -0,0 +1,228 @@
+---
+phase: 02-layout-and-brand-identity
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - frontend/src/components/ui/alert.tsx
+ - frontend/src/pages/LoginPage.tsx
+ - frontend/src/pages/RegisterPage.tsx
+ - frontend/src/pages/LoginPage.test.tsx
+ - frontend/src/pages/RegisterPage.test.tsx
+autonomous: true
+requirements: [AUTH-01, AUTH-02, AUTH-03, AUTH-04]
+
+must_haves:
+ truths:
+ - "Login page renders on a pastel gradient background, not plain white"
+ - "Login page displays a gradient text wordmark for the app name"
+ - "Register page has the same branded gradient and wordmark as login"
+ - "Auth form errors display inside a styled Alert with an error icon"
+ artifacts:
+ - path: "frontend/src/components/ui/alert.tsx"
+ provides: "shadcn Alert component with destructive variant"
+ - path: "frontend/src/pages/LoginPage.tsx"
+ provides: "Branded login with gradient bg, wordmark, alert errors"
+ contains: "linear-gradient"
+ - path: "frontend/src/pages/RegisterPage.tsx"
+ provides: "Branded register matching login look"
+ contains: "linear-gradient"
+ - path: "frontend/src/pages/LoginPage.test.tsx"
+ provides: "Unit tests for AUTH-01, AUTH-02, AUTH-04"
+ - path: "frontend/src/pages/RegisterPage.test.tsx"
+ provides: "Unit tests for AUTH-03"
+ key_links:
+ - from: "frontend/src/pages/LoginPage.tsx"
+ to: "frontend/src/lib/palette.ts"
+ via: "import palette for gradient light shades"
+ pattern: "palette\\."
+ - from: "frontend/src/pages/LoginPage.tsx"
+ to: "frontend/src/components/ui/alert.tsx"
+ via: "Alert destructive for error display"
+ pattern: "Alert.*destructive"
+---
+
+
+Brand the auth screens (login and register) with a pastel gradient background, gradient text wordmark, and styled error alerts -- transforming them from plain white cards into the first branded touchpoint users see.
+
+Purpose: Login is the first impression. A branded auth surface sets the perceptual quality bar before users even reach the dashboard.
+Output: Polished LoginPage.tsx and RegisterPage.tsx with gradient backgrounds, wordmark, Alert errors, and passing unit tests.
+
+
+
+@/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md
+@/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/02-layout-and-brand-identity/02-RESEARCH.md
+@.planning/phases/02-layout-and-brand-identity/02-VALIDATION.md
+
+@frontend/src/pages/LoginPage.tsx
+@frontend/src/pages/RegisterPage.tsx
+@frontend/src/lib/palette.ts
+
+
+
+
+From frontend/src/lib/palette.ts:
+```typescript
+export const palette: Record = {
+ saving: { light: 'oklch(0.95 0.04 280)', ... },
+ bill: { light: 'oklch(0.96 0.03 250)', ... },
+ investment: { light: 'oklch(0.96 0.04 320)', ... },
+ // ... other types
+}
+```
+
+From frontend/src/index.css (token values for wordmark gradient):
+```css
+--primary: oklch(0.50 0.12 260);
+/* Shift hue to ~300-320 for the gradient end stop */
+```
+
+From LoginPage.tsx current structure:
+```typescript
+interface Props {
+ auth: AuthContext
+ onToggle: () => void
+}
+// Uses: useState for email, password, error, loading
+// Renders: Card with CardHeader, form with CardContent, CardFooter
+// Current wrapper:
+// Current error:
{error}
+```
+
+
+
+
+
+
+ Task 1: Install shadcn Alert and create test scaffolds for auth pages
+ frontend/src/components/ui/alert.tsx, frontend/src/pages/LoginPage.test.tsx, frontend/src/pages/RegisterPage.test.tsx
+
+1. Install the shadcn alert component:
+ ```bash
+ cd frontend && bunx --bun shadcn add alert
+ ```
+ Verify `frontend/src/components/ui/alert.tsx` exists after installation.
+
+2. Create `frontend/src/pages/LoginPage.test.tsx` with these test cases (all should FAIL initially since the features are not yet implemented):
+ - AUTH-01: Login page wrapper div has an inline style containing `linear-gradient` (gradient background)
+ - AUTH-02: Login page renders an element with `data-testid="wordmark"` that has an inline style containing `background` (gradient text)
+ - AUTH-04: When error state is set, an element with `role="alert"` is rendered (shadcn Alert uses role="alert")
+ - AUTH-04: The alert contains an AlertCircle icon (verify by checking for an SVG inside the alert)
+
+3. Create `frontend/src/pages/RegisterPage.test.tsx` with these test cases:
+ - AUTH-03: Register page wrapper div has an inline style containing `linear-gradient`
+ - AUTH-03: Register page renders an element with `data-testid="wordmark"`
+
+Test setup notes:
+- Import `{ render, screen }` from `@testing-library/react`
+- LoginPage requires `auth` prop with `login` function and `onToggle` prop -- mock them with `vi.fn()`
+- RegisterPage requires `auth` prop with `register` function and `onToggle` prop
+- Both pages use `useTranslation` -- mock `react-i18next` with `vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key }) }))`
+- The `AuthContext` type must be satisfied: `{ user: null, loading: false, login: vi.fn(), register: vi.fn(), logout: vi.fn(), token: null }`
+
+
+ cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/pages/LoginPage.test.tsx src/pages/RegisterPage.test.tsx --reporter=verbose 2>&1 | tail -20
+
+ alert.tsx exists in ui/, LoginPage.test.tsx has 4 test cases, RegisterPage.test.tsx has 2 test cases. Tests run (expected: most FAIL since features not yet implemented).
+
+
+
+ Task 2: Brand LoginPage and RegisterPage with gradient background, wordmark, and Alert errors
+ frontend/src/pages/LoginPage.tsx, frontend/src/pages/RegisterPage.tsx
+
+Apply all four AUTH requirements to both auth pages simultaneously (AUTH-03 requires register to mirror login).
+
+**LoginPage.tsx changes:**
+
+1. Add imports:
+ ```typescript
+ import { palette } from '@/lib/palette'
+ import { Alert, AlertDescription } from '@/components/ui/alert'
+ import { AlertCircle } from 'lucide-react'
+ ```
+
+2. Replace the outer wrapper div `bg-background` with a gradient background using palette light shades (AUTH-01):
+ ```tsx
+
+ ```
+ Use the `light` shades (lightness 0.95-0.97, chroma 0.03-0.04) for a subtle tinted-paper feel, NOT medium or base shades which would be too saturated as backgrounds.
+
+3. Add a gradient text wordmark in the CardHeader (AUTH-02). Replace the `{t('app.title')}` with a styled wordmark element:
+ ```tsx
+
+ {t('app.title')}
+
+ ```
+ The gradient goes from --primary hue (260) to a pink-shifted hue (320). Keep `{t('auth.login')}` as-is above the wordmark.
+
+4. Replace the plain error `
` with a shadcn Alert (AUTH-04):
+ ```tsx
+ {error && (
+
+
+ {error}
+
+ )}
+ ```
+
+5. Add `shadow-lg` to the Card for visual lift against the gradient: ``
+
+**RegisterPage.tsx changes (AUTH-03):**
+
+Apply the identical structural changes as LoginPage:
+- Same gradient background wrapper with palette light shades
+- Same wordmark element with `data-testid="wordmark"`
+- Same Alert destructive for error display
+- Same Card shadow-lg
+- Keep `{t('auth.register')}` (not login)
+- Import palette, Alert, AlertDescription, AlertCircle
+
+Both files should be near-mirrors structurally. The only differences are: CardTitle text, form fields (register has displayName), submit handler, footer link text.
+
+
+ cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/pages/ --reporter=verbose && bun run build 2>&1 | tail -5
+
+ All 6 test cases pass (4 LoginPage + 2 RegisterPage). Production build succeeds. LoginPage and RegisterPage both render gradient backgrounds, gradient text wordmarks, and Alert-based error displays.
+
+
+
+
+
+- `cd frontend && bun vitest run src/pages/ --reporter=verbose` -- all tests green
+- `cd frontend && bun run build` -- zero errors
+- `cd frontend && bun vitest run` -- full suite green (no regressions)
+
+
+
+- Login page has a pastel gradient background using palette.ts light shades (not plain white)
+- Both auth pages display a gradient text wordmark for the app name
+- Auth errors render in a shadcn Alert with destructive variant and AlertCircle icon
+- Register page is structurally identical to login in branding treatment
+- All new and existing tests pass, production build succeeds
+
+
+
diff --git a/.planning/phases/02-layout-and-brand-identity/02-02-PLAN.md b/.planning/phases/02-layout-and-brand-identity/02-02-PLAN.md
new file mode 100644
index 0000000..1cb44d0
--- /dev/null
+++ b/.planning/phases/02-layout-and-brand-identity/02-02-PLAN.md
@@ -0,0 +1,205 @@
+---
+phase: 02-layout-and-brand-identity
+plan: 02
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - frontend/src/components/AppLayout.tsx
+ - frontend/src/components/AppLayout.test.tsx
+autonomous: true
+requirements: [NAV-01, NAV-02, NAV-03, NAV-04]
+
+must_haves:
+ truths:
+ - "Sidebar has a visually distinct pastel background from the main content area"
+ - "Sidebar app name displays as a branded gradient text wordmark"
+ - "Clicking a nav item produces a clearly visible active state indicator"
+ - "A toggle button exists to collapse/expand the sidebar"
+ artifacts:
+ - path: "frontend/src/components/AppLayout.tsx"
+ provides: "Branded sidebar with wordmark, active indicator, collapse trigger"
+ contains: "SidebarTrigger"
+ - path: "frontend/src/components/AppLayout.test.tsx"
+ provides: "Unit tests for NAV-01 through NAV-04"
+ key_links:
+ - from: "frontend/src/components/AppLayout.tsx"
+ to: "frontend/src/components/ui/sidebar.tsx"
+ via: "SidebarTrigger import for collapse toggle"
+ pattern: "SidebarTrigger"
+ - from: "frontend/src/components/AppLayout.tsx"
+ to: "SidebarMenuButton isActive"
+ via: "data-active styling override for visible indicator"
+ pattern: "data-\\[active=true\\]"
+---
+
+
+Polish the sidebar shell -- branded wordmark, visible active nav indicator, and collapse toggle -- so every authenticated page load feels intentionally designed.
+
+Purpose: The sidebar is visible on every page after login. Its polish directly determines the perceived quality of the entire app.
+Output: Updated AppLayout.tsx with branded sidebar and passing unit tests.
+
+
+
+@/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md
+@/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/02-layout-and-brand-identity/02-RESEARCH.md
+@.planning/phases/02-layout-and-brand-identity/02-VALIDATION.md
+
+@frontend/src/components/AppLayout.tsx
+
+
+
+
+From frontend/src/components/AppLayout.tsx:
+```typescript
+interface Props {
+ auth: AuthContext
+ children: React.ReactNode
+}
+// Uses: useTranslation, useLocation from react-router-dom
+// Imports from ui/sidebar: Sidebar, SidebarContent, SidebarFooter, SidebarGroup,
+// SidebarGroupContent, SidebarHeader, SidebarMenu, SidebarMenuButton,
+// SidebarMenuItem, SidebarProvider, SidebarInset
+// NOTE: SidebarTrigger is NOT currently imported
+// Current app name:
{t('app.title')}
+// Current active state: isActive={location.pathname === item.path} (no className override)
+// Current SidebarInset: {children} (no header bar)
+```
+
+From frontend/src/index.css (sidebar token values):
+```css
+--sidebar: oklch(0.97 0.012 280); /* light lavender background */
+--sidebar-primary: oklch(0.50 0.12 260); /* strong accent for active state */
+--sidebar-primary-foreground: oklch(0.99 0.005 290);
+--sidebar-accent: oklch(0.93 0.020 280); /* 4-point lightness diff from sidebar - may be too subtle */
+--primary: oklch(0.50 0.12 260); /* for wordmark gradient start */
+```
+
+From frontend/src/components/ui/sidebar.tsx (already exported):
+```typescript
+export { SidebarTrigger } // renders PanelLeftIcon button, calls toggleSidebar()
+```
+
+
+
+
+
+
+ Task 1: Create AppLayout test scaffold
+ frontend/src/components/AppLayout.test.tsx
+
+Create `frontend/src/components/AppLayout.test.tsx` with test cases for all four NAV requirements.
+
+Test setup:
+- Mock `react-i18next`: `vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key }) }))`
+- Mock `react-router-dom`: `vi.mock('react-router-dom', () => ({ Link: ({ children, to, ...props }: any) => {children}, useLocation: () => ({ pathname: '/' }) }))`
+- Create mock auth: `{ user: { display_name: 'Test' }, loading: false, login: vi.fn(), register: vi.fn(), logout: vi.fn(), token: 'test' } as unknown as AuthContext`
+- Render with: `render(
content
)`
+
+Note: SidebarProvider uses ResizeObserver internally. Add to test file top:
+```typescript
+// Mock ResizeObserver for sidebar tests
+globalThis.ResizeObserver = class { observe() {} unobserve() {} disconnect() {} } as any
+```
+
+Test cases:
+- NAV-01: The sidebar element renders (verify `
+
+ cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/components/AppLayout.test.tsx --reporter=verbose 2>&1 | tail -20
+
+ AppLayout.test.tsx exists with 4 test cases. Tests run (expected: most FAIL since features not yet implemented).
+
+
+
+ Task 2: Brand sidebar with wordmark, active indicator override, and collapse trigger
+ frontend/src/components/AppLayout.tsx
+
+Apply all four NAV requirements to AppLayout.tsx.
+
+1. Add `SidebarTrigger` to imports from `@/components/ui/sidebar` (NAV-04).
+
+2. Replace the plain `
` app name in SidebarHeader with a gradient text wordmark (NAV-02):
+ ```tsx
+
+
+ {t('app.title')}
+
+ {auth.user && (
+
{auth.user.display_name}
+ )}
+
+ ```
+ The gradient starts at --primary hue (260) and shifts to hue 300 for a subtle purple-to-pink sweep.
+
+3. Add a className override to SidebarMenuButton for a stronger active state indicator (NAV-03):
+ ```tsx
+
+ ```
+ This overrides the default `bg-sidebar-accent` (only 4 lightness points difference, nearly invisible) with `bg-sidebar-primary` (oklch 0.50 vs 0.97 -- very visible).
+
+4. Add a header bar with SidebarTrigger inside SidebarInset (NAV-04):
+ ```tsx
+
+
+
+
+ {children}
+
+ ```
+ The SidebarTrigger is placed inside SidebarInset (which is inside SidebarProvider), so the `useSidebar()` hook call is safe. Added `p-4` to main for consistent content padding.
+
+5. NAV-01 is already satisfied by the existing `--sidebar: oklch(0.97 0.012 280)` token in index.css -- the sidebar renders with `bg-sidebar` natively. No code change needed; just verify it works via tests and visual check.
+
+Do NOT edit `frontend/src/components/ui/sidebar.tsx` -- project constraint prohibits editing shadcn ui source files. All customization is via className props and CSS variable overrides.
+
+
+ cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/components/AppLayout.test.tsx --reporter=verbose && bun run build 2>&1 | tail -5
+
+ All 4 AppLayout test cases pass. Production build succeeds. Sidebar renders gradient wordmark, strong active indicator using sidebar-primary, and a visible SidebarTrigger collapse button in the content header.
+
+
+
+
+
+- `cd frontend && bun vitest run src/components/AppLayout.test.tsx --reporter=verbose` -- all tests green
+- `cd frontend && bun run build` -- zero errors
+- `cd frontend && bun vitest run` -- full suite green (no regressions)
+
+
+
+- Sidebar renders with bg-sidebar pastel background distinct from main content
+- App name in sidebar header is a gradient text wordmark, not a plain h2
+- Active nav item shows bg-sidebar-primary with high contrast (not the subtle default accent)
+- SidebarTrigger button is rendered in a header bar within SidebarInset
+- All new and existing tests pass, production build succeeds
+
+
+