feat: minimal HUD with one floating menu and objective chip

Phase 4 of turning the game into the company landing page.

- Only the menu button, a compact objective chip and the touch
  controls stay on screen; speed shows only while driving.
- The objective chip shows the next goal in one line, its distance and
  an arrow that turns towards it (replaces the compass strip); tapping
  it opens the mission list.
- One floating menu holds map, missions, status, products, real-world,
  camera, stable mode, sound, graphics, minimap, fullscreen, help,
  restart and back to the start screen. It closes on a second tap, a
  tap outside, Escape, or after an action.
- Missions, status and help open as sheets; street label, rank bar,
  status panel, toolbar and compass are gone. The minimap is optional
  and off by default.
- Share the icon set and sheet dialog between start screen and HUD.
- Layout checked for phone portrait, landscape and safe areas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 08:50:29 +03:30
co-authored by Claude Opus 5.5
parent d9ae8a45da
commit 5a4dffc9a3
26 changed files with 773 additions and 621 deletions
+8 -2
View File
@@ -19,8 +19,14 @@ describe('game theme', () => {
expect(allValues(gameTheme).filter((value) => String(value).includes('-var('))).toEqual([]);
});
it('keeps the phone rank bar at the top instead of stretching it to full height', () => {
expect(gameTheme['@media (max-width: 760px)']['#rank']).toMatchObject({ bottom: 'auto' });
it('keeps the floating menu and objective clear of the phone notch', () => {
expect(gameTheme['#game-menu'].top).toContain('safe-area-inset-top');
expect(gameTheme['#objective'].top).toContain('safe-area-inset-top');
});
it('gives every floating menu item a 44px tap target', () => {
expect(gameTheme['.menu-item']['min-height']).toBe('var(--game-token-32)');
expect(gameTheme[':root']['--game-token-32']).toBe('44px');
});
it('keeps the landscape phone layout as a top-level media block', () => {