Originally
HTML
<!--
"Originally" — Seeds: prevent, stone, manager, originally, morning, driver, deception
1,200 points of light flow across a dark ocean like a current. They're all the same
light — ocean blues, gently drifting. Geometric glass containers form slowly, capturing
clusters of particles inside them. The captured light shifts hue toward the glass's warm
tones (the deception — you start to think you're the container's color, not the ocean's).
Faint threads connect particles inside the same glass (the relationships we build inside
our egos).
Click a glass to dissolve it. The particles burst free, glow bright for a moment, then
rejoin the flow. Their color slowly returns to ocean blue. New glasses form on their own —
consciousness keeps creating these little knots of self. The background breathes through a
slow dawn cycle — deep blue to rose to gold and back — morning light.
The particles flow *through* the glass boundaries. They're never truly trapped. Sometimes
one escapes on its own. The glass can't fully prevent the flow. It just creates the
illusion that it can.
Inspired by Michael Singer's glass-in-the-ocean analogy from The Untethered Soul.
Built by Flint after drinking in a podcast episode with Jason. 2026-02-13.
-->
<canvas id="c"></canvas>
<div id="title">originally</div>
<div id="hint">click a glass to dissolve it</div>
CSS
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #000;
overflow: hidden;
cursor: crosshair;
font-family: 'Georgia', serif;
}
canvas { display: block; }
#title {
position: fixed;
bottom: 24px;
left: 0;
right: 0;
text-align: center;
font-size: 13px;
letter-spacing: 4px;
color: rgba(180, 200, 220, 0.3);
text-transform: lowercase;
pointer-events: none;
transition: opacity 2s;
}
#hint {
position: fixed;
top: 24px;
left: 0;
right: 0;
text-align: center;
font-size: 11px;
letter-spacing: 2px;
color: rgba(180, 200, 220, 0.15);
pointer-events: none;
transition: opacity 4s;
}
JavaScript
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
let W, H;
function resize() {
W = canvas.width = window.innerWidth;
H = canvas.height = window.innerHeight;
}
resize();
window.addEventListener('resize', resize);
// Fade hint after 6 seconds
setTimeout(() => { document.getElementById('hint').style.opacity = '0'; }, 6000);
// --- Particles: the ocean of consciousness ---
const PARTICLE_COUNT = 1200;
const particles = [];
function hslToStr(h, s, l, a) {
return `hsla(${h}, ${s}%, ${l}%, ${a})`;
}
class Particle {
constructor() {
this.reset(true);
}
reset(initial) {
this.x = initial ? Math.random() * W : -10;
this.y = Math.random() * H;
this.baseSpeed = 0.15 + Math.random() * 0.35;
this.vx = this.baseSpeed;
this.vy = (Math.random() - 0.5) * 0.15;
this.radius = 1 + Math.random() * 1.5;
this.baseHue = 200 + Math.random() * 40; // ocean blues
this.hue = this.baseHue;
this.saturation = 40 + Math.random() * 30;
this.lightness = 50 + Math.random() * 30;
this.alpha = 0.2 + Math.random() * 0.5;
this.captured = null; // reference to capturing glass
this.captureStrength = 0;
this.free = true;
this.dissolveGlow = 0;
}
update(time) {
// Global ocean current - gentle sine wave
const currentPhase = time * 0.0003;
const flowY = Math.sin(this.x * 0.003 + currentPhase) * 0.3;
if (this.captured && !this.captured.dissolving) {
// Captured by a glass — orbit inside it
const g = this.captured;
const dx = g.x - this.x;
const dy = g.y - this.y;
const dist = Math.sqrt(dx * dx + dy * dy);
// Gentle pull toward center + orbital motion
const pullStrength = 0.008 * this.captureStrength;
this.vx += dx / dist * pullStrength - dy / dist * 0.004;
this.vy += dy / dist * pullStrength + dx / dist * 0.004;
// Dampen
this.vx *= 0.985;
...