The ticket was supposed to be a victory lap. The checkout flow had been AI-built, AI-reviewed, AI-polished, and shipped to a review branch. Then a senior dev sent four notes back. Then another reviewer caught a button that grew when you clicked it.
This was not a greenfield build. It was the long tail of review feedback on a live checkout flow that an agent had already declared finished.
The senior dev’s pass forced another round of visual fixes I had not seen on my own. The stepper increments were off. The sticky checkout bar at the bottom of the page was misaligned with the content above it. Event cards were not navigating the way the rest of the site navigates. The price CTA was rendering in the site default font instead of DM Sans, which is small and stupid and immediately obvious once someone points at it. None of those are model failures. They are the failures of a reviewer who is also the author, which is what I am when an agent ships a UI and I look at it next.
I fixed them. I thought we were done.
the 4 pixel lie
Then the second reviewer caught the one I would never have noticed.
The checkout button was changing dimensions between its inactive and active states. Not by much. Four pixels of growth on the right side when you clicked it. Visually it read as the button shrugging. That reviewer noticed because he was looking at real DOM in a real browser, switching states, and his eye registered the layout shift.
The cause was the kind of thing AI-generated CSS produces all the time and then does not double-check. The inactive state had no border. The active state added a 2px border on each side. Browser border math pushed the content box out by 4 pixels. At the same time, the label text was wrapping differently between the two states because the box was now wider, so the height was also bouncing. Two layout bugs fighting each other and rendering as one twitchy button.
The fix was embarrassingly specific. A transparent 2px base border so the inactive state reserves the same space the active state will claim. box-sizing: border-box so the border is counted inside the width, not added to it. A 320px minimum width so the label never wraps. Centered content so both states render at exactly 320x90. Five lines of CSS that nobody wrote down in any reasoning trace because the agent did not know it was a problem.
That is the real shape of AI-assisted frontend work right now. The machine gets you 95 percent of the way to a plausible UI fast. A skilled skeptic finds the visual lies in the last 5 percent. Sometimes the last 5 percent is one button that grows by 4 pixels on a state transition.
the part that does not generalize from the prompt
The useful takeaway is not “AI is bad at UI.” It ships UI fine. It ships UI faster than I do.
The takeaway is that there is a specific class of bug the model will gloss over every time, and you need a human in the loop who knows to look for it. State transitions where geometry shifts. Layout edge cases where two CSS properties interact in a way that only shows up when you click the thing. Typography on price CTAs because nobody writes “and the font must be DM Sans” in a Jira ticket, they just see the wrong font and feel that something is off.
These problems come from the model not having the live thing in front of it, not from any lack of intelligence. The agent does not click the button and watch what happens. Human reviewers do. That asymmetry is what makes review still load-bearing on AI-assisted work, and it is not going away in the next model generation either.
What does change is how you set up the review. The agent’s job is to ship the plausible version fast and to be honest about what it could not check. The reviewer’s job is to know which classes of bug the agent is structurally blind to and to look for those, not to re-do the work the agent already did well. One reviewer is checking layout integrity across states. The other is checking checkout flow geometry under interaction. Neither of them is line-reviewing CSS. They are doing what the agent cannot.
The skeptic earns their keep on the 4 pixels the model could not see.