Add workout videos, editable HyperFrames projects and music tools

- diamond-pushup (with and without music) and bench-dips videos
- Editable project sources for both videos
- make_music.py: original copyright-free music generator

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXVsD1DgdzZLiPuwtKzMSY
This commit is contained in:
Claude committed 2026-10-21 23:40:56 +00:00
1 parent daac216bb9
commit 8b1eeff1ed
33 files changed
+1051

No files matched your search

@@ -0,0 +1,36 @@
<template>
<style>
#root { position: absolute; inset: 0; font-family: "Inter", sans-serif; color: #eaf2ff; }
.tip { position: absolute; left: 192px; bottom: 108px; width: 1100px; }
.tip .num { display: inline-block; font-weight: 700; font-size: 28px; letter-spacing: 0.16em; color: var(--accent, #ff7a45); margin-right: 20px; }
.tip h2 { font-family: "Oswald", sans-serif; font-weight: 700; font-size: 76px; line-height: 1.02; letter-spacing: 0.01em; }
.tip p { margin-top: 10px; font-weight: 500; font-size: 32px; line-height: 1.25; }
</style>
<div id="root" data-composition-id="tips" data-width="1920" data-height="1080">
<div id="tip1" class="clip tip" data-start="0.4" data-duration="2.0" data-track-index="0">
<h2>LOWER SLOWLY</h2><p><span class="num">01</span>Elbows close to your body</p>
</div>
<div id="tip2" class="clip tip" data-start="2.6" data-duration="2.0" data-track-index="0">
<h2>PUSH UP</h2><p><span class="num">02</span>Squeeze your chest and triceps</p>
</div>
<div id="tip3" class="clip tip" data-start="4.8" data-duration="2.4" data-track-index="0">
<h2>BODY STRAIGHT</h2><p><span class="num">03</span>Core tight, hips level</p>
</div>
<div id="tip4" class="clip tip" data-start="7.4" data-duration="2.7" data-track-index="0">
<h2>REPEAT WITH CONTROL</h2><p><span class="num">04</span>Breathe out as you push up</p>
</div>
</div>
<script>
const tl = gsap.timeline({ paused: true });
// Each tip blurs in, holds, and leaves faster than it arrived. Animate the children, never the .clip.
[["tip1", 0.4, 2.0], ["tip2", 2.6, 2.0], ["tip3", 4.8, 2.4], ["tip4", 7.4, 2.7]].forEach(([id, s, d]) => {
const kids = "#" + id + " > *";
tl.fromTo(kids, { opacity: 0, filter: "blur(8px)" },
{ opacity: 1, filter: "blur(0px)", duration: 0.22, ease: "power4.out", stagger: 0.06 }, s);
if (id !== "tip4") {
tl.to(kids, { opacity: 0, filter: "blur(8px)", duration: 0.14, ease: "power3.in" }, s + d - 0.2);
}
});
window.__timelines["tips"] = tl;
</script>
</template>
@@ -0,0 +1,33 @@
<template>
<style>
#root { position: absolute; inset: 0; font-family: "Inter", sans-serif; color: #eaf2ff; }
#title-block { position: absolute; left: 192px; top: 108px; }
#title-text { font-family: "Oswald", sans-serif; font-weight: 700; font-size: 96px; line-height: 1; letter-spacing: 0.01em; }
#title-text .w { display: inline-block; margin-right: 24px; }
#title-text .hot { color: var(--accent, #ff7a45); }
#title-muscles { margin-top: 18px; font-weight: 600; font-size: 30px; letter-spacing: 0.22em; }
#title-rule { width: 96px; height: 4px; margin-top: 22px; background: var(--accent, #ff7a45); transform-origin: left center; }
</style>
<div
id="root"
data-composition-id="title"
data-width="1920"
data-height="1080"
data-composition-variables='[{"id":"exercise","type":"string","label":"Exercise (first word)","default":"DIAMOND"},{"id":"exercise2","type":"string","label":"Exercise (second word)","default":"PUSH-UP"},{"id":"muscles","type":"string","label":"Muscles worked","default":"CHEST · TRICEPS · SHOULDERS"},{"id":"accent","type":"color","label":"Accent colour","default":"#ff7a45"}]'
>
<div id="title-block">
<h1 id="title-text"><span class="w" data-var-text="exercise">DIAMOND</span><span class="w hot" data-var-text="exercise2">PUSH-UP</span></h1>
<div id="title-muscles" data-var-text="muscles">CHEST · TRICEPS · SHOULDERS</div>
<div id="title-rule"></div>
</div>
</div>
<script>
const tl = gsap.timeline({ paused: true });
tl.fromTo("#title-text .w", { opacity: 0, filter: "blur(8px)" },
{ opacity: 1, filter: "blur(0px)", duration: 0.2, ease: "power4.out", stagger: 0.09 }, 0.3);
tl.fromTo("#title-muscles", { opacity: 0, filter: "blur(6px)" },
{ opacity: 1, filter: "blur(0px)", duration: 0.3, ease: "power3.out" }, 0.65);
tl.fromTo("#title-rule", { scaleX: 0 }, { scaleX: 1, duration: 0.5, ease: "expo.out" }, 0.7);
window.__timelines["title"] = tl;
</script>
</template>
@@ -0,0 +1,15 @@
<template>
<style>
#root { position: absolute; inset: 0; pointer-events: none; }
#wash-top { position: absolute; left: 0; top: 0; width: 100%; height: 420px; background: linear-gradient(to bottom, rgba(5,11,26,0.78), rgba(5,11,26,0)); }
#wash-bottom { position: absolute; left: 0; bottom: 0; width: 100%; height: 440px; background: linear-gradient(to top, rgba(5,11,26,0.82), rgba(5,11,26,0)); }
</style>
<div id="root" data-composition-id="wash" data-width="1920" data-height="1080">
<div id="wash-top" data-layout-ignore></div>
<div id="wash-bottom" data-layout-ignore></div>
</div>
<script>
const tl = gsap.timeline({ paused: true });
window.__timelines["wash"] = tl;
</script>
</template>