> For the complete documentation index, see [llms.txt](https://docs.kouch.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kouch.dev/docs/deck_ui_plan.md).

# Deck-grade UI: legible, touchable, no overlaps, true highlights, full parity (2026-09-28)

An addendum; it doesn't replace the other plans. The owner's goal:

*"optimize the guis, specially the steam deck one, valve requires everything to be clearly visible and not hard to read on the steam deck screen, meaning text has to be optimized, you can research this too, make sure guis are responsive, and do not overlap with each other, make sure the highlights actually highlight properly … make sure everything works properly, and full parity with steamdeck/linux and windows, everything must work together"*, then *"also optimize for touch, part of the goal too"*.

## What Valve requires (Steamworks, Steam Deck compatibility)

* **Text legibility (hard requirement):** "the smallest on-screen font character should never fall below 9 pixels in height at 1280x800", readable from 30 cm (12 in). Valve recommends aiming for 12 px.
* **Controls:**
  * the default controller configuration reaches all content, including any launcher;
  * glyphs match the active input, with no mouse or keyboard glyphs when a pad is in use;
  * text entry uses Steam's on-screen keyboard or a built-in controller keyboard.
* **Display and performance:** it runs at a resolution the Deck supports (1280×800 preferred), and the default configuration is playable (30 fps at 800p).
* **No published figures** for contrast, touch-target size or focus indication. Kouch sets its own below.

Kouch already covers controller-only navigation, Steam glyphs per pad family, both keyboards (Steam's floating one, and Kouch's own under a shortcut), 1280×800, and the fit and alignment sweep. This plan adds what the checks didn't measure.

## D1 Legible text (Deck: 1280×800, 100 % text)

* Kouch reads "character height" as the capital height. Inter's capitals are 0.727 em, so:
  * **a hard floor of 12.4 px font size** (capitals of 9 px);
  * **a target of 16.5 px** (capitals of 12 px) for body text, labels and prompts.
* Only incidental text (a timestamp, a small badge) may sit between the floor and the target.
* The size is measured as it's painted: font size × any transform scale.

## D2 Touch

* **Targets:** every focusable or clickable target is at least **44 × 44 px** on screen (about 5 mm on the Deck; Steam's own Deck buttons are \~48 px). A small icon can keep its look with a larger hit area (padding or a pseudo-element).
* **Tap:** focuses the item and activates it in one tap, the same as a mouse click.
* **Scrolling:** lists and rows scroll by drag and swipe with momentum, with no text selection or image drag on a swipe.
* **Library:** a horizontal swipe moves between sections; pinch-zoom stays blocked.
* **Sheets and panels:** close by tapping the scrim or the X, and a side panel also by swiping it back out.
* **Text fields:** a tap opens the on-screen keyboard.
* **No hover-only information** (already a design rule).

## D3 No overlaps

* No two visible text runs overlap, and no text sits under another element or the prompt bar.
* Layouts reflow rather than overlap at every sweep size and at 150 % text.

## D4 Highlights that highlight

* **Where it sits:** the focused item is always marked by the gliding ring (enclosing it within 12 px) or by its own drawn state.
* **Never:**
  * a ring left on a previous item or screen;
  * two rings at once;
  * a focused item off-screen, cut by its scroller, or under the prompt bar.
* **Motion:** the ring follows scroll and FLIP moves, and snaps when a scroll carries the motion.

## D5 Parity: Windows ↔ Linux/Deck

From the parity audit (2026-09-28); most pairs are already symmetric.

| Gap                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | Owner   |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| Theme accent from the OS: Linux returned none. **Done:** KDE `kdeglobals` (AccentColor, else the selection color) and GNOME `accent-color`, by `XDG_CURRENT_DESKTOP`                                                                                                                                                                                                                                                                                                                                                                                       | central |
| A handheld PC running Windows doesn't auto-fullscreen like the Deck. **Done:** one firmware matcher for both OSes (DMI on Linux, SMBIOS through WinRT on Windows; A's matcher)                                                                                                                                                                                                                                                                                                                                                                             | central |
| `.tar.xz` emulator archives weren't supported on either OS. **Done** (B `8bf99ac`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | B       |
| The keyboard + mouse seat had been proven in a real emulator on Windows only. **Verified on the Deck in Game Mode (2026-09-28):** a uinput keyboard through gamescope → Kouch's X raw-input seat → Kouch Pad 2 → the stand-in emulator with focus: K/L/J/I arrived as A/B/X/Y and D as the left stick                                                                                                                                                                                                                                                      | central |
| Virtual pads (`kouch-vpad`) were a stub on both OSes. **Done** (C, `docs/VPAD_PLAN.md` V1–V5: `556d6a2`, `482abf0`, `d9e08e6`, `d30a808`; B's double-input warning `8986dbd`). **Verified on the Deck:** all 12 kouch-vpad tests pass there (`/dev/uinput` is the deck user's; the pad's node gets uaccess within \~100 ms), and live: "Kouch Pad 1" appears when the session is launching, buttons, stick and d-pad reach the emulator, and the pad is gone after quit. Windows: the ViGEm pad plugged, took a report and unplugged on the owner's PC (C) | C       |
| Exclusive-fullscreen overlay, rumble end-to-end and split pads: untested on both OSes, hardware checks                                                                                                                                                                                                                                                                                                                                                                                                                                                     | central |

## Checks

* **Automated:** `scripts/ui-deck-metrics.js`, run by `node scripts/ui-sweep.mjs --deck 1`. It reports:
  * `text_small`, the texts under the floor, plus `text_below_target`;
  * `touch_small`;
  * `overlaps`;
  * `ring_missing`, `ring_off`, `ring_stale` and `focus_hidden`.
* **Gate:** each of those must be 0 on every screen at 1280×800 (Black and White), and the overlap and highlight checks at every sweep size. The result lives in `docs/UI_DECK.md`.
* **Live:** Game Mode captures on the Deck of every main screen (read back), a touch pass on the Deck (tap, swipe, keyboard), and the perf A/B after each batch.

## First audit (2026-09-28, 1280×800 Black, mock)

What the checks found once their false alarms were fixed (a text under a sheet or a layer, an ellipsis run, and a ring hidden from assistive tech all read as problems at first):

| # | Finding                                                                                                                                                                                               | Where                                                                                                                 | Owner |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ----- |
| 1 | **Weak list highlight:** a focused row is marked only by `--k-surface-4` (about 1.07:1 on a sheet) and a left bar; cards and buttons get the ring. Rows get the same all-round ring, plus the fill    | `ListRow`, `ToggleRow`, `Slider` row, `SocialRow`, `Tile`, `TextRow`'s input, Settings categories, every sheet's rows | A     |
| 2 | **Touch targets under 44 px:** the Library section tabs (36 tall), the A–Z rail letters (24×21), the game page's "Edit tags" (67×22), the tag chips (26 tall) and the top bar's player dots (32 wide) | Library, game page, tags sheet, top bar                                                                               | A     |
| 3 | The A–Z rail scrubs by drag: a finger moving along it moves to that letter, so the rail as a whole is the target                                                                                      | `AzGrid`                                                                                                              | A     |
| 4 | Edit Home's catalogue draws widget previews at 10 px text: mark the previews `data-deck-preview` (a picture, the name is printed beside it) or draw them larger                                       | `EditHome`                                                                                                            | A     |
| 5 | The setup disk cards wrap "1.0 TB" onto two lines, and the drive chip truncates ("Emulation folder fo…") at 1280×800                                                                                  | setup › More disks, Storage                                                                                           | C     |
| 6 | On the setup steps the primary action (Skip) is drawn filled in the accent while the focus ring is on a card: two things look selected. Keep the filled style for the focused button only             | setup wizard                                                                                                          | C     |
| 7 | The 7- and 12-drive stress cases shrink text to 8–10 px: page the drives instead of shrinking below the floor                                                                                         | setup › Main folder / More disks                                                                                      | C     |
| 8 | Battery detail "Lowest battery 62 %" at 12 px on the Controllers widget                                                                                                                               | Home widget                                                                                                           | C     |

**Checked on the Deck (same day):** the checks were run inside the Deck build's own WebKit (headless gamescope at 1280×800, the extracted `depot/` tree). It renders the bundled Inter Variable at device pixel ratio 1 and gives the same numbers as Chrome: Home's smallest text is 13 px, with no overlaps, and the card menu has the same missing row highlight (item 1). The browser sweep therefore stands in for the Deck's layout and text. The Deck-only checks are Game Mode captures, touch, and performance.

**Full run, Black and White:** 111 of 176 cells failed.

* 0 overlaps anywhere.
* The rest were the list and toggle-row highlight (every Settings page, every sheet with rows, the Quick Menu), the touch sizes above, Edit Home's previews and the setup stress cases.

## Status

| Part                            | Status                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| D1–D4 checks                    | done (central)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| D1–D4 fixes                     | done: A `6e1874b` (row ring, touch sizes, A–Z scrub, previews, section swipe) and `85bb6be` (4K rings on Playtime and Shelf); C `a066d65`, `ac2a6af`, `5336f7b` (only the focused button filled, drive cards legible and paged, text floor). 1280×800 Black + White: 0 of 188 cells failing (was 111)                                                                                                                                                                                                                                                                                                                                               |
| D5 parity                       | done except the hardware-only row (exclusive fullscreen, rumble to a real pad, split pads)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| Live on the Deck                | the checks run inside the Deck's WebKit match Chrome; virtual pads and the keyboard seat verified in Game Mode. Perf A/B in Game Mode at 90 Hz (main 0b173ff vs 59be9db, two rounds each): A–Z 85.5/86.1 vs 86.5/85.2, Shelf 86.3/86.2 vs 86.1/86.3, Playtime 87.4/87.9 vs 87.7/87.2, Home fold 88.6/88.3 vs 88.5/88.4, connect 86.7/85.0 vs 84.7/85.1, sheet 87.6/87.0 vs 87.3/88.0: no regression                                                                                                                                                                                                                                                 |
| Later fixes from the full sweep | the ring cut by its container (A `3dc1e77`, Library; `d8d73d0`, Downloads at 150 %), the Shelf's seeded spine heights (`8276c64`), the friends rail (C `6aa74ee`, `e4899b9`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| Connect hitches (closed)        | C instrumented where they fall (`5a035fc`, the `connect_hitches` tour line): about one dropped frame per seat change inside the FLIP move, spread across it, plus one around the change. Deck A/B of the leave fix (`528d43f`, leaving seats shrink out as designed): connect 85.9/85.4 vs 85.7/85.7, no difference. Nothing is left to cut without animating less (a shorter move at 5–8 seats, or not resizing boxes that only shift), which is the owner's call                                                                                                                                                                                  |
| Connect pop (owner 2026-09-28)  | Seat changes pop instead of sliding: the boxes that move pop out in place (120 ms), the layout changes while they're gone, and they pop in at their new places (180 ms, the spring), 20 ms apart along each row; every box's animation starts and ends with the wave and holds until its turn. A delay per box had cost the Deck \~10 fps (Desktop Mode switch A/B: delays 73.8–75.1, no stagger 85.0, the slide 85.3–86.4). Game Mode, final tune vs the slide, two rounds each: connect 85.1 / 84.0 vs 85.4 / 86.1 (hitches 56 / 56 vs 56 / 42), every other phase unchanged; above the 84.5 alpha floor, and a real join is one change at a time |
| Folded Home rail                | readings instead of bare icons (A `a2a570e`), and the friends glance fits at 150 % (C `93621e3`); 0 failing at every size, 150 %, Black and White                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| Final                           | every screen at 1280×800, 1920×1080, 2560×1080, 3840×2160 and 1920×1080 at 150 %, Black and White, with the Deck checks: 0 failing (2026-09-28; the three cells that failed under load pass on rerun). Gate at 0b173ff: 1003 Rust, 786 UI; release build smoke-tested                                                                                                                                                                                                                                                                                                                                                                               |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kouch.dev/docs/deck_ui_plan.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
