Porcelain octopus
A cream editorial hero with a giant DRIFT wordmark where a WebGL-rippled floating subject weaves between the back and front letters, with scrolling outlined ghost text, drifting dust and bokeh, and pointer-driven parallax.
Assets
Code: MIT license. Imagery generated with Google Gemini
<!doctype html>
<html lang="en"
><head
><script>
/* 6to9 pattern harness */ (function () {
var parentPaused = false,
hidden = document.hidden,
p = (window.__pattern = { paused: false, reducedMotion: false, maxDpr: 2 });
function sync() {
p.paused = parentPaused || hidden;
}
sync();
try {
p.reducedMotion = matchMedia("(prefers-reduced-motion: reduce)").matches;
} catch (e) {}
document.addEventListener("visibilitychange", function () {
hidden = document.hidden;
sync();
});
addEventListener("message", function (e) {
var d = e.data || {};
if (d.pattern === "pause") {
parentPaused = true;
sync();
}
if (d.pattern === "play") {
parentPaused = false;
sync();
}
});
})();</script
><meta charset="utf-8" /><meta
name="viewport"
content="width=device-width,initial-scale=1"
/><title>Drift</title
><script type="importmap">
{ "imports": {} }</script
><style>
html,
body {
margin: 0;
height: 100%;
background: #f2e8d5;
overflow: hidden;
}
* {
box-sizing: border-box;
}
#hero {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
background: radial-gradient(120% 90% at 55% 40%, #f6eddb 0%, #f2e8d5 55%, #e9dcc2 100%);
font-family:
system-ui,
-apple-system,
"Segoe UI",
Helvetica,
Arial,
sans-serif;
color: #14130f;
}
.layer {
position: absolute;
inset: 0;
will-change: transform;
pointer-events: none;
}
#ghost {
z-index: 1;
}
.grow {
position: absolute;
left: 0;
white-space: nowrap;
font-weight: 900;
font-size: 17vh;
line-height: 1;
letter-spacing: -0.03em;
color: transparent;
-webkit-text-stroke: 1.2px rgba(20, 19, 15, 0.16);
font-family: "Arial Black", Impact, "Helvetica Neue", system-ui, sans-serif;
}
.grow span {
display: inline-block;
margin-right: 0.35em;
}
#dust {
z-index: 2;
}
#back {
z-index: 3;
}
#octo {
position: absolute;
z-index: 4;
left: 56%;
top: 46%;
opacity: 0;
transition: opacity 1.4s ease;
pointer-events: none;
will-change: transform;
}
#octo.on {
opacity: 1;
}
#octo canvas,
#octo img {
width: 100%;
height: 100%;
display: block;
filter: drop-shadow(0 3vh 3.5vh rgba(20, 19, 15, 0.22));
}
#front {
z-index: 5;
}
.word {
position: absolute;
left: 50%;
top: 47%;
transform: translate(-50%, -50%);
white-space: nowrap;
text-align: center;
font-family: "Arial Black", Impact, "Helvetica Neue", system-ui, sans-serif;
font-weight: 900;
letter-spacing: -0.05em;
line-height: 0.8;
color: #14130f;
font-size: 100px;
}
.word span {
display: inline-block;
}
.word .br {
display: none;
}
.word.stack .br {
display: block;
}
#bokeh {
z-index: 6;
}
.ui {
position: absolute;
z-index: 10;
}
.brand {
top: 28px;
left: 32px;
font-weight: 800;
letter-spacing: 0.14em;
font-size: 13px;
text-transform: uppercase;
}
.tag {
top: 28px;
right: 32px;
font-size: 13px;
letter-spacing: 0.08em;
opacity: 0.65;
}
.copy {
left: 32px;
bottom: 36px;
max-width: 360px;
}
.copy p {
margin: 0 0 18px;
font-size: 17px;
line-height: 1.45;
font-weight: 500;
}
.btn {
display: inline-flex;
align-items: center;
gap: 10px;
border: 0;
cursor: pointer;
background: #14130f;
color: #f2e8d5;
font: inherit;
font-weight: 700;
font-size: 15px;
padding: 15px 26px;
border-radius: 999px;
transition:
background 0.25s,
transform 0.25s;
}
.btn:hover {
background: #1c48c4;
transform: translateY(-2px);
}
.btn i {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background: #2a5bff;
}
.btn:hover i {
background: #f2e8d5;
}
.nogl #octo img {
animation: bob 6s ease-in-out infinite;
}
@keyframes bob {
50% {
transform: translateY(-3%) rotate(2deg);
}
}
@media (max-aspect-ratio: 11/10) {
.brand {
top: 20px;
left: 22px;
}
.tag {
top: 20px;
right: 22px;
font-size: 11px;
}
.copy {
left: 22px;
bottom: 28px;
max-width: 300px;
}
.copy p {
font-size: 15px;
margin-bottom: 14px;
}
.grow {
font-size: 11vh;
}
}
</style></head
><body
><div id="hero"
><div id="ghost" class="layer"
><div class="grow" id="g1" style="top: 5%"></div
><div class="grow" id="g2" style="top: 68%"></div></div
><canvas id="dust" class="layer"></canvas
><div id="back" class="layer"><div class="word" id="bw"></div></div><div id="octo"></div
><div id="front" class="layer"><div class="word" id="fw" aria-hidden="true"></div></div
><canvas id="bokeh" class="layer"></canvas><div class="ui brand">Tidewell</div
><div class="ui tag">Vol. 01 — slow software</div
><div class="ui copy"
><p>Hand-glazed focus tools that keep your day gently afloat.</p
><button class="btn" type="button"><i></i>Start drifting</button></div
></div
><script>
(function () {
var P = window.__pattern || { paused: false, reducedMotion: false, maxDpr: 2 };
var hero = document.getElementById("hero"),
back = document.getElementById("back"),
front = document.getElementById("front"),
bw = document.getElementById("bw"),
fw = document.getElementById("fw"),
octo = document.getElementById("octo"),
g1 = document.getElementById("g1"),
g2 = document.getElementById("g2"),
dustC = document.getElementById("dust"),
bokC = document.getElementById("bokeh");
var WORD = "DRIFT",
FRONT = [1, 4];
function build(el, isF) {
el.innerHTML = "";
for (var i = 0; i < WORD.length; i++) {
var s = document.createElement("span");
s.textContent = WORD[i];
if (isF && FRONT.indexOf(i) < 0) s.style.visibility = "hidden";
el.appendChild(s);
if (i === 2) {
var b = document.createElement("br");
b.className = "br";
el.appendChild(b);
}
}
}
build(bw, false);
build(fw, true);
function fillGhost(g) {
var h = "";
for (var i = 0; i < 10; i++) h += "<span>DRIFT</span>";
g.innerHTML = h;
}
fillGhost(g1);
fillGhost(g2);
var S = 600,
port = false,
unitW = 300,
W = innerWidth,
H = innerHeight,
dpr = 1;
function getDpr() {
return Math.max(1, Math.min(window.devicePixelRatio || 1, P.maxDpr || 2));
}
var gl = null,
oc = null,
prog = null,
tex = null,
uT = null,
loaded = false,
dirty = true;
function layout() {
W = innerWidth;
H = innerHeight;
dpr = getDpr();
port = H > W * 1.1;
var st = port;
bw.classList.toggle("stack", st);
fw.classList.toggle("stack", st);
bw.style.fontSize = "100px";
fw.style.fontSize = "100px";
var w = bw.getBoundingClientRect().width || 300;
var fs = (100 * W * (port ? 0.92 : 0.95)) / w;
fs = Math.min(fs, H * 0.72);
bw.style.fontSize = fs + "px";
fw.style.fontSize = fs + "px";
var top = port ? "36%" : "47%";
bw.style.top = top;
fw.style.top = top;
S = port ? W * 1.05 : Math.min(H * 1.02, W * 0.72);
octo.style.width = S + "px";
octo.style.height = S + "px";
octo.style.left = port ? "50%" : "57%";
octo.style.top = port ? "41%" : "47%";
if (oc) {
oc.width = Math.round(S * dpr);
oc.height = Math.round(S * dpr);
}
var u = g1.querySelector("span");
unitW = u
? u.getBoundingClientRect().width + parseFloat(getComputedStyle(u).marginRight || 0)
: 300;
dustC.width = Math.round(W * dpr);
dustC.height = Math.round(H * dpr);
bokC.width = Math.round(W * dpr);
bokC.height = Math.round(H * dpr);
dirty = true;
}
function mk(type, src) {
var s = gl.createShader(type);
gl.shaderSource(s, src);
gl.compileShader(s);
if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) throw new Error("shader");
return s;
}
function initGL() {
oc = document.createElement("canvas");
try {
gl = oc.getContext("webgl", {
alpha: true,
premultipliedAlpha: true,
antialias: false,
});
} catch (e) {
gl = null;
}
if (!gl) return false;
try {
var vs =
"attribute vec2 p;varying vec2 v;void main(){v=p*.5+.5;gl_Position=vec4(p,0.,1.);}";
var fs =
"precision mediump float;varying vec2 v;uniform sampler2D tx;uniform float t;void main(){vec2 uv=vec2(v.x,1.-v.y);vec2 c=uv-vec2(.5,.45);float br=1.+sin(t*.9)*.008;uv=vec2(.5,.45)+c/br;float w=smoothstep(.38,.98,uv.y);float w2=w*w;uv.x+=sin(uv.y*7.-t*1.5+uv.x*3.)*.016*w+sin(uv.y*13.-t*2.1)*.004*w2;uv.y+=sin(uv.x*6.+t*1.15)*.01*w;vec4 col=texture2D(tx,uv);float lum=dot(col.rgb,vec3(.333));float sh=pow(max(0.,sin((uv.x*1.2+uv.y)*5.-t*.6)),24.)*.16*smoothstep(.6,.95,lum);col.rgb=min(col.rgb+vec3(sh)*col.a,vec3(1.));gl_FragColor=col;}";
prog = gl.createProgram();
gl.attachShader(prog, mk(gl.VERTEX_SHADER, vs));
gl.attachShader(prog, mk(gl.FRAGMENT_SHADER, fs));
gl.linkProgram(prog);
if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) throw new Error("link");
gl.useProgram(prog);
var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),
gl.STATIC_DRAW,
);
var loc = gl.getAttribLocation(prog, "p");
gl.enableVertexAttribArray(loc);
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
uT = gl.getUniformLocation(prog, "t");
gl.uniform1i(gl.getUniformLocation(prog, "tx"), 0);
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
} catch (e) {
gl = null;
return false;
}
octo.appendChild(oc);
return true;
}
var hasGL = initGL();
var img = new Image();
img.crossOrigin = "anonymous";
img.onload = function () {
if (hasGL && gl) {
try {
tex = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
loaded = true;
} catch (e) {
hasGL = false;
gl = null;
}
}
if (!hasGL || !gl) {
hero.classList.add("nogl");
if (oc && oc.parentNode) oc.parentNode.removeChild(oc);
octo.appendChild(img);
loaded = true;
}
octo.classList.add("on");
dirty = true;
};
img.onerror = function () {};
img.src = "https://agents-dev.6to9.ai/visuals/0ed80ccfe9c09aa4d198c8e827139a35.png";
if (!hasGL) {
hero.classList.add("nogl");
}
var dust = [],
bok = [],
i;
for (i = 0; i < 80; i++)
dust.push({
x: Math.random(),
y: Math.random(),
r: 0.6 + Math.random() * 1.6,
vy: 0.004 + Math.random() * 0.01,
vx: (Math.random() - 0.5) * 0.004,
a: 0.15 + Math.random() * 0.35,
ph: Math.random() * 6.28,
c: Math.random() < 0.35 ? "24,64,190" : "20,19,15",
});
var bcols = ["24,64,190", "24,64,190", "214,150,90", "255,252,240"];
for (i = 0; i < 12; i++)
bok.push({
x: Math.random(),
y: Math.random(),
r: 22 + Math.random() * 60,
vy: 0.003 + Math.random() * 0.008,
vx: (Math.random() - 0.5) * 0.004,
a: 0.5 + Math.random() * 0.6,
ph: Math.random() * 6.28,
c: bcols[i % bcols.length],
});
var dx = dustC.getContext("2d"),
bx = bokC.getContext("2d");
function drawParts(t, dt) {
dx.setTransform(1, 0, 0, 1, 0, 0);
dx.clearRect(0, 0, dustC.width, dustC.height);
dx.scale(dpr, dpr);
var k, p;
for (k = 0; k < dust.length; k++) {
p = dust[k];
p.y -= p.vy * dt;
p.x += p.vx * dt + Math.sin(t * 0.4 + p.ph) * 0.00012 * (dt > 0 ? 1 : 0);
if (p.y < -0.02) p.y = 1.02;
if (p.x < -0.02) p.x = 1.02;
if (p.x > 1.02) p.x = -0.02;
var tw = 0.6 + 0.4 * Math.sin(t * 0.8 + p.ph);
dx.fillStyle = "rgba(" + p.c + "," + p.a * tw + ")";
dx.beginPath();
dx.arc(p.x * W, p.y * H, p.r, 0, 6.283);
dx.fill();
}
bx.setTransform(1, 0, 0, 1, 0, 0);
bx.clearRect(0, 0, bokC.width, bokC.height);
bx.scale(dpr, dpr);
for (k = 0; k < bok.length; k++) {
p = bok[k];
p.y -= p.vy * dt;
p.x += p.vx * dt;
if (p.y < -0.1) p.y = 1.1;
if (p.x < -0.1) p.x = 1.1;
if (p.x > 1.1) p.x = -0.1;
var px = p.x * W,
py = p.y * H,
r = p.r * (port ? 0.7 : 1);
var g = bx.createRadialGradient(px, py, 0, px, py, r);
var al = 0.16 * p.a * (0.7 + 0.3 * Math.sin(t * 0.5 + p.ph));
g.addColorStop(0, "rgba(" + p.c + "," + al * 0.35 + ")");
g.addColorStop(0.78, "rgba(" + p.c + "," + al * 0.8 + ")");
g.addColorStop(0.94, "rgba(" + p.c + "," + al * 1.7 + ")");
g.addColorStop(1, "rgba(" + p.c + ",0)");
bx.fillStyle = g;
bx.beginPath();
bx.arc(px, py, r, 0, 6.283);
bx.fill();
}
}
var tx = 0,
ty = 0,
mx = 0,
my = 0;
window.addEventListener("pointermove", function (e) {
tx = (e.clientX / W) * 2 - 1;
ty = (e.clientY / H) * 2 - 1;
});
function update(t, dt) {
mx += (tx - mx) * Math.min(1, dt * 3);
my += (ty - my) * Math.min(1, dt * 3);
var a = Math.sin(t * 0.23) * 0.6 + mx,
b = Math.cos(t * 0.31) * 0.4 + my;
var tr = "translate3d(" + (-a * 14).toFixed(2) + "px," + (-b * 8).toFixed(2) + "px,0)";
back.style.transform = tr;
front.style.transform = tr;
var bob = Math.sin(t * 0.7) * S * 0.016 + Math.sin(t * 1.3) * S * 0.004;
octo.style.transform =
"translate(-50%,-50%) translate3d(" +
(a * 32 + Math.sin(t * 0.17) * S * 0.02).toFixed(2) +
"px," +
(b * 18 + bob).toFixed(2) +
"px,0) rotate(" +
(Math.sin(t * 0.4) * 2.2).toFixed(3) +
"deg)";
var off = (t * 22) % unitW;
g1.style.transform =
"translate3d(" + (-off + a * -6 - unitW).toFixed(1) + "px," + -b * 4 + "px,0)";
g2.style.transform =
"translate3d(" + (-unitW * 2 + off + a * -6).toFixed(1) + "px," + -b * 4 + "px,0)";
dustC.style.transform =
"translate3d(" + (-a * 6).toFixed(1) + "px," + (-b * 4).toFixed(1) + "px,0)";
bokC.style.transform =
"translate3d(" + (a * 46).toFixed(1) + "px," + (b * 28).toFixed(1) + "px,0)";
if (gl && loaded && tex) {
gl.viewport(0, 0, oc.width, oc.height);
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.uniform1f(uT, t);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
drawParts(t, dt);
}
var last = performance.now(),
T = 0;
function frame(now) {
requestAnimationFrame(frame);
var dt = Math.min(0.05, Math.max(0, (now - last) / 1000));
last = now;
if (P.paused) return;
if (P.reducedMotion) {
if (!dirty) return;
T = 3;
dt = 0;
} else T += dt;
dirty = false;
try {
update(T, dt);
} catch (e) {}
}
window.addEventListener("resize", layout);
layout();
requestAnimationFrame(frame);
})();
</script></body
></html
>
Made by 6to9. Back to all motion patterns.