diff --git a/desktop/src/shared/ui/markdown.tsx b/desktop/src/shared/ui/markdown.tsx index dc5b602484..5fea77687c 100644 --- a/desktop/src/shared/ui/markdown.tsx +++ b/desktop/src/shared/ui/markdown.tsx @@ -814,10 +814,23 @@ function ImageZoomOverlay({ const isOpen = phase === "open"; const isFading = phase === "fading"; const displayBox = imageLightboxZoomBox(targetBox, zoom); - const transform = - prefersReducedMotion || isOpen - ? imageLightboxTransform(sourceBox, displayBox) - : "translate3d(0, 0, 0) scale(1)"; + // Once fully settled at 1x, drop the transform to `none` so the wrapper + // leaves the GPU-composited path and the repaints through WebKit's + // high-quality paint rasterizer — matching inline-image sharpness. An + // identity `translate3d` would keep it composited, so it must be `none`. + const atRest = + isOpen && + hasEntered && + zoom === IMAGE_LIGHTBOX_MIN_ZOOM && + // Holds composited through the trackpad gesture-end idle window: after a + // pinch settles back to exactly 1x, `isAdjustingZoom` stays true for + // IMAGE_LIGHTBOX_TRACKPAD_ZOOM_IDLE_MS, avoiding a demote/re-promote thrash. + !isAdjustingZoom; + const transform = atRest + ? "none" + : prefersReducedMotion || isOpen + ? imageLightboxTransform(targetBox, displayBox) + : imageLightboxTransform(targetBox, sourceBox); const imageTransitionDuration = prefersReducedMotion ? IMAGE_LIGHTBOX_REDUCED_MOTION_MS : isClosing @@ -919,15 +932,22 @@ function ImageZoomOverlay({ }} />