---
import "../styles/site.css";
import Sprite from "../components/Sprite.astro";
import AddressBar from "../components/AddressBar.astro";
import Deskbar from "../components/Deskbar.astro";
import { icon } from "../lib/icons";
import type { Crumb, MenuGroup } from "../lib/site";
import { palettes } from "../lib/palettes";
import { DEFAULT_PALETTE } from "../lib/themes";
import { OG_HEIGHT, OG_WIDTH, ogPath } from "../lib/og";

interface Props {
  /** the page's own title; home has none */
  title?: string;
  description?: string;
  /** the link preview image, the site's own card when the page has none */
  og?: string;
  /** this page as markdown, for agents; llms.txt when the page has no copy of its own */
  markdown?: string;
  crumbs: Crumb[];
  pages: MenuGroup[];
  /** what the window's fixed edges outline: a list column of this width beside the paper,
   *  the paper alone, or nothing (home) */
  layout: number | "solo" | "none";
}
const { title, description, crumbs, pages, layout, og = ogPath(), markdown = "/llms.txt" } = Astro.props;
const markdownUrl = new URL(markdown, Astro.site);
const llms = new URL("/llms.txt", Astro.site);
const hint = markdownUrl.href === llms.href
  ? `every page of these docs is listed as plain markdown at ${llms}, which this url also returns for Accept: text/markdown`
  : `this page as plain markdown is at ${markdownUrl}, which this url also returns for Accept: text/markdown, and ${llms} lists every page of the docs that way`;
const desks = Object.fromEntries(palettes().palettes.map((p) => [p.id, { light: p.chip.light.desk, dark: p.chip.dark.desk }]));
const lip = typeof layout === "number" ? "lip" : `lip ${layout}`;
const listWidth = typeof layout === "number" ? `--list-w: ${layout}px` : undefined;
---
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <Fragment set:html={`<!-- for agents reading the source: ${hint} -->`} />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>{title ? `${title} · hydrant docs` : "hydrant docs"}</title>
    {description && <meta name="description" content={description} />}
    <!-- the link preview: bluesky, discord and the rest read these -->
    <meta property="og:site_name" content="hydrant docs" />
    <meta property="og:type" content="website" />
    <meta property="og:title" content={title ?? "hydrant docs"} />
    {description && <meta property="og:description" content={description} />}
    <meta property="og:url" content={new URL(Astro.url.pathname, Astro.site)} />
    <meta property="og:image" content={new URL(og, Astro.site)} />
    <meta property="og:image:width" content={String(OG_WIDTH)} />
    <meta property="og:image:height" content={String(OG_HEIGHT)} />
    <meta name="twitter:card" content="summary_large_image" />
    <!-- the default palette's desk in each half -->
    <meta name="theme-color" content={desks[DEFAULT_PALETTE].light} media="(prefers-color-scheme: light)" data-light />
    <meta name="theme-color" content={desks[DEFAULT_PALETTE].dark} media="(prefers-color-scheme: dark)" data-dark />
    <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
    <link rel="alternate" type="text/markdown" href={markdownUrl} />
    <link rel="stylesheet" href="/palettes.css" />
    <!-- the browser renders a page in the background when a link to it is pointed at, so
         following it is instant. plain json the browser reads itself, no js; browsers without
         speculation rules skip it -->
    <script type="speculationrules" is:inline>
      { "prerender": [{ "where": { "href_matches": "/*" }, "eagerness": "moderate" }] }
    </script>
    <script is:inline define:vars={{ desks, DEFAULT_PALETTE }}>
      // light or dark follows the system in plain css. this only applies what was picked in the
      // deskbar, before the first paint so it never flashes: a theme ("light" or "dark", none
      // means follow the system) and a palette (none means the default). the deskbar fires
      // hydrant-theme, other tabs hear it through storage
      const root = document.documentElement;
      const metas = document.querySelectorAll('meta[name="theme-color"]');
      // css hides what only works with js (the key legend, the deskbar's switches) without this
      root.dataset.js = "";
      const apply = () => {
        const pick = localStorage.getItem("hydrant-theme");
        const palette = localStorage.getItem("hydrant-palette");
        root.dataset.themePick = pick ?? "auto";
        if (pick) root.dataset.theme = pick;
        else delete root.dataset.theme;
        if (palette && desks[palette]) root.dataset.palette = palette;
        else delete root.dataset.palette;
        const desk = desks[root.dataset.palette ?? DEFAULT_PALETTE];
        for (const m of metas) m.content = desk[pick ?? ("light" in m.dataset ? "light" : "dark")];
      };
      apply();
      addEventListener("hydrant-theme", apply);
      // a prerendered page ran this when it was pointed at, so it reads the picks again when shown
      document.addEventListener("prerenderingchange", apply);
      addEventListener("storage", (e) => (e.key === "hydrant-theme" || e.key === "hydrant-palette") && apply());
    </script>
  </head>
  <body>
    <Sprite />
    <div class="desk">
      <!-- the window stays put and only what's in it moves, but it's still the page that
           scrolls, so the wheel, keys, find and links all work anywhere on the desk. the
           top and bottom of the window stick to the viewport and the content passes under them -->
      <div class="win" style={listWidth}>
        <header class="win-head" data-head>
          <div class="tabrow">
            <a class="tab" href="/"><Fragment set:html={icon("hydrant", 22)} />hydrant docs</a>
            <Deskbar />
          </div>
          <div class="frame-top">
            <div class="tb">
              <button class="btn" type="button" data-back aria-label="back">&#9664;</button>
              <button class="btn" type="button" data-forward aria-label="forward">&#9654;</button>
              <span class="sep"></span>
              <AddressBar crumbs={crumbs} pages={pages} />
            </div>
          </div>
          <div class={`${lip} top`} aria-hidden="true"><span class="l"></span><span class="p"></span></div>
        </header>
        <div class="frame">
          <slot />
        </div>
        <footer class="win-foot" data-foot>
          <div class={`${lip} bot`} aria-hidden="true"><span class="l"></span><span class="p"></span></div>
        </footer>
      </div>
    </div>
    <script>
      import "../scripts/history";
      import "../scripts/edges";
    </script>
  </body>
</html>
