← All analyses

A construction client's build (unnamed) · Hero · 02/10/2026

A construction client's build, hero section

A builder's hero that shows a house as found, then wipes across to a visualisation of the finished renovation, with controls to replay it or go back to the starting point. The strongest trade hero in our builds, and on a first visit in Chrome its signature wipe uncovers an empty layer.

Findings at a glance

12 of 12 findings

Ref
I7On a phone profile, a Chromium screenshot forces the deferred lazy load, so a visual test hides the bugverify-live takes no screenshot during a loading testInstrument trapInstrumentIn the probe
I6currentSrc and complete tell you when a picture is really there; the frame alone does notInstrument trapInstrumentRecorded
I5A Safari check returns clean: the fault is Chromium-onlyTest reveals in Chromium as well as WebKitInstrument trapInstrumentPromoted
F3The subject waits 4.1 s behind a logo introNot a lock: all 9 first-screen actions were pressableFailure modeMotionRecorded
F232 visible text runs under 12px on a phone, the visualisation label at 7pxThird exemplar behind the 12px floor; routed to the buildFailure modeTypeAlready covered
F1A lazy after-picture in a keyframe clip: the wipe uncovers an empty layer in ChromiumIn web-frontend with the mechanism tables, 02/10/2026Failure modePerformancePromoted
C6A lens over the house as found that shows the finished house, with the plan drawn around itPromoted 03/10/2026 as an option, not the better choice: proven buildable and accessible, not proven on buyersTechniqueInteractionPromoted
C5Flat daylight before, blue hour afterAmplifies the change and flatters it: pair it with C4TechniqueColourRecorded
C4The finished picture labelled as a visualisation, in the frameIn web-frontend, extended to materially altered photos: label in the frame, at 12px or aboveTechniqueContentPromoted
C3Replay, and a starting-point button whose label names where it goes nextOurs adds a pressed state and a keyboard sliderTechniqueInteractionRecorded
C2A wipe, not a fade: a clip-path over 2.8 s on a slow-in, slow-out curveOurs keeps the wipe and adds a draggable seamTechniqueMotionRecorded
C1One house, one camera position, before and after, as the heroweb-frontend rule 1 cites this build: for a trade, the transformation is the productTechniqueCompositionAlready covered

Analysed: 02/10/2026 · By: Design Lab · Evidence: captures/construction-client-a/2026-10-02/ (probe summary, frames, transform/transform.json, and the follow-up scripts' output quoted below). This is one of our own client builds, so it is not named here. The specimen's business and copy are invented. Its two pictures are the pair Pete supplied to that build, used here on his ruling (§5).

Instruments: the exemplar-probe skill on full Chromium (renderer ANGLE Metal), a timed follow-up that sampled the hero's layers and document.getAnimations() for 30 seconds and pressed each control, a cold-cache load check on three network profiles, and a mechanism test on a page served by request interception (no server), run in Chromium and WebKit.

1. Why this build

Pete pointed at it: "the 2 houses". web-frontend rule 1 already cites it as the winning build of a two-engine comparison, because its hero shows the product instead of describing it. It is the first of our own builds this lab has analysed, which is why it is anonymous: protection is a setting someone can change, and a client's name inside our site would then be public (steward ruling, 02/10/2026).

2. What it does, measured

time what happens how
0 to 2.5 s the logo assembles from five parts CSS keyframes, 1.4 s each, staggered 140 ms
2.4 s the headline and lead rise in 1.1 s, opacity and transform
0 to 4.1 s the logo travels to the top-left corner one 4.1 s keyframe animation
4.1 to 6.9 s the finished house wipes in over the house as found clip-path: inset(0 100% 0 0) → inset(0), 2.8 s, cubic-bezier(0.6, 0, 0.3, 1), on a layer above the first picture

Below it sit three controls: Replay transformation (named "Replay the house transformation"), a pause button that exists only while motion runs, and See the starting point, which wipes back and renames itself See the possibility. Two corner tags carry the context: one with the tagline, one saying Design visualisation.

3. The techniques

C1 · One house, one camera position

The before and the after are the same house from the same spot, so the wipe reads as the house changing, not as one picture replacing another. This is the whole technique, and it is easy to lose: two pictures from different angles turn the same wipe into a slideshow. Registration matters more than either picture's quality.

Suits: any trade whose product is a change to something that already exists (extensions, renovation, landscaping, kitchens, restoration, cleaning, signwriting). Does not suit: new builds with no before; services with nothing visible to compare; any client without a real before-and-after pair, or the right to use one.

C2 · A wipe, not a fade

A cross-fade blends two houses into a ghost in the middle. A hard-edged wipe keeps both readable at every instant, and the edge itself becomes a line the eye follows across the change. The 2.8 s curve starts and ends slowly, so the middle, where the most change is visible, is the fastest part.

C3 · Controls that name the destination

See the starting point becomes See the possibility once pressed. The button says where it takes you, not what state it is in, which reads well. It carries no aria-pressed, so a screen reader hears only a renamed button; the renaming is adequate, and a pressed state would be better.

C4 · The finished picture labelled as a visualisation

A Design visualisation tag sits in the frame. For a trade this is more than courtesy: a render shown as finished work is a claim the client cannot stand behind. The label lets the hero show the possibility without saying it was built. (Its type is 7 px on a phone, which defeats the point: F2.)

Promoted to web-frontend (02/10/2026), as proposed and extended by the steward to photographs that have been materially altered (relit, sky replaced, interiors composited): a visible label in the frame, never only in a caption, at the 12 px floor or above; never present a render as completed work. The 7 px label on this build is the reason for the floor clause: it labels the render in the markup and nobody can read it.

C5 · Flat daylight before, blue hour after

The before is shot in dull daylight; the after is dusk with every light on. The light change does as much work as the building work, and it flatters. That is fine when C4 is present and misleading when it is not.

4. Failures

F1 · The wipe uncovers an empty layer

The after picture is loading="lazy" inside the clipped layer. On a cold cache in Chromium, img.complete && naturalWidth was false for the whole wipe on every run:

run wipe after picture ready samples revealed but empty
desktop, unthrottled 4359 → 6962 ms 7116 ms 18, up to 100% revealed
desktop, fast 4G 4639 → 7393 ms 7694 ms 20
phone, fast 4G 4625 → 7366 ms 7672 ms 20

Positive control: the same check reads the first picture loaded at 1.5 s, and reads the after picture loaded mid-replay (clip at 61%), where the wipe visibly works. So the instrument can see the picture; the picture was not there. A visitor sees the house as found, then the finished house pops in after the wipe has ended. Replay works because the picture is cached by then, which is why nobody building it would notice.

The mechanism, isolated (a 64 px PNG served by request interception, one lazy image in one layer):

layer Chromium requests it at WebKit
no clip (control) 15 ms 88 ms
static clip-path: inset(0 100% 0 0) never 17 ms
keyframe clip-path, wipe 1000 → 3800 ms 3813 ms, as it ends 9 ms
clip-path set per frame from script 1018 ms, the first open frame 10 ms
a CSS variable set per frame 1019 ms 17 ms
opacity: 0 8 ms 14 ms
transform: scaleX(0) · translateX(-100%) · animated scale 8 · 8 · 7 ms not run

So: in Chromium, a lazy picture inside a keyframe-animated clip-path is not fetched until the animation ends. A script-driven clip is seen, but the fetch then starts as the wipe starts, so the opening of the reveal is still empty on a slow connection. WebKit fetches at once, so a check in Safari comes back clean (I5). Why Chromium behaves this way is not established here; the table is the finding.

The rule (promoted): the revealed picture is eager, and the reveal waits for img.decode().

I6: a screenshot taken mid-wipe looked like a wipe over the starting picture and could have passed as "the reveal is subtle". Only currentSrc, complete and naturalWidth, sampled against the clip, showed that nothing was there to reveal.

I7 · A screenshot can fetch the picture the bug withholds

Found while verifying our own specimen. Its lazy replay showed the picture arriving 1.32s into the wipe on a Pixel profile, twice, instead of at the end. The phone check took a screenshot at 1.30s. Measured on the live specimen with a cold URL:

profile screenshot at 1.3s lazy picture requested at wipe ends
Pixel 7 emulation no 2601 ms 2600 ms
Pixel 7 emulation yes 1265 ms 2598 ms
desktop 1440 no 2601 ms 2600 ms
desktop 1440 yes 2601 ms 2600 ms

So a screenshot-driven visual check on a phone profile makes the reveal work, and hides the fault. My first test of this was unsound and reported "no effect": its screenshot targeted /dev/null, which Playwright rejects, and the error was swallowed. Recorded via learn.sh.

F2 · Labels under the floor

Visible text runs under 12 px (hidden and screen-reader-only text excluded): 32 at 390 px wide, including the visualisation label at 7 px, the replay control's label at 9 px and the section eyebrows at 8 to 9 px; 28 at 1440 px, at 10 to 11 px. Already covered by the 12 px floor; routed to the build's own session.

F3 · The subject waits behind a logo

The house as found appears only after a 4.1 s logo intro. It is not a lock (all nine actions on the first screen were pressable and the wheel scrolled), so it costs time rather than control. For a trade, the house is the argument; leading with the logo delays it.

5. The specimens

The technique, Pete's direction (02/10/2026): "we already had a house with a slider; I wanted the landonorris technique done to the houses." A before-and-after slider is what this build already had, so a slider specimen added nothing. The craft worth rebuilding was the award technique, applied to this material: /specimens/house-lens puts the house as found under the pointer, draws the new design in line over it, and shows the finished house through a glass lens. It is landonorris.com's T9 on a renovation.

Promoted to web-frontend (03/10/2026) as an option with conditions, never as the better choice. Evidence status, in the steward's words, kept because it protects the technique: built and verified (60 fps on both phone engines, follows a tap to 0 px), so proven buildable and accessible; NOT proven on real visitors. Nobody has measured whether buyers prefer exploring to watching. The steward added four conditions, and the specimen now meets all four:

  • the idle tour stops under reduced motion
  • each place carries a short description of what changes there, announced when chosen
  • the lens goes live only on a frame that has actually drawn (read back, alpha 255), and falls back to the photograph on a lost context
  • a "Show it finished" view serves visitors who only want the result

On phones the copy now flows below the picture, so it can never sit over the lens.

The rule: /specimens/decode-gated-reveal, below, keeps the wipe for the one thing it is good for: showing F1 live.

The wipe, as a rule specimen

The pictures are Pete's. He supplied this before-and-after pair, a photograph and a visualisation made from it on the same footprint, and cleared them for this internal specimen (02/10/2026). That is the one exception to the lab's rule of using no material from the studied site, and the reason for it is recorded here. The pair registers well: in a 50/50 blend the roofline, rooflights, eaves, ground line and the neighbour's roof coincide, and only the parts the renovation changes show twice. (An edge phase-correlation peak was no stronger than its noise control, so it could not judge this; the blend did.) The rebuild:

  • the after picture loads eagerly and the wipe waits for it to decode; the readout states how long before the wipe it was ready
  • the seam is a real control: drag it, swipe it on a phone (vertical scrolling still scrolls), or move it with the keyboard as a slider
  • Starting point and Finished are a pressed-state toggle; every label is 12 px or larger
  • "Replay it lazily (the bug)" rebuilds the exemplar's construction on purpose (a fresh lazy picture in a keyframe clip, with the measured curve) and the readout reports when the picture arrived against the wipe. In Chrome it arrives after the wipe has ended; in Safari it does not
  • no logo intro: it plays when the stage is in view, and reduced motion shows the finished house