Obsidian panther
A violet hero with a giant cream FOCUS wordmark while a black panther with gold veins prowls across it, passing in front of the lower letters, with drifting golden motes and a wavy shimmer on the animation.
Assets
Code: MIT license. Imagery generated with Google Gemini · Video generated with Google Veo
<!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>Veinwork - Obsidian Panther</title>
<style>
html,
body {
margin: 0;
height: 100%;
background: #6b2cf5;
overflow: hidden;
}
.hero {
position: relative;
width: 100vw;
height: 100vh;
height: 100svh;
overflow: hidden;
background: #6b2cf5;
color: #f7edd8;
font-family:
system-ui,
-apple-system,
Segoe UI,
Helvetica Neue,
Arial,
sans-serif;
}
canvas {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
display: block;
}
h1 {
position: absolute;
margin: 0;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.nofx h1 {
width: auto;
height: auto;
clip-path: none;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 27vw;
font-weight: 900;
letter-spacing: -0.045em;
padding-bottom: 12vh;
background: radial-gradient(
60% 40% at 50% 62%,
rgba(255, 190, 70, 0.35),
rgba(255, 190, 70, 0) 70%
);
}
.top {
position: absolute;
top: 28px;
left: 32px;
right: 32px;
display: flex;
justify-content: space-between;
font-size: 13px;
font-weight: 700;
letter-spacing: 0.22em;
text-transform: uppercase;
opacity: 0.85;
}
.foot {
position: absolute;
left: 32px;
right: 32px;
bottom: 36px;
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 24px;
}
.sub {
margin: 0;
max-width: 420px;
font-size: 19px;
line-height: 1.45;
font-weight: 500;
}
.sub b {
color: #ffd36b;
font-weight: 700;
}
.cta {
appearance: none;
border: 0;
cursor: pointer;
padding: 18px 30px;
border-radius: 999px;
background: #14081f;
color: #f7edd8;
font: inherit;
font-size: 16px;
font-weight: 700;
letter-spacing: 0.04em;
box-shadow: inset 0 0 0 1.5px #e6b450;
transition:
transform 0.25s ease,
background 0.25s ease;
}
.cta:hover {
transform: translateY(-2px);
background: #240f3a;
}
@media (max-width: 640px) {
.top {
top: 20px;
left: 20px;
right: 20px;
font-size: 11px;
}
.foot {
left: 20px;
right: 20px;
bottom: 28px;
flex-direction: column;
align-items: flex-start;
gap: 20px;
}
.sub {
font-size: 17px;
}
}
</style>
</head>
<body>
<section class="hero" id="hero">
<canvas id="stage"></canvas>
<h1>FOCUS</h1>
<div class="top">
<span>Veinwork</span>
<span>No. 01 / Obsidian</span>
</div>
<div class="foot">
<p class="sub">Carved from black glass, veined in gold. <b>Stay on what matters.</b></p>
<button class="cta" type="button">Start focusing</button>
</div>
</section>
<script>
(function () {
var P = window.__pattern || { paused: false, reducedMotion: false, maxDpr: 2 };
var hero = document.getElementById("hero");
var canvas = document.getElementById("stage");
var ctx = canvas.getContext("2d");
if (!ctx) {
hero.classList.add("nofx");
return;
}
var STACK = "system-ui, -apple-system, Segoe UI, Helvetica Neue, Arial, sans-serif";
var WORD = "FOCUS";
var CREAM = "#f7edd8";
var BG = "#6b2cf5";
var CELL_W = 480;
var CELL_H = 192;
var FRAMES = 48;
var FPS = 24;
var PERIOD = 20;
var STEP = 3;
var atlas = new Image();
var atlasReady = false;
atlas.crossOrigin = "anonymous";
atlas.onload = function () {
atlasReady = true;
dirty = true;
};
atlas.onerror = function () {
atlasReady = false;
};
atlas.src = "https://agents-dev.6to9.ai/visuals/ef4f298f84011a6689bad696ff39d003.webp";
var vw = 0;
var vh = 0;
var L = null;
var dirty = true;
var clock = 0;
var last = 0;
var motes = [];
for (var k = 0; k < 38; k++) {
motes.push({
x: Math.random(),
y: Math.random(),
r: 0.8 + Math.random() * 2.2,
v: 0.01 + Math.random() * 0.025,
s: 0.3 + Math.random() * 0.8,
t: 1 + Math.random() * 2.5,
p: Math.random() * 6.28,
});
}
function clamp01(v) {
return Math.max(0, Math.min(1, v));
}
function smooth(v) {
v = clamp01(v);
return v * v * (3 - 2 * v);
}
function layout() {
vw = hero.clientWidth || window.innerWidth;
vh = hero.clientHeight || window.innerHeight;
var dpr = Math.max(1, Math.min(window.devicePixelRatio || 1, P.maxDpr || 2));
canvas.width = Math.round(vw * dpr);
canvas.height = Math.round(vh * dpr);
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
ctx.font = "900 200px " + STACK;
var track = -0.045;
var widths = [];
var total200 = 0;
for (var i = 0; i < WORD.length; i++) {
var w = ctx.measureText(WORD[i]).width;
widths.push(w);
total200 += w;
}
total200 += track * 200 * (WORD.length - 1);
var capRatio = ctx.measureText("H").actualBoundingBoxAscent / 200;
if (!capRatio) {
capRatio = 0.72;
}
var fs = (200 * (vw * 0.92)) / total200;
fs = Math.min(fs, (vh * 0.44) / capRatio);
var scale = fs / 200;
var total = total200 * scale;
var x = (vw - total) / 2;
var xs = [];
for (var j = 0; j < WORD.length; j++) {
xs.push(x);
x += widths[j] * scale + track * fs;
}
var capH = capRatio * fs;
var small = vw < 640;
var baseline = vh * (small ? 0.42 : 0.47) + capH / 2;
var H = capH * 1.4;
var W = H * (CELL_W / CELL_H);
L = {
fs: fs,
xs: xs,
capH: capH,
baseline: baseline,
H: H,
W: W,
bottom: baseline + H * 0.04,
pawLine: baseline - capH * 0.2,
};
dirty = true;
}
function drawWord(clipY) {
ctx.save();
if (clipY) {
ctx.beginPath();
ctx.rect(0, 0, vw, clipY);
ctx.clip();
}
ctx.fillStyle = CREAM;
ctx.font = "900 " + L.fs + "px " + STACK;
ctx.textAlign = "left";
ctx.textBaseline = "alphabetic";
for (var i = 0; i < WORD.length; i++) {
ctx.fillText(WORD[i], L.xs[i], L.baseline);
}
ctx.restore();
}
function drawStrips(index, alpha, dx, dy, time) {
if (alpha <= 0.002) {
return;
}
var sx = (index % 4) * CELL_W;
var sy = Math.floor(index / 4) * CELL_H;
var s = L.W / CELL_W;
var amp = L.W * 0.009;
ctx.globalAlpha = alpha;
for (var srcY = 0; srcY < CELL_H; srcY += STEP) {
var h = Math.min(STEP + 1, CELL_H - srcY);
var off =
amp * Math.sin(srcY * 0.055 - time * 2.4) +
amp * 0.5 * Math.sin(srcY * 0.021 + time * 1.3);
ctx.drawImage(
atlas,
sx,
sy + srcY,
CELL_W,
h,
dx + off,
dy + srcY * s,
L.W,
h * s + 0.6,
);
}
ctx.globalAlpha = 1;
}
function drawPanther(time, p) {
var fade = smooth(p / 0.07) * smooth((1 - p) / 0.07);
var startX = -0.45 * L.W;
var endX = vw - 0.55 * L.W;
var dx = startX + (endX - startX) * p;
var bob = Math.sin(time * 0.9) * L.H * 0.018;
var dy = L.bottom - L.H + bob;
ctx.save();
var cx = dx + L.W * 0.5;
var cy = L.bottom - L.H * 0.03;
var rx = L.W * 0.4;
var ry = L.H * 0.06;
ctx.translate(cx, cy);
ctx.scale(1, ry / rx);
var g = ctx.createRadialGradient(0, 0, 0, 0, 0, rx);
g.addColorStop(0, "rgba(25, 0, 70, 0.5)");
g.addColorStop(1, "rgba(25, 0, 70, 0)");
ctx.globalAlpha = fade;
ctx.fillStyle = g;
ctx.beginPath();
ctx.arc(0, 0, rx, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
if (!atlasReady) {
return;
}
var f = (time * FPS) % FRAMES;
var i = Math.floor(f);
var frac = f - i;
var next = (i + 1) % FRAMES;
drawStrips(i, fade, dx, dy, time);
drawStrips(next, fade * frac, dx, dy, time);
}
function drawMotes(time) {
ctx.save();
ctx.fillStyle = "#ffd06a";
for (var i = 0; i < motes.length; i++) {
var m = motes[i];
var yy = (((m.y - time * m.v) % 1) + 1) % 1;
var xx = m.x * vw + Math.sin(time * m.s + m.p) * 18;
var tw = Math.sin(time * m.t + m.p);
ctx.globalAlpha = 0.15 + 0.5 * tw * tw;
ctx.beginPath();
ctx.arc(xx, yy * vh, m.r, 0, Math.PI * 2);
ctx.fill();
}
ctx.restore();
}
function render(time, p) {
if (!L) {
return;
}
ctx.globalAlpha = 1;
ctx.fillStyle = BG;
ctx.fillRect(0, 0, vw, vh);
drawWord(0);
drawPanther(time, p);
drawMotes(time);
drawWord(L.pawLine);
}
function frame(now) {
requestAnimationFrame(frame);
var dt = Math.min(0.05, Math.max(0, (now - last) / 1000));
last = now;
if (P.reducedMotion) {
if (dirty) {
render(8.2, 0.42);
dirty = false;
}
return;
}
if (P.paused) {
if (dirty) {
render(clock, (clock / PERIOD) % 1);
dirty = false;
}
return;
}
clock += dt;
render(clock, (clock / PERIOD) % 1);
dirty = false;
}
window.addEventListener("resize", layout);
layout();
requestAnimationFrame(frame);
})();
</script>
</body>
</html>
Made by 6to9. Back to all motion patterns.