feat(tutorial): add movement and hand-tracking onboarding overlays

Mount two first-time tutorial overlays driven by the game state machine:

- MovementTutorial: visible during the intro reveal and the free-walk
  step before the ebike mount, dismissed on the first Z/Q/S/D keydown.
- HandTrackingTutorial: visible during the early ebike repair steps
  (fragmented, scanning, inspected), dismissed when MediaPipe detects
  any hand on screen.

Both share a generic TutorialOverlay shell (transparent panel, dark
blue border, lucide-react Hand / inline ZQSD keycap icons, centered
text). The overlay sits at z-index 14, behind Subtitles (15) and
the talkie overlay (16), so dialogue/subtitle UI stays in front.

Dismissals stay persistent for the session: keyboard-triggered uses
event-handler setState; hand-detection uses a guarded effect-driven
setState (same pattern as PylonDownedPylon resync).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tom Boullay
2026-06-03 01:43:25 +02:00
parent 1cc3b0e47e
commit 5f113cbba4
5 changed files with 210 additions and 0 deletions
+67
View File
@@ -1812,6 +1812,73 @@ canvas {
pointer-events: none;
}
.tutorial-overlay {
position: fixed;
inset: 0;
z-index: 14;
display: flex;
align-items: center;
justify-content: center;
background: rgba(96, 165, 250, 0.55);
pointer-events: none;
}
.tutorial-overlay__panel {
display: flex;
flex-direction: column;
align-items: center;
gap: 36px;
padding: 56px 72px;
max-width: 640px;
background: transparent;
border: 2px solid #1e3a8a;
border-radius: 24px;
color: #1e3a8a;
}
.tutorial-overlay__icon {
display: flex;
align-items: center;
justify-content: center;
}
.tutorial-overlay__text {
font-family: var(--font-body);
font-size: 1.1rem;
font-weight: 500;
line-height: 1.45;
text-align: center;
margin: 0;
}
.tutorial-overlay__keyboard {
display: grid;
grid-template-columns: repeat(3, 64px);
gap: 8px;
font-family: var(--font-primary);
}
.tutorial-overlay__keycap {
display: flex;
align-items: center;
justify-content: center;
width: 64px;
height: 64px;
background: #e0f2fe;
border: 2px solid #1e3a8a;
border-radius: 10px;
font-size: 1.6rem;
font-weight: 700;
color: #1e3a8a;
}
.tutorial-overlay__hands {
display: flex;
align-items: center;
gap: 32px;
color: #1e3a8a;
}
.hand-tracking-fallback__icon {
position: absolute;
width: 80px;