high priority low complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

Widget renders two labelled numeric input fields: 'Number of sessions' (min 1, max 9999) and 'Session duration in minutes' (min 5, max 480)
Each field includes increment/decrement stepper buttons with minimum tap target size 48x48dp per WCAG 2.2 AA
Inline validation error messages appear immediately when value is outside allowed range; errors are dismissed as soon as value re-enters valid range
Every interactive element and error message has a correct Semantics widget with label, hint, and value populated for VoiceOver/TalkBack
onChange callback fires with current (sessionCount, durationMinutes) tuple on every valid value change
onChange is NOT fired when values are in an invalid state to prevent propagating bad input to BLoC
Widget uses only design token constants for colors, typography, and spacing — zero hardcoded hex values or magic numbers
Dark mode renders correctly: background, field fill, label, error, and stepper icon colors all switch via ThemeData token lookup
Stepper buttons are disabled (greyed out, non-interactive) at boundary values to prevent out-of-range tap
Widget is stateless — all values are passed in via constructor; internal editing state managed by a StatefulWidget wrapper that calls onChange
Direct keyboard numeric entry is supported; non-numeric input is rejected silently without error flash
Widget renders correctly at 1.0x, 1.5x, and 2.0x text scale factors without layout overflow

Technical Requirements

frameworks
Flutter
BLoC
performance requirements
onChange callback debounced by at most 100ms to avoid excessive BLoC event dispatch on rapid stepper taps
Widget rebuild limited to inner StatefulWidget scope — no ancestor tree rebuild on value change
security requirements
Input clamped server-side as well; client-side min/max is UX only, not a security boundary
ui components
CalculatorInputPanel (StatefulWidget)
NumericStepperField (inner reusable field+stepper composite)
Semantics wrapper on each field, stepper button, and error text

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Use a StatefulWidget that holds internal TextEditingController instances; parse and clamp on every change event rather than only on submission to give immediate feedback. Stepper buttons call _increment/_decrement helpers that call setState and trigger onChange if result is valid. Define min/max as constructor parameters with defaults so the widget can be reused for other numeric inputs in the codebase. Apply InputDecoration using Theme.of(context).inputDecorationTheme so dark mode switches automatically.

Keep error string in the widget's local state — do not route errors through BLoC, that keeps BLoC focused on business state. Import design token constants from the project's tokens file; never reference raw Color values inline.

Testing Requirements

Unit tests (flutter_test): test onChange fires on valid input, does not fire on invalid input, boundary values (min-1, min, max, max+1) emit correct error/no-error states, stepper buttons disabled at boundaries. Widget tests: golden snapshot at light/dark mode and 1.0x/2.0x text scale. Accessibility test: ensure Semantics tree has non-empty labels for all interactive nodes. Target coverage ≥ 90% on widget logic.

Component
Calculator Input Panel
ui low
Epic Risks (3)
high impact medium prob technical

The RepaintBoundary PNG capture approach for sharing the results card may produce blurry or oversized images on high-DPI devices, or may silently fail on certain Android OEM configurations that restrict off-screen rendering. A failed share would break one of the core use cases (recruitment tool).

Mitigation & Contingency

Mitigation: Implement the capture using the established screenshot-capture-utility pattern already present in the Wrapped summary feature (component 542-screenshot-capture-utility). Test on a range of iOS and Android devices including Samsung and Huawei OEM builds during development. Set explicit pixel ratio (3.0) when calling toImage() to guarantee resolution.

Contingency: If image capture fails on a platform, the BenefitShareService falls back to sharing the plain-text summary only, with a user-facing message explaining the image could not be generated. This ensures the share flow never fully blocks.

high impact medium prob technical

Implementing full WCAG 2.2 AA compliance for the results card and metric tiles — including live regions, focus management, and semantic labels that read naturally in Norwegian — requires deep familiarity with Flutter semantics APIs. Gaps may only surface during screen reader testing on physical devices, late in the sprint.

Mitigation & Contingency

Mitigation: Use the existing semantics-wrapper-widget (606) and live-region-announcer (608) components from the accessibility feature rather than implementing custom semantics. Assign screen reader testing on a physical iPhone with VoiceOver as a mandatory acceptance gate, not an afterthought. Write widget tests using Flutter's AccessibilityGuideline matchers early in development.

Contingency: If screen reader issues are found late, the pure semantic markup approach (no Canvas numbers, all Semantics wrappers) limits the blast radius to label text corrections. Escalate to the accessibility feature team for a pairing session to resolve complex focus management issues.

medium impact low prob integration

The BenefitResultsCard must match the Wrapped design language used in the annual summary feature. If design tokens or widget patterns are inconsistent between the two features, the results card will look out of place and undermine the intended emotional impact for sharing.

Mitigation & Contingency

Mitigation: Review the existing Wrapped summary screen (529-wrapped-summary-screen) and stat card widget (530-stat-card-widget) implementations before building the results card. Reuse design tokens from the existing design-token-theme (200) system. Involve the designer in a review of the results card mock-up against the Wrapped language before implementation begins.

Contingency: If design parity issues are discovered post-implementation, isolate visual adjustments to the BenefitResultsCard widget. The feature's business logic and accessibility compliance are unaffected by visual polish changes.