32 shards with radial physics and shrinking cast shadow.
Edit these placeholders inline or pass --var NAME=value to hyperframes render.
| Variable | Type | Default | Range |
|---|---|---|---|
{{$TITLE}}Title | text | SHATTER | — |
{{$ACCENT_COLOR}}Accent color | color | #ff3b1f | — |
{{$SHARD_COUNT}}Shard count | number | 32 | 8 → 96 step 4 |
{{$BURST_DURATION}}Burst duration (s) | number | 2.4 | 0.8 → 5 step 0.1 |
<!doctype html>
<!-- Example: prism-shatter — N triangular shards · radial physics · shrinking cast shadow -->
<html data-duration="4" data-aspect="16:9"><head><style>
:root {
--cream:#f6f5f1; --cream-2:#efece4; --ink:#0a0a0a; --mute:#6b6862;
--line:#e3dfd3; --signal:#ff3b1f; --signal-2:#ff6a4a; --frame:#ffb800;
--green:#1f8a5b; --blue:#2b66ff;
}
* { box-sizing: border-box; }
body { margin:0; }
:root { --accent: {{$ACCENT_COLOR}}; }
body { background: var(--ink); color: white; height: 100vh; overflow: hidden;
display: grid; place-items: center; font-family: ui-sans-serif, system-ui; }
.stage { position: relative; width: 820px; height: 360px; }
.title { position: absolute; inset: 0; display: grid; place-items: center;
font-size: 156px; font-weight: 800; letter-spacing: -0.05em;
color: var(--accent);
text-shadow: 0 0 60px color-mix(in srgb, var(--accent) 45%, transparent);
filter: drop-shadow(0 30px 60px color-mix(in srgb, var(--accent) 40%, transparent)); }
.shard { position: absolute; left: 50%; top: 50%; width: 140px; height: 140px;
transform-origin: center; will-change: transform, opacity, filter; }
.cap { position: absolute; bottom: -40px; left: 0; right: 0; text-align: center;
font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: .25em;
color: rgba(255,255,255,.5); }
</style></head><body>
<div class="stage" id="s">
<div class="title" id="t">{{$TITLE}}</div>
</div>
<div class="cap">// shards · radial physics · t-driven</div>
<script>
var s = document.getElementById('s');
var title = document.getElementById('t');
var N = {{$SHARD_COUNT}};
var BURST = {{$BURST_DURATION}};
var shards = [];
for (var i = 0; i < N; i++) {
var el = document.createElement('i');
el.className = 'shard';
// Stable per-shard parameters so seek is deterministic.
var ang = (i / N) * Math.PI * 2 + (i % 3) * 0.15;
var spin = (i % 2 === 0 ? 1 : -1) * (1.2 + (i % 5) * 0.35);
var rot = ((i * 47) % 360);
var skew = ((i * 23) % 30) - 15;
el.style.clipPath = 'polygon(50% 0, 100% 100%, 0 100%)';
// Each shard carries the same brand gradient — pieces of the title.
el.style.background = 'linear-gradient(' + rot + 'deg, var(--accent), var(--frame))';
el.style.transform = 'translate(-50%, -50%) rotate(' + rot + 'deg)';
s.appendChild(el);
shards.push({ el: el, ang: ang, spin: spin, rot: rot, skew: skew, i: i });
}
var t = 0;
var reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
function ease(x){ return 1 - Math.pow(1 - x, 3); }
function render() {
var tt = reduced ? 3 : t;
var u = ease(Math.max(0, Math.min(1, (tt - 1.5) / BURST)));
title.style.opacity = String(1 - u);
title.style.transform = 'scale(' + (1 + u * 0.18).toFixed(3) + ')';
shards.forEach(function(o) {
// Quadratic radial fall-off — closer shards drift further.
var r = u * 720 * (0.7 + (o.i % 4) * 0.12) + 30;
var x = Math.cos(o.ang) * r;
var y = Math.sin(o.ang) * r;
var rot = o.rot + o.spin * u * 540;
var scale = (1 - u * 0.55);
o.el.style.transform =
'translate(calc(-50% + ' + x.toFixed(1) + 'px), calc(-50% + ' + y.toFixed(1) + 'px)) ' +
'rotate(' + rot.toFixed(1) + 'deg) scale(' + scale.toFixed(3) + ') skew(' + o.skew + 'deg)';
// Cast shadow shrinks as the shard flies away (drop-shadow goes from large+soft to small+sharp).
var sh = (1 - u) * 30 + 4;
var sy = (1 - u) * 18 + 4;
o.el.style.filter = 'drop-shadow(0 ' + sy.toFixed(0) + 'px ' + sh.toFixed(0) + 'px rgba(0,0,0,.55))';
o.el.style.opacity = u > 0 ? String(Math.max(0, 1 - u * 1.1)) : '0';
});
}
addEventListener('hf-seek', function(e) { t = e.detail.time; render(); });
render();
</script>
</body></html>