Focus system — three contexts, one ring
put.io has three focus contexts: keyboard (web), pointer (web, no ring), D-pad (TV). All three resolve to the same brand-yellow halo, scaled to the input device. Never invent another focus style.
Keyboard · web
Tab / arrows over buttons, inputs, links
Soft 3px brand-yellow halo (35% alpha) around any button. Sits outside the border, never replaces it. Triggered by :focus-visible, not :focus.
Pointer · web
Mouse hover & click
No halo. Hover lifts background to --yellow-solid-hover on primary, or --component-bg-hover on default. Cursor carries the intent.
D-pad · TV
Apple TV · Android TV · Roku · Smart-TV web
tile
focused
scale(1.06) + 1px yellow halo at 18% alpha + 14px drop shadow. Engine varies per platform (CSS on web / AndroidTV-web, focusable group on tvOS, BrightScript focus on Roku) — the visual is identical.
Spec — values lifted from system/tokens.css
Ring color--shadow-focus-colorTranslucent brand yellow — hsla(47, 100%, 65%, 0.35) (Radix-style accent-a8, not --yellow-solid). Also the shadcn --ring color.
Ring · button (web)--shadow-focusSoft 3px translucent halo via box-shadow (Radix-style accent-a8). Border stays unchanged.
Ring · input (web)--field-ringQuiet, not yellow: border shifts to step-8 --border-hover + a 1px ring of the same color. Error/success states swap to red/green.
Ring · TV tilescale(1.06) + 1px halo10-foot UI needs more presence. Scale is the affordance; the halo is the confirmation.
Trigger:focus-visibleNever :focus — that paints rings on clicks users don't want.
Transition120ms · ease-outMatch D-pad latency expectations. Slow focus = laggy app.