Files
hyperframes/skills/music-to-video/references/motion-primitives/kinetic-letter-in/index.html
T
Vance IngallsandClaude Opus 4.8 1c0eef835f 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>
2026-06-29 15:54:06 -07:00

99 lines
2.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1920, height=1080" />
<title>02 · kinetic_letter_in</title>
<script src="../assets/gsap.min.js"></script>
<style>
:root {
--hg-violet: #7c3aed;
--hg-violet-2: #a855f7;
--hg-bg: #0a0a0f;
--hg-fg: #f5f5fa;
--hg-dim: #6b6b78;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
margin: 0;
width: 1920px;
height: 1080px;
overflow: hidden;
background: var(--hg-bg);
font-family: "Inter", system-ui, sans-serif;
color: var(--hg-fg);
-webkit-font-smoothing: antialiased;
}
#scene {
position: absolute;
inset: 0;
width: 1920px;
height: 1080px;
}
.stage {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
}
.hero {
font-weight: 900;
font-size: 280px;
letter-spacing: -0.04em;
line-height: 0.95;
color: var(--hg-fg);
white-space: nowrap;
}
.char {
display: inline-block;
will-change: transform, opacity;
}
</style>
</head>
<body>
<div
id="root"
data-composition-id="main"
data-start="0"
data-duration="2"
data-width="1920"
data-height="1080"
>
<div id="scene" class="clip" data-start="0" data-duration="2" data-track-index="1">
<div class="stage">
<div class="hero" id="hero">
<span class="char">K</span><span class="char">I</span><span class="char">N</span
><span class="char">E</span><span class="char">T</span><span class="char">I</span
><span class="char">C</span>
</div>
</div>
</div>
</div>
<script>
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
tl.from(
".char",
{ y: 80, opacity: 0, stagger: 0.045, ease: "back.out(2)", duration: 0.55 },
0.05,
);
// 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>
</body>
</html>