Rule handbook metadata

Rule
DET.MOTION.NO_AUTO_PLAY_FLASH · lane deterministic
Page status
current
page_version
f6716461755c5906686a586535661bb7dc3d022d186faaf718efbf89ed7070d3
generated_at
2026-05-25T14:30:00.000Z
registry_fingerprint
2ce40848effce579d3e4879f6ca85535183a14db201870a6c007da424624550c

How this rule is fixed

Pilot deterministic fixer: handbook_after · harness mode standalone · verify expect_rule_clean.

  • Harness: apply-harness-fixture-remediation.py copies the After example HTML from this handbook page onto the defect fixture, then invoke-det-ruleset-remediation-verify.sh re-audits and expects zero findings for this rule.
  • Production sites: run-website-ux-remediation-loop.sh runs handbook_html_patch (HTML patches in lib/ux-deterministic-fixers/fixers/patches/) before invoking the Cursor agent when the quality gate still fails.

Detection module: docs/design/ux-audit/deterministic-design-rules.md#det-motion-no_auto_play_flash. Scroll down for Before / After examples and Evidence and remediation steps.

Purpose

Photosensitive visitors and readers under cognitive load need pages that do not auto-play strobing motion. Kitchen Sink ships always-on motion primitives in Ksc (css/forge-theme.css: .pulse, .pulse-amber, .breathe-link, .breathe-static), ambient loops, living backgrounds, and script-assembly fly-ins — most use slow cycles (≥2s) on box-shadow or outline, not rapid opacity toggles. This deterministic rule enforces the WCAG 2.3.1 general flash threshold: a simple on/off luminance cycle must not exceed three flashes per second (~0.67s minimum duration for an infinite opacity toggle).

The check module design-rules/deterministic/generated/det-motion-no-auto-play-flash.check.js scans visible DOM nodes and stylesheets in Playwright for:

  • Fast infinite animationsanimation-iteration-count: infinite with duration below the safe toggle cycle.
  • Risky animation/@keyframes namesblink, flash, strobe, seizure, or flicker.
  • Autoplay video — visible <video autoplay> that may include rapid luminance changes.

Plan: Inventory every visible infinite loop, custom @keyframes name, and autoplay video on first-screen URLs. Do: Keep decorative motion slow, rename risky keyframes, gate fast loops behind user intent, and provide static fallbacks under prefers-reduced-motion. Check: Run the auditor metrics phase or auditor-tests/invoke-det-ruleset-harness.sh --only-rule DET.MOTION.NO_AUTO_PLAY_FLASH. Adjust: When a product surface needs attention without strobing, use KS .pulse / hover .breathe-* (≥2s) or one-shot entrances — not sub-second opacity blinks.

Passing signals

  • No risky names on running animations or @keyframes rules (pulse-glow, breathe-cyan, forge-theme-aurora are fine; blink, flash-strobe, ks-flicker-border are not).
  • Infinite loops on visible elements use duration ≥ ~0.67s for simple on/off cycles, or use slow KS defaults (.pulse / .pulse-amber at 3s, .breathe-* at 2.2–2.5s on hover).
  • Opacity or luminance changes stay gradual (ease-in-out, box-shadow/outline pulses) rather than hard 0↔1 toggles faster than 3 Hz.
  • Autoplay video is absent, or muted decorative video is hidden/off-screen with prefers-reduced-motion: reduce pausing playback and a static poster fallback.
  • @media (prefers-reduced-motion: reduce) disables non-essential infinite animation (pairs with DET.MOTION.PREFERS_REDUCED).
  • Decorative motion stays on small accents (stat tile, badge) — not full-viewport strobing backgrounds behind body copy.

Failing signals

  • Custom @keyframes blink / flash / strobe applied with animation: … 0.2s infinite (or any duration < 0.67s with infinite iteration) on visible text, cards, or hero bands.
  • Animation names containing blink, flash, strobe, seizure, or flicker even when duration looks slow — the name signals intent the check flags.
  • Multiple fast infinite loops in the same viewport (status badge + alert banner + background mesh all strobing).
  • Autoplay video visible without user gesture (<video autoplay> on hero or ambient layer), especially when unmuted.
  • Inline <style> blocks in handbook/showcase pages that reintroduce seizure-risk patterns outside theme tokens.
  • Full-width .glass / .forge-card panels with hard opacity oscillation that estimates > 3 flashes per second on a simple toggle model.

Before example

Before (failing example)

Sync in progress — strobing faster than three flashes per second.

99
Checks passing

Failing KS markup: custom blink keyframes at 0.2s infinite on a hero stat band, plus visible autoplay video.

After example

After (passing example)

Sync complete — static text; motion reserved for hover accents.

99
Checks passing

Slow 3s glow — below flash threshold.

12
Guides linked

Passing KS markup: slow theme pulse on an accent tile, static copy for status, no autoplay video, reduced-motion fallback.

Evidence and remediation

Evidence: Auditor metrics field motionNoAutoPlayFlashReport.violations[] with kinds:

Kind Meaning
fast-infinite-animation Infinite loop duration below ~0.67s; estimatedFlashesPerSecond above 3
risky-animation-name Running animation-name matches blink/flash/strobe/seizure/flicker
risky-keyframes-name Stylesheet @keyframes rule name matches risky keywords
autoplay-video Visible <video autoplay> on the page

Each finding includes selectorHint (tag, class, optional data-ks-hash), duration, estimated Hz, and page URL.

Remediate (in order):

  1. Remove or slow infinite animations — target ≥ 0.67s per cycle for on/off toggles; prefer KS .pulse / .pulse-amber (3s) or hover-only .breathe-link / .breathe-static (≥2.2s).
  2. Rename @keyframes and animation-name values — drop blink, flash, strobe, seizure, flicker from identifiers.
  3. Delete autoplay on decorative video; require user play, or hide video under prefers-reduced-motion with a static poster image.
  4. Add reduced-motion overrides (animation: none !important) for any remaining decorative loops — see DET.MOTION.PREFERS_REDUCED.
  5. Re-run analyze-website-ux.mjs metrics on affected URLs; pair with AI.MOTION.INTENTIONALITY when motion volume still feels distracting but passes frequency gates.

Harness verification:

python3 generator/build_rule_defect_fixtures.py
auditor-tests/invoke-det-ruleset-harness.sh --only-rule DET.MOTION.NO_AUTO_PLAY_FLASH