// Lowkey ASCII flow-field, ertdfgcvb-inspired. ~10fps, paused on tab blur.
// Renders into the #ascii canvas (we treat it as a div, but using textContent for speed).
(function () {
  const el = document.getElementById('ascii');
  if (!el) return;

  // Skip entirely on mobile — the CSS hides #ascii but we don't want the per-frame
  // textContent build (cols × rows string concatenation) burning battery for nothing.
  const IS_MOBILE = (window.matchMedia && window.matchMedia('(max-width: 740px)').matches) ||
                    (window.matchMedia && window.matchMedia('(pointer: coarse)').matches);
  if (IS_MOBILE) { el.remove(); return; }

  // Replace canvas with a div for textContent rendering (canvas tag was a placeholder)
  const div = document.createElement('div');
  div.id = 'ascii';
  div.style.cssText = el.style.cssText;
  el.replaceWith(div);

  const CHARS = ' ·.:·-=+*%#'; // sparse → dense
  let cols = 0, rows = 0;
  let t = 0;
  let raf = null;
  let paused = false;
  const FPS = 10;
  const FRAME_MS = 1000 / FPS;
  let lastFrame = 0;

  function resize() {
    // Measure character size with a probe
    const probe = document.createElement('span');
    probe.style.cssText = 'position:absolute;visibility:hidden;font:11px/11px JetBrains Mono, monospace;white-space:pre;';
    probe.textContent = 'M'.repeat(50);
    document.body.appendChild(probe);
    const cw = probe.getBoundingClientRect().width / 50;
    document.body.removeChild(probe);

    cols = Math.ceil(window.innerWidth / cw) + 2;
    rows = Math.ceil(window.innerHeight / 11) + 2;
  }
  resize();
  window.addEventListener('resize', resize);

  function frame(now) {
    if (paused) { raf = requestAnimationFrame(frame); return; }
    if (now - lastFrame < FRAME_MS) { raf = requestAnimationFrame(frame); return; }
    lastFrame = now;
    t += 0.04;

    // Build line buffer
    const lines = new Array(rows);
    const cx = cols * 0.5;
    const cy = rows * 0.5;

    for (let y = 0; y < rows; y++) {
      let row = '';
      for (let x = 0; x < cols; x++) {
        const dx = (x - cx) / cols;
        const dy = (y - cy) / rows;
        // Lowkey pattern: drifting interference + radial fade
        const v =
          Math.sin(x * 0.18 + t) * 0.5 +
          Math.cos(y * 0.22 - t * 0.7) * 0.5 +
          Math.sin((x + y) * 0.06 + t * 0.4) * 0.3;
        const radial = 1 - Math.min(1, Math.sqrt(dx*dx + dy*dy) * 1.4);
        const i = Math.max(0, Math.min(CHARS.length - 1,
          Math.floor(((v + 1) * 0.5) * radial * CHARS.length * 0.55)));
        row += CHARS[i];
      }
      lines[y] = row;
    }
    div.textContent = lines.join('\n');
    raf = requestAnimationFrame(frame);
  }
  raf = requestAnimationFrame(frame);

  // Pause when tab hidden
  document.addEventListener('visibilitychange', () => {
    paused = document.hidden;
  });
})();
