refactor(skills,lint): migrate kinetic-letter-in off letterSpacing; document rule design

The kinetic-letter-in motion-primitive (a music-to-video reference authors copy)
animated the word's letterSpacing as a settle — a reflow tween that micro-stutters
under seek-by-frame capture, and outside the registry scan so the rule never fired
on it. The chars are already per-glyph spans, so migrate the settle to a per-glyph x
spread ((0.04em − −0.04em) × 280px = 22.4px/gap, centered about index 3), with a
comment naming the hazard and the rule. Render-verified: faithful, smooth.

Document two intentional design choices in gsap_non_transform_motion so future
readers don't read them as misses:
- No per-line/per-file suppression by design — the stance is fix-the-motion, not
  silence-the-rule; every plain-DOM case has a faithful transform equivalent.
- set() is skipped intentionally: a set() that seats an integer-snapped layout
  position before a later transform tween is a single from-state frame, not motion.

Also hoist loadParseGsapScript() above the per-script loop (the other async rules
do the same; dynamic-import cache makes it equivalent, but the placement no longer
reads as load-bearing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-06-29 15:54:06 -07:00
co-authored by Claude Opus 4.8
parent b95f2ca25e
commit 1c0eef835f
3 changed files with 21 additions and 4 deletions
@@ -84,7 +84,13 @@
{ y: 80, opacity: 0, stagger: 0.045, ease: "back.out(2)", duration: 0.55 },
0.05,
);
tl.to("#hero", { letterSpacing: "0.04em", duration: 0.6, ease: "power2.out" }, 0.7);
// Letters loosen apart as they settle. Animate each glyph's x (a transform), NOT the
// word's letter-spacing: animating letter-spacing reflows text and snaps glyph positions
// to the pixel grid, which micro-stutters on a slow settle under the seek-by-frame
// capture engine (the gsap_non_transform_motion lint rule flags it). The chars are
// already per-glyph spans, so spread them directly: (0.04em (0.04em)) × 280px = 22.4px
// per gap, centered about index 3 of the 7-letter word.
tl.to(".char", { x: (i) => (i - 3) * 22.4, duration: 0.6, ease: "power2.out" }, 0.7);
window.__timelines["main"] = tl;
</script>