(() => {
  "use strict";

  const articles = window.after2AMManualArticles || [];
  const pageID = document.body.dataset.page || "home";
  const root = document.body.dataset.root || ".";
  const currentIndex = Math.max(
    0,
    articles.findIndex((article) => article.id === pageID),
  );

  const urlFor = (path) => `${root}/${path}`;
  const escapeHTML = (value) =>
    String(value)
      .replaceAll("&", "&amp;")
      .replaceAll("<", "&lt;")
      .replaceAll(">", "&gt;")
      .replaceAll('"', "&quot;")
      .replaceAll("'", "&#039;");

  const grouped = articles.reduce((result, article) => {
    const section = article.section || "Guide";
    if (!result.has(section)) result.set(section, []);
    result.get(section).push(article);
    return result;
  }, new Map());

  const header = document.querySelector("[data-site-header]");
  if (header) {
    header.className = "site-header";
    header.innerHTML = `
      <div class="topbar">
        <button class="icon-button nav-toggle" type="button"
          data-nav-toggle aria-label="Open table of contents" aria-expanded="false">
          <span aria-hidden="true"></span><span aria-hidden="true"></span><span aria-hidden="true"></span>
        </button>
        <a class="brand" href="${urlFor("index.html")}">
          <img src="${urlFor("assets/sidebar-clapperboard.png")}" alt="" width="40" height="40">
          <span><strong>AFTER2AM</strong><small>Studio User Manual</small></span>
        </a>
        <button class="search-button" type="button" data-search-open>
          <span aria-hidden="true">⌕</span>
          <span>Search the manual</span>
          <kbd>/</kbd>
        </button>
        <span class="manual-version">0.1.1 · build 9</span>
      </div>`;
  }

  const navigation = document.querySelector("[data-site-nav]");
  if (navigation) {
    navigation.className = "site-navigation";
    navigation.setAttribute("aria-label", "Manual");
    navigation.innerHTML = `
      <div class="nav-heading">
        <span>Contents</span>
        <button class="icon-button nav-close" type="button" data-nav-close aria-label="Close contents">×</button>
      </div>
      ${Array.from(grouped.entries())
        .map(
          ([section, items]) => `
            <section class="nav-group">
              <h2>${escapeHTML(section)}</h2>
              <ul>
                ${items
                  .map(
                    (item) => `
                      <li>
                        <a href="${urlFor(item.path)}"
                           ${item.id === pageID ? 'aria-current="page"' : ""}>
                          ${escapeHTML(item.title)}
                        </a>
                      </li>`,
                  )
                  .join("")}
              </ul>
            </section>`,
        )
        .join("")}
      <div class="nav-promise">
        <strong>Offline by design</strong>
        <span>This manual is bundled with the app and uses no analytics, remote fonts, or trackers.</span>
      </div>`;
  }

  const backdrop = document.querySelector("[data-nav-backdrop]");
  const navToggle = document.querySelector("[data-nav-toggle]");
  const setNavigationOpen = (isOpen) => {
    document.body.classList.toggle("nav-open", isOpen);
    navToggle?.setAttribute("aria-expanded", String(isOpen));
  };
  navToggle?.addEventListener("click", () => setNavigationOpen(true));
  document
    .querySelector("[data-nav-close]")
    ?.addEventListener("click", () => setNavigationOpen(false));
  backdrop?.addEventListener("click", () => setNavigationOpen(false));

  const toc = document.querySelector("[data-page-toc]");
  if (toc) {
    const headings = Array.from(
      document.querySelectorAll("main article h2[id], main article h3[id]"),
    );
    if (headings.length) {
      toc.className = "page-toc";
      toc.setAttribute("aria-label", "On this page");
      toc.innerHTML = `
        <strong>On this page</strong>
        <ol>
          ${headings
            .map(
              (heading) => `
                <li class="${heading.tagName === "H3" ? "toc-subitem" : ""}">
                  <a href="#${encodeURIComponent(heading.id)}">${escapeHTML(heading.textContent)}</a>
                </li>`,
            )
            .join("")}
        </ol>`;
    }
  }

  const pagination = document.querySelector("[data-article-pagination]");
  if (pagination && pageID !== "home") {
    const previous = currentIndex > 1 ? articles[currentIndex - 1] : articles[0];
    const next =
      currentIndex < articles.length - 1 ? articles[currentIndex + 1] : articles[0];
    pagination.className = "article-pagination";
    pagination.setAttribute("aria-label", "Previous and next articles");
    pagination.innerHTML = `
      <a href="${urlFor(previous.path)}">
        <span>← Previous</span><strong>${escapeHTML(previous.title)}</strong>
      </a>
      <a class="next" href="${urlFor(next.path)}">
        <span>Next →</span><strong>${escapeHTML(next.title)}</strong>
      </a>`;
  }

  const footer = document.querySelector("[data-site-footer]");
  if (footer) {
    footer.className = "site-footer";
    footer.innerHTML = `
      <p><strong>After2AM Studio</strong> · Production should flow, even after 2 AM.</p>
      <p>Manual for version 0.1.1, build 9 · 28 July 2026</p>`;
  }

  const searchHost = document.querySelector("[data-search]");
  if (searchHost) {
    searchHost.innerHTML = `
      <dialog class="search-dialog" data-search-dialog aria-labelledby="search-title">
        <form method="dialog" class="search-shell">
          <div class="search-topline">
            <div>
              <span class="eyebrow">Manual search</span>
              <h2 id="search-title">What do you need?</h2>
            </div>
            <button class="icon-button search-close" value="close" aria-label="Close search">×</button>
          </div>
          <label class="search-field">
            <span aria-hidden="true">⌕</span>
            <span class="visually-hidden">Search articles</span>
            <input type="search" data-search-input placeholder="Try “archive”, “script”, or “publish”…"
              autocomplete="off" spellcheck="false">
          </label>
          <div class="search-results" data-search-results aria-live="polite"></div>
          <p class="search-hint"><kbd>↑</kbd><kbd>↓</kbd> move · <kbd>↵</kbd> open · <kbd>esc</kbd> close</p>
        </form>
      </dialog>`;
  }

  const dialog = document.querySelector("[data-search-dialog]");
  const input = document.querySelector("[data-search-input]");
  const results = document.querySelector("[data-search-results]");

  const renderResults = (query = "") => {
    if (!results) return;
    const terms = query
      .trim()
      .toLocaleLowerCase()
      .split(/\s+/)
      .filter(Boolean);
    const ranked = articles
      .map((article) => {
        const title = article.title.toLocaleLowerCase();
        const haystack =
          `${article.title} ${article.summary} ${article.keywords} ${article.section}`.toLocaleLowerCase();
        const score = terms.reduce((total, term) => {
          if (!haystack.includes(term)) return total - 20;
          return total + (title.includes(term) ? 10 : 3);
        }, 0);
        return { article, score };
      })
      .filter(({ score }) => !terms.length || score >= 0)
      .sort((a, b) => b.score - a.score)
      .slice(0, terms.length ? 7 : 5);

    results.innerHTML = ranked.length
      ? ranked
          .map(
            ({ article }) => `
              <a href="${urlFor(article.path)}">
                <span class="result-section">${escapeHTML(article.section)}</span>
                <strong>${escapeHTML(article.title)}</strong>
                <span>${escapeHTML(article.summary)}</span>
              </a>`,
          )
          .join("")
      : `<p class="empty-search"><strong>No article matched that search.</strong><br>Try a feature name or a shorter phrase.</p>`;
  };

  const openSearch = () => {
    if (!dialog) return;
    renderResults("");
    dialog.showModal();
    requestAnimationFrame(() => input?.focus());
  };
  document
    .querySelectorAll("[data-search-open]")
    .forEach((button) => button.addEventListener("click", openSearch));
  input?.addEventListener("input", (event) => renderResults(event.target.value));

  document.addEventListener("keydown", (event) => {
    const target = event.target;
    const isTyping =
      target instanceof HTMLInputElement ||
      target instanceof HTMLTextAreaElement ||
      target?.isContentEditable;
    if (event.key === "/" && !isTyping && !dialog?.open) {
      event.preventDefault();
      openSearch();
    }
    if (event.key === "Escape") setNavigationOpen(false);
  });

  dialog?.addEventListener("click", (event) => {
    if (event.target === dialog) dialog.close();
  });
})();
