diff --git a/components/AppButton.vue b/components/AppButton.vue
index 1164a35..73c770c 100644
--- a/components/AppButton.vue
+++ b/components/AppButton.vue
@@ -3,7 +3,11 @@
class="app-button"
:class="[
`app-button--${type}`,
- { 'app-button--block': block, 'app-button--disabled': disabled },
+ {
+ 'app-button--block': block,
+ 'app-button--compact': compact,
+ 'app-button--disabled': disabled,
+ },
]"
:disabled="disabled"
:aria-label="label"
@@ -24,6 +28,7 @@ const props = defineProps({
label: { type: String, default: "" },
type: { type: String, default: "primary" },
block: { type: Boolean, default: false },
+ compact: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
});
const emit = defineEmits(["click"]);
@@ -40,6 +45,8 @@ const handleClick = (event) => {
diff --git a/pages/family/f08-album-detail.vue b/pages/family/f08-album-detail.vue
index 2c6bff8..9dbce50 100644
--- a/pages/family/f08-album-detail.vue
+++ b/pages/family/f08-album-detail.vue
@@ -158,6 +158,8 @@ onBackPress(() => {
diff --git a/pages/profile/m04-change-password.vue b/pages/profile/m04-change-password.vue
index 60c9dae..8b29079 100644
--- a/pages/profile/m04-change-password.vue
+++ b/pages/profile/m04-change-password.vue
@@ -55,5 +55,6 @@ onUnmounted(() => clearTimeout(timer));
diff --git a/pages/profile/m05-change-phone.vue b/pages/profile/m05-change-phone.vue
index 63326a0..f3b8db9 100644
--- a/pages/profile/m05-change-phone.vue
+++ b/pages/profile/m05-change-phone.vue
@@ -51,5 +51,6 @@ onUnmounted(() => { clearInterval(countdownTimer); clearTimeout(stateTimer); cle
diff --git a/pages/profile/m06-help-center.vue b/pages/profile/m06-help-center.vue
index 5d440cd..ce55446 100644
--- a/pages/profile/m06-help-center.vue
+++ b/pages/profile/m06-help-center.vue
@@ -44,5 +44,6 @@ const contactSupport = () => uni.navigateTo({ url: "/pages/profile/m07-feedback"
diff --git a/pages/profile/m07-feedback.vue b/pages/profile/m07-feedback.vue
index ee6d1ce..1330af9 100644
--- a/pages/profile/m07-feedback.vue
+++ b/pages/profile/m07-feedback.vue
@@ -48,5 +48,6 @@ onUnmounted(() => clearTimeout(timer));
diff --git a/pages/profile/m08-promotion.vue b/pages/profile/m08-promotion.vue
index c81ce54..447e11b 100644
--- a/pages/profile/m08-promotion.vue
+++ b/pages/profile/m08-promotion.vue
@@ -42,5 +42,6 @@ onUnmounted(() => clearTimeout(timer));
diff --git a/pages/profile/m09-vip-orders.vue b/pages/profile/m09-vip-orders.vue
index 4ba18cd..4696572 100644
--- a/pages/profile/m09-vip-orders.vue
+++ b/pages/profile/m09-vip-orders.vue
@@ -35,5 +35,6 @@ const openServiceNotice = () => { serviceNoticeVisible.value = true; };
diff --git a/pages/profile/m10-about-settings.vue b/pages/profile/m10-about-settings.vue
index ac1c4f6..7a7520c 100644
--- a/pages/profile/m10-about-settings.vue
+++ b/pages/profile/m10-about-settings.vue
@@ -38,5 +38,6 @@ onUnmounted(() => clearTimeout(timer));
diff --git a/pages/records/r01-people-list.vue b/pages/records/r01-people-list.vue
index bc7487d..5fbf395 100644
--- a/pages/records/r01-people-list.vue
+++ b/pages/records/r01-people-list.vue
@@ -163,6 +163,8 @@ onUnmounted(() => {
')
+ foreach ($styleMatch in $styleMatches) {
+ $css = $styleMatch.Groups['css'].Value
+ $ruleMatches = [regex]::Matches($css, '(?ms)(?[^{}]+)\{(?[^{}]*)\}')
+ foreach ($rule in $ruleMatches) {
+ $selector = Normalize-Selector $rule.Groups['selector'].Value
+ $body = $rule.Groups['body'].Value
+ $checks = @(
+ @{ Name = 'fixed-height'; Pattern = '(?im)(?image", "property": "fixed-height", "reason": "Fixed-ratio security icon." },
+ { "path": "pages/profile/m03-security-settings.vue", "selector": ".security-row .chevron", "property": "fixed-height", "reason": "Fixed-ratio navigation icon." },
+ { "path": "pages/profile/m10-about-settings.vue", "selector": ".brand-card image", "property": "fixed-height", "reason": "Fixed-ratio brand mark." },
+ { "path": "pages/profile/m10-about-settings.vue", "selector": ".settings-row image", "property": "fixed-height", "reason": "Fixed-ratio settings icon." },
+
+ { "path": "pages/tree/t01-tree-overview.vue", "selector": ".generation-band", "property": "fixed-height", "reason": "Fixed-height generation lane in the scrollable tree canvas." },
+ { "path": "pages/tree/t01-tree-overview.vue", "selector": ".member-node", "property": "fixed-height", "reason": "Fixed-ratio interactive tree node." },
+ { "path": "pages/tree/t01-tree-overview.vue", "selector": ".member-node--selected", "property": "fixed-height", "reason": "Selected state preserves the fixed-ratio tree node." },
+ { "path": "pages/tree/t03-member-profile.vue", "selector": ".member-heading__seal", "property": "fixed-height", "reason": "Fixed-ratio member seal." }
+ ]
+}
diff --git a/tests/responsive-layout-coverage.json b/tests/responsive-layout-coverage.json
new file mode 100644
index 0000000..1346542
--- /dev/null
+++ b/tests/responsive-layout-coverage.json
@@ -0,0 +1,70 @@
+{
+ "covered": [
+ "components/AppButton.vue",
+ "components/AppDialog.vue",
+ "components/AppLoading.vue",
+ "components/AppTabbar.vue",
+ "components/AppToast.vue",
+ "components/AuthPageShell.vue",
+ "components/GenealogyCard.vue",
+ "components/GenealogyPageBackground.vue",
+ "components/ModulePage.vue",
+ "components/ModulePageBackground.vue",
+ "components/PageHeader.vue",
+ "pages/auth/a01-entry.vue",
+ "pages/auth/a04-register.vue",
+ "pages/auth/a05-reset-password.vue",
+ "pages/auth/a06-auth-status.vue",
+ "pages/genealogy/g01-my-genealogies.vue",
+ "pages/genealogy/g03-create-genealogy.vue",
+ "pages/genealogy/g05-genealogy-overview.vue",
+ "pages/genealogy/g06-search-genealogies.vue",
+ "pages/genealogy/g08-join-application.vue",
+ "pages/genealogy/g09-my-applications.vue",
+ "pages/genealogy/g10-application-review.vue",
+ "pages/genealogy/g11-genealogy-settings.vue",
+ "pages/genealogy/g12-generation-poems.vue",
+ "App.vue",
+ "components/tree/TreeMemberForm.vue",
+ "pages/family/f01-family-feed.vue",
+ "pages/family/f02-publish-feed.vue",
+ "pages/family/f03-feed-detail.vue",
+ "pages/family/f04-article-list.vue",
+ "pages/family/f05-article-detail.vue",
+ "pages/family/f06-article-editor.vue",
+ "pages/family/f07-album-list.vue",
+ "pages/family/f08-album-detail.vue",
+ "pages/family/f09-media-upload.vue",
+ "pages/family/f10-video-list.vue",
+ "pages/notification/n01-message-center.vue",
+ "pages/notification/n02-message-detail.vue",
+ "pages/profile/m01-profile-home.vue",
+ "pages/profile/m02-edit-profile.vue",
+ "pages/profile/m03-security-settings.vue",
+ "pages/profile/m04-change-password.vue",
+ "pages/profile/m05-change-phone.vue",
+ "pages/profile/m06-help-center.vue",
+ "pages/profile/m07-feedback.vue",
+ "pages/profile/m08-promotion.vue",
+ "pages/profile/m09-vip-orders.vue",
+ "pages/profile/m10-about-settings.vue",
+ "pages/records/r01-people-list.vue",
+ "pages/records/r02-person-detail.vue",
+ "pages/records/r03-gift-list.vue",
+ "pages/records/r04-gift-editor.vue",
+ "pages/records/r05-ritual-list.vue",
+ "pages/records/r06-ritual-detail.vue",
+ "pages/records/r07-ritual-editor.vue",
+ "pages/records/r08-growth-journal.vue",
+ "pages/records/r09-life-events.vue",
+ "pages/records/r10-memo-list.vue",
+ "pages/records/r11-merit-records.vue",
+ "pages/tree/t01-tree-overview.vue",
+ "pages/tree/t03-member-profile.vue",
+ "pages/tree/t04-add-relative.vue",
+ "pages/tree/t05-edit-member.vue",
+ "pages/tree/t06-edit-relationship.vue",
+ "pages/tree/t07-member-directory.vue",
+ "pages/tree/t08-member-states.vue"
+ ]
+}
diff --git a/tests/shared-component-document-flow-contract.ps1 b/tests/shared-component-document-flow-contract.ps1
index 71e6b5f..a46557a 100644
--- a/tests/shared-component-document-flow-contract.ps1
+++ b/tests/shared-component-document-flow-contract.ps1
@@ -60,7 +60,7 @@ foreach ($selector in @('card-meta', 'card-updated', 'card-role')) {
if ($dialog -match '(?s)\.app-dialog\s*\{[^}]*position\s*:|(?s)\.app-dialog__content\s*\{[^}]*position\s*:') {
throw 'AppDialog internal content must not use positioning'
}
-Assert-Match $dialog '(?s)\.app-dialog\s*\{[^}]*background:\s*url\("/static/assets/modules/auth/transparent/a01-scroll-dialog-v3\.png"\)' 'AppDialog must render its approved dialog asset as the dialog background'
+Assert-Match $dialog '(?s)\.app-dialog\s*\{[^}]*@include\s+adaptive\.adaptive-auth-dialog;' 'AppDialog must consume the approved adaptive dialog frame profile'
if ($loading -match '(?im)(?