<div id=”animated-bg”>
<canvas id=”bgCanvas”></canvas>
</div>

<style>
#animated-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
pointer-events: none;
/* ===== CHANGE BACKGROUND GRADIENT COLORS HERE ===== */
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 100%);
/* First color: #0a0a0a (dark black) */
/* Second color: #1a1a2e (dark blue-grey) */
/* =================================================== */
}

#bgCanvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>

<script>
const canvas = document.getElementById(‘bgCanvas’);
const ctx = canvas.getContext(‘2d’);

// Set canvas size
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener(‘resize’, resizeCanvas);

// ===== CHANGE MAIN ACCENT COLOR HERE =====
// This color affects: particles, connecting lines, grid lines, and code symbols
const mainColor = ‘#3b82f6’; // Blue – change to any hex color
// Examples: ‘#8b5cf6’ (purple), ‘#06b6d4’ (cyan), ‘#10b981’ (green),
// ‘#ec4899’ (pink), ‘#f59e0b’ (amber), ‘#ef4444’ (red)
// ==========================================

// Particle system
class Particle {
constructor() {
this.reset();
}

reset() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.size = Math.random() * 2 + 0.5;
this.speedX = (Math.random() – 0.5) * 0.3;
this.speedY = (Math.random() – 0.5) * 0.3;
this.opacity = Math.random() * 0.3 + 0.1;
}

update() {
this.x += this.speedX;
this.y += this.speedY;

if (this.x < 0 || this.x > canvas.width || this.y < 0 || this.y > canvas.height) {
this.reset();
}
}

draw() {
ctx.fillStyle = `rgba(${hexToRgb(mainColor)}, ${this.opacity})`;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
}

// Grid lines
class GridLine {
constructor(isVertical) {
this.isVertical = isVertical;
this.reset();
}

reset() {
if (this.isVertical) {
this.x = Math.random() * canvas.width;
this.progress = 0;
} else {
this.y = Math.random() * canvas.height;
this.progress = 0;
}
this.speed = Math.random() * 0.002 + 0.001;
this.opacity = Math.random() * 0.1 + 0.05;
}

update() {
this.progress += this.speed;
if (this.progress > 1) {
this.reset();
}
}

draw() {
ctx.strokeStyle = `rgba(${hexToRgb(mainColor)}, ${this.opacity})`;
ctx.lineWidth = 1;
ctx.beginPath();

if (this.isVertical) {
const height = canvas.height * this.progress;
ctx.moveTo(this.x, 0);
ctx.lineTo(this.x, height);
} else {
const width = canvas.width * this.progress;
ctx.moveTo(0, this.y);
ctx.lineTo(width, this.y);
}

ctx.stroke();
}
}

// Floating code symbols
class CodeSymbol {
constructor() {
this.symbols = [‘<‘, ‘>’, ‘{‘, ‘}’, ‘/’, ‘·’, ‘–’];
this.reset();
}

reset() {
this.x = Math.random() * canvas.width;
this.y = canvas.height + 50;
this.symbol = this.symbols[Math.floor(Math.random() * this.symbols.length)];
this.speed = Math.random() * 0.3 + 0.2;
this.opacity = Math.random() * 0.15 + 0.05;
this.size = Math.random() * 12 + 8;
this.drift = (Math.random() – 0.5) * 0.2;
}

update() {
this.y -= this.speed;
this.x += this.drift;

if (this.y < -50) {
this.reset();
}
}

draw() {
ctx.fillStyle = `rgba(${hexToRgb(mainColor)}, ${this.opacity})`;
ctx.font = `${this.size}px monospace`;
ctx.fillText(this.symbol, this.x, this.y);
}
}

// Helper function to convert hex to RGB
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ?
`${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}` :
’59, 130, 246′;
}

// Create particles, grid lines, and symbols
const particles = Array.from({length: 60}, () => new Particle());
const gridLines = [
…Array.from({length: 8}, () => new GridLine(true)),
…Array.from({length: 8}, () => new GridLine(false))
];
const codeSymbols = Array.from({length: 12}, () => new CodeSymbol());

// Animation loop
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Draw and update grid lines
gridLines.forEach(line => {
line.update();
line.draw();
});

// Draw and update particles
particles.forEach(particle => {
particle.update();
particle.draw();
});

// Connect nearby particles
for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
const dx = particles[i].x – particles[j].x;
const dy = particles[i].y – particles[j].y;
const distance = Math.sqrt(dx * dx + dy * dy);

if (distance < 120) {
const opacity = (1 – distance / 120) * 0.15;
ctx.strokeStyle = `rgba(${hexToRgb(mainColor)}, ${opacity})`;
ctx.lineWidth = 0.5;
ctx.beginPath();
ctx.moveTo(particles[i].x, particles[i].y);
ctx.lineTo(particles[j].x, particles[j].y);
ctx.stroke();
}
}
}

// Draw and update code symbols
codeSymbols.forEach(symbol => {
symbol.update();
symbol.draw();
});

requestAnimationFrame(animate);
}

animate();
</script>