- Add @custom-variant dark in globals.css for class-based dark mode
- Add ThemeToggle component with localStorage persistence and system preference fallback
- Inject blocking inline script in layout to prevent flash on load
- Apply dark: variants across all components (layout, site-nav, home-dashboard, expense-workspace, paycheck-workspace, recurring-expense-manager) and page headers
- Create openspec/changes/theming-dark-mode with proposal, design, and tasks artifacts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add RecurringExpense model to Prisma schema with migration
- Add lib/recurring-expenses.ts: CRUD + virtual projection per month
- Add /recurring-expenses API routes (GET, POST, PATCH, DELETE)
- Merge projected recurring expenses into dashboard totals and expense list
- Add RecurringExpenseManager component to /add-expense page
- Show amber "Recurring" badge on projected items; hide edit/delete for them
- Highlight active nav tab using usePathname() with hover state
- Fix Turbopack/Prisma stub issue by adding serverExternalPackages to next.config.ts
- Clear stale Turbopack stub in Dockerfile before each build
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>