0x55969715…1928sent to0x2052051a…3677·#25,744,500·view on Etherscan
data:text/html,%60%60%60%0A%3C!doctype%20html%3E%0A%3Chtml%20lang%3D%22en%22%3E%0A%3Chead%3E%0A%3Cmeta%20charset%3D%22utf-8%22%20%2F%3E%0A%3Cmeta%20name%3D%22viewport%22%20content%3D%22width%3Ddevice-width%2Cinitial-scale%3D1%2Cmaximum-scale%3D1%2Cuser-scalable%3Dno%22%20%2F%3E%0A%3Ctitle%3EPixel%20Wizard%20Spellcaster%3C%2Ftitle%3E%0A%3Cstyle%3E%0A%20%20html%2Cbody%7B%0A%20%20%20%20margin%3A0%3B%0A%20%20%20%20width%3A100%25%3B%0A%20%20%20%20height%3A100%25%3B%0A%20%20%20%20min-width%3A100%25%3B%0A%20%20%20%20min-height%3A100%25%3B%0A%20%20%20%20overflow%3Ahidden%3B%0A%20%20%20%20background%3A%23000%3B%0A%20%20%20%20touch-action%3Anone%3B%0A%20%20%20%20user-select%3Anone%3B%0A%20%20%20%20-webkit-user-select%3Anone%3B%0A%20%20%7D%0A%0A%20%20body%7B%0A%20%20%20%20display%3Aflex%3B%0A%20%20%20%20align-items%3Acenter%3B%0A%20%20%20%20justify-content%3Acenter%3B%0A%20%20%7D%0A%0A%20%20%2F*%0A%20%20%20%20Responsive%201%3A1%20stage.%0A%20%20%20%20The%20visible%20square%20grows%2Fshrinks%20to%20the%20largest%20square%20that%20fits%0A%20%20%20%20inside%20the%20current%20iframe%2Fviewport.%20The%20canvas%20drawing%20buffers%20remain%0A%20%20%20%20392x392%20so%20all%20existing%20spell%20coordinates%20and%20pixel%20scanning%20stay%20exact.%0A%20%20*%2F%0A%20%20%23stage%7B%0A%20%20%20%20position%3Arelative%3B%0A%20%20%20%20width%3Amin(100vw%2C%20100vh)%3B%0A%20%20%20%20height%3Amin(100vw%2C%20100vh)%3B%0A%20%20%20%20aspect-ratio%3A1%20%2F%201%3B%0A%20%20%20%20flex%3A0%200%20auto%3B%0A%20%20%20%20overflow%3Ahidden%3B%0A%20%20%20%20background%3A%23000%3B%0A%20%20%20%20cursor%3Apointer%3B%0A%20%20%20%20isolation%3Aisolate%3B%0A%20%20%20%20contain%3Alayout%20paint%20size%3B%0A%20%20%7D%0A%0A%20%20%23wizard%2C%0A%20%20%23fx%2C%0A%20%20%23overlay%7B%0A%20%20%20%20position%3Aabsolute%3B%0A%20%20%20%20inset%3A0%3B%0A%20%20%20%20width%3A100%25%3B%0A%20%20%20%20height%3A100%25%3B%0A%20%20%7D%0A%0A%20%20%23wizard%7B%0A%20%20%20%20z-index%3A1%3B%0A%20%20%20%20image-rendering%3Apixelated%3B%0A%20%20%20%20image-rendering%3Acrisp-edges%3B%0A%20%20%20%20transition%3Aopacity%202s%20linear%3B%0A%20%20%20%20will-change%3Afilter%2Copacity%2Ctransform%3B%0A%20%20%7D%0A%0A%20%20%23fx%7B%0A%20%20%20%20z-index%3A3%3B%0A%20%20%20%20pointer-events%3Anone%3B%0A%20%20%20%20image-rendering%3Apixelated%3B%0A%20%20%7D%0A%0A%20%20%23overlay%7B%0A%20%20%20%20z-index%3A4%3B%0A%20%20%20%20pointer-events%3Anone%3B%0A%20%20%20%20opacity%3A0%3B%0A%20%20%20%20mix-blend-mode%3Ascreen%3B%0A%20%20%7D%0A%0A%0A%20%20%23runes%7B%0A%20%20%20%20position%3Aabsolute%3B%0A%20%20%20%20inset%3A0%3B%0A%20%20%20%20width%3A100%25%3B%0A%20%20%20%20height%3A100%25%3B%0A%20%20%20%20z-index%3A2%3B%0A%20%20%20%20pointer-events%3Anone%3B%0A%20%20%7D%0A%0A%0A%0A%20%20%23cosmos%7B%0A%20%20%20%20position%3Aabsolute%3B%0A%20%20%20%20inset%3A0%3B%0A%20%20%20%20width%3A100%25%3B%0A%20%20%20%20height%3A100%25%3B%0A%20%20%20%20z-index%3A7%3B%0A%20%20%20%20display%3Anone%3B%0A%20%20%20%20pointer-events%3Aauto%3B%0A%20%20%20%20touch-action%3Anone%3B%0A%20%20%20%20background%3A%23000%3B%0A%20%20%20%20image-rendering%3Apixelated%3B%0A%20%20%20%20cursor%3Agrab%3B%0A%20%20%7D%0A%0A%20%20%23cosmos%3Aactive%7B%0A%20%20%20%20cursor%3Agrabbing%3B%0A%20%20%7D%0A%0A%20%20%23spellbar%7B%0A%20%20%20%20position%3Aabsolute%3B%0A%20%20%20%20z-index%3A10%3B%0A%20%20%20%20top%3A7px%3B%0A%20%20%20%20left%3A50%25%3B%0A%20%20%20%20transform%3AtranslateX(-50%25)%3B%0A%20%20%20%20display%3Aflex%3B%0A%20%20%20%20gap%3A2px%3B%0A%20%20%20%20padding%3A5px%3B%0A%20%20%20%20border%3A1px%20solid%20rgba(255%2C215%2C90%2C.38)%3B%0A%20%20%20%20border-radius%3A9px%3B%0A%20%20%20%20background%3Argba(0%2C0%2C0%2C.46)%3B%0A%20%20%20%20box-shadow%3A0%200%2015px%20rgba(255%2C190%2C40%2C.15)%3B%0A%20%20%20%20backdrop-filter%3Ablur(2px)%3B%0A%20%20%20%20-webkit-backdrop-filter%3Ablur(2px)%3B%0A%20%20%7D%0A%0A%20%20%23spellbar%20button%7B%0A%20%20%20%20appearance%3Anone%3B%0A%20%20%20%20-webkit-appearance%3Anone%3B%0A%20%20%20%20width%3A30px%3B%0A%20%20%20%20height%3A34px%3B%0A%20%20%20%20padding%3A0%3B%0A%20%20%20%20border%3A1px%20solid%20rgba(255%2C224%2C120%2C.28)%3B%0A%20%20%20%20border-radius%3A7px%3B%0A%20%20%20%20background%3Argba(20%2C12%2C0%2C.62)%3B%0A%20%20%20%20font-size%3A18px%3B%0A%20%20%20%20line-height%3A32px%3B%0A%20%20%20%20text-align%3Acenter%3B%0A%20%20%20%20cursor%3Apointer%3B%0A%20%20%20%20touch-action%3Amanipulation%3B%0A%20%20%20%20transition%3Atransform%20.1s%20ease%2C%20background%20.12s%20ease%2C%20box-shadow%20.12s%20ease%3B%0A%20%20%7D%0A%0A%20%20%23spellbar%20button%3Ahover%7B%0A%20%20%20%20background%3Argba(100%2C62%2C0%2C.58)%3B%0A%20%20%20%20box-shadow%3A0%200%2012px%20rgba(255%2C198%2C45%2C.28)%3B%0A%20%20%7D%0A%0A%20%20%23spellbar%20button%3Aactive%7B%0A%20%20%20%20transform%3Ascale(.9)%3B%0A%20%20%7D%0A%0A%20%20%2F*%20brief%20chromatic%20%2F%20glitch%20spell%20*%2F%0A%20%20.glitch%7B%0A%20%20%20%20animation%3AglitchSpell%20.65s%20steps(2%2Cend)%3B%0A%20%20%7D%0A%20%20%40keyframes%20glitchSpell%7B%0A%20%20%20%200%25%20%20%20%7B%20transform%3Atranslate(0%2C0)%3B%20filter%3Anone%3B%20%7D%0A%20%20%20%2012%25%20%20%7B%20transform%3Atranslate(-8px%2C2px)%3B%20filter%3Ahue-rotate(90deg)%20saturate(2)%3B%20%7D%0A%20%20%20%2024%25%20%20%7B%20transform%3Atranslate(7px%2C-3px)%3B%20filter%3Acontrast(1.7)%20hue-rotate(180deg)%3B%20%7D%0A%20%20%20%2036%25%20%20%7B%20transform%3Atranslate(-4px%2C5px)%3B%20filter%3Ainvert(1)%3B%20%7D%0A%20%20%20%2048%25%20%20%7B%20transform%3Atranslate(8px%2C1px)%3B%20filter%3Ahue-rotate(270deg)%20saturate(3)%3B%20%7D%0A%20%20%20%2065%25%20%20%7B%20transform%3Atranslate(-3px%2C-4px)%3B%20filter%3Acontrast(2)%3B%20%7D%0A%20%20%20%20100%25%20%7B%20transform%3Atranslate(0%2C0)%3B%20filter%3Anone%3B%20%7D%0A%20%20%7D%0A%0A%0A%20%20%2F*%20strobe%20*%2F%0A%20%20.strobe%7B%0A%20%20%20%20animation%3AstrobeSpell%20.09s%20steps(1%2Cend)%2034%3B%0A%20%20%7D%0A%20%20%40keyframes%20strobeSpell%7B%0A%20%20%20%200%25%2C49%25%7Bfilter%3Ainvert(0)%20contrast(1)%3B%7D%0A%20%20%20%2050%25%2C100%25%7Bfilter%3Ainvert(1)%20contrast(1.35)%3B%7D%0A%20%20%7D%0A%3C%2Fstyle%3E%0A%3C%2Fhead%3E%0A%3Cbody%3E%0A%0A%3Cdiv%20id%3D%22stage%22%20aria-label%3D%22Interactive%20pixel%20wizard%22%3E%0A%20%20%3Ccanvas%20id%3D%22wizard%22%20width%3D%22392%22%20height%3D%22392%22%3E%3C%2Fcanvas%3E%0A%20%20%3Ccanvas%20id%3D%22runes%22%20width%3D%22392%22%20height%3D%22392%22%3E%3C%2Fcanvas%3E%0A%20%20%3Ccanvas%20id%3D%22fx%22%20width%3D%22392%22%20height%3D%22392%22%3E%3C%2Fcanvas%3E%0A%20%20%3Ccanvas%20id%3D%22cosmos%22%20width%3D%22392%22%20height%3D%22392%22%3E%3C%2Fcanvas%3E%0A%20%20%3Cdiv%20id%3D%22overlay%22%3E%3C%2Fdiv%3E%0A%0A%20%20%3Cdiv%20id%3D%22spellbar%22%20aria-label%3D%22Spell%20controls%22%3E%0A%20%20%20%20%3Cbutton%20data-spell%3D%22random%22%20title%3D%22Cast%20random%20spell%22%3E%F0%9F%AA%84%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20data-spell%3D%22lightning%22%20title%3D%22Lightning%20explosion%22%3E%E2%9A%A1%EF%B8%8F%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20data-spell%3D%22cloak%22%20title%3D%22Invisibility%22%3E%F0%9F%91%BB%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20data-spell%3D%22runes%22%20title%3D%22CHAIN%20MANCER%20runes%22%3E%F0%9F%93%9C%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20data-spell%3D%22fire%22%20title%3D%22Flamethrower%20spell%22%3E%F0%9F%94%A5%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20data-spell%3D%22stars%22%20title%3D%22Sacred%20geometry%20starburst%22%3E%E2%AD%90%EF%B8%8F%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20data-spell%3D%22cosmos%22%20title%3D%223D%20pixel%20cosmos%22%3E%E2%9C%A8%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20data-spell%3D%22skull%22%20title%3D%22Black%20pixels%20to%20skulls%22%3E%F0%9F%92%80%3C%2Fbutton%3E%0A%20%20%3C%2Fdiv%3E%0A%3C%2Fdiv%3E%0A%0A%3Caudio%20id%3D%22fireSpellAudio%22%20preload%3D%22auto%22%20src%3D%22https%3A%2F%2Fwww.myinstants.com%2Fmedia%2Fsounds%2Fflamethrower.mp3%22%3E%3C%2Faudio%3E%0A%20%20%3Caudio%20id%3D%22skullSpellAudio%22%20preload%3D%22auto%22%20src%3D%22https%3A%2F%2Fwww.myinstants.com%2Fmedia%2Fsounds%2Fundertakers-bell_2UwFCIe.mp3%22%3E%3C%2Faudio%3E%0A%20%20%3Caudio%20id%3D%22starSpellAudio%22%20preload%3D%22auto%22%20src%3D%22https%3A%2F%2Fwww.myinstants.com%2Fmedia%2Fsounds%2Fsparkle-sound-effect.mp3%22%3E%3C%2Faudio%3E%0A%20%20%3Caudio%20id%3D%22lightningSpellAudio%22%20preload%3D%22auto%22%20src%3D%22https%3A%2F%2Fwww.myinstants.com%2Fmedia%2Fsounds%2Feletricity.mp3%22%3E%3C%2Faudio%3E%0A%20%20%3Caudio%20id%3D%22ghostSpellAudio%22%20preload%3D%22auto%22%20src%3D%22https%3A%2F%2Fwww.myinstants.com%2Fmedia%2Fsounds%2F04-sound-effects_-eerie-ghost-voice.mp3%22%3E%3C%2Faudio%3E%0A%20%20%3Caudio%20id%3D%22runeSpellAudio%22%20preload%3D%22auto%22%20src%3D%22https%3A%2F%2Fwww.myinstants.com%2Fmedia%2Fsounds%2Fspooky-indian-mystery.mp3%22%3E%3C%2Faudio%3E%0A%20%20%20%20%3Caudio%20id%3D%22wandSpellAudio%22%20preload%3D%22auto%22%20src%3D%22https%3A%2F%2Fwww.myinstants.com%2Fmedia%2Fsounds%2Fgrave-robber-flashing-dagger-miss.mp3%22%3E%3C%2Faudio%3E%0A%3Caudio%20id%3D%22cosmosSpellAudio%22%20preload%3D%22auto%22%20src%3D%22https%3A%2F%2Fwww.myinstants.com%2Fmedia%2Fsounds%2Fspace-music.mp3%22%3E%3C%2Faudio%3E%0A%0A%3Cscript%3E%0A(()%20%3D%3E%20%7B%0A%20%20const%20BASE64%20%3D%20%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd%2BUAAABK0lEQVR42u3VOw7CMAwGYC9MRdCqZQH1ANkZWbkDh2HnUogDcYmiIBn9dewmVgExMFhCoeTDj6TUNPXwzaA%2F%2BBMgEY3io2AEQtg%2Fo9tsh2q5dqE0B%2BPwoFRaKgvzooQb3q%2FHUfAGOcyDksRul%2F6VIaMWxuueno5AxmSJLUy2oATNglp2GoboLDBGKYbPW2gyNFoPPVgxqE3qFMbfW2sWStYZlH3xYMVgLCcej%2FOpTUD5jLX21gzfUlKE%2B2Yxq39uMOyq5EiUTmiMCMXfZKeUwUPokn9bik5hWVD2Noci5gK5h7IXUyhi8XPRwZcZ4h2Km%2BCg4M2E2Kpu%2FUOjve94E5xKRhHjkKgLxPJiZnxBSIzDBHkDLqmVIaKIaRnKLEm%2B%2B7SDLzHZSwlqKIMPUfDS2ezIONwAAAAASUVORK5CYII%3D%22%3B%0A%0A%20%20const%20stage%20%20%20%3D%20document.getElementById(%22stage%22)%3B%0A%20%20const%20wizard%20%3D%20document.getElementById(%22wizard%22)%3B%0A%20%20const%20runes%20%20%20%20%3D%20document.getElementById(%22runes%22)%3B%0A%20%20const%20fx%20%20%20%20%20%20%20%3D%20document.getElementById(%22fx%22)%3B%0A%20%20const%20cosmos%20%20%20%3D%20document.getElementById(%22cosmos%22)%3B%0A%20%20const%20overlay%20%20%3D%20document.getElementById(%22overlay%22)%3B%0A%20%20const%20spellbar%20%3D%20document.getElementById(%22spellbar%22)%3B%0A%20%20const%20fireSpellAudio%20%3D%20document.getElementById(%22fireSpellAudio%22)%3B%0A%20%20const%20skullSpellAudio%20%3D%20document.getElementById(%22skullSpellAudio%22)%3B%0A%20%20const%20starSpellAudio%20%3D%20document.getElementById(%22starSpellAudio%22)%3B%0A%20%20const%20lightningSpellAudio%20%3D%20document.getElementById(%22lightningSpellAudio%22)%3B%0A%20%20const%20ghostSpellAudio%20%3D%20document.getElementById(%22ghostSpellAudio%22)%3B%0A%20%20const%20runeSpellAudio%20%3D%20document.getElementById(%22runeSpellAudio%22)%3B%0A%20%20const%20cosmosSpellAudio%20%3D%20document.getElementById(%22cosmosSpellAudio%22)%3B%0A%20%20const%20wandSpellAudio%20%3D%20document.getElementById(%22wandSpellAudio%22)%3B%0A%0A%20%20const%20wctx%20%3D%20wizard.getContext(%222d%22%2C%20%7B%20alpha%3Atrue%20%7D)%3B%0A%20%20const%20rctx%20%3D%20runes.getContext(%222d%22%2C%20%7B%20alpha%3Atrue%20%7D)%3B%0A%20%20const%20fctx%20%3D%20fx.getContext(%222d%22%2C%20%7B%20alpha%3Atrue%20%7D)%3B%0A%20%20const%20cctx%20%3D%20cosmos.getContext(%222d%22%2C%20%7B%20alpha%3Afalse%20%7D)%3B%0A%0A%20%20wctx.imageSmoothingEnabled%20%3D%20false%3B%0A%20%20rctx.imageSmoothingEnabled%20%3D%20false%3B%0A%20%20fctx.imageSmoothingEnabled%20%3D%20false%3B%0A%20%20cctx.imageSmoothingEnabled%20%3D%20false%3B%0A%0A%20%20const%20img%20%3D%20new%20Image()%3B%0A%20%20let%20sourcePixels%20%3D%20null%3B%0A%20%20let%20particles%20%3D%20%5B%5D%3B%0A%20%20let%20animating%20%3D%20false%3B%0A%20%20let%20cloaked%20%3D%20false%3B%0A%0A%20%20%2F%2F%20Image-aware%20spell%20data%3A%20populated%20from%20the%20original%2028x28%20PNG.%0A%20%20const%20sourceCanvas%20%3D%20document.createElement(%22canvas%22)%3B%0A%20%20sourceCanvas.width%20%3D%2028%3B%0A%20%20sourceCanvas.height%20%3D%2028%3B%0A%20%20const%20sourceCtx%20%3D%20sourceCanvas.getContext(%222d%22%2C%20%7Balpha%3Atrue%7D)%3B%0A%20%20sourceCtx.imageSmoothingEnabled%20%3D%20false%3B%0A%20%20let%20yellowSpellPixels%20%3D%20%5B%5D%3B%0A%20%20let%20blackSpellPixels%20%3D%20%5B%5D%3B%0A%20%20let%20fireActive%20%3D%20false%3B%0A%20%20let%20fireEmitterTimer%20%3D%20null%3B%0A%0A%20%20%2F%2F%20Sacred%20geometry%20star%20spell%20state.%0A%20%20let%20starGeomActive%20%3D%20false%3B%0A%20%20let%20starGeomParticles%20%3D%20%5B%5D%3B%0A%20%20let%20starGeomRAF%20%3D%20null%3B%0A%0A%20%20%2F%2F%203D%20cosmos%20state.%0A%20%20let%20cosmosActive%20%3D%20false%3B%0A%20%20let%20cosmosParticles%20%3D%20%5B%5D%3B%0A%20%20let%20cosmosRAF%20%3D%20null%3B%0A%20%20let%20cosmosRotX%20%3D%20-0.20%3B%0A%20%20let%20cosmosRotY%20%3D%200.35%3B%0A%20%20let%20cosmosZoom%20%3D%201.0%3B%0A%20%20let%20cosmosPanX%20%3D%200%3B%0A%20%20let%20cosmosPanY%20%3D%200%3B%0A%20%20let%20cosmosDragging%20%3D%20false%3B%0A%20%20let%20cosmosReforming%20%3D%20false%3B%0A%20%20let%20cosmosReformStart%20%3D%200%3B%0A%20%20let%20cosmosExpandStart%20%3D%200%3B%0A%20%20const%20COSMOS_EXPAND_MS%20%3D%202400%3B%0A%20%20let%20cosmosLastX%20%3D%200%3B%0A%20%20let%20cosmosLastY%20%3D%200%3B%0A%20%20let%20cosmosPinchDistance%20%3D%200%3B%0A%0A%20%20img.onload%20%3D%20()%20%3D%3E%20%7B%0A%20%20%20%20sourceCtx.clearRect(0%2C0%2C28%2C28)%3B%0A%20%20%20%20sourceCtx.drawImage(img%2C0%2C0%2C28%2C28)%3B%0A%20%20%20%20scanYellowSpellPixels()%3B%0A%20%20%20%20scanBlackSpellPixels()%3B%0A%20%20%20%20drawWizard()%3B%0A%20%20%20%20overlay.style.setProperty(%22--wizard-mask%22%2C%20%60url(%22%24%7BBASE64%7D%22)%60)%3B%0A%20%20%7D%3B%0A%20%20img.src%20%3D%20BASE64%3B%0A%0A%20%20function%20isYellowGoldPixel(r%2Cg%2Cb%2Ca)%7B%0A%20%20%20%20if(a%20%3C%2070)%20return%20false%3B%0A%0A%20%20%20%20%2F%2F%20Broad%20yellow%2Fgold%20detector%20tuned%20for%20pixel-art%20palettes%3A%0A%20%20%20%20%2F%2F%20warm%20red%20%2B%20green%20dominance%2C%20with%20blue%20substantially%20lower.%0A%20%20%20%20const%20max%20%3D%20Math.max(r%2Cg%2Cb)%3B%0A%20%20%20%20const%20min%20%3D%20Math.min(r%2Cg%2Cb)%3B%0A%20%20%20%20const%20chroma%20%3D%20max%20-%20min%3B%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20r%20%3E%3D%20105%20%26%26%0A%20%20%20%20%20%20g%20%3E%3D%2078%20%26%26%0A%20%20%20%20%20%20b%20%3C%3D%20145%20%26%26%0A%20%20%20%20%20%20r%20%3E%20b%20*%201.18%20%26%26%0A%20%20%20%20%20%20g%20%3E%20b%20*%201.08%20%26%26%0A%20%20%20%20%20%20chroma%20%3E%3D%2028%20%26%26%0A%20%20%20%20%20%20%2F%2F%20Include%20yellow%2C%20ochre%20and%20gold%20while%20rejecting%20red%2Fbrown%20shadows.%0A%20%20%20%20%20%20(g%20%2F%20Math.max(r%2C1))%20%3E%3D%200.48%0A%20%20%20%20)%3B%0A%20%20%7D%0A%0A%20%20function%20scanYellowSpellPixels()%7B%0A%20%20%20%20yellowSpellPixels%20%3D%20%5B%5D%3B%0A%20%20%20%20const%20data%20%3D%20sourceCtx.getImageData(0%2C0%2C28%2C28).data%3B%0A%0A%20%20%20%20for(let%20y%3D0%3B%20y%3C28%3B%20y%2B%2B)%7B%0A%20%20%20%20%20%20for(let%20x%3D0%3B%20x%3C28%3B%20x%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20i%20%3D%20(y*28%2Bx)*4%3B%0A%20%20%20%20%20%20%20%20const%20r%3Ddata%5Bi%5D%2C%20g%3Ddata%5Bi%2B1%5D%2C%20b%3Ddata%5Bi%2B2%5D%2C%20a%3Ddata%5Bi%2B3%5D%3B%0A%0A%20%20%20%20%20%20%20%20if(isYellowGoldPixel(r%2Cg%2Cb%2Ca))%7B%0A%20%20%20%20%20%20%20%20%20%20yellowSpellPixels.push(%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sx%3Ax%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20sy%3Ay%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20r%2Cg%2Cb%2Ca%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20exact%20centre%20of%20the%20corresponding%2014x14%20block%20in%20392x392%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Ax*14%2B7%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Ay*14%2B7%0A%20%20%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%0A%0A%20%20function%20isBlackSpellPixel(r%2Cg%2Cb%2Ca)%7B%0A%20%20%20%20%2F%2F%20%F0%9F%92%80%20spell%20targets%20ONLY%20exact%2C%20fully%20opaque%20%23000000%20pixels.%0A%20%20%20%20return%20r%20%3D%3D%3D%200%20%26%26%20g%20%3D%3D%3D%200%20%26%26%20b%20%3D%3D%3D%200%20%26%26%20a%20%3D%3D%3D%20255%3B%0A%20%20%7D%0A%0A%20%20function%20scanBlackSpellPixels()%7B%0A%20%20%20%20blackSpellPixels%20%3D%20%5B%5D%3B%0A%20%20%20%20const%20data%20%3D%20sourceCtx.getImageData(0%2C0%2C28%2C28).data%3B%0A%0A%20%20%20%20for(let%20y%3D0%3B%20y%3C28%3B%20y%2B%2B)%7B%0A%20%20%20%20%20%20for(let%20x%3D0%3B%20x%3C28%3B%20x%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20i%3D(y*28%2Bx)*4%3B%0A%20%20%20%20%20%20%20%20const%20r%3Ddata%5Bi%5D%2C%20g%3Ddata%5Bi%2B1%5D%2C%20b%3Ddata%5Bi%2B2%5D%2C%20a%3Ddata%5Bi%2B3%5D%3B%0A%0A%20%20%20%20%20%20%20%20if(isBlackSpellPixel(r%2Cg%2Cb%2Ca))%7B%0A%20%20%20%20%20%20%20%20%20%20blackSpellPixels.push(%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sx%3Ax%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20sy%3Ay%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Ax*14%2B7%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Ay*14%2B7%0A%20%20%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20drawWizardWithoutBlack()%7B%0A%20%20%20%20wctx.clearRect(0%2C0%2C392%2C392)%3B%0A%20%20%20%20wctx.imageSmoothingEnabled%20%3D%20false%3B%0A%0A%20%20%20%20const%20src%20%3D%20sourceCtx.getImageData(0%2C0%2C28%2C28).data%3B%0A%0A%20%20%20%20for(let%20y%3D0%3B%20y%3C28%3B%20y%2B%2B)%7B%0A%20%20%20%20%20%20for(let%20x%3D0%3B%20x%3C28%3B%20x%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20i%3D(y*28%2Bx)*4%3B%0A%20%20%20%20%20%20%20%20const%20r%3Dsrc%5Bi%5D%2C%20g%3Dsrc%5Bi%2B1%5D%2C%20b%3Dsrc%5Bi%2B2%5D%2C%20a%3Dsrc%5Bi%2B3%5D%3B%0A%0A%20%20%20%20%20%20%20%20if(a%3D%3D%3D0)%20continue%3B%0A%20%20%20%20%20%20%20%20if(isBlackSpellPixel(r%2Cg%2Cb%2Ca))%20continue%3B%0A%0A%20%20%20%20%20%20%20%20wctx.fillStyle%3D%60rgba(%24%7Br%7D%2C%24%7Bg%7D%2C%24%7Bb%7D%2C%24%7Ba%2F255%7D)%60%3B%0A%20%20%20%20%20%20%20%20wctx.fillRect(x*14%2Cy*14%2C14%2C14)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20drawWizardWithoutYellow()%7B%0A%20%20%20%20wctx.clearRect(0%2C0%2C392%2C392)%3B%0A%20%20%20%20wctx.imageSmoothingEnabled%20%3D%20false%3B%0A%0A%20%20%20%20%2F%2F%20Redraw%20the%20source%20pixel-by-pixel%2C%20skipping%20detected%20yellow%2Fgold%20pixels.%0A%20%20%20%20const%20src%20%3D%20sourceCtx.getImageData(0%2C0%2C28%2C28).data%3B%0A%0A%20%20%20%20for(let%20y%3D0%3B%20y%3C28%3B%20y%2B%2B)%7B%0A%20%20%20%20%20%20for(let%20x%3D0%3B%20x%3C28%3B%20x%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20i%3D(y*28%2Bx)*4%3B%0A%20%20%20%20%20%20%20%20const%20r%3Dsrc%5Bi%5D%2C%20g%3Dsrc%5Bi%2B1%5D%2C%20b%3Dsrc%5Bi%2B2%5D%2C%20a%3Dsrc%5Bi%2B3%5D%3B%0A%20%20%20%20%20%20%20%20if(a%3D%3D%3D0)%20continue%3B%0A%20%20%20%20%20%20%20%20if(isYellowGoldPixel(r%2Cg%2Cb%2Ca))%20continue%3B%0A%0A%20%20%20%20%20%20%20%20wctx.fillStyle%3D%60rgba(%24%7Br%7D%2C%24%7Bg%7D%2C%24%7Bb%7D%2C%24%7Ba%2F255%7D)%60%3B%0A%20%20%20%20%20%20%20%20wctx.fillRect(x*14%2Cy*14%2C14%2C14)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20drawWizard()%7B%0A%20%20%20%20wctx.clearRect(0%2C0%2C392%2C392)%3B%0A%20%20%20%20wctx.imageSmoothingEnabled%20%3D%20false%3B%0A%0A%20%20%20%20%2F%2F%20Source%20is%2028x28.%20The%20stage%20is%20exactly%20392x392%20%3D%2028%20x%2014%2C%0A%20%20%20%20%2F%2F%20so%20every%20source%20pixel%20becomes%20an%20exact%2014x14%20block.%0A%20%20%20%20wctx.drawImage(img%2C%200%2C0%2C28%2C28%2C%200%2C0%2C392%2C392)%3B%0A%20%20%20%20sourcePixels%20%3D%20wctx.getImageData(0%2C0%2C392%2C392)%3B%0A%20%20%7D%0A%0A%20%20function%20restoreWizard()%7B%0A%20%20%20%20wizard.style.visibility%20%3D%20%22visible%22%3B%0A%20%20%20%20wizard.style.transform%20%3D%20%22%22%3B%0A%20%20%20%20wizard.style.filter%20%3D%20%22%22%3B%0A%20%20%20%20if(sourcePixels)%20wctx.putImageData(sourcePixels%2C0%2C0)%3B%0A%20%20%7D%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20SINGLE%20TAP%20%2F%20CLICK%3A%20random%20spell%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20function%20castRandomSpell(x%3D196%2Cy%3D186)%7B%0A%20%20%20%20playSpellAudio(wandSpellAudio%2C.78%2C%22wand%22)%3B%0A%20%20%20%20const%20spell%20%3D%20Math.floor(Math.random()*3)%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%200)%20arcaneBurst(x%2Cy)%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%201)%20glitchSpell()%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%202)%20strobeSpell()%3B%0A%20%20%7D%0A%0A%20%20function%20arcaneBurst(x%2Cy)%7B%0A%20%20%20%20const%20glyphs%20%3D%20%5B%22%E2%9C%A6%22%2C%22%E2%9C%A7%22%2C%22%C2%B7%22%2C%22*%22%2C%22%E2%9C%BA%22%2C%22%E2%9A%A1%22%5D%3B%0A%20%20%20%20for(let%20i%3D0%3Bi%3C54%3Bi%2B%2B)%7B%0A%20%20%20%20%20%20const%20a%20%3D%20Math.random()*Math.PI*2%3B%0A%20%20%20%20%20%20const%20speed%20%3D%201.5%20%2B%20Math.random()*6%3B%0A%20%20%20%20%20%20particles.push(%7B%0A%20%20%20%20%20%20%20%20x%2Cy%2C%0A%20%20%20%20%20%20%20%20vx%3AMath.cos(a)*speed%2C%0A%20%20%20%20%20%20%20%20vy%3AMath.sin(a)*speed%2C%0A%20%20%20%20%20%20%20%20life%3A45%2BMath.random()*45%2C%0A%20%20%20%20%20%20%20%20maxLife%3A90%2C%0A%20%20%20%20%20%20%20%20size%3A8%2BMath.random()*18%2C%0A%20%20%20%20%20%20%20%20rot%3AMath.random()*Math.PI*2%2C%0A%20%20%20%20%20%20%20%20vr%3A(Math.random()-.5)*.2%2C%0A%20%20%20%20%20%20%20%20glyph%3Aglyphs%5BMath.floor(Math.random()*glyphs.length)%5D%2C%0A%20%20%20%20%20%20%20%20type%3A%22glyph%22%0A%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%7D%0A%20%20%20%20startAnimation()%3B%0A%20%20%7D%0A%0A%20%20function%20glitchSpell()%7B%0A%20%20%20%20wizard.classList.remove(%22glitch%22)%3B%0A%20%20%20%20void%20wizard.offsetWidth%3B%0A%20%20%20%20wizard.classList.add(%22glitch%22)%3B%0A%20%20%20%20setTimeout(()%3D%3Ewizard.classList.remove(%22glitch%22)%2C700)%3B%0A%20%20%7D%0A%0A%20%20function%20strobeSpell()%7B%0A%20%20%20%20wizard.classList.remove(%22strobe%22)%3B%0A%20%20%20%20void%20wizard.offsetWidth%3B%0A%20%20%20%20wizard.classList.add(%22strobe%22)%3B%0A%20%20%20%20setTimeout(()%3D%3Ewizard.classList.remove(%22strobe%22)%2C3200)%3B%0A%20%20%7D%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20DOUBLE%20TAP%20%2F%20CLICK%3A%20wizard%20explodes%20into%20%E2%9A%A1%20and%20reforms%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20function%20lightningExplosion()%7B%0A%20%20%20%20if(!sourcePixels%20%7C%7C%20!yellowSpellPixels.length)%20return%3B%0A%20%20%20%20playSpellAudio(lightningSpellAudio%2C.80%2C%22lightning%22)%3B%0A%0A%20%20%20%20particles%20%3D%20particles.filter(p%20%3D%3E%20p.type%20!%3D%3D%20%22yellowLightning%22)%3B%0A%20%20%20%20wizard.style.visibility%20%3D%20%22visible%22%3B%0A%20%20%20%20drawWizardWithoutYellow()%3B%0A%0A%20%20%20%20for(const%20px%20of%20yellowSpellPixels)%7B%0A%20%20%20%20%20%20const%20angle%20%3D%20Math.random()*Math.PI*2%3B%0A%20%20%20%20%20%20const%20speed%20%3D%201.8%20%2B%20Math.random()*4.6%3B%0A%0A%20%20%20%20%20%20particles.push(%7B%0A%20%20%20%20%20%20%20%20x%3Apx.x%2C%0A%20%20%20%20%20%20%20%20y%3Apx.y%2C%0A%20%20%20%20%20%20%20%20homeX%3Apx.x%2C%0A%20%20%20%20%20%20%20%20homeY%3Apx.y%2C%0A%0A%20%20%20%20%20%20%20%20vx%3AMath.cos(angle)*speed%2C%0A%20%20%20%20%20%20%20%20vy%3AMath.sin(angle)*speed%2C%0A%0A%20%20%20%20%20%20%20%20life%3A600%2C%0A%20%20%20%20%20%20%20%20maxLife%3A600%2C%0A%20%20%20%20%20%20%20%20size%3A12%20%2B%20Math.random()*7%2C%0A%20%20%20%20%20%20%20%20rot%3A(Math.random()-.5)*.5%2C%0A%20%20%20%20%20%20%20%20vr%3A(Math.random()-.5)*.12%2C%0A%20%20%20%20%20%20%20%20glyph%3A%22%E2%9A%A1%22%2C%0A%20%20%20%20%20%20%20%20type%3A%22yellowLightning%22%2C%0A%0A%20%20%20%20%20%20%20%20phase%3A%22float%22%2C%0A%20%20%20%20%20%20%20%20age%3A0%2C%0A%20%20%20%20%20%20%20%20wanderSeed%3AMath.random()*1000%2C%0A%20%20%20%20%20%20%20%20returnDelay%3A145%20%2B%20Math.floor(Math.random()*35)%0A%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20startAnimation()%3B%0A%0A%20%20%20%20%2F%2F%20After%20a%20few%20seconds%20of%20free-floating%20wall-bouncing%20motion%2C%0A%20%20%20%20%2F%2F%20pull%20all%20emojis%20home%20to%20their%20exact%20source%20pixels.%0A%20%20%20%20setTimeout(()%3D%3E%7B%0A%20%20%20%20%20%20for(const%20p%20of%20particles)%7B%0A%20%20%20%20%20%20%20%20if(p.type%3D%3D%3D%22yellowLightning%22)%7B%0A%20%20%20%20%20%20%20%20%20%20p.phase%3D%22return%22%3B%0A%20%20%20%20%20%20%20%20%20%20p.life%3D82%3B%0A%20%20%20%20%20%20%20%20%20%20p.maxLife%3D82%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%2C5900)%3B%0A%0A%20%20%20%20setTimeout(()%3D%3E%7B%0A%20%20%20%20%20%20restoreWizard()%3B%0A%20%20%20%20%7D%2C6850)%3B%0A%0A%20%20%20%20setTimeout(()%3D%3E%7B%0A%20%20%20%20%20%20particles%20%3D%20particles.filter(p%3D%3Ep.type!%3D%3D%22yellowLightning%22)%3B%0A%20%20%20%20%20%20fctx.clearRect(0%2C0%2C392%2C392)%3B%0A%20%20%20%20%7D%2C7050)%3B%0A%20%20%7D%0A%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20FIRE%20SPELL%20%E2%80%94%20yellow%20pixels%20become%20%F0%9F%94%A5%20and%20blast%20outward%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20ROBUST%20SPELL%20AUDIO%0A%20%20%2F%2F%20Tries%20the%20requested%20Myinstants%20MP3%20first.%20If%20remote%20media%20is%20blocked%0A%20%20%2F%2F%20by%20the%20iframe%2Fbrowser%20sandbox%2C%20a%20local%20WebAudio%20spell%20sound%20is%20used.%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20let%20spellAudioCtx%20%3D%20null%3B%0A%0A%20%20function%20getSpellAudioCtx()%7B%0A%20%20%20%20if(!spellAudioCtx)%7B%0A%20%20%20%20%20%20const%20AC%20%3D%20window.AudioContext%20%7C%7C%20window.webkitAudioContext%3B%0A%20%20%20%20%20%20if(AC)%20spellAudioCtx%20%3D%20new%20AC()%3B%0A%20%20%20%20%7D%0A%20%20%20%20if(spellAudioCtx%20%26%26%20spellAudioCtx.state%20%3D%3D%3D%20%22suspended%22)%7B%0A%20%20%20%20%20%20spellAudioCtx.resume().catch(()%3D%3E%7B%7D)%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20spellAudioCtx%3B%0A%20%20%7D%0A%0A%20%20function%20noiseBuffer(ctx%2C%20seconds%3D1)%7B%0A%20%20%20%20const%20len%20%3D%20Math.max(1%2C%20Math.floor(ctx.sampleRate*seconds))%3B%0A%20%20%20%20const%20b%20%3D%20ctx.createBuffer(1%2Clen%2Cctx.sampleRate)%3B%0A%20%20%20%20const%20d%20%3D%20b.getChannelData(0)%3B%0A%20%20%20%20for(let%20i%3D0%3Bi%3Clen%3Bi%2B%2B)%20d%5Bi%5D%3DMath.random()*2-1%3B%0A%20%20%20%20return%20b%3B%0A%20%20%7D%0A%0A%20%20function%20synthFallback(kind%3D%22magic%22%2C%20volume%3D.35)%7B%0A%20%20%20%20const%20ctx%20%3D%20getSpellAudioCtx()%3B%0A%20%20%20%20if(!ctx)%20return%3B%0A%0A%20%20%20%20const%20now%20%3D%20ctx.currentTime%3B%0A%20%20%20%20const%20master%20%3D%20ctx.createGain()%3B%0A%20%20%20%20master.gain.setValueAtTime(Math.max(.02%2C%20volume)%2C%20now)%3B%0A%20%20%20%20master.connect(ctx.destination)%3B%0A%0A%20%20%20%20const%20osc%20%3D%20(type%2Cf0%2Cf1%2Cdur%2Cg%3D.3%2Cdelay%3D0)%3D%3E%7B%0A%20%20%20%20%20%20const%20o%3Dctx.createOscillator()%3B%0A%20%20%20%20%20%20const%20gn%3Dctx.createGain()%3B%0A%20%20%20%20%20%20o.type%3Dtype%3B%0A%20%20%20%20%20%20o.frequency.setValueAtTime(f0%2Cnow%2Bdelay)%3B%0A%20%20%20%20%20%20if(f1)%20o.frequency.exponentialRampToValueAtTime(Math.max(1%2Cf1)%2Cnow%2Bdelay%2Bdur)%3B%0A%20%20%20%20%20%20gn.gain.setValueAtTime(.0001%2Cnow%2Bdelay)%3B%0A%20%20%20%20%20%20gn.gain.exponentialRampToValueAtTime(Math.max(.002%2Cg)%2Cnow%2Bdelay%2B.02)%3B%0A%20%20%20%20%20%20gn.gain.exponentialRampToValueAtTime(.0001%2Cnow%2Bdelay%2Bdur)%3B%0A%20%20%20%20%20%20o.connect(gn)%3B%20gn.connect(master)%3B%0A%20%20%20%20%20%20o.start(now%2Bdelay)%3B%20o.stop(now%2Bdelay%2Bdur%2B.03)%3B%0A%20%20%20%20%7D%3B%0A%0A%20%20%20%20const%20noise%20%3D%20(dur%3D.4%2Cg%3D.18%2Ccut%3D1800%2Cdelay%3D0)%3D%3E%7B%0A%20%20%20%20%20%20const%20s%3Dctx.createBufferSource()%3B%0A%20%20%20%20%20%20const%20f%3Dctx.createBiquadFilter()%3B%0A%20%20%20%20%20%20const%20gn%3Dctx.createGain()%3B%0A%20%20%20%20%20%20s.buffer%3DnoiseBuffer(ctx%2Cdur%2B.05)%3B%0A%20%20%20%20%20%20f.type%3D%22lowpass%22%3B%20f.frequency.value%3Dcut%3B%0A%20%20%20%20%20%20gn.gain.setValueAtTime(.0001%2Cnow%2Bdelay)%3B%0A%20%20%20%20%20%20gn.gain.exponentialRampToValueAtTime(Math.max(.002%2Cg)%2Cnow%2Bdelay%2B.015)%3B%0A%20%20%20%20%20%20gn.gain.exponentialRampToValueAtTime(.0001%2Cnow%2Bdelay%2Bdur)%3B%0A%20%20%20%20%20%20s.connect(f)%3B%20f.connect(gn)%3B%20gn.connect(master)%3B%0A%20%20%20%20%20%20s.start(now%2Bdelay)%3B%20s.stop(now%2Bdelay%2Bdur%2B.03)%3B%0A%20%20%20%20%7D%3B%0A%0A%20%20%20%20if(kind%3D%3D%3D%22fire%22)%7B%0A%20%20%20%20%20%20noise(.85%2C.32%2C1200)%3B%0A%20%20%20%20%20%20osc(%22sawtooth%22%2C170%2C70%2C.8%2C.10)%3B%0A%20%20%20%20%20%20osc(%22triangle%22%2C95%2C55%2C.7%2C.08%2C.08)%3B%0A%20%20%20%20%7Delse%20if(kind%3D%3D%3D%22lightning%22)%7B%0A%20%20%20%20%20%20noise(.34%2C.36%2C4200)%3B%0A%20%20%20%20%20%20osc(%22square%22%2C900%2C95%2C.30%2C.16)%3B%0A%20%20%20%20%20%20osc(%22sawtooth%22%2C1500%2C180%2C.22%2C.08%2C.03)%3B%0A%20%20%20%20%7Delse%20if(kind%3D%3D%3D%22skull%22)%7B%0A%20%20%20%20%20%20osc(%22sine%22%2C110%2C58%2C1.35%2C.28)%3B%0A%20%20%20%20%20%20osc(%22sine%22%2C165%2C82%2C1.25%2C.13%2C.05)%3B%0A%20%20%20%20%7Delse%20if(kind%3D%3D%3D%22star%22)%7B%0A%20%20%20%20%20%20osc(%22sine%22%2C880%2C1760%2C.28%2C.18)%3B%0A%20%20%20%20%20%20osc(%22triangle%22%2C1320%2C2200%2C.30%2C.12%2C.10)%3B%0A%20%20%20%20%20%20osc(%22sine%22%2C1760%2C2640%2C.22%2C.08%2C.22)%3B%0A%20%20%20%20%7Delse%20if(kind%3D%3D%3D%22ghost%22)%7B%0A%20%20%20%20%20%20noise(1.2%2C.11%2C900)%3B%0A%20%20%20%20%20%20osc(%22sine%22%2C260%2C110%2C1.15%2C.13)%3B%0A%20%20%20%20%20%20osc(%22triangle%22%2C410%2C155%2C.9%2C.08%2C.16)%3B%0A%20%20%20%20%7Delse%20if(kind%3D%3D%3D%22rune%22)%7B%0A%20%20%20%20%20%20osc(%22sine%22%2C220%2C330%2C1.2%2C.12)%3B%0A%20%20%20%20%20%20osc(%22triangle%22%2C330%2C495%2C1.1%2C.08%2C.12)%3B%0A%20%20%20%20%20%20noise(1.0%2C.055%2C1400%2C.04)%3B%0A%20%20%20%20%7Delse%20if(kind%3D%3D%3D%22cosmos%22)%7B%0A%20%20%20%20%20%20osc(%22sine%22%2C90%2C135%2C2.2%2C.10)%3B%0A%20%20%20%20%20%20osc(%22sine%22%2C135%2C202%2C2.4%2C.07%2C.15)%3B%0A%20%20%20%20%20%20osc(%22triangle%22%2C270%2C405%2C1.8%2C.045%2C.3)%3B%0A%20%20%20%20%7Delse%20if(kind%3D%3D%3D%22wand%22)%7B%0A%20%20%20%20%20%20noise(.18%2C.12%2C3600)%3B%0A%20%20%20%20%20%20osc(%22triangle%22%2C1250%2C420%2C.34%2C.18)%3B%0A%20%20%20%20%20%20osc(%22sine%22%2C1900%2C760%2C.26%2C.09%2C.03)%3B%0A%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20osc(%22sine%22%2C440%2C880%2C.35%2C.15)%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20playSpellAudio(audio%2C%20volume%3D.78%2C%20fallbackKind%3D%22magic%22)%7B%0A%20%20%20%20const%20ctx%20%3D%20getSpellAudioCtx()%3B%0A%20%20%20%20if(ctx%20%26%26%20ctx.state%3D%3D%3D%22suspended%22)%20ctx.resume().catch(()%3D%3E%7B%7D)%3B%0A%0A%20%20%20%20if(!audio)%7B%0A%20%20%20%20%20%20synthFallback(fallbackKind%2Cvolume*.45)%3B%0A%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20fallbackFired%3Dfalse%3B%0A%20%20%20%20const%20fallback%3D()%3D%3E%7B%0A%20%20%20%20%20%20if(fallbackFired)%20return%3B%0A%20%20%20%20%20%20fallbackFired%3Dtrue%3B%0A%20%20%20%20%20%20synthFallback(fallbackKind%2Cvolume*.45)%3B%0A%20%20%20%20%7D%3B%0A%0A%20%20%20%20try%7B%0A%20%20%20%20%20%20audio.pause()%3B%0A%20%20%20%20%20%20audio.currentTime%3D0%3B%0A%20%20%20%20%20%20audio.volume%3Dvolume%3B%0A%0A%20%20%20%20%20%20const%20onError%3D()%3D%3E%7B%0A%20%20%20%20%20%20%20%20audio.removeEventListener(%22error%22%2ConError)%3B%0A%20%20%20%20%20%20%20%20fallback()%3B%0A%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20audio.addEventListener(%22error%22%2ConError%2C%7Bonce%3Atrue%7D)%3B%0A%0A%20%20%20%20%20%20if(audio.readyState%3D%3D%3D0)%20audio.load()%3B%0A%0A%20%20%20%20%20%20const%20p%3Daudio.play()%3B%0A%20%20%20%20%20%20if(p%20%26%26%20typeof%20p.catch%3D%3D%3D%22function%22)%7B%0A%20%20%20%20%20%20%20%20p.catch(()%3D%3Efallback())%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%2F%2F%20Some%20sandboxes%20silently%20refuse%20remote%20media%20without%20rejecting%20play().%0A%20%20%20%20%20%20setTimeout(()%3D%3E%7B%0A%20%20%20%20%20%20%20%20try%7B%0A%20%20%20%20%20%20%20%20%20%20if(audio.paused%20%7C%7C%20audio.readyState%20%3C%202%20%7C%7C%20audio.currentTime%20%3C%20.02)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20fallback()%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7Dcatch(_)%7B%0A%20%20%20%20%20%20%20%20%20%20fallback()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%2C220)%3B%0A%20%20%20%20%7Dcatch(_)%7B%0A%20%20%20%20%20%20fallback()%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20stopSpellAudio(audio)%7B%0A%20%20%20%20if(!audio)%20return%3B%0A%20%20%20%20try%7B%0A%20%20%20%20%20%20audio.pause()%3B%0A%20%20%20%20%20%20audio.currentTime%3D0%3B%0A%20%20%20%20%7Dcatch(_)%7B%7D%0A%20%20%7D%0A%0A%20%20function%20playFireSpellSound()%7B%0A%20%20%20%20playSpellAudio(fireSpellAudio%2C.82%2C%22fire%22)%3B%0A%20%20%7D%0A%0A%20%20function%20fireSpell()%7B%0A%20%20%20%20fireActive%20%3D%20!fireActive%3B%0A%0A%20%20%20%20if(fireActive)%7B%0A%20%20%20%20%20%20playFireSpellSound()%3B%0A%20%20%20%20%20%20drawWizardWithoutYellow()%3B%0A%0A%20%20%20%20%20%20if(fireEmitterTimer)%7B%0A%20%20%20%20%20%20%20%20clearInterval(fireEmitterTimer)%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20fireEmitterTimer%20%3D%20setInterval(()%3D%3E%7B%0A%20%20%20%20%20%20%20%20if(!fireActive)%20return%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Emit%20from%20the%20actual%20yellow%2Fgold%20source%20pixels.%0A%20%20%20%20%20%20%20%20const%20emitCount%20%3D%20Math.max(2%2C%20Math.round(yellowSpellPixels.length%20*%20.11))%3B%0A%0A%20%20%20%20%20%20%20%20for(let%20i%3D0%3Bi%3CemitCount%3Bi%2B%2B)%7B%0A%20%20%20%20%20%20%20%20%20%20const%20px%20%3D%20yellowSpellPixels%5BMath.floor(Math.random()*yellowSpellPixels.length)%5D%3B%0A%20%20%20%20%20%20%20%20%20%20if(!px)%20continue%3B%0A%0A%20%20%20%20%20%20%20%20%20%20particles.push(%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Apx.x%20%2B%20(Math.random()-.5)*4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Apx.y%20%2B%20(Math.random()-.5)*4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20homeX%3Apx.x%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20homeY%3Apx.y%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20Flow%20generally%20to%20the%20right%2C%20with%20soft%20upward%20flame%20lift.%0A%20%20%20%20%20%20%20%20%20%20%20%20vx%3A1.5%20%2B%20Math.random()*2.7%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20vy%3A-.35%20%2B%20(Math.random()-.5)*1.05%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20life%3A52%20%2B%20Math.random()*30%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20maxLife%3A82%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20size%3A10%20%2B%20Math.random()*8%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20rot%3A(Math.random()-.5)*.20%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20vr%3A(Math.random()-.5)*.07%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20glyph%3A%22%F0%9F%94%A5%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%22fireFlow%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20age%3A0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20seed%3AMath.random()*1000%0A%20%20%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20startAnimation()%3B%0A%20%20%20%20%20%20%7D%2C70)%3B%0A%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20if(fireEmitterTimer)%7B%0A%20%20%20%20%20%20%20%20clearInterval(fireEmitterTimer)%3B%0A%20%20%20%20%20%20%20%20fireEmitterTimer%20%3D%20null%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%2F%2F%20Existing%20flames%20fade%20naturally%2C%20then%20the%20yellow%20pixels%20return.%0A%20%20%20%20%20%20setTimeout(()%3D%3E%7B%0A%20%20%20%20%20%20%20%20restoreWizard()%3B%0A%20%20%20%20%20%20%7D%2C420)%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20LONG%20PRESS%3A%20invisibility%20cloak%20toggle%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20function%20invisibilitySpell()%7B%0A%20%20%20%20cloaked%20%3D%20!cloaked%3B%0A%20%20%20%20if(cloaked)%20playSpellAudio(ghostSpellAudio%2C.74%2C%22ghost%22)%3B%0A%20%20%20%20else%20stopSpellAudio(ghostSpellAudio)%3B%0A%20%20%20%20wizard.style.opacity%20%3D%20cloaked%20%3F%20%220.10%22%20%3A%20%221%22%3B%0A%20%20%20%20overlay.style.opacity%20%3D%20%220%22%3B%0A%20%20%7D%0A%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20ARCANE%20RUNE%20SCRIPTURE%20%E2%80%94%20%22CHAIN%20MANCER%22%0A%20%20%2F%2F%20Runic%20transliteration%3A%20%E1%9A%B2%E1%9A%BA%E1%9A%A8%E1%9B%81%E1%9A%BE%20%E1%9B%97%E1%9A%A8%E1%9A%BE%E1%9A%B2%E1%9B%96%E1%9A%B1%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20const%20RUNE_PHRASE%20%3D%20Array.from(%22%E1%9A%B2%E1%9A%BA%E1%9A%A8%E1%9B%81%E1%9A%BE%20%E1%9B%97%E1%9A%A8%E1%9A%BE%E1%9A%B2%E1%9B%96%E1%9A%B1%22)%3B%0A%0A%20%20let%20runeParticles%20%3D%20%5B%5D%3B%0A%20%20let%20runeMode%20%3D%20false%3B%0A%20%20let%20runeRAF%20%3D%20null%3B%0A%0A%20%20function%20seedRunes()%7B%0A%20%20%20%20runeParticles%20%3D%20%5B%5D%3B%0A%0A%20%20%20%20%2F%2F%20Three%20slow%20scripture%20bands%2C%20each%20spelling%20CHAIN%20MANCER.%0A%20%20%20%20const%20rings%20%3D%20%5B%0A%20%20%20%20%20%20%7Bradius%3A88%2C%20%20squash%3A.72%2C%20speed%3A%200.00115%2C%20phase%3A0.0%7D%2C%0A%20%20%20%20%20%20%7Bradius%3A128%2C%20squash%3A.76%2C%20speed%3A-0.00082%2C%20phase%3A1.35%7D%2C%0A%20%20%20%20%20%20%7Bradius%3A164%2C%20squash%3A.80%2C%20speed%3A%200.00058%2C%20phase%3A2.60%7D%0A%20%20%20%20%5D%3B%0A%0A%20%20%20%20rings.forEach((ring%2C%20ringIndex)%3D%3E%7B%0A%20%20%20%20%20%20const%20count%20%3D%20RUNE_PHRASE.length%3B%0A%20%20%20%20%20%20RUNE_PHRASE.forEach((glyph%2C%20i)%3D%3E%7B%0A%20%20%20%20%20%20%20%20runeParticles.push(%7B%0A%20%20%20%20%20%20%20%20%20%20glyph%2C%0A%20%20%20%20%20%20%20%20%20%20ringIndex%2C%0A%20%20%20%20%20%20%20%20%20%20angle%3Aring.phase%20%2B%20(i%2Fcount)*Math.PI*2%2C%0A%20%20%20%20%20%20%20%20%20%20radius%3Aring.radius%2C%0A%20%20%20%20%20%20%20%20%20%20squash%3Aring.squash%2C%0A%20%20%20%20%20%20%20%20%20%20speed%3Aring.speed%2C%0A%20%20%20%20%20%20%20%20%20%20size%3AringIndex%3D%3D%3D0%20%3F%2017%20%3A%20(ringIndex%3D%3D%3D1%20%3F%2015%20%3A%2013)%2C%0A%20%20%20%20%20%20%20%20%20%20alpha%3AringIndex%3D%3D%3D0%20%3F%20.92%20%3A%20(ringIndex%3D%3D%3D1%20%3F%20.74%20%3A%20.58)%2C%0A%20%20%20%20%20%20%20%20%20%20phase%3Ai*.73%20%2B%20ringIndex*1.7%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%7D)%3B%0A%20%20%7D%0A%0A%20%20function%20toggleRunes(force)%7B%0A%20%20%20%20runeMode%20%3D%20typeof%20force%20%3D%3D%3D%20%22boolean%22%20%3F%20force%20%3A%20!runeMode%3B%0A%0A%20%20%20%20if(runeMode)%7B%0A%20%20%20%20%20%20playSpellAudio(runeSpellAudio%2C.64%2C%22rune%22)%3B%0A%20%20%20%20%20%20if(!runeParticles.length)%20seedRunes()%3B%0A%20%20%20%20%20%20if(!runeRAF)%20runeRAF%20%3D%20requestAnimationFrame(drawRunes)%3B%0A%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20stopSpellAudio(runeSpellAudio)%3B%0A%20%20%20%20%20%20rctx.clearRect(0%2C0%2C392%2C392)%3B%0A%20%20%20%20%20%20if(runeRAF)%20cancelAnimationFrame(runeRAF)%3B%0A%20%20%20%20%20%20runeRAF%20%3D%20null%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20drawRunes(t)%7B%0A%20%20%20%20if(!runeMode)%7B%0A%20%20%20%20%20%20runeRAF%20%3D%20null%3B%0A%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20rctx.clearRect(0%2C0%2C392%2C392)%3B%0A%0A%20%20%20%20const%20cx%20%3D%20196%3B%0A%20%20%20%20const%20cy%20%3D%20208%3B%0A%0A%20%20%20%20%2F%2F%20Very%20faint%20orbit%20guides.%0A%20%20%20%20rctx.save()%3B%0A%20%20%20%20rctx.translate(cx%2Ccy)%3B%0A%20%20%20%20rctx.globalCompositeOperation%20%3D%20%22lighter%22%3B%0A%20%20%20%20rctx.strokeStyle%20%3D%20%22rgba(255%2C190%2C45%2C.10)%22%3B%0A%20%20%20%20rctx.lineWidth%20%3D%201%3B%0A%20%20%20%20%5B88%2C128%2C164%5D.forEach((r%2Cidx)%3D%3E%7B%0A%20%20%20%20%20%20rctx.beginPath()%3B%0A%20%20%20%20%20%20rctx.ellipse(0%2C0%2Cr%2Cr*%5B.72%2C.76%2C.80%5D%5Bidx%5D%2C0%2C0%2CMath.PI*2)%3B%0A%20%20%20%20%20%20rctx.stroke()%3B%0A%20%20%20%20%7D)%3B%0A%20%20%20%20rctx.restore()%3B%0A%0A%20%20%20%20for(const%20p%20of%20runeParticles)%7B%0A%20%20%20%20%20%20%2F%2F%20Deliberately%20slow%20movement.%0A%20%20%20%20%20%20p.angle%20%2B%3D%20p.speed%20*%2016.67%3B%0A%0A%20%20%20%20%20%20const%20breathe%20%3D%20Math.sin((t%7C%7C0)*.0009%20%2B%20p.phase)*2.5%3B%0A%20%20%20%20%20%20const%20rr%20%3D%20p.radius%20%2B%20breathe%3B%0A%0A%20%20%20%20%20%20const%20x%20%3D%20cx%20%2B%20Math.cos(p.angle)*rr%3B%0A%20%20%20%20%20%20const%20y%20%3D%20cy%20%2B%20Math.sin(p.angle)*rr*p.squash%3B%0A%0A%20%20%20%20%20%20const%20shimmer%20%3D%20.80%20%2B%20.20*Math.sin((t%7C%7C0)*.0014%2Bp.phase)%3B%0A%0A%20%20%20%20%20%20rctx.save()%3B%0A%20%20%20%20%20%20rctx.translate(Math.round(x)%2CMath.round(y))%3B%0A%0A%20%20%20%20%20%20%2F%2F%20Tangential%20orientation%20makes%20the%20phrase%20feel%20written%20around%20the%20orbit.%0A%20%20%20%20%20%20rctx.rotate(p.angle%20%2B%20Math.PI%2F2)%3B%0A%0A%20%20%20%20%20%20rctx.globalCompositeOperation%20%3D%20%22lighter%22%3B%0A%20%20%20%20%20%20rctx.globalAlpha%20%3D%20p.alpha%3B%0A%20%20%20%20%20%20rctx.shadowColor%20%3D%20%22rgba(255%2C184%2C35%2C.72)%22%3B%0A%20%20%20%20%20%20rctx.shadowBlur%20%3D%205%3B%0A%0A%20%20%20%20%20%20rctx.fillStyle%20%3D%20%60rgba(255%2C%24%7B205%2BMath.floor(shimmer*32)%7D%2C%24%7B62%2BMath.floor(shimmer*40)%7D%2C1)%60%3B%0A%20%20%20%20%20%20rctx.font%20%3D%20%60bold%20%24%7Bp.size%7Dpx%20%22Noto%20Sans%20Runic%22%2C%22Segoe%20UI%20Symbol%22%2C%22Times%20New%20Roman%22%2Cserif%60%3B%0A%20%20%20%20%20%20rctx.textAlign%20%3D%20%22center%22%3B%0A%20%20%20%20%20%20rctx.textBaseline%20%3D%20%22middle%22%3B%0A%20%20%20%20%20%20rctx.fillText(p.glyph%2C0%2C0)%3B%0A%20%20%20%20%20%20rctx.restore()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20runeRAF%20%3D%20requestAnimationFrame(drawRunes)%3B%0A%20%20%7D%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20PARTICLE%20ENGINE%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20function%20startAnimation()%7B%0A%20%20%20%20if(animating)%20return%3B%0A%20%20%20%20animating%20%3D%20true%3B%0A%20%20%20%20requestAnimationFrame(tick)%3B%0A%20%20%7D%0A%0A%20%20function%20tick()%7B%0A%20%20%20%20fctx.clearRect(0%2C0%2C392%2C392)%3B%0A%0A%20%20%20%20for(let%20i%3Dparticles.length-1%3Bi%3E%3D0%3Bi--)%7B%0A%20%20%20%20%20%20const%20p%20%3D%20particles%5Bi%5D%3B%0A%0A%20%20%20%20%20%20if(p.type%3D%3D%3D%22skullPixel%22)%7B%0A%20%20%20%20%20%20%20%20p.age%2B%2B%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20Exact%20overlay%3A%20remain%20locked%20to%20the%20centre%20of%20the%20original%0A%20%20%20%20%20%20%20%20%2F%2F%20100%25%20black%2028x28%20source%20pixel.%0A%20%20%20%20%20%20%20%20p.x%20%3D%20p.homeX%3B%0A%20%20%20%20%20%20%20%20p.y%20%3D%20p.homeY%3B%0A%20%20%20%20%20%20%20%20p.life%20%3D%20999999%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20else%20if(p.type%3D%3D%3D%22fireFlow%22)%7B%0A%20%20%20%20%20%20%20%20p.age%2B%2B%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Living%20flame%20motion%3A%20slow%20meander%2C%20flicker%2C%20and%20buoyant%20lift.%0A%20%20%20%20%20%20%20%20p.vx%20%2B%3D%20Math.sin((p.age%2Bp.seed)*.17)*.032%3B%0A%20%20%20%20%20%20%20%20p.vy%20%2B%3D%20Math.cos((p.age%2Bp.seed)*.13)*.026%20-%20.010%3B%0A%0A%20%20%20%20%20%20%20%20p.x%20%2B%3D%20p.vx%3B%0A%20%20%20%20%20%20%20%20p.y%20%2B%3D%20p.vy%3B%0A%0A%20%20%20%20%20%20%20%20p.vx%20*%3D%20.993%3B%0A%20%20%20%20%20%20%20%20p.vy%20*%3D%20.989%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Tiny%20flickering%20instability.%0A%20%20%20%20%20%20%20%20p.y%20%2B%3D%20Math.sin((p.age%2Bp.seed)*.31)*.11%3B%0A%20%20%20%20%20%20%20%20p.x%20%2B%3D%20Math.cos((p.age%2Bp.seed)*.23)*.06%3B%0A%0A%20%20%20%20%20%20%20%20if(p.x%20%3E%20414%20%7C%7C%20p.y%20%3C%20-18%20%7C%7C%20p.y%20%3E%20410)%7B%0A%20%20%20%20%20%20%20%20%20%20p.life%20%3D%20Math.min(p.life%2C8)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20else%20if(p.type%3D%3D%3D%22yellowLightning%22)%7B%0A%20%20%20%20%20%20%20%20p.age%2B%2B%3B%0A%0A%20%20%20%20%20%20%20%20if(p.phase%3D%3D%3D%22float%22)%7B%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20Brownian-style%20magical%20wandering.%0A%20%20%20%20%20%20%20%20%20%20p.vx%20%2B%3D%20Math.sin((p.age%2Bp.wanderSeed)*.13)*.045%20%2B%20(Math.random()-.5)*.035%3B%0A%20%20%20%20%20%20%20%20%20%20p.vy%20%2B%3D%20Math.cos((p.age%2Bp.wanderSeed)*.11)*.045%20%2B%20(Math.random()-.5)*.035%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20Clamp%20speed%20so%20particles%20keep%20floating%20instead%20of%20exploding%20forever.%0A%20%20%20%20%20%20%20%20%20%20const%20sp%20%3D%20Math.hypot(p.vx%2Cp.vy)%3B%0A%20%20%20%20%20%20%20%20%20%20const%20maxSp%20%3D%205.2%3B%0A%20%20%20%20%20%20%20%20%20%20if(sp%20%3E%20maxSp)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.vx%20%3D%20p.vx%2Fsp*maxSp%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.vy%20%3D%20p.vy%2Fsp*maxSp%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20p.x%20%2B%3D%20p.vx%3B%0A%20%20%20%20%20%20%20%20%20%20p.y%20%2B%3D%20p.vy%3B%0A%0A%20%20%20%20%20%20%20%20%20%20const%20pad%20%3D%20p.size*.55%20%2B%202%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20Elastic%20collision%20against%20the%20exact%20392x392%20frame.%0A%20%20%20%20%20%20%20%20%20%20if(p.x%20%3C%20pad)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.x%20%3D%20pad%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.vx%20%3D%20Math.abs(p.vx)%20*%20.94%3B%0A%20%20%20%20%20%20%20%20%20%20%7Delse%20if(p.x%20%3E%20392-pad)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.x%20%3D%20392-pad%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.vx%20%3D%20-Math.abs(p.vx)%20*%20.94%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20if(p.y%20%3C%20pad)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.y%20%3D%20pad%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.vy%20%3D%20Math.abs(p.vy)%20*%20.94%3B%0A%20%20%20%20%20%20%20%20%20%20%7Delse%20if(p.y%20%3E%20392-pad)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.y%20%3D%20392-pad%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20p.vy%20%3D%20-Math.abs(p.vy)%20*%20.94%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20else%20if(p.phase%3D%3D%3D%22return%22)%7B%0A%20%20%20%20%20%20%20%20%20%20p.x%20%2B%3D%20(p.homeX-p.x)*.19%3B%0A%20%20%20%20%20%20%20%20%20%20p.y%20%2B%3D%20(p.homeY-p.y)*.19%3B%0A%20%20%20%20%20%20%20%20%20%20p.vx%20*%3D%20.78%3B%0A%20%20%20%20%20%20%20%20%20%20p.vy%20*%3D%20.78%3B%0A%20%20%20%20%20%20%20%20%20%20p.rot%20*%3D%20.86%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20else%20if(p.reforming)%7B%0A%20%20%20%20%20%20%20%20p.x%20%2B%3D%20(p.homeX-p.x)*.13%3B%0A%20%20%20%20%20%20%20%20p.y%20%2B%3D%20(p.homeY-p.y)*.13%3B%0A%20%20%20%20%20%20%20%20p.vx%20*%3D%20.82%3B%0A%20%20%20%20%20%20%20%20p.vy%20*%3D%20.82%3B%0A%20%20%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20%20%20p.x%20%2B%3D%20p.vx%3B%0A%20%20%20%20%20%20%20%20p.y%20%2B%3D%20p.vy%3B%0A%20%20%20%20%20%20%20%20p.vx%20*%3D%20.985%3B%0A%20%20%20%20%20%20%20%20p.vy%20*%3D%20.985%3B%0A%20%20%20%20%20%20%20%20if(p.type!%3D%3D%22reform%22)%20p.vy%20%2B%3D%20.025%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20p.rot%20%2B%3D%20p.vr%3B%0A%20%20%20%20%20%20p.life--%3B%0A%0A%20%20%20%20%20%20let%20alpha%3B%0A%20%20%20%20%20%20if(p.type%3D%3D%3D%22skullPixel%22)%7B%0A%20%20%20%20%20%20%20%20if(skullFadeStart%3E0)%7B%0A%20%20%20%20%20%20%20%20%20%20const%20fadeAge%3Dperformance.now()-skullFadeStart%3B%0A%20%20%20%20%20%20%20%20%20%20alpha%3D.95*Math.max(0%2C1-fadeAge%2F850)%3B%0A%20%20%20%20%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20%20%20%20%20alpha%3D.95%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20else%20if(p.type%3D%3D%3D%22fireFlow%22)%7B%0A%20%20%20%20%20%20%20%20alpha%20%3D%20Math.max(0%2CMath.min(.90%2Cp.life%2F30))%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20else%20if(p.type%3D%3D%3D%22yellowLightning%22)%7B%0A%20%20%20%20%20%20%20%20alpha%20%3D%20p.phase%3D%3D%3D%22return%22%0A%20%20%20%20%20%20%20%20%20%20%3F%20Math.max(0%2CMath.min(1%2Cp.life%2F34))%0A%20%20%20%20%20%20%20%20%20%20%3A%201%3B%0A%20%20%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20%20%20alpha%20%3D%20Math.max(0%2CMath.min(1%2Cp.life%20%2F%20Math.min(28%2Cp.maxLife)))%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20fctx.save()%3B%0A%20%20%20%20%20%20fctx.translate(Math.round(p.x)%2CMath.round(p.y))%3B%0A%20%20%20%20%20%20fctx.rotate(p.rot)%3B%0A%20%20%20%20%20%20fctx.globalAlpha%20%3D%20alpha%3B%0A%20%20%20%20%20%20fctx.font%20%3D%20%60%24%7BMath.round(p.size)%7Dpx%20%22Apple%20Color%20Emoji%22%2C%22Segoe%20UI%20Emoji%22%2C%22Noto%20Color%20Emoji%22%2Csans-serif%60%3B%0A%20%20%20%20%20%20fctx.textAlign%20%3D%20%22center%22%3B%0A%20%20%20%20%20%20fctx.textBaseline%20%3D%20%22middle%22%3B%0A%0A%20%20%20%20%20%20if(p.type%3D%3D%3D%22yellowLightning%22)%7B%0A%20%20%20%20%20%20%20%20fctx.shadowColor%20%3D%20%22rgba(255%2C210%2C40%2C.95)%22%3B%0A%20%20%20%20%20%20%20%20fctx.shadowBlur%20%3D%209%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20if(p.type%3D%3D%3D%22fireFlow%22)%7B%0A%20%20%20%20%20%20%20%20fctx.shadowColor%20%3D%20%22rgba(255%2C115%2C20%2C.70)%22%3B%0A%20%20%20%20%20%20%20%20fctx.shadowBlur%20%3D%207%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20if(p.type%3D%3D%3D%22skullPixel%22)%7B%0A%20%20%20%20%20%20%20%20fctx.shadowColor%20%3D%20%22rgba(255%2C255%2C255%2C.25)%22%3B%0A%20%20%20%20%20%20%20%20fctx.shadowBlur%20%3D%203%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20fctx.fillText(p.glyph%2C0%2C0)%3B%0A%20%20%20%20%20%20fctx.restore()%3B%0A%0A%20%20%20%20%20%20if(p.life%3C%3D0)%20particles.splice(i%2C1)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(particles.length)%7B%0A%20%20%20%20%20%20requestAnimationFrame(tick)%3B%0A%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20fctx.clearRect(0%2C0%2C392%2C392)%3B%0A%20%20%20%20%20%20animating%3Dfalse%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20GESTURE%20RESOLUTION%0A%20%20%2F%2F%20Robust%20mouse%20%2B%20touch%2Fpointer%20handling.%0A%20%20%2F%2F%20Single%20tap%20waits%20briefly%20so%20a%20second%2Fthird%20tap%20can%20override%20it.%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20let%20tapCount%20%3D%200%3B%0A%20%20let%20tapTimer%20%3D%20null%3B%0A%20%20let%20pressTimer%20%3D%20null%3B%0A%20%20let%20longPressed%20%3D%20false%3B%0A%20%20let%20pointerDown%20%3D%20false%3B%0A%20%20let%20downX%20%3D%200%2C%20downY%20%3D%200%3B%0A%20%20let%20lastUpX%20%3D%20196%2C%20lastUpY%20%3D%20196%3B%0A%0A%20%20function%20localPos(e)%7B%0A%20%20%20%20const%20r%20%3D%20stage.getBoundingClientRect()%3B%0A%20%20%20%20return%20%7B%0A%20%20%20%20%20%20x%3A(e.clientX-r.left)*(392%2Fr.width)%2C%0A%20%20%20%20%20%20y%3A(e.clientY-r.top)*(392%2Fr.height)%0A%20%20%20%20%7D%3B%0A%20%20%7D%0A%0A%20%20function%20clearTapSequence()%7B%0A%20%20%20%20tapCount%20%3D%200%3B%0A%20%20%20%20clearTimeout(tapTimer)%3B%0A%20%20%20%20tapTimer%20%3D%20null%3B%0A%20%20%7D%0A%0A%20%20function%20resolveTapSequence()%7B%0A%20%20%20%20const%20count%20%3D%20tapCount%3B%0A%20%20%20%20clearTapSequence()%3B%0A%0A%20%20%20%20if(count%20%3D%3D%3D%201)%7B%0A%20%20%20%20%20%20castRandomSpell(lastUpX%2ClastUpY)%3B%0A%20%20%20%20%7D%20else%20if(count%20%3D%3D%3D%202)%7B%0A%20%20%20%20%20%20lightningExplosion()%3B%0A%20%20%20%20%7D%20else%20if(count%20%3E%3D%203)%7B%0A%20%20%20%20%20%20fireSpell()%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20stage.addEventListener(%22pointerdown%22%2C%20e%3D%3E%7B%0A%20%20%20%20e.preventDefault()%3B%0A%0A%20%20%20%20%2F%2F%20Only%20primary%20mouse%2Ftouch%2Fpen%20interaction.%0A%20%20%20%20if(e.isPrimary%20%3D%3D%3D%20false)%20return%3B%0A%0A%20%20%20%20pointerDown%20%3D%20true%3B%0A%20%20%20%20longPressed%20%3D%20false%3B%0A%0A%20%20%20%20const%20p%20%3D%20localPos(e)%3B%0A%20%20%20%20downX%20%3D%20p.x%3B%0A%20%20%20%20downY%20%3D%20p.y%3B%0A%0A%20%20%20%20try%20%7B%20stage.setPointerCapture(e.pointerId)%3B%20%7D%20catch(_)%20%7B%7D%0A%0A%20%20%20%20clearTimeout(pressTimer)%3B%0A%20%20%20%20pressTimer%20%3D%20setTimeout(()%3D%3E%7B%0A%20%20%20%20%20%20if(pointerDown)%7B%0A%20%20%20%20%20%20%20%20longPressed%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20clearTapSequence()%3B%0A%20%20%20%20%20%20%20%20invisibilitySpell()%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%2C700)%3B%0A%20%20%7D%2C%20%7Bpassive%3Afalse%7D)%3B%0A%0A%20%20stage.addEventListener(%22pointermove%22%2C%20e%3D%3E%7B%0A%20%20%20%20if(!pointerDown)%20return%3B%0A%20%20%20%20const%20p%20%3D%20localPos(e)%3B%0A%0A%20%20%20%20%2F%2F%20Moving%20cancels%20long-press%2C%20but%20still%20permits%20ordinary%20click%2Ftap.%0A%20%20%20%20if(Math.hypot(p.x-downX%2Cp.y-downY)%20%3E%2018)%7B%0A%20%20%20%20%20%20clearTimeout(pressTimer)%3B%0A%20%20%20%20%7D%0A%20%20%7D%2C%20%7Bpassive%3Afalse%7D)%3B%0A%0A%20%20stage.addEventListener(%22pointerup%22%2C%20e%3D%3E%7B%0A%20%20%20%20e.preventDefault()%3B%0A%20%20%20%20if(e.isPrimary%20%3D%3D%3D%20false)%20return%3B%0A%0A%20%20%20%20pointerDown%20%3D%20false%3B%0A%20%20%20%20clearTimeout(pressTimer)%3B%0A%0A%20%20%20%20try%20%7B%20stage.releasePointerCapture(e.pointerId)%3B%20%7D%20catch(_)%20%7B%7D%0A%0A%20%20%20%20if(longPressed)%7B%0A%20%20%20%20%20%20longPressed%20%3D%20false%3B%0A%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20p%20%3D%20localPos(e)%3B%0A%20%20%20%20lastUpX%20%3D%20p.x%3B%0A%20%20%20%20lastUpY%20%3D%20p.y%3B%0A%0A%20%20%20%20%2F%2F%20Count%20taps%20occurring%20in%20one%20compact%20gesture%20window.%0A%20%20%20%20tapCount%2B%2B%3B%0A%20%20%20%20clearTimeout(tapTimer)%3B%0A%20%20%20%20tapTimer%20%3D%20setTimeout(resolveTapSequence%2C%20330)%3B%0A%20%20%7D%2C%20%7Bpassive%3Afalse%7D)%3B%0A%0A%20%20stage.addEventListener(%22pointercancel%22%2C%20()%3D%3E%7B%0A%20%20%20%20pointerDown%20%3D%20false%3B%0A%20%20%20%20clearTimeout(pressTimer)%3B%0A%20%20%7D)%3B%0A%0A%20%20%2F%2F%20Desktop%20fallback%3A%20browser-native%20double%20click%20directly%20fires%20explosion.%0A%20%20%2F%2F%20The%20click%20sequence%20is%20cleared%20first%20so%20it%20cannot%20also%20trigger%20a%20single%20spell.%0A%20%20stage.addEventListener(%22dblclick%22%2C%20e%3D%3E%7B%0A%20%20%20%20e.preventDefault()%3B%0A%20%20%20%20clearTapSequence()%3B%0A%20%20%20%20lightningExplosion()%3B%0A%20%20%7D)%3B%0A%0A%20%20stage.addEventListener(%22contextmenu%22%2C%20e%3D%3Ee.preventDefault())%3B%0A%0A%0A%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20PERLIN%20NOISE%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20const%20PERM%20%3D%20(()%20%3D%3E%20%7B%0A%20%20%20%20const%20base%20%3D%20%5B151%2C160%2C137%2C91%2C90%2C15%2C131%2C13%2C201%2C95%2C96%2C53%2C194%2C233%2C7%2C225%2C%0A%20%20%20%20%20%20140%2C36%2C103%2C30%2C69%2C142%2C8%2C99%2C37%2C240%2C21%2C10%2C23%2C190%2C6%2C148%2C247%2C120%2C234%2C%0A%20%20%20%20%20%2075%2C0%2C26%2C197%2C62%2C94%2C252%2C219%2C203%2C117%2C35%2C11%2C32%2C57%2C177%2C33%2C88%2C237%2C149%2C%0A%20%20%20%20%20%2056%2C87%2C174%2C20%2C125%2C136%2C171%2C168%2C68%2C175%2C74%2C165%2C71%2C134%2C139%2C48%2C27%2C166%2C%0A%20%20%20%20%20%2077%2C146%2C158%2C231%2C83%2C111%2C229%2C122%2C60%2C211%2C133%2C230%2C220%2C105%2C92%2C41%2C55%2C46%2C%0A%20%20%20%20%20%20245%2C40%2C244%2C102%2C143%2C54%2C65%2C25%2C63%2C161%2C1%2C216%2C80%2C73%2C209%2C76%2C132%2C187%2C208%2C%0A%20%20%20%20%20%2089%2C18%2C169%2C200%2C196%2C135%2C130%2C116%2C188%2C159%2C86%2C164%2C100%2C109%2C198%2C173%2C186%2C%0A%20%20%20%20%20%203%2C64%2C52%2C217%2C226%2C250%2C124%2C123%2C5%2C202%2C38%2C147%2C118%2C126%2C255%2C82%2C85%2C212%2C207%2C%0A%20%20%20%20%20%20206%2C59%2C227%2C47%2C16%2C58%2C17%2C182%2C189%2C28%2C42%2C223%2C183%2C170%2C213%2C119%2C248%2C152%2C%0A%20%20%20%20%20%202%2C44%2C154%2C163%2C70%2C221%2C153%2C101%2C155%2C167%2C43%2C172%2C9%2C129%2C22%2C39%2C253%2C19%2C98%2C%0A%20%20%20%20%20%20108%2C110%2C79%2C113%2C224%2C232%2C178%2C185%2C112%2C104%2C218%2C246%2C97%2C228%2C251%2C34%2C242%2C%0A%20%20%20%20%20%20193%2C238%2C210%2C144%2C12%2C191%2C179%2C162%2C241%2C81%2C51%2C145%2C235%2C249%2C14%2C239%2C107%2C%0A%20%20%20%20%20%2049%2C192%2C214%2C31%2C181%2C199%2C106%2C157%2C184%2C84%2C204%2C176%2C115%2C121%2C50%2C45%2C127%2C%0A%20%20%20%20%20%204%2C150%2C254%2C138%2C236%2C205%2C93%2C222%2C114%2C67%2C29%2C24%2C72%2C243%2C141%2C128%2C195%2C78%2C%0A%20%20%20%20%20%2066%2C215%2C61%2C156%2C180%5D%3B%0A%20%20%20%20return%20base.concat(base)%3B%0A%20%20%7D)()%3B%0A%0A%20%20function%20fadeNoise(t)%7B%20return%20t*t*t*(t*(t*6-15)%2B10)%3B%20%7D%0A%20%20function%20lerpNoise(a%2Cb%2Ct)%7B%20return%20a%2Bt*(b-a)%3B%20%7D%0A%20%20function%20gradNoise(hash%2Cx%2Cy%2Cz)%7B%0A%20%20%20%20const%20h%3Dhash%2615%3B%0A%20%20%20%20const%20u%3Dh%3C8%3Fx%3Ay%3B%0A%20%20%20%20const%20v%3Dh%3C4%3Fy%3A(h%3D%3D%3D12%7C%7Ch%3D%3D%3D14%3Fx%3Az)%3B%0A%20%20%20%20return%20((h%261)%3F-u%3Au)%2B((h%262)%3F-v%3Av)%3B%0A%20%20%7D%0A%20%20function%20perlin3(x%2Cy%2Cz)%7B%0A%20%20%20%20const%20X%3DMath.floor(x)%26255%2C%20Y%3DMath.floor(y)%26255%2C%20Z%3DMath.floor(z)%26255%3B%0A%20%20%20%20x-%3DMath.floor(x)%3B%20y-%3DMath.floor(y)%3B%20z-%3DMath.floor(z)%3B%0A%20%20%20%20const%20u%3DfadeNoise(x)%2C%20v%3DfadeNoise(y)%2C%20w%3DfadeNoise(z)%3B%0A%20%20%20%20const%20A%3DPERM%5BX%5D%2BY%2C%20AA%3DPERM%5BA%5D%2BZ%2C%20AB%3DPERM%5BA%2B1%5D%2BZ%3B%0A%20%20%20%20const%20B%3DPERM%5BX%2B1%5D%2BY%2C%20BA%3DPERM%5BB%5D%2BZ%2C%20BB%3DPERM%5BB%2B1%5D%2BZ%3B%0A%0A%20%20%20%20return%20lerpNoise(%0A%20%20%20%20%20%20lerpNoise(%0A%20%20%20%20%20%20%20%20lerpNoise(gradNoise(PERM%5BAA%5D%2Cx%2Cy%2Cz)%2CgradNoise(PERM%5BBA%5D%2Cx-1%2Cy%2Cz)%2Cu)%2C%0A%20%20%20%20%20%20%20%20lerpNoise(gradNoise(PERM%5BAB%5D%2Cx%2Cy-1%2Cz)%2CgradNoise(PERM%5BBB%5D%2Cx-1%2Cy-1%2Cz)%2Cu)%2C%0A%20%20%20%20%20%20%20%20v%0A%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20lerpNoise(%0A%20%20%20%20%20%20%20%20lerpNoise(gradNoise(PERM%5BAA%2B1%5D%2Cx%2Cy%2Cz-1)%2CgradNoise(PERM%5BBA%2B1%5D%2Cx-1%2Cy%2Cz-1)%2Cu)%2C%0A%20%20%20%20%20%20%20%20lerpNoise(gradNoise(PERM%5BAB%2B1%5D%2Cx%2Cy-1%2Cz-1)%2CgradNoise(PERM%5BBB%2B1%5D%2Cx-1%2Cy-1%2Cz-1)%2Cu)%2C%0A%20%20%20%20%20%20%20%20v%0A%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20w%0A%20%20%20%20)%3B%0A%20%20%7D%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20%E2%AD%90%20SACRED%20GEOMETRY%20%E2%80%94%20MAX%20CHAOS%2C%20YELLOW%20PIXELS%20ONLY%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20function%20starGeometrySpell()%7B%0A%20%20%20%20starGeomActive%20%3D%20!starGeomActive%3B%0A%0A%20%20%20%20if(!starGeomActive)%7B%0A%20%20%20%20%20%20stopSpellAudio(starSpellAudio)%3B%0A%20%20%20%20%20%20if(starGeomRAF)%7B%0A%20%20%20%20%20%20%20%20cancelAnimationFrame(starGeomRAF)%3B%0A%20%20%20%20%20%20%20%20starGeomRAF%20%3D%20null%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20starGeomParticles%20%3D%20%5B%5D%3B%0A%20%20%20%20%20%20fctx.clearRect(0%2C0%2C392%2C392)%3B%0A%20%20%20%20%20%20restoreWizard()%3B%0A%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20playSpellAudio(starSpellAudio%2C.72%2C%22star%22)%3B%0A%20%20%20%20drawWizardWithoutYellow()%3B%0A%0A%20%20%20%20starGeomParticles%20%3D%20yellowSpellPixels.map((px%2Ci)%3D%3E%7B%0A%20%20%20%20%20%20const%20count%20%3D%20Math.max(1%2CyellowSpellPixels.length)%3B%0A%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20homeX%3Apx.x%2C%0A%20%20%20%20%20%20%20%20homeY%3Apx.y%2C%0A%20%20%20%20%20%20%20%20baseAngle%3A(i%2Fcount)*Math.PI*2%2C%0A%20%20%20%20%20%20%20%20phase%3AMath.random()*Math.PI*2%2C%0A%20%20%20%20%20%20%20%20seed%3AMath.random()*1000%20%2B%20i*.217%2C%0A%20%20%20%20%20%20%20%20size%3A8%20%2B%20(i%255)*1.7%2C%0A%20%20%20%20%20%20%20%20ring%3Ai%255%2C%0A%20%20%20%20%20%20%20%20polarity%3Ai%252%3D%3D%3D0%20%3F%201%20%3A%20-1%2C%0A%20%20%20%20%20%20%20%20fold%3A5%20%2B%20(i%257)%2C%20%2F%2F%205%E2%80%9311%20fold%20symmetry%0A%20%20%20%20%20%20%20%20arm%3A(i%2513)%2C%0A%20%20%20%20%20%20%20%20jitter%3AMath.random()%0A%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%7D)%3B%0A%0A%20%20%20%20const%20startTime%20%3D%20performance.now()%3B%0A%0A%20%20%20%20function%20drawStarGeometry(now)%7B%0A%20%20%20%20%20%20if(!starGeomActive)%7B%0A%20%20%20%20%20%20%20%20starGeomRAF%3Dnull%3B%0A%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20fctx.clearRect(0%2C0%2C392%2C392)%3B%0A%0A%20%20%20%20%20%20const%20t%3D(now-startTime)*.001%3B%0A%20%20%20%20%20%20const%20cx%3D196%2C%20cy%3D196%3B%0A%0A%20%20%20%20%20%20%2F%2F%20Macro%20phases%3A%20every%20few%20seconds%20the%20symmetry%20morphs.%0A%20%20%20%20%20%20const%20phaseIndex%3DMath.floor(t%2F2.6)%3B%0A%20%20%20%20%20%20const%20phaseMix%3D(t%252.6)%2F2.6%3B%0A%20%20%20%20%20%20const%20foldA%3D5%20%2B%20(phaseIndex%255)%3B%20%20%20%20%20%20%20%2F%2F%205..9%0A%20%20%20%20%20%20const%20foldB%3D7%20%2B%20((phaseIndex%2B2)%255)%3B%20%20%20%2F%2F%207..11%0A%20%20%20%20%20%20const%20foldMorph%3DMath.round(foldA*(1-phaseMix)%2BfoldB*phaseMix)%3B%0A%0A%20%20%20%20%20%20%2F%2F%20Radial%20pulse%20%2F%20breathing%0A%20%20%20%20%20%20const%20pulse%3D1%20%2B%20Math.sin(t*2.1)*.12%20%2B%20Math.sin(t*.47)*.08%3B%0A%0A%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20%2F%2F%20SACRED%20GEOMETRY%20GUIDE%20STRUCTURES%0A%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20fctx.save()%3B%0A%20%20%20%20%20%20fctx.globalCompositeOperation%3D%22lighter%22%3B%0A%0A%20%20%20%20%20%20%2F%2F%20rotating%20outer%20polygon%0A%20%20%20%20%20%20fctx.globalAlpha%3D.13%3B%0A%20%20%20%20%20%20fctx.strokeStyle%3D%22rgba(255%2C215%2C80%2C.9)%22%3B%0A%20%20%20%20%20%20fctx.lineWidth%3D1%3B%0A%20%20%20%20%20%20const%20outerR%3D(126%2BMath.sin(t*.9)*18)*pulse%3B%0A%20%20%20%20%20%20fctx.beginPath()%3B%0A%20%20%20%20%20%20for(let%20k%3D0%3Bk%3C%3DfoldMorph%3Bk%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20a%3D-Math.PI%2F2%2B(k%2FfoldMorph)*Math.PI*2%2Bt*.16%3B%0A%20%20%20%20%20%20%20%20const%20x%3Dcx%2BMath.cos(a)*outerR%3B%0A%20%20%20%20%20%20%20%20const%20y%3Dcy%2BMath.sin(a)*outerR%3B%0A%20%20%20%20%20%20%20%20if(k%3D%3D%3D0)%20fctx.moveTo(x%2Cy)%3B%20else%20fctx.lineTo(x%2Cy)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20fctx.stroke()%3B%0A%0A%20%20%20%20%20%20%2F%2F%20inner%20counter-rotating%20star%20polygon%0A%20%20%20%20%20%20fctx.globalAlpha%3D.10%3B%0A%20%20%20%20%20%20const%20starN%3D8%3B%0A%20%20%20%20%20%20const%20r1%3D82%2BMath.sin(t*1.3)*12%3B%0A%20%20%20%20%20%20const%20r2%3D34%2BMath.cos(t*.7)*9%3B%0A%20%20%20%20%20%20fctx.beginPath()%3B%0A%20%20%20%20%20%20for(let%20k%3D0%3Bk%3C%3DstarN*2%3Bk%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20rr%3D(k%252%3D%3D%3D0)%3Fr1%3Ar2%3B%0A%20%20%20%20%20%20%20%20const%20a%3D-Math.PI%2F2%2B(k%2F(starN*2))*Math.PI*2-t*.27%3B%0A%20%20%20%20%20%20%20%20const%20x%3Dcx%2BMath.cos(a)*rr%3B%0A%20%20%20%20%20%20%20%20const%20y%3Dcy%2BMath.sin(a)*rr%3B%0A%20%20%20%20%20%20%20%20if(k%3D%3D%3D0)%20fctx.moveTo(x%2Cy)%3B%20else%20fctx.lineTo(x%2Cy)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20fctx.stroke()%3B%0A%0A%20%20%20%20%20%20%2F%2F%20flower-of-life-ish%20circles%0A%20%20%20%20%20%20fctx.globalAlpha%3D.055%3B%0A%20%20%20%20%20%20for(let%20k%3D0%3Bk%3C6%3Bk%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20a%3Dt*.11%2Bk*Math.PI%2F3%3B%0A%20%20%20%20%20%20%20%20const%20ox%3DMath.cos(a)*42%3B%0A%20%20%20%20%20%20%20%20const%20oy%3DMath.sin(a)*42%3B%0A%20%20%20%20%20%20%20%20fctx.beginPath()%3B%0A%20%20%20%20%20%20%20%20fctx.arc(cx%2Box%2Ccy%2Boy%2C42%2BMath.sin(t%2Bk)*5%2C0%2CMath.PI*2)%3B%0A%20%20%20%20%20%20%20%20fctx.stroke()%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%2F%2F%20radial%20spokes%0A%20%20%20%20%20%20fctx.globalAlpha%3D.07%3B%0A%20%20%20%20%20%20for(let%20k%3D0%3Bk%3CfoldMorph%3Bk%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20a%3Dt*.09%2Bk*Math.PI*2%2FfoldMorph%3B%0A%20%20%20%20%20%20%20%20fctx.beginPath()%3B%0A%20%20%20%20%20%20%20%20fctx.moveTo(cx%2Ccy)%3B%0A%20%20%20%20%20%20%20%20fctx.lineTo(cx%2BMath.cos(a)*160%2Ccy%2BMath.sin(a)*160)%3B%0A%20%20%20%20%20%20%20%20fctx.stroke()%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20fctx.restore()%3B%0A%0A%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20%2F%2F%20PARTICLE%20GEOMETRY%0A%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20for(let%20i%3D0%3Bi%3CstarGeomParticles.length%3Bi%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20p%3DstarGeomParticles%5Bi%5D%3B%0A%0A%20%20%20%20%20%20%20%20const%20n1%3Dperlin3(p.seed%2Bt*.31%2C%20i*.031%2C%20t*.13)%3B%0A%20%20%20%20%20%20%20%20const%20n2%3Dperlin3(i*.027%2C%20p.seed%2Bt*.19%2C%20t*.09)%3B%0A%20%20%20%20%20%20%20%20const%20n3%3Dperlin3(t*.11%2C%20i*.043%2C%20p.seed%2Bt*.23)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Per-particle%20symmetry%20mutates%20over%20time%0A%20%20%20%20%20%20%20%20const%20fold%20%3D%20p.fold%20%2B%20((phaseIndex%2Bp.arm)%253)%3B%0A%20%20%20%20%20%20%20%20const%20snap%3D(Math.PI*2)%2Ffold%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Base%20spiral%20motion%0A%20%20%20%20%20%20%20%20let%20a%3Dp.baseAngle%0A%20%20%20%20%20%20%20%20%20%20%2B%20t*(.42%2B.035*p.ring)*p.polarity%0A%20%20%20%20%20%20%20%20%20%20%2B%20n1*.34%0A%20%20%20%20%20%20%20%20%20%20%2B%20Math.sin(t*.8%2Bp.phase)*.15%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20periodic%20hard%20symmetry%20lock%20%2F%20%22mandala%20snap%22%0A%20%20%20%20%20%20%20%20const%20snapWindow%3D(Math.sin(t*1.45)%2B1)%2F2%3B%0A%20%20%20%20%20%20%20%20const%20snapStrength%3DMath.pow(Math.max(0%2CsnapWindow-.72)%2F.28%2C2)%3B%0A%0A%20%20%20%20%20%20%20%20const%20snapped%3DMath.round(a%2Fsnap)*snap%3B%0A%20%20%20%20%20%20%20%20a%3Da*(1-snapStrength)%2Bsnapped*snapStrength%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Golden-ratio-inspired%20layered%20radii%0A%20%20%20%20%20%20%20%20const%20phi%3D1.61803398875%3B%0A%20%20%20%20%20%20%20%20const%20baseR%3D28%20%2B%20(p.ring%2B1)*19*phi%3B%0A%20%20%20%20%20%20%20%20const%20spiralGrowth%3D((t*18%20%2B%20i*3.7)%20%25%20145)%3B%0A%20%20%20%20%20%20%20%20let%20r%3D(baseR%20%2B%20spiralGrowth*.45)*pulse%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Noise%20folds%20the%20radius%20into%20breathing%20geometric%20lobes%0A%20%20%20%20%20%20%20%20r%20%2B%3D%20n2*34%3B%0A%20%20%20%20%20%20%20%20r%20%2B%3D%20Math.sin(a*fold%20%2B%20t*1.2)*18%3B%0A%20%20%20%20%20%20%20%20r%20%2B%3D%20Math.cos(a*(foldMorph%2F2)%20-%20t*.8)*10%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20occasional%20violent%20expansion%20pulses%0A%20%20%20%20%20%20%20%20const%20blast%3DMath.max(0%2CMath.sin(t*2.8-1.2))%3B%0A%20%20%20%20%20%20%20%20r%20%2B%3D%20blast*blast*(20%20%2B%20(i%257)*3)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20alternating%20mirror%20petals%0A%20%20%20%20%20%20%20%20const%20mirror%20%3D%20(i%252%3D%3D%3D0%20%3F%201%20%3A%20-1)%3B%0A%20%20%20%20%20%20%20%20const%20petalWarp%3DMath.sin(a*3%20%2B%20t*mirror)*12%3B%0A%0A%20%20%20%20%20%20%20%20const%20twist%3DMath.log(1%2Br*.03)*(.32%2B.07*p.ring)%3B%0A%20%20%20%20%20%20%20%20const%20x%3Dcx%20%2B%20Math.cos(a%2Btwist)*r%20%2B%20n3*14%20%2B%20Math.cos(a*2)*petalWarp*.25%3B%0A%20%20%20%20%20%20%20%20const%20y%3Dcy%20%2B%20Math.sin(a%2Btwist)*r%20%2B%20n1*14%20%2B%20Math.sin(a*2)*petalWarp*.25%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20occasional%20duplicate%20ghost%20star%20for%20more%20visual%20density%0A%20%20%20%20%20%20%20%20const%20ghost%3DMath.sin(t*3.2%2Bp.phase)%3E.72%3B%0A%0A%20%20%20%20%20%20%20%20fctx.save()%3B%0A%20%20%20%20%20%20%20%20fctx.translate(Math.round(x)%2CMath.round(y))%3B%0A%20%20%20%20%20%20%20%20fctx.rotate(a%2Bt*.35*p.polarity%2Bn2*.4)%3B%0A%0A%20%20%20%20%20%20%20%20const%20flicker%3D.60%20%2B%20.30*((Math.sin(t*5%2Bp.phase)%2B1)%2F2)%3B%0A%20%20%20%20%20%20%20%20fctx.globalAlpha%3D.62%20%2B%20flicker*.18%3B%0A%20%20%20%20%20%20%20%20fctx.shadowColor%3D%22rgba(255%2C205%2C45%2C.82)%22%3B%0A%20%20%20%20%20%20%20%20fctx.shadowBlur%3D6%20%2B%20Math.abs(n1)*6%3B%0A%0A%20%20%20%20%20%20%20%20fctx.font%3D%60%24%7BMath.round(p.size*(.9%2BMath.abs(n3)*.35))%7Dpx%20%22Apple%20Color%20Emoji%22%2C%22Segoe%20UI%20Emoji%22%2C%22Noto%20Color%20Emoji%22%2Csans-serif%60%3B%0A%20%20%20%20%20%20%20%20fctx.textAlign%3D%22center%22%3B%0A%20%20%20%20%20%20%20%20fctx.textBaseline%3D%22middle%22%3B%0A%20%20%20%20%20%20%20%20fctx.fillText(%22%E2%AD%90%22%2C0%2C0)%3B%0A%0A%20%20%20%20%20%20%20%20if(ghost)%7B%0A%20%20%20%20%20%20%20%20%20%20fctx.globalAlpha%3D.20%3B%0A%20%20%20%20%20%20%20%20%20%20fctx.rotate(Math.PI%2Ffold)%3B%0A%20%20%20%20%20%20%20%20%20%20fctx.scale(.72%2C.72)%3B%0A%20%20%20%20%20%20%20%20%20%20fctx.fillText(%22%E2%9C%A6%22%2C0%2C0)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20fctx.restore()%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20%2F%2F%20CENTRAL%20BURST%20%2F%20SIGIL%0A%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20const%20corePulse%3D(Math.sin(t*3.6)%2B1)%2F2%3B%0A%20%20%20%20%20%20fctx.save()%3B%0A%20%20%20%20%20%20fctx.translate(cx%2Ccy)%3B%0A%20%20%20%20%20%20fctx.globalCompositeOperation%3D%22lighter%22%3B%0A%20%20%20%20%20%20fctx.globalAlpha%3D.10%20%2B%20corePulse*.10%3B%0A%20%20%20%20%20%20fctx.strokeStyle%3D%22rgba(255%2C225%2C105%2C.95)%22%3B%0A%20%20%20%20%20%20fctx.lineWidth%3D1%3B%0A%0A%20%20%20%20%20%20const%20coreFold%3D6%20%2B%20(phaseIndex%254)%3B%0A%20%20%20%20%20%20const%20coreR%3D26%20%2B%20corePulse*16%3B%0A%20%20%20%20%20%20fctx.beginPath()%3B%0A%20%20%20%20%20%20for(let%20k%3D0%3Bk%3C%3DcoreFold*2%3Bk%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20rr%3D(k%252%3D%3D%3D0)%3FcoreR%3AcoreR*.38%3B%0A%20%20%20%20%20%20%20%20const%20a%3Dt*.42%2Bk*Math.PI%2FcoreFold%3B%0A%20%20%20%20%20%20%20%20const%20x%3DMath.cos(a)*rr%3B%0A%20%20%20%20%20%20%20%20const%20y%3DMath.sin(a)*rr%3B%0A%20%20%20%20%20%20%20%20if(k%3D%3D%3D0)%20fctx.moveTo(x%2Cy)%3B%20else%20fctx.lineTo(x%2Cy)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20fctx.stroke()%3B%0A%20%20%20%20%20%20fctx.restore()%3B%0A%0A%20%20%20%20%20%20starGeomRAF%3DrequestAnimationFrame(drawStarGeometry)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20starGeomRAF%3DrequestAnimationFrame(drawStarGeometry)%3B%0A%20%20%7D%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20%E2%9C%A8%203D%20PIXEL%20COSMOS%0A%20%20%2F%2F%20Entire%20image%20becomes%20navigable%20floating%203D%20pixel%20galaxy.%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20function%20buildCosmosParticles()%7B%0A%20%20%20%20cosmosParticles%3D%5B%5D%3B%0A%20%20%20%20const%20data%3DsourceCtx.getImageData(0%2C0%2C28%2C28).data%3B%0A%0A%20%20%20%20for(let%20y%3D0%3By%3C28%3By%2B%2B)%7B%0A%20%20%20%20%20%20for(let%20x%3D0%3Bx%3C28%3Bx%2B%2B)%7B%0A%20%20%20%20%20%20%20%20const%20i%3D(y*28%2Bx)*4%3B%0A%20%20%20%20%20%20%20%20const%20r%3Ddata%5Bi%5D%2Cg%3Ddata%5Bi%2B1%5D%2Cb%3Ddata%5Bi%2B2%5D%2Ca%3Ddata%5Bi%2B3%5D%3B%0A%20%20%20%20%20%20%20%20if(a%3C25)%20continue%3B%0A%0A%20%20%20%20%20%20%20%20const%20nx%3D(x-13.5)*10.5%3B%0A%20%20%20%20%20%20%20%20const%20ny%3D(y-13.5)*10.5%3B%0A%0A%20%20%20%20%20%20%20%20const%20ang%3DMath.atan2(ny%2Cnx)%3B%0A%20%20%20%20%20%20%20%20const%20rad%3DMath.hypot(nx%2Cny)%3B%0A%20%20%20%20%20%20%20%20const%20noise%3Dperlin3(x*.17%2Cy*.17%2C(x%2By)*.05)%3B%0A%0A%20%20%20%20%20%20%20%20cosmosParticles.push(%7B%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20Begin%20at%20the%20exact%20flat%20source%20position.%20The%20%E2%9C%A8%20spell%20then%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20gently%20opens%20this%20into%203D%20rather%20than%20instantly%20exploding.%0A%20%20%20%20%20%20%20%20%20%20x%3Anx%2C%0A%20%20%20%20%20%20%20%20%20%20y%3Any%2C%0A%20%20%20%20%20%20%20%20%20%20z%3A0%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20exact%20flat%20source%20target%20for%20reformation%0A%20%20%20%20%20%20%20%20%20%20ox%3Anx%2C%0A%20%20%20%20%20%20%20%20%20%20oy%3Any%2C%0A%20%20%20%20%20%20%20%20%20%20oz%3A0%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20softly%20separated%203D%20destination%20used%20during%20spell%20opening%0A%20%20%20%20%20%20%20%20%20%20ex%3Anx%20%2B%20Math.cos(ang)*rad*.35%20%2B%20noise*42%2C%0A%20%20%20%20%20%20%20%20%20%20ey%3Any%20%2B%20Math.sin(ang)*rad*.35%20%2B%20noise*42%2C%0A%20%20%20%20%20%20%20%20%20%20ez%3A(Math.random()-.5)*250%20%2B%20noise*95%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20autonomous%20space-dust%20dynamics%0A%20%20%20%20%20%20%20%20%20%20vx%3A(Math.random()-.5)*.045%2C%0A%20%20%20%20%20%20%20%20%20%20vy%3A(Math.random()-.5)*.045%2C%0A%20%20%20%20%20%20%20%20%20%20vz%3A(Math.random()-.5)*.045%2C%0A%20%20%20%20%20%20%20%20%20%20charge%3AMath.random()%3C.5%20%3F%20-1%20%3A%201%2C%0A%20%20%20%20%20%20%20%20%20%20mass%3A.65%2BMath.random()*1.4%2C%0A%0A%20%20%20%20%20%20%20%20%20%20r%2Cg%2Cb%2Ca%3Aa%2F255%2C%0A%20%20%20%20%20%20%20%20%20%20size%3A5.3%20%2B%20Math.random()*2.4%2C%0A%20%20%20%20%20%20%20%20%20%20phase%3AMath.random()*Math.PI*2%2C%0A%20%20%20%20%20%20%20%20%20%20drift%3A.25%2BMath.random()*.65%2C%0A%20%20%20%20%20%20%20%20%20%20seed%3AMath.random()*1000%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20cosmosSpell()%7B%0A%20%20%20%20if(!cosmosActive)%7B%0A%20%20%20%20%20%20cosmosActive%3Dtrue%3B%0A%20%20%20%20%20%20cosmosReforming%3Dfalse%3B%0A%20%20%20%20%20%20playSpellAudio(cosmosSpellAudio%2C.60%2C%22cosmos%22)%3B%0A%20%20%20%20%20%20cosmosExpandStart%3Dperformance.now()%3B%0A%0A%20%20%20%20%20%20wizard.style.visibility%3D%22hidden%22%3B%0A%20%20%20%20%20%20runes.style.display%3D%22none%22%3B%0A%20%20%20%20%20%20fx.style.display%3D%22none%22%3B%0A%20%20%20%20%20%20cosmos.style.display%3D%22block%22%3B%0A%0A%20%20%20%20%20%20buildCosmosParticles()%3B%0A%20%20%20%20%20%20cosmosRotX%3D-.20%3B%0A%20%20%20%20%20%20cosmosRotY%3D.35%3B%0A%20%20%20%20%20%20cosmosZoom%3D1%3B%0A%20%20%20%20%20%20cosmosPanX%3D0%3B%0A%20%20%20%20%20%20cosmosPanY%3D0%3B%0A%0A%20%20%20%20%20%20if(!cosmosRAF)%20cosmosRAF%3DrequestAnimationFrame(drawCosmos)%3B%0A%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20%2F%2F%20Do%20NOT%20instantly%20hide%20the%203D%20field.%0A%20%20%20%20%20%20%2F%2F%20First%20enter%20a%20liquid-metal%20reformation%20phase.%0A%20%20%20%20%20%20stopSpellAudio(cosmosSpellAudio)%3B%0A%20%20%20%20%20%20cosmosReforming%3Dtrue%3B%0A%20%20%20%20%20%20cosmosReformStart%3Dperformance.now()%3B%0A%20%20%20%20%20%20cosmosDragging%3Dfalse%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20drawCosmos(now)%7B%0A%20%20%20%20if(!cosmosActive)%7B%0A%20%20%20%20%20%20cosmosRAF%3Dnull%3B%0A%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20cctx.fillStyle%3D%22%23000%22%3B%0A%20%20%20%20cctx.fillRect(0%2C0%2C392%2C392)%3B%0A%0A%20%20%20%20const%20t%3Dnow*.001%3B%0A%0A%20%20%20%20%2F%2F%20Soft%20%E2%9C%A8%20opening%3A%20ease%20from%20the%20original%20flat%20wizard%20into%20the%0A%20%20%20%20%2F%2F%20navigable%203D%20dust%20field%20over%20~2.4%20seconds.%0A%20%20%20%20const%20expandRaw%20%3D%20cosmosReforming%0A%20%20%20%20%20%20%3F%201%0A%20%20%20%20%20%20%3A%20Math.max(0%2CMath.min(1%2C(now-cosmosExpandStart)%2FCOSMOS_EXPAND_MS))%3B%0A%20%20%20%20const%20expandEase%20%3D%201-Math.pow(1-expandRaw%2C3)%3B%0A%0A%20%20%20%20const%20cx%3D196%2BcosmosPanX%3B%0A%20%20%20%20const%20cy%3D196%2BcosmosPanY%3B%0A%20%20%20%20const%20focal%3D360*cosmosZoom%3B%0A%0A%20%20%20%20%2F%2F%20During%20liquid-metal%20return%2C%20gently%20relax%20camera%20orientation%20too.%0A%20%20%20%20if(cosmosReforming)%7B%0A%20%20%20%20%20%20cosmosRotX%20%2B%3D%20(0-cosmosRotX)*.035%3B%0A%20%20%20%20%20%20cosmosRotY%20%2B%3D%20(0-cosmosRotY)*.035%3B%0A%20%20%20%20%20%20cosmosZoom%20%2B%3D%20(1-cosmosZoom)*.035%3B%0A%20%20%20%20%20%20cosmosPanX%20*%3D%20.94%3B%0A%20%20%20%20%20%20cosmosPanY%20*%3D%20.94%3B%0A%20%20%20%20%7Delse%20if(!cosmosDragging)%7B%0A%20%20%20%20%20%20%2F%2F%20Camera%20motion%20also%20fades%20in%20softly%20with%20the%20particle%20expansion.%0A%20%20%20%20%20%20cosmosRotY%20%2B%3D%20.00045*expandEase%3B%0A%20%20%20%20%20%20cosmosRotX%20%2B%3D%20Math.sin(t*.17)*.00010*expandEase%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20cosY%3DMath.cos(cosmosRotY)%2C%20sinY%3DMath.sin(cosmosRotY)%3B%0A%20%20%20%20const%20cosX%3DMath.cos(cosmosRotX)%2C%20sinX%3DMath.sin(cosmosRotX)%3B%0A%0A%20%20%20%20const%20projected%3D%5B%5D%3B%0A%0A%20%20%20%20for(let%20i%3D0%3Bi%3CcosmosParticles.length%3Bi%2B%2B)%7B%0A%20%20%20%20%20%20const%20p%3DcosmosParticles%5Bi%5D%3B%0A%0A%20%20%20%20%20%20if(!cosmosReforming)%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20%20%20%2F%2F%20SOFT%20OPENING%20%E2%86%92%20CHARGED%20SPACE-DUST%20MOTION%0A%20%20%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20%20%20%2F%2F%20For%20the%20first%20~2.4s%2C%20particles%20gently%20peel%20away%20from%20their%0A%20%20%20%20%20%20%20%20%2F%2F%20exact%20source%20pixels%20toward%20their%203D%20destinations.%0A%20%20%20%20%20%20%20%20if(expandRaw%20%3C%201)%7B%0A%20%20%20%20%20%20%20%20%20%20const%20targetX%3Dp.ox%2B(p.ex-p.ox)*expandEase%3B%0A%20%20%20%20%20%20%20%20%20%20const%20targetY%3Dp.oy%2B(p.ey-p.oy)*expandEase%3B%0A%20%20%20%20%20%20%20%20%20%20const%20targetZ%3Dp.oz%2B(p.ez-p.oz)*expandEase%3B%0A%0A%20%20%20%20%20%20%20%20%20%20const%20softness%3D.025%20%2B%20expandEase*.018%3B%0A%20%20%20%20%20%20%20%20%20%20p.vx%20%2B%3D%20(targetX-p.x)*softness%3B%0A%20%20%20%20%20%20%20%20%20%20p.vy%20%2B%3D%20(targetY-p.y)*softness%3B%0A%20%20%20%20%20%20%20%20%20%20p.vz%20%2B%3D%20(targetZ-p.z)*softness%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20Very%20small%20organic%20drift%20appears%20gradually.%0A%20%20%20%20%20%20%20%20%20%20const%20n1%3Dperlin3(p.seed%2Bt*.045%2Cp.y*.004%2Cp.z*.004)%3B%0A%20%20%20%20%20%20%20%20%20%20const%20n2%3Dperlin3(p.seed%2B17.3%2Ct*.042%2Bp.z*.004%2Cp.x*.004)%3B%0A%20%20%20%20%20%20%20%20%20%20const%20n3%3Dperlin3(p.x*.004%2Cp.seed%2Bt*.040%2Cp.y*.004)%3B%0A%20%20%20%20%20%20%20%20%20%20const%20noiseStrength%3D.002%20%2B%20expandEase*.006%3B%0A%0A%20%20%20%20%20%20%20%20%20%20p.vx%20%2B%3D%20n1*noiseStrength%3B%0A%20%20%20%20%20%20%20%20%20%20p.vy%20%2B%3D%20n2*noiseStrength%3B%0A%20%20%20%20%20%20%20%20%20%20p.vz%20%2B%3D%20n3*noiseStrength%3B%0A%0A%20%20%20%20%20%20%20%20%20%20p.vx%20*%3D%20.84%3B%0A%20%20%20%20%20%20%20%20%20%20p.vy%20*%3D%20.84%3B%0A%20%20%20%20%20%20%20%20%20%20p.vz%20*%3D%20.84%3B%0A%0A%20%20%20%20%20%20%20%20%20%20p.x%20%2B%3D%20p.vx%3B%0A%20%20%20%20%20%20%20%20%20%20p.y%20%2B%3D%20p.vy%3B%0A%20%20%20%20%20%20%20%20%20%20p.z%20%2B%3D%20p.vz%3B%0A%20%20%20%20%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20%20%20%2F%2F%20CHARGED%20SPACE-DUST%20MOTION%0A%20%20%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20%20%20%2F%2F%20Low-frequency%20Perlin%20field%20behaves%20like%20a%20changing%0A%20%20%20%20%20%20%20%20%2F%2F%20electromagnetic%2Fturbulent%20vector%20field.%0A%20%20%20%20%20%20%20%20const%20n1%3Dperlin3(p.seed%20%2B%20t*.055%2C%20p.y*.004%2C%20p.z*.004)%3B%0A%20%20%20%20%20%20%20%20const%20n2%3Dperlin3(p.seed%20%2B%2017.3%2C%20t*.050%20%2B%20p.z*.004%2C%20p.x*.004)%3B%0A%20%20%20%20%20%20%20%20const%20n3%3Dperlin3(p.x*.004%2C%20p.seed%20%2B%20t*.047%2C%20p.y*.004)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Central%20weak%20orbital%20field.%0A%20%20%20%20%20%20%20%20const%20rad%3DMath.hypot(p.x%2Cp.y%2Cp.z)%20%7C%7C%201%3B%0A%20%20%20%20%20%20%20%20const%20inv%3D1%2Frad%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Tangential%20Lorentz-like%20swirl%20around%20centre.%0A%20%20%20%20%20%20%20%20const%20tx%3D-p.y*inv%3B%0A%20%20%20%20%20%20%20%20const%20ty%3D%20p.x*inv%3B%0A%0A%20%20%20%20%20%20%20%20const%20field%3D.0125%2Fp.mass%3B%0A%0A%20%20%20%20%20%20%20%20p.vx%20%2B%3D%20(n1*.020%20%2B%20tx*field*p.charge)%3B%0A%20%20%20%20%20%20%20%20p.vy%20%2B%3D%20(n2*.020%20%2B%20ty*field*p.charge)%3B%0A%20%20%20%20%20%20%20%20p.vz%20%2B%3D%20(n3*.020%20%2B%20Math.sin(t*.31%2Bp.phase)*.004)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Tiny%20mutual%20%22charged%20dust%22%20repulsion%2Fattraction%20against%0A%20%20%20%20%20%20%20%20%2F%2F%20a%20rotating%20virtual%20field%20rather%20than%20O(n%C2%B2)%20particle%20forces.%0A%20%20%20%20%20%20%20%20const%20fx%3DMath.sin(t*.23%2Bp.phase)*p.charge*.0035%3B%0A%20%20%20%20%20%20%20%20const%20fy%3DMath.cos(t*.19%2Bp.phase)*p.charge*.0035%3B%0A%20%20%20%20%20%20%20%20p.vx%20%2B%3D%20fx%3B%0A%20%20%20%20%20%20%20%20p.vy%20%2B%3D%20fy%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20damping%20%3D%20suspended%20dust%20rather%20than%20ballistic%20debris%0A%20%20%20%20%20%20%20%20p.vx%20*%3D%20.992%3B%0A%20%20%20%20%20%20%20%20p.vy%20*%3D%20.992%3B%0A%20%20%20%20%20%20%20%20p.vz%20*%3D%20.992%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20cap%20speed%0A%20%20%20%20%20%20%20%20const%20sp%3DMath.hypot(p.vx%2Cp.vy%2Cp.vz)%3B%0A%20%20%20%20%20%20%20%20const%20maxSp%3D1.45%3B%0A%20%20%20%20%20%20%20%20if(sp%3EmaxSp)%7B%0A%20%20%20%20%20%20%20%20%20%20p.vx%3Dp.vx%2Fsp*maxSp%3B%0A%20%20%20%20%20%20%20%20%20%20p.vy%3Dp.vy%2Fsp*maxSp%3B%0A%20%20%20%20%20%20%20%20%20%20p.vz%3Dp.vz%2Fsp*maxSp%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20p.x%20%2B%3D%20p.vx%3B%0A%20%20%20%20%20%20%20%20p.y%20%2B%3D%20p.vy%3B%0A%20%20%20%20%20%20%20%20p.z%20%2B%3D%20p.vz%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20soft%20spherical%20containment%2C%20like%20dust%20trapped%20in%20a%20field%0A%20%20%20%20%20%20%20%20const%20d%3DMath.hypot(p.x%2Cp.y%2Cp.z)%3B%0A%20%20%20%20%20%20%20%20const%20limit%3D245%3B%0A%20%20%20%20%20%20%20%20if(d%3Elimit)%7B%0A%20%20%20%20%20%20%20%20%20%20const%20nx%3Dp.x%2Fd%2C%20ny%3Dp.y%2Fd%2C%20nz%3Dp.z%2Fd%3B%0A%20%20%20%20%20%20%20%20%20%20const%20excess%3Dd-limit%3B%0A%20%20%20%20%20%20%20%20%20%20p.vx%20-%3D%20nx*excess*.0025%3B%0A%20%20%20%20%20%20%20%20%20%20p.vy%20-%3D%20ny*excess*.0025%3B%0A%20%20%20%20%20%20%20%20%20%20p.vz%20-%3D%20nz*excess*.0025%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20%20%20%2F%2F%20T-1000%20%2F%20LIQUID-METAL%20REFORMATION%0A%20%20%20%20%20%20%20%20%2F%2F%20--------------------------------------------------------%0A%20%20%20%20%20%20%20%20const%20elapsed%3Dnow-cosmosReformStart%3B%0A%20%20%20%20%20%20%20%20const%20reformT%3DMath.min(1%2Celapsed%2F2600)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20pull%20strength%20ramps%20up%20smoothly%0A%20%20%20%20%20%20%20%20const%20pull%3D.018%20%2B%20reformT*.12%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20damp%20old%20velocity%20while%20gravitating%20toward%20original%20pixel%0A%20%20%20%20%20%20%20%20p.vx%20%2B%3D%20(p.ox-p.x)*pull%3B%0A%20%20%20%20%20%20%20%20p.vy%20%2B%3D%20(p.oy-p.y)*pull%3B%0A%20%20%20%20%20%20%20%20p.vz%20%2B%3D%20(p.oz-p.z)*pull%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20viscous%20drag%0A%20%20%20%20%20%20%20%20const%20viscosity%3D.78%20-%20reformT*.18%3B%0A%20%20%20%20%20%20%20%20p.vx%20*%3D%20viscosity%3B%0A%20%20%20%20%20%20%20%20p.vy%20*%3D%20viscosity%3B%0A%20%20%20%20%20%20%20%20p.vz%20*%3D%20viscosity%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20liquid-metal%20wobble%20that%20fades%20out%20near%20completion%0A%20%20%20%20%20%20%20%20const%20wobble%3D(1-reformT)*Math.sin(t*5%2Bp.phase)*.18%3B%0A%20%20%20%20%20%20%20%20p.vx%20%2B%3D%20Math.cos(p.phase)*wobble%3B%0A%20%20%20%20%20%20%20%20p.vy%20%2B%3D%20Math.sin(p.phase)*wobble%3B%0A%0A%20%20%20%20%20%20%20%20p.x%20%2B%3D%20p.vx%3B%0A%20%20%20%20%20%20%20%20p.y%20%2B%3D%20p.vy%3B%0A%20%20%20%20%20%20%20%20p.z%20%2B%3D%20p.vz%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20final%20magnetic%20snap%20toward%20exact%20source%20coordinates%0A%20%20%20%20%20%20%20%20if(reformT%3E.82)%7B%0A%20%20%20%20%20%20%20%20%20%20const%20snap%3D(reformT-.82)%2F.18%3B%0A%20%20%20%20%20%20%20%20%20%20p.x%20%2B%3D%20(p.ox-p.x)*(.12%2B.38*snap)%3B%0A%20%20%20%20%20%20%20%20%20%20p.y%20%2B%3D%20(p.oy-p.y)*(.12%2B.38*snap)%3B%0A%20%20%20%20%20%20%20%20%20%20p.z%20%2B%3D%20(p.oz-p.z)*(.12%2B.38*snap)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20let%20x%3Dp.x%2C%20y%3Dp.y%2C%20z%3Dp.z%3B%0A%0A%20%20%20%20%20%20%2F%2F%20rotate%20Y%0A%20%20%20%20%20%20let%20x1%3Dx*cosY-z*sinY%3B%0A%20%20%20%20%20%20let%20z1%3Dx*sinY%2Bz*cosY%3B%0A%0A%20%20%20%20%20%20%2F%2F%20rotate%20X%0A%20%20%20%20%20%20let%20y1%3Dy*cosX-z1*sinX%3B%0A%20%20%20%20%20%20let%20z2%3Dy*sinX%2Bz1*cosX%3B%0A%0A%20%20%20%20%20%20const%20depth%3Dz2%2B430%3B%0A%20%20%20%20%20%20if(depth%3C40)%20continue%3B%0A%0A%20%20%20%20%20%20const%20s%3Dfocal%2Fdepth%3B%0A%0A%20%20%20%20%20%20projected.push(%7B%0A%20%20%20%20%20%20%20%20x%3Acx%2Bx1*s%2C%0A%20%20%20%20%20%20%20%20y%3Acy%2By1*s%2C%0A%20%20%20%20%20%20%20%20z%3Az2%2C%0A%20%20%20%20%20%20%20%20scale%3As%2C%0A%20%20%20%20%20%20%20%20p%0A%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20projected.sort((a%2Cb)%3D%3Ea.z-b.z)%3B%0A%0A%20%20%20%20for(const%20q%20of%20projected)%7B%0A%20%20%20%20%20%20const%20p%3Dq.p%3B%0A%20%20%20%20%20%20let%20sz%3DMath.max(1.5%2Cp.size*q.scale*1.35)%3B%0A%0A%20%20%20%20%20%20if(cosmosReforming)%7B%0A%20%20%20%20%20%20%20%20const%20reformT%3DMath.min(1%2C(now-cosmosReformStart)%2F2600)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20become%20slightly%20more%20solid%2Fpixel-like%20as%20form%20returns%0A%20%20%20%20%20%20%20%20sz%20*%3D%20.88%20%2B%20reformT*.28%3B%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20cctx.globalAlpha%3DMath.max(.25%2CMath.min(1%2Cp.a*(.65%2Bq.scale*.35)))%3B%0A%20%20%20%20%20%20cctx.fillStyle%3D%60rgb(%24%7Bp.r%7D%2C%24%7Bp.g%7D%2C%24%7Bp.b%7D)%60%3B%0A%20%20%20%20%20%20cctx.fillRect(%0A%20%20%20%20%20%20%20%20Math.round(q.x-sz%2F2)%2C%0A%20%20%20%20%20%20%20%20Math.round(q.y-sz%2F2)%2C%0A%20%20%20%20%20%20%20%20Math.ceil(sz)%2C%0A%20%20%20%20%20%20%20%20Math.ceil(sz)%0A%20%20%20%20%20%20)%3B%0A%0A%20%20%20%20%20%20if(q.scale%3E1.1%20%26%26%20!cosmosReforming)%7B%0A%20%20%20%20%20%20%20%20cctx.globalAlpha%3D.10%3B%0A%20%20%20%20%20%20%20%20cctx.fillStyle%3D%22%23fff%22%3B%0A%20%20%20%20%20%20%20%20cctx.fillRect(Math.round(q.x)%2CMath.round(q.y)%2C1%2C1)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20cctx.globalAlpha%3D1%3B%0A%0A%20%20%20%20if(cosmosReforming)%7B%0A%20%20%20%20%20%20const%20elapsed%3Dnow-cosmosReformStart%3B%0A%0A%20%20%20%20%20%20if(elapsed%3E%3D2800)%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20fully%20restored%3A%20return%20to%20normal%202D%20wizard%0A%20%20%20%20%20%20%20%20cosmosReforming%3Dfalse%3B%0A%20%20%20%20%20%20%20%20cosmosActive%3Dfalse%3B%0A%20%20%20%20%20%20%20%20cosmos.style.display%3D%22none%22%3B%0A%20%20%20%20%20%20%20%20runes.style.display%3D%22block%22%3B%0A%20%20%20%20%20%20%20%20fx.style.display%3D%22block%22%3B%0A%20%20%20%20%20%20%20%20restoreWizard()%3B%0A%20%20%20%20%20%20%20%20cosmosRAF%3Dnull%3B%0A%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20cosmosRAF%3DrequestAnimationFrame(drawCosmos)%3B%0A%20%20%7D%0A%0A%20%20function%20cosmosPointerDown(e)%7B%0A%20%20%20%20if(!cosmosActive%20%7C%7C%20cosmosReforming)%20return%3B%0A%20%20%20%20cosmosDragging%3Dtrue%3B%0A%20%20%20%20cosmosLastX%3De.clientX%3B%0A%20%20%20%20cosmosLastY%3De.clientY%3B%0A%20%20%20%20try%7Bcosmos.setPointerCapture(e.pointerId)%3B%7Dcatch(_)%7B%7D%0A%20%20%7D%0A%0A%20%20function%20cosmosPointerMove(e)%7B%0A%20%20%20%20if(!cosmosActive%20%7C%7C%20cosmosReforming%20%7C%7C%20!cosmosDragging)%20return%3B%0A%20%20%20%20const%20dx%3De.clientX-cosmosLastX%3B%0A%20%20%20%20const%20dy%3De.clientY-cosmosLastY%3B%0A%20%20%20%20cosmosLastX%3De.clientX%3B%0A%20%20%20%20cosmosLastY%3De.clientY%3B%0A%0A%20%20%20%20cosmosRotY%20%2B%3D%20dx*.009%3B%0A%20%20%20%20cosmosRotX%20%2B%3D%20dy*.009%3B%0A%20%20%20%20cosmosRotX%3DMath.max(-1.45%2CMath.min(1.45%2CcosmosRotX))%3B%0A%20%20%7D%0A%0A%20%20function%20cosmosPointerUp(e)%7B%0A%20%20%20%20cosmosDragging%3Dfalse%3B%0A%20%20%20%20try%7Bcosmos.releasePointerCapture(e.pointerId)%3B%7Dcatch(_)%7B%7D%0A%20%20%7D%0A%0A%20%20cosmos.addEventListener(%22pointerdown%22%2CcosmosPointerDown)%3B%0A%20%20cosmos.addEventListener(%22pointermove%22%2CcosmosPointerMove)%3B%0A%20%20cosmos.addEventListener(%22pointerup%22%2CcosmosPointerUp)%3B%0A%20%20cosmos.addEventListener(%22pointercancel%22%2C()%3D%3EcosmosDragging%3Dfalse)%3B%0A%0A%20%20cosmos.addEventListener(%22wheel%22%2Ce%3D%3E%7B%0A%20%20%20%20if(!cosmosActive%20%7C%7C%20cosmosReforming)%20return%3B%0A%20%20%20%20e.preventDefault()%3B%0A%20%20%20%20cosmosZoom%20*%3D%20Math.exp(-e.deltaY*.0012)%3B%0A%20%20%20%20cosmosZoom%3DMath.max(.38%2CMath.min(3.6%2CcosmosZoom))%3B%0A%20%20%7D%2C%7Bpassive%3Afalse%7D)%3B%0A%0A%20%20%2F%2F%20Touch%20pinch%20zoom.%0A%20%20const%20activeTouches%3Dnew%20Map()%3B%0A%0A%20%20cosmos.addEventListener(%22pointerdown%22%2Ce%3D%3E%7B%0A%20%20%20%20if(e.pointerType%3D%3D%3D%22touch%22)%7B%0A%20%20%20%20%20%20activeTouches.set(e.pointerId%2C%7Bx%3Ae.clientX%2Cy%3Ae.clientY%7D)%3B%0A%20%20%20%20%20%20if(activeTouches.size%3D%3D%3D2)%7B%0A%20%20%20%20%20%20%20%20const%20pts%3D%5B...activeTouches.values()%5D%3B%0A%20%20%20%20%20%20%20%20cosmosPinchDistance%3DMath.hypot(pts%5B0%5D.x-pts%5B1%5D.x%2Cpts%5B0%5D.y-pts%5B1%5D.y)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D)%3B%0A%0A%20%20cosmos.addEventListener(%22pointermove%22%2Ce%3D%3E%7B%0A%20%20%20%20if(e.pointerType!%3D%3D%22touch%22%20%7C%7C%20!activeTouches.has(e.pointerId))%20return%3B%0A%20%20%20%20activeTouches.set(e.pointerId%2C%7Bx%3Ae.clientX%2Cy%3Ae.clientY%7D)%3B%0A%0A%20%20%20%20if(activeTouches.size%3D%3D%3D2)%7B%0A%20%20%20%20%20%20const%20pts%3D%5B...activeTouches.values()%5D%3B%0A%20%20%20%20%20%20const%20d%3DMath.hypot(pts%5B0%5D.x-pts%5B1%5D.x%2Cpts%5B0%5D.y-pts%5B1%5D.y)%3B%0A%20%20%20%20%20%20if(cosmosPinchDistance%3E0)%7B%0A%20%20%20%20%20%20%20%20cosmosZoom%20*%3D%20d%2FcosmosPinchDistance%3B%0A%20%20%20%20%20%20%20%20cosmosZoom%3DMath.max(.38%2CMath.min(3.6%2CcosmosZoom))%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20cosmosPinchDistance%3Dd%3B%0A%20%20%20%20%7D%0A%20%20%7D)%3B%0A%0A%20%20function%20endCosmosTouch(e)%7B%0A%20%20%20%20activeTouches.delete(e.pointerId)%3B%0A%20%20%20%20if(activeTouches.size%3C2)%20cosmosPinchDistance%3D0%3B%0A%20%20%7D%0A%20%20cosmos.addEventListener(%22pointerup%22%2CendCosmosTouch)%3B%0A%20%20cosmos.addEventListener(%22pointercancel%22%2CendCosmosTouch)%3B%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20SKULL%20SPELL%20%E2%80%94%20black%20pixels%20become%20%F0%9F%92%80%20emojis%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20let%20skullActive%20%3D%20false%3B%0A%20%20let%20skullFadeStart%20%3D%200%3B%0A%20%20let%20skullAutoTimer%20%3D%20null%3B%0A%0A%20%20function%20skullSpell()%7B%0A%20%20%20%20%2F%2F%20Restart%20the%20spell%20cleanly%20if%20recast%20before%20it%20finishes.%0A%20%20%20%20if(skullAutoTimer)%7B%0A%20%20%20%20%20%20clearTimeout(skullAutoTimer)%3B%0A%20%20%20%20%20%20skullAutoTimer%3Dnull%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20particles%20%3D%20particles.filter(p%20%3D%3E%20p.type%20!%3D%3D%20%22skullPixel%22)%3B%0A%0A%20%20%20%20skullActive%20%3D%20true%3B%0A%20%20%20%20skullFadeStart%20%3D%200%3B%0A%0A%20%20%20%20playSpellAudio(skullSpellAudio%2C.82%2C%22skull%22)%3B%0A%0A%20%20%20%20%2F%2F%20Keep%20complete%20wizard%20intact%3B%20skulls%20overlay%20ONLY%20exact%20%23000%20pixels.%0A%20%20%20%20drawWizard()%3B%0A%0A%20%20%20%20for(const%20px%20of%20blackSpellPixels)%7B%0A%20%20%20%20%20%20particles.push(%7B%0A%20%20%20%20%20%20%20%20x%3Apx.x%2C%0A%20%20%20%20%20%20%20%20y%3Apx.y%2C%0A%20%20%20%20%20%20%20%20homeX%3Apx.x%2C%0A%20%20%20%20%20%20%20%20homeY%3Apx.y%2C%0A%20%20%20%20%20%20%20%20vx%3A0%2C%0A%20%20%20%20%20%20%20%20vy%3A0%2C%0A%20%20%20%20%20%20%20%20life%3A999999%2C%0A%20%20%20%20%20%20%20%20maxLife%3A999999%2C%0A%20%20%20%20%20%20%20%20size%3A12%2C%0A%20%20%20%20%20%20%20%20rot%3A0%2C%0A%20%20%20%20%20%20%20%20vr%3A0%2C%0A%20%20%20%20%20%20%20%20glyph%3A%22%F0%9F%92%80%22%2C%0A%20%20%20%20%20%20%20%20type%3A%22skullPixel%22%2C%0A%20%20%20%20%20%20%20%20age%3A0%2C%0A%20%20%20%20%20%20%20%20seed%3AMath.random()*1000%0A%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20startAnimation()%3B%0A%0A%20%20%20%20%2F%2F%20Hold%20at%20full%20strength%2C%20then%20begin%20a%20soft%20fade%20so%20total%20spell%0A%20%20%20%20%2F%2F%20duration%20is%20~4%20seconds.%0A%20%20%20%20skullAutoTimer%3DsetTimeout(()%3D%3E%7B%0A%20%20%20%20%20%20skullFadeStart%3Dperformance.now()%3B%0A%0A%20%20%20%20%20%20setTimeout(()%3D%3E%7B%0A%20%20%20%20%20%20%20%20skullActive%3Dfalse%3B%0A%20%20%20%20%20%20%20%20skullFadeStart%3D0%3B%0A%20%20%20%20%20%20%20%20particles%20%3D%20particles.filter(p%20%3D%3E%20p.type%20!%3D%3D%20%22skullPixel%22)%3B%0A%20%20%20%20%20%20%20%20stopSpellAudio(skullSpellAudio)%3B%0A%20%20%20%20%20%20%20%20restoreWizard()%3B%0A%20%20%20%20%20%20%20%20skullAutoTimer%3Dnull%3B%0A%20%20%20%20%20%20%7D%2C850)%3B%0A%20%20%20%20%7D%2C3150)%3B%0A%20%20%7D%0A%0A%0A%20%20function%20unlockSpellAudio()%7B%0A%20%20%20%20const%20ctx%3DgetSpellAudioCtx()%3B%0A%20%20%20%20if(ctx%20%26%26%20ctx.state%3D%3D%3D%22suspended%22)%20ctx.resume().catch(()%3D%3E%7B%7D)%3B%0A%20%20%7D%0A%20%20stage.addEventListener(%22pointerdown%22%2CunlockSpellAudio%2C%7Bpassive%3Atrue%7D)%3B%0A%20%20spellbar.addEventListener(%22pointerdown%22%2CunlockSpellAudio%2C%7Bpassive%3Atrue%7D)%3B%0A%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20%2F%2F%20SPELL%20BAR%0A%20%20%2F%2F%20------------------------------------------------------------%0A%20%20spellbar.addEventListener(%22pointerdown%22%2C%20e%3D%3E%7B%0A%20%20%20%20e.stopPropagation()%3B%0A%20%20%7D)%3B%0A%0A%20%20spellbar.addEventListener(%22pointerup%22%2C%20e%3D%3E%7B%0A%20%20%20%20e.stopPropagation()%3B%0A%20%20%7D)%3B%0A%0A%20%20spellbar.addEventListener(%22click%22%2C%20e%3D%3E%7B%0A%20%20%20%20e.preventDefault()%3B%0A%20%20%20%20e.stopPropagation()%3B%0A%0A%20%20%20%20const%20btn%20%3D%20e.target.closest(%22button%5Bdata-spell%5D%22)%3B%0A%20%20%20%20if(!btn)%20return%3B%0A%0A%20%20%20%20const%20spell%20%3D%20btn.dataset.spell%3B%0A%0A%20%20%20%20if(spell%20%3D%3D%3D%20%22random%22)%20castRandomSpell(196%2C205)%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%20%22lightning%22)%20lightningExplosion()%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%20%22cloak%22)%20invisibilitySpell()%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%20%22runes%22)%20toggleRunes()%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%20%22fire%22)%20fireSpell()%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%20%22stars%22)%20starGeometrySpell()%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%20%22skull%22)%20skullSpell()%3B%0A%20%20%20%20if(spell%20%3D%3D%3D%20%22cosmos%22)%20cosmosSpell()%3B%0A%20%20%7D)%3B%0A%0A%20%20%2F%2F%20Optional%20test%20keys%20while%20developing%3A%0A%20%20%2F%2F%201%20%3D%20burst%2C%202%20%3D%20glitch%2C%203%20%3D%20strobe%2C%204%20%3D%20lightning%2C%205%20%3D%20fire%2C%206%20%3D%20cloak%0A%20%20addEventListener(%22keydown%22%2C%20e%3D%3E%7B%0A%20%20%20%20if(e.key%3D%3D%3D%221%22)%20arcaneBurst(196%2C186)%3B%0A%20%20%20%20if(e.key%3D%3D%3D%222%22)%20glitchSpell()%3B%0A%20%20%20%20if(e.key%3D%3D%3D%223%22)%20strobeSpell()%3B%0A%20%20%20%20if(e.key%3D%3D%3D%224%22)%20lightningExplosion()%3B%0A%20%20%20%20if(e.key%3D%3D%3D%225%22)%20fireSpell()%3B%0A%20%20%20%20if(e.key%3D%3D%3D%226%22)%20invisibilitySpell()%3B%0A%20%20%20%20if(e.key%3D%3D%3D%227%22)%20toggleRunes()%3B%0A%20%20%20%20if(e.key%3D%3D%3D%228%22)%20starGeometrySpell()%3B%0A%20%20%20%20if(e.key%3D%3D%3D%229%22)%20skullSpell()%3B%0A%20%20%20%20if(e.key%3D%3D%3D%220%22)%20cosmosSpell()%3B%0A%20%20%7D)%3B%0A%7D)()%3B%0A%3C%2Fscript%3E%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A%60%60%60
load full (96,399 bytes) →