<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Verses &mdash; Poetry Showcase</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='12' fill='%230f0e0c'/%3E%3Ctext x='32' y='44' font-family='Georgia,serif' font-style='italic' font-size='34' fill='%23f4ede2' text-anchor='middle'%3EV%3C/text%3E%3C/svg%3E">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;1,400&family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Jost:wght@400;500&display=swap" rel="stylesheet">
<style>
  body { margin: 0; background: #0f0e0c; color: #f4ede2; }
  * { box-sizing: border-box; }
  ::selection { background: #f4ede2; color: #0f0e0c; }
  @keyframes riseIn { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: translateY(0); } }
  .poem-body, .reader-scroll { scrollbar-width: none; }
  .poem-body::-webkit-scrollbar, .reader-scroll::-webkit-scrollbar { display: none; }
</style>
</head>
<body>

<div style="position:relative; width:100%; height:100vh; overflow:hidden; font-family:'Jost',sans-serif;">

  <div id="bg-back" style="position:absolute; inset:0; background:linear-gradient(160deg, #1a1e2b 0%, #0f0e0c 70%); transition:opacity 0.05s;"></div>
  <div id="bg-front" style="position:absolute; inset:0; background:linear-gradient(160deg, #1a1e2b 0%, #0f0e0c 70%); opacity:0; transition:opacity 1.4s ease;"></div>
  <div style="position:absolute; inset:0; background:radial-gradient(ellipse at 50% 30%, rgba(0,0,0,0) 0%, rgba(0,0,0,0.45) 100%);"></div>

  <header style="position:fixed; top:0; left:0; right:0; z-index:20; display:flex; align-items:center; gap:clamp(10px,2vw,28px); padding:clamp(12px,2vw,20px) clamp(16px,3vw,40px); backdrop-filter:blur(10px); background:linear-gradient(to bottom, rgba(15,14,12,0.65), rgba(15,14,12,0)); flex-wrap:wrap;">
    <div style="display:flex; flex-direction:column; justify-content:center;">
      <div style="font-family:'Playfair Display',serif; font-size:clamp(18px,2.2vw,24px); letter-spacing:0.02em; white-space:nowrap; line-height:1.2;">Verses</div>
      <div style="font-family:'Cormorant Garamond',serif; font-size:clamp(13px,1.4vw,15px); opacity:0.8; font-style:italic; white-space:nowrap; line-height:1.2;">where emotions become words</div>
    </div>

    <div style="flex:1; display:flex; align-items:center; gap:10px; min-width:200px; max-width:380px;">
      <div style="flex:1; display:flex; align-items:center; gap:8px; background:rgba(244,237,226,0.08); border:1px solid rgba(244,237,226,0.18); border-radius:999px; padding:8px 16px;">
        <span style="opacity:0.6; font-size:14px;">&#9906;</span>
        <input id="search-input" placeholder="search title, poet, or a line" style="background:transparent; border:none; outline:none; color:#f4ede2; font-family:'Jost',sans-serif; font-size:clamp(13px,1.4vw,14px); width:100%;" />
      </div>
      <a href="/verses/admin/login" title="Admin sign in" aria-label="Admin sign in" style="flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center; width:38px; height:38px; border-radius:999px; border:1px solid rgba(244,237,226,0.18); background:rgba(244,237,226,0.06); color:#f4ede2; text-decoration:none; transition:background 0.2s;">
        <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
      </a>
    </div>

    <div id="tag-list" style="display:flex; gap:6px; flex-wrap:wrap; padding:2px 0; flex:1 1 auto;"></div>
  </header>

  <div id="scroll-container" style="position:relative; z-index:10; width:100%; height:100%; overflow-y:auto; overflow-x:hidden; scroll-snap-type:y mandatory; scroll-behavior:smooth;">
    <div id="poems-container"></div>

    <section id="empty-state" style="display:none; width:100%; height:100vh; align-items:center; justify-content:center; text-align:center; padding:0 20px;">
      <div style="font-family:'Cormorant Garamond',serif; font-size:clamp(18px,2.4vw,24px); opacity:0.7; font-style:italic;">No poems found &mdash; try another word or theme.</div>
    </section>
  </div>

  <div id="dots-container" style="position:fixed; right:clamp(10px,2vw,22px); top:50%; transform:translateY(-50%); z-index:20; display:flex; flex-direction:column; gap:7px;"></div>

  <div id="reader" style="display:none; position:fixed; inset:0; z-index:40; animation:riseIn 0.4s ease;">
    <div id="reader-bg" style="position:absolute; inset:0; background:linear-gradient(160deg, #1a1e2b 0%, #0f0e0c 70%);"></div>
    <div style="position:absolute; inset:0; background:radial-gradient(ellipse at 50% 30%, rgba(0,0,0,0) 0%, rgba(0,0,0,0.5) 100%);"></div>
    <button id="reader-close" title="Close" aria-label="Close" style="position:absolute; top:22px; right:26px; z-index:3; background:rgba(244,237,226,0.1); border:1px solid rgba(244,237,226,0.3); color:#f4ede2; width:40px; height:40px; border-radius:50%; font-size:17px; cursor:pointer;">&times;</button>
    <div class="reader-scroll" style="position:relative; z-index:2; height:100%; overflow-y:auto; padding:clamp(70px,10vh,110px) clamp(20px,6vw,60px) clamp(60px,10vh,110px);">
      <article style="width:min(680px,92vw); margin:0 auto;">
        <h1 id="reader-title" style="font-family:'Playfair Display',serif; font-weight:600; font-style:italic; font-size:clamp(28px,4.4vw,46px); line-height:1.15; margin:0 0 14px 0; color:#f4ede2;"></h1>
        <div id="reader-author" style="font-family:'Jost',sans-serif; font-size:clamp(13px,1.5vw,15px); letter-spacing:0.04em; opacity:0.65; margin-bottom:40px; color:#f4ede2;"></div>
        <div id="reader-body" style="font-family:'Cormorant Garamond',serif; font-size:clamp(18px,2.2vw,23px); line-height:1.8; white-space:pre-line; color:rgba(244,237,226,0.94);"></div>
      </article>
    </div>
  </div>

</div>

<script>
(function () {
  var THEME_GRAD = {
    nature: "linear-gradient(160deg, #1c2b1f 0%, #0f0e0c 70%)",
    hope:   "linear-gradient(160deg, #2b2412 0%, #0f0e0c 70%)",
    loss:   "linear-gradient(160deg, #1a1e2b 0%, #0f0e0c 70%)",
    joy:    "linear-gradient(160deg, #2b1c1a 0%, #0f0e0c 70%)",
    love:   "linear-gradient(160deg, #2b141e 0%, #0f0e0c 70%)",
    dreams: "linear-gradient(160deg, #1a1a2b 0%, #0f0e0c 70%)",
    seasons: "linear-gradient(160deg, #1a1e2b 0%, #0f0e0c 70%)",
    solitude: "linear-gradient(160deg, #1a1a2b 0%, #0f0e0c 70%)"
  };
  var DEFAULT_GRAD = THEME_GRAD.loss;
  var ALL_TAGS = []; // loaded from the DB via /verses/api/v1/tags

  var allPoems = [];
  var displayPoems = [];
  var activeTag = null;
  var query = "";
  var currentBg = null;
  var showingFront = false;
  var currentEditor = null;

  var poemsContainer = document.getElementById("poems-container");
  var emptyState = document.getElementById("empty-state");
  var dotsContainer = document.getElementById("dots-container");
  var tagListEl = document.getElementById("tag-list");
  var searchInput = document.getElementById("search-input");
  var scrollContainer = document.getElementById("scroll-container");
  var bgBack = document.getElementById("bg-back");
  var bgFront = document.getElementById("bg-front");
  var reader = document.getElementById("reader");
  var readerBg = document.getElementById("reader-bg");
  var readerTitle = document.getElementById("reader-title");
  var readerAuthor = document.getElementById("reader-author");
  var readerBody = document.getElementById("reader-body");

  var observer = null;

  // Full-screen reader for long poems (opened from "Continue reading").
  function openReader(poem) {
    if (poem.title) {
      readerTitle.textContent = poem.title;
      readerTitle.style.display = "block";
    } else {
      readerTitle.style.display = "none";
    }
    readerAuthor.textContent = poem.author || "";
    readerBody.textContent = poem.body || "";
    readerBg.style.background = bgFor(poem);
    reader.style.display = "block";
  }
  function closeReader() {
    reader.style.display = "none";
  }

  function gradFor(theme) {
    return THEME_GRAD[theme] || DEFAULT_GRAD;
  }

  // Background for a poem: its cover image if it has one, otherwise the theme
  // gradient. The dark base + radial overlay keep poem text readable over images.
  function bgFor(poem) {
    if (poem.coverImageUrl) {
      var safe = String(poem.coverImageUrl).replace(/["'()\\\s]/g, "");
      if (safe) return "#0f0e0c url('" + safe + "') center center / cover no-repeat";
    }
    return gradFor(poem.theme);
  }

  function crossfadeTo(bg) {
    if (bg === currentBg) return;
    currentBg = bg;
    if (showingFront) {
      // front is currently visible; put new background on back, hide front
      bgBack.style.background = bg;
      bgFront.style.opacity = "0";
      showingFront = false;
    } else {
      bgFront.style.background = bg;
      // force reflow so the opacity transition triggers
      void bgFront.offsetWidth;
      bgFront.style.opacity = "1";
      showingFront = true;
    }
  }

  function escapeHtml(s) {
    return String(s == null ? "" : s).replace(/[&<>"']/g, function (c) {
      return { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c];
    });
  }

  function renderTags() {
    tagListEl.innerHTML = "";
    ALL_TAGS.forEach(function (tag) {
      var isActive = activeTag === tag;
      var btn = document.createElement("button");
      btn.textContent = tag;
      btn.style.cssText = "flex:0 0 auto; padding:7px 15px; border-radius:999px; font-family:'Jost',sans-serif; font-size:12.5px; letter-spacing:0.03em; cursor:pointer; transition:all 0.2s; border:1px solid " +
        (isActive ? "#f4ede2" : "rgba(244,237,226,0.25)") + "; background:" +
        (isActive ? "#f4ede2" : "transparent") + "; color:" +
        (isActive ? "#0f0e0c" : "rgba(244,237,226,0.75)") + ";";
      btn.addEventListener("click", function () {
        activeTag = activeTag === tag ? null : tag;
        renderTags();
        applyFilter();
      });
      tagListEl.appendChild(btn);
    });
  }

  function matchesFilter(poem) {
    var tagOk = !activeTag || (poem.tags || []).indexOf(activeTag) !== -1;
    if (!tagOk) return false;
    if (!query) return true;
    var q = query.toLowerCase();
    var title = (poem.title || "").toLowerCase();
    var author = (poem.author || "").toLowerCase();
    var body = (poem.body || "").toLowerCase();
    return title.indexOf(q) !== -1 || author.indexOf(q) !== -1 || body.indexOf(q) !== -1;
  }

  function applyFilter() {
    displayPoems = allPoems.filter(matchesFilter);
    renderPoems();
  }

  function bodySizeFor(body) {
    return (body || "").length > 260 ? "clamp(16px,2vw,20px)" : "clamp(19px,2.6vw,26px)";
  }

  function renderPoems() {
    if (observer) {
      observer.disconnect();
      observer = null;
    }
    poemsContainer.innerHTML = "";
    dotsContainer.innerHTML = "";

    var currentEmptyState = emptyState || document.getElementById("empty-state");
    if (!displayPoems.length && !currentEditor) {
      if (currentEmptyState) currentEmptyState.style.display = "flex";
      var msgEl = currentEmptyState ? currentEmptyState.querySelector("div") : null;
      if (msgEl) {
        msgEl.textContent = (query || activeTag) ? "No poems found — try another word or theme." : "No poems have been published yet.";
      }
      return;
    }
    if (currentEmptyState) currentEmptyState.style.display = "none";

    if (currentEditor) {
      var edSection = document.createElement("section");
      edSection.setAttribute("data-poem-idx", "editor");
      edSection.setAttribute("data-bg", THEME_GRAD.solitude);
      edSection.style.cssText = "scroll-snap-align:start; scroll-snap-stop:always; width:100%; min-height:100vh; display:flex; align-items:center; justify-content:center; padding:clamp(140px,18vh,180px) clamp(20px,6vw,60px) clamp(40px,6vh,60px);";

      var edArticle = document.createElement("article");
      edArticle.className = "poem-body";
      edArticle.style.cssText = "width:min(680px,92vw); max-height:calc(100vh - clamp(150px,16vh,200px)); overflow-y:auto; opacity:0; transform:translateY(28px); transition:opacity 0.9s ease, transform 0.9s ease; text-align:center; padding-right:14px;";

      var edH1 = document.createElement("h1");
      edH1.style.cssText = "font-family:'Playfair Display',serif; font-weight:600; font-style:italic; font-size:clamp(32px,5vw,50px); line-height:1.15; margin:0 0 16px 0; color:#f4ede2;";
      edH1.textContent = currentEditor.displayName || "Poet";

      var edBio = document.createElement("div");
      edBio.style.cssText = "font-family:'Jost',sans-serif; font-size:clamp(15px,1.8vw,18px); opacity:0.8; margin-bottom:28px; line-height:1.6; max-width:500px; margin-left:auto; margin-right:auto;";
      edBio.textContent = currentEditor.bio || "";

      edArticle.appendChild(edH1);
      if (currentEditor.bio) edArticle.appendChild(edBio);

      if (currentEditor.socialLinks) {
         var socialWrap = document.createElement("div");
         socialWrap.style.cssText = "display:flex; gap:12px; justify-content:center; flex-wrap:wrap;";
         var map = currentEditor.socialLinks;
         var icons = { INSTAGRAM: "Instagram", YOUTUBE: "YouTube", TWITTER: "Twitter/X", FACEBOOK: "Facebook", WEBSITE: "Website" };
         for (var k in map) {
            if (map[k]) {
               var a = document.createElement("a");
               a.href = map[k];
               a.target = "_blank";
               a.style.cssText = "display:inline-flex; align-items:center; padding:8px 16px; border-radius:999px; border:1px solid rgba(244,237,226,0.3); color:#f4ede2; text-decoration:none; font-size:13.5px; opacity:0.85; transition:all 0.2s;";
               a.textContent = icons[k] || k;
               socialWrap.appendChild(a);
            }
         }
         if (socialWrap.children.length > 0) edArticle.appendChild(socialWrap);
      }

      edSection.appendChild(edArticle);
      poemsContainer.appendChild(edSection);

      var edDot = document.createElement("div");
      edDot.setAttribute("data-dot-idx", "editor");
      edDot.style.cssText = "width:7px; height:7px; border-radius:50%; background:rgba(244,237,226,0.3); cursor:pointer; transition:all 0.3s; margin-bottom:8px;";
      edDot.addEventListener("click", function () {
        edSection.scrollIntoView({ behavior: "smooth", block: "start" });
      });
      dotsContainer.appendChild(edDot);

      if (displayPoems.length === 0) {
        var emptyPoemSection = document.createElement("section");
        emptyPoemSection.setAttribute("data-poem-idx", "empty");
        emptyPoemSection.setAttribute("data-bg", THEME_GRAD.solitude);
        emptyPoemSection.style.cssText = "scroll-snap-align:start; scroll-snap-stop:always; width:100%; min-height:100vh; display:flex; align-items:center; justify-content:center; padding:clamp(140px,18vh,180px) clamp(20px,6vw,60px) clamp(40px,6vh,60px); text-align:center;";

        var emptyArticle = document.createElement("article");
        emptyArticle.className = "poem-body";
        emptyArticle.style.cssText = "width:min(680px,92vw); max-height:calc(100vh - clamp(150px,16vh,200px)); overflow-y:auto; opacity:0; transform:translateY(28px); transition:opacity 0.9s ease, transform 0.9s ease;";

        var msg = document.createElement("div");
        msg.style.cssText = "font-family:'Cormorant Garamond',serif; font-size:clamp(18px,2.4vw,24px); opacity:0.7; font-style:italic;";
        msg.textContent = "This poet hasn't published any pieces yet.";

        emptyArticle.appendChild(msg);
        emptyPoemSection.appendChild(emptyArticle);
        poemsContainer.appendChild(emptyPoemSection);

        var emptyDot = document.createElement("div");
        emptyDot.setAttribute("data-dot-idx", "empty");
        emptyDot.style.cssText = "width:7px; height:7px; border-radius:50%; background:rgba(244,237,226,0.3); cursor:pointer; transition:all 0.3s;";
        emptyDot.addEventListener("click", function () {
          emptyPoemSection.scrollIntoView({ behavior: "smooth", block: "start" });
        });
        dotsContainer.appendChild(emptyDot);
      }
    }

    displayPoems.forEach(function (poem, idx) {
      var section = document.createElement("section");
      section.setAttribute("data-poem-idx", idx);
      section.setAttribute("data-bg", bgFor(poem));
      section.style.cssText = "scroll-snap-align:start; scroll-snap-stop:always; width:100%; min-height:100vh; display:flex; align-items:center; justify-content:center; padding:clamp(140px,18vh,180px) clamp(20px,6vw,60px) clamp(40px,6vh,60px);";

      var article = document.createElement("article");
      article.className = "poem-body";
      article.style.cssText = "width:min(680px,92vw); max-height:calc(100vh - clamp(150px,16vh,200px)); overflow:hidden; opacity:0; transform:translateY(28px); transition:opacity 0.9s ease, transform 0.9s ease;";

      var chipsWrap = document.createElement("div");
      chipsWrap.style.cssText = "display:flex; gap:8px; margin-bottom:18px; flex-wrap:wrap;";
      (poem.tags || []).forEach(function (t) {
        var chip = document.createElement("span");
        chip.textContent = t;
        chip.style.cssText = "font-size:11px; letter-spacing:0.08em; text-transform:uppercase; padding:4px 11px; border-radius:999px; border:1px solid rgba(244,237,226,0.3); color:rgba(244,237,226,0.75);";
        chipsWrap.appendChild(chip);
      });

      var h1 = document.createElement("h1");
      h1.style.cssText = "font-family:'Playfair Display',serif; font-weight:600; font-style:italic; font-size:clamp(28px,4.4vw,46px); line-height:1.15; margin:0 0 14px 0; text-wrap:pretty;";
      if (poem.title) {
        h1.textContent = poem.title;
      } else {
        h1.style.display = "none";
      }

      var authorEl;
      if (poem.authorSlug) {
        authorEl = document.createElement("a");
        authorEl.href = "/verses/" + poem.authorSlug;
        authorEl.style.cssText = "font-family:'Jost',sans-serif; font-size:clamp(13px,1.5vw,15px); letter-spacing:0.04em; opacity:0.65; margin-bottom:36px; display:inline-block; color:#f4ede2; text-decoration:none; transition:opacity 0.2s;";
        authorEl.addEventListener("mouseover", function() { this.style.opacity = "0.85"; });
        authorEl.addEventListener("mouseout", function() { this.style.opacity = "0.65"; });
      } else {
        authorEl = document.createElement("div");
        authorEl.style.cssText = "font-family:'Jost',sans-serif; font-size:clamp(13px,1.5vw,15px); letter-spacing:0.04em; opacity:0.65; margin-bottom:36px;";
      }
      authorEl.textContent = poem.author || "";

      // Long poems are truncated to a preview with a fade; a reader modal shows the rest.
      var lines = (poem.body || "").split("\n");
      var isLong = lines.length > 14;
      var shownBody = isLong ? lines.slice(0, 10).join("\n") : (poem.body || "");
      var bodyMask = isLong ? "linear-gradient(to bottom, black 55%, transparent 100%)" : "none";

      var bodyEl = document.createElement("div");
      bodyEl.style.cssText = "font-family:'Cormorant Garamond',serif; font-size:" + bodySizeFor(poem.body) + "; line-height:1.75; white-space:pre-line; color:rgba(244,237,226,0.94); text-wrap:pretty; mask-image:" + bodyMask + "; -webkit-mask-image:" + bodyMask + ";";
      bodyEl.textContent = shownBody;

      article.appendChild(chipsWrap);
      article.appendChild(h1);
      article.appendChild(authorEl);
      article.appendChild(bodyEl);
      if (isLong) {
        var moreBtn = document.createElement("button");
        moreBtn.innerHTML = "Continue reading &rarr;";
        moreBtn.style.cssText = "margin-top:22px; padding:11px 24px; border-radius:999px; background:rgba(244,237,226,0.08); border:1px solid rgba(244,237,226,0.3); color:#f4ede2; font-family:'Jost',sans-serif; font-size:13px; letter-spacing:0.04em; cursor:pointer;";
        moreBtn.addEventListener("click", (function (pm) { return function () { openReader(pm); }; })(poem));
        article.appendChild(moreBtn);
      }
      section.appendChild(article);
      poemsContainer.appendChild(section);

      var dot = document.createElement("div");
      dot.setAttribute("data-dot-idx", idx);
      dot.style.cssText = "width:7px; height:7px; border-radius:50%; background:rgba(244,237,226,0.3); cursor:pointer; transition:all 0.3s;";
      dot.addEventListener("click", function () {
        section.scrollIntoView({ behavior: "smooth", block: "start" });
      });
      dotsContainer.appendChild(dot);
    });

    setupObserver();

    // Initialize background + active dot for the first section without waiting for scroll.
    var firstSection = poemsContainer ? poemsContainer.querySelector("section") : null;
    if (firstSection) {
      var firstBg = firstSection.getAttribute("data-bg");
      showingFront = false;
      if (bgBack) bgBack.style.background = firstBg;
      if (bgFront) bgFront.style.opacity = "0";
      currentBg = firstBg;
      var firstArticle = firstSection.querySelector("article");
      if (firstArticle) {
        firstArticle.style.opacity = "1";
        firstArticle.style.transform = "translateY(0)";
      }
      setActiveDot(firstSection.getAttribute("data-poem-idx"));
    }
  }

  function setActiveDot(activeIdx) {
    var activeStr = String(activeIdx);
    var dots = dotsContainer.querySelectorAll("[data-dot-idx]");
    dots.forEach(function (dot) {
      var idx = String(dot.getAttribute("data-dot-idx"));
      if (idx === activeStr) {
        dot.style.width = "9px";
        dot.style.height = "9px";
        dot.style.background = "#f4ede2";
      } else {
        dot.style.width = "7px";
        dot.style.height = "7px";
        dot.style.background = "rgba(244,237,226,0.3)";
      }
    });
  }

  function setupObserver() {
    var sections = poemsContainer.querySelectorAll("section[data-poem-idx]");
    if (!sections.length) return;

    observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        var article = entry.target.querySelector("article");
        if (entry.isIntersecting) {
          article.style.opacity = "1";
          article.style.transform = "translateY(0)";
          var idx = entry.target.getAttribute("data-poem-idx");
          crossfadeTo(entry.target.getAttribute("data-bg"));
          setActiveDot(idx);
        }
      });
    }, { root: scrollContainer, threshold: 0.35 });

    sections.forEach(function (s) { observer.observe(s); });
  }

  // A poet's vanity URL is /verses/{slug}; the bare showcase is /verses. When a
  // slug is present we load only that editor's poems instead of the whole feed.
  function poetSlugFromUrl() {
    var parts = location.pathname.split("/").filter(Boolean); // ["verses", "<slug>"?]
    return (parts.length >= 2 && parts[0] === "verses") ? decodeURIComponent(parts[1]) : null;
  }

  function toPoemView(p) {
    return {
      title: p.title,
      contentType: p.contentType,
      author: p.authorName,
      authorSlug: p.authorSlug,
      body: p.body,
      tags: p.tags || [],
      theme: p.theme,
      coverImageUrl: p.coverImageUrl
    };
  }

  function loadPoems() {
    var slug = poetSlugFromUrl();
    var url = slug ? "/verses/api/v1/poets/" + encodeURIComponent(slug) : "/verses/api/v1/poems";
    fetch(url, { headers: { "Content-Type": "application/json" } })
      .then(function (res) { return res.status === 404 ? null : res.json(); })
      .then(function (envelope) {
        var list = [];
        if (envelope && envelope.success) {
          if (slug && envelope.data && envelope.data.editor) {
            currentEditor = envelope.data.editor;
          }
          var raw = slug ? (envelope.data && envelope.data.poems) : envelope.data;
          if (Array.isArray(raw)) list = raw;
        }
        allPoems = list.map(toPoemView);
        applyFilter();
      })
      .catch(function () {
        allPoems = [];
        applyFilter();
      });
  }

  searchInput.addEventListener("input", function (e) {
    query = e.target.value || "";
    applyFilter();
  });

  document.getElementById("reader-close").addEventListener("click", closeReader);
  document.addEventListener("keydown", function (e) { if (e.key === "Escape") closeReader(); });

  function loadTags() {
    fetch("/verses/api/v1/tags", { headers: { "Content-Type": "application/json" } })
      .then(function (res) { return res.json(); })
      .then(function (envelope) {
        if (envelope && envelope.success && Array.isArray(envelope.data)) ALL_TAGS = envelope.data;
        renderTags();
      })
      .catch(function () { renderTags(); });
  }

  loadTags();
  loadPoems();
})();
</script>

</body>
</html>
