<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spinning Donut</title>
    <style>
        body {
            background-color: black;
            color: white;
            font-family: monospace;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }
        pre {
            line-height: 1;
            font-size: 12px;
        }
    </style>
</head>
<body>
    <pre id="donut"></pre>
    <script>
        const renderDonut = () => {
            let A = 0, B = 0;
            const donutElement = document.getElementById('donut');

            const drawFrame = () => {
                const z = Array(1760).fill(0);
                const b = Array(1760).fill(' ');

                for (let j = 0; j < 6.28; j += 0.07) {
                    for (let i = 0; i < 6.28; i += 0.02) {
                        const sini = Math.sin(i),
                              cosi = Math.cos(i),
                              sinj = Math.sin(j),
                              cosj = Math.cos(j),
                              sinA = Math.sin(A),
                              cosA = Math.cos(A),
                              sinB = Math.sin(B),
                              cosB = Math.cos(B),
                              cosj2 = cosj + 2,
                              denom = sini * cosj2 * sinA + sinj * cosA + 5;

                        if (denom === 0) continue;

                        const mess = 1 / denom,
                              t = sini * cosj2 * cosA - sinj * sinA;
                        const x = Math.floor(40 + 30 * mess * (cosi * cosj2 * cosB - t * sinB));
                        const y = Math.floor(12 + 15 * mess * (cosi * cosj2 * sinB + t * cosB));
                        const o = x + 80 * y;
                        const N = Math.floor(
                            8 * ((sinj * sinA - sini * cosj * cosA) * cosB -
                                sini * cosj * sinA - sinj * cosA - cosi * cosj * sinB)
                        );

                        if (y >= 0 && y < 22 && x >= 0 && x < 80 && mess > z[o]) {
                            z[o] = mess;
                            b[o] = ".,-~:;=!*#$@"[Math.max(0, Math.min(11, N))];
                        }
                    }
                }

                let output = '';
                for (let k = 0; k < 1760; k++) {
                    output += k % 80 ? b[k] : '\n';
                }
                donutElement.textContent = output;
            };

            setInterval(() => {
                drawFrame();
                A += 0.04;
                B += 0.02;
            }, 50);
        };

        renderDonut();
    </script>
</body>
</html>