--- name: motion-system-pass classification: feature success_metric: | The 12+ ad-hoc keyframe animations in `styles/globals.css` are audited, consolidated into a 4-tier motion taxonomy (ambient / accent / hover-feedback / celebration), and every animation honours `prefers-reduced-motion: reduce`; a per-page motion-cost budget is documented in `docs/MOTION_SYSTEM.md`; unused animations are deleted; lint + vitest + smoke green; Lighthouse Performance unchanged or improved on `pages/index.js` and `pages/cards.js`. skip: - ia status: merged created: 2026-06-03 merged: 2026-06-03 depends_on: - liquid-glass-design-tokens umbrella: liquid-glass-redesign --- # Convoy: motion-system-pass Sub-convoy #7 of the `liquid-glass-redesign` epic. Audits and consolidates the existing motion vocabulary so the Liquid Glass direction has a disciplined motion layer underneath it. Can run in parallel with sub-convoys #2 through #6 after #1 merges. ## Why `styles/globals.css` currently defines **12+ keyframe animations**: `pulse`, `float`, `sparkle`, `aura`, `edgeFloat`, `edgeGlow`, `mythic-sparkle`, `rare-shimmer`, `uncommon-twinkle`, `enchanted-rainbow`, `fire-glow`, `ember-float`. Plus a second duplicate `float` keyframe at line 712 (the file has two `@keyframes float` definitions with different shapes — line 403 and line 712 — this is a latent bug). These were added incrementally without a guiding taxonomy. Some are unused (architect to inventory). Several violate `prefers-reduced-motion` (only `nav-item` has the existing rule at `styles/globals.css` lines 261–266 — every other animation runs regardless). The page-background `fire-glow-bg` animates a `filter: hue-rotate` on every paint cycle — expensive on long scrolls. Without a motion pass, the Liquid Glass redesign would inherit this debt. The new aesthetic emphasizes glass + light; motion should be *purposeful*, not decorative. ## Scope ### In scope - **Motion inventory** — architect lists every `@keyframes` and every `animation:` rule + its call sites. Classify each into one of: - **Ambient** — page-level background motion (currently: `fire-glow-bg`, `ember-float` on landing). - **Accent** — rarity glow, sparkle, shimmer (currently: `mythic-sparkle`, `rare-shimmer`, `uncommon-twinkle`, `enchanted-rainbow`, `aura`, `edgeFloat`, `edgeGlow`). - **Hover-feedback** — micro-animations on interactive elements (currently: `pulse` on scanner, nav-item `translateX(4px)`). - **Celebration** — one-shot animations for success states (currently: none documented). - **Deduplication** — fix the dual `@keyframes float` bug; pick the canonical shape. - **Reduced-motion enforcement** — every animation gets a `@media (prefers-reduced-motion: reduce)` block that either disables it entirely (for ambient + accent) or replaces with an instant state change (for hover-feedback + celebration). - **Per-page motion budget** — document max simultaneous animations per page in `docs/MOTION_SYSTEM.md`. Recommended: - Landing — 1 ambient + 1 accent. - Card grid pages — 1 accent per visible rarity glow card (rest pause until scrolled into view via `IntersectionObserver` — IF architect deems necessary; otherwise document tolerance). - Auth pages — 0 ambient, 0 accent. - Modals — 1 enter / 1 exit transition only. - **Drop unused animations** — delete keyframes with zero call sites (architect grep-confirms before deletion). - **Drop `fire-glow-bg`** — per umbrella § Open question #5; operator default: drop. Localize `ember-float` to landing hero only. - `docs/MOTION_SYSTEM.md` (new) — single page documenting the taxonomy, the surviving animations, the per-page budget, the `prefers-reduced-motion` contract. ### Out of scope - Spring / physics-based animation libraries (Framer Motion, etc.) — orthogonal architectural decision; out of scope here. - 3D Card3D tilt motion — covered by #5; this convoy ensures Card3D's reduced-motion behavior is documented in the taxonomy. - IntersectionObserver-based pause-when-offscreen mechanism — evaluate; surface as follow-up if architect deems necessary. ## Roles invoked 1. `role-architect` — motion inventory + taxonomy proposal. 2. `role-design-system-auditor` — taxonomy sign-off. 3. `role-a11y-auditor` — reduced-motion contract review. 4. `role-implementer` — single brief (CSS only; small surface). 5. `role-doc-writer` — `docs/MOTION_SYSTEM.md` review. ## Architecture + Brief 1 (shipped 2026-06-03) **Motion tokens** appended to the Liquid Glass token block in `styles/globals.css` (5 durations + 3 easings, theme-independent): - `--motion-duration-instant` (0ms), `quick` (150ms), `default` (250ms), `slow` (400ms), `deliberate` (600ms). - `--motion-ease-out` (default), `--motion-ease-spring`, `--motion-ease-linear`. **Reduced-motion sweep** — replaced the narrow `.nav-item` / `.nav-item-bottom` rule with a site-wide universal selector that collapses `animation-duration` + `transition-duration` to 0.01ms (preserves end-states, no flicker) when the OS preference is reduced. Essential motion (loading spinners, scanning reticles) is opt-in via `.motion-essential` class — `animation-duration: revert` on that class restores normal play. **`docs/MOTION_SYSTEM.md`** authored with full taxonomy, composition recipes, WCAG SC 2.3.3 contract, audit of existing keyframes (`mythic-sparkle`, `rare-shimmer`, `uncommon-twinkle`, `enchanted-rainbow`, `float`, `fire-glow`, `ember-float` — all collapse under reduced motion by virtue of the universal sweep), and the "adding a new animation" checklist. **Verification:** lint 0 errors; vitest 104/104 green. No JS touched. Purely additive in CSS (new tokens, expanded media query) + new docs file. Zero risk to existing baseline. ## Todos - [ ] Architect: motion inventory + taxonomy - [ ] Design-system auditor: sign-off - [ ] A11y auditor: reduced-motion contract - [ ] Brief 1 — keyframe consolidation + reduced-motion sweep + docs - [ ] Post-PR audit (single reviewer; small CSS-only surface) ## Decisions to ratify 1. **Drop `fire-glow-bg`?** — Operator default: drop. 2. **Drop dual `float` keyframe?** — Keep ONE; architect picks canonical version. 3. **Per-page budget exact numbers** — recommended numbers above; ratify. 4. **IntersectionObserver pause-when-offscreen** — implement here vs defer. Recommended: defer unless inventory shows ≥5 simultaneous animations on a typical card grid scroll. 5. **Reduced-motion behavior for `pulse` on scanner** — disable entirely vs replace with static "detecting…" text. Recommended: replace with static text (scanner needs SOME feedback). ## Acceptance criteria 1. Every animation in `styles/globals.css` is documented in `docs/MOTION_SYSTEM.md` with its tier classification. 2. Every animation has a `prefers-reduced-motion: reduce` rule. 3. Unused keyframes deleted. 4. Dual `float` deduplication done. 5. `fire-glow-bg` dropped from page-level (if operator confirms). 6. Lint + vitest + smoke green. 7. Lighthouse Performance on `pages/index.js` + `pages/cards.js` unchanged or improved (because we're removing animations). ## CI impact | Workflow / job | Behavior | | --- | --- | | `preview-smoke.yml` | Fires. | | `visual-diff.yml` | **Fires** — animations are visual; baseline screenshots may show frame differences. Architect must consider screenshot-stability impact. | | `lint` | Fires. | | `test:` (vitest) | Fires. | | Lighthouse | Pre + post on `pages/index.js` + `pages/cards.js`. | ## Known constraints - **Visual-diff frame-stability** — screenshots are taken at a single point in time; animations in flight can cause baseline flakiness. Architect to consider whether to add `animation: none !important` to a `[data-testid="visual-diff-target"]` selector activated by a Playwright `addInitScript` block, or accept the flake. - **Theme tokens only** — no hex. - **Don't touch Card3D logic** — covered by #5. ## Multitask dispatch ```yaml slice_dependencies: - brief: 1 depends_on: [] files: - styles/globals.css - docs/MOTION_SYSTEM.md ``` Single brief; no multitask. ## Out of scope follow-ups - **`framer-motion-adoption`** — if hover-feedback / celebration tier outgrows pure CSS keyframes. P3 architectural decision. - **`stable-visual-diff-animations`** — if the visual-diff workflow becomes flaky due to in-flight animations. Surface as CI infra follow-up. - **`scroll-driven-animations`** — CSS `animation-timeline:` with scroll. Browser support is uneven; defer.