high priority low complexity frontend pending frontend specialist Tier 3

Acceptance Criteria

All colour values in BadgeCardWidget are referenced from the project's design token system (e.g., AppColors, AppTheme tokens) — no hardcoded hex or Color() literals
The earned badge card background and text colour combination achieves a WCAG 2.2 AA contrast ratio of at least 4.5:1 for normal-size badge name text
The earned badge card accent border or highlight colour achieves at least 3:1 contrast against the card background (large text / UI component threshold)
The locked badge card uses a muted/greyscale design token and its text still meets 4.5:1 contrast against the locked card background
In Flutter debug mode (kDebugMode), BadgeIconAssetManager.validateContrastRatio is called during widget construction and logs a warning (or asserts) if contrast fails
No debug-mode contrast assertion fires for any of the default design token combinations
The widget passes an automated contrast check using a test helper that calls validateContrastRatio with the exact token colour values used
Switching the app theme (if dark mode tokens exist) does not break contrast compliance — verified by running contrast assertions for both light and dark token sets

Technical Requirements

frameworks
Flutter
performance requirements
Contrast validation in debug mode must not add more than 1 ms to widget build time
Design token lookups must be constant-time (const or static field access)
ui components
BadgeCardWidget (updated)
Design token classes (AppColors / AppTheme)
BadgeIconAssetManager.validateContrastRatio

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

The WCAG 2.2 AA relative luminance formula (IEC 61966-2-1) is: L = 0.2126*R + 0.7152*G + 0.0722*B where sRGB channels are linearised. Contrast ratio = (L1 + 0.05) / (L2 + 0.05). Implement this in BadgeIconAssetManager.validateContrastRatio if not already done. Wrap the debug-mode assertion in an assert() statement or a kDebugMode guard so it is completely stripped in release builds — do not use if (kDebugMode) without confirming tree-shaking eliminates it.

Prefer token names that encode their intent (e.g., badgeEarnedBackground, badgeEarnedText) over generic palette names to make future token swaps safe. The greyscale locked variant should use the same token family as disabled UI elements already defined in the project's design token system for visual consistency.

Testing Requirements

Write unit tests that: (1) call BadgeIconAssetManager.validateContrastRatio with the earned card foreground/background token colour pair and assert it returns true (passes AA), (2) call validateContrastRatio with a known-failing pair (e.g., light grey on white) and assert it returns false, (3) verify the locked card text colour tokens also pass 4.5:1 via the same validator. Write a widget test that constructs BadgeCardWidget in debug mode and asserts no FlutterError or assertion error is thrown. If golden tests exist from task-008, update them to reflect the token-driven styling.

Component
Badge Card Widget
ui low
Epic Risks (2)
high impact medium prob scope

Badge criteria are stored as structured JSON in badge_definitions. If the JSON schema for criteria (threshold counts, streak lengths, training completion flags) is not well-defined upfront, the evaluation service will be built against a moving target, requiring costly migrations and refactors.

Mitigation & Contingency

Mitigation: Define and document the criteria JSON schema in a shared type file before any repository code is written. Review the schema with all three organisations' badge requirements — especially Blindeforbundet's honorar thresholds — and version the JSON schema using a 'criteria_version' field from day one.

Contingency: If the criteria schema must change after services are built, write a Supabase migration to backfill existing rows and add a migration version column. Keep the evaluation service criteria parser isolated behind an interface so only one function needs updating.

medium impact medium prob dependency

Badge icon assets may not yet exist or may fail WCAG 2.2 AA contrast validation (minimum 3:1 for graphical objects) when rendered over design-token backgrounds. Missing or non-compliant icons could block UI epic delivery for Blindeforbundet, for whom screen reader and visual accessibility is non-negotiable.

Mitigation & Contingency

Mitigation: During this epic, implement the contrast-ratio validator in badge-icon-asset-manager and run it as a Flutter test against all candidate icon assets early. Coordinate with the design team to provide WCAG-compliant SVG icons in both locked and unlocked variants before the UI epic begins.

Contingency: If assets are late or fail contrast checks, ship placeholder icons that are guaranteed compliant (solid design-token colour fills with text labels) and swap in final assets post-QA without requiring a code change.