diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 4fb60f5..33a40f7 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -636,7 +636,7 @@ Plans:
**Goal:** Make the household timezone an explicit, stored, user-changeable setting — auto-detected from the browser at first run, changeable from the role-gated /admin Settings — and route the server-side all-day "9 AM local" reminder computation through it (replacing the implicit `process.env.TZ` fallback), without touching the already-correct browser-local display/timed-write path.
**Requirements**: TBD (decision contract D-01..D-07 from 18-CONTEXT.md)
**Depends on:** Phase 10 (admin role + `/admin` Settings + `app_config`); Phase 11 (all-day reminder computation this rewires). Independent of Phase 17. Phase 12 (setup wizard) not required — seeding is self-contained.
-**Plans:** 3/4 plans executed
+**Plans:** 4/4 plans complete
Plans:
**Wave 1**
@@ -650,6 +650,6 @@ Plans:
**Wave 3** *(blocked on Wave 2 completion)*
-- [ ] 18-04-PLAN.md — PWA Timezone section in /admin Settings (searchable IANA picker + detected-zone seed) + client fns (D-02/D-04)
+- [x] 18-04-PLAN.md — PWA Timezone section in /admin Settings (searchable IANA picker + detected-zone seed) + client fns (D-02/D-04)
**UI hint**: yes
diff --git a/.planning/STATE.md b/.planning/STATE.md
index 43b9d3b..04ed418 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -2,16 +2,16 @@
gsd_state_version: 1.0
milestone: v1.1
milestone_name: Operability & Polish
-status: executing
+status: verifying
stopped_at: Phase 18 Plan 03 complete — broker rewire done; plan 4 of 4 is next
-last_updated: "2026-06-15T02:33:25.687Z"
+last_updated: "2026-06-15T02:46:09.819Z"
last_activity: 2026-06-15
progress:
total_phases: 23
- completed_phases: 9
+ completed_phases: 10
total_plans: 36
- completed_plans: 35
- percent: 39
+ completed_plans: 36
+ percent: 43
---
# Project State
@@ -27,7 +27,7 @@ See: .planning/PROJECT.md (updated 2026-06-10)
Phase: 18 (auto-timezone-detection-and-ability-to-change-timezone) — EXECUTING
Plan: 4 of 4
-Status: Ready to execute
+Status: Phase complete — ready for verification
Last activity: 2026-06-15
### ✅ Resolved Checkpoint — Phase 15 Plan 15-03 Task 2 (human-action)
@@ -110,6 +110,7 @@ _Updated after each plan completion_
| Phase 18-auto-timezone-detection-and-ability-to-change-timezone P01 | 2 | 2 tasks | 2 files |
| Phase 18 P02 | 3 | 2 tasks | 2 files |
| Phase 18 P03 | 28 | 2 tasks | 4 files |
+| Phase 18 P04 | 15 | 3 tasks | 3 files |
## Accumulated Context
@@ -256,7 +257,7 @@ Recent decisions affecting current work:
## Session Continuity
-Last session: 2026-06-15T02:33:25.669Z
+Last session: 2026-06-15T02:46:09.800Z
Stopped at: Phase 18 Plan 03 complete — broker rewire done; plan 4 of 4 is next
Resume file: None
diff --git a/.planning/phases/18-auto-timezone-detection-and-ability-to-change-timezone/18-04-SUMMARY.md b/.planning/phases/18-auto-timezone-detection-and-ability-to-change-timezone/18-04-SUMMARY.md
new file mode 100644
index 0000000..717c3cb
--- /dev/null
+++ b/.planning/phases/18-auto-timezone-detection-and-ability-to-change-timezone/18-04-SUMMARY.md
@@ -0,0 +1,126 @@
+---
+phase: 18-auto-timezone-detection-and-ability-to-change-timezone
+plan: "04"
+subsystem: pwa
+tags: [timezone, iana, admin, react, tanstack-query, playwright, ui]
+
+# Dependency graph
+requires:
+ - phase: 18-02
+ provides: GET/PUT /api/admin/config/timezone (consumed by fetchAdminTimezone/setAdminTimezone)
+
+provides:
+ - fetchAdminTimezone() — GET /api/admin/config/timezone in PWA API client
+ - setAdminTimezone(tz) — PUT /api/admin/config/timezone in PWA API client
+ - AdminTimezoneResponse interface (timezone: string, isExplicitlySet: boolean)
+ - Timezone section in AdminPage (/admin) — searchable IANA picker, save, detected-zone affordance
+
+affects:
+ - apps/pwa/src/api/client.ts
+ - apps/pwa/src/routes/AdminPage.tsx
+ - apps/pwa/e2e/timezone-verify.spec.ts (new verification spec)
+
+# Tech tracking
+tech-stack:
+ added: []
+ patterns:
+ - Intl.supportedValuesOf('timeZone') guarded for runtime availability (datalist population)
+ - ARIA combobox role for — Playwright locator uses getByRole('combobox') not getByRole('textbox')
+ - useQuery + useMutation with invalidateQueries on success (same pattern as calendars section)
+
+key-files:
+ created:
+ - apps/pwa/e2e/timezone-verify.spec.ts
+ modified:
+ - apps/pwa/src/api/client.ts
+ - apps/pwa/src/routes/AdminPage.tsx
+
+key-decisions:
+ - "Removed AdminTimezoneResponse from AdminPage.tsx import list — ESLint no-unused-vars; type is inferred from useQuery return"
+ - "Input with list= attribute has ARIA combobox role in Chromium, not textbox — Playwright e2e uses getByRole('combobox')"
+ - "timezoneInput state is null when the user has not interacted — effectiveTimezoneInput = timezoneInput ?? storedTimezone preserves stored value as pre-fill"
+ - "setTimezoneInput(null) on mutation success resets local override so save button re-disables to match new stored value"
+
+requirements-completed: [D-02, D-04]
+
+# Metrics
+duration: 15min
+completed: 2026-06-15
+---
+
+# Phase 18 Plan 04: Admin Timezone UI Summary
+
+**Searchable IANA timezone picker in /admin Settings — fetchAdminTimezone/setAdminTimezone in client.ts + Timezone section in AdminPage.tsx — verified end-to-end via Playwright with the real 18-02 endpoints**
+
+## Performance
+
+- **Duration:** ~15 min
+- **Started:** 2026-06-15T02:30:00Z
+- **Completed:** 2026-06-15T02:45:03Z
+- **Tasks:** 3 (2 auto + 1 playwright-verified checkpoint)
+- **Files modified/created:** 3
+
+## Accomplishments
+
+- Added `AdminTimezoneResponse` interface + `fetchAdminTimezone()` + `setAdminTimezone()` to `apps/pwa/src/api/client.ts`, following the exact pattern of `fetchAdminCalendars` / `setSharedCalendar` (credentials: include, redirect: manual, handleAuthResponse)
+- Added Timezone section to `AdminPage.tsx` after the Shared Calendar section (with `marginBottom` on the preceding section for spacing)
+- Timezone section features: 4-state loading/error/data pattern; `` + `