Add web UI with Smokey's crow as the stand-in mascot

- ui/: Vite + plain TypeScript, builds into ./web for `crows serve`
- CrowView mirrors CrowModel in RIVE_CONTRACT.md (pose, trust,
  reactions) so the .riv can replace the SVG later
- Event handling follows the contract's mapping table; server text
  is only ever inserted as text
- Prank: toast plus a send-button cooldown countdown
- art/crow.svg: source art for Rive import

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UQnSw4RRWp8uqpj3nsnnXF
This commit is contained in:
SmokeyandClaude Opus 5.5 committed 2026-10-27 11:44:54 -06:00
1 parent 940c74672a
commit a89157803b
12 files changed
+1796

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>So Many Crows</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@600;800;900&display=swap" rel="stylesheet" />
</head>
<body>
<header class="top">
<h1>So Many Crows</h1>
<label class="who">You are <input id="requester" maxlength="40" autocomplete="off" /></label>
</header>
<main>
<section class="perch" id="perch" aria-label="The flock"></section>
<p class="banner" id="banner" role="status" hidden></p>
<form class="composer" id="composer">
<label for="list">Your todo list, one item per line</label>
<textarea id="list" rows="5" placeholder="- [ ] What is the difference between a crow and a raven&#10;- [ ] Draft a tagline for So Many Crows"></textarea>
<button class="btn btn-go" id="send" type="submit">Send the flock</button>
</form>
<ol class="cards" id="cards" aria-live="polite"></ol>
<p class="meter" id="meter" hidden></p>
</main>
<div class="toast" id="toast" role="alert" hidden></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>