diff --git a/.superpowers/sdd/progress.md b/.superpowers/sdd/progress.md
new file mode 100644
index 0000000..d6e52a9
--- /dev/null
+++ b/.superpowers/sdd/progress.md
@@ -0,0 +1,9 @@
+# SDD Progress
+
+Plan: docs/superpowers/plans/2026-07-21-page-header-safe-area-g03.md
+Branch: fix/page-header-safe-area
+Base: 779a442
+
+Task 1: complete (commits 779a442..2f22df6, review clean)
+Task 2: complete (commits 2f22df6..a0d19f4, review clean after strict-regex fix)
+Task 3: complete (verification only at a0d19f4, review clean; 8 contracts + 2 H5 smokes pass)
diff --git a/.superpowers/sdd/review-task-1-779a442..2f22df6.diff b/.superpowers/sdd/review-task-1-779a442..2f22df6.diff
new file mode 100644
index 0000000..086e293
--- /dev/null
+++ b/.superpowers/sdd/review-task-1-779a442..2f22df6.diff
@@ -0,0 +1,143 @@
+# Review package: 779a442..2f22df6
+
+## Commits
+2f22df6 fix: adapt shared page header to safe area
+
+## Files changed
+ components/PageHeader.vue | 12 ++++++++++--
+ tests/shared-component-document-flow-contract.ps1 | 4 ++++
+ tests/shared-interaction-accessibility-contract.ps1 | 10 ++++++++++
+ 3 files changed, 24 insertions(+), 2 deletions(-)
+
+## Diff
+diff --git a/components/PageHeader.vue b/components/PageHeader.vue
+index 5ef28dd..17ab7ef 100644
+--- a/components/PageHeader.vue
++++ b/components/PageHeader.vue
+@@ -67,52 +67,60 @@
+
+
+
+
+
+ ').Groups[1].Value
+ $positions = [regex]::Matches([regex]::Replace($style, '(?s)/\*.*?\*/', ''), '(?m)\bposition\s*:\s*([^;]+);')
+ if ($positions.Count -ne 1 -or $positions[0].Groups[1].Value.Trim() -ne 'fixed') {
+ throw "G03 must retain only its combined fixed dialog layer rule; found $($positions.Count) position declarations"
+ }
+ foreach ($required in @(
+- 'background: url("/static/assets/foundation/opaque/root-header-cinnabar.jpg")',
+ 'background: url("/static/assets/modules/genealogy/transparent/g01-empty-panel-frame.png")',
+ 'background: url("/static/assets/modules/auth/transparent/a01-scroll-dialog-v3.png")',
+ 'background: url("/static/assets/foundation/transparent/a01-scroll-primary-v3.png")'
+ )) { if ($page -notmatch [regex]::Escape($required)) { throw "G03 is missing real asset background: $required" } }
++foreach ($forbidden in @('flow-header', 'root-header-cinnabar.jpg')) {
++ if ($page -match [regex]::Escape($forbidden)) { throw "G03 must not retain private header token: $forbidden" }
++}
+ Write-Output 'G03-DOCUMENT-FLOW-CONTRACT PASS'
+diff --git a/tests/g03-visual-states-contract.ps1 b/tests/g03-visual-states-contract.ps1
+index 5342acb..cfb7911 100644
+--- a/tests/g03-visual-states-contract.ps1
++++ b/tests/g03-visual-states-contract.ps1
+@@ -2,22 +2,22 @@ $ErrorActionPreference = 'Stop'
+
+ $root = Split-Path -Parent $PSScriptRoot
+ $g03 = Get-Content -LiteralPath (Join-Path $root 'pages/genealogy/g03-create-genealogy.vue') -Raw -Encoding utf8
+
+ function Assert-Match {
+ param([string]$Content, [string]$Pattern, [string]$Message)
+ if ($Content -notmatch $Pattern) { throw $Message }
+ }
+
+ if ($g03 -match '返回') { throw 'G03 header must use only the approved image back arrow' }
+-Assert-Match -Content $g03 -Pattern '(?s)\.flow-header__back,\s*\.flow-header__side\s*\{[^}]*width:\s*72rpx;' -Message 'G03 header side slots must preserve centered title after removing back text'
+-Assert-Match -Content $g03 -Pattern '(?s)\.flow-header__back-icon\s*\{[^}]*width:\s*34rpx;[^}]*height:\s*34rpx;' -Message 'G03 back arrow must use the approved visible size'
++Assert-Match -Content $g03 -Pattern '(?s)' -Message 'G03 must use PageHeader with its dynamic title and custom back handler'
++if ($g03 -match 'flow-header|flow-header__back|flow-header__title') { throw 'G03 must not retain a private header implementation' }
+ Assert-Match -Content $g03 -Pattern '(?s)\.flow-note,\s*\.flow-rule__note\s*\{[^}]*font-size:\s*25rpx;' -Message 'G03 guidance copy must use the approved readable size'
+ Assert-Match -Content $g03 -Pattern '(?s)\.flow-rule__option\s*\{[^}]*font-size:\s*23rpx;' -Message 'G03 visibility options must use the approved readable size'
+ Assert-Match -Content $g03 -Pattern '(?s)\.field-error\s*\{[^}]*font-size:\s*24rpx;[^}]*line-height:\s*34rpx;' -Message 'G03 field errors must use the approved readable size'
+ Assert-Match -Content $g03 -Pattern '(?s)\.flow-error\s*\{[^}]*font-size:\s*25rpx;[^}]*line-height:\s*36rpx;' -Message 'G03 submit errors must use the approved readable size'
+
+ foreach ($asset in @('a01-scroll-dialog-v3.png', 'a01-scroll-primary-v3.png', 'a01-scroll-secondary-v3.png')) {
+ if ($g03 -notmatch [regex]::Escape($asset)) { throw "G03 must retain approved shared asset: $asset" }
+ }
+
+ Write-Output 'G03-VISUAL-STATES-CONTRACT PASS'
diff --git a/.superpowers/sdd/review-task-2-rereview-2f22df6..a0d19f4.diff b/.superpowers/sdd/review-task-2-rereview-2f22df6..a0d19f4.diff
new file mode 100644
index 0000000..82c65d9
--- /dev/null
+++ b/.superpowers/sdd/review-task-2-rereview-2f22df6..a0d19f4.diff
@@ -0,0 +1,230 @@
+# Review package: 2f22df6..a0d19f4
+
+## Commits
+a0d19f4 test: tighten G03 shared header contract
+9362c47 refactor: reuse shared header on G03
+
+## Files changed
+ pages/genealogy/g03-create-genealogy.vue | 62 ++++----------------------------
+ tests/g03-create-flow-contract.ps1 | 9 +++--
+ tests/g03-document-flow-contract.ps1 | 4 ++-
+ tests/g03-visual-states-contract.ps1 | 4 +--
+ 4 files changed, 17 insertions(+), 62 deletions(-)
+
+## Diff
+diff --git a/pages/genealogy/g03-create-genealogy.vue b/pages/genealogy/g03-create-genealogy.vue
+index 2bc757d..f37cadc 100644
+--- a/pages/genealogy/g03-create-genealogy.vue
++++ b/pages/genealogy/g03-create-genealogy.vue
+@@ -1,30 +1,20 @@
+
+
+
+
+
+-
++
+
+
+
+
+ 第一步 · 立谱信息
+ 为家族立一部可传承的谱
+ 家谱建立后可继续完善,名称与访问规则由创建者维护。
+
+@@ -241,20 +231,21 @@
+
+
+
+
+
+
+
+
+ ').Groups[1].Value
+ $positions = [regex]::Matches([regex]::Replace($style, '(?s)/\*.*?\*/', ''), '(?m)\bposition\s*:\s*([^;]+);')
+ if ($positions.Count -ne 1 -or $positions[0].Groups[1].Value.Trim() -ne 'fixed') {
+ throw "G03 must retain only its combined fixed dialog layer rule; found $($positions.Count) position declarations"
+ }
+ foreach ($required in @(
+- 'background: url("/static/assets/foundation/opaque/root-header-cinnabar.jpg")',
+ 'background: url("/static/assets/modules/genealogy/transparent/g01-empty-panel-frame.png")',
+ 'background: url("/static/assets/modules/auth/transparent/a01-scroll-dialog-v3.png")',
+ 'background: url("/static/assets/foundation/transparent/a01-scroll-primary-v3.png")'
+ )) { if ($page -notmatch [regex]::Escape($required)) { throw "G03 is missing real asset background: $required" } }
++foreach ($forbidden in @('flow-header', 'root-header-cinnabar.jpg')) {
++ if ($page -match [regex]::Escape($forbidden)) { throw "G03 must not retain private header token: $forbidden" }
++}
+ Write-Output 'G03-DOCUMENT-FLOW-CONTRACT PASS'
+diff --git a/tests/g03-visual-states-contract.ps1 b/tests/g03-visual-states-contract.ps1
+index 5342acb..d539bc5 100644
+--- a/tests/g03-visual-states-contract.ps1
++++ b/tests/g03-visual-states-contract.ps1
+@@ -2,22 +2,22 @@ $ErrorActionPreference = 'Stop'
+
+ $root = Split-Path -Parent $PSScriptRoot
+ $g03 = Get-Content -LiteralPath (Join-Path $root 'pages/genealogy/g03-create-genealogy.vue') -Raw -Encoding utf8
+
+ function Assert-Match {
+ param([string]$Content, [string]$Pattern, [string]$Message)
+ if ($Content -notmatch $Pattern) { throw $Message }
+ }
+
+ if ($g03 -match '返回') { throw 'G03 header must use only the approved image back arrow' }
+-Assert-Match -Content $g03 -Pattern '(?s)\.flow-header__back,\s*\.flow-header__side\s*\{[^}]*width:\s*72rpx;' -Message 'G03 header side slots must preserve centered title after removing back text'
+-Assert-Match -Content $g03 -Pattern '(?s)\.flow-header__back-icon\s*\{[^}]*width:\s*34rpx;[^}]*height:\s*34rpx;' -Message 'G03 back arrow must use the approved visible size'
++Assert-Match -Content $g03 -Pattern '(?s)' -Message 'G03 must use PageHeader with its dynamic title and custom back handler'
++if ($g03 -match 'flow-header|flow-header__back|flow-header__title') { throw 'G03 must not retain a private header implementation' }
+ Assert-Match -Content $g03 -Pattern '(?s)\.flow-note,\s*\.flow-rule__note\s*\{[^}]*font-size:\s*25rpx;' -Message 'G03 guidance copy must use the approved readable size'
+ Assert-Match -Content $g03 -Pattern '(?s)\.flow-rule__option\s*\{[^}]*font-size:\s*23rpx;' -Message 'G03 visibility options must use the approved readable size'
+ Assert-Match -Content $g03 -Pattern '(?s)\.field-error\s*\{[^}]*font-size:\s*24rpx;[^}]*line-height:\s*34rpx;' -Message 'G03 field errors must use the approved readable size'
+ Assert-Match -Content $g03 -Pattern '(?s)\.flow-error\s*\{[^}]*font-size:\s*25rpx;[^}]*line-height:\s*36rpx;' -Message 'G03 submit errors must use the approved readable size'
+
+ foreach ($asset in @('a01-scroll-dialog-v3.png', 'a01-scroll-primary-v3.png', 'a01-scroll-secondary-v3.png')) {
+ if ($g03 -notmatch [regex]::Escape($asset)) { throw "G03 must retain approved shared asset: $asset" }
+ }
+
+ Write-Output 'G03-VISUAL-STATES-CONTRACT PASS'
diff --git a/.superpowers/sdd/review-task-3-a0d19f4..a0d19f4.diff b/.superpowers/sdd/review-task-3-a0d19f4..a0d19f4.diff
new file mode 100644
index 0000000..bbdf4e1
--- /dev/null
+++ b/.superpowers/sdd/review-task-3-a0d19f4..a0d19f4.diff
@@ -0,0 +1,7 @@
+# Review package: a0d19f4..a0d19f4
+
+## Commits
+
+## Files changed
+
+## Diff
diff --git a/.superpowers/sdd/task-1-brief.md b/.superpowers/sdd/task-1-brief.md
new file mode 100644
index 0000000..1c5e4e4
--- /dev/null
+++ b/.superpowers/sdd/task-1-brief.md
@@ -0,0 +1,116 @@
+### Task 1: 为公共 PageHeader 建立安全区与返回契约
+
+**Files:**
+- Modify: `tests/shared-component-document-flow-contract.ps1`
+- Modify: `tests/shared-interaction-accessibility-contract.ps1`
+- Modify: `components/PageHeader.vue`
+
+**Interfaces:**
+- Consumes: uni-app 提供的 `var(--status-bar-height, 0px)`、`getCurrentPages()`、`uni.navigateBack()`、`uni.reLaunch()`。
+- Produces: `customBack: Boolean = false` 属性和 `back` 事件;普通页头及占位槽均使用安全区总高度。
+
+- [ ] **Step 1: 写入普通页头安全区的失败契约**
+
+在 `tests/shared-component-document-flow-contract.ps1` 的 PageHeader 断言中加入:
+
+```powershell
+Assert-Match $header '(?s)\.page-header-slot\s*\{[^}]*height:\s*calc\(104rpx \+ var\(--status-bar-height, 0px\)\);' 'PageHeader secondary slot must reserve status bar plus 104rpx content height'
+Assert-Match $header '(?s)\.page-header\s*\{[^}]*height:\s*calc\(104rpx \+ var\(--status-bar-height, 0px\)\);[^}]*padding-top:\s*var\(--status-bar-height, 0px\);' 'PageHeader secondary header must place its 104rpx content below the status bar'
+Assert-Match $header '(?s)\.page-header-slot--root\s*\{[^}]*height:\s*calc\(124rpx \+ var\(--status-bar-height, 0px\)\);' 'PageHeader root slot height must remain unchanged'
+Assert-Match $header '(?s)\.page-header--root\s*\{[^}]*height:\s*calc\(124rpx \+ var\(--status-bar-height, 0px\)\);' 'PageHeader root height must remain unchanged'
+```
+
+- [ ] **Step 2: 写入自定义返回的失败契约**
+
+在 `tests/shared-interaction-accessibility-contract.ps1` 的 PageHeader 检查中加入:
+
+```powershell
+foreach ($token in @(
+ 'customBack: { type: Boolean, default: false }',
+ 'const emit = defineEmits(["brand", "notice", "action", "back"]);',
+ 'if (props.customBack) {',
+ 'emit("back");',
+ 'uni.navigateBack();',
+ 'uni.reLaunch({ url: props.fallbackUrl });'
+)) {
+ if (-not $header.Contains($token)) { throw "PageHeader back contract missing: $token" }
+}
+```
+
+- [ ] **Step 3: 运行聚焦契约并确认 RED**
+
+Run:
+
+```powershell
+& powershell -ExecutionPolicy Bypass -File tests/shared-component-document-flow-contract.ps1
+& powershell -ExecutionPolicy Bypass -File tests/shared-interaction-accessibility-contract.ps1
+```
+
+Expected: 两项均 FAIL,分别指出普通页头仍为固定 `104rpx`、`customBack` 合同不存在。
+
+- [ ] **Step 4: 实现最小公共组件改动**
+
+在 `components/PageHeader.vue` 中补充属性和事件:
+
+```js
+const props = defineProps({
+ title: { type: String, required: true },
+ action: { type: String, default: "" },
+ root: { type: Boolean, default: false },
+ unreadCount: { type: Number, default: 0 },
+ fallbackUrl: { type: String, default: "/pages/genealogy/g01-my-genealogies" },
+ customBack: { type: Boolean, default: false },
+});
+
+const emit = defineEmits(["brand", "notice", "action", "back"]);
+
+const goBack = () => {
+ if (props.customBack) {
+ emit("back");
+ return;
+ }
+ const stack = getCurrentPages();
+ if (stack.length > 1) {
+ uni.navigateBack();
+ return;
+ }
+ uni.reLaunch({ url: props.fallbackUrl });
+};
+```
+
+把普通变体的尺寸改为:
+
+```scss
+.page-header-slot {
+ height: calc(104rpx + var(--status-bar-height, 0px));
+ flex: none;
+}
+
+.page-header {
+ height: calc(104rpx + var(--status-bar-height, 0px));
+ padding: 0 24rpx;
+ padding-top: var(--status-bar-height, 0px);
+}
+```
+
+保留 `.page-header-slot--root` 与 `.page-header--root` 的现有 `124rpx` 规则不变。
+
+- [ ] **Step 5: 运行聚焦契约并确认 GREEN**
+
+Run:
+
+```powershell
+& powershell -ExecutionPolicy Bypass -File tests/shared-component-document-flow-contract.ps1
+& powershell -ExecutionPolicy Bypass -File tests/shared-interaction-accessibility-contract.ps1
+git diff --check
+```
+
+Expected: 两项输出 `PASS`,`git diff --check` 退出码为 0。
+
+- [ ] **Step 6: 提交公共组件改动**
+
+```powershell
+git add components/PageHeader.vue tests/shared-component-document-flow-contract.ps1 tests/shared-interaction-accessibility-contract.ps1
+git commit -m "fix: adapt shared page header to safe area"
+```
+
diff --git a/.superpowers/sdd/task-1-report.md b/.superpowers/sdd/task-1-report.md
new file mode 100644
index 0000000..3af5a92
--- /dev/null
+++ b/.superpowers/sdd/task-1-report.md
@@ -0,0 +1,56 @@
+# Task 1 Report
+
+Status: DONE
+
+## Changed files
+
+- `components/PageHeader.vue`
+- `tests/shared-component-document-flow-contract.ps1`
+- `tests/shared-interaction-accessibility-contract.ps1`
+
+## RED
+
+Command:
+
+```powershell
+& powershell -ExecutionPolicy Bypass -File tests/shared-component-document-flow-contract.ps1
+& powershell -ExecutionPolicy Bypass -File tests/shared-interaction-accessibility-contract.ps1
+```
+
+Failure evidence:
+
+- `PageHeader secondary slot must reserve status bar plus 104rpx content height`
+- `PageHeader back contract missing: customBack: { type: Boolean, default: false }`
+
+Both contract scripts exited with code `1`, for the expected missing behavior.
+
+## GREEN
+
+Command:
+
+```powershell
+& powershell -ExecutionPolicy Bypass -File tests/shared-component-document-flow-contract.ps1
+& powershell -ExecutionPolicy Bypass -File tests/shared-interaction-accessibility-contract.ps1
+git diff --check
+```
+
+Result summary:
+
+- `SHARED-COMPONENT-DOCUMENT-FLOW-CONTRACT PASS`
+- `SHARED-INTERACTION-ACCESSIBILITY-CONTRACT PASS`
+- `git diff --check` exited `0`
+
+## Commit
+
+`2f22df6 fix: adapt shared page header to safe area`
+
+## Self-review
+
+- Normal PageHeader slot and header use `calc(104rpx + var(--status-bar-height, 0px))`; the header applies status-bar top padding.
+- Root slot and header retain their `calc(124rpx + var(--status-bar-height, 0px))` rules.
+- `customBack` emits `back` and returns before navigation; normal navigation retains stack-aware back and fallback relaunch behavior.
+- The added contract tests cover the required exact public interface and layout declarations.
+
+## Concerns
+
+None. Git emitted existing line-ending conversion warnings during checks and commit, but all required checks passed.
diff --git a/.superpowers/sdd/task-2-brief.md b/.superpowers/sdd/task-2-brief.md
new file mode 100644
index 0000000..05fdf23
--- /dev/null
+++ b/.superpowers/sdd/task-2-brief.md
@@ -0,0 +1,98 @@
+### Task 2: 用公共 PageHeader 替换 G03 自建页头
+
+**Files:**
+- Modify: `tests/g03-visual-states-contract.ps1`
+- Modify: `tests/g03-create-flow-contract.ps1`
+- Modify: `tests/g03-document-flow-contract.ps1`
+- Modify: `pages/genealogy/g03-create-genealogy.vue`
+
+**Interfaces:**
+- Consumes: Task 1 的 ``。
+- Produces: G03 动态标题 `isAncestorStep ? "录入首代人物" : "创建家谱"`,以及现有 `goBack()` 对第一、第二步的业务分流。
+
+- [ ] **Step 1: 将 G03 契约改成公共页头要求**
+
+在 `tests/g03-visual-states-contract.ps1` 删除 `.flow-header__back`、`.flow-header__side` 和 `.flow-header__back-icon` 尺寸断言,改为:
+
+```powershell
+Assert-Match -Content $g03 -Pattern '(?s)' -Message 'G03 must use PageHeader with its dynamic title and custom back handler'
+if ($g03 -match 'flow-header|flow-header__back|flow-header__title') { throw 'G03 must not retain a private header implementation' }
+```
+
+在 `tests/g03-create-flow-contract.ps1` 的 required 项中加入:
+
+```powershell
+'import PageHeader from "@/components/PageHeader.vue";',
+'
+```
+
+在 `