diff --git a/src/web-ui/public/agent-companion-pets/bitblob/README.md b/src/web-ui/public/agent-companion-pets/bitblob/README.md
index 5a770fd9a8..803d30586f 100644
--- a/src/web-ui/public/agent-companion-pets/bitblob/README.md
+++ b/src/web-ui/public/agent-companion-pets/bitblob/README.md
@@ -19,6 +19,22 @@ Each state was generated as its own grounded strip: quiet breathing/blinking; ri
Deterministic extraction, registration, composition and edge cleanup use the skill's scripts. Jumping uses the supported shared-viewport extraction to preserve the generated vertical arc; other standard rows use connected-component extraction.
+## Consistent state transitions
+
+The packaged atlas re-registers the existing artwork across all states, including
+the neutral slot and look directions. Each cell is uniformly scaled against a
+15,000-pixel alpha-weighted silhouette area, retaining 15% of its original
+within-row area variation for breathing and squash. This avoids using the full
+antenna height or a raised hand as a proxy for body size. The lower-body center
+is aligned to x=95.5 and the baseline to y=194 in each 192×208 cell. Jump frames
+use offsets of 0, 4, 16, 6, 0 pixels from that baseline.
+
+This corrects the former half-sized jump, oversized working/waiting frames and
+per-frame size drift during review. The original poses, frame order, v2 layout
+and transparency remain intact. BitBlob plays only the atlas animation in the
+shared renderer; additional CSS breathing, hover squash and work/drag transforms
+are disabled for this built-in pet so they do not compound its authored motion.
+
## Verification
Validation covers the v2 geometry, populated and unused cells, alpha/chroma cleanup, frame clipping and component extraction. Independent visual review covers all nine animations, every look direction and continuity around the row boundaries. Three isolated reviewers classify the randomized horizontal/vertical direction sheet; cardinal ambiguity blocks packaging. Runtime/transport integration checks belong to the companion feature tests rather than the image pipeline.
diff --git a/src/web-ui/public/agent-companion-pets/bitblob/spritesheet.webp b/src/web-ui/public/agent-companion-pets/bitblob/spritesheet.webp
index 26838c0660..4686e0c4ee 100644
Binary files a/src/web-ui/public/agent-companion-pets/bitblob/spritesheet.webp and b/src/web-ui/public/agent-companion-pets/bitblob/spritesheet.webp differ
diff --git a/src/web-ui/src/flow_chat/components/AgentCompanionPet.test.tsx b/src/web-ui/src/flow_chat/components/AgentCompanionPet.test.tsx
index 12813777aa..c549fb7144 100644
--- a/src/web-ui/src/flow_chat/components/AgentCompanionPet.test.tsx
+++ b/src/web-ui/src/flow_chat/components/AgentCompanionPet.test.tsx
@@ -51,6 +51,25 @@ function sprite() {
}
describe('pet sprite renderer', () => {
+ it('keeps built-in BitBlob motion in the atlas across session states', async () => {
+ const bitblob = { ...pet, id: 'bitblob' };
+ for (const mood of ['rest', 'hover', 'working', 'waiting', 'analyzing', 'dragging'] as const) {
+ await act(async () => root.render());
+ expect(sprite().style.animationName).toBe('openbitfun-petdex-walk');
+ expect(sprite().style.imageRendering).toBe('auto');
+ }
+ await act(async () => root.render());
+ expect(sprite().dataset.petAction).toBe('jumping');
+ expect(sprite().style.animationDuration).toBe('1.2s');
+ await act(async () => root.render());
+ expect(sprite().style.animation).toBe('none');
+ // A user pet with the same id must retain its own/default presentation.
+ await act(async () => root.render());
+ expect(sprite().style.animationName).toBe('');
+ await act(async () => root.render());
+ expect(sprite().style.animationName).toBe('');
+ });
+
it.each([1, 2])('plays all three standard actions with v%s frame geometry and keeps drag priority', async version => {
vi.useFakeTimers();
vi.stubGlobal('Image', class {
diff --git a/src/web-ui/src/flow_chat/components/AgentCompanionPet.tsx b/src/web-ui/src/flow_chat/components/AgentCompanionPet.tsx
index 0ea7780c07..64099db191 100644
--- a/src/web-ui/src/flow_chat/components/AgentCompanionPet.tsx
+++ b/src/web-ui/src/flow_chat/components/AgentCompanionPet.tsx
@@ -483,6 +483,9 @@ export const AgentCompanionPet: React.FC = ({
className={`openbitfun-agent-companion-pet__petdex openbitfun-agent-companion-pet__petdex--${mood}`}
style={{
imageRendering: pet.source === 'preset' && pet.id === 'bitblob' ? 'auto' : undefined,
+ // BitBlob's atlas already contains breathing, squash and movement.
+ // Extra mood transforms change its apparent size when a session changes state.
+ animationName: pet.source === 'preset' && pet.id === 'bitblob' ? 'openbitfun-petdex-walk' : undefined,
'--openbitfun-petdex-src': `url("${petSrc}")`,
'--openbitfun-petdex-row': row,
'--openbitfun-petdex-frames': frames,