---
import '../assets/css/site.css';
import '../assets/css/input.css';
import scrollspyBehavior from '../assets/hyperscript/scrollspy.hs?raw';
import activeSearchBehavior from '../assets/hyperscript/active-search.hs?raw';

import {Image} from 'astro:assets';
import {getFile} from '../lib/content';
import {buildJsonLd} from '../lib/jsonld';
import {isCurrentPath} from '../lib/utils';
import bssBars from '../assets/img/bss-bars.png';

import Search from "../components/Search.astro";
import BackgroundGrid from "../components/BackgroundGrid.astro";

const {
    title = "htmx",
    description = "htmx gives you access to AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML, using attributes, so you can build modern user interfaces with the simplicity and power of hypertext\n\nhtmx is small (~10k min.gz'd), dependency-free, extendable, IE11 compatible & has reduced code base sizes by 67% when compared with react",
    image = "/img/og-image.png",
    keywords,
    article,
    breadcrumbs,
    hasSidebar = false,
} = Astro.props;

// Site links (header nav, footer extras, social) loaded from one source.
const links = (await getFile('links.yaml'))?.frontmatter;
const navigationItems = links.header;
const footerSections = [
    {name: "Links", items: links.header},
    {name: "Community", items: links.social.map((s: any) => ({name: s.name, url: s.url, iconClass: s.iconClass}))},
    {name: "Resources", items: links.footer},
];
---

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title set:html={title === 'htmx' ? title : `${title} ~ htmx`} />

    <script is:inline>
        if (/Mac|iPad|iPhone|iPod/.test(navigator.userAgent)) {
            document.documentElement.dataset.os = 'mac';
        }
    </script>

    <!-- Performance -->
    <link rel="dns-prefetch" href="https://cdn.jsdelivr.net">

    <!-- SEO & Page Meta -->
    <meta name="description" content={description.trim()}>
    <meta name="keywords" content={[
        ...(keywords ?? []),
        'htmx', 'hypermedia', 'ajax', 'html', 'javascript', 'frontend',
        'web development', 'hateoas', 'rest', 'websockets', 'server sent events', 'declarative',
    ].join(', ')}>
    <meta name="robots" content="index, follow">
    <meta name="author" content="Big Sky Software">
    <meta name="generator" content="Astro">

    <!-- Sitemap -->
    <link rel="sitemap" href="/sitemap-index.xml">

    <!-- Security -->
    <meta name="referrer" content="strict-origin-when-cross-origin">

    <!-- Prevents iOS from turning version numbers (e.g. 2.0.0) into phone links -->
    <meta name="format-detection" content="telephone=no">

    <!-- Theme Colors -->
    <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
    <meta name="theme-color" content="#171717" media="(prefers-color-scheme: dark)">

    {Astro.url &&
            <link rel="canonical" href={Astro.url.href}>}

    <!-- Open Graph / Social Media -->
    <meta property="og:type" content={article ? 'article' : 'website'}>
    <meta property="og:site_name" content="htmx">
    <meta property="og:locale" content="en_US">
    <meta property="og:url" content={Astro.url}>
    <meta property="og:title" content={title}>
    <meta property="og:description" content={description.trim()}>
    <meta property="og:image" content={new URL(image, Astro.url)}>

    {article?.publishedTime &&
            <meta property="article:published_time" content={article.publishedTime}>}
    {article?.modifiedTime &&
            <meta property="article:modified_time" content={article.modifiedTime}>}
    {article?.authors?.map((author: string) =>
            <meta property="article:author" content={author}>)}
    {article?.tags?.map((tag: string) =>
            <meta property="article:tag" content={tag}>)}

    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@htmx_org">
    <meta name="twitter:title" content={title}>
    <meta name="twitter:description" content={description.trim()}>
    <meta name="twitter:image" content={new URL(image, Astro.url)}>

    <!-- Favicon -->
    <link rel="icon" href="/favicon.svg" type="image/svg+xml">

    <!-- Feed auto-discovery (both formats). -->
    <link rel="alternate" type="application/atom+xml" title="htmx — Atom feed" href="/atom.xml">
    <link rel="alternate" type="application/rss+xml" title="htmx — RSS feed" href="/rss.xml">

    <!-- htmx & extensions -->
    <meta name="htmx-config"
          content='{"history":"true","morphSkip":["#search-shortcut-hint"],"morphIgnore":["data-htmx-powered","_"],"logAll":false}'>
    <script is:inline src="/js/htmx.js"></script>
    <script is:inline src="/js/ext/hx-preload.js"></script>

    <!-- _hyperscript 0.9.91 -->
    <script is:inline defer src="/js/_hyperscript.min.js"></script>

    <script type="text/hyperscript" is:inline set:html={scrollspyBehavior}></script>
    <script type="text/hyperscript" is:inline set:html={activeSearchBehavior}></script>

    <!-- Re-execute inline scripts after morph navigation (hyperscript + pattern demos) -->
    <script is:inline defer src="/js/morph-afterswap.js"></script>

    <!-- Enable :active pseudo-class on iOS Safari (requires touchstart listener).
         Used by our custom interact: TailwindCSS variant for touch feedback.
         https://stackoverflow.com/questions/3885018/active-pseudo-class-doesnt-work-in-mobile-safari -->
    <script>
        document.addEventListener('touchstart', function () {
        }, {passive: true});
    </script>

    <!-- Structured Data -->
    <script type="application/ld+json" set:html={JSON.stringify(buildJsonLd({
        title, description, image, article, breadcrumbs,
        url: Astro.url,
        siteUrl: Astro.site?.href ?? "https://four.htmx.org",
    }))}/>
</head>

<body hx-boost:inherited="true"
      hx-swap:inherited="innerMorph"
      class="group/body pt-(--header-height) has-[#mobile-navigation-toggle:checked]:overflow-hidden has-[dialog[open]]:overflow-hidden">

<BackgroundGrid/>

<!-- ─── HEADER ──────────────────────────────────────────────────────────── -->
<header role="banner"
        class="flex flex-col fixed inset-x-0 top-0 h-(--header-height) z-40 bg-neutral-10 dark:bg-neutral-920 border-b border-neutral-200 dark:border-neutral-850">
    <nav id="navigation"
         class="w-full h-(--navigation-bar-height) flex items-center justify-between px-4 sm:px-6 lg:px-8 py-3 lg:py-4 gap-4 lg:gap-12"
         aria-label="Primary Navigation">
        <div class="flex items-center gap-3">

            {hasSidebar && (
                    <label class="lg:hidden flex items-center justify-center size-10 cursor-pointer select-none rounded-xs text-neutral-600 dark:text-neutral-400 interact:text-neutral-800 dark:interact:text-neutral-100"
                           for="sidebar-toggle-mobile"
                           aria-label="Toggle Sidebar"
                           aria-controls="sidebar-nav"
                           role="button"
                           tabindex="0">
                        <i class="size-5 icon-[mdi--menu-open]
                              transition-opacity duration-200
                              [html:has(#sidebar-toggle-mobile:checked)_&]:opacity-0"></i>
                        <i class="size-5 icon-[mdi--menu-close]
                              absolute transition-opacity duration-200 opacity-0
                              [html:has(#sidebar-toggle-mobile:checked)_&]:opacity-100"></i>
                    </label>
            )}

            <!-- Logo -->
            <a href="/" aria-label="HTMX Homepage"
               class="group/logo text-xl sm:text-[1.375rem] lg:text-2xl whitespace-nowrap font-mono inline-flex items-center text-neutral-900 dark:text-neutral-100 interact:text-blue-700 dark:interact:text-blue-300 shrink-0 rounded-sm outline-hidden">
                <span aria-hidden="true">&lt;</span>
                <b class="relative text-blue-700 dark:text-blue-350 dark:group-interact/logo:text-blue-300"
                   aria-hidden="true">
                    <span class="group-interact/logo:opacity-0">/</span>
                    <span class="absolute inset-0 opacity-0 group-interact/logo:opacity-100">-</span>
                </b>
                <span aria-hidden="true" class="relative">
                    <span class="group-interact/logo:opacity-0">&gt;</span>
                    <span class="absolute inset-0 opacity-0 group-interact/logo:opacity-100">-</span>
                </span>
                <span class="font-chicago ms-2 inline-block relative">
                    <span class="group-interact/logo:opacity-0">
                        htm<b class="text-blue-700 dark:text-blue-350 dark:group-interact/logo:text-blue-300">x</b>
                    </span>
                    <span class="absolute inset-0 opacity-0 group-interact/logo:opacity-100 group-interact/logo:underline">
                        hom<b class="text-blue-700 dark:text-blue-350 dark:group-interact/logo:text-blue-300">e</b>
                    </span>
                </span>
            </a>

            <!-- Version Selector -->
            <div class="inline-flex items-center relative group/version">
                <select aria-label="Select htmx version"
                        class="appearance-none bg-transparent pl-2 pr-5 py-1 text-xs rounded-sm text-neutral-600 dark:text-neutral-400 interact:text-black dark:interact:text-white cursor-pointer outline-hidden border border-transparent interact:border-neutral-200 dark:interact:border-neutral-800 translate-y-0.5"
                        onchange="window.location.href = this.value">
                    <option value="/" selected>v4</option>
                    <option value="https://htmx.org">v2</option>
                    <option value="https://v1.htmx.org">v1</option>
                </select>
                <i class="icon-[mdi--chevron-down] absolute right-1 top-1/2 -translate-y-1/2 text-xs text-neutral-400 dark:text-neutral-500 group-hover/version:text-neutral-600 dark:group-hover/version:text-neutral-400 pointer-events-none"
                   aria-hidden="true"></i>
            </div>
        </div>

        <!-- Desktop: Nav Links + Search + Social -->
        <div class="hidden xl:flex items-center justify-between flex-1 gap-4 xl:gap-6">
            <div aria-label="Main" class="hidden xl:flex items-center gap-4 xl:gap-6 flex-1"
                 hx-preload:inherited="mouseenter">
                <ul class="flex gap-4 xl:gap-6 items-center justify-center xl:text-[1.075rem]">
                    {navigationItems.map((item) => (
                            <li>
                                <a href={item.url}
                                   data-label={item.name}
                                   aria-current={isCurrentPath(Astro.url.pathname, item.url) ? 'page' : undefined}
                                   class="inline-block px-3 py-1 text-neutral-600 dark:text-neutral-400 interact:text-blue-700 dark:interact:text-blue-300 interact:underline aria-[current=page]:font-bold aria-[current=page]:text-neutral-950 dark:aria-[current=page]:text-neutral-50 outline-hidden after:content-[attr(data-label)] after:block after:h-0 after:overflow-hidden after:font-bold after:invisible">
                                    {item.name}
                                </a>
                            </li>
                    ))}
                </ul>
            </div>
            <div class="flex items-center min-w-[200px]">
                <!-- Desktop: Search Trigger -->
                <div class="flex-1">
                    <button type="button"
                            class="relative group flex items-center min-h-[44px] min-w-[200px] w-full bg-white dark:bg-neutral-910
                                   border border-neutral-200 dark:border-neutral-800 rounded-lg py-2 px-3 text-base font-sans text-neutral-400
                                   interact:bg-neutral-100 dark:interact:bg-neutral-800/50
                                   interact:border-neutral-400 dark:interact:border-neutral-600
                                   shadow-xs outline-hidden cursor-pointer"
                            aria-label="Open Search"
                            aria-keyshortcuts="Control+K Meta+K"
                            _="on click
                                 showModal() from the first of <search-index > dialog/>
                               end
                               on keydown[key is 'k' and (metaKey or ctrlKey)] from window
                                 halt the event
                                 trigger click
                               end">
                        <i class="icon-[mdi--magnify] size-5 text-neutral-400 group-interact:text-neutral-600 dark:group-interact:text-neutral-200"
                           aria-hidden="true"></i>
                        <span class="text-sm mx-2 group-interact:text-neutral-600 dark:group-interact:text-neutral-200">Open
                            Search</span>
                        <kbd id="search-shortcut-hint" aria-hidden="true"
                             class="ms-auto pe-1 font-chicago text-xs group-interact:text-neutral-600 dark:group-interact:text-neutral-200">
                            <span class="mac:hidden">Ctrl K</span>
                            <span class="hidden mac:inline">⌘ K</span>
                        </kbd>
                    </button>
                </div>
                <div class="h-6 w-px bg-neutral-200 dark:bg-neutral-800 ml-7.5 mr-5.5" role="separator"></div>
                <a href="/discord" aria-label="Join Discord" title="Join the Discord community"
                   target="_blank" rel="noopener noreferrer"
                   hx-boost="false"
                   class="flex px-3 py-2 group">
                    <i class="icon-[simple-icons--discord] size-5.5 text-neutral-600 dark:text-neutral-400 group-interact:text-black dark:group-interact:text-white"
                       aria-hidden="true"></i>
                </a>
                <a href="https://github.com/bigskysoftware/htmx" aria-label="View Source on GitHub"
                   title="View source code on GitHub"
                   target="_blank" rel="noopener noreferrer"
                   class="flex px-3 py-2 group">
                    <i class="icon-[mdi--github] size-5.5 text-neutral-600 dark:text-neutral-400 group-interact:text-black dark:group-interact:text-white"
                       aria-hidden="true"></i>
                </a>
            </div>
        </div>

        <!-- Mobile: Search + Navigation toggle -->
        <div class="xl:hidden flex items-center gap-4">
            <button type="button"
                    class="flex items-center justify-center size-10 text-neutral-600 dark:text-neutral-400 rounded-xs outline-hidden"
                    aria-label="Search"
                    _="on click showModal() from the first of <search-index > dialog/>">
                <i class="icon-[mdi--magnify] size-5 sm:size-6" aria-hidden="true"></i>
            </button>
            <label class="flex items-center justify-center size-10 cursor-pointer rounded-xs outline-hidden"
                   for="mobile-navigation-toggle"
                   aria-label="Toggle Navigation Menu"
                   role="button"
                   tabindex="0">
                <input id="mobile-navigation-toggle" type="checkbox" class="sr-only">
                <i class="icon-[mdi--menu] [html:has(#mobile-navigation-toggle:checked)_&]:hidden size-5 sm:size-6 text-neutral-600 dark:text-neutral-400"
                   aria-hidden="true"></i>
                <i class="icon-[mdi--close] hidden [html:has(#mobile-navigation-toggle:checked)_&]:block size-5 sm:size-6 text-neutral-600 dark:text-neutral-400"
                   aria-hidden="true"></i>
            </label>
        </div>
    </nav>
</header>

<!-- Mobile Navigation Drawer -->
<nav id="mobile-navigation" aria-label="Mobile Navigation"
     class="xl:hidden z-50 opacity-0 top-(--header-height) fixed inset-0 h-screen bg-neutral-10 dark:bg-neutral-920 pointer-events-none select-none [html:has(#mobile-navigation-toggle:checked)_&]:opacity-100 [html:has(#mobile-navigation-toggle:checked)_&]:pointer-events-auto overflow-y-auto overscroll-contain">
    <div class="p-4">
        <ul class="flex flex-col gap-1">
            {navigationItems.map((item) => (
                    <li>
                        <a href={item.url}
                           data-label={item.name}
                           aria-current={isCurrentPath(Astro.url.pathname, item.url) ? 'page' : undefined}
                           class="block rounded-sm px-3 py-2 text-base font-medium text-neutral-600 dark:text-neutral-400 interact:text-blue-700 dark:interact:text-blue-300 interact:underline aria-[current=page]:font-bold aria-[current=page]:text-neutral-950 dark:aria-[current=page]:text-neutral-50 outline-hidden after:content-[attr(data-label)] after:block after:h-0 after:overflow-hidden after:font-bold after:invisible"
                           _="on click set #mobile-navigation-toggle.checked to false">
                            {item.name}
                        </a>
                    </li>
            ))}
        </ul>

        <div class="h-px bg-neutral-200 dark:bg-neutral-800 my-4" role="separator"></div>

        <ul class="flex flex-col gap-1">
            <li>
                <a href="/discord"
                   title="Join the Discord community"
                   hx-boost="false"
                   class="flex items-center gap-3 rounded-sm px-3 py-2 text-base font-medium text-neutral-600 dark:text-neutral-400 interact:text-blue-700 dark:interact:text-blue-300 interact:underline outline-hidden"
                   _="on click set #mobile-navigation-toggle.checked to false">
                    <i class="icon-[simple-icons--discord] size-4.5 text-current" aria-hidden="true"></i>
                    Discord
                </a>
            </li>

            <li>
                <a href="https://github.com/bigskysoftware/htmx"
                   target="_blank" rel="noopener noreferrer"
                   title="View source code on GitHub"
                   class="flex items-center gap-3 rounded-sm px-3 py-2 text-base font-medium text-neutral-600 dark:text-neutral-400 interact:text-blue-700 dark:interact:text-blue-300 interact:underline outline-hidden"
                   _="on click set #mobile-navigation-toggle.checked to false">
                    <i class="icon-[mdi--github] size-5 text-current" aria-hidden="true"></i>
                    GitHub
                </a>
            </li>
        </ul>
    </div>
</nav>

<!-- ─── CONSTRUCTION BANNER ─────────────────────────────────────────────── -->
<a href="/docs#migration"
   id="construction-banner"
   class="sticky top-(--header-height) z-30 h-10 [html:has(#sidebar)_&]:lg:pl-72 flex justify-center items-center text-center gap-2 px-4 py-3 text-xs sm:text-[0.825rem] tracking-tight bg-blue-50 dark:bg-[#161b26] border-y border-blue-200 dark:border-blue-600/30 text-blue-900 dark:text-blue-200 interact:bg-blue-100 dark:interact:bg-[#1b253a] transition font-medium"
   title="htmx 4.0 changes and migration guide">
    <i class="icon-[mdi--wrench] size-3.5 opacity-60" aria-hidden="true"></i>
    htmx 4.0 is under construction — <span class="underline underline-offset-4 font-chicago">migration guide</span>
</a>

<!-- ─── PAGE CONTENT ────────────────────────────────────────────────────── -->
<slot/>

<!-- ─── FOOTER ──────────────────────────────────────────────────────────── -->
<footer class:list={[
    "text-sm border-t border-neutral-200 dark:border-neutral-850 bg-neutral-10 dark:bg-neutral-920 mt-16 sm:mt-24 pt-12 pb-6 sm:pt-16 sm:pb-8 relative z-10",
    hasSidebar && "lg:pl-72"
]}>
    <div class={hasSidebar ? "px-4 sm:px-6 lg:px-12 xl:px-8" : "px-4 sm:px-6 lg:px-8"}>
        <div class={hasSidebar ? "mx-auto max-w-4xl" : "max-w-2xl lg:max-w-5xl mx-auto"}>

            <div class="grid grid-cols-2 lg:grid-cols-4 gap-x-6 gap-y-8 sm:gap-8 lg:gap-12">

                {footerSections.map((section) => (
                        <div>
                            <h2 class="font-sans text-xs font-medium uppercase tracking-widest text-neutral-700 dark:text-neutral-300 mb-4 sm:mb-6">
                                {section.name}
                            </h2>
                            <ul class="space-y-2 sm:space-y-3">
                                {section.items.map((link: {
                                    name: string;
                                    url: string;
                                    iconClass?: string;
                                    boost?: boolean
                                }) => (
                                        <li>
                                            <a href={link.url}
                                               target={link.url?.startsWith('http') ? "_blank" : undefined}
                                               rel={link.url?.startsWith('http') ? "noopener noreferrer" : undefined}
                                               hx-boost={section.name === "Community" || link.boost === false ? "false" : undefined}
                                               title={`Go to ${link.url}`}
                                               class:list={[
                                                   "text-neutral-600 dark:text-neutral-400 interact:text-blue-600 dark:interact:text-blue-300 interact:underline",
                                                   link.iconClass && "inline-flex items-center gap-3"
                                               ]}>
                                                {link.iconClass && (
                                                        <span class="w-5 flex justify-center shrink-0">
                                                            <i class:list={[link.iconClass, "text-base"]}></i>
                                                        </span>
                                                )}
                                                {link.name}
                                            </a>
                                        </li>
                                ))}
                            </ul>
                        </div>
                ))}

                <div>
                    <h2 class="font-sans text-xs font-medium uppercase tracking-widest text-neutral-700 dark:text-neutral-300 mb-4 sm:mb-6">
                        Haiku
                    </h2>
                    <p class="italic font-light text-sm text-neutral-550 dark:text-neutral-450 leading-loose -translate-y-2">
                        javascript fatigue:<br>longing for a hypertext<br>already in hand
                    </p>
                </div>
            </div>

            <div class="mt-12 sm:mt-16 flex items-center text-neutral-600 dark:text-neutral-400 text-xs sm:text-sm">
                <div class="flex-grow border-t border-neutral-100 dark:border-neutral-900"></div>
                <span class="flex items-center gap-2 px-4 sm:px-6">
                    &copy; {new Date().getFullYear()}
                    <span class="text-neutral-300 dark:text-neutral-800 mx-1">·</span>
                    <a href="https://bigsky.software" target="_blank" rel="noopener noreferrer"
                       title="Go to Big Sky Software's website"
                       class="group inline-flex items-center gap-1.5 text-neutral-600 dark:text-neutral-400 interact:text-blue-600 dark:interact:text-blue-300 interact:underline">
                        <Image src={bssBars} alt="" aria-hidden="true" loading="lazy"
                               class="size-3 shrink-0 group-interact:[filter:brightness(0)_saturate(100%)_invert(29%)_sepia(88%)_saturate(1124%)_hue-rotate(214deg)] dark:group-interact:[filter:brightness(0)_saturate(100%)_invert(72%)_sepia(60%)_saturate(430%)_hue-rotate(190deg)_brightness(1.2)]"/>
                        Big Sky Software
                    </a>
                </span>
                <div class="flex-grow border-t border-neutral-100 dark:border-neutral-900"></div>
            </div>

        </div>
    </div>
</footer>

<Search/>

</body>
</html>
