diff --git a/.planning/phase-A6-report.md b/.planning/phase-A6-report.md
new file mode 100644
index 000000000..ad9170f2f
--- /dev/null
+++ b/.planning/phase-A6-report.md
@@ -0,0 +1,106 @@
+# Phase A6 — Settings mobile audit + consistency
+
+**Owner:** A6 agent (Wave A, parallel with A1-A5, A7-A8)
+**Date:** 2026-05-10
+**Result:** done
+
+Audit findings and the fix plan live in
+[`.planning/phase-A6-settings-audit.md`](./phase-A6-settings-audit.md).
+The audit is keyed to `before/` screenshots captured against
+`https://healthlog.bombeck.io` at Pixel-5 (393×851) using Marc's
+session cookie; raw geometry was extracted with
+`scripts/audit-a6-v2.mjs` to spot the height mismatches the
+human eye missed.
+
+## What was wrong
+
+- **Four input heights in the same shell.** The shared ` `
+ primitive renders at 36 px (`h-9`) but Settings broke the contract
+ at three points: the AI active-provider native `` was
+ `h-10` (40 px), the AI fallback-chain "Add provider" select was
+ `h-8` (32 px), and the Dashboard "Compare to" `` was
+ `min-h-11` (44 px). Visible whenever two cards stacked on top of
+ each other.
+- **Action-button overflow.** "Restart onboarding tour" lived in a
+ `flex justify-between` row next to its card title. On Pixel-5 the
+ button (216 px wide) overflowed the right edge of the parent card
+ by ~48 px because nothing forced a wrap. The "Change password"
+ button used the same pattern and was on the borderline.
+- **Sprache buried.** The locale switch was paired with date-of-birth
+ inside the Profile card grid, implying it was a profile attribute
+ (it isn't — it's a cookie-backed UI preference).
+- **Three competing `space-y-*` strides** inside Settings cards
+ (`space-y-3`, `space-y-4`, `space-y-5`) — outer rhythm was already
+ `space-y-6` consistently.
+
+## What was fixed (5 commits)
+
+1. `957f8e9` — `fix(settings): equalize input heights across all
+ settings sections`. AI active-provider select `h-10` → `h-9`, AI
+ add-provider select `h-8` → `h-9`, Dashboard "Compare to" trigger
+ loses `min-h-11` so the default `h-9` applies.
+2. `9fda634` — `fix(settings): action-button placement consistent
+ across sections (right-side desktop, stacked mobile)`. Account →
+ Password, Account → Restart onboarding tour and Dashboard → Reset
+ to defaults all use `flex-col` on `=sm`,
+ so the button stacks below the title on mobile (full-width) and
+ right-aligns next to the title on desktop. Description paragraph
+ pulled into the title cluster on the two account cards so each
+ row is a clean `` flex pair.
+3. `1075784` — `fix(settings): Sprache select position + width
+ consistent`. Language lifted out of the dob/language pair into
+ its own row at the bottom of the Profile card. `max-w-xs` on
+ `>=sm` so it doesn't render heavier than other half-width fields.
+ Drive-by: pulled the duplicated native-select class string into a
+ single `NATIVE_SELECT_CLASS` constant so gender + language render
+ identically.
+4. `737b533` — `style(settings): uniform vertical spacing across all
+ sections`. Dashboard layout card `space-y-5` → `space-y-4`. AI
+ provider config forms `space-y-3` → `space-y-4`. Section roots
+ keep `space-y-6` so distinct cards still read as distinct
+ surfaces. Note: `.planning/STATE.md` got bundled into this commit
+ accidentally via index race with A5; STATE content is correct,
+ no semantic harm.
+5. `78f1f3f` — `test(settings): mobile e2e snapshot verifies
+ consistency`. Pixel-5 Playwright spec
+ (`e2e/settings-mobile-consistency.spec.ts`) locks in five
+ invariants: every form input on /settings/account is 36 px,
+ neither password nor tour buttons overflow the card right edge,
+ Sprache and dob no longer share a grid ancestor, the Dashboard
+ "Compare to" trigger is 36 px, every native select on
+ /settings/ai is 36 px. Mobile-only project — desktop skips it.
+
+## Verification
+
+- `pnpm test` — all 1637 tests pass
+- `pnpm typecheck` — zero source-tree errors (the four `.next/types`
+ errors are stale build artefacts from previous milestone's untracked
+ dotted-segment route directories, documented in CLAUDE.md / STATE.md
+ as Phase 0 leftovers)
+- `pnpm lint` — zero errors, 12 pre-existing warnings unrelated to A6
+
+A post-fix Playwright re-screenshot pass against production is gated
+on the v1.4.19 deploy (Phase E). The new e2e spec is the durable
+artifact and runs on every PR.
+
+## What I deliberately did NOT touch
+
+- `src/components/settings/integrations-section.tsx` (A5 owned and
+ shipped during this phase as commits `0dcc91a` + `47a8fc7`).
+ A prettier autofix bundled two trivial reformats of A5's files
+ into my draft "uniform spacing" commit; those reformats were
+ reverted before the final commit landed.
+- `src/components/admin/*` (A7).
+- `src/lib/insights/`, `src/lib/ai/`, `src/components/charts/`,
+ `src/components/insights/` (A1-A4).
+- Any settings copy or i18n keys — the focus stayed on layout, sizing,
+ and spacing per the brief.
+
+## Files touched
+
+- `src/components/settings/account-section.tsx`
+- `src/components/settings/ai-section.tsx`
+- `src/components/settings/dashboard-layout-section.tsx`
+- `e2e/settings-mobile-consistency.spec.ts` (new)
+- `.planning/phase-A6-settings-audit.md` (new — findings table)
+- `.planning/phase-A6-report.md` (this file)
diff --git a/.planning/phase-A6-settings-audit.md b/.planning/phase-A6-settings-audit.md
new file mode 100644
index 000000000..c67191093
--- /dev/null
+++ b/.planning/phase-A6-settings-audit.md
@@ -0,0 +1,118 @@
+# Settings mobile audit (Pixel 5, 393×851)
+
+Captured against production `https://healthlog.bombeck.io` on
+2026-05-10 with Marc's session cookie. Screenshots in
+`/tmp/healthlog-a6/before/-tall.png`. Geometry tables produced
+by `scripts/audit-a6-v2.mjs`.
+
+## Routes covered
+
+| Route | Purpose |
+| ------------------------- | ----------------------------------- |
+| `/settings/account` | profile + password + passkey + tour |
+| `/settings/dashboard` | tile/chart layout + comparison |
+| `/settings/ai` | provider config + fallback chain |
+| `/settings/notifications` | telegram + ntfy + web-push + status |
+| `/settings/export` | doctor report + CSV/JSON |
+
+## Inconsistency table
+
+### Input heights
+
+| Section | Element | Actual | Expected |
+| ------------- | ----------------------------------- | -----: | -------: |
+| account | Username ` ` | 36 | 36 |
+| account | Email ` ` | 36 | 36 |
+| account | Gender native `` | 36 | 36 |
+| account | Height ` ` | 36 | 36 |
+| account | Date of birth ` ` | 36 | 36 |
+| account | Language native `` | 36 | 36 |
+| ai | "Active provider" native `` | **40** | 36 |
+| ai | "Add provider" native `` | **32** | 36 |
+| dashboard | "Compare to" `` | **44** | 36 |
+| export | All date ` ` fields | 36 | 36 |
+| notifications | All telegram + ntfy ` ` | 36 | 36 |
+
+The account section is internally consistent at 36 px. AI and Dashboard
+break the 36-px contract: the AI active-provider select is 40 px, the
+fallback "Add provider" select is 32 px, and Dashboard's "Compare to"
+trigger uses `min-h-11` (44 px). All three are form fields the user
+fills with their finger, so they should match the rest of the app.
+
+### Action-button placement
+
+| Section | Button | Placement on mobile | Overflow? |
+| ------------- | ------------------------------- | ------------------------ | --------------------------------- |
+| account | Save (profile) | bottom of form, right | no |
+| account | Add passkey | bottom of card, right | no |
+| account | **Change password** | inline next to title | borderline (336 / 361) |
+| account | **Restart onboarding tour** | inline next to title | **YES — overflows card by 48 px** |
+| ai | Disconnect | full block, sm | no |
+| dashboard | Reset to defaults | inline next to title, sm | no |
+| export | Configure & generate / Download | bottom of card, sm | no |
+| notifications | Send test (status card) | inline | no |
+
+Critical bug: on a 393-px viewport the "Restart onboarding tour" button
+overflows the right edge of its parent card by ~48 px. The same flex
+pattern (`flex items-center justify-between gap-2`) is used by the
+password-reset card; with longer button copy it crosses the card edge.
+
+### Spacing inconsistencies
+
+| Section | Section-level spacing | Card-internal spacing |
+| ------------- | --------------------- | --------------------------------------------- |
+| account | `space-y-6` | `space-y-4` (form), `space-y-2` (field group) |
+| dashboard | `space-y-6` | `space-y-5` (card), `space-y-2` (field group) |
+| ai | `space-y-6` | `space-y-6` (card), `space-y-3` (sub-card) |
+| notifications | `space-y-6` | per-card varies |
+| export | `space-y-6` | `gap-3` grid + `mt-3 space-y-3` (card) |
+
+The `space-y-6` outer rhythm is consistent; the card-internal rhythm
+varies between `space-y-3` / `space-y-4` / `space-y-5`. Visible because
+the AI card crams its sub-cards with `p-4` while the Account card uses
+`p-6` — equivalent fields end up at different distances apart between
+sections.
+
+### Sprache-Menü specifics
+
+The Sprache (language) `` lives in the same row as the date-of-
+birth field on the Account → Profile form. Both render at 36 px on
+mobile, so technically consistent — but the Sprache field is paired
+with a row that already carries a hint paragraph below the date field,
+which makes the column heights asymmetric. On `=sm`.
+
+## Decisions
+
+1. **Standardise input height to 36 px** (`h-9`). Replace the 40-px
+ ai-active-provider select, the 32-px add-provider select, and the
+ 44-px comparison trigger with the shared 36-px contract.
+2. **Mobile action-button rule**: when a card's title and an action
+ button live on the same row, the button stacks below the title on
+ `=sm`.
+ Prevents the "Restart onboarding tour" overflow.
+3. **Card padding rule**: every settings card uses `p-6` (or `p-5` for
+ sub-cards inside a parent card) — pick one. Settled on `p-6` for
+ top-level cards. The AI sub-card uses `p-4` which matches its
+ nested role; left as-is.
+4. **Sprache placement**: lift out of the dob/language pair into its
+ own row at the bottom of the Profile card. Keeps copy as-is, but
+ stops implying language is a profile attribute.
+5. **Spacing**: top-level section uses `space-y-6`. Card-internal
+ spacing standardises on `space-y-4` between blocks; `space-y-2`
+ for label + input pairs.