121 lines
6.1 KiB
HTML
121 lines
6.1 KiB
HTML
|
|
<!doctype html>
|
||
|
|
<html><head>
|
||
|
|
<meta name="description" content="OFF-KEY Read the Pulse ON-KEY The Patient Hum Ahmed White — 30 years at the stack Hold Steady"><meta charset="UTF-8"/>
|
||
|
|
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||
|
|
<style>
|
||
|
|
:root{ --amber:#e8a449; --dim:#b0772a; --bg:#0d0a08; --steel:#3a4a4f; }
|
||
|
|
body{margin:0;background:#0d0a08;color:#f0e6d4;font-family:Georgia,'Times New Roman',serif}
|
||
|
|
#root{position:relative;width:1920px;height:1080px;overflow:hidden}
|
||
|
|
.clip{position:absolute;inset:0;display:grid;place-items:center}
|
||
|
|
.bg{position:absolute;inset:0;background:radial-gradient(circle at 50% 60%, #1a120b 0%, #0d0a08 70%)}
|
||
|
|
/* furnace glow */
|
||
|
|
.forge{position:absolute;left:50%;top:50%;width:520px;height:400px;transform:translate(-50%,-50%);border-radius:60px;
|
||
|
|
background:linear-gradient(180deg,#b03018 0%,#6e1b08 55%,#2a0e04 100%);border:6px solid #2a2018}
|
||
|
|
.door{position:absolute;left:50%;top:50%;width:380px;height:260px;transform:translate(-50%,-50%);border-radius:30px;
|
||
|
|
background:radial-gradient(circle at 50% 65%, #ffb45e 0%, #d85a1f 30%, #5e1806 75%, #200a02 100%);
|
||
|
|
box-shadow:0 0 120px 40px rgba(216,90,31,0.55), inset 0 0 60px 20px rgba(255,180,94,0.35)}
|
||
|
|
/* waveform bars */
|
||
|
|
.wave{position:absolute;left:50%;bottom:120px;transform:translateX(-50%);display:flex;align-items:flex-end;gap:8px;height:180px}
|
||
|
|
.bar{width:10px;border-radius:3px;background:#e8a449;height:40px}
|
||
|
|
/* atmosphere line */
|
||
|
|
.noise{position:absolute;left:60px;right:60px;bottom:210px;height:2px;background:linear-gradient(90deg,transparent,#b0772a33 20%,#b0772a33 80%,transparent)}
|
||
|
|
h1{position:absolute;font-size:64px;letter-spacing:2px;text-transform:uppercase;font-weight:400;color:#f0e6d4;opacity:0}
|
||
|
|
.tag{position:absolute;font-size:26px;color:#b0772a;letter-spacing:6px;text-transform:uppercase;opacity:0}
|
||
|
|
.cred{position:absolute;font-size:22px;color:#8a7a63}
|
||
|
|
</style> <script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div id="root" data-composition-id="main" data-start="0" data-width="1920" data-height="1080" data-duration="54">
|
||
|
|
<audio id="voice-s1" src="audio/s1.wav" data-start="0"></audio>
|
||
|
|
<audio id="voice-s2" src="audio/s2.wav" data-start="19"></audio>
|
||
|
|
<audio id="voice-s3" src="audio/s3.wav" data-start="37"></audio>
|
||
|
|
<audio id="bgm" src="audio/music.mp3" data-start="0" data-volume="0.14"></audio>
|
||
|
|
|
||
|
|
<!-- Scene 1: off-key, the alarm -->
|
||
|
|
<section id="s1" class="clip" data-start="0" data-duration="19" data-track-index="1">
|
||
|
|
<div class="bg"></div>
|
||
|
|
<div class="noise"></div>
|
||
|
|
<div class="forge"><div class="door"></div></div>
|
||
|
|
<div id="w1" class="wave"></div>
|
||
|
|
<p class="tag" id="tag1" style="top:80px">OFF-KEY</p>
|
||
|
|
<h1 id="t1" style="top:150px">Read the Pulse</h1>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<!-- Scene 2: on-key, the hum -->
|
||
|
|
<section id="s2" class="clip" data-start="19" data-duration="18" data-track-index="1">
|
||
|
|
<div class="bg"></div>
|
||
|
|
<div class="noise"></div>
|
||
|
|
<div class="forge"><div class="door"></div></div>
|
||
|
|
<div id="w2" class="wave"></div>
|
||
|
|
<p class="tag" id="tag2" style="top:80px">ON-KEY</p>
|
||
|
|
<h1 id="t2" style="top:150px">The Patient Hum</h1>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<!-- Scene 3: the hold -->
|
||
|
|
<section id="s3" class="clip" data-start="37" data-duration="17" data-track-index="1">
|
||
|
|
<div class="bg"></div>
|
||
|
|
<div class="noise"></div>
|
||
|
|
<div class="forge"><div class="door"></div></div>
|
||
|
|
<div id="w3" class="wave"></div>
|
||
|
|
<p class="cred" id="cred" style="top:80px;left:50%;transform:translateX(-50%)">Ahmed White — 30 years at the stack</p>
|
||
|
|
<h1 id="t3" style="top:150px">Hold Steady</h1>
|
||
|
|
</section>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
// build the bars deterministically
|
||
|
|
const counts = [28, 28, 28];
|
||
|
|
const waves = [document.getElementById('w1'), document.getElementById('w2'), document.getElementById('w3')];
|
||
|
|
// deterministic pseudo-heights (no Math.random allowed at runtime — precompute fixed arrays)
|
||
|
|
const jag = [22,66,18,78,14,80,20,70,16,84,12,74,24,68,18,82,14,76,26,66,20,78,12,84,18,72,22,80];
|
||
|
|
const hum = [50,58,64,68,70,70,69,68,66,64,63,64,66,68,70,70,68,66,63,62,63,66,70,72,70,66,60,54];
|
||
|
|
const hold = [64,66,67,68,68,68,67,66,66,67,68,69,68,67,66,66,68,70,70,68,66,66,68,70,70,68,66,64];
|
||
|
|
const sets = [jag, hum, hold];
|
||
|
|
for (let i = 0; i < 3; i++) {
|
||
|
|
const container = waves[i];
|
||
|
|
const h = sets[i];
|
||
|
|
for (let j = 0; j < h.length; j++) {
|
||
|
|
const b = document.createElement('div');
|
||
|
|
b.className = 'bar';
|
||
|
|
b.style.height = h[j] + 'px';
|
||
|
|
b.style.opacity = '0';
|
||
|
|
b.setAttribute('data-bar', j + '-' + i);
|
||
|
|
container.appendChild(b);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
window.__timelines = window.__timelines || {};
|
||
|
|
const tl = gsap.timeline({ paused: true });
|
||
|
|
const op = { duration: 0.5, ease: 'power1.out' };
|
||
|
|
const dur = { duration: 0.8, ease: 'power2.out' };
|
||
|
|
|
||
|
|
// precompute stagger positions for each wave: bars reveal left to right
|
||
|
|
function revealBars(sel, start, gap, maxOp) {
|
||
|
|
document.querySelectorAll(sel).forEach((el, i) => {
|
||
|
|
tl.to(el, { opacity: maxOp, duration: 0.15, ease: 'power1.out' }, start + i * gap);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
// scene 1: jagged alarm, bars come fast and bright, slight flicker
|
||
|
|
revealBars('#w1 .bar', 1.0, 0.22, 0.9);
|
||
|
|
tl.to('#tag1', op, 0.6);
|
||
|
|
tl.to('#t1', Object.assign({}, op, { y: 0 }), 1.4);
|
||
|
|
|
||
|
|
// scene 2: smooth hum, slower reveal, gentler opacity
|
||
|
|
revealBars('#w2 .bar', 20.5, 0.30, 0.75);
|
||
|
|
tl.to('#tag2', op, 20.0);
|
||
|
|
tl.to('#t2', Object.assign({}, op, { y: 0 }), 21.0);
|
||
|
|
|
||
|
|
// scene 3: settle — bars shift toward the calm hold height, wider air
|
||
|
|
revealBars('#w3 .bar', 39.0, 0.36, 0.65);
|
||
|
|
tl.to('#cred', op, 38.5);
|
||
|
|
tl.to('#t3', Object.assign({}, op, { y: 0 }), 39.5);
|
||
|
|
|
||
|
|
// gentle global breathing on the door glow (non-transform, safe)
|
||
|
|
['#s1 .door','#s2 .door','#s3 .door'].forEach(function(sel){
|
||
|
|
tl.fromTo(sel, {boxShadow:'0 0 110px 30px rgba(216,90,31,0.45)'},
|
||
|
|
{ boxShadow:'0 0 150px 50px rgba(216,90,31,0.65)', duration:3, yoyo:true, repeat:2, ease:'sine.inOut' });
|
||
|
|
});
|
||
|
|
|
||
|
|
window.__timelines['main'] = tl;
|
||
|
|
</script>
|
||
|
|
</body></html>
|