precision highp float;

uniform vec2 resolution;
uniform float time;
#define audioLevel (0.5 + 0.5 * sin(time * 2.0))
#define audioLow (0.5 + 0.5 * sin(time * 1.3))
#define audioMid (0.5 + 0.5 * sin(time * 3.7))
#define audioHigh (0.5 + 0.5 * sin(time * 5.1))

#define PI 3.14159265359
#define TAU (2.0 * PI)
#define MAX_STEPS 128
#define MAX_DIST 50.0
#define SURF_DIST 0.001

mat2 rot(float a) {
    float c = cos(a), s = sin(a);
    return mat2(c, s, -s, c);
}

vec3 hsv(float h, float s, float v) {
    vec3 c = vec3(h, h + 2.0/3.0, h + 1.0/3.0);
    c = fract(c) * 6.0 - 3.0;
    c = abs(c) - 1.0;
    c = clamp(c, 0.0, 1.0);
    return mix(vec3(1.0), c, s) * v;
}

float hash(vec2 p) {
    return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}

float hash13(vec3 p) {
    p = fract(p * 0.1031);
    p += dot(p, p.yzx + 33.33);
    return fract((p.x + p.y) * p.z);
}

float noise(vec3 p) {
    vec3 i = floor(p);
    vec3 f = fract(p);
    f = f * f * (3.0 - 2.0 * f);

    return mix(mix(mix(hash13(i), hash13(i + vec3(1,0,0)), f.x),
                   mix(hash13(i + vec3(0,1,0)), hash13(i + vec3(1,1,0)), f.x), f.y),
               mix(mix(hash13(i + vec3(0,0,1)), hash13(i + vec3(1,0,1)), f.x),
                   mix(hash13(i + vec3(0,1,1)), hash13(i + vec3(1,1,1)), f.x), f.y), f.z);
}

float fbm(vec3 p) {
    float value = 0.0;
    float amplitude = 0.5;
    for (int i = 0; i < 6; i++) {
        value += amplitude * noise(p);
        p *= 2.0;
        amplitude *= 0.5;
    }
    return value;
}

float sdBox(vec2 p, vec2 b) {
    vec2 d = abs(p) - b;
    return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
}

float sdBox3D(vec3 p, vec3 b) {
    vec3 q = abs(p) - b;
    return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}

float sdSphere(vec3 p, float r) {
    return length(p) - r;
}

float sdTorus(vec3 p, vec2 t) {
    vec2 q = vec2(length(p.xz) - t.x, p.y);
    return length(q) - t.y;
}

float sdS(vec2 p) {
    float d = 1e10;
    float t = 0.03;
    d = min(d, sdBox(p - vec2(0.0, 0.15), vec2(0.11, t)));
    d = min(d, sdBox(p - vec2(-0.08, 0.10), vec2(t, 0.08)));
    d = min(d, sdBox(p - vec2(0.0, 0.0), vec2(0.11, t)));
    d = min(d, sdBox(p - vec2(0.08, -0.10), vec2(t, 0.08)));
    d = min(d, sdBox(p - vec2(0.0, -0.15), vec2(0.11, t)));
    return d;
}

float sdE(vec2 p) {
    float d = 1e10;
    float t = 0.03;
    d = min(d, sdBox(p - vec2(-0.08, 0.0), vec2(t, 0.18)));
    d = min(d, sdBox(p - vec2(0.0, 0.15), vec2(0.11, t)));
    d = min(d, sdBox(p - vec2(0.0, 0.0), vec2(0.08, t)));
    d = min(d, sdBox(p - vec2(0.0, -0.15), vec2(0.11, t)));
    return d;
}

float sdI(vec2 p) {
    return sdBox(p, vec2(0.03, 0.18));
}

float sdO(vec2 p) {
    return abs(sdBox(p, vec2(0.1, 0.15))) - 0.03;
}

float sdN(vec2 p) {
    float d = 1e10;
    float t = 0.03;
    d = min(d, sdBox(p - vec2(-0.08, 0.0), vec2(t, 0.18)));
    d = min(d, sdBox(p - vec2(0.08, 0.0), vec2(t, 0.18)));
    vec2 rotP = (p - vec2(0.0, 0.0)) * rot(0.45);
    d = min(d, sdBox(rotP, vec2(t * 1.2, 0.18)));
    return d;
}

float drawSESSIONS(vec2 p) {
    float d = 1e10;
    float spacing = 0.25;
    float offset = -spacing * 3.25;
    d = min(d, sdS(p - vec2(offset, 0.0))); offset += spacing;
    d = min(d, sdE(p - vec2(offset, 0.0))); offset += spacing;
    d = min(d, sdS(p - vec2(offset, 0.0))); offset += spacing;
    d = min(d, sdS(p - vec2(offset, 0.0))); offset += 0.17;
    d = min(d, sdI(p - vec2(offset, 0.0))); offset += 0.19;
    d = min(d, sdO(p - vec2(offset, 0.0))); offset += 0.27;
    d = min(d, sdN(p - vec2(offset, 0.0))); offset += spacing;
    d = min(d, sdS(p - vec2(offset, 0.0)));
    return d;
}

// Snowflake SDF with 6-fold symmetry
float sdSnowflake(vec2 p, float size) {
    // Apply 6-fold radial symmetry
    float a = atan(p.y, p.x);
    float r = length(p);
    a = mod(a, PI / 3.0) - PI / 6.0;
    p = vec2(cos(a), sin(a)) * r;

    float d = 1e10;
    float w = size * 0.08;  // branch width

    // Main branch
    d = min(d, sdBox(p - vec2(size * 0.4, 0.0), vec2(size * 0.4, w)));

    // Side branches at different positions
    vec2 p1 = p - vec2(size * 0.5, 0.0);
    p1 *= rot(PI / 4.0);
    d = min(d, sdBox(p1, vec2(size * 0.15, w * 0.8)));

    vec2 p2 = p - vec2(size * 0.5, 0.0);
    p2 *= rot(-PI / 4.0);
    d = min(d, sdBox(p2, vec2(size * 0.15, w * 0.8)));

    vec2 p3 = p - vec2(size * 0.3, 0.0);
    p3 *= rot(PI / 3.5);
    d = min(d, sdBox(p3, vec2(size * 0.12, w * 0.7)));

    vec2 p4 = p - vec2(size * 0.3, 0.0);
    p4 *= rot(-PI / 3.5);
    d = min(d, sdBox(p4, vec2(size * 0.12, w * 0.7)));

    // Center hexagon
    float hexA = atan(p.y, p.x);
    float hexR = length(p);
    hexA = mod(hexA, TAU / 6.0) - TAU / 12.0;
    float hexD = hexR * cos(hexA) - size * 0.15;
    d = min(d, hexD);

    return d;
}

// Mandelbulb distance estimator
float sdMandelbulb(vec3 pos) {
    vec3 z = pos;
    float dr = 1.0;
    float r = 0.0;
    float power = 8.0 + audioLow * 4.0;

    for (int i = 0; i < 8; i++) {
        r = length(z);
        if (r > 2.0) break;

        float theta = acos(z.z / r);
        float phi = atan(z.y, z.x);
        dr = pow(r, power - 1.0) * power * dr + 1.0;

        float zr = pow(r, power);
        theta = theta * power;
        phi = phi * power;

        z = zr * vec3(sin(theta) * cos(phi), sin(phi) * sin(theta), cos(theta));
        z += pos;
    }
    return 0.5 * log(r) * r / dr;
}

// Menger sponge
float sdMenger(vec3 p) {
    float d = sdBox3D(p, vec3(1.0));
    float s = 1.0;
    for (int m = 0; m < 3; m++) {
        vec3 a = mod(p * s, 2.0) - 1.0;
        s *= 3.0;
        vec3 r = abs(1.0 - 3.0 * abs(a));
        float da = max(r.x, r.y);
        float db = max(r.y, r.z);
        float dc = max(r.z, r.x);
        float c = (min(da, min(db, dc)) - 1.0) / s;
        d = max(d, c);
    }
    return d;
}

// Scene distance function
float sdScene(vec3 p, float sceneTime) {
    float d = 1e10;

    // Rotating and morphing shapes
    vec3 q = p;
    q.xz *= rot(sceneTime * 0.3 + audioMid * 2.0);
    q.yz *= rot(sceneTime * 0.5 + audioHigh * 1.5);

    // Mandelbulb
    d = min(d, sdMandelbulb(q * 2.0) * 0.5);

    // Repeating spheres
    vec3 s = p;
    s.x = mod(s.x + 1.0, 2.0) - 1.0;
    s.z = mod(s.z + 1.0, 2.0) - 1.0;
    d = min(d, sdSphere(s, 0.3 + audioLevel * 0.2));

    return d;
}

vec3 getNormal(vec3 p, float sceneTime) {
    float d = sdScene(p, sceneTime);
    vec2 e = vec2(0.001, 0.0);
    vec3 n = d - vec3(
        sdScene(p - e.xyy, sceneTime),
        sdScene(p - e.yxy, sceneTime),
        sdScene(p - e.yyx, sceneTime)
    );
    return normalize(n);
}

float rayMarch(vec3 ro, vec3 rd, float sceneTime) {
    float dO = 0.0;
    for (int i = 0; i < MAX_STEPS; i++) {
        vec3 p = ro + rd * dO;
        float dS = sdScene(p, sceneTime);
        dO += dS;
        if (dO > MAX_DIST || abs(dS) < SURF_DIST) break;
    }
    return dO;
}

void main() {
    // Scene management: 7 scenes × 10 seconds = 70 seconds loop
    float worldTime = mod(time, 70.0);

    float TIME = 0.0;
    float SAM = 0.0;
    int sceneID = -1;

    for (int i = 0; i < 7; i++) {
        TIME = max(TIME, (1.0 - step(SAM + 10.0, worldTime)) * (worldTime - SAM));
        sceneID += int(step(SAM, worldTime));
        SAM += 10.0;
    }

    vec2 uv = (gl_FragCoord.xy * 2.0 - resolution) / resolution.y;
    vec2 originalUV = uv;
    vec3 col = vec3(0.0);

    // === Scene 0: Fractal Tunnel with Wave ===
    if (sceneID == 0) {
        vec2 p = uv;
        float zoom = TIME * 0.5 + audioLow * 2.0;

        for (int i = 0; i < 20; i++) {
            p = abs(p) / dot(p, p) - vec2(0.9 + audioMid * 0.2, 1.0 + audioHigh * 0.3);
        }

        float hue = length(p) * 0.1 + TIME * 0.1 + audioLevel * 0.3;
        col = hsv(hue, 0.8, 1.0) * (1.0 + audioLevel);

        // SESSIONS overlay with wave effect
        float wave = sin(uv.x * 3.0 + TIME * 2.0 + audioMid * 3.0) * (0.02 + audioHigh * 0.05);
        vec2 waveUV = uv - vec2(0.0, wave);
        float scale = 1.5 - audioLow * 0.2;
        float d = drawSESSIONS(waveUV / scale) * scale;

        vec3 sessColor = hsv(hue + 0.5, 0.8, 1.0);
        vec3 glow = sessColor * (0.03 / (abs(d) + 0.03));
        col += glow * (0.6 + audioLevel * 0.4);
        col = mix(col, sessColor, smoothstep(0.02, 0.0, d) * 0.5);
    }

    // === Scene 1: Volumetric Raymarch with Rainbow Wave ===
    else if (sceneID == 1) {
        vec3 ro = vec3(0.0, 0.0, -3.0 + sin(TIME * 0.3) * 2.0);
        vec3 rd = normalize(vec3(uv, 1.0));

        float d = rayMarch(ro, rd, TIME);

        if (d < MAX_DIST) {
            vec3 p = ro + rd * d;
            vec3 n = getNormal(p, TIME);

            vec3 lightPos = vec3(sin(TIME), 2.0, cos(TIME)) * 3.0;
            vec3 lightDir = normalize(lightPos - p);
            float diff = max(dot(n, lightDir), 0.0);

            float hue = 0.5 + sin(p.y * 2.0 + TIME) * 0.3 + audioLevel * 0.2;
            vec3 baseColor = hsv(hue, 0.7, 0.9);

            col = baseColor * (diff + 0.3);
            col += pow(max(dot(reflect(rd, n), lightDir), 0.0), 32.0) * audioHigh;

            // Fog
            col = mix(col, vec3(0.0), 1.0 - exp(-d * 0.05));
        }

        // SESSIONS overlay with rainbow wave
        float bigWave = sin(TIME * 1.5 + audioLow * 2.0) * (0.15 + audioMid * 0.1);
        vec2 waveUV = uv - vec2(0.0, bigWave);
        float scale = 1.2 - audioLevel * 0.2;
        float sessD = drawSESSIONS(waveUV / scale) * scale;

        float hue = TIME * 0.15 + uv.x * 0.3 + audioLevel * 0.3;
        vec3 sessGlow = hsv(hue, 0.8, 1.0) * (0.04 / (abs(sessD) + 0.04));
        col += sessGlow * (0.7 + audioHigh * 0.5);
        col = mix(col, hsv(hue, 0.8, 1.0), smoothstep(0.02, 0.0, sessD) * 0.3);
    }

    // === Scene 2: Snowflake Storm with Glitch ===
    else if (sceneID == 2) {
        // Glitch effect on UV
        vec2 glitchUV = uv;
        float glitchTime = floor(TIME * 8.0) / 8.0;
        float glitchStrength = audioHigh * 0.5;

        if (fract(glitchTime * 3.0) > 0.7 - glitchStrength) {
            float sliceY = floor(uv.y * 15.0) / 15.0;
            if (hash(vec2(sliceY, glitchTime)) > 0.7 - audioLevel * 0.3) {
                glitchUV.x += (hash(vec2(sliceY * 10.0, glitchTime)) - 0.5) * (0.2 + audioHigh * 0.3);
            }
        }

        for (float i = 0.0; i < 100.0; i++) {
            float seed = i * 0.1;
            vec3 pos = vec3(
                sin(TIME * 0.5 + seed * 10.0) * 2.0,
                cos(TIME * 0.7 + seed * 8.0) * 2.0,
                mod(TIME * 0.3 + seed * 5.0, 4.0) - 2.0
            );

            pos.xy += vec2(cos(seed * 50.0), sin(seed * 50.0)) * audioMid;

            vec2 screenPos = pos.xy / (pos.z + 3.0);
            vec2 localUV = (uv - screenPos) * (pos.z + 3.0);

            // Rotate each snowflake
            float rotation = TIME * 0.3 + seed * TAU;
            localUV *= rot(rotation);

            float size = 0.08 + audioHigh * 0.06;
            float snowflakeDist = sdSnowflake(localUV, size);

            // Blue-biased hue (cyan to blue range: 0.6-0.66)
            float hue = 0.62 + seed * 0.02 + TIME * 0.01 + audioLevel * 0.02;

            // Core snowflake with higher saturation for blue tint
            col += hsv(hue, 0.9, 1.0) * smoothstep(0.005, 0.0, snowflakeDist) * (1.0 + audioLevel * 2.0);

            // Glow with bright cyan shift
            col += hsv(hue + 0.03, 0.85, 0.8) * exp(-snowflakeDist * 20.0) * audioHigh * 0.5;
        }

        // SESSIONS text with chromatic aberration glitch
        float aberration = 0.01 + audioHigh * 0.02;
        float d = drawSESSIONS(glitchUV / 1.5) * 1.5;
        vec3 colR = vec3(1.0, 0.0, 0.0) * smoothstep(0.02, 0.0, d);
        vec3 colG = vec3(0.0, 1.0, 0.0) * smoothstep(0.02, 0.0, drawSESSIONS((glitchUV - vec2(aberration, 0.0)) / 1.5) * 1.5);
        vec3 colB = vec3(0.0, 0.0, 1.0) * smoothstep(0.02, 0.0, drawSESSIONS((glitchUV - vec2(-aberration, 0.0)) / 1.5) * 1.5);
        col += (colR + colG + colB) * 0.5;

        // Random noise glitch
        if (hash(vec2(originalUV.y * 100.0, glitchTime)) > 0.95 - audioLevel * 0.1) {
            col = mix(col, vec3(hash(originalUV + glitchTime)), 0.3);
        }
    }

    // === Scene 3: Infinite Grid with FBM and Mosaic ===
    else if (sceneID == 3) {
        vec3 ro = vec3(0.0, 2.0 + sin(TIME * 0.3) * 1.0, TIME * 2.0);
        vec3 rd = normalize(vec3(uv * 2.0, -1.0));

        // Ground intersection
        float t = -ro.y / rd.y;
        if (t > 0.0) {
            vec3 p = ro + rd * t;

            // FBM displacement
            float displacement = fbm(p * 0.5 + vec3(0.0, 0.0, TIME * 0.5)) * 2.0;
            displacement += audioLow * 0.5;

            // Grid
            vec2 grid = fract(p.xz * 2.0);
            float gridLine = step(0.95, max(grid.x, grid.y));

            float hue = displacement * 0.3 + TIME * 0.1 + audioLevel * 0.2;
            col = hsv(hue, 0.7, 0.8) * (displacement * 0.5 + 0.3);
            col = mix(col, col * 1.5, gridLine);

            // Fog
            col = mix(col, vec3(0.0), 1.0 - exp(-t * 0.1));
        }

        // SESSIONS with mosaic effect
        float pixelAmount = 20.0 + audioLevel * 30.0;
        vec2 pixelatedUV = floor(uv * pixelAmount) / pixelAmount;
        float colorSteps = 4.0 + audioMid * 8.0;

        vec2 skyUV = pixelatedUV + vec2(0.0, 0.5);
        float d = drawSESSIONS(skyUV / 1.5) * 1.5;

        float hue = 0.5 + audioLevel * 0.5;
        vec3 c = hsv(hue, 0.9, 1.0);
        vec3 glow = c * (0.03 / (abs(d) + 0.03));
        glow = floor(glow * colorSteps) / colorSteps;

        col += glow * (0.4 + audioHigh * 0.4);
        vec3 sessColor = mix(col, c, smoothstep(0.02, 0.0, d));
        sessColor = floor(sessColor * colorSteps) / colorSteps;

        // Blend mosaic text with background
        float textMask = smoothstep(0.02, 0.0, d);
        col = mix(col, sessColor, textMask * 0.5);

        // Pixel grid overlay
        vec2 pixelGrid = fract(uv * pixelAmount);
        float gridLinePixel = step(0.95, max(pixelGrid.x, pixelGrid.y));
        col = mix(col, col * 0.5, gridLinePixel * 0.3);
    }

    // === Scene 4: Kaleidoscope with Tiled Pattern ===
    else if (sceneID == 4) {
        // Background kaleidoscope
        vec2 p = uv;
        float a = atan(p.y, p.x);
        float r = length(p);

        float segments = 8.0 + floor(audioMid * 8.0);
        a = mod(a, TAU / segments);
        a = abs(a - TAU / segments * 0.5);

        p = vec2(cos(a), sin(a)) * r;

        // Nested shapes
        for (int i = 0; i < 10; i++) {
            p = abs(p);
            p -= vec2(0.5, 0.3);
            p *= rot(TIME * 0.5 + audioHigh * 2.0);
        }

        float d = drawSESSIONS(p * 2.0) * 0.5;
        float hue = r * 0.5 + TIME * 0.2 + audioLevel * 0.3;
        col = hsv(hue, 0.9, 1.0) * (0.05 / (abs(d) + 0.05));

        // Tiled SESSIONS overlay
        float gridSizeX = 1.0;
        float gridSizeY = 0.4;

        vec2 gridUV = uv;
        gridUV.x = mod(gridUV.x + gridSizeX * 0.5, gridSizeX) - gridSizeX * 0.5;
        gridUV.y = mod(gridUV.y + gridSizeY * 0.5, gridSizeY) - gridSizeY * 0.5;

        vec2 cellID = floor((uv + vec2(gridSizeX * 0.5, gridSizeY * 0.5)) / vec2(gridSizeX, gridSizeY));
        float cellHash = hash(cellID);
        float cellTime = TIME + cellHash * 3.0;

        // Wave effect per cell
        float wave = sin(cellTime * 2.0 + audioMid * 3.0) * (0.03 + audioHigh * 0.05);
        vec2 waveGridUV = gridUV - vec2(0.0, wave);
        float scale = 0.45 - audioLow * 0.1;
        float tileD = drawSESSIONS(waveGridUV / scale) * scale;

        float tileHue = cellHash + cellTime * 0.1 + audioLevel * 0.3;
        vec3 cellColor = hsv(tileHue, 0.8, 0.9);

        vec3 glow = cellColor * (0.02 / (abs(tileD) + 0.02));
        col += glow * (0.4 + audioLevel * 0.3);
        col = mix(col, cellColor, smoothstep(0.015, 0.0, tileD) * 0.3);

        // Grid lines
        vec2 gridLine = abs(gridUV);
        float lineX = smoothstep(gridSizeX * 0.5 - 0.01, gridSizeX * 0.5, gridLine.x);
        float lineY = smoothstep(gridSizeY * 0.5 - 0.01, gridSizeY * 0.5, gridLine.y);
        col = mix(col, col * 0.3, max(lineX, lineY) * 0.5);
    }

    // === Scene 5: DNA Helix with Matrix Rain ===
    else if (sceneID == 5) {
        for (float i = 0.0; i < 50.0; i++) {
            float t = i * 0.1;
            float z = t * 3.0 - TIME * 2.0;

            // Only draw if z is in visible range
            if (z > -2.0 && z < 5.0) {
                vec3 p1 = vec3(cos(z * 2.0 + audioLow * 2.0) * 0.6, sin(z * 3.0) * 0.3, z);
                vec3 p2 = vec3(-cos(z * 2.0 + audioLow * 2.0) * 0.6, -sin(z * 3.0) * 0.3, z);

                // Better projection
                float depth1 = 3.0 / (p1.z + 3.0);
                float depth2 = 3.0 / (p2.z + 3.0);

                vec2 s1 = p1.xy * depth1;
                vec2 s2 = p2.xy * depth2;

                float d1 = length(uv - s1);
                float d2 = length(uv - s2);
                float bridge = length(uv - mix(s1, s2, 0.5));

                float size = (0.03 + audioMid * 0.04) * depth1;
                float hue = t * 0.5 + TIME * 0.1;

                // Enhanced visibility
                col += hsv(hue, 0.8, 1.0) * smoothstep(size, 0.0, d1) * (1.0 + audioHigh * 2.0);
                col += hsv(hue + 0.5, 0.8, 1.0) * smoothstep(size, 0.0, d2) * (1.0 + audioHigh * 2.0);
                col += hsv(hue + 0.25, 0.6, 0.7) * smoothstep(size * 0.5, 0.0, bridge) * (0.5 + audioMid * 1.5);

                // Glow
                col += hsv(hue, 0.9, 0.5) * exp(-d1 * 5.0) * audioLevel * 0.5;
                col += hsv(hue + 0.5, 0.9, 0.5) * exp(-d2 * 5.0) * audioLevel * 0.5;
            }
        }

        // Matrix Rain SESSIONS
        float numLanes = 5.0 + audioLevel * 3.0;
        for (float i = 0.0; i < 8.0; i++) {
            if (i >= numLanes) break;

            float laneX = (i / (numLanes - 1.0)) * 2.4 - 1.2;
            float speed = hash(vec2(i, 0.0)) * 1.5 + 0.8 + audioMid * 0.5;
            float yOffset = mod(TIME * speed + hash(vec2(i, 1.0)) * 2.0, 2.5) - 1.2;

            vec2 p = uv - vec2(laneX, yOffset);
            float d = drawSESSIONS(p / 0.5) * 0.5;
            float fade = 1.0 - smoothstep(0.3, 1.0, abs(yOffset));
            float hue = 0.33 + audioLevel * 0.2;
            vec3 color = hsv(hue, 0.7, 1.0);

            // Trail effect
            for (float j = 0.1; j < 0.5; j += 0.1) {
                vec2 trailP = uv - vec2(laneX, yOffset + j);
                float trailD = drawSESSIONS(trailP / 0.5) * 0.5;
                float trailFade = (1.0 - j * 2.0) * fade * 0.3;
                col += color * (0.005 / (abs(trailD) + 0.005)) * trailFade;
            }

            col += color * (0.015 / (abs(d) + 0.015)) * fade * (0.4 + audioHigh * 0.4);
            col = mix(col, color * fade, smoothstep(0.015, 0.0, d) * 0.3);
        }
    }

    // === Scene 6: Kaleidoscope with Recursive SESSIONS ===
    else if (sceneID == 6) {
        vec2 p = uv;
        float a = atan(p.y, p.x);
        float r = length(p);

        float segments = 8.0 + floor(audioMid * 8.0);
        a = mod(a, TAU / segments);
        a = abs(a - TAU / segments * 0.5);

        p = vec2(cos(a), sin(a)) * r;

        // Nested shapes
        for (int i = 0; i < 10; i++) {
            p = abs(p);
            p -= vec2(0.5, 0.3);
            p *= rot(TIME * 0.5 + audioHigh * 2.0);
        }

        float d = drawSESSIONS(p * 2.0) * 0.5;
        float hue = r * 0.5 + TIME * 0.2 + audioLevel * 0.3;
        col = hsv(hue, 0.9, 1.0) * (0.05 / (abs(d) + 0.05));

        // Center recursive SESSIONS
        vec2 centerP = uv;
        vec3 accum = vec3(0.0);

        for (int i = 0; i < 15; i++) {
            float scale = pow(1.5, float(i));
            float rotation = TIME * 0.3 * float(i) + audioMid * 2.0;

            vec2 q = centerP * scale;
            q *= rot(rotation);

            float recurD = drawSESSIONS(q) / scale;
            float recurHue = float(i) * 0.1 + TIME * 0.1 + audioLevel * 0.2;

            accum += hsv(recurHue, 0.8, 1.0) * (0.01 / (abs(recurD) + 0.01)) * exp(-float(i) * 0.3);
        }

        col += accum * (0.5 + audioLevel * 0.5);
    }

    // Chromatic aberration
    float aberration = audioHigh * 0.01;
    if (aberration > 0.001) {
        col *= vec3(0.8, 1.0, 0.8);
    }

    // Vignette
    float vignette = 1.0 - length(originalUV) * 0.3;
    col *= vignette;

    // Scanlines
    col *= 0.95 + 0.05 * sin(originalUV.y * 300.0 + time * 10.0);

    // Contrast boost
    col = pow(col, vec3(0.9));

    gl_FragColor = vec4(col, 1.0);
}
