snyvi 1.0.2

A fast, beautiful viewer for the documents your agents produce
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark">
<title>{{TITLE}}</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%23c2410c'/%3E%3Cpath d='M9 10h14M9 16h14M9 22h9' stroke='%23fff' stroke-width='2.4' stroke-linecap='round'/%3E%3C/svg%3E">
<script src="/assets/boot.js?v={{V}}"></script>
<link rel="stylesheet" href="/assets/app.css?v={{V}}">
</head>
<body>
<div id="app">
  <aside id="side" tabindex="-1">
    <div class="side-head">
      <a class="brand" href="/" data-nav="inbox"><span class="brand-mark"></span>snyvi</a>
      <a class="live" id="live" href="/connect" data-nav="connect" title="No agent is connected" aria-label="Agents connected">0</a>
      <button class="icon" id="btn-search" title="Search  ⌘K" aria-label="Search">
        <svg viewBox="0 0 20 20" width="16" height="16"><circle cx="8.5" cy="8.5" r="5.5" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M13 13l4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
      </button>
    </div>
    <div id="trees">
      <div id="inbox-row"></div>
      <nav id="queue" aria-label="Waiting to be read"></nav>
      <nav id="browse-nav" aria-label="Folders"></nav>
      <nav id="tree" aria-label="Projects"></nav>
    </div>
    <div class="side-foot">
      <button class="icon" id="btn-theme" title="Theme (system → light → dark)" aria-label="Theme">
        <svg viewBox="0 0 20 20" width="16" height="16"><circle cx="10" cy="10" r="7" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M10 3a7 7 0 0 1 0 14z" fill="currentColor"/></svg>
      </button>
      <button class="icon" id="btn-font" title="Sans / serif body" aria-label="Font"><span class="aa">Aa</span></button>
      <button class="icon" id="btn-wide" title="Maximise width  w" aria-label="Width">
        <svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M7 6L3 10l4 4M13 6l4 4-4 4M10 4v12"/></svg>
      </button>
      <button class="icon" id="btn-wrap" title="Wrap long lines  z" aria-label="Wrap">
        <svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 5h14M3 10h10a2.5 2.5 0 0 1 0 5H8M10 13l-2 2 2 2M3 15h2"/></svg>
      </button>
      <span class="spacer"></span>
      <button class="hint" id="btn-help" aria-label="Keyboard shortcuts">? for keys</button>
    </div>
    <div class="gutter" role="separator" aria-orientation="vertical" aria-label="Sidebar width" aria-valuemin="200" aria-valuemax="440" tabindex="0" title="Drag to resize · double-click to reset"></div>
  </aside>
  <main id="main">
    <div id="chrome">
      <button class="icon" id="btn-side" title="Sidebar  \" aria-label="Show sidebar" aria-controls="side">
        <svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M3 5h14M3 10h14M3 15h14"/></svg>
      </button>
      <button class="icon" id="btn-rail" title="Contents  t" aria-label="Show contents" aria-controls="rail">
        <svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M7 5h10M7 10h10M7 15h10M3.5 5h.01M3.5 10h.01M3.5 15h.01"/></svg>
      </button>
    </div>
    <div id="queue-bar" hidden role="status" aria-live="polite"></div>
    <div id="find" hidden role="search"><input id="find-input" type="text" placeholder="Find in document" aria-label="Find in document" autocomplete="off" spellcheck="false"><span id="find-count" role="status" aria-live="polite"></span><button class="icon" id="find-prev" title="Previous (Shift+Enter)"></button><button class="icon" id="find-next" title="Next (Enter)"></button><button class="icon" id="find-close" title="Close (Esc)"></button></div>
    <div id="doc">{{INITIAL_HTML}}</div>
  </main>
  <aside id="rail" tabindex="-1">
    <nav id="toc" aria-label="Contents"></nav>
    <div id="meta"></div>
    <div class="gutter" role="separator" aria-orientation="vertical" aria-label="Contents width" aria-valuemin="180" aria-valuemax="400" tabindex="0" title="Drag to resize · double-click to reset"></div>
  </aside>
</div>
<div id="scrim"></div>
<div id="toasts" aria-live="polite"></div>
<div id="palette" hidden>
  <div class="palette-box" role="dialog" aria-modal="true" aria-label="Search">
    <input id="palette-input" type="text" placeholder="Search documents…" autocomplete="off" spellcheck="false">
    <ul id="palette-list" role="listbox"></ul>
  </div>
</div>
<div id="help" hidden>
  <div class="help-box" role="dialog" aria-modal="true" aria-label="Keyboard shortcuts" tabindex="-1">
    <button class="icon help-close" id="help-close" title="Close (Esc)" aria-label="Close"></button>
    <h2>Keys</h2>
    <dl>
      <dt>⌘K</dt><dd>search</dd>
      <dt>j / k</dt><dd>next / previous document</dd>
      <dt>[ / ]</dt><dd>older / newer version in this workflow</dd>
      <dt>c</dt><dd>compare with previous version</dd>
      <dt>s</dt><dd>split / inline diff view</dd>
      <dt>v</dt><dd>preview page / source</dd>
      <dt>/</dt><dd>find in document</dd>
      <dt>n</dt><dd>open the next document waiting</dd>
      <dt>Del</dt><dd>delete document (⌘/ctrl Z undoes it)</dd>
      <dt>p</dt><dd>pin (kept by prune)</dd>
      <dt>i</dt><dd>inbox</dd>
      <dt>w</dt><dd>maximise width</dd>
      <dt>z</dt><dd>wrap long lines</dd>
      <dt>f</dt><dd>fullscreen the diagram</dd>
      <dt>0</dt><dd>fit the diagram (⌘/ctrl + scroll zooms, drag pans)</dd>
      <dt>t</dt><dd>toggle contents</dd>
      <dt>\</dt><dd>toggle sidebar</dd>
      <dt>o</dt><dd>open source</dd>
      <dt>⌘K :120</dt><dd>go to line 120</dd>
      <dt>alt ← / →</dt><dd>back / forward</dd>
      <dt>esc</dt><dd>close</dd>
    </dl>
    <div class="help-foot"><button class="text" id="btn-connect">Connect an agent…</button><button class="text" id="btn-about">About snyvi</button><button class="text" id="btn-reset">Reset snyvi…</button></div>
  </div>
</div>
<div id="about" hidden>
  <div class="help-box about-box" role="dialog" aria-modal="true" aria-labelledby="about-title" tabindex="-1">
    <button class="icon help-close" id="about-close" title="Close (Esc)" aria-label="Close"></button>
    <h2 id="about-title">snyvi</h2>
    <p id="about-say">A fast, beautiful viewer for the documents your agents produce.</p>
    <dl id="about-facts"></dl>
  </div>
</div>
<div id="reset" hidden>
  <form class="help-box reset-box" role="dialog" aria-modal="true" aria-labelledby="reset-title" tabindex="-1">
    <button class="icon help-close" id="reset-close" type="button" title="Close (Esc)" aria-label="Close"></button>
    <h2 id="reset-title">Reset snyvi</h2>
    <p id="reset-say">Reading what there is…</p>
    <label id="reset-pinned-row" hidden><input type="checkbox" id="reset-pinned"> <span id="reset-pinned-say"></span></label>
    <label class="reset-ask">Type the number of documents to continue
      <input id="reset-n" type="text" inputmode="numeric" autocomplete="off" spellcheck="false" aria-describedby="reset-say">
    </label>
    <p id="reset-err" class="reset-err" role="alert" hidden></p>
    <div class="reset-act"><button class="text" type="button" id="reset-cancel">Cancel</button><button class="danger" type="submit" id="reset-go" disabled>Reset</button></div>
  </form>
</div>
<script id="boot" type="application/json">{{BOOT_JSON}}</script>
<script src="/assets/app.js?v={{V}}" defer></script>
</body>
</html>