Files
maze32/docs/UI_STYLE.md
T

272 lines
15 KiB
Markdown

# Browser UI style
## 1. Purpose
This document defines the canonical visual language, controls, responsive
layout, and presentation behavior for every maze32 browser mode. Product rules
remain in `MVP.md`, and browser authority boundaries remain in
`ARCHITECTURE.md`.
## 2. Visual direction and tone
- Use a dark retro arcade-game style throughout network provisioning, name
selection, lobby, player, and observer modes.
- Use humorous copy, imagery, animation, object names, and suggested player
names wherever the game remains clear and usable.
- Humor must be understandable to children, non-offensive, and based on
internet humor that is current when the release is designed. Runtime access
to external meme or content services is forbidden.
- Use only a dark theme. A light theme is outside the MVP.
- Use small SVG icons, pixel-art graphics, or graphics styled to resemble
pixel art. Locally authored icons must not require an external icon library.
- Use a system monospace font stack with CSS pixel-style treatment. The UI must
not download Google Fonts or any other external font at runtime.
## 3. Color system
The exact color values may be tuned during implementation, but their semantic
roles must remain stable:
- black or near-black for the application and map background;
- purple for panels and elevated surfaces;
- turquoise for interactive accents;
- yellow for Player 1 and blue for Player 2 across every screen, map object,
and message; each player's matching key and exit use the same ownership
color;
- green for success, amber for warnings, red for errors, periwinkle for pause,
and orange for disconnection;
- green vegetation, bushes, and plants for maze walls.
When two semantic roles use related colors, icons, labels, outlines, or shapes
must keep them unambiguous. Important player and object information must not be
communicated by color alone. Key objects use an additional label, outline, or
marker.
The gameplay icon family is locally authored SVG artwork derived from the
approved running-player, key, arched-exit, crystal, opened-exit, and spike
reference silhouettes. The spike icon remains a catalog asset only; blocked
movement uses the maze feedback defined below and never represents a trap or a
new gameplay mechanic.
WCAG AA contrast certification and dedicated color-vision-deficiency palettes
are not MVP requirements.
## 4. Animation, sound, and haptics
- Use frequent but purposeful animation for screen transitions, movement,
pickups, game events, and humorous feedback.
- Pending controls blink until their command is resolved.
- A visible reduced-motion toggle is required in player mode. It must suppress
non-essential animation without changing gameplay feedback or authority.
- Sound and vibration are enabled by default. They begin only after the first
user interaction when required by the browser, and are used only when the
browser and device support them.
- A visible mute toggle is required in player mode. It disables local sound and
vibration feedback only; it must never change protocol behavior.
## 5. Shared controls
- Controls use a retro arcade appearance with clear normal, hover, pressed,
disabled, and pending states.
- Visible keyboard-focus outlines are not required for the MVP.
- On computers, movement works from the keyboard and from an on-screen
directional control cluster fixed in the lower-right corner.
- On touch devices, an always-visible four-button directional pad in the lower
right is the primary movement control. Its centre is inactive, each button
is at least 48 by 48 CSS pixels, and it sends only one cardinal intention.
The centered player avatar remains an optional movement handle. Its
transparent touch target is at least 96 by 96 CSS pixels and its visible
character remains unobscured. During a drag, it deflects no more than 28 CSS
pixels from center and returns exactly to center on release, cancellation,
pause, disconnect, lost pointer capture, hidden document, and browser blur.
- The avatar drag has a 12 CSS-pixel dead zone and directional hysteresis. Its
bounded repeat cadence changes monotonically from 360 ms at a small
intentional displacement to 170 ms at the target edge; it never exceeds the
server's 150 ms movement cooldown. The pad's hold repeat is 170 ms. Touch
swipes remain supported. The pad, avatar drag, swipe, and keyboard inputs
share one bounded latest-intent path.
- The always-visible key-drop control is labelled `OK`, includes a key icon,
and is positioned closer to the upper edge of the screen than the
directional controls. Dropping does not require confirmation.
- The key-drop control has the Russian accessible label `Сбросить ключ`.
## 6. Shared layout
- The map fills all viewport space not required by fixed status and control
panels. The player match screen must not require page scrolling.
- A fixed status panel occupies the top of the screen.
- The persistent player status shows the player name, carried key when one is
held, active vision effect, and match state.
- The player identity is represented by a distinct character shape, not `P1`
or `P2`. Object, blocked-move, pause, and result feedback must pair a shape
or icon with its color.
- A single gear button beside the persistent Wi-Fi connection indicator opens
the secondary settings popover. It contains connection details and Wi-Fi
settings on every screen, plus the player-only sound, reduced-motion, and
help actions during an active player match. The popover is constrained to
safe areas, closes on outside activation or Escape, and never contains
primary game, lobby, observer, or result actions.
- The settings popover shows `Выйти из игры` only for an authenticated session.
It opens a confirmation modal; an unfinished player match warns that it ends
for everyone, while observer and lobby departures explain that only this
browser's place is released.
- A compact response indicator between the connection state and gear shows a
rounded total response time or an explicit unknown, stale, or offline state.
Its accessible description and settings details expose `Отклик`, `Связь`,
and `ESP`; `Связь` is a transport remainder and does not assign blame to
Wi-Fi, the ESP, or a player.
- Countdown, pause, and result states appear as modal overlays above the map.
- Textual system notices use one live message rail above the top bar and player
status area. It shows one message at a time: connection loss has highest
priority and persists until recovery; all other messages replace lower
priority content, deduplicate by event, and dismiss after 2.6 seconds.
- The lobby uses separate blocks for players, observers, and match actions.
- Network provisioning uses the same colors, type, controls, and humor as the
game application.
## 7. Player map presentation
- Keep the portrait player horizontally centered at approximately 30% of the
usable map height, above the directional-pad hand zone. In compact landscape,
use the stable left-biased focal point in the largest unobstructed map area.
Recalculate it after resize and rotation without moving the authoritative
player away from its received `self` cell.
- Render unknown space as a solid background. Never infer, retain, animate, or
decorate maze geometry outside the server-provided visible projection.
- Compute cell size from the current server projection and available map area.
At the minimum supported phone viewport a common 7 by 7 projection must use
at least 46 CSS-pixel cells, while smaller projections may grow to 72 pixels.
Do not alter, retain, or infer hidden maze cells to fill spare space.
- Player zoom and pan controls are not part of the MVP.
- Use different colors plus labels, outlines, shapes, or icons to distinguish
player ownership and object types.
- Server-approved breakthrough impacts one through four bend the visible bush
wall with four increasing restrained stages and no text or spike notice. A
fifth accepted move is reflected by a permanent textured trampled-bush gap.
Only a received opened-edge projection paired with an adjacent authoritative
player position may start one 480 ms hedge-parting, player dash, and fixed
four-accent leaf-and-sparkle sequence. It uses one restartable timer and no
unbounded generated particles.
`rate_limited` still darkens and blurs only the maze for at most 520 ms.
- Reduced-motion mode uses static deformation and the same trampled-gap state;
it never shows travel or moving accents.
### Hedge art review contract
- Hedge samples are direct top-down vectors for review only; they are not
runtime assets in this milestone. A segment occupies one cell edge and uses
a centered, 10 CSS-pixel-wide foliage band at 40 CSS pixels per cell, scaling
proportionally at 34 and 46 pixels.
- The family uses deep shadow `#173d2a`, branch `#765033`, foliage dark
`#296443`, foliage mid `#4f9b55`, foliage light `#8cc968`, and pale leaf
highlight `#c7e68a`. A dark outline and branch fork preserve silhouette in
grayscale; color is supplementary depth, not the only boundary cue.
- Each intact symbol combines three or more named leaf clusters with visible
twig forks, a restrained shadow, and an irregular outer silhouette. Straight
symbols tile end-to-end without double borders; corner, crossing, and end
symbols share their edge centre and may rotate or mirror without directional
lighting.
- Impact stages one through four retain the same wall centre while increasingly
compressing foliage, bending twigs, and shedding a fixed small number of
leaves. The breakthrough and trampled symbols leave a clear centred passage
at least 24 CSS pixels wide at 40-pixel scale, with two separated foliage
clusters, bent branches, and restrained ground debris on both sides. They
never imply movement beyond that one authoritative edge.
- Review sheets show the source symbols on neutral and dark-cell backgrounds
at 34, 40, and 46 CSS pixels. They contain no coordinates, objects,
ownership, hidden topology, animation, or runtime dependencies.
### Runtime hedge rendering
- The local `/hedges.svg` sprite is derived from the approved review source.
It contains only reusable runtime symbols and no scripts, raster data, or
external dependencies. The review sheet in `docs/` is never requested by a
browser page.
- A map uses one non-interactive hedge-edge element for each canonical closed
or server-opened edge in its current projection. Closed shared edges are
owned by their north or west cell; east and south edges are rendered only at
the current projection boundary. This bounds a full 32 by 32 map to 2,112
hedge elements and avoids duplicated foliage.
- A stable integer hash of the canonical edge index and orientation selects one
of the six approved intact variants. Opened edges select one of the three
approved breach variants. The same projection edge always receives the same
art without random state, retained exploration, or a protocol field.
- Gameplay readability takes priority over foliage density. Hedge foliage is
at most 20% of one cell, and the center line of every horizontal or vertical
symbol must coincide with its authoritative cell edge. Rotation must preserve
that center line instead of shifting a vertical hedge through cell centers.
Every runtime SVG instance uses the approved `160 x 40` view box scaled to
exactly one cell edge; source-coordinate artwork must never overflow into
unrelated cells. Cell interiors remain visually quiet and continuous so
passages read as open floor rather than as a grid of highlighted rectangles.
- Hedge edges are decorative, have `pointer-events: none`, sit below map
objects and players, and may overhang an edge by at most 15% of a cell. A
projection replacement removes all obsolete edge nodes. One restartable
breakthrough timer may briefly show the approved breakthrough frame; reduced
motion settles immediately on the permanent breach. A player-only transient
runner replaces the focal avatar for at most 480 ms after a matching opened
edge and adjacent authoritative move; it has exactly four non-interactive
accents and is cleared on any newer projection, pause, disconnect, result,
reset, screen change, or reduced-motion mode.
## 8. Responsive behavior
- The minimum supported player viewport is `412 x 916` CSS pixels.
- Support both portrait and landscape orientations. Suggest landscape when it
materially improves play, but do not block portrait play.
- Respect display safe areas and keep essential status and controls visible.
- At `412 x 916`, the map is the dominant visual region; controls overlay it
instead of creating an empty lower region. Status remains icon-first and
readable without requiring reading as the normal interaction path.
- Scale icons and controls up on tablets and computers while preserving map
priority and fixed panel placement.
- Validate the MVP against the current stable releases of Chrome, Safari,
Firefox, and Edge available at the time of validation. Record the tested
browser versions and date; legacy browser support is outside the MVP.
## 9. Observer presentation
- Observer mode is supported only at viewports of at least `1024 x 768` CSS
pixels. Smaller viewports show a Russian message explaining that a larger
screen is required.
- Place player and match status blocks above the full maze.
- Initially fit the complete `32 x 32` map into the available map area.
- Provide zoom and pan without granting any gameplay control or changing
server authority.
## 10. Asset and dependency budget
- Use plain project CSS without a third-party CSS framework.
- All runtime web assets must be served locally from the ESP. The UI must not
require internet access, remote fonts, external icons, analytics, or content
services.
- Precompress production web assets. Their complete compressed payload must
not exceed 1.5 MiB and must fit the existing 1,984 KiB LittleFS partition.
- The LittleFS partition size and Flash layout remain unchanged.
## 11. Visual verification
- Verify player layout at the minimum `412 x 916` viewport and representative
tablet and desktop viewports.
- Verify observer layout at `1024 x 768` and at a larger desktop viewport.
- Verify every control state, modal state, responsive transition, Russian
message, and semantic color role manually and through focused browser tests
where practical.
- Golden-image or screenshot-regression tests are not required for the MVP.
## 12. Pre-reader onboarding and usability
- On a player's first active projection, show an eight-step, wordless-first
walkthrough for avatar drag and release, walls, key, vision, compass,
exit, and meeting the other player. Each step uses a large icon; short
Russian text is secondary support for an adult.
- The walkthrough provides a replay button and an explicit Russian skip button
for adults. It is browser-local UI only and never changes server state.
- A child must be able to distinguish their character, the other character,
key, vision, compass, exit, blocked movement, and results through at least
two channels such as shape/icon, position, motion, outline, color, sound, or
haptic feedback.
- Before release, record a representative pre-reader observation using
`docs/PRE_READER_USABILITY.md`, or record a project-owner-approved deviation
with its reason and impact.