HedgeEm UI Component Inventory
This page catalogues every visual and interactive UI component that makes up a HedgeEm game. Components are grouped into two categories:- Common — present in every HedgeEm game variant (JS, TypeScript, UMA, V7)
- V7-specific — unique to the horse-race skin in hedgeem-v7
Common Components
These components appear in all game variants. The implementation differs per skin but the business function is identical.| Component | Description | Feature ID | V7 Implementation |
|---|---|---|---|
| Hole card display | Two face-up cards shown per hand from deal onwards | F022 | SVG cards in info panel rows, tilted ±5° |
| Community card display | 5 board cards revealed progressively (3 at FLOP, 1 at TURN, 1 at RIVER) | F022 | .grass-card elements in .posts-layer; scroll in from right in sync with stage fences (F100) |
| Odds display | Win probability shown as X:1 ratio per hand, updated each stage | F024 | Gold text in info panel rows (hr-odds) |
| Hand name display | Short hand description (e.g. “Pair of Kings”) per hand per stage | F023 | hr-hand text in info panel rows |
| Stage advance button | Primary CTA to advance game from HOLE→FLOP→TURN→RIVER→new round | F021 | Gold ▶ RUN / ▶ DEAL button below track; disabled during auto-run and transition |
| Stage label | Text description of current game state shown near advance button | F028 | Italic gold label below RUN button |
| Chip selector | Row of betting chip denominations (50p, £1, £2, £5, £10, £20) | F029 | Coloured circular chip buttons, active chip highlighted |
| Bet placement UI | Click a hand to place the selected chip denomination as a bet | F011 | Click horse row in info panel |
| Bet badge | Confirms active bet amount on a hand | F011 | Teal Bet: £X.XX badge inside horse info row |
| Clear bets button | Cancels all bets placed in the current stage | F012 | Outline gold button next to bet hint |
| Credits / wallet display | Running credit total visible at all times | F016 | Credits: £X.XX above chip row |
| Win / payout screen | Full-screen overlay announcing win amount with animation | F027 | Dark overlay with trophy, horse name, amount + coin fall |
| Coin animation | Celebratory coins burst on a win | F048 | 45 animated gold coins falling from top of track |
| Commentator / speech bubble | Character with speech bubble delivering stage commentary | — | Top-hat figure in grass area, right of RIVER sign; bubble appears/fades on each stage |
| Sound / ambient audio | Crowd noise, hoofbeats, bugle call, win fanfare | F060, F061 | Web Audio API; gallop loop, ambient MP3, bugle MP3 |
V7-Specific Components
These components are unique to the horse-race skin and have no equivalent in JS or TypeScript variants.| Component | Description | Source / Notes |
|---|---|---|
| Animated dirt track | Procedural scrolling dirt track using two 1920px SVG tiles looped via @keyframes dirt-move at 400 px/s | Controlled by setDirtRunning(on) — paused at HOLE, running from first Run click until River end (F198) |
| Grass area | Green strip above track; holds community cards, fence posts, and commentator | CSS gradient, top:82px height:80px |
| Crowd stand | Coloured dot crowd at top of track | 230 random-coloured dots, crowd-dots div |
| Fence rail | White rail separating grass from dirt | CSS white bar at top:156px height:12px |
| Starting gates | Gate structure at left edge of track; closed at HOLE, opens when race starts | gates.png background-image; clipped at HOLE, expands via .open class |
| Background fences | Semi-transparent unlabelled fence posts that scroll left at 400 px/s between stage fences | spawnFence() with subtle:true; spawned on FENCE_INTERVAL_MS timer while race is running; carry makeSubtlePostSVG() sign |
| Stage fences | Labelled coloured fence posts (FLOP=red, TURN=orange, RIVER=blue) that scroll in on each stage | spawnFence({label, cardEl, cardDockX, onAllCleared}); dock at POST_DOCK_X; onAllCleared fires when all active horses clear the post (F199) |
| Community card scroll | 5 individual .grass-card elements (grassCardEls[0..4]) in .posts-layer; each scrolls in from right at 400 px/s via scrollInCard() synchronised with its fence | FLOP: 3 fences sequential at ~580ms intervals; fence 3 carries FLOP post; TURN: 1 fence + card; RIVER: 1 fence + card, finish line ~580ms later (F200) |
| Finish line | Dynamically spawned green vertical bar + chequered flag; scrolls in and docks at 90% track width | spawnFinishFence() — appears ~580ms after RIVER fence |
| Horse SVG | Animated horse + jockey sprite per lane | Inline SVG, 116×86px; body, legs, tail, jockey all individually animated |
| Horse gallop animation | Continuous body bounce + leg cycling while race is in progress | CSS @keyframes gallop-bounce, leg-fl/fr/rl/rr, tail-wave at 0.36s cycle; only active (non-eliminated) horses animate |
| Horse jump animation | Leap animation as horse clears each hurdle | CSS @keyframes horse-jump 0.8s; triggered when nose is ~20px before fence post |
| Horse probability positioning | Horses positioned logarithmically by percentWin; no CSS transition — rAF lerp drift loop | probToPx(p, fi): HOLE/FLOP/TURN range 20–80% track width; RIVER range 20–90%; lerp factor horseLerpFactor × dt (F205) |
| Horse oscillation | Each active horse continuously drifts ±4% of track width around its base position using 3-sinusoid per-horse noise; rank order preserved | OSC_AMP_FRAC=0.04; OSC_MIN_GAP=20px; active while raceStarted=true and raceEnded=false (F201) |
| Auto-run on bugle | After bugle finishes, autoStartHoleRun() fires automatically: pistol sound, gate opens, dirt starts, horses gallop to HOLE-odds positions | Run button disabled during auto-run; re-enabled via waitForHorsesSettled(threshold, cb) (F202) |
| Eliminated horse scroll-off | horseScrollingOff[i] flag — horse scrolls left at dirt speed (400 px/s), flips upside-down (rotate(180deg), grayscale(0.9), opacity:0.5), vanishes off-screen | Triggered when percentWin <= 0 after FLOP/TURN fence cleared (F204) |
| Saddle number badge | Coloured rectangle on horse flank showing lane number (1=red, 2=silver, 3=blue, 4=gold) | .horse-num; jiggles in sync with gallop-bounce; hidden behind gate z-index at HOLE |
| Horse info panel | Left panel with one row per horse; rows vertically aligned with track lanes | 220px wide, 166px top spacer, 71px rows (LANE_H) |
| Horse info row | Per-lane display: number badge → horse name → hand name → bet badge → hole cards → odds | .horse-row; clickable to place a bet |
| Bet-placement horse pop | Scale bounce on the horse SVG when a bet is placed | horse-bet-pop keyframe: scales to 1.35× with springy ease, 400ms (F203) |
| Winner label | Gold 🏆 [Horse Name] badge above winning horse after race | .winner-label animated pop, z-index:20 |
| Win screen overlay | Full-screen semi-transparent overlay with winner details | .win-screen, sits inside .track-container at z-index:50 |
Layout Constants (V7)
These values are fixed design constants. Do not change without updating all dependent components.| Constant | Value | Used by |
|---|---|---|
| Track container height | 452px | .track-container, gate height calc |
| Crowd height | 82px | .crowd, spacer, commentator position |
| Grass height | 80px (top 82–162px) | .grass, commentator bottom alignment |
| Fence rail height | 12px (top 156–168px) | .fence-rail |
| Dirt / lane section top | 166px | .dirt, .gate-wrap, fence/horse positioning |
| Dirt height | 286px (452−166) | Gate image height, fence height |
| Lane height | 71px (LANE_H) | Horse positioning, info panel rows |
| Number of lanes | 4 (NUM_LANES) | Horse count, gate image |
| Info panel width | 220px | .info-panel, track flex layout |
| Info panel top spacer | 166px | .info-panel-spacer |
| Track/fence scroll speed | 400 px/s (TRACK_PX_PER_SEC) | Dirt tiles, fence rAF loop, card scroll, eliminated horse drift |
| Background fence interval | 4000ms (FENCE_INTERVAL_MS) | Subtle post spawn timer |
| FLOP fence dock position | 98px (POST_DOCK_X[0]) | Stage fence, FLOP community cards |
| TURN fence dock position | 340px (POST_DOCK_X[1]) | Stage fence, TURN community card |
| RIVER fence dock position | 474px (POST_DOCK_X[2]) | Stage fence, RIVER community card |
| FLOP card end position | 332px (STAGE_CARD_END_PX[0]) | Community card dock |
| TURN card end position | 466px (STAGE_CARD_END_PX[1]) | Community card dock |
| RIVER card end position | 600px (STAGE_CARD_END_PX[2]) | Community card dock |
| Sequential fence gap | 232px (HORSE_GAP) | Gap between FLOP’s 3 sequential fences (2 × horse width) |
| Horse oscillation half-range | 0.04 fraction of track width (OSC_AMP_FRAC) | Sinusoidal drift loop |
| Horse oscillation min gap | 20px (OSC_MIN_GAP) | Rank-order clamping between adjacent horses |
| Gallop cycle | 0.36s | All gallop / saddle-badge animations |
| Jump duration | 0.8s | horse-jump keyframe |
| Horse lerp transition | rAF lerp, factor horseLerpFactor × dt | Replaces CSS transition:left; smoothly tracks probability target position |
Race Flow
HOLE loaded
└─ bugle plays → autoStartHoleRun()
└─ pistol SFX, gate opens, setDirtRunning(true)
└─ horses lerp to HOLE-odds positions
└─ waitForHorsesSettled() → Run button re-enabled
Player clicks RUN (FLOP)
└─ 3 fences spawn sequentially at HORSE_GAP intervals
├─ fence 1: subtle post (no label)
├─ fence 2: subtle post (no label)
└─ fence 3: FLOP post (red) + 3 community cards scroll in
└─ onAllCleared → horses lerp to FLOP-odds positions
└─ percentWin=0 horses: horseScrollingOff[i]=true, flip upside-down
└─ waitForHorsesSettled() → Run button re-enabled
Player clicks RUN (TURN)
└─ 1 fence: TURN post (orange) + turn card scrolls in
└─ onAllCleared → horses lerp to TURN-odds positions
└─ percentWin=0 horses scroll off; waitForHorsesSettled() → re-enable
Player clicks RUN (RIVER)
└─ 1 fence: RIVER post (blue) + river card scrolls in
└─ ~580ms later: spawnFinishFence() → finish line scrolls in, docks at 90%
└─ setDirtRunning(false), raceEnded=true
└─ win screen + fanfare