The design system cannot ship a page covered by something closed: a lint and a phone-sized look on every release
What happened. Release 0.7.549 (2026-11-12) put a black panel over every page of the forge on a phone, with a close button that did nothing. Cause: the command palette's phone layout (#11684) set display: flex on the bare .palette selector inside @media (max-width: 719px) in src/web/style/components.ts, which overrides the browser's dialog:not([open]) { display: none }. The palette is a <dialog>; closed, it was drawn full-screen (fixed, 375×844) over the content. The check was green, the pull was reviewed, the release verify passed (it probes status codes), and nobody looked at a phone. The owner found it. The steward removed the declaration on main (0556849). Owner: "type of thing that the design system can never allow."
What.
A lint in scripts/ (design-lint), failing the check: no rule may set display (other than none) on a selector that can match a closed <dialog>, a [popover], or an element with the hidden attribute, unless the selector itself requires the open state ([open], :popover-open, :not([hidden])). The same for visibility: visible and opacity above 0 with position: fixed. The message names the selector and says what to write instead. Run it over every stylesheet source, including media queries.
A structural rule in the component vocabulary: overlays (dialog, palette, sheet, drawer, toast) get their layout from one shared rule keyed on the open state; a component adds only what is its own. docs/DESIGN.md says so in three lines.
A covered-page test in the browser suite, at 390×844 and 1280×800, for every page in the forge's looks list, signed out and signed in: on load, with nothing opened, no element that is a dialog, popover, backdrop or position: fixed layer larger than a quarter of the viewport may be the topmost element at the centre of the screen; the page's main content must be the element under the centre point and must receive a click. Then open each overlay the page has and assert that Escape, its close button and a tap outside each close it and return the page.
The release proof looks at a phone. The verify step that follows a release loads the home page, one repository page and one app page at phone size and runs the centre-point assertion from (3); a failure rolls the release back like any failed verify. Status 200 is not proof a person can use the page.
Looks are compared. A pull that changes any stylesheet source gets the phone and desktop looks of the home page before and after, side by side in the pull, and a reviewer may not approve a stylesheet change without them present.
Acceptance. Re-adding display: flex to bare .palette in a test branch fails (1) with the selector named, fails (3) on every page, and fails the release proof in (4). The lint passes on today's main after the fix. docs/DESIGN.md carries the overlay rule.
The design system cannot ship a page covered by something closed: a lint and a phone-sized look on every release
What happened. Release 0.7.549 (2026-11-12) put a black panel over every page of the forge on a phone, with a close button that did nothing. Cause: the command palette's phone layout (#11684) set
display: flexon the bare.paletteselector inside@media (max-width: 719px)insrc/web/style/components.ts, which overrides the browser'sdialog:not([open]) { display: none }. The palette is a<dialog>; closed, it was drawn full-screen (fixed, 375×844) over the content. The check was green, the pull was reviewed, the release verify passed (it probes status codes), and nobody looked at a phone. The owner found it. The steward removed the declaration on main (0556849). Owner: "type of thing that the design system can never allow."What.
scripts/(design-lint), failing the check: no rule may setdisplay(other thannone) on a selector that can match a closed<dialog>, a[popover], or an element with thehiddenattribute, unless the selector itself requires the open state ([open],:popover-open,:not([hidden])). The same forvisibility: visibleandopacityabove 0 withposition: fixed. The message names the selector and says what to write instead. Run it over every stylesheet source, including media queries.docs/DESIGN.mdsays so in three lines.lookslist, signed out and signed in: on load, with nothing opened, no element that is a dialog, popover, backdrop orposition: fixedlayer larger than a quarter of the viewport may be the topmost element at the centre of the screen; the page's main content must be the element under the centre point and must receive a click. Then open each overlay the page has and assert that Escape, its close button and a tap outside each close it and return the page.Acceptance. Re-adding
display: flexto bare.palettein a test branch fails (1) with the selector named, fails (3) on every page, and fails the release proof in (4). The lint passes on today's main after the fix. docs/DESIGN.md carries the overlay rule.