diff --git a/craft/src/utils/html-export.test.ts b/craft/src/utils/html-export.test.ts
index 07294e2..a07c09d 100644
--- a/craft/src/utils/html-export.test.ts
+++ b/craft/src/utils/html-export.test.ts
@@ -404,6 +404,22 @@ describe('buildAnimationScript (animation fix)', () => {
test('returns empty string when body has no data-animation', () => {
expect(buildAnimationScript('
Hi
')).toBe('');
});
+
+ test('reveal script coerces a bare-number delay to a valid CSS time (e.g. "2" -> "2s")', () => {
+ // animationDelay is stored as a plain seconds string ("2"); assigning that raw
+ // to el.style.animationDelay is invalid CSS and no-ops. The script must suffix a
+ // unit onto bare numbers while leaving unit-bearing values ("2s"/"200ms") alone.
+ const script = buildAnimationScript('Hi
');
+ expect(script).toContain("/^-?[0-9.]+$/.test(delay) ? delay + 's' : delay");
+ // guard against regressing to the raw (invalid) assignment
+ expect(script).not.toContain('animationDelay = delay;');
+ // sanity-check the coercion logic itself against representative inputs
+ const coerce = (delay: string) => (/^-?[0-9.]+$/.test(delay) ? delay + 's' : delay);
+ expect(coerce('2')).toBe('2s');
+ expect(coerce('0.5')).toBe('0.5s');
+ expect(coerce('2s')).toBe('2s');
+ expect(coerce('200ms')).toBe('200ms');
+ });
});
describe('Preview body-replacement keeps exactly one reveal script (animation fix)', () => {
diff --git a/craft/src/utils/html-export.ts b/craft/src/utils/html-export.ts
index 07df8ab..83588fd 100644
--- a/craft/src/utils/html-export.ts
+++ b/craft/src/utils/html-export.ts
@@ -354,7 +354,7 @@ const ANIMATION_CSS_MINIFIED = `@keyframes fadeIn{from{opacity:0}to{opacity:1}}@
const ANIMATION_SCRIPT = `