` at the top (good — separate W12-M5 fix).
+- The Coach Send button still active.
+- A generic 0/network error after the request times out.
+
+Recommend disabling Send when `navigator.onLine === false` so the user gets the actionable copy instantly instead of after a request timeout. This is additive to W12-M6 and could ride into v1.4.44 backlog.
+
+### M4 — Doctor-report disabled-not-hidden: strike-through styling reads as "deleted", not "unavailable"
+
+**Severity:** Medium — visual semantic mismatch.
+
+`doctor-report-dialog.tsx:638-642` applies `line-through` to the label of unavailable section toggles. Strike-through carries a strong "removed / deleted" connotation; for "no data in this period" the convention is the opacity dim + caption line (which the dialog already paints below). Recommend dropping the strike-through and relying on `opacity-60 cursor-not-allowed` + the existing italic hint line.
+
+The hint line copy is good ("Keine Daten in diesem Zeitraum") and covers all 6 locales.
+
+---
+
+## Low (5)
+
+### L1 — `comparison-baseline` pill DE copy "Dein Mittel" reads as personal-baseline noun, not toggle action verb
+
+**Severity:** Low — DE polish.
+
+`charts.personalBaseline` in `messages/de.json:858` reads "Dein Mittel" (noun phrase). On the comparison-baseline pill row in `chart-overlay-controls.tsx:251-260` the buttons are toggle actions; the noun form reads slightly odd next to the active label. Not a blocker, just a stylistic choice that may be worth tightening in a later QoL pass.
+
+### L2 — Sheet close-X mobile target uses `min-h-11 min-w-11 sm:min-h-9 sm:min-w-9`, fine — but the icon stays `size-4`
+
+**Severity:** Low — visual centering.
+
+`src/components/ui/sheet.tsx:88` and `src/components/ui/dialog.tsx:86` bump the tap target from 9 → 11 on mobile, leaving the 16 px X icon. The result is a 44 × 44 px target with a tiny dot in the middle — functionally correct, visually thin. Recommend `[&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-4` stays but mobile gets `size-5`, OR keep as-is and rely on the larger tap zone being self-explanatory.
+
+This is the iOS / Apple HIG convention so not strictly wrong. Calling out for awareness only.
+
+### L3 — Chart-skeleton `loadingSlowHint` caption fires after 3 s — good copy, but no `aria-live`
+
+**Severity:** Low — a11y minor.
+
+`chart-skeleton.tsx:125-132` paints the caption inside the parent `role="status" aria-live="polite"` skeleton container. The transition from skeleton-without-hint to skeleton-with-hint should announce; with `aria-live="polite"` on the outer it likely will, but the caption itself is wrapped in `` rather than an explicit live region. Recommend adding `aria-live="polite"` directly on the `
` or ensure the test covers the announcement.
+
+### L4 — `OfflineBanner` paints below `` even though comment says "first chrome line"
+
+**Severity:** Low — comment / behaviour mismatch.
+
+`auth-shell.tsx:164-169` puts `` immediately above `` (correct per code order). But the inline comment claims it sits "above the maintainership banner + top bar so the connection-status hint is always the first chrome line a user sees in the offline branch." Verified — the order is OfflineBanner → MaintainershipBanner → TopBar, so the comment is accurate. (This was a false alarm during my review — code matches the claim. Listing here for note-keeping only.)
+
+### L5 — `formatDateOrRelative` in `src/lib/format.ts:96-121` reads `relativeMinutesAgo` (legacy key — exists) while `formatRelativeTime` reads `*One/*Other` (missing keys — broken)
+
+**Severity:** Low — code-quality / consistency.
+
+Two helpers, two different key sets. `formatDateOrRelative` (`src/lib/format.ts`) reads the original `relativeMinutesAgo` keys (which still exist) and works correctly. `formatRelativeTime` (`src/lib/i18n/relative-time.ts`) reads the new `*One/*Other` plural-aware keys (which are missing — see Critical C1).
+
+Even after the C1 fix, having two helpers with two different key contracts is fragile. Recommend consolidating both call-sites onto one helper in a v1.4.44 simplification pass.
+
+---
+
+## Strengths
+
+- **i18n parity on most new keys is rock-solid.** `noDataInRangeTitle/Description`, `needMoreDistinctDaysTitle/Description`, `loadingSlowHint`, `errorNetwork`, `offlineBanner.message`, `notFound.title/backToDashboard`, `unavailableHint`, `resumeCta/Success/Error`, `warningServerError/parkedReconnect` — all 6 locales present, tight Marc-voice copy across the board.
+- **Empty-state coverage closes the silent-null gap.** `health-chart.tsx:1141-1334` swaps the legacy `return null` on empty `chartData` for an explicit `` with distinct copy from the < 3 raw and < 3 distinct days variants. The three-way gate is the right call — every "no data" path now paints something meaningful.
+- **W2-CHART-GATE rawCount logic is correct.** The `rawMeasurementCount` accumulator + non-enumerable `rawCount` property on the returned array is a clean way to thread the metric through without disturbing downstream array consumers. Mood + medication mirror the pattern correctly.
+- **Motion-reduce sweep + regression guard.** `motion-reduce-spin-coverage.test.ts` is the right kind of guard — textual, fast, catches drift. The 21-site sweep landed cleanly. (Gap: animate-pulse — see M2.)
+- **Skeleton heights match loaded content.** Insights mother-page skeleton heights bumped from `h-48/h-32/h-64` → `h-[24rem]/h-[20rem]/h-[20rem]` with a pinning regression test (`page-skeletons.test.ts`). Scatter-correlation skeleton mirrors `aspect-square` / `sm:aspect-[3/2]` responsive contract. Recent-workouts-tile and DrugLevelChart now reserve `min-h-[10rem]` / `min-h-[240px]` respectively.
+- **Reduced-motion scroll helper is the right shape.** `src/lib/motion.ts:scrollBehaviorForUser()` consolidates the four `scrollIntoView` / `scrollTo` smooth-behavior sites onto one helper that respects `prefers-reduced-motion`. Settings shell, admin shell, message thread, and the new W5-H5 sites all migrated; only WelcomeCarousel still does its own check (justified — separate context).
+- **Danger-zone visual quieting (`AlertTriangle` icon dropped, neutral title colour, red CTA only).** GitHub-style. Account-delete CTA card mirrors the data-reset shaping so the two surfaces read as siblings on the same page.
+- **Doctor-report disabled-not-hidden is the right architecture.** The submission payload still force-clears unavailable toggles (server never renders an empty section), so the user-facing change is purely visual — no behavioural regression risk.
+- **OfflineBanner architecture is clean.** SSR-safe (initial state `true`, paints nothing during SSR), microtask-deferred initial read of `navigator.onLine`, proper add/removeEventListener cleanup, `role="status" aria-live="polite"`, and i18n-aware copy.
+- **W14 parked-integration UX.** Distinct visual treatment (orange `dracula-orange/15`) from warning (yellow) and error (red destructive), proper aria, manual reconnect CTA with 44 px tap target on mobile (`min-h-[44px] sm:min-h-0`), success / error feedback as separate `role="status"` / `role="alert"` paragraphs.
+- **404 page server-resolves locale.** No more English-only `not-found` for German users; the implementation uses the existing `resolveServerLocale()` + `getServerTranslator()` infrastructure correctly. global-error is bilingual lockup because it cannot reach the i18n provider — also the right call.
+- **Apple Health / Withings visual coherence preserved.** The Apple Health pink badge accent on measurement source badges (`measurement-list.tsx:144-149`) survives unchanged, Withings parked banner uses dracula-orange (different tone from connected green / warning yellow), and the integration-pill remains the single source of truth for sync status (no v1.4.18-era redundancy resurfaced).
+
+---
+
+## Recommendation
+
+**Fix C1 (relative-time plural keys), then ship.** H1 (warning state wiring) is a documentation-only fix or a 6-line `pillStateFor` extension — either is fine. M-tier items are not blockers; L-tier items are pure polish for v1.4.44.
+
+**Suggested follow-up backlog for v1.4.44:**
+- C1 fix + regression test (5 min, 1 commit).
+- H1 warning-state wiring or doc-only deferral (10 min).
+- M1 Switch vertical inset (1 line).
+- M2 animate-pulse motion-reduce sweep + extend the guard (15 min).
+- L5 consolidate `formatDateOrRelative` + `formatRelativeTime` onto one helper.
diff --git a/.planning/round-v1443-QA-product-lead-findings.md b/.planning/round-v1443-QA-product-lead-findings.md
new file mode 100644
index 000000000..e2cf956cd
--- /dev/null
+++ b/.planning/round-v1443-QA-product-lead-findings.md
@@ -0,0 +1,429 @@
+# v1.4.43 QA — Product Lead release-readiness review
+
+Scope: strategic + release-readiness review of the full diff
+`2c68a48d..develop` (74 commits, +12,301 / -460 LOC across 197 files).
+Read-only; no source modifications. All four audit reports and all
+seven phase reports (W4 / W6 / W7 / W8 / W11 / W12 / W13 / W14) read
+end-to-end before this verdict.
+
+## Verdict
+
+**SHIP** — v1.4.43 is ready for production at
+`healthlog.bombeck.io` once the version bump + CHANGELOG entry +
+operator notes land. No Critical issues. One High (H3 partial-wire
+ship) is a quality concern, not a release blocker. All Discovery
+Highs and Criticals from the four audits closed; almost every Medium
+picked up; Lows correctly deferred to v1.4.44.
+
+## Critical / High count
+
+- **Critical**: 0
+- **High**: 1 (H3 partial wire — see below)
+- **Medium**: 3
+- **Low**: 4
+
+---
+
+## High (must address before tag — but not blocker if Operator notes
+the gap)
+
+### PL-H1 — `IntegrationStatusPill` `"warning"` state ships dark
+
+- **What**: W4 added a fourth pill state `"warning"` with locale copy
+ `settings.integrationPill.warningServerError` ("Verbunden, aber
+ Serverfehler" / "Connected, server error") to close audit-H3
+ (v1.4.42 `persistent` failure-kind has no user surface). The pill
+ component renders the state correctly when called. But no
+ production code path passes `state="warning"` to the pill.
+- **Why**: The wave's file allow-list excluded
+ `integrations-section.tsx` (the caller). W4's phase report
+ documents the gap explicitly and lists the three steps to wire it
+ (Prisma `lastFailureKind` column, `/api/integrations/status`
+ payload extension, `pillStateFor` branch). The follow-up wave W14
+ did touch `integrations-section.tsx` but only to wire `"parked"`;
+ the `"warning"` wire-up was missed.
+- **Result**: The audit-H3 contract is half-shipped. A Withings
+ persistent failure (rate-limit 601 / contract-mismatch 293/294)
+ still surfaces as the same red "Fehler — neu verbinden" pill that
+ every transient or reauth failure paints — the same UX confusion
+ the v1.4.42 classifier was meant to close.
+- **Severity rationale**: High because audit-H3 was tagged
+ ship-before-tag and the audit's reasoning ("a user clicking the
+ reconnect link 10 times learns nothing") still holds. Not a
+ blocker because (a) the `"parked"` state in W14 partially
+ compensates (a >24h persistent streak escalates to the parked pill
+ with copy "Pausiert — manuell wieder verbinden", which IS
+ user-distinct), and (b) the under-24h gap is a missing improvement
+ rather than a regression — the v1.4.42 behaviour ships unchanged.
+- **Recommended path**:
+ - Option A (defer cleanly): drop the `"warning"` pill state from
+ `integration-status-pill.tsx` and remove the four locale keys
+ (`warningServerError` × 6). The pill should not ship dark code.
+ Move the full wiring (Prisma + API + section + pill) to a
+ standalone v1.4.44 wave per the W4 phase-report blueprint.
+ - Option B (ship as-is + document): leave the dark code in place
+ and document under "Known follow-up" in the v1.4.43 operator
+ notes so v1.4.44 has the breadcrumb. Cost: one additional
+ component state to maintain.
+ - Recommend Option A — dark UI code violates the v1.4.40
+ audit-G "ghost-purge" hygiene rule and the W-SIMPLIFIER pattern
+ that's been the consistent direction since v1.4.41.
+
+---
+
+## Medium (recommended, not blockers)
+
+### PL-M1 — Version bump + CHANGELOG entry not yet landed
+
+- `package.json` still reads `"version": "1.4.42"`.
+- `CHANGELOG.md` has no `[1.4.43]` entry.
+- The handoff (`v1443-handoff.md` step 6 / 7) explicitly scopes both
+ for the fresh session.
+- The CHANGELOG draft needs to cite the 4 audit reports + 7 phase
+ reports + REG-11 (the Marc-authored dashboard summary fix that
+ doesn't sit under a wave). Shape mirrors `[1.4.42]` (Added /
+ Changed / Fixed / Performance / Operator notes).
+
+### PL-M2 — Operator notes must clearly call out `prisma migrate deploy`
+
+- v1.4.43 ships migration `0075_v1443_integration_park` (additive,
+ idempotent — two `ADD COLUMN IF NOT EXISTS` statements). Coolify
+ auto-deploy DOES NOT run `prisma migrate deploy`; the operator
+ must run it manually. Recommended note:
+ > **Migration**: run `pnpm exec prisma migrate deploy` against
+ > production Postgres **before** the new container starts serving
+ > traffic. The two new columns are nullable + back-filled lazily
+ > by the status writer, so existing rows keep working through the
+ > migration boundary; rollback is `DROP COLUMN IF EXISTS` on both
+ > columns + `UPDATE integration_statuses SET state =
+ > 'error_transient' WHERE state = 'parked'`.
+
+### PL-M3 — Cross-agent commit-attribution drift not relevant this
+release (positive observation)
+
+- Every commit on `develop` since `2c68a48d` is authored by
+ `Marc-André Bombeck` — `git log --format="%an" 2c68a48d..HEAD |
+ sort | uniq -c` returns `74 Marc-André Bombeck`.
+- Per the `feedback_marathon_worktree_isolation.md` rule (4
+ drift-marathons proved shared-tree is broken), the v1.4.43
+ marathon dispatched 9 worktree-isolated agents (per the handoff)
+ and the cherry-pick chain landed clean. **No drift recurrence.**
+- Action: cite this in the v1.4.43 retrospective. The worktree-
+ isolation rule is now proven across 3 consecutive marathons
+ (v1.4.41 / v1.4.42 / v1.4.43).
+
+---
+
+## Low (defer to v1.4.44 / non-blocking)
+
+### PL-L1 — `.planning/` audit + phase reports contain "Marc" mentions
+
+- `round-v1443-AUDIT-mobile-ui-findings.md`, `…qol-findings.md`,
+ `…analytics-9s-findings.md`, `phase-W4-QoL-COPY-v1443-report.md`,
+ `phase-W8-OPS-v1443-report.md` all contain literal "Marc"
+ references.
+- Per `feedback_no_pii_in_user_facing.md`, the rule scopes to
+ *user-facing* artifacts (CHANGELOG, GH releases, `docs/audit/v*`,
+ `docs/site`, landing). `.planning/` is operator-side work-product
+ and not published. The mentions are operationally-useful context
+ for the next marathon.
+- **No action required** — confirming the rule doesn't trip here.
+- The v1.4.43 CHANGELOG entry MUST stay PII-clean (no Marc-name, no
+ bombeck.io, no health figures, no BD-Zielbereich values).
+
+### PL-L2 — REG-11 (dashboard summary 7d window drop) lands without
+a phase report
+
+- Commit `600aa369` is the dashboard `latestEver` fix that closed a
+ iOS-side BP/pulse tile blank-state bug (5 iOS-side attempts
+ failed because the bug was in server SQL). It rides v1.4.43 but
+ doesn't sit under any wave. Marc authored it directly between
+ W11 dispatch and the QA round.
+- The commit body is in German (Marc-authored, not an agent — the
+ Marc-voice English rule applies to agent-authored commits, not
+ Marc's direct authorship).
+- **Action**: cite REG-11 explicitly in the CHANGELOG `[1.4.43]`
+ "Fixed" section so the iOS team has the breadcrumb without
+ hunting commit logs.
+
+### PL-L3 — W7 deferral semantics drifted between handoff and W14
+
+- The v1443-handoff (line 15) marks W7 as "B3 only — B4 + B7
+ deferred to v1.4.44". W14 then landed B4 + B7 inside v1.4.43.
+- Net effect: v1.4.43 ships more than the handoff scope claimed.
+ Audit closure is BETTER than promised, but the v1.4.44 backlog
+ documented in the handoff (line 53) now contains items that
+ already shipped.
+- **Action**: when v1.4.44 backlog rolls forward, drop W7-B4 + W7-B7
+ from the "deferred" list. Reflect the actual close in the
+ retrospective memo.
+
+### PL-L4 — Test-count delta not yet aggregated
+
+- Each phase report cites a local test-count delta against their
+ worktree baseline (W11: 4815→4861, W12: 4815→4877, W13: 4815→4839,
+ W14: 4815→4842, W6: 4929 total). With overlapping baselines the
+ net total against `develop` HEAD is unclear. The phase reports
+ add up to ~+300 unit tests across W4 + W6 + W11 + W12 + W13 + W14
+ ignoring overlaps; the full `pnpm test --run` against HEAD will
+ produce the authoritative number for the CHANGELOG.
+- **Action**: run `pnpm test --run` once at HEAD before the version
+ bump; cite the resulting test count in the CHANGELOG.
+
+---
+
+## Discovery → close coverage matrix
+
+### Audit: analytics-9s
+
+| Item | Severity | Status |
+|---|---|---|
+| W1 — `computeAvg30LastYearMap` `p-limit(4)` cap | URGENT | **Closed** via `c9a54154` + test pin `3218cb50` |
+
+Verdict: complete. The audit's "recommended fix" body landed
+exactly as prescribed. Optional follow-ups (granularity router pin,
+24h cache) correctly deferred.
+
+### Audit: mobile-ui
+
+| Severity | Closed | Open / Deferred |
+|---|---|---|
+| Critical (1) | C1 (raw-count gate + `noDataInRange` split) | — |
+| High (5) | H1 Switch 44 px, H2 comparison-baseline 44 px, H3 mood-kebab, H4 sheet close-X, H5 reduced-motion smooth-scroll | — |
+| Medium (6) | M1–M6 all closed via W11 | — |
+| Low (6) | L1, L2, L4 (folded), L6 | L3 (Textarea primitive — refactor scope), L5 (injection-site SVG — non-trivial refactor) |
+
+Verdict: **all Highs + Criticals closed**. Two Lows correctly
+deferred with audit-report-honest documentation in W11 phase report
+(L5 specifically rebutting the audit's misread of the element type
+— well-handled, Marc-voice).
+
+### Audit: QoL
+
+| Severity | Closed | Open / Deferred |
+|---|---|---|
+| High (6) | H1 loadError key, H2 Anbieter rename, H3 persistent (partial — see PL-H1), H4 not-found i18n, H5 global-error bilingual, H6 plural forms | — |
+| Medium (8) | M3 account-delete, M4 doctor-report disabled rows, M5 offline-banner, M6 errorNetwork, M7 daysAgo "d", M8 full Locale union | M1 (drag-drop reorder — a11y scope), M2 (Coach disable — feature scope) |
+| Low (8) | L1, L2, L3, L4, L5, L7, L8 | L6 (onboarding gate) |
+
+Verdict: H3 partial (PL-H1 above) is the single open thread.
+Everything else closed cleanly.
+
+### Audit: security
+
+| Severity | Closed | Open / Deferred |
+|---|---|---|
+| High (2) | H-1 audit-row identifier-hash, H-2 WithingsApiError 1024 slice | — |
+| Medium (4) | M-1 check-user audit, M-2 plain-text invariant docblock, M-3 replay-injection scan, M-4 trust-violation bucket | — |
+| Low (4) | L-2 snapshot scan guard, L-3 passkey Zod boundary | L-1 (withings_state nonce table — OAuth refactor scope), L-4 (legacy_form_total — wait for v1.4.27 cut) |
+
+Verdict: **all Highs + every Medium + 2/4 Lows closed**. M-3 was
+listed as "defer" in the audit but W13 closed it inside the
+release. Defence-in-depth surface significantly strengthened.
+
+---
+
+## Release-theme coherence
+
+v1.4.43 has a clear three-strand narrative:
+
+1. **9 s perf regression closure** (W1 + measurable in HAR — the
+ audit's URGENT call) — single largest user-visible win.
+2. **Audit-close marathon** — every Critical + every High across
+ four audits closed, almost every Medium picked up.
+3. **iOS-handoff hardening** — Zod multi-issue rollout (41 routes),
+ Withings parking + per-kind counters, docker version-cache fix
+ (B11) closes the v1.4.42 recurring paper-cut.
+
+A clean release-note title: **"v1.4.43 — Analytics 9 s closure,
+audit-marathon close (4 reports / 9 waves), Withings parking, iOS
+contract Zod rollout."**
+
+This is a *focused polishing release*, not a grab-bag. Compare with
+the v1.4.36 / v1.4.37 perf marathons or v1.4.40 architecture
+closure — same shape, same coherence.
+
+---
+
+## iOS contract preservation
+
+- **W6 Zod rollout (41 routes)**: envelope strictly additive. Every
+ caller reading `body.error` still gets a human-readable "Validation
+ failed" string. New callers branch on `body.details.issues`. iOS
+ v0.5.4 receives the same shape — no break.
+- **W14 `/api/integrations/withings/resume`**: net-new POST endpoint
+ with no payload. Additive. iOS v0.5.4 doesn't call it; future iOS
+ release MAY add it.
+- **W14 `IntegrationStatus.state = "parked"`**: new enum value in a
+ string field. Per the 0029 migration comment ("adding new
+ sentinels in v1.5 doesn't require a migration") this is the
+ documented evolution pattern. iOS v0.5.4 will fall through to a
+ generic state branch; verified the new `consecutiveFailuresByKind`
+ + `persistentFailureStartedAt` columns are NOT in the API
+ view-model (`/api/integrations/status` `IntegrationViewModel`
+ unchanged).
+- **W12 `DELETE /api/settings/account`**: pre-existing endpoint; the
+ v1.4.43 work is UI-only.
+- **REG-11 `/api/dashboard/summary`**: shape unchanged; behaviour
+ fixed — now serves BP/pulse rows older than 7 d. Pure server-side
+ bug fix, iOS surface improves with no client changes.
+
+**No iOS contract drift.** v1.4.43 is iOS v0.5.4-compatible.
+
+---
+
+## Migration readiness
+
+- Migration `0075_v1443_integration_park` is additive + idempotent +
+ reversible:
+ ```sql
+ ALTER TABLE "integration_statuses"
+ ADD COLUMN IF NOT EXISTS "consecutive_failures_by_kind" JSONB;
+ ALTER TABLE "integration_statuses"
+ ADD COLUMN IF NOT EXISTS "persistent_failure_started_at" TIMESTAMP(3);
+ ```
+- Both columns nullable — pre-migration rows keep working. The
+ status writer back-fills `consecutiveFailuresByKind` lazily on the
+ next failure write.
+- Operator notes draft: see PL-M2 above. The migration is the only
+ release-blocking ops action.
+
+---
+
+## v1.4.44 backlog seed (recommended)
+
+Carry forward to the next marathon brief:
+
+### High (must do early)
+
+- **WTH-WIRE-WARNING** — finalise the audit-H3 wiring: Prisma
+ `lastFailureKind` column on `IntegrationStatus`, plumb through
+ `/api/integrations/status` payload, branch `pillStateFor` to
+ return `"warning"` when `failureKind === "persistent"` (or drop
+ the dark `"warning"` pill state per PL-H1 Option A).
+- **WTH-DROP-LEGACY-COUNTER** — drop `IntegrationStatus.consecutiveFailures`
+ per the W14 phase report ("v1.4.44 will drop it once every reader
+ has migrated"). Migration `0076_v1444_drop_legacy_counter`.
+
+### Medium
+
+- **TEXTAREA-PRIMITIVE** (audit mobile-ui L3) — introduce
+ `