// @charset UTF-8
var szfyWinterMistEffect = {
  name: "Winter Mist",
  description: "Soft cold mist slowly drifts across the screen, creating a calm winter atmosphere with gentle fog movement that adds depth without distracting from page content.",
  icon: "❄️",
  type: "visual",
  author: "Krishna Katariya",
  thumbnail: "assets/effects/visual/thumbnails/winter-mist.webp",
  license: "https://seazonify.com/license",
  version: "1.0.0",
  created: "2026-03-15",
  updated: "2026-03-15",
  category: "weather",
  tags: ["mist", "fog", "winter", "atmosphere", "cold"],

  css: [
    ".szfy-winter-mist-canvas {",
    "  position: fixed;",
    "  top: 0;",
    "  left: 0;",
    "  width: 100%;",
    "  height: 100%;",
    "  pointer-events: none;",
    "  z-index: 9999;",
    "}"
  ].join("\n"),

  html: '<canvas class="szfy-winter-mist-canvas" id="szfy-winter-mist-canvas" aria-hidden="true"></canvas>',

  js: [
    "(function () {",
    "  var canvas = document.getElementById('szfy-winter-mist-canvas');",
    "  if (!canvas) return;",
    "  var ctx = canvas.getContext('2d');",
    "  var isMobile = window.innerWidth < 768;",
    "  var animationFrame = null;",
    "  var lastTime = 0;",
    "  var W = 0;",
    "  var H = 0;",
    "",
    "  // Large soft mist puffs -- very few, very large, very transparent",
    "  var MAX_PARTICLES = isMobile ? 6 : 11;",
    "  var particles = [];",
    "",
    "  function randomBetween(a, b) { return a + Math.random() * (b - a); }",
    "",
    "  function resizeCanvas() {",
    "    W = canvas.width = window.innerWidth;",
    "    H = canvas.height = window.innerHeight;",
    "  }",
    "",
    "  // Each mist puff: a large soft ellipse drifting slowly",
    "  function createPuff(scatter) {",
    "    var radiusX = randomBetween(isMobile ? W * 0.25 : W * 0.18, isMobile ? W * 0.55 : W * 0.42);",
    "    var radiusY = radiusX * randomBetween(0.28, 0.52);",
    "    var spawnX, spawnY;",
    "    if (scatter) {",
    "      spawnX = randomBetween(-radiusX * 0.5, W + radiusX * 0.5);",
    "      spawnY = randomBetween(H * 0.15, H * 0.9);",
    "    } else {",
    "      // Spawn fully off-screen on one side",
    "      spawnX = Math.random() < 0.5 ? -radiusX - 20 : W + radiusX + 20;",
    "      spawnY = randomBetween(H * 0.1, H * 0.92);",
    "    }",
    "    var dir = spawnX < W * 0.5 ? 1 : -1;",
    "    return {",
    "      x: spawnX,",
    "      y: spawnY,",
    "      radiusX: radiusX,",
    "      radiusY: radiusY,",
    "      speedX: dir * randomBetween(0.06, 0.22),",
    "      speedY: randomBetween(-0.04, 0.04),",
    "      // Very gentle vertical breathing",
    "      breathPhase: randomBetween(0, Math.PI * 2),",
    "      breathSpeed: randomBetween(0.00035, 0.0009),",
    "      breathAmp: randomBetween(H * 0.008, H * 0.022),",
    "      // Opacity lifecycle: fade in, hold, fade out",
    "      opacity: 0,",
    "      peakOpacity: randomBetween(isMobile ? 0.045 : 0.038, isMobile ? 0.085 : 0.072),",
    "      fadeState: 'in',",
    "      fadeSpeed: randomBetween(0.00008, 0.00018),",
    "      // Slow size drift: puff gently swells/shrinks",
    "      scalePhase: randomBetween(0, Math.PI * 2),",
    "      scaleSpeed: randomBetween(0.00025, 0.00065),",
    "      scaleAmp: randomBetween(0.04, 0.12),",
    "      // Rotation drift",
    "      rotation: randomBetween(-0.25, 0.25),",
    "      rotSpeed: randomBetween(-0.000045, 0.000045),",
    "      // Color tint: pure white to faint blue-grey",
    "      tint: randomBetween(0, 1)",
    "    };",
    "  }",
    "",
    "  function initPuffs() {",
    "    particles = [];",
    "    for (var i = 0; i < MAX_PARTICLES; i++) {",
    "      particles.push(createPuff(true));",
    "      // Start some already partially visible",
    "      if (Math.random() < 0.6) {",
    "        particles[i].opacity = randomBetween(0, particles[i].peakOpacity);",
    "        particles[i].fadeState = Math.random() < 0.5 ? 'in' : 'hold';",
    "      }",
    "    }",
    "  }",
    "",
    "  function update(dt) {",
    "    for (var i = 0; i < particles.length; i++) {",
    "      var p = particles[i];",
    "",
    "      // Drift",
    "      p.x += p.speedX * dt;",
    "      p.breathPhase += p.breathSpeed * dt;",
    "      p.y += p.speedY * dt + Math.sin(p.breathPhase) * p.breathAmp * 0.012;",
    "      p.rotation += p.rotSpeed * dt;",
    "      p.scalePhase += p.scaleSpeed * dt;",
    "",
    "      // Opacity lifecycle",
    "      if (p.fadeState === 'in') {",
    "        p.opacity += p.fadeSpeed * dt;",
    "        if (p.opacity >= p.peakOpacity) {",
    "          p.opacity = p.peakOpacity;",
    "          p.fadeState = 'hold';",
    "          // Hold for a long random duration then fade out",
    "          p._holdTimer = 0;",
    "          p._holdDuration = randomBetween(8000, 22000);",
    "        }",
    "      } else if (p.fadeState === 'hold') {",
    "        p._holdTimer += dt;",
    "        if (p._holdTimer >= p._holdDuration) {",
    "          p.fadeState = 'out';",
    "        }",
    "      } else if (p.fadeState === 'out') {",
    "        p.opacity -= p.fadeSpeed * dt * 0.7;",
    "        if (p.opacity <= 0) {",
    "          particles[i] = createPuff(false);",
    "        }",
    "      }",
    "",
    "      // Also recycle if drifted fully off-screen",
    "      if (p.x > W + p.radiusX * 1.4 || p.x < -p.radiusX * 1.4) {",
    "        particles[i] = createPuff(false);",
    "      }",
    "    }",
    "  }",
    "",
    "  function drawPuff(p) {",
    "    if (p.opacity <= 0) return;",
    "",
    "    var scale = 1.0 + Math.sin(p.scalePhase) * p.scaleAmp;",
    "    var rx = p.radiusX * scale;",
    "    var ry = p.radiusY * scale;",
    "",
    "    // Interpolate tint: white (255,255,255) to cool blue-grey (210,225,240)",
    "    var r = Math.round(255 - p.tint * 45);",
    "    var g = Math.round(255 - p.tint * 30);",
    "    var b = Math.round(255 - p.tint * 15);",
    "",
    "    ctx.save();",
    "    ctx.translate(p.x, p.y);",
    "    ctx.rotate(p.rotation);",
    "",
    "    // Outer soft halo",
    "    var grad = ctx.createRadialGradient(0, 0, 0, 0, 0, rx);",
    "    grad.addColorStop(0,    'rgba(' + r + ',' + g + ',' + b + ',' + (p.opacity) + ')');",
    "    grad.addColorStop(0.35, 'rgba(' + r + ',' + g + ',' + b + ',' + (p.opacity * 0.75) + ')');",
    "    grad.addColorStop(0.65, 'rgba(' + r + ',' + g + ',' + b + ',' + (p.opacity * 0.35) + ')');",
    "    grad.addColorStop(1,    'rgba(' + r + ',' + g + ',' + b + ',0)');",
    "",
    "    ctx.scale(1, ry / rx);",
    "    ctx.beginPath();",
    "    ctx.arc(0, 0, rx, 0, Math.PI * 2);",
    "    ctx.fillStyle = grad;",
    "    ctx.fill();",
    "    ctx.restore();",
    "  }",
    "",
    "  function loop(timestamp) {",
    "    var dt = Math.min(timestamp - lastTime, 50);",
    "    lastTime = timestamp;",
    "",
    "    ctx.clearRect(0, 0, W, H);",
    "    update(dt);",
    "",
    "    // Sort back-to-front by opacity so denser puffs overlap correctly",
    "    var sorted = particles.slice().sort(function(a, b) { return a.opacity - b.opacity; });",
    "    for (var i = 0; i < sorted.length; i++) {",
    "      drawPuff(sorted[i]);",
    "    }",
    "",
    "    animationFrame = requestAnimationFrame(loop);",
    "  }",
    "",
    "  function handleVisibility() {",
    "    if (document.hidden) {",
    "      cancelAnimationFrame(animationFrame);",
    "      animationFrame = null;",
    "    } else {",
    "      if (!animationFrame) {",
    "        lastTime = performance.now();",
    "        animationFrame = requestAnimationFrame(loop);",
    "      }",
    "    }",
    "  }",
    "",
    "  function resizeHandler() {",
    "    resizeCanvas();",
    "    initPuffs();",
    "  }",
    "",
    "  resizeCanvas();",
    "  initPuffs();",
    "  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")
};

// Auto-inject
if (typeof window !== "undefined" && window.SeazonifyController) {
  window.SeazonifyController.injectVisualEffect(szfyWinterMistEffect);
}

// Export
if (typeof module !== "undefined" && module.exports) {
  module.exports = { visual: szfyWinterMistEffect };
}