$ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot $pagePath = Join-Path $root 'pages/genealogy/g06-search-genealogies.vue' $page = Get-Content -LiteralPath $pagePath -Raw -Encoding utf8 $style = [regex]::Match($page, '(?s)]*>(.*?)').Groups[1].Value $styleWithoutComments = [regex]::Replace($style, '(?s)/\*.*?\*/', '') $positions = [regex]::Matches($styleWithoutComments, '(?m)\bposition\s*:\s*([^;]+);') if ($positions.Count -ne 0) { $values = ($positions | ForEach-Object { $_.Groups[1].Value.Trim() }) -join ', ' throw "G06 search and invitation layouts must use document flow; found $($positions.Count) position declarations: $values" } foreach ($required in @( '@include adaptive-g06-search-field;', '@include adaptive-g06-search-action;', '@include adaptive-genealogy-list-card;', 'background: url("/static/assets/foundation/transparent/a01-scroll-primary-v3.png")' )) { if ($styleWithoutComments -notmatch [regex]::Escape($required)) { throw "G06 document-flow migration is missing asset-backed surface: $required" } } foreach ($forbidden in @('search-title-strip', 'g06-search-title-strip.png')) { if ($page -match [regex]::Escape($forbidden)) { throw "G06 must not retain removed title-strip token: $forbidden" } } foreach ($obsoleteClass in @('search-title-strip__skin', 'search-field__skin', 'search-action__skin', 'result-card__skin')) { if ($page -match "class=`"$obsoleteClass`"") { throw "G06 must not retain decorative image layer .$obsoleteClass" } } if ($style -match '(?s)\.result-card\s*\{[^}]*overflow\s*:\s*hidden') { throw 'G06 result cards must grow with search-result data instead of clipping content' } Write-Output 'G06-DOCUMENT-FLOW-CONTRACT PASS'