JIT
Grid - Untitled
Matrix digital rain reimagined as viscous liquid chrome and glowing green mercury. The data streams are melting and dripping like heavy syrup, splashing upon contact with the bottom frame. Ripples of neon code distorting the reality behind it. Fluid simulation, metallic texture, reflective surfaces, ray tracing, hypnotic flow, cinematic lighting.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Liquid Chrome Matrix</title> <style> body, html { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background-color: #010201; } canvas { display: block; position: absolute; top: 0; left: 0; filter: brightness(1.1); } </style> </head> <body> <canvas id="liquid-matrix-canvas"></canvas>
<script>
    const canvas = document.getElementById('liquid-matrix-canvas');
    const ctx = canvas.getContext('2d');

    let width, height;
    let streams = [];
    let particles = [];
    const fontSize = 20;
    const characters = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン0123456789';

    function resizeCanvas() {
        width = canvas.width = window.innerWidth;
        height = canvas.height = window.innerHeight;
        initializeStreams();
    }

    function initializeStreams() {
        streams = [];
        const columns = Math.ceil(width / fontSize);
        for (let i = 0; i < columns; i++) {
            streams.push(new Stream(i * fontSize));
        }
    }

    class Particle {
        constructor(x, y, color) {
            this.x = x;
            this.y = y;
            this.color = color;
            this.size = Math.random() * 3 + 1;
            this.vx = (Math.random() - 0.5) * 4;
            this.vy = (Math.random() - 0.5) * 4 - 2; // Initial upward push
            this.life = 100;
            this.gravity = 0.1;
        }

        update() {
            this.vy += this.gravity;
            this.x += this.vx;
            this.y += this.vy;
            this.life--;
        }

        draw() {
            ctx.globalAlpha = this.life / 100;
            ctx.fillStyle = this.color;
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
            ctx.fill();
        }
    }

    class Stream {
        constructor(x) {
            this.x = x;
            this.y = Math.random() * -height;
            this.speed = Math.random() * 2 + 0.5; // Slower, syrupy speed
            this.length = Math.floor(Math.random() * 20 + 10);
            this.symbols = [];
            this.isChrome = Math.random() > 0.5;
            this.createSymbols();
        }

        createSymbols() {
            for (let i = 0; i < this.length; i++) {
                const char = characters.charAt(Math.floor(Math.random() * characters.length));
                this.symbols.push({ char, yOffset: i * fontSize });
            }
        }

        update() {
            this.y += this.speed;
            if (this.y - this.length * fontSize > height) {
                this.y = Math.random() * -height;
                this.speed = Math.random() * 2 + 0.5;
            }
        }

        draw() {
            for (let i = 0; i < this.symbols.length; i++) {
                const symbol = this.symbols[i];
                const yPos = this.y - symbol.yOffset;

                if (yPos > height + fontSize || yPos < 0) continue;

                const opacity = 1 - (i / this.symbols.length);
                const isHead = (i === 0);

                if (this.isChrome) {
                    this.drawChromeSymbol(symbol.char, yPos, opacity, isHead);
                } else {
                    this.drawGreenSymbol(symbol.char, yPos, opacity, isHead);
                }
            }
            this.checkSplash();
        }

        drawChromeSymbol(char, y, opacity, isHead) {
            const gradient = ctx.createLinearGradient(this.x, y - fontSize, this.x, y);
            gradient.addColorStop(0, '#f0f0f0');
            gradient.addColorStop(0.3, '#ffffff');
            gradient.addColorStop(0.5, '#c0c0c0');
            gradient.addColorStop(0.7, '#f0f0f0');
            gradient.addColorStop(1, '#a0a0a0');
            
            ctx.fillStyle = gradient;
            ctx.globalAlpha = opacity * 0.9;
            if (isHead) {
                ctx.shadowColor = '#ffffff';
                ctx.shadowBlur = 10;
                ctx.globalAlpha = 1;
            }
            ctx.fillText(char, this.x, y);
            ctx.shadowBlur = 0; // Reset shadow
        }
        
        drawGreenSymbol(char, y, opacity, isHead) {
            const gradient = ctx.createLinearGradient(this.x, y - fontSize, this.x, y);
            gradient.addColorStop(0, '#afffba');
            gradient.addColorStop(0.3, '#00ff41');
            gradient.addColorStop(0.5, '#ffffff');
            gradient.addColorStop(0.7, '#00ff41');
            gradient.addColorStop(1, '#0c6b20');
            
            ctx.fillStyle = gradient;
            ctx.globalAlpha = opacity;
            if (isHead) {
                ctx.shadowColor = '#00ff41';
                ctx.shadowBlur = 15;
                ctx.globalAlpha = 1;
            }
            ctx.fillText(char, this.x, y);
            ctx.shadowBlur = 0; // Reset shadow
        }

        checkSplash() {
            const headY = this.y;
            if (headY > height && !this.splashed) {
                const splashCount = Math.floor(Math.random() * 10 + 5);
                const splashColor = this.isChrome ? '#c0c0c0' : '#00ff41';
                for (let i = 0; i < splashCount; i++) {
                    particles.push(new Particle(this.x + (Math.random() - 0.5) * fontSize, height, splashColor));
                }
                this.splashed = true; // Prevent multiple splashes per fall
            }
            if (headY < height) {
                this.splashed = false;
            }
        }
    }

    function animate() {
        // Draw a semi-transparent black rectangle for the fading trail effect
        ctx.fillStyle = 'rgba(1, 2, 1, 0.1)';
        ctx.fillRect(0, 0, width, height);

        ctx.font = `${fontSize}px monospace`;

        streams.forEach(stream => {
            stream.update();
            stream.draw();
        });

        // Update and draw particles
        for (let i = particles.length - 1; i >= 0; i--) {
            particles[i].update();
            particles[i].draw();
            if (particles[i].life <= 0) {
                particles.splice(i, 1);
            }
        }
        ctx.globalAlpha = 1.0; // Reset global alpha

        requestAnimationFrame(animate);
    }

    window.addEventListener('resize', resizeCanvas);

    resizeCanvas();
    animate();
</script>
</body> </html>
Updated files
v1