'use strict';
document.documentElement.classList.add('js');

/* ─── Particle system ─────────────────────────────────────── */
(function initParticles() {
  const canvas = document.getElementById('bb-particles');
  if (!canvas) return;

  const ctx = canvas.getContext('2d');
  const isMobile = window.matchMedia('(max-width: 768px)').matches;
  const COUNT = isMobile ? 60 : 150;

  let W, H, particles, mouse = { x: -9999, y: -9999 }, raf;
  let canvasOpacity = 1;

  function resize() {
    W = canvas.width = window.innerWidth;
    H = canvas.height = window.innerHeight;
  }

  function rand(min, max) { return min + Math.random() * (max - min); }

  function createParticles() {
    particles = [];
    for (let i = 0; i < COUNT; i++) {
      particles.push({
        x: rand(0, W),
        y: rand(0, H),
        r: rand(1, 3),
        opacity: rand(0.15, 0.45),
        vx: rand(-0.15, 0.15),
        vy: rand(-0.2, -0.05),
        baseX: 0,
        baseY: 0,
      });
      particles[i].baseX = particles[i].x;
      particles[i].baseY = particles[i].y;
    }
  }

  function draw() {
    ctx.clearRect(0, 0, W, H);
    ctx.save();
    ctx.globalAlpha = canvasOpacity;

    for (const p of particles) {
      // Mouse parallax: shift up to 15px toward cursor
      const dx = mouse.x - p.x;
      const dy = mouse.y - p.y;
      const dist = Math.sqrt(dx * dx + dy * dy);
      const maxDist = 300;
      if (dist < maxDist) {
        const factor = (1 - dist / maxDist) * 15;
        p.x += dx / dist * factor * 0.015;
        p.y += dy / dist * factor * 0.015;
      }

      // Drift
      p.x += p.vx;
      p.y += p.vy;

      // Wrap
      if (p.x < -5) p.x = W + 5;
      if (p.x > W + 5) p.x = -5;
      if (p.y < -5) p.y = H + 5;
      if (p.y > H + 5) p.y = -5;

      ctx.beginPath();
      ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
      // Electric blue color: #1B6FD8 or #4A9FE8
      const shade = p.r > 2 ? '74,159,232' : '27,111,216';
      ctx.fillStyle = `rgba(${shade},${p.opacity})`;
      ctx.fill();
    }

    ctx.restore();
    raf = requestAnimationFrame(draw);
  }

  // Fade canvas as user scrolls past hero section
  window.addEventListener('scroll', () => {
    const hero = document.querySelector('.bb-sec-hero');
    const heroHeight = hero ? hero.offsetHeight : window.innerHeight;
    const scrollPct = Math.min(window.scrollY / heroHeight, 1);
    canvasOpacity = Math.max(0.15, 1 - scrollPct * 0.7);
  }, { passive: true });

  window.addEventListener('mousemove', e => {
    mouse.x = e.clientX;
    mouse.y = e.clientY;
  }, { passive: true });

  // Respect reduced-motion
  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
    canvas.style.display = 'none';
    return;
  }

  resize();
  createParticles();
  draw();
  window.addEventListener('resize', () => { resize(); createParticles(); }, { passive: true });
})();

/* ─── Ghost word parallax ─────────────────────────────────── */
(function initGhostParallax() {
  const ghost = document.querySelector('.ghost-word');
  if (!ghost) return;
  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;

  let ticking = false;
  let currentY = window.scrollY;

  window.addEventListener('scroll', () => {
    currentY = window.scrollY;
    if (!ticking) {
      requestAnimationFrame(() => {
        // Move down slower than content: atmospheric layer
        ghost.style.transform = `translateY(calc(-50% + ${currentY * 0.15}px))`;
        ticking = false;
      });
      ticking = true;
    }
  }, { passive: true });
})();

/* ─── Scroll-triggered reveal ─────────────────────────────── */
(function initReveal() {
  const revealObserver = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const el = entry.target;
        const delay = parseInt(el.dataset.delay || '0', 10);
        setTimeout(() => {
          el.classList.add('in-view');
          el.classList.add('bb-reveal--in');
        }, delay);
        revealObserver.unobserve(el);
      }
    });
  }, { threshold: 0.10, rootMargin: '0px 0px -40px 0px' });

  document.querySelectorAll('[data-animate], .bb-reveal').forEach(el => revealObserver.observe(el));

  // Philosophy divider line (separate observer, uses scaleY)
  const divider = document.querySelector('.philosophy-divider');
  if (divider) {
    const divObs = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          divider.classList.add('in-view');
          divObs.unobserve(divider);
        }
      });
    }, { threshold: 0.2 });
    divObs.observe(divider);
  }

  // Fallback: reveal everything after 1.2s in case observer never fires
  setTimeout(() => {
    document.querySelectorAll('[data-animate]:not(.in-view)').forEach(el => {
      el.classList.add('in-view');
    });
    if (divider) divider.classList.add('in-view');
  }, 1200);
})();

/* ─── Stat counters ───────────────────────────────────────── */
(function initStatCounters() {
  const section = document.querySelector('.bb-sec-bigjoe');
  if (!section) return;

  let triggered = false;

  function easeOutExpo(t) {
    return t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
  }

  function animateCounter(el, target, duration) {
    // target is already the display value (143 for 143K, 15000 for 15,000+, etc.)
    const start = performance.now();

    function tick(now) {
      const elapsed = now - start;
      const progress = Math.min(elapsed / duration, 1);
      const value = Math.round(easeOutExpo(progress) * target);
      el.textContent = value.toLocaleString();
      if (progress < 1) requestAnimationFrame(tick);
      else el.textContent = target.toLocaleString();
    }

    requestAnimationFrame(tick);
  }

  const obs = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting && !triggered) {
        triggered = true;
        const nums = section.querySelectorAll('.stat-num');
        nums.forEach(num => {
          const target = parseInt(num.dataset.target || '0', 10);
          animateCounter(num, target, 2000);
        });
        obs.disconnect();
      }
    });
  }, { threshold: 0.3 });

  obs.observe(section);
})();

/* ─── Sticky header ───────────────────────────────────────── */
(function initHeader() {
  const header = document.querySelector('.bb-header');
  if (!header) return;

  let lastY = 0;

  window.addEventListener('scroll', () => {
    const y = window.scrollY;
    if (y > 60) header.classList.add('scrolled');
    else header.classList.remove('scrolled');
    if (y > lastY && y > 240) header.classList.add('hidden');
    else header.classList.remove('hidden');
    lastY = y;
  }, { passive: true });
})();

/* ─── Mobile nav ──────────────────────────────────────────── */
(function initMobileNav() {
  const hamburger = document.querySelector('.bb-hamburger');
  const mobileNav = document.querySelector('.bb-mobile-nav');
  if (!hamburger || !mobileNav) return;

  hamburger.addEventListener('click', () => {
    const open = hamburger.classList.toggle('open');
    mobileNav.classList.toggle('open');
    document.body.classList.toggle('nav-open');
    hamburger.setAttribute('aria-expanded', open);
  });

  mobileNav.querySelectorAll('a').forEach(a => {
    a.addEventListener('click', () => {
      hamburger.classList.remove('open');
      mobileNav.classList.remove('open');
      document.body.classList.remove('nav-open');
      hamburger.setAttribute('aria-expanded', 'false');
    });
  });
})();

/* ─── Services dropdown ───────────────────────────────────── */
(function initDropdown() {
  const trigger = document.querySelector('.nav-has-dropdown');
  if (!trigger) return;

  const menu = trigger.querySelector('.nav-dropdown');
  if (!menu) return;

  let hideTimer = null;

  const show = () => { clearTimeout(hideTimer); menu.classList.add('visible'); };
  const scheduleHide = () => {
    hideTimer = setTimeout(() => menu.classList.remove('visible'), 180);
  };

  trigger.addEventListener('mouseenter', show);
  trigger.addEventListener('mouseleave', scheduleHide);
  menu.addEventListener('mouseenter', show);
  menu.addEventListener('mouseleave', scheduleHide);
  trigger.addEventListener('focusin', show);
  trigger.addEventListener('focusout', scheduleHide);

  // Click outside
  document.addEventListener('click', e => {
    if (!trigger.contains(e.target)) menu.classList.remove('visible');
  });
})();

/* ─── Hero H1 word reveal + subhead fade ─────────────────── */
(function initHeroReveal() {
  const heroH1 = document.querySelector('.hero-h1');
  const heroSub = document.querySelector('.hero-sub');
  if (!heroH1) return;

  let wordIndex = 0;
  const walker = document.createTreeWalker(heroH1, NodeFilter.SHOW_TEXT);
  const textNodes = [];
  while (walker.nextNode()) textNodes.push(walker.currentNode);

  textNodes.forEach(node => {
    const frag = document.createDocumentFragment();
    node.textContent.split(/(\s+)/).forEach(chunk => {
      if (/^\s+$/.test(chunk)) {
        frag.appendChild(document.createTextNode(chunk));
      } else if (chunk) {
        const span = document.createElement('span');
        span.className = 'word';
        // 200ms page load delay + 120ms stagger per word
        span.style.transitionDelay = (200 + wordIndex * 120) + 'ms';
        span.textContent = chunk;
        frag.appendChild(span);
        wordIndex++;
      }
    });
    node.parentNode.replaceChild(frag, node);
  });

  // Trigger on next paint
  requestAnimationFrame(() => {
    setTimeout(() => {
      heroH1.classList.add('revealed');
      // Hero subhead: fade in after all words have staggered
      if (heroSub) {
        const subDelay = 200 + wordIndex * 120 + 400;
        setTimeout(() => heroSub.classList.add('revealed'), subDelay);
      }
    }, 0);
  });
})();

/* ─── FAQ accordion ───────────────────────────────────────── */
(function initFAQ() {
  document.querySelectorAll('.faq-item').forEach(item => {
    const btn = item.querySelector('.faq-q');
    const body = item.querySelector('.faq-a');
    if (!btn || !body) return;
    btn.addEventListener('click', () => {
      const open = item.classList.toggle('open');
      btn.setAttribute('aria-expanded', open);
      body.style.maxHeight = open ? body.scrollHeight + 'px' : '0';
    });
  });
})();

/* ─── Gallery drag-scroll ─────────────────────────────────── */
(function initGallery() {
  const wrap = document.querySelector('.gallery-track-wrap');
  if (!wrap) return;
  let isDown = false, startX = 0, scrollLeft = 0;
  wrap.addEventListener('mousedown', e => {
    isDown = true;
    wrap.classList.add('dragging');
    startX = e.pageX - wrap.offsetLeft;
    scrollLeft = wrap.scrollLeft;
  });
  ['mouseleave', 'mouseup'].forEach(ev => {
    wrap.addEventListener(ev, () => { isDown = false; wrap.classList.remove('dragging'); });
  });
  wrap.addEventListener('mousemove', e => {
    if (!isDown) return;
    e.preventDefault();
    const x = e.pageX - wrap.offsetLeft;
    wrap.scrollLeft = scrollLeft - (x - startX) * 1.5;
  });
})();

/* ─── Smooth scroll ───────────────────────────────────────── */
document.querySelectorAll('a[href^="#"]').forEach(a => {
  a.addEventListener('click', e => {
    const id = a.getAttribute('href');
    if (!id || id === '#' || id.length < 2) return;
    const target = document.querySelector(id);
    if (target) {
      e.preventDefault();
      target.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  });
});
