/* NetworkField: an ambient, slowly-animated field of the PHYOMIC.AG
   microbial-network mark, for dark navy panels only (brand-sanctioned faint
   texture). Marks drift diagonally and bounce DVD-style while each spins
   slowly in place. Honours prefers-reduced-motion. Fills its positioned
   parent (which must be position:relative + overflow:hidden); sits at z0,
   so give the panel's content position:relative + zIndex:1. */

(function () {
  // seeded PRNG so the layout is stable across renders
  function mulberry32(a) {
    return function () {
      a |= 0; a = a + 0x6D2B79F5 | 0;
      let t = Math.imul(a ^ a >>> 15, 1 | a);
      t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
      return ((t ^ t >>> 14) >>> 0) / 4294967296;
    };
  }

  const AR = 552 / 499; // native aspect of the mark, keeps it round
  const PAD = 240;      // travel + generation margin
  const SRC = "assets/phyomic-icon-teal.png";

  const reduceMotion = typeof window !== "undefined" && window.matchMedia
    && window.matchMedia("(prefers-reduced-motion: reduce)").matches;

  // inject the spin keyframes once
  if (typeof document !== "undefined" && !document.getElementById("ph-net-spin-kf")) {
    const s = document.createElement("style");
    s.id = "ph-net-spin-kf";
    s.textContent = "@keyframes ph-net-spin{to{transform:rotate(360deg)}}";
    document.head.appendChild(s);
  }

  function buildIcons(W, H, spacing, intensity, seed) {
    const S = spacing;
    const rng = mulberry32(seed);
    const rowH = S * 0.86;
    const icons = [];
    let row = 0, key = 0;
    for (let y = -PAD; y < H + PAD; y += rowH, row++) {
      const xoff = (row % 2) ? S / 2 : 0;
      for (let x = -PAD; x < W + PAD; x += S) {
        const px = x + xoff + (rng() - 0.5) * S * 0.20;
        const py = y + (rng() - 0.5) * S * 0.20;
        const tier = rng();
        let size, baseOp;
        if (tier < 0.18)      { size = S * 1.18; baseOp = 0.045; }
        else if (tier < 0.55) { size = S * 0.82; baseOp = 0.075; }
        else                  { size = S * 0.52; baseOp = 0.110; }
        const w = size, h = size / AR;
        const rot = (rng() - 0.5) * 30;
        const op = Math.min(0.4, baseOp * intensity);
        const dur = 80 + rng() * 100;
        const dir = rng() < 0.5 ? "normal" : "reverse";
        const delay = -(((rot % 360) + 360) % 360) / 360 * dur;
        const style = {
          position: "absolute",
          left: (px - w / 2) + "px",
          top: (py - h / 2) + "px",
          width: w + "px",
          height: h + "px",
          display: "block",
          opacity: op,
          transform: "rotate(" + rot.toFixed(1) + "deg)",
          filter: tier < 0.18 ? "blur(1.2px)" : "none",
          userSelect: "none",
        };
        if (!reduceMotion) {
          style.animation = "ph-net-spin " + dur.toFixed(0) + "s linear " + delay.toFixed(1) + "s infinite " + dir;
        }
        icons.push({ key: key++, style });
      }
    }
    return icons;
  }

  function NetworkField({ spacing = 340, intensity = 1, seed = 11 }) {
    const wrapRef = React.useRef(null);
    const layerRef = React.useRef(null);
    const [dims, setDims] = React.useState({ w: 1200, h: 600 });

    // measure the panel we cover
    React.useEffect(function () {
      const el = wrapRef.current;
      if (!el) return;
      const measure = function () { setDims({ w: el.offsetWidth, h: el.offsetHeight }); };
      measure();
      let ro;
      if (typeof ResizeObserver !== "undefined") {
        ro = new ResizeObserver(measure);
        ro.observe(el);
      } else {
        window.addEventListener("resize", measure);
      }
      return function () { if (ro) ro.disconnect(); else window.removeEventListener("resize", measure); };
    }, []);

    // slow DVD-style drift of the whole field
    React.useEffect(function () {
      if (reduceMotion) return;
      const el = layerRef.current;
      if (!el) return;
      let x = 0, y = 0, vx = 0.009, vy = 0.0065, last = null, raf;
      const step = function (t) {
        if (last == null) last = t;
        const dt = Math.min(64, t - last); last = t;
        x += vx * dt; y += vy * dt;
        if (x > PAD) { x = PAD; vx = -vx; } else if (x < -PAD) { x = -PAD; vx = -vx; }
        if (y > PAD) { y = PAD; vy = -vy; } else if (y < -PAD) { y = -PAD; vy = -vy; }
        el.style.transform = "translate(" + x.toFixed(2) + "px," + y.toFixed(2) + "px)";
        raf = requestAnimationFrame(step);
      };
      raf = requestAnimationFrame(step);
      return function () { cancelAnimationFrame(raf); };
    }, []);

    const icons = React.useMemo(
      function () { return buildIcons(dims.w, dims.h, spacing, intensity, seed); },
      [dims.w, dims.h, spacing, intensity, seed]
    );

    return React.createElement(
      "div",
      { ref: wrapRef, "aria-hidden": "true", style: { position: "absolute", inset: 0, overflow: "hidden", pointerEvents: "none", zIndex: 0 } },
      React.createElement(
        "div",
        { ref: layerRef, style: { position: "absolute", inset: 0, willChange: "transform" } },
        icons.map(function (ic) {
          return React.createElement("img", { key: ic.key, src: SRC, alt: "", draggable: false, style: ic.style });
        })
      )
    );
  }

  window.NetworkField = NetworkField;
})();
