$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 @( 'background: url("/static/assets/modules/genealogy/opaque/g06-search-title-strip.png")', 'background: url("/static/assets/modules/genealogy/opaque/g06-search-input-wide.png")', 'background: url("/static/assets/modules/genealogy/opaque/g06-search-button.png")', 'background: url("/static/assets/modules/genealogy/transparent/list-slip-frame.png")', 'background: url("/static/assets/foundation/transparent/a01-scroll-primary-v3.png")' )) { if ($page -notmatch [regex]::Escape($required)) { throw "G06 document-flow migration is missing asset-backed surface: $required" } } 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'