diff --git a/desktop/src/features/messages/ui/TimelineMessageList.tsx b/desktop/src/features/messages/ui/TimelineMessageList.tsx
index d1186ef2eb..4f149cf097 100644
--- a/desktop/src/features/messages/ui/TimelineMessageList.tsx
+++ b/desktop/src/features/messages/ui/TimelineMessageList.tsx
@@ -283,6 +283,13 @@ export const TimelineMessageList = React.memo(function TimelineMessageList({
{group.items.map((item) => (
diff --git a/desktop/src/shared/styles/globals/utilities.css b/desktop/src/shared/styles/globals/utilities.css
index 461409e91a..d84df68b37 100644
--- a/desktop/src/shared/styles/globals/utilities.css
+++ b/desktop/src/shared/styles/globals/utilities.css
@@ -22,6 +22,15 @@
content-visibility: visible;
}
+ /* Rows with an animated working badge must stay painted: under
+ content-visibility: auto the browser may skip/throttle rendering work for
+ off-screen or contained rows, which makes the badge pulse stutter on
+ closed thread ingress rows (the open-thread panel has no containment and
+ animates smoothly). Scoped to the 1-2 rows with active agent work. */
+ .timeline-row-cv[data-agent-working="true"] {
+ content-visibility: visible;
+ }
+
.content-visibility-auto-interactive {
content-visibility: auto;
contain-intrinsic-size: auto 200px;