Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
<div class="auroraField"></div>
<div class="auroraBlob3"></div>
{% else %}
<div class="page-field"></div>
<canvas id="page-canvas" aria-hidden="true"></canvas>
{% endif %}
<div class="page-grain"></div>
{% if page.layout == 'post' %}
Expand Down
10 changes: 4 additions & 6 deletions assets/css/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,13 @@ body {
}

/* Ambient page background */
.page-field {
#page-canvas {
position: fixed;
inset: 0;
z-index: -2;
background:
radial-gradient(60% 55% at 12% 8%, rgba(29, 107, 176, 0.22), transparent 60%),
radial-gradient(50% 50% at 92% 0%, rgba(153, 204, 51, 0.10), transparent 55%),
radial-gradient(70% 60% at 80% 100%, rgba(0, 51, 102, 0.55), transparent 62%),
linear-gradient(180deg, var(--navy-950), var(--navy-900) 40%, var(--navy-950));
width: 100%;
height: 100%;
display: block;
}
.page-grain {
position: fixed;
Expand Down
125 changes: 125 additions & 0 deletions assets/js/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,131 @@
"use strict";
var reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

/* ---- Animated gradient background canvas ---- */
var canvas = document.getElementById("page-canvas");
if (canvas) {
var ctx = canvas.getContext("2d");

var spots = [
{
// blue — upper-left
cx: 0.12, cy: 0.08,
rx: 0.60, ry: 0.55,
color: "29,107,176", alpha: 0.22,
dx: 0.00007, dy: 0.00005,
drx: 0.00004, dry: 0.00003,
phase: 0
},
{
// lime — upper-right
cx: 0.92, cy: 0.00,
rx: 0.50, ry: 0.50,
color: "153,204,51", alpha: 0.10,
dx: -0.00006, dy: 0.00008,
drx: 0.00003, dry: 0.00004,
phase: 1.5
},
{
// deep-navy — lower-right
cx: 0.80, cy: 1.00,
rx: 0.70, ry: 0.60,
color: "0,51,102", alpha: 0.55,
dx: -0.00005, dy: -0.00006,
drx: 0.00005, dry: 0.00003,
phase: 3.0
}
];

// Store origin values on each spot for bounce reference
for (var si = 0; si < spots.length; si++) {
spots[si].ocx = spots[si].cx;
spots[si].ocy = spots[si].cy;
spots[si].orx = spots[si].rx;
spots[si].ory = spots[si].ry;
}

// Travel bounds for center position (fraction of viewport)
var DRIFT = 0.12;
// Pulse amplitude (fraction of base radius)
var PULSE = 0.18;

function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resize();
window.addEventListener("resize", resize, { passive: true });

var then = 0;
var raf = null;
function draw(now) {
var dt = now - then;
then = now;

var W = canvas.width;
var H = canvas.height;

// Navy base fill
ctx.fillStyle = "#000d18";
ctx.fillRect(0, 0, W, H);

for (var i = 0; i < spots.length; i++) {
var s = spots[i];

if (!reduce) {
s.phase += dt * 0.0004;
// Drift center — oscillate around original cx/cy
s.cx += s.dx;
s.cy += s.dy;
// Bounce drift within range
if (Math.abs(s.cx - s.ocx) > DRIFT) s.dx *= -1;
if (Math.abs(s.cy - s.ocy) > DRIFT) s.dy *= -1;
// Pulse radius
s.rx += s.drx;
s.ry += s.dry;
if (Math.abs(s.rx - s.orx) > PULSE * s.orx) s.drx *= -1;
if (Math.abs(s.ry - s.ory) > PULSE * s.ory) s.dry *= -1;
}

var px = s.cx * W;
var py = s.cy * H;
var rw = s.rx * W;
var rh = s.ry * H;
var r = Math.max(rw, rh);

if (r <= 0) continue;

// Draw as ellipse via scale transform
ctx.save();
ctx.translate(px, py);
ctx.scale(rw / r, rh / r);
var grad = ctx.createRadialGradient(0, 0, 0, 0, 0, r);
grad.addColorStop(0, "rgba(" + s.color + "," + s.alpha + ")");
grad.addColorStop(1, "rgba(" + s.color + ",0)");
ctx.fillStyle = grad;
ctx.beginPath();
ctx.arc(0, 0, r, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}

raf = requestAnimationFrame(draw);
}

document.addEventListener("visibilitychange", function () {
if (document.hidden) {
cancelAnimationFrame(raf);
raf = null;
} else if (!raf) {
then = performance.now();
raf = requestAnimationFrame(draw);
}
});

then = performance.now();
raf = requestAnimationFrame(draw);
}

/* ---- Nav: frost on scroll ---- */
var nav = document.querySelector("[data-nav]");
if (nav) {
Expand Down