55 Commits
Author SHA1 Message Date
snowspeederandClaude Fable 5 e9f2393c96 Remove the Academy films
Test and deploy / test-and-deploy (push) Successful in 1m3s
The generated videos weren't good enough — pull the films card, its
styles, and the video assets. The service-worker hardening stays: media
paths bypass the cache (Range/206 responses) and only full 200 responses
are cached.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-11 19:02:03 -04:00
snowspeederandClaude Fable 5 cc735aba82 Academy films: locally generated physics videos of the roast and the brew
Test and deploy / test-and-deploy (push) Successful in 1m1s
Two short macro films generated on the local ComfyUI instance (Wan 2.2
14B t2v + lightx2v 4-step LoRAs, 9 clips at 832x480) and stitched with
crossfades and burned-in phase labels: roast-physics.mp4 (charge, drying,
Maillard, first crack, drop) and brew-physics.mp4 (grind, bloom,
immersion, espresso). A "Films — the physics in motion" card on the
Academy menu plays them with posters; opening a lesson hides and pauses
them. The service worker now bypasses /academy-video/ and /academy-audio/
(Range/206 responses the Cache API rejects) and only caches full 200s.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-11 18:12:15 -04:00
snowspeederandClaude Fable 5 385474ecef Removable reference curves, audit fixes across pages, shaded Academy art
Test and deploy / test-and-deploy (push) Successful in 1m8s
The planner's Artisan .alog drawer now shows what's attached with a
"Remove reference curve" control (re-rendered per drawer open), so adding
a reference curve is no longer a one-way door; /api/alog shares the 8 MB
body cap so real-sized logs parse instead of failing with "bad_request".

Deep-evaluation fixes: editing a brew of an archived bean no longer
silently detaches the bean; the roasts pending-review poll no longer
wipes in-progress after-roast edits; roasters gain an Edit (rename/model)
action; the gear page refuses to autosave over a failed load; duplicating
a plan carries its custom name; cupping sessions can attach a plan after
creation (ownership-checked PUT + selector); admin user deletion also
refreshes plans/audit; cupping cup-count subtitle stays live; roasts
error-row colspan corrected. Regression tests cover the new cupping PUT
and the /api/alog body cap.

Academy scenes drop the flat paper-cutout look: shared defs provide
radial-gradient shading on every bean/half-bean/particle, flame gradients
with radiant halos, soft ground shadows, and a warm-lit stage background;
fill-shift animations now ride a partial-opacity tint overlay so shading
survives the color change.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-11 16:59:28 -04:00
Shane MaynardandClaude Fable 5 8b80c3fa6f Academy v4: 3 research-backed lessons (30 slides + audio); new bean logo; custom plan/lot names
Test and deploy / test-and-deploy (push) Successful in 59s
Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 14:30:42 -04:00
Shane MaynardandClaude Fable 5 ec078116b4 Add colored SCA-style flavor wheel to cupping; colorize the radar chart
Test and deploy / test-and-deploy (push) Successful in 55s
- New flavor-wheel.js: two-ring sunburst (families inner, descriptors
  outer) in SCA hue families; tapping a wedge toggles the same flavor
  tag as the checkbox list; selections render bold with a dark outline;
  respects the tag limit; labels drawn above all wedges so long names
  never clip (screenshot-verified in headless Chromium)
- Cupping radar: one hue per attribute on labels + vertex dots

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 10:11:31 -04:00
Shane MaynardandClaude Fable 5 2e1b8d24f9 Academy v3: screenshot-verified scenes, transform-override fix, hero bean-journey slide
Test and deploy / test-and-deploy (push) Successful in 56s
Root cause of the broken diagrams found and fixed: CSS transform
animations were overriding the SVG positioning transform on the same
element, throwing animated elements (beans, flames) to the canvas
origin — the bean/flame helpers now split position (outer group) from
animation (inner group).

Every scene was then rendered in headless Chromium and screenshot-
inspected, with fixes applied and re-verified: drying-scene label
collision, RoR ideal-line label overlap, first-crack dot off the curve,
composition bar stagger orphaning its labels, moka flame hidden behind
the base.

New opening slide (user request): 'The whole journey, in one bean' — a
large bean on a 14-second loop living the full roast (heat in, drying
steam out, green→yellow→brown, pressure swell, crack) synced to a
stage timeline with a riding marker; narrated like the rest.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 10:06:30 -04:00
Shane MaynardandClaude Fable 5 9448712a8a Academy v2: one trackable roasting lesson; every scene redesigned to layout discipline
Test and deploy / test-and-deploy (push) Successful in 1m2s
- Roasting is now a single continuous 11-slide lesson ('The roast,
  start to finish') merging the six lessons' content; brewing keeps its
  four per-family lessons
- Progress tracking: resume-where-you-left-off per lesson, progress bar
  and completed badge on the lesson cards (localStorage)
- Every scene rebuilt against a fixed safe area (nothing off-canvas),
  with animations that depict the narrated mechanism: contained
  thermometer fills, a drawn dip-and-turn for the turning point, chaff
  drifting off the swelling Maillard bean, crash/flick/stall on one
  annotated RoR chart, per-brewer water/grounds anchored to each
  silhouette's actual bowl, gauge needle sweeps instead of spinning
  clocks; multiline labels replace out-of-frame text
- 9 new narration clips generated, 23 orphaned ones removed (31 total)

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 09:22:40 -04:00
Shane MaynardandClaude Fable 5 64c1b3605b Add the Academy: narrated, animated roasting & brewing lessons; cupping link on roast detail
Test and deploy / test-and-deploy (push) Successful in 53s
Academy (/academy, 'Learn' nav group):
- 10 lessons / 45 slides across two tracks. Roasting: seed anatomy and
  composition, drying & the turning point, Maillard, first crack &
  development (DTR), curve/RoR reading (crash, flick, stall), defects →
  one-change discipline. Brewing: extraction physics (dissolving order,
  yield, grind, temp/time/ratio), then technique per brewer family —
  immersion (French press, AeroPress, Clever/Hario Switch, cold brew,
  cupping), percolation (bloom, V60, Chemex/Kalita, batch, percolator),
  espresso & pressure (puck prep, shot reading, dialing in, moka)
- One cohesive scene system: 25 parameterized animated SVG scenes drawn
  from the app's palette (beans, curves, phase bars, brewers reusing the
  silhouette library), CSS keyframe animations, reduced-motion support
- Narration: Azure TTS (en-US-Andrew HD, eastus) pre-generated to 45
  committed MP3s by scripts/generate-academy-audio.mjs; slides speak
  phonetic respellings (my-YARD, KEM-ex, MOH-kah…) while captions show
  normal spelling; hands-free autoplay advances after each clip
- Player: slide dots, keyboard arrows/space, per-slide captions

Roast detail: 'Open cupping session' button next to cup notes (opens or
creates the linked plan's session) — its score and flavors flow into
the updated .alog download.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 09:04:39 -04:00
Shane MaynardandClaude Fable 5 0b4857c225 Hotfix: planner init crashed for admin accounts, killing autosave and the plans list
Test and deploy / test-and-deploy (push) Successful in 1m34s
The admin nav-link reveal ran before the generated nav existed
(getElementById('nav-admin') was null only for admins — which is why
tests and non-admin checks missed it), aborting init before form wiring,
autosave, and loadPlans. initSideNav now runs first, the reveal is
null-safe, and wireCuppingLink degrades instead of crashing (its button
lost its home when After-the-Roast moved — it now lives at the end of
the Roast Log section with a pointer to the Roasts page).

Also: the Roasts page graph now honors the planner's °C/°F preference.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 08:53:56 -04:00
Shane MaynardandClaude Fable 5 c6c392730f Fix desktop header overflow; add plan attachment on roast detail
Test and deploy / test-and-deploy (push) Successful in 55s
- The app header now wraps: brand + actions on the first row (actions
  shrink and wrap instead of pushing Print off-screen), section pills
  always on their own full-width row; the planner's sticky offsets use
  a two-row --header-h via body:has(#plan-form)
- Roast detail gains a Plan selector (attach/detach any of your plans)
  alongside the Machine selector; PUT /api/roasts/:id accepts
  roastPlanId with ownership checks

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 08:47:13 -04:00
Shane MaynardandClaude Fable 5 4a3d192c2c Move After-the-Roast onto actual roasts; add Artisan-importable updated .alog download
Test and deploy / test-and-deploy (push) Successful in 56s
One system: post-roast observations (weights, colour, DTR, cup notes,
'one change next batch', disproof) now live on the uploaded roast
(actual_roasts.after, migration 011), edited on the roast detail view
with weights/DTR prefilled from the .alog itself. The planner's screen
section is removed (the print worksheet keeps its hand-fill copy), and
the lot 'last refine' suggestion reads the note from both the new home
and legacy plans, newest wins.

Every roast now downloads two ways: the untouched original .alog, and
an updated supplemental copy with the app's data written back as valid
Artisan fields (weight, beans, roastingnotes incl. the LLM review,
cuppingnotes incl. linked cupping score/flavors) — serialized as a
Python literal so Artisan's ast.literal_eval re-imports it.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 08:35:11 -04:00
Shane MaynardandClaude Fable 5 9b6ea9880e Remove the header's hidden scroll region: section pills become a fixed grid on mobile
Test and deploy / test-and-deploy (push) Successful in 42s
The section nav (Plan/Bean/Machine/Log/After) was an overflow-x:auto
strip with hidden scrollbars — undiscoverable on touch. It now wraps on
desktop and renders as a fixed five-column grid of equal pills at
≤720px (labels shortened to fit 320px), and the actions row lets the
autosave chip shrink/ellipsize so nothing can force horizontal overflow.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 08:26:59 -04:00
Shane MaynardandClaude Fable 5 a341d67467 Add roaster (machine) management, mobile header-tools redesign, and profile pictures
Test and deploy / test-and-deploy (push) Successful in 1m0s
Machines:
- roasters table + actual_roasts.roaster_id (migrations 009): per-user
  machines with a default; uploads attach to the default roaster and are
  reassignable from the roast detail view
- Learning is now per machine: /api/roaster-profile scopes to a roaster
  (default when unspecified) and applies the user's override tweaks
  (milestone temps, TP time, pace factor) on top of learned medians
- /roasters page: machine list + analysis report showing learned vs
  applied values with editable tweaks, typical RoR, and a plain-language
  list of the adjustments applied to plans; planner honors a manual pace
  override; evaluations use the roast's own machine profile

Mobile header redesign:
- The planner's header tools collapse behind a single 'Tools ▾'
  disclosure (dropdown card) at ≤720px, keeping the fixed three-row
  mobile header with no wrapped or scrolling button rows; desktop
  renders inline via display:contents (same DOM, same handlers)

Profile pictures:
- users.avatar (migration 010) + PUT/GET/DELETE /api/account/avatar;
  client-side centre-crop resize to 128px JPEG; avatar shows in the nav
  chip on every page; included in full backups

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 08:17:10 -04:00
Shane MaynardandClaude Fable 5 e62b9601a2 Add Equipment page: owned brewers and grinders filter the Brews UI
Test and deploy / test-and-deploy (push) Successful in 59s
- user_gear table (migration 008) + GET/PUT /api/gear (brewer keys
  validated against the taxonomy, grinders deduped/trimmed)
- /gear page: silhouette multi-select for owned brewers (autosaves) and
  a grinder list; nav gains Brewing → Equipment
- Brews page: with gear configured, the picker shows only owned brewers
  (plus the edited brew's method) with a show-all toggle; grinder field
  suggests your grinders; empty-gear state links to /gear
- Included in full backups, per-user export, and the OpenAPI spec

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 08:08:32 -04:00
Shane MaynardandClaude Fable 5 3bceb44ae3 Move the planner's page-scoped tools from the left nav into the page header
Test and deploy / test-and-deploy (push) Successful in 1m4s
The Tools group (Plans, Ask the LLM, Prefill, Curves, Import/export,
Field IDs, Settings) acted on the open plan, not on navigation — it now
renders as compact action buttons in the planner header's existing
actions row (wrapping on narrow screens), and the left rail is pure
navigation, identical on every page.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 08:05:45 -04:00
Shane MaynardandClaude Fable 5 c130efb180 Prefill: classify unknown cultivars into a reference group so the ledger still computes
Test and deploy / test-and-deploy (push) Successful in 59s
The extraction schema gains cultivarGroup (typica/bourbon/ethiopian/
hybrid, classified by the LLM from coffee genetics); when the named
variety isn't in the cultivar table, deriveFields now falls back to the
group's first-crack anchor (number still comes only from the reference
table) instead of leaving 1.4 blank and breaking every downstream
calculation. deriveFields exported + unit-tested.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 08:03:46 -04:00
Shane MaynardandClaude Fable 5 f781930832 Add a Recipe/steps field to brew logging
Test and deploy / test-and-deploy (push) Successful in 1m16s
Free-text recipe (bloom, pours, timings) distinct from tasting notes and
next-time notes: new brews.recipe column (migration 007), form textarea,
shown under the recipe summary in brew history, carried by Brew again,
included in backups and the OpenAPI spec.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-09 08:02:06 -04:00
Shane MaynardandClaude Fable 5 16d5af83f7 Add Hario Switch to the brewer picker (immersion)
Test and deploy / test-and-deploy (push) Successful in 53s
Also test that every brew method ships a silhouette so the picker can
never render an empty tile.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-08 23:18:25 -04:00
Shane MaynardandClaude Fable 5 38c7d01e03 Add brewing section, plan chat, roaster learning, API tokens, Swagger docs, and full backup
Test and deploy / test-and-deploy (push) Successful in 1m6s
Brewing:
- roasted_beans + brews tables; /beans (bean management with LLM URL
  prefill) and /brews (silhouette brewer picker across immersion/
  percolation/espresso, recipe fields, auto ratio, 0-10 rating, tasting
  notes); bean remaining weight derived from logged brew doses
- Green inventory lot form also prefills from a product URL

Navigation/UX:
- Side nav is now generated from one definition in nav.js, grouped
  Roasting / Brewing / account, consistent on every page

LLM:
- 'Ask the LLM' chat drawer on the planner (stateless /api/plan-chat)
  grounded in the plan, computed ledger, learned pace, and a new
  roaster-behavior profile aggregated from uploaded .alogs
  (/api/roaster-profile: TP lag, phase RoR, median milestone temps)
- The profile also feeds roast reviews and the planner curve's fallback
  milestone temps

API platform:
- User-generated bearer tokens (rpt_…) with account-page management;
  token requests skip CSRF; hand-authored OpenAPI 3 spec at
  /api/openapi.json rendered by self-hosted Swagger UI at /api-docs
- Full-database backup export/import (admin) + per-user data export

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-08 22:37:42 -04:00
Shane MaynardandClaude Fable 5 5efaeb63c9 Add admin LLM model setting; rename Pi to LLM in the UI; drop table Review column
Test and deploy / test-and-deploy (push) Successful in 49s
- New server/llm.js consolidates ModelRuntime + model selection: admin
  setting (app_settings.llm_model) > LLM_MODEL/PREFILL_MODEL env > first
  available; used by both prefill and roast evaluation
- GET/PUT /api/admin/llm lists configured models and stores the choice
  (validated against the list; empty = auto; audited); admin page gains
  an LLM section with a model picker
- All user-facing 'Pi agent' wording is now 'LLM'; no_model error message
  no longer references the pi CLI
- /roasts table: Review column removed (review lives in the detail view)

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-08 22:12:42 -04:00
Shane MaynardandClaude Fable 5 eb82263ead Add finished-roast .alog uploads with Pi agent deep review and /roasts history
Test and deploy / test-and-deploy (push) Successful in 1m39s
- POST /api/roasts stores the original .alog verbatim (multiple per plan),
  parses it server-side, and kicks off an async zero-tool Pi agent review
  (grade, highlights, concerns, next-batch suggestions, plan-vs-actual)
- /roasts page: table of historical actual roasts with review summaries;
  row detail renders the BT curve as SVG with the plan curve overlaid,
  shows the full review, and offers original-.alog backup download,
  re-evaluate, and delete
- Planner's Reference curve drawer gains a multi-file finished-roast
  uploader that attaches to the open (synced) plan
- Failed reviews record the error on the row and are retryable via
  POST /api/roasts/:id/evaluate (e.g. once a model is configured)

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-08 20:18:22 -04:00
snowspeederandClaude Sonnet 5 84ce75dc14 Fix New plan feeling like a no-op; add plan delete and why-panel collapse
Test and deploy / test-and-deploy (push) Successful in 1m34s
New plan reset the form correctly but left the Plans drawer open over
it, so the reset was invisible until the user closed the drawer
themselves. Now closes it immediately, matching selectPlan().

Also adds a delete button per plan in the Plans drawer (server route
already existed) - deleting the currently open plan resets to a fresh
blank one, matching New plan.

Why-panel teaching callouts ("WHY CULTIVAR SETS THE CLOCK" etc.) now
default collapsed instead of wall-to-wall expanded on first load, with
an "Expand all" button in the header on both the planner and cupping
pages. Persistence flips from tracking collapsed-vs-default-open to
expanded-vs-default-closed to match.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-07-31 15:34:56 -04:00
snowspeederandClaude Sonnet 5 2237c199c1 Add per-user learned machine profile; fix methodology honesty issues
Test and deploy / test-and-deploy (push) Successful in 1m26s
Replaces the flat additive batch-size correction with a per-user
multiplicative pace factor learned from each account's own logged
roasts (shared/learn.js, GET /api/machine-profile), plus a lot-scoped
"last refine" auto-suggestion. Also fixes the reference data being
framed as "your own roasts" on a now-multi-user product, and
reclassifies the drying/Maillard sanity checks as informational since
they're algebraically derived from the DTR check rather than
independent (yellow = 0.56 x first crack, not entered separately).

Bug fixes found by an adversarial Opus review of the first pass:
- Unicode minus sign (U+2212) broke duration parsing against the
  app's own generated refine-suggestion text
- Printed sanity-checks table still showed a bare pass/fail glyph for
  the now-informational drying/Maillard rows
- Printed time-ledger box didn't show the pace multiplication step,
  so it stopped reconciling by hand once pace != 1
- Field 6.4 (manual batch correction) was double-counted: excluded
  from the learned-pace fit but added back after the multiplication
- Learned pace had no outlier rejection or hard clamp
- computeLedger had no test coverage
- Batch-size help copy overstated what the pace factor models (it's
  a single blanket ratio, not conditioned on batch weight)

A follow-up Opus pass also caught the per-user profile cache
surviving logout/account-switch in a shared browser; fixed by
sweeping it alongside the existing plan-draft cleanup.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-07-31 12:40:03 -04:00
snowspeederandFable 0a0356b86e Fix field-help review findings (Fable review + Opus verification)
Test and deploy / test-and-deploy (push) Successful in 1m25s
Highest severity: injected "?" buttons were hijacking the implicit
<label> association on 14 fields, so clicking the label text opened
the help dialog instead of focusing the input and screen readers lost
the input's accessible name. ensureLabelAssociation() now gives each
affected input an explicit id/for pairing before the button lands.

Also: milestones-ror/actuators topic placement is now text-matched
with a warning fallback instead of blind array indexing; every topic
warns if it resolves zero containers; dialog temperatures (milestone
table, RoR budget, worked example, both charge-setting tables) now
respect the °C/°F toggle instead of being stuck in °C; the print
worksheet's duplicate curve chart was missing the data-tempc
attributes its live counterpart had, so only its title/caption (not
its axis numbers) converted; the "?" trigger's touch target grew from
15px to a WCAG-conformant ~25px without changing the visual dot; two
genuine coverage gaps closed (a roast-log checklist topic, a
curve-reading topic); a worked feasibility example was restored; two
claims that didn't trace back to the source worksheet were corrected
(an invented "±15 seconds" sweet-spot tolerance, a wrong
moisture-to-time mapping); three cultivar cells regained detail lost
in the original transcription; a data-transcription footnote no
longer leaks into an unrelated topic; checklist items keep their list
semantics under VoiceOver.

Co-Authored-By: Fable <[email protected]>
Co-Authored-By: Opus <[email protected]>
2026-07-31 07:17:44 -04:00
snowspeederandClaude Sonnet 5 84fb396c7d Add field help dialog with cultivar/process reference notes
Test and deploy / test-and-deploy (push) Successful in 1m32s
Adds a help-dialog UI (field-help.js/field-help-content.js) surfacing
per-field guidance, expands cultivar and process reference data with
cup notes, sweet-spot width, and watch-fors, and adds a Makefile for
common npm tasks.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-07-31 06:37:33 -04:00
snowspeeder df5c4aef48 Document Gitea Actions deployment workflow
Test and deploy / test-and-deploy (push) Successful in 1m4s
2026-07-31 06:30:20 -04:00
snowspeeder e51bfd3dca Wait for application readiness in deployment
Test and deploy / test-and-deploy (push) Successful in 55s
2026-07-31 06:27:09 -04:00
snowspeeder 19fc1e4dcb Isolate Gitea Actions build workspace
Test and deploy / test-and-deploy (push) Failing after 56s
2026-07-31 06:24:49 -04:00
snowspeeder 0a160f0800 Verify Actions checkout before tests
Test and deploy / test-and-deploy (push) Failing after 53s
2026-07-31 06:20:53 -04:00
snowspeeder 1cc3f72a62 Allow CI container tests beside production
Test and deploy / test-and-deploy (push) Failing after 49s
2026-07-31 06:17:58 -04:00
snowspeeder 7c9e5b0d0d Add Gitea Actions deployment workflow
Test and deploy / test-and-deploy (push) Failing after 1m15s
2026-07-31 06:15:08 -04:00
snowspeeder 45e67c918f Document Unraid deployment automation 2026-07-31 06:09:01 -04:00
snowspeeder 8d6c471b10 Seed writable Pi runtime config in Docker 2026-07-30 20:31:10 -04:00
snowspeeder 1a63da77f3 Generate asset versions during Docker builds 2026-07-30 18:37:39 -04:00
snowspeeder eec422661b Version static app assets for CDN releases 2026-07-30 18:37:39 -04:00
snowspeeder 792714c6d5 Bust cached stylesheet on deploy 2026-07-30 18:37:39 -04:00
snowspeeder 5a780cefa8 Convert every remaining °C reference to the temp-unit toggle
The Machine Plan chart's axis ticks and first-crack band caption, the
print worksheet's axis title, and its "Your logged band" reference
column were all still hardcoded in °C. They're now data-driven
(data-tempc / data-band-lo / data-band-hi) and update alongside every
other temperature field when the unit is switched.
2026-07-30 16:57:30 -04:00
snowspeeder 306d256832 Add a °C/°F display toggle for Machine Plan and Roast Log temps
Plans are always stored in canonical °C; the unit is a client-side
display preference (localStorage) that converts Machine Plan planned
temps, Roast Log actual temps, and actuator expected BT on the fly,
including band-marker positioning. Toggle lives in Settings & sync.
2026-07-30 16:51:01 -04:00
snowspeeder 5ef82748ea Merge branch 'feature/commercial-redesign'
Commercial redesign: landing page, session-cookie auth (signup/login/
forgot/reset), side-nav app shell, full account and admin pages, and
a teaching-layer UI overhaul. Adds green-bean inventory management
and SCA-style cupping scoring ported from hope_roaster.
2026-07-30 15:41:33 -04:00
snowspeeder 59645e59b5 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.
2026-07-30 14:47:15 -04:00
snowspeeder 9f0a3dbc74 Fallback to Browserless for rate-limited prefills 2026-07-30 08:16:22 -04:00
snowspeeder f3d026a109 Fix planner review findings 2026-07-30 08:11:08 -04:00
snowspeeder 7416898bec Elevate planner UX and offline resilience 2026-07-30 07:03:35 -04:00
snowspeeder 057d68156b Polish planner styling 2026-07-30 06:37:41 -04:00
snowspeeder 99d7e8f121 fix: make account menu actions reliable 2026-07-29 23:29:01 -04:00
snowspeeder 8f82000e31 feat: replace account actions with menu 2026-07-29 23:25:49 -04:00
snowspeeder 089ee6916f fix: refresh installed clients and hide admin control by role 2026-07-29 23:08:32 -04:00
snowspeeder 122427d30d fix: redirect authenticated users to planner 2026-07-29 22:56:06 -04:00
snowspeeder f56dc8efa9 feat: allow initial admin setup from landing page 2026-07-29 22:12:37 -04:00
snowspeeder 22e6e721a7 chore: format auth code and update runtime 2026-07-29 22:11:08 -04:00