docs/platforms/mac/icon.md
Scope: macOS app (apps/macos). Rendering: CritterIconRenderer.makeIcon(...). Animation/state wiring: CritterStatusLabel + CritterStatusLabel+Behavior.swift.
| State | Trigger | Visual |
|---|---|---|
| Idle | Default | Normal blink/wiggle animation |
| Paused | isPaused=true | Status item uses appearsDisabled; no motion |
| Voice wake (big ears) | Wake word heard | Ears scale to 1.9x with earHoles=true (circular holes for readability); drops after silence |
| Working | isWorking=true or an active IconState | Faster leg wiggle (legWiggle up to 1.0) plus a small horizontal offset; additive to idle wiggle |
A tool-activity badge (SF Symbol puck, e.g. chevron.left.slash.chevron.right for exec) can render on top of the same critter icon when a session has an active job or tool. That badge comes from IconState/ActivityKind; see Menu bar for the full state model.
AppStateStore.shared.triggerVoiceEars(ttl: nil), called from the voice-wake capture pipeline (VoiceWakeRuntime) and from voice-wake debug/test tooling (VoiceWakeTester, VoiceWakeOverlayController).stopVoiceEars(), called when capture finalizes.2.0s normally, 5.0s if only the trigger word was heard and no further speech followed (VoiceWakeRuntime.silenceWindow / triggerOnlySilenceWindow).earBoostActive gates the animation task in CritterStatusLabel+Behavior).1.0; voice boost sets earScale=1.9 and earHoles=true without changing the overall frame.legWiggle up to 1.0 with a small horizontal jiggle.AppState.setWorking, AppState.triggerVoiceEars) to avoid accidental flapping.