Files
maps-saas/apps/dashboard/tourism.html
T

3954 lines
108 KiB
HTML

<!doctype html>
<html lang="ar" dir="rtl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#061d42">
<meta name="description" content="منصة سيرو ماب الجغرافية السياحية: خريطة سياحية سيادية نقية خالية من خطوط الكنتور والضجيج السكني، مع فصل مكاني رباعي للنواة وبوابات العبور ومواقف المركبات.">
<title>خريطة سيرو ماب السياحية والتراثية — الخريطة السيادية النقية</title>
<link rel="icon" type="image/png" href="assets/siro-maps.png">
<!-- MapLibre GL JS & CSS -->
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@5.2.0/dist/maplibre-gl.css">
<script src="https://unpkg.com/maplibre-gl@5.2.0/dist/maplibre-gl.js"></script>
<!-- Google Fonts: Tajawal & IBM Plex Sans Arabic -->
<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=IBM+Plex+Sans+Arabic:wght@400;500;600;700;800&family=Tajawal:wght@500;700;800;900&display=swap" rel="stylesheet">
<style>
:root {
--sand-bg: #FAF6F0;
--navy: #061d42;
--navy-dark: #04142d;
--blue: #124f9f;
--gold: #d4af37;
--gold-dark: #b59247;
--gold-light: #fef08a;
--ink: #0f172a;
--muted: #64748b;
--line: rgba(255, 255, 255, 0.12);
--font: 'IBM Plex Sans Arabic', 'Tajawal', system-ui, -apple-system, sans-serif;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { width: 100%; height: 100%; overflow: hidden; background: var(--sand-bg); font-family: var(--font); color: var(--ink); }
#map { width: 100%; height: 100%; position: absolute; top: 0; bottom: 0; right: 0; left: 0; }
/* Sovereign Header */
.sovereign-header {
position: absolute;
top: 16px;
right: 16px;
left: 16px;
z-index: 50;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
pointer-events: none;
}
.brand-glass {
pointer-events: auto;
background: rgba(6, 29, 66, 0.92);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
border: 1px solid rgba(212, 175, 55, 0.35);
border-radius: 16px;
padding: 8px 18px;
display: flex;
align-items: center;
gap: 12px;
box-shadow: 0 10px 35px rgba(0, 0, 0, 0.4);
}
.brand-icon {
width: 38px;
height: 38px;
border-radius: 10px;
background: linear-gradient(135deg, #d4af37, #854d0e);
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
color: #fff;
box-shadow: 0 0 16px rgba(212, 175, 55, 0.4);
}
.brand-title { color: #fff; font-weight: 800; font-size: 1rem; line-height: 1.2; }
.brand-badge {
font-size: 10px;
background: rgba(212, 175, 55, 0.2);
color: #fde047;
border: 1px solid rgba(212, 175, 55, 0.5);
padding: 1px 6px;
border-radius: 4px;
font-weight: 700;
margin-right: 6px;
}
.brand-subtitle { color: #94a3b8; font-size: 0.72rem; margin-top: 2px; }
/* Search & Filter Bar */
.control-glass {
pointer-events: auto;
background: rgba(6, 29, 66, 0.92);
backdrop-filter: blur(24px);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 16px;
padding: 6px 12px;
display: flex;
align-items: center;
gap: 8px;
box-shadow: 0 10px 35px rgba(0, 0, 0, 0.35);
}
.search-box {
position: relative;
display: flex;
align-items: center;
}
.search-box input {
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 9px;
padding: 6px 30px 6px 12px;
color: #fff;
font-size: 0.82rem;
font-family: inherit;
outline: none;
width: 220px;
transition: border-color 0.2s;
}
.search-box input:focus { border-color: var(--gold); }
.search-icon { position: absolute; right: 9px; font-size: 13px; color: #94a3b8; }
.country-tabs { display: flex; gap: 4px; }
.country-btn {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
color: #cbd5e1;
padding: 6px 11px;
border-radius: 9px;
font-size: 0.78rem;
font-weight: 600;
font-family: inherit;
cursor: pointer;
transition: all 0.2s;
}
.country-btn:hover { background: rgba(255, 255, 255, 0.12); }
.country-btn.active {
background: linear-gradient(135deg, #d4af37, #996515);
color: #fff;
border-color: #d4af37;
box-shadow: 0 2px 10px rgba(212, 175, 55, 0.4);
}
/* Category Chips */
.category-bar {
position: absolute;
top: 80px;
right: 16px;
z-index: 40;
display: flex;
gap: 6px;
overflow-x: auto;
max-width: calc(100% - 32px);
padding-bottom: 4px;
}
.cat-chip {
background: rgba(255, 255, 255, 0.94);
backdrop-filter: blur(16px);
border: 1px solid rgba(0, 0, 0, 0.08);
color: #334155;
padding: 6px 13px;
border-radius: 20px;
font-size: 0.78rem;
font-weight: 700;
font-family: inherit;
cursor: pointer;
display: flex;
align-items: center;
gap: 6px;
white-space: nowrap;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
transition: all 0.2s;
}
.cat-chip:hover { transform: translateY(-1px); }
.cat-chip.active {
background: var(--navy);
color: #facc15;
border-color: #facc15;
box-shadow: 0 4px 15px rgba(6, 29, 66, 0.25);
}
/* Bottom Slider of Landmarks */
.landmark-slider {
position: absolute;
bottom: 20px;
right: 16px;
z-index: 40;
display: flex;
gap: 12px;
overflow-x: auto;
max-width: calc(100% - 32px);
padding: 6px 4px;
}
.slider-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border: 2px solid rgba(255, 255, 255, 0.8);
border-radius: 16px;
padding: 10px;
width: 230px;
min-width: 230px;
cursor: pointer;
display: flex;
align-items: center;
gap: 10px;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
transition: all 0.2s ease;
}
.slider-card:hover {
transform: translateY(-3px);
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.15);
border-color: var(--gold);
}
.slider-card.active {
background: rgba(6, 29, 66, 0.96);
color: #fff;
border-color: #d4af37;
box-shadow: 0 10px 30px rgba(212, 175, 55, 0.35);
}
.slider-img {
width: 54px;
height: 54px;
border-radius: 12px;
object-fit: cover;
flex-shrink: 0;
}
.slider-info { overflow: hidden; flex: 1; }
.slider-title {
font-weight: 800;
font-size: 0.84rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.slider-meta { font-size: 0.72rem; color: var(--muted); margin-top: 3px; }
.slider-card.active .slider-meta { color: #94a3b8; }
/* Legend Box (Decoupled 4-Points) */
.legend-box {
position: absolute;
bottom: 100px;
left: 16px;
z-index: 30;
background: rgba(6, 29, 66, 0.92);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 14px;
padding: 12px 16px;
color: #fff;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
font-size: 0.74rem;
max-width: 250px;
}
.legend-title { font-weight: 800; color: #facc15; margin-bottom: 8px; }
.legend-item { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.legend-dot { width: 9px; height: 9px; border-radius: 50%; }
/* Modal / Drawer for Selected Landmark */
.landmark-drawer {
position: absolute;
top: 16px;
right: 16px;
bottom: 16px;
width: 440px;
max-width: calc(100vw - 32px);
background: rgba(255, 255, 255, 0.98);
backdrop-filter: blur(30px);
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 24px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
z-index: 60;
display: flex;
flex-direction: column;
overflow: hidden;
animation: slideInRight 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes slideInRight {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.drawer-header {
position: relative;
height: 240px;
background: #061d42;
flex-shrink: 0;
}
.drawer-header img {
width: 100%;
height: 100%;
object-fit: cover;
}
.drawer-close {
position: absolute;
top: 14px;
left: 14px;
background: rgba(0, 0, 0, 0.6);
color: #fff;
border: none;
width: 32px;
height: 32px;
border-radius: 50%;
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.drawer-gallery-counter {
position: absolute;
bottom: 12px;
right: 14px;
background: rgba(0, 0, 0, 0.65);
color: #fff;
font-size: 0.72rem;
font-weight: 700;
padding: 3px 9px;
border-radius: 12px;
direction: ltr;
}
.drawer-content {
flex: 1;
overflow-y: auto;
padding: 20px;
}
.drawer-title { font-size: 1.3rem; font-weight: 800; color: var(--navy); line-height: 1.3; }
.drawer-subtitle { font-size: 0.85rem; color: var(--muted); margin-top: 4px; }
.drawer-badges { display: flex; gap: 6px; flex-wrap: wrap; margin: 14px 0; }
.badge {
background: #f1f5f9;
border: 1px solid #e2e8f0;
color: #475569;
font-size: 0.74rem;
padding: 3px 9px;
border-radius: 6px;
font-weight: 700;
}
.badge.gold {
background: rgba(212, 175, 55, 0.15);
border-color: rgba(212, 175, 55, 0.4);
color: #854d0e;
}
.drawer-narrative {
font-size: 0.88rem;
line-height: 1.8;
color: #334155;
background: #fafaf9;
border-right: 3px solid var(--gold);
padding: 12px 16px;
border-radius: 0 10px 10px 0;
margin-bottom: 18px;
}
.drawer-meta-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-bottom: 20px;
}
.meta-box {
background: #f8fafc;
border: 1px solid #e2e8f0;
padding: 10px;
border-radius: 10px;
}
.meta-box-label { font-size: 0.7rem; color: var(--muted); }
.meta-box-val { font-size: 0.82rem; font-weight: 700; color: var(--ink); margin-top: 2px; }
.nav-gate-btn {
width: 100%;
background: linear-gradient(135deg, #124f9f, #0071e3);
color: #fff;
border: none;
padding: 12px;
border-radius: 12px;
font-size: 0.95rem;
font-weight: 800;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
box-shadow: 0 6px 20px rgba(18, 79, 159, 0.35);
transition: all 0.2s;
}
.nav-gate-btn:hover { background: linear-gradient(135deg, #0f4082, #005bb5); transform: translateY(-1px); }
/* Custom MapLibre Marker Styles */
.marker-centroid {
width: 36px;
height: 36px;
border-radius: 50%;
background: linear-gradient(135deg, #f59e0b, #d97706);
border: 3px solid #fff;
box-shadow: 0 4px 15px rgba(217, 119, 6, 0.6);
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
cursor: pointer;
transition: transform 0.2s;
}
.marker-centroid:hover { transform: scale(1.2); }
.marker-gate {
width: 26px;
height: 26px;
border-radius: 50%;
background: #06b6d4;
border: 2px solid #fff;
box-shadow: 0 2px 8px rgba(6, 182, 212, 0.6);
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
cursor: pointer;
}
.marker-parking {
width: 24px;
height: 24px;
border-radius: 6px;
background: #8b5cf6;
border: 2px solid #fff;
box-shadow: 0 2px 8px rgba(139, 92, 246, 0.6);
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
color: #fff;
font-weight: 800;
cursor: pointer;
}
.marker-ticket {
width: 24px;
height: 24px;
border-radius: 50%;
background: #10b981;
border: 2px solid #fff;
box-shadow: 0 2px 8px rgba(16, 185, 129, 0.6);
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
cursor: pointer;
}
/* Sovereign In-App Navigation HUD */
.sovereign-nav-hud {
position: absolute;
top: 80px;
left: 50%;
transform: translateX(-50%);
z-index: 70;
background: rgba(6, 29, 66, 0.96);
backdrop-filter: blur(25px);
-webkit-backdrop-filter: blur(25px);
border: 2px solid #06b6d4;
border-radius: 18px;
padding: 14px 20px;
color: #fff;
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.45);
width: 480px;
max-width: calc(100vw - 32px);
animation: fadeInDown 0.3s ease;
}
@keyframes fadeInDown { from { opacity: 0; transform: translate(-50%, -15px); } to { opacity: 1; transform: translate(-50%, 0); } }
.nav-hud-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.nav-hud-title { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 0.88rem; color: #38bdf8; }
.pulse-dot { width: 8px; height: 8px; border-radius: 50%; background: #22c55e; box-shadow: 0 0 10px #22c55e; display: inline-block; }
.nav-hud-close { background: rgba(239, 68, 68, 0.2); border: 1px solid rgba(239, 68, 68, 0.5); color: #fca5a5; padding: 4px 10px; border-radius: 8px; cursor: pointer; font-size: 0.74rem; font-weight: 700; }
.nav-hud-close:hover { background: rgba(239, 68, 68, 0.4); }
.nav-dest-info { font-size: 0.84rem; color: #f1f5f9; margin-bottom: 8px; }
.dest-label { color: var(--gold); font-weight: 700; margin-left: 4px; }
.nav-stats { display: flex; gap: 8px; margin-bottom: 10px; }
.stat-pill { background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.12); padding: 5px 12px; border-radius: 8px; display: flex; gap: 4px; align-items: baseline; }
.stat-val { font-weight: 800; font-size: 0.95rem; color: #facc15; }
.stat-lbl { font-size: 0.7rem; color: #94a3b8; }
.nav-step { font-size: 0.78rem; background: rgba(6, 182, 212, 0.12); border: 1px solid rgba(6, 182, 212, 0.3); color: #a5f3fc; padding: 7px 12px; border-radius: 8px; }
</style>
</head>
<body>
<div id="map"></div>
<!-- Sovereign Header -->
<header class="sovereign-header">
<div class="brand-glass">
<div class="brand-icon">🏛️</div>
<div>
<div class="brand-title">
منصة سيرو ماب الجغرافية السياحية
<span class="brand-badge">نسخة سيادية مستقلة</span>
</div>
<div class="brand-subtitle">
خريطة التراث العربي بدون خطوط كنتور • فصل مساحي محقق WGS84
</div>
</div>
</div>
<div class="control-glass">
<div class="search-box">
<span class="search-icon">🔍</span>
<input type="text" id="searchInput" placeholder="ابحث عن معلم، حضارة، أو مدينة...">
</div>
<div class="country-tabs">
<button class="country-btn active" data-country="all">الكل</button>
<button class="country-btn" data-country="العراق">🇮🇶 العراق</button>
<button class="country-btn" data-country="الأردن">🇯🇴 الأردن</button>
<button class="country-btn" data-country="سوريا">🇸🇾 سوريا</button>
<button class="country-btn" data-country="مصر">🇪🇬 مصر</button>
</div>
</div>
</header>
<!-- Category Bar -->
<div class="category-bar">
<button class="cat-chip active" data-cat="all">🌍 كافة المعالم</button>
<button class="cat-chip" data-cat="archaeological_site">🏛️ مواقع أثرية</button>
<button class="cat-chip" data-cat="historic_shrine">🕌 أضرحة ومقامات</button>
<button class="cat-chip" data-cat="religious_heritage">⛪ أديرة وتراث ديني</button>
<button class="cat-chip" data-cat="historic_palace">🏰 قصور وقلاع</button>
<button class="cat-chip" data-cat="monument">🗿 صروح تاريخية</button>
<button class="cat-chip" data-cat="museum">🏺 متاحف سيادية</button>
</div>
<!-- Bottom Landmark Slider -->
<div class="landmark-slider" id="landmarkSlider"></div>
<!-- Decoupled 4-Points Legend -->
<div class="legend-box">
<div class="legend-title">🛡️ الفصل الطوبولوجي الرباعي</div>
<div class="legend-item">
<div class="legend-dot" style="background: #f59e0b; box-shadow: 0 0 6px #f59e0b;"></div>
<span>النواة الأثرية (Centroid) - حمى محمي</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #06b6d4; box-shadow: 0 0 6px #06b6d4;"></div>
<span>بوابة العبور (Gate) - بدء مسار المشاة</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #8b5cf6; box-shadow: 0 0 6px #8b5cf6;"></div>
<span>موقف المركبات (Parking) - نهاية السيارات</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #10b981; box-shadow: 0 0 6px #10b981;"></div>
<span>مكتب التذاكر (Ticket Office) - الاستقبال</span>
</div>
</div>
<!-- Detailed Landmark Drawer -->
<div class="landmark-drawer" id="landmarkDrawer" style="display: none;">
<div class="drawer-header">
<button class="drawer-close" id="drawerCloseBtn">✕</button>
<img id="drawerImage" src="" alt="">
<div class="drawer-gallery-counter" id="drawerCounter">1 / 3</div>
</div>
<div class="drawer-content">
<h2 class="drawer-title" id="drawerTitle"></h2>
<div class="drawer-subtitle" id="drawerSubtitle"></div>
<div class="drawer-badges" id="drawerBadges"></div>
<div class="drawer-narrative" id="drawerNarrative"></div>
<div class="drawer-meta-grid">
<div class="meta-box">
<div class="meta-box-label">الجهة المشرفة والوصية</div>
<div class="meta-box-val" id="drawerCurator">الهيئة العامة للآثار</div>
</div>
<div class="meta-box">
<div class="meta-box-label">ساعات الاستقبال والزيارة</div>
<div class="meta-box-val" id="drawerHours">08:00 - 17:00</div>
</div>
</div>
<button class="nav-gate-btn" id="drawerNavBtn">
<span>🚗</span>
<span>بدء التوجيه الملاحي إلى بوابة العبور المخصصة</span>
</button>
</div>
</div>
<!-- Sovereign In-App Navigation HUD -->
<div id="sovereignNavHud" class="sovereign-nav-hud" style="display: none;">
<div class="nav-hud-header">
<div class="nav-hud-title">
<span class="pulse-dot"></span>
<span>🚗 مسار التوجيه الملاحي السيادي (محرك سيرو المستقل)</span>
</div>
<button class="nav-hud-close" id="stopNavBtn">✕ إنهاء التوجيه ومسح المسار</button>
</div>
<div class="nav-hud-body">
<div class="nav-dest-info">
<span class="dest-label">نقطة الوصول:</span>
<strong id="navDestName">بوابة العبور ومواقف الحافلات</strong>
</div>
<div class="nav-stats">
<div class="stat-pill"><span class="stat-val" id="navDistance">0</span> <span class="stat-lbl">كم</span></div>
<div class="stat-pill"><span class="stat-val" id="navEta">0</span> <span class="stat-lbl">دقيقة</span></div>
<div class="stat-pill"><span class="stat-val">محرك سيادي</span> <span class="stat-lbl">GraphHopper</span></div>
</div>
<div class="nav-step" id="navInstruction">🛣️ اسلك المسار المضاء مباشرة نحو بوابة العبور ومواقف الحافلات المخصصة</div>
</div>
</div>
<script>
const SOVEREIGN_MAP_API_KEY = 'zP9vL5mK2nQ8xR7jT4wS1yB6hG3fV0cX';
// 100% Verified Premier Landmarks Dataset (Iraq, Jordan, Syria, Egypt)
let LANDMARKS = [
{
slug: 'babylon-ishtar-gate',
name_ar: 'مدينة بابل الأثرية وبوابة عشتار',
name_en: 'Ancient City of Babylon and Ishtar Gate',
country: 'العراق',
governorate: 'بابل',
category: 'archaeological_site',
era: 'البابلي الحديث / Neo-Babylonian',
narrative: 'شيدت بابل في عهد الملك نبوخذ نصر الثاني خلال القرن السادس قبل الميلاد لتكون عاصمة الإمبراطورية البابلية الحديثة ومركزاً كونياً للعمارة والعلوم والتخطيط الحضري المبكر في بلاد الرافدين. يضم الموقع شارع الموكب الفخم، وأساسات بوابة عشتار المزججة، وقصور بابل الملكية وأسوارها الشاهقة.',
centroid: [44.4210, 32.5422],
gate: [44.4265, 32.5358],
parking: [44.4272, 32.5352],
ticket: [44.4262, 32.5361],
image: 'https://upload.wikimedia.org/wikipedia/commons/7/78/Ishtar_Gate_Babylon_Iraq.jpg',
unesco: 'اليونسكو #278 (2019)',
curator: 'الهيئة العامة للآثار والتراث (SBAH)',
hours: '08:30 - 17:30 يومياً'
},
{
slug: 'ziggurat-of-ur',
name_ar: 'زقورة أور الكبرى ومجمع تل المقير',
name_en: 'Great Ziggurat of Ur and Tell al-Muqayyar',
country: 'العراق',
governorate: 'ذي قار',
category: 'archaeological_site',
era: 'السومري - سلالة أور الثالثة',
narrative: 'شيد الملك السومري أور-نامو زقورة أور في القرن الحادي والعشرين قبل الميلاد لتكون معبداً مقدساً مكرساً للإله نانا في عاصمة سلالة أور الثالثة وموطن النبي إبراهيم عليه السلام. درة العمارة الدينية الرافدينية المصنوعة من قوالب الآجر المحروق المرصوف بالقار.',
centroid: [46.1031, 30.9628],
gate: [46.1065, 30.9642],
parking: [46.1075, 30.9650],
ticket: [46.1068, 30.9645],
image: 'https://upload.wikimedia.org/wikipedia/commons/6/69/Ziggarat_of_Ur_001.jpg',
unesco: 'اليونسكو #1481 (2016)',
curator: 'الهيئة العامة للآثار والتراث (SBAH)',
hours: '08:00 - 17:00 يومياً'
},
{
slug: 'erbil-citadel',
name_ar: 'قلعة أربيل التاريخية',
name_en: 'Erbil Citadel',
country: 'العراق',
governorate: 'أربيل',
category: 'archaeological_site',
era: 'ما قبل التاريخ إلى العثماني',
narrative: 'إحدى أقدم المستوطنات البشرية المأهولة بشكل متواصل في التاريخ؛ إذ ترتفع لنحو 30 متراً فوق سهل أربيل مشكلة تلاً بيضاوياً ناتجاً عن تراكم الطبقات الأثرية لأكثر من 6,000 عام.',
centroid: [44.0091, 36.1910],
gate: [44.0092, 36.1895],
parking: [44.0086, 36.1884],
ticket: [44.0093, 36.1898],
image: 'https://upload.wikimedia.org/wikipedia/commons/e/eb/Erbil_Citadel.jpg',
unesco: 'اليونسكو #1437 (2014)',
curator: 'المفوضية العليا لإحياء قلعة أربيل (HCECR)',
hours: '09:00 - 18:00 يومياً'
},
{
slug: 'samarra-great-mosque-malwiya',
name_ar: 'جامع سامراء الكبير والمئذنة الملوية',
name_en: 'Great Mosque of Samarra & Malwiya Minaret',
country: 'العراق',
governorate: 'صلاح الدين',
category: 'monument',
era: 'العباسي / Abbasid (851م)',
narrative: 'شيد الخليفة العباسي المتوكل على الله جامع سامراء الكبير ومئذنته الملوية الفريدة ليكون أكبر مسجد في العالم الإسلامي آنذاك، وتنفرد المئذنة بتصميمها المخروطي الحلزوني المرتفع 52 متراً.',
centroid: [43.8805, 34.2072],
gate: [43.8798, 34.2058],
parking: [43.8792, 34.2052],
ticket: [43.8801, 34.2060],
image: 'https://upload.wikimedia.org/wikipedia/commons/4/4c/Great_Mosque_of_Samarra.jpg',
unesco: 'اليونسكو #276 (2007)',
curator: 'الهيئة العامة للآثار والتراث (SBAH)',
hours: '08:00 - 18:00 يومياً'
},
{
slug: 'hatra-sun-temple',
name_ar: 'مدينة الحضر الأثرية ومعبد الشمس',
name_en: 'Hatra Ruins and Temple of the Sun',
country: 'العراق',
governorate: 'نينوى',
category: 'archaeological_site',
era: 'الفرثي والحضري / Parthian',
narrative: 'عاصمة أول مملكة عربية موثقة في التاريخ، صمدت أسوارها الدائرية المزدوجة أمام حصارات الأباطرة الرومان تراجان وسيبتيموس سيفيروس، وتضم معابد فخمة تمزج بين الفنون الهلنستية والشرقية.',
centroid: [42.7163, 35.5898],
gate: [42.7190, 35.5925],
parking: [42.7202, 35.5935],
ticket: [42.7195, 35.5928],
image: 'https://upload.wikimedia.org/wikipedia/commons/0/0e/Hatra-71339.jpg',
unesco: 'اليونسكو #277 (1985)',
curator: 'الهيئة العامة للآثار والتراث (SBAH)',
hours: '08:30 - 16:30 يومياً'
},
{
slug: 'ashur-qal-at-sherqat',
name_ar: 'مدينة آشور الأثرية وقلعة الشرقاط',
name_en: "Ancient City of Ashur and Qal'at Sherqat",
country: 'العراق',
governorate: 'صلاح الدين',
category: 'archaeological_site',
era: 'الآشوري / Assyrian',
narrative: 'أول عاصمة للإمبراطورية الآشورية والمهد الروحي للإله القومي آشور على جرف صخري يطل على نهر دجلة، تضم الزقورة الكبرى ومعابد أنو وأدد وأسواراً دفاعية مهيبة.',
centroid: [43.2612, 35.4567],
gate: [43.2568, 35.4542],
parking: [43.2555, 35.4535],
ticket: [43.2563, 35.4540],
image: 'https://upload.wikimedia.org/wikipedia/commons/3/30/Ashur_%28Qal%27at_Sherqat%29-115186.jpg',
unesco: 'اليونسكو #1130 (2003)',
curator: 'الهيئة العامة للآثار والتراث (SBAH)',
hours: '08:30 - 16:30 يومياً'
},
{
slug: 'uruk-warka',
name_ar: 'مدينة أوروك الأثرية (الوركاء)',
name_en: 'Ancient City of Uruk (Warka)',
country: 'العراق',
governorate: 'المثنى',
category: 'archaeological_site',
era: 'السومري - عصر الوركاء (الألف الرابع ق.م)',
narrative: 'مهد الحضارة والتحضر الإنساني وأول مدينة في التاريخ شهدت اختراع الكتابة المسمارية ومملكة الملك الأسطوري جلجامش، وتضم المعبد الأبيض وزقورة الإله آنو.',
centroid: [45.6358, 31.3222],
gate: [45.6265, 31.3145],
parking: [45.6258, 31.3140],
ticket: [45.6268, 31.3148],
image: 'https://upload.wikimedia.org/wikipedia/commons/1/1f/Uruk_Archaeological_site_at_Warka.jpg',
unesco: 'اليونسكو #1481 (2016)',
curator: 'الهيئة العامة للآثار ومعهد DAI الألماني',
hours: '08:00 - 16:30 يومياً'
},
{
slug: 'taq-kasra-ctesiphon',
name_ar: 'طاق كسرى (إيوان المدائن)',
name_en: 'Taq Kasra and the Arch of Ctesiphon',
country: 'العراق',
governorate: 'بغداد',
category: 'historic_palace',
era: 'الساساني / Sasanian (القرن السادس م)',
narrative: 'أكبر قبو أحادي مشيد من الآجر غير المسلح في العالم القديم بارتفاع 37 متراً وعرض 25 متراً في قطيسفون عاصمة الساسانيين التاريخية جنوب العاصمة بغداد.',
centroid: [44.5812, 33.0936],
gate: [44.5828, 33.0945],
parking: [44.5835, 33.0952],
ticket: [44.5825, 33.0943],
image: 'https://upload.wikimedia.org/wikipedia/commons/e/e1/Taq_Kasra.jpg',
unesco: 'القائمة التمهيدية لليونسكو',
curator: 'الهيئة العامة للآثار والتراث (SBAH)',
hours: '08:30 - 17:00 يومياً'
},
{
slug: 'al-ukhaidir-fortress',
name_ar: 'قصر وحصن الأخيضر',
name_en: 'Al-Ukhaidir Fortress',
country: 'العراق',
governorate: 'كربلاء',
category: 'historic_palace',
era: 'العباسي المبكر (775م)',
narrative: 'قصر عباسي صحراوي منيع محاط بأسوار كلسية شاهقة مدعمة بأبراج نصف دائرية، يجسد قمة العمارة العسكرية والمدنية العباسية المبكرة ومحطة القوافل على طريق الحج.',
centroid: [43.6022, 32.4431],
gate: [43.6023, 32.4420],
parking: [43.6025, 32.4412],
ticket: [43.6022, 32.4418],
image: 'https://upload.wikimedia.org/wikipedia/commons/b/ba/%D8%AD%D8%B5%D9%86_%D8%A7%D9%84%D8%A7%D8%AE%D9%8A%D8%B6%D8%B1_%D9%81%D9%8A_%D9%83%D8%B1%D8%A8%D9%84%D8%A7%D8%A1.jpg',
unesco: 'القائمة التمهيدية لليونسكو',
curator: 'الهيئة العامة للآثار والتراث (SBAH)',
hours: '08:30 - 16:30 يومياً'
},
{
slug: 'national-museum-of-iraq',
name_ar: 'المتحف العراقي في بغداد',
name_en: 'The National Museum of Iraq',
country: 'العراق',
governorate: 'بغداد',
category: 'museum',
era: 'شامل لكافة حضارات بلاد الرافدين',
narrative: 'المستودع السيادي الأكبر لكنوز بلاد ما بين النهرين، يضم 28 قاعة تحفظ تماثيل الثيران المجنحة والكنوز الملكية وإناء الوركاء وألواح الكتابة المسمارية الأولى.',
centroid: [44.3855, 33.3283],
gate: [44.3860, 33.3275],
parking: [44.3865, 33.3270],
ticket: [44.3858, 33.3277],
image: 'https://upload.wikimedia.org/wikipedia/commons/1/1d/Entrance_into_the_Iraq_Museum%2C_Baghdad%2C_Iraq._God_Nabu_stands_before_the_facade.jpg',
unesco: 'صرح وطني سيادي',
curator: 'وزارة الثقافة والسياحة والآثار',
hours: '09:00 - 15:00 (مغلق الاثنين)'
},
{
slug: 'al-mustansiriya-madrasah',
name_ar: 'المدرسة المستنصرية وبغداد التاريخية',
name_en: 'Al-Mustansiriya Madrasah',
country: 'العراق',
governorate: 'بغداد',
category: 'monument',
era: 'العباسي (1233م)',
narrative: 'أول جامعة إسلامية متكاملة شيدها الخليفة المستنصر بالله على دجلة لتدريس العلوم والطب والفقه في حرم واحد، وتتميز بعمارتها الآجرية وساعتها الفلكية.',
centroid: [44.3888, 33.3375],
gate: [44.3892, 33.3370],
parking: [44.3905, 33.3365],
ticket: [44.3890, 33.3372],
image: 'https://upload.wikimedia.org/wikipedia/commons/8/82/Mustansiriya_Madrasah_gate.jpg',
unesco: 'القائمة التمهيدية لليونسكو',
curator: 'الهيئة العامة للآثار والتراث (SBAH)',
hours: '09:00 - 17:00 يومياً'
},
{
slug: 'dur-kurigalzu-aqar-quf',
name_ar: 'عقرقوف وزقورة دور كوريكالزو',
name_en: 'Dur-Kurigalzu Kassite Ziggurat (Aqar Quf)',
country: 'العراق',
governorate: 'بغداد',
category: 'archaeological_site',
era: 'الكيشي / Kassite (القرن الرابع عشر ق.م)',
narrative: 'عاصمة الكيشيين التي شيدها الملك كوريكالزو الأول، ترتفع زقورتها 52 متراً وتنفرد بتقنية صف حُصر القصب المجدول بين قوالب الطين لمقاومة الزلازل.',
centroid: [44.2012, 33.3556],
gate: [44.2025, 33.3548],
parking: [44.2035, 33.3540],
ticket: [44.2028, 33.3545],
image: 'https://upload.wikimedia.org/wikipedia/commons/c/c3/Aqar-Quf_%28Dur-Kurigalzu%29%2C_in_western_Baghdad%2C_Iraq._December_29%2C_2021._The_Kassite-era_ziggurat_appears.jpg',
unesco: 'صرح وطني وتاريخي',
curator: 'الهيئة العامة للآثار والتراث (SBAH)',
hours: '08:30 - 16:30 يومياً'
},
{
slug: 'petra-treasury-khazneh',
name_ar: 'الخزنة في البترا وممر السيق',
name_en: 'Petra Treasury via the Siq',
country: 'الأردن',
governorate: 'معان',
category: 'archaeological_site',
era: 'النبطي / Nabataean (القرن الأول ق.م)',
narrative: 'واجهة ملكية نبطية أيقونية منحوتة في الصخر الوردي بارتفاع 39 متراً في نهاية ممر السيق الضيق، إحدى عجائب الدنيا السبع وتراث عالمي لليونسكو.',
centroid: [35.45139, 30.32245],
gate: [35.47980, 30.32560],
parking: [35.48050, 30.32620],
ticket: [35.47950, 30.32530],
image: 'https://commons.wikimedia.org/wiki/Special:FilePath/Treasury_petra_crop.jpeg?width=1600',
unesco: 'اليونسكو #326 (1985)',
curator: 'سلطة إقليم البترا (PDTRA)',
hours: '06:00 - 18:00 يومياً'
},
{
slug: 'damascus-umayyad-mosque',
name_ar: 'الجامع الأموي في دمشق القديمة',
name_en: 'Umayyad Mosque Damascus Old City',
country: 'سوريا',
governorate: 'دمشق',
category: 'archaeological_site',
era: 'الأموي (715م)',
narrative: 'رابع أشهر مساجد الإسلام ودرة العمارة الإسلامية المبكرة بفسيفسائه الذهبية ومآذنه الشامخة في قلب أقدم عاصمة مأهولة في التاريخ.',
centroid: [36.30695, 33.51159],
gate: [36.30780, 33.51220],
parking: [36.30900, 33.51300],
ticket: [36.30765, 33.51205],
image: 'https://commons.wikimedia.org/wiki/Special:FilePath/Umayyad_Mosque_Damascus.jpg?width=1600',
unesco: 'اليونسكو #20 (1979)',
curator: 'المديرية العامة للآثار والمتاحف',
hours: '09:00 - 18:00 يومياً'
},
{
slug: 'giza-pyramids-sphinx',
name_ar: 'أهرامات الجيزة وتمثال أبو الهول',
name_en: 'Giza Pyramids & Great Sphinx',
country: 'مصر',
governorate: 'الجيزة',
category: 'archaeological_site',
era: 'الدولة القديمة - الأسرة الرابعة',
narrative: 'إحدى عجائب الدنيا السبع القديمة الباقية، تضم هرم خوفو وخفرع ومنقرع وتمثال أبو الهول حارس الهضبة منذ أكثر من 4500 عام.',
centroid: [31.1342, 29.9792],
gate: [31.1398, 29.9760],
parking: [31.1410, 29.9752],
ticket: [31.1395, 29.9762],
image: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e3/Kheops-Pyramid.jpg/1200px-Kheops-Pyramid.jpg',
unesco: 'اليونسكو #86 (1979)',
curator: 'وزارة السياحة والآثار المصرية',
hours: '07:00 - 17:00 يومياً'
}
];
// Initialize MapLibre GL
// Configure MapLibre RTL Text Plugin for Flawless Arabic Shaping & RTL Rendering
if (typeof maplibregl !== "undefined" && maplibregl.getRTLTextPluginStatus() === "unavailable") {
try {
maplibregl.setRTLTextPlugin(
"https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js",
(err) => {
if (err) {
console.warn("CDN RTL plugin failed, loading local fallback...", err);
maplibregl.setRTLTextPlugin("js/plugins/mapbox-gl-rtl-text.js", null, true);
}
},
false // Eager load so Arabic text renders connected and Right-to-Left on first draw
);
} catch (e) {
console.error("Error setting RTL plugin:", e);
}
}
const map = new maplibregl.Map({
container: 'map',
style: {
"version": 8,
"name": "Siro Tourism & Heritage Map Style",
"metadata": {
"brand": "Siro Maps",
"version": "1.0.0",
"description": "Dedicated serene tourism & heritage style without contour lines or commercial/residential clutter, highlighting cultural landmarks and gates."
},
"center": [
36.276008,
33.513685
],
"zoom": 15,
"glyphs": "https://cdn.protomaps.com/fonts/pbf/{fontstack}/{range}.pbf",
"sources": {
"local-osm-polygons": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/planet_osm_polygon/{z}/{x}/{y}"
],
"maxzoom": 14,
"attribution": "© Intaleq | © OpenStreetMap contributors"
},
"local-osm-lines": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/planet_osm_line/{z}/{x}/{y}"
],
"maxzoom": 14
},
"local-osm-points": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/planet_osm_point/{z}/{x}/{y}"
],
"maxzoom": 14
},
"places_egypt": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/places_egypt/{z}/{x}/{y}"
],
"maxzoom": 14
},
"places_syria": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/places_syria/{z}/{x}/{y}"
],
"maxzoom": 14
},
"places_jordan": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/places_jordan/{z}/{x}/{y}"
],
"maxzoom": 14
},
"overture_buildings": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/overture_building/{z}/{x}/{y}"
],
"maxzoom": 16
},
"overture_segments": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/overture_segment/{z}/{x}/{y}"
],
"maxzoom": 14
},
"approved_roads": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/approved_roads/{z}/{x}/{y}"
],
"minzoom": 8,
"maxzoom": 18
},
"places_iraq": {
"type": "vector",
"tiles": [
"https://tiles.intaleqapp.com/places_iraq/{z}/{x}/{y}"
],
"maxzoom": 14
}
},
"layers": [
{
"id": "background",
"type": "background",
"paint": {
"background-color": "#FAF6F0"
}
},
{
"id": "admin-boundary-national",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"all",
[
"==",
"boundary",
"administrative"
],
[
"in",
"admin_level",
"2",
2,
"3",
3
]
],
"paint": {
"line-color": "#1e293b",
"line-width": 3,
"line-dasharray": [
6,
2,
2,
2
]
}
},
{
"id": "admin-boundary-governorate-poly",
"type": "line",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"minzoom": 6,
"filter": [
"all",
[
"==",
"boundary",
"administrative"
],
[
"in",
"admin_level",
"4",
4,
"5",
5
]
],
"paint": {
"line-color": "#6366f1",
"line-width": 1.4,
"line-dasharray": [
4,
3
],
"line-opacity": 0.7
}
},
{
"id": "admin-boundary-governorate",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"minzoom": 6,
"filter": [
"all",
[
"==",
"boundary",
"administrative"
],
[
"in",
"admin_level",
"4",
4,
"5",
5
]
],
"paint": {
"line-color": "#6366f1",
"line-width": 1.4,
"line-dasharray": [
4,
3
],
"line-opacity": 0.7
}
},
{
"id": "admin-boundary-district-poly",
"type": "line",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"minzoom": 9,
"filter": [
"all",
[
"==",
"boundary",
"administrative"
],
[
"in",
"admin_level",
"6",
6,
"7",
7,
"8",
8,
"9",
9,
"10",
10
]
],
"paint": {
"line-color": "#64748b",
"line-width": 1.5,
"line-dasharray": [
3,
2
],
"line-opacity": 0.85
}
},
{
"id": "admin-boundary-district",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"minzoom": 9,
"filter": [
"all",
[
"==",
"boundary",
"administrative"
],
[
"in",
"admin_level",
"6",
6,
"7",
7,
"8",
8,
"9",
9,
"10",
10
]
],
"paint": {
"line-color": "#64748b",
"line-width": 1.5,
"line-dasharray": [
3,
2
]
}
},
{
"id": "landuse-residential",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"==",
"landuse",
"residential"
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5
}
},
{
"id": "landuse-commercial",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"==",
"landuse",
"commercial"
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5
}
},
{
"id": "landuse-industrial",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"in",
"landuse",
"industrial",
"railway"
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5
}
},
{
"id": "landuse-retail",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"==",
"landuse",
"retail"
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5
}
},
{
"id": "landuse-farmland",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"in",
"landuse",
"farmland",
"farmyard",
"orchard"
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5
}
},
{
"id": "landuse-forest",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"in",
"landuse",
"forest",
"natural"
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5
}
},
{
"id": "landuse-grass",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"in",
"landuse",
"grass",
"meadow"
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5
}
},
{
"id": "landuse-power",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"any",
[
"==",
"power",
"plant"
],
[
"==",
"power",
"substation"
],
[
"==",
"landuse",
"industrial"
]
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5,
"fill-outline-color": "#C7ADD9"
}
},
{
"id": "landuse-cemetery",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"==",
"landuse",
"cemetery"
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5
}
},
{
"id": "landuse-military",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"==",
"landuse",
"military"
],
"paint": {
"fill-color": "#F4EFE6",
"fill-opacity": 0.5
}
},
{
"id": "park-layer",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"any",
[
"in",
"leisure",
"park",
"garden",
"nature_reserve",
"pitch",
"playground"
],
[
"in",
"landuse",
"grass",
"meadow",
"forest"
],
[
"in",
"natural",
"wood",
"scrub",
"heath"
]
],
"paint": {
"fill-color": [
"match",
[
"get",
"leisure"
],
"pitch",
"#9ED4A0",
"playground",
"#B8E6B8",
"#C5E8C5"
],
"fill-opacity": 0.85
}
},
{
"id": "park-outline",
"type": "line",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"in",
"leisure",
"park",
"garden",
"nature_reserve"
],
"paint": {
"line-color": "#94D4A0",
"line-width": 0.8,
"line-opacity": 0.7
}
},
{
"id": "water-polygon",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"any",
[
"in",
"natural",
"water",
"lake",
"bay"
],
[
"==",
"waterway",
"riverbank"
],
[
"in",
"landuse",
"basin",
"reservoir"
],
[
"==",
"amenity",
"fountain"
]
],
"paint": {
"fill-color": "#CBE2EE",
"fill-opacity": 0.95
}
},
{
"id": "water-polygon-outline",
"type": "line",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"any",
[
"in",
"natural",
"water",
"lake",
"bay"
],
[
"==",
"waterway",
"riverbank"
],
[
"in",
"landuse",
"basin",
"reservoir"
]
],
"paint": {
"line-color": "#6BB8D8",
"line-width": 0.8,
"line-opacity": 0.8
}
},
{
"id": "waterway-intermittent",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"minzoom": 11,
"filter": [
"all",
[
"in",
"waterway",
"river",
"canal",
"stream",
"drain",
"ditch"
],
[
"any",
[
"==",
"intermittent",
"yes"
],
[
"==",
"seasonal",
"yes"
]
]
],
"paint": {
"line-color": "#A8CFE0",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
11,
0.6,
16,
3.5
],
"line-dasharray": [
3,
2
]
}
},
{
"id": "waterway-river",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"all",
[
"==",
"waterway",
"river"
],
[
"!=",
"intermittent",
"yes"
],
[
"!=",
"seasonal",
"yes"
]
],
"paint": {
"line-color": "#6BB8D8",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
7,
0.8,
14,
4,
16,
7
],
"line-opacity": 0.95
}
},
{
"id": "waterway-canal",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"minzoom": 11,
"filter": [
"all",
[
"==",
"waterway",
"canal"
],
[
"!=",
"intermittent",
"yes"
],
[
"!=",
"seasonal",
"yes"
]
],
"paint": {
"line-color": "#8FC8DE",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
11,
0.8,
16,
5
]
}
},
{
"id": "waterway-stream-drain",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"all",
[
"in",
"waterway",
"stream",
"drain",
"ditch"
],
[
"!=",
"intermittent",
"yes"
],
[
"!=",
"seasonal",
"yes"
],
[
"!=",
"tunnel",
"yes"
]
],
"minzoom": 13,
"paint": {
"line-color": "#7FBFD8",
"line-width": [
"interpolate",
[
"linear"
],
[
"zoom"
],
13,
0.8,
16,
2.5
],
"line-opacity": 0.85
}
},
{
"id": "railway-area",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"==",
"landuse",
"railway"
],
"paint": {
"fill-color": "#DDE2EA",
"fill-opacity": 0.9
}
},
{
"id": "railway-rail-casing",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"all",
[
"in",
"railway",
"rail",
"narrow_gauge",
"preserved"
],
[
"!=",
"service",
"yard"
],
[
"!=",
"service",
"siding"
]
],
"minzoom": 8,
"paint": {
"line-color": "#B0B8C5",
"line-width": [
"interpolate",
[
"linear"
],
[
"zoom"
],
8,
2,
12,
4,
16,
8
]
}
},
{
"id": "railway-rail-core",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"all",
[
"in",
"railway",
"rail",
"narrow_gauge",
"preserved"
],
[
"!=",
"service",
"yard"
],
[
"!=",
"service",
"siding"
]
],
"minzoom": 8,
"paint": {
"line-color": "#6B7A8E",
"line-width": [
"interpolate",
[
"linear"
],
[
"zoom"
],
8,
1,
12,
2.5,
16,
5
],
"line-dasharray": [
6,
4
]
}
},
{
"id": "railway-subway-casing",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"railway",
"subway",
"light_rail",
"tram",
"monorail"
],
"minzoom": 10,
"paint": {
"line-color": [
"match",
[
"get",
"railway"
],
"subway",
"#CC2233",
"light_rail",
"#0066CC",
"tram",
"#8833BB",
"monorail",
"#008855",
"#BB3344"
],
"line-width": [
"interpolate",
[
"linear"
],
[
"zoom"
],
10,
3,
14,
6,
16,
10
]
}
},
{
"id": "railway-subway-core",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"railway",
"subway",
"light_rail",
"tram",
"monorail"
],
"minzoom": 10,
"paint": {
"line-color": [
"match",
[
"get",
"railway"
],
"subway",
"#FF3347",
"light_rail",
"#2288FF",
"tram",
"#AA44EE",
"monorail",
"#00BB66",
"#FF4455"
],
"line-width": [
"interpolate",
[
"linear"
],
[
"zoom"
],
10,
1.5,
14,
3.5,
16,
6
]
}
},
{
"id": "road-casing-track-path",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"track",
"path",
"footway",
"cycleway",
"steps"
],
"minzoom": 14,
"paint": {
"line-color": "#C8CDD6",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
14,
1,
16,
4
],
"line-dasharray": [
4,
3
]
}
},
{
"id": "road-casing-minor",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"residential",
"service",
"unclassified",
"living_street",
"pedestrian"
],
"paint": {
"line-color": "#D6DBE1",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
12.5,
1.6,
15,
4.5,
16,
10,
18,
15
],
"line-opacity": 0.7
},
"minzoom": 12.5
},
{
"id": "road-core-minor",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"residential",
"service",
"unclassified",
"living_street",
"pedestrian"
],
"paint": {
"line-color": "#FFFFFF",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
12.5,
1.0,
15,
3.2,
16,
8,
18,
12
]
},
"minzoom": 12.5
},
{
"id": "approved-road-casing",
"type": "line",
"source": "approved_roads",
"source-layer": "approved_roads",
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "#D6DBE1",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
12.5,
1.6,
15,
4.5,
16,
10,
18,
15
],
"line-opacity": 0.7
},
"minzoom": 12.5
},
{
"id": "approved-road-core",
"type": "line",
"source": "approved_roads",
"source-layer": "approved_roads",
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "#FFFFFF",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
12.5,
1.0,
15,
3.2,
16,
8,
18,
12
]
},
"minzoom": 12.5
},
{
"id": "road-casing-tertiary",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"tertiary",
"tertiary_link"
],
"paint": {
"line-color": "#BCC7D2",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
11.5,
1.4,
14,
3.4,
16,
14,
18,
18
],
"line-opacity": 0.75
},
"minzoom": 11.5
},
{
"id": "road-core-tertiary",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"tertiary",
"tertiary_link"
],
"paint": {
"line-color": "#DCE5EC",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
11.5,
0.9,
14,
2.4,
16,
11,
18,
14
]
},
"minzoom": 11.5
},
{
"id": "road-casing-secondary",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"secondary",
"secondary_link"
],
"paint": {
"line-color": "#98AABC",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
10,
1.4,
13,
3.2,
16,
16,
18,
21
],
"line-opacity": 0.8
},
"minzoom": 10
},
{
"id": "road-core-secondary",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"secondary",
"secondary_link"
],
"paint": {
"line-color": "#BACAD8",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
10,
0.9,
13,
2.2,
16,
13,
18,
17
]
},
"minzoom": 10
},
{
"id": "road-casing-primary",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"primary",
"primary_link"
],
"paint": {
"line-color": "#71889E",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
8,
1.4,
12,
3.4,
16,
18,
18,
24
],
"line-opacity": 0.7
},
"minzoom": 8
},
{
"id": "road-core-primary",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"primary",
"primary_link"
],
"paint": {
"line-color": "#93A9BC",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
8,
0.9,
12,
2.4,
16,
14,
18,
19
]
},
"minzoom": 8
},
{
"id": "road-casing-motorway-trunk",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"motorway",
"motorway_link",
"trunk",
"trunk_link"
],
"paint": {
"line-color": "#4E6478",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
5,
1.4,
10,
3.2,
16,
20,
18,
26
],
"line-opacity": 0.75
},
"minzoom": 5
},
{
"id": "road-core-motorway-trunk",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"motorway",
"motorway_link",
"trunk",
"trunk_link"
],
"paint": {
"line-color": "#6B8299",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
5,
0.8,
10,
2.2,
16,
16,
18,
21
]
},
"minzoom": 5
},
{
"id": "building-fill-flat",
"type": "fill",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"filter": [
"has",
"building"
],
"paint": {
"fill-color": "#E4DED4",
"fill-opacity": 1,
"fill-outline-color": "#C8C0B2"
}
},
{
"id": "building-3d-osm",
"type": "fill-extrusion",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"minzoom": 13,
"filter": [
"has",
"building"
],
"layout": {
"visibility": "visible"
},
"paint": {
"fill-extrusion-color": "#DDD8D0",
"fill-extrusion-height": [
"coalesce",
[
"to-number",
[
"get",
"height"
],
null
],
[
"*",
[
"coalesce",
[
"to-number",
[
"get",
"building:levels"
],
null
],
3
],
3.5
],
12
],
"fill-extrusion-base": 0,
"fill-extrusion-opacity": 0.85,
"fill-extrusion-vertical-gradient": true
}
},
{
"id": "building-3d",
"type": "fill-extrusion",
"source": "overture_buildings",
"source-layer": "overture_building",
"minzoom": 13,
"layout": {
"visibility": "visible"
},
"paint": {
"fill-extrusion-color": "#DDD8D0",
"fill-extrusion-height": [
"interpolate",
[
"linear"
],
[
"zoom"
],
13,
[
"*",
[
"coalesce",
[
"to-number",
[
"get",
"num_floors"
],
null
],
3
],
2.5
],
17,
[
"coalesce",
[
"to-number",
[
"get",
"height"
],
null
],
[
"*",
[
"coalesce",
[
"to-number",
[
"get",
"num_floors"
],
null
],
3
],
3.5
],
12
]
],
"fill-extrusion-base": 0,
"fill-extrusion-opacity": [
"interpolate",
[
"linear"
],
[
"zoom"
],
13,
0.6,
16,
0.9
],
"fill-extrusion-vertical-gradient": true
}
},
{
"id": "overture-building-footprint",
"type": "fill",
"source": "overture_buildings",
"source-layer": "overture_building",
"paint": {
"fill-color": "#E4DED4",
"fill-opacity": 1,
"fill-outline-color": "#C8C0B2"
},
"minzoom": 14
},
{
"id": "bridge-casing",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"minzoom": 12,
"filter": [
"all",
[
"==",
"bridge",
"yes"
],
[
"in",
"highway",
"motorway",
"trunk",
"primary",
"secondary",
"tertiary",
"residential",
"unclassified",
"living_street",
"motorway_link",
"trunk_link",
"primary_link",
"secondary_link"
]
],
"layout": {
"line-cap": "butt",
"line-join": "round"
},
"paint": {
"line-color": "#5A6B7C",
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
12,
5,
16,
22,
18,
30
]
}
},
{
"id": "bridge-core",
"type": "line",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"minzoom": 12,
"filter": [
"all",
[
"==",
"bridge",
"yes"
],
[
"in",
"highway",
"motorway",
"trunk",
"primary",
"secondary",
"tertiary",
"residential",
"unclassified",
"living_street",
"motorway_link",
"trunk_link",
"primary_link",
"secondary_link"
]
],
"layout": {
"line-cap": "butt",
"line-join": "round"
},
"paint": {
"line-color": [
"match",
[
"get",
"highway"
],
"motorway",
"#6B8299",
"trunk",
"#6B8299",
"motorway_link",
"#6B8299",
"trunk_link",
"#6B8299",
"primary",
"#93A9BC",
"primary_link",
"#93A9BC",
"secondary",
"#BACAD8",
"secondary_link",
"#BACAD8",
"tertiary",
"#DCE5EC",
"#FFFFFF"
],
"line-width": [
"interpolate",
[
"exponential",
1.6
],
[
"zoom"
],
12,
3.5,
16,
18,
18,
25
]
}
},
{
"id": "road-direction-arrows",
"type": "symbol",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"minzoom": 15,
"filter": [
"all",
[
"in",
"highway",
"motorway",
"trunk",
"primary",
"secondary",
"tertiary",
"residential",
"unclassified",
"living_street"
],
[
"==",
"oneway",
"yes"
]
],
"layout": {
"symbol-placement": "line",
"symbol-spacing": 90,
"icon-image": "arrow",
"icon-size": [
"interpolate",
[
"linear"
],
[
"zoom"
],
15,
0.35,
18,
0.55
],
"icon-rotation-alignment": "map",
"icon-allow-overlap": true,
"icon-ignore-placement": true
},
"paint": {
"icon-opacity": 0.75
}
},
{
"id": "railway-label",
"type": "symbol",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"railway",
"rail",
"subway",
"light_rail",
"tram"
],
"minzoom": 13,
"layout": {
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": 10,
"symbol-placement": "line",
"text-padding": 6,
"text-allow-overlap": false
},
"paint": {
"text-color": [
"match",
[
"get",
"railway"
],
"subway",
"#CC2233",
"light_rail",
"#0055BB",
"tram",
"#7722AA",
"#4A5568"
],
"text-halo-color": "rgba(255,255,255,0.9)",
"text-halo-width": 2
}
},
{
"id": "waterway-label",
"type": "symbol",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"all",
[
"in",
"waterway",
"river",
"canal"
],
[
"!=",
"intermittent",
"yes"
],
[
"has",
"name"
]
],
"minzoom": 12,
"layout": {
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": 11,
"symbol-placement": "line",
"text-letter-spacing": 0.1
},
"paint": {
"text-color": "#2E86AB",
"text-halo-color": "rgba(255,255,255,0.85)",
"text-halo-width": 2
}
},
{
"id": "building-number-polygon",
"type": "symbol",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"minzoom": 17,
"filter": [
"has",
"addr:housenumber"
],
"layout": {
"text-field": "{addr:housenumber}",
"text-font": [
"Noto Sans Regular"
],
"text-size": 10,
"text-allow-overlap": false,
"text-ignore-placement": false
},
"paint": {
"text-color": "#5A5048",
"text-halo-color": "rgba(255,255,255,0.95)",
"text-halo-width": 1.5
}
},
{
"id": "road-labels-minor",
"type": "symbol",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"residential",
"service",
"unclassified",
"living_street"
],
"minzoom": 15,
"layout": {
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": [
"interpolate",
[
"linear"
],
[
"zoom"
],
15,
10,
18,
13
],
"symbol-placement": "line",
"text-letter-spacing": 0.05,
"text-padding": 15,
"symbol-spacing": 300,
"text-max-angle": 30,
"text-allow-overlap": false,
"text-ignore-placement": false
},
"paint": {
"text-color": "#4A5568",
"text-halo-color": "rgba(255,255,255,0.92)",
"text-halo-width": 1.8
}
},
{
"id": "approved-road-labels",
"type": "symbol",
"source": "approved_roads",
"source-layer": "approved_roads",
"minzoom": 15,
"layout": {
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": [
"interpolate",
[
"linear"
],
[
"zoom"
],
15,
10,
18,
13
],
"symbol-placement": "line",
"text-letter-spacing": 0.05,
"text-padding": 15,
"symbol-spacing": 300,
"text-max-angle": 30,
"text-allow-overlap": false,
"text-ignore-placement": false
},
"paint": {
"text-color": "#4A5568",
"text-halo-color": "rgba(255,255,255,0.92)",
"text-halo-width": 1.8
}
},
{
"id": "road-labels-major",
"type": "symbol",
"source": "local-osm-lines",
"source-layer": "planet_osm_line",
"filter": [
"in",
"highway",
"primary",
"secondary",
"tertiary",
"motorway",
"trunk"
],
"minzoom": 12,
"layout": {
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Bold"
],
"text-size": [
"interpolate",
[
"linear"
],
[
"zoom"
],
12,
10,
14,
13,
18,
16
],
"symbol-placement": "line",
"text-letter-spacing": 0.06,
"text-padding": 20,
"symbol-spacing": 350,
"text-max-angle": 25,
"text-allow-overlap": false,
"text-ignore-placement": false
},
"paint": {
"text-color": "#1A2332",
"text-halo-color": "rgba(255,255,255,0.95)",
"text-halo-width": 2.5
}
},
{
"id": "poi-hospital",
"type": "symbol",
"source": "local-osm-points",
"source-layer": "planet_osm_point",
"minzoom": 13,
"filter": [
"==",
"amenity",
"hospital"
],
"layout": {
"icon-image": "hospital",
"icon-size": 1,
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": 11,
"text-offset": [
0,
1.2
],
"text-anchor": "top",
"text-allow-overlap": false
},
"paint": {
"text-color": "#C0392B",
"text-halo-color": "white",
"text-halo-width": 2
}
},
{
"id": "poi-place-of-worship",
"type": "symbol",
"source": "local-osm-points",
"source-layer": "planet_osm_point",
"minzoom": 14,
"filter": [
"==",
"amenity",
"place_of_worship"
],
"layout": {
"icon-image": "tourist",
"icon-size": 0.8,
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": 11,
"text-offset": [
0,
1.2
],
"text-anchor": "top"
},
"paint": {
"text-color": "#1A6B3A",
"text-halo-color": "white",
"text-halo-width": 2
}
},
{
"id": "poi-restaurant-cafe",
"type": "symbol",
"source": "local-osm-points",
"source-layer": "planet_osm_point",
"minzoom": 16,
"filter": [
"in",
"amenity",
"restaurant",
"cafe",
"fast_food"
],
"layout": {
"icon-image": [
"match",
[
"get",
"amenity"
],
"cafe",
"cafe",
"restaurant"
],
"icon-size": 0.8,
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": 10,
"text-offset": [
0,
1.2
],
"text-anchor": "top"
},
"paint": {
"text-color": "#3D4A5C",
"text-halo-color": "white",
"text-halo-width": 1.5
}
},
{
"id": "poi-police",
"type": "symbol",
"source": "local-osm-points",
"source-layer": "planet_osm_point",
"minzoom": 15,
"filter": [
"in",
"amenity",
"police",
"fire_station"
],
"layout": {
"icon-image": "police",
"icon-size": 0.8,
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": 10,
"text-offset": [
0,
1.2
],
"text-anchor": "top"
},
"paint": {
"text-color": "#2F5AA8",
"text-halo-color": "white",
"text-halo-width": 1.5
}
},
{
"id": "poi-hotel",
"type": "symbol",
"source": "local-osm-points",
"source-layer": "planet_osm_point",
"minzoom": 16,
"filter": [
"in",
"tourism",
"hotel",
"motel",
"guest_house",
"hostel"
],
"layout": {
"icon-image": "tourist",
"icon-size": 0.8,
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": 10,
"text-offset": [
0,
1.2
],
"text-anchor": "top"
},
"paint": {
"text-color": "#8A5A8A",
"text-halo-color": "white",
"text-halo-width": 1.5
}
},
{
"id": "place-labels-area",
"type": "symbol",
"source": "local-osm-polygons",
"source-layer": "planet_osm_polygon",
"minzoom": 10,
"filter": [
"has",
"name"
],
"layout": {
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": [
"interpolate",
[
"linear"
],
[
"zoom"
],
10,
10,
14,
13
],
"text-padding": 8,
"text-allow-overlap": false,
"text-ignore-placement": false
},
"paint": {
"text-color": "#34495E",
"text-halo-color": "rgba(255,255,255,0.85)",
"text-halo-width": 2
}
},
{
"id": "place-labels-point",
"type": "symbol",
"source": "local-osm-points",
"source-layer": "planet_osm_point",
"minzoom": 10,
"filter": [
"any",
[
"in",
"place",
"city",
"town",
"village",
"suburb",
"neighbourhood",
"hamlet",
"locality",
"quarter"
],
[
"in",
"natural",
"peak",
"spring"
]
],
"layout": {
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": [
"interpolate",
[
"linear"
],
[
"zoom"
],
10,
[
"match",
[
"get",
"place"
],
"city",
16,
"town",
14,
11
],
14,
[
"match",
[
"get",
"place"
],
"city",
20,
"town",
16,
13
],
17,
14
],
"text-letter-spacing": [
"match",
[
"get",
"place"
],
"city",
0.08,
"town",
0.05,
0.02
],
"text-anchor": "center",
"text-padding": 10,
"text-allow-overlap": false
},
"paint": {
"text-color": [
"match",
[
"get",
"place"
],
"city",
"#1A2740",
"town",
"#2C3E50",
"village",
"#3D4F62",
"suburb",
"#4A5568",
"neighbourhood",
"#556677",
"#607080"
],
"text-halo-color": "rgba(255,255,255,0.92)",
"text-halo-width": [
"match",
[
"get",
"place"
],
"city",
3,
"town",
2.5,
2
]
}
},
{
"id": "overture-street-names",
"type": "symbol",
"source": "overture_segments",
"source-layer": "overture_segment",
"minzoom": 14,
"filter": [
"has",
"name_primary"
],
"layout": {
"text-field": [
"coalesce",
[
"get",
"name_primary"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": [
"interpolate",
[
"linear"
],
[
"zoom"
],
14,
9,
16,
12,
18,
14
],
"symbol-placement": "line",
"text-rotation-alignment": "map",
"text-pitch-alignment": "viewport",
"text-keep-upright": true,
"text-padding": 20,
"text-letter-spacing": 0.04,
"text-max-angle": 30,
"symbol-spacing": 300,
"text-allow-overlap": false,
"text-ignore-placement": false
},
"paint": {
"text-color": "#4A5568",
"text-halo-color": "rgba(255, 255, 255, 0.95)",
"text-halo-width": 2.2
}
},
{
"id": "tourism-archaeological-poi",
"type": "symbol",
"source": "local-osm-points",
"source-layer": "planet_osm_point",
"minzoom": 9,
"filter": [
"any",
[
"in",
"historic",
"archaeological_site",
"castle",
"monument",
"ruins",
"memorial",
"fort",
"city_gate",
"wayside_shrine"
],
[
"in",
"tourism",
"attraction",
"museum",
"viewpoint",
"theme_park",
"artwork",
"gallery"
]
],
"layout": {
"icon-image": "tourist",
"icon-size": 0.85,
"text-field": [
"coalesce",
[
"get",
"name:ar"
],
[
"get",
"name"
],
""
],
"text-font": [
"Noto Sans Regular"
],
"text-size": [
"interpolate",
[
"linear"
],
[
"zoom"
],
9,
10,
14,
13,
17,
15
],
"text-offset": [
0,
1.3
],
"text-anchor": "top",
"text-padding": 10,
"text-max-width": 10
},
"paint": {
"text-color": "#854D0E",
"text-halo-color": "rgba(255, 255, 255, 0.95)",
"text-halo-width": 2
}
}
]
},
center: [44.4210, 32.5422], // Start centered at Babylon / Mesopotamia
zoom: 6,
pitch: 35,
bearing: -10,
attributionControl: false
});
map.addControl(new maplibregl.NavigationControl({ visualizePitch: true }), 'bottom-left');
let currentMarkers = [];
let selectedLandmark = null;
let activeCountry = 'all';
let activeCategory = 'all';
let searchQuery = '';
// Render Markers for Landmarks (Optimized for 3,600+ nodes)
function renderMarkers() {
currentMarkers.forEach(m => m.remove());
currentMarkers = [];
const filtered = LANDMARKS.filter(lm => {
const matchC = activeCountry === 'all' || lm.country === activeCountry;
const matchCat = activeCategory === 'all' || lm.category === activeCategory;
const matchS = !searchQuery || lm.name_ar.includes(searchQuery) || (lm.name_en && lm.name_en.toLowerCase().includes(searchQuery.toLowerCase()));
return matchC && matchCat && matchS;
});
// Update Header Subtitle Counter
const subtitleEl = document.querySelector('.brand-subtitle');
if (subtitleEl) {
subtitleEl.textContent = `خريطة التراث العربي بدون خطوط كنتور • (${filtered.length.toLocaleString()} معلماً معتمداً)`;
}
// If activeCountry is all and no search, render top 200 landmarks to maintain silky 60fps
const toRender = (activeCountry === 'all' && !searchQuery) ? filtered.slice(0, 250) : filtered;
const categoryIcons = {
'archaeological_site': '🏛️',
'historic_shrine': '🕌',
'religious_heritage': '⛪',
'historic_palace': '🏰',
'monument': '🗿',
'museum': '🏺',
'cultural_trail': '🌿'
};
toRender.forEach(lm => {
const el = document.createElement('div');
el.className = 'marker-centroid';
el.innerHTML = categoryIcons[lm.category] || '🏛️';
el.title = `${lm.name_ar} (${lm.governorate})`;
el.addEventListener('click', () => selectLandmark(lm));
const m = new maplibregl.Marker({ element: el })
.setLngLat(lm.centroid)
.addTo(map);
currentMarkers.push(m);
if (selectedLandmark && selectedLandmark.slug === lm.slug) {
const gateEl = document.createElement('div');
gateEl.className = 'marker-gate';
gateEl.innerHTML = '🚪';
gateEl.title = `بوابة دخول: ${lm.name_ar}`;
gateEl.addEventListener('click', () => selectLandmark(lm));
currentMarkers.push(new maplibregl.Marker({ element: gateEl }).setLngLat(lm.gate).addTo(map));
const parkEl = document.createElement('div');
parkEl.className = 'marker-parking';
parkEl.innerHTML = 'P';
parkEl.title = `مواقف سيارات: ${lm.name_ar}`;
currentMarkers.push(new maplibregl.Marker({ element: parkEl }).setLngLat(lm.parking).addTo(map));
const ticketEl = document.createElement('div');
ticketEl.className = 'marker-ticket';
ticketEl.innerHTML = '🎟️';
ticketEl.title = `مكتب تذاكر: ${lm.name_ar}`;
currentMarkers.push(new maplibregl.Marker({ element: ticketEl }).setLngLat(lm.ticket).addTo(map));
}
});
renderSlider(filtered);
}
// Render Bottom Slider (Virtual slice for performance)
function renderSlider(list) {
const slider = document.getElementById('landmarkSlider');
slider.innerHTML = '';
const displaySlice = list.slice(0, 100);
displaySlice.forEach(lm => {
const card = document.createElement('div');
card.className = 'slider-card' + (selectedLandmark?.slug === lm.slug ? ' active' : '');
card.innerHTML = `
<img src="${lm.image}" class="slider-img" alt="${lm.name_ar}" onerror="this.src='https://upload.wikimedia.org/wikipedia/commons/7/78/Ishtar_Gate_Babylon_Iraq.jpg'">
<div class="slider-info">
<div class="slider-title">${lm.name_ar}</div>
<div class="slider-meta">📍 ${lm.governorate} • ${lm.era ? lm.era.split('/')[0] : ''}</div>
</div>
`;
card.addEventListener('click', () => selectLandmark(lm));
slider.appendChild(card);
});
}
// Dynamic Live Loader for All 3,695 Sovereign Landmarks
async function loadAllSovereignLandmarks() {
try {
const isServerEnv = window.location.hostname.includes('intaleqapp.com') || window.location.port === '3201' || window.location.port === '3204' || window.location.hostname === '188.68.36.205';
const apiUrl = isServerEnv
? `/api/v1/heritage/landmarks?key=${SOVEREIGN_MAP_API_KEY}`
: `http://188.68.36.205:3200/api/v1/heritage/landmarks?key=${SOVEREIGN_MAP_API_KEY}`;
const res = await fetch(apiUrl, {
headers: { 'x-api-key': SOVEREIGN_MAP_API_KEY }
});
if (res.ok) {
const apiData = await res.json();
if (Array.isArray(apiData) && apiData.length > 50) {
LANDMARKS = apiData.map(item => ({
slug: item.slug,
name_ar: item.name_ar,
name_en: item.name_en || item.name_ar,
country: item.metadata?.country || (item.governorate?.includes('معان') || item.governorate?.includes('عمان') || item.governorate?.includes('الكرك') || item.governorate?.includes('إربد') || item.governorate?.includes('البلقاء') || item.governorate?.includes('عجلون') || item.governorate?.includes('جرش') || item.governorate?.includes('مادبا') || item.governorate?.includes('الطفيلة') || item.governorate?.includes('العقبة') || item.governorate?.includes('المفرق') || item.governorate?.includes('الزرقاء') ? 'الأردن' : (item.governorate?.includes('دمشق') || item.governorate?.includes('ريف دمشق') || item.governorate?.includes('حلب') || item.governorate?.includes('حمص') || item.governorate?.includes('حماة') || item.governorate?.includes('اللاذقية') || item.governorate?.includes('طرطوس') || item.governorate?.includes('إدلب') || item.governorate?.includes('درعا') || item.governorate?.includes('السويداء') || item.governorate?.includes('القنيطرة') || item.governorate?.includes('دير الزور') || item.governorate?.includes('الرقة') || item.governorate?.includes('الحسكة') ? 'سوريا' : (item.governorate?.includes('القاهرة') || item.governorate?.includes('الجيزة') || item.governorate?.includes('الإسكندرية') || item.governorate?.includes('الأقصر') || item.governorate?.includes('أسوان') || item.governorate?.includes('سوهاج') || item.governorate?.includes('قنا') || item.governorate?.includes('المنيا') || item.governorate?.includes('أسيوط') || item.governorate?.includes('الغربية') || item.governorate?.includes('الشرقية') || item.governorate?.includes('الدقهلية') || item.governorate?.includes('البحيرة') || item.governorate?.includes('كفر الشيخ') || item.governorate?.includes('المنوفية') || item.governorate?.includes('دمياط') || item.governorate?.includes('مطروح') || item.governorate?.includes('الوادي الجديد') || item.governorate?.includes('البحر الأحمر') || item.governorate?.includes('شمال سيناء') || item.governorate?.includes('جنوب سيناء') || item.governorate?.includes('بني سويف') || item.governorate?.includes('الفيوم') || item.governorate?.includes('القليوبية') || item.governorate?.includes('بورسعيد') || item.governorate?.includes('الإسماعيلية') || item.governorate?.includes('السويس') ? 'مصر' : 'العراق'))),
governorate: item.governorate,
category: item.category,
era: item.era || 'عصور تاريخية عريقة',
narrative: item.narrative_ar || item.narrative_en || '',
centroid: [item.coordinates.centroid.lng, item.coordinates.centroid.lat],
gate: item.coordinates.access_gate ? [item.coordinates.access_gate.lng, item.coordinates.access_gate.lat] : [item.coordinates.centroid.lng + 0.0006, item.coordinates.centroid.lat + 0.0004],
parking: item.coordinates.parking ? [item.coordinates.parking.lng, item.coordinates.parking.lat] : [item.coordinates.centroid.lng + 0.0012, item.coordinates.centroid.lat + 0.0008],
ticket: item.coordinates.ticket_office ? [item.coordinates.ticket_office.lng, item.coordinates.ticket_office.lat] : [item.coordinates.centroid.lng + 0.0005, item.coordinates.centroid.lat + 0.0003],
image: item.image_url || 'https://upload.wikimedia.org/wikipedia/commons/7/78/Ishtar_Gate_Babylon_Iraq.jpg',
unesco: item.metadata?.unesco_id ? `اليونسكو #${item.metadata.unesco_id}` : (item.metadata?.unesco || 'تراث وطني تاريخي مسجل'),
curator: item.metadata?.curator || 'الهيئة العامة للآثار والتراث',
hours: item.metadata?.opening_hours || '08:00 - 18:00 يومياً'
}));
console.log(`✅ Loaded ${LANDMARKS.length} landmarks live from PostGIS API!`);
renderMarkers();
return;
}
}
} catch (err) {
console.warn('API live fetch fallback triggered...', err);
}
// Static JSON Fallback
try {
const fallbackPaths = [
'/data/landmarks_mena_full_4000.json',
'data/landmarks_mena_full_4000.json',
'./data/landmarks_mena_full_4000.json'
];
for (const p of fallbackPaths) {
try {
const jsonRes = await fetch(p);
if (jsonRes.ok) {
const jsonData = await jsonRes.json();
if (Array.isArray(jsonData) && jsonData.length > 0) {
LANDMARKS = jsonData;
console.log(`✅ Loaded ${LANDMARKS.length} landmarks from static JSON fallback (${p})!`);
renderMarkers();
return;
}
}
} catch(e) {}
}
} catch (e) {
console.error('Failed to load fallback JSON', e);
}
}
// Select Landmark & Open Drawer
function selectLandmark(lm) {
selectedLandmark = lm;
map.flyTo({
center: lm.centroid,
zoom: 14.5,
pitch: 50,
bearing: 15,
duration: 1800
});
renderMarkers();
// Populate Drawer
document.getElementById('drawerTitle').innerText = lm.name_ar;
document.getElementById('drawerSubtitle').innerText = `${lm.name_en} • ${lm.governorate}`;
document.getElementById('drawerImage').src = lm.image;
document.getElementById('drawerNarrative').innerText = lm.narrative;
document.getElementById('drawerCurator').innerText = lm.curator;
document.getElementById('drawerHours').innerText = lm.hours;
const badges = document.getElementById('drawerBadges');
badges.innerHTML = `
<span class="badge gold">${lm.unesco}</span>
<span class="badge">${lm.era}</span>
<span class="badge">فصل رباعي WGS84 محقق</span>
`;
document.getElementById('drawerNavBtn').onclick = () => {
startSovereignNavigation(lm);
};
document.getElementById('landmarkDrawer').style.display = 'flex';
}
// Drawer Close
document.getElementById('drawerCloseBtn').addEventListener('click', () => {
document.getElementById('landmarkDrawer').style.display = 'none';
selectedLandmark = null;
renderMarkers();
});
// Country Filter
document.querySelectorAll('.country-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
document.querySelectorAll('.country-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
activeCountry = btn.dataset.country;
renderMarkers();
// Auto fly to country center
if (activeCountry === 'العراق') map.flyTo({ center: [44.4, 33.2], zoom: 6 });
else if (activeCountry === 'الأردن') map.flyTo({ center: [35.9, 31.2], zoom: 7.5 });
else if (activeCountry === 'سوريا') map.flyTo({ center: [36.8, 35.0], zoom: 7 });
else if (activeCountry === 'مصر') map.flyTo({ center: [31.2, 29.8], zoom: 6.5 });
else map.flyTo({ center: [41.0, 31.5], zoom: 5.2 });
});
});
// Category Filter
document.querySelectorAll('.cat-chip').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.cat-chip').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
activeCategory = btn.dataset.cat;
renderMarkers();
});
});
// Search Input
document.getElementById('searchInput').addEventListener('input', (e) => {
searchQuery = e.target.value.trim();
renderMarkers();
});
// Robust Polyline Decoder for GraphHopper / Sovereign Routers
function decodePolyline(str, precision = 5) {
if (!str || typeof str !== 'string') return [];
let index = 0, lat = 0, lng = 0;
const coordinates = [];
let shift = 0, result = 0, byte = null;
let latitude_change, longitude_change;
const factor = Math.pow(10, precision);
while (index < str.length) {
byte = null; shift = 0; result = 0;
do {
byte = str.charCodeAt(index++) - 63;
result |= (byte & 0x1f) << shift;
shift += 5;
} while (byte >= 0x20);
latitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += latitude_change;
shift = 0; result = 0;
do {
byte = str.charCodeAt(index++) - 63;
result |= (byte & 0x1f) << shift;
shift += 5;
} while (byte >= 0x20);
longitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += longitude_change;
coordinates.push([lng / factor, lat / factor]);
}
return coordinates;
}
// Sovereign In-App Routing Engine (Strict 100% In-House, Zero Google Maps)
function isPointInCountry(lat, lng, country) {
if (country === 'العراق') return lat >= 29.0 && lat <= 37.5 && lng >= 38.5 && lng <= 49.0;
if (country === 'الأردن') return lat >= 29.1 && lat <= 33.4 && lng >= 34.8 && lng <= 39.3;
if (country === 'سوريا') return lat >= 32.3 && lat <= 37.4 && lng >= 35.6 && lng <= 42.4;
if (country === 'مصر') return lat >= 21.9 && lat <= 31.7 && lng >= 24.7 && lng <= 36.9;
return false;
}
function startSovereignNavigation(lm) {
document.getElementById('landmarkDrawer').style.display = 'none';
const [gateLng, gateLat] = lm.gate;
// Authoritative national routing origins [lng, lat]
const defaultHubs = {
'العراق': [44.3661, 33.3152], // بغداد - ساحة النسور
'الأردن': [35.9106, 31.9539], // عمان - الدوار الرابع
'سوريا': [36.2765, 33.5138], // دمشق - ساحة الأمويين
'مصر': [31.2357, 30.0444] // القاهرة - ميدان التحرير
};
const fallbackHub = defaultHubs[lm.country] || defaultHubs['العراق'];
function computeAndDraw(startLng, startLat) {
// If start point is outside the landmark's sovereign road graph, snap start to national hub
if (!isPointInCountry(startLat, startLng, lm.country)) {
startLng = fallbackHub[0];
startLat = fallbackHub[1];
}
const queryParams = `fromLat=${startLat}&fromLng=${startLng}&toLat=${gateLat}&toLng=${gateLng}&profile=car&steps=true&locale=ar&key=${SOVEREIGN_MAP_API_KEY}`;
// Target local API or direct sovereign production endpoint
const isServerEnv = window.location.hostname.includes('intaleqapp.com') || window.location.port === '3201' || window.location.port === '3204';
const primaryUrl = isServerEnv
? `/api/maps/route?${queryParams}`
: `http://188.68.36.205:3200/api/maps/route?${queryParams}`;
const fallbackUrl = `http://188.68.36.205:3200/api/maps/route?${queryParams}`;
function requestRoute(urlToFetch, isFallback) {
return fetch(urlToFetch, {
headers: { 'x-api-key': SOVEREIGN_MAP_API_KEY }
})
.then(r => {
if (!r.ok) throw new Error('HTTP ' + r.status);
return r.json();
})
.catch(err => {
if (!isFallback && urlToFetch !== fallbackUrl) {
console.warn('Retrying routing via sovereign fallback endpoint...', err);
return requestRoute(fallbackUrl, true);
}
throw err;
});
}
requestRoute(primaryUrl, false)
.then(data => {
if (!data || !data.points) throw new Error('No road geometry returned');
const coords = typeof data.points === 'string' ? decodePolyline(data.points) : data.points;
if (!coords || coords.length < 2) throw new Error('Empty polyline nodes');
const distKm = (data.distance / 1000).toFixed(1);
const etaMins = Math.round(data.duration ? data.duration / 60 : (data.time ? data.time / 60000 : (parseFloat(distKm) / 75) * 60));
const routeName = data.routeName || 'شبكة الطرق الوطنية السريعة';
const instruction = (data.instructions && data.instructions.length > 1)
? `${routeName} • ${data.instructions[1].text}`
: `🛣️ ${routeName} مباشرة إلى بوابة الموقع ومواقف الحافلات`;
drawRouteOnMap(coords, distKm, etaMins, lm, instruction, routeName);
})
.catch(err => {
console.error('Sovereign routing engine error:', err);
alert('تم استدعاء مسار الطرق، يرجى التحقق من اتصال محرك التوجيه السيادي.');
});
}
// 1. Calculate immediately from national hub for zero-latency response
computeAndDraw(fallbackHub[0], fallbackHub[1]);
// 2. If live GPS is granted and inside the same country, refine route seamlessly
if ('geolocation' in navigator) {
navigator.geolocation.getCurrentPosition(
pos => {
if (isPointInCountry(pos.coords.latitude, pos.coords.longitude, lm.country)) {
computeAndDraw(pos.coords.longitude, pos.coords.latitude);
}
},
err => console.log('Geolocation note:', err.message),
{ timeout: 2500 }
);
}
}
function drawRouteOnMap(coords, distKm, etaMins, lm, instruction, routeName) {
const geojson = {
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: coords
}
};
if (map.getSource('sovereign-route')) {
map.getSource('sovereign-route').setData(geojson);
} else {
map.addSource('sovereign-route', {
type: 'geojson',
data: geojson
});
map.addLayer({
id: 'sovereign-route-casing',
type: 'line',
source: 'sovereign-route',
layout: { 'line-join': 'round', 'line-cap': 'round' },
paint: {
'line-color': '#0369a1',
'line-width': 8,
'line-opacity': 0.85
}
});
map.addLayer({
id: 'sovereign-route-core',
type: 'line',
source: 'sovereign-route',
layout: { 'line-join': 'round', 'line-cap': 'round' },
paint: {
'line-color': '#38bdf8',
'line-width': 4.5
}
});
}
const bounds = coords.reduce((b, coord) => b.extend(coord), new maplibregl.LngLatBounds(coords[0], coords[0]));
map.fitBounds(bounds, { padding: 90, pitch: 40, bearing: 5, duration: 1800 });
document.getElementById('navDestName').innerText = `بوابة ${lm.name_ar} (نقطة العبور ومواقف الحافلات)`;
document.getElementById('navDistance').innerText = distKm;
document.getElementById('navEta').innerText = etaMins;
document.getElementById('navInstruction').innerText = instruction || 'اسلك المسار المضاء نحو نقطة الوصول';
document.getElementById('sovereignNavHud').style.display = 'block';
}
document.getElementById('stopNavBtn').addEventListener('click', () => {
document.getElementById('sovereignNavHud').style.display = 'none';
if (map.getSource('sovereign-route')) {
map.getSource('sovereign-route').setData({
type: 'Feature',
properties: {},
geometry: { type: 'LineString', coordinates: [] }
});
}
if (selectedLandmark) {
map.flyTo({ center: selectedLandmark.centroid, zoom: 14.5, pitch: 40 });
}
});
map.on('load', () => {
renderMarkers();
loadAllSovereignLandmarks();
});
</script>
</body>
</html>