The screenshot was lying about the app
The Hub is one HTML file rendered by WKWebView on macOS and WebView2 on Windows, so screenshots are how it gets checked. Both builds take one with a --shot flag, because the obvious tools lie about this kind of window — screencapture -l<windowid> answers "could not create image from window" for a perfectly healthy WKWebView, since it composites out of process.
Then the screenshots started lying too.
What it showed#
Click "Extensions" in the sidebar. The Extensions page appears. The highlight stays on "Dashboard".
That is a real bug shape, and a familiar one: an attribute selector that the style engine did not re-evaluate.
.nav button[aria-current="true"] { background: var(--accent-soft); }What it actually was#
Before rewriting anything, ask the page what it thinks. Dispatch a real click, wait well past the transition, and read the computed style rather than looking at pixels:
dash = false / 213,90,52,0.14
ext = true / 0,0,0,0The attributes are correct. dash is false and still painted the accent colour; ext is true and still transparent. Nine hundred milliseconds after a .18s transition should have finished.
The tell is that both are sitting exactly on their starting values. Not stale, not wrong — unstarted. Removing one line settled it:
.nav button { transition: none }With that, the same run is correct in both the computed style and the picture. Which identifies the timeline, not the selector, and not style invalidation.
Why#
The window is never put on a screen. A --shot run creates it, renders, snaps and quits, and a web engine has no reason to advance an animation for a surface nobody is looking at. The transition is queued, the first frame is committed, and time stops.
So the picture was accurate. It was an accurate picture of a moment 200ms into a 180ms transition that would never advance — and every human who looked at it read a permanent state.
Two things changed, and neither was the page#
The page was already correct and was left alone. The mistake was nearly "fixing" it, and shipping a class-based workaround plus a confident comment about a WebKit bug that does not exist. That comment would have outlived everyone who could contradict it.
The screenshot flag now turns transitions and animations off before it changes anything:
var s = document.createElement('style');
s.textContent = '*{transition:none !important;animation:none !important}';
document.head.appendChild(s);And it grew --shot-delay, because the next thing to photograph had to sign in, download something and start a browser first, and none of that fits in the second and a half the default allows.
The general version#
A measurement can be wrong in a way that looks exactly like the thing you were measuring being wrong. The instrument had a known failure mode already — that is why the flag exists — and it acquired a second one that pointed at the subject instead of at itself.
Cheap defence, and the only one that worked here: before believing a diagnosis, change one variable that should be irrelevant. transition: none should not have been able to fix a broken selector. It did, and that was the answer.