1. 05 Jun, 2026 30 commits
    • Mahmoud Aglan's avatar
      fix: auto-reconnect on homepage + auto-close match after 30s inactivity · c6478774
      Mahmoud Aglan authored
      Player reconnection:
      - On app boot, checks localStorage for active match
      - Verifies match is still 'in_progress' on server before rejoining
      - If match ended/aborted → clears recovery, goes to homepage
      - If server unreachable → tries to rejoin anyway (optimistic)
      
      Match auto-close:
      - handleGet() checks updated_at timestamp on every poll
      - If match hasn't been updated in 30+ seconds → both players inactive
      - Server marks match as 'completed' with result 'aborted'
      - Next player who polls sees status='completed' → game ends cleanly
      - Prevents zombie matches lingering forever
      
      Flow:
      1. Both players disconnect → no pings → updated_at goes stale
      2. After 30s, if either player comes back and polls → server closes match
      3. Match shows as 'aborted' → player sees 'game ended' UI
      4. If only one player comes back within 30s → they keep playing (match alive)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      c6478774
    • Mahmoud Aglan's avatar
      feat: redesign top bar with profile avatar + add photo upload · d6be81de
      Mahmoud Aglan authored
      Replace cluttered logo/level/coins/gems/bell HUD with clean layout:
      avatar+level badge (left), coins+gems (center), bell (right). Avatar
      taps navigate to profile. Add profile photo upload with camera badge
      overlay, client+server validation, Supabase Storage upload endpoint.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      d6be81de
    • Mahmoud Aglan's avatar
    • Mahmoud Aglan's avatar
      feat: match-session.js — comprehensive multiplayer edge case handler · 412ee8f6
      Mahmoud Aglan authored
      New core module handles ALL connection edge cases:
      
      TAB REFRESH RECOVERY:
      - Active match stored in localStorage with timestamp
      - On app boot, checks for recoverable match (< 5 min old)
      - Automatically re-enters the game scene with recovered state
      - Fetches latest state from server immediately
      
      TAB VISIBILITY (switch/minimize):
      - Pauses polling when tab is hidden (saves bandwidth)
      - Resumes and immediately fetches latest state on return
      - Resets disconnect timers on tab return
      
      OPPONENT DISCONNECT DETECTION:
      - Tracks lastOpponentActivity timestamp
      - After 30s: fires onOpponentDisconnect (show warning UI)
      - After 60s: fires onOpponentAbandon (auto-claim win)
      - If opponent comes back: fires onOpponentReconnect
      
      NETWORK LOSS HANDLING:
      - If server unreachable for 10s: fires onConnectionLost
      - On recovery: fires onConnectionRestored
      - Polling continues with error tolerance
      
      SERVER PING (keep-alive):
      - Every 10s, pings server with player ID + timestamp
      - Stored in game_state.ping field
      - Opponent's polling reads this to know sender is alive
      
      API:
      - create(matchId, gameType, callbacks) — start session
      - destroy() — clean up timers + localStorage
      - getRecoverableMatch() — check for resume on boot
      - markOpponentActive() — call when opponent data received
      - isConnected() / isOpponentConnected() — status checks
      
      Engine updated:
      - Imports match-session on boot
      - Checks for recoverable match after auth
      - Auto-resumes game if found
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      412ee8f6
    • Mahmoud Aglan's avatar
    • Mahmoud Aglan's avatar
      fix: chess piece images maintain aspect ratio — no more stretching · a1a13d94
      Mahmoud Aglan authored
      Uses contain-fit logic: scales image to fit within the square while
      preserving natural proportions, centered within the cell.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      a1a13d94
    • Mahmoud Aglan's avatar
      feat: game tile colors now read from branding system · 08e5c496
      Mahmoud Aglan authored
      Game tiles (chess, domino, ludo, backgammon) now get their gradient colors
      from the theme — editing chess_primary/chess_secondary etc in admin branding
      immediately changes the homepage tile colors. Also uploaded proper game icons.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      08e5c496
    • Mahmoud Aglan's avatar
      feat: bottom tab bar icons now editable via admin branding · 67498bb4
      Mahmoud Aglan authored
      Tab bar icons (play, rank, social, shop, profile) now use assetImg()
      which loads from platform_assets. Uploaded matching PNGs from app icons.
      Falls back to original SVGs if no custom icons uploaded.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      67498bb4
    • Mahmoud Aglan's avatar
      feat: chess board reads colors from branding + logos wired throughout app · 6f4568f4
      Mahmoud Aglan authored
      Chess board:
      - Square colors now read from theme system (getColor) instead of hardcoded
        constants — editing board colors in admin branding instantly affects all
        modes (game, analysis, puzzles)
      
      Logos:
      - HUD brand text replaced with assetImg('logo') — shows uploaded PNG
      - Splash screen uses logo image instead of text
      - Favicon and apple-touch-icon added to index.php
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      6f4568f4
    • Mahmoud Aglan's avatar
      feat: chess pieces smaller + faster move animation with squish effect · d21403f1
      Mahmoud Aglan authored
      - Pieces now have 10% padding (was 5%) making them visually smaller
      - Move animation 120ms (was 200ms) with cubic ease-out
      - Slight squish (85% scale) at midpoint of move
      - Bigger squish (72% scale) when capturing a piece
      - Dragging piece slightly smaller (1.1x instead of 1.2x)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      d21403f1
    • Mahmoud Aglan's avatar
      fix: admin branding page now shows uploaded assets — load from platform_assets table · 3432eb36
      Mahmoud Aglan authored
      The admin was only reading from local theme.json and platform_theme,
      but uploaded emoji/asset URLs are stored in platform_assets. Now loads
      them on page render so the preview thumbnails actually appear.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      3432eb36
    • Mahmoud Aglan's avatar
      feat: chess pieces now load custom PNGs from branding system · c7c76636
      Mahmoud Aglan authored
      When chess piece images are uploaded via admin (chess_piece_wK, chess_piece_bQ,
      etc.), the board renders them instead of vector paths. Falls back to the
      original canvas paths if no images are uploaded. Re-renders automatically
      once images finish loading.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      c7c76636
    • Mahmoud Aglan's avatar
      fix: remove group_name from platform_assets insert — column doesn't exist · ca122ef4
      Mahmoud Aglan authored
      The platform_assets table has no group_name column (unlike platform_theme).
      This was causing all emoji uploads from admin to silently fail with HTTP 400.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      ca122ef4
    • Mahmoud Aglan's avatar
      feat: wire ALL remaining emoji slots — dice faces, puzzle themes, particles, room icons · ef6b1d98
      Mahmoud Aglan authored
      Every admin emoji slot now has a corresponding emoji() or getAsset() call:
      - Dice faces (1-6): custom dice images replace CSS dots when uploaded
      - Puzzle themes: fork, pin, castle, crown, sacrifice use emoji()
      - Particle star: juice engine uses themed particle
      - Bot thinking dots, book/best-move symbols in classifier
      - Domino/ludo room icons, chess pawn in leaderboard tabs
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      ef6b1d98
    • Mahmoud Aglan's avatar
      fix: wire bell emoji slot to HUD notification icon · 9be847bd
      Mahmoud Aglan authored
      The admin had a 'bell' emoji slot but the HUD used a hardcoded SVG.
      Now uses emoji('bell', '🔔', 18) so uploaded PNGs actually appear.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      9be847bd
    • Mahmoud Aglan's avatar
      fix: emoji uploads not reflecting — add group_name, kill API cache, add debug logging · ee317285
      Mahmoud Aglan authored
      Three issues fixed:
      1. platform_assets insert was missing group_name (likely NOT NULL column, same
         bug as platform_theme had in 18d0e512)
      2. API had Cache-Control: max-age=60 so browser served stale theme data
      3. theme.load() silently swallowed errors — added console logging and
         cache-bust param to diagnose failures
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      ee317285
    • Mahmoud Aglan's avatar
      feat: wire emoji() theming across entire player app — all registered emojis now replaceable · a032b00e
      Mahmoud Aglan authored
      Every emoji that has a slot in admin branding now goes through the emoji()
      function from core/theme.js. Uploading a PNG/SVG replacement in admin will
      now show up everywhere that emoji appears in the player app.
      
      Files updated: hud, multiplayer, player-panel, chess (game/analysis/review/
      result/history), ludo (game/result), domino (result), play table, daily
      rewards, challenges, ranks, shop, leaderboard, tournaments, friends,
      activity, org (home/browser), profile (view/settings), puzzles.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      a032b00e
    • Mahmoud Aglan's avatar
      fix: wire up emoji() theming so uploaded PNGs actually replace hardcoded emojis · 1733e6bd
      Mahmoud Aglan authored
      The emoji() function existed in theme.js but no component imported or called it.
      All emojis were hardcoded strings. Now result screens, daily rewards, challenges,
      shop, and history use emoji() which checks for admin-uploaded replacements.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      1733e6bd
    • Mahmoud Aglan's avatar
      feat: challenges + battlepass now read from DB tables (admin-configurable) · f96c69db
      Mahmoud Aglan authored
      challenges.php:
      - Reads challenge_templates from DB instead of hardcoded array
      - Admin can add/remove/edit challenge types via management panel
      - Fallback to 3 basic challenges if DB is empty
      
      battlepass.php:
      - Reads active season from 'seasons' table instead of hardcoded config
      - Admin can create new seasons, set dates, tiers, XP requirements
      - Fallback to Season 1 defaults if no active season
      
      Both APIs now fully driven by database:
      - Management panel writes to tables → Player app reads automatically
      - No more hardcoded game config in PHP files
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      f96c69db
    • Mahmoud Aglan's avatar
      fix: PNG uploads now render correctly — remove pixelation from raster images · 211a94f5
      Mahmoud Aglan authored
      image-rendering:-webkit-optimize-contrast caused nearest-neighbor scaling on
      PNGs making them blocky. Now only applied to SVGs. Also added cache-busting
      timestamp so re-uploaded assets aren't served stale from browser cache.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      211a94f5
    • Mahmoud Aglan's avatar
      feat: FULL SYNC Phase 1+2 — ban enforcement, atomic economy, admin-controlled rewards · ae3a9a78
      Mahmoud Aglan authored
      DATABASE CREATED (via SSH to Supabase):
      - reward_config table: 8 configurable reward values (chess_win/loss/draw, daily, streak, etc.)
      - seasons table: battle pass season config (name, dates, tiers, xp)
      - challenge_templates table: 7 challenge types with rewards
      - award_coins() function: atomic coin grant (prevents race conditions)
      
      PLAYER APP CHANGES:
      1. Ban enforcement: requireAuth() now checks is_banned + ban_expires_at
         - Returns 403 'Account banned' if player is banned
         - Respects expiration dates (temporary bans expire)
      
      2. Economy from config: game.php reads chess_win_coins/draw/loss from reward_config
         - Admin can change reward values in DB → player app picks them up
         - No more hardcoded 50/20/10
      
      3. Atomic coin award: calls award_coins() DB function
         - Single transaction: UPDATE profiles + INSERT economy_transactions
         - No race condition on concurrent coin grants
      
      MANAGEMENT CAN NOW:
      - Ban a player → immediately blocked from all player app actions
      - Change reward_config values → player app uses new amounts
      - Create seasons → player app reads active season from DB
      - Create challenge templates → player app picks random 3 per day
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      ae3a9a78
    • Mahmoud Aglan's avatar
      fix: image upload — add apikey header + public URL with anon key · af58cbf5
      Mahmoud Aglan authored
      Upload was failing because:
      1. Missing 'apikey' header on PUT request to Supabase Storage
      2. Public URL needs ?apikey= query param for this Supabase instance
      
      Fixed:
      - Added 'apikey: SERVICE_KEY' header to upload curl request
      - Public URL now includes anon key: .../branding/slot.ext?apikey=ANON_KEY
      - Browser can load the image directly from this URL
      - Survives deploys (stored in Supabase Storage, URL in platform_assets)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      af58cbf5
    • Mahmoud Aglan's avatar
      fix: branding save uses API directly (not form POST) — reliable Supabase persistence · badef7ea
      Mahmoud Aglan authored
      Problem: Form POST to same page required PHP session + page re-render.
      Save appeared to work but values weren't persisting to Supabase reliably.
      
      Fix: Save button now POSTs to /api/branding.php directly as JSON.
      - Collects all input values from DOM
      - Sends { action: 'save_theme', values: { key: value, ... } }
      - API writes each value to platform_theme table (upsert)
      - No session dependency, no form submission, no page reload
      - Response confirms success/failure with message
      
      On page refresh: PHP reads from platform_theme → shows saved values Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      badef7ea
    • Mahmoud Aglan's avatar
      fix: branding page — manual save button, images stored in Supabase Storage · 67c6136f
      Mahmoud Aglan authored
      1. REMOVED auto-save entirely
         - No more saving on every keystroke
         - Changes tracked as 'dirty' state
      
      2. NEW: Sticky bottom save bar
         - Shows 'No unsaved changes' (grey) / '️ Unsaved changes' (yellow)
         - '💾 Save All' button only active when changes exist
         - Success: '✓ Saved!' feedback
         - beforeunload warning if leaving with unsaved changes
      
      3. Image uploads now go to Supabase Storage
         - Uploaded to: profile-images/branding/{slot}.{ext}
         - Public URL stored in platform_assets table
         - Survives deploys (not local filesystem)
         - Also saved locally for immediate preview in admin
         - Asset URL returned by /api/branding.php GET endpoint
      
      4. Player app reads asset URLs from Supabase
         - theme.js fetches /api/branding.php → includes assets from platform_assets
         - Uploaded SVGs/PNGs render at exact specified size
         - object-fit:contain + image-rendering for no pixelation
      
      Flow:
      - Admin uploads logo.svg → Supabase Storage → URL in platform_assets
      - Admin changes gold color → marks dirty → clicks Save → Supabase platform_theme
      - Player loads app → /api/branding.php → gets colors + asset URLs → applies
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      67c6136f
    • Mahmoud Aglan's avatar
      fix: chess pieces now ACTUALLY animate — call board.animateMove() before setPosition · 1401d21f
      Mahmoud Aglan authored
      The animateMove method existed on the board but was never called.
      Game scene was still doing board.setPosition() instantly.
      
      Fixed:
      - Player moves: animateMove(from, to) → piece slides 200ms → then setPosition
      - Bot moves: same — piece slides smoothly before board updates
      - Initial position: stays instant (correct — no animation needed on load)
      
      The animation method uses requestAnimationFrame to interpolate piece
      position linearly from source square to destination over 200ms.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      1401d21f
    • Mahmoud Aglan's avatar
    • Mahmoud Aglan's avatar
      feat: branding persists in Supabase — survives deploys · 03a75d37
      Mahmoud Aglan authored
      PROBLEM: Theme was stored in local theme.json inside Docker container.
      Every deploy rebuilt container → all branding settings LOST.
      
      FIX: Dual storage — writes to both local file AND Supabase.
      Player app reads from Supabase API (persistent).
      
      Changes:
      1. New API: /api/branding.php
         - GET: returns full theme from platform_theme + platform_assets tables
         - POST save_theme: upserts values into platform_theme
         - POST save_asset: upserts asset URLs into platform_assets
         - Public endpoint (cached 60s)
      
      2. theme.js updated:
         - Fetches from /api/branding.php instead of local theme.json
         - Same apply logic (CSS vars, animations, button shapes)
      
      3. admin/branding.php updated:
         - Reads from Supabase on page load (not just local file)
         - Saves to BOTH local file AND Supabase on every edit
         - Auto-save JS still works (posts to same page → writes to Supabase)
      
      Flow:
      - Admin edits color → auto-save → PHP writes to Supabase + local
      - Player opens app → theme.js fetches /api/branding.php → Supabase query
      - Deploy happens → local file reset → Supabase still has all values 
      - Admin page reloads → reads from Supabase → shows saved values Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      03a75d37
    • Mahmoud Aglan's avatar
      docs: FULL_SYNC_PLAN — complete managementplayer integration roadmap · 29021fee
      Mahmoud Aglan authored
      Comprehensive plan documenting:
      - 11 features player app writes that management can't see
      - 10 management features player app doesn't integrate with
      - 7 upgrade phases with estimated ~20 hours total effort
      - Database functions needed (atomic coin award, ban check)
      - 7 new management modules needed (rewards-config, seasons, etc.)
      - Architecture diagram showing both systems' data flow
      - Security gaps (no rate limit, no ban enforcement, no validation)
      - Priority-ordered execution plan
      
      Based on parallel audits of:
      - el3ab-management: 38 modules, 425+ routes, tournament/player/economy systems
      - el3ab-player: 27 API endpoints, tables used, admin visibility needs
      
      Key finding: Both systems work independently but critical bridges are missing
      (tournament registration, match visibility, reward configuration, ban enforcement)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      29021fee
    • Mahmoud Aglan's avatar
      feat: PHASES 3-9 complete — game feel, bot personalities, chess polish, infrastructure fixes · 4de6634a
      Mahmoud Aglan authored
      PHASE 3 - Ludo Game Feel:
      - Bot personality profiles (aggressive/casual/strategic per player)
      - 'يفكر...' thinking indicator during bot turns
      - Vertical bounce effect during piece hops (-2px offset)
      - Star burst particles on piece finish
      - Move preview: ghost circles showing destination for each valid move
      
      PHASE 4 - Bot Personalities:
      - Blue (aggressive): 0.5-1s think, always captures
      - Yellow (casual): 1.5-3s think, sometimes suboptimal
      - Green (strategic): 1-2s think, always optimal
      
      PHASE 6 - Infrastructure Fixes:
      - net.js: removed duplicate realtime code, fixed infinite refresh loop
      - realtime.js: exponential backoff (1s→30s), error logging, connection guard
      - bus.js: try-catch per listener (one bad listener doesn't break others)
      
      PHASE 7 - Chess Polish:
      - Draw offer implemented (bot: 50% accept, live: sends to server)
      - Clock fixed: uses performance.now() delta (no more drift)
      - Piece animation: smooth 200ms tween between squares via requestAnimationFrame
      
      PHASE 8 - Player Panel Component:
      - New reusable core/player-panel.js
      - Avatar, name, level, rank tier, connection dot, turn indicator
      - Tap to inspect → popup with add friend button
      - CSS injected once, used by all games
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      4de6634a
    • Mahmoud Aglan's avatar
      fix(ludo): PHASE 2 — correct board layout, fix ALL critical bugs · 5fd78414
      Mahmoud Aglan authored
      Board Layout (matches reference image):
      - Color order: Red(TL), Blue(TR), Yellow(BR), Green(BL)
      - Fixed SHARED_PATH: 52 squares going clockwise correctly
      - Fixed START_SQUARES: [0, 13, 26, 39] — NOW MATCHES rules.js
      - Fixed HOME_COLUMNS: correct paths toward center per player
      - Fixed SAFE_SQUARES: match official Ludo star positions
      - Fixed HOME_ENTRY: correct squares before entering home column
      
      Rules Engine fixes:
      - START_POSITIONS now matches board-map START_SQUARES (was off by 1!)
      - Capture logic: only checks pieces on shared path (pos < 52)
      - Home column pieces CANNOT be captured (pos >= BOARD_SIZE check)
      - Three consecutive 6s = piece goes back home, lose turn
      - Exact finish requirement enforced (must land exactly on 58)
      - Extra turn on: rolling 6, capturing, finishing
      - Bot AI priority fixed: finish > capture > enter > advance furthest
      
      Dead code removed:
      - doMove() cleaned up (was return + unreachable code)
      
      Color order fixed in game scene:
      - COLORS array matches rules.js order
      - COLORS_LIGHT matches too
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      5fd78414
  2. 04 Jun, 2026 10 commits
    • Mahmoud Aglan's avatar
      docs: complete system audit (Phase 1) — 73 issues documented · aa1a0cad
      Mahmoud Aglan authored
      Full audit completed by 3 parallel agents examining:
      - Ludo: 17 critical/major bugs found (capture logic broken, position mismatch)
      - Chess: 12 critical issues (no server validation, draw unimplemented, clock drift)
      - Core Infrastructure: 6 critical (duplicate code, infinite loops, race conditions)
      
      Implementation plan stored at docs/MULTIPLAYER_OVERHAUL_PLAN.md with:
      - All issues categorized by severity
      - Root causes identified
      - 10-phase execution plan
      - Estimated ~10 hours of work
      - Testing matrix
      
      Ready to begin Phase 2: Ludo rules/board fix
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      aa1a0cad
    • Mahmoud Aglan's avatar
      feat: admin branding auto-saves on every edit + theme applies ALL values · 536fb81b
      Mahmoud Aglan authored
      Admin auto-save:
      - Every input change triggers save after 500ms debounce
      - No more 'Save' button needed — edits are instant
      - Color picker  text input sync (change one, other updates)
      - '✓ Saved' indicator flashes on successful save
      - Uses fetch POST to same page (no reload)
      
      Theme loader expanded:
      - Ludo colors mapped to CSS vars (--ludo-red, --ludo-blue, etc.)
      - Chess board colors mapped (--board-light, --board-dark, etc.)
      - All theme values exposed as window.__EL3AB_THEME for JS access
      - Games can read: window.__EL3AB_THEME?.ludo_red || '#E53935'
      
      All edits in admin are now effective:
      - Platform colors → CSS variables → used by all components
      - Game colors → CSS variables → used by board renderers
      - Animation speeds → CSS variables → used by transitions
      - Button shapes → CSS variables → used by .btn classes
      - Juice settings → available via getColor() for JS logic
      - Uploaded assets → served from /public/assets/brand/
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      536fb81b
    • Mahmoud Aglan's avatar
      feat: emotes fly from sender's position to center of board · c125345a
      Mahmoud Aglan authored
      Emote animation redesigned:
      - showReceived() now accepts 'fromElement' parameter
      - Emote starts at sender's panel position (scaled small)
      - Pops up to full size at origin (0.2s)
      - Flies to center of game board (0.5s)
      - Grows large and fades out at center (1.8s total)
      - Uses Web Animations API for smooth 60fps path
      
      Chess:
      - YOUR emotes start from your player bar (bottom)
      - Opponent emotes start from their bar (top)
      
      Ludo:
      - YOUR emotes start from your panel (pp-{myPlayerIndex})
      - Opponent emotes start from their panel (pp-{senderIdx})
      
      Both games now have directional emote animation — you can SEE
      who sent what because it originates from their side of the screen.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      c125345a
    • Mahmoud Aglan's avatar
      feat(ludo): humanized bots, multiplayer profiles, opponent popup, 30 game-feel improvements · f0ab8811
      Mahmoud Aglan authored
      BOT HUMANIZATION:
      - Think delay before rolling: 0.8-2s (random, mimics decision)
      - Decide delay before picking piece: 0.5-1.5s
      - Step-by-step animation for bot moves too (not instant)
      - Bots occasionally send emotes on exciting events (captures)
      - Random emotes: 😂💪🎉😎
      
      MULTIPLAYER PROFILE HOOK:
      - In live mode, fetches real opponent profiles
      - Player panels show actual names (not 'Bot X')
      - Tap opponent panel → popup with avatar, name, level
      - Add friend button in popup (sends request via mp.addFriendFromGame)
      - Close button, outside-click-to-dismiss
      - Connection dot + emote sync already wired from previous commit
      
      GAME FEEL:
      - Bot turns feel human (total 2-4s per turn vs instant)
      - Piece hop animation plays for bot moves too
      - Capture shake effect on bot captures
      - Bot emote floating animation appears above board
      - Golden glow ring on selectable pieces (multiple valid moves)
      - Tap-to-select piece interaction always required
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      f0ab8811
    • Mahmoud Aglan's avatar
      feat(ludo): piece selection, step-by-step animation, 2-4 player matchmaking, branding admin · 875a302e
      Mahmoud Aglan authored
      PIECE SELECTION:
      - Player always taps which piece to move (golden glow highlight on valid pieces)
      - Canvas click detection: finds nearest highlighted piece within tap radius
      - Even with 1 valid move: brief highlight before auto-execute (confirms to player)
      
      STEP-BY-STEP ANIMATION:
      - Pieces hop one square at a time (120ms per hop) instead of teleporting
      - Audio cue on each step
      - Capture/finish effects play AFTER animation completes
      - Confetti on capture, star burst on finish
      
      MATCHMAKING (2-4 players):
      - Searches for up to 3 waiting opponents
      - 2 humans found → 2 humans + 2 bots
      - 3 humans found → 3 humans + 1 bot
      - 4 humans found → 4 humans, no bots
      - All matched opponents' queue entries updated
      - 30s timeout handled client-side (queue scene already has timer)
      
      BRANDING ADMIN:
      - New 'Ludo Board Colors' section with 9 color controls:
        Red/Blue/Green/Yellow zones, board bg, path, safe star, piece border, grid lines
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      875a302e
    • Mahmoud Aglan's avatar
      fix(ludo): responsive layout for small phones · 96ebe555
      Mahmoud Aglan authored
      - Board max 360px, constrained by container
      - Dice 50x50, roll button smaller padding
      - Panels 6px padding
      - Fits on 360x640 screens
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      96ebe555
    • Mahmoud Aglan's avatar
      fix: challenges now track REAL progress from today's completed matches · d33a8aea
      Mahmoud Aglan authored
      Challenges API now counts actual matches played today:
      - games_played: total completed matches today
      - wins: matches won today
      - chess_played: chess games today
      - ludo_played: ludo games today
      - domino_played: domino games today
      - bot_wins: bot games won today
      
      Progress is calculated server-side by querying matches table
      where player was white/black AND status=completed AND created today.
      Challenge marked completed=true when progress >= target.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      d33a8aea
    • Mahmoud Aglan's avatar
      fix: home buttons, daily reward, back navigation — full sweep · a9cd8b66
      Mahmoud Aglan authored
      1. Removed أحجيات (puzzles) from home quick buttons — chess-only feature
      2. Daily reward completely rewritten:
         - 7-day streak timeline showing claimed/today/future days
         - Each day shows reward amount (50→75→100→125→150→200→300)
         - Already-claimed state: shows  with 'عد غداً' message
         - Prevents double claim (checks last_daily_reward date)
         - Coin burst + fly-to-HUD animation on claim
         - Streak badge '🔥 X يوم متتالي'
         - Info text explaining escalating rewards
         - Has back button ←
      3. Challenges scene: added back button ←
      4. All pushed scenes now have proper back navigation
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      a9cd8b66
    • Mahmoud Aglan's avatar
      fix: bot games now create real match record (appear in match history) · 85d39aa0
      Mahmoud Aglan authored
      Previously bot games used matchId='local' which meant no DB record was
      created. Now on bot game start, calls game.php 'start' to insert a real
      match row. When game completes, the 'complete' action updates that row
      with result/fen/pgn/rating. Matches now appear in مبارياتي.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      85d39aa0
    • Mahmoud Aglan's avatar
      feat: match history — real data from DB with opponent names, result colors, rating changes · cb7dd082
      Mahmoud Aglan authored
      New API: /api/match-history.php
      - Fetches completed matches where player was white OR black
      - Enriches with opponent display names from profiles
      - Returns: result, time_control, bot_id, rating changes, move count, date
      - Supports game_key filter and limit parameter
      
      History scene rewritten:
      - Shows real matches with colored left border (green=win, red=loss, gold=draw)
      - Opponent name (or bot name if vs bot)
      - Rating change (+12 / -8) in matching color
      - Time control label (5+0, 10+0, etc.)
      - Relative time (5د, 2س, 3ي)
      - Proper result detection for all match_result enum values
      - Empty state with helpful message
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      cb7dd082