/* ============================================================
   Globinex Research — custom.js
   ============================================================ */
(function () {
  "use strict";

  /* ---------- 1. Navbar on scroll ---------- */
  var nav = document.getElementById("gxNav");
  function onScroll() {
    if (window.scrollY > 60) nav.classList.add("scrolled");
    else nav.classList.remove("scrolled");
  }
  window.addEventListener("scroll", onScroll, { passive: true });
  onScroll();

  /* ---------- 2. Scroll reveal ---------- */
  var revealEls = document.querySelectorAll(".reveal");
  var revObserver = new IntersectionObserver(function (entries) {
    entries.forEach(function (e) {
      if (e.isIntersecting) {
        e.target.classList.add("in");
        revObserver.unobserve(e.target);
      }
    });
  }, { threshold: 0.15, rootMargin: "0px 0px -40px 0px" });
  revealEls.forEach(function (el) { revObserver.observe(el); });

  /* ---------- 3. Count-up numbers ---------- */
  function animateCount(el) {
    var target = parseFloat(el.getAttribute("data-count"));
    var suffix = el.getAttribute("data-suffix") || "";
    var dur = 1600, start = null;
    function step(ts) {
      if (!start) start = ts;
      var p = Math.min((ts - start) / dur, 1);
      var eased = 1 - Math.pow(1 - p, 3);
      var val = target * eased;
      el.textContent = (target % 1 === 0 ? Math.round(val) : val.toFixed(1)) + suffix;
      if (p < 1) requestAnimationFrame(step);
      else el.textContent = target + suffix;
    }
    requestAnimationFrame(step);
  }
  var countObserver = new IntersectionObserver(function (entries) {
    entries.forEach(function (e) {
      if (e.isIntersecting) {
        animateCount(e.target);
        countObserver.unobserve(e.target);
      }
    });
  }, { threshold: 0.6 });
  document.querySelectorAll("[data-count]").forEach(function (el) { countObserver.observe(el); });

  /* ---------- 4. FAQ — left list drives right answer panel ---------- */
  var faqItems = document.querySelectorAll(".faq-item");
  var pNum = document.getElementById("faqPanelNum");
  var pTitle = document.getElementById("faqPanelTitle");
  var pA1 = document.getElementById("faqPanelA1");
  var pA2 = document.getElementById("faqPanelA2");
  var faqPanel = document.getElementById("faqPanel");

  function selectFaq(item) {
    faqItems.forEach(function (i) { i.classList.remove("active"); });
    item.classList.add("active");
    if (!pTitle) return;
    var num = item.querySelector(".num").textContent;
    if (pNum) pNum.textContent = num;
    pTitle.textContent = item.getAttribute("data-title");
    pA1.textContent = item.getAttribute("data-a1");
    pA2.textContent = item.getAttribute("data-a2");
    // tiny fade pulse
    faqPanel.classList.remove("swap");
    void faqPanel.offsetWidth;
    faqPanel.classList.add("swap");
  }

  faqItems.forEach(function (item) {
    item.querySelector(".faq-q").addEventListener("click", function () {
      selectFaq(item);
    });
  });

  /* ---------- 5. Blog carousel — slides one card at a time ---------- */
  (function () {
    var track = document.getElementById("blogTrack");
    if (!track) return;
    var dotsWrap = document.getElementById("blogDots");
    var prevBtn = document.getElementById("blogPrev");
    var nextBtn = document.getElementById("blogNext");
    var slides = track.querySelectorAll(".blog-slide");
    var total = slides.length;
    var index = 0;
    var autoTimer = null;

    function perView() {
      if (window.innerWidth <= 575) return 1;
      if (window.innerWidth <= 991) return 2;
      return 3;
    }
    function maxIndex() { return Math.max(0, total - perView()); }

    function step() {
      // distance of one card (card width + gap)
      var first = slides[0];
      var gap = parseFloat(getComputedStyle(track).gap) || 24;
      return first.getBoundingClientRect().width + gap;
    }

    function render() {
      if (index > maxIndex()) index = maxIndex();
      track.style.transform = "translateX(" + (-index * step()) + "px)";
      dotsWrap.querySelectorAll(".dot").forEach(function (d, i) {
        d.classList.toggle("active", i === index);
      });
      if (prevBtn) prevBtn.disabled = index === 0;
      if (nextBtn) nextBtn.disabled = index === maxIndex();
    }

    function buildDots() {
      dotsWrap.innerHTML = "";
      var count = maxIndex() + 1;
      for (var i = 0; i < count; i++) {
        var d = document.createElement("span");
        d.className = "dot" + (i === 0 ? " active" : "");
        (function (i) { d.addEventListener("click", function () { index = i; render(); restart(); }); })(i);
        dotsWrap.appendChild(d);
      }
    }

    function go(dir) {
      var mi = maxIndex();
      index += dir;
      if (index > mi) index = 0;        // loop to start
      if (index < 0) index = mi;        // loop to end
      render();
    }

    function restart() {
      clearInterval(autoTimer);
      autoTimer = setInterval(function () { go(1); }, 3500);
    }

    if (nextBtn) nextBtn.addEventListener("click", function () { go(1); restart(); });
    if (prevBtn) prevBtn.addEventListener("click", function () { go(-1); restart(); });

    var rt;
    window.addEventListener("resize", function () {
      clearTimeout(rt);
      rt = setTimeout(function () { buildDots(); render(); }, 150);
    });

    buildDots();
    render();
    restart();
  })();

  /* ---------- 6. Hero network canvas ---------- */
  var canvas = document.getElementById("heroCanvas");
  if (!canvas) return;
  var ctx = canvas.getContext("2d");
  var nodes = [], W = 0, H = 0, DPR = Math.min(window.devicePixelRatio || 1, 2);

  function resize() {
    var r = canvas.getBoundingClientRect();
    W = r.width; H = r.height;
    canvas.width = W * DPR; canvas.height = H * DPR;
    ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
    buildNodes();
  }

  function buildNodes() {
    nodes = [];
    // weight the cluster toward the right half of the hero
    var count = Math.max(26, Math.round(W / 36));
    for (var i = 0; i < count; i++) {
      var rightBias = Math.random() * Math.random(); // skews to the right
      var x = W * (0.42 + rightBias * 0.56);
      var y = H * (0.08 + Math.random() * 0.84);
      nodes.push({
        x: x, y: y,
        ox: x, oy: y,
        r: 2 + Math.random() * 2.6,
        phase: Math.random() * Math.PI * 2,
        speed: 0.4 + Math.random() * 0.7,
        amp: 8 + Math.random() * 18,
        person: Math.random() > 0.55
      });
    }
  }

  function drawPerson(n, alpha) {
    ctx.save();
    ctx.globalAlpha = alpha;
    ctx.fillStyle = "#00CC5E";
    // head
    ctx.beginPath();
    ctx.arc(n.x, n.y - n.r * 1.4, n.r * 0.95, 0, Math.PI * 2);
    ctx.fill();
    // body
    ctx.beginPath();
    ctx.moveTo(n.x - n.r * 1.3, n.y + n.r * 1.7);
    ctx.quadraticCurveTo(n.x, n.y - n.r * 0.2, n.x + n.r * 1.3, n.y + n.r * 1.7);
    ctx.closePath();
    ctx.fill();
    ctx.restore();
  }

  var t = 0;
  function frame() {
    ctx.clearRect(0, 0, W, H);
    t += 0.012;

    // update positions (gentle float)
    for (var i = 0; i < nodes.length; i++) {
      var n = nodes[i];
      n.x = n.ox + Math.cos(t * n.speed + n.phase) * n.amp;
      n.y = n.oy + Math.sin(t * n.speed * 0.8 + n.phase) * n.amp * 0.6;
    }

    // connecting lines
    for (var a = 0; a < nodes.length; a++) {
      for (var b = a + 1; b < nodes.length; b++) {
        var dx = nodes[a].x - nodes[b].x;
        var dy = nodes[a].y - nodes[b].y;
        var dist = Math.sqrt(dx * dx + dy * dy);
        if (dist < 130) {
          var op = (1 - dist / 130) * 0.45;
          ctx.strokeStyle = "rgba(0, 171, 79," + op + ")";
          ctx.lineWidth = 1;
          ctx.beginPath();
          ctx.moveTo(nodes[a].x, nodes[a].y);
          ctx.lineTo(nodes[b].x, nodes[b].y);
          ctx.stroke();
        }
      }
    }

    // nodes
    for (var k = 0; k < nodes.length; k++) {
      var nd = nodes[k];
      var pulse = 0.55 + 0.45 * Math.sin(t * 1.5 + nd.phase);
      if (nd.person) {
        drawPerson(nd, 0.5 + pulse * 0.5);
      } else {
        ctx.beginPath();
        ctx.fillStyle = "rgba(0, 204, 94," + (0.4 + pulse * 0.5) + ")";
        ctx.arc(nd.x, nd.y, nd.r, 0, Math.PI * 2);
        ctx.fill();
        // glow
        ctx.beginPath();
        ctx.fillStyle = "rgba(0, 204, 94, 0.08)";
        ctx.arc(nd.x, nd.y, nd.r * 3.4, 0, Math.PI * 2);
        ctx.fill();
      }
    }

    requestAnimationFrame(frame);
  }

  window.addEventListener("resize", resize);
  resize();
  requestAnimationFrame(frame);
})();

/* ============================================================
   About section — subtle animated network background
   ============================================================ */
(function () {
  "use strict";
  var canvas = document.getElementById("aboutCanvas");
  if (!canvas) return;
  var ctx = canvas.getContext("2d");
  var pts = [], W = 0, H = 0, running = false, raf = null;
  var DPR = Math.min(window.devicePixelRatio || 1, 2);

  function resize() {
    var r = canvas.getBoundingClientRect();
    W = r.width; H = r.height;
    if (!W || !H) return;
    canvas.width = W * DPR; canvas.height = H * DPR;
    ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
    build();
  }

  function build() {
    pts = [];
    var count = Math.max(28, Math.round((W * H) / 26000));
    for (var i = 0; i < count; i++) {
      pts.push({
        x: Math.random() * W,
        y: Math.random() * H,
        vx: (Math.random() - 0.5) * 0.35,
        vy: (Math.random() - 0.5) * 0.35,
        r: 1.4 + Math.random() * 2.2
      });
    }
  }

  function frame() {
    ctx.clearRect(0, 0, W, H);
    for (var i = 0; i < pts.length; i++) {
      var p = pts[i];
      p.x += p.vx; p.y += p.vy;
      if (p.x < 0 || p.x > W) p.vx *= -1;
      if (p.y < 0 || p.y > H) p.vy *= -1;
    }
    // links
    for (var a = 0; a < pts.length; a++) {
      for (var b = a + 1; b < pts.length; b++) {
        var dx = pts[a].x - pts[b].x, dy = pts[a].y - pts[b].y;
        var d = Math.sqrt(dx * dx + dy * dy);
        if (d < 150) {
          ctx.strokeStyle = "rgba(0,135,62," + (1 - d / 150) * 0.16 + ")";
          ctx.lineWidth = 1;
          ctx.beginPath();
          ctx.moveTo(pts[a].x, pts[a].y);
          ctx.lineTo(pts[b].x, pts[b].y);
          ctx.stroke();
        }
      }
    }
    // dots
    for (var k = 0; k < pts.length; k++) {
      ctx.beginPath();
      ctx.fillStyle = "rgba(0,135,62,0.30)";
      ctx.arc(pts[k].x, pts[k].y, pts[k].r, 0, Math.PI * 2);
      ctx.fill();
    }
    raf = requestAnimationFrame(frame);
  }

  // Only animate while the section is on screen (saves CPU)
  var io = new IntersectionObserver(function (entries) {
    entries.forEach(function (e) {
      if (e.isIntersecting && !running) {
        running = true; raf = requestAnimationFrame(frame);
      } else if (!e.isIntersecting && running) {
        running = false; cancelAnimationFrame(raf);
      }
    });
  }, { threshold: 0 });

  window.addEventListener("resize", resize);
  resize();
  io.observe(canvas);
})();

/* ============================================================
   Services section — flowing aurora gradient background
   ============================================================ */
(function () {
  "use strict";
  var canvas = document.getElementById("servicesCanvas");
  if (!canvas) return;
  var ctx = canvas.getContext("2d");
  var pts = [], W = 0, H = 0, running = false, raf = null;
  var DPR = Math.min(window.devicePixelRatio || 1, 2);

  function resize() {
    var r = canvas.getBoundingClientRect();
    W = r.width; H = r.height;
    if (!W || !H) return;
    canvas.width = W * DPR; canvas.height = H * DPR;
    ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
    build();
  }

  function build() {
    pts = [];
    var count = Math.max(28, Math.round((W * H) / 26000));
    for (var i = 0; i < count; i++) {
      pts.push({
        x: Math.random() * W,
        y: Math.random() * H,
        vx: (Math.random() - 0.5) * 0.35,
        vy: (Math.random() - 0.5) * 0.35,
        r: 1.4 + Math.random() * 2.2
      });
    }
  }

  function frame() {
    ctx.clearRect(0, 0, W, H);
    for (var i = 0; i < pts.length; i++) {
      var p = pts[i];
      p.x += p.vx; p.y += p.vy;
      if (p.x < 0 || p.x > W) p.vx *= -1;
      if (p.y < 0 || p.y > H) p.vy *= -1;
    }
    // links
    for (var a = 0; a < pts.length; a++) {
      for (var b = a + 1; b < pts.length; b++) {
        var dx = pts[a].x - pts[b].x, dy = pts[a].y - pts[b].y;
        var d = Math.sqrt(dx * dx + dy * dy);
        if (d < 150) {
          ctx.strokeStyle = "rgba(0,135,62," + (1 - d / 150) * 0.16 + ")";
          ctx.lineWidth = 1;
          ctx.beginPath();
          ctx.moveTo(pts[a].x, pts[a].y);
          ctx.lineTo(pts[b].x, pts[b].y);
          ctx.stroke();
        }
      }
    }
    // dots
    for (var k = 0; k < pts.length; k++) {
      ctx.beginPath();
      ctx.fillStyle = "rgba(0,135,62,0.30)";
      ctx.arc(pts[k].x, pts[k].y, pts[k].r, 0, Math.PI * 2);
      ctx.fill();
    }
    raf = requestAnimationFrame(frame);
  }

  // Only animate while the section is on screen (saves CPU)
  var io = new IntersectionObserver(function (entries) {
    entries.forEach(function (e) {
      if (e.isIntersecting && !running) {
        running = true; raf = requestAnimationFrame(frame);
      } else if (!e.isIntersecting && running) {
        running = false; cancelAnimationFrame(raf);
      }
    });
  }, { threshold: 0 });

  window.addEventListener("resize", resize);
  resize();
  io.observe(canvas);
})();
