<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://blockland.wiki/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AKuranokaFX.js</id>
	<title>MediaWiki:KuranokaFX.js - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://blockland.wiki/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AKuranokaFX.js"/>
	<link rel="alternate" type="text/html" href="https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;action=history"/>
	<updated>2026-10-20T18:12:42Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8879&amp;oldid=prev</id>
		<title>2026年10月16日 (五) 07:06 KK</title>
		<link rel="alternate" type="text/html" href="https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8879&amp;oldid=prev"/>
		<updated>2026-10-16T07:06:16Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;amp;diff=8879&amp;amp;oldid=8876&quot;&gt;显示更改&lt;/a&gt;</summary>
		<author><name>KK</name></author>
	</entry>
	<entry>
		<id>https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8876&amp;oldid=prev</id>
		<title>2026年10月16日 (五) 06:54 KK</title>
		<link rel="alternate" type="text/html" href="https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8876&amp;oldid=prev"/>
		<updated>2026-10-16T06:54:13Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;amp;diff=8876&amp;amp;oldid=8873&quot;&gt;显示更改&lt;/a&gt;</summary>
		<author><name>KK</name></author>
	</entry>
	<entry>
		<id>https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8873&amp;oldid=prev</id>
		<title>2026年10月16日 (五) 06:43 KK</title>
		<link rel="alternate" type="text/html" href="https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8873&amp;oldid=prev"/>
		<updated>2026-10-16T06:43:42Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;amp;diff=8873&amp;amp;oldid=8872&quot;&gt;显示更改&lt;/a&gt;</summary>
		<author><name>KK</name></author>
	</entry>
	<entry>
		<id>https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8872&amp;oldid=prev</id>
		<title>2026年10月16日 (五) 06:15 KK</title>
		<link rel="alternate" type="text/html" href="https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8872&amp;oldid=prev"/>
		<updated>2026-10-16T06:15:57Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;amp;diff=8872&amp;amp;oldid=8869&quot;&gt;显示更改&lt;/a&gt;</summary>
		<author><name>KK</name></author>
	</entry>
	<entry>
		<id>https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8869&amp;oldid=prev</id>
		<title>2026年10月16日 (五) 06:04 KK</title>
		<link rel="alternate" type="text/html" href="https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8869&amp;oldid=prev"/>
		<updated>2026-10-16T06:04:38Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;amp;diff=8869&amp;amp;oldid=8860&quot;&gt;显示更改&lt;/a&gt;</summary>
		<author><name>KK</name></author>
	</entry>
	<entry>
		<id>https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8860&amp;oldid=prev</id>
		<title>2026年10月16日 (五) 05:17 KK</title>
		<link rel="alternate" type="text/html" href="https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8860&amp;oldid=prev"/>
		<updated>2026-10-16T05:17:10Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;amp;diff=8860&amp;amp;oldid=8859&quot;&gt;显示更改&lt;/a&gt;</summary>
		<author><name>KK</name></author>
	</entry>
	<entry>
		<id>https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8859&amp;oldid=prev</id>
		<title>2026年10月16日 (五) 04:59 KK</title>
		<link rel="alternate" type="text/html" href="https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8859&amp;oldid=prev"/>
		<updated>2026-10-16T04:59:55Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;amp;diff=8859&amp;amp;oldid=8855&quot;&gt;显示更改&lt;/a&gt;</summary>
		<author><name>KK</name></author>
	</entry>
	<entry>
		<id>https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8855&amp;oldid=prev</id>
		<title>KK：​创建页面，内容为“/*  * KURANOKA / STORMBREAK v2  * File page: MediaWiki:KuranokaFX.js  * Only operates on the Kuranoka view page. Never rewrites / filters article text.  * Canvas-based cinematic storm / rain / spatial tear / glass rifts / clearing.  */ (function () {   &#039;use strict&#039;;   if (window.__kkStormbreakLoaded) return;   if (window.mw &amp;&amp; (     mw.config.get(&#039;wgPageName&#039;) !== &#039;Kuranoka&#039; ||     mw.config.get(&#039;wgAction&#039;) !== &#039;view&#039; ||     mw.config.get(&#039;wgNamespaceNumber&#039;) !…”</title>
		<link rel="alternate" type="text/html" href="https://blockland.wiki/index.php?title=MediaWiki:KuranokaFX.js&amp;diff=8855&amp;oldid=prev"/>
		<updated>2026-10-16T04:42:24Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“&lt;span class=&quot;autocomment&quot;&gt;* KURANOKA / STORMBREAK v2  * File page: MediaWiki:KuranokaFX.js  * Only operates on the Kuranoka view page. Never rewrites / filters article text.  * Canvas-based cinematic storm / rain / spatial tear / glass rifts / clearing.：​&lt;/span&gt; (function () {   &amp;#039;use strict&amp;#039;;   if (window.__kkStormbreakLoaded) return;   if (window.mw &amp;amp;&amp;amp; (     mw.config.get(&amp;#039;wgPageName&amp;#039;) !== &amp;#039;Kuranoka&amp;#039; ||     mw.config.get(&amp;#039;wgAction&amp;#039;) !== &amp;#039;view&amp;#039; ||     mw.config.get(&amp;#039;wgNamespaceNumber&amp;#039;) !…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/*&lt;br /&gt;
 * KURANOKA / STORMBREAK v2&lt;br /&gt;
 * File page: MediaWiki:KuranokaFX.js&lt;br /&gt;
 * Only operates on the Kuranoka view page. Never rewrites / filters article text.&lt;br /&gt;
 * Canvas-based cinematic storm / rain / spatial tear / glass rifts / clearing.&lt;br /&gt;
 */&lt;br /&gt;
(function () {&lt;br /&gt;
  &amp;#039;use strict&amp;#039;;&lt;br /&gt;
  if (window.__kkStormbreakLoaded) return;&lt;br /&gt;
  if (window.mw &amp;amp;&amp;amp; (&lt;br /&gt;
    mw.config.get(&amp;#039;wgPageName&amp;#039;) !== &amp;#039;Kuranoka&amp;#039; ||&lt;br /&gt;
    mw.config.get(&amp;#039;wgAction&amp;#039;) !== &amp;#039;view&amp;#039; ||&lt;br /&gt;
    mw.config.get(&amp;#039;wgNamespaceNumber&amp;#039;) !== 0&lt;br /&gt;
  )) return;&lt;br /&gt;
&lt;br /&gt;
  function start() {&lt;br /&gt;
    var ids = [&amp;#039;kk-fx-start&amp;#039;,&amp;#039;kk-fx-rift&amp;#039;,&amp;#039;kk-fx-void&amp;#039;,&amp;#039;kk-fx-clear&amp;#039;];&lt;br /&gt;
    var markers = ids.map(function(id) { return document.getElementById(id); });&lt;br /&gt;
    if (markers.some(function(e) { return !e; })) return;&lt;br /&gt;
    window.__kkStormbreakLoaded = true;&lt;br /&gt;
    document.documentElement.classList.add(&amp;#039;kk-stormbreak-enabled&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
    var canvas = document.createElement(&amp;#039;canvas&amp;#039;);&lt;br /&gt;
    canvas.id = &amp;#039;kk-stormbreak-canvas&amp;#039;;&lt;br /&gt;
    canvas.setAttribute(&amp;#039;aria-hidden&amp;#039;,&amp;#039;true&amp;#039;);&lt;br /&gt;
    var veil = document.createElement(&amp;#039;div&amp;#039;);&lt;br /&gt;
    veil.id = &amp;#039;kk-stormbreak-atmosphere&amp;#039;;&lt;br /&gt;
    veil.setAttribute(&amp;#039;aria-hidden&amp;#039;,&amp;#039;true&amp;#039;);&lt;br /&gt;
    // Put FX outside article. Never wrap, filter, scale or re-style article DOM.&lt;br /&gt;
    document.body.appendChild(veil);&lt;br /&gt;
    document.body.appendChild(canvas);&lt;br /&gt;
    var ctx = canvas.getContext(&amp;#039;2d&amp;#039;, { alpha: true });&lt;br /&gt;
    if (!ctx) return;&lt;br /&gt;
&lt;br /&gt;
    var ctrl = document.createElement(&amp;#039;div&amp;#039;);&lt;br /&gt;
    ctrl.id = &amp;#039;kk-stormbreak-controls&amp;#039;;&lt;br /&gt;
    ctrl.innerHTML = &amp;#039;&amp;lt;span aria-hidden=&amp;quot;true&amp;quot;&amp;gt;◈ STORMBREAK&amp;lt;/span&amp;gt;&amp;#039; +&lt;br /&gt;
      &amp;#039;&amp;lt;label for=&amp;quot;kk-stormbreak-power&amp;quot;&amp;gt;强度&amp;lt;/label&amp;gt;&amp;#039; +&lt;br /&gt;
      &amp;#039;&amp;lt;input id=&amp;quot;kk-stormbreak-power&amp;quot; type=&amp;quot;range&amp;quot; min=&amp;quot;25&amp;quot; max=&amp;quot;100&amp;quot; value=&amp;quot;100&amp;quot; step=&amp;quot;5&amp;quot; aria-label=&amp;quot;调整特效强度&amp;quot;&amp;gt;&amp;#039; +&lt;br /&gt;
      &amp;#039;&amp;lt;button type=&amp;quot;button&amp;quot; id=&amp;quot;kk-stormbreak-toggle&amp;quot; aria-pressed=&amp;quot;false&amp;quot;&amp;gt;关闭特效&amp;lt;/button&amp;gt;&amp;#039;;&lt;br /&gt;
    document.body.appendChild(ctrl);&lt;br /&gt;
    var slider = ctrl.querySelector(&amp;#039;input&amp;#039;);&lt;br /&gt;
    var button = ctrl.querySelector(&amp;#039;button&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
    var media = window.matchMedia ? window.matchMedia(&amp;#039;(prefers-reduced-motion: reduce)&amp;#039;) : null;&lt;br /&gt;
    var disabled = !!(media &amp;amp;&amp;amp; media.matches);&lt;br /&gt;
    var power = 1;&lt;br /&gt;
    var dpr = 1, w = 0, h = 0;&lt;br /&gt;
    var lastTime = 0, raf = 0, ticking = false, active = false;&lt;br /&gt;
    var geom = [], drops = [];&lt;br /&gt;
    var pos = [];&lt;br /&gt;
    var probe = { intensity:0, storm:0, rift:0, void:0, clear:0 };&lt;br /&gt;
&lt;br /&gt;
    function clamp(n, a, b) { return Math.max(a, Math.min(b, n)); }&lt;br /&gt;
    function smooth(a,b,x) { if (b&amp;lt;=a) return x&amp;gt;=b ? 1 : 0; var t=clamp((x-a)/(b-a),0,1); return t*t*(3-2*t); }&lt;br /&gt;
    function rng(seed) { return function () { seed |= 0; seed = seed+0x6D2B79F5|0; var t=Math.imul(seed^(seed&amp;gt;&amp;gt;&amp;gt;15),1|seed); t=t+Math.imul(t^(t&amp;gt;&amp;gt;&amp;gt;7),61|t)^t; return ((t^(t&amp;gt;&amp;gt;&amp;gt;14))&amp;gt;&amp;gt;&amp;gt;0)/4294967296; }; }&lt;br /&gt;
    var random = rng(2241984);&lt;br /&gt;
    for (var i=0;i&amp;lt;95;i++) drops.push({x:random(),y:random(),v:.7+random()*1.5,len:12+random()*40,weight:.45+random()*1.7});&lt;br /&gt;
    for (var j=0;j&amp;lt;18;j++) geom.push({x:random(),y:random(),len:random(),phase:random()*6.28});&lt;br /&gt;
&lt;br /&gt;
    function measure() {&lt;br /&gt;
      dpr = Math.min(window.devicePixelRatio||1, window.innerWidth &amp;lt; 700 ? 1.2 : 1.5);&lt;br /&gt;
      w = Math.max(1,window.innerWidth); h=Math.max(1,window.innerHeight);&lt;br /&gt;
      canvas.width=Math.round(w*dpr); canvas.height=Math.round(h*dpr);&lt;br /&gt;
      canvas.style.width=w+&amp;#039;px&amp;#039;; canvas.style.height=h+&amp;#039;px&amp;#039;;&lt;br /&gt;
      ctx.setTransform(dpr,0,0,dpr,0,0);&lt;br /&gt;
      pos = markers.map(function(el) {return el.getBoundingClientRect().top+window.scrollY;});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateScroll() {&lt;br /&gt;
      ticking=false;&lt;br /&gt;
      var center=window.scrollY+h*.55;&lt;br /&gt;
      var s=pos[0], r=pos[1], v=pos[2], c=pos[3];&lt;br /&gt;
      var inChapter=center&amp;gt;=s-h*.35 &amp;amp;&amp;amp; center&amp;lt;c+h*.72;&lt;br /&gt;
      document.documentElement.classList.toggle(&amp;#039;kk-stormbreak-inchapter&amp;#039;,inChapter);&lt;br /&gt;
      if (disabled) { disableVisuals(); return; }&lt;br /&gt;
      var enter=smooth(s-h*.35,s+h*.32,center);&lt;br /&gt;
      var leave=1-smooth(c+h*.05,c+h*.94,center);&lt;br /&gt;
      var intensity=enter*leave*power;&lt;br /&gt;
      probe.intensity=intensity;&lt;br /&gt;
      probe.storm=smooth(s+h*.05, r, center);&lt;br /&gt;
      probe.rift=smooth(r-h*.1, v, center);&lt;br /&gt;
      probe.void=smooth(v-h*.18, v+h*.42, center);&lt;br /&gt;
      probe.clear=smooth(c-h*.45,c+h*.25, center);&lt;br /&gt;
      active=intensity&amp;gt;.008;&lt;br /&gt;
      document.documentElement.classList.toggle(&amp;#039;kk-stormbreak-active&amp;#039;,active);&lt;br /&gt;
      veil.style.setProperty(&amp;#039;--kk-atmosphere&amp;#039;,String(clamp(intensity*(.78+.24*probe.void)*(1-.98*probe.clear),0,1)));&lt;br /&gt;
      if (active &amp;amp;&amp;amp; !raf) raf=window.requestAnimationFrame(tick);&lt;br /&gt;
    }&lt;br /&gt;
    function scrollListener() { if (!ticking) {ticking=true; requestAnimationFrame(updateScroll);} }&lt;br /&gt;
    function disableVisuals() {&lt;br /&gt;
      active=false;&lt;br /&gt;
      document.documentElement.classList.remove(&amp;#039;kk-stormbreak-active&amp;#039;);&lt;br /&gt;
      veil.style.setProperty(&amp;#039;--kk-atmosphere&amp;#039;,&amp;#039;0&amp;#039;);&lt;br /&gt;
      ctx.clearRect(0,0,w,h);&lt;br /&gt;
      button.textContent=&amp;#039;开启特效&amp;#039;;&lt;br /&gt;
      button.setAttribute(&amp;#039;aria-pressed&amp;#039;,&amp;#039;true&amp;#039;);&lt;br /&gt;
    }&lt;br /&gt;
    function setEnabled() {&lt;br /&gt;
      button.textContent=disabled ? &amp;#039;开启特效&amp;#039; : &amp;#039;关闭特效&amp;#039;;&lt;br /&gt;
      button.setAttribute(&amp;#039;aria-pressed&amp;#039;,String(disabled));&lt;br /&gt;
      updateScroll();&lt;br /&gt;
    }&lt;br /&gt;
    button.addEventListener(&amp;#039;click&amp;#039;,function(){ disabled=!disabled; setEnabled(); });&lt;br /&gt;
    slider.addEventListener(&amp;#039;input&amp;#039;,function(){ power=Number(slider.value)/100; updateScroll(); });&lt;br /&gt;
    if (media &amp;amp;&amp;amp; media.addEventListener) media.addEventListener(&amp;#039;change&amp;#039;,function(e){disabled=e.matches; setEnabled();});&lt;br /&gt;
&lt;br /&gt;
    function gradEllipse(x,y,rX,rY,inner,outer,alpha) {&lt;br /&gt;
      ctx.save();ctx.translate(x,y);ctx.scale(1,rY/rX);&lt;br /&gt;
      var g=ctx.createRadialGradient(0,0,0,0,0,rX);&lt;br /&gt;
      g.addColorStop(0,inner);g.addColorStop(1,outer);&lt;br /&gt;
      ctx.globalAlpha=alpha;ctx.fillStyle=g;&lt;br /&gt;
      ctx.beginPath();ctx.arc(0,0,rX,0,Math.PI*2);ctx.fill();ctx.restore();&lt;br /&gt;
    }&lt;br /&gt;
    function linePath(points,color,width,alpha) {&lt;br /&gt;
      ctx.save();ctx.globalAlpha=alpha;ctx.lineWidth=width;ctx.strokeStyle=color;&lt;br /&gt;
      ctx.lineCap=&amp;#039;round&amp;#039;;ctx.lineJoin=&amp;#039;round&amp;#039;;ctx.beginPath();&lt;br /&gt;
      points.forEach(function(p,i){if(i===0)ctx.moveTo(p[0],p[1]);else ctx.lineTo(p[0],p[1]);});&lt;br /&gt;
      ctx.stroke();ctx.restore();&lt;br /&gt;
    }&lt;br /&gt;
    function drawClouds(t, strength) {&lt;br /&gt;
      // Storm walls press inward from all four sides, leaving the article&amp;#039;s central text clear.&lt;br /&gt;
      var n=24;&lt;br /&gt;
      for (var i=0;i&amp;lt;n;i++) {&lt;br /&gt;
        var side=i%4, a=i/n*7.2, xx,yy;&lt;br /&gt;
        var drift=Math.sin(t*.00018+i*3.4)*28;&lt;br /&gt;
        if(side===0){xx=((i*109)%w)+drift;yy=-45+Math.sin(a)*75;}&lt;br /&gt;
        if(side===1){xx=w+55+drift;yy=((i*153)%h);}&lt;br /&gt;
        if(side===2){xx=((i*159)%w)+drift;yy=h+15+Math.sin(a)*90;}&lt;br /&gt;
        if(side===3){xx=-55+drift;yy=((i*149)%h);}&lt;br /&gt;
        var r=160+((i*71)%190);&lt;br /&gt;
        var color=i%3===0?&amp;#039;rgba(78,18,103,.51)&amp;#039;:&amp;#039;rgba(9,38,115,.57)&amp;#039;;&lt;br /&gt;
        gradEllipse(xx,yy,r,r*.46,color,&amp;#039;rgba(4,9,22,0)&amp;#039;,strength*1.15);&lt;br /&gt;
      }&lt;br /&gt;
      gradEllipse(w*.51,h*.52,w*.58,h*.54,&amp;#039;rgba(6,14,40,.23)&amp;#039;,&amp;#039;rgba(6,14,40,0)&amp;#039;,strength*.65);&lt;br /&gt;
    }&lt;br /&gt;
    function drawRain(t, strength) {&lt;br /&gt;
      ctx.save();ctx.beginPath();ctx.rect(0,0,w,h);ctx.clip();&lt;br /&gt;
      var offset=t*.095;&lt;br /&gt;
      for(var i=0;i&amp;lt;drops.length;i++) {&lt;br /&gt;
        var d=drops[i], px=d.x*w, py=((d.y*h+offset*d.v)%(h+100))-50;&lt;br /&gt;
        var edge=Math.abs(px-w/2)/(w/2);&lt;br /&gt;
        var a=(.11+.6*Math.pow(edge,1.6))*strength;&lt;br /&gt;
        ctx.strokeStyle=i%8===0?&amp;#039;rgba(175,110,192,&amp;#039;+a+&amp;#039;)&amp;#039;:&amp;#039;rgba(115,182,238,&amp;#039;+a+&amp;#039;)&amp;#039;;&lt;br /&gt;
        ctx.lineWidth=d.weight;&lt;br /&gt;
        ctx.beginPath();ctx.moveTo(px,py);ctx.lineTo(px-9-d.len*.15,py+d.len);ctx.stroke();&lt;br /&gt;
      }ctx.restore();&lt;br /&gt;
    }&lt;br /&gt;
    function drawSignal(t, strength) {&lt;br /&gt;
      // 180 BPM concept is translated to an ECG-like trace running around the edges,&lt;br /&gt;
      // with NO rapid full-screen flashes and NO article text modifications.&lt;br /&gt;
      var yy=h*.84, seg=17, points=[];&lt;br /&gt;
      var shift=(t*.055)%(w+140);&lt;br /&gt;
      for (var x=-140;x&amp;lt;=w+150;x+=seg) {&lt;br /&gt;
        var u=(x+shift)%185;&lt;br /&gt;
        var peak= u&amp;gt;75&amp;amp;&amp;amp;u&amp;lt;90 ? -50*Math.sin((u-75)/15*Math.PI):0;&lt;br /&gt;
        var y=yy+Math.sin(x*.018+t*.0013)*3+peak;&lt;br /&gt;
        points.push([x,y]);&lt;br /&gt;
      }&lt;br /&gt;
      linePath(points,&amp;#039;#69d6ed&amp;#039;,1.5,strength*.7);&lt;br /&gt;
      linePath(points.map(function(p){return [p[0]+4,p[1]+1];}),&amp;#039;#e65d91&amp;#039;,1.2,strength*.36);&lt;br /&gt;
      // Blunt angular bands, suggesting a mismatched signal.&lt;br /&gt;
      ctx.save();ctx.globalAlpha=strength*.75;&lt;br /&gt;
      ctx.fillStyle=&amp;#039;rgba(218,74,111,.28)&amp;#039;;&lt;br /&gt;
      var k=Math.floor(t/220);&lt;br /&gt;
      for(var i=0;i&amp;lt;7;i++){&lt;br /&gt;
        var seed=(k*19+i*317)&amp;gt;&amp;gt;&amp;gt;0, xx=((seed*73)%1301)/1301*w;&lt;br /&gt;
        var y=((seed*139)%997)/997*h;&lt;br /&gt;
        var rw=35+(seed%100);&lt;br /&gt;
        ctx.fillRect(xx,y,rw,2+seed%5);&lt;br /&gt;
      }ctx.restore();&lt;br /&gt;
    }&lt;br /&gt;
    function drawFracture(t, strength) {&lt;br /&gt;
      // Large static-ish fractures, spanning view edges (never filters text).&lt;br /&gt;
      var centers=[[-w*.08,h*.23],[w*1.06,h*.42],[w*.47,-h*.13],[w*.58,h*1.08]];&lt;br /&gt;
      var now=Math.sin(t*.0006);&lt;br /&gt;
      centers.forEach(function(base,index){&lt;br /&gt;
        var local=rng(24111+index*441);&lt;br /&gt;
        var maxR=Math.min(w,h)*(.60 + .13*index);&lt;br /&gt;
        var points=[];&lt;br /&gt;
        var heading=(index*1.57)+.06;&lt;br /&gt;
        for(var j=0;j&amp;lt;9;j++) {&lt;br /&gt;
          var rad=j/8*maxR;&lt;br /&gt;
          var a=heading+Math.sin(j*.63+index)*.42+(local()-.5)*.2;&lt;br /&gt;
          points.push([base[0]+Math.cos(a)*rad,base[1]+Math.sin(a)*rad]);&lt;br /&gt;
        }&lt;br /&gt;
        linePath(points,&amp;#039;rgba(9,13,37,1)&amp;#039;,8,strength*.75);&lt;br /&gt;
        linePath(points,&amp;#039;#88d8f8&amp;#039;,2.5,strength*(.92+now*.06));&lt;br /&gt;
        linePath(points.map(function(p){return[p[0]+5,p[1]-2];}),&amp;#039;#fe638e&amp;#039;,1.9,strength*.93);&lt;br /&gt;
        for(var k=2;k&amp;lt;8;k+=2) {&lt;br /&gt;
          var c=points[k], b=points[Math.min(k+1,8)], a=Math.atan2(b[1]-c[1],b[0]-c[0])+((k%4)?1:-1)*.8;&lt;br /&gt;
          var len=40+local()*100;&lt;br /&gt;
          linePath([c,[c[0]+Math.cos(a)*len,c[1]+Math.sin(a)*len]],&amp;#039;#a1b6f0&amp;#039;,.8,strength*.55);&lt;br /&gt;
        }&lt;br /&gt;
      });&lt;br /&gt;
      // Screen-tear slices shift translucent atmosphere only (never page DOM).&lt;br /&gt;
      var index=Math.floor(t/360);&lt;br /&gt;
      var tear=rng(index*5923+772);&lt;br /&gt;
      for(var z=0;z&amp;lt;7;z++){&lt;br /&gt;
        var ty=tear()*h, tw=40+tear()*Math.min(w*.45,380), tx=tear()*w;&lt;br /&gt;
        ctx.save();ctx.globalAlpha=strength*(.18+tear()*.28);&lt;br /&gt;
        ctx.fillStyle=z%2?&amp;#039;#ff4b90&amp;#039;:&amp;#039;#34bde3&amp;#039;;&lt;br /&gt;
        ctx.fillRect(tx,ty,tw,4+tear()*18);&lt;br /&gt;
        ctx.restore();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    function drawAbyss(t, strength) {&lt;br /&gt;
      // A ring / distorted horizon instead of replacing or morphing paragraphs.&lt;br /&gt;
      var cx=w*.5,cy=h*.49,base=Math.max(w,h)*.46;&lt;br /&gt;
      gradEllipse(cx,cy,base,base*.74,&amp;#039;rgba(4,4,19,.14)&amp;#039;,&amp;#039;rgba(4,4,19,0)&amp;#039;,strength);&lt;br /&gt;
      var rings=3;&lt;br /&gt;
      for (var ring=0;ring&amp;lt;rings;ring++) {&lt;br /&gt;
        ctx.save();ctx.translate(cx,cy);ctx.scale(1,.70);&lt;br /&gt;
        var radius=base*(.72+ring*.17)+Math.sin(t*.00048+ring)*7;&lt;br /&gt;
        ctx.strokeStyle=ring===1?&amp;#039;rgba(255,55,121,.82)&amp;#039;:&amp;#039;rgba(68,197,255,.58)&amp;#039;;&lt;br /&gt;
        ctx.lineWidth=ring===1?3.4:2;&lt;br /&gt;
        ctx.globalAlpha=strength;&lt;br /&gt;
        ctx.beginPath();&lt;br /&gt;
        for(var a=0;a&amp;lt;Math.PI*2;a+=.035) {&lt;br /&gt;
          var rr=radius+Math.sin(a*13+t*.00054+ring)*7+Math.cos(a*37+ring)*4;&lt;br /&gt;
          if(a===0) ctx.moveTo(Math.cos(a)*rr,Math.sin(a)*rr);&lt;br /&gt;
          else ctx.lineTo(Math.cos(a)*rr,Math.sin(a)*rr);&lt;br /&gt;
        }ctx.closePath();ctx.stroke();ctx.restore();&lt;br /&gt;
      }&lt;br /&gt;
      // Staggered geometric shards in peripheral vision.&lt;br /&gt;
      ctx.save();ctx.globalAlpha=strength*.7;&lt;br /&gt;
      for(var i=0;i&amp;lt;geom.length;i++){&lt;br /&gt;
        var d=geom[i];var x=d.x*w,y=d.y*h;&lt;br /&gt;
        var edge=Math.max(Math.abs(d.x-.5)*2,Math.abs(d.y-.5)*2);&lt;br /&gt;
        if(edge&amp;lt;.55)continue;&lt;br /&gt;
        var spread=20+d.len*85;&lt;br /&gt;
        var sway=Math.sin(t*.00032+d.phase)*8;&lt;br /&gt;
        ctx.fillStyle=i%3?&amp;#039;rgba(80,145,232,.09)&amp;#039;:&amp;#039;rgba(232,59,112,.13)&amp;#039;;&lt;br /&gt;
        ctx.strokeStyle=i%2?&amp;#039;rgba(114,195,252,.35)&amp;#039;:&amp;#039;rgba(243,93,148,.3)&amp;#039;;&lt;br /&gt;
        ctx.lineWidth=1.0;&lt;br /&gt;
        ctx.beginPath();ctx.moveTo(x+sway,y-spread);ctx.lineTo(x+spread*.9+sway,y+spread*.3);ctx.lineTo(x-spread*.4+sway,y+spread);ctx.closePath();ctx.fill();ctx.stroke();&lt;br /&gt;
      }ctx.restore();&lt;br /&gt;
    }&lt;br /&gt;
    function drawClear(t, strength) {&lt;br /&gt;
      // Light begins to reclaim the storm without a full-screen white flash.&lt;br /&gt;
      ctx.save();ctx.globalAlpha=strength;&lt;br /&gt;
      for(var i=0;i&amp;lt;9;i++){&lt;br /&gt;
        var x=w*.27+i*w*.075;&lt;br /&gt;
        var g=ctx.createLinearGradient(x-150,-100,x+50,h+100);&lt;br /&gt;
        g.addColorStop(0,&amp;#039;rgba(119,213,255,.0)&amp;#039;);&lt;br /&gt;
        g.addColorStop(.30,&amp;#039;rgba(145,224,255,.14)&amp;#039;);&lt;br /&gt;
        g.addColorStop(.7,&amp;#039;rgba(126,201,255,.045)&amp;#039;);&lt;br /&gt;
        g.addColorStop(1,&amp;#039;rgba(160,237,255,0)&amp;#039;);&lt;br /&gt;
        ctx.fillStyle=g;&lt;br /&gt;
        ctx.beginPath();ctx.moveTo(x-22,-60);ctx.lineTo(x+26,-60);ctx.lineTo(x+220,h+60);ctx.lineTo(x+80,h+60);ctx.fill();&lt;br /&gt;
      }&lt;br /&gt;
      for(var j=0;j&amp;lt;40;j++){&lt;br /&gt;
        var p=drops[j], px=p.x*w, py=((p.y*h -t*.022*p.v)%(h+60)+h+60)%(h+60);&lt;br /&gt;
        ctx.fillStyle=&amp;#039;rgba(181,230,255,&amp;#039;+(.08+.2*((j%9)/9))+&amp;#039;)&amp;#039;;&lt;br /&gt;
        ctx.fillRect(px,py,1.2,1.2);&lt;br /&gt;
      }ctx.restore();&lt;br /&gt;
    }&lt;br /&gt;
    function render(t) {&lt;br /&gt;
      ctx.clearRect(0,0,w,h);&lt;br /&gt;
      var q=probe, mag=q.intensity;&lt;br /&gt;
      if(mag&amp;lt;=.008) return;&lt;br /&gt;
      var intensity=Math.min(1,mag);&lt;br /&gt;
      drawClouds(t,intensity*(.72+.9*q.storm)*(1-q.clear*.93));&lt;br /&gt;
      drawRain(t,intensity*(.6+.8*q.rift)*(1-q.clear*.97));&lt;br /&gt;
      drawSignal(t,intensity*smooth(.25,.75,q.rift)*(.8+.3*q.void)*(1-q.clear));&lt;br /&gt;
      drawFracture(t,intensity*q.rift*(1-q.clear*.98));&lt;br /&gt;
      drawAbyss(t,intensity*q.void*(1-q.clear*.98));&lt;br /&gt;
      if(q.clear&amp;gt;0) drawClear(t,intensity*q.clear);&lt;br /&gt;
    }&lt;br /&gt;
    function tick(t) {&lt;br /&gt;
      raf=0;&lt;br /&gt;
      if(!active||disabled||document.hidden) return;&lt;br /&gt;
      // 30 FPS cap, plus device-pixel-ratio cap, for CPU-friendly effects.&lt;br /&gt;
      if(t-lastTime&amp;gt;=32){ lastTime=t;render(t); }&lt;br /&gt;
      raf=requestAnimationFrame(tick);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    window.addEventListener(&amp;#039;scroll&amp;#039;,scrollListener,{passive:true});&lt;br /&gt;
    window.addEventListener(&amp;#039;resize&amp;#039;,function(){measure();updateScroll();},{passive:true});&lt;br /&gt;
    window.addEventListener(&amp;#039;load&amp;#039;,function(){measure();updateScroll();},{once:true});&lt;br /&gt;
    document.addEventListener(&amp;#039;visibilitychange&amp;#039;,function(){if(!document.hidden)updateScroll();});&lt;br /&gt;
    measure(); setEnabled();&lt;br /&gt;
  }&lt;br /&gt;
  if(document.readyState===&amp;#039;loading&amp;#039;)document.addEventListener(&amp;#039;DOMContentLoaded&amp;#039;,start,{once:true});&lt;br /&gt;
  else start();&lt;br /&gt;
}());&lt;/div&gt;</summary>
		<author><name>KK</name></author>
	</entry>
</feed>