3.1 KiB · text History 487bb12
<!DOCTYPE html>
{# Iframe target for slides and docs. Deliberately free of the app shell: no
   CSS bundle, no htmx, just the card scaled to fill the frame.

   Theme handshake with the embedding page, mirroring Diogramos':
     parent → embed  {type: "bismuth:set-theme", theme: "forest"}
     embed → parent  {type: "bismuth:ready"} once listening
   A theme is any palette id. On a change the card is re-rendered server-side
   in the new palette (so a `solarized` card flips light/dark with it) and
   swapped in. Any origin may ask; the worst it can do is repaint the card in
   another of our own palettes. #}
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{{ snippet.title or "bismuth" }}</title>
  <style>
    @font-face { font-family: "B612 Mono"; font-weight: 400; font-style: normal; src: url(/assets/css/files/b612-mono-latin-400-normal.woff2) format("woff2"); }
    @font-face { font-family: "B612 Mono"; font-weight: 700; font-style: normal; src: url(/assets/css/files/b612-mono-latin-700-normal.woff2) format("woff2"); }
    @font-face { font-family: "B612 Mono"; font-weight: 400; font-style: italic; src: url(/assets/css/files/b612-mono-latin-400-italic.woff2) format("woff2"); }
    @font-face { font-family: "B612 Mono"; font-weight: 700; font-style: italic; src: url(/assets/css/files/b612-mono-latin-700-italic.woff2) format("woff2"); }
    @font-face { font-family: "B612"; font-weight: 700; font-style: normal; src: url(/assets/css/files/b612-latin-700-normal.woff2) format("woff2"); }
    html, body { margin: 0; height: 100%; background: transparent; overflow: hidden; }
    #card { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
    #card > svg { width: 100%; height: 100%; display: block; }
  </style>
</head>
<body>
  <div id="card" data-theme="{{ palette }}" data-themes="{{ themes }}" data-src="{{ src }}">{{ card_svg|safe }}</div>
  <script>
    (() => {
      const root = document.getElementById("card");
      const themes = root.dataset.themes.split(" ");
      const src = new URL(root.dataset.src, location.href);
      src.searchParams.set("inline", "1");
      const cache = new Map();

      async function setTheme(name) {
        if (!themes.includes(name) || root.dataset.theme === name) return;
        root.dataset.theme = name;
        let svg = cache.get(name);
        if (!svg) {
          const url = new URL(src);
          url.searchParams.set("theme", name);
          const res = await fetch(url);
          if (!res.ok) return;
          svg = await res.text();
          cache.set(name, svg);
        }
        // A newer request may have landed while this one was in flight.
        if (root.dataset.theme === name) root.innerHTML = svg;
      }

      window.addEventListener("message", (e) => {
        const msg = e.data;
        if (msg && msg.type === "bismuth:set-theme") setTheme(msg.theme);
      });
      if (window.parent !== window) {
        window.parent.postMessage({ type: "bismuth:ready" }, "*");
      }
    })();
  </script>
</body>
</html>