Editorial split-screen drift with difference masthead and ticker.
<!doctype html>
<!-- Example: parallax-stars — editorial split drift · difference masthead · ticker strip -->
<html data-duration="10" 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; }
body { background: #050510; height: 100vh; overflow: hidden;
font-family: ui-sans-serif, system-ui; position: relative;
display: grid; grid-template-rows: 1fr 1fr auto; color: white; }
.panel { position: relative; overflow: hidden; }
.top { background: radial-gradient(circle at 30% 50%, #1a0a40, #050510 70%); }
.bottom { background: radial-gradient(circle at 70% 50%, #401a0a, #100404 70%); }
.layer { position: absolute; inset: 0; will-change: background-position; }
.l1 { background-image: radial-gradient(white 1px, transparent 1px); background-size: 28px 28px; opacity: .35; }
.l2 { background-image: radial-gradient(white 1.4px, transparent 1.4px); background-size: 60px 60px; opacity: .7; }
.l3 { background-image: radial-gradient(var(--signal) 1.6px, transparent 1.6px); background-size: 140px 140px; }
.divider { position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
background: var(--signal); z-index: 5; }
.mast { position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%);
text-align: center; color: white; font-size: 132px; font-weight: 700;
letter-spacing: -0.04em; mix-blend-mode: difference; z-index: 10;
pointer-events: none; }
.mast em { color: var(--signal); font-style: italic; }
.ticker { background: var(--signal); color: white; padding: 12px 24px;
font-family: ui-monospace, monospace; font-size: 13px; letter-spacing: .15em;
text-transform: uppercase; overflow: hidden; white-space: nowrap; }
.ticker .belt { display: inline-block; will-change: transform; }
.ticker .belt span { padding-right: 64px; }
</style></head><body>
<div class="panel top">
<div class="layer l1" id="A1"></div>
<div class="layer l2" id="A2"></div>
<div class="layer l3" id="A3"></div>
</div>
<div class="panel bottom">
<div class="layer l1" id="B1"></div>
<div class="layer l2" id="B2"></div>
<div class="layer l3" id="B3"></div>
<div class="divider"></div>
</div>
<h1 class="mast">Into the <em>deep</em> field</h1>
<div class="ticker">
<div class="belt" id="belt">
<span>● LATEST · HYPERFRAMES v1.0 · BROWSER-NATIVE 4K · DETERMINISTIC PIPELINE · MIT LICENSED · GIT-FRIENDLY MOTION · </span>
<span>● LATEST · HYPERFRAMES v1.0 · BROWSER-NATIVE 4K · DETERMINISTIC PIPELINE · MIT LICENSED · GIT-FRIENDLY MOTION · </span>
</div>
</div>
<script>
var A = [document.getElementById('A1'), document.getElementById('A2'), document.getElementById('A3')];
var B = [document.getElementById('B1'), document.getElementById('B2'), document.getElementById('B3')];
var belt = document.getElementById('belt');
var t = 0;
var reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
function render() {
var tt = reduced ? 0 : t;
// Top panel drifts right; bottom panel drifts left (opposing parallax).
A[0].style.backgroundPosition = (tt * 10) + 'px ' + (tt * 4) + 'px';
A[1].style.backgroundPosition = (tt * 26) + 'px ' + (tt * 10) + 'px';
A[2].style.backgroundPosition = (tt * 58) + 'px ' + (tt * 28) + 'px';
B[0].style.backgroundPosition = (-tt * 10) + 'px ' + (tt * 4) + 'px';
B[1].style.backgroundPosition = (-tt * 26) + 'px ' + (tt * 10) + 'px';
B[2].style.backgroundPosition = (-tt * 58) + 'px ' + (tt * 28) + 'px';
// Ticker belt scrolls at a constant rate.
var x = -((tt * 120) % 1200);
belt.style.transform = 'translateX(' + x.toFixed(0) + 'px)';
}
addEventListener('hf-seek', function(e) { t = e.detail.time; render(); });
render();
</script>
</body></html>