Editorial line-by-line clip reveal with monospace ticker and accent flash.
Edit these placeholders inline or pass --var NAME=value to hyperframes render.
| Variable | Type | Default | Range |
|---|---|---|---|
{{$LINE_1}}Line 1 | text | Write HTML. | — |
{{$LINE_2}}Line 2 | text | Render video. | — |
{{$LINE_3}}Line 3 | text | Diff in git. | — |
{{$ACCENT_COLOR}}Accent color | color | #ff3b1f | — |
{{$LINE_STAGGER}}Line stagger (s) | number | 0.55 | 0.15 → 1.2 step 0.05 |
<!doctype html>
<!-- Example: typewriter-reveal — editorial clip-path block reveal · monospace ticker · accent flash -->
<html data-duration="8" 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: #f4f1ea; color: var(--ink); height: 100vh; overflow: hidden;
font-family: ui-serif, Georgia, serif; position: relative;
display: grid; grid-template-rows: auto 1fr auto; padding: 56px 72px; }
.ghost { position: absolute; left: -2vw; top: 18vh; font-size: 38vw; font-weight: 800;
letter-spacing: -0.06em; color: color-mix(in srgb, var(--accent) 5%, transparent); pointer-events: none;
line-height: 0.85; font-family: ui-serif, Georgia, serif; }
.rule { position: absolute; left: 72px; right: 72px; top: 56px; height: 1px;
background: rgba(10,10,10,.18); }
.hd { display: flex; justify-content: space-between; align-items: baseline;
font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: .26em;
text-transform: uppercase; color: var(--mute); position: relative; z-index: 2; }
.hd .live { color: var(--accent); display: inline-flex; align-items: center; gap: 6px; }
.hd .live::before { content:""; width: 7px; height: 7px; border-radius:50%; background: var(--accent); }
.stage { display: grid; align-content: center; gap: 22px; position: relative; z-index: 2; }
.lwrap { overflow: hidden; }
.line { font-size: 124px; line-height: 0.98; letter-spacing: -0.035em; margin: 0;
font-weight: 500; transform: translateY(110%); }
.line .word { display: inline-block; transition: color .12s; }
.line .word.on { color: var(--accent); font-style: italic; }
.kicker { display: flex; align-items: center; gap: 18px; margin-top: 18px;
font-family: ui-monospace, monospace; font-size: 12.5px; letter-spacing: .18em;
text-transform: uppercase; color: var(--mute); opacity: 0; }
.kicker .pip { width: 26px; height: 1px; background: var(--ink); display: inline-block; }
.foot { display: flex; justify-content: space-between; align-items: center; position: relative; z-index: 2;
font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: .26em;
text-transform: uppercase; color: var(--mute); }
.foot .ticks { display: flex; gap: 5px; }
.foot .ticks i { display: block; width: 5px; height: 14px; background: rgba(10,10,10,.18); }
.foot .ticks i.on { background: var(--accent); }
</style></head><body>
<div class="ghost" id="gh">HF</div>
<div class="rule"></div>
<div class="hd">
<span>Chapter 01 — a study in pacing</span>
<span class="live">live · t<span id="tc">0.00</span>s</span>
</div>
<div class="stage">
<div class="lwrap"><h1 class="line" id="l1">{{$LINE_1}}</h1></div>
<div class="lwrap"><h1 class="line" id="l2">{{$LINE_2}}</h1></div>
<div class="lwrap"><h1 class="line" id="l3">{{$LINE_3}}</h1></div>
<div class="kicker" id="kk"><span class="pip"></span> Hyperframes · v1 · editorial release</div>
</div>
<div class="foot">
<span>// rev. <span id="rv">000</span></span>
<span class="ticks" id="tk"></span>
<span>1920 × 1080</span>
</div>
<script>
var lines = [document.getElementById('l1'), document.getElementById('l2'), document.getElementById('l3')];
// Wrap each word so we can flash the last one as the line settles.
lines.forEach(function(el) {
var raw = el.textContent || '';
el.innerHTML = raw.split(/(\s+)/).map(function(tok) {
return /^\s+$/.test(tok) ? tok : '<span class="word">' + tok + '</span>';
}).join('');
});
var allWords = lines.map(function(l){ return Array.prototype.slice.call(l.querySelectorAll('.word')); });
var stagger = {{$LINE_STAGGER}};
var rv = document.getElementById('rv');
var tc = document.getElementById('tc');
var kk = document.getElementById('kk');
var gh = document.getElementById('gh');
var tk = document.getElementById('tk');
for (var i = 0; i < 12; i++) { var b = document.createElement('i'); tk.appendChild(b); }
var ticks = tk.children;
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.0 : t;
// Each line slides up from below behind a clip-path window (set on the wrapper via overflow).
lines.forEach(function(el, i) {
var start = 0.15 + i * stagger;
var u = Math.max(0, Math.min(1, (tt - start) / 0.75));
var e = ease(u);
el.style.transform = 'translateY(' + ((1 - e) * 110).toFixed(1) + '%)';
// Accent the most important word per line, flashing during a short window.
var words = allWords[i];
var lastIdx = words.length - 1;
words.forEach(function(w, j) {
var on = (j === lastIdx) && tt > start + 0.65 && tt < start + 1.6;
w.classList.toggle('on', on);
});
});
// Kicker fades in after all three lines have settled.
var uk = Math.max(0, Math.min(1, (tt - 2.4) / 0.9));
kk.style.opacity = uk;
kk.style.transform = 'translateY(' + ((1 - uk) * 8).toFixed(1) + 'px)';
// Ghost letterform breathes — a slow, persistent ambient pulse.
var br = 0.85 + 0.15 * Math.sin(tt * 0.6);
gh.style.transform = 'scale(' + br.toFixed(3) + ')';
// Footer ticks fill across the duration as a progress indicator.
var nTicks = Math.min(ticks.length, Math.floor((tt / 8) * ticks.length + 0.5));
for (var j = 0; j < ticks.length; j++) ticks[j].classList.toggle('on', j < nTicks);
rv.textContent = String(Math.floor(tt * 60)).padStart(3, '0');
tc.textContent = tt.toFixed(2);
}
addEventListener('hf-seek', function(e) { t = e.detail.time; render(); });
render();
</script>
</body></html>SVG path interpolation between topology-matched glyph shapes.
Constrained damped-spring char stagger with decaying chromatic split.
Ink-bleed displacement with hand-drawn underline path-draw.