$ErrorActionPreference = 'Stop' function Read-Utf8([string]$Path) { [System.IO.File]::ReadAllText((Join-Path (Join-Path $PSScriptRoot '..') $Path), [System.Text.Encoding]::UTF8) } function Assert-Contains([string]$Content, [string]$Expected, [string]$Message) { if (-not $Content.Contains($Expected)) { throw $Message } } function Assert-Match([string]$Content, [string]$Pattern, [string]$Message) { if ($Content -notmatch $Pattern) { throw $Message } } $f01 = Read-Utf8 'pages/family/f01-family-feed.vue' $f02 = Read-Utf8 'pages/family/f02-publish-feed.vue' $module = Read-Utf8 'components/ModulePage.vue' foreach ($expected in @('24rpx','23rpx','22rpx')) { Assert-Match $f01 "font-size:\s*$expected" "F01 readability token missing: $expected" } foreach ($expected in @('24rpx','23rpx')) { Assert-Match $f02 "font-size:\s*$expected" "F02 readability token missing: $expected" } foreach ($expected in @( '(?s)\.module-lead\s*\{[^}]*height:\s*56rpx;[^}]*font-size:\s*23rpx;', '(?s)\.form-row > text\s*\{[^}]*font-size:\s*24rpx;', '(?s)\.form-row input\s*\{[^}]*height:\s*56rpx;[^}]*font-size:\s*23rpx;', '(?s)\.list-card__copy text:nth-child\(2\)\s*\{[^}]*font-size:\s*23rpx;', '(?s)\.detail-card text:last-child\s*\{[^}]*font-size:\s*24rpx;', '(?s)\.status-card__note\s*\{[^}]*font-size:\s*24rpx;' )) { Assert-Match $module $expected "ModulePage readability contract missing: $expected" } Write-Output 'F series all-states visual contract passed.'