// Structural family: looking straight down a stairwell. Floor after floor of
// landings and balustrades, each one turned a little from the one above, going
// down forever.
//
// Gate Corridor also travels through repeated structure, but it travels
// horizontally past gates that arrive and leave: the frame has a middle and two
// sides. Here the vanishing point is dead centre, every floor is a closed ring
// around it, and the motion is entirely radial. The turn per floor is what makes
// it a stairwell rather than a tunnel — the flights spiral even though nothing
// in the image rotates.

export const stairwellDescent = {
    name: 'Stairwell Descent',
    family: 'structural',
    kind: 'fragment',
    texture: 0.7,
    consumes: ['ink'],
    traits: ['camera', 'space', 'style'],

    params: {
        floors:  { type: 'float', range: [0.18, 0.6],  default: 0.32, uniform: 'u_floors', bias: 'density' },
        turn:    { type: 'float', range: [-0.5, 0.5],  default: 0.22, uniform: 'u_turn' },
        well:    { type: 'float', range: [0.1, 0.6],   default: 0.3,  uniform: 'u_well' },
        rails:   { type: 'int',   range: [6, 40],      default: 18,   uniform: 'u_rails', bias: 'density' },
        landing: { type: 'float', range: [0.1, 0.45],  default: 0.25, uniform: 'u_landing' },
        lit:     { type: 'float', range: [0, 1.4],     default: 0.6,  uniform: 'u_lit', bias: 'energy' },
        depth:   { type: 'float', range: [0.2, 1],     default: 0.65, uniform: 'u_deep', slowAxis: true },
        fall:    { type: 'float', range: [0.01, 0.35], default: 0.08, uniform: 'u_fall', bias: 'motion', rate: true },
        palette: { type: 'palette', count: 5 },
    },

    reactive: {
        lit:   { feature: 'bandHigh', amount: 0.3,  response: 'smooth' },
        rails: { feature: 'bandMid',  amount: 0.15, response: 'smooth' },
    },

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

    float r = length(p) + 0.001;
    float th = atan(p.y, p.x);

    // Log-radial: one unit is one floor. Descending is a constant slide down
    // this axis, which is what makes the fall never end and never repeat a cut.
    float z = log(r / u_well) / u_floors + t * 3.0;
    float floorId = floor(z);
    float f = fract(z);

    // Each flight is turned from the one above it.
    float a = th + floorId * u_turn * 6.28318530718;

    // The balustrade: uprights around the well, and the handrail on top of them.
    float posts = abs(fract(a / 6.28318530718 * float(u_rails)) - 0.5) * 2.0;
    float w = 0.25 + u_sigLine * 0.5;
    float upright = smoothstep(w, w * 0.25, posts) * smoothstep(0.75, 0.35, f);
    float rail = smoothstep(0.12, 0.02, abs(f - 0.72));

    // The landing slab: a solid quarter of every floor, so there is somewhere to
    // stand and the eye can count the floors.
    float quarter = fract(a / 6.28318530718 + 0.5);
    float slab = smoothstep(0.5, 0.44, abs(quarter - 0.5)) *
                 smoothstep(0.08, 0.2, f) * smoothstep(u_landing + 0.25, u_landing, f);

    // Everything dims toward the middle. This is the only cue that the well has
    // a bottom, so it carries the whole read of the image — and it is measured
    // off the radius rather than off the floor index, because the floors below
    // us occupy a few pixels at the centre while the darkness has to fill half
    // the frame to read as depth at all.
    float fade = mix(1.0, sat(r * 0.7), u_deep);
    float sky = smoothstep(0.85, 1.6, r);       // the top of the well, above us

    vec3 col = pal(0) * 0.07;
    col += palRamp(0.25 + f * 0.2) * upright * 0.45 * fade;
    col += pal(4) * rail * (0.4 + u_lit * 0.7) * fade;
    col += mix(pal(2) * 0.3, pal(1) * 0.22, fract(floorId * 0.37)) * slab * fade;

    // A light on each landing, catching the rail below it.
    float lamp = exp(-abs(f - 0.45) * 6.0) * smoothstep(0.55, 0.2, abs(quarter - 0.25));
    col += pal(3) * lamp * u_lit * 0.5 * fade;

    col = mix(col, pal(1) * 0.3, sky * 0.5);
    col = sigAir(col, p, sat(1.0 - fade));
    return vec4(inkValue(col), 1.0);
}
`,
};

export default stairwellDescent;
