// Flow family: curtains of light standing above the track's horizon.
//
// Distinct from Curl Flow (a full-frame advected field) and Silk Ribbon (one
// strand): this is several tall vertical sheets, each rippling on its own phase,
// dense at the base and dissolving upward. The rippling is a sum of sines rather
// than noise, which is what gives an aurora its folded-sheet look instead of a
// smoky one — noise curtains read as fog.
//
// The horizon is the track's, so this stands in the same place as every other
// scene that has ground.

export const auroraVeil = {
    name: 'Aurora Veil',
    family: 'flow',
    kind: 'fragment',
    traits: ['camera', 'space', 'style'],

    params: {
        curtains: { type: 'int',   range: [2, 9],      default: 4,    uniform: 'u_curtains', bias: 'density' },
        height:   { type: 'float', range: [0.4, 1.8],  default: 1.0,  uniform: 'u_height' },
        fold:     { type: 'float', range: [0.1, 1.4],  default: 0.55, uniform: 'u_fold', bias: 'density' },
        speed:    { type: 'float', range: [0.03, 0.5], default: 0.15, uniform: 'u_speed', bias: 'motion', rate: true },
        glow:     { type: 'float', range: [0, 1.4],    default: 0.5,  uniform: 'u_glow', bias: 'energy' },
        ground:   { type: 'float', range: [0, 0.8],    default: 0.3,  uniform: 'u_ground' },
        palette:  { type: 'palette', count: 5 },
    },

    reactive: {
        glow: { feature: 'bandHigh', amount: 0.4, response: 'smooth' },
        fold: { feature: 'bandLow',  amount: 0.3, response: 'smooth' },
    },

    shader: `
vec4 scene(vec2 uv, vec2 p) {
    float t = u_time * u_speed + u_seed;
    p = sigCamera(p);

    float horizon = sigHorizonY() * 0.8 - 0.55;
    float above = p.y - horizon;

    vec3 col = pal(0) * 0.06;

    for (int i = 0; i < 9; i++) {
        if (i >= u_curtains) break;
        float fi = float(i);
        float s = u_seed + fi * 37.13;

        // Each sheet is a vertical line whose x wanders as a sum of three sines.
        // Three is the fewest that stops reading as a single wobble.
        float x = (fract(s * 0.61) - 0.5) * 2.2
                + sin(above * 1.7 + t * 1.3 + s) * u_fold * 0.35
                + sin(above * 3.1 - t * 0.8 + s * 1.7) * u_fold * 0.18
                + sin(above * 0.7 + t * 0.4 + s * 2.3) * u_fold * 0.5;

        float d = abs(p.x - x);
        float widthAt = 0.05 + above * 0.06 + u_sigLine * 0.05;

        // Bright and tight at the base, wide and faint at the top: the vertical
        // falloff is what makes it a curtain rather than a stripe.
        float rise = smoothstep(-0.05, 0.0, above) * exp(-max(above, 0.0) / max(u_height, 0.05));
        float sheet = exp(-d * d / max(widthAt * widthAt, 1e-5)) * rise;

        vec3 tint = palRamp(fract(s) * 0.5 + above * 0.12 + 0.1);
        col += tint * sheet * (0.55 + u_glow * 0.6);
        col += tint * exp(-d * 5.0) * rise * u_glow * 0.12;
    }

    // Ground: the curtains reflected, dim and compressed.
    if (u_ground > 0.01 && above < 0.0) {
        float below = -above;
        col += pal(2) * u_ground * exp(-below * 6.0) * 0.35;
    }

    col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.x)));
    col += sigGrain(uv);
    return vec4(col, 1.0);
}
`,
};

export default auroraVeil;
