// Based on Flame by:
// Created by anatole duprat - XT95/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.


<style>
    /* Target Confluence's main content area */
    #main-content, 
    .wiki-content,
    .contentLayout2,
    .cell,
    #content {
        position: relative !important;
    }

    /* Make the background div cover the entire content area */
    #flameBackground {
        position: absolute !important;
        top: 0 !important;
        left: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        width: 100% !important;
        height: 100% !important;
        z-index: 0 !important;
        pointer-events: none !important;
    }

    #flameCanvas {
        width: 100%;
        height: 100%;
        display: block;
    }

    /* Ensure actual page content is rendered on top */
    .wiki-content > *:not(#flameBackground),
    .contentLayout2 > *:not(#flameBackground) {
        position: relative;
        z-index: 1;
    }

    /* Text readability */
    .wiki-content h1,
    .wiki-content h2,
    .wiki-content h3,
    .wiki-content p {
        text-shadow: 0 2px 8px rgba(0,0,0,0.7);
    }
</style>

<div id="flameBackground">
    <canvas id="flameCanvas"></canvas>
</div>

<script>
(function() {
    const canvas = document.getElementById('flameCanvas');
    if (!canvas) return;

    // Максимальное качество контекста
    const gl = canvas.getContext('webgl', { 
        antialias: true,           // Включено сглаживание
        alpha: true,
        depth: false,
        stencil: false,
        powerPreference: 'high-performance' // Требуем макс. производительность от GPU
    }) || canvas.getContext('experimental-webgl');
    
    if (!gl) return;
    
    const maxSteps = 64; // Максимум шагов для детализации
    const resolutionScale = 1.0; // 100% разрешение

    const vertexShaderSource = `
        attribute vec2 position;
        void main() {
            gl_Position = vec4(position, 0.0, 1.0);
        }
    `;

    const fragmentShaderSource = `
        precision highp float; // Высокая точность вычислений
        uniform vec2 iResolution;
        uniform float iTime;
        uniform int maxSteps;

        float noise(vec3 p) {
            vec3 i = floor(p);
            vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.);
            vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5;
            a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x);
            a.xy = mix(a.xz, a.yw, f.y);
            return mix(a.x, a.y, f.z);
        }

        float sphere(vec3 p, vec4 spr) {
            return length(spr.xyz-p) - spr.w;
        }

        float flame(vec3 p) {
            float d = sphere(p*vec3(1.,.5,1.), vec4(.0,-1.,.0,1.));
            return d + (noise(p+vec3(.0,iTime*2.,.0)) + noise(p*3.)*.5)*.25*(p.y);
        }

        float scene(vec3 p) {
            return min(100.-length(p), abs(flame(p)));
        }

        vec4 raymarch(vec3 org, vec3 dir) {
            float d = 0.0, glow = 0.0, eps = 0.02;
            vec3 p = org;
            bool glowed = false;
            
            // Цикл отрисовки
            for(int i=0; i<64; i++) {
                if(i >= maxSteps) break;
                d = scene(p) + eps;
                p += d * dir;
                if(d > eps) {
                    if(flame(p) < .0) glowed = true;
                    if(glowed) glow = float(i)/float(maxSteps);
                }
            }
            return vec4(p, glow);
        }

        void main() {
            vec2 fragCoord = gl_FragCoord.xy;
            vec2 v = -1.0 + 2.0 * fragCoord.xy / iResolution.xy;
            v.x *= iResolution.x/iResolution.y;
            vec3 org = vec3(0., -2., 14.);
            vec3 dir = normalize(vec3(v.x*1.6, -v.y, -1.5));
            vec4 p = raymarch(org, dir);
            float glow = p.w;
            vec4 col = mix(vec4(1.,.5,.1,1.), vec4(0.1,.5,1.,1.), p.y*.02+.4);
            gl_FragColor = mix(vec4(0.), col, pow(glow*2., 4.));
        }
    `;

    function compileShader(source, type) {
        const shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            console.error('Shader compile error:', gl.getShaderInfoLog(shader));
            gl.deleteShader(shader);
            return null;
        }
        return shader;
    }

    const vs = compileShader(vertexShaderSource, gl.VERTEX_SHADER);
    const fs = compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER);
    if (!vs || !fs) return;

    const program = gl.createProgram();
    gl.attachShader(program, vs);
    gl.attachShader(program, fs);
    gl.linkProgram(program);
    
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.error('Program link error:', gl.getProgramInfoLog(program));
        return;
    }
    
    gl.useProgram(program);

    const buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1,1,-1,-1,1,1,1]), gl.STATIC_DRAW);

    const pos = gl.getAttribLocation(program, 'position');
    gl.enableVertexAttribArray(pos);
    gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);

    const iRes = gl.getUniformLocation(program, 'iResolution');
    const iTime = gl.getUniformLocation(program, 'iTime');
    const maxStepsUniform = gl.getUniformLocation(program, 'maxSteps');
    
    gl.uniform1i(maxStepsUniform, maxSteps);

    function resize() {
        const container = canvas.parentElement;
        if (!container) return;
        const rect = container.getBoundingClientRect();
        
        const displayWidth = rect.width || window.innerWidth;
        const displayHeight = rect.height || window.innerHeight;
        
        // Установка полного разрешения без масштабирования
        canvas.width = Math.floor(displayWidth * resolutionScale);
        canvas.height = Math.floor(displayHeight * resolutionScale);

        gl.viewport(0, 0, canvas.width, canvas.height);
    }
    
    // Вставка фона в контент
    setTimeout(function() {
        const bg = document.getElementById('flameBackground');
        const content = document.querySelector('.wiki-content') || 
                       document.querySelector('#main-content') ||
                       document.querySelector('.contentLayout2') ||
                       document.querySelector('#content');
        if (content && bg) {
            content.insertBefore(bg, content.firstChild);
            resize();
        }
    }, 100);

    window.addEventListener('resize', resize);
    
    const start = Date.now();
    let animationId = null;
    let isPageVisible = true;
    
    // Остановка только если вкладка полностью скрыта (стандарт браузера)
    document.addEventListener('visibilitychange', function() {
        isPageVisible = !document.hidden;
        if (isPageVisible && !animationId) {
            animationId = requestAnimationFrame(render);
        }
    });
    
    function render() {
        if (!isPageVisible || gl.isContextLost()) {
            animationId = null;
            return;
        }
        
        // Рендер без ограничения FPS - максимальная плавность
        gl.uniform2f(iRes, canvas.width, canvas.height);
        gl.uniform1f(iTime, (Date.now() - start) / 1000);
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        
        animationId = requestAnimationFrame(render);
    }

    animationId = requestAnimationFrame(render);
    
    // Очистка при удалении элемента
    if (window.MutationObserver) {
        const observer = new MutationObserver(function(mutations) {
            if (!document.body.contains(canvas)) {
                if (animationId) {
                    cancelAnimationFrame(animationId);
                    animationId = null;
                }
                observer.disconnect();
            }
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }
})();
</script>


Если станет холодно на просторах вселенной - наш огонь согреет.

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。

。゚•┈୨♡୧┈•゚。