# EL3AB — Game Architecture

## Experience Pillars

| # | Pillar | Design Test |
|---|--------|-------------|
| 1 | **GAME IN 30 SECONDS** | Does this add steps before playing? Remove it. |
| 2 | **THE TABLE IS SACRED** | Does this distract from gameplay? Kill it. |
| 3 | **COMPETITIVE PRESTIGE** | Does this make ranking feel important? Keep it. |
| 4 | **ARAB-BORN, NOT ARAB-TRANSLATED** | Would this feel foreign in Cairo/Riyadh? Fix it. |
| 5 | **ALWAYS ALIVE** | Is any pixel on screen completely still? Animate it. |

---

## The Mental Model: THE TABLE

The player is always "at the table." The table is the center of the universe.

```
      RANK ← ← ←  [  PLAY  ]  → → → SHOP
     SOCIAL ← ←   [ CENTER ]    → → PROFILE
                   [THE TABLE]
```

5 horizontal worlds (tabs). PLAY is center. You start here, return here.

---

## Tech Stack

| Layer | Choice | Why |
|-------|--------|-----|
| **Rendering: Game Boards** | Canvas 2D (60fps) | Pixel-perfect control, smooth piece animation, touch/drag, no DOM layout thrashing |
| **Rendering: UI/Menus** | DOM + CSS animations | Faster to build, accessible, text-heavy screens (leaderboard, shop, profile). Still animated and game-feeling. |
| **Animation Engine** | Custom tween system (JS) | Powers both Canvas objects and DOM elements. Easings, springs, sequences. |
| **State Management** | Reactive store (pub/sub) | Modules subscribe to player data changes. HUD auto-updates. No framework needed. |
| **Module Communication** | Event bus | Modules never import each other. Fire events, subscribe to events. |
| **Network: REST** | fetch → PHP API → Supabase | PHP proxy hides keys, validates, does business logic (rating calc, etc.) |
| **Network: Realtime** | Supabase Realtime (WebSocket) | Multiplayer sync, matchmaking notifications, live game state. |
| **Audio** | Web Audio API + sprite sheet | One file, multiple sound cues. Instant playback. Categories (UI/game/reward). |
| **Backend** | PHP 8.3 (JSON API only) | No HTML rendering. Pure data endpoints. Stateless. |
| **Deployment** | Docker (PHP Apache) → CapRover | Same as management panel. Auto-deploy on git push. |
| **Database** | Supabase PostgreSQL (existing 106 tables) | Already built. Player app uses anon key + user JWT. |

### Why Canvas for game boards specifically:
- Piece drag with sub-pixel accuracy
- Smooth 60fps move animations (no CSS reflow)
- Custom rendering (domino chains, ludo paths, chess highlights)
- Touch handling with gesture recognition
- Board flip/rotation with real transforms
- Particle effects (captures, wins, power-ups) without DOM bloat

### Why DOM for UI screens:
- Text-heavy (leaderboard, notifications, shop)
- Accessibility (screen readers, focus management)
- Faster iteration (HTML+CSS vs. canvas draw calls for buttons/lists)
- CSS animations are GPU-accelerated and sufficient for UI transitions
- Input elements (search, forms) are native

---

## Navigation Architecture

### 5 Worlds (Horizontal Swipe / Bottom Tabs)

```
┌──────┬────────┬────────┬──────┬─────────┐
│ RANK │ SOCIAL │  PLAY  │ SHOP │ PROFILE │
│      │        │(center)│      │         │
└──────┴────────┴────────┴──────┴─────────┘
```

- Bottom tab bar (5 icons) — always visible EXCEPT during active gameplay
- Swipe horizontally between worlds (momentum, snap)
- Active tab glows
- Each world has its own internal navigation (push/pop scenes within)
- PLAY tab is always index 2 (center)

### SOCIAL World (Deep Structure)

The SOCIAL world contains the org sub-world. Entering your org is like entering a building — it has its own internal tab navigation:

```
SOCIAL WORLD
├── Friends (list, search, pending)
├── Notifications (feed)
├── Activity Feed (timeline of friend actions)
└── MY ORG (sub-world entry) ─────────────────┐
     │                                          │
     ├── Org Home (announcements, spotlights)   │
     ├── Chat (channels, messages, realtime)    │
     ├── Events (calendar, training, RSVP)      │
     ├── Members (list, roles, online)          │
     ├── Compete (leaderboard, challenges)      │
     ├── Rewards (org achievements, loyalty)    │
     ├── Content (articles, media gallery)      │
     └── Recruitment (browse, apply)            │
                                                │
     If not in an org: shows ORG BROWSER        │
     (search, browse, join via link/code/apply) │
────────────────────────────────────────────────┘
```

### Advertising System (Subtle Arena Sponsorship)

Ads are designed to look like arena sponsorship — never popups, never during gameplay.

| Slot | Location | Style |
|------|----------|-------|
| lobby_banner | Play tab (bottom area) | Horizontal banner that looks like arena sponsor signage |
| between_matches | After game result, before return to lobby | Full-screen interstitial (skippable, arena-sponsor branded) |
| tournament_sponsor | Tournament detail page | Sponsor logo + banner integrated into tournament branding |
| reward_video | Daily reward / retry puzzle | Opt-in: "Watch for bonus" button. Player chooses. |

All ad views tracked in `ad_impressions`. Active ads loaded from `ad_campaigns` + `ad_creatives` based on `ad_slots` config.

### In-Game Chat System

| Context | Mode | Tables |
|---------|------|--------|
| During match (strangers) | Preset emotes only (👍 Good move, ⏱ Hurry, 🤝 GG) | `chat_messages` (type=emote) |
| During match (friends/org-mates) | Emotes + free text | `chat_messages` (type=text) |
| Org chat | Full text + channels + replies | `org_chat_channels`, `org_chat_messages` |

### Dynamic Theming (3 Layers)

```
Layer 1: PLATFORM (base)     → platform_theme, platform_assets, platform_branding
Layer 2: GAME (board colors) → game_theme_overrides (per game_key)
Layer 3: ORG (accent colors) → org_theme_overrides (when in org context)

Final theme = Layer 1 ← override with Layer 2 ← override with Layer 3
```

Applied via CSS custom properties that get swapped when context changes.

### Player Reporting

Flow: Tap opponent avatar (from result screen or their profile) → "Report" → Pick reason → Optional: add description → Submit.

Reasons: cheating, harassment, inappropriate_name, spam, other.
Stored in `cheat_reports` with match reference.

### Clubs (Merged)

Clubs = lightweight orgs (free tier). Same UI. `clubs` and `club_members` tables are surfaced within the org browser with a "club" badge. No separate module.

### In-Game Mode
When a game starts, the entire screen becomes the game board:
- Tab bar hides (slides down)
- HUD minimizes to essential (clocks, player names)
- BACK = resign confirmation
- Game end → result overlay → tap to return to PLAY world

---

## Screen Flow Map

```
APP OPEN
    │
    ├─ Has token? → Validate → OK → PLAY world (center)
    │                         → Expired → AUTH (login)
    └─ No token → AUTH (splash → login/register)

PLAY WORLD (center tab)
    │
    ├── Game Carousel (swipe through chess/backgammon/domino/ludo)
    │     └── Each card shows: live preview, your rating, game name
    │
    ├── PLAY button (below active card)
    │     ├── vs Bot → Bot Selector → Time Control → GAME START
    │     ├── vs Human → Time Control → Matchmaking Queue → GAME START
    │     └── vs Friend → Friend Picker → Invite → Wait → GAME START
    │
    ├── Daily Reward widget (tap to claim)
    └── Friends Online widget (tap to challenge)

GAME (full screen, canvas)
    │
    ├── Active Gameplay (moves, clock, captures)
    ├── Game Controls (resign, draw, flip, chat)
    └── Game End → Result Screen
          ├── Rating change animation
          ├── Coins/XP earned
          ├── Achievement unlocked (if any)
          └── Actions: Rematch / New Game / Back to Table

RANK WORLD (tab 1)
    ├── Leaderboard (tabs: game × time control)
    ├── Your Rank card (tier, rating, percentile)
    ├── Season info (if seasonal)
    └── Tournaments (upcoming, live, past)
          └── Tournament Detail → Register / View Bracket

SOCIAL WORLD (tab 2)
    ├── Friends List (online first, with challenge button)
    ├── Friend Requests (pending)
    ├── Notifications feed
    ├── Organization (if member)
    │     └── Org page, members, events
    └── Search (find players)

SHOP WORLD (tab 4)
    ├── Featured / Daily Deals
    ├── Categories (frames, boards, pieces, effects, bundles)
    ├── Item Detail → Purchase → Equip
    └── Your Collection (owned items)

PROFILE WORLD (tab 5)
    ├── Player Card (avatar, frame, rank badge, ratings)
    ├── Stats Dashboard (games, wins, streaks per game)
    ├── Match History
    ├── Achievements Grid
    ├── Rating History Graph
    └── Settings (sound, language, preferences)
```

---

## Module Architecture

### Module Structure

```
modules/
├── core/                    # Game engine (not a "module" — the foundation)
│   ├── engine.js            # Boot sequence, lifecycle
│   ├── scene.js             # Scene stack, transitions, world management
│   ├── store.js             # Reactive state store
│   ├── bus.js               # Event bus (pub/sub)
│   ├── net.js               # REST + Realtime wrapper
│   ├── canvas.js            # Canvas utilities (draw, hit-test, sprite)
│   ├── tween.js             # Animation system (DOM + Canvas objects)
│   ├── audio.js             # Sound sprite system
│   ├── input.js             # Touch/mouse/gesture handler
│   ├── hud.js               # Persistent HUD renderer
│   └── i18n.js              # Arabic/English string management
│
├── auth/                    # AUTH MODULE
│   ├── mod.js               # register, mount, unmount
│   ├── scenes/
│   │   ├── splash.js        # Animated logo, token check
│   │   ├── login.js         # Email + password
│   │   └── register.js      # Username + email + password
│   ├── api.js               # signup, login, refresh, logout
│   └── style.css
│
├── play/                    # PLAY WORLD MODULE (center tab)
│   ├── mod.js
│   ├── scenes/
│   │   ├── table.js         # Main play screen: carousel + play button
│   │   ├── bot-select.js    # Bot portrait grid
│   │   ├── time-select.js   # Time control visual picker
│   │   ├── queue.js         # Matchmaking search animation
│   │   └── friend-pick.js   # Challenge a friend
│   ├── components/
│   │   ├── game-card.js     # Carousel card (with canvas preview)
│   │   ├── play-button.js   # Animated play button
│   │   └── mode-picker.js   # vs Bot / vs Human / vs Friend
│   ├── api.js               # matchmaking queue/dequeue
│   └── style.css
│
├── chess/                   # CHESS GAME MODULE
│   ├── mod.js
│   ├── scenes/
│   │   ├── game.js          # Full game screen (canvas board + DOM panels)
│   │   └── result.js        # Game over + reward ceremony
│   ├── canvas/
│   │   ├── board.js         # Canvas: 8x8 board rendering
│   │   ├── pieces.js        # Canvas: piece sprites, drag, animate
│   │   ├── highlights.js    # Canvas: legal moves, last move, check
│   │   └── effects.js       # Canvas: capture particles, check flash
│   ├── components/
│   │   ├── clock.js         # DOM: dual game clocks
│   │   ├── moves.js         # DOM: scrollable move list
│   │   ├── controls.js      # DOM: resign, draw, flip buttons
│   │   └── captured.js      # DOM: captured pieces row
│   ├── logic/
│   │   ├── engine.js        # chess.js wrapper + move validation
│   │   ├── clock.js         # Timer logic (increment, low-time)
│   │   └── premove.js       # Pre-move queue
│   ├── api.js               # start, move, resign, draw, end
│   └── style.css
│
├── domino/                  # DOMINO GAME MODULE
│   ├── mod.js
│   ├── scenes/
│   │   ├── room.js          # Waiting room (players joining)
│   │   ├── game.js          # Active game (canvas table + DOM hand)
│   │   └── result.js        # Round/game over
│   ├── canvas/
│   │   ├── table.js         # Canvas: domino chain on table
│   │   ├── tiles.js         # Canvas: tile rendering + pip drawing
│   │   └── effects.js       # Canvas: place animation, draw animation
│   ├── components/
│   │   ├── hand.js          # DOM/Canvas: player's hand (interactive)
│   │   ├── scores.js        # DOM: score tracker
│   │   └── turn.js          # DOM: turn indicator
│   ├── logic/
│   │   ├── rules.js         # Domino game rules, valid placements
│   │   ├── scoring.js       # Pip counting, round/game scoring
│   │   └── ai.js            # Bot logic (if single-player)
│   ├── api.js               # create, join, play, draw-tile, end
│   └── style.css
│
├── ludo/                    # LUDO GAME MODULE
│   ├── mod.js
│   ├── scenes/
│   │   ├── room.js          # Waiting room
│   │   ├── game.js          # Active game (canvas board)
│   │   └── result.js        # Winner ceremony
│   ├── canvas/
│   │   ├── board.js         # Canvas: cross-shaped board + paths
│   │   ├── pieces.js        # Canvas: colored pieces + animation
│   │   ├── dice.js          # Canvas: animated dice roll
│   │   └── effects.js       # Canvas: capture, safe zone, finish
│   ├── logic/
│   │   ├── rules.js         # Movement rules, captures, safe squares
│   │   ├── dice.js          # Dice logic, extra turns on 6
│   │   └── ai.js            # Bot logic
│   ├── api.js               # create, join, roll, move, end
│   └── style.css
│
├── rank/                    # RANK WORLD MODULE (tab 1)
│   ├── mod.js
│   ├── scenes/
│   │   ├── leaderboard.js   # Rankings (tabs per game/time)
│   │   ├── my-rank.js       # Player's rank card + tier
│   │   └── tournaments.js   # Tournament list + detail + bracket
│   ├── components/
│   │   ├── rank-card.js     # Visual rank/tier display
│   │   ├── player-row.js    # Leaderboard entry
│   │   └── bracket.js       # Tournament bracket renderer
│   ├── api.js               # leaderboard, tournaments, register
│   └── style.css
│
├── social/                  # SOCIAL WORLD MODULE (tab 2)
│   ├── mod.js
│   ├── scenes/
│   │   ├── friends.js       # Friends list + requests
│   │   ├── notifications.js # Notification feed
│   │   └── org.js           # Organization page
│   ├── components/
│   │   ├── friend-card.js   # Avatar, name, online, actions
│   │   ├── notif-item.js    # Notification row
│   │   └── org-card.js      # Organization info
│   ├── api.js               # friends, notifications, org
│   └── style.css
│
├── shop/                    # SHOP WORLD MODULE (tab 4)
│   ├── mod.js
│   ├── scenes/
│   │   ├── browse.js        # Category tabs + item grid
│   │   ├── item.js          # Item detail + preview
│   │   └── collection.js    # Owned items
│   ├── components/
│   │   ├── item-card.js     # Cosmetic item card (rarity glow)
│   │   ├── purchase.js      # Purchase confirmation overlay
│   │   └── price-tag.js     # Coin/gem price display
│   ├── api.js               # list, purchase, equip
│   └── style.css
│
├── profile/                 # PROFILE WORLD MODULE (tab 5)
│   ├── mod.js
│   ├── scenes/
│   │   ├── view.js          # Full player card + stats
│   │   ├── edit.js          # Edit profile fields
│   │   ├── history.js       # Match history
│   │   └── achievements.js  # Achievement grid
│   ├── components/
│   │   ├── player-card.js   # Big avatar + frame + rank + ratings
│   │   ├── stat-grid.js     # Games/wins/streaks per game
│   │   ├── rating-chart.js  # Canvas: sparkline rating history
│   │   └── achievement.js   # Achievement tile (progress bar)
│   ├── api.js               # get, update, history, achievements
│   └── style.css
│
├── rewards/                 # REWARDS MODULE (cross-cutting)
│   ├── mod.js
│   ├── scenes/
│   │   ├── daily.js         # Daily reward chest/calendar
│   │   └── levelup.js       # Level-up full-screen ceremony
│   ├── components/
│   │   ├── coin-rain.js     # Canvas: coin particle effect
│   │   ├── xp-fill.js       # Animated XP bar fill
│   │   ├── badge-unlock.js  # Achievement badge animation
│   │   └── rank-up.js       # Rank tier promotion animation
│   ├── api.js               # daily claim, XP/level endpoints
│   └── style.css
│
└── puzzles/                 # PUZZLES MODULE
    ├── mod.js
    ├── scenes/
    │   ├── puzzle.js         # Puzzle board (reuses chess/canvas/)
    │   └── result.js         # Solved/failed + rating change
    ├── logic/
    │   └── validator.js      # Check solution moves
    ├── api.js                # random, submit
    └── style.css
```

---

## Module Isolation Rules

1. **A module NEVER imports from another module's folder.**
2. **A module CAN import from `modules/core/`** (engine, bus, store, net, tween, canvas, audio).
3. **Modules communicate ONLY via the event bus.**
4. **Working on module X = touching ONLY `modules/X/` and its PHP API endpoint.**
5. **Each module's CSS is scoped** (data-module attribute or class prefix).
6. **A module can be deleted and the app still works** (tab just shows "coming soon").
7. **Each game module owns its Canvas** — no shared canvas between games.

### Shared Canvas Utilities (from core)

Games DON'T share canvas code between modules. But they DO share utility functions from `core/canvas.js`:
- `createCanvas(container, width, height)` — sized/retina-ready canvas
- `hitTest(x, y, rect)` — point-in-rect collision
- `drawSprite(ctx, sheet, frame, x, y, w, h)` — sprite drawing
- `clear(ctx)` — clear canvas

Each game module has its OWN board rendering, piece logic, and game-specific drawing code. Chess board code lives in `chess/canvas/board.js`. Domino table code lives in `domino/canvas/table.js`. They never share.

---

## Event Bus Contracts

### Events Any Module Can Emit
```
'game:started'     → { gameKey, matchId, opponent, mode }
'game:ended'       → { gameKey, matchId, result, ratingChange, coinsEarned, xpEarned }
'coins:earned'     → { amount, reason }
'xp:earned'        → { amount }
'achievement:unlocked' → { id, name, nameAr }
'friend:challenge' → { friendId, gameKey }
'navigate'         → { world, scene, params }
```

### Events the Core Listens To
- `'coins:earned'` → HUD animates coin counter
- `'xp:earned'` → HUD animates XP bar, checks level-up
- `'game:started'` → Hides tab bar, enters game mode
- `'game:ended'` → Shows tab bar, triggers reward module
- `'achievement:unlocked'` → Triggers badge animation overlay
- `'navigate'` → Scene manager transitions

---

## State Store Schema

```javascript
store = {
  // Auth
  auth: { token, refreshToken, userId },
  
  // Player (synced from Supabase on login)
  player: {
    id, username, displayName, displayNameAr,
    avatarUrl, frameId, borderColor,
    level, xp, xpToNext,
    coins, gems,
    countryCode,
    isOnline: true,
    ratings: {
      chess: { bullet: 1200, blitz: 1350, rapid: 1400 },
      domino: { classic: 1100 },
      ludo: { standard: 1050 }
    }
  },
  
  // Live state
  notifications: { unreadCount: 0 },
  friends: { onlineCount: 0 },
  currentGame: null,  // { matchId, gameKey } if in a game
  features: {},       // feature flags from server
  
  // UI state
  activeWorld: 'play', // which tab is active
  audioEnabled: true,
  language: 'ar'
}
```

---

## Backend (PHP API)

The backend is STATELESS and THIN. It does NOT render HTML. Every endpoint returns JSON.

```
api/
├── auth.php           # POST: signup, login, logout, refresh
├── game.php           # POST: start, move, resign, draw, end (chess)
├── matchmaking.php    # POST: queue, dequeue, status
├── domino.php         # POST: create, join, play, draw-tile, pass, end
├── ludo.php           # POST: create, join, roll, move, end
├── profile.php        # GET/PATCH: get, update, upload avatar
├── friends.php        # GET/POST/DELETE: list, request, accept, remove
├── notifications.php  # GET/PATCH: list, mark-read, count
├── leaderboard.php    # GET: by game, time-control, period
├── puzzles.php        # GET/POST: random, submit solution
├── shop.php           # GET/POST: list, purchase, equip
├── achievements.php   # GET: list with progress
├── daily-reward.php   # POST: claim
├── tournaments.php    # GET/POST: list, register, cancel, bracket
├── bots.php           # GET/POST: list bots, proxy move to Stockfish
├── ratings.php        # GET: history
└── config.php         # GET: feature flags, game plugins, version
```

---

## File System (Complete)

```
el3ab-player/
├── index.php                     # HTML shell (single page, no rendering)
├── Dockerfile                    # PHP 8.3 Apache
├── captain-definition            # CapRover deploy
├── .htaccess                     # Rewrite all non-asset URLs to index.php
│
├── api/                          # PHP JSON endpoints
│   ├── auth.php
│   ├── game.php
│   ├── matchmaking.php
│   ├── domino.php
│   ├── ludo.php
│   ├── profile.php
│   ├── friends.php
│   ├── notifications.php
│   ├── leaderboard.php
│   ├── puzzles.php
│   ├── shop.php
│   ├── achievements.php
│   ├── daily-reward.php
│   ├── tournaments.php
│   ├── bots.php
│   ├── ratings.php
│   └── config.php
│
├── config/                       # PHP config
│   ├── constants.php             # URLs, keys, settings
│   └── database.php              # Supabase REST client class
│
├── includes/                     # PHP helpers
│   ├── supabase.php              # REST client (GET/POST/PATCH/DELETE)
│   └── auth.php                  # Token validation helper
│
├── public/                       # Static assets (served directly by Apache)
│   ├── css/
│   │   ├── tokens.css            # Design tokens
│   │   └── core.css              # Engine styles (layers, HUD, transitions)
│   ├── js/
│   │   ├── engine.js             # Entry point (boots the game)
│   │   ├── core/                 # Game engine core
│   │   │   ├── scene.js
│   │   │   ├── store.js
│   │   │   ├── bus.js
│   │   │   ├── net.js
│   │   │   ├── canvas.js
│   │   │   ├── tween.js
│   │   │   ├── audio.js
│   │   │   ├── input.js
│   │   │   ├── hud.js
│   │   │   └── i18n.js
│   │   ├── modules/              # Game modules (loaded on demand)
│   │   │   ├── auth/
│   │   │   ├── play/
│   │   │   ├── chess/
│   │   │   ├── domino/
│   │   │   ├── ludo/
│   │   │   ├── rank/
│   │   │   ├── social/
│   │   │   ├── shop/
│   │   │   ├── profile/
│   │   │   ├── rewards/
│   │   │   └── puzzles/
│   │   └── lib/
│   │       └── chess.min.js
│   ├── assets/
│   │   ├── sprites/              # Sprite sheets (pieces, tiles, icons)
│   │   ├── audio/                # Sound sprites
│   │   └── img/                  # Static images (logos, bots, backgrounds)
│   └── fonts/
│       └── ibm-plex-arabic/
│
└── docs/                         # Reference documentation
    ├── supabase_master_audit.md
    └── ...
```

---

## Rendering Strategy Per Screen

| Screen | Renderer | Why |
|--------|----------|-----|
| Splash / Login / Register | DOM + CSS animation | Text-heavy forms, simple animations |
| Play Tab (carousel + button) | DOM + Canvas mini-previews | Cards are DOM, game previews are tiny canvases |
| Bot Selector | DOM | Portrait grid, text labels |
| Matchmaking Queue | DOM + Canvas background | Animated search radar on canvas, UI is DOM |
| Chess Game Board | **Canvas (full)** | 60fps piece drag, highlights, particles |
| Chess Panels (clock, moves) | DOM | Text updates, scrollable lists |
| Domino Table | **Canvas (full)** | Tile chain rendering, place animations |
| Domino Hand | DOM or Canvas | Interactive tile selection |
| Ludo Board | **Canvas (full)** | Animated pieces, dice roll, path highlights |
| Leaderboard | DOM | Text table with scroll |
| Shop | DOM + Canvas previews | Item cards are DOM, cosmetic previews are canvas |
| Profile | DOM + Canvas chart | Stats are DOM, rating sparkline is canvas |
| Notifications | DOM | Scrollable text list |
| Reward Ceremonies | Canvas overlay | Full-screen particles, coin rain, badge glow |

---

## Game-Specific Canvas Requirements

### Chess Canvas
- 8x8 grid with alternating colors (themed)
- Piece sprite sheet (6 pieces × 2 colors × 2 sizes = 24 frames)
- Drag: piece follows finger/cursor smoothly (no snapping until release)
- Legal move indicators: circles on empty squares, outlines on captures
- Last move: highlighted squares with subtle pulse
- Check: king square flashes red
- Animations: piece slides to destination, captured piece shrinks/fades
- Promotion: piece choice popup
- Board flip: 180° rotation with smooth tween

### Domino Canvas
- Table surface with chains growing outward from center
- Tile: rounded rectangle with pips (dots) rendered from data
- Rotation: tiles orient based on placement direction
- Chain logic: left end, right end, spinner (double)
- Place animation: tile slides from hand to table position
- Draw animation: tile slides from boneyard to hand

### Ludo Canvas
- Cross-shaped board with 4 colored home zones
- 52 shared squares + 4×6 home columns + 4 finish squares
- Pieces: colored circles with player number
- Dice: animated 3D-ish cube roll
- Movement: piece hops square-by-square with bounce easing
- Capture: opponent piece flies back to home with trail effect
- Finish: piece glows and scales when reaching finish

---

## Design Tokens

```css
:root {
  /* Surfaces */
  --bg-deep: #050810;        /* Deepest background */
  --bg-base: #0A1020;        /* Main background */
  --bg-card: #121A2E;        /* Card surfaces */
  --bg-elevated: #1A2440;    /* Elevated elements, inputs */
  --bg-hover: #223050;       /* Hover states */
  
  /* Brand */
  --gold: #E4AC38;           /* Primary accent, CTAs, trophies */
  --gold-soft: #FFCC66;      /* Secondary gold, warm highlights */
  --blue: #2082F0;           /* Competitive blue, links, active */
  --cyan: #00FFFF;           /* Hover glows, electric accents */
  --orange: #E84D1E;         /* Alerts, live indicators, urgency */
  --purple: #6834BE;         /* Rare/legendary, elite */
  
  /* Text */
  --text-primary: #F8FAFC;   /* Primary text */
  --text-secondary: #94A3B8; /* Secondary text */
  --text-muted: #475569;     /* Muted/disabled */
  
  /* Feedback */
  --success: #34D399;
  --error: #EF4444;
  --warning: #F59E0B;
  
  /* Borders */
  --border: rgba(255,255,255,0.06);
  --border-hover: rgba(255,255,255,0.12);
  --border-active: rgba(32,130,240,0.4);
  
  /* Radii */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 24px;
  --r-full: 9999px;
  
  /* Spacing (8px base) */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px;
  --s-4: 16px; --s-5: 20px; --s-6: 24px;
  --s-8: 32px; --s-10: 40px; --s-12: 48px;
  --s-16: 64px;
  
  /* Typography */
  --font-ar: 'IBM Plex Sans Arabic', sans-serif;
  --font-lat: 'Inter', sans-serif;
  --font-mono: 'IBM Plex Mono', monospace;
  
  /* Motion */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --dur-fast: 150ms;
  --dur-normal: 250ms;
  --dur-slow: 400ms;
}
```

---

## Summary

| Aspect | Decision |
|--------|----------|
| What is it | A game that runs in the browser |
| Core metaphor | The Table — game is center, everything orbits |
| Navigation | 5 horizontal worlds (swipe/tabs), PLAY is center |
| Game rendering | Canvas 2D @ 60fps |
| UI rendering | DOM + CSS animations |
| Architecture | Sealed modules, event bus communication |
| Backend | PHP JSON API (no HTML rendering) |
| First action | Game in 30 seconds — open → carousel → tap → play |
| Identity | Layered: rank gives respect, cosmetics give style, org gives belonging |
| Feel | Premium Arab arena. Always alive. Never a dead pixel. |
