# Ludo kiosk and large-format touch guide

> How to build public touch kiosks (32 to 55 in portrait) in Ludo style: reach zones from ADA and AS 1428.1, physical target sizes converted to px for named panels, idle attractor, session reset, payment-adjacent privacy, and which token colours survive sunlight.

Source of truth: `apps/ui/tokens/ludo.tokens.json` v0.1.0. Served from https://ui.ludo.computer/guides/kiosk-large-format.md. Generated 2026-07-26. Self-contained: every value is inline, no images required.

Ludo kiosks sit in showground crowds: gloved hands, direct sun, queues, and a new visitor every 90 seconds. Honest current state of the design system: the shipped kiosk affordances are the `data-density="touch"` variant in `registry/ludo/theme.css` and a decorative kiosk mockup frame in the registry. Everything below is the specification new kiosk work must meet.

## Use these tokens

```text
Reference panel        55 in UHD portrait, 2160 x 3840 px, ~80 ppi (1 mm = 3.15 px)
Alternate panels       55 in FHD portrait ~40 ppi (1 mm = 1.57 px); 32 in UHD ~138 ppi (1 mm = 5.42 px)

Touch target           20 mm minimum, 26 mm preferred, 3 mm+ gaps (Colle & Hiszem 2004, Ergonomics 47(13))
  on 55 in UHD         63 px minimum, 82 px preferred
  on 55 in FHD         32 px minimum, 41 px preferred
  on 32 in UHD         108 px minimum, 143 px preferred
Rule: author kiosk hit areas in mm and resolve to px per panel. Never hardcode a px size.

Outdoor surface        #FFFFFF or #FAFAFA background, #09090B text (19.90:1)
Primary action fill    #5A3FD0 with #FFFFFF label (6.87:1). Avoid #825FFF fills for text-bearing buttons in sun.
Highlight              #FFD059 with #09090B label (13.66:1)
Borders                #D4D4D8 (borderStrong) at 2 px minimum; #EBEBEB is too faint under glare
Status text            success #047857, warning #B45309, error #B91C1C on their bg tints
                       (#ECFDF5 / #FFFBEB / #FEF2F2)
Radius                 12 px (xl) minimum on buttons at kiosk scale; scale radius with the control
Typeface               Geist, weights 400 / 500 / 600 (cap 600)
Motion                 attract loop allowed; interaction feedback within 100 ms; transitions 150 to 200 ms
Density                wrap the UI subtree in data-density="touch" (shipped in theme.css)
```

## Layout

Height zones, measured from the finished floor (AFF):

- All interactive elements between 380 mm and 1220 mm AFF. Basis: ADA 2010 Standards §308 (unobstructed reach 380 to 1220 mm) and EN 301 549 v3.2.1 §8.3 (essential controls no higher than 1220 mm).
- Primary actions, keypads and payment prompts in the 900 to 1100 mm band (AS 1428.1:2021 control zone).
- Obstructed forward reach over a 510 to 635 mm counter drops the maximum to 1120 mm (ADA §308.2.2).
- Worked example: a 55 in portrait panel is about 1218 mm tall. Mounted with its bottom edge at 500 mm AFF, the top of the panel sits at about 1718 mm. Everything above 1220 mm AFF, roughly the top 500 mm of the panel, is display-only: branding, attract content, status. No buttons there, ever.
- Interaction distance is 400 to 700 mm; attract distance is 3 to 5 m. Design both layers.
- One task per screen, 3 to 5 choices maximum. A queue is forming behind every decision.
- Hardware spec to hand the integrator: 6 mm+ thermally tempered glass, IK08 to IK10 impact rating, projected-capacitive controller tuned for glove and rain rejection, optical bonding, anti-glare etch, auto-brightness.

## Type

Physical sizes govern. Convert with px = mm x ppi / 25.4. The px column below is for the 55 in UHD reference panel (80 ppi).

| Role | Physical size | On 55 in UHD | Weight |
|---|---|---|---|
| Attract headline (read at 4 m) | 27 mm cap height (~95 mm line) | ~300 px font size | 500 |
| Screen title | 12 mm em | 38 px | 500 |
| Body / instructions | 8 mm em | 25 px | 400 |
| Body floor (600 mm viewing) | 6 mm em, 4 mm cap height | 19 px | 400 |
| Button labels | 9 mm em | 28 px | 600 |
| Legal / receipt footnote | 5 mm em | 16 px | 400 |

- Legibility basis: cap height >= viewing distance / 150 (ANSI/AVIXA V202.01 DISCAS). At 600 mm that is 4 mm caps; at 4 m attract distance, 27 mm caps.
- These px values look small because the reference panel is low density. On the 32 in UHD panel the same 8 mm body is 43 px. Author in mm.

## Colour

Sunlight is the design constraint. Standard commercial panels (350 to 700 nits) wash out outdoors; direct-sun placement needs 2500 to 4000 nits and shaded or semi-outdoor placement 1000 to 2500 (industry guidance: Litemax outdoor brightness guide; Samsung OM window-facing series ships at 2500 nits). Hold text contrast at 7:1 or better (ISO 9241-303 preferred level). In high ambient light, dark text on light fields beats dark UI.

Colours that survive outdoor glare:

- #09090B on #FFFFFF: 19.90:1. The default.
- #09090B on #FFD059: 13.66:1. The highlight pairing.
- #FFFFFF on #5A3FD0: 6.87:1. The brand-purple button that still works.
- #3F3F46 on #FAFAFA: 10.01:1. Secondary text.

Colours that fail outdoors:

- #FFFFFF on #825FFF: 4.17:1. Passes indoor large-text AA, washes out in sun. Use #5A3FD0 fills instead.
- zinc-400 #A1A1AA (2.56:1) and zinc-500 #71717A (4.83:1) as text: too light for glare. Nothing lighter than #3F3F46.
- #F76CAF on white: 2.72:1. Decorative only.
- Raw semantic fills as text: #10B981 (2.54:1) and #F59E0B (2.15:1) on white. Use the foreground shades #047857 / #B45309 / #B91C1C.
- Dark mode. Reflections turn a #09090B screen into a mirror outdoors. Dark kiosk UI is for indoor, shaded or night placements only.

## Interaction

- Targets: 20 mm minimum, 26 mm preferred, 3 mm+ gaps. Evidence: Colle & Hiszem (2004) tested standing kiosk entry at 10 / 15 / 20 / 25 mm keys; 20 mm was sufficient and preferred, and spacing beyond 3 mm added nothing. Prefer 26 mm here: vandal glass adds parallax and showground winters add gloves.
- Feedback within 100 ms of touch (the `instant` motion token): visible state change plus optional sound. Capacitive glass gives no tactile response, so the screen must answer.
- No hover states, no double-tap, no drag as the only way to do anything. Single tap and large paging buttons.
- Idle attractor: motion is welcome here, it draws visitors from 3 to 5 m. It must stop on first touch. Anything auto-playing over 5 s needs a pause control (WCAG 2.2.2). Never more than three flashes per second (WCAG 2.3.1).
- Session timeout: prompt after 30 to 60 s of inactivity, show a visible countdown and give at least 20 s to respond (WCAG 2.2.1), then hard-reset to attract.
- The hard reset clears everything: cart, form fields, on-screen personal data, and any session state in memory. The next visitor must never see the last visitor's order.
- Payment-adjacent privacy: mask phone numbers and email addresses as typed. Never render a card number; the payment terminal owns card data and the screen shows at most the last 4 digits it reports. Offer receipt by QR or printed slip rather than demanding an email in a crowd. Screens this size are shoulder-surfable from metres away.

## Do / Don't

- Do author hit areas in mm (20 minimum, 26 preferred) and convert per panel. Don't ship a 44 px web button: on a 32 in UHD panel that is about 8 mm, a third of the evidence-based minimum.
- Do keep every interactive element between 380 and 1220 mm AFF with primary actions at 900 to 1100 mm. Don't put buttons in the top zone of a portrait panel.
- Do use dark-on-light UI with 7:1+ contrast outdoors. Don't ship the web dark theme to a sunlit kiosk.
- Do stop the attract loop on first touch and reset hard after timeout. Don't leave the last visitor's details on screen.
- Do give visible feedback within 100 ms of every touch. Don't leave a tap unanswered while a network call runs.
- Do use #5A3FD0 for text-bearing purple buttons and #FFD059 with #09090B for highlights. Don't put white body text on #825FFF outdoors.
- Do wrap the kiosk subtree in data-density="touch". Don't hand-tune individual component sizes to fake density.
- Do write instructions in plain operational language for visitors. Don't use "guest", em dashes, or hover-dependent hints like "mouse over for details".

## Checklist before shipping

- [ ] Every target at least 20 mm (26 mm preferred) with 3 mm+ gaps, verified in mm on the actual panel
- [ ] No interactive element outside 380 to 1220 mm AFF; primary actions at 900 to 1100 mm
- [ ] Body text at least 6 mm em (4 mm cap height); attract text 27 mm caps for 4 m
- [ ] Text contrast 7:1 or better; no text lighter than #3F3F46 on light fields
- [ ] Panel brightness matches placement: 2500 to 4000 nits direct sun, 1000 to 2500 shaded
- [ ] Attract loop stops on first touch; nothing flashes more than 3 times per second
- [ ] Inactivity prompt at 30 to 60 s with a 20 s+ countdown, then hard reset that clears all visitor data
- [ ] Personal data masked as typed; card data never rendered beyond last 4 from the terminal
- [ ] Touch feedback within 100 ms on every control
- [ ] data-density="touch" applied; no em dashes; "visitor" never "guest"
