import { ChevronDown, Menu, Search as SearchIcon, X } from "lucide-react";
import { AnimatePresence, m } from "framer-motion";
import { useEffect, useRef, useState } from "react";
import { Link, useLocation, useNavigate, useOutlet } from "react-router-dom";
import { pageTransition } from "../motion";
import { ArkLogoMark } from "../components/ArkLogoMark";
import { usePageTitle } from "../components/PageTitleContext";
import { prefetchPostStream } from "../components/messageStream/hooks/usePostStream";
import { BackToTop } from "../components/BackToTop";
import { DocumentMeta } from "../components/DocumentMeta";
import { SearchPanel } from "../components/SearchPanel";
import { useI18n, type Lang } from "../i18n";
import { LANG_OPTIONS } from "../i18nLanguages";

type PublicNavWhich =
  | "home"
  | "browseAll"
  | "categories"
  | "browseLatest"
  | "browseRecommended"
  | "browsePopular"
  | "favorites";

function navIsActive(
  pathname: string,
  search: string,
  hash: string,
  which: PublicNavWhich,
): boolean {
  const sp = new URLSearchParams(search);
  switch (which) {
    case "home":
      return pathname === "/";
    case "browseAll":
      return pathname === "/browse" && !sp.has("sort");
    case "categories":
      return (
        pathname === "/categories" ||
        (pathname === "/" && hash === "#categories")
      );
    case "browseLatest":
      return pathname === "/browse" && sp.get("sort") === "latest";
    case "browseRecommended":
      return pathname === "/official-recommendations";
    case "browsePopular":
      return pathname === "/browse" && sp.get("sort") === "popular";
    case "favorites":
      return (
        pathname === "/favorites" || (pathname === "/" && hash === "#favorites")
      );
    default:
      return false;
  }
}

function navClassName(active: boolean) {
  return [
    "relative shrink-0 rounded-sm px-2 py-2 text-[13px] font-medium leading-none whitespace-nowrap no-underline outline-none transition-colors",
    // Hover-only gold underline that slides in (resting/active look unchanged).
    "after:pointer-events-none after:absolute after:inset-x-2 after:bottom-1 after:h-[2px] after:origin-left after:scale-x-0 after:rounded-full after:bg-ark-gold after:transition-transform after:duration-300 hover:after:scale-x-100 motion-reduce:after:transition-none",
    "focus-visible:ring-2 focus-visible:ring-ark-gold/90 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg",
    active
      ? "text-ark-gold visited:text-ark-gold"
      : "text-[#d7d7dc] visited:text-[#d7d7dc] hover:text-ark-gold",
  ].join(" ");
}

const dropdownAnimationClass = "ark-header-popover-enter";
const headerMenuAnimationClass = "ark-header-menu-enter";

const publicMenuOpenChangeEvent = "ark:public-menu-open-change";

type LanguageDropdownProps = {
  lang: Lang;
  setLang: (lang: Lang) => void;
  ariaLabel: string;
  className?: string;
};

function flagSrc(code: Lang): string {
  return `/assets/ark-library/flags/${code}.svg`;
}

function FlagIcon({
  code,
  className = "",
}: {
  code: Lang;
  className?: string;
}) {
  return (
    <img
      src={flagSrc(code)}
      alt=""
      aria-hidden
      draggable={false}
      decoding="async"
      className={`shrink-0 rounded-full object-cover ${className}`}
    />
  );
}

function LanguageDropdown({
  lang,
  setLang,
  ariaLabel,
  className = "",
}: LanguageDropdownProps) {
  const [open, setOpen] = useState(false);
  const rootRef = useRef<HTMLDivElement>(null);
  const selected = LANG_OPTIONS.find((option) => option.code === lang);

  useEffect(() => {
    if (!open) return;

    const closeOnOutside = (event: MouseEvent | TouchEvent) => {
      if (!rootRef.current?.contains(event.target as Node)) setOpen(false);
    };
    const closeOnEscape = (event: KeyboardEvent) => {
      if (event.key === "Escape") setOpen(false);
    };

    document.addEventListener("mousedown", closeOnOutside);
    document.addEventListener("touchstart", closeOnOutside);
    window.addEventListener("keydown", closeOnEscape);
    return () => {
      document.removeEventListener("mousedown", closeOnOutside);
      document.removeEventListener("touchstart", closeOnOutside);
      window.removeEventListener("keydown", closeOnEscape);
    };
  }, [open]);

  return (
    <div ref={rootRef} className={`relative ${className}`}>
      <button
        type="button"
        onClick={() => setOpen((value) => !value)}
        className="flex h-full w-full items-center gap-2 rounded-full border border-ark-line bg-[#1a1b20] px-3 py-2 text-sm text-neutral-200 shadow-inner outline-none transition hover:border-ark-gold/50 focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg"
        aria-label={ariaLabel}
        aria-haspopup="listbox"
        aria-expanded={open}
      >
        <FlagIcon code={lang} className="h-5 w-5" />
        <span className="min-w-0 flex-1 truncate text-left">
          {selected?.label ?? lang}
        </span>
        <ChevronDown
          size={16}
          className={`shrink-0 text-neutral-400 transition ${
            open ? "rotate-180 text-ark-gold" : ""
          }`}
          aria-hidden
        />
      </button>

      {open ? (
        <div
          className={`${dropdownAnimationClass} absolute left-0 right-0 top-[calc(100%+0.5rem)] z-50 overflow-hidden rounded-2xl border border-white/10 bg-[#1c1c21]/95 p-1.5 shadow-2xl shadow-black/70 ring-1 ring-ark-line/80 backdrop-blur-xl`}
          role="listbox"
          aria-label={ariaLabel}
        >
          {LANG_OPTIONS.map((option) => {
            const active = option.code === lang;
            return (
              <button
                key={option.code}
                type="button"
                role="option"
                aria-selected={active}
                onClick={() => {
                  setLang(option.code as Lang);
                  setOpen(false);
                }}
                className={`flex w-full items-center gap-2 rounded-xl px-3 py-2 text-left text-sm transition ${
                  active
                    ? "bg-ark-gold/10 text-ark-gold2"
                    : "text-neutral-200 hover:bg-white/10 hover:text-white"
                }`}
              >
                <FlagIcon code={option.code} className="h-5 w-5" />
                <span className="truncate font-medium">{option.label}</span>
              </button>
            );
          })}
        </div>
      ) : null}
    </div>
  );
}

type MobileLanguageButtonProps = {
  lang: Lang;
  setLang: (lang: Lang) => void;
  ariaLabel: string;
  onOpen?: () => void;
};

function MobileLanguageButton({
  lang,
  setLang,
  ariaLabel,
  onOpen,
}: MobileLanguageButtonProps) {
  const [open, setOpen] = useState(false);
  const rootRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!open) return;

    const closeOnOutside = (event: MouseEvent | TouchEvent) => {
      if (!rootRef.current?.contains(event.target as Node)) setOpen(false);
    };
    const closeOnEscape = (event: KeyboardEvent) => {
      if (event.key === "Escape") setOpen(false);
    };

    document.addEventListener("mousedown", closeOnOutside);
    document.addEventListener("touchstart", closeOnOutside);
    window.addEventListener("keydown", closeOnEscape);
    return () => {
      document.removeEventListener("mousedown", closeOnOutside);
      document.removeEventListener("touchstart", closeOnOutside);
      window.removeEventListener("keydown", closeOnEscape);
    };
  }, [open]);

  return (
    <div ref={rootRef} className="relative shrink-0">
      <button
        type="button"
        onClick={() => {
          onOpen?.();
          setOpen((value) => !value);
        }}
        className="flex h-10 w-10 items-center justify-center overflow-hidden rounded-full bg-[#191921] outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#08070c]"
        aria-label={ariaLabel}
        aria-haspopup="listbox"
        aria-expanded={open}
      >
        <FlagIcon code={lang} className="h-7 w-7" />
      </button>

      {open ? (
        <div
          className={`${dropdownAnimationClass} absolute right-0 top-[calc(100%+0.5rem)] z-50 w-44 overflow-hidden rounded-2xl border border-white/10 bg-[#1c1c21]/95 p-1.5 shadow-2xl shadow-black/70 ring-1 ring-ark-line/80 backdrop-blur-xl`}
          role="listbox"
          aria-label={ariaLabel}
        >
          {LANG_OPTIONS.map((option) => {
            const active = option.code === lang;
            return (
              <button
                key={option.code}
                type="button"
                role="option"
                aria-selected={active}
                onClick={() => {
                  setLang(option.code as Lang);
                  setOpen(false);
                }}
                className={`flex w-full items-center gap-2 rounded-xl px-3 py-2 text-left text-sm transition ${
                  active
                    ? "bg-ark-gold/10 text-ark-gold2"
                    : "text-neutral-200 hover:bg-white/10 hover:text-white"
                }`}
              >
                <FlagIcon code={option.code} className="h-5 w-5" />
                <span className="truncate font-medium">{option.label}</span>
              </button>
            );
          })}
        </div>
      ) : null}
    </div>
  );
}

export function PublicLayout() {
  const { t, lang, setLang } = useI18n();
  const { pathname, search, hash } = useLocation();
  const outlet = useOutlet();
  const [open, setOpen] = useState(false);
  const [mobileSearchOpen, setMobileSearchOpen] = useState(false);
  const [q, setQ] = useState("");
  const menuRef = useRef<HTMLDivElement>(null);
  const mobileMenuButtonRef = useRef<HTMLButtonElement>(null);
  const desktopMenuButtonRef = useRef<HTMLButtonElement>(null);
  const nav = useNavigate();

  const na = (which: PublicNavWhich) =>
    navIsActive(pathname, search, hash, which);
  const isHome = pathname === "/";
  const footerInContentFlow = pathname === "/browse";
  // Current page name shown in the header brand slot (falls back to the brand).
  const pageTitle = usePageTitle();

  // Warm the common stream views (全部资料 / 热门资料 / 最新) in the background so
  // tapping them shows content immediately. Run one at a time, spaced out and
  // only while idle, so prefetching never competes with the current page or
  // janks low-end phones. Prefetch is JSON-only (no images).
  useEffect(() => {
    const base = { scope: { kind: "all" as const }, type: "all", q: "", lang };
    const jobs = [
      () => prefetchPostStream({ ...base, sort: "" }),
      () => prefetchPostStream({ ...base, sort: "popular" }),
      () => prefetchPostStream({ ...base, sort: "latest" }),
    ];
    const ric = window as typeof window & {
      requestIdleCallback?: (cb: () => void) => number;
      cancelIdleCallback?: (id: number) => void;
    };

    let i = 0;
    let stepTimer = 0;
    let idleId = 0;
    const runNext = () => {
      if (i >= jobs.length) return;
      jobs[i++]();
      stepTimer = window.setTimeout(schedule, 400); // space requests apart
    };
    const schedule = () => {
      if (ric.requestIdleCallback) idleId = ric.requestIdleCallback(runNext);
      else stepTimer = window.setTimeout(runNext, 200);
    };

    const startTimer = window.setTimeout(schedule, 600);
    return () => {
      window.clearTimeout(startTimer);
      window.clearTimeout(stepTimer);
      if (idleId) ric.cancelIdleCallback?.(idleId);
    };
  }, [lang]);
  const popularHref = "/browse?sort=popular";

  const goSearch = () => {
    const s = q.trim();
    if (!s) return;
    nav(`/browse?q=${encodeURIComponent(s)}`);
    setOpen(false);
    setMobileSearchOpen(false);
  };

  useEffect(() => {
    window.dispatchEvent(
      new CustomEvent<boolean>(publicMenuOpenChangeEvent, { detail: open }),
    );
  }, [open]);

  useEffect(() => {
    if (!open) return;

    // Opening the menu from the burger also closes the search overlay, whose
    // scroll-lock cleanup fires a programmatic scroll. Ignore scroll-to-close
    // for a brief window so that restore scroll doesn't shut the menu we just
    // opened; genuine user scrolls afterwards still close it.
    const openedAt = Date.now();

    const closeOnOutside = (event: MouseEvent | TouchEvent) => {
      const target = event.target as Node;
      if (
        menuRef.current?.contains(target) ||
        mobileMenuButtonRef.current?.contains(target) ||
        desktopMenuButtonRef.current?.contains(target)
      ) {
        return;
      }
      setOpen(false);
    };
    const closeOnScroll = () => {
      if (Date.now() - openedAt < 250) return;
      setOpen(false);
    };

    document.addEventListener("mousedown", closeOnOutside);
    document.addEventListener("touchstart", closeOnOutside);
    window.addEventListener("scroll", closeOnScroll);
    return () => {
      document.removeEventListener("mousedown", closeOnOutside);
      document.removeEventListener("touchstart", closeOnOutside);
      window.removeEventListener("scroll", closeOnScroll);
    };
  }, [open]);

  // Lock background scroll while the mobile search overlay is open.
  // Uses the iOS-compatible position-fixed pattern so the underlying page
  // doesn't move at all (overflow:hidden alone is not enough on iOS Safari).
  useEffect(() => {
    if (!mobileSearchOpen) return;
    const scrollY = window.scrollY;
    const body = document.body;
    const prev = {
      position: body.style.position,
      top: body.style.top,
      left: body.style.left,
      right: body.style.right,
      width: body.style.width,
    };
    body.style.position = "fixed";
    body.style.top = `-${scrollY}px`;
    body.style.left = "0";
    body.style.right = "0";
    body.style.width = "100%";
    return () => {
      body.style.position = prev.position;
      body.style.top = prev.top;
      body.style.left = prev.left;
      body.style.right = prev.right;
      body.style.width = prev.width;
      window.scrollTo(0, scrollY);
    };
  }, [mobileSearchOpen]);

  return (
    <div className="min-h-full flex flex-col">
      <DocumentMeta />
      <header className="sticky top-0 z-40 bg-[#08070c] backdrop-blur-md md:border-b md:border-ark-line md:bg-ark-nav/98">
        <div className="flex h-[64px] items-center justify-between bg-[#08070c] px-4 py-3 md:hidden">
          <div className="flex h-8 min-w-0 shrink items-center gap-2 text-[20px] font-black leading-5 tracking-tight text-ark-gold">
            {/* Logo → home; page-name text → scroll to top of the current page. */}
            <Link
              to="/"
              aria-label={t("brand")}
              onClick={(e) => {
                if (isHome) {
                  e.preventDefault();
                  window.scrollTo({ top: 0, behavior: "smooth" });
                }
              }}
              className="shrink-0 rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#08070c]"
            >
              <ArkLogoMark className="h-8 w-8 shrink-0" />
            </Link>
            <button
              type="button"
              onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}
              className="truncate rounded-sm text-left text-ark-gold outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#08070c]"
            >
              {pageTitle || t("brand")}
            </button>
          </div>

          <div className="flex h-[40px] w-[136px] shrink-0 items-center gap-[8px]">
            <button
              type="button"
              onClick={() => {
                setOpen(false);
                setMobileSearchOpen((value) => !value);
              }}
              className="flex h-[40px] w-[40px] items-center justify-center rounded-full bg-[#191921] outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#08070c]"
              aria-label={t("search")}
              aria-expanded={mobileSearchOpen}
            >
              <img
                src="/assets/ark-library/header-search.svg"
                alt=""
                className="h-6 w-6"
                width={24}
                height={24}
                aria-hidden
                draggable={false}
              />
            </button>
            <MobileLanguageButton
              lang={lang}
              setLang={setLang}
              ariaLabel={t("langLabel")}
              onOpen={() => {
                setOpen(false);
                setMobileSearchOpen(false);
              }}
            />
            <button
              ref={mobileMenuButtonRef}
              type="button"
              className="inline-flex h-[40px] w-[40px] shrink-0 items-center justify-center rounded-full bg-[#191921] text-[#a8a9ae] outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#08070c]"
              onClick={() => {
                setMobileSearchOpen(false);
                setOpen((v) => !v);
              }}
              aria-label="menu"
              aria-expanded={open}
            >
              {open ? (
                <X size={24} strokeWidth={2.4} />
              ) : (
                <img
                  src="/assets/ark-library/header-menu.svg"
                  alt=""
                  className="h-6 w-6"
                  width={24}
                  height={24}
                  aria-hidden
                  draggable={false}
                />
              )}
            </button>
          </div>
        </div>

        <div className="mx-auto hidden max-w-[1280px] px-4 py-[15px] min-[440px]:px-5 sm:px-6 md:block md:px-9 xl:px-0">
          {/* Single row (md+): logo | scrollable nav (左對齊，可橫向滑動) | 搜尋 + 語言 */}
          <div className="flex h-10 items-center gap-2 min-[1200px]:gap-0 lg:gap-4">
            <div className="flex min-w-0 shrink items-center gap-2.5 text-xl font-bold tracking-wide text-ark-gold">
              {/* Logo → home; page-name text → scroll to top of the current page. */}
              <Link
                to="/"
                aria-label={t("brand")}
                onClick={(e) => {
                  if (isHome) {
                    e.preventDefault();
                    window.scrollTo({ top: 0, behavior: "smooth" });
                  }
                }}
                className="shrink-0 rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg"
              >
                <ArkLogoMark className="h-10 w-10 shrink-0" />
              </Link>
              <button
                type="button"
                onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}
                className="max-w-[10rem] truncate rounded-sm text-left text-ark-gold outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg sm:inline"
              >
                {pageTitle || t("brand")}
              </button>
            </div>

            <nav
              className="header-nav-scroll hidden min-w-0 flex-1 items-center justify-center gap-4 overflow-x-auto overflow-y-hidden py-1 min-[1200px]:flex lg:gap-5"
              aria-label={t("mainNav")}
            >
              <Link
                to="/browse"
                className={navClassName(na("browseAll"))}
                aria-current={na("browseAll") ? "page" : undefined}
              >
                {t("all")}
              </Link>
              <Link
                to="/categories"
                className={navClassName(na("categories"))}
                aria-current={na("categories") ? "page" : undefined}
              >
                {t("categories")}
              </Link>
              <Link
                to="/official-recommendations"
                className={navClassName(na("browseRecommended"))}
                aria-current={na("browseRecommended") ? "page" : undefined}
              >
                {t("official")}
              </Link>
              <Link
                to="/browse?sort=latest"
                className={navClassName(na("browseLatest"))}
                aria-current={na("browseLatest") ? "page" : undefined}
              >
                {t("latest")}
              </Link>
              <Link
                to={popularHref}
                className={navClassName(na("browsePopular"))}
                aria-current={na("browsePopular") ? "page" : undefined}
              >
                {t("popular")}
              </Link>
              <Link
                to="/favorites"
                className={navClassName(na("favorites"))}
                aria-current={na("favorites") ? "page" : undefined}
              >
                {t("favorites")}
              </Link>
            </nav>

            <div className="flex min-w-0 flex-1 items-center justify-end gap-2 min-[1200px]:flex-none">
              <div className="hidden h-10 min-w-0 flex-1 items-center gap-2 rounded-full border border-ark-line bg-[#1a1b20] py-2 pl-3 pr-3 shadow-inner md:flex min-[1200px]:w-44 min-[1200px]:flex-none lg:pr-4 xl:w-52">
                <button
                  type="button"
                  onClick={goSearch}
                  className="shrink-0 rounded-full p-1 text-[#c6c7cf] transition hover:bg-white/5 hover:text-ark-gold focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/60"
                  aria-label={t("searchNow")}
                >
                  <SearchIcon size={16} />
                </button>
                <input
                  value={q}
                  onChange={(e) => setQ(e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && goSearch()}
                  placeholder={t("searchPlaceholder")}
                  className="min-w-0 flex-1 rounded-md bg-transparent text-sm text-neutral-200 outline-none placeholder:text-[#777985] focus-visible:ring-2 focus-visible:ring-ark-gold/60 focus-visible:ring-offset-2 focus-visible:ring-offset-[#1a1b20]"
                />
              </div>
              <LanguageDropdown
                lang={lang}
                setLang={setLang}
                ariaLabel={t("langLabel")}
                className="hidden h-10 w-36 md:block lg:w-40"
              />
              <button
                ref={desktopMenuButtonRef}
                type="button"
                className="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-full border border-ark-line bg-[#1a1b20] text-neutral-200 outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg min-[1200px]:hidden"
                onClick={() => setOpen((v) => !v)}
                aria-label="menu"
              >
                {open ? <X size={18} /> : <Menu size={18} />}
              </button>
            </div>
          </div>
        </div>

        {open ? (
          <div
            ref={menuRef}
            className={`${headerMenuAnimationClass} fixed inset-x-0 top-[64px] z-50 grid gap-2 bg-[#08070c] px-4 py-3 shadow-2xl shadow-black/50 min-[440px]:px-5 sm:px-6 md:top-[70px] md:px-9 min-[1200px]:hidden`}
          >
            <div className="mb-1 hidden items-center gap-2 rounded-full border border-ark-line bg-[#1a1b20] px-3 py-2 md:flex">
              <button
                type="button"
                onClick={goSearch}
                className="shrink-0 rounded-full p-1 text-[#c6c7cf] transition hover:bg-white/5 hover:text-ark-gold focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/60"
                aria-label={t("searchNow")}
              >
                <SearchIcon size={16} />
              </button>
              <input
                value={q}
                onChange={(e) => setQ(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && goSearch()}
                placeholder={t("searchPlaceholder")}
                className="flex-1 bg-transparent text-sm outline-none placeholder:text-[#777985]"
              />
            </div>
            <Link
              to="/browse"
              className={navClassName(na("browseAll"))}
              aria-current={na("browseAll") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("all")}
            </Link>
            <Link
              to="/categories"
              className={navClassName(na("categories"))}
              aria-current={na("categories") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("categories")}
            </Link>
            <Link
              to="/official-recommendations"
              className={navClassName(na("browseRecommended"))}
              aria-current={na("browseRecommended") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("official")}
            </Link>
            <Link
              to="/browse?sort=latest"
              className={navClassName(na("browseLatest"))}
              aria-current={na("browseLatest") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("latest")}
            </Link>
            <Link
              to={popularHref}
              className={navClassName(na("browsePopular"))}
              aria-current={na("browsePopular") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("popular")}
            </Link>
            <Link
              to="/favorites"
              className={navClassName(na("favorites"))}
              aria-current={na("favorites") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("favorites")}
            </Link>
          </div>
        ) : null}
      </header>

      {mobileSearchOpen ? (
        <SearchPanel
          lang={lang}
          t={t}
          query={q}
          onQueryChange={setQ}
          onSearch={goSearch}
        />
      ) : null}

      <main
        className={`mx-auto w-full max-w-[1280px] ${
          isHome
            ? "flex-1 px-0 pb-6 pt-0 md:px-9 md:pb-10 md:pt-10 xl:px-0"
            : footerInContentFlow
              ? "flex-1 px-0 pb-0 pt-0 md:px-9 md:pt-10 xl:px-0"
              : "flex-1 px-4 pb-6 pt-6 min-[440px]:px-5 sm:px-6 md:px-9 md:pb-10 md:pt-10 xl:px-0"
        }`}
      >
        <AnimatePresence mode="wait" initial={false}>
          <m.div
            key={`${pathname}${search}`}
            variants={pageTransition}
            initial="initial"
            animate="enter"
            exit="exit"
          >
            {outlet}
          </m.div>
        </AnimatePresence>
      </main>

      <nav className="sticky inset-x-0 bottom-0 z-40 bg-[#0C0D0F]/90 backdrop-blur md:hidden">
        <div className="grid h-[78px] grid-cols-4 gap-3 px-5 py-4 text-center text-[11px] leading-[17.6px]">
          <BottomNavIcon
            to="/"
            label={t("home")}
            icon="home"
            active={pathname === "/"}
          />
          <BottomNavIcon
            to="/browse"
            label={t("all")}
            icon="document"
            active={
              pathname === "/browse" && !new URLSearchParams(search).get("sort")
            }
          />
          <BottomNavIcon
            to="/favorites"
            label={t("favorites")}
            icon="bookmark"
            active={na("favorites")}
          />
          <BottomNavIcon
            to={popularHref}
            label={t("popular")}
            icon="update"
            active={na("browsePopular")}
          />
        </div>
      </nav>

      {pathname === "/browse" ? <BackToTop /> : null}
    </div>
  );
}

const NAVBAR_ICON_BASE = "/assets/ark-library/navbar";

function BottomNavIcon({
  to,
  label,
  icon,
  active,
}: {
  to: string;
  label: string;
  icon: "home" | "document" | "bookmark" | "update";
  active: boolean;
}) {
  const src = active
    ? `${NAVBAR_ICON_BASE}/${icon}-active.svg`
    : `${NAVBAR_ICON_BASE}/${icon}-inactive.svg`;
  return (
    <Link
      to={to}
      className={[
        "flex min-w-0 flex-col items-center gap-1 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg",
        active ? "text-ark-gold" : "text-[#908F92]",
      ].join(" ")}
    >
      <img
        src={src}
        alt=""
        className="mx-auto h-6 w-6 object-contain"
        width={24}
        height={24}
        loading="lazy"
        decoding="async"
      />
      <span className="leading-tight">{label}</span>
    </Link>
  );
}
