- /city /deb now free, capped at 10/day each (was 2 pts cost)
- Welcome bonus +20 pts on first-ever valid message
- First-message-of-day bonus +2 pts
- Weekly winner point bonuses reduced (500→200, 300→100, 150→50)
- Weekly participation rewards for all active users (+5 base, +15 for ≥20 pts)
- Pro-day rewards for top 3 unchanged
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Removed the scan KPI bar, trimmed redundant decision-card content, and shortened the primary reason text so the city analysis cards read like concise signals instead of repeating the same state across sections.
Constraint: Keep existing city decision logic and data flow unchanged while simplifying the UI
Rejected: Rework the full card layout or mobile card flow | larger surface area than requested
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep hero, decision band, and market line responsibilities separate to avoid duplicate copy returning
Tested: frontend npm run build
Not-tested: Manual visual QA in browser across desktop/mobile breakpoints
Mobile review found that account payment rows could collapse labels vertically and several secondary links had small touch targets on narrow phones. The patch keeps the existing visual system but allows account rows to stack on mobile, improves tap height, and tightens the Scan Terminal narrow-screen container.
Constraint: Must keep the current desktop layout and avoid adding dependencies
Rejected: Rebuild the account page layout wholesale | too broad for a targeted mobile audit
Confidence: high
Scope-risk: narrow
Directive: Keep long account/payment identifiers breakable on narrow screens
Tested: iPhone SE and iPhone 12 Playwright mobile audits show no horizontal overflow on checked pages
Tested: npx tsc --noEmit --pretty false --project frontend/tsconfig.json
Tested: npm run build
Tested: npm run test:business
Not-tested: Authenticated /ops data state because local Supabase/admin gating redirects to the public shell
Proxy routes now share one upstream-error adapter so client-actionable statuses such as auth, entitlement, validation, and rate limits survive the BFF instead of becoming opaque 502s. The scan terminal mobile overrides also load last and remove desktop rail constraints so phones get a single readable column.
Constraint: Mobile users reported the dashboard was unreadable, and BFF proxy errors were masking expected client states.
Rejected: Let every route keep bespoke error JSON | continued inconsistent status codes and production detail leakage.
Confidence: high
Scope-risk: moderate
Directive: Keep ScanTerminalMobile.module.css imported after desktop scan-terminal CSS so mobile breakpoints win.
Tested: npx tsc --noEmit --pretty false --project frontend/tsconfig.json
Tested: npm run build
Tested: npm run test:business
Tested: Chrome mobile smoke test at 390px with no horizontal overflow
Not-tested: Real device Safari/Android manual QA
The dashboard had several oversized orchestration, component, and CSS files that made product-copy changes and mobile/performance work risky. This refactor preserves behavior while splitting scan terminal CSS, opportunity helpers, future forecast panels, history/detail charts, and probability/model sections into smaller ownership boundaries.
Constraint: No user-visible version bump because this batch is architecture and performance cleanup, not a release announcement.
Rejected: Rewrite dashboard state management in the same batch | too broad for a safe upload after CSS and component splitting.
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep new component/CSS boundaries instead of moving product copy back into the large dashboard files.
Tested: npm run build; npm run test:business; git diff --check
Not-tested: Browser visual smoke test after push
The scan terminal had grown into overlapping CSS, request-state, AI-provider, and city-card data responsibilities. This refactor separates those boundaries without changing product behavior: CSS modules are split by surface, city AI prompt/provider/fallback logic is isolated, and scan terminal request state now has reusable RemoteData adapters plus business-state tests.
Constraint: Preserve existing global scan-terminal class names and API responses during the refactor
Constraint: No new dependencies; keep this as a file-boundary cleanup
Rejected: Introduce React Query now | higher migration risk than the requested lightweight query-client path
Rejected: Rewrite AI stream behavior | progressive/fallback states are product-sensitive and were only adapter-split
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep AI stream state changes covered by business snapshots before changing fallback/cache wording
Tested: npm run test:business; npx tsc --noEmit; npm run build; python pytest -q; ruff check; py_compile targeted city AI modules
Not-tested: Live DeepSeek provider network replay and browser visual QA
The dashboard risk is now mostly contradictory state combinations rather than styling. This extracts calendar action grouping into a pure utility and adds a lightweight TypeScript business-state runner so key decision states can be asserted without adding a test dependency.
Constraint: No new dependencies; use the existing TypeScript package for a local runner.
Rejected: Only rely on Next build/typecheck | it cannot catch product-language regressions such as fallback AI being labeled complete.
Confidence: high
Scope-risk: moderate
Reversibility: clean
Tested: npm run test:business
Tested: npm run build
Not-tested: Browser-rendered mobile fold interaction snapshots.
Phone users need the city card to answer what matters first instead of inheriting the full desktop analysis hierarchy. This adds a MobileDecisionCard that leads with city, observed temperature, expected high, peak window, one decision reason, status tags, freshness, and a separate market-price row, while keeping AI, model evidence, and the chart behind collapsible sections.
Constraint: Preserve the existing desktop city-card layout and decision state semantics.
Rejected: Continue relying only on CSS hide/show | it keeps mobile coupled to the desktop information architecture.
Confidence: high
Scope-risk: moderate
Reversibility: clean
Tested: TypeScript diagnostics for AiPinnedCityCard and MobileDecisionCard
Tested: npm run build
Not-tested: Device screenshot QA across iOS/Android viewport sizes.
Weather labels, METAR translation, risk badges, and hero meta chips were still embedded in dashboard-utils even though panel, modal, and detail views use them as focused presentation helpers. This moves them into weather-summary-utils while keeping dashboard-utils re-export compatibility.
Constraint: Preserve existing weather/METAR/risk/hero meta wording.
Rejected: Move airport narrative in the same pass | it has broader AI narrative coupling and should be separated independently.
Confidence: high
Scope-risk: narrow
Reversibility: clean
Tested: TypeScript diagnostics for weather-summary-utils, dashboard-utils, PanelSections, DetailPanel, and FutureForecastModal
Tested: npm run build
Not-tested: Visual snapshot of every weather icon/label combination.
Probability and multi-model view adapters were still embedded in dashboard-utils even though table, panel, modal, and city-card views use them as small pure selectors. This moves them into model-utils and keeps dashboard-utils re-export compatibility.
Constraint: Preserve model/probability return shapes and existing fallback behavior.
Rejected: Merge model-utils with chart-utils | model selectors and chart data preparation change at different rates.
Confidence: high
Scope-risk: narrow
Reversibility: clean
Tested: TypeScript diagnostics for model-utils, dashboard-utils, and PanelSections
Tested: npm run build
Not-tested: Bundle analyzer size comparison.