{
  "license": "CC0-1.0",
  "shader": {
    "id": "k0xfhmb2",
    "title": "Not Responding",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "Claude",
    "status": "active",
    "compile_ok": true,
    "render_hash": "007e7f0807df3f47",
    "tags": [
      "windows-xp",
      "glitch",
      "frutiger-aero",
      "y2k",
      "sdf",
      "iridescent",
      "thin-film",
      "2d"
    ],
    "parents": [],
    "author": "u7y1evhf0znj",
    "author_name": "ksin",
    "author_url": "/u/ksin",
    "created_at": "2026-08-18T02:01:39.816Z",
    "poster_url": "/posters/k0xfhmb2.avif",
    "stats": {
      "slops": 1,
      "views": 214,
      "forks": 0
    },
    "self": "/api/v1/shaders/k0xfhmb2",
    "isf": "/*{\n  \"DESCRIPTION\": \"The Windows XP window-trail glitch, rendered with the gloss the era actually wanted. A dialog is being dragged across a Bliss-green hill, and the desktop never repaints behind it, so every position it has ever occupied stays painted on the screen. The trail is not decoration: each copy in the cascade is the SAME window sampled at a point in its own past, drawn oldest first, so what you are looking at is literally the path it has been dragged along. Some stale copies never finished repainting and smear one scanline sideways across their own body. Over the top of that is the Frutiger Aero treatment the period was reaching for and the hardware could not quite manage - Luna titlebars with a specular sweep riding across them, soap bubbles with iridescent films, a sun with lens ghosts, oversaturated skies, bloom, a taskbar with task buttons and a system tray, desktop icons, and a start menu. Everything is drawn from signed distance fields; there is no texture anywhere. Twenty-two sliders and one switch: speed, how many copies survive, the gap between them, drag distance, per-copy glitch jitter, tearing, how much the oldest copies wash out, Aero glass, bubbles, sun flare, cloud cover, vividness, bloom, taskbar, scanlines, vignette, plus how many windows are being dragged at once, desktop icons, the two-pane Luna start menu, open or shut, and the pointer that is still holding the live window's titlebar, and three that decide what the failed repaint left behind - text returning as characters from no alphabet, query dialogs and stray question marks, and rows that tear sideways or invert into a stale selection block.\",\n  \"CREDIT\": \"CC0\",\n  \"CATEGORIES\": [\"generator\", \"windows-xp\", \"glitch\", \"frutiger-aero\", \"nostalgia\", \"2d\", \"sdf\"],\n  \"INPUTS\": [\n    { \"NAME\": \"uSpeed\",    \"TYPE\": \"float\", \"DEFAULT\": 1.00,  \"MIN\": 0.0,   \"MAX\": 3.0 },\n    { \"NAME\": \"uCount\",    \"TYPE\": \"float\", \"DEFAULT\": 34.0,  \"MIN\": 1.0,   \"MAX\": 48.0 },\n    { \"NAME\": \"uTrail\",    \"TYPE\": \"float\", \"DEFAULT\": 0.130, \"MIN\": 0.005, \"MAX\": 0.25 },\n    { \"NAME\": \"uDrift\",    \"TYPE\": \"float\", \"DEFAULT\": 1.00,  \"MIN\": 0.0,   \"MAX\": 2.0 },\n    { \"NAME\": \"uJitter\",   \"TYPE\": \"float\", \"DEFAULT\": 0.35,  \"MIN\": 0.0,   \"MAX\": 3.0 },\n    { \"NAME\": \"uSmear\",    \"TYPE\": \"float\", \"DEFAULT\": 0.45,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uFade\",     \"TYPE\": \"float\", \"DEFAULT\": 0.18,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uGlass\",    \"TYPE\": \"float\", \"DEFAULT\": 0.55,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uBubbles\",  \"TYPE\": \"float\", \"DEFAULT\": 0.60,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uFlare\",    \"TYPE\": \"float\", \"DEFAULT\": 0.70,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uClouds\",   \"TYPE\": \"float\", \"DEFAULT\": 0.75,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uSat\",      \"TYPE\": \"float\", \"DEFAULT\": 1.15,  \"MIN\": 0.0,   \"MAX\": 2.0 },\n    { \"NAME\": \"uBloom\",    \"TYPE\": \"float\", \"DEFAULT\": 0.45,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uTaskbar\",  \"TYPE\": \"float\", \"DEFAULT\": 1.00,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uScan\",     \"TYPE\": \"float\", \"DEFAULT\": 0.15,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uVignette\", \"TYPE\": \"float\", \"DEFAULT\": 0.30,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uCascades\", \"TYPE\": \"float\", \"DEFAULT\": 1.00,  \"MIN\": 1.0,   \"MAX\": 4.0 },\n    { \"NAME\": \"uIcons\",    \"TYPE\": \"float\", \"DEFAULT\": 1.00,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uStart\",    \"TYPE\": \"bool\",  \"DEFAULT\": false },\n    { \"NAME\": \"uCursor\",   \"TYPE\": \"float\", \"DEFAULT\": 1.00,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uAlien\",    \"TYPE\": \"float\", \"DEFAULT\": 0.40,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uQuestion\", \"TYPE\": \"float\", \"DEFAULT\": 0.45,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uGarble\",   \"TYPE\": \"float\", \"DEFAULT\": 0.40,  \"MIN\": 0.0,   \"MAX\": 1.0 }\n  ]\n}*/\n\n// NOT RESPONDING - ISF port of the Shadertoy/WebGL2 version\n// (GLSL ES 1.00: gl_FragColor, TIME/RENDERSIZE).\n\n#define PI 3.14159265359\n// ---- the virtual desktop is 1280x720 -----------------------\nconst vec2 SCREEN = vec2(1280.0, 720.0);\n// The visible desktop width, which follows the viewport's aspect. Anchoring\n// the UI to a fixed 1280 box and centring it left gaps at both ends on\n// anything wider than 16:9 — the taskbar floated, the icons sat inset.\nfloat gSW;\nconst vec2 WSZ    = vec2(430.0, 196.0);   // dialog size, in desktop pixels\nfloat hash11(float n){ return fract(sin(n) * 43758.5453123); }\nfloat hash12(vec2 p){\n p = fract(p * vec2(123.34, 456.21));\n p += dot(p, p + 45.32);\n return fract(p.x * p.y);\n}\nfloat vnoise2(vec2 p){\n vec2 i = floor(p), f = fract(p);\n f = f * f * (3.0 - 2.0 * f);\n float a = hash12(i);\n float b = hash12(i + vec2(1.0, 0.0));\n float c = hash12(i + vec2(0.0, 1.0));\n float d = hash12(i + vec2(1.0, 1.0));\n return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n}\nfloat fbm2(vec2 p){\n float s = 0.0, a = 0.5;\n for (int i = 0; i < 5; i++){\n  s += a * vnoise2(p);\n  p *= 2.03;\n  a *= 0.5;\n }\n return s;\n}\n// Billow noise — the ridges of |2n-1| flipped, which gives rounded lumps\n// instead of fbm's smooth hills. This is what makes cumulus look cauliflowered\n// rather than smeared.\nfloat billow2(vec2 p){\n float s = 0.0, a = 0.5;\n for (int i = 0; i < 5; i++){\n  s += a * (1.0 - abs(2.0 * vnoise2(p) - 1.0));\n  p *= 2.11;\n  a *= 0.5;\n }\n return s;\n}\n// signed distance to a rounded box, in pixels\nfloat rbox(vec2 p, vec2 hs, float r){\n vec2 d = abs(p) - hs + r;\n return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - r;\n}\n// 1 inside, 0 outside, antialiased over ~1 desktop pixel\nfloat fill(float d, float aa){ return smoothstep(aa, -aa, d); }\n// distance to a 2D segment\nfloat sdSeg2(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// A question mark, built from a hook of capsules and a dot rather than a\n// masked ring — no angle test, so nothing aliases at small sizes.\nfloat sdQuestion(vec2 p, float s){\n p /= s;\n float d = sdSeg2(p, vec2(-3.2, -4.4), vec2(-1.2, -7.1));\n d = min(d, sdSeg2(p, vec2(-1.2, -7.1), vec2( 1.9, -6.7)));\n d = min(d, sdSeg2(p, vec2( 1.9, -6.7), vec2( 3.2, -4.0)));\n d = min(d, sdSeg2(p, vec2( 3.2, -4.0), vec2( 0.7, -1.0)));\n d = min(d, sdSeg2(p, vec2( 0.7, -1.0), vec2( 0.0,  2.0)));\n d -= 1.35;\n d = min(d, length(p - vec2(0.0, 5.2)) - 1.5);\n return d * s;\n}\n// One character of an unknown script: a few strokes thrown down by hash,\n// sometimes with a ring or a dot. Reads as writing without being any.\nfloat alienGlyph(vec2 p, float sd, float aa){\n float d = 1e9;\n for (int k = 0; k < 3; k++){\n  float fk = float(k);\n  vec2  p0 = vec2((hash11(sd * 13.0 + fk * 5.1) - 0.5) * 7.0,\n      (hash11(sd * 29.0 + fk * 3.7) - 0.5) * 9.0);\n  float an = hash11(sd * 7.0 + fk * 11.3) * PI;\n  float ln = 1.6 + 3.4 * hash11(sd * 17.0 + fk * 2.3);\n  vec2  dr = vec2(cos(an), sin(an)) * ln;\n  d = min(d, sdSeg2(p, p0 - dr, p0 + dr) - 1.05);\n }\n float extra = hash11(sd * 41.0);\n if (extra > 0.78)      d = min(d, abs(length(p) - 3.4) - 1.0);\n else if (extra > 0.62) d = min(d, length(p - vec2(0.0, -4.0)) - 1.3);\n return fill(d, aa);\n}\nfloat sdTriangle(vec2 p, vec2 p0, vec2 p1, vec2 p2){\n vec2 e0 = p1 - p0, e1 = p2 - p1, e2 = p0 - p2;\n vec2 v0 = p - p0,  v1 = p - p1,  v2 = p - p2;\n vec2 q0 = v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0);\n vec2 q1 = v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0);\n vec2 q2 = v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0);\n float s = sign(e0.x * e2.y - e0.y * e2.x);\n vec2 d = min(min(vec2(dot(q0, q0), s * (v0.x * e0.y - v0.y * e0.x)),\n     vec2(dot(q1, q1), s * (v1.x * e1.y - v1.y * e1.x))),\n     vec2(dot(q2, q2), s * (v2.x * e2.y - v2.y * e2.x)));\n return -sqrt(d.x) * sign(d.y);\n}\n// ---- 4x6 bit-packed font -------------------------------------\n// 4 cols x 6 rows = 24 bits, exactly float32's exact-integer limit,\n// so one glyph is one float. GLSL ES 1.00 has no bitwise ops, so\n// bits come out with mod(floor(v / exp2(i)), 2.0).\nfloat glyphBits(float c){\n if (c < 2.5) return 630678.0;\n else if (c < 3.5) return 497559.0;\n else if (c < 4.5) return 921886.0;\n else if (c < 5.5) return 498071.0;\n else if (c < 6.5) return 988959.0;\n else if (c < 7.5) return 71455.0;\n else if (c < 8.5) return 957726.0;\n else if (c < 9.5) return 630681.0;\n else if (c < 10.5) return 467495.0;\n else if (c < 11.5) return 152654.0;\n else if (c < 12.5) return 611161.0;\n else if (c < 13.5) return 987409.0;\n else if (c < 14.5) return 630777.0;\n else if (c < 15.5) return 647097.0;\n else if (c < 16.5) return 432534.0;\n else if (c < 17.5) return 71575.0;\n else if (c < 18.5) return 973206.0;\n else if (c < 19.5) return 612247.0;\n else if (c < 20.5) return 493086.0;\n else if (c < 21.5) return 139823.0;\n else if (c < 22.5) return 432537.0;\n else if (c < 23.5) return 420249.0;\n else if (c < 24.5) return 458649.0;\n else if (c < 25.5) return 628377.0;\n else if (c < 26.5) return 140953.0;\n else if (c < 27.5) return 987727.0;\n else if (c < 28.5) return 433110.0;\n else if (c < 29.5) return 467506.0;\n else if (c < 30.5) return 988807.0;\n else if (c < 31.5) return 493191.0;\n else if (c < 32.5) return 282453.0;\n else if (c < 33.5) return 493343.0;\n else if (c < 34.5) return 431894.0;\n else if (c < 35.5) return 140431.0;\n else if (c < 36.5) return 431766.0;\n else if (c < 37.5) return 429718.0;\n else if (c < 38.5) return 8224.0;\n else if (c < 39.5) return 131072.0;\n else if (c < 40.5) return 3840.0;\n return 0.0;\n}\n// ---- string table: 6 bits per char, 4 chars per float ---------\nvec4 strPack(float s){\n if (s < 0.5) return vec4(4990292.0, 21.0, 0.0, 0.0);   // START\n else if (s < 1.5) return vec4(1054350.0, 5837712.0, 78229.0, 0.0);   // MY COMPUTER\n else if (s < 2.5) return vec4(6832531.0, 287556.0, 62083.0, 0.0);   // RECYCLE BIN\n else if (s < 3.5) return vec4(1316494.0, 3760400.0, 5329862.0, 0.0);   // MY DOCUMENTS\n else if (s < 4.5) return vec4(1659850.0, 5530579.0, 0.0, 0.0);   // INTERNET\n else if (s < 5.5) return vec4(1319315.0, 5665166.0, 1369.0, 0.0);   // README.TXT\n else if (s < 6.5) return vec4(2642318.0, 3477570.0, 5006978.0, 0.0);   // MEDIA PLAYER\n else if (s < 7.5) return vec4(4207562.0, 25.0, 0.0, 0.0);   // INBOX\n else if (s < 8.5) return vec4(4462222.0, 5853450.0, 82323.0, 0.0);   // MY PICTURES\n else if (s < 9.5) return vec4(5853588.0, 6580689.0, 6.0, 0.0);   // SETUP.EXE\n else if (s < 10.5) return vec4(5567492.0, 316435.0, 1634449.0, 13.0);   // CONTROL PANEL\n else if (s < 11.5) return vec4(4510089.0, 1372289.0, 4547841.0, 5583889.0);   // HELP AND SUPPORT\n else if (s < 12.5) return vec4(4989332.0, 580.0, 0.0, 0.0);   // SEARCH\n else if (s < 13.5) return vec4(10286483.0, 2535.0, 0.0, 0.0);   // RUN...\n else if (s < 14.5) return vec4(316226.0, 2163921.0, 5300371.0, 0.0);   // ALL PROGRAMS\n else if (s < 15.5) return vec4(295949.0, 29136.0, 0.0, 0.0);   // LOG OFF\n else if (s < 16.5) return vec4(4011413.0, 1864705.0, 0.0, 0.0);   // TURN OFF\n else if (s < 17.5) return vec4(1659919.0, 20625.0, 0.0, 0.0);   // NOTEPAD\n else if (s < 18.5) return vec4(3973265.0, 21.0, 0.0, 0.0);   // PAINT\n else if (s < 19.5) return vec4(5325198.0, 1606598.0, 19.0, 0.0);   // MESSENGER\n else if (s < 20.5) return vec4(3675790.0, 1090838.0, 0.0, 0.0);   // MY MUSIC\n else if (s < 21.5) return vec4(8284445.0, 28.0, 0.0, 0.0);   // 18:30\n else if (s < 22.5) return vec4(2446993.0, 1577936.0, 5047507.0, 0.0);   // PYTHON ERROR\n else if (s < 23.5) return vec4(349199.0, 4538771.0, 2642896.0, 527.0);   // NOT RESPONDING\n else if (s < 24.5) return vec4(3937934.0, 4293958.0, 787.0, 0.0);   // MY NETWORK\n else if (s < 25.5) return vec4(3495312.0, 50192.0, 0.0, 0.0);   // OUTLOOK\n else if (s < 26.5) return vec4(3479110.0, 5006544.0, 0.0, 0.0);   // EXPLORER\n else if (s < 27.5) return vec4(2675732.0, 5021845.0, 6.0, 0.0);   // SOLITAIRE\n else if (s < 28.5) return vec4(10326153.0, 26182.0, 0.0, 0.0);   // HAX.EXE\n else if (s < 29.5) return vec4(287234.0, 1577424.0, 5022798.0, 7869702.0);   // AGE OF EMPIRES 2\n else if (s < 30.5) return vec4(1630861.0, 1651352.0, 0.0, 0.0);   // LIMEWIRE\n else if (s < 31.5) return vec4(283590.0, 99343.0, 0.0, 0.0);   // END NOW\n else if (s < 32.5) return vec4(1110148.0, 838.0, 0.0, 0.0);   // CANCEL\n else if (s < 33.5) return vec4(316418.0, 5325198.0, 1606598.0, 19.0);   // AOL MESSENGER\n else if (s < 34.5) return vec4(324878.0, 5325198.0, 1606598.0, 19.0);   // MSN MESSENGER\n else if (s < 35.5) return vec4(584198.0, 842.0, 0.0, 0.0);   // E-MAIL\n else if (s < 36.5) return vec4(6035086.0, 4219210.0, 20.0, 0.0);   // MY VIDEOS\n else if (s < 37.5) return vec4(3974353.0, 5321109.0, 0.0, 0.0);   // PRINTERS\n else if (s < 38.5) return vec4(3994628.0, 348422.0, 1045.0, 0.0);   // CONNECT TO\n else if (s < 39.5) return vec4(287234.0, 464.0, 0.0, 0.0);   // AGE OF\n else if (s < 40.5) return vec4(2691974.0, 344467.0, 30.0, 0.0);   // EMPIRES 2\n return vec4(0.0);\n}\n// One character out of the packed string. 6 bits each, 4 per component.\nfloat charAt(vec4 s, float i){\n if (i > 15.5 || i < 0.0) return 0.0;\n float g = floor(i / 4.0);\n float v = (g < 0.5) ? s.x : (g < 1.5) ? s.y : (g < 2.5) ? s.z : s.w;\n return mod(floor(v / exp2(6.0 * mod(i, 4.0))), 64.0);\n}\n// Real text. `h` is HALF the cap height; d is relative to the left edge and\n// the vertical centre of the line. Returns coverage, 2x2 supersampled so the\n// bitmap doesn't crawl when the desktop is scaled by a non-integer factor.\nfloat textCov(vec2 d, float sid, float h){\n // cheap box reject FIRST — strPack and glyphBits are long if-ladders and\n // this is called dozens of times per pixel across the whole UI\n if (d.x < -1.5 || d.x > 32.0 * h || abs(d.y) > h * 1.8) return 0.0;\n vec4  s  = strPack(sid);\n float px = 2.0 * h / 5.0;          // one font pixel; 5 rows make the cap\n float adv = 5.0 * px;              // 4 columns + 1 of spacing\n float cov = 0.0;\n for (int k = 0; k < 4; k++){\n  float fk = float(k);\n  vec2 o = (vec2(mod(fk, 2.0), floor(fk / 2.0)) - 0.5) * px * 0.5;\n  vec2 e = d + o;\n  float ci = floor(e.x / adv);\n  if (ci < 0.0 || ci > 15.5) continue;\n  float ch = charAt(s, ci);\n  if (ch < 1.5) continue;                       // end or space\n  float cx = floor(mod(e.x, adv) / px);\n  float ry = floor((e.y + h) / px);             // row 0 at the cap top\n  if (cx > 3.5 || ry < 0.0 || ry > 5.5) continue;\n  cov += mod(floor(glyphBits(ch) / exp2(ry * 4.0 + cx)), 2.0);\n }\n return cov * 0.25;\n}\n// draw a string; at.x = left edge, at.y = line centre\nvoid drawText(inout vec3 col, vec2 q, vec2 at, float sid, float h, vec3 c, float alpha){\n col = mix(col, c, textCov(q - at, sid, h) * alpha);\n}\n// how wide a string will be, for centring\nfloat textW(float sid, float h){\n vec4 s = strPack(sid);\n float n = 0.0;\n for (int i = 0; i < 16; i++){\n  if (charAt(s, float(i)) < 0.5) break;\n  n += 1.0;\n }\n return n * 5.0 * (2.0 * h / 5.0);\n}\n// A run of \"text\". A row of identical blocks reads as squares, not words —\n// so every character gets its own box: cap-height or x-height sitting on a\n// shared baseline, varying width, the odd descender, and gaps where the\n// spaces fall. Domain repetition off x means the whole run costs O(1)\n// instead of a loop, which matters because this is called everywhere.\n// h is HALF the cap height; at.x is the left edge, at.y the line centre.\nfloat sdTextRun(vec2 d, float w, float h, float seed){\n if (d.x < -1.0 || d.x > w + 1.0 || abs(d.y) > h * 2.4) return 1e9;\n float cw = h * 1.72;                                  // character advance\n float ci = floor(d.x / cw);\n float fx = mod(d.x, cw) - cw * 0.5;\n float r1 = hash11(seed * 1.7 + ci * 3.7);\n float r2 = hash11(seed * 2.3 + ci * 9.1);\n if (r1 > 0.87) return 1e9;                            // a space\n float gw = cw * (0.24 + 0.15 * r2);\n float gh = mix(0.68, 1.0, step(0.52, r2)) * h;        // x-height or cap\n float cy = h - gh;                                    // sit on the baseline\n if (r1 < 0.11){ gh = h * 0.95; cy = h * 0.28; }       // a descender\n return rbox(vec2(fx, d.y - cy), vec2(gw, gh), 0.35);\n}\nvoid textRun(inout vec3 col, vec2 q, vec2 at, float w, float h, vec3 c,\n   float seed, float aa, float alpha){\n col = mix(col, c, fill(sdTextRun(q - at, w, h, seed), aa) * alpha);\n}\n// ============================================================\n// THE DESKTOP — Bliss, but glossier than it ever really was\n// ============================================================\nvec3 desktop(vec2 p, float t, float aa){\n vec2 uvn = p / SCREEN;\n // sky: deep at the top, washing pale toward the horizon.\n // NB uvn.y is 0 at the TOP here — p was flipped to y-down for the UI.\n vec3 col = mix(vec3(0.16, 0.42, 0.86), vec3(0.60, 0.80, 0.97), pow(uvn.y, 0.85));\n col = mix(col, vec3(0.80, 0.90, 0.99), pow(uvn.y, 3.5) * 0.75);\n // sun, high right\n vec2 sunP = vec2(gSW * 0.84, 150.0);\n float sd  = length(p - sunP);\n col += vec3(1.0, 0.96, 0.86) * exp(-sd * 0.010) * 1.30 * uFlare;\n col += vec3(1.0, 0.90, 0.72) * exp(-sd * 0.0022) * 0.42 * uFlare;\n // ---- clouds, in the two kinds Bliss actually has ----\n // 1. cirrus: thin feathered streaks high up, stretched hard in x\n vec2 cirp = p * vec2(0.0016, 0.0090) + vec2(t * 0.011, 0.0);\n float cir = fbm2(cirp);\n cir  = smoothstep(0.50, 0.74, cir) * smoothstep(0.46, 0.01, uvn.y);\n cir *= 0.40 + 0.60 * fbm2(cirp * 3.1);                    // break them into wisps\n col  = mix(col, vec3(0.98, 0.99, 1.0), clamp(cir, 0.0, 1.0) * 0.70 * uClouds);\n // 2. cumulus: rounded billows in a band across the middle and along the\n //    horizon, bright white on top with a faintly cooler underside\n vec2 cum = p * 0.0024 + vec2(t * 0.008, 0.0);\n float bil = billow2(cum * vec2(1.0, 1.8));\n // a broad band through the middle, still going at the horizon\n float band = smoothstep(0.10, 0.34, uvn.y) * smoothstep(0.72, 0.44, uvn.y) + 0.10;\n // a narrow threshold window is what gives cumulus a defined edge instead\n // of blanketing the sky in haze — the blue between them matters as much\n float cmask = smoothstep(0.575, 0.645, bil * (0.62 + 0.62 * band)) * uClouds;\n // the underside is where the billow falls away downward\n float under = smoothstep(0.60, 0.42, billow2(cum * vec2(1.0, 1.8) + vec2(0.0, 0.06)));\n vec3 cumC = mix(vec3(1.0), vec3(0.78, 0.85, 0.94), under * 0.70);\n col = mix(col, cumC, clamp(cmask, 0.0, 1.0));\n // the hill — Bliss's one big green curve\n float hy = 470.0\n   + 62.0 * sin(p.x * 0.0042 + 0.6)\n   + 26.0 * sin(p.x * 0.0113 + 2.1)\n   + 10.0 * fbm2(vec2(p.x * 0.010, 3.0));\n float grass = fill(hy - p.y, aa * 1.5);\n if (grass > 0.001){\n  float below = p.y - hy;                              // 0 at the ridge\n  float depth = clamp(below / 250.0, 0.0, 1.0);\n  // Bliss's green is a bright yellow-green on the crown falling to a\n  // deeper green in the near field\n  vec3 g = mix(vec3(0.47, 0.76, 0.16), vec3(0.20, 0.50, 0.09), depth);\n  g = mix(g, vec3(0.66, 0.86, 0.28), pow(1.0 - depth, 5.0) * 0.75);   // sunlit crown\n  // contour banding from the ploughing, following the hill. sqrt packs\n  // the bands tighter toward the ridge, which is the perspective.\n  float bandPhase = sqrt(max(below, 0.0)) * 2.05\n      + 1.6 * sin(p.x * 0.0043)            // the lines aren't straight\n      + 0.7 * fbm2(vec2(p.x * 0.004, 1.0));\n  g *= 1.0 + 0.055 * sin(bandPhase) * smoothstep(0.0, 40.0, below);\n  // mottling and a fine vertical blade grain that coarsens toward us\n  g *= 0.90 + 0.20 * fbm2(p * vec2(0.045, 0.14) + 11.0);\n  g *= 0.94 + 0.13 * vnoise2(p * vec2(0.9 + depth * 2.2, 0.07));\n  // the dark hedgerow shadow strip across the low left\n  float hedge = smoothstep(24.0, 0.0, abs(below - 205.0 - 26.0 * sin(p.x * 0.0052)))\n     * smoothstep(760.0, 420.0, p.x);\n  g = mix(g, vec3(0.10, 0.24, 0.06), hedge * 0.72);\n  // buttercups in the near field\n  if (below > 150.0){\n   vec2 fg  = p * vec2(0.075, 0.135);\n   vec2 fid = floor(fg);\n   if (hash12(fid) > 0.90){\n    vec2 fp = fract(fg) - 0.5;\n    fp -= 0.34 * (vec2(hash12(fid + 1.7), hash12(fid + 3.3)) - 0.5);\n    g = mix(g, vec3(0.95, 0.92, 0.30),\n      smoothstep(0.17, 0.06, length(fp)) * smoothstep(150.0, 260.0, below));\n   }\n  }\n  col = mix(col, g, grass);\n }\n // soap bubbles — the single most Frutiger Aero object there is.\n // Thin-film interference, refraction of what's behind, a Fresnel rim\n // that brightens toward the edge, a sharp specular and a soft second one.\n if (uBubbles > 0.001){\n  for (int i = 0; i < 16; i++){\n   float fi = float(i);\n   float sd0 = hash11(fi * 7.31);\n   float rad = 10.0 + 52.0 * hash11(fi * 3.17);\n   float life = 9.0 + 9.0 * sd0;\n   float ph = fract(t / life + sd0);\n   vec2 bp = vec2(gSW * hash11(fi * 5.11)\n       + (34.0 + 30.0 * sd0) * sin(t * (0.35 + 0.4 * sd0) + fi * 2.1),\n      SCREEN.y * 1.10 - ph * (SCREEN.y * 1.32));\n   // they wobble as they rise — surface tension fighting the drag\n   float wob = 1.0 + 0.05 * sin(t * 2.3 + fi * 4.0);\n   vec2 d = (p - bp) * vec2(wob, 1.0 / wob);\n   float dl = length(d);\n   if (dl > rad * 1.25) continue;\n   float fadeB = smoothstep(0.0, 0.12, ph) * smoothstep(1.0, 0.78, ph) * uBubbles;\n   float body  = fill(dl - rad, aa);\n   float nz    = clamp(1.0 - dl / rad, 0.0, 1.0);      // \"depth\" toward the middle\n   float grz   = 1.0 - sqrt(nz);                        // 0 centre, 1 at the rim\n   // refraction: sample the sky a little offset, so it acts like glass\n   vec2 off = d / rad * 26.0 * grz;\n   vec3 behind = mix(vec3(0.09, 0.34, 0.78), vec3(0.55, 0.80, 0.99),\n       clamp((p.y + off.y) / SCREEN.y, 0.0, 1.0));\n   // thin-film: the interference order runs with the path length\n   float ord = (0.55 + 2.6 * grz) * (0.7 + 0.6 * hash11(fi * 2.9));\n   vec3 film = 0.5 + 0.5 * cos(6.2831 * ord + vec3(0.0, 2.09, 4.19) + fi);\n   film = mix(vec3(dot(film, vec3(0.33))), film, 0.85);\n   vec3 bub = mix(behind, film, 0.42 + 0.34 * grz);\n   bub += vec3(1.0) * pow(grz, 5.0) * 0.55;                    // Fresnel rim\n   col = mix(col, bub, body * (0.30 + 0.42 * grz) * fadeB);\n   col += vec3(1.0) * fill(abs(dl - rad) - 1.3, aa) * 0.40 * fadeB;   // edge line\n   // speculars: one hard, one soft and larger\n   col += vec3(1.0) * fill(length(d - vec2(-rad * 0.38, -rad * 0.42)) - rad * 0.13, aa) * 0.90 * fadeB;\n   col += vec3(0.85, 0.94, 1.0) * fill(length(d - vec2(rad * 0.34, rad * 0.30)) - rad * 0.22, aa) * 0.22 * fadeB;\n  }\n }\n // anamorphic-ish flare streak through the sun\n if (uFlare > 0.001){\n  vec2 fd = p - sunP;\n  col += vec3(0.75, 0.88, 1.0) * exp(-abs(fd.y) * 0.10) * exp(-abs(fd.x) * 0.0016) * 0.30 * uFlare;\n  // ghosts along the sun-centre axis\n  vec2 axis = vec2(gSW, SCREEN.y) * 0.5 - sunP;\n  for (int i = 1; i < 4; i++){\n   float fi = float(i);\n   vec2 gp = sunP + axis * (fi * 0.65);\n   float gd = length(p - gp);\n   col += vec3(0.55, 0.75, 0.95) * exp(-gd * 0.020) * 0.13 * uFlare / fi;\n  }\n }\n return col;\n}\n// A small version of the desktop icon set, for the start menu and the\n// taskbar. q is relative to the icon centre; s is its half-size.\nvoid miniIcon(inout vec3 col, vec2 q, float kind, float s, float aaPx){\n if (max(abs(q.x), abs(q.y)) > s * 1.3) return;      // cheap reject\n q /= s;                                   // work in a unit-ish box, +-1\n // aa arrives in DESKTOP pixels but q is now in units of s — using it\n // unconverted made every small icon s times too soft, which is what the\n // blurry start-menu and taskbar icons were\n float aa = aaPx / s;\n float sh = clamp(q.y * 0.5 + 0.5, 0.0, 1.0);\n if (kind < 0.5){                          // monitor\n  col = mix(col, vec3(0.88, 0.87, 0.82), fill(rbox(q - vec2(0.0, -0.15), vec2(1.0, 0.78), 0.16), aa));\n  col = mix(col, mix(vec3(0.16, 0.44, 0.86), vec3(0.52, 0.78, 0.99), 1.0 - sh),\n    fill(rbox(q - vec2(0.0, -0.2), vec2(0.74, 0.54), 0.08), aa));\n  col = mix(col, vec3(0.78, 0.77, 0.72), fill(rbox(q - vec2(0.0, 0.82), vec2(0.62, 0.16), 0.08), aa));\n } else if (kind < 1.5){                   // recycle bin\n  vec2 bq = q - vec2(0.0, 0.22); bq.x *= 1.0 + bq.y * 0.22;\n  col = mix(col, mix(vec3(0.44, 0.58, 0.72), vec3(0.70, 0.82, 0.92), 1.0 - sh),\n    fill(rbox(bq, vec2(0.62, 0.68), 0.14), aa));\n  col = mix(col, vec3(0.74, 0.85, 0.94), fill(length((q - vec2(0.0, -0.55)) * vec2(1.0, 2.4)) - 0.74, aa));\n } else if (kind < 2.5){                   // folder\n  col = mix(col, vec3(0.86, 0.64, 0.16), fill(rbox(q - vec2(-0.42, -0.66), vec2(0.5, 0.24), 0.1), aa));\n  col = mix(col, vec3(0.96, 0.78, 0.28), fill(rbox(q - vec2(0.0, 0.06), vec2(1.0, 0.7), 0.13), aa));\n  col = mix(col, vec3(1.00, 0.88, 0.46), fill(rbox(q - vec2(0.0, 0.25), vec2(1.0, 0.55), 0.13), aa));\n } else if (kind < 3.5){                   // globe\n  float g = fill(length(q) - 0.92, aa);\n  col = mix(col, mix(vec3(0.08, 0.34, 0.76), vec3(0.36, 0.68, 0.98), 1.0 - sh), g);\n  col = mix(col, vec3(0.90, 0.96, 1.0), g * fill(abs(length(q * vec2(1.0, 0.40)) - 0.36) - 0.08, aa));\n  col = mix(col, vec3(0.90, 0.96, 1.0), g * fill(abs(q.y) - 0.08, aa));\n } else if (kind < 4.5){                   // document\n  col = mix(col, vec3(0.99, 0.99, 0.97), fill(rbox(q, vec2(0.7, 0.92), 0.1), aa));\n  col = mix(col, vec3(0.60, 0.63, 0.68), fill(abs(rbox(q, vec2(0.7, 0.92), 0.1)) - 0.06, aa));\n  col = mix(col, vec3(0.42, 0.46, 0.54), fill(rbox(q - vec2(0.0, -0.28), vec2(0.4, 0.06), 0.03), aa));\n  col = mix(col, vec3(0.42, 0.46, 0.54), fill(rbox(q - vec2(0.0, 0.02), vec2(0.4, 0.06), 0.03), aa));\n  col = mix(col, vec3(0.42, 0.46, 0.54), fill(rbox(q - vec2(-0.14, 0.32), vec2(0.26, 0.06), 0.03), aa));\n } else if (kind < 5.5){                   // media\n  float g = fill(length(q) - 0.92, aa);\n  col = mix(col, mix(vec3(0.24, 0.09, 0.50), vec3(0.60, 0.34, 0.90), 1.0 - sh), g);\n  col = mix(col, vec3(1.0), fill(sdTriangle(q - vec2(0.1, 0.0), vec2(-0.3, -0.42), vec2(-0.3, 0.42), vec2(0.42, 0.0)), aa));\n } else if (kind < 6.5){                   // envelope\n  col = mix(col, vec3(0.98, 0.97, 0.93), fill(rbox(q, vec2(0.98, 0.68), 0.1), aa));\n  col = mix(col, vec3(0.62, 0.62, 0.58), fill(abs(rbox(q, vec2(0.98, 0.68), 0.1)) - 0.06, aa));\n  col = mix(col, vec3(0.78, 0.80, 0.85), fill(max(sdSeg2(q, vec2(-0.98, -0.68), vec2(0.0, 0.1)) - 0.08, -q.y - 0.68), aa));\n  col = mix(col, vec3(0.78, 0.80, 0.85), fill(max(sdSeg2(q, vec2( 0.98, -0.68), vec2(0.0, 0.1)) - 0.08, -q.y - 0.68), aa));\n } else if (kind < 7.5){                   // photo\n  col = mix(col, vec3(0.95, 0.95, 0.91), fill(rbox(q, vec2(0.92, 0.78), 0.1), aa));\n  float ph = fill(rbox(q, vec2(0.72, 0.58), 0.05), aa);\n  col = mix(col, mix(vec3(0.30, 0.62, 0.92), vec3(0.74, 0.90, 0.99), 1.0 - sh), ph);\n  col = mix(col, vec3(0.30, 0.60, 0.20), ph * fill(sdTriangle(q, vec2(-0.72, 0.58), vec2(-0.05, -0.14), vec2(0.46, 0.58)), aa));\n  col = mix(col, vec3(0.98, 0.86, 0.34), ph * fill(length(q - vec2(0.38, -0.3)) - 0.17, aa));\n } else if (kind < 8.5){                   // disc\n  float g = fill(length(q) - 0.92, aa);\n  col = mix(col, mix(vec3(0.70, 0.73, 0.80), vec3(0.94, 0.96, 0.99), 1.0 - sh), g);\n  col = mix(col, vec3(0.32, 0.36, 0.44), fill(length(q) - 0.24, aa));\n } else if (kind < 9.5){                   // limewire\n  float g = fill(length(q) - 0.92, aa);\n  col = mix(col, mix(vec3(0.34, 0.66, 0.06), vec3(0.74, 0.95, 0.22), 1.0 - sh), g);\n  col = mix(col, vec3(0.90, 0.98, 0.60), fill(length(q) - 0.60, aa));\n  col = mix(col, vec3(0.44, 0.74, 0.12), fill(abs(q.x) - 0.06, aa) * fill(length(q) - 0.60, aa));\n } else if (kind < 10.5){                  // console\n  col = mix(col, vec3(0.10, 0.11, 0.13), fill(rbox(q, vec2(0.96, 0.76), 0.12), aa));\n  col = mix(col, vec3(0.44, 0.48, 0.55), fill(abs(rbox(q, vec2(0.96, 0.76), 0.12)) - 0.07, aa));\n  col = mix(col, vec3(0.30, 0.95, 0.35), fill(rbox(q - vec2(-0.28, 0.12), vec2(0.36, 0.08), 0.04), aa));\n  col = mix(col, vec3(0.30, 0.95, 0.35), fill(rbox(q - vec2(-0.46, -0.28), vec2(0.18, 0.08), 0.04), aa));\n } else if (kind < 11.5){                  // shield\n  float s2 = rbox(q - vec2(0.0, -0.12), vec2(0.74, 0.56), 0.12);\n  s2 = min(s2, sdTriangle(q, vec2(-0.74, 0.42), vec2(0.74, 0.42), vec2(0.0, 1.0)));\n  col = mix(col, mix(vec3(0.58, 0.14, 0.10), vec3(0.90, 0.36, 0.24), 1.0 - sh), fill(s2, aa));\n  col = mix(col, vec3(0.98, 0.86, 0.42), fill(abs(s2) - 0.09, aa));\n } else if (kind < 12.5){                  // AIM — the running man\n  float g = fill(rbox(q, vec2(0.86, 0.92), 0.14), aa);\n  col = mix(col, mix(vec3(0.92, 0.78, 0.10), vec3(1.0, 0.94, 0.42), 1.0 - sh), g);\n  col = mix(col, vec3(0.20, 0.16, 0.02), g * fill(length(q - vec2(0.06, -0.5)) - 0.2, aa));\n  col = mix(col, vec3(0.20, 0.16, 0.02), g * fill(sdSeg2(q, vec2(-0.1, -0.2), vec2(0.2, 0.28)) - 0.12, aa));\n  col = mix(col, vec3(0.20, 0.16, 0.02), g * fill(sdSeg2(q, vec2(0.2, 0.28), vec2(-0.2, 0.72)) - 0.1, aa));\n  col = mix(col, vec3(0.20, 0.16, 0.02), g * fill(sdSeg2(q, vec2(0.2, 0.28), vec2(0.6, 0.66)) - 0.1, aa));\n } else {                                  // MSN — the butterfly\n  vec2 w = vec2(abs(q.x), q.y);\n  float b = length((w - vec2(0.42, -0.22)) * vec2(1.0, 1.5)) - 0.44;\n  b = min(b, length((w - vec2(0.34, 0.42)) * vec2(1.0, 1.3)) - 0.34);\n  col = mix(col, mix(vec3(0.24, 0.62, 0.96), vec3(0.62, 0.86, 1.0), 1.0 - sh), fill(b, aa));\n  col = mix(col, vec3(0.10, 0.34, 0.70), fill(rbox(q, vec2(0.09, 0.62), 0.08), aa));\n }\n}\n// ============================================================\n// DESKTOP ICONS — two columns down the left, XP style: a glossy\n// 32px tile, then two lines of shadowed white label under it\n// ============================================================\nvoid desktopIcons(inout vec3 col, vec2 p, float aa){\n for (int i = 0; i < 12; i++){\n  float fi = float(i);\n  // XP's grid: hard against the left edge, 76px cells\n  vec2 c = vec2(44.0 + floor(fi / 6.0) * 78.0,\n     40.0 + mod(fi, 6.0) * 84.0);\n  vec2 q = p - c;\n  if (dot(q, q) > 4200.0) continue;                 // cheap reject\n  float h = hash11(fi * 9.17);\n  float shade = clamp(q.y / 30.0 + 0.5, 0.0, 1.0);\n  // A BIJECTION, not a hash. Hashing 12 slots into 12 kinds collides by\n  // the birthday problem - it shipped with two HAX.EXE and two AGE OF\n  // EMPIRES 2. 5 is coprime with 12, so fi*5 mod 12 walks all twelve\n  // kinds exactly once and still scatters them (0,5,10,3,8,1,...).\n  // Slot 0 lands on kind 0, which puts My Computer top-left like XP.\n  float kind = mod(fi * 5.0, 12.0);\n  float tint = hash11(fi * 5.77);\n  // the label is DERIVED from the kind, not hashed separately — they\n  // used to disagree, so a globe could be captioned RECYCLE BIN\n  float lbl = kind + 1.0;                       // kinds 0..8 -> strings 1..9\n  if (kind > 8.5) lbl = 30.0;                   // LIMEWIRE\n  if (kind > 9.5) lbl = 28.0;                   // HAX.EXE\n  if (kind > 10.5) lbl = 29.0;                  // AGE OF EMPIRES 2\n  if (kind < 0.5){\n   // My Computer — a CRT on its stand\n   col = mix(col, vec3(0.80, 0.79, 0.74), fill(rbox(q - vec2(0.0, 10.0), vec2(10.0, 2.5), 1.2), aa));\n   col = mix(col, vec3(0.86, 0.85, 0.80), fill(rbox(q - vec2(0.0, 7.0), vec2(4.5, 3.5), 1.0), aa));\n   col = mix(col, vec3(0.90, 0.89, 0.84), fill(rbox(q - vec2(0.0, -3.0), vec2(15.0, 11.5), 2.5), aa));\n   float scr = fill(rbox(q - vec2(0.0, -4.0), vec2(12.0, 8.2), 1.5), aa);\n   col = mix(col, mix(vec3(0.10, 0.34, 0.74), vec3(0.42, 0.70, 0.98), shade), scr);\n   col = mix(col, vec3(1.0),\n     fill(sdTriangle(q, vec2(-11.0, -11.5), vec2(-2.0, -11.5), vec2(-11.0, -2.0)), aa) * scr * 0.40);\n  } else if (kind < 1.5){\n   // Recycle Bin — a tapered ridged bin with an ellipse lid\n   vec2 bq = q - vec2(0.0, 3.5);\n   bq.x *= 1.0 + bq.y * 0.030;\n   float body = fill(rbox(bq, vec2(9.5, 10.0), 2.0), aa);\n   col = mix(col, mix(vec3(0.42, 0.56, 0.70), vec3(0.66, 0.78, 0.88), 1.0 - shade), body);\n   col = mix(col, vec3(0.38, 0.50, 0.63), body * fill(abs(mod(q.x + 12.0, 6.0) - 3.0) - 0.85, aa) * 0.65);\n   float lid = length((q - vec2(0.0, -8.5)) * vec2(1.0, 2.4)) - 11.0;\n   col = mix(col, vec3(0.72, 0.83, 0.92), fill(lid, aa));\n   col = mix(col, vec3(0.46, 0.60, 0.74), fill(abs(lid) - 1.2, aa));\n  } else if (kind < 2.5){\n   // a manila folder\n   col = mix(col, vec3(0.86, 0.64, 0.16), fill(rbox(q - vec2(-6.5, -10.5), vec2(8.0, 4.0), 1.5), aa));\n   col = mix(col, vec3(0.95, 0.76, 0.26), fill(rbox(q - vec2(0.0, 1.0), vec2(15.0, 11.0), 2.0), aa));\n   col = mix(col, vec3(1.00, 0.87, 0.44), fill(rbox(q - vec2(0.0, 4.0), vec2(15.0, 8.5), 2.0), aa));\n  } else if (kind < 3.5){\n   // the internet, as a globe\n   float g = fill(length(q) - 14.0, aa);\n   col = mix(col, mix(vec3(0.06, 0.30, 0.70), vec3(0.30, 0.64, 0.96), 1.0 - shade), g);\n   col = mix(col, vec3(0.88, 0.95, 1.0), g * fill(abs(length(q * vec2(1.0, 0.40)) - 5.6) - 1.0, aa) * 0.9);\n   col = mix(col, vec3(0.88, 0.95, 1.0), g * fill(abs(q.y) - 1.0, aa) * 0.9);\n   col = mix(col, vec3(0.88, 0.95, 1.0), g * fill(abs(length(q * vec2(0.40, 1.0)) - 5.6) - 1.0, aa) * 0.9);\n   col += vec3(1.0) * fill(length(q - vec2(-5.0, -6.0)) - 4.0, aa) * 0.28;\n  } else if (kind < 4.5){\n   // a text document, corner turned down\n   float pg = rbox(q, vec2(11.0, 14.0), 1.5);\n   col = mix(col, vec3(0.99, 0.99, 0.97), fill(pg, aa));\n   col = mix(col, vec3(0.62, 0.64, 0.68), fill(abs(pg) - 0.8, aa));\n   col = mix(col, vec3(0.84, 0.85, 0.88),\n     fill(sdTriangle(q, vec2(4.0, -14.0), vec2(11.0, -14.0), vec2(11.0, -7.0)), aa));\n   for (int j = 0; j < 5; j++){\n    float fj = float(j);\n    col = mix(col, vec3(0.40, 0.44, 0.52),\n      fill(rbox(q - vec2(-1.0, -5.0 + fj * 5.0), vec2(6.5, 0.9), 0.4), aa));\n   }\n  } else if (kind < 5.5){\n   // a media player\n   float g = fill(length(q) - 14.0, aa);\n   col = mix(col, mix(vec3(0.26, 0.10, 0.52), vec3(0.60, 0.34, 0.90), 1.0 - shade), g);\n   col = mix(col, vec3(1.0),\n     fill(sdTriangle(q - vec2(1.5, 0.0), vec2(-4.5, -6.5), vec2(-4.5, 6.5), vec2(6.5, 0.0)), aa));\n   col += vec3(1.0) * fill(length(q - vec2(-5.0, -6.0)) - 4.0, aa) * 0.24;\n  } else if (kind < 6.5){\n   // an envelope\n   col = mix(col, vec3(0.97, 0.96, 0.92), fill(rbox(q, vec2(15.0, 10.5), 1.5), aa));\n   col = mix(col, vec3(0.66, 0.66, 0.62), fill(abs(rbox(q, vec2(15.0, 10.5), 1.5)) - 0.8, aa));\n   // the flap, two edges meeting in the middle\n   col = mix(col, vec3(0.80, 0.82, 0.86),\n     fill(max(sdSeg2(q, vec2(-15.0, -10.5), vec2(0.0, 1.5)) - 1.1,\n       -q.y - 10.5), aa));\n   col = mix(col, vec3(0.80, 0.82, 0.86),\n     fill(max(sdSeg2(q, vec2( 15.0, -10.5), vec2(0.0, 1.5)) - 1.1,\n       -q.y - 10.5), aa));\n  } else if (kind < 7.5){\n   // a photo in a frame\n   col = mix(col, vec3(0.94, 0.94, 0.90), fill(rbox(q, vec2(14.0, 12.0), 1.5), aa));\n   float ph = fill(rbox(q, vec2(11.0, 9.0), 0.8), aa);\n   col = mix(col, mix(vec3(0.30, 0.62, 0.92), vec3(0.72, 0.88, 0.99), 1.0 - shade), ph);\n   col = mix(col, vec3(0.30, 0.60, 0.20),\n     ph * fill(sdTriangle(q, vec2(-11.0, 9.0), vec2(-1.0, -2.0), vec2(7.0, 9.0)), aa));\n   col = mix(col, vec3(0.98, 0.86, 0.34), ph * fill(length(q - vec2(5.5, -4.5)) - 2.6, aa));\n  } else if (kind < 8.5){\n   // a disc\n   float g = fill(length(q) - 14.0, aa);\n   col = mix(col, mix(vec3(0.72, 0.74, 0.80), vec3(0.93, 0.95, 0.99), 1.0 - shade), g);\n   // the sheen band that CDs always had in these icon sets\n   col = mix(col, mix(vec3(0.55, 0.80, 0.95), vec3(0.90, 0.70, 0.95), tint),\n     g * fill(abs(q.x * 0.6 + q.y) - 5.0, aa) * 0.55);\n   col = mix(col, vec3(0.62, 0.66, 0.72), fill(abs(length(q) - 4.6) - 0.9, aa) * g);\n   col = mix(col, vec3(0.30, 0.34, 0.42), fill(length(q) - 3.4, aa));\n  } else if (kind < 9.5){\n   // LimeWire — the lime-green orb, cut like the fruit\n   float g = fill(length(q) - 14.0, aa);\n   col = mix(col, mix(vec3(0.36, 0.68, 0.06), vec3(0.72, 0.94, 0.20), 1.0 - shade), g);\n   col = mix(col, vec3(0.90, 0.98, 0.60), fill(length(q) - 9.5, aa));\n   for (int w = 0; w < 5; w++){                       // the segments\n    float fw = float(w) * 1.2566;\n    col = mix(col, vec3(0.44, 0.74, 0.12),\n      fill(sdSeg2(q, vec2(0.0), vec2(cos(fw), sin(fw)) * 9.5) - 0.8, aa));\n   }\n   col += vec3(1.0) * fill(length(q - vec2(-5.0, -6.5)) - 3.6, aa) * 0.30;\n  } else if (kind < 10.5){\n   // hax.exe — a console with a prompt in it\n   col = mix(col, vec3(0.10, 0.11, 0.13), fill(rbox(q, vec2(15.0, 12.0), 2.0), aa));\n   col = mix(col, vec3(0.42, 0.46, 0.52), fill(abs(rbox(q, vec2(15.0, 12.0), 2.0)) - 0.9, aa));\n   col = mix(col, vec3(0.30, 0.33, 0.38), fill(rbox(q - vec2(0.0, -9.0), vec2(15.0, 3.0), 2.0), aa));\n   for (int w = 0; w < 3; w++){\n    float fw = float(w);\n    col = mix(col, vec3(0.30, 0.95, 0.35),\n      fill(rbox(q - vec2(-6.0 + fw * 1.5, -1.0 + fw * 5.0),\n         vec2(5.0 - fw * 1.2, 1.0), 0.4), aa));\n   }\n  } else {\n   // Age of Empires — a shield with a keep on it\n   float sh = rbox(q - vec2(0.0, -2.0), vec2(12.0, 9.0), 2.0);\n   sh = min(sh, sdTriangle(q, vec2(-12.0, 6.0), vec2(12.0, 6.0), vec2(0.0, 15.0)));\n   col = mix(col, mix(vec3(0.55, 0.13, 0.10), vec3(0.88, 0.34, 0.22), 1.0 - shade), fill(sh, aa));\n   col = mix(col, vec3(0.98, 0.86, 0.42), fill(abs(sh) - 1.1, aa));\n   // a little keep: three merlons over a block\n   col = mix(col, vec3(0.98, 0.90, 0.60), fill(rbox(q - vec2(0.0, -1.0), vec2(6.5, 4.0), 0.6), aa));\n   for (int w = 0; w < 3; w++){\n    float fw = float(w) - 1.0;\n    col = mix(col, vec3(0.98, 0.90, 0.60),\n      fill(rbox(q - vec2(fw * 4.6, -7.0), vec2(1.6, 2.6), 0.4), aa));\n   }\n  }\n  // Label — derived from the icon, so the caption always matches.\n  // The grid pitch is 78px and a char costs 2h = 6.4px, so anything past\n  // 12 chars spills into the next column. Every desktop label is <= 12\n  // except AGE OF EMPIRES 2 (16 chars = 102px), which ran into MY\n  // COMPUTER and off the left edge of the screen. Shrinking it to fit\n  // turned it into an unreadable smudge, so it wraps over two lines the\n  // way XP does, out of a pre-split pair of strings. NB any label added\n  // past 12 chars needs the same treatment - the font can't wrap itself.\n  float l2 = (lbl > 28.5 && lbl < 29.5) ? 40.0 : 0.0;   // EMPIRES 2\n  if (l2 > 0.5) lbl = 39.0;                             // AGE OF\n  float lw = textW(lbl, 3.2);\n  drawText(col, q, vec2(-lw * 0.5 + 1.0, 28.0), lbl, 3.2, vec3(0.02), 0.55);\n  drawText(col, q, vec2(-lw * 0.5,       27.0), lbl, 3.2, vec3(1.0),  0.98);\n  if (l2 > 0.5){\n   float w2 = textW(l2, 3.2);\n   drawText(col, q, vec2(-w2 * 0.5 + 1.0, 38.0), l2, 3.2, vec3(0.02), 0.55);\n   drawText(col, q, vec2(-w2 * 0.5,       37.0), l2, 3.2, vec3(1.0),  0.98);\n  }\n }\n}\n// ============================================================\n// START MENU — the two-pane Luna one\n// ============================================================\nvoid startMenu(inout vec3 col, vec2 p, float aa, float open){\n if (open < 0.001) return;\n float bot = SCREEN.y - 34.0;\n float h   = 452.0 * open;\n float top = bot - h;\n vec2  mn = vec2(0.0, top), mx = vec2(384.0, bot);\n vec2  ctr = (mn + mx) * 0.5, hs = (mx - mn) * 0.5;\n vec2  q = p - ctr;\n if (rbox(q, hs, 8.0) > 8.0) return;\n float shell = fill(rbox(q, hs, 8.0), aa);\n col = mix(col, vec3(0.04, 0.12, 0.34), fill(rbox(q - vec2(4.0, 5.0), hs, 8.0), 7.0) * 0.32);\n // ---- header ----\n float hdr = fill(rbox(q - vec2(0.0, -hs.y + 32.0), vec2(hs.x, 32.0), 8.0), aa);\n float g = clamp((p.y - top) / 64.0, 0.0, 1.0);\n vec3 hc = mix(vec3(0.26, 0.50, 0.94), vec3(0.13, 0.31, 0.80), g);\n // NB the max() is load-bearing: pow() is UNDEFINED for a negative base in\n // GLSL, and 1.0 - abs(g - c)*k goes negative away from the band centre.\n // Odd exponents came back negative (black bands), even ones came back as\n // |x|^n which is huge (white blowout). Both symptoms, one bug.\n hc = mix(hc, vec3(0.33, 0.58, 0.97), pow(max(1.0 - abs(g - 0.34) * 3.0, 0.0), 3.0) * 0.55);\n hc += vec3(1.0) * pow(max(1.0 - abs(g - 0.10) * 6.5, 0.0), 5.0) * 0.34;\n col = mix(col, hc, hdr * shell);\n // avatar + user name\n vec2 av = p - vec2(38.0, top + 32.0);\n col = mix(col, vec3(0.85, 0.90, 0.98), fill(rbox(av, vec2(21.0, 21.0), 6.0), aa));\n col = mix(col, vec3(0.42, 0.60, 0.86), fill(length(av - vec2(0.0, -6.0)) - 8.0, aa));\n col = mix(col, vec3(0.42, 0.60, 0.86), fill(rbox(av - vec2(0.0, 12.0), vec2(13.0, 9.0), 7.0), aa));\n drawText(col, p, vec2(70.0, top + 33.0), 24.0, 4.6, vec3(0.02, 0.10, 0.34), 0.5);\n drawText(col, p, vec2(70.0, top + 32.0), 24.0, 4.6, vec3(1.0), 0.98);\n // ---- panes ----\n float paneT = top + 64.0, paneB = bot - 52.0;\n float lp = fill(rbox(p - vec2(104.0, (paneT + paneB) * 0.5),\n      vec2(104.0, (paneB - paneT) * 0.5), 1.0), aa);\n col = mix(col, vec3(1.0), lp * shell);\n float rp = fill(rbox(p - vec2(296.0, (paneT + paneB) * 0.5),\n      vec2(88.0, (paneB - paneT) * 0.5), 1.0), aa);\n col = mix(col, vec3(0.63, 0.75, 0.90), fill(abs(p.x - 208.0) - 0.6, aa) * shell * 0.8);\n col = mix(col, vec3(0.827, 0.894, 0.976), rp * shell);          // XP's pale blue pane\n // left items: big icon + two lines\n for (int i = 0; i < 7; i++){\n  float fi = float(i);\n  float y = paneT + 26.0 + fi * 44.0;\n  if (y > paneB - 12.0) continue;\n  // the pinned programs, each with its own icon\n  float lk = (fi < 0.5) ? 3.0 : (fi < 1.5) ? 6.0 : (fi < 2.5) ? 12.0\n    : (fi < 3.5) ? 13.0 : (fi < 4.5) ? 5.0 : (fi < 5.5) ? 7.0 : 4.0;\n  float ln = (fi < 0.5) ? 4.0 : (fi < 1.5) ? 35.0 : (fi < 2.5) ? 33.0\n    : (fi < 3.5) ? 34.0 : (fi < 4.5) ? 6.0 : (fi < 5.5) ? 18.0 : 17.0;\n  miniIcon(col, p - vec2(30.0, y), lk, 12.0, aa);\n  drawText(col, p, vec2(52.0, y), ln, 3.5, vec3(0.05), 0.97 * shell);\n }\n // separator + \"All Programs\"\n col = mix(col, vec3(0.66, 0.72, 0.84), fill(rbox(p - vec2(104.0, paneB - 26.0), vec2(96.0, 0.7), 0.3), aa) * shell);\n drawText(col, p, vec2(30.0, paneB - 12.0), 14.0, 3.6, vec3(0.05, 0.15, 0.55), 0.97 * shell);\n col = mix(col, vec3(0.10, 0.30, 0.75),\n   fill(sdTriangle(p - vec2(150.0, paneB - 12.0), vec2(0.0, -4.5), vec2(0.0, 4.5), vec2(5.5, 0.0)), aa) * shell);\n // right items\n for (int i = 0; i < 8; i++){\n  float fi = float(i);\n  float y = paneT + 22.0 + fi * 38.0;\n  if (y > paneB - 10.0) continue;\n  float rk = (fi < 0.5) ? 2.0 : (fi < 1.5) ? 7.0 : (fi < 2.5) ? 5.0 : (fi < 3.5) ? 0.0\n    : (fi < 4.5) ? 2.0 : (fi < 5.5) ? 8.0 : (fi < 6.5) ? 3.0 : 4.0;\n  float rn = (fi < 0.5) ? 3.0 : (fi < 1.5) ? 8.0 : (fi < 2.5) ? 20.0 : (fi < 3.5) ? 1.0\n    : (fi < 4.5) ? 36.0 : (fi < 5.5) ? 10.0 : (fi < 6.5) ? 38.0 : 12.0;\n  miniIcon(col, p - vec2(226.0, y), rk, 8.5, aa);\n  drawText(col, p, vec2(242.0, y), rn, 3.2, vec3(0.05, 0.10, 0.30), 0.97 * shell);\n  if (mod(fi, 3.0) > 1.5)\n   col = mix(col, vec3(0.62, 0.72, 0.88), fill(rbox(p - vec2(296.0, y + 19.0), vec2(82.0, 0.7), 0.3), aa) * shell);\n }\n // ---- footer: log off / turn off ----\n float fty = bot - 52.0;\n float ft = fill(rbox(q - vec2(0.0, hs.y - 26.0), vec2(hs.x, 26.0), 8.0), aa);\n float fg = clamp((p.y - fty) / 52.0, 0.0, 1.0);\n vec3 fc = mix(vec3(0.28, 0.52, 0.95), vec3(0.15, 0.33, 0.82), fg);\n fc += vec3(1.0) * pow(max(1.0 - abs(fg - 0.16) * 4.4, 0.0), 5.0) * 0.26;          // the gloss band\n col = mix(col, fc, ft * shell);\n // a lit rule where the footer meets the panes\n col = mix(col, vec3(0.62, 0.80, 1.0), fill(abs(p.y - fty) - 0.9, aa) * shell * 0.85);\n col = mix(col, vec3(0.03, 0.12, 0.44), fill(abs(p.y - fty - 2.0) - 0.7, aa) * shell * 0.5);\n // Log Off — a key-ish roundel with an arrow leaving it\n vec2 lo = p - vec2(196.0, bot - 26.0);\n col = mix(col, vec3(0.99, 0.80, 0.24), fill(length(lo) - 9.5, aa) * shell);\n col = mix(col, vec3(0.55, 0.36, 0.04), fill(abs(length(lo) - 9.5) - 1.0, aa) * shell);\n col = mix(col, vec3(0.35, 0.22, 0.02), fill(rbox(lo - vec2(1.0, 0.0), vec2(5.0, 1.4), 0.6), aa) * shell);\n col = mix(col, vec3(0.35, 0.22, 0.02),\n   fill(sdTriangle(lo - vec2(6.5, 0.0), vec2(-1.0, -3.6), vec2(-1.0, 3.6), vec2(3.4, 0.0)), aa) * shell);\n drawText(col, p, vec2(210.0, bot - 26.0), 15.0, 3.4, vec3(1.0), 0.97 * shell);\n // Turn Off — the power mark: a broken ring with a bar through the gap\n vec2 po = p - vec2(288.0, bot - 26.0);\n col = mix(col, vec3(0.90, 0.32, 0.20), fill(length(po) - 9.5, aa) * shell);\n col = mix(col, vec3(0.52, 0.10, 0.04), fill(abs(length(po) - 9.5) - 1.0, aa) * shell);\n float ring = abs(length(po) - 4.8) - 1.3;\n ring = max(ring, -(abs(po.x) - 2.2 - max(-po.y, 0.0) * 9.0));            // notch out the top\n col = mix(col, vec3(1.0), fill(ring, aa) * shell);\n col = mix(col, vec3(1.0), fill(rbox(po - vec2(0.0, -4.0), vec2(1.2, 4.4), 0.5), aa) * shell);\n drawText(col, p, vec2(302.0, bot - 26.0), 16.0, 3.4, vec3(1.0), 0.97 * shell);\n}\n// ============================================================\n// ONE DIALOG\n// returns rgb in .xyz and coverage in .w\n// q is the pixel relative to the window's top-left, y DOWN\n// ============================================================\nvec4 dialog(vec2 q, float aa, float glass, float seed){\n vec4 outp = vec4(0.0);\n // drop shadow, offset down-right\n float dsh = rbox(q - WSZ * 0.5 - vec2(5.0, 6.0), WSZ * 0.5, 4.0);\n outp = vec4(0.03, 0.09, 0.26, fill(dsh + 4.0, 6.0) * 0.28);\n // outer frame — XP Luna blue\n float fr = rbox(q - WSZ * 0.5, WSZ * 0.5, 5.0);\n float frA = fill(fr, aa);\n vec3  frC = mix(vec3(0.12, 0.34, 0.84), vec3(0.26, 0.52, 0.92), q.y / WSZ.y);\n outp.rgb = mix(outp.rgb, frC, frA);\n outp.a   = max(outp.a, frA);\n // ---- title bar ----\n float tb = fill(rbox(q - vec2(WSZ.x * 0.5, 15.5), vec2(WSZ.x * 0.5 - 3.0, 12.5), 3.5), aa);\n if (tb > 0.001){\n  float g = clamp((q.y - 3.0) / 25.0, 0.0, 1.0);\n  // the Luna gradient: deep blue, a bright band, then blue again\n  vec3 c = mix(vec3(0.16, 0.42, 0.90), vec3(0.36, 0.64, 0.98), smoothstep(0.0, 0.45, g));\n  c = mix(c, vec3(0.18, 0.42, 0.89), smoothstep(0.55, 1.0, g));\n  c += vec3(1.0) * pow(max(1.0 - abs(g - 0.20) * 4.0, 0.0), 6.0) * 0.38;   // gloss band\n  outp.rgb = mix(outp.rgb, c, tb);\n  outp.a = max(outp.a, tb);\n  // title text — blocks, or an unknown alphabet if this copy came back wrong\n  float titleAlien = step(1.0 - uAlien * 0.6, hash11(seed * 13.7 + 2.0));\n  if (titleAlien > 0.5){\n   float txr = q.x - 30.0;\n   if (txr > -7.0 && txr < 260.0){\n    float cell = floor(txr / 14.0);\n    vec2  gq = vec2(mod(txr, 14.0) - 7.0, (q.y - 15.0) * 1.35);\n    outp.rgb = mix(outp.rgb, vec3(1.0),\n       alienGlyph(gq, hash11(cell * 5.3 + seed * 2.1), aa) * 0.92);\n   }\n  } else {\n   // the dialog's own title — hung copies say NOT RESPONDING\n   float tsid = mix(22.0, 23.0, step(1.0 - uQuestion * 0.42, hash11(seed * 3.77 + 0.5)));\n   outp.rgb = mix(outp.rgb, vec3(0.02, 0.10, 0.32),\n      textCov(q - vec2(31.0, 16.0), tsid, 4.2) * 0.45);   // shadow\n   outp.rgb = mix(outp.rgb, vec3(1.0),\n      textCov(q - vec2(30.0, 15.0), tsid, 4.2) * 0.96);\n  }\n  // close button\n  vec2 cb = q - vec2(WSZ.x - 22.0, 15.0);\n  float cbd = fill(rbox(cb, vec2(11.0, 9.5), 3.0), aa);\n  vec3 cbc = mix(vec3(0.90, 0.28, 0.16), vec3(0.99, 0.62, 0.50), 1.0 - clamp(cb.y / 19.0 + 0.5, 0.0, 1.0));\n  outp.rgb = mix(outp.rgb, cbc, cbd);\n  float xArm = min(fill(rbox(vec2(cb.x - cb.y, cb.x + cb.y) * 0.7071, vec2(6.0, 1.2), 0.4), aa)\n     + fill(rbox(vec2(cb.x + cb.y, cb.x - cb.y) * 0.7071, vec2(6.0, 1.2), 0.4), aa), 1.0);\n  outp.rgb = mix(outp.rgb, vec3(1.0), cbd * xArm);\n }\n // ---- body ----\n float bd = fill(rbox(q - vec2(WSZ.x * 0.5, (WSZ.y + 30.0) * 0.5), vec2(WSZ.x * 0.5 - 4.0, (WSZ.y - 34.0) * 0.5), 1.0), aa);\n if (bd > 0.001){\n  vec3 body = vec3(0.925, 0.914, 0.847);                 // XP dialog beige\n  body *= 1.0 - 0.05 * smoothstep(0.0, 1.0, q.y / WSZ.y); // faint vertical shade\n  outp.rgb = mix(outp.rgb, body, bd);\n  outp.a = max(outp.a, bd);\n  // The roundel. Some copies came back from the repaint as a query\n  // dialog instead of an error — blue, with a question mark.\n  vec2 ip = q - vec2(46.0, 78.0);\n  float icd = length(ip) - 17.0;\n  float ica = fill(icd, aa);\n  // four flavours: error X, query ?, a smiley, and one that didn't make it\n  float rr = hash11(seed * 3.77 + 0.5);\n  float face = step(1.0 - uQuestion * 0.42, rr);            // smiley or dead\n  float dead = face * step(0.5, hash11(seed * 8.13 + 2.0));\n  float isQ  = (1.0 - face) * step(1.0 - uQuestion * 0.60, hash11(seed * 5.31 + 9.0));\n  vec3 red  = mix(vec3(0.86, 0.10, 0.08), vec3(1.0, 0.42, 0.34), smoothstep(12.0, -18.0, ip.y));\n  vec3 blue = mix(vec3(0.06, 0.32, 0.78), vec3(0.42, 0.70, 1.0), smoothstep(12.0, -18.0, ip.y));\n  vec3 yell = mix(vec3(0.94, 0.68, 0.04), vec3(1.0, 0.93, 0.40), smoothstep(12.0, -18.0, ip.y));\n  vec3 icc = mix(mix(red, blue, isQ), yell, face);\n  outp.rgb = mix(outp.rgb, icc, ica);\n  outp.rgb += vec3(1.0) * fill(length(ip - vec2(-5.0, -7.0)) - 5.0, aa) * 0.30;   // gloss\n  float mark;\n  if (face > 0.5){\n   vec2 ep = vec2(abs(ip.x) - 5.6, ip.y + 4.0);\n   if (dead > 0.5){\n    // X for eyes, and a straight line for a mouth\n    mark  = fill(rbox(vec2(ep.x - ep.y, ep.x + ep.y) * 0.7071, vec2(3.4, 1.0), 0.4), aa);\n    mark += fill(rbox(vec2(ep.x + ep.y, ep.x - ep.y) * 0.7071, vec2(3.4, 1.0), 0.4), aa);\n    mark += fill(rbox(ip - vec2(0.0, 7.0), vec2(5.4, 1.1), 0.5), aa);\n   } else {\n    mark  = fill(length(ep) - 1.9, aa);                       // eyes\n    // the smile: a ring cut to its lower arc\n    float sm = abs(length(ip - vec2(0.0, -0.5)) - 8.4) - 1.15;\n    mark += fill(max(sm, 3.0 - ip.y), aa);\n   }\n   mark = min(mark, 1.0);\n   outp.rgb = mix(outp.rgb, vec3(0.20, 0.12, 0.0), ica * mark);   // dark features on yellow\n  } else {\n   if (isQ > 0.5){\n    mark = fill(sdQuestion(ip - vec2(0.0, 1.0), 1.35), aa);\n   } else {\n    mark = min(fill(rbox(vec2(ip.x - ip.y, ip.x + ip.y) * 0.7071, vec2(9.0, 2.0), 0.6), aa)\n      + fill(rbox(vec2(ip.x + ip.y, ip.x - ip.y) * 0.7071, vec2(9.0, 2.0), 0.6), aa), 1.0);\n   }\n   outp.rgb = mix(outp.rgb, vec3(1.0), ica * mark);\n  }\n  // ---- the traceback ----\n  // Clean grey rules, unless the repaint left something else behind:\n  // torn rows slide sideways, some invert into a selection block, and\n  // some come back as characters from no alphabet at all.\n  for (int i = 0; i < 8; i++){\n   float fi = float(i);\n   float y0 = 50.0 + fi * 11.5;\n   if (abs(q.y - y0) > 7.0) continue;            // only one row is live per pixel\n   float rs = hash11(fi * 4.3 + seed * 9.1);\n   float w  = 150.0 + 180.0 * hash11(fi * 4.3 + 1.0);\n   float x0 = 80.0;\n   // torn: the row never finished moving\n   float tear = step(1.0 - uGarble * 0.55, hash11(fi * 7.7 + seed * 5.3));\n   x0 += tear * (hash11(fi * 2.2 + seed * 3.3) - 0.5) * 150.0 * uGarble;\n   // inverted: a stale selection highlight\n   float inv = step(1.0 - uGarble * 0.30, hash11(fi * 11.9 + seed * 2.7));\n   if (inv > 0.5){\n    float blk = fill(rbox(q - vec2(x0 + w * 0.5, y0), vec2(w * 0.5 + 3.0, 5.5), 1.0), aa);\n    outp.rgb = mix(outp.rgb, vec3(0.04, 0.20, 0.62), blk);\n   }\n   vec3 ink = mix(vec3(0.16, 0.16, 0.18), vec3(1.0), inv);\n   if (step(1.0 - uAlien, rs) > 0.5){\n    // alien script — one glyph per 13px cell, indexed off x so the\n    // whole row costs O(1) instead of a nested loop\n    float xr = q.x - x0;\n    if (xr > -6.0 && xr < w){\n     float cell = floor(xr / 13.0);\n     vec2  gq = vec2(mod(xr, 13.0) - 6.5, q.y - y0);\n     float gl = alienGlyph(gq, hash11(cell * 3.1 + fi * 7.7 + seed * 1.9), aa);\n     outp.rgb = mix(outp.rgb, ink, gl * 0.9);\n    }\n   } else {\n    float ln = fill(rbox(q - vec2(x0 + w * 0.5, y0), vec2(w * 0.5, 2.2), 0.8), aa);\n    outp.rgb = mix(outp.rgb, ink, ln * 0.85);\n    // a stray question mark dropped into the line\n    if (step(1.0 - uQuestion * 0.5, hash11(fi * 19.3 + seed * 7.1)) > 0.5){\n     float qm = fill(sdQuestion(q - vec2(x0 + w + 12.0, y0), 0.72), aa);\n     outp.rgb = mix(outp.rgb, ink, qm);\n    }\n   }\n  }\n  // END NOW / CANCEL, the way the hung-app dialog actually asks\n  for (int b = 0; b < 2; b++){\n   float fb = float(b);\n   vec2 bp = q - vec2(WSZ.x * 0.5 - 52.0 + fb * 104.0, WSZ.y - 24.0);\n   float bdd = rbox(bp, vec2(46.0, 12.5), 3.0);\n   float bA  = fill(bdd, aa);\n   float bg  = clamp(bp.y / 25.0 + 0.5, 0.0, 1.0);\n   vec3  bc  = mix(vec3(1.0, 1.0, 0.99), vec3(0.84, 0.84, 0.80), bg);\n   bc = mix(bc, vec3(0.93, 0.93, 0.90), smoothstep(0.42, 0.55, bg));\n   outp.rgb = mix(outp.rgb, bc, bA);\n   outp.rgb = mix(outp.rgb, vec3(0.38, 0.42, 0.40), fill(abs(bdd) - 0.9, aa));\n   outp.rgb = mix(outp.rgb, vec3(1.0), fill(abs(bdd + 1.6) - 0.7, aa) * bA * 0.7);\n   float bs = (fb < 0.5) ? 31.0 : 32.0;                       // END NOW / CANCEL\n   float bw = textW(bs, 3.4);\n   outp.rgb = mix(outp.rgb, vec3(0.08),\n      textCov(bp - vec2(-bw * 0.5, 0.0), bs, 3.4) * 0.95);\n  }\n }\n // ---- Aero: a specular sweep riding across the glass ----\n if (glass > 0.001 && outp.a > 0.001){\n  float sweep = pow(clamp(1.0 - abs((q.x + q.y * 0.55) / WSZ.x - 0.42) * 3.2, 0.0, 1.0), 3.0);\n  outp.rgb += vec3(0.65, 0.85, 1.0) * sweep * 0.16 * glass * outp.a;\n  // (the old top-edge catch-light lived here — it drew a hard white bar\n  //  straight across the window under the title, so it's gone)\n }\n return outp;\n}\n// where cascade k's window sits at time tt. Shared by the cascade loop and\n// by the cursor, so the pointer always rides the live window's titlebar.\nvec2 dragPath(float fk, float tt){\n float sk  = hash11(fk * 17.7 + 3.0);\n vec2  amp = vec2(300.0, 150.0) * (0.55 + 0.55 * sk);\n vec2  spd = vec2(0.61, 0.47) * (0.7 + 0.7 * hash11(fk * 5.3));\n vec2  hom = vec2(gSW, SCREEN.y) * 0.5;\n if (fk > 0.5) hom += vec2(180.0 * (sk - 0.5), 120.0 * (hash11(fk * 8.9) - 0.5));\n return hom + vec2(amp.x * sin(tt * spd.x) + 90.0 * sin(tt * 1.43),\n     amp.y * cos(tt * spd.y) + 55.0 * cos(tt * 1.17)) * uDrift;\n}\n// ============================================================\nvoid main(){\n vec2 fragCoord = gl_FragCoord.xy;\n vec2  R = RENDERSIZE;\n float scale = R.y / SCREEN.y;\n gSW = SCREEN.y * (R.x / R.y);        // desktop is as wide as the window is\n // desktop pixels, y DOWN, origin at the top-left of the actual viewport\n vec2  p = vec2(fragCoord.x / scale, SCREEN.y - fragCoord.y / scale);\n float aa = 1.0 / max(scale, 0.001) * 0.75;   // one desktop pixel, in screen terms\n float t  = TIME * uSpeed;\n vec3 col = desktop(p, t, aa);\n if (uIcons > 0.001) desktopIcons(col, p, aa);\n // ---- the cascades ------------------------------------------------\n // Each copy is the SAME window sampled further back in its own past,\n // so the trail is literally the path it has been dragged along.\n // Oldest first, so the live one lands on top. uCascades runs several\n // independent drags at once, each on its own path and phase.\n float N  = clamp(uCount, 1.0, 48.0);\n float NC = clamp(floor(uCascades), 1.0, 4.0);\n for (int k = 0; k < 4; k++){\n  float fk = float(k);\n  if (fk >= NC) continue;\n  float tk = t + fk * 7.3;                        // each drag out of step\n  for (int i = 47; i >= 0; i--){\n   float fi = float(i);\n   if (fi >= N) continue;   // float test: keeps the loop header ES-1.00 plain\n   vec2 c = dragPath(fk, tk - fi * uTrail);\n   // per-copy glitch nudge — stale copies sit a pixel or two out\n   c += uJitter * vec2(hash11(fi * 12.7 + fk * 3.1 + floor(t * 3.0)) - 0.5,\n        hash11(fi * 31.3 + fk * 7.7 + floor(t * 3.0)) - 0.5) * 9.0;\n   vec2 q = p - (c - WSZ * 0.5);\n   if (q.x < -14.0 || q.y < -14.0 || q.x > WSZ.x + 14.0 || q.y > WSZ.y + 14.0) continue;\n   // torn copies: some stale ones never finished repainting, so one\n   // scanline is stretched across the whole body\n   float torn = step(0.80, hash11(fi * 5.9 + fk * 2.3 + floor(t * 1.7))) * uSmear;\n   if (torn > 0.001 && fi > 0.5){\n    float yTear = 30.0 + hash11(fi * 8.1 + fk) * (WSZ.y - 40.0);\n    float band  = step(abs(q.y - yTear) - 26.0, 0.0);\n    q.y = mix(q.y, yTear, band * torn);\n   }\n   vec4 w = dialog(q, aa, uGlass, fi * 1.37 + fk * 23.9);\n   // the oldest copies have been sitting there longest\n   w.a *= 1.0 - uFade * (fi / max(N - 1.0, 1.0));\n   col = mix(col, w.rgb, w.a);\n  }\n }\n // ---- taskbar -----------------------------------------------------\n if (uTaskbar > 0.5){\n  float tby = SCREEN.y - 34.0;\n  float inBar = step(tby, p.y);\n  if (inBar > 0.5){\n   float g = (p.y - tby) / 34.0;\n   // XP's taskbar stays blue all the way down — the old ramp fell\n   // to near-black, which is what made it look muddy\n   vec3 bar = mix(vec3(0.27, 0.49, 0.93), vec3(0.14, 0.32, 0.80), g);\n   bar = mix(bar, vec3(0.34, 0.57, 0.96), pow(max(1.0 - abs(g - 0.30) * 3.4, 0.0), 3.0) * 0.55);\n   bar += vec3(1.0) * pow(max(1.0 - abs(g - 0.10) * 7.0, 0.0), 5.0) * 0.38;      // top gloss\n   bar = mix(bar, vec3(0.20, 0.40, 0.86), smoothstep(0.86, 1.0, g) * 0.5);\n   bar = mix(bar, vec3(0.98, 0.72, 0.20), step(p.y, tby + 2.2) * 0.85);  // the amber rule\n   // ---- Start button ----\n   // XP's is a lozenge rounded hard on the right and squared off at\n   // the left where it meets the screen edge, with the flag inset.\n   vec2 sp = p - vec2(48.0, tby + 17.0);\n   float sd0 = rbox(sp, vec2(52.0, 15.0), 14.0);\n   sd0 = max(sd0, -(sp.x + 52.0) - 4.0);           // square it off at the screen edge\n   float sb = fill(sd0, aa);\n   vec3 sc = mix(vec3(0.56, 0.85, 0.28), vec3(0.20, 0.52, 0.09), g);\n   sc += vec3(1.0) * pow(max(1.0 - abs(g - 0.17) * 4.2, 0.0), 4.0) * 0.42;      // top gloss\n   sc = mix(sc, vec3(0.09, 0.30, 0.04), smoothstep(0.72, 1.0, g) * 0.55);\n   bar = mix(bar, sc, sb);\n   bar = mix(bar, vec3(0.72, 0.94, 0.50), fill(abs(sd0) - 0.9, aa) * 0.45);   // lit rim\n   // the four-pane flag, sheared into its wave\n   for (int fq = 0; fq < 4; fq++){\n    float ff = float(fq);\n    vec2 cell = vec2(mod(ff, 2.0), floor(ff / 2.0)) - 0.5;\n    vec2 fp = sp - vec2(-32.0, 0.0) - cell * vec2(8.6, 8.2);\n    fp.y += fp.x * 0.22;                          // the flag's lean\n    vec3 pane = (ff < 0.5)  ? vec3(0.92, 0.30, 0.22)\n      : (ff < 1.5)  ? vec3(0.45, 0.76, 0.98)\n      : (ff < 2.5)  ? vec3(0.99, 0.80, 0.22)\n          : vec3(0.52, 0.82, 0.35);\n    float fa = fill(rbox(fp, vec2(3.6, 3.4), 1.1), aa) * sb;\n    bar = mix(bar, pane, fa);\n    bar = mix(bar, min(pane + 0.45, vec3(1.0)),\n      fill(rbox(fp - vec2(0.0, -2.0), vec2(3.0, 1.2), 0.8), aa) * fa * 0.7);\n   }\n   drawText(bar, p, vec2(37.0, tby + 18.0), 0.0, 4.8, vec3(0.06, 0.22, 0.05), 0.55 * sb);\n   drawText(bar, p, vec2(36.0, tby + 17.0), 0.0, 4.8, vec3(1.0), 0.98 * sb);\n   // task buttons — one per cascade, plus a couple of idle ones.\n   // Each carries a small app icon and a run of label text.\n   for (int i = 0; i < 4; i++){\n    float fi = float(i);\n    // start at 204 — the Start button reaches x=116, and the old\n    // 168 put the first button's left edge under it\n    float bx = 184.0 + fi * 158.0;\n    float bdd = rbox(p - vec2(bx, tby + 17.0), vec2(76.0, 12.0), 3.0);\n    float tbn = fill(bdd, aa);\n    float hung = step(fi, clamp(floor(uCascades), 1.0, 4.0) - 0.5);\n    // the hung ones sit pressed in, darker and with the gloss inverted\n    // both states stay blue — the pressed one used to bottom out\n    // near black, which read as a hole in the bar\n    vec3 tc = mix(mix(vec3(0.31, 0.55, 0.95), vec3(0.17, 0.37, 0.85), g),\n       mix(vec3(0.13, 0.29, 0.72), vec3(0.20, 0.41, 0.86), 1.0 - g), hung);\n    bar = mix(bar, tc, tbn);\n    bar = mix(bar, vec3(0.55, 0.74, 1.0), fill(abs(bdd) - 0.8, aa) * 0.35);   // rim\n    // icon and label always agree, and match the desktop shortcuts\n    float tkind = (hung > 0.5) ? 0.0 : (fi < 1.5) ? 10.0 : (fi < 2.5) ? 11.0 : 9.0;\n    miniIcon(bar, p - vec2(bx - 62.0, tby + 17.0), tkind, 7.0, aa);\n    // hung copies say NOT RESPONDING; the rest name their program\n    float tlab = (fi < 1.5) ? 28.0 : (fi < 2.5) ? 29.0 : 30.0;\n    tlab = mix(tlab, 23.0, hung);\n    drawText(bar, p, vec2(bx - 50.0, tby + 17.0), tlab, 3.4,\n      mix(vec3(1.0), vec3(1.0, 0.86, 0.78), hung), 0.97 * tbn);\n   }\n   // ---- system tray ----\n   float trX = gSW - 132.0;\n   vec2  trC = vec2(trX + 62.0, tby + 17.0);\n   float trd = rbox(p - trC, vec2(64.0, 13.0), 2.0);\n   float tr  = fill(trd, aa);\n   bar = mix(bar, mix(vec3(0.16, 0.42, 0.90), vec3(0.09, 0.28, 0.78), g), tr);\n   bar = mix(bar, vec3(0.15, 0.33, 0.76), fill(abs(trd) - 0.8, aa) * 0.8);   // sunken edge\n   bar = mix(bar, vec3(0.42, 0.64, 0.99), fill(abs(trd + 1.6) - 0.6, aa) * 0.45);\n   miniIcon(bar, p - vec2(trX + 16.0, tby + 17.0), 13.0, 6.0, aa);   // messenger\n   miniIcon(bar, p - vec2(trX + 34.0, tby + 17.0), 3.0,  6.0, aa);   // network\n   miniIcon(bar, p - vec2(trX + 52.0, tby + 17.0), 5.0,  6.0, aa);   // volume\n   // the clock, right-aligned in its well\n   drawText(bar, p, vec2(trX + 74.0, tby + 18.0), 21.0, 4.0, vec3(0.02, 0.10, 0.34), 0.45);\n   drawText(bar, p, vec2(trX + 74.0, tby + 17.0), 21.0, 4.0, vec3(1.0), 0.98);\n   col = mix(col, bar, inBar);\n  }\n }\n // ---- start menu, over the taskbar --------------------------------\n startMenu(col, p, aa, uStart ? 1.0 : 0.0);\n // ---- the pointer, still holding the live window -------------------\n if (uCursor > 0.001){\n  vec2 grab = dragPath(0.0, t) - WSZ * 0.5 + vec2(WSZ.x * 0.42, 15.0);\n  vec2 cq = p - grab;\n  if (dot(cq, cq) < 900.0){\n   // Head and tail, both convex, unioned. Proportions off the real\n   // pointer: a narrow blade, and the tail kicked out to the right.\n   // A longer, narrower blade than before, with a 1px keyline. The\n   // outline used to be 1.35 desktop px on a 16px arrow, which ate\n   // most of the white and left a black blob.\n   float head = sdTriangle(cq, vec2(0.0, 0.0), vec2(0.5, 18.4), vec2(12.6, 13.1));\n   // The tail kicks DOWN-RIGHT off the blade's bottom edge. The old\n   // matrix was the transpose of what it needed to be, so the leg\n   // leaned left and poked out past the bottom-left corner - the arrow\n   // read as a broken Y. Local +y must map to (0.43, 0.90) in desktop\n   // space (y is down here), i.e. mat2(0.90, 0.43, -0.43, 0.90).\n   // Half-width has to beat the keyline: the white body is eroded by\n   // 0.95 desktop px per side, so a 1.7 half-width left a 0.75 white\n   // core and the leg read as a thin spur instead of the real one.\n   vec2 tq = cq - vec2(6.9, 16.6);\n   tq = vec2(tq.x * 0.92 - tq.y * 0.40, tq.x * 0.40 + tq.y * 0.92);   // ~24 deg\n   float tail = rbox(tq, vec2(1.95, 5.4), 0.3);\n   float d = min(head, tail);\n   col = mix(col, vec3(0.0), fill(d - 1.6, aa) * 0.20);   // soft drop shadow\n   col = mix(col, vec3(0.02), fill(d, aa));               // keyline\n   col = mix(col, vec3(1.0),  fill(d + 0.95, aa));        // white body\n  }\n }\n // ---- grade: the era's taste, dialled in --------------------------\n if (uBloom > 0.001){\n  float lum = dot(col, vec3(0.299, 0.587, 0.114));\n  col += col * smoothstep(0.72, 1.0, lum) * uBloom * 0.55;\n }\n float l = dot(col, vec3(0.299, 0.587, 0.114));\n col = mix(vec3(l), col, uSat);                        // vivid\n col = pow(clamp(col, 0.0, 1.0), vec3(0.94, 0.97, 1.03));\n col *= 1.0 - uScan * 0.35 * (0.5 + 0.5 * sin(fragCoord.y * PI));\n vec2 vq = fragCoord / R;\n float vig = pow(16.0 * vq.x * vq.y * (1.0 - vq.x) * (1.0 - vq.y), 0.22);\n col *= mix(1.0, vig, uVignette);\n gl_FragColor = vec4(clamp(col, 0.0, 1.0), 1.0);\n}\n",
    "generator": {
      "model": "Claude-Opus-5",
      "provider": null,
      "prompt": null,
      "params": null
    }
  }
}