// Shared behavior for every page: mobile nav + footer year + tiny helpers.
(function () {
  document.addEventListener('DOMContentLoaded', function () {
    var toggle = document.querySelector('[data-nav-toggle]');
    var links = document.querySelector('[data-nav-links]');
    if (toggle && links) {
      toggle.addEventListener('click', function () {
        links.classList.toggle('is-open');
      });
      links.querySelectorAll('a,button').forEach(function (el) {
        el.addEventListener('click', function () { links.classList.remove('is-open'); });
      });
    }
    document.querySelectorAll('[data-year]').forEach(function (el) {
      el.textContent = new Date().getFullYear();
    });

    // Blog article swipe navigation — swipe left for next, right for previous.
    // Purely additive to the click-based pager buttons already on the page;
    // this just gives the same navigation a touch gesture on mobile.
    var pager = document.querySelector('.article-pager');
    if (pager) {
      var touchStartX = null, touchStartY = null;
      var SWIPE_THRESHOLD = 60;
      document.addEventListener('touchstart', function (e) {
        if (!e.touches || !e.touches.length) return;
        touchStartX = e.touches[0].clientX;
        touchStartY = e.touches[0].clientY;
      }, { passive: true });
      document.addEventListener('touchend', function (e) {
        if (touchStartX === null || !e.changedTouches || !e.changedTouches.length) return;
        var dx = e.changedTouches[0].clientX - touchStartX;
        var dy = e.changedTouches[0].clientY - touchStartY;
        touchStartX = null;
        if (Math.abs(dx) < SWIPE_THRESHOLD || Math.abs(dx) < Math.abs(dy) * 1.5) return; // mostly-vertical scroll, ignore
        var target = dx < 0 ? pager.dataset.next : pager.dataset.prev;
        if (target) window.location.href = target;
      }, { passive: true });
    }

    // Sidebar tool search — filters links within each category and expands
    // any category with a match; collapses/hides categories with none.
    var sidebarSearch = document.getElementById('sidebar-search-input');
    if (sidebarSearch) {
      sidebarSearch.addEventListener('input', function () {
        var q = sidebarSearch.value.trim().toLowerCase();
        var anyVisible = false;
        document.querySelectorAll('.sidebar-cat').forEach(function (details) {
          var catHasMatch = false;
          details.querySelectorAll('.sidebar-tool-link').forEach(function (link) {
            var matches = !q || (link.dataset.toolName || '').indexOf(q) !== -1;
            link.style.display = matches ? '' : 'none';
            if (matches) catHasMatch = true;
          });
          details.style.display = catHasMatch ? '' : 'none';
          if (q && catHasMatch) details.open = true;
          if (catHasMatch) anyVisible = true;
        });
        var emptyMsg = document.getElementById('sidebar-empty-msg');
        if (emptyMsg) emptyMsg.style.display = anyVisible ? 'none' : 'block';
      });
    }

    // Back-to-top button — created here rather than added to every page's HTML,
    // so it appears site-wide from this one file. Shows once the page has been
    // scrolled a bit, hides again near the top.
    var backToTop = document.createElement('button');
    backToTop.id = 'back-to-top';
    backToTop.type = 'button';
    backToTop.setAttribute('aria-label', 'Back to top');
    backToTop.setAttribute('data-noprint', '');
    backToTop.innerHTML = '&#8593;';
    document.body.appendChild(backToTop);
    var toggleBackToTop = function () {
      backToTop.classList.toggle('is-visible', window.scrollY > 500);
    };
    window.addEventListener('scroll', toggleBackToTop, { passive: true });
    toggleBackToTop();
    backToTop.addEventListener('click', function () {
      window.scrollTo({ top: 0, behavior: 'smooth' });
    });

    // Blog article slider ("From the blog") — prev/next buttons scroll by
    // one card width; buttons disable at each end instead of just no-op'ing.
    var slider = document.getElementById('blog-slider');
    if (slider) {
      var prevBtn = document.getElementById('blog-slider-prev');
      var nextBtn = document.getElementById('blog-slider-next');
      var updateNav = function () {
        if (!prevBtn || !nextBtn) return;
        prevBtn.disabled = slider.scrollLeft <= 4;
        nextBtn.disabled = slider.scrollLeft >= slider.scrollWidth - slider.clientWidth - 4;
      };
      var cardWidth = function () {
        var card = slider.querySelector('.blog-slide-card');
        return card ? card.getBoundingClientRect().width + 16 : 280;
      };
      if (prevBtn) prevBtn.addEventListener('click', function () { slider.scrollBy({ left: -cardWidth(), behavior: 'smooth' }); });
      if (nextBtn) nextBtn.addEventListener('click', function () { slider.scrollBy({ left: cardWidth(), behavior: 'smooth' }); });
      slider.addEventListener('scroll', updateNav);
      updateNav();
    }
  });

  // Copy text to clipboard with a temporary "Copied!" label swap on the trigger element.
  window.crawlieCopy = function (text, btn) {
    var original = btn ? btn.textContent : null;
    var done = function (ok) {
      if (!btn) return;
      btn.textContent = ok ? 'Copied!' : 'Copy failed';
      setTimeout(function () { btn.textContent = original; }, 1500);
    };
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(text).then(function () { done(true); }, function () { done(false); });
    } else {
      try {
        var ta = document.createElement('textarea');
        ta.value = text; document.body.appendChild(ta); ta.select();
        document.execCommand('copy'); document.body.removeChild(ta);
        done(true);
      } catch (e) { done(false); }
    }
  };

  // Trigger a browser download of a text/blob payload.
  window.crawlieDownload = function (filename, content, mime) {
    var blob = new Blob([content], { type: mime || 'text/plain' });
    var url = URL.createObjectURL(blob);
    var a = document.createElement('a');
    a.href = url; a.download = filename;
    document.body.appendChild(a); a.click(); document.body.removeChild(a);
    setTimeout(function () { URL.revokeObjectURL(url); }, 2000);
  };

  // Wraps a raw code snippet (meta tags, JSON-LD, etc.) in a real, viewable HTML page.
  // Downloading the snippet by itself is invisible when opened: a file containing only
  // <meta>/<script type="application/ld+json"> tags has no visible <body> content, so a
  // browser shows a blank page even though the download "worked". This wraps it in a
  // documented page with a <pre> block so the content is always visible.
  window.crawlieDownloadSnippet = function (filename, code, label) {
    var esc = function (s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; };
    var html = '<!DOCTYPE html><html><head><meta charset="utf-8"><title>' + esc(label || 'Code snippet') + ' — Crawlie</title>' +
      '<style>body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;background:#f5f3fb;color:#1b1430;margin:0;padding:40px;}' +
      '.wrap{max-width:760px;margin:0 auto;background:#fff;border:1px solid #ece7f7;border-radius:16px;padding:32px;}' +
      'h1{font-size:20px;margin:0 0 6px;} p{color:#6b6580;font-size:14px;line-height:1.5;margin:0 0 20px;}' +
      'pre{background:#f5f3fb;border:1px solid #ece7f7;border-radius:12px;padding:18px;overflow:auto;' +
      'font-family:"Space Mono",Consolas,monospace;font-size:13px;line-height:1.7;white-space:pre-wrap;word-break:break-word;margin:0;}</style></head><body>' +
      '<div class="wrap"><h1>' + esc(label || 'Code snippet') + '</h1>' +
      '<p>Generated by Crawlie. Copy the code below and paste it into your page\u2019s <code>&lt;head&gt;</code>.</p>' +
      '<pre>' + esc(code) + '</pre></div></body></html>';
    window.crawlieDownload(filename, html, 'text/html');
  };
})();


  // Auto-focus audit input if hash is #audit
  window.addEventListener("load", function() {
    if (window.location.hash === "#audit") {
      var input = document.getElementById("audit-url");
      if (input) {
        setTimeout(function() { input.focus(); }, 300);
      }
    }
  });

