Replace the ordering-dependent onConfigure value-latching dance with a
convergent refreshFromWidgets() reconcile that is safe to call any time:
crop_state is parsed to a source-space st.pendingCrop, consumed exactly
once by the first successful initLayout, and colors + AR-lock button are
reconciled from the hidden widgets. Removes _latched* state and the
per-site replay logic; collapses the double-rAF init to a single frame
(ResizeObserver uniformly owns geometry-readiness).
Sizing contract is hardened belt-and-suspenders: add getHeight and the
--comfy-widget-min-height CSS var alongside getMinHeight, and add a
one-shot warnIfSizingIgnored() that flags (never fights) a frontend that
stops honoring the undocumented DOM-widget sizing options.
Fix two blob-URL leaks via setFrameImg/revokeIfBlob: the scrub blob
overwritten by applyFrameData's data: URL, and the final blob on removal.
Also document in V3_DOC_GAPS #2 that only the onResize width-clamp was
actually shipped-and-reverted. Full plan in VACE_OUTPAINT_HARDENING.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>