Motion Craft
Every animation must serve feedback ("it worked"), continuity ("that's
where it went"), or hierarchy ("look here"). An animation serving none of
the three is removed, not tuned. When in doubt: shorter, subtler, or none.
1. Duration budgets
Numbers first; taste second. Defaults for product UI:
| Surface |
Budget |
| Hover / press feedback |
90-160ms |
| Tooltip, micro popover |
80-200ms |
| Dropdown, select, small panel |
150-250ms |
| Accordion, tab switch |
160-240ms |
| Card / list item entrance |
180-350ms |
| Modal, drawer, sheet |
200-400ms |
| Route / page transition |
240-500ms |
- Standard interactions stay under 300ms; nothing in product UI exceeds
500ms. A 180ms dropdown reads as more responsive than a 400ms one.
- Exit = 65-75% of entrance. Leaving is confirmation, not an event.
The rows above bound ENTRANCES; a rule-derived exit may drop below its
row - that is the intent, not a violation.
- Distance scales duration: 100px is the base; 200px ~1.3x, 400px ~1.6x,
full-screen ~1.8-2.0x. Small moves at long durations read as lag.
- Frequency scales duration DOWN. An action done 100 times a day
approaches instant. Hard sub-rule: never animate keyboard-initiated
actions - they repeat hundreds of times daily and animation makes them
feel disconnected from the keystroke.
❌ "the command palette fades in over 250ms - it looks polished in the demo."
✅ keyboard-opened palette appears instantly; its pointer-opened twin may
animate.
- Trigger for this section: any duration you are about to write, or any
existing duration outside the table. Done when every duration in the diff
sits inside its row's budget or carries a written justification.
2. Easing
| Direction |
Curve |
Why |
| Enter |
ease-out |
fast start = instant feedback, soft landing |
| Exit |
ease-in |
soft start, fast leave |
| On-screen move / morph |
ease-in-out |
smooth both ends |
| Spinners, progress, marquee |
linear |
mechanical processes read linear |
- Never linear for finite point-to-point movement; never ease-in for
entrances. Continuous mechanical motion - spinners, progress bars,
marquee loops - is the linear exception the table names, not a
contradiction of it. An ease-in dropdown at 300ms feels slower than
ease-out at the same 300ms: it delays movement in the exact frames the
user watches most closely.
- Named defaults: Material 3 standard
cubic-bezier(0.2, 0, 0, 1); M3
emphasized-decelerate cubic-bezier(0.05, 0.7, 0.1, 1); Core Animation's
kCAMediaTimingFunctionDefault / CSS ease is cubic-bezier(0.25, 0.1, 0.25, 1) - Apple's HIG publishes principles, not bezier tokens, so any
"Apple HIG curve" value circulating online is reverse-engineered, not
vendor-published. Two mislabels to refuse: (0.4, 0, 0.2, 1) is
Material 2's standard routinely pasted as "M3", and (0.25, 0.1, 0.25, 1) labeled "the Apple HIG default" is the CSS ease curve wearing a
vendor costume.
3. Springs and gesture physics
- Spring parameters below are Framer Motion-convention coefficients
(stiffness + damping). Two unit traps: React Spring parameterizes as
tension/friction, not these; and a damping ratio (where <1.0
oscillates, 1.0 is critical) is a different unit again - an error that
has reached published tables (this pack's own LottieFiles source
conflates the two). Name which convention you are using.
- Critical damping (no overshoot) for mass 1 is
damping = 2 * sqrt(stiffness) - stiffness 400 needs damping 40, stiffness 300
needs ~35. The presets below are deliberately UNDERDAMPED (they
overshoot a little), which per the settle rule places them on
momentum-driven interactions only:
| Feel |
Stiffness |
Damping |
Where it belongs |
| Snappy (mild overshoot) |
~400 |
25-30 |
flick-driven UI |
| Standard (visible settle) |
250-350 |
18-24 |
drag release |
| Bouncy (sparingly) |
150-250 |
10-15 |
playful, earned |
- Springs must settle. Click-triggered UI defaults to critically
damped (use the formula above); overshoot is earned by a flick, never
by a click, and never appears on error paths. Prolonged wobble
("jello") is a defect, not personality.
- Momentum projection (where a flick should land): Apple ships the
exponential-decay form
projectedDistance = (velocity / 1000) * d / (1 - d)
with d ~= 0.998, velocity in px per SECOND (the /1000 folds it onto the
per-millisecond decay step; the dismissal rule below uses px/ms - mixing
the two units is a 1000x error) - NOT the physics-textbook
v^2 / (2 * deceleration).
- Rubber-band overscroll:
(overshoot * dimension * c) / (dimension + c * |overshoot|) with c = 0.55 - resistance grows the further past the bound.
- Velocity handoff: when a gesture ends, the animation continues at the
finger's velocity:
relativeVelocity = gestureVelocity / (target - current) (libraries taking raw px/s can be handed the gesture velocity
directly). Guard the zero/near-zero displacement case: when target - current is ~0 there is nothing to animate - skip the spring instead of
dividing by it. A visible seam between drag and animation is the tell
this rule was skipped.
- Momentum dismissal: velocity OR distance - either alone suffices. A
flick dismisses on velocity above
0.11 px/ms (110 px/s; the source's cheap
approximation is average |distance| / elapsedMs; prefer the gesture's
actual release velocity where the framework exposes it). A slow drag
past the distance threshold still dismisses - velocity-only would snap
a deliberate full drag back. The failure this rule exists to prevent is
requiring distance from a fast flick.
4. Choreography
- Stagger: 30-80ms between items; total sequence under 500ms; stagger is
decorative - it must never block interaction while playing.
- One thing leads. Everything animating at once with equal weight is
noise; pick the hero element, let the rest follow or fade.
- Overshoot budget by context: success 5-10%; generic feedback 2-5%;
celebration up to 25%; errors and destructive confirmations 0% - play
nothing bouncy on the worst moment of the user's session.
- Asymmetric deliberate/response timing: where the user is deciding
(press-and-hold, destructive confirm) the animation may run slow; the
system's response snaps. Symmetric timing on a press-and-release
interaction is a finding, not a style choice.
5. Performance traps
transform and opacity are the workhorses; paint-only properties
(color, background-color, border-color) are acceptable for state
feedback. What is BANNED is animating layout-triggering properties
(width, height, top, left, margin, padding) - those are rewritten, not
accepted.
transition: all is banned.
❌ transition: all 300ms ease - it animates every property that
happens to change, layout-affecting ones you never intended included,
plus whichever property a future edit adds; the failure signature is
surprise animations and layout work appearing when unrelated styles
change.
✅ transition: transform 200ms ease-out, opacity 200ms ease-out.
- Framer Motion's shorthand props (
x, y, scale) animate on the main
thread via rAF rather than as compositor-run transforms (Kowalski's
production finding; the observable symptom is dropped frames while the
page is busy). Under load, use the full transform string.
- Updating an inheriting CSS variable on a parent recalculates style for
its children - the default for unregistered custom properties (a
registered
@property with inherits: false sidesteps it) - so in a
drawer with many items, drive transform on the moving element directly
instead of --offset on the container.
- Animations are interruptible: new input retargets mid-flight (CSS
transitions and springs retarget; keyframes restart from zero - wrong for
toasts, toggles, anything triggered rapidly); no fill-mode or delay may
block interaction.
- Never enter from
scale(0) - nothing real appears from nothing; enter
from scale(0.9-0.97) plus opacity.
- Set
transform-origin for scale/rotate: popovers, dropdowns, and tooltips
scale from their trigger, not center (modals are the exemption - they stay
centered); SVG needs transform-box: fill-box on a wrapping <g>.
- Gate hover motion behind
@media (hover: hover) and (pointer: fine) -
touch devices fire false hovers on tap.
6. Reduced motion is a floor, not a feature
- Every animation ships a
prefers-reduced-motion variant. Reduced means
fewer and gentler, not zero: keep opacity/color transitions that aid
comprehension; drop movement - slide+fade -> fade; scale+fade -> fade;
spring -> short tween; parallax and auto-playing loops -> removed.
Transform-based full-screen motion is the highest-cost vestibular
trigger - it is exactly what this media query exists for.
- Motion is never the only signal of a state change: pair it with a static
affordance (color, position, label) or reduced-motion users miss the
change entirely.
7. Misquoted research - do not cite these wrong
These corrections are adapted from open-design's primary-literature review
(Apache-2.0; adaptation notice in THIRD-PARTY-NOTICES). The papers were
NOT re-opened for this pack - each line below is that review's checked
claim, restated, not this pack's own reading of the source:
- "Skeleton screens feel 11% faster" - per that review, Harrison/Yeo/
Hudson (CHI 2010) measured backwards-decelerating ribbed progress
bars (n=16), not skeletons; the mechanism does not transfer.
- "Doherty threshold = 400ms" - per that review, the source contains no
400ms figure; the lowest measured threshold is 300ms. And cite the
source itself correctly: Doherty & Thadhani, "The Economic Value of
Rapid Response Time", IBM technical report GE20-0752 (1982) - the
"IBM Systems Journal 1982" venue and the "Thadani" spelling circulating
online (and in the review this pack adapted) are themselves
miscitations, corrected here.
- "Heer & Robertson recommend 300-1000ms transitions" - per that review,
they tested 1.25s and 2s only, and recommend roughly one second per
animated stage.
- Motion confirms state changes; it must not perform them. Optimistic
UI first, animation second.
8. Pre-ship gate
Run against the built surface, not the source: trigger each interaction and
watch it. Severity-tiered; every CRITICAL verified by observation before
"done".
- CRITICAL: reduced-motion variant exists and was toggled on and
observed; nothing exceeds 500ms (unless the When-NOT spectacle
exception was invoked in writing - the purpose test and reduced-motion
floor still bind there); no spring fails to settle; no
keyboard-initiated action animates; no
transition: all.
- HIGH: durations inside §1 budgets; easing direction per §2; exits
faster than entrances; layout-property animation absent.
- MEDIUM: stagger within budget;
transform-origin set for scale;
consistent timings across sibling components; overshoot within §4 context
budget.
Done when: every CRITICAL item observed passing, HIGH items pass or carry a
written exception, and any failure names the rule it broke (not "feels off").
When NOT to use this skill
- Debugging one library's API surface -> that library's docs; this file owns
budgets and judgment, not APIs.
- Static layout/type/color decisions ->
ui-design-craft.
- Running a full design review with measurement and fix loop ->
design-review-gate (its motion pass applies this file's budgets).
- Marketing hero choreography on a page whose brief explicitly buys
spectacle: §1 caps may be exceeded there, deliberately and in writing -
the purpose test and reduced-motion floor still apply.
Provenance
Composed 2026-07-19 for design-pack 0.1.0. Sources, all verified in their
repos at composition time: Emil Kowalski's emilkowalski/skills (MIT) -
duration budgets, keyboard rule, stagger numbers, Framer shorthand and CSS
variable performance traps, Apple-derived projection / rubber-band / velocity
handoff forms (his distillation of Apple WWDC material; formulas quoted from
his files); LottieFiles motion-design-skill (MIT) - element duration table,
distance-duration multipliers, exit ratio, stagger and overshoot budgets,
severity-tier gate shape (their damping-units conflation is corrected here,
not copied; §1's duration rows are envelope syntheses across the three
motion sources, not quotes of any single table); referodesign/refero_skill (MIT) - purpose triad, easing
direction table, reduced-motion mapping, transition: all ban. §7's
corrections and the M2/M3 mislabel are adapted from nexu-io/open-design's
craft/animation-discipline.md primary-source review (Apache-2.0; the
correction items keep that review's selection, figures, and framing - an
ADAPTATION carried with notice in THIRD-PARTY-NOTICES, not an ideas-only
borrow). The primary papers were not independently re-opened for this
pack, with one exception: the Doherty citation itself (report GE20-0752,
"Thadhani") is this pack's own correction of the review's miscite. greensock/gsap-skills was
surveyed and deliberately not mined: library-usage doctrine, out of scope
here. Numeric values (beziers, spring pairs, budgets) are the volatile
facts - re-verify beziers against the published Material 3 motion tokens
(m3.material.io) and, for Apple, the SwiftUI Animation API's actual values
(the HIG publishes no numeric curves); spring pairs against the Framer
Motion / Motion docs - on major vendor releases. Probe status: probe-tested 2026-07-19 on a
private over-budget motion-spec fixture (fresh weak-tier agent, n=1 per
arm, smoke grade): the bare arm caught ~3 of 7 planted violations, loosely
phrased - though it did catch the missing reduced-motion variant, recorded
honestly - while the ruled arm caught 7 of 7 with budget citations,
including the keyboard rule and the 500ms total-stagger cap the bare arm
lacked as concepts. A round-0 run was voided for a leaked in-fixture
answer key. Trail in the design-pack PR.
1---2name: motion-craft3description: Implementation-agnostic motion judgment for product UI. Load when you are adding, reviewing, or tuning animation in any framework - durations, easings, springs, staggers, entrances/exits, gesture handoff, reduced motion - when a spec says "smooth" or "delightful" with no numbers attached, or when you notice animation being judged by feel instead of against a budget. NOT for debugging one animation library's API (use its docs), for static visual decisions (ui-design-craft), or for running a design review end-to-end (design-review-gate).4---56# Motion Craft78Every animation must serve **feedback** ("it worked"), **continuity** ("that's9where it went"), or **hierarchy** ("look here"). An animation serving none of10the three is removed, not tuned. When in doubt: shorter, subtler, or none.1112## 1. Duration budgets1314Numbers first; taste second. Defaults for product UI:1516| Surface | Budget |17|---|---|18| Hover / press feedback | 90-160ms |19| Tooltip, micro popover | 80-200ms |20| Dropdown, select, small panel | 150-250ms |21| Accordion, tab switch | 160-240ms |22| Card / list item entrance | 180-350ms |23| Modal, drawer, sheet | 200-400ms |24| Route / page transition | 240-500ms |2526- **Standard interactions stay under 300ms; nothing in product UI exceeds27 500ms.** A 180ms dropdown reads as more responsive than a 400ms one.28- **Exit = 65-75% of entrance.** Leaving is confirmation, not an event.29 The rows above bound ENTRANCES; a rule-derived exit may drop below its30 row - that is the intent, not a violation.31- **Distance scales duration:** 100px is the base; 200px ~1.3x, 400px ~1.6x,32 full-screen ~1.8-2.0x. Small moves at long durations read as lag.33- **Frequency scales duration DOWN.** An action done 100 times a day34 approaches instant. Hard sub-rule: **never animate keyboard-initiated35 actions** - they repeat hundreds of times daily and animation makes them36 feel disconnected from the keystroke.37 ❌ "the command palette fades in over 250ms - it looks polished in the demo."38 ✅ keyboard-opened palette appears instantly; its pointer-opened twin may39 animate.40- Trigger for this section: any duration you are about to write, or any41 existing duration outside the table. Done when every duration in the diff42 sits inside its row's budget or carries a written justification.4344## 2. Easing4546| Direction | Curve | Why |47|---|---|---|48| Enter | ease-out | fast start = instant feedback, soft landing |49| Exit | ease-in | soft start, fast leave |50| On-screen move / morph | ease-in-out | smooth both ends |51| Spinners, progress, marquee | linear | mechanical processes read linear |5253- **Never linear for finite point-to-point movement; never ease-in for54 entrances.** Continuous mechanical motion - spinners, progress bars,55 marquee loops - is the linear exception the table names, not a56 contradiction of it. An ease-in dropdown at 300ms feels slower than57 ease-out at the same 300ms: it delays movement in the exact frames the58 user watches most closely.59- Named defaults: Material 3 standard `cubic-bezier(0.2, 0, 0, 1)`; M360 emphasized-decelerate `cubic-bezier(0.05, 0.7, 0.1, 1)`; Core Animation's61 `kCAMediaTimingFunctionDefault` / CSS `ease` is `cubic-bezier(0.25, 0.1,62 0.25, 1)` - Apple's HIG publishes principles, not bezier tokens, so any63 "Apple HIG curve" value circulating online is reverse-engineered, not64 vendor-published. Two mislabels to refuse: `(0.4, 0, 0.2, 1)` is65 Material *2*'s standard routinely pasted as "M3", and `(0.25, 0.1, 0.25,66 1)` labeled "the Apple HIG default" is the CSS `ease` curve wearing a67 vendor costume.6869## 3. Springs and gesture physics7071- Spring parameters below are **Framer Motion-convention coefficients**72 (stiffness + damping). Two unit traps: React Spring parameterizes as73 tension/friction, not these; and a damping *ratio* (where <1.074 oscillates, 1.0 is critical) is a different unit again - an error that75 has reached published tables (this pack's own LottieFiles source76 conflates the two). Name which convention you are using.77- **Critical damping (no overshoot) for mass 1 is `damping = 2 *78 sqrt(stiffness)`** - stiffness 400 needs damping 40, stiffness 30079 needs ~35. The presets below are deliberately UNDERDAMPED (they80 overshoot a little), which per the settle rule places them on81 momentum-driven interactions only:8283| Feel | Stiffness | Damping | Where it belongs |84|---|---|---|---|85| Snappy (mild overshoot) | ~400 | 25-30 | flick-driven UI |86| Standard (visible settle) | 250-350 | 18-24 | drag release |87| Bouncy (sparingly) | 150-250 | 10-15 | playful, earned |8889- **Springs must settle.** Click-triggered UI defaults to critically90 damped (use the formula above); overshoot is earned by a flick, never91 by a click, and never appears on error paths. Prolonged wobble92 ("jello") is a defect, not personality.93- **Momentum projection** (where a flick should land): Apple ships the94 exponential-decay form `projectedDistance = (velocity / 1000) * d / (1 - d)`95 with `d ~= 0.998`, velocity in px per SECOND (the /1000 folds it onto the96 per-millisecond decay step; the dismissal rule below uses px/ms - mixing97 the two units is a 1000x error) - NOT the physics-textbook98 `v^2 / (2 * deceleration)`.99- **Rubber-band overscroll:** `(overshoot * dimension * c) / (dimension + c *100 |overshoot|)` with `c = 0.55` - resistance grows the further past the bound.101- **Velocity handoff:** when a gesture ends, the animation continues at the102 finger's velocity: `relativeVelocity = gestureVelocity / (target -103 current)` (libraries taking raw px/s can be handed the gesture velocity104 directly). Guard the zero/near-zero displacement case: when `target -105 current` is ~0 there is nothing to animate - skip the spring instead of106 dividing by it. A visible seam between drag and animation is the tell107 this rule was skipped.108- **Momentum dismissal: velocity OR distance - either alone suffices.** A109 flick dismisses on velocity above ~0.11 px/ms (~110 px/s; the source's cheap110 approximation is average `|distance| / elapsedMs`; prefer the gesture's111 actual release velocity where the framework exposes it). A slow drag112 past the distance threshold still dismisses - velocity-only would snap113 a deliberate full drag back. The failure this rule exists to prevent is114 requiring distance from a fast flick.115116## 4. Choreography117118- **Stagger:** 30-80ms between items; total sequence under 500ms; stagger is119 decorative - it must never block interaction while playing.120- **One thing leads.** Everything animating at once with equal weight is121 noise; pick the hero element, let the rest follow or fade.122- **Overshoot budget by context:** success 5-10%; generic feedback 2-5%;123 celebration up to 25%; **errors and destructive confirmations 0%** - play124 nothing bouncy on the worst moment of the user's session.125- **Asymmetric deliberate/response timing:** where the user is deciding126 (press-and-hold, destructive confirm) the animation may run slow; the127 system's response snaps. Symmetric timing on a press-and-release128 interaction is a finding, not a style choice.129130## 5. Performance traps131132- `transform` and `opacity` are the workhorses; paint-only properties133 (color, background-color, border-color) are acceptable for state134 feedback. What is BANNED is animating layout-triggering properties135 (width, height, top, left, margin, padding) - those are rewritten, not136 accepted.137- **`transition: all` is banned.**138 ❌ `transition: all 300ms ease` - it animates every property that139 happens to change, layout-affecting ones you never intended included,140 plus whichever property a future edit adds; the failure signature is141 surprise animations and layout work appearing when unrelated styles142 change.143 ✅ `transition: transform 200ms ease-out, opacity 200ms ease-out`.144- Framer Motion's shorthand props (`x`, `y`, `scale`) animate on the main145 thread via rAF rather than as compositor-run transforms (Kowalski's146 production finding; the observable symptom is dropped frames while the147 page is busy). Under load, use the full `transform` string.148- Updating an inheriting CSS variable on a parent recalculates style for149 its children - the default for unregistered custom properties (a150 registered `@property` with `inherits: false` sidesteps it) - so in a151 drawer with many items, drive `transform` on the moving element directly152 instead of `--offset` on the container.153- Animations are interruptible: new input retargets mid-flight (CSS154 transitions and springs retarget; keyframes restart from zero - wrong for155 toasts, toggles, anything triggered rapidly); no fill-mode or delay may156 block interaction.157- **Never enter from `scale(0)`** - nothing real appears from nothing; enter158 from `scale(0.9-0.97)` plus opacity.159- Set `transform-origin` for scale/rotate: popovers, dropdowns, and tooltips160 scale from their trigger, not center (modals are the exemption - they stay161 centered); SVG needs `transform-box: fill-box` on a wrapping `<g>`.162- Gate hover motion behind `@media (hover: hover) and (pointer: fine)` -163 touch devices fire false hovers on tap.164165## 6. Reduced motion is a floor, not a feature166167- Every animation ships a `prefers-reduced-motion` variant. Reduced means168 **fewer and gentler, not zero**: keep opacity/color transitions that aid169 comprehension; drop movement - slide+fade -> fade; scale+fade -> fade;170 spring -> short tween; parallax and auto-playing loops -> removed.171 Transform-based full-screen motion is the highest-cost vestibular172 trigger - it is exactly what this media query exists for.173- Motion is never the only signal of a state change: pair it with a static174 affordance (color, position, label) or reduced-motion users miss the175 change entirely.176177## 7. Misquoted research - do not cite these wrong178179These corrections are adapted from open-design's primary-literature review180(Apache-2.0; adaptation notice in THIRD-PARTY-NOTICES). The papers were181NOT re-opened for this pack - each line below is that review's checked182claim, restated, not this pack's own reading of the source:183184- "Skeleton screens feel 11% faster" - per that review, Harrison/Yeo/185 Hudson (CHI 2010) measured backwards-decelerating ribbed *progress186 bars* (n=16), not skeletons; the mechanism does not transfer.187- "Doherty threshold = 400ms" - per that review, the source contains no188 400ms figure; the lowest measured threshold is 300ms. And cite the189 source itself correctly: Doherty & Thadhani, "The Economic Value of190 Rapid Response Time", IBM technical report GE20-0752 (1982) - the191 "IBM Systems Journal 1982" venue and the "Thadani" spelling circulating192 online (and in the review this pack adapted) are themselves193 miscitations, corrected here.194- "Heer & Robertson recommend 300-1000ms transitions" - per that review,195 they tested 1.25s and 2s only, and recommend roughly one second per196 animated stage.197- Motion *confirms* state changes; it must not *perform* them. Optimistic198 UI first, animation second.199200## 8. Pre-ship gate201202Run against the built surface, not the source: trigger each interaction and203watch it. Severity-tiered; every CRITICAL verified by observation before204"done".205206- **CRITICAL:** reduced-motion variant exists and was toggled on and207 observed; nothing exceeds 500ms (unless the When-NOT spectacle208 exception was invoked in writing - the purpose test and reduced-motion209 floor still bind there); no spring fails to settle; no210 keyboard-initiated action animates; no `transition: all`.211- **HIGH:** durations inside §1 budgets; easing direction per §2; exits212 faster than entrances; layout-property animation absent.213- **MEDIUM:** stagger within budget; `transform-origin` set for scale;214 consistent timings across sibling components; overshoot within §4 context215 budget.216217Done when: every CRITICAL item observed passing, HIGH items pass or carry a218written exception, and any failure names the rule it broke (not "feels off").219220## When NOT to use this skill221222- Debugging one library's API surface -> that library's docs; this file owns223 budgets and judgment, not APIs.224- Static layout/type/color decisions -> `ui-design-craft`.225- Running a full design review with measurement and fix loop ->226 `design-review-gate` (its motion pass applies this file's budgets).227- Marketing hero choreography on a page whose brief explicitly buys228 spectacle: §1 caps may be exceeded there, deliberately and in writing -229 the purpose test and reduced-motion floor still apply.230231## Provenance232233Composed 2026-07-19 for design-pack 0.1.0. Sources, all verified in their234repos at composition time: Emil Kowalski's `emilkowalski/skills` (MIT) -235duration budgets, keyboard rule, stagger numbers, Framer shorthand and CSS236variable performance traps, Apple-derived projection / rubber-band / velocity237handoff forms (his distillation of Apple WWDC material; formulas quoted from238his files); LottieFiles `motion-design-skill` (MIT) - element duration table,239distance-duration multipliers, exit ratio, stagger and overshoot budgets,240severity-tier gate shape (their damping-units conflation is corrected here,241not copied; §1's duration rows are envelope syntheses across the three242motion sources, not quotes of any single table); `referodesign/refero_skill` (MIT) - purpose triad, easing243direction table, reduced-motion mapping, `transition: all` ban. §7's244corrections and the M2/M3 mislabel are adapted from nexu-io/open-design's245`craft/animation-discipline.md` primary-source review (Apache-2.0; the246correction items keep that review's selection, figures, and framing - an247ADAPTATION carried with notice in THIRD-PARTY-NOTICES, not an ideas-only248borrow). The primary papers were not independently re-opened for this249pack, with one exception: the Doherty citation itself (report GE20-0752,250"Thadhani") is this pack's own correction of the review's miscite. greensock/gsap-skills was251surveyed and deliberately not mined: library-usage doctrine, out of scope252here. Numeric values (beziers, spring pairs, budgets) are the volatile253facts - re-verify beziers against the published Material 3 motion tokens254(m3.material.io) and, for Apple, the SwiftUI Animation API's actual values255(the HIG publishes no numeric curves); spring pairs against the Framer256Motion / Motion docs - on major vendor releases. Probe status: probe-tested 2026-07-19 on a257private over-budget motion-spec fixture (fresh weak-tier agent, n=1 per258arm, smoke grade): the bare arm caught ~3 of 7 planted violations, loosely259phrased - though it did catch the missing reduced-motion variant, recorded260honestly - while the ruled arm caught 7 of 7 with budget citations,261including the keyboard rule and the 500ms total-stagger cap the bare arm262lacked as concepts. A round-0 run was voided for a leaked in-fixture263answer key. Trail in the design-pack PR.