- Visible canvases (>=48px) are captured as PNG stills at capture time
(toDataURL, element-screenshot fallback for tainted/webgl) and emitted as
cid-carrying <img> elements filling the captured box, so canvas-driven
bands no longer render blank
- Source AND clone full-page screenshots now capture via CDP
Page.captureScreenshot with captureBeyondViewport: no scroll-stitching,
no scroll events, so scroll-linked animations can't smear mid-scrub
states into perceptual evidence (pixel-identical to the old path on
static pages; Playwright fallback retained)
- DittoLottie's runtime overlay stays position:absolute/inset:0 for its
whole life and the host carries data-ditto-lottie with a scoped
svg/canvas fit rule, so the runtime animation always fills the pinned
per-viewport box instead of escaping to aspect height
259 tests pass (12 new), typecheck clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- heightFlows() bails when the capture probe proved a height authored-
explicit (hAuto=false, hFill=false), so circular parent/child flow
reasoning can no longer drop 100vh heroes to 0px; the probe verdict now
vetoes the drop through both OR'd paths at the call site
- Space-distributing flex columns (space-between/around/evenly, center,
flex-end) disqualify the content-driven read - the box height is load-
bearing for the distribution
- Lottie mounts pin their captured per-viewport height like other replaced
content, so aspect-fit runtime svgs can't inflate past the captured box
- DittoLottie forwards the placeholder's data-cid onto the runtime svg/
canvas so the media stays addressable after the swap
240 tests pass (9 new), typecheck clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Capture:
- Preserve real asset extensions (.lottie no longer truncated); extract the
default animation JSON from dotLottie ZIP containers at materialization
(minimal built-in ZIP reader, no new deps)
- Reset scroll + settle before every viewport snapshot so scroll-linked
styles can't bake into captured computed values
- Marquee detection now requires content overflow (>1.35x), sustained
velocity across separated windows, scroll independence (jiggle test), and
genuine content repetition — kills scroll-settle-lerp false positives
- Sizing probe trusts authored explicit heights (px/vh/calc) over circular
parent/child reflow verdicts, fixing dropped 100vh heroes
Normalize/generate:
- Canonicalize identity transforms to "none" per viewport; emit explicit
transform resets across bands when any band has a real transform
- DittoLottie keeps the captured placeholder until DOMLoaded; failed loads
no longer blank the container
- mx-auto only for true auto-margin centering; literal per-band margins are
preserved (fixes full-bleed regressions)
- Spacing-scale snap tightened to 0.25px (3.5px stays p-[3.5px]); emit
whitespace-nowrap for wrap-vulnerable single-line text leaves
- Grid recipes no longer override captured track counts or column spans;
responsive re-flow plans apply only when geometry agrees
Quality scoring:
- Rewritten 6-dimension rubric (payload, decomposition, duplication,
semantics, hygiene, runtime) with catastrophe caps and per-dimension
reporting; thresholds are documented calibration guides
218 tests pass (74 new), typecheck clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>