Workspace ghost, first paint

PR #11895 · board row p11-x-skeleton-everywhere · Gera decision b90278665 · companion to pr-11895-evidence (the loaded page).

What a signed-in hard load paints before the layout has read anything: the rail column, the top-bar strip, and now one neutral line where the page heading will land. Before this PR the ghost had no text, image or SVG, so the browser's first contentful paint waited for the real frame (+209 ms p50 / +330 ms p75 on a warm instance, 2026-09-24).

How this was captured. This state lasts a few hundred milliseconds, so the capture tool's route-and-wait flow cannot reach it. Instead Playwright requested /dashboard from the branch's own dev server (stage data), intercepted the real server response, and cut it right after the ghost's markup. It kept the theme and side-nav pre-paint scripts and dropped every other script. In the frozen page, first-contentful-paint fired, and its only text was the loading line plus the dev-only persona pill (bottom left), which production strips at build time.

Re-shot after review round 1. The line now takes the muted token from FRAME_SURFACE.loadingLine (the class text-muted compiled to no CSS). Its computed colour is rgb(79,107,158) = #4F6B9E in light, against body text #0F2060, and rgb(136,136,151) = #888897 in dark, against #F4F4F6.

Frame ghost, light theme: empty rail, top strip, and the line Loading your workspace
Light theme, 1440×900.
Frame ghost, dark theme: the same frame with the loading line
Dark theme, 1440×900.
PropFlow Docs