// ─────────────────────────────────────────────────────────────
// deck.js — Bifrost Advisory Board presentation runtime
//
//   1. Builds the bottom dot-nav from the slides in the DOM (one
//      dot per slide, Danish label from data-label).
//   2. Scroll-snap is CSS-driven; here we keep the active dot +
//      slide counter in sync via an IntersectionObserver, and
//      smooth-scroll to a slide when its dot is clicked.
//   3. Adds .in-view to the active slide so its .reveal children
//      animate in.
//   4. Keyboard: ↑/↓, PageUp/PageDown, Home/End jump between slides.
//
// No external libraries; no inline scripts (CSP-friendly).
// ─────────────────────────────────────────────────────────────
(function () {
  'use strict';

  // Mark that JS is live — the .reveal hiding rule is gated on this, so a
  // failed/blocked script leaves the deck fully visible rather than blank.
  document.documentElement.classList.add('js');

  const deck = document.getElementById('deck');
  const nav = document.getElementById('dot-nav');
  const counter = document.getElementById('counter-now');
  const counterTotal = document.getElementById('counter-total');
  const slides = Array.from(document.querySelectorAll('.slide'));
  if (!deck || !nav || !slides.length) return;

  const pad = (n) => String(n).padStart(2, '0');

  // Keep the "/ NN" total in sync with however many slides exist.
  if (counterTotal) counterTotal.textContent = pad(slides.length);

  // ─── Build the dot-nav ───────────────────────────────────────
  const dots = slides.map((slide, i) => {
    const btn = document.createElement('button');
    btn.className = 'dot-btn';
    btn.type = 'button';
    btn.dataset.index = String(i);
    btn.setAttribute('aria-label', `${i + 1}. ${slide.dataset.label || ''}`.trim());

    const label = document.createElement('span');
    label.className = 'label';
    label.textContent = slide.dataset.label || `Slide ${i + 1}`;

    const dot = document.createElement('span');
    dot.className = 'dot';

    btn.appendChild(label);
    btn.appendChild(dot);
    btn.addEventListener('click', () => goTo(i));
    nav.appendChild(btn);
    return btn;
  });

  let activeIndex = 0;

  function setActive(i) {
    if (i === activeIndex) return;
    activeIndex = i;
    dots.forEach((d, j) => d.classList.toggle('is-active', j === i));
    if (counter) counter.textContent = pad(i + 1);
  }

  function goTo(i) {
    const target = slides[i];
    if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }

  // ─── Active-slide tracking + reveal ──────────────────────────
  const io = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      const i = slides.indexOf(entry.target);
      if (entry.isIntersecting) {
        entry.target.classList.add('in-view');
        // A slide counts as "active" once it owns most of the viewport.
        if (entry.intersectionRatio >= 0.5) setActive(i);
      }
    });
  }, { root: deck, threshold: [0, 0.5, 0.9] });

  slides.forEach((s) => io.observe(s));

  // First slide is visible immediately on load.
  slides[0].classList.add('in-view');
  setActive(0);
  if (counter) counter.textContent = pad(1);

  // ─── Keyboard navigation ─────────────────────────────────────
  window.addEventListener('keydown', (e) => {
    // Ignore when a control/input has focus (none here, but future-proof).
    const tag = (e.target && e.target.tagName) || '';
    if (tag === 'INPUT' || tag === 'TEXTAREA') return;

    switch (e.key) {
      case 'ArrowDown':
      case 'PageDown':
      case ' ':
        e.preventDefault();
        goTo(Math.min(activeIndex + 1, slides.length - 1));
        break;
      case 'ArrowUp':
      case 'PageUp':
        e.preventDefault();
        goTo(Math.max(activeIndex - 1, 0));
        break;
      case 'Home':
        e.preventDefault();
        goTo(0);
        break;
      case 'End':
        e.preventDefault();
        goTo(slides.length - 1);
        break;
    }
  });
})();
