/* ── PARTICLE SYSTEM ── */
(function(){
  const canvas = document.getElementById('particleCanvas');
  const ctx = canvas.getContext('2d');
  let W, H, particles = [];
  function resize(){ W = canvas.width = window.innerWidth; H = canvas.height = window.innerHeight; }
  resize(); window.addEventListener('resize', resize);
  const COLORS = ['rgba(7,102,107,','rgba(245,194,5,','rgba(10,139,146,'];
  class P {
    constructor(){ this.reset(); }
    reset(){ this.x=Math.random()*W; this.y=Math.random()*H; this.r=Math.random()*2+0.5; this.alpha=Math.random()*0.3+0.05; this.vx=(Math.random()-0.5)*0.28; this.vy=(Math.random()-0.5)*0.28; this.c=COLORS[Math.floor(Math.random()*COLORS.length)]; }
    update(){ this.x+=this.vx; this.y+=this.vy; if(this.x<0||this.x>W||this.y<0||this.y>H) this.reset(); }
    draw(){ ctx.beginPath(); ctx.arc(this.x,this.y,this.r,0,Math.PI*2); ctx.fillStyle=this.c+this.alpha+')'; ctx.fill(); }
  }
  for(let i=0;i<65;i++) particles.push(new P());
  function loop(){ ctx.clearRect(0,0,W,H); particles.forEach(p=>{p.update();p.draw();}); requestAnimationFrame(loop); }
  loop();
})();

/* ── TOGGLE CARD with RIPPLE ── */
function toggleCard(id, e){
  const card = document.getElementById(id);
  if(e){
    const header = card.querySelector('.sm-card-header');
    const rect = header.getBoundingClientRect();
    const rip = document.createElement('span');
    rip.classList.add('ripple');
    const size = Math.max(rect.width, rect.height);
    rip.style.cssText = `width:${size}px;height:${size}px;left:${e.clientX-rect.left-size/2}px;top:${e.clientY-rect.top-size/2}px`;
    header.appendChild(rip);
    rip.addEventListener('animationend',()=>rip.remove());
  }
  card.classList.toggle('collapsed');
}

function expandAll(){ document.querySelectorAll('.sm-card').forEach(c=>c.classList.remove('collapsed')); }
function collapseAll(){ document.querySelectorAll('.sm-card').forEach(c=>c.classList.add('collapsed')); }

/* ── SCROLL REVEAL ── */
const revObs = new IntersectionObserver((entries)=>{
  entries.forEach(entry=>{
    if(entry.isIntersecting){
      const delay = parseInt(entry.target.dataset.delay||0);
      setTimeout(()=>entry.target.classList.add('in-view'), delay);
      revObs.unobserve(entry.target);
    }
  });
},{threshold:0.07});
document.querySelectorAll('.sm-card').forEach(c=>revObs.observe(c));

/* ── ANIMATED COUNTERS ── */
function animCount(el,target,dur=1400){
  const start=performance.now();
  const step=now=>{
    const pct=Math.min((now-start)/dur,1);
    const ease=1-Math.pow(1-pct,3);
    el.textContent=Math.round(ease*target);
    if(pct<1) requestAnimationFrame(step); else el.textContent=target;
  };
  requestAnimationFrame(step);
}
const cObs = new IntersectionObserver((entries)=>{
  if(entries[0].isIntersecting){
    document.querySelectorAll('.stat-num[data-target]').forEach(el=>animCount(el,parseInt(el.dataset.target)));
    cObs.disconnect();
  }
},{threshold:0.4});
cObs.observe(document.querySelector('.stats-bar'));

/* ── SCROLL TO TOP ── */
const sBtn = document.getElementById('scrollTopBtn');
window.addEventListener('scroll',()=>sBtn.classList.toggle('show',scrollY>350));
sBtn.addEventListener('click',()=>window.scrollTo({top:0,behavior:'smooth'}));

/* ── SEARCH ── */
const searchInput = document.getElementById('sitemapSearch');
const searchClear = document.getElementById('searchClear');

function highlight(text, q){
  if(!q) return text;
  const rx = new RegExp(`(${q.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')})`, 'gi');
  return text.replace(rx, '<mark>$1</mark>');
}

searchInput.addEventListener('input', function(){
  const q = this.value.trim().toLowerCase();
  searchClear.classList.toggle('visible', q.length>0);

  document.querySelectorAll('[data-searchable]').forEach(el=>{
    const txt = el.dataset.searchable.toLowerCase();
    const match = !q || txt.includes(q);
    el.style.display = match ? '' : 'none';
    const span = el.querySelector('.sm-link-text, .sm-loc-name, .sm-nav-pill span');
    if(span){
      if(!span.dataset.rawText) span.dataset.rawText = span.textContent;
      span.innerHTML = match && q ? highlight(span.dataset.rawText, q) : span.dataset.rawText;
    }
  });

  let any = false;
  document.querySelectorAll('[data-searchable]').forEach(el=>{ if(el.style.display!=='none') any=true; });
  document.getElementById('noResults').style.display = q && !any ? 'block' : 'none';

  if(q) document.querySelectorAll('.sm-card').forEach(card=>{
    const has = [...card.querySelectorAll('[data-searchable]')].some(el=>el.style.display!=='none');
    if(has) card.classList.remove('collapsed');
  });
});

searchClear.addEventListener('click',()=>{
  searchInput.value='';
  searchInput.dispatchEvent(new Event('input'));
  searchInput.focus();
});