# Module: `src/class-colors/classColors.ts`

> **Source**: `src/class-colors/classColors.ts` (24 lines; moved from `src/features/annotations/classColors.ts` by AZ-511 on 2026-05-13 — closes Finding F3)
> **Public API barrel**: `src/class-colors/index.ts` re-exports `getClassColor`, `getClassNameFallback`, `getPhotoModeSuffix`, `FALLBACK_CLASS_NAMES`.
> **Topo batch**: B1 (leaf — no internal imports)

## Purpose

Pure-function fallbacks for detection-class color and display name. Used when the live `DetectionClass[]` from the admin API hasn't been loaded (initial render) or doesn't include a class for a given `Detection.classNum`.

Also exposes the **PhotoMode-aware suffix** logic that mirrors the WPF-era `yoloId = classId + photoModeOffset` convention (see `_docs/legacy/wpf-era.md` §10): class numbers in `[0, 19]` are "Regular", `[20, 39]` are "Winter", `[40, 59]` are "Night".

## Public interface

```ts
export const FALLBACK_CLASS_NAMES: string[]   // 12 generic English labels
export function getClassColor(classNum: number): string             // hex, no '#' alpha
export function getPhotoModeSuffix(classNum: number): string        // '' | ' (winter)' | ' (night)'
export function getClassNameFallback(classNum: number): string      // FALLBACK_CLASS_NAMES[base] or '#<n>'
```

A 12-color palette `CLASS_COLORS` is defined module-private and referenced through `getClassColor`.

## Internal logic

```
base = classNum % 20
mode = floor(classNum / 20)
color = CLASS_COLORS[base % CLASS_COLORS.length]    // wraps if base >= 12
name  = FALLBACK_CLASS_NAMES[base % FALLBACK_CLASS_NAMES.length]
                   ?? `#${classNum}`
suffix = mode === 1 ? ' (winter)' : mode === 2 ? ' (night)' : ''
```

The `??` guard exists for the unreachable case `base = 12..19` against an array of length 12 — except `base % length` brings it back into range first, so `?? '#<n>'` is dead. **Flag for Step 4 verification** — either the array is wrong or the `??` is dead code.

## Dependencies

- **Internal**: none.
- **External**: none.

## Consumers (intra-repo)

- `src/features/annotations/CanvasEditor.tsx` — labels + crosshair color.
- `src/features/annotations/AnnotationsPage.tsx` — `getClassColor` for selected class indicator.
- `src/features/annotations/AnnotationsSidebar.tsx` — gradient stops in the annotation row.
- `src/features/annotations/MediaList.tsx` — *not currently a consumer* despite being adjacent (no import seen).
- `src/components/DetectionClasses.tsx` — fallback name + color when admin classes haven't loaded. **This is the cross-layer edge** flagged in `00_discovery.md` §8: a `components/` (shared-layer) file imports from a feature.

## Data models

`CLASS_COLORS: string[]` (12 hex strings) and `FALLBACK_CLASS_NAMES: string[]` (12 English strings). Neither is wire-coupled — pure UI defaults.

## Configuration

None.

## External integrations

None.

## Security

None.

## Tests

None.

## Notes / open questions

- The "+20 winter / +40 night" PhotoMode convention is a direct port of the legacy WPF DetectionClasses contract (`_docs/legacy/wpf-era.md` §10). Verify against the current admin API DTO during component assembly (Step 2) — if the API exposes `photoMode` as a separate field on `DetectionClass` (it does, per `src/types/index.ts`), then computing the suffix from `classNum / 20` here is **redundant** and risks disagreeing with the admin-defined value. Candidate Step 4 testability fix: remove `getPhotoModeSuffix` once consumers have access to the typed `photoMode`.
- `FALLBACK_CLASS_NAMES` lists generic English labels (Car, Person, Truck, …) that bear no relation to the actual military classes the legacy doc enumerates (Military Vehicle, Truck, Car, Artillery, Active Mine — see `_docs/ui_design/README.md` §"Detection Classes Table"). Acceptable for a *fallback* only ever shown if the admin classes failed to load; document this in Step 5 (Solution Extraction).
- Cross-layer import surfaced in `00_discovery.md` §8 — proper home for these helpers is either `src/components/detection/` (with `DetectionClasses.tsx`) or a new `src/shared/` namespace. Decision deferred to Step 2.5 module-layout derivation.
