var szfyBlizzardStormEffect = {
name: "Blizzard Storm",
description: "Fast diagonal snowstorm with strong wind. Snow moves top-right to bottom-left with varied particle sizes, creating a dense blizzard on smooth canvas.",
icon: "❄️",
type: "visual",
author: "Krishna Katariya",
thumbnail: "assets/effects/visual/thumbnails/blizzard-storm.webp",
license: "https://seazonify.com/license",
version: "1.0.0",
created: "2026-03-14",
updated: "2026-03-14",
category: "weather",
tags: ["snow", "blizzard", "storm", "winter", "wind"],
css: [
".szfy-blizzard-canvas {",
"  position: fixed;",
"  top: 0;",
"  left: 0;",
"  width: 100%;",
"  height: 100%;",
"  pointer-events: none;",
"  z-index: 9999;",
"}"
].join("\n"),
html: '<canvas class="szfy-blizzard-canvas" id="szfy-blizzard-canvas" aria-hidden="true"></canvas>',
js: [
"(function () {",
"  var canvas = document.getElementById('szfy-blizzard-canvas');",
"  if (!canvas) return;",
"  var ctx = canvas.getContext('2d');",
"  var isMobile = window.innerWidth < 768;",
"  var MAX_PARTICLES = isMobile ? 45 : 110;",
"  var windGust = 3.5;",
"  var windTarget = 3.5;",
"  var gustTimer = 0;",
"  var particles = [];",
"  var animationFrame = null;",
"  var lastTime = 0;",
"",
"  function randomBetween(a, b) { return a + Math.random() * (b - a); }",
"",
"  function resizeCanvas() {",
"    canvas.width = window.innerWidth;",
"    canvas.height = window.innerHeight;",
"  }",
"",
"  function createParticle() {",
"    var size = randomBetween(isMobile ? 1.5 : 1.8, isMobile ? 4.5 : 6.5);",
"    var spawnFromRight = Math.random() < 0.35;",
"    return {",
"      x: spawnFromRight ? canvas.width + randomBetween(0, 60) : randomBetween(-60, canvas.width + 60),",
"      y: spawnFromRight ? randomBetween(-60, canvas.height * 0.6) : randomBetween(-80, -size),",
"      size: size,",
"      speedX: randomBetween(-6.5, -3.2),",
"      speedY: randomBetween(3.0, 7.5),",
"      opacity: randomBetween(0.55, 1.0),",
"      wobble: randomBetween(0, Math.PI * 2),",
"      wobbleSpeed: randomBetween(0.025, 0.07),",
"      wobbleAmp: randomBetween(0.3, 1.1),",
"      blur: size < 2.5 ? 0.5 : 0",
"    };",
"  }",
"",
"  resizeCanvas();",
"",
"  for (var ii = 0; ii < MAX_PARTICLES; ii++) {",
"    var pp = createParticle();",
"    pp.x = randomBetween(-60, canvas.width + 60);",
"    pp.y = randomBetween(0, canvas.height);",
"    particles.push(pp);",
"  }",
"",
"  function update(dt) {",
"    gustTimer += dt;",
"    if (gustTimer > randomBetween(1800, 4000)) {",
"      gustTimer = 0;",
"      windTarget = randomBetween(2.5, 5.5);",
"    }",
"    windGust += (windTarget - windGust) * 0.02;",
"    var H = canvas.height;",
"    for (var i = 0; i < particles.length; i++) {",
"      var p = particles[i];",
"      p.wobble += p.wobbleSpeed;",
"      var wobbleX = Math.sin(p.wobble) * p.wobbleAmp;",
"      p.x += p.speedX * windGust * dt * 0.06 + wobbleX * dt * 0.04;",
"      p.y += p.speedY * dt * 0.06;",
"      if (p.y > H + 20 || p.x < -80) { particles[i] = createParticle(); }",
"    }",
"  }",
"",
"  function draw() {",
"    ctx.clearRect(0, 0, canvas.width, canvas.height);",
"    for (var i = 0; i < particles.length; i++) {",
"      var p = particles[i];",
"      ctx.save();",
"      if (p.blur > 0) { ctx.filter = 'blur(' + p.blur + 'px)'; }",
"      ctx.globalAlpha = p.opacity;",
"      ctx.fillStyle = '#ffffff';",
"      ctx.beginPath();",
"      ctx.arc(p.x, p.y, p.size * 0.5, 0, Math.PI * 2);",
"      ctx.fill();",
"      if (p.size > 3.5) {",
"        ctx.globalAlpha = p.opacity * 0.25;",
"        ctx.strokeStyle = '#ffffff';",
"        ctx.lineWidth = p.size * 0.25;",
"        var sLen = p.size * 2.2;",
"        ctx.beginPath();",
"        ctx.moveTo(p.x, p.y);",
"        ctx.lineTo(p.x + p.speedX * sLen * 0.18, p.y - p.speedY * sLen * 0.18);",
"        ctx.stroke();",
"      }",
"      ctx.restore();",
"    }",
"  }",
"",
"  function loop(timestamp) {",
"    var dt = Math.min(timestamp - lastTime, 50);",
"    lastTime = timestamp;",
"    update(dt);",
"    draw();",
"    animationFrame = requestAnimationFrame(loop);",
"  }",
"",
"  function handleVisibility() {",
"    if (document.hidden) {",
"      cancelAnimationFrame(animationFrame);",
"      animationFrame = null;",
"    } else {",
"      if (!animationFrame) {",
"        lastTime = performance.now();",
"        animationFrame = requestAnimationFrame(loop);",
"      }",
"    }",
"  }",
"",
"  function resizeHandler() { resizeCanvas(); }",
"",
"  document.addEventListener('visibilitychange', handleVisibility);",
"  window.addEventListener('resize', resizeHandler);",
"  lastTime = performance.now();",
"  animationFrame = requestAnimationFrame(loop);",
"",
"  canvas._szfyDestroy = function () {",
"    cancelAnimationFrame(animationFrame);",
"    animationFrame = null;",
"    document.removeEventListener('visibilitychange', handleVisibility);",
"    window.removeEventListener('resize', resizeHandler);",
"  };",
"})();"
].join("\n")
};
if (typeof window !== "undefined" && window.SeazonifyController) {
window.SeazonifyController.injectVisualEffect(szfyBlizzardStormEffect);
}
if (typeof module !== "undefined" && module.exports) {
module.exports = { visual: szfyBlizzardStormEffect };
}