diff --git a/CLAUDE.md b/CLAUDE.md
deleted file mode 100644
index 5890eac..0000000
--- a/CLAUDE.md
+++ /dev/null
@@ -1,117 +0,0 @@
-# CLAUDE.md - UMBRA
-
-## IMPORTANT:
-- When you've completed an edit, commit with details and push to main
-- Utilise the subagents whenever possible, for backend work invoke the '@backend-engineer' subagent, with front end, invoke the '@frontend-engineer'. To review work use the '@senior-code-reviewer' subagent and for any research use the '@research-analyst' subagent.
-
-## Hard Rules
-
-- **Naive datetimes only.** The DB uses `TIMESTAMP WITHOUT TIME ZONE`. Never send timezone-aware strings (no `Z` suffix, no `.toISOString()`). Use local datetime formatting helpers instead.
-- **Eager load relationships in async SQLAlchemy.** Any `response_model` that includes a relationship (e.g. `ProjectResponse.tasks`) must use `selectinload()` when querying. Lazy loading raises `MissingGreenlet` in async context.
-- **Never shadow SQLAlchemy names.** Model columns must not be named `relationship`, `column`, `metadata`, or other SQLAlchemy reserved names. The `person.py` model aliases the import as `sa_relationship` for this reason.
-- **Frontend date inputs require exact formats.** `` needs `YYYY-MM-DD`, `` needs `YYYY-MM-DDThh:mm`. Backend may return `2026-02-15T00:00:00` which must be sliced/converted before binding.
-- **All API routes are prefixed with `/api`.** Frontend axios base URL is `/api`. Nginx proxies `/api/` to backend:8000. Never duplicate the prefix.
-
-## Tech Stack
-
-### Backend
-- **Python 3.12** (slim Docker image - no curl, use `urllib` for healthchecks)
-- **FastAPI** with async lifespan, Pydantic v2 (`model_dump()`, `ConfigDict(from_attributes=True)`)
-- **SQLAlchemy 2.0** async with `Mapped[]` type hints, `mapped_column()`, `async_sessionmaker`
-- **PostgreSQL 16** (Alpine) via `asyncpg`
-- **Alembic** for migrations
-- **Auth:** PIN-based with bcrypt + itsdangerous signed cookies (not JWT)
-
-### Frontend
-- **React 18** + TypeScript + Vite 6
-- **TanStack Query v5** for server state (`useQuery`, `useMutation`, `invalidateQueries`)
-- **FullCalendar 6** (dayGrid, timeGrid, interaction plugins)
-- **Tailwind CSS 3** with custom dark theme + accent color CSS variables
-- **Sonner** for toast notifications
-- **Lucide React** for icons
-- Custom shadcn/ui-style components in `frontend/src/components/ui/`
-
-### Infrastructure
-- **Docker Compose** - 3 services: `db`, `backend`, `frontend`
-- **Nginx** (Alpine) serves frontend SPA, proxies `/api/` to backend
-- Frontend served on port **80**, backend on port **8000**
-
-## Authority Links
-
-- [progress.md](progress.md) - Project tracker, milestone status, fix history, outstanding items
-
-## Project Structure
-
-```
-backend/app/
- main.py # FastAPI app, router registration, health endpoint
- config.py # Pydantic BaseSettings (DATABASE_URL, SECRET_KEY)
- database.py # Async engine, session factory, get_db dependency
- models/ # SQLAlchemy 2.0 models (Mapped[] style)
- schemas/ # Pydantic v2 request/response schemas
- routers/ # One router per feature (auth, todos, events, etc.)
-
-frontend/src/
- App.tsx # Routes + ProtectedRoute wrapper
- lib/api.ts # Axios instance + getErrorMessage helper
- hooks/ # useAuth, useSettings, useTheme
- types/index.ts # TypeScript interfaces matching backend schemas
- components/
- ui/ # 12 base components (Button, Dialog, Input, etc.)
- layout/ # AppLayout + Sidebar
- auth/ # LockScreen (PIN setup/login)
- dashboard/ # DashboardPage + widgets
- calendar/ # CalendarPage + EventForm
- todos/ # TodosPage + TodoList + TodoItem + TodoForm
- reminders/ # RemindersPage + ReminderList + ReminderForm
- projects/ # ProjectsPage + ProjectCard + ProjectDetail + forms
- people/ # PeoplePage + PersonCard + PersonForm
- locations/ # LocationsPage + LocationCard + LocationForm
- settings/ # SettingsPage (accent color, PIN change)
-```
-
-## Essential Commands
-
-```bash
-# Build and run all services
-docker-compose up --build
-
-# Rebuild single service after changes
-docker-compose up --build backend
-docker-compose up --build frontend
-
-# View logs
-docker-compose logs -f
-docker-compose logs -f backend
-
-# Reset database (destroys all data)
-docker-compose down -v && docker-compose up --build
-
-# Stop everything
-docker-compose down
-```
-
-## API Routes
-
-All routes require auth (signed cookie) except `/api/auth/*` and `/health`.
-
-| Prefix | Resource |
-|--------------------|-----------------|
-| `/api/auth` | PIN setup/login/logout/status |
-| `/api/todos` | Todos CRUD + toggle |
-| `/api/events` | Calendar events CRUD |
-| `/api/reminders` | Reminders CRUD + dismiss |
-| `/api/projects` | Projects + nested tasks CRUD |
-| `/api/people` | People CRUD |
-| `/api/locations` | Locations CRUD |
-| `/api/settings` | Settings + PIN change |
-| `/api/dashboard` | Dashboard aggregation |
-| `/api/upcoming` | Unified upcoming items |
-
-## Stop Conditions
-
-- **Do not** add timezone info to datetime strings sent to the backend
-- **Do not** use `datetime.utcnow()` - use `datetime.now(timezone.utc)` instead (deprecated in 3.12)
-- **Do not** return relationships from async endpoints without `selectinload()`
-- **Do not** use `curl` in backend Docker healthchecks (not available in python:slim)
-- **Do not** use `git push --force` or destructive git operations without explicit approval
diff --git a/progress.md b/progress.md
deleted file mode 100644
index 64bac85..0000000
--- a/progress.md
+++ /dev/null
@@ -1,351 +0,0 @@
-# UMBRA - Project Progress
-
-## Overview
-Personal life administration web app with dark theme, accent color customization, and Docker deployment.
-
-**Stack:** React + TypeScript | FastAPI + SQLAlchemy | PostgreSQL | Docker Compose
-
----
-
-## Milestone Tracker
-
-### Phase 1: Scaffolding & Infrastructure
-- [x] `docker-compose.yaml` - 3-service architecture (db, backend, frontend)
-- [x] `.env` / `.env.example` - Environment configuration
-- [x] `.gitignore` - Root gitignore
-- [x] Backend: FastAPI app skeleton (`app/main.py`, `config.py`, `database.py`)
-- [x] Backend: `requirements.txt` with all Python dependencies
-- [x] Backend: Alembic migration setup (`alembic.ini`, `env.py`, initial migration)
-- [x] Backend: `start.sh` startup script
-- [x] Backend: `Dockerfile` - Python 3.12-slim
-- [x] Frontend: Vite + React scaffold (`package.json`, `vite.config.ts`, `tsconfig.json`)
-- [x] Frontend: Tailwind CSS + PostCSS configuration
-- [x] Frontend: `index.html` entry point
-- [x] Frontend: `nginx.conf` - SPA serving + API proxy
-- [x] Frontend: `Dockerfile` - Multi-stage node build + nginx serve
-- [x] Verify `docker-compose up --build` boots all services
-
-### Phase 2: Auth & Layout
-- [x] Backend: Settings model + schema
-- [x] Backend: Auth router (PIN setup, login, logout, status with bcrypt + itsdangerous)
-- [x] Frontend: `LockScreen.tsx` - PIN setup/login UI
-- [x] Frontend: `useAuth.ts` hook (TanStack Query)
-- [x] Frontend: `AppLayout.tsx` + `Sidebar.tsx` - Main layout with navigation
-- [x] Frontend: Accent color theming system (`useTheme.ts`, CSS custom properties)
-- [x] Frontend: 12 shadcn/ui components (button, card, input, dialog, select, badge, etc.)
-
-### Phase 3: Core Features
-- [x] Backend: Todo model, schema, router (CRUD + toggle + filters)
-- [x] Frontend: `TodosPage`, `TodoList`, `TodoItem`, `TodoForm`
-- [x] Backend: Calendar Event model, schema, router (CRUD + date range filter)
-- [x] Frontend: `CalendarPage` (FullCalendar integration), `EventForm`
-- [x] Frontend: FullCalendar dark theme CSS overrides in `index.css`
-- [x] Backend: Reminder model, schema, router (CRUD + dismiss)
-- [x] Frontend: `RemindersPage`, `ReminderList`, `ReminderForm`
-
-### Phase 4: Project Management
-- [x] Backend: Project model with tasks relationship + cascade delete
-- [x] Backend: ProjectTask model, schema, router (nested CRUD under projects)
-- [x] Frontend: `ProjectsPage`, `ProjectCard`, `ProjectDetail`, `ProjectForm`, `TaskForm`
-
-### Phase 5: People & Locations
-- [x] Backend: Person model, schema, router (CRUD + search)
-- [x] Frontend: `PeoplePage`, `PersonCard`, `PersonForm`
-- [x] Backend: Location model, schema, router (CRUD + category filter)
-- [x] Frontend: `LocationsPage`, `LocationCard`, `LocationForm`
-
-### Phase 6: Dashboard & Upcoming
-- [x] Backend: Dashboard aggregation endpoint (stats, events, todos, reminders)
-- [x] Backend: Upcoming endpoint (unified items sorted by date)
-- [x] Frontend: `DashboardPage` with all widgets + upcoming integration
-- [x] Frontend: `StatsWidget` (projects, people, locations counts)
-- [x] Frontend: `UpcomingWidget` (unified timeline with type icons)
-- [x] Frontend: `TodoWidget` (upcoming todos with priority badges)
-- [x] Frontend: `CalendarWidget` (today's events with color indicators)
-- [x] Frontend: Active reminders section in dashboard
-
-### Phase 6b: Project Subtasks
-- [x] Backend: Self-referencing `parent_task_id` FK on `project_tasks` with CASCADE delete
-- [x] Backend: Alembic migration `002_add_subtasks.py`
-- [x] Backend: Schema updates — `parent_task_id` in create, nested `subtasks` in response, `model_rebuild()`
-- [x] Backend: Chained `selectinload` for two-level subtask loading, parent validation on create
-- [x] Frontend: `ProjectTask` type updated with `parent_task_id` and `subtasks`
-- [x] Frontend: `TaskForm` accepts `parentTaskId` prop, context-aware dialog title
-- [x] Frontend: `ProjectDetail` — expand/collapse chevrons, subtask progress bars, indented subtask cards
-
-### Phase 7: Settings & Polish
-- [x] Backend: Settings router (get/update settings, change PIN)
-- [x] Frontend: `SettingsPage` (accent color picker, upcoming range, PIN change)
-- [x] Integration fixes: All frontend API paths match backend routes
-- [x] Integration fixes: HTTP methods (PUT for updates, PATCH for toggle/dismiss)
-- [x] Integration fixes: Type definitions match backend response schemas
-- [ ] Integration testing (end-to-end CRUD verification) <-- POST-BUILD
-- [x] Final styling pass (responsive sidebar, empty states, loading skeletons)
-
----
-
-## Integration Fixes Applied
-These were caught during review and fixed:
-
-| Issue | Fix |
-|-------|-----|
-| Settings field `upcoming_days_range` | Renamed to `upcoming_days` |
-| CalendarEvent fields `start`/`end` | Renamed to `start_datetime`/`end_datetime` |
-| Reminder field `dismissed` | Renamed to `is_dismissed`, added `is_active` |
-| Project status values | Changed from `active/on_hold` to `not_started/in_progress/completed` |
-| Calendar API path `/calendar/events` | Fixed to `/events` |
-| All update forms using `api.patch` | Fixed to `api.put` (backend uses PUT) |
-| Todo toggle using generic PATCH | Fixed to `api.patch('/todos/{id}/toggle')` |
-| Reminder dismiss using generic PATCH | Fixed to `api.patch('/reminders/{id}/dismiss')` |
-| Settings update using PATCH | Fixed to `api.put` |
-| PIN change path `/auth/change-pin` | Fixed to `/settings/pin` |
-| Dashboard data shape mismatch | Aligned TodoWidget, CalendarWidget with actual API response |
-| Missing UpcomingWidget in dashboard | Added with `/api/upcoming` fetch |
-
-## Post-Build Fixes Applied
-These were found during first Docker build and integration testing:
-
-| Issue | Fix |
-|-------|-----|
-| `Person.relationship` column shadowed SQLAlchemy's `relationship()` function | Aliased import to `sa_relationship` in `person.py` |
-| Missing `backend/app/__init__.py` | Created empty `__init__.py` for Python package recognition |
-| Backend port 8000 not exposed in `docker-compose.yaml` | Added `ports`, `healthcheck`, and `condition: service_healthy` |
-| `get_db()` redundant `session.close()` inside `async with` | Removed `finally: await session.close()` |
-| `datetime.utcnow()` deprecated in Python 3.12 | Replaced with `datetime.now(timezone.utc)` in `todos.py` |
-| Calendar date selection wiped start/end fields | Added `formatInitialDate()` to convert date-only to `datetime-local` format |
-| Dashboard "today's events" used server UTC time | Added `client_date` query param so frontend sends its local date |
-| Calendar drag-and-drop didn't persist | Added `eventDrop` handler with backend PUT call |
-| Timed event drag-and-drop sent timezone-aware datetimes to naive DB column | Used `toLocalDatetime()` helper instead of `.toISOString()` |
-| All-day event dates empty when editing (datetime vs date format mismatch) | Added `formatForInput()` to normalize values for `date` vs `datetime-local` inputs |
-| Project create/update `MissingGreenlet` error (lazy load in async context) | Re-fetch with `selectinload(Project.tasks)` after commit in `projects.py` |
-| Generic error toasts gave no useful information | Added `getErrorMessage()` helper to `api.ts`, updated all 8 form components |
-| Sidebar not responsive on mobile | Split into desktop sidebar + mobile overlay with hamburger menu in `AppLayout` |
-| Plain "Loading..." text on all pages | Created `Skeleton`, `ListSkeleton`, `GridSkeleton`, `DashboardSkeleton` components |
-| Basic empty states with no visual cue | Created `EmptyState` component with icon, message, and action button across all pages |
-| No logout button | Added logout button to sidebar footer with `LogOut` icon and destructive hover style |
-| Todo category filter was case sensitive | Changed to case-insensitive comparison with `.toLowerCase()` |
-| Dialog/popup forms too narrow and cramped | Widened `DialogContent` from `max-w-lg` to `max-w-xl` with mobile margin |
-
----
-
-## Code Review Findings — Round 1 (Senior Review)
-
-### Critical:
-- [x] C1: CORS `allow_origins=["*"]` with `allow_credentials=True` — already restricted to `["http://localhost:5173"]` (`main.py`)
-- [x] C2: `datetime.now(timezone.utc)` in naive column — changed to `datetime.now()` (`todos.py`)
-- [x] C3: Session cookie missing `secure` flag — added `secure=True` + `_set_session_cookie` helper (`auth.py`)
-- [x] C4: No PIN length validation on backend — added `field_validator` for min 4 chars (`schemas/settings.py`)
-
-### High:
-- [x] H1: No brute-force protection on login — added in-memory rate limiting (5 attempts / 5 min) (`auth.py`)
-- [x] H2: `echo=True` on SQLAlchemy engine — set to `False` (`database.py`)
-- [x] H3: Double commit pattern — removed auto-commit from `get_db`, routers handle commits (`database.py`)
-- [ ] H4: `Person.relationship` column shadows SQLAlchemy name — deferred (requires migration + schema changes across stack)
-- [x] H5: Upcoming events missing lower bound filter — added `>= today_start` (`dashboard.py`)
-- [x] H6: `ReminderForm.tsx` doesn't slice `remind_at` — added `.slice(0, 16)` for datetime-local input
-
-### Medium:
-- [x] M1: Default `SECRET_KEY` is predictable — added stderr warning on startup (`config.py`)
-- [x] M3: `create_all` in lifespan conflicts with Alembic — removed (`main.py`)
-- [x] M6: No confirmation dialog before destructive actions — added `window.confirm()` on all delete buttons
-- [x] M7: Authenticated users can still navigate to `/login` — added `Navigate` redirect in `LockScreen.tsx`
-- [x] L1: Error handling in LockScreen used `error: any` — replaced with `getErrorMessage` helper
-
-## Code Review Findings — Round 2 (Senior Review)
-
-### Critical:
-- [x] C1: Default SECRET_KEY only warns, doesn't block production — added env-aware fail-fast (`config.py`)
-- [x] C2: `secure=True` cookie breaks HTTP development — made configurable via `COOKIE_SECURE` setting (`auth.py`, `config.py`)
-- [x] C3: No enum validation on status/priority fields — added `Literal` types (`schemas/project_task.py`, `todo.py`, `project.py`)
-- [x] C4: Race condition in PIN setup (TOCTOU) — added `select().with_for_update()` (`auth.py`)
-
-### High:
-- [x] H1: Rate limiter memory leak — added stale key cleanup, `del` empty entries (`auth.py`)
-- [ ] H2: Dashboard runs 7 sequential DB queries — deferred (asyncpg single-session limitation)
-- [ ] H3: Subtask eager loading fragile at 2 levels — accepted (business logic enforces single nesting)
-- [x] H4: No `withCredentials` on Axios for Vite dev — added to `api.ts`
-- [x] H5: Logout doesn't invalidate session server-side — added in-memory `_revoked_sessions` set (`auth.py`)
-
-### Medium:
-- [ ] M1: TodosPage fetches all then filters client-side — deferred (acceptable for personal app scale)
-- [x] M2: Dashboard uses `.toISOString()` violating CLAUDE.md rules — replaced with local date formatter (`DashboardPage.tsx`)
-- [x] M3: No CSP header in nginx — added CSP + Referrer-Policy, removed deprecated X-XSS-Protection (`nginx.conf`)
-- [x] M4: Event date filtering misses range-spanning events — fixed range overlap logic (`events.py`)
-- [x] M5: `accent_color` accepts arbitrary strings — added `Literal` validation for allowed colors (`schemas/settings.py`)
-- [x] M6: Logout `delete_cookie` doesn't match `set_cookie` attributes — matched all cookie params (`auth.py`)
-- [x] M7: bcrypt silently truncates PIN at 72 bytes — added max 72 char validation (`schemas/settings.py`)
-
-### Low:
-- [x] L1: `as any` type casts in frontend forms — replaced with proper `Type['field']` casts (`TaskForm.tsx`, `ProjectForm.tsx`)
-- [x] L2: Unused imports in `events.py` — false positive, all imports are used
-- [ ] L3: Upcoming endpoint mixes date/datetime string sorting — deferred (works correctly for ISO format)
-- [ ] L4: Backend port 8000 exposed directly, bypassing nginx — deferred (useful for dev)
-- [ ] L5: `parseInt(id!)` without NaN validation — deferred (low risk, route-level protection)
-- [x] L6: `X-XSS-Protection` header is deprecated — removed, replaced with CSP (`nginx.conf`)
-- [x] L7: Missing `Referrer-Policy` header — added `strict-origin-when-cross-origin` (`nginx.conf`)
-
----
-
-## Outstanding Items (Resume Here If Halted)
-
-### Critical (blocks deployment):
-1. ~~**Docker build verification**~~ - DONE: All 3 services boot successfully
-2. ~~**npm install verification**~~ - DONE: Frontend packages install correctly
-
-### Important (blocks functionality):
-3. ~~**Alembic migration test**~~ - DONE: Tables create correctly on first boot
-4. ~~**Auth flow test**~~ - DONE: PIN setup works, PIN change works, session persistence works, logout added
-5. ~~**End-to-end CRUD test**~~ - DONE: All features verified — Calendar, Projects, Todos (create/edit/filter/search), People (CRUD + search), Locations (CRUD + filter), Reminders (CRUD + dismiss), Settings (accent color + PIN)
-
-### Nice to have (polish):
-6. ~~**Responsive sidebar**~~ - DONE: Mobile hamburger menu with overlay, desktop collapse/expand
-7. ~~**Toast notifications**~~ - DONE: All forms now show meaningful error messages via `getErrorMessage()`
-8. ~~**Empty states**~~ - DONE: All pages show icon + message + action button when empty
-9. ~~**Loading skeletons**~~ - DONE: Animated skeleton placeholders replace plain "Loading..." text
-
----
-
-## File Inventory (100+ files total)
-
-### Backend (40 files)
-```
-backend/
-├── Dockerfile
-├── requirements.txt
-├── start.sh
-├── .gitignore
-├── alembic.ini
-├── alembic/
-│ ├── env.py
-│ ├── script.py.mako
-│ └── versions/
-│ ├── 001_initial_migration.py
-│ └── 002_add_subtasks.py
-└── app/
- ├── main.py
- ├── config.py
- ├── database.py
- ├── models/
- │ ├── __init__.py
- │ ├── settings.py
- │ ├── todo.py
- │ ├── calendar_event.py
- │ ├── reminder.py
- │ ├── project.py
- │ ├── project_task.py
- │ ├── person.py
- │ └── location.py
- ├── schemas/
- │ ├── __init__.py
- │ ├── settings.py
- │ ├── todo.py
- │ ├── calendar_event.py
- │ ├── reminder.py
- │ ├── project.py
- │ ├── project_task.py
- │ ├── person.py
- │ └── location.py
- └── routers/
- ├── __init__.py
- ├── auth.py
- ├── dashboard.py
- ├── todos.py
- ├── events.py
- ├── reminders.py
- ├── projects.py
- ├── people.py
- ├── locations.py
- └── settings.py
-```
-
-### Frontend (60+ files)
-```
-frontend/
-├── Dockerfile
-├── nginx.conf
-├── package.json
-├── vite.config.ts
-├── tsconfig.json
-├── tsconfig.node.json
-├── postcss.config.js
-├── tailwind.config.ts
-├── components.json
-├── index.html
-├── .gitignore
-└── src/
- ├── main.tsx
- ├── App.tsx
- ├── index.css (includes FullCalendar dark overrides)
- ├── lib/
- │ ├── utils.ts
- │ └── api.ts
- ├── hooks/
- │ ├── useAuth.ts
- │ ├── useSettings.ts
- │ └── useTheme.ts
- ├── types/
- │ └── index.ts
- └── components/
- ├── ui/ (12 components)
- ├── layout/ (AppLayout, Sidebar)
- ├── auth/ (LockScreen)
- ├── dashboard/ (DashboardPage, StatsWidget, UpcomingWidget, TodoWidget, CalendarWidget, ProjectsWidget)
- ├── todos/ (TodosPage, TodoList, TodoItem, TodoForm)
- ├── calendar/ (CalendarPage, EventForm)
- ├── reminders/ (RemindersPage, ReminderList, ReminderForm)
- ├── projects/ (ProjectsPage, ProjectCard, ProjectDetail, ProjectForm, TaskForm)
- ├── people/ (PeoplePage, PersonCard, PersonForm)
- ├── locations/ (LocationsPage, LocationCard, LocationForm)
- └── settings/ (SettingsPage)
-```
-
-### Root
-```
-docker-compose.yaml
-.env / .env.example
-.gitignore
-progress.md
-```
-
----
-
-## How to Resume Development
-
-If development is halted, pick up from the **Outstanding Items** section above:
-
-1. Check which items are still marked incomplete in the Milestone Tracker
-2. Address **Critical** items first (Docker build verification)
-3. Then **Important** items (auth flow, CRUD testing)
-4. Finally **Polish** items (responsive, loading states)
-
-### Quick Start Commands
-```bash
-# Build and run everything
-docker-compose up --build
-
-# Rebuild just backend after changes
-docker-compose up --build backend
-
-# Rebuild just frontend after changes
-docker-compose up --build frontend
-
-# View logs
-docker-compose logs -f
-
-# View specific service logs
-docker-compose logs -f backend
-docker-compose logs -f frontend
-
-# Reset database (destructive)
-docker-compose down -v && docker-compose up --build
-
-# Stop everything
-docker-compose down
-```
-
-### First-Time Setup
-1. Run `docker-compose up --build`
-2. Navigate to `http://localhost`
-3. You'll see the PIN setup screen (first run)
-4. Create a PIN and you'll be redirected to the dashboard
-5. Use the sidebar to navigate between features