{
  "license": "CC0-1.0",
  "shader": {
    "id": "qgi71c8k",
    "title": "Stick Figure V2",
    "license": "CC0-1.0",
    "provenance_type": "user_upload",
    "made_with": "glslop",
    "status": "active",
    "compile_ok": true,
    "render_hash": "0018181818181400",
    "tags": [],
    "parents": [],
    "author": "jab6zg50vals",
    "author_name": "ogcraig",
    "author_url": "/u/ogcraig",
    "created_at": "2026-10-22T16:22:18.414Z",
    "poster_url": "/posters/qgi71c8k.webp",
    "stats": {
      "slops": 0,
      "views": 6,
      "forks": 1
    },
    "superseded_by": "4mdpp7el",
    "self": "/api/v1/shaders/qgi71c8k",
    "isf": "/*{\n  \"DESCRIPTION\": \"Restroom-sign pictogram: white standing figure on a rounded black tile, with a Motion Mode dropdown: Wave, Walk, Run in Place, Dance, Jumping Jacks and Stand Still. Fully jointed figure (shoulders, elbows, rounded nub ends, knees) with body bounce, sway and head follow. Moves lock to a BPM. Also color cycle, glow, outline and pulse for live use.\",\n  \"CREDIT\": \"Craig\",\n  \"ISFVSN\": \"2\",\n  \"CATEGORIES\": [\"generator\"],\n  \"INPUTS\": [\n    { \"NAME\": \"motionMode\",  \"LABEL\": \"Motion Mode\",  \"TYPE\": \"long\",  \"DEFAULT\": 0,\n      \"VALUES\": [0, 1, 2, 3, 4, 5],\n      \"LABELS\": [\"Wave\", \"Walk\", \"Run in Place\", \"Dance\", \"Jumping Jacks\", \"Stand Still\"] },\n    { \"NAME\": \"bpm\",         \"LABEL\": \"Tempo (BPM)\",  \"TYPE\": \"float\", \"DEFAULT\": 120.0, \"MIN\": 60.0, \"MAX\": 200.0 },\n    { \"NAME\": \"moveAmount\",  \"LABEL\": \"Move Amount\",  \"TYPE\": \"float\", \"DEFAULT\": 1.0, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"speed\",       \"TYPE\": \"float\", \"DEFAULT\": 1.0, \"MIN\": 0.0,  \"MAX\": 4.0 },\n\n    { \"NAME\": \"hue\",         \"TYPE\": \"float\", \"DEFAULT\": 0.5, \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"colorCycle\",  \"LABEL\": \"Color Cycle\",  \"TYPE\": \"float\", \"DEFAULT\": 0.0, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"figureColor\", \"LABEL\": \"Figure Color\", \"TYPE\": \"color\", \"DEFAULT\": [1.0, 1.0, 1.0, 1.0] },\n    { \"NAME\": \"tileColor\",   \"LABEL\": \"Tile Color\",   \"TYPE\": \"color\", \"DEFAULT\": [0.0, 0.0, 0.0, 1.0] },\n    { \"NAME\": \"outerColor\",  \"LABEL\": \"Outer Color\",  \"TYPE\": \"color\", \"DEFAULT\": [1.0, 1.0, 1.0, 1.0] },\n    { \"NAME\": \"showTile\",    \"LABEL\": \"Show Tile\",    \"TYPE\": \"bool\",  \"DEFAULT\": 1 },\n    { \"NAME\": \"zoom\",        \"TYPE\": \"float\", \"DEFAULT\": 1.0, \"MIN\": 0.25, \"MAX\": 3.0 },\n\n    { \"NAME\": \"waveAuto\",    \"LABEL\": \"Auto Wave Loop\", \"TYPE\": \"bool\",  \"DEFAULT\": 1 },\n    { \"NAME\": \"waveStyle\",   \"LABEL\": \"Wave Style\",     \"TYPE\": \"long\",  \"DEFAULT\": 0,\n      \"VALUES\": [0, 1, 2], \"LABELS\": [\"Elbow Wave\", \"Wrist Flick\", \"Big Wave\"] },\n    { \"NAME\": \"waveRaise\",   \"LABEL\": \"Arm Raise\",      \"TYPE\": \"float\", \"DEFAULT\": 1.0, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"waveCycle\",   \"LABEL\": \"Loop Length (s)\",\"TYPE\": \"float\", \"DEFAULT\": 6.0, \"MIN\": 2.0, \"MAX\": 20.0 },\n    { \"NAME\": \"waveSpeed\",   \"LABEL\": \"Wave Speed\",     \"TYPE\": \"float\", \"DEFAULT\": 1.6, \"MIN\": 0.0, \"MAX\": 5.0 },\n    { \"NAME\": \"waveAmount\",  \"LABEL\": \"Wave Amount\",    \"TYPE\": \"float\", \"DEFAULT\": 0.6, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"bodyFollow\",  \"LABEL\": \"Head Follow\",    \"TYPE\": \"float\", \"DEFAULT\": 0.5, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"waveLeft\",    \"LABEL\": \"Mirror Figure\",  \"TYPE\": \"bool\",  \"DEFAULT\": 0 },\n\n    { \"NAME\": \"pulse\",       \"TYPE\": \"float\", \"DEFAULT\": 0.0, \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"glow\",        \"TYPE\": \"float\", \"DEFAULT\": 0.0, \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"outlineMix\",  \"LABEL\": \"Outline Only\", \"TYPE\": \"float\", \"DEFAULT\": 0.0, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"lineWidth\",   \"LABEL\": \"Line Width\",   \"TYPE\": \"float\", \"DEFAULT\": 0.3, \"MIN\": 0.0, \"MAX\": 1.0 }\n  ]\n}*/\n\n// All geometry is measured off the 1000x1000 reference, in a y-up pixel frame\n// (Y = 1000 - imageY), so the numbers map straight back to the photo.\n// Every motion mode returns to the exact reference silhouette at rest.\n// \"Mirror Figure\" flips the sample point about the figure's centre line (x = 491),\n// which also moves the wave to the other arm.\n\n#define PI      3.14159265\n#define HALF_PI 1.5707963\n\n// Reference rest geometry\n#define PELVIS   vec2(491.0, 452.0)\n#define HIP_L    vec2(445.5, 470.0)\n#define HIP_R    vec2(537.0, 470.0)\n#define FOOT_L   vec2(445.5, 153.5)\n#define FOOT_R   vec2(537.0, 153.5)\n#define LEG_SEG  158.25            // thigh = shin, so the rest leg is exactly straight\n\nmat2 rot(float a) {\n    float c = cos(a), s = sin(a);\n    return mat2(c, -s, s, c);\n}\n\n// iq rounded box with per-corner radii: r = (topRight, bottomRight, topLeft, bottomLeft)\nfloat sdRoundBox(vec2 p, vec2 b, vec4 r) {\n    r.xy = (p.x > 0.0) ? r.xy : r.zw;\n    r.x  = (p.y > 0.0) ? r.x  : r.y;\n    vec2 q = abs(p) - b + r.x;\n    return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;\n}\n\n// Box defined by min/max corners\nfloat boxMM(vec2 p, vec2 mn, vec2 mx, vec4 r) {\n    vec2 c = 0.5 * (mn + mx);\n    vec2 h = 0.5 * (mx - mn);\n    return sdRoundBox(p - c, h, r);\n}\n\nfloat sdSeg(vec2 p, vec2 a, vec2 b) {\n    vec2 pa = p - a, ba = b - a;\n    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);\n    return length(pa - ba * h);\n}\n\nfloat dot2(vec2 v) { return dot(v, v); }\n\n// iq exact distance to a quadratic Bezier (A -> C, control B)\nfloat sdBezier(vec2 pos, vec2 A, vec2 B, vec2 C) {\n    vec2 a = B - A;\n    vec2 b = A - 2.0 * B + C;\n    vec2 c = a * 2.0;\n    vec2 d = A - pos;\n    float kk = 1.0 / dot(b, b);\n    float kx = kk * dot(a, b);\n    float ky = kk * (2.0 * dot(a, a) + dot(d, b)) / 3.0;\n    float kz = kk * dot(d, a);\n    float res;\n    float pp = ky - kx * kx;\n    float p3 = pp * pp * pp;\n    float qq = kx * (2.0 * kx * kx - 3.0 * ky) + kz;\n    float h = qq * qq + 4.0 * p3;\n    if (h >= 0.0) {\n        h = sqrt(h);\n        vec2 x = (vec2(h, -h) - qq) / 2.0;\n        vec2 uv = sign(x) * pow(abs(x), vec2(1.0 / 3.0));\n        float t = clamp(uv.x + uv.y - kx, 0.0, 1.0);\n        res = dot2(d + (c + b * t) * t);\n    } else {\n        float z = sqrt(-pp);\n        float v = acos(qq / (pp * z * 2.0)) / 3.0;\n        float m = cos(v);\n        float n = sin(v) * 1.732050808;\n        vec3 t = clamp(vec3(m + m, -n - m, n - m) * z - kx, 0.0, 1.0);\n        res = min(dot2(d + (c + b * t.x) * t.x), dot2(d + (c + b * t.y) * t.y));\n    }\n    return sqrt(res);\n}\n\nfloat smin(float a, float b, float k) {\n    k = max(k, 0.001);\n    float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);\n    return mix(b, a, h) - k * h * (1.0 - h);\n}\n\n// Arm angle convention, per side: 0 = pointing outward from the body,\n// -PI/2 = hanging down, +PI/2 = straight up. sx = +1 screen right, -1 screen left.\nvec2 aDir(float a, float sx) {\n    return vec2(sx * cos(a), sin(a));\n}\n\n// How far an arm is lifted (drives the shoulder tuck and joint slide)\nfloat liftOf(float upper) {\n    return clamp((upper + HALF_PI) / (HALF_PI + 0.16), 0.0, 1.0);\n}\n\n// Ease with a small late overshoot, so the waving arm \"arrives\" instead of stopping dead\nfloat liftCurve(float x) {\n    x = clamp(x, 0.0, 1.0);\n    return smoothstep(0.0, 0.8, x) + 0.07 * sin(PI * clamp((x - 0.6) / 0.4, 0.0, 1.0));\n}\n\n// ---------------------------------------------------------------------------\n// Pose: everything the figure needs for one frame\n// ---------------------------------------------------------------------------\nstruct Pose {\n    vec2  body;      // upper-body offset (bounce / sway)\n    float tilt;      // upper-body roll around the pelvis (+ = counter-clockwise)\n    float headTilt;  // extra head roll around the neck\n    vec3  armL;      // left arm angles: (upper, forearm, nub)\n    vec2  lenL;      // left arm lengths: (forearm, nub)\n    vec3  armR;      // right arm angles\n    vec2  lenR;      // right arm lengths\n    vec2  footL;     // foot targets (world space)\n    vec2  footR;\n    float splay;     // how far knees bow outward when the legs bend (0..1)\n};\n\nvoid restPose(inout Pose P) {\n    P.body = vec2(0.0);\n    P.tilt = 0.0;\n    P.headTilt = 0.0;\n    P.armL = vec3(-HALF_PI);\n    P.armR = vec3(-HALF_PI);\n    P.lenL = vec2(103.0, 0.0);\n    P.lenR = vec2(103.0, 0.0);\n    P.footL = FOOT_L;\n    P.footR = FOOT_R;\n    P.splay = 0.45;\n}\n\n// Even-width arm tube: straight upper arm, then forearm + rounded nub as one\n// smooth Bezier curve (so a trailing nub bends the forearm instead of kinking).\n// With nub length 0 it is a plain straight capsule, identical to the reference arm.\nfloat armTube(vec2 p, vec2 S, float sx, float r, vec3 ang, vec2 len) {\n    vec2 E = S + 115.0 * aDir(ang.x, sx);\n    vec2 W = E + len.x * aDir(ang.y, sx);\n    vec2 T = W + len.y * aDir(ang.z, sx);\n    float dU = sdSeg(p, S, E) - r;\n    float dF = sdBezier(p, E, W, T) - r;\n    return smin(dU, dF, 4.0 * clamp(len.y / 30.0, 0.0, 1.0) + 0.001);\n}\n\n// Two-bone leg with simple IK: hip H reaches for foot target F.\n// If F is out of reach the leg straightens toward it. side = -1 left, +1 right.\nfloat legTube(vec2 p, vec2 H, vec2 F, float r, float side, float splay) {\n    vec2 d = F - H;\n    float len = max(length(d), 0.001);\n    vec2 dir = d / len;\n    float reach = min(len, 2.0 * LEG_SEG);\n    vec2 Fp = H + dir * reach;\n    float h = sqrt(max(LEG_SEG * LEG_SEG - 0.25 * reach * reach, 0.0));\n    vec2 perp = vec2(-dir.y, dir.x);              // pointing +x for a leg hanging down\n    vec2 K = H + dir * (0.5 * reach) + perp * h * splay * side;\n    return min(sdSeg(p, H, K), sdSeg(p, K, Fp)) - r;\n}\n\nfloat figure(vec2 p, Pose P) {\n    // Upper-body space: undo the bounce/sway and roll around the pelvis\n    vec2 pu = rot(P.tilt) * (p - PELVIS - P.body) + PELVIS;\n\n    // Head, rolled around the neck\n    vec2 N = vec2(491.0, 772.0);\n    vec2 hp = rot(P.headTilt) * (pu - N) + N;\n    float head = length(hp - vec2(491.0, 854.0)) - 67.0;\n\n    // Shoulder yoke with rounded top corners. On a lifted side the shoulder cap\n    // tucks in and tightens, so the raised arm becomes the shoulder line.\n    float liftL = liftOf(P.armL.x);\n    float liftR = liftOf(P.armR.x);\n    float xL = mix(333.0, 407.0, liftL), rL = mix(80.0, 34.0, liftL);\n    float xR = mix(648.0, 576.0, liftR), rR = mix(80.0, 34.0, liftR);\n    float yoke = boxMM(pu, vec2(xL, 600.0), vec2(xR, 772.0), vec4(rR, 0.0, rL, 0.0));\n\n    // Below the armpit line outside the torso the arms own the space;\n    // the cut rises on a lifted side to make room for a clean armpit.\n    float cutL = boxMM(pu, vec2(-1000.0, -1000.0), vec2(407.0, 668.0 + 40.0 * liftL), vec4(0.0));\n    float cutR = boxMM(pu, vec2(576.0, -1000.0),  vec2(2000.0, 668.0 + 40.0 * liftR), vec4(0.0));\n    yoke = max(yoke, -min(cutL, cutR));\n\n    // Torso block down to the crotch\n    float torso = boxMM(pu, vec2(407.0, 452.0), vec2(576.0, 700.0), vec4(0.0));\n    float body = min(yoke, torso);\n\n    // Arms. Shoulder joints slide up and in as each arm lifts, so a raised arm\n    // comes out of the top of the shoulder instead of the armpit.\n    vec2 SL = mix(vec2(363.0, 700.0), vec2(404.0, 744.0), smoothstep(0.0, 0.6, liftL));\n    vec2 SR = mix(vec2(619.0, 700.0), vec2(578.0, 744.0), smoothstep(0.0, 0.6, liftR));\n    float armL = armTube(pu, SL, -1.0, 30.0, P.armL, P.lenL);\n    float armR = armTube(pu, SR,  1.0, 29.0, P.armR, P.lenR);\n\n    // Blend lifted arms into the shoulder/armpit; razor sharp at rest\n    float d = smin(body, armR, 0.5 + 24.0 * liftR);\n    d = smin(d, armL, 0.5 + 24.0 * liftL);\n    d = min(d, head);\n\n    // Legs: hips ride with the upper body, feet go where the pose puts them\n    mat2 back = rot(-P.tilt);\n    vec2 HL = back * (HIP_L - PELVIS) + PELVIS + P.body;\n    vec2 HR = back * (HIP_R - PELVIS) + PELVIS + P.body;\n    float legL = legTube(p, HL, P.footL, 38.5, -1.0, P.splay);\n    float legR = legTube(p, HR, P.footR, 39.0,  1.0, P.splay);\n    d = min(d, min(legL, legR));\n    return d;\n}\n\n// ---------------------------------------------------------------------------\n// Motion modes\n// ---------------------------------------------------------------------------\n\n// Wave: elbow-led lift, forearm wave with trailing nub, auto loop or manual\nvoid poseWave(inout Pose P, float t) {\n    float ph = fract(t / waveCycle);\n    float autoRaise = smoothstep(0.06, 0.24, ph) * (1.0 - smoothstep(0.80, 0.96, ph));\n    float raise = waveAuto ? autoRaise * waveRaise : waveRaise;\n\n    float lift = liftCurve(raise);\n    float fold = smoothstep(0.35, 1.0, raise);\n    float env  = smoothstep(0.78, 1.0, raise);\n\n    // Style presets: pose = (upper angle, elbow bend), amp = (forearm, nub flick, shoulder)\n    float style = float(waveStyle);\n    vec2 pose = vec2(0.16, 1.22);\n    vec3 amp  = vec3(0.75, 0.30, 0.00);\n    if (style > 0.5 && style < 1.5) {\n        pose = vec2(0.22, 1.12); amp = vec3(0.08, 0.60, 0.00);\n    } else if (style > 1.5) {\n        pose = vec2(0.08, 0.86); amp = vec3(0.10, 0.30, 0.27);\n    }\n\n    float w   = t * waveSpeed * 2.0 * PI;\n    float A   = waveAmount * env;\n    float osc = sin(w);\n    float lag = sin(w - 1.1);\n\n    float upper = mix(-HALF_PI, pose.x, lift) + A * (amp.z - 0.25 * amp.x) * osc;\n    float foreHang = min(upper, -HALF_PI + 0.3);\n    float foreUp   = upper + pose.y + A * amp.x * osc;\n    float fore = mix(foreHang, foreUp, fold);\n    float nub  = fore - 0.12 * fold + A * amp.y * lag;\n\n    P.armR = vec3(upper, fore, nub);\n    P.lenR = vec2(mix(103.0, 84.0, fold), 30.0 * fold);\n    P.headTilt = bodyFollow * (0.09 * clamp(lift, 0.0, 1.0) + 0.035 * A * sin(w - 1.8));\n}\n\n// Walk in place: alternating knee lifts, opposite arm swings forward\n// (shown front-on as the arm foreshortening and the nub rising), weight shift and bob.\nvoid poseWalk(inout Pose P, float beats, float E) {\n    float ph = PI * beats;                         // one step per beat\n    float s  = sin(ph);\n    P.footL.y += 62.0 * E * pow(max( s, 0.0), 1.3);\n    P.footR.y += 62.0 * E * pow(max(-s, 0.0), 1.3);\n    P.splay = 0.3;\n    P.body  = vec2(8.0 * E * s, -2.0 * E * (1.0 - abs(s)));   // tiny settle between steps\n    P.tilt  = 0.025 * E * s;\n\n    float fR = 0.5 + 0.5 * s;                       // right arm forward while left knee is up\n    float fL = 1.0 - fR;\n    float uR = -HALF_PI + E * mix(0.04, 0.16, fR);\n    float uL = -HALF_PI + E * mix(0.04, 0.16, fL);\n    float aR = uR + E * mix(0.0, 0.30, fR);\n    float aL = uL + E * mix(0.0, 0.30, fL);\n    P.armR = vec3(uR, aR, aR + 0.15 * E * fR);\n    P.armL = vec3(uL, aL, aL + 0.15 * E * fL);\n    P.lenR = vec2(103.0 - 46.0 * E * fR, 14.0 * E * fR);\n    P.lenL = vec2(103.0 - 46.0 * E * fL, 14.0 * E * fL);\n    P.headTilt = bodyFollow * 0.05 * E * sin(ph + 0.6);\n}\n\n// Run in place: high knees, a little flight between steps, and bent arms pumping\n// the nubs up and down in front of the chest (forearms foreshortened toward camera)\nvoid poseRun(inout Pose P, float beats, float E) {\n    float ph = 2.0 * PI * beats;                   // one stride (two steps) per beat\n    float s  = sin(ph);\n    P.footL.y += 120.0 * E * pow(max( s, 0.0), 1.2);\n    P.footR.y += 120.0 * E * pow(max(-s, 0.0), 1.2);\n    P.splay = 0.4;\n    float flight = pow(1.0 - abs(s), 2.0);         // airborne as the legs switch\n    P.body = vec2(4.0 * E * s, E * (12.0 * flight - 5.0));\n    P.tilt = 0.02 * E * s;\n\n    float fR = 0.5 + 0.5 * s;                      // arms opposite the legs\n    float fL = 1.0 - fR;\n    float uR = -HALF_PI + E * mix(0.22, 0.82, fR);\n    float uL = -HALF_PI + E * mix(0.22, 0.82, fL);\n    float aR = mix(-HALF_PI, mix(1.95, 2.30, fR), E);\n    float aL = mix(-HALF_PI, mix(1.95, 2.30, fL), E);\n    float trail = 0.2 * E * cos(ph);\n    P.armR = vec3(uR, aR, aR - trail);\n    P.armL = vec3(uL, aL, aL + trail);\n    P.lenR = vec2(mix(103.0, 52.0, E), 18.0 * E);\n    P.lenL = P.lenR;\n    P.headTilt = bodyFollow * 0.05 * E * s;\n}\n\n// Dance: side-to-side groove, dip on every beat, heel pops, alternating arm raises\nvoid poseDance(inout Pose P, float beats, float E) {\n    float ph  = PI * beats;                        // full groove every two beats\n    float s   = sin(ph);\n    float dip = 0.5 + 0.5 * cos(2.0 * ph);         // 1 on each beat\n    P.body = vec2(24.0 * E * s, -14.0 * E * dip);\n    P.tilt = -0.07 * E * s;                        // lean into the sway\n    P.headTilt = bodyFollow * 0.12 * E * sin(ph + 0.8);\n\n    // Slightly wider stance, unweighted heel pops up\n    P.footL = FOOT_L + vec2(-20.0 * E, 18.0 * E * pow(max( s, 0.0), 2.0));\n    P.footR = FOOT_R + vec2( 20.0 * E, 18.0 * E * pow(max(-s, 0.0), 2.0));\n    P.splay = 0.6;\n\n    float upR = smoothstep(0.1, 0.9, 0.5 + 0.5 * s);\n    float upL = smoothstep(0.1, 0.9, 0.5 - 0.5 * s);\n    float pump = 0.15 * (dip - 0.5);\n    float lagR = 0.25 * cos(ph), lagL = -lagR;\n\n    float uR = mix(-1.25, 0.45, upR), aR = mix(-0.35, 1.35, upR) + pump;\n    float uL = mix(-1.25, 0.45, upL), aL = mix(-0.35, 1.35, upL) + pump;\n    P.armR = mix(vec3(-HALF_PI), vec3(uR, aR, aR - 0.1 * upR + lagR), E);\n    P.armL = mix(vec3(-HALF_PI), vec3(uL, aL, aL - 0.1 * upL + lagL), E);\n    P.lenR = mix(vec2(103.0, 0.0), vec2(mix(95.0, 84.0, upR), mix(16.0, 30.0, upR)), E);\n    P.lenL = mix(vec2(103.0, 0.0), vec2(mix(95.0, 84.0, upL), mix(16.0, 30.0, upL)), E);\n}\n\n// Jumping jacks: hop on each switch, land open (arms up, feet wide) then closed\nvoid poseJacks(inout Pose P, float beats, float E) {\n    float ph  = PI * beats;                        // open on one beat, closed on the next\n    float j   = (0.5 - 0.5 * cos(ph)) * E;         // 0 closed .. 1 open\n    float hop = 24.0 * E * abs(sin(ph));           // airborne between positions\n    P.body = vec2(0.0, hop - 9.0 * j);             // sink a touch when landing wide\n    P.footL = FOOT_L + vec2(-75.0 * j, hop);\n    P.footR = FOOT_R + vec2( 75.0 * j, hop);\n    P.splay = 0.3;\n\n    float u = mix(-HALF_PI, 0.85, j);\n    float a = mix(-HALF_PI, 0.95, j);\n    float trail = 0.15 * E * sin(ph);\n    P.armR = vec3(u, a, a - trail);\n    P.armL = vec3(u, a, a - trail);\n    P.lenR = vec2(mix(103.0, 84.0, j), 30.0 * j);\n    P.lenL = P.lenR;\n}\n\n// Stand still: just a slow breath\nvoid poseStand(inout Pose P, float t, float E) {\n    P.body = vec2(0.0, 2.5 * E * sin(t * 1.3));\n}\n\nvoid main() {\n    float t = TIME * speed;\n    float beats = t * bpm / 60.0;\n    float E = moveAmount;\n\n    // Aspect-correct coords, mapped into the reference's 1000-unit frame\n    vec2 p = isf_FragNormCoord - 0.5;\n    p.x *= RENDERSIZE.x / RENDERSIZE.y;\n    float upp = 1000.0 / (RENDERSIZE.y * zoom);   // reference units per screen pixel (for AA)\n    vec2 q = p * 1000.0 / zoom + 500.0;\n\n    // Rounded black tile\n    float dTile = sdRoundBox(q - vec2(500.0), vec2(468.0), vec4(95.0));\n    float tileM = showTile ? clamp(0.5 - dTile / upp, 0.0, 1.0) : 1.0;\n\n    // ---------------- Pose for the selected motion ----------------\n    Pose P;\n    restPose(P);\n    float mode = float(motionMode);\n    if (mode < 0.5)      poseWave(P, t);\n    else if (mode < 1.5) poseWalk(P, beats, E);\n    else if (mode < 2.5) poseRun(P, beats, E);\n    else if (mode < 3.5) poseDance(P, beats, E);\n    else if (mode < 4.5) poseJacks(P, beats, E);\n    else                 poseStand(P, t, E);\n\n    // ---------------- Figure ----------------\n    float s = 1.0 + pulse * 0.08 * sin(t * 3.0);\n    vec2 c = vec2(491.0, 500.0);\n    vec2 fq = (q - c) / s + c;\n    if (waveLeft) fq.x = 982.0 - fq.x;             // mirror about the figure's centre line\n\n    float dFig = figure(fq, P) * s;\n\n    // Fill vs outline\n    float lw    = mix(3.0, 40.0, lineWidth);\n    float mFill = clamp(0.5 - dFig / upp, 0.0, 1.0);\n    float mLine = clamp(0.5 - (abs(dFig) - lw * 0.5) / upp, 0.0, 1.0);\n    float m     = mix(mFill, mLine, outlineMix);\n\n    // Color: solid figure color blended toward the reference cosine palette\n    vec3 pal = 0.5 + 0.5 * cos(t + q.y * 0.006 + q.x * 0.002 + vec3(0.0, 2.0, 4.0) + hue * 6.2831);\n    vec3 fig = mix(figureColor.rgb, pal, colorCycle);\n\n    // Soft halo around the figure\n    float g = glow * exp(-max(dFig, 0.0) / 60.0) * 0.8;\n\n    vec3 inside = tileColor.rgb + fig * g;\n    inside = mix(inside, fig, m);\n\n    vec3 col = mix(outerColor.rgb, inside, tileM);\n    gl_FragColor = vec4(col, 1.0);\n}"
  }
}