diff --git a/.planning/phases/20-admin-member-editor-form-declutter/20-CONTEXT.md b/.planning/phases/20-admin-member-editor-form-declutter/20-CONTEXT.md
new file mode 100644
index 0000000..fe9e36e
--- /dev/null
+++ b/.planning/phases/20-admin-member-editor-form-declutter/20-CONTEXT.md
@@ -0,0 +1,112 @@
+# Phase 20: Admin Member Editor & Form Declutter - Context
+
+**Gathered:** 2026-06-18
+**Status:** Ready for planning
+
+
+## Phase Boundary
+
+Rework the **admin Members panel** (`apps/pwa/src/routes/AdminPage.tsx`, "Members & Accounts" tab) so an admin edits all of a member's details from **one editor** instead of scattered per-row action buttons:
+
+- Replace the per-row `Rotate` / `Add credential` button **and** the separate `Reset password` button with a single member editor opened from the row.
+- The editor changes: **display name**, **local-login password**, the **Fastmail/CalDAV app password** (calendar credential), and the member's **admin flag (`is_admin`)** — using clear, non-jargon labels that **retire the "Rotate" term**.
+- Collapse the always-open inline **Add member** form behind a single "Add member" trigger.
+
+Primarily a client-side `AdminPage` + `CredentialSheet` rework over the existing `/api/admin` surface. **No new auth/authorization boundary** — everything stays behind `requireAdmin`. One small new *route* (member-profile update) is in scope; it is not a new boundary. Seeded by the gripe that "Rotate" for the app password is unintuitive.
+
+**Out of scope (deferred):** editable member color, admin-driven OIDC link/unlink, member deletion/removal.
+
+
+
+## Implementation Decisions
+
+### Editor field scope
+- **D-01:** The editor exposes **four** things: display name, local-login password, Fastmail/CalDAV app password, and the **admin toggle (`is_admin`)**. Color, OIDC link/unlink, and remove-member are explicitly deferred (see Deferred Ideas).
+- **D-02:** **Editing display name + `is_admin` needs one new route** within the existing `requireAdmin` boundary — today `displayName` is only written at member-create (`POST /members`) and there is no member-update route. Recommended shape: a single `PATCH /api/admin/members/:id` (or `POST`) accepting `displayName` and/or `is_admin`; exact verb/shape is the planner's call. `AdminMember` (`apps/pwa/src/api/client.ts:563`) and the `GET /members` select (`apps/api/src/routes/admin.ts:102`) must surface `isAdmin` for the toggle's initial state.
+
+### Admin toggle safety
+- **D-03:** **Server blocks demoting the last admin.** Toggling `is_admin` off is rejected (409/422) when the target is the only remaining admin; self-demotion is permitted only when another admin exists. The client surfaces this as a clear inline error. The Phase 19 break-glass CLI/host command remains the true lockout-recovery path ([[19-CONTEXT]] D-13) — no new role/capability model.
+
+### Edit affordance
+- **D-04:** **Whole-row tap opens the editor**, with a trailing chevron / edit icon as the affordance signal. The current per-row action buttons (`Rotate`/`Add credential`, `Reset password`) are removed from `MemberRow`. Big mobile tap target; matches the low-friction, warm aesthetic.
+
+### Editor layout & save model
+- **D-05:** **One sheet, per-section save** — not a single combined Save. Sections:
+ 1. **Profile** — display name input + admin toggle, with one Save (writes the new member-profile route; subject to D-03 guard).
+ 2. **Set new password** — optional, **write-only** (blank = unchanged), with confirm; maps to existing `POST /members/:id/password` (`admin.ts:225`). Only shown for members with a local credential (`hasLocalCredential`).
+ 3. **Set app password** — optional, **write-only**; collects Fastmail email + app password, **CalDAV-validated** before store; maps to existing `POST /credentials` (`admin.ts:279`).
+ Each section maps 1:1 to an endpoint, avoiding partial-failure ambiguity when CalDAV validation fails. Passwords are never prefilled/returned to the client (preserve T-10-15/T-10-16).
+- **D-06:** **Retire "Rotate" copy** everywhere; use plain labels (e.g. "Set app password" / "Update calendar password"). The standalone `ResetPasswordSheet` (currently in `AdminPage.tsx`) is **folded into** the editor's "Set new password" section — no separate reset sheet remains.
+
+### Add-member declutter
+- **D-07:** **"Add member" opens a sheet**, not an inline-expanded form. Preferred: the **same Member sheet in a create mode** (compose_event-style — one component, create vs edit), so the panel collapses to a clean member list + a single "Add member" trigger. Create mode keeps today's fields (display name, username, initial password + confirm → `POST /members`).
+
+### Claude's Discretion
+- Exact new-route verb/path/shape for the member-profile update (D-02).
+- Whether the Member editor and Add-member sheet are literally one component with a mode prop vs two siblings sharing a base — planner's call, but D-07 prefers unification.
+- In edit mode, whether the app-password section prefills/display the stored Fastmail email (read-only) or requires re-entry — minor UX detail for planning; note the stored `fastmailEmail` exists on the credential.
+- Icon choice for the row chevron/edit affordance (lucide, consistent with existing `CheckCircle`/`AlertCircle` usage).
+
+
+
+## Canonical References
+
+**Downstream agents MUST read these before planning or implementing.**
+
+### Phase definition
+- `.planning/ROADMAP.md` §"Phase 20: Admin Member Editor & Form Declutter" — goal + the open-scope note this discussion resolved.
+
+### Code being reworked
+- `apps/pwa/src/routes/AdminPage.tsx` — the Members panel, `MemberRow`, the inline Add-member form, and the standalone `ResetPasswordSheet` being consolidated.
+- `apps/pwa/src/components/CredentialSheet.tsx` — dialog/focus-trap/Escape + CalDAV-validation sheet to generalize into the Member editor (and Add-member create mode).
+- `apps/pwa/src/api/client.ts` — `AdminMember` type (`:563`), admin fetchers (`fetchAdminMembers`, `fetchCreateMember`, `fetchAdminResetPassword`, `saveCredential`); add the new member-profile fetcher + `isAdmin` field here.
+- `apps/api/src/routes/admin.ts` — existing endpoints: `GET /members` (`:102`), `POST /members` (`:143`), `POST /members/:id/password` (`:225`), `POST /credentials` (`:279`); add the member-profile update route here behind the same `requireAdmin`.
+
+### Prior decisions that constrain this phase
+- `.planning/phases/19-local-auth-no-oidc-mode/19-CONTEXT.md` — D-11 (password lifecycle = self-change + admin-reset, no email reset), D-12 (OIDC link is self-service only, deletes local credential), D-13 (single `is_admin`, break-glass = CLI/host, no role split).
+
+
+
+## Existing Code Insights
+
+### Reusable Assets
+- **`CredentialSheet`**: full dialog scaffold (role=dialog, `aria-modal`, `useFocusTrap`, Escape-to-close, focus-return-to-trigger, phone bottom-sheet vs desktop modal, CalDAV-validating mutation). Generalize into the Member editor + Add-member create mode.
+- **`ResetPasswordSheet`** (in `AdminPage.tsx`): password + confirm + mismatch validation logic — folds into the editor's "Set new password" section (D-06).
+- **`useFocusTrap`, `useIsPhone`** hooks — reuse for the new sheet.
+- **Existing endpoints** cover login-password reset and app-password set; only the member-profile (displayName + is_admin) write is new.
+
+### Established Patterns
+- Two-tab `AdminPage` ("Members & Accounts" / "Settings") with roving-tabindex tabs — keep; this phase only restructures the Members tab body.
+- Mutations invalidate `['admin','members']` (+ `['me']` for credential changes) on success; success toast via `showToast` (D-08 pattern). Reuse for editor saves.
+- Write-only password handling: never prefill, never log, `autoComplete="new-password"` (T-10-15/16).
+
+### Integration Points
+- New `PATCH/POST /api/admin/members/:id` mounts on `adminRouter` behind `requireAdmin` (no new boundary).
+- `GET /members` select + `AdminMember` type gain `isAdmin` so the editor's toggle has initial state.
+- `MemberRow` becomes a single tappable row (chevron affordance), dropping its action-button cluster.
+
+
+
+## Specific Ideas
+
+- "Same sheet, create vs edit mode" is explicitly modeled on the Fastmail `compose_event` pattern (one widget, `id` present = edit, absent = create) — apply that shape to the Member sheet.
+- Labels must read for a non-technical household member: retire "Rotate"; prefer "Set app password" / "Set new password" / plain "Save".
+
+
+
+## Deferred Ideas
+
+- **Editable member color** — colors are currently derived by row index (`var(--color-member-N)`); there is no stored per-member color to edit. Would need schema + assignment UX. → backlog / future phase.
+- **Admin-driven OIDC link/unlink** — Phase 19 D-12 makes OIDC linking a self-service action performed *as that user*, never by an admin. Admin-side link/unlink is a different security model. → out of scope.
+- **Remove / delete member** — destructive, with cascade concerns (events, lists, credentials, last-admin). Not part of the gripe-seeded scope. → backlog / future phase.
+
+### Reviewed Todos (not folded)
+- "Gitea CI — full regression + Docker publish" (score 0.6) — stale keyword match (already delivered as Phase 8); unrelated to this UI phase.
+- "PWA phone layout — BottomTabBar overlaps FAB + legend" (score 0.4) — already addressed in Phase 17; unrelated.
+
+
+
+---
+
+*Phase: 20-admin-member-editor-form-declutter*
+*Context gathered: 2026-06-18*
diff --git a/.planning/phases/20-admin-member-editor-form-declutter/20-DISCUSSION-LOG.md b/.planning/phases/20-admin-member-editor-form-declutter/20-DISCUSSION-LOG.md
new file mode 100644
index 0000000..7a684e5
--- /dev/null
+++ b/.planning/phases/20-admin-member-editor-form-declutter/20-DISCUSSION-LOG.md
@@ -0,0 +1,83 @@
+# Phase 20: Admin Member Editor & Form Declutter - Discussion Log
+
+> **Audit trail only.** Do not use as input to planning, research, or execution agents.
+> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
+
+**Date:** 2026-06-18
+**Phase:** 20-admin-member-editor-form-declutter
+**Areas discussed:** Editor field scope, Edit affordance, Editor layout & save model, Add-member declutter, Admin toggle safety
+
+---
+
+## Editor field scope
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Core 3 only | Display name + local login password + app password; defer admin toggle/color/OIDC/remove. | |
+| Core 3 + admin toggle | Also flip `is_admin` from the editor, with a last-admin guard. | ✓ |
+
+**User's choice:** "The entire scope plus admin toggle" — core 3 fields plus the `is_admin` toggle.
+**Notes:** Color, OIDC link/unlink, and remove-member stay deferred. Display name + admin toggle require one new within-`requireAdmin` route (no member-update route exists today).
+
+---
+
+## Edit affordance
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Whole-row tap + chevron | Tapping anywhere on the member row opens the editor; trailing chevron signals it. | ✓ |
+| Name link + pencil button | Literal roadmap wording — name link + dedicated edit icon. | |
+
+**User's choice:** Whole-row tap + chevron.
+**Notes:** Removes the per-row `Rotate`/`Add credential` + `Reset password` button cluster.
+
+---
+
+## Editor layout & save model
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| One sheet, per-section save | Name+toggle save; "Set new password"; "Set app password" — each independent, maps 1:1 to an endpoint. | ✓ |
+| One sheet, single combined Save | One Save writes every changed field; needs partial-failure handling for CalDAV validation. | |
+
+**User's choice:** One sheet, per-section save.
+**Notes:** Avoids partial-failure ambiguity when CalDAV validation fails mid-save. Passwords stay write-only (blank = unchanged).
+
+---
+
+## Add-member declutter
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Open as a sheet | "Add member" opens a sheet — ideally the same Member sheet in create mode. | ✓ |
+| Expand inline form | Button toggles the existing inline form visible/hidden in place. | |
+
+**User's choice:** Open as a sheet.
+**Notes:** Prefer the compose_event-style one-component create-vs-edit pattern so the panel collapses to a clean list + one button.
+
+---
+
+## Admin toggle safety
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Block demoting last admin | Server rejects toggling `is_admin` off when they're the only admin; self-demotion only if another admin exists. | ✓ |
+| Warn but allow | Confirm dialog when demoting the last admin/yourself, but permit it; rely on break-glass CLI. | |
+
+**User's choice:** Block demoting the last admin (server-enforced).
+**Notes:** Phase 19 break-glass CLI/host command remains the true lockout-recovery path; no new role model.
+
+---
+
+## Claude's Discretion
+
+- Exact verb/path/shape of the new member-profile update route (`displayName` + `is_admin`).
+- Whether the Member editor and Add-member sheet are literally one component (mode prop) vs two siblings on a shared base.
+- Whether the app-password section prefills the stored Fastmail email (read-only) or requires re-entry in edit mode.
+- Chevron/edit icon choice for the row affordance.
+
+## Deferred Ideas
+
+- Editable member color (no stored per-member color — derived by row index).
+- Admin-driven OIDC link/unlink (Phase 19 D-12: self-service only).
+- Remove / delete member (destructive, cascade concerns).