/**
 * Animated tab favicon — browsers ignore CSS/SMIL on static favicon files,
 * so we paint frames to canvas and update link[rel=icon] (Cursor-style shimmer).
 */
(function () {
    if (typeof document === 'undefined') return;
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;

    const SIZE = 32;
    const canvas = document.createElement('canvas');
    canvas.width = SIZE;
    canvas.height = SIZE;
    const ctx = canvas.getContext('2d', { alpha: true });
    if (!ctx) return;

    const C1 = [99, 102, 241];
    const C2 = [139, 92, 246];
    const scale = SIZE / 48;
    const radius = Math.max(2, 10 * scale);

    function lerp(a, b, t) {
        return a + (b - a) * t;
    }

    function lerpRgb(t) {
        return [
            Math.round(lerp(C1[0], C2[0], t)),
            Math.round(lerp(C1[1], C2[1], t)),
            Math.round(lerp(C1[2], C2[2], t)),
        ];
    }

    function roundRectPath(x, y, w, h, r) {
        const rr = Math.min(r, w / 2, h / 2);
        ctx.beginPath();
        ctx.moveTo(x + rr, y);
        ctx.arcTo(x + w, y, x + w, y + h, rr);
        ctx.arcTo(x + w, y + h, x, y + h, rr);
        ctx.arcTo(x, y + h, x, y, rr);
        ctx.arcTo(x, y, x + w, y, rr);
        ctx.closePath();
    }

    function clipTile() {
        roundRectPath(0, 0, SIZE, SIZE, radius);
        ctx.clip();
    }

    function drawWave(cx, cy, rx, ry, baseOp, phaseMs, phaseOff) {
        const pulse = 0.5 + 0.5 * Math.sin((phaseMs / 2600 + phaseOff) * Math.PI * 2);
        const op = baseOp * (0.35 + 0.65 * pulse);
        ctx.strokeStyle = `rgba(255,255,255,${op.toFixed(3)})`;
        ctx.lineWidth = Math.max(1, 1.8 * scale);
        ctx.beginPath();
        ctx.ellipse(cx, cy, rx, ry, 0, Math.PI * 0.5, Math.PI * 1.5);
        ctx.stroke();
    }

    function drawBar(x, y, w, h, baseOp, phaseMs, phaseOff) {
        const pulse = 0.5 + 0.5 * Math.sin((phaseMs / 950 + phaseOff) * Math.PI * 2);
        const sh = 0.5 + 0.5 * pulse;
        const bh = h * sh;
        const by = y + (h - bh);
        ctx.fillStyle = `rgba(255,255,255,${(baseOp * (0.72 + 0.28 * pulse)).toFixed(3)})`;
        roundRectPath(x * scale, by * scale, w * scale, bh * scale, Math.max(0.5, scale));
        ctx.fill();
    }

    function drawFrame(ms) {
        ctx.setTransform(1, 0, 0, 1, 0, 0);
        ctx.clearRect(0, 0, SIZE, SIZE);

        const gradT = (ms / 7000) % 1;
        const g = ctx.createLinearGradient(0, 0, SIZE, SIZE);
        const rgbA = lerpRgb((gradT * 0.35) % 1);
        const rgbB = lerpRgb((gradT * 0.35 + 0.55) % 1);
        g.addColorStop(0, `rgb(${rgbA[0]},${rgbA[1]},${rgbA[2]})`);
        g.addColorStop(1, `rgb(${rgbB[0]},${rgbB[1]},${rgbB[2]})`);
        roundRectPath(0, 0, SIZE, SIZE, radius);
        ctx.fillStyle = g;
        ctx.fill();

        ctx.save();
        clipTile();

        const shimmerT = (ms / 3400) % 1;
        const sx = lerp(-SIZE * 1.2, SIZE * 1.4, shimmerT);
        ctx.save();
        ctx.translate(sx, 0);
        ctx.rotate((14 * Math.PI) / 180);
        const sh = ctx.createLinearGradient(-SIZE, 0, SIZE, 0);
        sh.addColorStop(0, 'rgba(255,255,255,0)');
        sh.addColorStop(0.5, 'rgba(255,255,255,0.38)');
        sh.addColorStop(1, 'rgba(255,255,255,0)');
        ctx.fillStyle = sh;
        ctx.fillRect(-SIZE * 2, -SIZE, SIZE * 4, SIZE * 3);
        ctx.restore();

        ctx.lineCap = 'round';
        drawWave(17 * scale, 24 * scale, 7.5 * scale, 13 * scale, 0.3, ms, 0);
        drawWave(20 * scale, 24 * scale, 5 * scale, 8 * scale, 0.55, ms, 0.22);
        drawWave(21.5 * scale, 24 * scale, 2.5 * scale, 4 * scale, 0.9, ms, 0.44);

        drawBar(31, 20, 2, 8, 0.95, ms, 0);
        drawBar(36, 16, 2, 16, 1, ms, 0.14);
        drawBar(41, 22, 2, 4, 0.75, ms, 0.28);

        const corePulse = 1 + 0.18 * Math.sin((ms / 2200) * Math.PI * 2);
        ctx.fillStyle = '#ffffff';
        ctx.beginPath();
        ctx.arc(23 * scale, 24 * scale, 1.4 * scale * corePulse, 0, Math.PI * 2);
        ctx.fill();

        ctx.restore();
    }

    let iconLink = document.getElementById('favicon-anim');
    if (!iconLink) {
        iconLink = document.createElement('link');
        iconLink.id = 'favicon-anim';
        iconLink.rel = 'icon';
        iconLink.type = 'image/png';
        iconLink.sizes = '32x32';
        document.head.appendChild(iconLink);
    }

    const t0 = performance.now();
    let lastPaint = 0;
    const FRAME_MS = 90;

    function tick(now) {
        if (now - lastPaint >= FRAME_MS) {
            drawFrame(now - t0);
            iconLink.href = canvas.toDataURL('image/png');
            lastPaint = now;
        }
        if (!document.hidden) requestAnimationFrame(tick);
        else pending = true;
    }

    let pending = false;
    document.addEventListener('visibilitychange', () => {
        if (!document.hidden && pending) {
            pending = false;
            requestAnimationFrame(tick);
        }
    });

    drawFrame(0);
    iconLink.href = canvas.toDataURL('image/png');
    requestAnimationFrame(tick);
})();
