HyperFrames composition
S1NTR work
A browser-visible composition preview for HTML + GSAP assets. The generated stage stays live above; export/render details stay available without dominating the artist-facing view.
GSAP timeline / export preview
Use @hyperframes/producer / Exporter.exportVideo() for final MP4 output. This shell is for quick visual inspection inside Studio.
Source code and export details
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<style>
html, body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
background: #1c1a17;
}
[data-composition-id] {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
background:
radial-gradient(ellipse 70% 55% at 72% 18%, rgba(120, 108, 92, 0.35) 0%, transparent 55%),
radial-gradient(ellipse 55% 48% at 18% 78%, rgba(72, 68, 60, 0.55) 0%, transparent 50%),
linear-gradient(168deg, #2a2722 0%, #3d3830 22%, #524a40 48%, #6a5f52 72%, #8a7d6c 100%);
}
.clip {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
will-change: transform, opacity;
}
.layer-far { z-index: 1; opacity: 0.48; }
.layer-mid { z-index: 2; opacity: 0.78; }
.layer-near { z-index: 3; opacity: 1; }
.layer-veil {
z-index: 4;
mix-blend-mode: soft-light;
opacity: 0.32;
}
svg {
width: 100%;
height: 100%;
display: block;
}
.wire {
fill: none;
stroke-linejoin: round;
stroke-linecap: square;
}
.slab {
stroke-linejoin: miter;
}
.mass {
filter: drop-shadow(0 8px 18px rgba(20, 16, 12, 0.35));
}
</style>
</head>
<body>
<div id="stage" data-composition-id="brutal-bead-659" data-width="1920" data-height="1080">
<div class="clip layer-far" data-start="0" data-duration="14" data-track-index="0" id="layer-far">
<svg viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
<defs>
<linearGradient id="far-wash" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#5a5348" stop-opacity="0.25"/>
<stop offset="100%" stop-color="#2e2a24" stop-opacity="0.05"/>
</linearGradient>
</defs>
<g class="grid-field" stroke="#9a9080" stroke-width="1" opacity="0.42">
<rect class="slab wire" x="80" y="120" width="420" height="280" fill="url(#far-wash)"/>
<rect class="slab wire" x="560" y="80" width="360" height="220" fill="rgba(90,83,72,0.12)"/>
<rect class="slab wire" x="980" y="140" width="480" height="260" fill="rgba(70,64,56,0.14)"/>
<rect class="slab wire" x="1520" y="100" width="280" height="320" fill="rgba(80,74,66,0.1)"/>
<line class="wire" x1="80" y1="400" x2="1840" y2="400"/>
<line class="wire" x1="80" y1="560" x2="1840" y2="560"/>
<line class="wire" x1="80" y1="720" x2="1840" y2="720"/>
<line class="wire" x1="320" y1="120" x2="320" y2="920"/>
<line class="wire" x1="720" y1="80" x2="720" y2="960"/>
<line class="wire" x1="1120" y1="100" x2="1120" y2="940"/>
<line class="wire" x1="1520" y1="100" x2="1520" y2="900"/>
</g>
<g class="feedback-echo" stroke="#b8aea0" stroke-width="0.8" opacity="0.28">
<polyline class="wire" points="140,860 280,780 420,860 560,790 700,860"/>
<polyline class="wire" points="1220,840 1360,760 1500,840 1640,770 1780,850"/>
<rect class="slab wire" x="200" y="620" width="160" height="100" fill="none"/>
<rect class="slab wire" x="1560" y="600" width="140" height="120" fill="none"/>
</g>
</svg>
</div>
<div class="clip layer-mid" data-start="0" data-duration="14" data-track-index="1" id="layer-mid">
<svg viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
<defs>
<linearGradient id="concrete-a" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#c4b8a8"/>
<stop offset="55%" stop-color="#8e8476"/>
<stop offset="100%" stop-color="#5c554c"/>
</linearGradient>
<linearGradient id="concrete-b" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#a89c8c"/>
<stop offset="100%" stop-color="#6e655a"/>
</linearGradient>
<linearGradient id="oxide" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#7a6a58"/>
<stop offset="100%" stop-color="#4a433a"/>
</linearGradient>
</defs>
<g id="modular-core" transform="translate(960,540)">
<g class="block-stack mass" fill="url(#concrete-a)" stroke="#2a2620" stroke-width="2.2">
<polygon class="slab" points="-320,-40 -80,-40 -80,160 -320,160"/>
<polygon class="slab" points="-80,-180 140,-180 140,-40 -80,-40" fill="url(#concrete-b)"/>
<polygon class="slab" points="140,-40 340,-40 340,120 140,120" fill="url(#oxide)"/>
<polygon class="slab" points="-200,160 40,160 40,280 -200,280" fill="#7d7366"/>
</g>
<g class="hydra-orbit" fill="none" stroke="#d4c8b8" stroke-width="1.6" opacity="0.85">
<rect class="slab wire" x="-260" y="-120" width="120" height="80"/>
<rect class="slab wire" x="40" y="-220" width="100" height="60"/>
<rect class="slab wire" x="180" y="40" width="90" height="110"/>
<rect class="slab wire" x="-140" y="180" width="150" height="70"/>
<line class="wire" x1="-200" y1="-80" x2="90" y2="-190"/>
<line class="wire" x1="90" y1="-160" x2="225" y2="40"/>
<line class="wire" x1="225" y1="95" x2="-65" y2="215"/>
<line class="wire" x1="-65" y1="215" x2="-200" y2="-40"/>
</g>
<g class="bead-nodes" fill="#e8dcc8" stroke="#3a342c" stroke-width="1.2">
<circle cx="-200" cy="-80" r="7"/>
<circle cx="90" cy="-190" r="7"/>
<circle cx="225" cy="95" r="7"/>
<circle cx="-65" cy="215" r="7"/>
<circle cx="0" cy="0" r="10" fill="#f0e6d4"/>
</g>
</g>
<g class="buttress" stroke="#a89e90" stroke-width="1.4" fill="rgba(120,110,96,0.18)">
<polygon class="slab" points="120,820 280,680 320,700 180,860"/>
<polygon class="slab" points="1640,800 1780,660 1820,680 1700,840"/>
<rect class="slab" x="860" y="760" width="200" height="140"/>
</g>
</svg>
</div>
<div class="clip layer-near" data-start="0" data-duration="14" data-track-index="2" id="layer-near">
<svg viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
<defs>
<linearGradient id="edge-light" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#efe6d8" stop-opacity="0.9"/>
<stop offset="100%" stop-color="#8a8072" stop-opacity="0.35"/>
</linearGradient>
</defs>
<g id="foreground-mass" class="mass">
<polygon class="slab" fill="url(#edge-light)" stroke="#1e1b17" stroke-width="2.4"
points="60,980 220,620 380,640 280,980"/>
<polygon class="slab" fill="#9c9080" stroke="#1e1b17" stroke-width="2.4"
points="1640,980 1720,700 1860,720 1800,980"/>
<polygon class="slab" fill="#6e655a" stroke="#1e1b17" stroke-width="2"
points="1480,980 1560,820 1680,840 1620,980"/>
</g>
<g class="feedback-frame" fill="none" stroke="#f2eadc" stroke-width="2" opacity="0.72">
<rect class="slab wire" id="frame-a" x="480" y="260" width="960" height="540"/>
<rect class="slab wire" id="frame-b" x="560" y="320" width="800" height="420"/>
<rect class="slab wire" id="frame-c" x="640" y="380" width="640" height="300"/>
</g>
<g class="shear-planes" fill="rgba(236,228,214,0.08)" stroke="#d8cec0" stroke-width="1.3">
<polygon class="slab" points="720,200 880,160 920,280 760,320"/>
<polygon class="slab" points="1100,180 1280,220 1240,340 1060,300"/>
<polygon class="slab" points="840,700 980,660 1020,780 880,820"/>
</g>
<g class="pivot" fill="#f5efe4" stroke="#2c2822" stroke-width="1.4">
<rect class="slab" x="940" y="520" width="40" height="40"/>
<circle cx="960" cy="540" r="6" fill="#2c2822"/>
</g>
</svg>
</div>
<div class="clip layer-veil" data-start="0" data-duration="14" data-track-index="3" id="layer-veil">
<svg viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
<defs>
<radialGradient id="dust" cx="50%" cy="40%" r="65%">
<stop offset="0%" stop-color="#d8cfc0" stop-opacity="0.2"/>
<stop offset="55%" stop-color="#8a8072" stop-opacity="0.08"/>
<stop offset="100%" stop-color="#2a2620" stop-opacity="0"/>
</radialGradient>
</defs>
<rect width="1920" height="1080" fill="url(#dust)"/>
<g stroke="#efe6d8" stroke-width="0.7" opacity="0.22">
<line class="wire" x1="0" y1="240" x2="1920" y2="280"/>
<line class="wire" x1="0" y1="540" x2="1920" y2="520"/>
<line class="wire" x1="0" y1="820" x2="1920" y2="860"/>
<line class="wire" x1="480" y1="0" x2="520" y2="1080"/>
<line class="wire" x1="1400" y1="0" x2="1360" y2="1080"/>
</g>
</svg>
</div>
</div>
<script>
(function () {
var far = document.getElementById("layer-far");
var mid = document.getElementById("layer-mid");
var near = document.getElementById("layer-near");
var veil = document.getElementById("layer-veil");
var core = document.getElementById("modular-core");
var frameA = document.getElementById("frame-a");
var frameB = document.getElementById("frame-b");
var frameC = document.getElementById("frame-c");
var foreground = document.getElementById("foreground-mass");
var master = gsap.timeline({
defaults: { ease: "sine.inOut" },
repeat: -1,
yoyo: true
});
master.from(far, { y: 28, scale: 1.04, duration: 7, transformOrigin: "50% 50%" }, 0);
master.to(far, { y: -36, x: 18, scale: 1.0, duration: 7, ease: "power1.inOut" }, 0);
master.from(mid, { y: 48, x: -12, scale: 1.06, duration: 7, transformOrigin: "50% 55%" }, 0);
master.to(mid, { y: -62, x: 26, scale: 0.98, duration: 7, ease: "power1.inOut" }, 0);
master.from(near, { y: 76, x: 10, scale: 1.08, duration: 7, transformOrigin: "50% 70%" }, 0);
master.to(near, { y: -92, x: -22, scale: 0.96, duration: 7, ease: "power2.inOut" }, 0);
master.from(veil, { opacity: 0.18, scale: 1.02, duration: 7 }, 0);
master.to(veil, { opacity: 0.42, x: 14, y: -20, scale: 1.0, duration: 7 }, 0);
master.from(core, { rotation: -8, scale: 0.94, duration: 7, transformOrigin: "50% 50%" }, 0);
master.to(core, { rotation: 10, scale: 1.03, duration: 7, ease: "sine.inOut" }, 0);
master.from(".hydra-orbit", { opacity: 0.35, scale: 0.92, duration: 7, transformOrigin: "50% 50%" }, 0);
master.to(".hydra-orbit", { opacity: 1, scale: 1.06, rotation: -6, duration: 7 }, 0);
master.from(".bead-nodes circle", { scale: 0.6, opacity: 0.4, duration: 3.5, stagger: 0.18, transformOrigin: "50% 50%" }, 0);
master.to(".bead-nodes circle", { scale: 1.15, opacity: 1, duration: 3.5, stagger: 0.18, yoyo: true, repeat: 1 }, 3.5);
master.from(frameA, { scale: 0.88, opacity: 0.25, duration: 7, transformOrigin: "50% 50%" }, 0);
master.to(frameA, { scale: 1.04, opacity: 0.85, duration: 7 }, 0);
master.from(frameB, { scale: 0.9, opacity: 0.2, duration: 7, transformOrigin: "50% 50%" }, 0.15);
master.to(frameB, { scale: 1.08, opacity: 0.7, duration: 7 }, 0.15);
master.from(frameC, { scale: 0.92, opacity: 0.15, duration: 7, transformOrigin: "50% 50%" }, 0.3);
master.to(frameC, { scale: 1.12, opacity: 0.55, duration: 7 }, 0.3);
master.from(foreground, { y: 40, opacity: 0.7, duration: 7 }, 0);
master.to(foreground, { y: -28, opacity: 1, duration: 7 }, 0);
master.from(".shear-planes polygon", { y: 24, opacity: 0.15, duration: 5, stagger: 0.25 }, 0.4);
master.to(".shear-planes polygon", { y: -18, opacity: 0.55, duration: 5, stagger: 0.25 }, 0.4);
master.from(".block-stack polygon", { y: 16, opacity: 0.55, duration: 6, stagger: 0.12 }, 0.2);
master.to(".block-stack polygon", { y: -12, opacity: 1, duration: 6, stagger: 0.12 }, 0.2);
master.from(".grid-field .slab", { opacity: 0.15, duration: 6, stagger: 0.08 }, 0);
master.to(".grid-field .slab", { opacity: 0.55, duration: 6, stagger: 0.08 }, 0);
window.__timelines = {
master: master,
clips: {
"layer-far": master,
"layer-mid": master,
"layer-near": master,
"layer-veil": master
}
};
})();
</script>
</body>
</html>