# Win Dictation — Fix Note 01

**Every control renders as the blue Record pill**

**Applies to:** the single-surface UI rewrite described in `UI-and-Progress-Rebuild.md` (Part 1), after the first build.
**Status:** root cause confirmed, one-line fix below.

---

## Symptom

After wiring up the single-surface paint, every control — **Record**, **Pin**, the **mic** and **model** selects, and **Copy / Paste / Clear** — renders as the *same* blue accent pill with a white dot. No labels, no distinct styles. (The window chrome, card, and scrollbar are correct; only the widgets are wrong.)

## The mistake

`Widget::kind` is declared without an initializer, and the widget array has static storage duration, so the whole array is zero-initialized:

```cpp
struct Widget {
    WK     kind;        // <-- no initializer
    RectF  r;
    bool   hover = false;
    bool   pressed = false;
    float  anim = 0.0f;
};
static Widget g_w[ (int)WK::Transcript + 1 ];   // zero-filled → every kind == 0
```

`WK::RecordHero` is the first enumerator, i.e. value `0`. So **every** slot's `kind` reads as `RecordHero`. `LayoutWidgets()` assigns each slot's *rectangle* (`g_w[(int)WK::Pin].r = …`, etc.) but never its `kind`. The paint loop dispatches on `kind`:

```cpp
for (auto& w : g_w) {
    switch (w.kind) {                 // 0 for every widget
        case WK::RecordHero: DrawHero(g, w);          break;   // <-- all eight land here
        case WK::Copy:       DrawGhost(g, w, L"Copy");  break; // unreachable
        case WK::SelAudio:   DrawSelectSurface(...);    break; // unreachable
        ...
    }
}
```

Result: `DrawHero` paints all eight widgets → eight identical blue pills.

## The required change

The array is **indexed by enum value** (`g_w[(int)WK::Pin]`, `g_w[(int)WK::Copy]`, …), so slot `i` must carry `kind == (WK)i`. Stamp the kinds once, at the top of `LayoutWidgets()` — it runs before the first paint and again on every resize / DPI change, so the invariant is always re-asserted:

```cpp
void LayoutWidgets(int W, int H) {
    for (int i = 0; i < (int)std::size(g_w); ++i)   // <-- ADD THESE TWO LINES
        g_w[i].kind = (WK)i;                         //     slot index == kind

    for (auto& w : g_w) w.r = RectF(0, 0, 0, 0);
    float s = g_dpiScale;
    // ... unchanged ...
}
```

Equivalent alternative: an `InitWidgets()` helper called once in `wWinMain` before the first `LayoutWidgets`/paint. Doing it *inside* `LayoutWidgets` is the most robust, because nothing can paint before layout has run.

**Invariant to preserve:** `g_w[i].kind == (WK)i`. As long as rectangles keep being assigned via `g_w[(int)WK::X].r`, the slot index always equals the enum value and this holds.

After this change, `DrawGhost` (Copy/Paste/Clear), `DrawPinSurface`, and `DrawSelectSurface` (mic/model) take over their slots, and you get the intended distinct, borderless, label-bearing controls.

## Secondary issue noticed (cosmetic — not fixed here)

The transcript **placeholder** ("Your transcription will appear here…") won't appear. `PaintSurface` draws it into the transcript rect, but the real multiline `EDIT` child window covers that rect and is opaque, so it hides the parent-painted text. `EM_SETCUEBANNER` only works on *single-line* edits. Clean fix: subclass the multiline `EDIT` and draw the cue in its own `WM_PAINT` when the control is empty and unfocused. Tracked as a separate follow-up.

## Verify after rebuilding

1. **Top row:** a wide blue **Record** pill + a quiet **Pin** toggle (accent only when pinned).
2. **Bottom:** **mic** and **model** selects (label + chevron, faint at rest) and quiet **Copy / Paste / Clear** ghost buttons (text only at rest).
3. **Hover** a ghost button → a soft fill fades in; **press** → slightly darker. No resting borders, no hairlines.
4. Independent of this fix, run a transcription and confirm the progress **%** rises smoothly and the **"… s left"** value counts **down** (not up).

---

*Companion to `UI-and-Progress-Rebuild.md`. This note documents a correction to that guide's Part 1 scaffold; the guide itself is left unchanged.*
