package web import ( "regexp" "strings" "testing" ) // Dashboard layout fixes, 2026-10-08 (REPORT-dashboard-layout.md). A Go test cannot measure pixels; these pin the // markup and the rules the layout stands on, and the screenshots (felhom.eu/documentation/audits/ // dashboard-layout-2026-10-08/) show the consequence. // cssRule returns the body of the top-level rule whose selector line is exactly `selector {`. func cssRule(t *testing.T, css, selector string) string { t.Helper() i := strings.Index(css, "\n"+selector+" {") if i < 0 { t.Fatalf("style.css has no top-level %q rule", selector) } body := css[i+len(selector)+3:] return body[:strings.IndexByte(body, '}')] } // The Apps card header. Before: the title row and every tag were siblings in ONE space-between flex row; with two // or more tags (any installed app) the one-word name ran under them, and the logo was centred on the name block, // so a card with an address carried it lower than one without. // // RED-PROOF (REPORT): against 05e12921's stacks.html and style.css this fails — no .stack-tags, a tag before it, // no address title, and the header rule still `justify-content: space-between`. func TestStackCardHeaderLayout(t *testing.T) { s := i18nTestServer(t) var full i18nCase for _, c := range i18nCases() { if c.name == "stacks_full" { full = c } } if full.name == "" { t.Fatal("no stacks_full parity case") } addrRe := regexp.MustCompile(`\s*([^<]*) ↗\s*`) for _, lang := range []string{"hu", "en"} { page := renderI18nCase(t, s, lang, full) cards := strings.Split(page, `