<!doctype html>
<html lang="en" data-star-root>
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, viewport-fit=cover"
    />
    <meta
      name="description"
      content="{% block description %}
        Self-hosted coffee logging — track roasters, roasts, bags, brews, and
        gear.
      {% endblock %}"
    />
    <meta property="og:type" content="website" />
    <meta property="og:site_name" content="Brewlog" />
    <meta
      property="og:title"
      content="{% block og_title %}Brewlog{% endblock %}"
    />
    <meta
      property="og:description"
      content="{% block og_description %}
        Self-hosted coffee logging — track roasters, roasts, bags, brews, and
        gear.
      {% endblock %}"
    />
    <meta name="twitter:card" content="summary_large_image" />
    <title>{% block title %}Brewlog{% endblock %}</title>
    <link rel="stylesheet" href="/static/css/styles.css" />
    <link
      rel="icon"
      id="favicon"
      type="image/svg+xml"
      href="/static/favicon-light.svg"
    />
    <link rel="apple-touch-icon" href="/static/app-icon-192.png" />
    <link rel="manifest" href="/static/site.webmanifest" />
    <meta name="apple-mobile-web-app-title" content="Brewlog" />
    <meta name="theme-color" content="#c2410c" />
    <script>
      (() => {
        const stored = localStorage.getItem("theme");
        const isDark =
          stored === "dark" ||
          (!stored && matchMedia("(prefers-color-scheme: dark)").matches);
        if (isDark) {
          document.documentElement.setAttribute("data-theme", "dark");
          document.getElementById("favicon").href = "/static/favicon-dark.svg";
        }
      })();
    </script>
    <script
      type="module"
      src="https://cdn.jsdelivr.net/gh/starfederation/datastar@1.0.0-RC.6/bundles/datastar.js"
    ></script>
    <script defer src="/static/js/location.js"></script>
    <script defer src="/static/js/image-utils.js"></script>
    <script defer src="/static/js/components/photo-capture.js"></script>
    <script defer src="/static/js/components/searchable-select.js"></script>
    <script defer src="/static/js/components/chip-scroll.js"></script>
    <script defer src="/static/js/components/world-map.js"></script>
    <script defer src="/static/js/components/donut-chart.js"></script>
    <script defer src="/static/js/components/image-upload.js"></script>
    {% block head %}{% endblock %}
    <script>
      const showToast = (msg, ms = 3000) => {
        const el = document.getElementById("toast-message");
        if (!el) return;
        el.textContent = msg;
        el.parentElement.classList.remove("hidden");
        clearTimeout(showToast._t);
        showToast._t = setTimeout(
          () => el.parentElement.classList.add("hidden"),
          ms,
        );
      };
      document.addEventListener("DOMContentLoaded", () => {
        const t = sessionStorage.getItem("toast");
        if (t) {
          sessionStorage.removeItem("toast");
          showToast(t);
        }
      });
    </script>
    <script>
      const toggleRow = (event) => {
        if (event.target.closest(".card-detail")) return;
        const row = event.currentTarget;
        row.classList.toggle("expanded");
        row.querySelector(".card-detail")?.classList.toggle("hidden");
        const r = row.nextElementSibling;
        if (r?.classList.contains("detail-row")) r.classList.toggle("hidden");
        row.querySelector(".icon-expand")?.classList.toggle("hidden");
        row.querySelector(".icon-collapse")?.classList.toggle("hidden");
      };
    </script>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        const mobileQuery = window.matchMedia("(max-width: 767px)");
        if (!mobileQuery.matches) return;

        const setupInfiniteScroll = () => {
          document
            .querySelectorAll("[data-infinite-scroll]")
            .forEach((container) => {
              const sentinel = container.querySelector(
                ".infinite-scroll-sentinel",
              );
              if (!sentinel || sentinel.dataset.observed) return;
              sentinel.dataset.observed = "true";

              const observer = new IntersectionObserver(
                (entries) => {
                  entries.forEach((entry) => {
                    if (!entry.isIntersecting) return;

                    const nextUrl = container.getAttribute("data-next-url");
                    const targetSelector =
                      container.getAttribute("data-target");
                    if (!nextUrl || !targetSelector) {
                      observer.disconnect();
                      return;
                    }

                    observer.disconnect();
                    sentinel.remove();

                    fetch(nextUrl, {
                      headers: { "datastar-request": "true" },
                    })
                      .then((res) => res.text())
                      .then((html) => {
                        const doc = new DOMParser().parseFromString(
                          html,
                          "text/html",
                        );
                        const newTarget = doc.querySelector(targetSelector);
                        if (!newTarget) return;

                        // Append new rows to existing tbody
                        const existingTbody = container.querySelector("tbody");
                        const newTbody = newTarget.querySelector("tbody");
                        if (existingTbody && newTbody) {
                          Array.from(newTbody.children).forEach((row) => {
                            existingTbody.appendChild(document.adoptNode(row));
                          });
                        }

                        // Check if there are more pages
                        const newContainer = newTarget.querySelector(
                          "[data-infinite-scroll]",
                        );
                        const newNextUrl =
                          newContainer &&
                          newContainer.getAttribute("data-next-url");
                        if (newNextUrl) {
                          container.setAttribute("data-next-url", newNextUrl);
                          const newSentinel = document.createElement("div");
                          newSentinel.className =
                            "infinite-scroll-sentinel h-4 md:hidden";
                          newSentinel.setAttribute("aria-hidden", "true");
                          container.appendChild(newSentinel);
                          setupInfiniteScroll();
                        } else {
                          container.removeAttribute("data-next-url");
                          container.removeAttribute("data-infinite-scroll");
                        }
                      });
                  });
                },
                { rootMargin: "200px" },
              );

              observer.observe(sentinel);
            });
        };

        setupInfiniteScroll();

        const bodyObserver = new MutationObserver(() => {
          setupInfiniteScroll();
        });
        bodyObserver.observe(document.body, { childList: true, subtree: true });
      });
    </script>
  </head>
  <body class="min-h-screen bg-page text-text">
    <main
      class="mx-auto flex w-full max-w-5xl flex-col gap-8 px-6 pb-4 md:py-10"
    >
      {% include "partials/nav.html" %} {% block content %}{% endblock %}
      <footer
        class="mt-8 text-center text-xs tracking-widest text-text-muted small-caps"
      >
        <p>
          B{rew}log by
          <a
            href="https://jnsgr.uk"
            class="text-text-muted hover:text-accent transition"
            target="_blank"
            rel="noreferrer noopener"
            >jnsgruk</a
          >
          ·
          <a
            href="https://github.com/jnsgruk/brewlog/commit/{{ version_info.commit }}"
            class="text-text-muted hover:text-accent transition"
            target="_blank"
            rel="noreferrer noopener"
            >{{ version_info.commit }}</a
          >
        </p>
      </footer>
    </main>

    <div
      id="toast-container"
      class="fixed bottom-4 left-1/2 -translate-x-1/2 z-50"
    >
      <div
        class="hidden rounded-lg border border-success-border bg-surface px-4 py-3 text-sm font-medium text-success-text shadow-lg"
        role="status"
        aria-live="polite"
      >
        <span id="toast-message"></span>
      </div>
    </div>
  </body>
</html>
