Validation waits for webfonts before measuring; sticky wrappers keep fluid width

- The render walk and screenshots now await document.fonts.ready plus a
  bounded state-based poll until every declared face is terminal
  (loaded/error); pending families surface as a font_wait_warning event
  instead of skewing text metrics with fallback-font boxes
- position:sticky full-width wrappers share the static/relative
  fluid-fill branch (a sticky box fills its containing block like any
  in-flow box) instead of freezing at canonical px; fixed-width sticky
  rails still freeze

447 tests pass (12 new), typecheck clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samraaj Bath
2026-07-04 06:21:07 -07:00
co-authored by Claude Fable 5
parent 5b60ded62d
commit fae44aab93
5 changed files with 215 additions and 7 deletions
+3
View File
@@ -108,6 +108,9 @@ export async function validateRun(runDir: string, opts?: { harnessDir?: string;
try {
const r = await renderApp({ url: server.url + "/", viewports, renderedDir });
snapshots = r.snapshots; runtimeErrors = r.runtimeErrors; httpStatus = r.httpStatus; failedResources = r.failedResources;
// Non-fatal: webfonts that never loaded before the render walk (text was measured in a fallback
// face). Surfaced as a warning event, NOT a runtime error, so it never fails gate 0.
if (r.fontWarnings.length) log({ event: "font_wait_warning", families: r.fontWarnings });
probeSnaps = await measureProbeWidths({ url: server.url + "/", widths: probeWidthsFor(viewports) });
if (capture.interaction) {
interactionGate = await driveInteractionGate({ url: server.url + "/", viewports, ir, interaction: capture.interaction });