Transform Order Is Not Cosmetic
MUST: Compose transform as translate → rotate → scale, and keep that order everywhere in the system. transform is a right-to-left matrix chain, so a translate written after a scale is measured in the scaled space: scale(0.5) translateY(60px) travels 30px, and the distance grows as the scale animates, bending the path into an easing you never wrote. Hoist the order with the rest of the motion constants; this bug never throws.
translate-then-scale is a different result from scale-then-translate — the second scales the distance, so a 60px lift at scale 0.5 travels 30px
// bad — translate lives in the scaled space; 60px becomes 30px at scale 0.5
transform: scale(0.5) translateY(60px);
// good — translation first, scale last: 60px is 60px at every scale
transform: translate3d(0, 60px, 0) scale(0.5);Bad
Good
Why it matters
The catalog does not argue this in prose — it pins the order in a machine-readable `rendering_contract` field on every one of its 24 effects, which is the tell: reproductions diverged until the order became part of the contract. The reason is that `transform` is a chain of matrix multiplications applied right to left, so every function operates inside the coordinate space the functions after it have already established.
Write `scale(0.5) translateY(60px)` and the translation happens in a space that is already half size, so the glyph rises 30px rather than 60 — and as the scale animates toward 1 the effective distance GROWS, which bends the path into an easing you never authored and cannot find in your easing constant. Write `translateY(60px) scale(0.5)` and the two are independent: 60px is 60px at every scale, which is why the catalog puts translation first and scale last.
The discipline generalises past text: pick one order, hoist it with the rest of the motion constants (animations-named-timing-constants), and never let two components in the same system disagree, because this bug does not throw — it just makes the motion quietly wrong in a way that reads as "the animation feels off". Distinct from animations-correct-transform-origin, which fixes WHERE a scale starts from; this fixes what every other function in the same chain means once a scale is in it.
The individual `translate` / `rotate` / `scale` properties avoid the ambiguity — the spec fixes their order — but they still compose with `transform` in a defined sequence, so mixing the two forms needs the same care.