ALAMDIENG commited on
Commit
cb8bd0e
·
1 Parent(s): 6995537

feat(ui): implement Eco-Joy Analytics light-mode UI/UX redesign with custom fonts, colors, Voyager map, and micro-animations

Browse files
Files changed (3) hide show
  1. frontend/app.js +3 -3
  2. frontend/index.html +1 -1
  3. frontend/style.css +497 -619
frontend/app.js CHANGED
@@ -241,7 +241,7 @@ function initMap() {
241
  minZoom: 9
242
  }).setView([-6.175, 106.825], 11.5);
243
 
244
- L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
245
  maxZoom: 20
246
  }).addTo(map);
247
 
@@ -842,7 +842,7 @@ class DataParticle {
842
  }
843
  }
844
  draw() {
845
- ctx.fillStyle = `rgba(0, 240, 255, ${this.alpha})`;
846
  ctx.beginPath();
847
  ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
848
  ctx.fill();
@@ -868,7 +868,7 @@ class RainDrop {
868
  }
869
  }
870
  draw() {
871
- ctx.strokeStyle = `rgba(0, 240, 255, ${this.alpha})`;
872
  ctx.lineWidth = this.weight;
873
  ctx.beginPath();
874
  ctx.moveTo(this.x, this.y);
 
241
  minZoom: 9
242
  }).setView([-6.175, 106.825], 11.5);
243
 
244
+ L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
245
  maxZoom: 20
246
  }).addTo(map);
247
 
 
842
  }
843
  }
844
  draw() {
845
+ ctx.fillStyle = `rgba(0, 107, 95, ${this.alpha})`;
846
  ctx.beginPath();
847
  ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
848
  ctx.fill();
 
868
  }
869
  }
870
  draw() {
871
+ ctx.strokeStyle = `rgba(0, 107, 95, ${this.alpha})`;
872
  ctx.lineWidth = this.weight;
873
  ctx.beginPath();
874
  ctx.moveTo(this.x, this.y);
frontend/index.html CHANGED
@@ -52,7 +52,7 @@
52
  <!-- Google Fonts -->
53
  <link rel="preconnect" href="https://fonts.googleapis.com">
54
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
55
- <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;800&family=Space+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@300;400;700&display=swap" rel="stylesheet">
56
 
57
  <!-- Leaflet.js Map Library -->
58
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
 
52
  <!-- Google Fonts -->
53
  <link rel="preconnect" href="https://fonts.googleapis.com">
54
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
55
+ <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;600;700;800&family=Be+Vietnam+Pro:wght@300;400;500;600;700&family=JetBrains+Mono:wght@300;400;700&display=swap" rel="stylesheet">
56
 
57
  <!-- Leaflet.js Map Library -->
58
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
frontend/style.css CHANGED
@@ -1,30 +1,46 @@
1
- /* CSS Variables for Theming */
2
  :root {
3
- --bg-void: #02040a;
4
- --bg-panel: rgba(6, 10, 22, 0.75);
5
- --border-color: rgba(0, 240, 255, 0.12);
6
- --border-hover: rgba(0, 240, 255, 0.3);
 
 
7
 
8
- --text-main: #E1E3E8;
9
- --text-muted: #8c93a3;
10
 
11
- /* Neon Colors */
12
- --cyan: #00F0FF;
13
- --cyan-glow: rgba(0, 240, 255, 0.45);
14
- --green: #39FF14;
15
- --green-glow: rgba(57, 255, 20, 0.35);
16
- --yellow: #FFE600;
17
- --yellow-glow: rgba(255, 230, 0, 0.35);
18
- --red: #FF0055;
19
- --red-glow: rgba(255, 0, 85, 0.45);
20
 
21
- /* Fonts */
22
- --font-display: 'Outfit', 'Space Grotesk', system-ui, sans-serif;
23
- --font-body: 'Space Grotesk', system-ui, sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  --font-mono: 'JetBrains Mono', monospace;
25
  }
26
 
27
- /* Base resets */
28
  * {
29
  box-sizing: border-box;
30
  margin: 0;
@@ -35,6 +51,7 @@ body {
35
  background-color: var(--bg-void);
36
  color: var(--text-main);
37
  font-family: var(--font-body);
 
38
  overflow-x: hidden;
39
  min-height: 100vh;
40
  display: flex;
@@ -50,54 +67,53 @@ body {
50
  height: 100%;
51
  z-index: 0;
52
  pointer-events: none;
53
- opacity: 0.45;
54
  }
55
 
56
- /* Header */
57
  header {
58
  width: 100%;
59
- padding: 1.5rem 2.5rem;
60
- background: linear-gradient(to bottom, rgba(2, 4, 10, 0.95) 60%, transparent);
61
  display: flex;
62
  justify-content: space-between;
63
  align-items: center;
64
- border-bottom: 1px solid rgba(255, 255, 255, 0.03);
65
  z-index: 10;
66
  position: relative;
 
67
  }
68
 
69
  .logo-container {
70
  display: flex;
71
- align-items: baseline;
72
- gap: 10px;
73
  }
74
 
75
  .logo-text {
76
  font-family: var(--font-display);
77
  font-size: 1.8rem;
78
  font-weight: 800;
79
- letter-spacing: 2px;
80
- background: linear-gradient(135deg, #FFF 40%, var(--cyan) 100%);
81
  -webkit-background-clip: text;
82
  -webkit-text-fill-color: transparent;
83
- text-shadow: 0 0 20px rgba(0, 240, 255, 0.15);
84
  }
85
 
86
  .logo-text .highlight {
87
- font-weight: 300;
88
- letter-spacing: 0px;
89
- color: var(--cyan);
90
- margin-left: 4px;
91
  }
92
 
93
  .version-tag {
94
  font-family: var(--font-mono);
95
- font-size: 0.75rem;
96
  color: var(--text-muted);
97
- background: rgba(255, 255, 255, 0.05);
98
  padding: 2px 8px;
99
- border-radius: 4px;
100
- border: 1px solid rgba(255, 255, 255, 0.08);
 
101
  }
102
 
103
  .system-status {
@@ -107,14 +123,14 @@ header {
107
  }
108
 
109
  .status-indicator {
110
- width: 8px;
111
- height: 8px;
112
  border-radius: 50%;
113
  }
114
 
115
  .status-indicator.online {
116
  background-color: var(--green);
117
- box-shadow: 0 0 10px var(--green-glow), 0 0 20px var(--green-glow);
118
  animation: pulse-green 2s infinite;
119
  }
120
 
@@ -122,63 +138,110 @@ header {
122
  font-family: var(--font-mono);
123
  font-size: 0.8rem;
124
  color: var(--text-muted);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
126
 
127
  /* Grid Layout */
128
  .dashboard-grid {
129
  display: grid;
130
- grid-template-columns: 320px 1fr 340px;
131
- gap: 1.5rem;
132
- padding: 1.5rem 2.5rem;
133
  flex: 1;
134
  z-index: 5;
135
  position: relative;
 
 
 
136
  }
137
 
138
- @media (max-width: 1200px) {
139
- .dashboard-grid {
140
- grid-template-columns: 1fr;
141
- }
142
- }
143
-
144
- /* Panels */
145
  .panel {
146
  background: var(--bg-panel);
147
- border: 1px solid var(--border-color);
148
- border-radius: 12px;
149
- padding: 1.5rem;
150
- backdrop-filter: blur(16px);
151
- box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
152
- transition: border-color 0.3s, box-shadow 0.3s;
 
153
  }
154
 
155
  .panel:hover {
156
- border-color: var(--border-hover);
157
- box-shadow: 0 8px 32px 0 rgba(0, 240, 255, 0.05);
 
158
  }
159
 
160
  .panel-title {
161
  font-family: var(--font-display);
162
- font-size: 0.95rem;
163
- font-weight: 600;
164
- letter-spacing: 1.5px;
165
- color: var(--text-main);
166
  margin-bottom: 1.2rem;
167
- border-left: 3px solid var(--cyan);
168
- padding-left: 8px;
169
  text-transform: uppercase;
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  }
171
 
172
  .panel-subtitle {
173
  font-family: var(--font-display);
174
  font-size: 0.85rem;
175
- font-weight: 600;
176
- color: var(--cyan);
177
  margin-bottom: 1rem;
178
  text-transform: uppercase;
179
  }
180
 
181
- /* Controls */
182
  .control-group {
183
  margin-bottom: 1.2rem;
184
  }
@@ -189,54 +252,60 @@ header {
189
  color: var(--text-muted);
190
  margin-bottom: 6px;
191
  text-transform: uppercase;
192
- font-family: var(--font-mono);
 
193
  }
194
 
195
  .form-control {
196
  width: 100%;
197
- background: rgba(0, 0, 0, 0.4);
198
- border: 1px solid var(--border-color);
199
  color: var(--text-main);
200
  padding: 10px 14px;
201
  border-radius: 8px;
202
  outline: none;
203
  font-family: var(--font-body);
204
  font-size: 0.9rem;
205
- transition: border-color 0.3s;
 
206
  }
207
 
208
  .form-control:focus {
209
- border-color: var(--cyan);
 
210
  }
211
 
 
212
  .slider {
213
  width: 100%;
214
  -webkit-appearance: none;
215
- height: 6px;
216
- border-radius: 3px;
217
- background: rgba(255, 255, 255, 0.1);
218
  outline: none;
219
  }
220
 
221
  .slider::-webkit-slider-thumb {
222
  -webkit-appearance: none;
223
- width: 16px;
224
- height: 16px;
225
  border-radius: 50%;
226
- background: var(--cyan);
227
- box-shadow: 0 0 10px var(--cyan-glow);
 
228
  cursor: pointer;
229
- transition: transform 0.1s;
230
  }
231
 
232
  .slider::-webkit-slider-thumb:hover {
233
- transform: scale(1.25);
 
234
  }
235
 
236
  .value-display, .override-display {
237
  font-family: var(--font-mono);
238
- color: var(--cyan);
239
- font-weight: bold;
240
  float: right;
241
  }
242
 
@@ -247,34 +316,40 @@ header {
247
  }
248
 
249
  .divider {
250
- height: 1px;
251
- background: rgba(255, 255, 255, 0.05);
252
  margin: 1.5rem 0;
 
253
  }
254
 
255
- /* Buttons */
256
  .action-btn {
257
  width: 100%;
258
- padding: 12px;
259
- background: rgba(0, 240, 255, 0.06);
260
- border: 1px solid var(--cyan);
261
- color: var(--cyan);
262
- font-family: var(--font-mono);
263
- font-size: 0.90rem;
264
- font-weight: bold;
265
- border-radius: 8px;
266
  cursor: pointer;
267
  position: relative;
268
  overflow: hidden;
269
- transition: background 0.3s, box-shadow 0.3s;
 
270
  }
271
 
272
  .action-btn:hover {
273
- background: rgba(0, 240, 255, 0.15);
274
- box-shadow: 0 0 20px var(--cyan-glow);
275
  }
276
 
277
- /* Map Panel with Leaflet Map */
 
 
 
 
278
  .map-panel {
279
  display: flex;
280
  flex-direction: column;
@@ -285,10 +360,10 @@ header {
285
  .map-container {
286
  flex: 1;
287
  position: relative;
288
- background: rgba(0, 0, 0, 0.3);
289
- border-radius: 8px;
290
  overflow: hidden;
291
- border: 1px solid var(--border-color);
292
  }
293
 
294
  #map {
@@ -297,15 +372,29 @@ header {
297
  background: var(--bg-void) !important;
298
  }
299
 
300
- /* Custom Marker Styling for Leaflet */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  .leaflet-custom-marker {
302
  position: absolute;
303
  width: 24px !important;
304
  height: 24px !important;
305
- /* Allow Leaflet's dynamic engine to set margins from iconAnchor without CSS overrides */
306
  transform-origin: center center;
307
- backface-visibility: hidden;
308
- -webkit-backface-visibility: hidden;
309
  cursor: pointer;
310
  }
311
 
@@ -317,11 +406,11 @@ header {
317
  height: 28px;
318
  margin-left: -14px;
319
  margin-top: -14px;
320
- background: var(--cyan);
321
  border-radius: 50%;
322
- opacity: 0.15;
323
  transform: scale(1);
324
- animation: pulse-node 2s infinite;
325
  pointer-events: none;
326
  }
327
 
@@ -329,15 +418,15 @@ header {
329
  position: absolute;
330
  top: 50%;
331
  left: 50%;
332
- width: 12px;
333
- height: 12px;
334
- margin-left: -6px;
335
- margin-top: -6px;
336
- background: var(--cyan);
337
- border: 2px solid #FFF;
338
  border-radius: 50%;
339
- box-shadow: 0 0 10px var(--cyan-glow);
340
- transition: transform 0.2s, background 0.3s;
341
  }
342
 
343
  .leaflet-custom-marker .marker-label {
@@ -345,90 +434,72 @@ header {
345
  top: -24px;
346
  left: 50%;
347
  transform: translateX(-50%);
348
- font-family: var(--font-mono);
349
  font-size: 10px;
350
- font-weight: bold;
351
- color: var(--text-muted);
352
- background: rgba(0, 0, 0, 0.85);
353
- padding: 2px 6px;
354
- border-radius: 4px;
355
- border: 1px solid rgba(255, 255, 255, 0.15);
356
  white-space: nowrap;
357
  pointer-events: none;
358
- transition: color 0.3s, border-color 0.3s;
 
359
  }
360
 
361
- /* Hover and Active State */
362
  .leaflet-custom-marker:hover .marker-core {
363
  transform: scale(1.2);
364
  }
365
 
366
  .leaflet-custom-marker.active .marker-core {
367
  transform: scale(1.3);
368
- background: var(--cyan);
369
- box-shadow: 0 0 15px var(--cyan), 0 0 25px var(--cyan-glow);
370
  }
371
 
372
  .leaflet-custom-marker.active .marker-label {
373
- color: var(--cyan);
374
- border-color: var(--cyan);
375
- box-shadow: 0 0 10px rgba(0, 240, 255, 0.2);
376
  }
377
 
378
- /* Risk indicator classes for Leaflet Markers */
379
- .leaflet-custom-marker.safe .marker-core {
380
- background: var(--green);
381
- box-shadow: 0 0 10px var(--green-glow);
382
- }
383
- .leaflet-custom-marker.safe .marker-pulse {
384
- background: var(--green);
385
- }
386
 
387
- .leaflet-custom-marker.warning .marker-core {
388
- background: var(--yellow);
389
- box-shadow: 0 0 10px var(--yellow-glow);
390
- }
391
- .leaflet-custom-marker.warning .marker-pulse {
392
- background: var(--yellow);
393
- }
394
 
395
- .leaflet-custom-marker.critical .marker-core {
396
- background: var(--red);
397
- box-shadow: 0 0 10px var(--red-glow);
398
- }
399
- .leaflet-custom-marker.critical .marker-pulse {
400
- background: var(--red);
401
- }
402
 
403
- /* Leaflet Layout UI Overrides */
404
  .leaflet-bar {
405
- border: 1px solid var(--border-color) !important;
406
  border-radius: 8px !important;
407
  overflow: hidden;
408
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6) !important;
409
  }
410
 
411
  .leaflet-bar a {
412
- background-color: rgba(6, 10, 22, 0.85) !important;
413
  color: var(--text-main) !important;
414
- border-bottom: 1px solid var(--border-color) !important;
415
  transition: background-color 0.2s, color 0.2s;
416
  }
417
 
418
  .leaflet-bar a:hover {
419
- background-color: rgba(0, 240, 255, 0.15) !important;
420
- color: var(--cyan) !important;
421
  }
422
 
423
- .leaflet-container {
424
- background: var(--bg-void) !important;
425
- }
426
-
427
- /* Stats Cards */
428
  .stats-row {
429
  display: grid;
430
  grid-template-columns: repeat(3, 1fr);
431
- gap: 1.5rem;
432
  }
433
 
434
  .stat-card {
@@ -440,58 +511,57 @@ header {
440
  }
441
 
442
  .card-label {
443
- font-family: var(--font-mono);
444
- font-size: 0.7rem;
445
  color: var(--text-muted);
446
- margin-bottom: 6px;
447
  text-transform: uppercase;
 
448
  }
449
 
450
  .card-value {
451
  font-family: var(--font-display);
452
- font-size: 1.5rem;
453
  font-weight: 800;
454
- color: #FFF;
455
  }
456
 
457
  .card-value .unit {
458
  font-size: 0.85rem;
459
- font-weight: 400;
460
  color: var(--text-muted);
461
  }
462
 
 
463
  .status-badge {
464
  display: inline-block;
465
- padding: 4px 12px;
466
- border-radius: 6px;
467
- font-size: 0.95rem;
468
- font-weight: bold;
469
  text-align: center;
470
  width: fit-content;
471
  }
472
 
473
  .status-badge.safe {
474
- background: rgba(57, 255, 20, 0.08);
475
- border: 1px solid var(--green);
476
- color: var(--green);
477
- text-shadow: 0 0 10px var(--green-glow);
478
  }
479
 
480
  .status-badge.warning {
481
- background: rgba(255, 230, 0, 0.08);
482
- border: 1px solid var(--yellow);
483
- color: var(--yellow);
484
- text-shadow: 0 0 10px var(--yellow-glow);
485
  }
486
 
487
  .status-badge.critical {
488
- background: rgba(255, 0, 85, 0.08);
489
- border: 1px solid var(--red);
490
  color: var(--red);
491
- text-shadow: 0 0 10px var(--red-glow);
492
  }
493
 
494
- /* Composition / Progress bars */
495
  .progress-item {
496
  margin-bottom: 1.2rem;
497
  }
@@ -502,77 +572,57 @@ header {
502
  font-size: 0.8rem;
503
  color: var(--text-muted);
504
  margin-bottom: 6px;
505
- font-family: var(--font-mono);
 
506
  }
507
 
508
  .progress-bar-bg {
509
  width: 100%;
510
- height: 8px;
511
- background: rgba(255, 255, 255, 0.05);
512
- border-radius: 4px;
513
  overflow: hidden;
 
514
  }
515
 
516
  .progress-bar-fill {
517
  height: 100%;
518
- border-radius: 4px;
519
  width: 0%;
520
  transition: width 0.8s cubic-bezier(0.25, 0.8, 0.25, 1);
521
  }
522
 
523
- .progress-bar-fill.organic {
524
- background: linear-gradient(to right, #4CAF50, #8BC34A);
525
- box-shadow: 0 0 10px rgba(76, 175, 80, 0.3);
526
- }
527
-
528
- .progress-bar-fill.plastic {
529
- background: linear-gradient(to right, var(--cyan), #00BCD4);
530
- box-shadow: 0 0 10px rgba(0, 240, 255, 0.3);
531
- }
532
 
533
- .progress-bar-fill.paper {
534
- background: linear-gradient(to right, var(--yellow), #FF9900);
535
- box-shadow: 0 0 10px rgba(255, 230, 0, 0.3);
536
- }
537
-
538
- .progress-bar-fill.glass {
539
- background: linear-gradient(to right, var(--red), #E040FB);
540
- box-shadow: 0 0 10px rgba(255, 0, 85, 0.3);
541
- }
542
-
543
- .progress-bar-fill.textile {
544
- background: linear-gradient(to right, #CC66FF, #2196F3);
545
- box-shadow: 0 0 10px rgba(204, 102, 255, 0.3);
546
- }
547
-
548
- .progress-bar-fill.metal {
549
- background: linear-gradient(to right, #E1E3E8, var(--cyan));
550
- box-shadow: 0 0 10px rgba(225, 227, 232, 0.3);
551
- }
552
-
553
- /* Weather & Event Panel */
554
  .weather-grid {
555
  display: flex;
556
  justify-content: space-between;
557
  align-items: center;
558
- background: rgba(0, 0, 0, 0.25);
559
  padding: 12px;
560
  border-radius: 8px;
561
- border: 1px solid rgba(255, 255, 255, 0.03);
562
  margin-bottom: 1rem;
563
  }
564
 
565
  .weather-temp {
566
  font-family: var(--font-display);
567
  font-size: 1.2rem;
568
- font-weight: 700;
569
- color: #FFF;
570
  }
571
 
572
  .weather-label {
573
  display: block;
574
  font-size: 0.75rem;
575
  color: var(--text-muted);
 
576
  }
577
 
578
  .weather-details {
@@ -580,34 +630,40 @@ header {
580
  font-size: 0.75rem;
581
  text-align: right;
582
  line-height: 1.4;
 
583
  }
584
 
585
  .weather-details .highlight {
586
- color: var(--cyan);
587
  }
588
 
589
  .event-box {
590
- padding: 10px;
591
- background: rgba(255, 230, 0, 0.03);
592
- border-left: 3px solid var(--yellow);
593
- border-radius: 0 6px 6px 0;
 
 
 
594
  }
595
 
596
  .event-title {
597
  display: block;
598
  font-size: 0.75rem;
599
- font-weight: bold;
600
- color: var(--yellow);
601
- font-family: var(--font-mono);
602
  margin-bottom: 4px;
 
603
  }
604
 
605
  .event-desc {
606
  font-size: 0.8rem;
607
  color: var(--text-main);
 
608
  }
609
 
610
- /* Logistics Grid */
611
  .logistics-grid {
612
  display: grid;
613
  grid-template-columns: 1fr 1fr;
@@ -615,34 +671,34 @@ header {
615
  }
616
 
617
  .log-item {
618
- background: rgba(0, 0, 0, 0.2);
619
- border: 1px solid rgba(255, 255, 255, 0.03);
620
- border-radius: 8px;
621
  padding: 10px;
622
  display: flex;
623
  flex-direction: column;
624
  }
625
 
626
  .log-label {
627
- font-family: var(--font-mono);
628
- font-size: 0.65rem;
629
  color: var(--text-muted);
630
  text-transform: uppercase;
 
631
  margin-bottom: 4px;
632
  }
633
 
634
  .log-value {
635
  font-size: 0.95rem;
636
- font-weight: bold;
637
- color: #FFF;
638
  }
639
 
640
  .log-value.highlight {
641
- color: var(--cyan);
642
- text-shadow: 0 0 10px var(--cyan-glow);
643
  }
644
 
645
- /* Timeline Container */
646
  .timeline-container {
647
  margin-top: 1.5rem;
648
  padding: 0 2.5rem;
@@ -659,47 +715,53 @@ header {
659
 
660
  .timeline-card {
661
  min-width: 140px;
662
- background: rgba(0, 0, 0, 0.4);
663
- border: 1px solid var(--border-color);
664
- border-radius: 8px;
665
- padding: 12px;
666
  display: flex;
667
  flex-direction: column;
668
  align-items: center;
669
  text-align: center;
670
- transition: transform 0.2s, border-color 0.2s;
 
 
 
671
  }
672
 
673
  .timeline-card:hover {
674
  transform: translateY(-4px);
675
- border-color: var(--cyan);
 
676
  }
677
 
678
  .timeline-date {
679
- font-family: var(--font-mono);
680
- font-size: 0.7rem;
 
681
  color: var(--text-muted);
682
  margin-bottom: 6px;
 
683
  }
684
 
685
  .timeline-vol {
686
  font-family: var(--font-display);
687
- font-size: 1.1rem;
688
- font-weight: bold;
689
- color: #FFF;
690
  margin-bottom: 6px;
691
  }
692
 
693
  .timeline-status {
694
  font-size: 0.7rem;
695
  padding: 2px 8px;
696
- border-radius: 4px;
697
- font-weight: bold;
698
  }
699
 
700
- .timeline-status.safe { background: rgba(57, 255, 20, 0.1); color: var(--green); }
701
- .timeline-status.warning { background: rgba(255, 230, 0, 0.1); color: var(--yellow); }
702
- .timeline-status.critical { background: rgba(255, 0, 85, 0.1); color: var(--red); }
703
 
704
  .empty-timeline {
705
  width: 100%;
@@ -710,22 +772,23 @@ header {
710
  font-size: 0.9rem;
711
  }
712
 
713
- /* Hourly Breakdown Container */
714
  .hourly-container {
715
  margin-top: 1.5rem;
716
  padding: 0 2.5rem;
717
  z-index: 5;
718
  position: relative;
719
- margin-bottom: 2rem;
720
  }
721
 
722
  .hourly-grid {
723
  display: grid;
724
  grid-template-columns: repeat(24, 1fr);
725
  gap: 4px;
726
- background: rgba(0, 0, 0, 0.3);
 
727
  padding: 10px;
728
- border-radius: 8px;
729
  overflow-x: auto;
730
  }
731
 
@@ -739,41 +802,44 @@ header {
739
  .cell-block {
740
  width: 100%;
741
  height: 40px;
742
- border-radius: 4px;
743
  transition: opacity 0.3s;
744
  }
745
 
746
- .cell-block.low { background-color: rgba(57, 255, 20, 0.35); border: 1px solid var(--green); }
747
- .cell-block.medium { background-color: rgba(255, 230, 0, 0.35); border: 1px solid var(--yellow); }
748
- .cell-block.high { background-color: rgba(255, 0, 85, 0.35); border: 1px solid var(--red); }
749
 
750
  .cell-time {
751
  font-family: var(--font-mono);
752
  font-size: 8px;
753
  color: var(--text-muted);
 
754
  }
755
 
756
- /* Footer */
757
  footer {
758
  width: 100%;
759
- padding: 1.5rem;
760
  text-align: center;
761
- border-top: 1px solid rgba(255, 255, 255, 0.03);
 
762
  color: var(--text-muted);
763
  font-size: 0.75rem;
764
  font-family: var(--font-mono);
 
765
  margin-top: auto;
766
  }
767
 
768
- /* Animations */
769
  @keyframes pulse-green {
770
- 0% { box-shadow: 0 0 0 0 rgba(57, 255, 20, 0.4); }
771
- 70% { box-shadow: 0 0 0 8px rgba(57, 255, 20, 0); }
772
- 100% { box-shadow: 0 0 0 0 rgba(57, 255, 20, 0); }
773
  }
774
 
775
  @keyframes pulse-node {
776
- 0% { transform: scale(0.9); opacity: 0.35; }
777
  70% { transform: scale(1.6); opacity: 0; }
778
  100% { transform: scale(0.9); opacity: 0; }
779
  }
@@ -785,6 +851,7 @@ footer {
785
  margin-top: 6px;
786
  display: block;
787
  text-transform: uppercase;
 
788
  }
789
 
790
  .button-row {
@@ -794,23 +861,22 @@ footer {
794
  }
795
 
796
  .secondary-btn {
797
- background: rgba(57, 255, 20, 0.04) !important;
798
- border: 1px solid var(--green) !important;
799
- color: var(--green) !important;
 
800
  }
801
 
802
  .secondary-btn:hover {
803
- background: rgba(57, 255, 20, 0.12) !important;
804
- box-shadow: 0 0 20px var(--green-glow) !important;
805
  }
806
 
807
-
808
- /* SPA Multi-Page Styling */
809
  .page-container {
810
  display: none;
811
  opacity: 0;
812
- transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
813
- animation: fade-in 0.4s forwards;
814
  padding: 1.5rem 2.5rem;
815
  flex: 1;
816
  z-index: 5;
@@ -820,53 +886,19 @@ footer {
820
  .page-container.active {
821
  display: block;
822
  opacity: 1;
 
823
  }
824
 
825
- @keyframes fade-in {
826
- from { opacity: 0; transform: translateY(8px); }
827
  to { opacity: 1; transform: translateY(0); }
828
  }
829
 
830
- /* Nav Links in Header */
831
- .nav-links {
832
- display: flex;
833
- gap: 1.25rem;
834
- background: rgba(255, 255, 255, 0.03);
835
- border: 1px solid rgba(255, 255, 255, 0.06);
836
- padding: 4px;
837
- border-radius: 8px;
838
- }
839
-
840
- .nav-btn {
841
- background: transparent;
842
- border: none;
843
- color: var(--text-muted);
844
- font-family: var(--font-display);
845
- font-size: 0.85rem;
846
- font-weight: 600;
847
- letter-spacing: 1px;
848
- padding: 8px 16px;
849
- cursor: pointer;
850
- border-radius: 6px;
851
- transition: color 0.3s, background 0.3s, box-shadow 0.3s;
852
- }
853
-
854
- .nav-btn:hover {
855
- color: var(--cyan);
856
- background: rgba(255, 255, 255, 0.02);
857
- }
858
-
859
- .nav-btn.active {
860
- color: var(--bg-void);
861
- background: var(--cyan);
862
- box-shadow: 0 0 15px var(--cyan-glow);
863
- }
864
-
865
- /* Hero Section */
866
  .hero-section {
867
  display: grid;
868
- grid-template-columns: 1.2fr 0.8fr;
869
- gap: 2rem;
870
  align-items: center;
871
  padding: 3rem 0;
872
  }
@@ -880,51 +912,52 @@ footer {
880
  .hero-content {
881
  display: flex;
882
  flex-direction: column;
883
- gap: 1.5rem;
884
  }
885
 
886
  .hero-title {
887
  font-family: var(--font-display);
888
- font-size: 3rem;
889
  font-weight: 800;
890
- letter-spacing: 2px;
891
- line-height: 1.1;
892
- background: linear-gradient(135deg, #FFF 40%, var(--cyan) 100%);
893
  -webkit-background-clip: text;
894
  -webkit-text-fill-color: transparent;
895
- text-shadow: 0 0 30px rgba(0, 240, 255, 0.15);
896
  }
897
 
898
  .hero-subtitle {
899
  font-size: 1.1rem;
900
  color: var(--text-muted);
901
  line-height: 1.6;
 
902
  }
903
 
904
  .hero-actions {
905
  display: flex;
906
- gap: 1rem;
907
- max-width: 400px;
908
  }
909
 
910
  .hero-stats-panel {
911
  display: flex;
912
  flex-direction: column;
913
  gap: 1rem;
914
- background: rgba(6, 10, 22, 0.6) !important;
 
915
  }
916
 
917
  .hero-stat-grid {
918
  display: grid;
919
  grid-template-columns: 1fr 1fr;
920
- gap: 1rem;
921
  }
922
 
923
  .hero-stat-card {
924
- background: rgba(0, 0, 0, 0.25);
925
- border: 1px solid rgba(255, 255, 255, 0.05);
926
  padding: 1.2rem;
927
- border-radius: 8px;
928
  display: flex;
929
  flex-direction: column;
930
  gap: 4px;
@@ -932,19 +965,20 @@ footer {
932
 
933
  .h-stat-label {
934
  font-size: 0.75rem;
935
- font-family: var(--font-mono);
936
  color: var(--text-muted);
937
  text-transform: uppercase;
 
938
  }
939
 
940
  .h-stat-value {
941
  font-size: 1.8rem;
942
  font-family: var(--font-display);
943
  font-weight: 800;
944
- color: #FFF;
945
  }
946
 
947
- /* Features Grid */
948
  .features-section {
949
  padding: 2rem 0;
950
  }
@@ -952,12 +986,22 @@ footer {
952
  .section-title {
953
  font-family: var(--font-display);
954
  font-size: 1.4rem;
955
- font-weight: 700;
956
- letter-spacing: 1.5px;
957
  margin-bottom: 2rem;
958
- color: #FFF;
959
- border-left: 3px solid var(--cyan);
960
- padding-left: 10px;
 
 
 
 
 
 
 
 
 
 
961
  }
962
 
963
  .features-grid {
@@ -970,7 +1014,7 @@ footer {
970
  display: flex;
971
  flex-direction: column;
972
  gap: 1rem;
973
- transition: transform 0.3s;
974
  }
975
 
976
  .feature-card:hover {
@@ -978,17 +1022,17 @@ footer {
978
  }
979
 
980
  .feature-icon {
981
- font-size: 2rem;
982
  font-weight: 800;
983
- color: rgba(0, 240, 255, 0.25);
984
- text-shadow: 0 0 10px rgba(0, 240, 255, 0.05);
985
  }
986
 
987
  .feature-name {
988
  font-family: var(--font-display);
989
- font-size: 1.05rem;
990
- font-weight: 600;
991
- color: var(--cyan);
992
  }
993
 
994
  .feature-desc {
@@ -997,7 +1041,7 @@ footer {
997
  line-height: 1.6;
998
  }
999
 
1000
- /* Page Headers */
1001
  .page-header-section {
1002
  padding: 2rem 0 1rem 0;
1003
  }
@@ -1006,9 +1050,10 @@ footer {
1006
  font-size: 0.95rem;
1007
  color: var(--text-muted);
1008
  margin-top: 6px;
 
1009
  }
1010
 
1011
- /* News Page Styling */
1012
  .news-grid {
1013
  display: grid;
1014
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
@@ -1017,21 +1062,23 @@ footer {
1017
  }
1018
 
1019
  .news-card {
1020
- background: var(--bg-panel);
1021
- border: 1px solid var(--border-color);
1022
  border-radius: 12px;
1023
- padding: 1.5rem;
1024
- backdrop-filter: blur(16px);
1025
  display: flex;
1026
  flex-direction: column;
1027
  gap: 1rem;
1028
- transition: transform 0.3s, border-color 0.3s, box-shadow 0.3s;
 
 
 
1029
  }
1030
 
1031
  .news-card:hover {
1032
- transform: translateY(-3px);
1033
- border-color: var(--border-hover);
1034
- box-shadow: 0 8px 32px 0 rgba(0, 240, 255, 0.05);
1035
  }
1036
 
1037
  .news-card-header {
@@ -1041,27 +1088,29 @@ footer {
1041
  }
1042
 
1043
  .news-source {
1044
- font-family: var(--font-mono);
1045
  font-size: 0.75rem;
1046
- background: rgba(0, 240, 255, 0.08);
1047
- color: var(--cyan);
1048
- padding: 2px 8px;
1049
- border-radius: 4px;
1050
- border: 1px solid rgba(0, 240, 255, 0.2);
 
1051
  }
1052
 
1053
  .news-date {
1054
  font-family: var(--font-mono);
1055
  font-size: 0.75rem;
1056
  color: var(--text-muted);
 
1057
  }
1058
 
1059
  .news-title {
1060
  font-family: var(--font-display);
1061
- font-size: 1.1rem;
1062
- font-weight: 600;
1063
- color: #FFF;
1064
- line-height: 1.4;
1065
  }
1066
 
1067
  .news-summary {
@@ -1074,11 +1123,11 @@ footer {
1074
  margin-top: auto;
1075
  display: inline-flex;
1076
  align-items: center;
1077
- color: var(--cyan);
1078
  text-decoration: none;
1079
- font-family: var(--font-mono);
1080
- font-size: 0.8rem;
1081
- font-weight: bold;
1082
  gap: 6px;
1083
  transition: gap 0.2s;
1084
  }
@@ -1087,16 +1136,7 @@ footer {
1087
  gap: 10px;
1088
  }
1089
 
1090
- .loading-news, .loading-alerts {
1091
- grid-column: 1 / -1;
1092
- text-align: center;
1093
- padding: 3rem;
1094
- color: var(--text-muted);
1095
- font-family: var(--font-mono);
1096
- font-size: 0.9rem;
1097
- }
1098
-
1099
- /* Alerts Page Styling */
1100
  .alerts-summary {
1101
  margin-top: 1.5rem;
1102
  }
@@ -1112,10 +1152,11 @@ footer {
1112
  grid-template-columns: 120px 180px 100px 1fr;
1113
  gap: 1rem;
1114
  align-items: center;
1115
- background: rgba(0, 0, 0, 0.2);
1116
- border: 1px solid rgba(255, 255, 255, 0.04);
1117
- padding: 1rem 1.5rem;
1118
- border-radius: 8px;
 
1119
  transition: all 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
1120
  cursor: pointer;
1121
  }
@@ -1125,9 +1166,9 @@ footer {
1125
  }
1126
 
1127
  .alert-row:hover {
1128
- background: rgba(0, 240, 255, 0.04) !important;
1129
- border-color: var(--cyan) !important;
1130
- box-shadow: 0 0 15px rgba(0, 240, 255, 0.1) !important;
1131
  transform: translateX(6px);
1132
  }
1133
 
@@ -1135,45 +1176,44 @@ footer {
1135
  font-family: var(--font-mono);
1136
  font-size: 0.85rem;
1137
  color: var(--text-muted);
 
1138
  }
1139
 
1140
  .alert-location {
1141
  font-family: var(--font-display);
1142
- font-weight: 600;
1143
- color: #FFF;
1144
  }
1145
 
1146
  .alert-badge {
1147
- font-family: var(--font-mono);
1148
  font-size: 0.75rem;
1149
- font-weight: bold;
1150
- padding: 3px 8px;
1151
- border-radius: 4px;
1152
  text-align: center;
 
1153
  }
1154
 
1155
  .alert-badge.critical {
1156
- background: rgba(255, 0, 85, 0.12);
1157
  color: var(--red);
1158
- border: 1px solid var(--red);
1159
- box-shadow: 0 0 10px rgba(255, 0, 85, 0.1);
1160
  }
1161
 
1162
  .alert-badge.warning {
1163
- background: rgba(255, 230, 0, 0.12);
1164
- color: var(--yellow);
1165
- border: 1px solid var(--yellow);
1166
- box-shadow: 0 0 10px rgba(255, 230, 0, 0.1);
1167
  }
1168
 
1169
  .alert-desc {
1170
  font-size: 0.85rem;
1171
  color: var(--text-muted);
 
1172
  }
1173
 
1174
- /* ==========================================
1175
- CUSTOM CYBER HUD CURSOR & INTERACTIVITY
1176
- ========================================== */
1177
  #cursor-dot,
1178
  #cursor-ring {
1179
  position: fixed;
@@ -1183,141 +1223,50 @@ footer {
1183
  z-index: 10000;
1184
  border-radius: 50%;
1185
  display: none;
1186
- backface-visibility: hidden;
1187
  }
1188
 
1189
  #cursor-dot {
1190
  width: 6px;
1191
  height: 6px;
1192
- background: var(--cyan);
1193
- box-shadow: 0 0 10px var(--cyan);
1194
  }
1195
 
1196
  #cursor-ring {
1197
  width: 40px;
1198
  height: 40px;
1199
- border: 1px solid var(--border-hover);
1200
- transition: width 0.25s cubic-bezier(0.25, 1, 0.5, 1),
1201
- height 0.25s cubic-bezier(0.25, 1, 0.5, 1),
1202
- border-color 0.25s ease,
1203
- background 0.25s ease;
 
1204
  }
1205
 
1206
- /* Hover state on buttons/interactive elements */
1207
  #cursor-ring.hover-state {
1208
- width: 55px;
1209
- height: 55px;
1210
- border-color: var(--cyan);
1211
- background: rgba(0, 240, 255, 0.04);
1212
- box-shadow: 0 0 15px rgba(0, 240, 255, 0.15);
1213
  }
1214
 
1215
  @media (pointer: coarse) {
1216
- #cursor-dot,
1217
- #cursor-ring {
1218
- display: none !important;
1219
- }
1220
- * {
1221
- cursor: auto !important;
1222
- }
1223
  }
1224
 
1225
- /* Hide default cursor on desktops for the custom cursor feel */
1226
  @media (pointer: fine) {
1227
  body, a, button, select, input, [role="button"], .leaflet-interactive {
1228
  cursor: none !important;
1229
  }
1230
  }
1231
 
1232
- /* ==========================================
1233
- RADAR SWEEP EFFECT (ON MAP OVERLAY)
1234
- ========================================== */
1235
- .map-container {
1236
- position: relative;
1237
- }
1238
-
1239
- .map-container::after {
1240
- content: '';
1241
- position: absolute;
1242
- inset: 0;
1243
- pointer-events: none;
1244
- z-index: 1000;
1245
- background: conic-gradient(from 0deg at 50% 50%, rgba(0, 240, 255, 0.08) 0deg, transparent 90deg, transparent 360deg);
1246
- animation: radar-sweep 8s linear infinite;
1247
- opacity: 0.7;
1248
- border-radius: 8px;
1249
- mix-blend-mode: screen;
1250
- }
1251
-
1252
- @keyframes radar-sweep {
1253
- from {
1254
- transform: rotate(0deg);
1255
- }
1256
- to {
1257
- transform: rotate(360deg);
1258
- }
1259
- }
1260
-
1261
- /* ==========================================
1262
- AMBIENT GLOWS & GLASSMORPHISM UPGRADES
1263
- ========================================== */
1264
- body::before {
1265
- content: '';
1266
- position: fixed;
1267
- top: -10%;
1268
- left: -10%;
1269
- width: 50%;
1270
- height: 50%;
1271
- background: radial-gradient(circle, rgba(0, 240, 255, 0.05) 0%, transparent 70%);
1272
- z-index: 0;
1273
- pointer-events: none;
1274
- }
1275
-
1276
- body::after {
1277
- content: '';
1278
- position: fixed;
1279
- bottom: -10%;
1280
- right: -10%;
1281
- width: 60%;
1282
- height: 60%;
1283
- background: radial-gradient(circle, rgba(0, 102, 255, 0.04) 0%, transparent 70%);
1284
- z-index: 0;
1285
- pointer-events: none;
1286
- }
1287
-
1288
- /* Neon glow for progress bars */
1289
- .progress-bar-fill.organic {
1290
- box-shadow: 0 0 8px var(--green-glow);
1291
- }
1292
- .progress-bar-fill.plastic {
1293
- box-shadow: 0 0 8px var(--cyan-glow);
1294
- }
1295
- .progress-bar-fill.paper {
1296
- box-shadow: 0 0 8px var(--yellow-glow);
1297
- }
1298
- .progress-bar-fill.glass {
1299
- box-shadow: 0 0 8px rgba(0, 240, 255, 0.25);
1300
- }
1301
- .progress-bar-fill.textile {
1302
- box-shadow: 0 0 8px rgba(255, 0, 85, 0.25);
1303
- }
1304
- .progress-bar-fill.metal {
1305
- box-shadow: 0 0 8px rgba(255, 255, 255, 0.25);
1306
- }
1307
-
1308
- /* Logo Reflective Polish */
1309
- .logo-text {
1310
- position: relative;
1311
- -webkit-box-reflect: below -4px linear-gradient(transparent, rgba(255, 255, 255, 0.08));
1312
- }
1313
-
1314
- /* ==========================================
1315
- DEVELOPMENT TEAM STYLING
1316
- ========================================== */
1317
  .developers-section {
1318
  padding: 2.5rem 0;
1319
  margin-top: 3.5rem;
1320
- border-top: 1px solid rgba(255, 255, 255, 0.05);
1321
  }
1322
 
1323
  .developers-grid {
@@ -1329,14 +1278,14 @@ body::after {
1329
 
1330
  .developer-card {
1331
  position: relative;
1332
- background: rgba(6, 10, 22, 0.5) !important;
1333
- border: 1px solid var(--border-color) !important;
1334
- border-radius: 12px;
1335
  padding: 2.2rem;
1336
  text-align: center;
 
1337
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
1338
  overflow: hidden;
1339
- backdrop-filter: blur(16px);
1340
  }
1341
 
1342
  .developer-card::before {
@@ -1345,67 +1294,50 @@ body::after {
1345
  top: 0;
1346
  left: 0;
1347
  right: 0;
1348
- height: 3px;
1349
- background: linear-gradient(90deg, transparent, var(--cyan), transparent);
1350
- opacity: 0.7;
1351
  }
1352
 
1353
  .developer-card:hover {
1354
  transform: translateY(-6px);
1355
- border-color: var(--cyan) !important;
1356
- box-shadow: 0 10px 25px rgba(0, 240, 255, 0.15) !important;
1357
  }
1358
 
1359
  .dev-role {
1360
  font-size: 0.75rem;
1361
  text-transform: uppercase;
1362
- letter-spacing: 2px;
1363
- color: var(--cyan);
1364
- font-weight: 700;
1365
  margin-bottom: 0.6rem;
1366
- font-family: var(--font-mono);
1367
  }
1368
 
1369
  .dev-name {
1370
- font-size: 1.25rem;
1371
- color: #FFF;
1372
  font-weight: 800;
1373
  margin-bottom: 0.8rem;
1374
  font-family: var(--font-display);
1375
- text-shadow: 0 0 10px rgba(255, 255, 255, 0.15);
1376
  }
1377
 
1378
  .dev-desc {
1379
- font-size: 0.82rem;
1380
  color: var(--text-muted);
1381
  line-height: 1.6;
1382
  }
1383
 
1384
- /* ==========================================
1385
- COMPREHENSIVE LAYOUT RESPONSIVENESS
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;
1407
- overflow: visible !important;
1408
  }
 
 
 
1409
  }
1410
 
1411
  @media (max-width: 992px) {
@@ -1428,42 +1360,29 @@ body::after {
1428
  flex-direction: column !important;
1429
  gap: 1.2rem !important;
1430
  padding: 1.2rem 1.5rem !important;
1431
- text-align: center;
1432
  }
1433
  .logo-container {
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;
1466
- gap: 1rem !important;
1467
  }
1468
  .hero-stat-grid {
1469
  grid-template-columns: 1fr !important;
@@ -1471,58 +1390,17 @@ body::after {
1471
  .hero-title {
1472
  font-size: 2.2rem !important;
1473
  }
1474
- .hero-subtitle {
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) {
1512
- .logo-text {
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;
1521
- }
1522
- .developer-card {
1523
- padding: 1.5rem !important;
1524
  }
1525
  }
1526
-
1527
-
1528
-
 
1
+ /* CSS Variables for Theming - Eco-Joy Analytics */
2
  :root {
3
+ /* Color Palette */
4
+ --background: #f4fbf8; /* Soft minty void */
5
+ --bg-void: #f4fbf8;
6
+ --bg-panel: #ffffff; /* Clean white containers */
7
+ --border-color: #bacac5; /* Soft outline-variant */
8
+ --border-hover: #006b5f; /* Primary highlight */
9
 
10
+ --text-main: #161d1b; /* deep dark gray-green */
11
+ --text-muted: #6b7a76; /* warm outline / secondary gray */
12
 
13
+ /* Core Brand Accents */
14
+ --primary: #006b5f; /* Eco-Teal */
15
+ --primary-glow: rgba(0, 107, 95, 0.06);
16
+ --secondary: #735c00; /* Sunny Yellow */
17
+ --secondary-container: #fed01b; /* Warm accent yellow */
18
+ --secondary-glow: rgba(254, 208, 27, 0.06);
 
 
 
19
 
20
+ /* Semantics */
21
+ --cyan: #006b5f; /* Action items */
22
+ --cyan-glow: rgba(0, 107, 95, 0.15);
23
+
24
+ --green: #4ADE80; /* Leaf Green success */
25
+ --green-glow: rgba(74, 222, 128, 0.15);
26
+
27
+ --yellow: #fed01b; /* Warning yellow */
28
+ --yellow-glow: rgba(254, 208, 27, 0.15);
29
+
30
+ --red: #ba1a1a; /* Alert / Error red */
31
+ --red-glow: rgba(186, 26, 26, 0.15);
32
+
33
+ --sky-blue: #38BDF8;
34
+ --leaf-green: #4ADE80;
35
+ --soft-surface: #F8FAFC;
36
+
37
+ /* Typography System */
38
+ --font-display: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
39
+ --font-body: 'Be Vietnam Pro', system-ui, -apple-system, sans-serif;
40
  --font-mono: 'JetBrains Mono', monospace;
41
  }
42
 
43
+ /* Base resets & layouts */
44
  * {
45
  box-sizing: border-box;
46
  margin: 0;
 
51
  background-color: var(--bg-void);
52
  color: var(--text-main);
53
  font-family: var(--font-body);
54
+ font-weight: 400;
55
  overflow-x: hidden;
56
  min-height: 100vh;
57
  display: flex;
 
67
  height: 100%;
68
  z-index: 0;
69
  pointer-events: none;
70
+ opacity: 0.35;
71
  }
72
 
73
+ /* Navigation Header */
74
  header {
75
  width: 100%;
76
+ padding: 1.2rem 2.5rem;
77
+ background: #ffffff;
78
  display: flex;
79
  justify-content: space-between;
80
  align-items: center;
81
+ border-bottom: 2px solid var(--border-color);
82
  z-index: 10;
83
  position: relative;
84
+ box-shadow: 0 4px 12px rgba(0, 107, 95, 0.02);
85
  }
86
 
87
  .logo-container {
88
  display: flex;
89
+ align-items: center;
90
+ gap: 8px;
91
  }
92
 
93
  .logo-text {
94
  font-family: var(--font-display);
95
  font-size: 1.8rem;
96
  font-weight: 800;
97
+ letter-spacing: -0.02em;
98
+ background: linear-gradient(135deg, var(--primary) 30%, var(--secondary) 100%);
99
  -webkit-background-clip: text;
100
  -webkit-text-fill-color: transparent;
 
101
  }
102
 
103
  .logo-text .highlight {
104
+ font-weight: 400;
105
+ color: var(--primary);
 
 
106
  }
107
 
108
  .version-tag {
109
  font-family: var(--font-mono);
110
+ font-size: 0.7rem;
111
  color: var(--text-muted);
112
+ background: var(--soft-surface);
113
  padding: 2px 8px;
114
+ border-radius: 12px;
115
+ border: 1px solid var(--border-color);
116
+ font-weight: 600;
117
  }
118
 
119
  .system-status {
 
123
  }
124
 
125
  .status-indicator {
126
+ width: 10px;
127
+ height: 10px;
128
  border-radius: 50%;
129
  }
130
 
131
  .status-indicator.online {
132
  background-color: var(--green);
133
+ box-shadow: 0 0 8px var(--green-glow);
134
  animation: pulse-green 2s infinite;
135
  }
136
 
 
138
  font-family: var(--font-mono);
139
  font-size: 0.8rem;
140
  color: var(--text-muted);
141
+ font-weight: 600;
142
+ }
143
+
144
+ /* Nav Links Segmented Control */
145
+ .nav-links {
146
+ display: flex;
147
+ gap: 8px;
148
+ background: var(--soft-surface);
149
+ border: 2px solid var(--border-color);
150
+ padding: 4px;
151
+ border-radius: 24px;
152
+ }
153
+
154
+ .nav-btn {
155
+ background: transparent;
156
+ border: none;
157
+ color: var(--text-muted);
158
+ font-family: var(--font-display);
159
+ font-size: 0.85rem;
160
+ font-weight: 700;
161
+ padding: 8px 18px;
162
+ cursor: pointer;
163
+ border-radius: 20px;
164
+ transition: color 0.25s, background-color 0.25s, transform 0.1s;
165
+ }
166
+
167
+ .nav-btn:hover {
168
+ color: var(--primary);
169
+ }
170
+
171
+ .nav-btn:active {
172
+ transform: scale(0.95);
173
+ }
174
+
175
+ .nav-btn.active {
176
+ color: #ffffff;
177
+ background: var(--primary);
178
+ box-shadow: 0 4px 10px rgba(0, 107, 95, 0.25);
179
  }
180
 
181
  /* Grid Layout */
182
  .dashboard-grid {
183
  display: grid;
184
+ grid-template-columns: 340px 1fr 360px;
185
+ gap: 24px;
186
+ padding: 2.5rem;
187
  flex: 1;
188
  z-index: 5;
189
  position: relative;
190
+ max-width: 1280px;
191
+ margin: 0 auto;
192
+ width: 100%;
193
  }
194
 
195
+ /* Panels (Tactile Islands) */
 
 
 
 
 
 
196
  .panel {
197
  background: var(--bg-panel);
198
+ border: 2px solid var(--border-color);
199
+ border-radius: 16px;
200
+ padding: 1.8rem;
201
+ box-shadow: 0 8px 24px rgba(0, 107, 95, 0.03);
202
+ transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),
203
+ border-color 0.3s ease,
204
+ box-shadow 0.3s ease;
205
  }
206
 
207
  .panel:hover {
208
+ transform: translateY(-4px);
209
+ border-color: var(--primary);
210
+ box-shadow: 0 16px 32px rgba(0, 107, 95, 0.08);
211
  }
212
 
213
  .panel-title {
214
  font-family: var(--font-display);
215
+ font-size: 1rem;
216
+ font-weight: 800;
217
+ color: var(--primary);
 
218
  margin-bottom: 1.2rem;
 
 
219
  text-transform: uppercase;
220
+ letter-spacing: 0.05em;
221
+ display: flex;
222
+ align-items: center;
223
+ gap: 8px;
224
+ }
225
+
226
+ .panel-title::before {
227
+ content: '';
228
+ display: inline-block;
229
+ width: 4px;
230
+ height: 16px;
231
+ background: var(--secondary-container);
232
+ border-radius: 2px;
233
  }
234
 
235
  .panel-subtitle {
236
  font-family: var(--font-display);
237
  font-size: 0.85rem;
238
+ font-weight: 700;
239
+ color: var(--text-muted);
240
  margin-bottom: 1rem;
241
  text-transform: uppercase;
242
  }
243
 
244
+ /* Controls & Form Inputs */
245
  .control-group {
246
  margin-bottom: 1.2rem;
247
  }
 
252
  color: var(--text-muted);
253
  margin-bottom: 6px;
254
  text-transform: uppercase;
255
+ font-family: var(--font-display);
256
+ font-weight: 700;
257
  }
258
 
259
  .form-control {
260
  width: 100%;
261
+ background: #ffffff;
262
+ border: 2px solid var(--border-color);
263
  color: var(--text-main);
264
  padding: 10px 14px;
265
  border-radius: 8px;
266
  outline: none;
267
  font-family: var(--font-body);
268
  font-size: 0.9rem;
269
+ font-weight: 500;
270
+ transition: border-color 0.25s, box-shadow 0.25s;
271
  }
272
 
273
  .form-control:focus {
274
+ border-color: var(--primary);
275
+ box-shadow: 0 0 0 3px rgba(0, 107, 95, 0.1);
276
  }
277
 
278
+ /* Friendly Sliders */
279
  .slider {
280
  width: 100%;
281
  -webkit-appearance: none;
282
+ height: 8px;
283
+ border-radius: 4px;
284
+ background: var(--border-color);
285
  outline: none;
286
  }
287
 
288
  .slider::-webkit-slider-thumb {
289
  -webkit-appearance: none;
290
+ width: 20px;
291
+ height: 20px;
292
  border-radius: 50%;
293
+ background: var(--primary);
294
+ border: 3px solid #ffffff;
295
+ box-shadow: 0 4px 8px rgba(0, 107, 95, 0.2);
296
  cursor: pointer;
297
+ transition: transform 0.1s ease, background-color 0.1s;
298
  }
299
 
300
  .slider::-webkit-slider-thumb:hover {
301
+ transform: scale(1.2);
302
+ background: var(--secondary-container);
303
  }
304
 
305
  .value-display, .override-display {
306
  font-family: var(--font-mono);
307
+ color: var(--primary);
308
+ font-weight: 800;
309
  float: right;
310
  }
311
 
 
316
  }
317
 
318
  .divider {
319
+ height: 2px;
320
+ background: var(--border-color);
321
  margin: 1.5rem 0;
322
+ opacity: 0.5;
323
  }
324
 
325
+ /* Tactile Buttons */
326
  .action-btn {
327
  width: 100%;
328
+ padding: 12px 24px;
329
+ background: var(--primary);
330
+ border: none;
331
+ color: #ffffff;
332
+ font-family: var(--font-display);
333
+ font-size: 0.95rem;
334
+ font-weight: 800;
335
+ border-radius: 24px;
336
  cursor: pointer;
337
  position: relative;
338
  overflow: hidden;
339
+ box-shadow: 0 4px 12px rgba(0, 107, 95, 0.2);
340
+ transition: background-color 0.2s, transform 0.1s, box-shadow 0.2s;
341
  }
342
 
343
  .action-btn:hover {
344
+ background: #00574d;
345
+ box-shadow: 0 6px 16px rgba(0, 107, 95, 0.3);
346
  }
347
 
348
+ .action-btn:active {
349
+ transform: scale(0.96);
350
+ }
351
+
352
+ /* Map Panel & Container */
353
  .map-panel {
354
  display: flex;
355
  flex-direction: column;
 
360
  .map-container {
361
  flex: 1;
362
  position: relative;
363
+ background: #ffffff;
364
+ border-radius: 12px;
365
  overflow: hidden;
366
+ border: 2px solid var(--border-color);
367
  }
368
 
369
  #map {
 
372
  background: var(--bg-void) !important;
373
  }
374
 
375
+ /* Radar soft scan overlays */
376
+ .map-container::after {
377
+ content: '';
378
+ position: absolute;
379
+ inset: 0;
380
+ pointer-events: none;
381
+ z-index: 1000;
382
+ background: conic-gradient(from 0deg at 50% 50%, rgba(0, 107, 95, 0.02) 0deg, transparent 90deg, transparent 360deg);
383
+ animation: radar-sweep 10s linear infinite;
384
+ border-radius: 12px;
385
+ }
386
+
387
+ @keyframes radar-sweep {
388
+ from { transform: rotate(0deg); }
389
+ to { transform: rotate(360deg); }
390
+ }
391
+
392
+ /* Map Custom Markers styling */
393
  .leaflet-custom-marker {
394
  position: absolute;
395
  width: 24px !important;
396
  height: 24px !important;
 
397
  transform-origin: center center;
 
 
398
  cursor: pointer;
399
  }
400
 
 
406
  height: 28px;
407
  margin-left: -14px;
408
  margin-top: -14px;
409
+ background: var(--primary);
410
  border-radius: 50%;
411
+ opacity: 0.12;
412
  transform: scale(1);
413
+ animation: pulse-node 2.2s infinite;
414
  pointer-events: none;
415
  }
416
 
 
418
  position: absolute;
419
  top: 50%;
420
  left: 50%;
421
+ width: 14px;
422
+ height: 14px;
423
+ margin-left: -7px;
424
+ margin-top: -7px;
425
+ background: var(--primary);
426
+ border: 2.5px solid #ffffff;
427
  border-radius: 50%;
428
+ box-shadow: 0 4px 8px rgba(0, 107, 95, 0.25);
429
+ transition: transform 0.2s, background-color 0.25s;
430
  }
431
 
432
  .leaflet-custom-marker .marker-label {
 
434
  top: -24px;
435
  left: 50%;
436
  transform: translateX(-50%);
437
+ font-family: var(--font-display);
438
  font-size: 10px;
439
+ font-weight: 700;
440
+ color: var(--text-main);
441
+ background: #ffffff;
442
+ padding: 2px 8px;
443
+ border-radius: 10px;
444
+ border: 2px solid var(--border-color);
445
  white-space: nowrap;
446
  pointer-events: none;
447
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
448
+ transition: color 0.25s, border-color 0.25s, transform 0.2s;
449
  }
450
 
451
+ /* Hover / Active Marker states */
452
  .leaflet-custom-marker:hover .marker-core {
453
  transform: scale(1.2);
454
  }
455
 
456
  .leaflet-custom-marker.active .marker-core {
457
  transform: scale(1.3);
458
+ border-color: var(--secondary-container);
459
+ box-shadow: 0 0 12px var(--primary);
460
  }
461
 
462
  .leaflet-custom-marker.active .marker-label {
463
+ color: var(--primary);
464
+ border-color: var(--primary);
465
+ transform: translateX(-50%) scale(1.05);
466
  }
467
 
468
+ /* Semantic Map indicators */
469
+ .leaflet-custom-marker.safe .marker-core { background-color: var(--green); }
470
+ .leaflet-custom-marker.safe .marker-pulse { background-color: var(--green); }
 
 
 
 
 
471
 
472
+ .leaflet-custom-marker.warning .marker-core { background-color: var(--yellow); }
473
+ .leaflet-custom-marker.warning .marker-pulse { background-color: var(--yellow); }
 
 
 
 
 
474
 
475
+ .leaflet-custom-marker.critical .marker-core { background-color: var(--red); }
476
+ .leaflet-custom-marker.critical .marker-pulse { background-color: var(--red); }
 
 
 
 
 
477
 
478
+ /* Leaflet Zoom control layout */
479
  .leaflet-bar {
480
+ border: 2px solid var(--border-color) !important;
481
  border-radius: 8px !important;
482
  overflow: hidden;
483
+ box-shadow: 0 4px 12px rgba(0, 107, 95, 0.05) !important;
484
  }
485
 
486
  .leaflet-bar a {
487
+ background-color: #ffffff !important;
488
  color: var(--text-main) !important;
489
+ border-bottom: 2px solid var(--border-color) !important;
490
  transition: background-color 0.2s, color 0.2s;
491
  }
492
 
493
  .leaflet-bar a:hover {
494
+ background-color: var(--soft-surface) !important;
495
+ color: var(--primary) !important;
496
  }
497
 
498
+ /* Stats Cards Section */
 
 
 
 
499
  .stats-row {
500
  display: grid;
501
  grid-template-columns: repeat(3, 1fr);
502
+ gap: 16px;
503
  }
504
 
505
  .stat-card {
 
511
  }
512
 
513
  .card-label {
514
+ font-family: var(--font-display);
515
+ font-size: 0.75rem;
516
  color: var(--text-muted);
517
+ margin-bottom: 4px;
518
  text-transform: uppercase;
519
+ font-weight: 700;
520
  }
521
 
522
  .card-value {
523
  font-family: var(--font-display);
524
+ font-size: 1.6rem;
525
  font-weight: 800;
526
+ color: var(--text-main);
527
  }
528
 
529
  .card-value .unit {
530
  font-size: 0.85rem;
531
+ font-weight: 600;
532
  color: var(--text-muted);
533
  }
534
 
535
+ /* Custom Risk Badges */
536
  .status-badge {
537
  display: inline-block;
538
+ padding: 6px 16px;
539
+ border-radius: 20px;
540
+ font-size: 0.9rem;
541
+ font-weight: 800;
542
  text-align: center;
543
  width: fit-content;
544
  }
545
 
546
  .status-badge.safe {
547
+ background: #eef5f2;
548
+ border: 2px solid var(--green);
549
+ color: var(--primary);
 
550
  }
551
 
552
  .status-badge.warning {
553
+ background: #fff9db;
554
+ border: 2px solid var(--yellow);
555
+ color: var(--secondary);
 
556
  }
557
 
558
  .status-badge.critical {
559
+ background: #ffdad6;
560
+ border: 2px solid var(--red);
561
  color: var(--red);
 
562
  }
563
 
564
+ /* Composition bars (Waste composition) */
565
  .progress-item {
566
  margin-bottom: 1.2rem;
567
  }
 
572
  font-size: 0.8rem;
573
  color: var(--text-muted);
574
  margin-bottom: 6px;
575
+ font-family: var(--font-display);
576
+ font-weight: 700;
577
  }
578
 
579
  .progress-bar-bg {
580
  width: 100%;
581
+ height: 10px;
582
+ background: var(--border-color);
583
+ border-radius: 5px;
584
  overflow: hidden;
585
+ opacity: 0.75;
586
  }
587
 
588
  .progress-bar-fill {
589
  height: 100%;
590
+ border-radius: 5px;
591
  width: 0%;
592
  transition: width 0.8s cubic-bezier(0.25, 0.8, 0.25, 1);
593
  }
594
 
595
+ .progress-bar-fill.organic { background-color: var(--green); }
596
+ .progress-bar-fill.plastic { background-color: var(--sky-blue); }
597
+ .progress-bar-fill.paper { background-color: var(--yellow); }
598
+ .progress-bar-fill.glass { background-color: var(--red); }
599
+ .progress-bar-fill.textile { background-color: #a855f7; } /* Purple */
600
+ .progress-bar-fill.metal { background-color: #94a3b8; } /* Steel gray */
 
 
 
601
 
602
+ /* Live Weather Card */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
603
  .weather-grid {
604
  display: flex;
605
  justify-content: space-between;
606
  align-items: center;
607
+ background: var(--soft-surface);
608
  padding: 12px;
609
  border-radius: 8px;
610
+ border: 2px solid var(--border-color);
611
  margin-bottom: 1rem;
612
  }
613
 
614
  .weather-temp {
615
  font-family: var(--font-display);
616
  font-size: 1.2rem;
617
+ font-weight: 800;
618
+ color: var(--text-main);
619
  }
620
 
621
  .weather-label {
622
  display: block;
623
  font-size: 0.75rem;
624
  color: var(--text-muted);
625
+ font-weight: 700;
626
  }
627
 
628
  .weather-details {
 
630
  font-size: 0.75rem;
631
  text-align: right;
632
  line-height: 1.4;
633
+ font-weight: 600;
634
  }
635
 
636
  .weather-details .highlight {
637
+ color: var(--primary);
638
  }
639
 
640
  .event-box {
641
+ padding: 10px 14px;
642
+ background: #fffdf5;
643
+ border-left: 4px solid var(--yellow);
644
+ border-radius: 0 8px 8px 0;
645
+ border-top: 2px solid var(--border-color);
646
+ border-right: 2px solid var(--border-color);
647
+ border-bottom: 2px solid var(--border-color);
648
  }
649
 
650
  .event-title {
651
  display: block;
652
  font-size: 0.75rem;
653
+ font-weight: 800;
654
+ color: var(--secondary);
655
+ font-family: var(--font-display);
656
  margin-bottom: 4px;
657
+ text-transform: uppercase;
658
  }
659
 
660
  .event-desc {
661
  font-size: 0.8rem;
662
  color: var(--text-main);
663
+ font-weight: 500;
664
  }
665
 
666
+ /* Logistics Cards */
667
  .logistics-grid {
668
  display: grid;
669
  grid-template-columns: 1fr 1fr;
 
671
  }
672
 
673
  .log-item {
674
+ background: var(--soft-surface);
675
+ border: 2px solid var(--border-color);
676
+ border-radius: 10px;
677
  padding: 10px;
678
  display: flex;
679
  flex-direction: column;
680
  }
681
 
682
  .log-label {
683
+ font-family: var(--font-display);
684
+ font-size: 0.7rem;
685
  color: var(--text-muted);
686
  text-transform: uppercase;
687
+ font-weight: 700;
688
  margin-bottom: 4px;
689
  }
690
 
691
  .log-value {
692
  font-size: 0.95rem;
693
+ font-weight: 800;
694
+ color: var(--text-main);
695
  }
696
 
697
  .log-value.highlight {
698
+ color: var(--primary);
 
699
  }
700
 
701
+ /* Timeline slide-in & cards styling */
702
  .timeline-container {
703
  margin-top: 1.5rem;
704
  padding: 0 2.5rem;
 
715
 
716
  .timeline-card {
717
  min-width: 140px;
718
+ background: #ffffff;
719
+ border: 2px solid var(--border-color);
720
+ border-radius: 12px;
721
+ padding: 14px;
722
  display: flex;
723
  flex-direction: column;
724
  align-items: center;
725
  text-align: center;
726
+ box-shadow: 0 4px 10px rgba(0, 107, 95, 0.02);
727
+ transition: transform 0.25s cubic-bezier(0.25, 0.8, 0.25, 1),
728
+ border-color 0.25s ease,
729
+ box-shadow 0.25s ease;
730
  }
731
 
732
  .timeline-card:hover {
733
  transform: translateY(-4px);
734
+ border-color: var(--primary);
735
+ box-shadow: 0 10px 20px rgba(0, 107, 95, 0.06);
736
  }
737
 
738
  .timeline-date {
739
+ font-family: var(--font-display);
740
+ font-weight: 700;
741
+ font-size: 0.75rem;
742
  color: var(--text-muted);
743
  margin-bottom: 6px;
744
+ text-transform: uppercase;
745
  }
746
 
747
  .timeline-vol {
748
  font-family: var(--font-display);
749
+ font-size: 1.15rem;
750
+ font-weight: 800;
751
+ color: var(--text-main);
752
  margin-bottom: 6px;
753
  }
754
 
755
  .timeline-status {
756
  font-size: 0.7rem;
757
  padding: 2px 8px;
758
+ border-radius: 10px;
759
+ font-weight: 800;
760
  }
761
 
762
+ .timeline-status.safe { background: #eef5f2; color: var(--primary); }
763
+ .timeline-status.warning { background: #fff9db; color: var(--secondary); }
764
+ .timeline-status.critical { background: #ffdad6; color: var(--red); }
765
 
766
  .empty-timeline {
767
  width: 100%;
 
772
  font-size: 0.9rem;
773
  }
774
 
775
+ /* Hourly cells */
776
  .hourly-container {
777
  margin-top: 1.5rem;
778
  padding: 0 2.5rem;
779
  z-index: 5;
780
  position: relative;
781
+ margin-bottom: 2.5rem;
782
  }
783
 
784
  .hourly-grid {
785
  display: grid;
786
  grid-template-columns: repeat(24, 1fr);
787
  gap: 4px;
788
+ background: var(--soft-surface);
789
+ border: 2px solid var(--border-color);
790
  padding: 10px;
791
+ border-radius: 12px;
792
  overflow-x: auto;
793
  }
794
 
 
802
  .cell-block {
803
  width: 100%;
804
  height: 40px;
805
+ border-radius: 6px;
806
  transition: opacity 0.3s;
807
  }
808
 
809
+ .cell-block.low { background-color: rgba(74, 222, 128, 0.35); border: 2.5px solid var(--green); }
810
+ .cell-block.medium { background-color: rgba(254, 208, 27, 0.35); border: 2.5px solid var(--yellow); }
811
+ .cell-block.high { background-color: rgba(186, 26, 26, 0.35); border: 2.5px solid var(--red); }
812
 
813
  .cell-time {
814
  font-family: var(--font-mono);
815
  font-size: 8px;
816
  color: var(--text-muted);
817
+ font-weight: 700;
818
  }
819
 
820
+ /* Footer Section */
821
  footer {
822
  width: 100%;
823
+ padding: 1.8rem;
824
  text-align: center;
825
+ border-top: 2px solid var(--border-color);
826
+ background: #ffffff;
827
  color: var(--text-muted);
828
  font-size: 0.75rem;
829
  font-family: var(--font-mono);
830
+ font-weight: 600;
831
  margin-top: auto;
832
  }
833
 
834
+ /* Keyframes pulse-indicator */
835
  @keyframes pulse-green {
836
+ 0% { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.4); }
837
+ 70% { box-shadow: 0 0 0 8px rgba(74, 222, 128, 0); }
838
+ 100% { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0); }
839
  }
840
 
841
  @keyframes pulse-node {
842
+ 0% { transform: scale(0.9); opacity: 0.3; }
843
  70% { transform: scale(1.6); opacity: 0; }
844
  100% { transform: scale(0.9); opacity: 0; }
845
  }
 
851
  margin-top: 6px;
852
  display: block;
853
  text-transform: uppercase;
854
+ font-weight: 700;
855
  }
856
 
857
  .button-row {
 
861
  }
862
 
863
  .secondary-btn {
864
+ background: var(--secondary-container) !important;
865
+ color: #574500 !important;
866
+ border: none;
867
+ box-shadow: 0 4px 10px rgba(254, 208, 27, 0.2);
868
  }
869
 
870
  .secondary-btn:hover {
871
+ background: #eec200 !important;
872
+ box-shadow: 0 6px 14px rgba(254, 208, 27, 0.3) !important;
873
  }
874
 
875
+ /* Single-Page Router View Transition */
 
876
  .page-container {
877
  display: none;
878
  opacity: 0;
879
+ transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
 
880
  padding: 1.5rem 2.5rem;
881
  flex: 1;
882
  z-index: 5;
 
886
  .page-container.active {
887
  display: block;
888
  opacity: 1;
889
+ animation: slide-fade-in 0.4s forwards cubic-bezier(0.25, 0.8, 0.25, 1);
890
  }
891
 
892
+ @keyframes slide-fade-in {
893
+ from { opacity: 0; transform: translateY(12px); }
894
  to { opacity: 1; transform: translateY(0); }
895
  }
896
 
897
+ /* Hero UI */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
898
  .hero-section {
899
  display: grid;
900
+ grid-template-columns: 1.25fr 0.75fr;
901
+ gap: 24px;
902
  align-items: center;
903
  padding: 3rem 0;
904
  }
 
912
  .hero-content {
913
  display: flex;
914
  flex-direction: column;
915
+ gap: 1.2rem;
916
  }
917
 
918
  .hero-title {
919
  font-family: var(--font-display);
920
+ font-size: 3.2rem;
921
  font-weight: 800;
922
+ letter-spacing: -0.02em;
923
+ line-height: 1.15;
924
+ background: linear-gradient(135deg, var(--primary) 30%, var(--secondary) 100%);
925
  -webkit-background-clip: text;
926
  -webkit-text-fill-color: transparent;
 
927
  }
928
 
929
  .hero-subtitle {
930
  font-size: 1.1rem;
931
  color: var(--text-muted);
932
  line-height: 1.6;
933
+ font-family: var(--font-body);
934
  }
935
 
936
  .hero-actions {
937
  display: flex;
938
+ gap: 12px;
939
+ max-width: 440px;
940
  }
941
 
942
  .hero-stats-panel {
943
  display: flex;
944
  flex-direction: column;
945
  gap: 1rem;
946
+ background: #ffffff !important;
947
+ border: 2px solid var(--border-color) !important;
948
  }
949
 
950
  .hero-stat-grid {
951
  display: grid;
952
  grid-template-columns: 1fr 1fr;
953
+ gap: 12px;
954
  }
955
 
956
  .hero-stat-card {
957
+ background: var(--soft-surface);
958
+ border: 2px solid var(--border-color);
959
  padding: 1.2rem;
960
+ border-radius: 10px;
961
  display: flex;
962
  flex-direction: column;
963
  gap: 4px;
 
965
 
966
  .h-stat-label {
967
  font-size: 0.75rem;
968
+ font-family: var(--font-display);
969
  color: var(--text-muted);
970
  text-transform: uppercase;
971
+ font-weight: 700;
972
  }
973
 
974
  .h-stat-value {
975
  font-size: 1.8rem;
976
  font-family: var(--font-display);
977
  font-weight: 800;
978
+ color: var(--text-main);
979
  }
980
 
981
+ /* Feature list grid */
982
  .features-section {
983
  padding: 2rem 0;
984
  }
 
986
  .section-title {
987
  font-family: var(--font-display);
988
  font-size: 1.4rem;
989
+ font-weight: 800;
990
+ letter-spacing: -0.01em;
991
  margin-bottom: 2rem;
992
+ color: var(--primary);
993
+ display: flex;
994
+ align-items: center;
995
+ gap: 8px;
996
+ }
997
+
998
+ .section-title::before {
999
+ content: '';
1000
+ display: inline-block;
1001
+ width: 5px;
1002
+ height: 22px;
1003
+ background: var(--secondary-container);
1004
+ border-radius: 2px;
1005
  }
1006
 
1007
  .features-grid {
 
1014
  display: flex;
1015
  flex-direction: column;
1016
  gap: 1rem;
1017
+ transition: transform 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
1018
  }
1019
 
1020
  .feature-card:hover {
 
1022
  }
1023
 
1024
  .feature-icon {
1025
+ font-size: 2.2rem;
1026
  font-weight: 800;
1027
+ color: var(--primary);
1028
+ opacity: 0.8;
1029
  }
1030
 
1031
  .feature-name {
1032
  font-family: var(--font-display);
1033
+ font-size: 1.1rem;
1034
+ font-weight: 700;
1035
+ color: var(--primary);
1036
  }
1037
 
1038
  .feature-desc {
 
1041
  line-height: 1.6;
1042
  }
1043
 
1044
+ /* Page headers */
1045
  .page-header-section {
1046
  padding: 2rem 0 1rem 0;
1047
  }
 
1050
  font-size: 0.95rem;
1051
  color: var(--text-muted);
1052
  margin-top: 6px;
1053
+ font-weight: 500;
1054
  }
1055
 
1056
+ /* News page container layout */
1057
  .news-grid {
1058
  display: grid;
1059
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
 
1062
  }
1063
 
1064
  .news-card {
1065
+ background: #ffffff;
1066
+ border: 2px solid var(--border-color);
1067
  border-radius: 12px;
1068
+ padding: 1.6rem;
 
1069
  display: flex;
1070
  flex-direction: column;
1071
  gap: 1rem;
1072
+ box-shadow: 0 4px 12px rgba(0, 107, 95, 0.02);
1073
+ transition: transform 0.25s cubic-bezier(0.25, 0.8, 0.25, 1),
1074
+ border-color 0.25s ease,
1075
+ box-shadow 0.25s ease;
1076
  }
1077
 
1078
  .news-card:hover {
1079
+ transform: translateY(-4px);
1080
+ border-color: var(--primary);
1081
+ box-shadow: 0 12px 24px rgba(0, 107, 95, 0.08);
1082
  }
1083
 
1084
  .news-card-header {
 
1088
  }
1089
 
1090
  .news-source {
1091
+ font-family: var(--font-display);
1092
  font-size: 0.75rem;
1093
+ font-weight: 700;
1094
+ background: #eef5f2;
1095
+ color: var(--primary);
1096
+ padding: 2px 10px;
1097
+ border-radius: 12px;
1098
+ border: 1px solid var(--border-color);
1099
  }
1100
 
1101
  .news-date {
1102
  font-family: var(--font-mono);
1103
  font-size: 0.75rem;
1104
  color: var(--text-muted);
1105
+ font-weight: 600;
1106
  }
1107
 
1108
  .news-title {
1109
  font-family: var(--font-display);
1110
+ font-size: 1.15rem;
1111
+ font-weight: 800;
1112
+ color: var(--text-main);
1113
+ line-height: 1.35;
1114
  }
1115
 
1116
  .news-summary {
 
1123
  margin-top: auto;
1124
  display: inline-flex;
1125
  align-items: center;
1126
+ color: var(--primary);
1127
  text-decoration: none;
1128
+ font-family: var(--font-display);
1129
+ font-size: 0.85rem;
1130
+ font-weight: 800;
1131
  gap: 6px;
1132
  transition: gap 0.2s;
1133
  }
 
1136
  gap: 10px;
1137
  }
1138
 
1139
+ /* Alerts Page container lists */
 
 
 
 
 
 
 
 
 
1140
  .alerts-summary {
1141
  margin-top: 1.5rem;
1142
  }
 
1152
  grid-template-columns: 120px 180px 100px 1fr;
1153
  gap: 1rem;
1154
  align-items: center;
1155
+ background: #ffffff;
1156
+ border: 2px solid var(--border-color);
1157
+ padding: 1.1rem 1.6rem;
1158
+ border-radius: 12px;
1159
+ box-shadow: 0 4px 10px rgba(0, 107, 95, 0.01);
1160
  transition: all 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
1161
  cursor: pointer;
1162
  }
 
1166
  }
1167
 
1168
  .alert-row:hover {
1169
+ background: var(--soft-surface) !important;
1170
+ border-color: var(--primary) !important;
1171
+ box-shadow: 0 8px 20px rgba(0, 107, 95, 0.06) !important;
1172
  transform: translateX(6px);
1173
  }
1174
 
 
1176
  font-family: var(--font-mono);
1177
  font-size: 0.85rem;
1178
  color: var(--text-muted);
1179
+ font-weight: 600;
1180
  }
1181
 
1182
  .alert-location {
1183
  font-family: var(--font-display);
1184
+ font-weight: 700;
1185
+ color: var(--text-main);
1186
  }
1187
 
1188
  .alert-badge {
1189
+ font-family: var(--font-display);
1190
  font-size: 0.75rem;
1191
+ font-weight: 800;
1192
+ padding: 4px 10px;
1193
+ border-radius: 12px;
1194
  text-align: center;
1195
+ border: 2px solid transparent;
1196
  }
1197
 
1198
  .alert-badge.critical {
1199
+ background: #ffdad6;
1200
  color: var(--red);
1201
+ border-color: var(--red);
 
1202
  }
1203
 
1204
  .alert-badge.warning {
1205
+ background: #fff9db;
1206
+ color: var(--secondary);
1207
+ border-color: var(--yellow);
 
1208
  }
1209
 
1210
  .alert-desc {
1211
  font-size: 0.85rem;
1212
  color: var(--text-muted);
1213
+ font-weight: 500;
1214
  }
1215
 
1216
+ /* Custom Interactive pointer (Glow Cursor) */
 
 
1217
  #cursor-dot,
1218
  #cursor-ring {
1219
  position: fixed;
 
1223
  z-index: 10000;
1224
  border-radius: 50%;
1225
  display: none;
 
1226
  }
1227
 
1228
  #cursor-dot {
1229
  width: 6px;
1230
  height: 6px;
1231
+ background: var(--primary);
1232
+ box-shadow: 0 0 6px var(--primary);
1233
  }
1234
 
1235
  #cursor-ring {
1236
  width: 40px;
1237
  height: 40px;
1238
+ border: 2px solid var(--primary);
1239
+ opacity: 0.5;
1240
+ transition: width 0.22s cubic-bezier(0.25, 1, 0.5, 1),
1241
+ height 0.22s cubic-bezier(0.25, 1, 0.5, 1),
1242
+ border-color 0.22s ease,
1243
+ background-color 0.22s ease;
1244
  }
1245
 
 
1246
  #cursor-ring.hover-state {
1247
+ width: 52px;
1248
+ height: 52px;
1249
+ border-color: var(--primary);
1250
+ background-color: rgba(0, 107, 95, 0.05);
1251
+ opacity: 0.8;
1252
  }
1253
 
1254
  @media (pointer: coarse) {
1255
+ #cursor-dot, #cursor-ring { display: none !important; }
1256
+ * { cursor: auto !important; }
 
 
 
 
 
1257
  }
1258
 
 
1259
  @media (pointer: fine) {
1260
  body, a, button, select, input, [role="button"], .leaflet-interactive {
1261
  cursor: none !important;
1262
  }
1263
  }
1264
 
1265
+ /* Developer Credits styling */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1266
  .developers-section {
1267
  padding: 2.5rem 0;
1268
  margin-top: 3.5rem;
1269
+ border-top: 2px solid var(--border-color);
1270
  }
1271
 
1272
  .developers-grid {
 
1278
 
1279
  .developer-card {
1280
  position: relative;
1281
+ background: #ffffff !important;
1282
+ border: 2px solid var(--border-color) !important;
1283
+ border-radius: 16px;
1284
  padding: 2.2rem;
1285
  text-align: center;
1286
+ box-shadow: 0 4px 12px rgba(0, 107, 95, 0.01);
1287
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
1288
  overflow: hidden;
 
1289
  }
1290
 
1291
  .developer-card::before {
 
1294
  top: 0;
1295
  left: 0;
1296
  right: 0;
1297
+ height: 4px;
1298
+ background: linear-gradient(90deg, transparent, var(--primary), transparent);
 
1299
  }
1300
 
1301
  .developer-card:hover {
1302
  transform: translateY(-6px);
1303
+ border-color: var(--primary) !important;
1304
+ box-shadow: 0 12px 28px rgba(0, 107, 95, 0.08) !important;
1305
  }
1306
 
1307
  .dev-role {
1308
  font-size: 0.75rem;
1309
  text-transform: uppercase;
1310
+ letter-spacing: 0.1em;
1311
+ color: var(--primary);
1312
+ font-weight: 800;
1313
  margin-bottom: 0.6rem;
1314
+ font-family: var(--font-display);
1315
  }
1316
 
1317
  .dev-name {
1318
+ font-size: 1.3rem;
1319
+ color: var(--text-main);
1320
  font-weight: 800;
1321
  margin-bottom: 0.8rem;
1322
  font-family: var(--font-display);
 
1323
  }
1324
 
1325
  .dev-desc {
1326
+ font-size: 0.85rem;
1327
  color: var(--text-muted);
1328
  line-height: 1.6;
1329
  }
1330
 
1331
+ /* Responsiveness adjustments */
 
 
1332
  @media (max-width: 1200px) {
1333
  .dashboard-grid {
1334
  display: flex !important;
1335
  flex-direction: column !important;
1336
+ gap: 24px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1337
  }
1338
+ .map-and-stats { order: -1 !important; }
1339
+ .control-panel { order: 0 !important; }
1340
+ .analysis-panel { order: 1 !important; }
1341
  }
1342
 
1343
  @media (max-width: 992px) {
 
1360
  flex-direction: column !important;
1361
  gap: 1.2rem !important;
1362
  padding: 1.2rem 1.5rem !important;
 
1363
  }
1364
  .logo-container {
1365
  justify-content: center;
 
1366
  }
 
1367
  .nav-links {
1368
  display: grid !important;
1369
  grid-template-columns: repeat(3, 1fr) !important;
1370
+ gap: 4px !important;
1371
  width: 100% !important;
1372
+ border-radius: 24px;
1373
  padding: 4px;
 
 
1374
  }
1375
  .nav-btn {
1376
  width: 100% !important;
1377
+ padding: 8px 2px !important;
1378
+ font-size: 0.75rem !important;
1379
  text-align: center !important;
 
 
 
 
 
 
 
1380
  }
1381
  .page-container {
1382
+ padding: 1.2rem 1.5rem !important;
1383
  }
1384
  .stats-row {
1385
  grid-template-columns: 1fr !important;
 
1386
  }
1387
  .hero-stat-grid {
1388
  grid-template-columns: 1fr !important;
 
1390
  .hero-title {
1391
  font-size: 2.2rem !important;
1392
  }
 
 
 
1393
  .map-panel {
1394
+ height: 340px !important;
1395
  }
1396
  .logistics-grid {
1397
  grid-template-columns: 1fr !important;
1398
  }
 
 
 
 
 
 
1399
  .alert-row, .autopilot-row {
1400
  display: flex !important;
1401
  flex-direction: column !important;
1402
  align-items: flex-start !important;
1403
+ gap: 8px !important;
1404
+ padding: 1.2rem 1.5rem !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1405
  }
1406
  }