critical priority medium complexity backend pending backend specialist Tier 0

Acceptance Criteria

A pure Dart function `double relativeLuminance(Color color)` is implemented with no Flutter widget dependencies
The function linearizes each RGB channel using the IEC 61966-2-1 formula: channel <= 0.04045 ? channel/12.92 : ((channel+0.055)/1.055)^2.4
Luminance is computed as L = 0.2126*R + 0.7152*G + 0.0722*B on linearized channels
A function `double contrastRatio(Color foreground, Color background)` returns (L1+0.05)/(L2+0.05) where L1 >= L2
White on black returns exactly 21.0 (within floating-point epsilon of 0.001)
Black on black returns exactly 1.0
The implementation handles Color values with alpha channel by using only the RGB components (alpha ignored per WCAG spec)
No external dependencies beyond `dart:ui` (Color class from Flutter SDK) are introduced
The functions are placed in a file that can be imported by both Flutter app code and standalone Dart CLI scripts

Technical Requirements

frameworks
Dart
Flutter (dart:ui Color class)
performance requirements
contrastRatio() executes in under 1 microsecond per call — it is pure math with no I/O

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Place the implementation in `lib/core/accessibility/contrast_ratio_calculator.dart` (or equivalent path under `src/`). Keep the file free of any Flutter widget imports so it can be used in CLI dart scripts — import only `dart:ui` for the Color type, or accept raw RGB int values and provide a factory constructor that takes a Flutter Color. The IEC 61966-2-1 linearization formula is the most commonly mis-implemented part: the exponent is 2.4, not 2.2, and the threshold is 0.04045, not 0.03928 (the older WCAG 2.0 value). Use the 2.4/0.04045 values for WCAG 2.2 compliance.

Avoid using `dart:math` `pow()` in a hot loop — it is fine here since this is not called in build methods, but document the performance characteristic. Consider exposing both `relativeLuminance` and `contrastRatio` as top-level functions (not class methods) for ease of use in tests and scripts.

Testing Requirements

Write flutter_test unit tests covering: (1) white (#FFFFFF) on black (#000000) = 21.0 ±0.001, (2) black on white = 21.0 ±0.001 (symmetric), (3) mid-grey (#777777) on white — compute expected value manually and assert within 0.01, (4) identical colors = 1.0, (5) WCAG sample pair #595959 on white = 7.0 (AA large pass), (6) negative: #AAAAAA on white = ~2.32 (AA fail). Use `closeTo` matcher for all floating-point assertions. 100% branch coverage on the linearization branch (<=0.04045 vs >0.04045 paths).

Component
Contrast Ratio Validator Service
service medium
Epic Risks (3)
high impact medium prob technical

The WCAG 2.2 relative luminance formula requires gamma-corrected sRGB calculations. Floating-point rounding differences between Dart and reference implementations could produce off-by-one classifications for near-threshold color pairs, resulting in pairs that just pass or just fail in CI but behave differently at runtime.

Mitigation & Contingency

Mitigation: Implement the algorithm directly from the WCAG 2.2 specification using the exact linearisation constants. Validate the Dart implementation against the W3C reference test vectors and against a known-good JavaScript implementation for at least 50 color pairs spanning the compliance boundaries.

Contingency: If discrepancies are found, add a configurable tolerance margin (e.g., ±0.005 on the ratio) and flag near-threshold pairs as warnings rather than hard failures, escalating to the design team for manual review.

medium impact high prob scope

The token manifest is a static data file. If developers add new color tokens to the design-token-provider without updating the manifest, the manifest becomes stale and the CI validator produces false negatives — passing builds that contain unvalidated color pairs.

Mitigation & Contingency

Mitigation: Add a CI step that cross-references every token constant exported by the design-token-provider against the manifest at build time, failing if any token is present in the provider but absent from the manifest. Document this requirement clearly in the contributing guide.

Contingency: If drift is detected post-merge, run a full manifest regeneration script and treat the resulting manifest diff as a blocking pull request with mandatory accessibility review.

medium impact medium prob dependency

The flutter_accessibility_lints package (or custom lint rules) may produce false positives on patterns the team deliberately uses — for example, decorative icon widgets that intentionally omit semantic labels. Excessive false positives will lead developers to add blanket ignore comments, undermining the entire lint strategy.

Mitigation & Contingency

Mitigation: Audit the full lint rule set against the existing codebase before enabling rules. Create a documented list of approved ignore-comment patterns with mandatory justification comments. Restrict ignore patterns to decorative-only contexts.

Contingency: If false positive rates exceed 10% of lint output, disable the highest-noise individual rules and replace them with targeted custom lint rules scoped to the specific patterns the team controls.