ALAMDIENG commited on
Commit
ee58c74
·
1 Parent(s): 7544422

docs & style: upgrade README to production-grade detail and polish mobile responsive UX layouts

Browse files
Files changed (3) hide show
  1. README.md +117 -81
  2. frontend/app.js +1 -3
  3. frontend/style.css +61 -17
README.md CHANGED
@@ -9,81 +9,99 @@ pinned: false
9
  ---
10
 
11
  # 🚛 Aeterna AI: Next-Gen Waste Intelligence Platform
12
- **Platform Sistem Peringatan Dini & Peramalan Sampah Real-Time DKI Jakarta**
13
 
14
- Aeterna AI (sebelumnya Eco-Twin AI) adalah platform analitik cerdas berbasis *Machine Learning* yang dirancang untuk memantau, memprediksi, dan mengoptimalkan manajemen logistik sampah DKI Jakarta secara spasial-temporal harian.
15
 
16
- Sistem ini didesain menggunakan **Clean Architecture** (memisahkan frontend statis yang di-host di Vercel dan backend model AI di Hugging Face Spaces) dengan performa model prediksi yang sangat tinggi.
17
 
18
- ---
 
 
19
 
20
  > [!NOTE]
21
- > **📖 DOKUMENTASI SISTEM BACKEND**:
22
- > Untuk rincian mendalam mengenai arsitektur backend, model machine learning (GBR & Chronos), metrik akurasi GBR (R² 81.51%, MAPE 1.59%), formula rekayasa fitur cuaca/event, dan deployment Docker, silakan merujuk ke **[BACKEND_DOC.md](file:///c:/khusus project IT/Fine tuning ulang AI jakarta/waste-prediction-api/BACKEND_DOC.md)**.
23
 
24
  ---
25
 
26
  ## 🌟 Fitur Unggulan (Key Features)
27
 
28
- 1. **AI Autopilot Forecaster**: AI berjalan secara asinkron dan mandiri untuk memprediksi volume timbulan sampah harian di seluruh **44 Kecamatan DKI Jakarta** secara paralel berdasarkan cuaca live tingkat koordinat dan kalender event aktif hari ini.
29
- 2. **6-Kategori Komposisi Sampah**: Memprediksi rincian tonase sampah secara proporsional sesuai statistik riil Dinas Lingkungan Hidup (DLH) DKI Jakarta menjadi 6 kategori: *Sisa Makanan (~50.2%), Plastik (~22.8%), Kertas (~11.5%), Tekstil (~4.2%), Kaca (~3.2%), dan Logam/Lainnya (~8.1%)*.
30
- 3. **Integrasi Cuaca Live Open-Meteo**: API menarik data curah hujan real-time per kecamatan berdasarkan titik koordinat geografis asli untuk mengukur penambahan berat sampah basah akibat resapan air hujan (2% s.d. 5% multiplier).
31
- 4. **Kalender Event Jakarta 2026**: Mengidentifikasi jadwal acara besar Jakarta (seperti PRJ JIExpo, BTN Marathon, HUT RI di Monas, dll.) untuk menghitung lonjakan kapasitas sampah kerumunan (15% s.d. 30% multiplier).
32
- 5. **Interactive Cyber HUD UI**: Antarmuka bertema *Dark Glassmorphism* modern yang terinspirasi oleh floodzy.id dengan kursor interaktif kustom, visualisasi progress bar kategori neon glow, rincian logistik armada truk, dan efek radar sweep live di peta.
33
 
34
  ---
35
 
36
- ## 📊 Hasil Evaluasi & Akurasi Model GBR
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- Model inti Gradient Boosting Regressor (GBR) dilatih menggunakan **GridSearchCV** untuk mencari hyperparameter terbaik di atas dataset historis teraugmentasi 2 tahun dengan baseline rata-rata kota **8.020 Ton/hari**.
 
 
 
39
 
40
- ### Metrik Evaluasi Model:
 
 
 
 
41
 
42
  | Metrik Evaluasi | Model Baseline | Model Upgraded (Aeterna AI) | Status Performa |
43
  | :--- | :---: | :---: | :--- |
44
- | **Mean Absolute Error (MAE)** | `149.13 Ton` | **`132.29 Ton`** | Semakin Baik (Turun ⬇️) |
45
- | **Root Mean Squared Error (RMSE)** | `188.46 Ton` | **`165.46 Ton`** | Semakin Baik (Turun ⬇️) |
46
- | **R-Squared ($R^2$ Score)** | `76.02%` | **`81.51%`** | Semakin Baik (Naik ⬆️) |
47
  | **Mean Absolute Percentage Error (MAPE)** | `1.78%` | **`1.59%`** | **Sangat Akurat (< 10%) (⬇️)** |
48
 
49
- ### Hyperparameter Terbaik (GBR):
50
- * `n_estimators` (Pohon keputusan): **100**
51
- * `learning_rate`: **0.03**
52
- * `max_depth`: **3**
53
- * `subsample`: **0.9**
54
-
55
  ---
56
 
57
- ## 📂 Struktur Berkas (Clean Architecture)
58
 
59
- ```
60
- waste-prediction-api/
61
- ├── frontend/ (📂 Client-side statis Vercel-ready)
62
- │ ├── index.html (Dashboard Visual)
63
- ├── style.css (Estetika HUD Neon & Animasi)
64
- ├── app.js (Logika Interaksi & Dynamic API routing)
65
- └── vercel.json (Konfigurasi standalone Vercel subfolder)
66
-
67
- ├── vercel.json (Konfigurasi Vercel root level)
68
- ├── app.py (Python FastAPI Backend)
69
- ├── train.py (Skrip training GBR & GridSearchCV)
70
- ├── Dockerfile (Hugging Face Docker deployment)
71
- ├── requirements.txt (Python library dependencies)
72
- ├── model_sampah_advanced.pkl (Binary Model GBR)
73
- ├── latest_waste_news.json (Database Berita Rill)
74
- └── event_jakarta_2026.txt (Jadwal Event Jakarta 2026)
75
- ```
76
 
77
  ---
78
 
79
- ## 📡 Dokumentasi Endpoint API Utama
80
 
81
  Semua endpoint didukung dengan dokumentasi interaktif Swagger UI di `/docs`.
82
 
83
  ### 1. Predict Waste Volume (Forecasting)
84
  * **Method**: `POST`
85
  * **Endpoint**: `/api/v1/predict`
86
- * **Request Body**:
87
  ```json
88
  {
89
  "forecast_days": 7,
@@ -94,72 +112,90 @@ Semua endpoint didukung dengan dokumentasi interaktif Swagger UI di `/docs`.
94
  "granularity": "daily"
95
  }
96
  ```
97
- * **Response JSON (Truncated)**:
98
  ```json
99
  {
100
  "status": "success",
101
- "confidence_score": 0.92,
102
  "message": "Normal conditions.",
103
  "data": {
104
  "prediction_results": [
105
  {
106
- "date": "2026-07-11",
107
- "total_volume_ton": 120.80,
 
108
  "organic_waste_ton": 60.64,
109
  "plastic_waste_ton": 27.54,
110
  "paper_waste_ton": 13.89,
111
- "metal_waste_ton": 9.78,
112
- "glass_waste_ton": 3.87,
113
- "textile_waste_ton": 5.07,
114
- "other_waste_ton": 0.00,
115
- "risk_status": "SAFE",
116
- "event_info": null,
117
- "recommended_trucks": 25
118
  }
119
- ]
 
 
 
 
 
 
120
  }
121
  }
122
  ```
123
 
124
- ### 2. AI Autopilot
125
  * **Method**: `GET`
126
  * **Endpoint**: `/api/v1/autopilot`
127
- * **Description**: Mengembalikan kalkulasi prediksi otonom hari ini untuk seluruh 44 kecamatan DKI secara paralel.
128
 
129
- ### 3. News Feed
130
  * **Method**: `GET`
131
  * **Endpoint**: `/api/v1/news`
132
- * **Description**: Mengembalikan 12 berita riil DKI Jakarta lengkap dengan link langsung ke artikel aslinya.
133
 
134
  ---
135
 
136
- ## 🚀 Panduan Deployment
137
 
138
- ### 1. Deploy ke Hugging Face Spaces (Backend API)
139
- Aplikasi ini sudah dikonfigurasi untuk berjalan di Hugging Face Spaces menggunakan Docker:
140
- 1. Buat Space baru di Hugging Face dengan memilih **SDK: Docker**.
141
- 2. Hubungkan Git Anda atau unggah file di root direktori (termasuk `app.py`, `Dockerfile`, `requirements.txt`, dan `model_sampah_advanced.pkl`).
142
- 3. Port internal Docker sudah otomatis disetel ke `7860` (standar Hugging Face). Space Anda akan otomatis memuat dan menjalankan backend.
143
-
144
- ### 2. Deploy ke Vercel (Frontend Dashboard)
145
- Frontend dirancang agar terpisah dan di-host di Vercel:
146
- 1. Hubungkan repositori GitHub Anda ke akun Vercel.
147
- 2. Buat proyek baru dan pilih repositori `Aeterna-Ai`.
148
- 3. Di bagian pengaturan Vercel, Anda dapat membiarkannya default (Vercel akan mendeteksi `vercel.json` di root) atau mengatur **Root Directory** langsung ke folder `frontend/`.
149
- 4. Vercel akan menyajikan frontend statis dan secara otomatis mem-proxy pemanggilan API `/api` langsung ke backend Hugging Face Space Anda tanpa kendala CORS.
150
-
151
- ---
152
 
153
- ## 🛠️ Pengembangan Lokal (Local Development)
 
 
 
 
154
 
155
- ### 1. Instalasi Dependensi
 
156
  ```bash
157
- pip install -r requirements.txt
 
 
 
 
 
 
 
158
  ```
159
 
160
- ### 2. Jalankan Server API Lokal
161
  ```bash
162
- python -m uvicorn app:app --port 8001 --host 127.0.0.1
 
 
163
  ```
164
- Akses UI lokal di: **[http://localhost:8001](http://localhost:8001)**
165
- Akses Swagger Docs di: **[http://localhost:8001/docs](http://localhost:8001/docs)**
 
 
 
 
 
 
 
 
 
 
 
 
9
  ---
10
 
11
  # 🚛 Aeterna AI: Next-Gen Waste Intelligence Platform
12
+ **Platform Sistem Peringatan Dini & Peramalan Sampah Real-Time DKI Jakarta (Case 2 - AI Open Innovation Challenge 2026)**
13
 
14
+ ---
15
 
16
+ ## 📖 Overview
17
 
18
+ **Aeterna AI** (sebelumnya Eco-Twin AI) adalah platform analitik cerdas berbasis *Machine Learning* yang dirancang untuk memantau, memprediksi, dan mengoptimalkan manajemen logistik sampah DKI Jakarta secara spasial-temporal harian.
19
+
20
+ Platform ini mengubah paradigma pengelolaan sampah dari **reaktif** (menangani setelah terjadi penumpukan) menjadi **prediktif** (memprediksi surge sebelum terjadi) guna mengoptimalkan penyebaran truk pengangkut ke 44 kecamatan DKI Jakarta.
21
 
22
  > [!NOTE]
23
+ > **📖 DOKUMENTASI SISTEM BACKEND MENDALAM**:
24
+ > Untuk rincian mendalam mengenai formula rekayasa fitur cuaca/event, detail hyperparameter GridSearchCV, dan arsitektur asinkron FastAPI, silakan merujuk ke **[BACKEND_DOC.md](file:///c:/khusus project IT/Fine tuning ulang AI jakarta/waste-prediction-api/BACKEND_DOC.md)**.
25
 
26
  ---
27
 
28
  ## 🌟 Fitur Unggulan (Key Features)
29
 
30
+ 1. **AI Autopilot Forecaster**: Sistem asinkron otonom yang mengevaluasi seluruh **44 Kecamatan DKI Jakarta** secara paralel berdasarkan curah hujan tingkat koordinat (Open-Meteo) dan kalender event aktif.
31
+ 2. **6-Kategori Komposisi Sampah**: Memprediksi rincian tonase sampah secara proporsional sesuai statistik riil DLH DKI Jakarta: *Sisa Makanan (~50.2%), Plastik (~22.8%), Kertas (~11.5%), Tekstil (~4.2%), Kaca (~3.2%), dan Logam/Lainnya (~8.1%)*.
32
+ 3. **Dynamic Weather Multiplier**: Mengintegrasikan curah hujan real-time per kecamatan berdasarkan titik koordinat geografis asli untuk mengukur penambahan berat sampah basah akibat resapan air hujan (2% s.d. 5% multiplier).
33
+ 4. **Event Calendar Crowd Engine**: Mengidentifikasi jadwal acara besar Jakarta (seperti PRJ, BTN Marathon, HUT RI, dll.) untuk menghitung lonjakan kapasitas sampah kerumunan (10% s.d. 35% multiplier).
34
+ 5. **Interactive Cyber HUD UI**: Antarmuka bertema *Dark Glassmorphism* dengan kursor delay kustom (lerp), visualisasi progress bar kategori neon glow, rincian logistik armada truk (15-Ton Heavy Compactor), dan rute logistik ke TPST Bantargebang.
35
 
36
  ---
37
 
38
+ ## 🏗️ Arsitektur Sistem (Clean Architecture)
39
+
40
+ Sistem ini didesain menggunakan arsitektur modular multi-platform yang terpisah (*decoupled*):
41
+
42
+ ```
43
+ +-----------------------------------+
44
+ | NEXT.JS FRONTEND |
45
+ | (Hosted on Vercel Global CDN) |
46
+ +-----------------------------------+
47
+ |
48
+ | HTTPS Requests
49
+ v
50
+ +-----------------------------------+
51
+ | LARAVEL BACKEND |
52
+ | (API Controller & Gateway) |
53
+ +-----------------------------------+
54
+ |
55
+ | REST Proxy API
56
+ v
57
+ +---------------------------------------------------------------------------------------------------+
58
+ | PYTHON ML MICROSERVICE CONTAINER |
59
+ | (Docker - Hosted on Hugging Face Spaces) |
60
+ | |
61
+ | [ FastAPI ] --> [ GBR Model (GridSearchCV) ] & [ Amazon Chronos-T5 ] --> [ Open-Meteo API Sync ] |
62
+ +---------------------------------------------------------------------------------------------------+
63
+ ```
64
 
65
+ ### Penjelasan Lapisan (Layers):
66
+ * **Front-End Layer (Next.js)**: Menyajikan antarmuka pengguna interaktif. Memanfaatkan *Next.js Dynamic Imports* dengan SSR dinonaktifkan khusus untuk modul **Leaflet.js** agar peta interaktif dapat dirender secara asinkron di client-side tanpa memicu error server-node.
67
+ * **API Gateway Layer (Laravel)**: Berfungsi sebagai backend pengendali utama. Menangani middleware CORS, validasi skema request, manajemen kalender event, parsing berita, dan mengamankan pemanggilan proxy ke microservice AI.
68
+ * **ML Microservice Layer (Python)**: Kontainer Docker yang memuat model AI (GBR & Chronos) dan menyajikan API prediksi berkecepatan tinggi menggunakan FastAPI dengan threadpool non-blocking.
69
 
70
+ ---
71
+
72
+ ## 📊 Hasil Evaluasi & Akurasi Model GBR
73
+
74
+ Model GBR dilatih dengan **GridSearchCV** di atas dataset historis teraugmentasi 2 tahun dengan baseline rata-rata kota **8.020 Ton/hari**.
75
 
76
  | Metrik Evaluasi | Model Baseline | Model Upgraded (Aeterna AI) | Status Performa |
77
  | :--- | :---: | :---: | :--- |
78
+ | **Mean Absolute Error (MAE)** | `149.13 Ton` | **`132.29 Ton`** | Lebih Baik (Turun ⬇️) |
79
+ | **Root Mean Squared Error (RMSE)** | `188.46 Ton` | **`165.46 Ton`** | Lebih Baik (Turun ⬇️) |
80
+ | **R-Squared ($R^2$ Score)** | `76.02%` | **`81.51%`** | Lebih Baik (Naik ⬆️) |
81
  | **Mean Absolute Percentage Error (MAPE)** | `1.78%` | **`1.59%`** | **Sangat Akurat (< 10%) (⬇️)** |
82
 
 
 
 
 
 
 
83
  ---
84
 
85
+ ## 🌦️ Model Rekayasa Fitur Matematika
86
 
87
+ ### A. Rainfall weight multiplier:
88
+ $$Volume_{calibrated} = Volume_{pred} \times \left(1.0 + \frac{Precipitation_{mm}}{1000} \right)$$
89
+
90
+ ### B. Event Crowd Multiplier:
91
+ * Skala 1 s.d. 2 (Lokal): **+10% s.d. +15%** volume sampah.
92
+ * Skala 3 s.d. 4 (Regional): **+20% s.d. +25%** volume sampah.
93
+ * Skala 5 (Nasional / Hari Raya): **+30% s.d. +35%** volume sampah.
 
 
 
 
 
 
 
 
 
 
94
 
95
  ---
96
 
97
+ ## 📡 Referensi Endpoint API Utama
98
 
99
  Semua endpoint didukung dengan dokumentasi interaktif Swagger UI di `/docs`.
100
 
101
  ### 1. Predict Waste Volume (Forecasting)
102
  * **Method**: `POST`
103
  * **Endpoint**: `/api/v1/predict`
104
+ * **Request Payload**:
105
  ```json
106
  {
107
  "forecast_days": 7,
 
112
  "granularity": "daily"
113
  }
114
  ```
115
+ * **Response Payload**:
116
  ```json
117
  {
118
  "status": "success",
119
+ "confidence_score": 0.9325,
120
  "message": "Normal conditions.",
121
  "data": {
122
  "prediction_results": [
123
  {
124
+ "date": "2026-07-15",
125
+ "location": "Menteng",
126
+ "total_volume_ton": 120.8,
127
  "organic_waste_ton": 60.64,
128
  "plastic_waste_ton": 27.54,
129
  "paper_waste_ton": 13.89,
130
+ "recommended_trucks": 8,
131
+ "risk_status": "SAFE"
 
 
 
 
 
132
  }
133
+ ],
134
+ "logistics_plan": {
135
+ "trucks_needed": 8,
136
+ "manpower": 24,
137
+ "estimated_duration_hours": 8.1,
138
+ "efficiency_rate": "85% (Optimal)"
139
+ }
140
  }
141
  }
142
  ```
143
 
144
+ ### 2. Autopilot Live DKI (Today)
145
  * **Method**: `GET`
146
  * **Endpoint**: `/api/v1/autopilot`
147
+ * **Description**: Mengembalikan kalkulasi prediksi otonom hari ini untuk seluruh 44 kecamatan DKI secara paralel lengkap dengan data koordinat (latitude, longitude) untuk plotting peta instan.
148
 
149
+ ### 3. News Feed API
150
  * **Method**: `GET`
151
  * **Endpoint**: `/api/v1/news`
152
+ * **Description**: Mengembalikan 10 berita persampahan DKI Jakarta terbaru yang diperbarui dinamis menggunakan Conduit AI API (dengan generator fallback lokal).
153
 
154
  ---
155
 
156
+ ## 🛠️ Panduan Instalasi & Pengembangan Lokal
157
 
158
+ ### 1. Prasyarat & Backend Setup (Python ML)
159
+ Masuk ke root folder proyek:
160
+ ```bash
161
+ # Install dependencies
162
+ pip install -r requirements.txt
 
 
 
 
 
 
 
 
 
163
 
164
+ # Jalankan server FastAPI lokal
165
+ python -m uvicorn app:app --port 8001 --host 127.0.0.1
166
+ ```
167
+ * Akses UI di: `http://localhost:8001`
168
+ * Akses Swagger di: `http://localhost:8001/docs`
169
 
170
+ ### 2. Setup Backend Controller (Laravel)
171
+ Jika menggunakan controller Laravel untuk mengamankan route API:
172
  ```bash
173
+ # Clone atau masuk ke direktori Laravel Anda
174
+ composer install
175
+ cp .env.example .env
176
+ php artisan key:generate
177
+ ```
178
+ Di dalam berkas `.env` Laravel, arahkan URL microservice AI Anda:
179
+ ```env
180
+ AETERNA_ML_SERVICE_URL=http://localhost:8001
181
  ```
182
 
183
+ ### 3. Setup Frontend Dashboard (Next.js)
184
  ```bash
185
+ # Masuk ke folder Next.js
186
+ npm install
187
+ npm run dev
188
  ```
189
+ * Pastikan Leaflet di-import dinamis:
190
+ ```javascript
191
+ import dynamic from 'next/dynamic';
192
+ const MapComponent = dynamic(() => import('../components/Map'), { ssr: false });
193
+ ```
194
+
195
+ ---
196
+
197
+ ## 👥 Kontributor Tim Pengembang (Aeterna Team)
198
+
199
+ * **FARIL PUTRA PRATAMA** (AI Engineer) — *SMK Taruna Bangsa*
200
+ * **ARGA KURNIAWAN** (Front End Developer)
201
+ * **BAGAS TRESNA MUSTIDA SAKLI** (System Architecture)
frontend/app.js CHANGED
@@ -729,9 +729,7 @@ async function loadAutopilotFeed() {
729
  autoRiskList.innerHTML = "";
730
  data.top_kecamatan.forEach((item, index) => {
731
  const card = document.createElement("div");
732
- card.className = "alert-row";
733
- card.style.gridTemplateColumns = "60px 180px 100px 1fr";
734
- card.style.padding = "0.6rem 1.2rem";
735
  card.innerHTML = `
736
  <span class="alert-date" style="font-weight:bold; color:var(--cyan);">#0${index+1}</span>
737
  <span class="alert-location">${item.location}</span>
 
729
  autoRiskList.innerHTML = "";
730
  data.top_kecamatan.forEach((item, index) => {
731
  const card = document.createElement("div");
732
+ card.className = "alert-row autopilot-row";
 
 
733
  card.innerHTML = `
734
  <span class="alert-date" style="font-weight:bold; color:var(--cyan);">#0${index+1}</span>
735
  <span class="alert-location">${item.location}</span>
frontend/style.css CHANGED
@@ -1120,10 +1120,8 @@ footer {
1120
  cursor: pointer;
1121
  }
1122
 
1123
- @media (max-width: 768px) {
1124
- .alert-row {
1125
- grid-template-columns: 1fr 1fr;
1126
- }
1127
  }
1128
 
1129
  .alert-row:hover {
@@ -1388,9 +1386,21 @@ body::after {
1388
  ========================================== */
1389
  @media (max-width: 1200px) {
1390
  .dashboard-grid {
1391
- grid-template-columns: 1fr !important;
 
1392
  height: auto !important;
1393
  overflow: visible !important;
 
 
 
 
 
 
 
 
 
 
 
1394
  }
1395
  .page-container {
1396
  height: auto !important;
@@ -1424,24 +1434,32 @@ body::after {
1424
  justify-content: center;
1425
  flex-wrap: wrap;
1426
  }
 
1427
  .nav-links {
1428
- flex-wrap: wrap;
1429
- justify-content: center;
1430
- gap: 0.6rem !important;
1431
- width: 100%;
 
 
 
 
1432
  }
1433
  .nav-btn {
1434
- padding: 6px 12px !important;
1435
- font-size: 0.75rem !important;
1436
- flex-grow: 1;
1437
- text-align: center;
 
 
1438
  }
1439
  .system-status {
1440
  justify-content: center;
1441
  width: 100%;
 
1442
  }
1443
  .page-container {
1444
- padding: 1rem 1.5rem !important;
1445
  }
1446
  .stats-row {
1447
  grid-template-columns: 1fr !important;
@@ -1457,11 +1475,37 @@ body::after {
1457
  font-size: 0.95rem !important;
1458
  }
1459
  .map-panel {
1460
- height: 320px !important;
1461
  }
1462
  .logistics-grid {
1463
  grid-template-columns: 1fr !important;
1464
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1465
  }
1466
 
1467
  @media (max-width: 480px) {
@@ -1469,8 +1513,8 @@ body::after {
1469
  font-size: 1.5rem !important;
1470
  }
1471
  .nav-btn {
1472
- font-size: 0.7rem !important;
1473
- padding: 5px 10px !important;
1474
  }
1475
  .section-title {
1476
  font-size: 1.2rem !important;
 
1120
  cursor: pointer;
1121
  }
1122
 
1123
+ .autopilot-row {
1124
+ grid-template-columns: 60px 180px 100px 1fr !important;
 
 
1125
  }
1126
 
1127
  .alert-row:hover {
 
1386
  ========================================== */
1387
  @media (max-width: 1200px) {
1388
  .dashboard-grid {
1389
+ display: flex !important;
1390
+ flex-direction: column !important;
1391
  height: auto !important;
1392
  overflow: visible !important;
1393
+ gap: 1.5rem !important;
1394
+ }
1395
+ /* Smart re-ordering for mobile: Show Map & Stats first, then Config Panel, then Charts */
1396
+ .map-and-stats {
1397
+ order: -1 !important;
1398
+ }
1399
+ .control-panel {
1400
+ order: 0 !important;
1401
+ }
1402
+ .analysis-panel {
1403
+ order: 1 !important;
1404
  }
1405
  .page-container {
1406
  height: auto !important;
 
1434
  justify-content: center;
1435
  flex-wrap: wrap;
1436
  }
1437
+ /* Sleek Equal-width Segmented Tab-bar on Mobile */
1438
  .nav-links {
1439
+ display: grid !important;
1440
+ grid-template-columns: repeat(3, 1fr) !important;
1441
+ gap: 0.5rem !important;
1442
+ width: 100% !important;
1443
+ background: rgba(0, 0, 0, 0.4);
1444
+ padding: 4px;
1445
+ border-radius: 8px;
1446
+ border: 1px solid rgba(255, 255, 255, 0.05);
1447
  }
1448
  .nav-btn {
1449
+ width: 100% !important;
1450
+ padding: 8px 4px !important;
1451
+ font-size: 0.72rem !important;
1452
+ text-align: center !important;
1453
+ justify-content: center !important;
1454
+ margin: 0 !important;
1455
  }
1456
  .system-status {
1457
  justify-content: center;
1458
  width: 100%;
1459
+ margin-top: 0.2rem;
1460
  }
1461
  .page-container {
1462
+ padding: 1rem 1.2rem !important;
1463
  }
1464
  .stats-row {
1465
  grid-template-columns: 1fr !important;
 
1475
  font-size: 0.95rem !important;
1476
  }
1477
  .map-panel {
1478
+ height: 350px !important;
1479
  }
1480
  .logistics-grid {
1481
  grid-template-columns: 1fr !important;
1482
  }
1483
+ /* Stack progress bars in 1 column to prevent text clipping */
1484
+ .progress-container {
1485
+ grid-template-columns: 1fr !important;
1486
+ gap: 1rem !important;
1487
+ }
1488
+ /* Flex stack alerts to fit narrow viewports beautifully */
1489
+ .alert-row, .autopilot-row {
1490
+ display: flex !important;
1491
+ flex-direction: column !important;
1492
+ align-items: flex-start !important;
1493
+ gap: 0.5rem !important;
1494
+ padding: 1rem 1.2rem !important;
1495
+ }
1496
+ .alert-row > *, .autopilot-row > * {
1497
+ width: auto !important;
1498
+ margin: 0 !important;
1499
+ text-align: left !important;
1500
+ }
1501
+ .alert-desc, .alert-location {
1502
+ font-size: 0.8rem !important;
1503
+ word-break: break-word !important;
1504
+ line-height: 1.4 !important;
1505
+ }
1506
+ .alert-badge {
1507
+ align-self: flex-start !important;
1508
+ }
1509
  }
1510
 
1511
  @media (max-width: 480px) {
 
1513
  font-size: 1.5rem !important;
1514
  }
1515
  .nav-btn {
1516
+ font-size: 0.68rem !important;
1517
+ padding: 6px 2px !important;
1518
  }
1519
  .section-title {
1520
  font-size: 1.2rem !important;