feat: توجيه كل النداءات إلى api.intaleqapp.com وطيّ تبديل الدول

⚠️ الطيّ ضرورة أمان لا ترتيب: كل عائلة سيرفرات في links.dart كانت switch
بأربعة فروع (Syria · Egypt · Jordan · default)، وفروع سوريا ومصر تشير إلى
**سيرفرات سيرو الإنتاجية** (api-syria.siromove.com وغيرها). إبقاؤها في
انطلق يعني أن أي جهاز مخزَّن فيه countryCode='Syria' يخاطب إنتاج سيرو
مباشرة. انطلق نشرٌ واحد على مضيف واحد (docs/34: سيرفر لكل مستأجر)،
والدولة تُحل على السيرفر من GLOBAL_COUNTRY.

طُويت 35 كتلة switch إلى قيمة واحدة (11 rider · 11 driver · 6 admin ·
7 service)، والخريطة مأخوذة من تعليق docker/nginx/default.conf نفسه
(«نقطة واحدة لكل الخدمات — التطبيق يغيّر الدومين فقط»):
  server / rideServer   → https://api.intaleqapp.com/backend
  paymentServer         → https://api.intaleqapp.com/v2/main
  location              → …/backend/ride/location
  locationServerSide(د) → …/loction_server/siro/ride/location
  سوكيت الركاب          → https://api.intaleqapp.com:3030
  سوكيت السائقين        → https://api.intaleqapp.com:2020

وأيضاً:
- appDomain و invite: siromove.com → intaleqapp.com، والمجلد
  siromove.com/ → intaleqapp.com/ (فيه invite.php الذي يقصده التطبيق).
- روابط التنزيل siro.app → intaleqapp.com · بريد السائق المولَّد
  @siromove.com → @intaleqapp.com · صفحة التتبع · محاكاة تسجيل سوريا.
- حُذف getter `syria` الميت من links.dart الثلاثة (لا مستدعي له، وكان
  يشير إلى إنتاج سيرو).

لم يُمسّ عمداً:
- `ssl_pinning.dart`: `badCertificateCallback` لا يُستدعى إلا عند فشل
  التحقق العادي، فشهادة api.intaleqapp.com الصالحة تمرّ بلا مساس. ولا
  أختلق بصمة شهادة: تُضاف بصمة انطلق بعد إصدار الشهادة (docs/30 G7).
- `routesjo.intaleq.xyz` و `map-saas.intaleqapp.com`: خدمات خارجية قائمة
  بذاتها للمالك (قرار الخرائط المباشرة) لا تُنقل إلى api.
- `com.siromove.admin` في userAgentPackageName (5 مواضع): من عائلة هويات
  المتاجر — كوميت الهويات، وهو يحتاج قرار المالك.

⚠️ يحتاج نشراً على الطرف الآخر: invite.php و track/index.php و /driver
على intaleqapp.com.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-07-27 16:14:45 +03:00
co-authored by Claude Opus 5
parent 0aab85c732
commit 53322d87a6
16 changed files with 53 additions and 377 deletions
+86
View File
@@ -0,0 +1,86 @@
<?php
/**
* Siro Unified Redirect Gateway (One-Click Redirect for non-Syrian countries)
* URL Format: https://siromove.com/invite.php?code=REF_CODE&app=rider|driver
*/
// 1. Core Config & Links
$config = [
'rider' => [
'ios_store' => 'https://apps.apple.com/st/app/siro-rider/id6748075179',
'android_store' => 'https://play.google.com/store/apps/details?id=com.Siro.siro'
],
'driver' => [
'ios_store' => 'https://apps.apple.com/st/app/siro-driver/id6482995159',
'android_store' => 'https://play.google.com/store/apps/details?id=com.siro_driver'
]
];
$code = htmlspecialchars($_GET['code'] ?? '', ENT_QUOTES, 'UTF-8');
$appType = ($_GET['app'] ?? 'rider') === 'driver' ? 'driver' : 'rider';
$appConfig = $config[$appType];
// 2. Helper Functions
function getVisitorCountry() {
if (!empty($_SERVER['HTTP_CF_IPCOUNTRY'])) {
return strtoupper($_SERVER['HTTP_CF_IPCOUNTRY']);
}
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
if (!empty($_SESSION['visitor_country'])) {
return $_SESSION['visitor_country'];
}
$ip = $_SERVER['REMOTE_ADDR'];
if ($ip === '127.0.0.1' || $ip === '::1' || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
return 'JO'; // Default Jordan
}
try {
$ctx = stream_context_create(['http' => ['timeout' => 2]]);
$apiResponse = @file_get_contents("http://ip-api.com/json/{$ip}", false, $ctx);
if ($apiResponse) {
$data = json_decode($apiResponse, true);
if (!empty($data['countryCode'])) {
$_SESSION['visitor_country'] = strtoupper($data['countryCode']);
return $_SESSION['visitor_country'];
}
}
} catch (Exception $e) {
// Fallback
}
return 'JO';
}
function getDeviceOS() {
$userAgent = strtolower($_SERVER['HTTP_USER_AGENT'] ?? '');
if (strpos($userAgent, 'iphone') !== false || strpos($userAgent, 'ipad') !== false || strpos($userAgent, 'ipod') !== false) {
return 'ios';
}
if (strpos($userAgent, 'android') !== false) {
return 'android';
}
return 'desktop';
}
$country = getVisitorCountry();
$os = getDeviceOS();
// 3. Fallback Handoff for Syrian Users
if ($country === 'SY') {
header("Location: https://siromove.com/inviteSyria.php?code=" . urlencode($code) . "&app=" . urlencode($appType));
exit;
}
// 4. One-Click Instant Redirection (Jordan / Egypt / others)
if ($os === 'ios') {
header("Location: " . $appConfig['ios_store']);
exit;
} else {
// Android or Desktop default
header("Location: " . $appConfig['android_store']);
exit;
}
?>
+357
View File
@@ -0,0 +1,357 @@
<?php
/**
* Siro Syria Redirect Gateway
* URL Format: https://siromove.com/inviteSyria.php?code=REF_CODE&app=rider|driver
*/
$config = [
'rider' => [
'ios_store' => 'https://apps.apple.com/st/app/siro-rider/id6748075179',
'android_store' => 'https://play.google.com/store/apps/details?id=com.Siro.siro',
'direct_apk' => 'https://api-syria.siromove.com/downloads/siro_rider.apk',
'app_name' => 'Siro Rider',
'app_name_ar' => 'سيرو الراكب'
],
'driver' => [
'ios_store' => 'https://apps.apple.com/st/app/siro-driver/id6482995159',
'android_store' => 'https://play.google.com/store/apps/details?id=com.siro_driver',
'direct_apk' => 'https://api-syria.siromove.com/downloads/siro_driver.apk',
'app_name' => 'Siro Driver',
'app_name_ar' => 'سيرو الكابتن'
]
];
$code = htmlspecialchars($_GET['code'] ?? '', ENT_QUOTES, 'UTF-8');
$appType = ($_GET['app'] ?? 'rider') === 'driver' ? 'driver' : 'rider';
$appConfig = $config[$appType];
?>
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>تحميل تطبيق <?php echo $appConfig['app_name_ar']; ?></title>
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;700;900&family=Outfit:wght@400;600;800;900&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#00E5FF',
secondary: '#9C27B0',
bg: '#0F172A',
}
}
}
}
</script>
<style>
body {
font-family: 'Cairo', 'Outfit', sans-serif;
-webkit-font-smoothing: antialiased;
}
/* Smart Highlight Animations & Classes */
.highlight-btn {
border-color: rgba(0, 229, 255, 0.5);
background-color: rgba(0, 229, 255, 0.08);
transform: scale(1.02);
box-shadow: 0 0 20px rgba(0, 229, 255, 0.15);
}
.dimmed-btn {
opacity: 0.4;
filter: grayscale(0.8);
}
.dimmed-btn:hover {
opacity: 1;
filter: none;
transform: scale(1.01);
}
/* Clipboard confirmation bubble animation */
@keyframes scaleIn {
from { transform: scale(0.9) translateY(5px); opacity: 0; }
to { transform: scale(1) translateY(0); opacity: 1; }
}
.toast-active {
animation: scaleIn 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
</style>
</head>
<body class="bg-[#0F172A] text-slate-100 min-h-screen relative overflow-x-hidden selection:bg-cyan-500 selection:text-white flex items-center justify-center p-4">
<!-- Ambient Glowing Background Elements -->
<div class="fixed inset-0 z-0 overflow-hidden pointer-events-none">
<div class="absolute -top-[10%] -left-[10%] w-[60%] h-[60%] bg-cyan-500/10 rounded-full filter blur-[120px] animate-pulse"></div>
<div class="absolute bottom-[5%] -right-[10%] w-[50%] h-[50%] bg-purple-500/8 rounded-full filter blur-[120px] animate-pulse" style="animation-delay: 2s;"></div>
</div>
<!-- Language Toggle Button -->
<div class="absolute top-5 left-5 z-50">
<button id="lang-toggle" class="px-5 py-2 text-sm font-bold bg-white/5 hover:bg-white/10 hover:border-white/20 backdrop-blur-md rounded-full transition duration-300 border border-white/10 shadow-lg cursor-pointer">
English
</button>
</div>
<!-- Main Card Container -->
<div class="relative z-10 w-full max-w-lg bg-slate-900/60 backdrop-blur-xl border border-white/10 rounded-3xl p-8 shadow-2xl flex flex-col items-center">
<!-- Animated Glow Header -->
<header class="text-center mb-8">
<h1 class="text-4xl font-black tracking-widest mb-3 bg-gradient-to-r from-cyan-400 to-purple-500 bg-clip-text text-transparent" id="logo">
SIRO
</h1>
<h2 class="text-2xl font-bold mb-2 text-slate-100" id="welcome-title">مرحباً بك في سيرو</h2>
<p class="text-sm text-slate-400 max-w-sm mx-auto leading-relaxed" id="tagline">
تمت دعوتك للانضمام إلى منصة التوصيل الأسرع والأوفر. يرجى اتباع التعليمات بالأسفل لتحميل التطبيق.
</p>
<!-- Floating Device Message Badge -->
<div id="device-message" class="hidden mt-4 inline-block px-4 py-1.5 rounded-full bg-cyan-500/10 border border-cyan-500/30 text-cyan-300 text-xs font-bold animate-bounce">
<!-- JS Populated -->
</div>
</header>
<!-- Referral Code Section -->
<?php if (!empty($code)): ?>
<div class="w-full bg-slate-950/40 border border-dashed border-cyan-500/30 rounded-2xl p-5 mb-8 flex flex-col items-center gap-3">
<span class="text-xs font-semibold tracking-wider text-slate-400 uppercase" id="referral-label">كود الإحالة الخاص بك</span>
<span class="text-3xl font-black tracking-widest text-cyan-400" id="refCode"><?php echo $code; ?></span>
<button class="px-5 py-2 text-xs font-bold bg-cyan-400/10 text-cyan-300 border border-cyan-400/20 hover:bg-cyan-400 hover:text-slate-950 rounded-full transition duration-300 cursor-pointer" onclick="copyReferralCode()" id="copy-btn">نسخ كود الإحالة</button>
<div id="copy-toast" class="hidden text-xs text-green-400 font-bold mt-1"></div>
<p class="text-xs text-slate-400 text-center leading-relaxed mt-2" id="referral-tip">💡 إذا لم تفتح الروابط تلقائياً، قم بنسخ هذا الكود يدوياً وأدخله في التطبيق بعد تحميله.</p>
</div>
<?php endif; ?>
<!-- Dynamic Action Cards -->
<main class="w-full space-y-4">
<!-- iOS App Card -->
<div class="ios-card bg-slate-800/30 border border-white/5 rounded-2xl p-5 text-right transition duration-300 flex flex-col">
<div class="flex items-center gap-3 mb-2 justify-end">
<span class="text-xs text-slate-400" id="ios-info">المتجر الرسمي</span>
<h3 class="text-md font-bold text-slate-100" id="ios-title">🔒 متجر التطبيقات محظور</h3>
</div>
<p class="text-xs text-slate-400 leading-relaxed mb-4" id="ios-desc">
نظراً للقيود الجغرافية، يرجى تفعيل تطبيق الـ VPN على هاتفك أولاً، ثم الضغط على الزر بالأسفل للانتقال لصفحة التحميل الرسمية على متجر آبل.
</p>
<a href="<?php echo $appConfig['ios_store']; ?>" target="_blank" class="w-full py-3 bg-slate-800 border border-white/10 hover:bg-slate-700/80 text-slate-100 text-sm font-bold rounded-xl transition duration-300 flex items-center justify-center gap-2" id="ios-btn">
<!-- Apple SVG -->
<svg class="w-4 h-4 fill-current" viewBox="0 0 24 24"><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-4.2 14.33-1.38 18.82zM15.97 4.17c.66-.81 1.11-1.93.99-3.06-1 .04-2.2.67-2.92 1.49-.62.71-1.16 1.85-1.01 2.96 1.1.09 2.22-.57 2.94-1.39z"/></svg>
<span>التحميل من App Store</span>
</a>
</div>
<!-- Android Direct APK Card -->
<div class="android-card bg-slate-800/30 border border-white/5 rounded-2xl p-5 text-right transition duration-300 flex flex-col">
<div class="flex items-center gap-3 mb-2 justify-end">
<span class="text-xs text-green-400 font-bold" id="apk-info">✅ لا يحتاج VPN</span>
<h3 class="text-md font-bold text-slate-100" id="apk-title">🚀 تحميل مباشر (APK) - بدون VPN</h3>
</div>
<p class="text-xs text-slate-400 leading-relaxed mb-4" id="apk-desc">
يمكنك تحميل وتثبيت التطبيق مباشرة كملف تثبيت أندرويد دون الحاجة لمتجر جوجل بلاي أو تفعيل VPN.
</p>
<a href="<?php echo $appConfig['direct_apk']; ?>" class="w-full py-3 bg-cyan-400 text-slate-950 hover:bg-cyan-300 text-slate-950 text-sm font-bold rounded-xl transition duration-300 flex items-center justify-center gap-2" id="apk-btn">
<!-- Download SVG -->
<svg class="w-4 h-4 fill-none stroke-current" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>
<span>تحميل تطبيق APK مباشرة</span>
</a>
</div>
<!-- Android Play Store Card -->
<div class="android-card bg-slate-800/30 border border-white/5 rounded-2xl p-5 text-right transition duration-300 flex flex-col">
<div class="flex items-center gap-3 mb-2 justify-end">
<span class="text-xs text-yellow-500 font-bold" id="play-info">⚠️ قد يحتاج VPN</span>
<h3 class="text-md font-bold text-slate-100" id="play-title">🤖 التحميل من Google Play</h3>
</div>
<p class="text-xs text-slate-400 leading-relaxed mb-4" id="play-desc">
إذا كنت تستخدم شبكة VPN نشطة على جهازك، يمكنك التحميل من متجر جوجل بلاي الرسمي.
</p>
<a href="<?php echo $appConfig['android_store']; ?>" target="_blank" class="w-full py-3 bg-slate-800 border border-white/10 hover:bg-slate-700/80 text-slate-100 text-sm font-bold rounded-xl transition duration-300 flex items-center justify-center gap-2" id="play-btn">
<!-- Play Store SVG -->
<svg class="w-4 h-4 fill-current" viewBox="0 0 24 24"><path d="M5.223 2.013a1.5 1.5 0 00-1.31 1.782l3.29 5.637-3.29 5.637a1.5 1.5 0 001.31 1.782l10.99-6.419c.75-.447.75-1.58 0-2.027L5.223 2.013z"/></svg>
<span>التحميل من Google Play</span>
</a>
</div>
</main>
<footer class="mt-8 text-center text-xs text-slate-500" id="footer-text">
حقوق النشر © <?php echo date('Y'); ?> سيرو. جميع الحقوق محفوظة.
</footer>
</div>
<!-- Bilingual content JSON -->
<script>
const content = {
ar: {
appName: "سيرو",
welcome: "مرحباً بك في سيرو",
tagline: "تمت دعوتك للانضمام إلى منصة التوصيل الأسرع والأوفر. يرجى اتباع التعليمات بالأسفل لتحميل التطبيق.",
referralLabel: "كود الإحالة الخاص بك",
copyBtn: "نسخ كود الإحالة",
copiedMsg: "تم نسخ كود الإحالة: ",
referralTip: "💡 إذا لم تفتح الروابط تلقائياً، قم بنسخ هذا الكود يدوياً وأدخله في التطبيق بعد تحميله.",
iosTitle: "🔒 متجر التطبيقات محظور",
iosDesc: "نظراً للقيود الجغرافية، يرجى تفعيل تطبيق الـ VPN على هاتفك أولاً، ثم الضغط على الزر بالأسفل للانتقال لصفحة التحميل الرسمية على متجر آبل.",
iosBtn: "التحميل من App Store",
iosInfo: "المتجر الرسمي",
apkTitle: "🚀 تحميل مباشر (APK) - بدون VPN",
apkDesc: "يمكنك تحميل وتثبيت التطبيق مباشرة كملف تثبيت أندرويد دون الحاجة لمتجر جوجل بلاي أو تفعيل VPN.",
apkBtn: "تحميل تطبيق APK مباشرة",
apkInfo: "✅ لا يحتاج VPN",
playTitle: "🤖 التحميل من Google Play",
playDesc: "إذا كنت تستخدم شبكة VPN نشطة على جهازك، يمكنك التحميل من متجر جوجل بلاي الرسمي.",
playBtn: "التحميل من Google Play",
playInfo: "⚠️ قد يحتاج VPN",
footer: "حقوق النشر © 2026 سيرو. جميع الحقوق محفوظة.",
msgAndroid: "تم اكتشاف جهاز أندرويد 🤖 - تم تظليل الروابط المباشرة",
msgIos: "تم اكتشاف جهاز آيفون 🍎 - تم تظليل متجر التطبيقات"
},
en: {
appName: "SIRO",
welcome: "Welcome to Siro",
tagline: "You have been invited to join the fastest and most affordable delivery platform. Please follow the instructions below to download the app.",
referralLabel: "Your Referral Code",
copyBtn: "Copy Referral Code",
copiedMsg: "Referral code copied: ",
referralTip: "💡 If deep links don't open automatically, copy this code and enter it manually in the app after downloading.",
iosTitle: "🔒 App Store is Geo-Restricted",
iosDesc: "Due to local network restrictions, please enable a VPN on your device first, then click below to download from the Apple App Store.",
iosBtn: "Download from App Store",
iosInfo: "Official Store",
apkTitle: "🚀 Direct APK Download - No VPN Required",
apkDesc: "You can download and install the app directly as an Android package (APK) without needing a VPN or the Play Store.",
apkBtn: "Download APK Directly",
apkInfo: "✅ No VPN Required",
playTitle: "🤖 Download from Google Play",
playDesc: "If you have an active VPN connection on your device, you can download the app from the official Google Play Store.",
playBtn: "Download from Google Play",
playInfo: "⚠️ May Require VPN",
footer: "Copyright © 2026 Siro. All rights reserved.",
msgAndroid: "Android Device Detected 🤖 - Direct APK links highlighted",
msgIos: "iOS Device Detected 🍎 - Apple Store highlighted"
}
};
let currentLang = 'ar';
function detectOS() {
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
const androidCards = document.querySelectorAll('.android-card');
const iosCards = document.querySelectorAll('.ios-card');
const deviceMessage = document.getElementById('device-message');
// Reset highlight/dimmed states
[...androidCards, ...iosCards].forEach(card => {
card.classList.remove('highlight-btn', 'dimmed-btn');
});
deviceMessage.classList.add('hidden');
if (/android/i.test(userAgent)) {
androidCards.forEach(c => c.classList.add('highlight-btn'));
iosCards.forEach(c => c.classList.add('dimmed-btn'));
deviceMessage.textContent = content[currentLang].msgAndroid;
deviceMessage.classList.remove('hidden');
} else if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
iosCards.forEach(c => c.classList.add('highlight-btn'));
androidCards.forEach(c => c.classList.add('dimmed-btn'));
deviceMessage.textContent = content[currentLang].msgIos;
deviceMessage.classList.remove('hidden');
}
}
function updateLanguage(lang) {
currentLang = lang;
const t = content[lang];
const isAr = lang === 'ar';
document.documentElement.setAttribute('dir', isAr ? 'rtl' : 'ltr');
document.documentElement.setAttribute('lang', lang);
// Update DOM text contents
document.getElementById('logo').textContent = t.appName;
document.getElementById('welcome-title').textContent = t.welcome;
document.getElementById('tagline').textContent = t.tagline;
const refLabel = document.getElementById('referral-label');
if (refLabel) refLabel.textContent = t.referralLabel;
const copyBtn = document.getElementById('copy-btn');
if (copyBtn) copyBtn.textContent = t.copyBtn;
const refTip = document.getElementById('referral-tip');
if (refTip) refTip.textContent = t.referralTip;
document.getElementById('ios-title').textContent = t.iosTitle;
document.getElementById('ios-desc').textContent = t.iosDesc;
document.querySelector('#ios-btn span').textContent = t.iosBtn;
document.getElementById('ios-info').textContent = t.iosInfo;
document.getElementById('apk-title').textContent = t.apkTitle;
document.getElementById('apk-desc').textContent = t.apkDesc;
document.querySelector('#apk-btn span').textContent = t.apkBtn;
document.getElementById('apk-info').textContent = t.apkInfo;
document.getElementById('play-title').textContent = t.playTitle;
document.getElementById('play-desc').textContent = t.playDesc;
document.querySelector('#play-btn span').textContent = t.playBtn;
document.getElementById('play-info').textContent = t.playInfo;
document.getElementById('footer-text').textContent = t.footer;
// Toggle language button text
document.getElementById('lang-toggle').textContent = isAr ? 'English' : 'العربية';
detectOS();
}
document.getElementById('lang-toggle').addEventListener('click', () => {
updateLanguage(currentLang === 'ar' ? 'en' : 'ar');
});
function copyReferralCode() {
const codeText = document.getElementById("refCode").innerText;
const toast = document.getElementById("copy-toast");
navigator.clipboard.writeText(codeText).then(() => {
showToast(content[currentLang].copiedMsg + codeText);
}, () => {
// Fallback
const dummy = document.createElement("textarea");
document.body.appendChild(dummy);
dummy.value = codeText;
dummy.select();
document.execCommand("copy");
document.body.removeChild(dummy);
showToast(content[currentLang].copiedMsg + codeText);
});
}
function showToast(message) {
const toast = document.getElementById("copy-toast");
toast.textContent = message;
toast.classList.remove('hidden');
toast.classList.add('toast-active');
setTimeout(() => {
toast.classList.add('hidden');
toast.classList.remove('toast-active');
}, 3000);
}
document.addEventListener('DOMContentLoaded', () => {
updateLanguage('ar');
});
</script>
</body>
</html>
+539
View File
@@ -0,0 +1,539 @@
<meta charset="utf-8">
<title>سيرو — التقرير الشامل للمنظومة</title>
<style>
:root{
--bg:#F6F7F5; --surface:#FFFFFF; --surface2:#EEF1EE;
--ink:#1A241F; --muted:#5B6862; --faint:#8B968F;
--line:#E1E5E1; --line2:#D2D8D3;
--brand:#0E7A5F; --brand-ink:#0A5945; --brand-soft:#E4F0EB;
--amber:#9A6B12; --amber-soft:#F6EDDA;
--red:#B3362B; --red-soft:#F7E5E2;
--good:#2E7D4F; --good-soft:#E4F1E8;
--sans:-apple-system, BlinkMacSystemFont, "SF Pro Arabic", "Helvetica Neue", Arial, sans-serif;
--mono:ui-monospace,"SF Mono",Consolas,monospace;
}
@media (prefers-color-scheme: dark){
:root{
--bg:#0F1512; --surface:#161E19; --surface2:#1C2620;
--ink:#E8EDEA; --muted:#9BA8A1; --faint:#6E7B74;
--line:#26302B; --line2:#32403A;
--brand:#3FBF97; --brand-ink:#8FE0C5; --brand-soft:#15342A;
--amber:#E0AE55; --amber-soft:#33290F;
--red:#E07065; --red-soft:#361A16;
--good:#57C287; --good-soft:#14301F;
}
}
:root[data-theme="dark"]{
--bg:#0F1512; --surface:#161E19; --surface2:#1C2620;
--ink:#E8EDEA; --muted:#9BA8A1; --faint:#6E7B74;
--line:#26302B; --line2:#32403A;
--brand:#3FBF97; --brand-ink:#8FE0C5; --brand-soft:#15342A;
--amber:#E0AE55; --amber-soft:#33290F;
--red:#E07065; --red-soft:#361A16;
--good:#57C287; --good-soft:#14301F;
}
:root[data-theme="light"]{
--bg:#F6F7F5; --surface:#FFFFFF; --surface2:#EEF1EE;
--ink:#1A241F; --muted:#5B6862; --faint:#8B968F;
--line:#E1E5E1; --line2:#D2D8D3;
--brand:#0E7A5F; --brand-ink:#0A5945; --brand-soft:#E4F0EB;
--amber:#9A6B12; --amber-soft:#F6EDDA;
--red:#B3362B; --red-soft:#F7E5E2;
--good:#2E7D4F; --good-soft:#E4F1E8;
}
html{ scroll-behavior:smooth; }
@media (prefers-reduced-motion: reduce){ html{ scroll-behavior:auto; } }
.page{
background:var(--bg); color:var(--ink);
font-family:var(--sans); font-size:16px; line-height:1.85;
min-height:100%;
}
.page *{ box-sizing:border-box; }
.wrap{ max-width:840px; margin:0 auto; padding:0 22px; }
.page h1,.page h2,.page h3,.page h4{ margin:0; color:var(--ink); text-wrap:balance; line-height:1.35; }
.page p{ margin:0; }
.page a{ color:var(--brand); }
.page a:focus-visible, .page summary:focus-visible{ outline:2px solid var(--brand); outline-offset:2px; border-radius:4px; }
code{
direction:ltr; unicode-bidi:isolate; font-family:var(--mono); font-size:.82em;
background:var(--surface2); border:1px solid var(--line); border-radius:5px; padding:.08em .4em;
}
.num{ font-variant-numeric:tabular-nums; }
/* ===== Hero ===== */
.hero{ padding:64px 0 36px; border-bottom:1px solid var(--line); }
.hero .kicker{
display:inline-block; font-size:.78rem; font-weight:700; letter-spacing:.04em;
color:var(--brand-ink); background:var(--brand-soft); border-radius:99px; padding:4px 14px;
margin-bottom:18px;
}
.hero h1{ font-size:clamp(1.7rem, 4.5vw, 2.5rem); font-weight:800; }
.hero .lede{ margin-top:14px; font-size:1.05rem; color:var(--muted); max-width:60ch; }
.hero .meta{ margin-top:16px; font-size:.8rem; color:var(--faint); }
.stats{ display:grid; grid-template-columns:repeat(6,1fr); gap:0; margin-top:30px;
border:1px solid var(--line); border-radius:14px; background:var(--surface); overflow:hidden; }
.stat{ padding:14px 10px; text-align:center; border-inline-start:1px solid var(--line); }
.stat:first-child{ border-inline-start:none; }
.stat b{ display:block; font-size:1.35rem; font-weight:800; color:var(--brand-ink); font-variant-numeric:tabular-nums; }
.stat span{ font-size:.72rem; color:var(--muted); line-height:1.4; display:block; margin-top:2px; }
@media (max-width:700px){
.stats{ grid-template-columns:repeat(3,1fr); }
.stat:nth-child(4){ border-inline-start:none; }
.stat:nth-child(-n+3){ border-bottom:1px solid var(--line); }
}
/* ===== Sticky TOC ===== */
.tocbar{
position:sticky; top:0; z-index:10;
background:color-mix(in srgb, var(--bg) 75%, transparent);
backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
border-bottom:1px solid var(--line); padding:10px 0;
}
.tocbar .row{ display:flex; gap:8px; overflow-x:auto; scrollbar-width:none; padding:2px; }
.tocbar .row::-webkit-scrollbar{ display:none; }
.tocbar a{
flex:none; text-decoration:none; font-size:.8rem; font-weight:700; color:var(--muted);
border:1px solid var(--line); background:var(--surface); border-radius:99px; padding:5px 13px;
white-space:nowrap; transition: all 0.2s ease;
}
.tocbar a b{ color:var(--brand); font-weight:800; margin-inline-end:4px; font-variant-numeric:tabular-nums; }
.tocbar a:hover{ border-color:var(--brand); color:var(--ink); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.05); }
/* ===== Sections ===== */
section{ padding:46px 0 8px; }
.sec-head{ margin-bottom:20px; }
.sec-head .eyebrow{
font-size:.75rem; font-weight:800; color:var(--brand); letter-spacing:.08em;
font-variant-numeric:tabular-nums;
}
.sec-head h2{ font-size:1.45rem; font-weight:800; margin-top:4px; }
.sec-head .thesis{ margin-top:8px; color:var(--muted); font-size:.95rem; max-width:66ch; }
.subhead{
font-size:.82rem; font-weight:800; color:var(--faint); letter-spacing:.03em;
margin:26px 0 10px; display:flex; align-items:center; gap:10px;
}
.subhead::after{ content:""; flex:1; height:1px; background:var(--line); }
/* compact feature rows */
.rows{ border:1px solid var(--line); border-radius:14px; background:var(--surface); overflow:hidden; box-shadow: 0 2px 10px rgba(0,0,0,0.02); }
.row-item{ padding:13px 18px; border-top:1px solid var(--line); transition: all 0.2s ease; cursor: default; }
.row-item:first-child{ border-top:none; }
.row-item:hover{ background:var(--surface2); padding-inline-start:22px; }
.row-item h4{ font-size:.95rem; font-weight:800; display:inline; }
.row-item p{ display:inline; color:var(--muted); font-size:.9rem; }
.row-item h4::after{ content:" — "; color:var(--faint); font-weight:400; }
.row-item .why{ display:block; margin-top:3px; font-size:.83rem; color:var(--brand-ink); }
/* alerts */
.alert{ border-radius:12px; padding:14px 18px; margin:16px 0; font-size:.9rem; border:1px solid; }
.alert p{ color:var(--ink); }
.alert .tag{ display:inline-block; font-size:.72rem; font-weight:800; border-radius:6px; padding:1px 9px; margin-bottom:6px; }
.alert.crit{ background:var(--red-soft); border-color:color-mix(in srgb, var(--red) 35%, transparent); }
.alert.crit .tag{ background:var(--red); color:var(--bg); }
.alert.warn{ background:var(--amber-soft); border-color:color-mix(in srgb, var(--amber) 35%, transparent); }
.alert.warn .tag{ background:var(--amber); color:var(--bg); }
.alert.good{ background:var(--good-soft); border-color:color-mix(in srgb, var(--good) 35%, transparent); }
.alert.good .tag{ background:var(--good); color:var(--bg); }
/* ===== Ride flow timeline ===== */
.flow{ position:relative; padding-inline-start:26px; margin-top:8px; }
.flow::before{ content:""; position:absolute; inset-inline-start:8px; top:8px; bottom:8px; width:2px;
background:linear-gradient(var(--brand), var(--line2)); border-radius:2px; }
.step{ position:relative; padding:0 0 26px; }
.step::before{
content:""; position:absolute; inset-inline-start:-24px; top:7px; width:12px; height:12px;
border-radius:50%; background:var(--bg); border:3px solid var(--brand);
}
.step h4{ font-size:1rem; font-weight:800; }
.step h4 .t{ font-size:.72rem; font-weight:700; color:var(--brand-ink); background:var(--brand-soft);
border-radius:99px; padding:2px 10px; margin-inline-start:8px; vertical-align:2px; white-space:nowrap; }
.step p{ color:var(--muted); font-size:.9rem; margin-top:4px; max-width:62ch; }
/* ===== two-col mini grid ===== */
.duo{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
@media (max-width:640px){ .duo{ grid-template-columns:1fr; } }
.panel{ border:1px solid var(--line); border-radius:14px; background:var(--surface); padding:16px 18px; transition: all 0.2s ease; cursor: default; }
.panel:hover{ transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,0,0,0.04); border-color: color-mix(in srgb, var(--brand) 30%, var(--line)); }
.panel h4{ font-size:.95rem; font-weight:800; margin-bottom:6px; }
.panel p, .panel li{ color:var(--muted); font-size:.88rem; }
.panel ul{ margin:6px 0 0; padding-inline-start:18px; display:flex; flex-direction:column; gap:5px; }
.panel.can h4{ color:var(--good); }
.panel.cannot h4{ color:var(--red); }
/* ===== tutorial modules ===== */
.mods{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
@media (max-width:640px){ .mods{ grid-template-columns:1fr; } }
.mod{ border:1px solid var(--line); border-radius:14px; background:var(--surface); padding:16px 18px; position:relative; transition: all 0.2s ease; cursor: default; }
.mod:hover{ transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,0,0,0.04); border-color: color-mix(in srgb, var(--brand) 30%, var(--line)); }
.mod .shots{ position:absolute; top:14px; inset-inline-end:16px; font-size:.7rem; font-weight:800;
color:var(--brand-ink); background:var(--brand-soft); border-radius:99px; padding:2px 10px; font-variant-numeric:tabular-nums; }
.mod h4{ font-size:.95rem; font-weight:800; padding-inline-end:70px; }
.mod ol{ margin:8px 0 0; padding-inline-start:18px; color:var(--muted); font-size:.85rem; display:flex; flex-direction:column; gap:4px; }
.mod .note{ margin-top:8px; font-size:.8rem; color:var(--brand-ink); }
/* transit actors */
.actors{ display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin:14px 0 4px; }
@media (max-width:760px){ .actors{ grid-template-columns:1fr 1fr; } }
.actor{ border:1px solid var(--line); border-radius:12px; background:var(--surface); padding:12px 14px; text-align:center; }
.actor .ic{ font-size:1.4rem; }
.actor b{ display:block; font-size:.85rem; margin-top:4px; }
.actor span{ font-size:.74rem; color:var(--muted); display:block; line-height:1.5; }
footer.end{ margin-top:56px; border-top:1px solid var(--line); padding:22px 0 60px;
font-size:.8rem; color:var(--faint); display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px; }
</style>
<div class="page" dir="rtl" lang="ar">
<header class="hero"><div class="wrap">
<span class="kicker">التقرير الشامل — نسخة محدّثة تشمل مواصلاتي وسير الرحلة والتوتوريال</span>
<h1>سيرو — الإرث الرقمي لمنظومة التنقّل المتكاملة</h1>
<p class="lede">
جرد كامل لكل ما بُني في منصة Siro ولماذا بُني: تطبيقات الراكب والسائق والإدارة وخدمة العملاء،
البنية الخلفية ومحرك التسعير، الخرائط والتتبع الحي، نظام «مواصلاتي» لباصات الجامعات،
البوتات والذكاء الاصطناعي، والمنظومة المالية — مع سير الرحلة خطوة بخطوة وخطة التوتوريال الكاملة.
</p>
<p class="meta">أُعدّ بفحص مباشر للكود المصدري — كل رقم ومسار ملف تمّ التحقق منه فعلياً · آخر تحديث 2026-07-14</p>
<div class="stats">
<div class="stat"><b>4</b><span>تطبيقات موبايل</span></div>
<div class="stat"><b>9</b><span>فئات مركبات</span></div>
<div class="stat"><b>3</b><span>دول تشغيل</span></div>
<div class="stat"><b>13+</b><span>لغة مدعومة</span></div>
<div class="stat"><b>10+</b><span>طرق دفع محلية</span></div>
<div class="stat"><b>2</b><span>خطا أعمال: مشاوير + مواصلاتي</span></div>
</div>
</div></header>
<nav class="tocbar" aria-label="فهرس التقرير"><div class="wrap"><div class="row">
<a href="#overview"><b>00</b>نظرة عامة</a>
<a href="#rideflow"><b>01</b>سير الرحلة</a>
<a href="#rider"><b>02</b>الراكب</a>
<a href="#driver"><b>03</b>السائق</a>
<a href="#ops"><b>04</b>الإدارة والدعم</a>
<a href="#backend"><b>05</b>البنية والتسعير</a>
<a href="#maps"><b>06</b>الخرائط</a>
<a href="#transit"><b>07</b>مواصلاتي</a>
<a href="#bots"><b>08</b>البوتات</a>
<a href="#finance"><b>09</b>المالية والاستثمار</a>
<a href="#legacy"><b>10</b>القيمة</a>
<a href="#risks"><b>11</b>المخاطر</a>
<a href="#tutorial"><b>12</b>التوتوريال</a>
</div></div></nav>
<main class="wrap">
<!-- 00 -->
<section id="overview">
<div class="sec-head">
<span class="eyebrow">00</span>
<h2>نظرة عامة: منصة واحدة، تسعة أنظمة متكاملة</h2>
<p class="thesis">سيرو ليست «تطبيق طلب سيارة» — هي منظومة من 4 تطبيقات Flutter، وباك اند PHP/Node ضخم، وخوادم Socket خاصة للتتبع الحي، ومحرك تسعير بالذكاء الاصطناعي، ونظام نقل جماعي للجامعات، وبنية مالية متعددة الدول — كلها مبنية داخلياً وتعمل في الأردن ومصر وسوريا.</p>
</div>
<div class="rows">
<div class="row-item"><h4>🚕 أربعة تطبيقات Flutter</h4><p>الراكب (226 ملف)، السائق (275 ملف — الأكبر)، الإدارة (131)، خدمة العملاء (66) — تشترك بنفس الباك اند.</p></div>
<div class="row-item"><h4>🗄️ باك اند PHP مقسّم بأمان مركزي</h4><p>كل وحدة (مصادقة، رحلات، تسعير، تأمين…) تمر إجبارياً عبر طبقة JWT + تشفير + تحديد معدل طلبات واحدة.</p></div>
<div class="row-item"><h4>📍 خوادم Socket خاصة للموقع</h4><p>خادم سائق وخادم راكب منفصلان — تتبع لحظي دون الاعتماد على Google Maps، بتوفير تكلفة ضخم.</p></div>
<div class="row-item"><h4>🤖 محرك تسعير ذكي</h4><p>بوت يقرأ أسعار المنافسين من تطبيقاتهم، محرك يفكّك معادلاتهم، وكرون جوبز تُبقي سيرو أرخص بـ 6.5% آلياً.</p></div>
<div class="row-item"><h4>🚌 مواصلاتي</h4><p>نظام نقل جماعي للجامعات والمؤسسات (SaaS مجاني) بقاعدة بيانات معزولة ولوحة تحكم ويب مستقلة — القسم 07.</p></div>
<div class="row-item"><h4>💳 محفظة ودفع متعدد الدول</h4><p>خدمة منفصلة (268 ملف) تربط MTN وSyriatel Cash وShamCash وCliq وPayMob وeCash.</p></div>
</div>
</section>
<!-- 01 RIDE FLOW -->
<section id="rideflow">
<div class="sec-head">
<span class="eyebrow">01</span>
<h2>سير الرحلة — من فتح التطبيق حتى التقييم</h2>
<p class="thesis">الدورة الكاملة كما تعمل فعلياً في الكود: كل خطوة لها شاشة وحالة (State) وقناة تواصل حي. هذه الدورة نفسها هي أساس التوتوريال في القسم 12.</p>
</div>
<div class="flow">
<div class="step"><h4>الدخول والتحقق <span class="t">أقل من دقيقة</span></h4><p>رقم الهاتف + رمز OTP (واتساب/SMS حسب الدولة) — لا بريد إلكتروني إجباري ولا بطاقة. الجلسة تُربط ببصمة الجهاز فلا يعمل الرمز المسروق على جهاز آخر.</p></div>
<div class="step"><h4>تحديد الوجهة والسعر <span class="t">فوري</span></h4><p>بحث عن المكان، اختيار فئة من 9 فئات، والسعر يُحسب بالكامل على الخادم ويُختم برمز موقّت صالح 7 دقائق — لا يمكن التلاعب به بين شاشة العرض والتأكيد.</p></div>
<div class="step"><h4>البحث عن كابتن <span class="t">حتى 90 ثانية</span></h4><p>مطابقة «أقرب سائق» عبر Redis الجغرافي. إذا لم يقبل أحد خلال 90 ثانية يقترح «المفاوض الذكي» رفع السعر ~5% بدل إلغاء الطلب.</p></div>
<div class="step"><h4>قبول الكابتن والتوجه إليك <span class="t">تتبع حي</span></h4><p>بطاقة الكابتن (اسم، تقييم، سيارة، لوحة) ومسار أصفر يتحرك لحظياً عبر WebSocket، مع إشعار FCM وLive Activity على iOS.</p></div>
<div class="step"><h4>الوصول والانتظار <span class="t">مهلة 5 دقائق</span></h4><p>إشعار «الكابتن وصل» ويبدأ عداد انتظار. الإلغاء قبل القبول مجاني دائماً؛ بعد الوصول قد تُطبَّق رسوم.</p></div>
<div class="step"><h4>الرحلة الجارية <span class="t">مسار أزرق + SOS</span></h4><p>عداد حي، كشف انحراف عن المسار (50م)، تنبيه تجاوز سرعة 100كم/س، زر طوارئ يعمل بهزّ الهاتف، ومشاركة الرحلة مع الأهل برابط حي.</p></div>
<div class="step"><h4>التسوية والدفع <span class="t">من الخادم</span></h4><p>السعر النهائي يُعاد حسابه من المسافة والزمن الفعليين بسقوف أمان (≤1.6× المعروض)، ثم الدفع: كاش، محفظة، PayMob، MTN، Syriatel، Cliq.</p></div>
<div class="step"><h4>التقييم والإكرامية <span class="t">اختياري</span></h4><p>تقييم الكابتن بالنجوم مع إكرامية اختيارية، وتُحفظ الرحلة في السجل مع الفاتورة.</p></div>
</div>
</section>
<!-- 02 RIDER -->
<section id="rider">
<div class="sec-head">
<span class="eyebrow">02</span>
<h2>تطبيق الراكب</h2>
<p class="thesis">واجهة المستخدم النهائي — أعمق بكثير من «اطلب وادفع»، وفيها ميزات ثقة وسلامة نادرة حتى عند منافسين أكبر.</p>
</div>
<div class="subhead">الحجز والتسعير</div>
<div class="rows">
<div class="row-item"><h4>9 فئات ركوب</h4><p>اقتصادية (Balash/Awfar)، Comfort، كهربائية، Lady نسائية، Van عائلية، VIP/مشوار (اختيار سائق بالاسم لموعد لاحق)، توصيل، ورايح-جاي بين المدن (+23 كم).</p><span class="why">كل فئة تفتح شريحة سوق مختلفة — من الطالب حتى العائلة والراكبات.</span></div>
<div class="row-item"><h4>شارة مقارنة أسعار</h4><p>«أنت توفّر X% مقارنة بكريم/أوبر/يلا-جو» بالاسم صراحة على شاشة الطلب.</p></div>
<div class="row-item"><h4>المفاوض الذكي</h4><p>اقتراح آلي لرفع السعر عند عدم توفر كابتن — يقلل الطلبات الفاشلة.</p></div>
</div>
<div class="subhead">الدفع والولاء</div>
<div class="rows">
<div class="row-item"><h4>Siro Prime</h4><p>اشتراك ~4$ شهرياً: بلا تسعير ذروة، أولوية مطابقة، شارة تزيد قبول السائقين — إيراد شهري متكرر.</p></div>
<div class="row-item"><h4>مكافآت شحن المحفظة</h4><p>«ادفع 20 خذ 21» — يشجع الرصيد المسبق ويقلل الكاش.</p></div>
<div class="row-item"><h4>تنبيه الرصيد السالب</h4><p>بانر دائم + قراءة صوتية عند وجود دين من رحلة كاش سابقة — تحصيل استباقي.</p></div>
<div class="row-item"><h4>إحالة ثنائية</h4><p>دعوة أصدقاء كركاب أو سائقين عبر واتساب، والمكافأة تُفتح بعد رحلتين فعليتين.</p></div>
</div>
<div class="subhead">السلامة والثقة</div>
<div class="rows">
<div class="row-item"><h4>زر الطوارئ SOS</h4><p>واتساب فوري لجهة طوارئ مع الموقع الحي واسم السائق واللوحة — ويتفعّل بهزّ الهاتف 5 مرات.</p></div>
<div class="row-item"><h4>مراقبة حية لطرف ثالث</h4><p>رابط يتيح لولي الأمر متابعة الموقع والسرعة دون تثبيت التطبيق — تمايز حقيقي لشريحة الطالبات.</p></div>
<div class="row-item"><h4>مكالمات WebRTC داخلية</h4><p>اتصال راكب↔سائق دون كشف الأرقام، ببنية ذاتية بدل Agora المدفوعة.</p></div>
<div class="row-item"><h4>تسجيل صوتي للرحلة + تنبيه سرعة</h4><p>دليل عند النزاع، وتنبيه فوري عند تجاوز 100 كم/س.</p></div>
<div class="row-item"><h4>حماية تقنية</h4><p>بصمة جهاز، كشف Root/Jailbreak، تثبيت SSL ضد اعتراض البيانات.</p></div>
</div>
<div class="subhead">تجربة مصممة للمنطقة</div>
<div class="rows">
<div class="row-item"><h4>13+ لغة بثلاث لهجات عربية</h4><p>مصري/أردني/سوري بملفات منفصلة + RTL كامل — جاهزية توسع حقيقية.</p></div>
<div class="row-item"><h4>خرائط دون اتصال + كشف نوعية الجهاز</h4><p>تحميل مسبق للبلاطات، وتخفيف الرسوميات آلياً على الأجهزة الاقتصادية.</p></div>
<div class="row-item"><h4>قراءة صوتية TTS</h4><p>وصف الرحلات والتنبيهات صوتياً — يشمل ضعاف البصر، سوق مهمَل من المنافسين.</p></div>
</div>
</section>
<!-- 03 DRIVER -->
<section id="driver">
<div class="sec-head">
<span class="eyebrow">03</span>
<h2>تطبيق السائق</h2>
<p class="thesis">أكبر تطبيق في المنظومة (275 ملف) — محرك تشغيل الأسطول: مكافحة احتيال، نظام تدرّج بخصومات عمولة فعلية، وذكاء تشغيلي يوجّه السائق للربح.</p>
</div>
<div class="alert good"><span class="tag">✅ مؤكد في الكود</span>
<p>ميزة «أرباحك أعلى بـ X مقارنة بالتطبيقات الأخرى» موجودة ومفعّلة: <code>driver_earnings_badge.dart</code> يعرض شارة خضراء على شاشة قبول الطلب مبنية على حقل <code>driver_earnings_extra</code> من الخادم.</p>
</div>
<div class="rows">
<div class="row-item"><h4>تدرّج بخصم عمولة حقيقي</h4><p>برونزي ← فضي (−1%) ← ذهبي (−2%) ← ماسي (−5% + أولوية) — ولاء بمكافأة مالية ملموسة.</p></div>
<div class="row-item"><h4>سلسلة رحلات بلا إلغاء</h4><p>5 رحلات متتالية = عمولة 0% لبقية اليوم؛ أي إلغاء يصفّر السلسلة.</p></div>
<div class="row-item"><h4>خارطة طلب تنبؤية</h4><p>أين سيرتفع الطلب خلال الساعة القادمة، من بيانات الرحلات التاريخية.</p></div>
<div class="row-item"><h4>حد 12 ساعة قيادة + حظر بعد 3 إلغاءات</h4><p>راحة إجبارية 6 ساعات، وحماية موثوقية السوق من الإلغاء المتكرر.</p></div>
<div class="row-item"><h4>تحقق مسافة قبل إنهاء الرحلة</h4><p>مقارنة إزاحة GPS الفعلية بالمتوقعة — يمنع تزوير إتمام الرحلات.</p></div>
<div class="row-item"><h4>توثيق بالذكاء الاصطناعي</h4><p>Gemini يقرأ الهوية والرخصة، ومطابقة وجه (سيلفي↔هوية) قبل قبول التسجيل، وكشف «الرحلة الذاتية» بمقارنة بصمتي الجهازين.</p></div>
<div class="row-item"><h4>Android Auto / CarPlay</h4><p>جسر ملاحة مخصص لشاشة السيارة — تجربة مكافئة لأوبر/كريم.</p></div>
<div class="row-item"><h4>سحب أرباح متعدد القنوات</h4><p>PayMob، MTN، Cliq، eCash، حساب بنكي، وحتى SMS في سوريا.</p></div>
</div>
</section>
<!-- 04 OPS -->
<section id="ops">
<div class="sec-head">
<span class="eyebrow">04</span>
<h2>الإدارة وخدمة العملاء</h2>
<p class="thesis">لوحة تشغيل داخلية حقيقية بطبقتين (قديمة + V2 تحليلية)، وتطبيق دعم ميداني سريع — مع فجوات تشغيلية يجب قولها بصراحة.</p>
</div>
<div class="rows">
<div class="row-item"><h4>مركز عمليات حي (V2)</h4><p>رحلات نشطة، سائقون متصلون، إيراد اليوم مقابل الأمس، شكاوى — يتحدث كل دقيقتين.</p></div>
<div class="row-item"><h4>محرر تسعير «كازان»</h4><p>عمولة كل دولة، سعر الكيلومتر لكل فئة، وتسعير الدقيقة حسب الوقت — أهم رافعة إيراد في المنصة.</p></div>
<div class="row-item"><h4>مساعد تسجيل بالذكاء الاصطناعي</h4><p>Gemini + Claude Haiku يقرآن الوثائق المصرية ويكشفان الانتهاء وعدم تطابق الأسماء آلياً.</p></div>
<div class="row-item"><h4>بطاقة جودة السائق + سجل تدقيق</h4><p>قرارات حظر مبنية على بيانات، وكل إجراء موظف حساس مسجّل بالاسم والوقت.</p></div>
<div class="row-item"><h4>دعم ميداني سريع</h4><p>بحث برقم هاتف/رحلة، تفعيل سائقين، وقوالب واتساب عربية جاهزة — بدون CRM مكلف.</p></div>
</div>
<div class="alert warn"><span class="tag">فجوات تشغيلية</span>
<p>شاشة عرض الشكوى في تطبيق خدمة العملاء ما زالت فارغة (stub) رغم جاهزية قاعدة البيانات لسير تحقيق كامل · لا توجد أداة استرجاع مبلغ (Refund) في كامل النظام · لا يوجد تتبع SLA أو تصعيد للشكاوى الحرجة.</p>
</div>
</section>
<!-- 05 BACKEND -->
<section id="backend">
<div class="sec-head">
<span class="eyebrow">05</span>
<h2>البنية الخلفية ومحرك التسعير</h2>
<p class="thesis">قلب المنصة: كل طلب يمر عبر طبقة أمان مركزية قبل أي منطق عمل، ومحرك رحلات (202 ملف) يتخذ قرارات تجارية آلياً.</p>
</div>
<div class="rows">
<div class="row-item"><h4>JWT مربوط ببصمة الجهاز</h4><p>الرمز المسروق لا يعمل على جهاز آخر.</p></div>
<div class="row-item"><h4>تشفير AES-256 للبيانات الحساسة</h4><p>أسماء، هواتف، هويات، لوحات — مشفّرة حتى لو تسربت القاعدة.</p></div>
<div class="row-item"><h4>Rate Limiting مخصص لكل نوع طلب</h4><p>حدود أشد للشكاوى لأن كل شكوى تستدعي Gemini + واتساب.</p></div>
<div class="row-item"><h4>رمز سعر موقّع (7 دقائق)</h4><p>يغلق ثغرة التلاعب بالسعر بين العرض والتأكيد.</p></div>
<div class="row-item"><h4>تسوية أجرة آمنة</h4><p>إعادة حساب من الخادم بسقوف (≤1.6× السعر، ≤1.5× المسافة) قبل التحويل للمحفظة.</p></div>
<div class="row-item"><h4>مطابقة الوجهة (Destination Matching)</h4><p>سائق متجه للبيت يأخذ أولوية الطلبات القريبة من وجهته، والراكب يخصم 14%.</p></div>
<div class="row-item"><h4>تسعير ديناميكي متكامل</h4><p>ذروة حسب العرض/الطلب لكل قطعة جغرافية، مطابقة ذروة المنافسين، مضاعفات رمضان/الأعياد، وخصم مسافات طويلة.</p></div>
</div>
<div class="alert good"><span class="tag">وثيقة موجودة فعلاً</span>
<p>يوجد تدقيق أمني داخلي بأسلوب اختبار اختراق يصنّف النتائج من حرج لمنخفض — نقاط قوة موثقة (لا SQL Injection، AES-256) مقابل بنود مفتوحة (Rate limiting معطّل بأماكن، ملفات اختبار في الإنتاج، تشفير CBC بـ IV ثابت). راجع <code>docs/08_security</code>.</p>
</div>
</section>
<!-- 06 MAPS -->
<section id="maps">
<div class="sec-head">
<span class="eyebrow">06</span>
<h2>الخرائط والموقع الجغرافي</h2>
<p class="thesis">القرار الأهم: لا اعتماد على Google Maps للتتبع الحي أو المطابقة — خادما WebSocket خاصان وفهرسة Redis جغرافية، بتحكم كامل وتوفير ضخم.</p>
</div>
<div class="rows">
<div class="row-item"><h4>تتبع حي مُفلتر ومُجمّع</h4><p>موقع السائق كل 1–3 ثوانٍ، يُرسل فقط عند تحرك حقيقي (10م)، يُجمَّع ويُكتب لـ Redis كل نصف ثانية دفعة واحدة ثم يُدفع للراكب.</p></div>
<div class="row-item"><h4>أقرب سائق عبر GEORADIUS</h4><p>بحث نصف قطر على آلاف السائقين لحظياً، مرتب بالتقييم — لا توجد خدمة جاهزة تقدم هذا.</p></div>
<div class="row-item"><h4>استعلام مخصص لكل فئة</h4><p>Balash يختار أقدم السيارات فعلياً، وElectric يفلتر وقود «كهربائي» — منطق عمل مستحيل بخدمة عامة.</p></div>
<div class="row-item"><h4>خرائط حرارية + تتبع أسطول حي</h4><p>«رؤية إلهية» لفريق العمليات دون شراء أداة BI.</p></div>
<div class="row-item"><h4>تجزئة جغرافية (Geo-Sharding)</h4><p>كل نطاق إحداثيات يمكن ربطه بخادم مختلف — توسع مدينة-بمدينة دون إعادة هندسة.</p></div>
</div>
</section>
<!-- 07 TRANSIT -->
<section id="transit">
<div class="sec-head">
<span class="eyebrow">07</span>
<h2>مواصلاتي — النقل الجماعي للجامعات والمؤسسات</h2>
<p class="thesis">خط الأعمال الثاني: رقمنة أساطيل الجامعات والمدارس والشركات مجاناً (SaaS)، مقابل استحواذ سيرو على المستخدمين وتحويلهم لركاب مدفوعين — بعزل تقني كامل عن نظام المشاوير (قاعدة <code>siro_transit</code> مستقلة + سوكيتات خاصة).</p>
</div>
<div class="actors">
<div class="actor"><span class="ic">🏛️</span><b>فريق سيرو</b><span>ينشئ المؤسسة، يضيف مشرفيها، ويعتمد الخطوط المرسومة قبل ظهورها للطلاب</span></div>
<div class="actor"><span class="ic">🧑‍💼</span><b>مشرف المؤسسة</b><span>لوحة ويب: باصات، سائقون، رسم الخطوط والمحطات، الجداول، ورفع كشف الطلاب CSV</span></div>
<div class="actor"><span class="ic">🚌</span><b>سائق الباص</b><span>تطبيق السائق بوضع Bus Mode مبسّط: زر ابدأ/أنهِ فقط، والمحطات تمرّ آلياً بالـ Geofencing</span></div>
<div class="actor"><span class="ic">🎓</span><b>الطالب</b><span>تفعيل فوري بالرقم الجامعي، تتبع حي للباص، وإشعارات اقتراب ذكية</span></div>
</div>
<div class="subhead">كيف تسير رحلة الباص</div>
<div class="flow">
<div class="step"><h4>الإعداد <span class="t">مرة واحدة</span></h4><p>المشرف يرسم المسار على خريطة تفاعلية ويحدد المحطات بمحيط جغرافي (150م افتراضياً)، والخط يبقى «مسودة» حتى يعتمده فريق سيرو، ثم تُحدد أوقات الانطلاق وأيام العمل.</p></div>
<div class="step"><h4>بدء الرحلة <span class="t">زر واحد</span></h4><p>السائق يضغط «ابدأ الرحلة» ويبدأ بث موقعه عبر السوكيت كل عدة ثوانٍ — مع إشعار انطلاق للمشتركين.</p></div>
<div class="step"><h4>المرور بالمحطات <span class="t">آلي بالكامل</span></h4><p>دخول الباص محيط أي محطة يحدّث شريط التقدم تلقائياً دون تدخل السائق، ويُرسل «الباص يبعد محطة واحدة عنك» للطلاب التاليين. زر «تأخير» متاح عند الزحام.</p></div>
<div class="step"><h4>التتبع الحي للطالب <span class="t">Socket</span></h4><p>الطالب يرى الباص يتحرك على المسار لحظياً — ولا يُسمح له بالانضمام لغرفة البث إلا بعضوية نشطة في المؤسسة المالكة للخط.</p></div>
<div class="step"><h4>نقطة التحويل الربحية <span class="t">جوهر النموذج</span></h4><p>إذا فات الطالبَ الباصُ يظهر زر بارز: «فاتك الباص؟ اطلب سيارة الآن» — يحوّله لرحلة مدفوعة عادية من سيرو. هذا هو العائد الأساسي لخط الأعمال كله.</p></div>
</div>
<div class="duo" style="margin-top:14px;">
<div class="panel"><h4>ضوابط أمنية مبنية</h4><ul>
<li>حماية IDOR: لا يستطيع سائق إنهاء رحلة سائق آخر.</li>
<li>تشفير أرقام الهواتف والأرقام الجامعية في القاعدة.</li>
<li>Rate Limiting على OTP وتسجيل الدخول.</li>
<li>تفعيل الطالب فوري بمطابقة الكشف — دون OTP إضافي لتوفير التكلفة.</li>
</ul></div>
<div class="panel"><h4>نمطان تشغيليان</h4><ul>
<li><b>أسطول المؤسسة:</b> الجامعة تملك باصاتها وسائقيها.</li>
<li><b>الناقل المتعاقد:</b> شركة نقل طرف ثالث تشغّل خطوط مؤسسة بلا أسطول، بنفس برمجيات التتبع.</li>
<li>سائق الباص منفصل تماماً عن كابتن المشاوير ولا يتلقى طلبات عادية.</li>
</ul></div>
</div>
<div class="alert warn"><span class="tag">فجوات معروفة قيد المعالجة</span>
<p>المراجعة الفنية الكاملة في <code>docs/05_transit_mawasalati</code> توثّق بنوداً مفتوحة: نواقص في ربط السائق، واعتماد الخطوط، وحالات IDOR إضافية — يجب إغلاقها قبل أول إطلاق جامعي واسع.</p>
</div>
</section>
<!-- 08 BOTS -->
<section id="bots">
<div class="sec-head">
<span class="eyebrow">08</span>
<h2>البوتات والذكاء الاصطناعي التسويقي</h2>
<p class="thesis">منظومة مغلقة: بوت يسحب أسعار المنافسين من تطبيقاتهم ← محرك يفكّك معادلاتهم ← إعادة تسعير آلية ← بوتات سوشيال تصنع «نقاشات» لصالح سيرو. ميزة تنافسية حقيقية، بمخاطر قانونية وسمعية واضحة.</p>
</div>
<div class="rows">
<div class="row-item"><h4>بوت أندرويد يقرأ تطبيقات المنافسين</h4><p>Accessibility Service يفتح كريم/أوبر/يلا-جو/TaxiF/زاكن فعلياً، يدخل نقطتين، ويقرأ السعر من الشاشة.</p></div>
<div class="row-item"><h4>فك معادلة تسعير المنافس</h4><p>انحدار إحصائي يشتق (أساس + لكل كم + لكل دقيقة) ويكشف حتى الحد الأدنى الخفي للأجرة.</p></div>
<div class="row-item"><h4>إعادة تسعير آلية −6.5%</h4><p>كرون جوب يُبقي سيرو أرخص تلقائياً، مع «وضع الظل»: العروض المؤقتة للمنافس تُقابل بكود خصم بدل حرق السعر الأساسي (سقف تغيير 3% وتهدئة 3 أيام).</p></div>
<div class="row-item"><h4>بوتات سوشيال بلهجات محلية</h4><p>حسابات مُدارة بتدوير IP، تعليقات Gemini بلهجة كل بلد، و«دراما حوار» مفتعلة (تشكيك ثم رد داعم) بتأخير عشوائي.</p></div>
</div>
<div class="alert crit"><span class="tag">⚠️ خطر قانوني وسمعي</span>
<p>سحب الأسعار آلياً يخالف غالباً شروط استخدام تطبيقات المنافسين، والحسابات المنسّقة الوهمية تُصنَّف «تلاعباً منسّقاً غير أصيل» يخالف سياسات المنصات صراحة — خطر حظر جماعي وضرر سمعي إذا انكشف. قرار يجب اتخاذه بوعي كامل بالمخاطرة، لا بالعائد فقط.</p>
</div>
</section>
<!-- 09 FINANCE -->
<section id="finance">
<div class="sec-head">
<span class="eyebrow">09</span>
<h2>نبيه، المحفظة، والاستثمار</h2>
<p class="thesis">تصحيح مهم: «نبيه» ليست منصة استثمار — لا فوائد ولا حصص في الكود. هي مزوّد أتمتة خارجي عبر واتساب. الاستثمار الحقيقي في وثائق المستثمرين، مع نقطة تحتاج انتباهاً فورياً.</p>
</div>
<div class="rows">
<div class="row-item"><h4>نبيه فعلياً</h4><p>أتمتة واتساب بالذكاء الاصطناعي: تسجيل سائقين بالمحادثة، استفسارات أرباح، فحص شكاوى بـ Gemini، وتحقق بصري من إيصالات الدفع.</p></div>
<div class="row-item"><h4>محفظة سيرو</h4><p>خدمة منفصلة (268 ملف): MTN، Syriatel Cash، ShamCash، Cliq، PayMob، eCash — مع تحويل فعلي بين محافظ السائقين برسوم للشركة.</p></div>
<div class="row-item"><h4>طلب تمويل موثّق</h4><p>200,000$ مقابل 22% (تقييم ضمني ~909K$) بأربع طبقات إيراد: عمولة، Prime، إعلانات جغرافية، وترخيص خرائط سيرو كبديل أرخص من Google Maps.</p></div>
<div class="row-item"><h4>عقد سوريا المنفصل</h4><p>اتفاقية حصة أرباح 180,000$ لسوريا فقط — سرديتان تمويليتان تحتاجان توحيداً قبل أي عرض رسمي.</p></div>
</div>
<div class="alert crit"><span class="tag">⚠️ تسريب بيانات — إجراء فوري</span>
<p><code>siromove.com/contract.html</code> على النطاق العام يحتوي نص العقد الاستثماري كاملاً مع <b>أرقام هوية/جواز حقيقية</b> لمؤسسَين ومستثمر — متاح لأي زائر. يجب إزالته من الوصول العام أو حمايته بمصادقة فوراً.</p>
</div>
</section>
<!-- 10 LEGACY -->
<section id="legacy">
<div class="sec-head">
<span class="eyebrow">10</span>
<h2>الإرث الرقمي: القيمة الفكرية والمادية</h2>
<p class="thesis">لو حلّ نموذج ذكاء اصطناعي محل الفريق، هل كان يبني هذا من الصفر؟ جزء كبير من الكود: نعم. الجزء الأكثر قيمة: لا — وهذا ما يحدد قيمة المشروع.</p>
</div>
<div class="duo">
<div class="panel can"><h4>✅ ما يُنتجه الذكاء الاصطناعي بسرعة</h4><ul>
<li>شاشات Flutter القياسية والتكاملات الجاهزة (PayMob، Gemini، Firebase).</li>
<li>منطق CRUD الإداري والأمان القياسي (JWT، تشفير، Rate Limiting).</li>
<li>نمط Socket + Redis Geo كتصميم هندسي معروف بالصناعة.</li>
</ul></div>
<div class="panel cannot"><h4>❌ ما لا يُخترع بمجرد Prompt</h4><ul>
<li><b>معادلات تسعير المنافسين الفعلية</b> — أشهر من بيانات سوق حقيقية.</li>
<li><b>القيم المضبوطة تشغيلياً</b> (12 ساعة، 3 إلغاءات، 90 ثانية) — نتاج حوادث وتجربة موثقة.</li>
<li><b>العلاقات المحلية</b>: ترخيص سوريا (قانون 16/2021)، اتفاقيات MTN وSyriatel وCliq، وتوزيع APK خارج المتجر بسبب العقوبات.</li>
<li><b>القاعدة الفعلية</b>: 1,447 سائقاً و2,891 راكباً في 45 يوماً بميزانية محدودة — أصل شبكي لا يُشترى.</li>
</ul></div>
</div>
<div class="alert good" style="margin-top:14px;"><span class="tag">الخلاصة</span>
<p>هذا المشروع مثال حي على الفرق بين «الكود» و«الشركة»: الذكاء الاصطناعي يسرّع كتابة الكود فعلاً، لكنه لا يعوّض الوقت الفعلي والمخاطرة الفعلية والعلاقات الفعلية — وهذه، لا الكود، هي القيمة غير القابلة للنسخ. القيمة المادية الموثقة داخلياً: تقييم ضمني ~909 ألف دولار.</p>
</div>
</section>
<!-- 11 RISKS -->
<section id="risks">
<div class="sec-head">
<span class="eyebrow">11</span>
<h2>المخاطر والفجوات المجمّعة</h2>
<p class="thesis">كل ما يحتاج قراراً أو إجراءً، من الأشد إلحاحاً للأقل.</p>
</div>
<div class="alert crit"><span class="tag">حرج — الآن</span><p>أرقام هوية حقيقية منشورة بلا حماية على <code>siromove.com/contract.html</code> — القسم 09.</p></div>
<div class="alert warn"><span class="tag">قانوني وسمعي</span><p>بوتات سحب الأسعار والتلاعب المنسّق بالسوشيال — القسم 08.</p></div>
<div class="alert warn"><span class="tag">حوكمة تمويل</span><p>سرديتان تمويليتان متضاربتان (180K$ سوريا مقابل 200K$/22% عامة) تحتاجان توحيداً.</p></div>
<div class="alert warn"><span class="tag">تشغيلي</span><p>لا أداة عرض/حل شكوى فعلية، لا Refund، لا SLA — القسم 04. وفجوات مواصلاتي المفتوحة — القسم 07.</p></div>
<div class="alert warn"><span class="tag">أمني</span><p>بنود التدقيق الأمني غير المغلقة: Rate limiting معطّل بأماكن، ملفات اختبار في الإنتاج، تشفير CBC بـ IV ثابت.</p></div>
</section>
<!-- 12 TUTORIAL -->
<section id="tutorial">
<div class="sec-head">
<span class="eyebrow">12</span>
<h2>خطة التوتوريال داخل الموقع — «كيف تستخدم سيرو»</h2>
<p class="thesis">صفحة <code>siromove.com/tutorial</code> بسبع وحدات تشرح كل عملية خطوة بخطوة بلقطات شاشة حقيقية داخل إطار هاتف. المطلوب تصويره: <b class="num">34 لقطة</b> في جلسة واحدة (~ساعتين) على بيئة تجريبية. الخطة التفصيلية بأسماء الشاشات في الكود: <code>docs/02_journeys_and_tutorials/TUTORIAL_PLAN_AR.md</code>.</p>
</div>
<div class="mods">
<div class="mod"><span class="shots">5 لقطات</span><h4>1 · التسجيل</h4>
<ol><li>شاشة البداية بالشعار</li><li>شرائح التعريف</li><li>رقم الهاتف واختيار الدولة</li><li>رمز التحقق OTP</li><li>إكمال الاسم والبدء</li></ol>
<p class="note">الرسالة: رقم هاتف فقط — أقل من دقيقة حتى الخريطة.</p></div>
<div class="mod"><span class="shots">6 لقطات</span><h4>2 · طلب الرحلة</h4>
<ol><li>الخريطة والسيارات القريبة</li><li>البحث عن الوجهة</li><li>دبوس الانطلاق</li><li>الفئات التسع مع شارة التوفير</li><li>كود الخصم</li><li>تأكيد الطلب بالسعر النهائي</li></ol>
<p class="note">الرسالة: السعر نهائي ومحسوب من الخادم — لا مفاجآت.</p></div>
<div class="mod"><span class="shots">4 لقطات</span><h4>3 · الانتظار والمطابقة</h4>
<ol><li>نافذة البحث مع المؤقّت</li><li>اقتراح المفاوض الذكي (بعد 90 ثانية)</li><li>بطاقة الكابتن</li><li>الكابتن في الطريق مع المسار</li></ol></div>
<div class="mod"><span class="shots">5 لقطات</span><h4>4 · أثناء الرحلة والسلامة</h4>
<ol><li>إشعار «الكابتن وصل» ومهلة 5 دقائق</li><li>المسار الأزرق والعداد</li><li>مشاركة الرحلة مع الأهل</li><li>زر SOS وهزّ الهاتف</li><li>المكالمة داخل التطبيق</li></ol></div>
<div class="mod"><span class="shots">3 لقطات</span><h4>5 · الإلغاء</h4>
<ol><li>مكان زر الإلغاء</li><li>اختيار السبب</li><li>التأكيد وسياسة الرسوم</li></ol>
<p class="note">قبل قبول الكابتن: مجاني دائماً. بعد وصوله: قد تُطبَّق رسوم.</p></div>
<div class="mod"><span class="shots">6 لقطات</span><h4>6 · الدفع والتقييم</h4>
<ol><li>الفاتورة النهائية</li><li>قائمة طرق الدفع</li><li>تأكيد الكاش</li><li>المحفظة والشحن بمكافأة</li><li>التقييم والإكرامية</li><li>سجل الرحلات</li></ol></div>
<div class="mod"><span class="shots">5 لقطات</span><h4>7 · مواصلاتي للطلاب</h4>
<ol><li>اختيار الجامعة</li><li>تفعيل الرقم الجامعي</li><li>الخطوط والجداول</li><li>التتبع الحي للباص</li><li>زر «فاتك الباص؟ اطلب سيارة»</li></ol></div>
<div class="mod"><span class="shots">التنفيذ</span><h4>خطوات الإطلاق</h4>
<ol><li>بناء الصفحة بتبويبات RTL بنفس هوية هذا التقرير</li><li>صور Placeholder بأسماء الملفات النهائية حتى تجهز اللقطات</li><li>جلسة تصوير واحدة للـ 34 لقطة بترتيب الوحدات</li><li>لاحقاً: فيديوهات 30–60 ثانية + Coach Marks داخل التطبيق</li></ol></div>
</div>
</section>
<footer class="end">
<span>أُعدّ بفحص مباشر لكود المشروع — لا تخمين ولا محتوى عام.</span>
<span class="num">آخر تحديث 2026-07-14 · Siro Digital Legacy Report</span>
</footer>
</main>
</div>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+253
View File
@@ -0,0 +1,253 @@
import json
units = [
{
"id": 1,
"title": "التسجيل وإنشاء الحساب",
"desc": "التسجيل يحتاج رقم هاتف فقط — لا بريد إلكتروني إجباري ولا بطاقة دفع. أقل من دقيقة من التحميل حتى أول شاشة خريطة.",
"steps": [
{"title": "تحميل التطبيق وفتحه", "desc": "شاشة البداية بشعار Siro", "img": "tutorial/registration/01_splash_screen.png"},
{"title": "شاشات التعريف", "desc": "شريحة الـ Onboarding الأولى", "img": "tutorial/registration/02_onboarding.png"},
{"title": "إدخال رقم الهاتف", "desc": "حقل الهاتف مع اختيار الدولة", "img": "tutorial/registration/03_phone_number.png"},
{"title": "رمز التحقق OTP", "desc": "شاشة إدخال الرمز (يصل واتساب/SMS)", "img": "tutorial/registration/04_otp.png"},
{"title": "إكمال البيانات", "desc": "الاسم + البريد (اختياري) ثم «ابدأ»", "img": "tutorial/registration/05_complete_profile.png"}
]
},
{
"id": 2,
"title": "طلب الرحلة",
"desc": "السعر المعروض نهائي ومحسوب من الخادم — لا مفاجآت عند الدفع (ما لم تتغير الوجهة أو يزد الانتظار).",
"steps": [
{"title": "الخريطة الرئيسية", "desc": "الخريطة مع السيارات القريبة تتحرك", "img": "tutorial/booking/01_map_main.png"},
{"title": "تحديد الوجهة", "desc": "شريط البحث + النتائج", "img": "tutorial/booking/02_search_destination.png"},
{"title": "تأكيد نقطة الانطلاق", "desc": "دبوس الانطلاق قابل للسحب", "img": "tutorial/booking/03_pickup_pin.png"},
{"title": "اختيار فئة السيارة", "desc": "قائمة الفئات التسع مع السعر وشارة التوفير", "img": "tutorial/booking/04_select_car_type.png"},
{"title": "كود الخصم", "desc": "حقل البرومو مطبّق على السعر", "img": "tutorial/booking/05_promo_code.png"},
{"title": "تأكيد الطلب", "desc": "زر «اطلب الآن» مع السعر النهائي", "img": "tutorial/booking/06_confirm_order.png"}
]
},
{
"id": 3,
"title": "الانتظار والمطابقة",
"desc": "متوسط زمن المطابقة أقل من 90 ثانية. إذا لم يقبل أحد، النظام يقترح تعديلاً بسيطاً على السعر بدل إلغاء طلبك.",
"steps": [
{"title": "البحث عن كابتن", "desc": "نافذة البحث مع المؤقّت", "img": "tutorial/matching/01_searching_captain.png"},
{"title": "اقتراح المفاوض الذكي", "desc": "حوار رفع السعر بعد 90 ثانية", "img": "tutorial/matching/02_smart_negotiator.png"},
{"title": "قبول الكابتن", "desc": "بطاقة الكابتن: الاسم، الصورة، التقييم، اللوحة", "img": "tutorial/matching/03_captain_card.png"},
{"title": "الكابتن في الطريق", "desc": "الخريطة مع المسار الأصفر والوقت المتوقع", "img": "tutorial/matching/04_captain_on_way.png"}
]
},
{
"id": 4,
"title": "أثناء الرحلة والسلامة",
"desc": "تتبع حي للرحلة مع خيارات أمان متقدمة واتصال آمن بالكابتن.",
"steps": [
{"title": "وصول الكابتن", "desc": "إشعار «الكابتن وصل» ومهلة انتظار 5 دقائق", "img": "tutorial/ride/01_captain_arrived.png"},
{"title": "بدء الرحلة", "desc": "المسار الأزرق + العداد الحي", "img": "tutorial/ride/02_ride_started.png"},
{"title": "مشاركة الرحلة", "desc": "رابط متابعة لطرف ثالث (للأهل)", "img": "tutorial/ride/03_share_ride.png"},
{"title": "زر الطوارئ SOS", "desc": "زر الطوارئ (وهزّ الهاتف 5 مرات)", "img": "tutorial/ride/04_sos_button.png"},
{"title": "الاتصال بالكابتن", "desc": "شاشة المكالمة داخل التطبيق", "img": "tutorial/ride/05_in_app_call.png"}
]
},
{
"id": 5,
"title": "الإلغاء",
"desc": "الإلغاء قبل القبول مجاني، وبعد الوصول قد تُطبّق رسوم. السائق يواجه إيقافاً بعد 3 إلغاءات.",
"steps": [
{"title": "زر الإلغاء", "desc": "مكان الزر أثناء البحث/الانتظار", "img": "tutorial/cancel/01_cancel_button.png"},
{"title": "اختيار السبب", "desc": "قائمة أسباب الإلغاء", "img": "tutorial/cancel/02_cancel_reason.png"},
{"title": "تأكيد الإلغاء", "desc": "رسالة التأكيد + سياسة الرسوم", "img": "tutorial/cancel/03_cancel_confirm.png"}
]
},
{
"id": 6,
"title": "الدفع والتقييم",
"desc": "دفع مرن مع نقاط مكافأة للمحفظة، وتقييم يعزز جودة الخدمة.",
"steps": [
{"title": "نهاية الرحلة", "desc": "شاشة الفاتورة النهائية", "img": "tutorial/payment/01_ride_finished.png"},
{"title": "طرق الدفع", "desc": "كاش/محفظة/بطاقة ووسائل الدفع المحلية", "img": "tutorial/payment/02_payment_methods.png"},
{"title": "الدفع كاش", "desc": "حوار تأكيد الكاش", "img": "tutorial/payment/03_cash_confirm.png"},
{"title": "الدفع بالمحفظة", "desc": "الخصم من الرصيد وعروض الشحن", "img": "tutorial/payment/04_wallet_pay.png"},
{"title": "تقييم الكابتن", "desc": "النجوم + الإكرامية", "img": "tutorial/payment/05_rate_captain.png"},
{"title": "سجل الرحلات", "desc": "قائمة الرحلات السابقة والفواتير", "img": "tutorial/payment/06_ride_history.png"}
]
},
{
"id": 7,
"title": "مواصلاتي — للطلاب",
"desc": "خدمة تتبع باصات الجامعات مجاناً مع إمكانية تحويل الطالب لرحلة مدفوعة إذا فاته الباص.",
"steps": [
{"title": "اختيار الجامعة", "desc": "تبويب مواصلاتي واختيار الجامعة", "img": "tutorial/transit/01_select_university.png"},
{"title": "تفعيل العضوية", "desc": "إدخال الرقم الجامعي للتفعيل الفوري", "img": "tutorial/transit/02_activate_student_id.png"},
{"title": "استعراض الخطوط", "desc": "قائمة الخطوط المعتمدة وجداولها", "img": "tutorial/transit/03_transit_lines.png"},
{"title": "التتبع الحي", "desc": "الباص يتحرك على المسار والمحطات", "img": "tutorial/transit/04_live_tracking.png"},
{"title": "فاتك الباص؟", "desc": "الزر البارز لطلب سيارة بديلة", "img": "tutorial/transit/05_missed_bus.png"}
]
}
]
html_template = """<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>كيف تستخدم سيرو — التوتوريال الشامل</title>
<style>
:root{
--bg:#F6F7F5; --surface:#FFFFFF; --surface2:#EEF1EE;
--ink:#1A241F; --muted:#5B6862; --faint:#8B968F;
--line:#E1E5E1; --line2:#D2D8D3;
--brand:#0E7A5F; --brand-ink:#0A5945; --brand-soft:#E4F0EB;
--amber:#9A6B12; --amber-soft:#F6EDDA;
--red:#B3362B; --red-soft:#F7E5E2;
--good:#2E7D4F; --good-soft:#E4F1E8;
--sans:"SF Arabic","Segoe UI",system-ui,-apple-system,"Noto Sans Arabic",Tahoma,sans-serif;
--mono:ui-monospace,"SF Mono",Consolas,monospace;
}
@media (prefers-color-scheme: dark){
:root{
--bg:#0F1512; --surface:#161E19; --surface2:#1C2620;
--ink:#E8EDEA; --muted:#9BA8A1; --faint:#6E7B74;
--line:#26302B; --line2:#32403A;
--brand:#3FBF97; --brand-ink:#8FE0C5; --brand-soft:#15342A;
--amber:#E0AE55; --amber-soft:#33290F;
--red:#E07065; --red-soft:#361A16;
--good:#57C287; --good-soft:#14301F;
}
}
body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-size: 16px; line-height: 1.85; }
* { box-sizing: border-box; }
.wrap { max-width: 1060px; margin: 0 auto; padding: 0 22px; }
h1, h2, h3, h4 { margin: 0; color: var(--ink); line-height: 1.35; text-wrap: balance; }
p { margin: 0; }
.hero { padding: 64px 0 36px; border-bottom: 1px solid var(--line); }
.hero .kicker {
display: inline-block; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em;
color: var(--brand-ink); background: var(--brand-soft); border-radius: 99px; padding: 4px 14px;
margin-bottom: 18px;
}
.hero h1 { font-size: clamp(1.7rem, 4.5vw, 2.5rem); font-weight: 800; }
.hero .lede { margin-top: 14px; font-size: 1.05rem; color: var(--muted); max-width: 60ch; }
.hero .meta { margin-top: 16px; font-size: 0.8rem; color: var(--faint); }
.tabs {
display: flex; gap: 8px; overflow-x: auto; padding: 20px 0 10px;
margin-top: 10px; scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab-btn {
background: var(--surface); border: 1px solid var(--line); color: var(--muted);
font-family: var(--sans); font-size: 0.95rem; font-weight: 700; padding: 10px 20px;
border-radius: 99px; cursor: pointer; white-space: nowrap; transition: all 0.2s;
}
.tab-btn:hover { border-color: var(--brand); color: var(--ink); }
.tab-btn.active { background: var(--brand-soft); color: var(--brand-ink); border-color: var(--brand-ink); font-weight: 800; }
.tab-content { display: none; animation: fadeIn 0.3s ease; padding: 30px 0 80px; }
.tab-content.active { display: block; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.sec-head { margin-bottom: 40px; text-align: center; }
.sec-head h2 { font-size: 1.8rem; font-weight: 800; margin-bottom: 12px; }
.sec-head .thesis { color: var(--muted); font-size: 1.1rem; max-width: 66ch; margin: 0 auto; }
.steps-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 40px; margin-top: 20px; }
.step-card {
display: flex; flex-direction: column; gap: 20px; align-items: center;
background: var(--surface); border: 1px solid var(--line); border-radius: 24px; padding: 30px 20px;
}
.step-info { text-align: center; }
.step-num {
display: inline-flex; align-items: center; justify-content: center;
width: 32px; height: 32px; background: var(--brand); color: #fff;
border-radius: 50%; font-size: 1rem; font-weight: 800; margin-bottom: 12px; font-variant-numeric: tabular-nums;
}
.step-info h4 { font-size: 1.1rem; font-weight: 800; margin-bottom: 6px; }
.step-info p { font-size: 0.9rem; color: var(--muted); }
.phone-frame {
width: 260px; height: 540px; border: 12px solid #1a1a1a; border-radius: 36px;
overflow: hidden; position: relative; box-shadow: 0 10px 25px rgba(0,0,0,0.05); background: #f1f3f2;
}
.phone-notch {
position: absolute; top: 0; left: 50%; transform: translateX(-50%);
width: 110px; height: 26px; background: #1a1a1a;
border-bottom-left-radius: 16px; border-bottom-right-radius: 16px; z-index: 2;
}
.phone-screen {
width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
text-align: center; padding: 20px; color: var(--faint); font-family: var(--mono);
font-size: 0.75rem; word-break: break-all; background-color: var(--surface2);
}
</style>
</head>
<body>
<header class="hero"><div class="wrap">
<span class="kicker">خطة التوتوريال — 34 لقطة</span>
<h1>كيف تستخدم سيرو</h1>
<p class="lede">صفحات شرح تفاعلية تشرح للمستخدم الجديد كل عملية خطوة بخطوة، مدعومة بلقطات شاشة حقيقية من التطبيق.</p>
<p class="meta">تم بناء هذه الصفحة حسب التقرير الشامل — في انتظار إدراج اللقطات النهائية</p>
</div></header>
<div class="wrap">
<div class="tabs">
{tabs_html}
</div>
<div class="tab-contents">
{contents_html}
</div>
</div>
<script>
function showTab(id) {
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
document.getElementById('btn-' + id).classList.add('active');
document.getElementById('tab-' + id).classList.add('active');
}
</script>
</body>
</html>
"""
tabs_html = ""
contents_html = ""
for unit in units:
active_class = " active" if unit["id"] == 1 else ""
tabs_html += f'<button id="btn-{unit["id"]}" class="tab-btn{active_class}" onclick="showTab({unit["id"]})">{unit["id"]}. {unit["title"]}</button>\n '
steps_html = ""
for i, step in enumerate(unit["steps"]):
steps_html += f"""
<div class="step-card">
<div class="step-info">
<span class="step-num">{i+1}</span>
<h4>{step['title']}</h4>
<p>{step['desc']}</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">{step['img']}</div>
</div>
</div>"""
contents_html += f"""
<div id="tab-{unit['id']}" class="tab-content{active_class}">
<div class="sec-head">
<h2>الوحدة {unit['id']}: {unit['title']}</h2>
<p class="thesis">{unit['desc']}</p>
</div>
<div class="steps-grid">
{steps_html}
</div>
</div>
"""
final_html = html_template.replace('{tabs_html}', tabs_html).replace('{contents_html}', contents_html)
with open("/Users/hamzaaleghwairyeen/development/App/Siro/siromove.com/tutorial/index.html", "w", encoding="utf-8") as f:
f.write(final_html)
print("Generated HTML successfully.")
+574
View File
@@ -0,0 +1,574 @@
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>كيف تستخدم سيرو — التوتوريال الشامل</title>
<style>
:root{
--bg:#F6F7F5; --surface:#FFFFFF; --surface2:#EEF1EE;
--ink:#1A241F; --muted:#5B6862; --faint:#8B968F;
--line:#E1E5E1; --line2:#D2D8D3;
--brand:#0E7A5F; --brand-ink:#0A5945; --brand-soft:#E4F0EB;
--amber:#9A6B12; --amber-soft:#F6EDDA;
--red:#B3362B; --red-soft:#F7E5E2;
--good:#2E7D4F; --good-soft:#E4F1E8;
--sans:"SF Arabic","Segoe UI",system-ui,-apple-system,"Noto Sans Arabic",Tahoma,sans-serif;
--mono:ui-monospace,"SF Mono",Consolas,monospace;
}
@media (prefers-color-scheme: dark){
:root{
--bg:#0F1512; --surface:#161E19; --surface2:#1C2620;
--ink:#E8EDEA; --muted:#9BA8A1; --faint:#6E7B74;
--line:#26302B; --line2:#32403A;
--brand:#3FBF97; --brand-ink:#8FE0C5; --brand-soft:#15342A;
--amber:#E0AE55; --amber-soft:#33290F;
--red:#E07065; --red-soft:#361A16;
--good:#57C287; --good-soft:#14301F;
}
}
body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-size: 16px; line-height: 1.85; }
* { box-sizing: border-box; }
.wrap { max-width: 1060px; margin: 0 auto; padding: 0 22px; }
h1, h2, h3, h4 { margin: 0; color: var(--ink); line-height: 1.35; text-wrap: balance; }
p { margin: 0; }
.hero { padding: 64px 0 36px; border-bottom: 1px solid var(--line); }
.hero .kicker {
display: inline-block; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em;
color: var(--brand-ink); background: var(--brand-soft); border-radius: 99px; padding: 4px 14px;
margin-bottom: 18px;
}
.hero h1 { font-size: clamp(1.7rem, 4.5vw, 2.5rem); font-weight: 800; }
.hero .lede { margin-top: 14px; font-size: 1.05rem; color: var(--muted); max-width: 60ch; }
.hero .meta { margin-top: 16px; font-size: 0.8rem; color: var(--faint); }
.tabs {
display: flex; gap: 8px; overflow-x: auto; padding: 20px 0 10px;
margin-top: 10px; scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab-btn {
background: var(--surface); border: 1px solid var(--line); color: var(--muted);
font-family: var(--sans); font-size: 0.95rem; font-weight: 700; padding: 10px 20px;
border-radius: 99px; cursor: pointer; white-space: nowrap; transition: all 0.2s;
}
.tab-btn:hover { border-color: var(--brand); color: var(--ink); }
.tab-btn.active { background: var(--brand-soft); color: var(--brand-ink); border-color: var(--brand-ink); font-weight: 800; }
.tab-content { display: none; animation: fadeIn 0.3s ease; padding: 30px 0 80px; }
.tab-content.active { display: block; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.sec-head { margin-bottom: 40px; text-align: center; }
.sec-head h2 { font-size: 1.8rem; font-weight: 800; margin-bottom: 12px; }
.sec-head .thesis { color: var(--muted); font-size: 1.1rem; max-width: 66ch; margin: 0 auto; }
.steps-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 40px; margin-top: 20px; }
.step-card {
display: flex; flex-direction: column; gap: 20px; align-items: center;
background: var(--surface); border: 1px solid var(--line); border-radius: 24px; padding: 30px 20px;
}
.step-info { text-align: center; }
.step-num {
display: inline-flex; align-items: center; justify-content: center;
width: 32px; height: 32px; background: var(--brand); color: #fff;
border-radius: 50%; font-size: 1rem; font-weight: 800; margin-bottom: 12px; font-variant-numeric: tabular-nums;
}
.step-info h4 { font-size: 1.1rem; font-weight: 800; margin-bottom: 6px; }
.step-info p { font-size: 0.9rem; color: var(--muted); }
.phone-frame {
width: 260px; height: 540px; border: 12px solid #1a1a1a; border-radius: 36px;
overflow: hidden; position: relative; box-shadow: 0 10px 25px rgba(0,0,0,0.05); background: #f1f3f2;
}
.phone-notch {
position: absolute; top: 0; left: 50%; transform: translateX(-50%);
width: 110px; height: 26px; background: #1a1a1a;
border-bottom-left-radius: 16px; border-bottom-right-radius: 16px; z-index: 2;
}
.phone-screen {
width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
text-align: center; padding: 20px; color: var(--faint); font-family: var(--mono);
font-size: 0.75rem; word-break: break-all; background-color: var(--surface2);
}
</style>
</head>
<body>
<header class="hero"><div class="wrap">
<span class="kicker">خطة التوتوريال — 34 لقطة</span>
<h1>كيف تستخدم سيرو</h1>
<p class="lede">صفحات شرح تفاعلية تشرح للمستخدم الجديد كل عملية خطوة بخطوة، مدعومة بلقطات شاشة حقيقية من التطبيق.</p>
<p class="meta">تم بناء هذه الصفحة حسب التقرير الشامل — في انتظار إدراج اللقطات النهائية</p>
</div></header>
<div class="wrap">
<div class="tabs">
<button id="btn-1" class="tab-btn active" onclick="showTab(1)">1. التسجيل وإنشاء الحساب</button>
<button id="btn-2" class="tab-btn" onclick="showTab(2)">2. طلب الرحلة</button>
<button id="btn-3" class="tab-btn" onclick="showTab(3)">3. الانتظار والمطابقة</button>
<button id="btn-4" class="tab-btn" onclick="showTab(4)">4. أثناء الرحلة والسلامة</button>
<button id="btn-5" class="tab-btn" onclick="showTab(5)">5. الإلغاء</button>
<button id="btn-6" class="tab-btn" onclick="showTab(6)">6. الدفع والتقييم</button>
<button id="btn-7" class="tab-btn" onclick="showTab(7)">7. مواصلاتي — للطلاب</button>
</div>
<div class="tab-contents">
<div id="tab-1" class="tab-content active">
<div class="sec-head">
<h2>الوحدة 1: التسجيل وإنشاء الحساب</h2>
<p class="thesis">التسجيل يحتاج رقم هاتف فقط — لا بريد إلكتروني إجباري ولا بطاقة دفع. أقل من دقيقة من التحميل حتى أول شاشة خريطة.</p>
</div>
<div class="steps-grid">
<div class="step-card">
<div class="step-info">
<span class="step-num">1</span>
<h4>تحميل التطبيق وفتحه</h4>
<p>شاشة البداية بشعار Siro</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/registration/01_splash_screen.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">2</span>
<h4>شاشات التعريف</h4>
<p>شريحة الـ Onboarding الأولى</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/registration/02_onboarding.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">3</span>
<h4>إدخال رقم الهاتف</h4>
<p>حقل الهاتف مع اختيار الدولة</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/registration/03_phone_number.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">4</span>
<h4>رمز التحقق OTP</h4>
<p>شاشة إدخال الرمز (يصل واتساب/SMS)</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/registration/04_otp.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">5</span>
<h4>إكمال البيانات</h4>
<p>الاسم + البريد (اختياري) ثم «ابدأ»</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/registration/05_complete_profile.png</div>
</div>
</div>
</div>
</div>
<div id="tab-2" class="tab-content">
<div class="sec-head">
<h2>الوحدة 2: طلب الرحلة</h2>
<p class="thesis">السعر المعروض نهائي ومحسوب من الخادم — لا مفاجآت عند الدفع (ما لم تتغير الوجهة أو يزد الانتظار).</p>
</div>
<div class="steps-grid">
<div class="step-card">
<div class="step-info">
<span class="step-num">1</span>
<h4>الخريطة الرئيسية</h4>
<p>الخريطة مع السيارات القريبة تتحرك</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/booking/01_map_main.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">2</span>
<h4>تحديد الوجهة</h4>
<p>شريط البحث + النتائج</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/booking/02_search_destination.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">3</span>
<h4>تأكيد نقطة الانطلاق</h4>
<p>دبوس الانطلاق قابل للسحب</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/booking/03_pickup_pin.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">4</span>
<h4>اختيار فئة السيارة</h4>
<p>قائمة الفئات التسع مع السعر وشارة التوفير</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/booking/04_select_car_type.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">5</span>
<h4>كود الخصم</h4>
<p>حقل البرومو مطبّق على السعر</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/booking/05_promo_code.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">6</span>
<h4>تأكيد الطلب</h4>
<p>زر «اطلب الآن» مع السعر النهائي</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/booking/06_confirm_order.png</div>
</div>
</div>
</div>
</div>
<div id="tab-3" class="tab-content">
<div class="sec-head">
<h2>الوحدة 3: الانتظار والمطابقة</h2>
<p class="thesis">متوسط زمن المطابقة أقل من 90 ثانية. إذا لم يقبل أحد، النظام يقترح تعديلاً بسيطاً على السعر بدل إلغاء طلبك.</p>
</div>
<div class="steps-grid">
<div class="step-card">
<div class="step-info">
<span class="step-num">1</span>
<h4>البحث عن كابتن</h4>
<p>نافذة البحث مع المؤقّت</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/matching/01_searching_captain.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">2</span>
<h4>اقتراح المفاوض الذكي</h4>
<p>حوار رفع السعر بعد 90 ثانية</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/matching/02_smart_negotiator.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">3</span>
<h4>قبول الكابتن</h4>
<p>بطاقة الكابتن: الاسم، الصورة، التقييم، اللوحة</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/matching/03_captain_card.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">4</span>
<h4>الكابتن في الطريق</h4>
<p>الخريطة مع المسار الأصفر والوقت المتوقع</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/matching/04_captain_on_way.png</div>
</div>
</div>
</div>
</div>
<div id="tab-4" class="tab-content">
<div class="sec-head">
<h2>الوحدة 4: أثناء الرحلة والسلامة</h2>
<p class="thesis">تتبع حي للرحلة مع خيارات أمان متقدمة واتصال آمن بالكابتن.</p>
</div>
<div class="steps-grid">
<div class="step-card">
<div class="step-info">
<span class="step-num">1</span>
<h4>وصول الكابتن</h4>
<p>إشعار «الكابتن وصل» ومهلة انتظار 5 دقائق</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/ride/01_captain_arrived.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">2</span>
<h4>بدء الرحلة</h4>
<p>المسار الأزرق + العداد الحي</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/ride/02_ride_started.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">3</span>
<h4>مشاركة الرحلة</h4>
<p>رابط متابعة لطرف ثالث (للأهل)</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/ride/03_share_ride.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">4</span>
<h4>زر الطوارئ SOS</h4>
<p>زر الطوارئ (وهزّ الهاتف 5 مرات)</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/ride/04_sos_button.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">5</span>
<h4>الاتصال بالكابتن</h4>
<p>شاشة المكالمة داخل التطبيق</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/ride/05_in_app_call.png</div>
</div>
</div>
</div>
</div>
<div id="tab-5" class="tab-content">
<div class="sec-head">
<h2>الوحدة 5: الإلغاء</h2>
<p class="thesis">الإلغاء قبل القبول مجاني، وبعد الوصول قد تُطبّق رسوم. السائق يواجه إيقافاً بعد 3 إلغاءات.</p>
</div>
<div class="steps-grid">
<div class="step-card">
<div class="step-info">
<span class="step-num">1</span>
<h4>زر الإلغاء</h4>
<p>مكان الزر أثناء البحث/الانتظار</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/cancel/01_cancel_button.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">2</span>
<h4>اختيار السبب</h4>
<p>قائمة أسباب الإلغاء</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/cancel/02_cancel_reason.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">3</span>
<h4>تأكيد الإلغاء</h4>
<p>رسالة التأكيد + سياسة الرسوم</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/cancel/03_cancel_confirm.png</div>
</div>
</div>
</div>
</div>
<div id="tab-6" class="tab-content">
<div class="sec-head">
<h2>الوحدة 6: الدفع والتقييم</h2>
<p class="thesis">دفع مرن مع نقاط مكافأة للمحفظة، وتقييم يعزز جودة الخدمة.</p>
</div>
<div class="steps-grid">
<div class="step-card">
<div class="step-info">
<span class="step-num">1</span>
<h4>نهاية الرحلة</h4>
<p>شاشة الفاتورة النهائية</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/payment/01_ride_finished.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">2</span>
<h4>طرق الدفع</h4>
<p>كاش/محفظة/بطاقة ووسائل الدفع المحلية</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/payment/02_payment_methods.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">3</span>
<h4>الدفع كاش</h4>
<p>حوار تأكيد الكاش</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/payment/03_cash_confirm.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">4</span>
<h4>الدفع بالمحفظة</h4>
<p>الخصم من الرصيد وعروض الشحن</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/payment/04_wallet_pay.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">5</span>
<h4>تقييم الكابتن</h4>
<p>النجوم + الإكرامية</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/payment/05_rate_captain.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">6</span>
<h4>سجل الرحلات</h4>
<p>قائمة الرحلات السابقة والفواتير</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/payment/06_ride_history.png</div>
</div>
</div>
</div>
</div>
<div id="tab-7" class="tab-content">
<div class="sec-head">
<h2>الوحدة 7: مواصلاتي — للطلاب</h2>
<p class="thesis">خدمة تتبع باصات الجامعات مجاناً مع إمكانية تحويل الطالب لرحلة مدفوعة إذا فاته الباص.</p>
</div>
<div class="steps-grid">
<div class="step-card">
<div class="step-info">
<span class="step-num">1</span>
<h4>اختيار الجامعة</h4>
<p>تبويب مواصلاتي واختيار الجامعة</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/transit/01_select_university.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">2</span>
<h4>تفعيل العضوية</h4>
<p>إدخال الرقم الجامعي للتفعيل الفوري</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/transit/02_activate_student_id.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">3</span>
<h4>استعراض الخطوط</h4>
<p>قائمة الخطوط المعتمدة وجداولها</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/transit/03_transit_lines.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">4</span>
<h4>التتبع الحي</h4>
<p>الباص يتحرك على المسار والمحطات</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/transit/04_live_tracking.png</div>
</div>
</div>
<div class="step-card">
<div class="step-info">
<span class="step-num">5</span>
<h4>فاتك الباص؟</h4>
<p>الزر البارز لطلب سيارة بديلة</p>
</div>
<div class="phone-frame">
<div class="phone-notch"></div>
<div class="phone-screen">tutorial/transit/05_missed_bus.png</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function showTab(id) {
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
document.getElementById('btn-' + id).classList.add('active');
document.getElementById('tab-' + id).classList.add('active');
}
</script>
</body>
</html>