<!DOCTYPE html>
<html lang="en" data-theme="arcana">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script>
    (function () {
      try {
        var k = "dexarcana.theme.v1";
        var t = localStorage.getItem(k);
        if (t === "arcana") t = "dark";
        if (t === "light" || t === "dark" || t === "nightforge") {
          document.documentElement.setAttribute("data-theme", t);
        }
      } catch (e) {}
    })();
  </script>
  <title>DexArcana</title>
  <meta name="description" content="DexArcana — worlds, maps, characters, and a sealed package for CozyVTT.">
  <link rel="icon" href="favicon.svg" type="image/svg+xml">
  <link rel="stylesheet" href="theme.css?v=nightforge-theme-20260919c">
</head>
<body>
  <a class="skip-link" href="#main">Skip to content</a>
  <header class="site-header">
    <a class="wordmark" href="index.html" aria-label="DexArcana"><span class="sigil" aria-hidden="true"></span><span class="brand-lockup" aria-hidden="true"><span class="wm-cap">D</span><span class="wm-rest">ex</span><span class="wm-cap">A</span><span class="wm-rest">rcana</span></span></a>
    <button class="nav-toggle" type="button" aria-label="Open menu">Menu</button>
    <nav class="site-nav" data-page="home">
      <a href="world.html" data-nav="world">World Builder</a>
      <a href="map.html" data-nav="map">Map</a>
      <a href="forge.html" data-nav="forge">Forge</a>
      <a href="campaign.html" data-nav="campaign">Campaign</a>
      <a href="play.html" data-nav="play">Play</a>
      <a href="reference.html" data-nav="reference">Reference</a>
    </nav>
    <div class="theme-switch" role="group" aria-label="Color theme">
      <button type="button" data-theme-set="light" aria-pressed="false">Light</button>
      <button type="button" data-theme-set="dark" aria-pressed="true">Dark</button>
      <button type="button" data-theme-set="nightforge" aria-pressed="false"><span class="theme-full">Nightforge</span><span class="theme-short">Night</span></button>
    </div>
    <div id="auth-slot" class="auth-slot"></div>
  </header>

  <main id="main" class="page">
    <section class="hero card">
      <p class="kicker">Table workshop</p>
      <h1 class="hero-wordmark"><span class="brand-lockup"><span class="wm-cap">D</span><span class="wm-rest">ex</span><span class="wm-cap">A</span><span class="wm-rest">rcana</span></span></h1>
      <p class="pitch">A premium hall for worlds, maps, and people — then a sealed package for the table. Write lore in the archive, paint the marches, forge the party, assemble a campaign, and push it to CozyVTT. Guests may browse; the vault lives in this browser until you sign the ledger.</p>
      <div class="btn-row" style="margin-top:1.1rem">
        <a class="btn btn-primary" href="world.html">Open the archive</a>
        <a class="btn" href="play.html">Sit the table</a>
        <button type="button" class="btn btn-ghost" data-action="register">Register a table name</button>
      </div>
    </section>

    <section class="plate-grid">
      <a class="plate card" href="world.html">
        <p class="kicker">Lore</p>
        <h2>World</h2>
        <p>Chapters, required years, a timeline, and a mind map. Link maps. Never store cartographer JSON in the lore book.</p>
      </a>
      <a class="plate card" href="map.html">
        <p class="kicker">Cartographer</p>
        <h2>Map</h2>
        <p>A library of MapDocs — region, battle, city, dungeon, coast, or other — with a paint-and-pan editor that round-trips.</p>
      </a>
      <a class="plate card" href="forge.html">
        <p class="kicker">People &amp; gear</p>
        <h2>Forge</h2>
        <p>Player sheets, NPC cards, mundane kit, spells, magic items, and monsters — generate fills the sheet; Save to Repository keeps it. House labels only.</p>
      </a>
      <a class="plate card" href="campaign.html">
        <p class="kicker">Assembly</p>
        <h2>Campaign</h2>
        <p>One world, many maps and faces. Seats for the table. Preview the package. Push to CozyVTT. The VTT itself stays on Play.</p>
      </a>
      <a class="plate card" href="play.html">
        <p class="kicker">CozyVTT</p>
        <h2>Play</h2>
        <p>Embed the table. Load the last package or push-and-play. Mute and fullscreen chrome only — no second character editor.</p>
      </a>
      <a class="plate card" href="reference.html">
        <p class="kicker">House book</p>
        <h2>Reference</h2>
        <p>Original wording for checks, conditions, combat, and gear. Searchable. Read-only. No scraped publisher text.</p>
      </a>
    </section>

    <section class="card" style="margin-top:1.2rem">
      <p class="kicker">How the vault works</p>
      <h2 class="display" style="margin:.2rem 0 .5rem;font-size:1.35rem">One vault, guest or signed</h2>
      <p class="lede">Guest writes stay in <code>dexarcana.rebuild.vault.v1</code>. Sign in and the same shapes sync through the thin API — worlds, maps, characters, NPCs, items, campaigns — with a monotonic revision. Unknown keys survive every merge.</p>
      <div class="btn-row" style="margin-top:0.9rem">
        <button type="button" class="primary" data-action="signin">Sign in</button>
        <button type="button" id="export-vault">Export vault JSON</button>
        <button type="button" class="ghost" id="import-vault">Import JSON</button>
      </div>
    </section>
  </main>

  <script src="vault.js"></script>
  <script src="app.js?v=nightforge-theme-20260919c"></script>
  <script>
    document.addEventListener("da:ready", () => {
      document.getElementById("export-vault").addEventListener("click", () => {
        const { filename, payload } = DAVault.exportJson("vault");
        DAVault.download(filename, payload);
        DA.toast("Vault exported.", "ok");
      });
      document.getElementById("import-vault").addEventListener("click", async () => {
        const payload = await DA.pickFile();
        if (!payload) return;
        try {
          DAVault.importJson(payload);
          DA.toast("Imported into the vault.", "ok");
        } catch (e) {
          DA.toast(e.message, "err");
        }
      });
    });
  </script>
</body>
</html>
