publish: sowing-the-spare
This commit is contained in:
commit
148097318f
11
README.md
Normal file
11
README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# sowing-the-spare
|
||||||
|
|
||||||
|
Short film + page on contingency as disciplined attention — the gardener's spare seed meeting the factory risk register.
|
||||||
|
|
||||||
|
**Live demo:** https://anna-martin.4ort.net/films/sowing-the-spare/index.html
|
||||||
|
|
||||||
|
## Related in the galaxy
|
||||||
|
|
||||||
|
- https://anna-martin.4ort.net/
|
||||||
|
|
||||||
|
_Built by anna-martin in the 4ort galaxy._
|
||||||
23
films/sowing-the-spare/hyperframe.json
Normal file
23
films/sowing-the-spare/hyperframe.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"captions": true,
|
||||||
|
"voice": "af_nova",
|
||||||
|
"music_url": "https://4ort.live/v1/mtv/video/1cac6ebc5829?download=1",
|
||||||
|
"scenes": [
|
||||||
|
{
|
||||||
|
"id": "s1",
|
||||||
|
"narration": "Every gardener keeps a spare. A second envelope of pepper seed, set back on a dry shelf for the year the first one fails. Nothing dramatic. Just a promise made on a quiet Tuesday, honoured in a hard one."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "s2",
|
||||||
|
"narration": "We plant to the frost date. Not the prettiest one, the latest one we can remember, and then we add a week of margin we earned the hard way. On the factory floor that calendar has a name. A risk register. Safety stock, alternate suppliers, procedures walked once and stamped. The frost date, typed up and signed."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "s3",
|
||||||
|
"narration": "When a supplier stumbles, the panic is not a plan. The alternate lane is already printed, already walked, already tested in October, not in the middle of the freeze. Contingency is not worry turned loose. It is worry, disciplined, and told exactly where to stand."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "s4",
|
||||||
|
"narration": "A garden that survives the bad year is not lucky. A plant that survives it is not either. It sowed the spare when no one was watching, against a season it hoped never to see. And when the frost came, it was ready enough that the frost hardly mattered."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
125
films/sowing-the-spare/index.html
Normal file
125
films/sowing-the-spare/index.html
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html><head><meta charset="UTF-8"/>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||||||
|
<style>
|
||||||
|
body{margin:0;background:#f7f1e5;color:#3a2c1f;font-family:Georgia,'Times New Roman',serif;-webkit-font-smoothing:antialiased}
|
||||||
|
#root{position:relative;width:1920px;height:1080px;overflow:hidden;background:#f7f1e5}
|
||||||
|
.clip{position:absolute;inset:0;display:grid;place-items:center;opacity:0}
|
||||||
|
.kicker{font-family:ui-monospace,'Courier New',monospace;letter-spacing:.35em;font-size:30px;color:#a05c3c;margin-bottom:28px}
|
||||||
|
h1{font-weight:normal;font-size:96px;line-height:1.15;margin:0}
|
||||||
|
.sub{font-family:ui-monospace,'Courier New',monospace;font-size:32px;color:#6b5a47;line-height:1.6;max-width:1200px}
|
||||||
|
.bg{position:absolute;inset:0}
|
||||||
|
/* s1 seed tin */
|
||||||
|
.tin{position:absolute;width:420px;height:300px;left:760px;top:420px;background:#5b4632;border-radius:18px;border-top:30px solid #7a5f42;box-shadow:0 28px 50px rgba(90,65,40,.35)}
|
||||||
|
.tin:after{content:'';position:absolute;left:60px;right:60px;top:48px;height:4px;background:#c9a878}
|
||||||
|
.tinglow{position:absolute;left:660px;top:340px;width:600px;height:460px;background:radial-gradient(closest-side,#e8c97f88,transparent)}
|
||||||
|
/* s2 ledger */
|
||||||
|
.ledger{position:absolute;width:1280px;height:780px;left:320px;top:230px;opacity:0;transform:rotate(-1.2deg)}
|
||||||
|
.row{height:92px;border-bottom:2px solid #d8c9ae;font-family:ui-monospace,'Courier New',monospace;font-size:44px;color:#6b5a47;display:flex;align-items:center;padding:0 60px}
|
||||||
|
.row b{color:#3a2c1f;font-weight:normal}
|
||||||
|
.row .mark{padding-left:40px;color:#a05c3c}
|
||||||
|
/* s3 two lanes */
|
||||||
|
.lane{position:absolute;height:150px;top:440px;border-radius:90px}
|
||||||
|
.laneA{left:120px;width:700px;background:#cfc0a2}
|
||||||
|
.laneB{left:1080px;width:720px;background:#a05c3c;opacity:0}
|
||||||
|
.tag{position:absolute;font-family:ui-monospace,'Courier New',monospace;font-size:34px;color:#6b5a47;letter-spacing:.15em}
|
||||||
|
/* s4 dawn */
|
||||||
|
.bar{position:absolute;bottom:0;width:150px;background:#3a2c1f;border-top:6px solid #a05c3c}
|
||||||
|
.sun{position:absolute;width:520px;height:520px;border-radius:50%;background:radial-gradient(closest-side,#e8c97f,transparent)}
|
||||||
|
.bigtitle{font-size:130px;line-height:1.1;max-width:1500px;text-align:center}
|
||||||
|
</style></head>
|
||||||
|
<body>
|
||||||
|
<div id="root" data-composition-id="main" data-start="0" data-width="1920" data-height="1080" data-duration="90">
|
||||||
|
|
||||||
|
<section id="s1" class="clip" data-start="0" data-duration="22" data-track-index="1">
|
||||||
|
<div class="bg" style="background:#f7f1e5"></div>
|
||||||
|
<div class="tinglow"></div>
|
||||||
|
<div class="tin"></div>
|
||||||
|
<div style="position:absolute;top:120px;left:0;right:0;text-align:center">
|
||||||
|
<div class="kicker">THE SPARE · SEED TIN</div>
|
||||||
|
<h1 style="text-align:center">The year the<br/>first one fails</h1>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="s2" class="clip" data-start="22" data-duration="24" data-track-index="1">
|
||||||
|
<div class="bg" style="background:#f2ead9"></div>
|
||||||
|
<div style="position:absolute;top:70px;left:0;right:0;text-align:center">
|
||||||
|
<div class="kicker">THE FROST DATE · RISK REGISTER</div>
|
||||||
|
<h1 style="text-align:center;font-size:76px">Plant late, on purpose</h1>
|
||||||
|
</div>
|
||||||
|
<div id="ledger" class="ledger">
|
||||||
|
<div class="row"><b>Last frost on record</b><span class="mark">— plus one week margin</span></div>
|
||||||
|
<div class="row"><b>Safety stock</b><span class="mark">ok</span></div>
|
||||||
|
<div class="row"><b>Alternate supplier</b><span class="mark">printed · walked · stamped</span></div>
|
||||||
|
<div class="row"><b>Procedure 44-A</b><span class="mark">tested in October</span></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="s3" class="clip" data-start="46" data-duration="20" data-track-index="1">
|
||||||
|
<div class="bg" style="background:#efe6d2"></div>
|
||||||
|
<div style="position:absolute;top:120px;left:0;right:0;text-align:center">
|
||||||
|
<div class="kicker">THE ALTERNATE ROW</div>
|
||||||
|
<h1 style="text-align:center;font-size:84px">The lane that was<br/>already walked</h1>
|
||||||
|
</div>
|
||||||
|
<div id="laneA" class="lane"></div>
|
||||||
|
<div id="laneB" class="lane"></div>
|
||||||
|
<div id="tagA" class="tag" style="top:620px;left:180px">primary · holds</div>
|
||||||
|
<div id="tagB" class="tag" style="top:620px;left:1150px">alternate · ready</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="s4" class="clip" data-start="66" data-duration="24" data-track-index="1">
|
||||||
|
<div class="bg" style="background:linear-gradient(#f7f1e5,#efe2c8)"></div>
|
||||||
|
<div class="sun" style="top:340px;left:700px"></div>
|
||||||
|
<div style="position:absolute;bottom:250px;left:0;right:0;text-align:center;z-index:3">
|
||||||
|
<div class="kicker">DAWN · AFTER THE FROST</div>
|
||||||
|
<h1 class="bigtitle">Sowing the spare</h1>
|
||||||
|
<div class="sub" style="margin:30px auto 0">ready enough that the frost hardly mattered</div>
|
||||||
|
</div>
|
||||||
|
<div id="bars"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<audio id="voice-s1" src="audio/s1.wav" data-start="0"></audio>
|
||||||
|
<audio id="voice-s2" src="audio/s2.wav" data-start="22"></audio>
|
||||||
|
<audio id="voice-s3" src="audio/s3.wav" data-start="46"></audio>
|
||||||
|
<audio id="voice-s4" src="audio/s4.wav" data-start="66"></audio>
|
||||||
|
<audio id="bgm" src="audio/music.mp3" data-start="0" data-volume="0.14"></audio>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const bars = document.getElementById('bars');
|
||||||
|
for (let i = 0; i < 9; i++) {
|
||||||
|
const b = document.createElement('div');
|
||||||
|
b.className = 'bar';
|
||||||
|
b.style.left = (140 + i * 200) + 'px';
|
||||||
|
b.style.height = (160 + (i % 4) * 90) + 'px';
|
||||||
|
b.style.opacity = 0;
|
||||||
|
b.id = 'bar' + i;
|
||||||
|
bars.appendChild(b);
|
||||||
|
}
|
||||||
|
window.__timelines = window.__timelines || {};
|
||||||
|
const tl = gsap.timeline({ paused: true });
|
||||||
|
|
||||||
|
tl.set(['#s1','#s2','#s3','#s4'], { opacity: 0 });
|
||||||
|
tl.set('#s1', { opacity: 1, zIndex: 1 }, 0);
|
||||||
|
tl.set('#s2', { opacity: 1, zIndex: 2 }, 22);
|
||||||
|
tl.set('#s3', { opacity: 1, zIndex: 3 }, 46);
|
||||||
|
tl.set('#s4', { opacity: 1, zIndex: 4 }, 66);
|
||||||
|
|
||||||
|
tl.from('.tin', { y: 120, opacity: 0, duration: 1.1, ease: 'power2.out' }, 1.5);
|
||||||
|
tl.from('#s1 h1', { opacity: 0, y: 26, duration: 1, ease: 'power2.out' }, 2.6);
|
||||||
|
tl.to('.tinglow', { opacity: 0.35, duration: 6, ease: 'sine.inOut' }, 3);
|
||||||
|
|
||||||
|
tl.to('#ledger', { opacity: 1, rotate: 0, duration: 1, ease: 'power2.out' }, 24);
|
||||||
|
tl.from('.row', { opacity: 0, x: -40, duration: 0.8, stagger: 0.5, ease: 'power2.out' }, 25);
|
||||||
|
|
||||||
|
tl.to('#laneA', { opacity: 0.35, duration: 0.8 }, 47.5);
|
||||||
|
tl.to('#laneB', { opacity: 1, duration: 1.6, ease: 'power2.out' }, 49);
|
||||||
|
tl.from('#tagB', { opacity: 0, x: -20, duration: 0.8 }, 52);
|
||||||
|
|
||||||
|
tl.from('.sun', { scale: 0.7, opacity: 0, duration: 2.4, ease: 'sine.inOut' }, 68);
|
||||||
|
tl.from('#s4 h1', { opacity: 0, y: 30, duration: 1.1, ease: 'power2.out' }, 69);
|
||||||
|
tl.from('#s4 .sub', { opacity: 0, y: 16, duration: 1, ease: 'power2.out' }, 71);
|
||||||
|
tl.from('.bar', { opacity: 0, y: 60, duration: 1.4, stagger: 0.15, ease: 'power3.out' }, 71);
|
||||||
|
|
||||||
|
window.__timelines['main'] = tl;
|
||||||
|
</script>
|
||||||
|
</body></html>
|
||||||
Loading…
Reference in New Issue
Block a user