106 lines
4.1 KiB
HTML
106 lines
4.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Arcana FX — Soundboard</title>
|
|
<link rel="stylesheet" href="/styles.css" />
|
|
<link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><text y='52' font-size='52'>%F0%9F%94%AE</text></svg>" />
|
|
</head>
|
|
<body>
|
|
<div class="aurora"></div>
|
|
|
|
<header class="topbar">
|
|
<div class="brand">
|
|
<span class="sigil">🔮</span>
|
|
<div>
|
|
<h1>Arcana FX</h1>
|
|
<p class="tagline">D&D soundboard mixer</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="status" id="status">
|
|
<span class="dot" id="status-dot"></span>
|
|
<span id="status-text">Loading effects…</span>
|
|
</div>
|
|
|
|
<div class="actions">
|
|
<button id="stream-btn" class="primary" title="Start the continuous Home Assistant stream">Start device stream</button>
|
|
<button id="now-btn" class="ghost" title="Show currently playing effects">Now Playing <span id="now-count">0</span></button>
|
|
<button id="stop-btn" class="danger" title="Stop injected effects">Stop FX</button>
|
|
</div>
|
|
</header>
|
|
|
|
<main>
|
|
<section class="panel hero-panel">
|
|
<div>
|
|
<h2>Prepared Sets</h2>
|
|
<p class="muted">Main workflow: build encounter sets, then fire sounds from the set during play.</p>
|
|
</div>
|
|
<div class="set-tools">
|
|
<select id="set-select" aria-label="Current set"></select>
|
|
<button id="new-set-btn" class="ghost">New set</button>
|
|
<button id="rename-set-btn" class="ghost">Rename</button>
|
|
<button id="delete-set-btn" class="danger ghost">Delete</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="panel filter-panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>Atmosphere Filters</h2>
|
|
<p class="muted">Change the live device stream: click Toggle to latch, or hold Momentary and release to clear.</p>
|
|
</div>
|
|
<span class="badge" id="filter-status">No filter</span>
|
|
</div>
|
|
<div id="filter-grid" class="filter-grid" aria-live="polite"></div>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<h2 id="set-title">Current Set</h2>
|
|
<span class="badge" id="set-count">0 items</span>
|
|
</div>
|
|
<div id="set-grid" class="grid set-grid" aria-live="polite"></div>
|
|
<p id="set-empty" class="empty">No effects in this set yet. Search below and use + Set.</p>
|
|
</section>
|
|
|
|
<section class="panel library-panel">
|
|
<div class="panel-head">
|
|
<h2>Adhoc Library</h2>
|
|
<div class="panel-controls">
|
|
<input id="search" type="search" placeholder="Search names, categories, tags…" autocomplete="off" />
|
|
</div>
|
|
</div>
|
|
<div id="categories" class="categories" role="tablist" aria-label="Categories"></div>
|
|
<div id="grid" class="grid" aria-live="polite"></div>
|
|
<p id="empty" class="empty" hidden>No effects match the search.</p>
|
|
</section>
|
|
</main>
|
|
|
|
<footer>
|
|
<span>Device: <code id="entity-label">media_player.…</code></span>
|
|
<span class="sep">·</span>
|
|
<span id="count-label">0 effects</span>
|
|
<span class="sep">·</span>
|
|
<button id="refresh-btn" class="linkish" title="Rescan share">Rescan library</button>
|
|
</footer>
|
|
|
|
<div id="drawer-backdrop" class="drawer-backdrop" hidden></div>
|
|
<aside id="now-drawer" class="drawer" aria-label="Now playing" aria-hidden="true">
|
|
<div class="drawer-head">
|
|
<h2>Now Playing</h2>
|
|
<button id="drawer-close" class="ghost">Close</button>
|
|
</div>
|
|
<div class="drawer-actions">
|
|
<button id="drawer-stop-all" class="danger">Stop all effects</button>
|
|
<button id="stream-stop-btn" class="danger ghost">Stop device stream</button>
|
|
</div>
|
|
<div id="active-list" class="active-list"></div>
|
|
<p id="active-empty" class="empty">Nothing is currently injected into the stream.</p>
|
|
</aside>
|
|
|
|
<script src="/app.js"></script>
|
|
</body>
|
|
</html>
|