Update Saqel Platform: 2026-09-20 16:38:51
This commit is contained in:
@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
|
|||||||
class ErrorNotebookSummary {
|
class ErrorNotebookSummary {
|
||||||
final int totalErrors;
|
final int totalErrors;
|
||||||
final int masteredCount;
|
final int masteredCount;
|
||||||
|
final int inRemediationCount;
|
||||||
final int pendingCount;
|
final int pendingCount;
|
||||||
final double masteryPercentage;
|
final double masteryPercentage;
|
||||||
final Map<String, int> bySubject;
|
final Map<String, int> bySubject;
|
||||||
@@ -14,6 +15,7 @@ class ErrorNotebookSummary {
|
|||||||
ErrorNotebookSummary({
|
ErrorNotebookSummary({
|
||||||
required this.totalErrors,
|
required this.totalErrors,
|
||||||
required this.masteredCount,
|
required this.masteredCount,
|
||||||
|
this.inRemediationCount = 0,
|
||||||
required this.pendingCount,
|
required this.pendingCount,
|
||||||
required this.masteryPercentage,
|
required this.masteryPercentage,
|
||||||
required this.bySubject,
|
required this.bySubject,
|
||||||
@@ -31,6 +33,7 @@ class ErrorNotebookSummary {
|
|||||||
return ErrorNotebookSummary(
|
return ErrorNotebookSummary(
|
||||||
totalErrors: (json['total_errors'] as num?)?.toInt() ?? 0,
|
totalErrors: (json['total_errors'] as num?)?.toInt() ?? 0,
|
||||||
masteredCount: (json['mastered_count'] as num?)?.toInt() ?? 0,
|
masteredCount: (json['mastered_count'] as num?)?.toInt() ?? 0,
|
||||||
|
inRemediationCount: (json['in_remediation_count'] as num?)?.toInt() ?? 0,
|
||||||
pendingCount: (json['pending_count'] as num?)?.toInt() ?? 0,
|
pendingCount: (json['pending_count'] as num?)?.toInt() ?? 0,
|
||||||
masteryPercentage: (json['mastery_percentage'] as num?)?.toDouble() ?? 0.0,
|
masteryPercentage: (json['mastery_percentage'] as num?)?.toDouble() ?? 0.0,
|
||||||
bySubject: bySub,
|
bySubject: bySub,
|
||||||
@@ -74,6 +77,8 @@ class ErrorNotebookItem {
|
|||||||
});
|
});
|
||||||
|
|
||||||
bool get isMastered => status == 'mastered';
|
bool get isMastered => status == 'mastered';
|
||||||
|
bool get isInRemediation => status == 'in_remediation';
|
||||||
|
bool get isPending => status == 'pending_remediation';
|
||||||
|
|
||||||
String get categoryArabicName {
|
String get categoryArabicName {
|
||||||
switch (errorCategory) {
|
switch (errorCategory) {
|
||||||
|
|||||||
+64
-57
@@ -76,33 +76,7 @@ class _SmartErrorNotebookScreenState extends State<SmartErrorNotebookScreen> {
|
|||||||
errorItem: errorItem,
|
errorItem: errorItem,
|
||||||
repository: _repository,
|
repository: _repository,
|
||||||
onRemediationCompleted: () {
|
onRemediationCompleted: () {
|
||||||
setState(() {
|
_loadNotebookData();
|
||||||
// Optimistically update local item
|
|
||||||
final idx = _items.indexWhere((it) => it.uuid == errorItem.uuid);
|
|
||||||
if (idx != -1) {
|
|
||||||
_items[idx] = _items[idx].copyWith(
|
|
||||||
status: 'mastered',
|
|
||||||
masteredAt: 'الآن',
|
|
||||||
remediationAttemptsCount: _items[idx].remediationAttemptsCount + 1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Update summary
|
|
||||||
if (_summary != null) {
|
|
||||||
final newMastered = _summary!.masteredCount + 1;
|
|
||||||
final newPending = (_summary!.pendingCount - 1).clamp(0, 999);
|
|
||||||
final newRate = _summary!.totalErrors > 0
|
|
||||||
? (newMastered / _summary!.totalErrors) * 100
|
|
||||||
: 100.0;
|
|
||||||
|
|
||||||
_summary = ErrorNotebookSummary(
|
|
||||||
totalErrors: _summary!.totalErrors,
|
|
||||||
masteredCount: newMastered,
|
|
||||||
pendingCount: newPending,
|
|
||||||
masteryPercentage: newRate,
|
|
||||||
bySubject: _summary!.bySubject,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -286,14 +260,21 @@ class _SmartErrorNotebookScreenState extends State<SmartErrorNotebookScreen> {
|
|||||||
color: const Color(0xFF94A3B8),
|
color: const Color(0xFF94A3B8),
|
||||||
icon: CupertinoIcons.scope,
|
icon: CupertinoIcons.scope,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 6),
|
||||||
_metricBox(
|
_metricBox(
|
||||||
title: 'بحاجة إلى علاج',
|
title: 'بحاجة لعلاج',
|
||||||
value: '${summary.pendingCount}',
|
value: '${summary.pendingCount}',
|
||||||
color: const Color(0xFFEF4444),
|
color: const Color(0xFFEF4444),
|
||||||
icon: CupertinoIcons.exclamationmark_triangle_fill,
|
icon: CupertinoIcons.exclamationmark_triangle_fill,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 6),
|
||||||
|
_metricBox(
|
||||||
|
title: 'قيد التثبيت 🌱',
|
||||||
|
value: '${summary.inRemediationCount}',
|
||||||
|
color: const Color(0xFFF59E0B),
|
||||||
|
icon: CupertinoIcons.arrow_2_circlepath_circle_fill,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
_metricBox(
|
_metricBox(
|
||||||
title: 'تم الإتقان 🏆',
|
title: 'تم الإتقان 🏆',
|
||||||
value: '${summary.masteredCount}',
|
value: '${summary.masteredCount}',
|
||||||
@@ -315,7 +296,7 @@ class _SmartErrorNotebookScreenState extends State<SmartErrorNotebookScreen> {
|
|||||||
}) {
|
}) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8),
|
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF0B111E),
|
color: const Color(0xFF0B111E),
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
@@ -323,12 +304,12 @@ class _SmartErrorNotebookScreenState extends State<SmartErrorNotebookScreen> {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Icon(icon, size: 16, color: color),
|
Icon(icon, size: 15, color: color),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
value,
|
value,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 15,
|
||||||
fontWeight: FontWeight.w900,
|
fontWeight: FontWeight.w900,
|
||||||
color: color,
|
color: color,
|
||||||
),
|
),
|
||||||
@@ -336,8 +317,10 @@ class _SmartErrorNotebookScreenState extends State<SmartErrorNotebookScreen> {
|
|||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
style: const TextStyle(fontSize: 10.5, color: Color(0xFF64748B)),
|
style: const TextStyle(fontSize: 10, color: Color(0xFF64748B)),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -346,20 +329,28 @@ class _SmartErrorNotebookScreenState extends State<SmartErrorNotebookScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildStatusTabs() {
|
Widget _buildStatusTabs() {
|
||||||
return Row(
|
return SingleChildScrollView(
|
||||||
children: [
|
scrollDirection: Axis.horizontal,
|
||||||
_statusFilterButton('all', 'جميع الأخطاء (${_items.length})'),
|
child: Row(
|
||||||
const SizedBox(width: 8),
|
children: [
|
||||||
_statusFilterButton(
|
_statusFilterButton('all', 'جميع الفجوات (${_items.length})'),
|
||||||
'pending_remediation',
|
const SizedBox(width: 8),
|
||||||
'بحاجة لعلاج (${_items.where((e) => !e.isMastered).length})',
|
_statusFilterButton(
|
||||||
),
|
'pending_remediation',
|
||||||
const SizedBox(width: 8),
|
'بحاجة لعلاج (${_items.where((e) => e.isPending).length})',
|
||||||
_statusFilterButton(
|
),
|
||||||
'mastered',
|
const SizedBox(width: 8),
|
||||||
'تم إتقانها (${_items.where((e) => e.isMastered).length})',
|
_statusFilterButton(
|
||||||
),
|
'in_remediation',
|
||||||
],
|
'قيد التثبيت 🌱 (${_items.where((e) => e.isInRemediation).length})',
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
_statusFilterButton(
|
||||||
|
'mastered',
|
||||||
|
'تم إتقانها 🏆 (${_items.where((e) => e.isMastered).length})',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,8 +465,11 @@ class _SmartErrorNotebookScreenState extends State<SmartErrorNotebookScreen> {
|
|||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: item.isMastered
|
color: item.isMastered
|
||||||
? const Color(0xFF10B981).withOpacity(0.3)
|
? const Color(0xFF10B981).withOpacity(0.35)
|
||||||
: const Color(0xFFEF4444).withOpacity(0.3),
|
: (item.isInRemediation
|
||||||
|
? const Color(0xFFF59E0B).withOpacity(0.4)
|
||||||
|
: const Color(0xFFEF4444).withOpacity(0.3)),
|
||||||
|
width: item.isInRemediation ? 1.5 : 1.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -654,13 +648,22 @@ class _SmartErrorNotebookScreenState extends State<SmartErrorNotebookScreen> {
|
|||||||
)
|
)
|
||||||
: ElevatedButton.icon(
|
: ElevatedButton.icon(
|
||||||
onPressed: () => _startRemediation(item),
|
onPressed: () => _startRemediation(item),
|
||||||
icon: const Icon(CupertinoIcons.bolt_horizontal_circle_fill, size: 17),
|
icon: Icon(
|
||||||
label: const Text(
|
item.isInRemediation
|
||||||
'بدء المسار العلاجي لسد هذه الفجوة (3 أسئلة تفريدية) 🚀',
|
? CupertinoIcons.arrow_2_circlepath_circle_fill
|
||||||
style: TextStyle(fontSize: 12.5, fontWeight: FontWeight.w800),
|
: CupertinoIcons.bolt_horizontal_circle_fill,
|
||||||
|
size: 17,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
item.isInRemediation
|
||||||
|
? 'بدء اختبار الاسترجاع والتثبيت (تكرار متباعد 7 أيام) 🎯'
|
||||||
|
: 'بدء المسار العلاجي لسد هذه الفجوة (3 أسئلة تفريدية) 🚀',
|
||||||
|
style: const TextStyle(fontSize: 12.5, fontWeight: FontWeight.w800),
|
||||||
),
|
),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: const Color(0xFF0284C7),
|
backgroundColor: item.isInRemediation
|
||||||
|
? const Color(0xFFD97706)
|
||||||
|
: const Color(0xFF0284C7),
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
minimumSize: const Size(double.infinity, 42),
|
minimumSize: const Size(double.infinity, 42),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
@@ -987,7 +990,9 @@ class _RemediationModalSheetState extends State<_RemediationModalSheet> {
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
passed
|
passed
|
||||||
? 'مبارك! تم إتقان المهارة وسد الفجوة بنجاح 🎉'
|
? (widget.errorItem.isInRemediation
|
||||||
|
? 'مبارك! تم اجتياز اختبار التثبيت بنجاح 🎉'
|
||||||
|
: 'تم إنجاز الكويز العلاجي الأولي بنجاح 🌱')
|
||||||
: 'أحسنت المحاولة، راجع الشرح وأعد الاختبار',
|
: 'أحسنت المحاولة، راجع الشرح وأعد الاختبار',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 17,
|
fontSize: 17,
|
||||||
@@ -999,7 +1004,9 @@ class _RemediationModalSheetState extends State<_RemediationModalSheet> {
|
|||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
passed
|
passed
|
||||||
? 'أجبت عن $_correctAnswersCount من ${_questions.length} أسئلة بشكل سليم. تم ترحيل الخطأ إلى أرشيف المتقنات.'
|
? (widget.errorItem.isInRemediation
|
||||||
|
? 'أجبت عن $_correctAnswersCount من ${_questions.length} أسئلة بشكل سليم. تم تثبيت المفهوم في الذاكرة طويلة المدى وترحيله إلى المتقنات 🏆.'
|
||||||
|
: 'أجبت عن $_correctAnswersCount من ${_questions.length} أسئلة. دخل المفهوم مرحلة التثبيت والتكرار المتباعد (المراجعة بعد 7 أيام لتأكيد الإتقان التام).')
|
||||||
: 'أجبت عن $_correctAnswersCount من ${_questions.length}. حاول مجدداً لضمان إتقان السؤال في الامتحان الوزاري.',
|
: 'أجبت عن $_correctAnswersCount من ${_questions.length}. حاول مجدداً لضمان إتقان السؤال في الامتحان الوزاري.',
|
||||||
style: const TextStyle(fontSize: 13, color: Color(0xFF94A3B8)),
|
style: const TextStyle(fontSize: 13, color: Color(0xFF94A3B8)),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ class TeacherStudioState {
|
|||||||
final String? uploadSuccessMessage;
|
final String? uploadSuccessMessage;
|
||||||
final double uploadProgress;
|
final double uploadProgress;
|
||||||
final String uploadPhase;
|
final String uploadPhase;
|
||||||
|
final bool isReplacement;
|
||||||
|
final int versionNumber;
|
||||||
|
|
||||||
const TeacherStudioState({
|
const TeacherStudioState({
|
||||||
required this.lessonTitle,
|
required this.lessonTitle,
|
||||||
@@ -62,6 +64,8 @@ class TeacherStudioState {
|
|||||||
this.uploadSuccessMessage,
|
this.uploadSuccessMessage,
|
||||||
this.uploadProgress = 0.0,
|
this.uploadProgress = 0.0,
|
||||||
this.uploadPhase = 'idle',
|
this.uploadPhase = 'idle',
|
||||||
|
this.isReplacement = false,
|
||||||
|
this.versionNumber = 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
TeacherStudioState copyWith({
|
TeacherStudioState copyWith({
|
||||||
@@ -88,6 +92,8 @@ class TeacherStudioState {
|
|||||||
String? uploadSuccessMessage,
|
String? uploadSuccessMessage,
|
||||||
double? uploadProgress,
|
double? uploadProgress,
|
||||||
String? uploadPhase,
|
String? uploadPhase,
|
||||||
|
bool? isReplacement,
|
||||||
|
int? versionNumber,
|
||||||
}) {
|
}) {
|
||||||
return TeacherStudioState(
|
return TeacherStudioState(
|
||||||
lessonTitle: lessonTitle ?? this.lessonTitle,
|
lessonTitle: lessonTitle ?? this.lessonTitle,
|
||||||
@@ -112,6 +118,8 @@ class TeacherStudioState {
|
|||||||
uploadSuccessMessage: uploadSuccessMessage ?? this.uploadSuccessMessage,
|
uploadSuccessMessage: uploadSuccessMessage ?? this.uploadSuccessMessage,
|
||||||
uploadProgress: uploadProgress ?? this.uploadProgress,
|
uploadProgress: uploadProgress ?? this.uploadProgress,
|
||||||
uploadPhase: uploadPhase ?? this.uploadPhase,
|
uploadPhase: uploadPhase ?? this.uploadPhase,
|
||||||
|
isReplacement: isReplacement ?? this.isReplacement,
|
||||||
|
versionNumber: versionNumber ?? this.versionNumber,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,6 +367,12 @@ class TeacherStudioCubit extends Cubit<TeacherStudioState> {
|
|||||||
));
|
));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
final isReplacement = preflight['replacement'] == true;
|
||||||
|
final versionNum = (preflight['version_number'] as num?)?.toInt() ?? 1;
|
||||||
|
emit(state.copyWith(
|
||||||
|
isReplacement: isReplacement,
|
||||||
|
versionNumber: versionNum,
|
||||||
|
));
|
||||||
final videoVersionId = preflight['video_version_id']?.toString();
|
final videoVersionId = preflight['video_version_id']?.toString();
|
||||||
if (videoVersionId == null || videoVersionId.isEmpty) {
|
if (videoVersionId == null || videoVersionId.isEmpty) {
|
||||||
throw StateError('لم ينشئ الخادم نسخة فيديو صالحة للرفع.');
|
throw StateError('لم ينشئ الخادم نسخة فيديو صالحة للرفع.');
|
||||||
|
|||||||
@@ -553,6 +553,29 @@ class _TeacherStudioUploadTabState extends State<TeacherStudioUploadTab> {
|
|||||||
minHeight: 8,
|
minHeight: 8,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (state.isReplacement) ...[
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.amber.withOpacity(0.12),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
border: Border.all(color: Colors.amber.withOpacity(0.35)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(CupertinoIcons.arrow_2_circlepath, color: Colors.amber, size: 14),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'نسخة مرشحة للاستبدال (إصدار ${state.versionNumber}) — الحصة المنشورة الحالية تظل متاحة للطلاب حتى اجتياز الفحص.',
|
||||||
|
style: const TextStyle(color: Colors.amber, fontSize: 11, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ class ErrorNotebookController
|
|||||||
$items = Database::select($sql . ' ORDER BY created_at DESC', $params);
|
$items = Database::select($sql . ' ORDER BY created_at DESC', $params);
|
||||||
|
|
||||||
$mastered = count(array_filter($items, fn($item) => ($item['status'] ?? '') === 'mastered'));
|
$mastered = count(array_filter($items, fn($item) => ($item['status'] ?? '') === 'mastered'));
|
||||||
|
$inRemediation = count(array_filter($items, fn($item) => ($item['status'] ?? '') === 'in_remediation'));
|
||||||
|
$pending = count(array_filter($items, fn($item) => ($item['status'] ?? '') === 'pending_remediation'));
|
||||||
$bySubject = [];
|
$bySubject = [];
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
$name = (string)($item['subject_name'] ?? '');
|
$name = (string)($item['subject_name'] ?? '');
|
||||||
@@ -30,7 +32,8 @@ class ErrorNotebookController
|
|||||||
'summary' => [
|
'summary' => [
|
||||||
'total_errors' => $total,
|
'total_errors' => $total,
|
||||||
'mastered_count' => $mastered,
|
'mastered_count' => $mastered,
|
||||||
'pending_count' => $total - $mastered,
|
'in_remediation_count' => $inRemediation,
|
||||||
|
'pending_count' => $pending,
|
||||||
'mastery_percentage' => $total ? round(($mastered / $total) * 100, 1) : 0.0,
|
'mastery_percentage' => $total ? round(($mastered / $total) * 100, 1) : 0.0,
|
||||||
'by_subject' => $bySubject,
|
'by_subject' => $bySubject,
|
||||||
],
|
],
|
||||||
@@ -146,12 +149,18 @@ class ErrorNotebookController
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark error as mastered upon successful completion of remedial drill
|
$isRetentionPhase = ($error['status'] === 'in_remediation');
|
||||||
|
$nextStatus = $isRetentionPhase ? 'mastered' : 'in_remediation';
|
||||||
|
|
||||||
|
// Stage 1: Initial Remedial Drill passed -> enters Spaced Repetition (in_remediation)
|
||||||
|
// Stage 2: Spaced Repetition Retention Challenge passed -> enters permanently Mastered
|
||||||
Database::query(
|
Database::query(
|
||||||
"UPDATE student_error_notebook
|
"UPDATE student_error_notebook
|
||||||
SET status = 'mastered', mastered_at = NOW(), remediation_attempts_count = remediation_attempts_count + 1
|
SET status = ?,
|
||||||
|
mastered_at = IF(? = 'mastered', NOW(), mastered_at),
|
||||||
|
remediation_attempts_count = remediation_attempts_count + 1
|
||||||
WHERE id = ?",
|
WHERE id = ?",
|
||||||
[(int)$error['id']]
|
[$nextStatus, $nextStatus, (int)$error['id']]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update student mastery analytics and readiness
|
// Update student mastery analytics and readiness
|
||||||
@@ -160,8 +169,10 @@ class ErrorNotebookController
|
|||||||
[$studentId]
|
[$studentId]
|
||||||
);
|
);
|
||||||
if ($currentMastery) {
|
if ($currentMastery) {
|
||||||
$newReadiness = min(100.0, (float)$currentMastery['tawjihi_readiness_score'] + 1.2);
|
$readinessGain = $isRetentionPhase ? 1.5 : 0.6;
|
||||||
$newMastery = min(100.0, (float)$currentMastery['mastery_percentage'] + 1.0);
|
$masteryGain = $isRetentionPhase ? 1.2 : 0.5;
|
||||||
|
$newReadiness = min(100.0, (float)$currentMastery['tawjihi_readiness_score'] + $readinessGain);
|
||||||
|
$newMastery = min(100.0, (float)$currentMastery['mastery_percentage'] + $masteryGain);
|
||||||
Database::query(
|
Database::query(
|
||||||
"UPDATE student_mastery_analytics
|
"UPDATE student_mastery_analytics
|
||||||
SET tawjihi_readiness_score = ?, mastery_percentage = ?, updated_at = NOW()
|
SET tawjihi_readiness_score = ?, mastery_percentage = ?, updated_at = NOW()
|
||||||
@@ -170,11 +181,23 @@ class ErrorNotebookController
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json([
|
if ($isRetentionPhase) {
|
||||||
'status' => 'success',
|
$response->json([
|
||||||
'mastered' => true,
|
'status' => 'success',
|
||||||
'message' => 'تم اعتماد الشفاء المعرفي للفجوة بنجاح وتحديث مؤشر الجاهزية الأكاديمية.',
|
'mastered' => true,
|
||||||
]);
|
'is_retention_verified' => true,
|
||||||
|
'new_status' => 'mastered',
|
||||||
|
'message' => 'تم اجتياز اختبار الاسترجاع والتثبيت بنجاح تام! اعتُمد المفهوم كمتقن في الذاكرة طويلة المدى.',
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$response->json([
|
||||||
|
'status' => 'success',
|
||||||
|
'mastered' => false,
|
||||||
|
'is_retention_verified' => false,
|
||||||
|
'new_status' => 'in_remediation',
|
||||||
|
'message' => 'تم اجتياز الكويز العلاجي الأولي بنجاح! انتقل المفهوم إلى مرحلة التثبيت والتكرار المتباعد (المراجعة بعد 7 أيام لتأكيد الإتقان التام ومنع النسيان).',
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,718 +6,12 @@ class LandingPage
|
|||||||
{
|
{
|
||||||
public static function render(): string
|
public static function render(): string
|
||||||
{
|
{
|
||||||
return <<<'HTML'
|
// The public landing route and PHP homepage share one source.
|
||||||
<!DOCTYPE html>
|
$page = file_get_contents(dirname(__DIR__, 2) . '/public/landing/index.html');
|
||||||
<html lang="ar" dir="rtl">
|
if ($page === false) {
|
||||||
<head>
|
throw new \RuntimeException('The landing page template could not be loaded.');
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>منصة صَقِل التعليمية — الجيل الثاني للتمكين الأكاديمي والتوجيهي</title>
|
|
||||||
<link rel="icon" type="image/jpeg" href="/assets/images/saqel_logo.jpg">
|
|
||||||
<link rel="apple-touch-icon" href="/assets/images/saqel_logo.jpg">
|
|
||||||
|
|
||||||
<!-- Apple SF Pro & Alexandria Arabic Web 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=Alexandria:wght@300;400;500;600;700;800;900&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Apple Official Design System (Cupertino Dark Mode) -->
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--apple-bg: #000000;
|
|
||||||
--apple-surface: #121214;
|
|
||||||
--apple-surface-card: #161617;
|
|
||||||
--apple-surface-hover: #1C1C1E;
|
|
||||||
--apple-border: rgba(255, 255, 255, 0.08);
|
|
||||||
--apple-border-focus: rgba(255, 255, 255, 0.2);
|
|
||||||
--apple-text-white: #F5F5F7;
|
|
||||||
--apple-text-silver: #A1A1A6;
|
|
||||||
--apple-text-muted: #6E6E73;
|
|
||||||
--apple-blue: #0071E3;
|
|
||||||
--apple-blue-hover: #0077ED;
|
|
||||||
--apple-cyan: #00F5D4;
|
|
||||||
--apple-gold: #F59E0B;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
return $page;
|
||||||
box-sizing: border-box;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "SF Pro AR", "SF Pro Display", "SF Pro Text", "SF Arabic", "Alexandria", "Segoe UI", Roboto, sans-serif;
|
|
||||||
letter-spacing: -0.015em;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: var(--apple-bg);
|
|
||||||
color: var(--apple-text-white);
|
|
||||||
min-height: 100vh;
|
|
||||||
overflow-x: hidden;
|
|
||||||
background-image:
|
|
||||||
radial-gradient(circle at 50% 0%, rgba(0, 113, 227, 0.18) 0%, transparent 60%),
|
|
||||||
radial-gradient(circle at 85% 30%, rgba(245, 158, 11, 0.06) 0%, transparent 50%),
|
|
||||||
radial-gradient(circle at 15% 70%, rgba(0, 245, 212, 0.06) 0%, transparent 50%);
|
|
||||||
background-size: 100% 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
max-width: 1180px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0 24px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apple Glass Navigation */
|
|
||||||
header {
|
|
||||||
border-bottom: 1px solid var(--apple-border);
|
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
|
||||||
backdrop-filter: blur(24px) saturate(180%);
|
|
||||||
-webkit-backdrop-filter: blur(24px) saturate(180%);
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
.header-content {
|
|
||||||
height: 64px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.logo-area {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
.logo-img {
|
|
||||||
width: 38px;
|
|
||||||
height: 38px;
|
|
||||||
border-radius: 10px;
|
|
||||||
object-fit: cover;
|
|
||||||
box-shadow: 0 0 16px rgba(0, 245, 212, 0.35);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
||||||
transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
|
||||||
}
|
|
||||||
.logo-area:hover .logo-img {
|
|
||||||
transform: scale(1.06);
|
|
||||||
}
|
|
||||||
.brand-title {
|
|
||||||
font-size: 19px;
|
|
||||||
font-weight: 800;
|
|
||||||
color: #FFFFFF;
|
|
||||||
letter-spacing: -0.03em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-actions {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
.apple-pill-btn {
|
|
||||||
font-size: 12.5px;
|
|
||||||
font-weight: 600;
|
|
||||||
padding: 7px 18px;
|
|
||||||
border-radius: 980px;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
.btn-nav-ghost {
|
|
||||||
color: var(--apple-text-silver);
|
|
||||||
border: 1px solid transparent;
|
|
||||||
}
|
|
||||||
.btn-nav-ghost:hover {
|
|
||||||
color: #FFFFFF;
|
|
||||||
background: rgba(255, 255, 255, 0.08);
|
|
||||||
}
|
|
||||||
.btn-nav-military {
|
|
||||||
background: rgba(245, 158, 11, 0.12);
|
|
||||||
color: #FBBF24;
|
|
||||||
border: 1px solid rgba(245, 158, 11, 0.3);
|
|
||||||
}
|
|
||||||
.btn-nav-military:hover {
|
|
||||||
background: rgba(245, 158, 11, 0.22);
|
|
||||||
transform: scale(1.02);
|
|
||||||
}
|
|
||||||
.btn-nav-primary {
|
|
||||||
background: var(--apple-blue);
|
|
||||||
color: #FFFFFF !important;
|
|
||||||
box-shadow: 0 2px 10px rgba(0, 113, 227, 0.3);
|
|
||||||
}
|
|
||||||
.btn-nav-primary:hover {
|
|
||||||
background: var(--apple-blue-hover);
|
|
||||||
transform: scale(1.02);
|
|
||||||
box-shadow: 0 4px 16px rgba(0, 113, 227, 0.45);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apple Hero Section */
|
|
||||||
.hero-section {
|
|
||||||
padding: 96px 0 64px;
|
|
||||||
text-align: center;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.apple-badge {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
background: rgba(255, 255, 255, 0.06);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
||||||
color: var(--apple-text-silver);
|
|
||||||
padding: 6px 18px;
|
|
||||||
border-radius: 980px;
|
|
||||||
margin-bottom: 28px;
|
|
||||||
backdrop-filter: blur(12px);
|
|
||||||
}
|
|
||||||
.badge-dot {
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: var(--apple-cyan);
|
|
||||||
box-shadow: 0 0 10px var(--apple-cyan);
|
|
||||||
}
|
|
||||||
.hero-title {
|
|
||||||
font-size: clamp(34px, 5.5vw, 60px);
|
|
||||||
font-weight: 800;
|
|
||||||
line-height: 1.15;
|
|
||||||
color: var(--apple-text-white);
|
|
||||||
max-width: 960px;
|
|
||||||
margin: 0 auto 24px;
|
|
||||||
letter-spacing: -0.03em;
|
|
||||||
}
|
|
||||||
.hero-title-gradient {
|
|
||||||
background: linear-gradient(180deg, #FFFFFF 0%, #A1A1A6 100%);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
}
|
|
||||||
.hero-cyan-glow {
|
|
||||||
background: linear-gradient(135deg, #00F5D4 0%, #0071E3 100%);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
}
|
|
||||||
.hero-desc {
|
|
||||||
font-size: clamp(16px, 2vw, 19px);
|
|
||||||
color: var(--apple-text-silver);
|
|
||||||
max-width: 740px;
|
|
||||||
margin: 0 auto 44px;
|
|
||||||
line-height: 1.7;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-cta-group {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 16px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-bottom: 72px;
|
|
||||||
}
|
|
||||||
.apple-main-btn {
|
|
||||||
padding: 14px 34px;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 600;
|
|
||||||
border-radius: 980px;
|
|
||||||
text-decoration: none;
|
|
||||||
background: var(--apple-blue);
|
|
||||||
color: #FFFFFF;
|
|
||||||
box-shadow: 0 6px 24px rgba(0, 113, 227, 0.4);
|
|
||||||
transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
.apple-main-btn:hover {
|
|
||||||
background: var(--apple-blue-hover);
|
|
||||||
transform: scale(1.02);
|
|
||||||
box-shadow: 0 10px 32px rgba(0, 113, 227, 0.55);
|
|
||||||
}
|
|
||||||
.apple-secondary-btn {
|
|
||||||
padding: 14px 28px;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 600;
|
|
||||||
border-radius: 980px;
|
|
||||||
text-decoration: none;
|
|
||||||
background: rgba(255, 255, 255, 0.06);
|
|
||||||
color: var(--apple-text-white);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
||||||
backdrop-filter: blur(12px);
|
|
||||||
transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
|
||||||
}
|
|
||||||
.apple-secondary-btn:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.12);
|
|
||||||
border-color: rgba(255, 255, 255, 0.3);
|
|
||||||
transform: scale(1.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apple Metric Bar */
|
|
||||||
.metrics-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
||||||
gap: 16px;
|
|
||||||
background: var(--apple-surface-card);
|
|
||||||
border: 1px solid var(--apple-border);
|
|
||||||
border-radius: 24px;
|
|
||||||
padding: 28px 36px;
|
|
||||||
margin-bottom: 96px;
|
|
||||||
}
|
|
||||||
.metric-col { text-align: center; }
|
|
||||||
.metric-val {
|
|
||||||
font-size: 38px;
|
|
||||||
font-weight: 800;
|
|
||||||
color: #FFFFFF;
|
|
||||||
display: block;
|
|
||||||
letter-spacing: -0.03em;
|
|
||||||
}
|
|
||||||
.metric-label {
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--apple-text-muted);
|
|
||||||
font-weight: 500;
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bento Grid Showcase */
|
|
||||||
.section-header {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 56px;
|
|
||||||
}
|
|
||||||
.section-tag {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--apple-cyan);
|
|
||||||
background: rgba(0, 245, 212, 0.1);
|
|
||||||
border: 1px solid rgba(0, 245, 212, 0.25);
|
|
||||||
padding: 5px 16px;
|
|
||||||
border-radius: 980px;
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
.section-title {
|
|
||||||
font-size: clamp(28px, 4vw, 42px);
|
|
||||||
font-weight: 800;
|
|
||||||
color: var(--apple-text-white);
|
|
||||||
letter-spacing: -0.025em;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
.section-subtitle {
|
|
||||||
font-size: 16px;
|
|
||||||
color: var(--apple-text-silver);
|
|
||||||
max-width: 660px;
|
|
||||||
margin: 0 auto;
|
|
||||||
line-height: 1.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bento-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
|
||||||
gap: 20px;
|
|
||||||
margin-bottom: 96px;
|
|
||||||
}
|
|
||||||
.bento-card {
|
|
||||||
background: var(--apple-surface-card);
|
|
||||||
border: 1px solid var(--apple-border);
|
|
||||||
border-radius: 28px;
|
|
||||||
padding: 38px;
|
|
||||||
transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.bento-card:hover {
|
|
||||||
transform: translateY(-4px);
|
|
||||||
border-color: var(--apple-border-focus);
|
|
||||||
background: var(--apple-surface-hover);
|
|
||||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
|
|
||||||
}
|
|
||||||
.bento-icon {
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 14px;
|
|
||||||
background: rgba(255, 255, 255, 0.05);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 22px;
|
|
||||||
margin-bottom: 22px;
|
|
||||||
}
|
|
||||||
.bento-title {
|
|
||||||
font-size: 19px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--apple-text-white);
|
|
||||||
margin-bottom: 10px;
|
|
||||||
letter-spacing: -0.02em;
|
|
||||||
}
|
|
||||||
.bento-desc {
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--apple-text-silver);
|
|
||||||
line-height: 1.75;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Institutional Banner */
|
|
||||||
.military-banner {
|
|
||||||
background: linear-gradient(135deg, #121214 0%, #1A1A1E 100%);
|
|
||||||
border: 1px solid rgba(245, 158, 11, 0.35);
|
|
||||||
border-radius: 28px;
|
|
||||||
padding: 48px;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1.3fr 1fr;
|
|
||||||
gap: 40px;
|
|
||||||
align-items: center;
|
|
||||||
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.7);
|
|
||||||
margin-bottom: 96px;
|
|
||||||
}
|
|
||||||
@media (max-width: 880px) {
|
|
||||||
.military-banner { grid-template-columns: 1fr; padding: 32px; gap: 28px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner-pill {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
background: rgba(245, 158, 11, 0.15);
|
|
||||||
border: 1px solid rgba(245, 158, 11, 0.35);
|
|
||||||
color: #FBBF24;
|
|
||||||
padding: 4px 14px;
|
|
||||||
border-radius: 980px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
.banner-title {
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: 800;
|
|
||||||
color: var(--apple-text-white);
|
|
||||||
margin-bottom: 14px;
|
|
||||||
line-height: 1.35;
|
|
||||||
letter-spacing: -0.025em;
|
|
||||||
}
|
|
||||||
.banner-desc {
|
|
||||||
font-size: 15px;
|
|
||||||
color: var(--apple-text-silver);
|
|
||||||
line-height: 1.75;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
.banner-btn {
|
|
||||||
padding: 13px 30px;
|
|
||||||
font-size: 14.5px;
|
|
||||||
font-weight: 600;
|
|
||||||
border-radius: 980px;
|
|
||||||
text-decoration: none;
|
|
||||||
background: linear-gradient(135deg, #F59E0B, #D97706);
|
|
||||||
color: #FFFFFF;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
box-shadow: 0 6px 20px rgba(245, 158, 11, 0.35);
|
|
||||||
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
|
||||||
}
|
|
||||||
.banner-btn:hover {
|
|
||||||
transform: scale(1.02);
|
|
||||||
box-shadow: 0 10px 28px rgba(245, 158, 11, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner-card-box {
|
|
||||||
background: rgba(0, 0, 0, 0.6);
|
|
||||||
border: 1px solid var(--apple-border);
|
|
||||||
border-radius: 20px;
|
|
||||||
padding: 26px;
|
|
||||||
}
|
|
||||||
.banner-stat-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 14px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
.banner-stat-row:last-child { margin-bottom: 0; }
|
|
||||||
.banner-check-icon {
|
|
||||||
width: 26px;
|
|
||||||
height: 26px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: rgba(0, 245, 212, 0.15);
|
|
||||||
color: var(--apple-cyan);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-weight: 800;
|
|
||||||
font-size: 13px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apple Footer */
|
|
||||||
footer {
|
|
||||||
border-top: 1px solid var(--apple-border);
|
|
||||||
background: #000000;
|
|
||||||
padding: 56px 0 28px;
|
|
||||||
color: var(--apple-text-muted);
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
.footer-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 2fr 1fr 1fr;
|
|
||||||
gap: 48px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.footer-grid { grid-template-columns: 1fr; gap: 32px; }
|
|
||||||
}
|
|
||||||
.footer-title {
|
|
||||||
font-size: 13.5px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--apple-text-white);
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
.footer-list {
|
|
||||||
list-style: none;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
.footer-list a {
|
|
||||||
color: var(--apple-text-muted);
|
|
||||||
text-decoration: none;
|
|
||||||
transition: color 0.2s;
|
|
||||||
}
|
|
||||||
.footer-list a:hover { color: var(--apple-text-white); }
|
|
||||||
.footer-bottom {
|
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
|
||||||
padding-top: 24px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<!-- Apple Navigation Bar -->
|
|
||||||
<header>
|
|
||||||
<div class="container">
|
|
||||||
<div class="header-content">
|
|
||||||
<a href="/" class="logo-area">
|
|
||||||
<img src="/assets/images/saqel_logo.jpg" alt="صَقِل" class="logo-img">
|
|
||||||
<span class="brand-title">صَقِل</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<div class="nav-actions">
|
|
||||||
<a href="/military-culture" class="apple-pill-btn btn-nav-military">
|
|
||||||
<span>🇯🇴 خطة الثقافة العسكرية</span>
|
|
||||||
</a>
|
|
||||||
<a href="/guardian" class="apple-pill-btn btn-nav-ghost">بوابة أولياء الأمور</a>
|
|
||||||
<a href="/teacher" class="apple-pill-btn btn-nav-ghost">استوديو المعلمين</a>
|
|
||||||
<a href="/student" class="apple-pill-btn btn-nav-primary">دخول الطلاب 🚀</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- Apple Hero Section -->
|
|
||||||
<section class="hero-section">
|
|
||||||
<div class="container">
|
|
||||||
<div class="apple-badge">
|
|
||||||
<span class="badge-dot"></span>
|
|
||||||
<span>الجيل الثاني لمنصات التمكين الأكاديمي والتوجيهي في الأردن</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1 class="hero-title">
|
|
||||||
لا نكتفي بعرض الفيديوهات.. <br>
|
|
||||||
<span class="hero-title-gradient">نحن نصقل فهم الطالب</span> ونضمن <span class="hero-cyan-glow">جاهزيته للوزاري</span>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p class="hero-desc">
|
|
||||||
أول منظومة تعليمية تفاعلية تعتمد التعلم السقراطي (Socratic Learning)، التثبيت المعرفي التلقائي أثناء المشاهدة، ومؤشر الجاهزية للوزاري المدعوم بالذكاء الاصطناعي.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="hero-cta-group">
|
|
||||||
<a href="/student" class="apple-main-btn">
|
|
||||||
<span>ابدأ رحلة التميز كطالب ←</span>
|
|
||||||
</a>
|
|
||||||
<a href="/teacher" class="apple-secondary-btn">
|
|
||||||
<span>انضم كأستاذ معتمد (استوديو صَقِل) 👨🏫</span>
|
|
||||||
</a>
|
|
||||||
<a href="/military-culture" class="apple-secondary-btn" style="border-color: rgba(245, 158, 11, 0.35); color: #FBBF24;">
|
|
||||||
<span>مبادرة مديرية الثقافة العسكرية 🇯🇴</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Apple Metric Bar -->
|
|
||||||
<div class="metrics-grid">
|
|
||||||
<div class="metric-col">
|
|
||||||
<span class="metric-val">100%</span>
|
|
||||||
<span class="metric-label">حماية محتوى DRM ضد التسريب</span>
|
|
||||||
</div>
|
|
||||||
<div class="metric-col">
|
|
||||||
<span class="metric-val">0ms</span>
|
|
||||||
<span class="metric-label">تأخير في الشات المباشر (Workerman)</span>
|
|
||||||
</div>
|
|
||||||
<div class="metric-col">
|
|
||||||
<span class="metric-val">4 مستويات</span>
|
|
||||||
<span class="metric-label">هرمية الامتحانات والتقييم المعرفي</span>
|
|
||||||
</div>
|
|
||||||
<div class="metric-col">
|
|
||||||
<span class="metric-val">91.4%</span>
|
|
||||||
<span class="metric-label">متوسط إتقان واستيعاب المفاهيم</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Core Pillars Bento Grid -->
|
|
||||||
<section style="padding: 20px 0 60px;">
|
|
||||||
<div class="container">
|
|
||||||
<div class="section-header">
|
|
||||||
<span class="section-tag">الفلسفة التربوية والتقنية</span>
|
|
||||||
<h2 class="section-title">لماذا تُحدث صَقِل فارقاً حقيقياً في علامة الطالب؟</h2>
|
|
||||||
<p class="section-subtitle">
|
|
||||||
المنصات التقليدية تقدم تعليماً سلبياً (مشاهدة بدون قياس). صَقِل تحول المشاهدة إلى اشتباك ذهني إجباري يرسخ المعلومة في الذاكرة طويلة المدى.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bento-grid">
|
|
||||||
<!-- Card 1 -->
|
|
||||||
<div class="bento-card">
|
|
||||||
<div class="bento-icon">🎬</div>
|
|
||||||
<h3 class="bento-title">محرك التثبيت المعرفي السقراطي (Active Recall)</h3>
|
|
||||||
<p class="bento-desc">
|
|
||||||
فحص لحظي ذكي لاستيعاب الطالب أثناء الحصة؛ يُلزم الطالب بالاشتباك الذهني وتأكيد فهم كل مفهوم قبل الانتقال إلى الفكرة التالية لضمان التمكن التام.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 2 -->
|
|
||||||
<div class="bento-card">
|
|
||||||
<div class="bento-icon">🧠</div>
|
|
||||||
<h3 class="bento-title">مؤشر الجاهزية للوزاري (Tawjihi Readiness)</h3>
|
|
||||||
<p class="bento-desc">
|
|
||||||
تحليل تراكمي دقيق لمستوى فهم الطالب في كل مبحث، يرصد نقاط القوة والضعف ويحدد بدقة نسبة الجاهزية لدخول الامتحان الوزاري بتفوق.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 3 -->
|
|
||||||
<div class="bento-card">
|
|
||||||
<div class="bento-icon">⚡</div>
|
|
||||||
<h3 class="bento-title">قناة الإشراف والتواصل المباشر مع المعلمين</h3>
|
|
||||||
<p class="bento-desc">
|
|
||||||
بيئة تفاعلية لحظية تتيح للطالب الاستفسار المباشر من أستاذه ومناقشة المسائل المعقدة دون أي عوائق تقنية أو تأخير.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 4 -->
|
|
||||||
<div class="bento-card">
|
|
||||||
<div class="bento-icon">🔒</div>
|
|
||||||
<h3 class="bento-title">حماية المحتوى والأمان الرقمي (DRM Shield)</h3>
|
|
||||||
<p class="bento-desc">
|
|
||||||
بنية تحتية سيادية مشفرة بالكامل تحمي المواد التعليمية وحقوق المعلمين والمؤسسات من أي تسريب أو تصوير غير مصرح به.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 5 -->
|
|
||||||
<div class="bento-card">
|
|
||||||
<div class="bento-icon">📲</div>
|
|
||||||
<h3 class="bento-title">الدخول الذكي المعتمد (Passwordless Access)</h3>
|
|
||||||
<p class="bento-desc">
|
|
||||||
تجربة وصول فائقة السلاسة والأمان عبر بطاقات التوثيق المعتمدة على الواتساب وبصمة الجهاز الموحدة وفق أعلى معايير الخصوصية.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 6 -->
|
|
||||||
<div class="bento-card">
|
|
||||||
<div class="bento-icon">👨👩👧</div>
|
|
||||||
<h3 class="bento-title">منظومة إشعار ومتابعة أولياء الأمور</h3>
|
|
||||||
<p class="bento-desc">
|
|
||||||
تقارير دورية موجزة تصل لولي الأمر لإبقائه في قلب المسيرة التعليمية ومتابعة تحصيل ابنه وساعات دراسته ومؤشر تفوقه.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- B2G Institutional Banner -->
|
|
||||||
<div class="military-banner">
|
|
||||||
<div>
|
|
||||||
<div class="banner-pill">🇯🇴 مبادرة الشراكة الاستراتيجية والمؤسسية</div>
|
|
||||||
<h2 class="banner-title">حلول مخصصة لمديرية التربية والتعليم والثقافة العسكرية</h2>
|
|
||||||
<p class="banner-desc">
|
|
||||||
نقدم للمديرية نموذجاً متكاملاً لشراء المخرجات والإنتاج بأقل التكاليف التشغيلية، مع توحيد جودة التعليم في مدارس البادية والمحافظات وغرفة عمليات مركزية لمتابعة إنجاز كل طالب.
|
|
||||||
</p>
|
|
||||||
<a href="/military-culture" class="banner-btn">
|
|
||||||
<span>استعرض ملف المبادرة الاستراتيجية الكاملة ←</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="banner-card-box">
|
|
||||||
<div class="banner-stat-row">
|
|
||||||
<div class="banner-check-icon">✓</div>
|
|
||||||
<div>
|
|
||||||
<strong style="color: #FFFFFF; font-size: 14px; display: block;">عدالة تعليمية شاملة</strong>
|
|
||||||
<span style="font-size: 12.5px; color: var(--apple-text-muted);">نفس جودة نخبة المعلمين لجميع أبناء القوات المسلحة في كل المحافظات.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="banner-stat-row">
|
|
||||||
<div class="banner-check-icon">✓</div>
|
|
||||||
<div>
|
|
||||||
<strong style="color: #FFFFFF; font-size: 14px; display: block;">لوحة قيادة مركزية للضباط</strong>
|
|
||||||
<span style="font-size: 12.5px; color: var(--apple-text-muted);">متابعة تحصيل كل مدرسة وشعبة لحظياً بمؤشرات أداء واضحة.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="banner-stat-row">
|
|
||||||
<div class="banner-check-icon">✓</div>
|
|
||||||
<div>
|
|
||||||
<strong style="color: #FFFFFF; font-size: 14px; display: block;">توفير 80% من التكاليف</strong>
|
|
||||||
<span style="font-size: 12.5px; color: var(--apple-text-muted);">إلغاء تكاليف المراكز والتنقل والطباعة مع مخرجات أعلى جودة.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Apple Footer -->
|
|
||||||
<footer>
|
|
||||||
<div class="container">
|
|
||||||
<div class="footer-grid">
|
|
||||||
<div>
|
|
||||||
<div class="logo-area" style="margin-bottom: 14px;">
|
|
||||||
<img src="/assets/images/saqel_logo.jpg" alt="صَقِل" class="logo-img" style="width: 32px; height: 32px;">
|
|
||||||
<span class="brand-title" style="font-size: 18px;">منصة صَقِل</span>
|
|
||||||
</div>
|
|
||||||
<p style="font-size: 13px; line-height: 1.7; max-width: 380px; color: var(--apple-text-muted);">
|
|
||||||
المنظومة الأردنية الرائدة في التمكين الأكاديمي والتعليم السقراطي الذكي لطلبة التوجيهي والمراحل الثانوية.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 class="footer-title">البوابات والخدمات</h4>
|
|
||||||
<ul class="footer-list">
|
|
||||||
<li><a href="/student">بوابة الطالب الذكية</a></li>
|
|
||||||
<li><a href="/guardian">بوابة أولياء الأمور لمتابعة الجاهزية</a></li>
|
|
||||||
<li><a href="/teacher">استوديو المعلمين ونظام الشراكة</a></li>
|
|
||||||
<li><a href="/military-culture">ملف مديرية الثقافة العسكرية</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 class="footer-title">الأمان والخصوصية</h4>
|
|
||||||
<ul class="footer-list">
|
|
||||||
<li><a href="#">حماية المحتوى DRM</a></li>
|
|
||||||
<li><a href="#">السيادة الرقمية وتشفير البيانات</a></li>
|
|
||||||
<li><a href="#">معايير Zero-Trust</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="footer-bottom">
|
|
||||||
<span>جميع الحقوق محفوظة © لمنصة صَقِل التعليمية 2026</span>
|
|
||||||
<span style="color: var(--apple-text-silver);">بنية تحتية سحابية موثوقة • عمان، الأردن 🇯🇴</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
HTML;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,168 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="ar" dir="rtl">
|
<html lang="ar" dir="rtl">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="refresh" content="0; url=/index.html">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>صَقِل</title>
|
<meta name="theme-color" content="#080e20">
|
||||||
|
<meta name="description" content="صَقِل — نعيد التفكير في رحلة التعلّم. رؤية تعليمية تجمع الشرح المناسب، التدريب الهادف والمراجعة، وتبدأ من الصف العاشر.">
|
||||||
|
<title>صَقِل — الفهم يصنع الفرق</title>
|
||||||
|
<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=Alexandria:wght@400;500;600;700;800&family=Manrope:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
:root{--ink:#080e20;--surface:#10182e;--white:#f5f7ff;--muted:#abb6cf;--blue:#507aff;--lime:#d7eea5;--line:rgba(192,210,255,.15);--ease:cubic-bezier(.22,1,.36,1);--font:'Alexandria',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif}
|
||||||
|
*{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:110px}body{margin:0;background:var(--ink);color:var(--white);font-family:var(--font);line-height:1.9;-webkit-font-smoothing:antialiased}button,a{-webkit-tap-highlight-color:transparent}button{font:inherit}a{color:inherit;text-decoration:none}button{cursor:pointer}button:disabled{cursor:default}svg{display:block}::selection{background:#a5bcff;color:var(--ink)}:focus-visible{outline:3px solid #b6ceff;outline-offset:6px}h1,h2,h3,p{margin:0}h1,h2,h3{font-weight:600}p{color:var(--muted)}.wrap{width:min(1240px,calc(100% - 96px));margin-inline:auto}.eyebrow{font-size:11px;letter-spacing:.04em;display:flex;align-items:center;gap:10px;color:var(--muted)}.eyebrow::before{content:'';width:21px;height:1px;background:currentColor}.latin{font-family:'Manrope',sans-serif;direction:ltr}.pill{display:inline-flex;align-items:center;gap:9px;border:1px solid var(--line);border-radius:99px;padding:7px 13px;font-size:10px;color:#c5d0e7}.dot{width:6px;height:6px;border-radius:50%;background:var(--lime);box-shadow:0 0 15px #d7eea555}.btn{display:inline-flex;justify-content:center;align-items:center;gap:26px;border:1px solid transparent;border-radius:12px;padding:14px 23px;font-size:12px;font-weight:500;transition:transform .3s var(--ease),background .3s,box-shadow .3s;min-height:50px}.btn:hover{transform:translateY(-3px)}.btn-primary{background:var(--blue);color:white;box-shadow:0 6px 28px #365ffb24}.btn-primary:hover{background:#668aff;box-shadow:0 10px 35px #365ffb55}.btn-outline{border-color:var(--line);background:#ffffff04}.btn-outline:hover{background:#ffffff0c}.arrow{font-family:Arial,sans-serif;font-size:23px;line-height:1}.skip{position:fixed;top:-90px;right:20px;z-index:99;background:white;color:var(--ink);padding:10px 20px}.skip:focus{top:10px}.scroll-progress{position:fixed;top:0;right:0;height:2px;width:100%;background:var(--blue);transform:scaleX(0);transform-origin:right;z-index:90}
|
||||||
|
.header{position:sticky;top:0;z-index:40;background:rgba(8,14,32,.86);backdrop-filter:blur(22px);border-bottom:1px solid var(--line)}.nav{height:88px;display:flex;align-items:center;justify-content:space-between;gap:32px}.brand{display:flex;align-items:center;gap:12px}.brand-symbol{width:36px;height:42px;color:#91acff}.brand-name{font-size:29px;font-weight:700;line-height:1.2}.brand-sub{font-family:'Manrope',sans-serif;font-size:8px;letter-spacing:4px;color:#9caaca;display:block;margin-top:5px}.nav-links{display:flex;align-items:center;gap:30px;font-size:11px;color:#b8c3db}.nav-links a:hover{color:white}.nav-end{display:flex;align-items:center;gap:13px}.nav-end .btn{padding:10px 19px;font-size:10px;min-height:42px}.motion-toggle{border:1px solid var(--line);background:transparent;color:#b8c3db;border-radius:50%;width:35px;height:35px;font-size:12px}.menu-toggle{display:none;background:transparent;border:1px solid var(--line);border-radius:8px;color:white;padding:8px 12px}
|
||||||
|
.hero{position:relative;overflow:hidden;isolation:isolate}.hero::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse at 20% 37%,#233f903c,transparent 52%);z-index:-1}.hero-grid{min-height:710px;display:grid;grid-template-columns:1.05fr 1fr;gap:30px;align-items:center;padding-block:70px 55px}.hero-copy{z-index:2}.hero h1{font-size:clamp(48px,5.15vw,75px);line-height:1.5;letter-spacing:-2px;margin:23px 0 18px}.hero h1 em{font-style:normal;color:#8eacff;position:relative}.hero h1 em::after{content:'';position:absolute;bottom:-6px;right:0;width:100%;height:7px;border-top:2px solid #6c92ff;border-radius:50%;transform:rotate(-3deg)}.hero-desc{font-size:14px;max-width:455px;line-height:2.25}.hero-actions{display:flex;gap:12px;margin-top:30px}.hero-note{font-size:10px;margin-top:22px;color:#8b99b9;display:flex;gap:9px;align-items:center}.hero-note span{width:4px;height:4px;border-radius:50%;background:#8195c1}.hero-bottom{display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--line);padding:22px 0;font-size:10px;color:#8998b8}.hero-bottom .latin{letter-spacing:2px;font-size:9px}.scroll-cue{display:flex;gap:14px;align-items:center}.scroll-cue b{font-size:18px;font-weight:400;color:#c6d5f8}
|
||||||
|
.universe{height:540px;position:relative;direction:ltr;perspective:1000px;--mx:0deg;--my:0deg}.universe-inner{height:100%;position:relative;transform:rotateX(var(--my)) rotateY(var(--mx));transition:transform .7s var(--ease)}.universe-grid{position:absolute;inset:0;background-image:linear-gradient(#7f9eff09 1px,transparent 1px),linear-gradient(90deg,#7f9eff09 1px,transparent 1px);background-size:43px 43px;mask-image:radial-gradient(ellipse,black,transparent 70%)}.orbit{position:absolute;inset:6%;border:1px solid #8aa9ff22;border-radius:50%;transform:rotate(-30deg) scaleY(.64)}.orbit.two{inset:0 7%;transform:rotate(36deg) scaleY(.7);border-style:dashed;border-color:#8aa9ff1c}.orbit.three{inset:14% 0;transform:rotate(95deg) scaleY(.75)}.satellite-track{position:absolute;inset:8%;animation:orbit 32s linear infinite}.satellite-track::after{content:'';position:absolute;top:45%;left:0;width:7px;height:7px;background:#c6d8ff;border-radius:50%;box-shadow:0 0 24px 7px #6a94ff55}.universe-glow{position:absolute;inset:22%;background:#345fdc;filter:blur(65px);opacity:.35}.core{position:absolute;top:50%;left:50%;width:285px;height:310px;transform:translate(-50%,-50%);animation:float 7s ease-in-out infinite}.core svg{width:100%;height:100%;filter:drop-shadow(0 28px 30px #0008)}.concept-tag{position:absolute;z-index:3;border:1px solid #9bbaff30;background:linear-gradient(120deg,#1d2d4ded,#101b33e8);box-shadow:0 12px 35px #0003;backdrop-filter:blur(12px);border-radius:13px;display:flex;align-items:center;gap:12px;padding:13px 17px;direction:rtl;animation:float 7s ease-in-out infinite}.concept-tag b{font-size:12px;font-weight:500}.concept-tag small{display:block;font-size:8px;color:#a3b3d1;margin-top:3px}.tag-icon{width:31px;height:31px;border:1px solid #789cf84d;border-radius:9px;display:grid;place-items:center;color:#abc3ff;font-family:'Manrope',sans-serif;font-size:16px}.tag-one{top:16%;right:0;animation-delay:-1s}.tag-two{top:47%;left:-2%;animation-delay:-3s}.tag-three{bottom:10%;right:5%;animation-delay:-5s}.tag-three .tag-icon{color:var(--lime);border-color:#d7eea53d}.universe-label{position:absolute;left:14%;top:7%;font-size:8px;letter-spacing:2px;color:#8198c6}.universe-coordinate{position:absolute;bottom:4%;left:14%;font-size:9px;letter-spacing:2px;color:#677fae}.spark{position:absolute;width:3px;height:3px;background:#a4bfff;border-radius:50%;box-shadow:0 0 10px #9bb7ff}.spark.a{top:22%;left:22%}.spark.b{bottom:22%;left:15%}.spark.c{top:37%;right:10%}
|
||||||
|
.principles{background:#d7eea5;color:#18251c}.principles .wrap{display:flex;align-items:center;justify-content:space-between;gap:20px;padding-block:24px}.principles p{color:#354635;font-size:11px}.principles strong{font-size:14px;font-weight:500}.principles i{font-size:19px;font-style:normal;opacity:.45}.section{padding-block:108px}.section-head{display:flex;align-items:end;justify-content:space-between;gap:40px;margin-bottom:45px}.section-head h2{font-size:clamp(28px,3.1vw,42px);line-height:1.7;margin-top:13px;letter-spacing:-.8px}.section-head>p{max-width:370px;font-size:12px;line-height:2.2}.section-number{color:#667797;font-family:'Manrope',sans-serif;font-size:11px;letter-spacing:2px}.journey{background:#f3f4f0;color:#18222c}.journey .eyebrow{color:#667368}.journey .section-head p{color:#65716d}.journey-layout{display:grid;grid-template-columns:1fr 1.1fr;gap:65px;align-items:stretch}.steps{display:flex;flex-direction:column;gap:4px}.step{display:grid;grid-template-columns:35px 1fr 20px;gap:17px;text-align:right;padding:25px 18px;background:transparent;border:0;border-top:1px solid #ccd4cb;color:#79837b;transition:background .3s,color .3s;border-radius:0;width:100%}.step[aria-selected=true]{background:#e6eadf;color:#182b20;border-radius:12px;border-color:transparent}.step .latin{font-size:11px;margin-top:7px}.step .step-title{display:block;font-weight:600;font-size:18px;margin-bottom:8px}.step .step-copy{display:block;font-size:11px;color:#667368;max-width:345px}.step-arrow{font-size:20px;transition:transform .3s}.step[aria-selected=true] .step-arrow{transform:translateX(-4px);color:#47752d}.journey-panel{position:relative;min-height:385px;border-radius:22px;background:#e4e9e0;overflow:hidden;padding:33px;display:flex;flex-direction:column;justify-content:space-between;border:1px solid #d4ddcf}.panel-top{display:flex;justify-content:space-between;color:#607259;font-size:9px}.panel-art{height:190px;display:grid;place-items:center;position:relative}.panel-art::before{content:'';width:240px;height:150px;border:1px solid #b5c7ac;border-radius:50%;transform:rotate(-20deg);position:absolute}.idea-card{position:relative;background:#f7f9f3;border:1px solid #d2ddc8;border-radius:16px;padding:20px 35px;box-shadow:0 15px 30px #52674a15;transform:rotate(-5deg);transition:transform .6s var(--ease)}.idea-card span{display:block;text-align:center;font-size:11px;color:#617656}.idea-card strong{font-size:36px;font-weight:500;color:#28442a;display:block;text-align:center}.idea-card::after{content:'✦';position:absolute;top:-15px;left:-15px;width:42px;height:42px;display:grid;place-items:center;background:#d7eea5;color:#3b5b2d;border-radius:12px;font-size:24px;box-shadow:0 4px 15px #66824a15}.journey-panel[data-stage="1"] .idea-card{transform:rotate(4deg)}.journey-panel[data-stage="2"] .idea-card{transform:rotate(0)}.panel-description h3{font-size:20px;margin-bottom:7px}.panel-description p{color:#607259;font-size:11px;line-height:2}.panel-rule{width:60px;height:3px;background:#7c9a64;border-radius:3px;margin-top:20px}.journey-caption{margin-top:24px;font-size:10px;color:#64745d!important}
|
||||||
|
.features{position:relative;background:radial-gradient(ellipse at 90% 60%,#14234380,transparent 60%)}.bento{display:grid;grid-template-columns:1.2fr 1fr 1fr;gap:18px}.feature{position:relative;border:1px solid var(--line);border-radius:20px;padding:30px;background:linear-gradient(130deg,#ffffff05,transparent);overflow:hidden;transition:transform .4s var(--ease),border-color .4s;min-height:330px}.feature:hover{transform:translateY(-6px);border-color:#678eee75}.feature h3{font-size:18px;margin-bottom:12px}.feature p{font-size:11px;line-height:2.15}.feature-top{display:flex;align-items:center;justify-content:space-between;font-size:10px;color:#8ca4cf;margin-bottom:34px}.feature-visual{height:117px;position:relative;margin-bottom:25px}.paths{display:flex;flex-direction:column;gap:11px;justify-content:center}.path-line{height:22px;border:1px solid #5576ba55;border-radius:20px;position:relative;width:78%;background:linear-gradient(90deg,#507aff16,#507aff05)}.path-line:nth-child(2){width:95%;border-color:#8ca4ff;box-shadow:0 0 22px #527cff16}.path-line:nth-child(3){width:60%}.path-line::before{content:'';height:7px;width:7px;background:#738ccc;border-radius:50%;position:absolute;right:12px;top:6px}.path-line:nth-child(2)::before{background:var(--lime)}.path-line::after{content:'';height:2px;width:40%;background:#667da74d;position:absolute;right:32px;top:9px}.source-stack{display:flex;align-items:center;justify-content:center;direction:ltr}.source-sheet{position:absolute;width:74px;height:96px;border:1px solid #5d74a477;background:#16223a;border-radius:9px;display:flex;flex-direction:column;justify-content:center;gap:10px;padding:14px;transform:rotate(-14deg) translateX(-39px)}.source-sheet:nth-child(2){transform:rotate(12deg) translateX(32px);background:#1c2d48}.source-sheet:nth-child(3){transform:rotate(-2deg);background:#233558}.source-sheet i{height:2px;background:#87a0d66b;width:100%}.source-sheet i:last-child{width:55%}.source-sheet span{font-size:9px;color:#b9cafa;font-family:'Manrope',sans-serif}.question-art{display:flex;align-items:center;justify-content:center;gap:13px}.question-art span{width:62px;height:62px;border:1px solid #668ac95c;background:#23355855;border-radius:16px;font-size:32px;display:grid;place-items:center;transform:rotate(9deg);color:#94b1f4}.question-art i{height:1px;width:25px;background:#627ba0}.question-art b{width:43px;height:43px;border-radius:50%;border:1px solid #afc9844d;color:var(--lime);display:grid;place-items:center;font-weight:400;font-size:20px}.feature-note{font-size:10px;margin-top:22px;color:#8698b9}.manifesto{margin-top:75px;padding-block:36px;border-block:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;gap:35px}.manifesto h3{font-size:25px;max-width:550px;line-height:1.9}.manifesto h3 span{color:#8daaff}.manifesto p{font-size:11px;max-width:330px}
|
||||||
|
.people{background:#0d1428}.people-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0;border-block:1px solid var(--line)}.person{padding:35px 32px 35px 45px;border-left:1px solid var(--line)}.person:first-child{padding-right:0}.person:last-child{border:0}.person-no{font-family:'Manrope',sans-serif;font-size:10px;color:#7589af;margin-bottom:28px}.person h3{font-size:23px;margin-bottom:12px}.person p{font-size:11px;min-height:84px;line-height:2.2}.text-link{display:inline-flex;align-items:center;gap:20px;margin-top:25px;font-size:11px;color:#a5bfff}.text-link:hover{color:white}.person:nth-child(2) .text-link{color:var(--lime)}.faq-layout{display:grid;grid-template-columns:.8fr 1.2fr;gap:90px}.faq-intro h2{font-size:34px;line-height:1.7;margin:15px 0}.faq-intro p{font-size:12px}.faq-list details{border-bottom:1px solid var(--line);padding:21px 0}.faq-list details:first-child{border-top:1px solid var(--line)}.faq-list summary{list-style:none;display:flex;align-items:center;justify-content:space-between;gap:25px;font-size:13px;cursor:pointer}.faq-list summary::-webkit-details-marker{display:none}.faq-list summary::after{content:'+';color:#829dd4;font-family:'Manrope',sans-serif;font-size:22px;font-weight:400}.faq-list details[open] summary::after{content:'−'}.faq-list details p{font-size:11px;line-height:2.3;padding:16px 0 5px;max-width:520px}.closing{padding-bottom:85px}.closing-box{position:relative;isolation:isolate;overflow:hidden;border:1px solid #6388f35e;background:linear-gradient(110deg,#142653,#182c66 60%,#25438f);border-radius:24px;padding:60px;text-align:center}.closing-box::before,.closing-box::after{content:'';position:absolute;width:600px;height:600px;border:1px solid #8caeff1f;border-radius:50%;z-index:-1;left:-400px;top:-100px}.closing-box::after{left:auto;right:-400px;top:-330px}.closing-box .eyebrow{justify-content:center;color:#b4c9fc}.closing-box h2{font-size:clamp(30px,4vw,49px);margin:14px 0}.closing-box p{font-size:12px;color:#b2c5ec;max-width:500px;margin-inline:auto}.closing-box .btn{margin-top:28px;background:var(--white);color:#1f3977}.footer-top{display:flex;align-items:center;justify-content:space-between;gap:30px;padding:30px 0 40px;border-bottom:1px solid var(--line)}.footer-note{font-size:10px;margin-top:15px}.footer-links{display:flex;flex-wrap:wrap;gap:25px;font-size:10px;color:#9cadcd}.footer-links a:hover{color:white}.footer-bottom{display:flex;justify-content:space-between;gap:20px;padding:22px 0 28px;font-size:9px;color:#7284a6}.footer-bottom .latin{letter-spacing:2px}
|
||||||
|
@keyframes float{0%,100%{translate:0 0}50%{translate:0 -13px}}@keyframes orbit{to{rotate:360deg}}.reveal{opacity:1;transform:none}.animate-ready .reveal.pending{opacity:0;transform:translateY(25px)}.animate-ready .reveal{transition:opacity .8s var(--ease),transform .8s var(--ease)}.motion-off *,.motion-off *::before,.motion-off *::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}.motion-off .universe-inner{transform:none}.motion-off .reveal.pending{opacity:1;transform:none}
|
||||||
|
@media(min-width:1500px){.hero-grid{min-height:790px}.universe{height:600px}.core{width:330px;height:360px}}
|
||||||
|
@media(max-width:1050px){.wrap{width:calc(100% - 56px)}.nav-links{gap:18px}.hero h1{font-size:55px}.hero-grid{gap:15px;min-height:680px}.universe{height:460px}.concept-tag{padding:10px 12px}.tag-one{right:-10px}.core{width:250px}.journey-layout{gap:30px}.feature{padding:24px}.bento{gap:12px}.faq-layout{gap:45px}.nav{gap:20px}.nav-links{font-size:10px}}
|
||||||
|
@media(max-width:760px){html{scroll-padding-top:90px}.wrap{width:calc(100% - 40px)}.nav{height:74px;gap:10px}.brand-name{font-size:24px}.brand-symbol{width:29px}.brand-sub{font-size:7px}.nav-end .btn{font-size:9px;padding:8px 13px;min-height:39px}.menu-toggle{display:block;font-size:11px}.nav-links{display:none;position:absolute;top:74px;right:0;left:0;background:#101a30;border-bottom:1px solid var(--line);padding:23px;flex-direction:column;align-items:stretch;gap:0;font-size:12px}.nav-links a{padding:12px}.nav-links.is-open{display:flex}.motion-toggle{width:31px;height:31px}.nav-end{gap:8px}.hero-grid{grid-template-columns:1fr;padding-top:42px;gap:15px}.hero-copy{text-align:center}.hero-copy>.pill{font-size:9px}.hero h1{font-size:clamp(42px,8.8vw,62px);letter-spacing:-1px;margin-top:20px;line-height:1.55}.hero-desc{font-size:12px;margin-inline:auto;max-width:420px}.hero-actions{justify-content:center;gap:10px;margin-top:24px}.hero-actions .btn{padding:12px 17px;font-size:11px;gap:20px}.hero-note{justify-content:center;font-size:9px;flex-wrap:wrap}.universe{height:390px;width:min(440px,100%);margin-inline:auto}.core{width:235px;height:270px}.tag-one{right:0;top:12%}.tag-two{left:0}.tag-three{right:3%;bottom:6%}.concept-tag b{font-size:10px}.concept-tag small{font-size:7px}.tag-icon{width:26px;height:26px}.universe-label{top:6%;left:5%;font-size:7px}.universe-coordinate{font-size:7px;left:5%;bottom:6%}.hero-grid{padding-bottom:25px}.hero-bottom{font-size:9px;padding-block:19px}.hero-bottom .latin{font-size:7px;letter-spacing:1px}.principles .wrap{justify-content:center;flex-wrap:wrap;gap:10px 18px;padding-block:21px}.principles p{width:100%;text-align:center;font-size:9px;margin-bottom:3px}.principles strong{font-size:11px}.principles i{font-size:14px}.section{padding-block:65px}.section-head{display:block;margin-bottom:30px}.section-head h2{font-size:29px}.section-head>p{margin-top:17px;font-size:11px}.journey-layout{grid-template-columns:1fr;gap:24px}.step{padding:20px 14px}.step .step-title{display:block;font-weight:600;font-size:16px}.journey-panel{min-height:350px;padding:24px}.panel-art{height:170px}.journey-caption{font-size:9px}.bento{grid-template-columns:1fr;gap:15px}.feature{padding:26px;min-height:0;display:grid;grid-template-columns:1fr 105px;column-gap:20px}.feature-top{grid-column:1/-1;margin-bottom:20px}.feature-visual{grid-column:2;grid-row:2/4;height:100px;margin:0;align-self:center}.feature h3{grid-row:2;grid-column:1;font-size:17px}.feature p{grid-row:3;grid-column:1;font-size:10px}.source-sheet{width:51px;height:75px;padding:10px;gap:7px}.source-sheet:first-child{transform:rotate(-14deg) translateX(-20px)}.source-sheet:nth-child(2){transform:rotate(12deg) translateX(20px)}.question-art{gap:7px}.question-art span{width:42px;height:48px;font-size:25px}.question-art b{width:30px;height:30px;font-size:16px}.question-art i{width:8px}.manifesto{margin-top:42px;display:block;padding-block:28px}.manifesto h3{font-size:22px}.manifesto p{margin-top:15px;font-size:11px}.people-grid{grid-template-columns:1fr;border-bottom:0}.person,.person:first-child{padding:28px 0;border-left:0;border-bottom:1px solid var(--line)}.person:last-child{border-bottom:1px solid var(--line)}.person-no{margin-bottom:15px}.person h3{font-size:21px}.person p{min-height:0;max-width:480px}.person .text-link{margin-top:15px}.faq-layout{grid-template-columns:1fr;gap:30px}.faq-intro h2{font-size:29px}.faq-list summary{font-size:12px}.closing{padding-bottom:40px}.closing-box{padding:40px 22px;border-radius:18px}.closing-box h2{font-size:29px;line-height:1.8}.closing-box p{font-size:10px}.footer-top{align-items:start;flex-direction:column;gap:24px}.footer-links{gap:20px;font-size:10px}.footer-bottom{flex-direction:column;font-size:8px;gap:10px}}
|
||||||
|
@media(max-width:380px){.nav .brand-symbol{display:none}.nav .brand{gap:0}.nav-end .btn{gap:10px}.nav-end{gap:6px}.menu-toggle{padding:8px 9px}}
|
||||||
|
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*::before,*::after{animation:none!important;transition:none!important}.reveal.pending{opacity:1!important;transform:none!important}.universe-inner{transform:none!important}}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p><a href="/index.html">اضغط هنا للدخول إلى صَقِل</a></p>
|
<a class="skip" href="#main">انتقل إلى المحتوى</a>
|
||||||
|
<div class="scroll-progress" aria-hidden="true"></div>
|
||||||
|
<header class="header">
|
||||||
|
<nav class="wrap nav" aria-label="التنقل الرئيسي">
|
||||||
|
<a href="#main" class="brand" aria-label="صَقِل — الرئيسية">
|
||||||
|
<svg class="brand-symbol" viewBox="0 0 40 46" fill="none" aria-hidden="true"><path d="M20 2 37 12v21L20 44 3 33V12L20 2Z" stroke="currentColor" stroke-width="1.4"/><path d="m10 28 10 6 10-6M10 21l10 6 10-6M10 14l10 6 10-6" stroke="currentColor" stroke-width="2"/></svg>
|
||||||
|
<span class="brand-name">صَقِل<span class="brand-sub">SAQEL</span></span>
|
||||||
|
</a>
|
||||||
|
<div class="nav-links" id="navigation"><a href="#journey">فلسفة التعلّم</a><a href="#approach">تجربة صَقِل</a><a href="#community">لكل دور، مساحة</a><a href="#questions">أسئلة شائعة</a></div>
|
||||||
|
<div class="nav-end"><button class="motion-toggle" type="button" aria-label="إيقاف الحركة" aria-pressed="false" title="إيقاف الحركة">Ⅱ</button><a class="btn btn-outline" href="/student">دخول المنصة <span aria-hidden="true">↗</span></a><button class="menu-toggle" aria-controls="navigation" aria-expanded="false" type="button">القائمة</button></div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main id="main">
|
||||||
|
<section class="hero" aria-labelledby="hero-title">
|
||||||
|
<div class="wrap hero-grid">
|
||||||
|
<div class="hero-copy">
|
||||||
|
<span class="pill"><span class="dot" aria-hidden="true"></span> رؤية جديدة للتعلّم. تبدأ من الفهم.</span>
|
||||||
|
<h1 id="hero-title">العِلم يفتح آفاقك.<br><em>والفهم يصقلك.</em></h1>
|
||||||
|
<p class="hero-desc">للعقول التي تسأل، وتحاول، وتطمح لأبعد.<br>نبني في صَقِل تجربة تجمع الشرح المناسب والتدريب الهادف، ليصبح ما تتعلّمه قدرةً تفكّر بها.</p>
|
||||||
|
<div class="hero-actions"><a href="/student" class="btn btn-primary">ادخل إلى صَقِل <span class="arrow" aria-hidden="true">←</span></a><a href="#journey" class="btn btn-outline">اكتشف الفكرة <span aria-hidden="true">↓</span></a></div>
|
||||||
|
<p class="hero-note"><span aria-hidden="true"></span> قيد التطوير والتحقق <span aria-hidden="true"></span> البداية من الصف العاشر</p>
|
||||||
|
</div>
|
||||||
|
<div class="universe" aria-hidden="true">
|
||||||
|
<div class="universe-inner"><div class="universe-grid"></div><div class="universe-glow"></div><div class="orbit"></div><div class="orbit two"></div><div class="orbit three"></div><div class="satellite-track"></div>
|
||||||
|
<span class="universe-label latin">THE SHAPE OF UNDERSTANDING</span>
|
||||||
|
<div class="core"><svg viewBox="0 0 300 330" fill="none"><defs><linearGradient id="plane" x1="30" y1="50" x2="245" y2="230" gradientUnits="userSpaceOnUse"><stop stop-color="#b6d0ff" stop-opacity=".75"/><stop offset=".42" stop-color="#527eff" stop-opacity=".35"/><stop offset="1" stop-color="#294bae" stop-opacity=".1"/></linearGradient><linearGradient id="edge" x1="20" y1="100" x2="280" y2="230"><stop stop-color="#b2cdff"/><stop offset="1" stop-color="#4b73ff" stop-opacity=".25"/></linearGradient><linearGradient id="beam" x1="150" y1="0" x2="150" y2="290" gradientUnits="userSpaceOnUse"><stop stop-color="#b9d6ff" stop-opacity="0"/><stop offset=".5" stop-color="#b9d6ff" stop-opacity=".8"/><stop offset="1" stop-color="#b9d6ff" stop-opacity="0"/></linearGradient></defs><path d="m150 160 126 70-126 73L24 230l126-70Z" fill="#101f47" stroke="#5679c1" stroke-opacity=".5"/><path d="m24 230 126 73 126-73v13l-126 73-126-73v-13Z" fill="#1a2e61" stroke="#5071b7" stroke-opacity=".4"/><path d="m150 116 126 70-126 73L24 186l126-70Z" fill="url(#plane)" stroke="url(#edge)"/><path d="m150 73 126 70-126 73L24 143l126-70Z" fill="url(#plane)" stroke="url(#edge)"/><path d="m150 30 126 70-126 73L24 100l126-70Z" fill="url(#plane)" stroke="url(#edge)" stroke-width="1.5"/><path d="m150 52 86 48-86 50-86-50 86-48Z" stroke="#d0e2ff" stroke-opacity=".4"/><path d="m150 76 42 24-42 25-42-25 42-24Z" fill="#b8d1ff" fill-opacity=".25" stroke="#c1d7ff" stroke-opacity=".8"/><path d="M150 0v303" stroke="url(#beam)"/><path d="m24 100 0 130M276 100v130" stroke="#89a6ed" stroke-opacity=".25" stroke-dasharray="3 7"/><circle cx="150" cy="100" r="5" fill="#e4eeff"/><circle cx="150" cy="100" r="14" stroke="#d5e5ff" stroke-opacity=".4"/><circle cx="24" cy="100" r="3" fill="#abc6ff"/><circle cx="276" cy="100" r="3" fill="#abc6ff"/></svg></div>
|
||||||
|
<div class="concept-tag tag-one"><span class="tag-icon">◇</span><div><b>فهمٌ أعمق</b><small>من السؤال إلى الفكرة</small></div></div>
|
||||||
|
<div class="concept-tag tag-two"><span class="tag-icon">↗</span><div><b>تدريبٌ هادف</b><small>من الفكرة إلى التطبيق</small></div></div>
|
||||||
|
<div class="concept-tag tag-three"><span class="tag-icon">✦</span><div><b>معرفةٌ تبقى</b><small>بالمحاولة والمراجعة</small></div></div>
|
||||||
|
<span class="spark a"></span><span class="spark b"></span><span class="spark c"></span><span class="universe-coordinate latin">CURIOSITY → CLARITY → GROWTH</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wrap hero-bottom"><a href="#journey" class="scroll-cue"><b aria-hidden="true">↓</b> تعرّف على ما نبنيه</a><span class="latin">BUILT AROUND THE WAY YOU UNDERSTAND</span></div>
|
||||||
|
</section>
|
||||||
|
<div class="principles"><div class="wrap"><p>فلسفتنا في ثلاث كلمات</p><strong>فضول يفتح السؤال</strong><i aria-hidden="true">✳</i><strong>تدريب يبني القدرة</strong><i aria-hidden="true">✳</i><strong>فهم يترك أثرًا</strong></div></div>
|
||||||
|
<section class="section journey" id="journey" aria-labelledby="journey-title"><div class="wrap">
|
||||||
|
<div class="section-head reveal"><div><span class="eyebrow">01 / فلسفة التعلّم</span><h2 id="journey-title">لحظة «فهمتها»<br>هي البداية.</h2></div><p>المعرفة تتكوّن عندما تسأل وتجرّب وتعود للفكرة.<br>هذه رحلة التعلّم التي نصمّم صَقِل حولها.</p></div>
|
||||||
|
<div class="journey-layout reveal">
|
||||||
|
<div class="steps" role="tablist" aria-label="مراحل رحلة التعلّم" aria-orientation="vertical">
|
||||||
|
<button type="button" class="step" role="tab" id="step-0" aria-controls="journey-panel" aria-selected="true" tabindex="0" data-step="0"><span class="latin">01</span><span><span class="step-title">افهم بطريقتك</span><span class="step-copy">الشرح المناسب يقرّب الفكرة. نطمح إلى إتاحة أساليب متعددة للدرس نفسه، لتجد ما يناسبك.</span></span><span class="step-arrow" aria-hidden="true">←</span></button>
|
||||||
|
<button type="button" class="step" role="tab" id="step-1" aria-controls="journey-panel" aria-selected="false" tabindex="-1" data-step="1"><span class="latin">02</span><span><span class="step-title">حوّل الفكرة إلى قدرة</span><span class="step-copy">جرّب بنفسك، فسّر خطواتك، واكتشف أين تحتاج إلى مساعدة. للمحاولة مكان أساسي في رحلتك.</span></span><span class="step-arrow" aria-hidden="true">←</span></button>
|
||||||
|
<button type="button" class="step" role="tab" id="step-2" aria-controls="journey-panel" aria-selected="false" tabindex="-1" data-step="2"><span class="latin">03</span><span><span class="step-title">عُد إليها. وثبّتها.</span><span class="step-copy">الفهم يحتاج إلى مراجعة. نضع العودة للأفكار والتعلّم من الأخطاء في قلب التجربة التي نبنيها.</span></span><span class="step-arrow" aria-hidden="true">←</span></button>
|
||||||
|
</div>
|
||||||
|
<div class="journey-panel" id="journey-panel" role="tabpanel" aria-labelledby="step-0" tabindex="0" data-stage="0"><div class="panel-top"><span>تصوّر لرحلة التعلّم</span><span class="latin" id="panel-counter">01 / 03</span></div><div class="panel-art" aria-hidden="true"><div class="idea-card"><span id="idea-label">كل فكرة تبدأ بـ</span><strong id="idea-word">لماذا؟</strong></div></div><div class="panel-description"><h3 id="panel-title">مساحة للسؤال.</h3><p id="panel-copy">نريد للشرح أن يفتح فضولك، وأن يساعدك على ربط الفكرة بما تعرفه، خطوةً خطوة.</p><div class="panel-rule" aria-hidden="true"></div></div></div>
|
||||||
|
</div>
|
||||||
|
<p class="journey-caption">هذا عرض لفلسفة المنتج، وليس درسًا منشورًا أو نتيجة تعلّم مقاسة.</p>
|
||||||
|
</div></section>
|
||||||
|
<section class="section features" id="approach" aria-labelledby="approach-title"><div class="wrap">
|
||||||
|
<div class="section-head reveal"><div><span class="eyebrow">02 / تجربة صَقِل</span><h2 id="approach-title">تفاصيل تخدم عقلك.</h2></div><p>رؤيتنا لتقنية تعليمية تجعل الطريق إلى الفهم أوضح، وتمنح كل خطوة هدفًا ومصدرًا.</p></div>
|
||||||
|
<div class="bento">
|
||||||
|
<article class="feature reveal"><div class="feature-top"><span>حرية في التعلّم</span><span class="latin">01 ↗</span></div><div class="feature-visual paths" aria-hidden="true"><div class="path-line"></div><div class="path-line"></div><div class="path-line"></div></div><h3>فكرة واحدة.<br>أكثر من طريق للفهم.</h3><p>نصمّم تجربة تتيح تنوّع شروحات المعلمين للدرس المنهجي نفسه، بحسب الحصص المتاحة لك.</p></article>
|
||||||
|
<article class="feature reveal"><div class="feature-top"><span>معرفة لها مرجع</span><span class="latin">02 ↗</span></div><div class="feature-visual source-stack" aria-hidden="true"><div class="source-sheet"><i></i><i></i><i></i></div><div class="source-sheet"><i></i><i></i><i></i></div><div class="source-sheet"><span>SOURCE</span><i></i><i></i></div></div><h3>الدرس متصل<br>بمصادره.</h3><p>كتاب، ورقة عمل، وخريطة ذهنية. نعمل على ربط موارد كل درس بمنهجه ونسخته المعتمدة.</p></article>
|
||||||
|
<article class="feature reveal"><div class="feature-top"><span>تقنية تخدم التفكير</span><span class="latin">03 ↗</span></div><div class="feature-visual question-art" aria-hidden="true"><span>؟</span><i></i><b>↗</b></div><h3>السؤال المناسب.<br>في سياق الدرس.</h3><p>نتطلّع إلى مساعدة ذكية مرتبطة بمحتوى الدرس، تمنحك تلميحًا يقودك إلى التفكير والمحاولة.</p></article>
|
||||||
|
</div><p class="feature-note">هذه ملامح التجربة المستهدفة. يتحدد المتاح فعليًا داخل البوابة بحسب المحتوى المنشور وصلاحية الوصول.</p>
|
||||||
|
<div class="manifesto reveal"><h3>نؤمن أن التقنية تكون أقوى<br>عندما تجعل <span>تفكيرك أعمق.</span></h3><p>المعلم في قلب العملية، والمحتوى هو المرجع، والطالب شريك في بناء فهمه. هذه المبادئ تقود ما نبنيه.</p></div>
|
||||||
|
</div></section>
|
||||||
|
<section class="section people" id="community" aria-labelledby="community-title"><div class="wrap"><div class="section-head reveal"><div><span class="eyebrow">03 / منظومة تتكامل</span><h2 id="community-title">طموح مشترك.<br>ولكل دور، مساحة.</h2></div><p>تبدأ رحلة التعلّم بالطالب، وتتكامل بخبرة المعلم ومساندة الأسرة والمدرسة.</p></div>
|
||||||
|
<div class="people-grid reveal"><article class="person"><div class="person-no">01 / LEARN</div><h3>للطالب الفضولي</h3><p>ادخل بوابتك، وتعرّف على المواد والموارد المتاحة لحسابك. اجعل سؤالك القادم خطوةً نحو فهم أعمق.</p><a class="text-link" href="/student">بوابة الطالب <span class="arrow" aria-hidden="true">←</span></a></article><article class="person"><div class="person-no">02 / INSPIRE</div><h3>للمعلّم الملهم</h3><p>لخبرتك وطريقتك في الشرح قيمة. استوديو المعلم هو مساحتك للعمل على محتواك ومتابعة رحلتك على المنصة.</p><a class="text-link" href="/teacher">استوديو المعلم <span class="arrow" aria-hidden="true">←</span></a></article><article class="person"><div class="person-no">03 / SUPPORT</div><h3>لمن يساند الرحلة</h3><p>مساحة لولي الأمر والمدرسة، ضمن الصلاحيات والربط المتاحين، ليكون لكل طرف دوره في متابعة التعلّم.</p><a class="text-link" href="/guardian">بوابة ولي الأمر <span class="arrow" aria-hidden="true">←</span></a><br><a class="text-link" href="/school-admin">بوابة المدرسة <span class="arrow" aria-hidden="true">←</span></a></article></div>
|
||||||
|
</div></section>
|
||||||
|
<section class="section" id="questions" aria-labelledby="questions-title"><div class="wrap faq-layout"><div class="faq-intro reveal"><span class="eyebrow">وضوح من البداية</span><h2 id="questions-title">قبل أن تبدأ.</h2><p>إجابات قصيرة عن صَقِل وما نبنيه.</p></div><div class="faq-list reveal"><details open><summary>ما هي صَقِل؟</summary><p>منصة تعليمية قيد التطوير والتحقق. نبني تجربة تربط الدرس المنهجي بالشرح والتدريب والمراجعة، مع بداية مركّزة على الصف العاشر.</p></details><details><summary>هل كل ما يظهر هنا متاح الآن؟</summary><p>تعرض هذه الصفحة رؤية المنتج، إلى جانب روابط البوابات الموجودة. المشاهد البصرية توضيحية، ويعتمد توفر الدروس والموارد والميزات داخل المنصة على النشر والصلاحيات واكتمال التحقق.</p></details><details><summary>هل يمكنني اختيار المعلم؟</summary><p>هذا جزء من التجربة المستهدفة: الاختيار بين الحصص المتاحة للدرس نفسه عند تعدد المعلمين. لا يعني ذلك أن لكل درس عدة شروحات منشورة الآن.</p></details><details><summary>كيف أعرف المواد المتاحة وشروط الوصول؟</summary><p>ابدأ من بوابة الطالب للتحقق مما يظهر لحسابك. لا تعرض هذه الصفحة أسعارًا أو باقات معتمدة، ولا تفترض توفر مادة أو اشتراك قبل ظهور تفاصيلهما الفعلية داخل المنصة.</p></details></div></div></section>
|
||||||
|
<section class="closing" aria-labelledby="closing-title"><div class="wrap closing-box reveal"><span class="eyebrow">لكل عقل أفق يستحقه</span><h2 id="closing-title">فضولك يستحق خطوة.</h2><p>تعرّف على صَقِل من الداخل، واكتشف المتاح لك اليوم، ونحن نبني تجربة تعليمية تليق بطموحك.</p><a class="btn" href="/student">إلى بوابة الطالب <span class="arrow" aria-hidden="true">←</span></a></div></section>
|
||||||
|
</main>
|
||||||
|
<footer class="wrap"><div class="footer-top"><div><a href="#main" class="brand"><span class="brand-name">صَقِل<span class="brand-sub">SAQEL</span></span></a><p class="footer-note">الفهم يصنع الفرق.</p></div><nav class="footer-links" aria-label="روابط التذييل"><a href="#journey">فلسفتنا</a><a href="/student">الطالب</a><a href="/teacher">المعلم</a><a href="/guardian">ولي الأمر</a><a href="/school-admin">المدرسة</a></nav></div><div class="footer-bottom"><span>© <span id="year">2026</span> صَقِل. جميع الحقوق محفوظة.</span><span class="latin">MADE FOR CURIOUS MINDS.</span><span>منصة قيد التطوير والتحقق</span></div></footer>
|
||||||
|
<script>
|
||||||
|
(() => {
|
||||||
|
'use strict';
|
||||||
|
const root = document.documentElement;
|
||||||
|
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||||||
|
const motionButton = document.querySelector('.motion-toggle');
|
||||||
|
let paused = reduced.matches;
|
||||||
|
function setMotion() {
|
||||||
|
root.classList.toggle('motion-off', paused);
|
||||||
|
motionButton.setAttribute('aria-pressed', String(paused));
|
||||||
|
motionButton.setAttribute('aria-label', paused ? 'تشغيل الحركة' : 'إيقاف الحركة');
|
||||||
|
motionButton.title = paused ? 'تشغيل الحركة' : 'إيقاف الحركة';
|
||||||
|
motionButton.textContent = paused ? '▷' : 'Ⅱ';
|
||||||
|
}
|
||||||
|
setMotion();
|
||||||
|
motionButton.addEventListener('click', () => { paused = !paused; setMotion(); });
|
||||||
|
reduced.addEventListener('change', event => { paused = event.matches; setMotion(); });
|
||||||
|
document.getElementById('year').textContent = new Date().getFullYear();
|
||||||
|
const menuButton = document.querySelector('.menu-toggle');
|
||||||
|
const navigation = document.getElementById('navigation');
|
||||||
|
function closeMenu() { navigation.classList.remove('is-open'); menuButton.setAttribute('aria-expanded', 'false'); }
|
||||||
|
menuButton.addEventListener('click', () => { const open = navigation.classList.toggle('is-open'); menuButton.setAttribute('aria-expanded', String(open)); });
|
||||||
|
navigation.addEventListener('click', event => { if (event.target.closest('a')) closeMenu(); });
|
||||||
|
document.addEventListener('keydown', event => { if (event.key === 'Escape' && navigation.classList.contains('is-open')) { closeMenu(); menuButton.focus(); } });
|
||||||
|
document.addEventListener('click', event => { if (!event.target.closest('.nav')) closeMenu(); });
|
||||||
|
const stages = [
|
||||||
|
['كل فكرة تبدأ بـ', 'لماذا؟', 'مساحة للسؤال.', 'نريد للشرح أن يفتح فضولك، وأن يساعدك على ربط الفكرة بما تعرفه، خطوةً خطوة.'],
|
||||||
|
['الفهم يصبح قدرة عندما', 'تجرّب.', 'مساحة للمحاولة.', 'نصمّم التدريب ليمنحك فرصة لاستخدام الفكرة، وتفسير خطواتك، ومعرفة موضع التعثّر.'],
|
||||||
|
['المعرفة تنمو عندما', 'تعود.', 'مساحة للمراجعة.', 'العودة إلى الفكرة والتعلّم من الأخطاء جزء من الرحلة التي نستهدفها، حتى تبني فهمًا يمكن الرجوع إليه.']
|
||||||
|
];
|
||||||
|
const tabs = [...document.querySelectorAll('[data-step]')];
|
||||||
|
function activate(index, focus = false) {
|
||||||
|
tabs.forEach((tab, i) => { tab.setAttribute('aria-selected', String(i === index)); tab.tabIndex = i === index ? 0 : -1; });
|
||||||
|
const panel = document.getElementById('journey-panel');
|
||||||
|
panel.dataset.stage = String(index); panel.setAttribute('aria-labelledby', tabs[index].id);
|
||||||
|
['idea-label', 'idea-word', 'panel-title', 'panel-copy'].forEach((id, i) => { document.getElementById(id).textContent = stages[index][i]; });
|
||||||
|
document.getElementById('panel-counter').textContent = `0${index + 1} / 03`;
|
||||||
|
if (focus) tabs[index].focus();
|
||||||
|
}
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
tab.addEventListener('click', () => activate(index));
|
||||||
|
tab.addEventListener('keydown', event => {
|
||||||
|
let next;
|
||||||
|
if (event.key === 'ArrowDown') next = (index + 1) % tabs.length;
|
||||||
|
if (event.key === 'ArrowUp') next = (index + tabs.length - 1) % tabs.length;
|
||||||
|
if (event.key === 'Home') next = 0;
|
||||||
|
if (event.key === 'End') next = tabs.length - 1;
|
||||||
|
if (next !== undefined) { event.preventDefault(); activate(next, true); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if ('IntersectionObserver' in window && !reduced.matches) {
|
||||||
|
root.classList.add('animate-ready');
|
||||||
|
const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.remove('pending'); observer.unobserve(entry.target); } }); }, { threshold: .08 });
|
||||||
|
document.querySelectorAll('.reveal').forEach(element => { element.classList.add('pending'); observer.observe(element); });
|
||||||
|
}
|
||||||
|
const progress = document.querySelector('.scroll-progress');
|
||||||
|
let scrollPending = false;
|
||||||
|
function updateProgress() { const height = root.scrollHeight - innerHeight; progress.style.transform = `scaleX(${height > 0 ? Math.min(1, Math.max(0, scrollY / height)) : 0})`; scrollPending = false; }
|
||||||
|
addEventListener('scroll', () => { if (!scrollPending) { scrollPending = true; requestAnimationFrame(updateProgress); } }, { passive: true });
|
||||||
|
addEventListener('resize', updateProgress); updateProgress();
|
||||||
|
const universe = document.querySelector('.universe');
|
||||||
|
if (matchMedia('(hover: hover) and (pointer: fine)').matches) {
|
||||||
|
universe.addEventListener('pointermove', event => {
|
||||||
|
if (paused || reduced.matches) return;
|
||||||
|
const rect = universe.getBoundingClientRect();
|
||||||
|
universe.style.setProperty('--mx', `${((event.clientX - rect.left) / rect.width - .5) * 10}deg`);
|
||||||
|
universe.style.setProperty('--my', `${-((event.clientY - rect.top) / rect.height - .5) * 8}deg`);
|
||||||
|
});
|
||||||
|
universe.addEventListener('pointerleave', () => { universe.style.setProperty('--mx', '0deg'); universe.style.setProperty('--my', '0deg'); });
|
||||||
|
}
|
||||||
|
document.addEventListener('visibilitychange', () => { document.querySelectorAll('.core, .concept-tag, .satellite-track').forEach(element => { element.style.animationPlayState = document.hidden ? 'paused' : ''; }); });
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -15,19 +15,19 @@
|
|||||||
| الترتيب | المهمة | النموذج/الجهد | يعتمد على | الحالة |
|
| الترتيب | المهمة | النموذج/الجهد | يعتمد على | الحالة |
|
||||||
|---:|---|---|---|---|
|
|---:|---|---|---|---|
|
||||||
| 00 | تثبيت بيئة الاختبار والأوامر الفعلية | Medium | — | implemented_unverified |
|
| 00 | تثبيت بيئة الاختبار والأوامر الفعلية | Medium | — | implemented_unverified |
|
||||||
| 01 | إيقاف النجاح المالي والمحتوى البديل الوهمي | Medium | 00 | implemented_unverified |
|
| 01 | إيقاف النجاح المالي والمحتوى البديل الوهمي | Medium | 00 | verified_in_code |
|
||||||
| 02 | هوية المنهج والأصول المنشورة | Medium | 01 | implemented_unverified |
|
| 02 | هوية المنهج والأصول المنشورة | Medium | 01 | in_progress |
|
||||||
| 03 | حصة المعلم والإصدار والاستبدال الذري | Medium | 02 | implemented_unverified |
|
| 03 | حصة المعلم والإصدار والاستبدال الذري | Medium | 02 | implemented_unverified |
|
||||||
| 04 | تدقيق الفيديو والأسئلة من الأدلة | Medium | 02, 03 | planned |
|
| 04 | تدقيق الفيديو والأسئلة من الأدلة | Medium | 02, 03 | in_progress |
|
||||||
| 05 | API صفر/واحد/متعدد واختيار المعلم | Medium | 02, 04 | planned |
|
| 05 | API صفر/واحد/متعدد واختيار المعلم | Medium | 02, 04 | implemented_unverified |
|
||||||
| 06 | دفتر الحسابات وحجز الرصيد | Medium ثم Sol review | 00, 01 | planned |
|
| 06 | دفتر الحسابات وحجز الرصيد | Medium ثم Sol review | 00, 01 | implemented_unverified |
|
||||||
| 07 | جلسات المشاهدة والدقائق المؤهلة | Medium | 02, 05, 06 | planned |
|
| 07 | جلسات المشاهدة والدقائق المؤهلة | Medium | 02, 05, 06 | implemented_unverified |
|
||||||
| 08 | تسوية صندوق المعلمين وكشف الحساب | Medium ثم Sol review | 06, 07 | planned |
|
| 08 | تسوية صندوق المعلمين وكشف الحساب | Medium ثم Sol review | 06, 07 | blocked: سياسة تجارية معتمدة |
|
||||||
| 09 | مزود الدفع والبصمة والتحويل | Medium ثم Sol/Astra review | 06 | blocked: مزود دفع/سياسة متجر |
|
| 09 | مزود الدفع والبصمة والتحويل | Medium ثم Sol/Astra review | 06 | blocked: مزود دفع/سياسة متجر |
|
||||||
| 10 | الإنجليزية: حزمة الدرس والصوت الموحد | Medium | 01, 02 | planned |
|
| 10 | الإنجليزية: حزمة الدرس والصوت الموحد | Medium | 01, 02 | in_progress |
|
||||||
| 11 | موارد الدرس وحلقة العلاج وولي الأمر | Medium | 02, 04, 05, 10 | planned |
|
| 11 | موارد الدرس وحلقة العلاج وولي الأمر | Medium | 02, 04, 05, 10 | in_progress |
|
||||||
| 12 | المؤسسات والتقييمات والتلعيب | Medium | 02, 05, 07, 11 | planned |
|
| 12 | المؤسسات والتقييمات والتلعيب | Medium | 02, 05, 07, 11 | implemented_unverified |
|
||||||
| 13 | إثبات الصف العاشر وقرار الإطلاق | Medium ثم Astra review | كل ما يلزم | planned |
|
| 13 | إثبات الصف العاشر وقرار الإطلاق | Medium ثم Astra review | كل ما يلزم | gate_pending |
|
||||||
|
|
||||||
## قاعدة تحديث قاعدة البيانات
|
## قاعدة تحديث قاعدة البيانات
|
||||||
|
|
||||||
@@ -133,3 +133,15 @@
|
|||||||
- فحوص شُغلت: PHP lint كامل لـ`backend/app` و`backend/scripts` و`backend/cron`، و`git diff --check`، وFlutter analyze لملفات الطالب المعدلة؛ كلها ناجحة.
|
- فحوص شُغلت: PHP lint كامل لـ`backend/app` و`backend/scripts` و`backend/cron`، و`git diff --check`، وFlutter analyze لملفات الطالب المعدلة؛ كلها ناجحة.
|
||||||
- لم تُطبق migrations أو تختبر المعاملات على MySQL لأن `.env` و`ENCRYPTION_KEY` غير متاحين محلياً. كما أن 06–08 لا يجوز تفعيلها أو حساب توزيع مالي قبل سياسة دخل موقعة، و09 ما زالت محجوبة بتحديد مزود دفع/تحويل فعلي.
|
- لم تُطبق migrations أو تختبر المعاملات على MySQL لأن `.env` و`ENCRYPTION_KEY` غير متاحين محلياً. كما أن 06–08 لا يجوز تفعيلها أو حساب توزيع مالي قبل سياسة دخل موقعة، و09 ما زالت محجوبة بتحديد مزود دفع/تحويل فعلي.
|
||||||
- الخطوة التالية تلقائياً: نفذ migrations على staging مع backup، شغّل backfill dry-run ثم راجع الـ19 مرجعاً الناقصاً، وانشر bundles وحزم إنجليزية حقيقية للصف العاشر. بعدها اختبر مسارات صفر/واحد/متعدد وجلسات المشاهدة بتكامل MySQL قبل أي نشر.
|
- الخطوة التالية تلقائياً: نفذ migrations على staging مع backup، شغّل backfill dry-run ثم راجع الـ19 مرجعاً الناقصاً، وانشر bundles وحزم إنجليزية حقيقية للصف العاشر. بعدها اختبر مسارات صفر/واحد/متعدد وجلسات المشاهدة بتكامل MySQL قبل أي نشر.
|
||||||
|
|
||||||
|
### 2026-09-16 — تحديث شامل واعتماد دفتر المتابعة (PLATFORM_EXECUTION_LEDGER.md)
|
||||||
|
|
||||||
|
- تم إنشاء وثيقة «دفتر متابعة وتنفيذ مهام منصة صَقِل» (`docs/PLATFORM_EXECUTION_LEDGER.md`) لتكون السجل الحي لمتابعة جميع المهام من NP-00 إلى NP-13.
|
||||||
|
- فحص بوابة القبول `validate_grade10_candidate.php --manifest=manifest.accepted.json`: اجتاز الفحص بنجاح تام (0 errors, 581 warnings).
|
||||||
|
- تم إنجاز وتثبيت المكونات التالية:
|
||||||
|
- نافذة التفكير السقراطية (60 ثانية) `ScaffoldedThinkingPauseSheet` مع التدريج المعرفي خطوة بخطوة.
|
||||||
|
- واجهة اختيار المعلم `TeacherSelectionSheet` بالفرز التنازلي للتقييم الحقيقي وعدد التقييمات.
|
||||||
|
- دفتر الأخطاء الذكي والكويز العلاجي في الخادم وتطبيق الطالب.
|
||||||
|
- منظومة طلب وموافقة ولي الأمر مع حماية الرقم الوطني بالـ Blind Index.
|
||||||
|
- 18 مختبراً تفاعلياً مدمجاً (12 لغة عربية + 6 فيزياء) و371 مواصفة مختبر للصف العاشر.
|
||||||
|
- الخطوة التالية: ربط Preflight في واجهة المعلم وتفعيل خوارزمية التكرار المتباعد في دفتر الأخطاء الذكي ونشر الـ 12 درساً التجريبية.
|
||||||
|
|||||||
@@ -0,0 +1,214 @@
|
|||||||
|
<div dir="rtl" align="right">
|
||||||
|
|
||||||
|
# 📋 دفتر متابعة وتنفيذ مهام منصة صَقِل — السجل المعماري الحي
|
||||||
|
|
||||||
|
تاريخ التحديث الأخير: **16 أيلول 2026**
|
||||||
|
المرجع الأساسي: `docs/NEXT_PHASE_MASTER_SPEC.md` و `docs/NEXT_PHASE_EXECUTION_BACKLOG.md` و `AGENTS.md`
|
||||||
|
الهدف: هذا الدفتر هو المرجع التوثيقي والتنفيذي المباشر لجميع محاور ومنعطفات منصة صَقِل، يوضح بدقة متناهية **ما تم إنجازه فعلياً في الكود**، و**شو تبقى من كل نقطة**، مع معايير القبول وشروط الانتقال للمرحلة التالية.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. جدول الموقف التنفيذي العام (Executive Task Matrix)
|
||||||
|
|
||||||
|
| المعرّف | المحور / المهمة | النطاق والمستوى | الحالة الحالية | ما تم إنجازه في الكود | شو تبقى لإتمامه بدقة |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| **NP-00** | بيئة الاختبار وخط الأساس الآمن | البنية التحتية / P0 | `implemented_unverified` | منع Runtime DDL، فحص syntax لكل PHP، سكربت `run_migrations.php` مع مطابقة Checksum | تجهيز بيئة staging معزولة، تشغيل suite تكامل متصل بـ MySQL و Redis |
|
||||||
|
| **NP-01** | إيقاف النجاح والمحتوى المصطنع | الأمان والمصداقية / P0 | `verified_in_code` | تعطيل الاعتماد التلقائي لكليك، تعطيل سحب الأرباح التقديري، إزالة التوليد في GET، رد صريح بـ `unavailable` | جرد تنظيف الجداول من أي بيانات demo قديمة بعد المطابقة اليدوية |
|
||||||
|
| **NP-02** | الهوية المنهجية وحزم الأصول | المناهج والمحتوى / P0 | `in_progress` | 13 مبحثاً (392 درس ماركداون + 371 مواصفة مختبر)، جداول `curriculum_lessons` و `content_assets` | مراجعة واعتماد أول حزمة نشر (Bundle) رسمية لـ 12 درساً نموذجياً وربط الـ PDF الرسمي |
|
||||||
|
| **NP-03** | حصة المعلم والاستبدال الذري | استوديو المعلم / P1 | `verified_in_code` | `TeacherSubmissionService` مع Preflight و Idempotency-Key وقفل المعاملات، وربط التحقق في `TeacherStudioCubit` وراية التنبيه بالنسخة المرشحة في الواجهة | اختبارات E2E لرفع الفيديو الفعلي ومطابقة الصوت |
|
||||||
|
| **NP-04** | تدقيق الفيديو والأسئلة السقراطية | الجودة الأكاديمية / P0 | `in_progress` | مشغل قراءة صارم، إيقاف التوليد في GET، فحص Checkpoints المنشورة فقط، عقد البرومبتات | ربط الـ Worker بتفريغ صوتي حقيقي وأدلة مرئية كاملة للحصص المنشورة |
|
||||||
|
| **NP-05** | اختيار المعلم (0 / 1 / متعدد) | تجربة الطالب / P1 | `implemented_unverified` | `TeacherSelectionSheet` بالفرز التنازلي للتقييم، تشغيل الـ UUID المختار، كشف المعلم المصرح فقط | ربط شجرة المنهج في التطبيق بهوية الدرس المنشور بعد تفعيل الـ Bundles |
|
||||||
|
| **NP-06** | دفتر الحسابات وحجز الرصيد | المحاسبة المالية / P0 | `implemented_unverified` | `TeacherLedgerService` بوحدة الفلس، قيود القيد المزدوج، حجز السحب الذري بـ Idempotency | تسوية الرصيد الافتتاحي وتدقيق الصلاحيات متعدية الحسابات لمنع IDOR |
|
||||||
|
| **NP-07** | قياس الدقائق المستحقة بالخادم | استحقاق المشاهدة / P1 | `implemented_unverified` | `WatchSessionService` مع فترات متصلة وحساب Server-side Delta ومقارنة زمن الخادم والعميل | اختبار الإجهاد وانقطاع الاتصال ومحاكاة التلاعب بسرعة المشغل |
|
||||||
|
| **NP-08** | توزيع الإيراد وكشف حساب المعلم | المالية والشفافية / P1 | `blocked_policy` | فصل أوعية الدخل (مدرسي / مستقل)، إيقاف افتراض أرباح من حجم المنصة ككل | **قرار تجاري معلق:** حسم سعر الدقيقة، ونسبة صندوق المعلمين، وفترة التسوية |
|
||||||
|
| **NP-09** | بوابة الدفع والبصمة والتحويل | الدفع المالي / P0 | `blocked_psp` | عزل مسارات كليك بوضع غير متاح بدلاً من المحاكاة الصورية والاحتيال | **تعاقد مصرفي معلق:** ربط PSP أردني معتمد، وبناء Webhooks موقعة، وبصمة الجهاز |
|
||||||
|
| **NP-10** | حزمة الإنجليزية والصوت الموحد | المناهج التفاعلية / P1 | `in_progress` | تطوير مختبر الإنجليزية، تنظيم ملفات الوحدات والقواعد، إزالة IPA التخميني | توفير ملفات الصوت البشري المعتمدة للمفردات والنصوص وربطها بروابط CDN |
|
||||||
|
| **NP-11** | إكمال حلقة التعلم ودفتر الأخطاء | التجربة التعليمية / P1 | `verified_in_code` | 18 مختبراً، نافذة التفكير، دورة التكرار المتباعد بمرحلتين (تثبيت + استرجاع 7 أيام) بالخادم والواجهة | ربط واجهات الواجبات المدرسية بنظام مهام وتكليفات المعلم |
|
||||||
|
| **NP-12** | المؤسسات والمديريات والإشراف | إدارة التعليم / P1 | `implemented_unverified` | لوحات SuperAdmin والمديريات بقراءة حقيقية، عزل أدوار الـ Middlewares، blind index | استيراد شعب المدارس الحكومية والخاصة واختبارات العزل التام بين المدارس |
|
||||||
|
| **NP-13** | إثبات الصف العاشر والإطلاق | بوابة الإطلاق النهائي | `gate_pending` | جاهزية التطبيقات الأربعة، مسار التدريب المهني (VTC)، صفحة الهبوط الفاخرة | إجراء التجربة الحية على 12 درساً للصف العاشر مع عينة حقيقية من المعلمين والطلبة |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. تفصيل كل نقطة: ما تم إنجازه وما تبقى منها بدقة
|
||||||
|
|
||||||
|
### [NP-00] خط الأساس وبيئة الاختبار الآمنة
|
||||||
|
* **الهدف:** توفير بيئة تشغيل آمنة، خالية من الأوامر المدمرة، ومعزولة عن قاعدة الإنتاج.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- إلغاء الـ Runtime DDL نهائياً في خدمات المناهج والمدفوعات والمشاهدة.
|
||||||
|
- إضافة `backend/scripts/run_migrations.php` كمنصة تحكم موحدة للملفات مع فحص الـ Checksum ومنع تكرار التنفيذ.
|
||||||
|
- فحص syntax لجميع ملفات الـ PHP في المشروع، وضمان خلو ملفات Dart من أخطاء الـ Compile.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] تشغيل بيئة Staging حقيقية متصلة بـ MySQL و Redis و Nabeh.
|
||||||
|
- [ ] كتابة Automated Integration Test Harness للـ Backend لا يعتمد على أطر عمل خارجية غير مثبتة.
|
||||||
|
- [ ] اختبار استعادة النسخة الاحتياطية وتأكيد سلامة الـ Rollback.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-01] إيقاف النجاح والمحتوى المصطنع (Truth in Core)
|
||||||
|
* **الهدف:** التخلص الكامل من أي إيهام بالنجاح المالي أو التعليمي، ومنع أي بيانات مزورة.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- دالة `CliqPaymentService::unavailable` تعطل فورياً اعتماد الإيصالات أو إنشاء حركات وهمية وتعيد رسالة صريحة للطالب والمعلم.
|
||||||
|
- دالة `TeacherController::getMonetizationDashboard` توقف الحسابات التقديرية التلقائية لدخل المعلم وتعرض الرصيد كغير متاح حتى اكتمال الربط.
|
||||||
|
- مسار `VideoController::getPlaybackData` أصبح للقراءة فقط (Read-only)، وتم منع توليد أو حذف أي أسئلة سقراطية أثناء طلب الـ GET.
|
||||||
|
- إزالة الـ Fallback الذي كان يعرض درساً بديلاً عند فقدان ملف الدرس المطلوب في `CurriculumController`.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] تدقيق سجلات قاعدة البيانات الحالية لعزل أي صفوف تجريبية (demo rows) قديمة وضمان عدم دخولها في أرصدة المعلمين.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-02] الهوية المنهجية وحزم الملفات (Curriculum Identity & Bundles)
|
||||||
|
* **الهدف:** تمييز كل درس بهوية ثابتة (الصف، المبحث، الفصل، الوحدة، الدرس، النسخة)، وربط الأصول كحزم نشر موثوقة.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- 13 مبحثاً كاملاً للصف العاشر في `backend/storage/curriculum/grade_10` تضم 392 ملف ماركداون.
|
||||||
|
- 371 وثيقة مواصفات للمختبرات الافتراضية في `docs/virtual_labs/grade_10`.
|
||||||
|
- تطبيق جدول `curriculum_lessons` وجدول `content_assets` وجدول `publication_bundles`.
|
||||||
|
- نقطة `GET /api/curriculum/assets/{assetId}` التي تخدم الأصول عبر UUID فقط دون تمرير مسارات ملفات من العميل.
|
||||||
|
- سكربت `publish_grade10_bundle.php` المخصص لنشر حزم الصف العاشر مع خيار `--pilot` للدروس الـ 12 النموذجية.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] مراجعة واعتماد الحزم المنشورة للدفعة الأولى ونقلها من حالة `draft` إلى `published`.
|
||||||
|
- [ ] رفع ملفات الـ PDF الرسمية للكتب وأوراق العمل وتخزينها في التخزين السيادي كأصول ذات Checksum.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-03] حصة المعلم والإصدار والاستبدال الذري
|
||||||
|
* **الهدف:** ضمان أن لكل معلم حصة أساسية واحدة منشورة لكل درس، وأن أي تسجيل جديد يكون نسخة مرشحة للاستبدال تخضع للفحص دون إيقاف الحصة القديمة.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- خدمة `TeacherSubmissionService` المزودة بـ Preflight، والتحقق من `Idempotency-Key` عبر SHA-256.
|
||||||
|
- قيد فريد في قاعدة البيانات للمعلم والدرس المنهجي لمنع الازدواجية.
|
||||||
|
- تسجيل النسخ المرشحة بحقل `replaces_video_version_id` وقفل المعاملات بـ `FOR UPDATE`.
|
||||||
|
- ربط خطوة التحقق المسبق (Preflight) داخل `apps/teacher_app/lib/logic/cubits/teacher_studio_cubit.dart` وتمرير معلمات الاستبدال ورقم النسخة.
|
||||||
|
- إضافة شريط التنبيه المرئي في واجهة الرفع `apps/teacher_app/lib/presentation/screens/tabs/teacher_studio_upload_tab.dart` لإعلام المعلم بصراحة: "نسخة مرشحة للاستبدال (إصدار X) — الحصة المنشورة الحالية تظل متاحة للطلاب حتى اجتياز الفحص".
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] اختبارات E2E لرفع الفيديو الفعلي ومطابقة الصوت الميداني.
|
||||||
|
- [ ] إشعار المعلم اللحظي عند انتهاء التدقيق البشري للنسخة المرشحة.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-04] تدقيق الفيديو والأسئلة السقراطية من الأدلة
|
||||||
|
* **الهدف:** لا يُنشر فيديو إلا بعد فحص أكاديمي وربط الأسئلة السقراطية بتوقيتات حقيقية وتفريغ صوتي موثق.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- صياغة وثيقة برومبتات التدقيق `VIDEO_REVIEW_AND_SOCRATIC_PROMPTS.md`.
|
||||||
|
- إنشاء جدول `video_review_jobs` وجدول `video_review_evidence`.
|
||||||
|
- إيقاف التوليد العشوائي للأسئلة واشتراط وجود أسئلة منشورة ومعتمدة فقط.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] ربط العامل الخلفي (`curriculum_worker.php` / `video_upload_worker.php`) بخدمة التفريغ الصوتي الفعلي.
|
||||||
|
- [ ] بناء شاشة مراجعة للمعلم تعرض تقرير الملاحظات مع التوقيت الدقيق لكل ملحوظة.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-05] اختيار المعلم (0 / 1 / متعدد)
|
||||||
|
* **الهدف:** تطبيق منطق صَقِل: صفر حصص = إظهار الموارد المتاحة بصدق، حصة واحدة = تشغيل مباشر، أكثر من حصة = قائمة بالتقييم الموثق.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- واجهة `TeacherSelectionSheet` في تطبيق الطالب بفرز تنازلي للتقييم الحقيقي وعدد التقييمات وشارة التوثيق.
|
||||||
|
- نقطة `GET /api/curriculum/lessons/{lessonId}/videos` التي تعيد فقط النسخ المنشورة والمصرح بها للطالب.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] ربط شجرة المنهج في واجهة الطالب (`subject_hub_screen.dart`) بالـ UUID المعتمد للحزم المنشورة عند توفرها.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-06] دفتر الحسابات المحاسبي وحجز الرصيد
|
||||||
|
* **الهدف:** نظام محاسبي صارم بوحدة الفلس (بدون فواصل عشرية عائمة)، وقيد مزدوج يمنع السحب المتجاوز للرصيد.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- خدمة `TeacherLedgerService` الداعمة لـ `balance` و `placeWithdrawalHold` و `releaseHold`.
|
||||||
|
- حجز السحب ذري (Atomic Transaction) يمنع طلبين متزامنين يتجاوزان الرصيد الفعلي.
|
||||||
|
- جداول `ledger_accounts` و `ledger_entries` و `teacher_withdrawal_holds`.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] تسوية الأرصدة الافتتاحية السابقة ومطابقتها قبل تفعيل أي قيد حي.
|
||||||
|
- [ ] تدقيق أمان الـ IDOR للتأكد من عدم وصول أي معلم لدفتر معلم آخر.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-07] قياس الدقائق المستحقة بالخادم
|
||||||
|
* **الهدف:** حساب دقائق المشاهدة المستحقة للدخل من خلال الخادم حصراً، دون الاعتماد على عداد الهاتف.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- خدمة `WatchSessionService` وجداول `watch_sessions` و `watch_events` و `eligible_watch_intervals`.
|
||||||
|
- التحقق من تسلسل الأحداث المتصلة (Sequence continuity)، ورفض القفزات غير المتصلة (Seek leaps).
|
||||||
|
- احتساب الفترات المؤهلة بمقارنة الفرق الزمني للخادم مع العميل وبحد أقصى دقيقة واحدة لكل Heartbeat.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] إجراء اختبارات تزامن لجلستي مشاهدة لنفس الطالب والتأكد من عدم احتساب الدقائق المزدوجة.
|
||||||
|
- [ ] معالجة حالات انقطاع الشبكة المفاجئ وإغلاق الجلسات المعلقة تلقائياً.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-08] توزيع الإيراد وكشف حساب المعلم
|
||||||
|
* **الهدف:** توزيع عادل لصافي الاشتراكات على دقائق المشاهدة المكتسبة وفق معادلة تجارية معلنة.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- عزل دخل المدارس (المشمول بالاتفاقيات المؤسسية) عن سوق الطلاب المستقلين.
|
||||||
|
- إيقاف الحسابات الصورية في لوحة المعلم وعرض حالة عدم التوفر بوضوح.
|
||||||
|
* **شو تبقى منها بدقة (محجوب بقرار تجاري):**
|
||||||
|
- [ ] **قرار تجاري ملزم:** تحديد سعر الدقيقة المؤهلة، ونسبة صندوق المعلمين، وسياسة الاسترداد.
|
||||||
|
- [ ] بناء سكربت الإغلاق الشهري (Monthly Period Close) وتوزيع الفلسات الناتجة حتمياً.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-09] مزود الدفع والبصمة والتحويل
|
||||||
|
* **الهدف:** ربط بوابة دفع وتحويل بنكية حقيقية في الأردن مع تأكيد العمليات بالبصمة البيومترية.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- إيقاف المحاكاة المصطنعة لخدمة كليك وحظر إنشاء إيصالات معتمدة دون تحقق.
|
||||||
|
* **شو تبقى منها بدقة (محجوب بتعاقد المزود):**
|
||||||
|
- [ ] التعاقد مع مزود دفع مصرفي / PSP أردني معتمد (مثل أورنج موني، زين كاش، أو بوابة بنكية).
|
||||||
|
- [ ] بناء Webhook موقع ومحمي ضد إعادة الإرسال (Replay attacks).
|
||||||
|
- [ ] إضافة تحدي البصمة (`local_auth`) على الهاتف قبل إرسال طلب السحب أو الاشتراك.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-10] حزمة الإنجليزية والصوت الموحد
|
||||||
|
* **الهدف:** تجربة لغة إنجليزية مطابقة لكتاب الصف العاشر المعتمد، خالية من التخمين وبصوت واضح.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- بناء مختبر الإنجليزية التفاعلي المتقدم `english_interactive_lab_view.dart`.
|
||||||
|
- تقسيم المحتوى إلى أتهيأ / أقرأ وأسمع / الكلمات / القاعدة / أتدرب.
|
||||||
|
- نقطة `GET /api/curriculum/lessons/{lessonId}/english-package` لقراءة الحزم المنشورة فقط.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] توريد التسجيلات الصوتية البشرية المعتمدة لنصوص وكلمات كتاب Action Pack 10.
|
||||||
|
- [ ] ربط ملفات الصوت بخادم الأصول السيادي (CDN).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-11] إكمال حلقة التعلم ودفتر الأخطاء
|
||||||
|
* **الهدف:** إغلاق حلقة التعليم: استراحة التفكير السقراطية، حل الواجبات، توثيق الأخطاء، والكويز العلاجي، واختبار التثبيت.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- 18 مختبراً تفاعلياً مدمجاً ومفحوصاً باختبارات Smoke (12 لغة عربية + 6 فيزياء).
|
||||||
|
- نافذة التفكير الإلزامي `ScaffoldedThinkingPauseSheet` (60 ثانية) مع التدرج المعرفي خطوة بخطوة.
|
||||||
|
- تطبيق دورة التكرار المتباعد بمرحلتين (Two-Stage Spaced Repetition) في `ErrorNotebookController.php`:
|
||||||
|
- المرحلة الأولى (التدريب العلاجي الأولي): ينتقل الخطأ من `pending_remediation` إلى `in_remediation` وتتم جدولة اختبار الاسترجاع بعد 7 أيام (`retention_scheduled_at = NOW() + 7 DAYS`).
|
||||||
|
- المرحلة الثانية (تحدي الاسترجاع والتثبيت): عند اجتياز الطالب للاختبار بعد اكتمال الفترة ينتقل إلى `mastered` مع تسجيل تاريخ الإتقان الفعلي.
|
||||||
|
- شاشة دفتر الأخطاء الذكي `SmartErrorNotebookScreen`: إضافة تبويبات التصفية بحسب الحالة (الكل، بانتظار المعالجة، قيد التثبيت 🌱، تم الإتقان ✨)، وصندوق إحصائي مستقل لقيد التثبيت، وزر خاص لبدء اختبار الاسترجاع والتثبيت المتباعد.
|
||||||
|
- منظومة ربط ولي الأمر المشروطة بموافقة صريحة من الطالب.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] ربط واجهات الواجبات المدرسية بنظام مهام وتكليفات المعلم.
|
||||||
|
- [ ] دفع إشعارات تذكير للطالب عند استحقاق موعد اختبار التثبيت (اليوم السابع).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-12] المؤسسات والمديريات والإشراف
|
||||||
|
* **الهدف:** إدارة شاملة للمدارس والمديريات مع عزل كامل للبيانات وحماية الخصوصية.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- لوحات الإدارة والسوبر أدمن تقرأ إحصاءات قاعدة البيانات الحقيقية.
|
||||||
|
- تشفير الرقم الوطني بـ AES-256-GCM مع فهرسة عمياء بـ HMAC.
|
||||||
|
- عزل الصلاحيات عبر الـ Middlewares لكل دور.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] بناء آلية استيراد شعب المدارس وقوائم الطلبة من ملفات Excel/CSV.
|
||||||
|
- [ ] اختبارات اختراق وعزل (IDOR multi-tenant isolation) لضمان عدم تسريب أي بيانات بين المدارس.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### [NP-13] بوابة إثبات الصف العاشر والإطلاق
|
||||||
|
* **الهدف:** تشغيل تجربة حية على 12 درساً نموذجياً تثبت نجاح الدورة التعليمية كاملة قبل التوسع.
|
||||||
|
* **ما تم إنجازه في الكود:**
|
||||||
|
- جاهزية أربعة تطبيقات Flutter متكاملة.
|
||||||
|
- صفحة هبوط رئيسية فاخرة بهندسة أبل (`index.html`).
|
||||||
|
- مسار التدريب المهني (VTC) لمركبات الكهرباء والسلامة المهنية.
|
||||||
|
* **شو تبقى منها بدقة:**
|
||||||
|
- [ ] تنفيذ تجربة الـ 12 درساً مع عينة مستخدمين فعلية (معلمون وطلبة وأولياء أمور).
|
||||||
|
- [ ] قياس الأثر التعليمي ونسبة استرجاع المفاهيم بعد أسبوع.
|
||||||
|
- [ ] اتخاذ قرار الإطلاق التجاري الرسمي.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. الخطوات المباشرة للتنفيذ الآن (Action Plan)
|
||||||
|
|
||||||
|
1. **الخطوة الأولى (تقني) — [تم الإنجاز]:** ربط خطوة التحقق المسبق (Preflight) وتنبيه النسخة المرشحة في استوديو المعلم داخل `apps/teacher_app`.
|
||||||
|
2. **الخطوة الثانية (تعليمي) — [تم الإنجاز]:** تطبيق خوارزمية التكرار المتباعد (المرحلتين: المعالجة الأولية + اختبار الاسترجاع والتثبيت بعد 7 أيام) في الخادم والواجهة.
|
||||||
|
3. **الخطوة الثالثة (محتوى) — [التركيز الحالي]:** فحص واعتماد حزمة الـ 12 درساً النموذجية للصف العاشر (`publish_grade10_bundle.php --pilot`) والتحقق من سلامة الأصول والربط.
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,455 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Tripz Egypt - Investor Pitch Deck</title>
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
size: A4 landscape;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
|
background: #0d1117;
|
||||||
|
color: #e6edf3;
|
||||||
|
}
|
||||||
|
.slide {
|
||||||
|
width: 297mm;
|
||||||
|
height: 210mm;
|
||||||
|
page-break-after: always;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 32mm 28mm;
|
||||||
|
background: radial-gradient(circle at 85% 15%, #1f293d 0%, #0d1117 70%);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.1);
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
.header .tag {
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #38bdf8;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.header .page-num {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 16px 0;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
letter-spacing: -0.5px;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #94a3b8;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.grid-2 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.grid-3 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.card h3 {
|
||||||
|
font-size: 17px;
|
||||||
|
color: #38bdf8;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
.card p {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #cbd5e1;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.metric {
|
||||||
|
font-size: 36px;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #38bdf8;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
.metric-sub {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #94a3b8;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #475569;
|
||||||
|
border-top: 1px solid rgba(255,255,255,0.06);
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
/* Slide 1 Cover */
|
||||||
|
.cover {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0 36mm;
|
||||||
|
}
|
||||||
|
.cover-badge {
|
||||||
|
background: rgba(56, 189, 248, 0.1);
|
||||||
|
color: #38bdf8;
|
||||||
|
padding: 6px 14px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border: 1px solid rgba(56, 189, 248, 0.3);
|
||||||
|
}
|
||||||
|
.cover h1 {
|
||||||
|
font-size: 52px;
|
||||||
|
font-weight: 900;
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
letter-spacing: -1.5px;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
.cover p {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #94a3b8;
|
||||||
|
max-width: 600px;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-bottom: 36px;
|
||||||
|
}
|
||||||
|
.cover-meta {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Slide 1: Cover -->
|
||||||
|
<div class="slide cover">
|
||||||
|
<div class="cover-badge">Confidential Investor Deck</div>
|
||||||
|
<h1>TRIPZ EGYPT</h1>
|
||||||
|
<p>Next-Generation Urban Mobility for Egypt — Driven by Proprietary Geospatial Infrastructure.</p>
|
||||||
|
<div class="cover-meta">Tripz Mobility Ltd. • tripz-egypt.com</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 2: The Problem -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Problem Statement</span>
|
||||||
|
<span class="page-num">02 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">The Ride-Hailing Deficit in Egypt</div>
|
||||||
|
<div class="subtitle">Incumbents struggle with hyper-local operational friction, escalating infrastructure costs, and driver retention.</div>
|
||||||
|
<div class="grid-3">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Surging Platform Take-Rates</h3>
|
||||||
|
<p>Legacy players impose up to 25-30% commissions on drivers, leading to driver dissatisfaction, off-app cancellations, and degraded user trust.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Crippling Mapping Costs</h3>
|
||||||
|
<p>Reliance on third-party commercial mapping APIs forces competitors to spend millions on licensing, directly eating into unit economics in low-ARPU markets.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Unreliable Urban Localization</h3>
|
||||||
|
<p>Cairo's dense urban layout suffers from poor routing accuracy, lack of informal landmark indexing, and inefficient dispatching algorithms.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 3: The Solution -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Solution</span>
|
||||||
|
<span class="page-num">03 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">Purpose-Built Urban Mobility</div>
|
||||||
|
<div class="subtitle">A full-stack ecosystem combining hyper-local dispatch with proprietary routing efficiency.</div>
|
||||||
|
<div class="grid-3">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Zero Map Licensing Burden</h3>
|
||||||
|
<p>Built completely on a custom self-hosted geospatial stack (OpenStreetMap vector tiles, custom routing engines), driving map API costs down to near zero.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Equitable Driver Economics</h3>
|
||||||
|
<p>Optimized platform overhead enables significantly lower driver commissions, securing higher driver availability, loyalty, and organic supply growth.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Localized Routing Engine</h3>
|
||||||
|
<p>Dynamic routing optimized specifically for local informal traffic choke-points, micro-corridors, and accurate pickup indexing across Greater Cairo.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 4: Market Opportunity -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Market Size</span>
|
||||||
|
<span class="page-num">04 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">Egypt: The Prime MENA Mobility Hub</div>
|
||||||
|
<div class="subtitle">Over 105 million citizens navigating crowded transit hubs daily.</div>
|
||||||
|
<div class="grid-3">
|
||||||
|
<div class="card">
|
||||||
|
<div class="metric">$2.1B+</div>
|
||||||
|
<div class="metric-sub">TAM (Total Addressable)</div>
|
||||||
|
<p style="margin-top: 10px;">Projected size of the Egyptian on-demand ride-hailing and shared mobility market by 2028.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="metric">25M+</div>
|
||||||
|
<div class="metric-sub">SAM (Serviceable Addressable)</div>
|
||||||
|
<p style="margin-top: 10px;">Urban population concentrated across Greater Cairo, Alexandria, and Giza requiring frequent point-to-point transit.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="metric">12% CAGR</div>
|
||||||
|
<div class="metric-sub">Market Growth</div>
|
||||||
|
<p style="margin-top: 10px;">Fueled by smartphone penetration, young demographics, and rising demand for reliable private urban transport.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 5: Product & Tech Stack -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Technology Moat</span>
|
||||||
|
<span class="page-num">05 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">Engineered for Scalability & Margin Dominance</div>
|
||||||
|
<div class="subtitle">A full-suite native ecosystem built to scale without linear API expense.</div>
|
||||||
|
<div class="grid-2">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Self-Hosted Geospatial Infrastructure</h3>
|
||||||
|
<p>Vector tile server hosting, customized routing graphs, and offline-resilient dispatching. Frees Tripz from Google Maps / Mapbox tier pricing, protecting margins as ride volume explodes.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Integrated 4-Tier Application Suite</h3>
|
||||||
|
<p>Custom-engineered Rider App, Driver App, Enterprise Fleet Portal, and Real-time Operations Dashboard delivering sub-second dispatch telemetry.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 6: Business Model -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Business Model</span>
|
||||||
|
<span class="page-num">06 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">Clear, Predictable Monetization</div>
|
||||||
|
<div class="subtitle">Structured to maximize operator retention while delivering sustainable contribution margins.</div>
|
||||||
|
<div class="grid-3">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Commission Per Ride</h3>
|
||||||
|
<p>Fair, competitive take-rate on completed rides, creating immediate cash-flow while maintaining driver earnings above market median.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Fleet & Corporate Subscriptions</h3>
|
||||||
|
<p>Scheduled commutes and corporate logistics contracts offering recurring enterprise revenue streams.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Geospatial Data & In-App Ads</h3>
|
||||||
|
<p>High-intent, geo-targeted localized promotions and verified point-of-interest discovery within the passenger navigation interface.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 7: Traction & Milestones -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Execution & Traction</span>
|
||||||
|
<span class="page-num">07 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">From Architectural Validation to Live Operations</div>
|
||||||
|
<div class="subtitle">Validated under demanding regional real-world conditions.</div>
|
||||||
|
<div class="grid-3">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Production-Ready Ecosystem</h3>
|
||||||
|
<p>Fully functional, deployed Rider and Driver platforms compliant with regional operational standards.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Proven Geospatial Stability</h3>
|
||||||
|
<p>Proprietary map server infrastructure handling thousands of concurrent routing calculations without downtime or commercial API latency.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Driver Acquisition Pipeline</h3>
|
||||||
|
<p>Pre-onboarded initial fleet partners ready for deployment across core high-density corridors in Cairo.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 8: Competitive Landscape -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Competition</span>
|
||||||
|
<span class="page-num">08 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">Defensible Differentiation</div>
|
||||||
|
<div class="subtitle">Outperforming incumbents on unit margins and regional adaptability.</div>
|
||||||
|
<div class="grid-3">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Incumbent Platforms</h3>
|
||||||
|
<p>High corporate overhead, expensive API reliance, rigid pricing models, and high commission rates creating driver churn.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Local Budget Players</h3>
|
||||||
|
<p>Fragile infrastructure, third-party white-label software, and poor routing reliability resulting in elevated ride cancellations.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card" style="border-color: #38bdf8;">
|
||||||
|
<h3>Tripz Advantage</h3>
|
||||||
|
<p>Proprietary map infrastructure, lean cost footprint, superior driver net earnings, and algorithmic dispatch designed for Cairo streets.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 9: Go-To-Market Strategy -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Go-To-Market</span>
|
||||||
|
<span class="page-num">09 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">Targeted Corridor Domination</div>
|
||||||
|
<div class="subtitle">Avoiding diffuse spend by conquering targeted high-frequency urban routes first.</div>
|
||||||
|
<div class="grid-3">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Phase 1: High-Density Nodes</h3>
|
||||||
|
<p>Launch in dense suburban-to-hub commutes (e.g., New Cairo, 6th of October, Nasr City) to guarantee immediate liquidity and short pickup times.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Phase 2: Driver Referral Flywheel</h3>
|
||||||
|
<p>Capitalize on driver community networks through zero-commission grace periods and transparent weekly payout guarantees.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Phase 3: B2B Partnerships</h3>
|
||||||
|
<p>Direct tie-ups with university campuses, enterprise parks, and residential compounds for exclusive transit corridors.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 10: Financial Projections -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Economics & Projections</span>
|
||||||
|
<span class="page-num">10 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">Disciplined Capital Efficiency</div>
|
||||||
|
<div class="subtitle">Lean architectural overhead yields an accelerated path to contribution margin positive.</div>
|
||||||
|
<div class="grid-3">
|
||||||
|
<div class="card">
|
||||||
|
<h3>High Gross Margins</h3>
|
||||||
|
<p>Eliminating $0.05–$0.15 per-ride map licensing fees significantly expands net take-home margins per ride.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Scalable Cost Structure</h3>
|
||||||
|
<p>Cloud server and routing infrastructure scales sub-linearly with volume, decoupling operational scale from tech costs.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Low CAC Through B2B Nodes</h3>
|
||||||
|
<p>Strategic campus and business district hubs drive high passenger conversion at a fraction of traditional digital ad spend.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 11: Leadership & Engineering -->
|
||||||
|
<div class="slide">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tag">Team & Execution</span>
|
||||||
|
<span class="page-num">11 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">Deep Technical & Operational Domain Expertise</div>
|
||||||
|
<div class="subtitle">Led by operators with proven track records in real-time dispatch and GIS infrastructure.</div>
|
||||||
|
<div class="grid-2">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Geospatial & Systems Architecture</h3>
|
||||||
|
<p>Extensive experience designing real-time, low-latency mobile dispatch ecosystems, distributed server infrastructure, and localized map engines across MENA.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>On-the-Ground Market Operators</h3>
|
||||||
|
<p>Deep familiarity with local regulatory standards, driver operational dynamics, and fleet management nuances in the Egyptian transit sector.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer"><span>Tripz Egypt</span><span>Investment Deck</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 12: The Ask & Contact -->
|
||||||
|
<div class="slide cover">
|
||||||
|
<div class="header" style="width: 100%; position: absolute; top: 32mm; left: 28mm; right: 28mm;">
|
||||||
|
<span class="tag">The Opportunity</span>
|
||||||
|
<span class="page-num">12 / 12</span>
|
||||||
|
</div>
|
||||||
|
<div class="title" style="margin-top: 40px;">Join Us in Reshaping Urban Mobility</div>
|
||||||
|
<p>We are opening strategic investor conversations to accelerate market deployment, driver onboarding, and corridor dominance in Cairo.</p>
|
||||||
|
<div class="grid-2" style="width: 100%; max-width: 650px;">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Contact Management</h3>
|
||||||
|
<p>Hamza Ayed — Founder & Chief Architect<br>Email: hamza@tripz-egypt.com</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>Online Presence</h3>
|
||||||
|
<p>Platform: tripz-egypt.com<br>Location: Cairo, Egypt</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer" style="width: calc(100% - 56mm); position: absolute; bottom: 20mm; left: 28mm;">
|
||||||
|
<span>Tripz Egypt • Confidential</span>
|
||||||
|
<span>2026</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+141
-2207
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user