Commit f09aa13d authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat: branding admin panel + asset registry

Admin panel (/admin/branding.php):
- Hardcoded login (admin / El3ab@Brand2024)
- Color editor for all 13 platform colors with live preview
- Game color editor (8 game-specific colors)
- Chess board color editor (5 board theme colors)
- Animation/motion settings (speeds, scale, radius)
- 19 asset upload slots with size hints:
  - Logo (200×60), Icon (64×64), Splash (1080×1920)
  - Coin/Gem/XP icons (24×24)
  - Game icons (64×64 each)
  - Win/Loss/Draw icons (128×128)
  - Medals (32×32), Avatar default (128×128)
- Each upload shows expected dimensions in Arabic
- Changes save to theme.json and appear as platform defaults
- Does NOT override user skins/cosmetics

Asset Registry (ASSET_REGISTRY.md):
- 44 emojis cataloged with file locations
- 71 colors mapped
- 9 gradients
- 17 animations
- 5 board visual configs
- 1 piece renderer (vector paths)
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 02573701
# EL3AB — Visual Asset Registry
This file documents EVERY visual asset in the platform.
Used to build the theming/branding admin panel.
---
## Emojis Used (44)
| Emoji | File | Context |
|---|---|---|
| ◆ | `./public/js/core/hud.js` | <span class="icon"></span> |
| ⬡ | `./public/js/core/hud.js` | <span class="icon"></span> |
| ● | `./public/js/core/hud.js` | <span class="icon"></span> |
| 📊 | `./public/js/modules/chess/scenes/analysis.js` | <span style="font-size:14px;font-weight:700;color:#f8fafc;"> |
| ♜ | `./public/js/modules/chess/scenes/game.js` | const names = { q: '♛', r: '♜', b: '♝', n: '♞' }; |
| ♞ | `./public/js/modules/chess/scenes/game.js` | const names = { q: '♛', r: '♜', b: '♝', n: '♞' }; |
| 🤖 | `./public/js/modules/chess/scenes/game.js` | <img src="https://stockfishapi.caprover.al-arcade.com/portra |
| ♟ | `./public/js/modules/chess/scenes/game.js` | const pieceSymbols = { p: '♟', n: '♞', b: '♝', r: '♜', q: '♛ |
| ♚ | `./public/js/modules/chess/scenes/game.js` | const pieceSymbols = { p: '♟', n: '♞', b: '♝', r: '♜', q: '♛ |
| ♕ | `./public/js/modules/chess/scenes/game.js` | if (color === 'w') { names.q = '♕'; names.r = '♖'; names.b = |
| ♘ | `./public/js/modules/chess/scenes/game.js` | if (color === 'w') { names.q = '♕'; names.r = '♖'; names.b = |
| ♝ | `./public/js/modules/chess/scenes/game.js` | const names = { q: '♛', r: '♜', b: '♝', n: '♞' }; |
| ♖ | `./public/js/modules/chess/scenes/game.js` | if (color === 'w') { names.q = '♕'; names.r = '♖'; names.b = |
| ♗ | `./public/js/modules/chess/scenes/game.js` | if (color === 'w') { names.q = '♕'; names.r = '♖'; names.b = |
| ♛ | `./public/js/modules/chess/scenes/game.js` | const names = { q: '♛', r: '♜', b: '♝', n: '♞' }; |
| ⚐ | `./public/js/modules/chess/scenes/game.js` | <button class="ctrl-btn" id="btn-resign">⚐ ${t('game.resign' |
| 🤝 | `./public/js/modules/chess/scenes/result.js` | draw: { icon: '🤝', title: t('game.draw_result'), color: '#E4 |
| 💀 | `./public/js/modules/domino/scenes/result.js` | const icon = isWin ? '🏆' : '💀'; |
| 🏆 | `./public/js/modules/domino/scenes/result.js` | const icon = isWin ? '🏆' : '💀'; |
| ⬚ | `./public/js/modules/domino/scenes/room.js` | <div class="pulse" style="width:60px;height:60px;border-radi |
| 🎲 | `./public/js/modules/ludo/scenes/game.js` | <button class="btn btn-primary" id="roll-btn" style="font-si |
| 👥 | `./public/js/modules/org/scenes/browser.js` | <div style="font-size:11px;color:var(--text-secondary);">👥 $ |
| ✅ | `./public/js/modules/org/scenes/home.js` | el.querySelector('#join-btn').textContent = '✅ تم الانضمام'; |
| 👤 | `./public/js/modules/org/scenes/home.js` | <div style="width:24px;height:24px;border-radius:50%;backgro |
| ️ | `./public/js/modules/org/scenes/home.js` | ${org.logo_url ? `<img src="${org.logo_url}" style="width:10 |
| 🏛 | `./public/js/modules/org/scenes/home.js` | ${org.logo_url ? `<img src="${org.logo_url}" style="width:10 |
| 🧩 | `./public/js/modules/play/scenes/table.js` | ${game.key === 'chess' ? '<div class="feature-chip" id="btn- |
| 📋 | `./public/js/modules/play/scenes/table.js` | <div class="feature-chip" id="btn-history">📋 مبارياتي</div> |
| 🎮 | `./public/js/modules/play/scenes/table.js` | <div class="menu-btn-icon">🎮</div> |
| ✕ | `./public/js/modules/play/scenes/table.js` | <button class="game-menu-close" id="menu-close"></button> |
| ◎ | `./public/js/modules/play/scenes/table.js` | { key: 'backgammon', name: 'طاولة', nameEn: 'Backgammon', co |
| 🔇 | `./public/js/modules/profile/scenes/settings.js` | <button class="btn btn-secondary" id="toggle-audio" style="m |
| 🔊 | `./public/js/modules/profile/scenes/settings.js` | <button class="btn btn-secondary" id="toggle-audio" style="m |
| ⚡ | `./public/js/modules/puzzles/scenes/puzzle.js` | ratingEl.textContent = `⚡ ${puzzle.rating || '?'}`; |
| ❌ | `./public/js/modules/puzzles/scenes/puzzle.js` | status.textContent = '❌ حل خاطئ'; |
| 🥈 | `./public/js/modules/rank/scenes/leaderboard.js` | const medals = ['🥇', '🥈', '🥉']; |
| 🥉 | `./public/js/modules/rank/scenes/leaderboard.js` | const medals = ['🥇', '🥈', '🥉']; |
| 🥇 | `./public/js/modules/rank/scenes/leaderboard.js` | const medals = ['🥇', '🥈', '🥉']; |
| 💰 | `./public/js/modules/rank/scenes/tournaments.js` | ${tour.entry_fee_coins ? `<span style="font-size:11px;color: |
| 🎁 | `./public/js/modules/rewards/scenes/daily.js` | <div style="font-size:48px;animation:float 3s ease-in-out in |
| 🪙 | `./public/js/modules/rewards/scenes/daily.js` | <span style="color:var(--gold);font-size:18px;font-weight:70 |
| 💎 | `./public/js/modules/shop/scenes/browse.js` | ${item.price_gems ? `${item.price_gems} 💎` : ''} |
| 🎨 | `./public/js/modules/shop/scenes/browse.js` | 🎨 |
| ⚔ | `./public/js/modules/social/scenes/friends.js` | ${f.is_online ? `<button class="btn btn-secondary" style="fo |
## Colors (71)
| Color | File |
|---|---|
| `#000` | `./public/js/modules/chess/scenes/analysis.js` |
| `#00FFFF` | `./public/css/tokens.css` |
| `#050810` | `./index.php` |
| `#065f46` | `./public/js/modules/play/scenes/table.js` |
| `#06B6D4` | `./public/css/tokens.css` |
| `#0A1020` | `./public/css/tokens.css` |
| `#0a0a1a` | `./public/js/modules/chess/scenes/result.js` |
| `#0a2a0e` | `./public/js/modules/domino/scenes/game.js` |
| `#0d3311` | `./public/js/modules/domino/scenes/game.js` |
| `#0f0f1e` | `./public/js/modules/chess/scenes/game.js` |
| `#10B981` | `./public/css/tokens.css` |
| `#111` | `./public/js/modules/domino/scenes/game.js` |
| `#121A2E` | `./public/css/tokens.css` |
| `#1A2440` | `./public/css/tokens.css` |
| `#1B5E20` | `./public/js/modules/domino/scenes/game.js` |
| `#1E88E5` | `./public/js/modules/ludo/scenes/game.js` |
| `#1a1a1a` | `./public/css/core.css` |
| `#1a1a2e` | `./public/js/modules/chess/scenes/game.js` |
| `#1e1e3a` | `./public/js/modules/chess/scenes/game.js` |
| `#1e40af` | `./public/js/modules/play/scenes/table.js` |
| `#2082F0` | `./public/css/tokens.css` |
| `#223050` | `./public/css/tokens.css` |
| `#2563EB` | `./public/css/tokens.css` |
| `#2E7D32` | `./public/js/modules/domino/scenes/game.js` |
| `#2a1a40` | `./public/css/core.css` |
| `#2a2a4a` | `./public/js/modules/chess/scenes/game.js` |
| `#2a2a5a` | `./public/js/modules/chess/scenes/game.js` |
| `#333` | `./public/js/modules/domino/scenes/game.js` |
| `#34D399` | `./public/css/tokens.css` |
| `#388E3C` | `./public/js/modules/domino/scenes/game.js` |
| `#3B82F6` | `./public/js/modules/ludo/logic/rules.js` |
| `#3a3a7a` | `./public/js/modules/chess/scenes/game.js` |
| `#43A047` | `./public/js/modules/ludo/scenes/game.js` |
| `#475569` | `./public/css/tokens.css` |
| `#4CAF50` | `./public/js/modules/domino/scenes/game.js` |
| `#555` | `./public/js/modules/domino/scenes/game.js` |
| `#5b21b6` | `./public/js/modules/play/scenes/table.js` |
| `#64748b` | `./public/js/modules/chess/scenes/analysis.js` |
| `#6834BE` | `./public/css/tokens.css` |
| `#81C784` | `./public/js/modules/domino/scenes/game.js` |
| `#8B5CF6` | `./public/css/tokens.css` |
| `#90CAF9` | `./public/js/modules/ludo/scenes/game.js` |
| `#92400e` | `./public/js/modules/play/scenes/table.js` |
| `#94A3B8` | `./public/css/tokens.css` |
| `#999` | `./public/js/modules/domino/scenes/game.js` |
| `#A5D6A7` | `./public/js/modules/ludo/scenes/game.js` |
| `#AAA23A` | `./public/js/modules/chess/canvas/board.js` |
| `#B58863` | `./public/js/modules/chess/canvas/board.js` |
| `#CDD16A` | `./public/js/modules/chess/canvas/board.js` |
| `#E0E0E0` | `./public/js/modules/ludo/scenes/game.js` |
| `#E4AC38` | `./public/css/tokens.css` |
| `#E53935` | `./public/js/modules/ludo/scenes/game.js` |
| `#E84D1E` | `./public/css/tokens.css` |
| `#EC4899` | `./public/css/tokens.css` |
| `#EF4444` | `./public/css/tokens.css` |
| `#EF9A9A` | `./public/js/modules/ludo/scenes/game.js` |
| `#F0D9B5` | `./public/js/modules/chess/canvas/board.js` |
| `#F59E0B` | `./public/css/tokens.css` |
| `#F5B731` | `./public/css/tokens.css` |
| `#F87171` | `./public/css/tokens.css` |
| `#F8FAFC` | `./public/css/tokens.css` |
| `#FAFAFA` | `./public/js/modules/ludo/scenes/game.js` |
| `#FDD835` | `./public/js/modules/ludo/scenes/game.js` |
| `#FF6B6B88` | `./public/js/modules/chess/canvas/board.js` |
| `#FFCC66` | `./public/css/tokens.css` |
| `#FFF59D` | `./public/js/modules/ludo/scenes/game.js` |
| `#FFFFF0` | `./public/js/modules/domino/scenes/game.js` |
| `#FFFFFF` | `./public/js/modules/ludo/scenes/game.js` |
| `#bac` | `./public/js/modules/org/scenes/home.js` |
| `#e2e8f0` | `./public/js/modules/chess/scenes/game.js` |
| `#fff` | `./public/js/modules/domino/scenes/game.js` |
## Gradients (9)
| Gradient | File |
|---|---|
| `linear-gradient(135deg, #1a2440, #2a1a40)` | `./public/css/core.css` |
| `linear-gradient(135deg, var(--gold)` | `./public/css/core.css` |
| `linear-gradient(135deg, var(--game-primary, var(--blue)` | `./public/css/core.css` |
| `linear-gradient(90deg, var(--bg-card)` | `./public/css/core.css` |
| `linear-gradient(135deg, #1e40af, #3b82f6)` | `./public/js/modules/play/scenes/table.js` |
| `linear-gradient(135deg, #065f46, #10b981)` | `./public/js/modules/play/scenes/table.js` |
| `linear-gradient(135deg, #5b21b6, #8b5cf6)` | `./public/js/modules/play/scenes/table.js` |
| `linear-gradient(135deg, #92400e, #f59e0b)` | `./public/js/modules/play/scenes/table.js` |
| `linear-gradient(135deg, #2563eb, #3b82f6)` | `./public/js/modules/play/scenes/table.js` |
## Animations (21)
| Animation | File |
|---|---|
| `toastIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1)` | `./public/css/core.css` |
| `toastOut 0.2s ease-in forwards` | `./public/css/core.css` |
| `sceneIn 0.35s cubic-bezier(0.16, 1, 0.3, 1)` | `./public/css/core.css` |
| `sceneOut 0.2s ease-in forwards` | `./public/css/core.css` |
| `shimmer 1.5s infinite` | `./public/css/core.css` |
| `pulse 2s ease-in-out infinite` | `./public/css/core.css` |
| `float 3s ease-in-out infinite` | `./public/css/core.css` |
| `shake 0.4s ease` | `./public/css/core.css` |
| `popIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1)` | `./public/css/core.css` |
| `bounceIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1)` | `./public/css/core.css` |
| `slideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1)` | `./public/css/core.css` |
| `float 2s ease-in-out infinite` | `./public/js/modules/domino/scenes/result.js` |
| `glow 2s ease-in-out infinite` | `./public/js/modules/auth/scenes/splash.js` |
| `loadBar 2s ease-out forwards` | `./public/js/modules/auth/scenes/splash.js` |
| `clockPulse 1s infinite` | `./public/js/modules/chess/scenes/game.js` |
| `pulse 1s ease-in-out infinite` | `./public/js/modules/play/scenes/queue.js` |
| `radarPing 2s ease-out infinite` | `./public/js/modules/play/scenes/queue.js` |
## Fonts (5)
- `var(--font-ar)` (./public/css/core.css)
- `var(--font-lat)` (./public/css/core.css)
- `Inter,sans-serif` (./public/js/modules/ludo/scenes/game.js)
- `Inter,monospace` (./public/js/modules/chess/scenes/game.js)
- `inherit` (./public/js/modules/chess/scenes/game.js)
## SVG/Icons (2)
- `./public/js/core/hud.js` — inline SVG
- `./public/icons/sprite.svg` — inline SVG
## Image URLs (0)
## Piece Rendering (1)
- `./public/js/modules/chess/canvas/board.js` — chess piece vector paths
## Board/Game Visuals (5)
- `./public/js/modules/domino/scenes/game.js` — board color constants
- `./public/js/modules/ludo/scenes/game.js` — board color constants
- `./public/js/modules/ludo/logic/rules.js` — board color constants
- `./public/js/modules/shop/scenes/browse.js` — board color constants
- `./public/js/modules/chess/canvas/board.js` — board color constants
<?php
session_start();
$ADMIN_USER = 'admin';
$ADMIN_PASS = 'El3ab@Brand2024';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login'])) {
if ($_POST['username'] === $ADMIN_USER && $_POST['password'] === $ADMIN_PASS) {
$_SESSION['branding_auth'] = true;
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['logout'])) {
unset($_SESSION['branding_auth']);
}
if (!($_SESSION['branding_auth'] ?? false)) {
?><!DOCTYPE html><html lang="ar" dir="rtl"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>EL3AB Branding Admin</title>
<style>body{background:#0a0a1a;color:#f8fafc;font-family:'IBM Plex Sans Arabic',sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0}form{background:#1a1a2e;padding:40px;border-radius:16px;width:320px;text-align:center}input{width:100%;padding:12px;margin:8px 0;background:#2a2a4a;border:1px solid #333;border-radius:8px;color:#fff;font-size:14px}button{width:100%;padding:12px;margin-top:16px;background:linear-gradient(135deg,#E4AC38,#FFCC66);border:none;border-radius:8px;color:#1a1a1a;font-weight:700;font-size:15px;cursor:pointer}h2{color:#E4AC38;margin-bottom:16px}</style></head><body>
<form method="POST"><h2>EL3AB Branding</h2><input name="username" placeholder="Username" required><input name="password" type="password" placeholder="Password" required><button name="login" value="1">دخول</button></form></body></html><?php
exit;
}
$BRAND_DIR = __DIR__ . '/../public/assets/brand/';
if (!is_dir($BRAND_DIR)) mkdir($BRAND_DIR, 0777, true);
$THEME_FILE = __DIR__ . '/../public/assets/brand/theme.json';
$theme = file_exists($THEME_FILE) ? json_decode(file_get_contents($THEME_FILE), true) : [];
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_theme'])) {
$theme = array_merge($theme, $_POST['theme'] ?? []);
file_put_contents($THEME_FILE, json_encode($theme, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['asset'])) {
$slot = $_POST['slot'] ?? '';
$file = $_FILES['asset'];
if ($file['error'] === 0 && $slot) {
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$dest = $BRAND_DIR . $slot . '.' . $ext;
move_uploaded_file($file['tmp_name'], $dest);
$theme['assets'][$slot] = '/public/assets/brand/' . $slot . '.' . $ext;
file_put_contents($THEME_FILE, json_encode($theme, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}
}
?>
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>EL3AB — Branding Admin</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { background: #0a0a1a; color: #f8fafc; font-family: 'IBM Plex Sans Arabic', 'Inter', sans-serif; line-height: 1.6; }
.container { max-width: 900px; margin: 0 auto; padding: 24px 16px; }
h1 { color: #E4AC38; font-size: 24px; margin-bottom: 8px; }
h2 { color: #94a3b8; font-size: 18px; margin: 32px 0 12px; border-bottom: 1px solid #1a1a2e; padding-bottom: 8px; }
h3 { color: #64748b; font-size: 14px; margin: 16px 0 8px; }
.logout { float: left; background: none; border: 1px solid #333; color: #94a3b8; padding: 6px 14px; border-radius: 6px; cursor: pointer; font-size: 12px; }
.section { background: #1a1a2e; border-radius: 12px; padding: 20px; margin-bottom: 16px; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media(max-width:600px) { .grid { grid-template-columns: 1fr; } }
.field { margin-bottom: 12px; }
.field label { display: block; font-size: 12px; color: #94a3b8; margin-bottom: 4px; font-weight: 600; }
.field .hint { font-size: 10px; color: #64748b; margin-top: 2px; }
input[type="color"] { width: 48px; height: 36px; border: 1px solid #333; border-radius: 6px; background: #2a2a4a; cursor: pointer; }
input[type="text"], input[type="number"], select { width: 100%; padding: 8px 12px; background: #2a2a4a; border: 1px solid #333; border-radius: 6px; color: #fff; font-size: 13px; }
.color-row { display: flex; align-items: center; gap: 8px; }
.color-row input[type="text"] { flex: 1; }
.upload-box { border: 2px dashed #333; border-radius: 8px; padding: 16px; text-align: center; cursor: pointer; transition: border-color 0.2s; }
.upload-box:hover { border-color: #E4AC38; }
.upload-box .size-hint { font-size: 11px; color: #E4AC38; font-weight: 600; margin-top: 4px; }
.upload-box .current { margin-top: 8px; }
.upload-box img { max-width: 80px; max-height: 80px; border-radius: 4px; }
button[type="submit"] { background: linear-gradient(135deg, #E4AC38, #FFCC66); color: #1a1a1a; border: none; padding: 12px 32px; border-radius: 8px; font-weight: 700; font-size: 14px; cursor: pointer; margin-top: 16px; }
.saved { background: #34D399; color: #000; padding: 8px 16px; border-radius: 6px; margin: 8px 0; font-size: 13px; font-weight: 600; }
</style>
</head>
<body>
<div class="container">
<form method="POST" style="display:inline;"><button class="logout" name="logout" value="1">خروج</button></form>
<h1>🎨 EL3AB Branding Admin</h1>
<p style="color:#64748b;font-size:13px;margin-bottom:24px;">إدارة الهوية البصرية — الألوان والأيقونات والأصول تظهر كافتراضي لكل اللاعبين</p>
<?php if (isset($_POST['save_theme'])): ?><div class="saved">✓ تم حفظ التغييرات</div><?php endif; ?>
<form method="POST">
<input type="hidden" name="save_theme" value="1">
<!-- COLORS -->
<h2>🎨 الألوان الأساسية</h2>
<div class="section">
<div class="grid">
<?php
$colors = [
['key' => 'bg_deep', 'label' => 'خلفية عميقة', 'default' => '#050810', 'hint' => 'أغمق طبقة في التطبيق'],
['key' => 'bg_base', 'label' => 'خلفية أساسية', 'default' => '#0A1020', 'hint' => 'خلفية الشاشات'],
['key' => 'bg_card', 'label' => 'خلفية البطاقات', 'default' => '#121A2E', 'hint' => 'سطح البطاقات'],
['key' => 'bg_elevated', 'label' => 'خلفية مرتفعة', 'default' => '#1A2440', 'hint' => 'الحقول والعناصر المرتفعة'],
['key' => 'gold', 'label' => 'الذهبي (العلامة التجارية)', 'default' => '#E4AC38', 'hint' => 'اللون الرئيسي، الأزرار، الجوائز'],
['key' => 'gold_soft', 'label' => 'ذهبي فاتح', 'default' => '#FFCC66', 'hint' => 'تدرج الأزرار الذهبية'],
['key' => 'blue', 'label' => 'الأزرق', 'default' => '#2082F0', 'hint' => 'الروابط، المنافسة'],
['key' => 'cyan', 'label' => 'السماوي', 'default' => '#00FFFF', 'hint' => 'تأثيرات التوهج'],
['key' => 'purple', 'label' => 'البنفسجي', 'default' => '#6834BE', 'hint' => 'النادر/الأسطوري'],
['key' => 'success', 'label' => 'النجاح/الفوز', 'default' => '#34D399', 'hint' => 'لون الفوز والنجاح'],
['key' => 'error', 'label' => 'الخطأ/الخسارة', 'default' => '#EF4444', 'hint' => 'لون الخسارة والخطأ'],
['key' => 'text_primary', 'label' => 'نص أساسي', 'default' => '#F8FAFC', 'hint' => 'لون النص الرئيسي'],
['key' => 'text_secondary', 'label' => 'نص ثانوي', 'default' => '#94A3B8', 'hint' => 'نص أقل أهمية'],
];
foreach ($colors as $c):
$val = $theme[$c['key']] ?? $c['default'];
?>
<div class="field">
<label><?= $c['label'] ?></label>
<div class="color-row">
<input type="color" name="theme[<?= $c['key'] ?>]" value="<?= $val ?>">
<input type="text" name="theme[<?= $c['key'] ?>]" value="<?= $val ?>" pattern="#[0-9A-Fa-f]{6}">
</div>
<div class="hint"><?= $c['hint'] ?></div>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- GAME COLORS -->
<h2>🎮 ألوان الألعاب</h2>
<div class="section">
<div class="grid">
<?php
$gameColors = [
['key' => 'chess_primary', 'label' => 'شطرنج — أساسي', 'default' => '#2563EB'],
['key' => 'chess_secondary', 'label' => 'شطرنج — ثانوي', 'default' => '#F5B731'],
['key' => 'domino_primary', 'label' => 'دومينو — أساسي', 'default' => '#10B981'],
['key' => 'domino_secondary', 'label' => 'دومينو — ثانوي', 'default' => '#06B6D4'],
['key' => 'ludo_primary', 'label' => 'لودو — أساسي', 'default' => '#8B5CF6'],
['key' => 'ludo_secondary', 'label' => 'لودو — ثانوي', 'default' => '#EC4899'],
['key' => 'backgammon_primary', 'label' => 'طاولة — أساسي', 'default' => '#F59E0B'],
['key' => 'backgammon_secondary', 'label' => 'طاولة — ثانوي', 'default' => '#EF4444'],
];
foreach ($gameColors as $c):
$val = $theme[$c['key']] ?? $c['default'];
?>
<div class="field">
<label><?= $c['label'] ?></label>
<div class="color-row">
<input type="color" name="theme[<?= $c['key'] ?>]" value="<?= $val ?>">
<input type="text" name="theme[<?= $c['key'] ?>]" value="<?= $val ?>">
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- CHESS BOARD -->
<h2>♟ ألوان رقعة الشطرنج</h2>
<div class="section">
<div class="grid">
<?php
$boardColors = [
['key' => 'board_light', 'label' => 'مربع فاتح', 'default' => '#F0D9B5', 'hint' => 'لون المربعات الفاتحة'],
['key' => 'board_dark', 'label' => 'مربع غامق', 'default' => '#B58863', 'hint' => 'لون المربعات الغامقة'],
['key' => 'board_highlight_light', 'label' => 'تمييز فاتح', 'default' => '#CDD16A', 'hint' => 'آخر نقلة — مربع فاتح'],
['key' => 'board_highlight_dark', 'label' => 'تمييز غامق', 'default' => '#AAA23A', 'hint' => 'آخر نقلة — مربع غامق'],
['key' => 'board_check', 'label' => 'تهديد الملك', 'default' => '#FF6B6B', 'hint' => 'عندما يكون الملك مكشوف'],
];
foreach ($boardColors as $c):
$val = $theme[$c['key']] ?? $c['default'];
?>
<div class="field">
<label><?= $c['label'] ?></label>
<div class="color-row">
<input type="color" name="theme[<?= $c['key'] ?>]" value="<?= $val ?>">
<input type="text" name="theme[<?= $c['key'] ?>]" value="<?= $val ?>">
</div>
<div class="hint"><?= $c['hint'] ?></div>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- ANIMATIONS -->
<h2>⚡ الحركة والرسوم المتحركة</h2>
<div class="section">
<div class="grid">
<?php
$anims = [
['key' => 'anim_speed', 'label' => 'سرعة الانتقال (ms)', 'default' => '250', 'hint' => 'المدة الافتراضية للانتقالات', 'type' => 'number'],
['key' => 'anim_fast', 'label' => 'سرعة سريعة (ms)', 'default' => '150', 'hint' => 'أزرار، تغذية راجعة', 'type' => 'number'],
['key' => 'anim_slow', 'label' => 'سرعة بطيئة (ms)', 'default' => '400', 'hint' => 'انتقالات المشاهد', 'type' => 'number'],
['key' => 'btn_scale', 'label' => 'تصغير الزر عند الضغط', 'default' => '0.92', 'hint' => '0.9 = ضغط قوي, 0.97 = ضغط خفيف', 'type' => 'text'],
['key' => 'border_radius', 'label' => 'انحناء الزوايا (px)', 'default' => '12', 'hint' => 'نصف قطر الأزرار', 'type' => 'number'],
['key' => 'card_radius', 'label' => 'انحناء البطاقات (px)', 'default' => '20', 'hint' => 'نصف قطر البطاقات والنوافذ', 'type' => 'number'],
];
foreach ($anims as $a):
$val = $theme[$a['key']] ?? $a['default'];
?>
<div class="field">
<label><?= $a['label'] ?></label>
<input type="<?= $a['type'] ?>" name="theme[<?= $a['key'] ?>]" value="<?= $val ?>">
<div class="hint"><?= $a['hint'] ?></div>
</div>
<?php endforeach; ?>
</div>
</div>
<button type="submit">💾 حفظ كل التغييرات</button>
</form>
<!-- ASSET UPLOADS -->
<h2>📦 الأصول البصرية</h2>
<p style="color:#64748b;font-size:12px;margin-bottom:16px;">ارفع صور SVG أو PNG — ستظهر فوراً كافتراضي لكل اللاعبين</p>
<div class="section">
<div class="grid">
<?php
$assetSlots = [
['slot' => 'logo', 'label' => 'شعار المنصة', 'size' => 'SVG أو PNG — 200×60px', 'accept' => '.svg,.png'],
['slot' => 'logo_icon', 'label' => 'أيقونة الشعار', 'size' => 'SVG أو PNG — 64×64px', 'accept' => '.svg,.png'],
['slot' => 'splash_bg', 'label' => 'خلفية البداية', 'size' => 'PNG/JPG — 1080×1920px', 'accept' => '.png,.jpg,.webp'],
['slot' => 'favicon', 'label' => 'Favicon', 'size' => 'PNG — 32×32px', 'accept' => '.png,.ico'],
['slot' => 'coin_icon', 'label' => 'أيقونة العملات', 'size' => 'SVG أو PNG — 24×24px', 'accept' => '.svg,.png'],
['slot' => 'gem_icon', 'label' => 'أيقونة الجواهر', 'size' => 'SVG أو PNG — 24×24px', 'accept' => '.svg,.png'],
['slot' => 'xp_icon', 'label' => 'أيقونة الخبرة', 'size' => 'SVG أو PNG — 24×24px', 'accept' => '.svg,.png'],
['slot' => 'chess_icon', 'label' => 'أيقونة الشطرنج', 'size' => 'SVG أو PNG — 64×64px', 'accept' => '.svg,.png'],
['slot' => 'domino_icon', 'label' => 'أيقونة الدومينو', 'size' => 'SVG أو PNG — 64×64px', 'accept' => '.svg,.png'],
['slot' => 'ludo_icon', 'label' => 'أيقونة اللودو', 'size' => 'SVG أو PNG — 64×64px', 'accept' => '.svg,.png'],
['slot' => 'backgammon_icon', 'label' => 'أيقونة الطاولة', 'size' => 'SVG أو PNG — 64×64px', 'accept' => '.svg,.png'],
['slot' => 'win_trophy', 'label' => 'كأس الفوز', 'size' => 'SVG أو PNG — 128×128px', 'accept' => '.svg,.png'],
['slot' => 'loss_icon', 'label' => 'أيقونة الخسارة', 'size' => 'SVG أو PNG — 128×128px', 'accept' => '.svg,.png'],
['slot' => 'draw_icon', 'label' => 'أيقونة التعادل', 'size' => 'SVG أو PNG — 128×128px', 'accept' => '.svg,.png'],
['slot' => 'daily_reward', 'label' => 'صندوق المكافأة اليومية', 'size' => 'SVG أو PNG — 128×128px', 'accept' => '.svg,.png'],
['slot' => 'rank_gold', 'label' => 'ميدالية ذهبية', 'size' => 'SVG أو PNG — 32×32px', 'accept' => '.svg,.png'],
['slot' => 'rank_silver', 'label' => 'ميدالية فضية', 'size' => 'SVG أو PNG — 32×32px', 'accept' => '.svg,.png'],
['slot' => 'rank_bronze', 'label' => 'ميدالية برونزية', 'size' => 'SVG أو PNG — 32×32px', 'accept' => '.svg,.png'],
['slot' => 'default_avatar', 'label' => 'صورة افتراضية للاعب', 'size' => 'PNG — 128×128px', 'accept' => '.png,.jpg,.webp'],
['slot' => 'notification_bell', 'label' => 'أيقونة الإشعارات', 'size' => 'SVG — 24×24px', 'accept' => '.svg,.png'],
];
foreach ($assetSlots as $a):
$current = $theme['assets'][$a['slot']] ?? null;
?>
<div class="field">
<form method="POST" enctype="multipart/form-data">
<input type="hidden" name="slot" value="<?= $a['slot'] ?>">
<label><?= $a['label'] ?></label>
<div class="upload-box" onclick="this.querySelector('input[type=file]').click()">
<input type="file" name="asset" accept="<?= $a['accept'] ?>" style="display:none" onchange="this.form.submit()">
📤 اضغط للرفع
<div class="size-hint">⚠️ <?= $a['size'] ?></div>
<?php if ($current): ?>
<div class="current"><img src="<?= $current ?>"></div>
<?php endif; ?>
</div>
</form>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment