- #42: Replace deficit framing — "You'd need:" → "To complete this recipe:", element_gaps
card-warning → card-secondary, missing/gap chips status-warning → status-info,
"Your pantry is missing..." → "These would expand your options:"
- #46: Add activeNutritionFilterCount computed; show count in Advanced filters summary
when filters are active so it's visible while collapsed
- #47: Wildcard confirmation status-warning → status-info, copy updated to calm framing;
wildcard recipe card badge status-warning → status-info
- M1: Add re-search hint below Hard Day Mode toggle when results are already showing
- M8: Move swap candidates collapsible to after directions/steps section
- L2: Add autocomplete="off" to filter search, constraint, and allergy text inputs
- L5: Add title="This is an affiliate link" disclosure to grocery affiliate links
Items already correct (no change needed):
- M2: Level description already always visible via activeLevel computed
- M3: Rate limit copy already using calm framing
- M5: No-results copy already calm
- M6: levelLabels already uses full names
- M7: "that's part of the fun" was part of the wildcard copy fixed under #47
- L1: Neon/konami handler not present in this file
- Import and mount OrchUsagePill near the recipe level selector in RecipesView;
pill is self-hiding when not enabled or no lifetime key is present
- Add useOrchUsage composable to SettingsView with a Display section checkbox
so users can opt in to seeing the cloud recipe call budget pill
- Add @/ path alias to vite.config.ts and tsconfig.app.json to resolve the
existing @/services/api import in useOrchUsage.ts (fixes vite build error)
- tsc --noEmit and vite build both pass clean
- Default app landing changed from Pantry to Recipes tab
- Pre-fetch inventory on app mount so Find tab has data immediately
- Reorder recipe sub-tabs: Saved > Build Your Own > Community > Find > Browse
- Default active sub-tab changed to Saved
- Auto-redirect from Saved to Build Your Own when saved list is empty
- Add freeform custom ingredient input: typing a non-pantry item now shows
"Use X anyway" button so users aren't blocked on unknown ingredients
- PublishPayload gains optional slots field; PublishPlanModal maps
plan.slots into the payload so the backend can compute element
snapshot scores (seasoning, richness, etc.) from actual recipes
- plan-forked emit type updated to ForkResult across CommunityFeedPanel
and RecipesView so forked_from is preserved for future navigation
- Add migration 021: recipe_browser_fts FTS5 table on category + keywords
columns, eliminating LIKE '%keyword%' full sequential scans on 3.1M rows
- _count_recipes_for_keywords now uses FTS5 MATCH (O(log N) vs O(N))
- browse_recipes reuses cached count, eliminating the second COUNT(*) scan
per page request; ORDER BY r.id replaces the unindexed ORDER BY title sort
- Module-level _COUNT_CACHE keyed by (db_path, keywords) means domain-switch
category counts are computed once per process lifetime
feat(find): dietary preset grid, Big 9 allergen pills, Hard Day Mode surface
- Dietary constraints replaced with toggle-button preset grid (8 options)
+ free-text "Other" field; removes dense freeform text input
- Allergies replaced with Big 9 pill picker (peanuts, tree nuts, shellfish,
fish, milk, eggs, wheat, soy, sesame) + "Other" for custom entries
- Hard Day Mode surfaced as a standalone aria-pressed button above the
dietary collapsible; no longer buried inside a collapsed section
- Active-state dot indicators on both collapsibles show filter engagement
at a glance without expanding
fix(a11y): aria-describedby wiring for wildcard checkbox and tag inputs (#40)
- Persistent hint spans replace placeholder-only instructions for constraint
and allergy fields (WCAG 3.3.2)
fix(browse): auto-select highest-count category on domain switch (#41)
- Eliminates the 3-decision cold start (domain → category → content)
- Surprise Me button added for zero-decision random navigation
- "Use What I Have" / "Allow Swaps" / "Get Creative" / "Surprise Me 🎲"
- Active level shows a one-liner description beneath the selector
- Hover tooltips repeat the description for mouse users
- Label changed from "Creativity Level" to "How far should we stretch?"
- Wildcard confirmation copy updated to match new framing
- Style/category filter panel with active chip display
- Dismiss (excluded_ids) support — recipes don't reappear until next fresh search
- Load more appends next batch without full re-fetch
- Prep notes 'Before you start:' section above directions
- Nutrition macro chips (kcal, fat, protein, carbs, fiber, sugar, sodium)
- Composables extracted for reuse
- EditItemModal: replace all hardcoded colors (#eee, #f5f5f5, #2196F3, etc.) with CSS variable tokens; restyle modal header with display font, blur backdrop, and theme-aware form elements
- ReceiptsView: replace emoji headings, hardcoded spinner, and non-theme .button class with themed equivalents; all colors through var(--color-*) tokens
- RecipesView: fix broken --color-warning-rgb / --color-primary-rgb references (not defined in theme); use --color-warning-bg and --color-info-bg instead; apply section-title to heading
- SettingsView: apply section-title display-font class to heading for consistency
- InventoryList: remove three dead functions (formatDate, getDaysUntilExpiry, getExpiryClass) that caused TS6133 build errors
- RecipesView: level selector (1-4), constraints/allergies tag inputs,
hard day mode toggle, max missing input, expiry-first pantry extraction,
recipe cards with collapsible swaps/directions, grocery links, rate
limit banner
- SettingsView: cooking equipment tag input with quick-add chips, save
with confirmation feedback
- stores/recipes.ts: Pinia store for recipe state + suggest() action
- stores/settings.ts: Pinia store for cooking_equipment persistence
- api.ts: RecipeRequest/Result/Suggestion types + recipesAPI + settingsAPI
- App.vue: two new tabs (Recipes, Settings), lazy inventory load on tab switch