Add green-bean inventory and cupping features

Ports inventory management and SCA-style cupping scoring from
hope_roaster: lot tracking with audit-logged consumption, cupping
sessions with server-authoritative scoring and a live radar chart,
and links from the planner (draw-from-lot, open-cupping-session).

Also fixes the Blend/Single-origin toggle layout, replaces tooltips
with an in-context "why" teaching layer, and stages the planner UI
into pre-roast vs. post-roast phases.
This commit is contained in:
2026-07-30 14:47:15 -04:00
parent 9f0a3dbc74
commit 59645e59b5
43 changed files with 7582 additions and 566 deletions
+63
View File
@@ -0,0 +1,63 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Administrator setup — Roast Planner</title>
<link rel="stylesheet" href="/app.css" />
<link rel="icon" href="/icon.svg" type="image/svg+xml" />
<meta name="theme-color" content="#A8481A" />
</head>
<body>
<main class="auth-page">
<section class="panel-card auth-card">
<div class="auth-brand">
<span class="brand-mark" aria-hidden="true"></span>
<strong>Roast Planner</strong>
</div>
<h1>Create the administrator account</h1>
<p class="lede">
This runs once, before anyone else can sign up. You'll need the
setup token from the deployment environment.
</p>
<div id="message" class="auth-message" role="alert"></div>
<form id="setup-form">
<label
>Administrator email
<input
class="field-input"
required
type="email"
name="email"
value="[email protected]"
readonly
/></label>
<label
>Password
<input
class="field-input"
required
type="password"
minlength="12"
name="password"
autocomplete="new-password"
/></label>
<label
>Setup token
<input
class="field-input"
required
type="password"
name="setupToken"
autocomplete="off"
/></label>
<button class="primary-btn" type="submit">Create administrator</button>
</form>
<div class="auth-links">
<a href="/login">Back to log in</a>
</div>
</section>
</main>
<script type="module" src="/js/setup.js"></script>
</body>
</html>