webapp1 commited on
Commit
604f034
·
verified ·
1 Parent(s): cc3fce6

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +372 -161
templates/index.html CHANGED
@@ -5,62 +5,139 @@
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
  <title>CrashVision AI - Accident Detection</title>
7
 
 
8
  <!-- 📱 MOBILE APP & HOME SCREEN ICONS SETUP 📱 -->
 
9
  <meta name="apple-mobile-web-app-capable" content="yes">
10
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
11
  <meta name="apple-mobile-web-app-title" content="CrashVision">
12
  <meta name="mobile-web-app-capable" content="yes">
13
  <meta name="theme-color" content="#1e1b4b">
14
 
 
15
  <link rel="icon" type="image/png" sizes="192x192" href="{{ url_for('static', filename='logo.PNG') }}">
16
  <link rel="apple-touch-icon" href="{{ url_for('static', filename='logo.PNG') }}">
 
 
17
  <link rel="manifest" href='data:application/manifest+json;utf8,{"name":"CrashVision AI","short_name":"CrashVision","start_url":"/","display":"standalone","background_color":"#F4F4F9","theme_color":"#1e1b4b","icons":[{"src":"/static/logo.PNG","sizes":"192x192","type":"image/png"},{"src":"/static/logo.PNG","sizes":"512x512","type":"image/png"}]}'>
 
18
 
 
19
  <script src="https://cdn.tailwindcss.com"></script>
20
  <script>
21
  tailwind.config = {
22
  darkMode: 'class',
23
  theme: {
24
  extend: {
25
- fontFamily: { sans: ['-apple-system', 'BlinkMacSystemFont', 'San Francisco', 'Inter', 'sans-serif'], },
26
- animation: { 'blob': 'blob 10s infinite', 'pulse-glow': 'pulse-glow 3s infinite', },
 
 
 
 
 
27
  keyframes: {
28
  blob: {
29
  '0%': { transform: 'translate(0px, 0px) scale(1)' },
30
  '33%': { transform: 'translate(40px, -60px) scale(1.2)' },
31
  '66%': { transform: 'translate(-30px, 30px) scale(0.8)' },
32
  '100%': { transform: 'translate(0px, 0px) scale(1)' },
 
 
 
 
33
  }
34
  }
35
  }
36
  }
37
  }
38
  </script>
 
39
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
40
  <style>
41
- body { background-color: #F4F4F9; -webkit-font-smoothing: antialiased; transition: background-color 0.5s ease, background-image 0.5s ease; }
42
- .dark body { background-color: #151518; background-image: linear-gradient(135deg, #151518 0%, #2a1f3d 50%, #101012 100%); background-attachment: fixed; }
43
- .modal-bg { background-color: #F4F4F9; }
44
- .dark .modal-bg { background-color: #151518; background-image: linear-gradient(135deg, #151518 0%, #2a1f3d 50%, #101012 100%); background-attachment: fixed; }
45
-
46
- .ios-glass { background: rgba(255, 255, 255, 0.45); backdrop-filter: blur(40px) saturate(200%); border: 1.5px solid rgba(255, 255, 255, 0.9); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5), 0 8px 32px rgba(0, 0, 0, 0.08); transition: all 0.5s ease; }
47
- .dark .ios-glass { background: rgba(20, 20, 25, 0.35); border: 1px solid rgba(255, 255, 255, 0.15); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05), 0 8px 32px rgba(0, 0, 0, 0.6); backdrop-filter: blur(40px) saturate(200%); }
48
- .ios-glass-inner { background: rgba(255, 255, 255, 0.5); border: 1px solid rgba(255, 255, 255, 0.8); transition: all 0.5s ease; }
49
- .dark .ios-glass-inner { background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.12); }
50
- .bg-mesh { background-size: 40px 40px; background-image: linear-gradient(to right, rgba(100, 100, 150, 0.06) 1px, transparent 1px), linear-gradient(to bottom, rgba(100, 100, 150, 0.06) 1px, transparent 1px); }
51
- .dark .bg-mesh { background-image: linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px), linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  ::-webkit-scrollbar { width: 6px; }
53
  ::-webkit-scrollbar-track { background: transparent; }
54
  ::-webkit-scrollbar-thumb { background: rgba(156, 163, 175, 0.5); border-radius: 10px; }
55
  .dark ::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); }
56
- .predict-input { width: 100%; padding: 0.75rem 1rem; border-radius: 0.75rem; font-size: 0.875rem; font-weight: 600; outline: none; transition: all 0.3s ease; }
57
- @keyframes jiggle { 0%, 100% { transform: scale3d(1, 1, 1); } 30% { transform: scale3d(1.25, 0.75, 1); } 40% { transform: scale3d(0.75, 1.25, 1); } 50% { transform: scale3d(1.15, 0.85, 1); } 65% { transform: scale3d(0.95, 1.05, 1); } 75% { transform: scale3d(1.05, 0.95, 1); } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  .animate-jiggle { animation: jiggle 1.5s ease-in-out infinite; transform-origin: bottom; }
59
  </style>
60
  </head>
61
  <body class="relative min-h-screen transition-colors duration-500 overflow-x-hidden">
62
 
63
- <!-- Splash Screen -->
64
  <div id="appSplashScreen" class="fixed inset-0 z-[100] flex flex-col items-center justify-center bg-[#F4F4F9] dark:bg-[#151518] transition-all duration-700 ease-in-out">
65
  <div class="mb-8">
66
  <svg class="w-24 h-24 text-indigo-700 dark:text-purple-400 drop-shadow-xl" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
@@ -77,6 +154,7 @@
77
  </div>
78
  <h1 class="text-4xl font-black tracking-tight text-indigo-950 dark:text-white drop-shadow-sm">CrashVision AI</h1>
79
  <p class="text-xs font-black uppercase tracking-[0.3em] text-indigo-500 mt-3">Initializing Systems</p>
 
80
  <div class="mt-8 flex gap-3">
81
  <div class="w-3 h-3 rounded-md bg-fuchsia-500 animate-jiggle" style="animation-delay: 0s;"></div>
82
  <div class="w-3 h-3 rounded-md bg-indigo-500 animate-jiggle" style="animation-delay: 0.15s;"></div>
@@ -107,7 +185,7 @@
107
  <!-- Emergency Dispatch Banner -->
108
  <div id="emergencyBanner" class="hidden fixed top-0 left-0 w-full bg-red-600 text-white py-3 px-4 z-50 flex items-center justify-center gap-4 animate-pulse shadow-lg shadow-red-500/50">
109
  <i class="fas fa-exclamation-triangle text-xl"></i>
110
- <span class="font-black uppercase tracking-widest text-sm sm:text-base">Major Collision Detected. Automated SOS Dispatched to ntfy.sh</span>
111
  <i class="fas fa-exclamation-triangle text-xl"></i>
112
  </div>
113
 
@@ -127,35 +205,47 @@
127
  </div>
128
 
129
  <div class="text-center">
130
- <h1 class="text-3xl sm:text-5xl font-black tracking-tight leading-tight text-indigo-700 dark:text-purple-400 drop-shadow-sm transition-colors duration-500">CrashVision AI</h1>
131
- <span class="text-[9px] sm:text-xs text-indigo-800/60 dark:text-purple-200 font-black tracking-[0.4em] uppercase mt-2 sm:mt-3 block opacity-90 transition-colors duration-500">Road Safety Analytics</span>
 
 
 
 
132
  </div>
133
  </header>
134
 
135
  <main class="relative z-10 container mx-auto pb-12 px-4 sm:px-6 lg:px-8 max-w-6xl">
136
  <div class="w-full transition-all duration-500">
137
 
138
- <!-- SECTION 1: HOME AREA -->
139
  <div id="uploadSection" class="flex flex-col gap-8 sm:gap-6">
 
 
140
  <div class="ios-glass rounded-[32px] sm:rounded-[40px] px-6 py-10 sm:p-10 md:p-16 text-center shadow-lg">
141
  <div class="max-w-3xl mx-auto">
142
- <h2 class="text-2xl sm:text-3xl font-extrabold mb-2 sm:mb-4 tracking-tight text-indigo-950 dark:text-white">Incident Analysis</h2>
143
- <p class="text-indigo-800/60 dark:text-purple-100 mb-6 sm:mb-10 text-xs sm:text-base leading-relaxed font-semibold">Input surveillance streams or connect a live IP camera.</p>
 
 
 
 
144
 
145
  <div class="grid grid-cols-2 gap-3 sm:gap-6 justify-center">
 
146
  <div class="relative group cursor-pointer h-full" onclick="openIpCamModal()">
147
- <div class="block w-full h-full py-10 px-4 sm:p-10 border-2 border-dashed border-rose-400/30 dark:border-rose-400/40 rounded-[20px] sm:rounded-[32px] ios-glass-inner hover:bg-rose-50/70 dark:hover:bg-rose-900/20 transition-all group-hover:border-rose-500/50 flex flex-col items-center justify-center">
148
  <div class="w-16 h-16 sm:w-20 sm:h-20 bg-rose-50 dark:bg-rose-500/20 rounded-[14px] sm:rounded-3xl flex items-center justify-center mb-3 sm:mb-4 group-hover:scale-110 transition-transform duration-500 shadow-sm border border-rose-100 dark:border-rose-400/30">
149
  <i class="fas fa-satellite-dish text-2xl sm:text-3xl text-rose-600 dark:text-rose-300"></i>
150
  </div>
151
  <span class="block text-sm sm:text-xl font-black text-rose-900 dark:text-rose-100 mb-0 sm:mb-1 leading-tight">Live IP</span>
152
- <span class="block text-[9px] sm:text-xs text-rose-600/60 dark:text-rose-300 font-bold uppercase tracking-widest hidden sm:block">Connect RTSP / Web</span>
153
  </div>
154
  </div>
155
 
 
156
  <form id="uploadForm" class="relative group cursor-pointer h-full">
157
  <input type="file" id="fileInput" name="file" accept="image/png, image/jpeg, image/jpg, video/mp4" class="hidden">
158
- <label for="fileInput" class="block w-full h-full py-10 px-4 sm:p-10 border-2 border-dashed border-indigo-400/30 dark:border-purple-400/40 rounded-[20px] sm:rounded-[32px] ios-glass-inner hover:bg-white/70 dark:hover:bg-white/5 transition-all cursor-pointer group-hover:border-indigo-500/50 flex flex-col items-center justify-center">
159
  <div class="w-16 h-16 sm:w-20 sm:h-20 bg-indigo-50 dark:bg-white/10 rounded-[14px] sm:rounded-3xl flex items-center justify-center mb-3 sm:mb-4 group-hover:scale-110 transition-transform duration-500 shadow-sm border border-indigo-100 dark:border-white/20">
160
  <i class="fas fa-arrow-up-from-bracket text-2xl sm:text-3xl text-indigo-600 dark:text-purple-200"></i>
161
  </div>
@@ -167,10 +257,11 @@
167
  </div>
168
  </div>
169
 
 
170
  <div class="relative group cursor-pointer mt-2 mb-2" onclick="openPredictModal()">
171
- <div class="ios-glass p-7 sm:p-6 rounded-[32px] hover:-translate-y-1 transition-transform duration-300 shadow-sm border border-cyan-400/30 flex items-center justify-between bg-gradient-to-r from-transparent to-cyan-50/30 dark:to-cyan-900/10">
172
  <div class="flex items-center gap-5">
173
- <div class="w-16 h-16 sm:w-14 sm:h-14 rounded-2xl bg-cyan-100 dark:bg-cyan-500/20 flex items-center justify-center shadow-sm group-hover:scale-110 transition-transform border border-cyan-200/50">
174
  <i class="fas fa-chart-line text-cyan-600 dark:text-cyan-300 text-3xl sm:text-2xl"></i>
175
  </div>
176
  <div class="text-left">
@@ -178,32 +269,40 @@
178
  <p class="text-[10px] sm:text-[10px] font-bold text-indigo-800/60 dark:text-purple-200 uppercase tracking-widest mt-1">Run Tabular AI Simulations</p>
179
  </div>
180
  </div>
181
- <div class="w-12 h-12 sm:w-10 sm:h-10 rounded-full bg-indigo-900/5 dark:bg-white/5 flex items-center justify-center group-hover:bg-cyan-100 transition-colors">
182
- <i class="fas fa-arrow-right text-indigo-400 dark:text-purple-300 text-base sm:text-sm"></i>
183
  </div>
184
  </div>
185
  </div>
186
 
 
187
  <div class="grid grid-cols-1 md:grid-cols-3 gap-6 text-left">
188
  <div class="ios-glass p-6 rounded-[32px] hover:-translate-y-1 transition-transform duration-300 shadow-sm cursor-default">
189
- <div class="w-12 h-12 rounded-2xl bg-indigo-100 dark:bg-white/10 flex items-center justify-center mb-5 border border-indigo-200/50 shadow-sm"><i class="fas fa-eye text-indigo-600 dark:text-purple-300 text-xl"></i></div>
 
 
190
  <h4 class="text-sm font-black uppercase tracking-wider text-indigo-950 dark:text-purple-50 mb-2">Spatial Engine</h4>
191
  <p class="text-xs text-indigo-800/70 dark:text-purple-100 leading-relaxed font-bold">YOLOv8 XAI Tracking overlays.</p>
192
  </div>
193
  <div class="ios-glass p-6 rounded-[32px] hover:-translate-y-1 transition-transform duration-300 shadow-sm cursor-default">
194
- <div class="w-12 h-12 rounded-2xl bg-fuchsia-100 dark:bg-white/10 flex items-center justify-center mb-5 border border-fuchsia-200/50 shadow-sm"><i class="fas fa-layer-group text-fuchsia-600 dark:text-fuchsia-300 text-xl"></i></div>
 
 
195
  <h4 class="text-sm font-black uppercase tracking-wider text-indigo-950 dark:text-purple-50 mb-2">Temporal Engine</h4>
196
  <p class="text-xs text-indigo-800/70 dark:text-purple-100 leading-relaxed font-bold">3D-CNN models physical motion.</p>
197
  </div>
198
  <div class="ios-glass p-6 rounded-[32px] hover:-translate-y-1 transition-transform duration-300 shadow-sm cursor-default">
199
- <div class="w-12 h-12 rounded-2xl bg-rose-100 dark:bg-white/10 flex items-center justify-center mb-5 border border-rose-200/50 shadow-sm"><i class="fas fa-bolt text-rose-600 dark:text-rose-300 text-xl"></i></div>
 
 
200
  <h4 class="text-sm font-black uppercase tracking-wider text-indigo-950 dark:text-purple-50 mb-2">Automated SOS</h4>
201
- <p class="text-xs text-indigo-800/70 dark:text-purple-100 leading-relaxed font-bold">Instant HTTP Webhook Push via ntfy.</p>
202
  </div>
203
  </div>
 
204
  </div>
205
 
206
- <!-- SECTION 2: RESULTS DASHBOARD -->
207
  <div id="results" class="hidden ios-glass rounded-[40px] overflow-hidden shadow-2xl">
208
  <div class="grid grid-cols-1 lg:grid-cols-12 gap-0">
209
 
@@ -211,22 +310,27 @@
211
  <div class="lg:col-span-7 p-8 md:p-12 border-b lg:border-b-0 lg:border-r border-indigo-200/50 dark:border-white/10">
212
  <div class="flex justify-between items-center mb-6">
213
  <h3 class="text-xs font-black uppercase tracking-[0.3em] text-indigo-800/50 dark:text-purple-200">XAI Analytics Feed</h3>
214
- <span class="px-4 py-1.5 text-[10px] font-black uppercase tracking-widest bg-white/60 dark:bg-white/10 rounded-full text-indigo-900 dark:text-white border shadow-sm">Channel: CV-PRIME</span>
215
  </div>
216
 
217
- <!-- NEW YOUTUBE-STYLE INTERACTIVE MEDIA PLAYER AREA -->
218
- <div class="rounded-[32px] overflow-hidden shadow-2xl border border-white/50 dark:border-white/20 relative bg-black aspect-video flex items-center justify-center group" id="videoPlayerContainer">
219
-
220
- <!-- Display Image (Single video feed element) -->
221
  <img id="previewImg" src="" class="w-full h-full object-contain z-10 hidden" alt="Video View">
222
 
223
  <!-- Snapshot Container Overlay -->
224
- <div id="snapshotContainer" class="absolute inset-0 z-50 hidden bg-black flex items-center justify-center">
225
  <img id="snapshotImg" src="" class="w-full h-full object-contain">
 
226
  <div class="absolute top-6 right-6 flex gap-3">
227
- <button onclick="fullscreenSnapshot()" class="w-8 h-8 rounded-full bg-white/20 hover:bg-white/40 border border-white/40 text-white flex items-center justify-center transition-all shadow-lg backdrop-blur-md"><i class="fas fa-expand"></i></button>
228
- <button onclick="closeSnapshot()" class="w-8 h-8 rounded-full bg-red-500/80 hover:bg-red-500 border border-red-400 text-white flex items-center justify-center transition-all shadow-lg backdrop-blur-md"><i class="fas fa-times"></i></button>
 
 
 
 
229
  </div>
 
230
  <div class="absolute top-6 left-6 z-20">
231
  <span class="bg-black/60 backdrop-blur-xl text-white text-[10px] px-3 py-1.5 rounded-xl font-black uppercase tracking-widest border border-white/20 flex items-center gap-2">
232
  <i class="fas fa-camera text-blue-400"></i> CAPTURED SNAPSHOT
@@ -235,36 +339,36 @@
235
  </div>
236
 
237
  <!-- Live Tag -->
238
- <div id="liveBadgeContainer" class="absolute top-4 left-4 z-20">
239
- <span id="liveBadge" class="bg-black/60 backdrop-blur-xl text-white text-[9px] sm:text-[10px] px-3 py-1.5 rounded-xl font-black uppercase tracking-widest border border-white/20 flex items-center gap-2 transition-all">
240
  <span class="w-2 h-2 rounded-full bg-red-500 animate-pulse shadow-[0_0_8px_red]"></span> LIVE AI FEED
241
  </span>
242
  </div>
243
 
244
- <!-- IN-VIDEO CONTROLS OVERLAY (Appears on Hover) -->
245
- <div id="inVideoControls" class="absolute bottom-0 left-0 w-full bg-gradient-to-t from-black/95 via-black/60 to-transparent p-4 sm:p-6 opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-40 hidden flex-col justify-end">
246
 
247
  <!-- Progress Bar -->
248
- <div class="w-full h-1.5 sm:h-2 bg-white/30 rounded-full cursor-pointer relative mb-3 sm:mb-4 group/bar" onclick="seekVideo(event)" id="progressBarContainer">
249
- <div id="progressFill" class="absolute top-0 left-0 h-full bg-indigo-500 rounded-full transition-all duration-300 pointer-events-none group-hover/bar:bg-indigo-400 shadow-[0_0_10px_rgba(99,102,241,0.5)]" style="width: 0%"></div>
250
  </div>
251
-
252
- <!-- Bottom Row -->
253
- <div class="flex justify-between items-center text-white w-full">
254
- <!-- Left Side: Play/Pause/Skip -->
255
- <div class="flex items-center gap-4 sm:gap-6">
256
- <button onclick="togglePlayPause()" class="hover:text-indigo-400 transition-colors transform hover:scale-110 active:scale-95"><i id="playPauseIcon" class="fas fa-pause text-lg sm:text-xl"></i></button>
257
- <button onclick="skipVideo(-5)" class="hover:text-indigo-400 transition-colors hidden sm:block transform hover:-translate-x-1"><i class="fas fa-backward"></i> <span class="text-[10px] font-black ml-1">-5s</span></button>
258
- <button onclick="skipVideo(5)" class="hover:text-indigo-400 transition-colors hidden sm:block transform hover:translate-x-1"><span class="text-[10px] font-black mr-1">+5s</span> <i class="fas fa-forward"></i></button>
 
 
259
  </div>
260
 
261
- <!-- Right Side: Views & Snapshot -->
262
- <div class="flex items-center gap-3 sm:gap-4">
263
- <button onclick="goTracking()" id="tBtnOverlay" class="text-[9px] sm:text-[10px] font-black uppercase tracking-widest text-rose-400 hover:text-rose-300 transition-colors">AI Tracking</button>
264
- <div class="h-3 w-[1px] bg-white/30"></div>
265
- <button onclick="goOriginal()" id="oBtnOverlay" class="text-[9px] sm:text-[10px] font-black uppercase tracking-widest text-white/50 hover:text-white transition-colors">Raw Feed</button>
266
- <div class="h-3 w-[1px] bg-white/30 ml-1"></div>
267
- <button onclick="takeSnapshot()" class="hover:text-blue-400 transition-colors transform hover:scale-110 ml-1" title="Take Snapshot"><i class="fas fa-camera sm:text-lg"></i></button>
268
  </div>
269
  </div>
270
  </div>
@@ -315,7 +419,9 @@
315
  <div id="alprSection" class="hidden">
316
  <div class="flex justify-between items-end mb-3">
317
  <span class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-50 flex items-center gap-3">
318
- <div class="w-8 h-8 rounded-xl bg-white/60 dark:bg-white/10 flex items-center justify-center border border-indigo-200/50 shadow-sm"><i class="fas fa-car-side text-indigo-600 dark:text-fuchsia-300 text-xs"></i></div>
 
 
319
  ALPR (License Plates)
320
  </span>
321
  </div>
@@ -325,7 +431,9 @@
325
  <div>
326
  <div class="flex justify-between items-end mb-3">
327
  <span class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-50 flex items-center gap-3">
328
- <div class="w-8 h-8 rounded-xl bg-white/60 dark:bg-white/10 flex items-center justify-center border border-indigo-200/50 shadow-sm"><i class="fas fa-layer-group text-indigo-600 dark:text-fuchsia-300 text-xs"></i></div>
 
 
329
  Temporal (3D-CNN)
330
  </span>
331
  <span id="rcnnVal" class="font-black text-sm text-indigo-900 dark:text-white">0%</span>
@@ -337,7 +445,9 @@
337
  <div>
338
  <div class="flex justify-between items-end mb-3">
339
  <span class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-50 flex items-center gap-3">
340
- <div class="w-8 h-8 rounded-xl bg-white/60 dark:bg-white/10 flex items-center justify-center border border-indigo-200/50 shadow-sm"><i class="fas fa-crosshairs text-amber-600 dark:text-amber-400 text-xs"></i></div>
 
 
341
  Spatial (YOLOv8 Max)
342
  </span>
343
  <span id="cnnVal" class="font-black text-sm text-indigo-900 dark:text-white">0%</span>
@@ -350,7 +460,7 @@
350
  </div>
351
 
352
  <div class="mt-8 flex gap-4">
353
- <button onclick="resetApp()" class="flex-1 py-4 px-6 bg-indigo-950 dark:bg-purple-600 text-white rounded-2xl font-black uppercase tracking-widest transition-all active:scale-95 text-xs flex justify-center items-center gap-3 shadow-xl hover:opacity-90">
354
  <i class="fas fa-stop text-white"></i> End Session
355
  </button>
356
  </div>
@@ -364,146 +474,222 @@
364
  <div id="ipCamModal" class="hidden fixed inset-0 z-[60] flex items-center justify-center bg-indigo-950/60 dark:bg-black/80 backdrop-blur-md p-4">
365
  <div class="ios-glass p-8 rounded-[32px] max-w-md w-full shadow-2xl relative">
366
  <h3 class="text-2xl font-black text-indigo-950 dark:text-white mb-2">Connect IP Camera</h3>
367
- <p class="text-sm font-bold text-indigo-800/60 dark:text-purple-200 mb-6">Enter the RTSP, HTTP, or YouTube Live stream URL.</p>
368
 
369
- <input type="text" id="ipCamUrl" placeholder="e.g., https://youtube.com/live/xyz" class="w-full px-5 py-4 rounded-xl border border-indigo-200 dark:border-white/20 bg-white/50 dark:bg-white/5 text-indigo-900 dark:text-white font-semibold outline-none focus:border-indigo-500 mb-6 placeholder-indigo-300">
370
 
371
  <div class="flex gap-4">
372
- <button onclick="closeIpCamModal()" class="flex-1 py-3 rounded-xl font-black uppercase tracking-widest text-xs bg-white dark:bg-white/10 text-indigo-900 dark:text-white border shadow-sm hover:bg-gray-50 transition-all">Cancel</button>
373
- <button onclick="connectIpCam()" class="flex-1 py-3 rounded-xl font-black uppercase tracking-widest text-xs bg-rose-600 text-white shadow-lg hover:bg-rose-500 transition-all">Connect</button>
374
  </div>
375
  </div>
376
  </div>
377
 
378
- <!-- Predictive Analysis Form Modal (Same as before) -->
379
  <div id="predictiveModal" class="hidden fixed inset-0 z-[60] modal-bg overflow-y-auto transition-colors duration-500">
 
 
380
  <div class="fixed inset-0 z-0 bg-mesh pointer-events-none"></div>
381
  <div class="fixed inset-0 z-0 overflow-hidden pointer-events-none">
382
- <div class="absolute top-[10%] left-[20%] w-[35rem] h-[35rem] bg-cyan-400 dark:bg-cyan-500/20 rounded-full mix-blend-multiply dark:mix-blend-screen filter blur-[120px] opacity-20 animate-blob"></div>
383
- <div class="absolute bottom-[20%] right-[10%] w-[30rem] h-[30rem] bg-indigo-300 dark:bg-indigo-500/20 rounded-full mix-blend-multiply dark:mix-blend-screen filter blur-[120px] opacity-20 animate-blob" style="animation-delay: 2s"></div>
384
  </div>
385
 
386
- <button onclick="closePredictModal()" class="fixed top-6 left-6 sm:top-8 sm:left-8 z-[70] w-10 h-10 rounded-full flex items-center justify-center hover:scale-105 active:scale-95 transition-all shadow-sm text-indigo-900 dark:text-purple-100 cursor-pointer bg-white/30 dark:bg-white/10 backdrop-blur-xl border border-white/40"><i class="fas fa-arrow-left text-sm"></i></button>
 
 
 
387
 
 
388
  <div class="relative z-10 min-h-screen flex flex-col">
 
 
389
  <div class="pt-20 sm:pt-24 pb-8 px-4 flex flex-col items-center justify-center text-center">
390
  <div class="mb-4 sm:mb-6 flex items-center justify-center group transition-all duration-500 hover:scale-110 drop-shadow-xl">
391
- <div class="w-14 h-14 sm:w-16 sm:h-16 rounded-2xl bg-cyan-100 dark:bg-cyan-500/20 flex items-center justify-center border border-cyan-200/50 shadow-sm relative overflow-hidden"><i class="fas fa-chart-line text-cyan-600 dark:text-cyan-300 text-2xl sm:text-3xl z-10"></i></div>
 
 
392
  </div>
393
  <h2 class="text-3xl sm:text-4xl font-black tracking-tight text-indigo-950 dark:text-white mb-3">Accident Risk Predictor</h2>
394
- <p class="text-indigo-800/60 dark:text-purple-200 text-xs sm:text-sm font-semibold max-w-xl mx-auto px-4">Predict the probability of an accident using our trained Tabular AI model.</p>
 
 
395
  </div>
396
 
 
397
  <div class="container mx-auto px-4 pb-16 max-w-4xl flex-grow">
398
  <div class="ios-glass p-6 sm:p-10 rounded-[32px] sm:rounded-[40px] shadow-2xl w-full">
 
 
399
  <div id="predictiveFormView">
400
  <form id="tabularForm" onsubmit="submitPredictiveData(event)">
 
401
  <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-6">
402
 
403
- <div class="ios-glass-inner p-5 sm:p-6 rounded-[24px] shadow-sm border border-white/50 hover:bg-white/50 transition-colors group">
404
- <div class="flex items-center gap-3 mb-4 border-b border-indigo-100/50 pb-3">
405
- <div class="w-8 h-8 rounded-xl bg-cyan-100 flex items-center justify-center border group-hover:scale-110 transition-transform"><i class="fas fa-cloud-sun text-cyan-600 text-xs"></i></div>
406
- <h4 class="font-black text-[11px] uppercase tracking-widest text-indigo-900">Conditions</h4>
 
 
 
407
  </div>
408
  <div class="space-y-4">
409
  <div>
410
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Weather</label>
411
- <select id="tab_weather" class="predict-input bg-white/60 border border-indigo-200/60 text-indigo-950 cursor-pointer"><option value="">Unknown</option><option value="Clear">Clear</option><option value="Rainy">Rainy</option><option value="Foggy">Foggy</option><option value="Snowy">Snowy</option></select>
 
 
 
 
 
 
412
  </div>
413
  <div>
414
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Light Cond.</label>
415
- <select id="tab_light" class="predict-input bg-white/60 border text-indigo-950 cursor-pointer"><option value="">Unknown</option><option value="Daylight">Daylight</option><option value="Artificial Light">Artificial Light</option><option value="No Light">No Light</option></select>
 
 
 
 
 
416
  </div>
417
  <div>
418
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Time of Day</label>
419
- <select id="tab_time" class="predict-input bg-white/60 border text-indigo-950 cursor-pointer"><option value="">Unknown</option><option value="Morning">Morning</option><option value="Afternoon">Afternoon</option><option value="Evening">Evening</option><option value="Night">Night</option></select>
 
 
 
 
 
 
420
  </div>
421
  </div>
422
  </div>
423
 
424
- <div class="ios-glass-inner p-5 sm:p-6 rounded-[24px] shadow-sm border hover:bg-white/50 transition-colors group">
425
- <div class="flex items-center gap-3 mb-4 border-b pb-3">
426
- <div class="w-8 h-8 rounded-xl bg-rose-100 flex items-center justify-center border group-hover:scale-110 transition-transform"><i class="fas fa-road text-rose-600 text-xs"></i></div>
427
- <h4 class="font-black text-[11px] uppercase tracking-widest text-indigo-900">Road Specs</h4>
 
 
 
428
  </div>
429
  <div class="space-y-4">
430
  <div>
431
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Road Type</label>
432
- <select id="tab_road_type" class="predict-input bg-white/60 border text-indigo-950"><option value="City Road">City Road</option><option value="Highway">Highway</option><option value="Rural Road">Rural Road</option></select>
 
 
 
 
433
  </div>
434
  <div>
435
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Surface</label>
436
- <select id="tab_road_cond" class="predict-input bg-white/60 border text-indigo-950"><option value="Dry">Dry</option><option value="Wet">Wet</option><option value="Icy">Icy</option><option value="Under Construction">Under Construction</option></select>
 
 
 
 
 
437
  </div>
438
  <div>
439
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Speed Limit</label>
440
- <input type="number" id="tab_speed" placeholder="e.g. 60" min="10" max="250" class="predict-input bg-white/60 border text-indigo-950 shadow-sm">
441
  </div>
442
  </div>
443
  </div>
444
 
445
- <div class="ios-glass-inner p-5 sm:p-6 rounded-[24px] shadow-sm border hover:bg-white/50 transition-colors group">
446
- <div class="flex items-center gap-3 mb-4 border-b pb-3">
447
- <div class="w-8 h-8 rounded-xl bg-amber-100 flex items-center justify-center border group-hover:scale-110 transition-transform"><i class="fas fa-car-side text-amber-600 text-xs"></i></div>
448
- <h4 class="font-black text-[11px] uppercase tracking-widest text-indigo-900">Traffic Data</h4>
 
 
 
449
  </div>
450
  <div class="space-y-4">
451
  <div>
452
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Density (0-5)</label>
453
- <input type="number" id="tab_density" placeholder="e.g. 2" min="0" max="5" class="predict-input bg-white/60 border text-indigo-950">
454
  </div>
455
  <div>
456
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Vehicles Inv.</label>
457
- <input type="number" id="tab_vehicles" placeholder="e.g. 2" min="1" max="20" class="predict-input bg-white/60 border text-indigo-950">
458
  </div>
459
  <div>
460
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Vehicle Type</label>
461
- <select id="tab_vehicle" class="predict-input bg-white/60 border text-indigo-950"><option value="Car">Car</option><option value="Truck">Truck</option><option value="Bus">Bus</option><option value="Motorcycle">Motorcycle</option></select>
 
 
 
 
 
462
  </div>
463
  </div>
464
  </div>
465
 
466
- <div class="ios-glass-inner p-5 sm:p-6 rounded-[24px] shadow-sm border hover:bg-white/50 transition-colors group">
467
- <div class="flex items-center gap-3 mb-4 border-b pb-3">
468
- <div class="w-8 h-8 rounded-xl bg-fuchsia-100 flex items-center justify-center border group-hover:scale-110 transition-transform"><i class="fas fa-user text-fuchsia-600 text-xs"></i></div>
469
- <h4 class="font-black text-[11px] uppercase tracking-widest text-indigo-900">Driver Profile</h4>
 
 
 
470
  </div>
471
  <div class="space-y-4">
472
  <div>
473
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Driver Age</label>
474
- <input type="number" id="tab_age" placeholder="e.g. 35" min="16" max="99" class="predict-input bg-white/60 border text-indigo-950">
475
  </div>
476
  <div>
477
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Experience (Yrs)</label>
478
- <input type="number" id="tab_exp" placeholder="e.g. 5" min="0" max="80" class="predict-input bg-white/60 border text-indigo-950">
479
  </div>
480
  <div>
481
- <label class="block text-[10px] font-black uppercase text-indigo-900/70 mb-1.5 ml-1">Drunk</label>
482
- <select id="tab_alcohol" class="predict-input bg-white/60 border text-indigo-950"><option value="No">No</option><option value="Yes">Yes</option></select>
 
 
 
483
  </div>
484
  </div>
485
  </div>
 
486
  </div>
487
 
488
- <div class="mt-8 pt-6 border-t border-indigo-200/50 flex justify-end">
489
- <button type="submit" id="predictBtn" class="w-full sm:w-auto px-8 py-4 rounded-2xl font-black uppercase tracking-widest text-xs bg-cyan-600 text-white shadow-lg hover:bg-cyan-500 active:scale-95 transition-all flex items-center justify-center gap-3">
490
- <span>Run Risk Simulation</span><i id="predictSpinner" class="fas fa-circle-notch fa-spin hidden"></i>
 
 
491
  </button>
492
  </div>
493
  </form>
494
  </div>
495
 
 
496
  <div id="predictiveResultView" class="hidden text-center animate-fade-in py-6">
497
- <h3 class="text-xs font-black uppercase tracking-[0.3em] text-indigo-800/50 mb-6">Prediction Outcome</h3>
 
498
  <div class="flex flex-col items-center justify-center gap-6">
499
- <div id="riskStatusCard" class="ios-glass-inner p-10 rounded-[32px] shadow-sm relative overflow-hidden w-full max-w-sm border">
500
- <div id="riskBadge" class="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl text-xs font-black mb-6 uppercase tracking-[0.2em] border shadow-sm text-white"><i id="riskIcon" class="fas fa-check-circle"></i><span id="riskLabelText">Low Risk</span></div>
501
- <h4 class="text-6xl font-black tracking-tighter text-indigo-950 dark:text-white mb-2" id="riskLevelResult">--</h4>
502
- <p class="text-[10px] font-black uppercase tracking-widest mt-4">Predicted Accident Severity</p>
 
 
 
 
503
  </div>
 
504
  <div class="flex gap-4 max-w-sm w-full mt-4">
505
- <button onclick="resetPredictModal()" class="flex-1 py-4 px-6 bg-cyan-600 text-white rounded-2xl font-black uppercase tracking-widest transition-all active:scale-95 text-xs flex justify-center items-center gap-2 shadow-xl hover:bg-cyan-500"><i class="fas fa-redo"></i> Retry</button>
506
- <button onclick="closePredictModal()" class="flex-1 py-4 px-6 bg-indigo-950 dark:bg-white/10 text-white rounded-2xl font-black uppercase tracking-widest transition-all active:scale-95 text-xs flex justify-center items-center gap-2 shadow-xl border">Dashboard</button>
 
 
 
 
507
  </div>
508
  </div>
509
  </div>
@@ -517,12 +703,20 @@
517
  const themeToggleBtn = document.getElementById('themeToggle');
518
  const htmlElement = document.documentElement;
519
 
520
- if (localStorage.theme === 'dark') { htmlElement.classList.add('dark'); }
521
- else { htmlElement.classList.remove('dark'); localStorage.theme = 'light'; }
 
 
 
 
522
 
523
  themeToggleBtn.addEventListener('click', () => {
524
  htmlElement.classList.toggle('dark');
525
- localStorage.theme = htmlElement.classList.contains('dark') ? 'dark' : 'light';
 
 
 
 
526
  });
527
 
528
  window.addEventListener('load', () => {
@@ -531,7 +725,9 @@
531
  if(splash) {
532
  splash.style.opacity = '0';
533
  splash.style.transform = 'scale(1.05)';
534
- setTimeout(() => { splash.style.display = 'none'; }, 700);
 
 
535
  }
536
  }, 1800);
537
  });
@@ -542,9 +738,21 @@
542
 
543
  function openIpCamModal() { document.getElementById('ipCamModal').classList.remove('hidden'); }
544
  function closeIpCamModal() { document.getElementById('ipCamModal').classList.add('hidden'); }
545
- function openPredictModal() { document.getElementById('predictiveModal').classList.remove('hidden'); document.body.style.overflow = 'hidden'; }
546
- function closePredictModal() { document.getElementById('predictiveModal').classList.add('hidden'); document.body.style.overflow = ''; document.getElementById('tabularForm').reset(); resetPredictModal(); }
547
- function resetPredictModal() { document.getElementById('predictiveResultView').classList.add('hidden'); document.getElementById('predictiveFormView').classList.remove('hidden'); }
 
 
 
 
 
 
 
 
 
 
 
 
548
 
549
  async function connectIpCam() {
550
  const url = document.getElementById('ipCamUrl').value;
@@ -563,6 +771,7 @@
563
  async function startSession(payload, endpoint, isFormData=false) {
564
  document.getElementById('uploadSection').classList.add('hidden');
565
  document.getElementById('results').classList.remove('hidden');
 
566
  document.getElementById('labelText').innerText = "Initializing Stream...";
567
 
568
  const opts = { method: 'POST' };
@@ -573,35 +782,35 @@
573
  const data = await res.json();
574
  streamId = data.stream_id;
575
 
 
576
  if(document.getElementById('vLoc')) document.getElementById('vLoc').innerText = data.location || "--";
577
  if(document.getElementById('vWx')) document.getElementById('vWx').innerText = data.weather || "--";
578
  if(document.getElementById('vTime')) document.getElementById('vTime').innerText = data.time || "--";
579
 
580
- // Initialize Player UI & Overlay
581
  document.getElementById('previewImg').classList.remove('hidden');
582
- document.getElementById('inVideoControls').classList.remove('hidden');
583
- document.getElementById('inVideoControls').classList.add('flex');
584
 
585
- // Reset AI Tracking toggles
586
- document.getElementById('tBtnOverlay').classList.remove('opacity-50', 'text-rose-400');
587
- document.getElementById('tBtnOverlay').classList.add('text-rose-400');
588
- document.getElementById('oBtnOverlay').classList.add('opacity-50', 'text-white/50');
589
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-red-500 animate-pulse shadow-[0_0_8px_red]"></span> LIVE AI FEED';
590
 
591
  document.getElementById('previewImg').src = `/video_feed/${streamId}?loc=${encodeURIComponent(data.location)}&t=${Date.now()}`;
 
 
592
  isPaused = false;
593
- document.getElementById('playPauseIcon').className = 'fas fa-pause text-lg sm:text-xl';
594
 
595
  if(poller) clearInterval(poller);
596
  poller = setInterval(update, 1000);
597
  }
598
 
 
599
  async function goTracking() {
600
- document.getElementById('oBtnOverlay').classList.add('opacity-50', 'text-white/50');
601
- document.getElementById('oBtnOverlay').classList.remove('text-white');
602
- document.getElementById('tBtnOverlay').classList.remove('opacity-50');
603
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-red-500 animate-pulse shadow-[0_0_8px_red]"></span> LIVE AI FEED';
604
-
605
  await fetch(`/video_control/${streamId}`, {
606
  method: 'POST',
607
  headers: {'Content-Type': 'application/json'},
@@ -610,11 +819,9 @@
610
  }
611
 
612
  async function goOriginal() {
613
- document.getElementById('tBtnOverlay').classList.add('opacity-50');
614
- document.getElementById('oBtnOverlay').classList.remove('opacity-50', 'text-white/50');
615
- document.getElementById('oBtnOverlay').classList.add('text-white');
616
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-blue-500 shadow-[0_0_8px_blue]"></span> RAW FEED';
617
-
618
  await fetch(`/video_control/${streamId}`, {
619
  method: 'POST',
620
  headers: {'Content-Type': 'application/json'},
@@ -625,16 +832,12 @@
625
  async function togglePlayPause() {
626
  if(!streamId) return;
627
  isPaused = !isPaused;
628
- document.getElementById('playPauseIcon').className = isPaused ? 'fas fa-play text-lg sm:text-xl ml-1' : 'fas fa-pause text-lg sm:text-xl';
629
  await fetch(`/video_control/${streamId}`, {
630
  method: 'POST',
631
  headers: {'Content-Type': 'application/json'},
632
- body: JSON.stringify({action: 'pause', value: isPaused}) // Trigger pause based on state
633
  });
634
- // Additional call if playing
635
- if(!isPaused) {
636
- await fetch(`/video_control/${streamId}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({action: 'play'}) });
637
- }
638
  }
639
 
640
  async function skipVideo(seconds) {
@@ -651,6 +854,7 @@
651
  const container = document.getElementById('progressBarContainer');
652
  const rect = container.getBoundingClientRect();
653
  const pos = Math.max(0, Math.min(1, (event.clientX - rect.left) / rect.width));
 
654
  await fetch(`/video_control/${streamId}`, {
655
  method: 'POST',
656
  headers: {'Content-Type': 'application/json'},
@@ -668,15 +872,17 @@
668
 
669
  document.getElementById('snapshotImg').src = c.toDataURL('image/jpeg');
670
  document.getElementById('snapshotContainer').classList.remove('hidden');
671
- document.getElementById('inVideoControls').classList.add('hidden');
672
  document.getElementById('liveBadgeContainer').classList.add('hidden');
 
673
  }
674
  }
675
 
676
  function closeSnapshot() {
677
  document.getElementById('snapshotContainer').classList.add('hidden');
678
- document.getElementById('inVideoControls').classList.remove('hidden');
679
  document.getElementById('liveBadgeContainer').classList.remove('hidden');
 
680
  }
681
 
682
  function fullscreenSnapshot() {
@@ -703,8 +909,7 @@
703
  document.getElementById('severityLevel').innerText = data.severity || "--";
704
 
705
  if (data.progress !== undefined) {
706
- if (data.progress >= 100) { document.getElementById('progressFill').style.width = `100%`; }
707
- else { document.getElementById('progressFill').style.width = `${data.progress}%`; }
708
  }
709
 
710
  const statusCard = document.getElementById('statusCard');
@@ -738,6 +943,7 @@
738
  } catch(e) {}
739
  }
740
 
 
741
  function resetApp() {
742
  if(poller) clearInterval(poller);
743
  streamId = null;
@@ -747,12 +953,15 @@
747
  document.getElementById('emergencyBanner').classList.add('hidden');
748
  document.getElementById('alprSection').classList.add('hidden');
749
  document.getElementById('progressFill').style.width = "0%";
750
- document.getElementById('inVideoControls').classList.add('hidden');
 
751
 
 
752
  document.getElementById('fileInput').value = "";
753
  document.getElementById('uploadForm').reset();
754
  document.getElementById('ipCamUrl').value = "";
755
 
 
756
  document.getElementById('confVal').innerText = "0";
757
  document.getElementById('severityLevel').innerText = "--";
758
  document.getElementById('cnnBar').style.width = "0%";
@@ -783,6 +992,7 @@
783
  Vehicle_Type: document.getElementById('tab_vehicle').value,
784
  Driver_Age: document.getElementById('tab_age').value,
785
  Driver_Experience: document.getElementById('tab_exp').value,
 
786
  Driver_Alcohol: document.getElementById('tab_alcohol').value === "Yes" ? 1.0 : 0.0
787
  };
788
 
@@ -806,6 +1016,7 @@
806
  riskCard.className = 'ios-glass-inner p-10 rounded-[32px] shadow-sm dark:shadow-lg relative overflow-hidden w-full max-w-sm border';
807
  riskBadge.className = 'inline-flex items-center gap-2 px-5 py-2.5 rounded-xl text-xs font-black mb-6 uppercase tracking-[0.2em] border shadow-sm text-white';
808
 
 
809
  if(data.status === "Major") {
810
  riskCard.classList.add('border-red-500', 'bg-red-50/10', 'dark:bg-red-900/20');
811
  riskBadge.classList.add('bg-red-500', 'border-red-400');
 
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
  <title>CrashVision AI - Accident Detection</title>
7
 
8
+ <!-- ========================================== -->
9
  <!-- 📱 MOBILE APP & HOME SCREEN ICONS SETUP 📱 -->
10
+ <!-- ========================================== -->
11
  <meta name="apple-mobile-web-app-capable" content="yes">
12
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
13
  <meta name="apple-mobile-web-app-title" content="CrashVision">
14
  <meta name="mobile-web-app-capable" content="yes">
15
  <meta name="theme-color" content="#1e1b4b">
16
 
17
+ <!-- Custom App Icon from Static Folder -->
18
  <link rel="icon" type="image/png" sizes="192x192" href="{{ url_for('static', filename='logo.PNG') }}">
19
  <link rel="apple-touch-icon" href="{{ url_for('static', filename='logo.PNG') }}">
20
+
21
+ <!-- Inline PWA Manifest for Android Home Screen Icon Mapping -->
22
  <link rel="manifest" href='data:application/manifest+json;utf8,{"name":"CrashVision AI","short_name":"CrashVision","start_url":"/","display":"standalone","background_color":"#F4F4F9","theme_color":"#1e1b4b","icons":[{"src":"/static/logo.PNG","sizes":"192x192","type":"image/png"},{"src":"/static/logo.PNG","sizes":"512x512","type":"image/png"}]}'>
23
+ <!-- ========================================== -->
24
 
25
+ <!-- Tailwind CSS -->
26
  <script src="https://cdn.tailwindcss.com"></script>
27
  <script>
28
  tailwind.config = {
29
  darkMode: 'class',
30
  theme: {
31
  extend: {
32
+ fontFamily: {
33
+ sans: ['-apple-system', 'BlinkMacSystemFont', 'San Francisco', 'Inter', 'sans-serif'],
34
+ },
35
+ animation: {
36
+ 'blob': 'blob 10s infinite',
37
+ 'pulse-glow': 'pulse-glow 3s infinite',
38
+ },
39
  keyframes: {
40
  blob: {
41
  '0%': { transform: 'translate(0px, 0px) scale(1)' },
42
  '33%': { transform: 'translate(40px, -60px) scale(1.2)' },
43
  '66%': { transform: 'translate(-30px, 30px) scale(0.8)' },
44
  '100%': { transform: 'translate(0px, 0px) scale(1)' },
45
+ },
46
+ 'pulse-glow': {
47
+ '0%, 100%': { opacity: 0.6, transform: 'scale(1)' },
48
+ '50%': { opacity: 1, transform: 'scale(1.05)' },
49
  }
50
  }
51
  }
52
  }
53
  }
54
  </script>
55
+ <!-- FontAwesome -->
56
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
57
  <style>
58
+ body {
59
+ background-color: #F4F4F9;
60
+ -webkit-font-smoothing: antialiased;
61
+ transition: background-color 0.5s ease, background-image 0.5s ease;
62
+ }
63
+ .dark body {
64
+ background-color: #151518;
65
+ background-image: linear-gradient(135deg, #151518 0%, #2a1f3d 50%, #101012 100%);
66
+ background-attachment: fixed;
67
+ }
68
+
69
+ .modal-bg {
70
+ background-color: #F4F4F9;
71
+ }
72
+ .dark .modal-bg {
73
+ background-color: #151518;
74
+ background-image: linear-gradient(135deg, #151518 0%, #2a1f3d 50%, #101012 100%);
75
+ background-attachment: fixed;
76
+ }
77
+
78
+ .ios-glass {
79
+ background: rgba(255, 255, 255, 0.45);
80
+ backdrop-filter: blur(40px) saturate(200%);
81
+ -webkit-backdrop-filter: blur(40px) saturate(200%);
82
+ border: 1.5px solid rgba(255, 255, 255, 0.9);
83
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5), 0 8px 32px rgba(0, 0, 0, 0.08);
84
+ transition: all 0.5s ease;
85
+ }
86
+ .dark .ios-glass {
87
+ background: rgba(20, 20, 25, 0.35);
88
+ border: 1px solid rgba(255, 255, 255, 0.15);
89
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05), 0 8px 32px rgba(0, 0, 0, 0.6);
90
+ backdrop-filter: blur(40px) saturate(200%);
91
+ -webkit-backdrop-filter: blur(40px) saturate(200%);
92
+ }
93
+ .ios-glass-inner {
94
+ background: rgba(255, 255, 255, 0.5);
95
+ border: 1px solid rgba(255, 255, 255, 0.8);
96
+ transition: all 0.5s ease;
97
+ }
98
+ .dark .ios-glass-inner {
99
+ background: rgba(255, 255, 255, 0.06);
100
+ border: 1px solid rgba(255, 255, 255, 0.12);
101
+ }
102
+ .bg-mesh {
103
+ background-size: 40px 40px;
104
+ background-image:
105
+ linear-gradient(to right, rgba(100, 100, 150, 0.06) 1px, transparent 1px),
106
+ linear-gradient(to bottom, rgba(100, 100, 150, 0.06) 1px, transparent 1px);
107
+ }
108
+ .dark .bg-mesh {
109
+ background-image:
110
+ linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px),
111
+ linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
112
+ }
113
  ::-webkit-scrollbar { width: 6px; }
114
  ::-webkit-scrollbar-track { background: transparent; }
115
  ::-webkit-scrollbar-thumb { background: rgba(156, 163, 175, 0.5); border-radius: 10px; }
116
  .dark ::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); }
117
+
118
+ .predict-input {
119
+ width: 100%;
120
+ padding: 0.75rem 1rem;
121
+ border-radius: 0.75rem;
122
+ font-size: 0.875rem;
123
+ font-weight: 600;
124
+ outline: none;
125
+ transition: all 0.3s ease;
126
+ }
127
+
128
+ @keyframes jiggle {
129
+ 0%, 100% { transform: scale3d(1, 1, 1); }
130
+ 30% { transform: scale3d(1.25, 0.75, 1); }
131
+ 40% { transform: scale3d(0.75, 1.25, 1); }
132
+ 50% { transform: scale3d(1.15, 0.85, 1); }
133
+ 65% { transform: scale3d(0.95, 1.05, 1); }
134
+ 75% { transform: scale3d(1.05, 0.95, 1); }
135
+ }
136
  .animate-jiggle { animation: jiggle 1.5s ease-in-out infinite; transform-origin: bottom; }
137
  </style>
138
  </head>
139
  <body class="relative min-h-screen transition-colors duration-500 overflow-x-hidden">
140
 
 
141
  <div id="appSplashScreen" class="fixed inset-0 z-[100] flex flex-col items-center justify-center bg-[#F4F4F9] dark:bg-[#151518] transition-all duration-700 ease-in-out">
142
  <div class="mb-8">
143
  <svg class="w-24 h-24 text-indigo-700 dark:text-purple-400 drop-shadow-xl" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
 
154
  </div>
155
  <h1 class="text-4xl font-black tracking-tight text-indigo-950 dark:text-white drop-shadow-sm">CrashVision AI</h1>
156
  <p class="text-xs font-black uppercase tracking-[0.3em] text-indigo-500 mt-3">Initializing Systems</p>
157
+
158
  <div class="mt-8 flex gap-3">
159
  <div class="w-3 h-3 rounded-md bg-fuchsia-500 animate-jiggle" style="animation-delay: 0s;"></div>
160
  <div class="w-3 h-3 rounded-md bg-indigo-500 animate-jiggle" style="animation-delay: 0.15s;"></div>
 
185
  <!-- Emergency Dispatch Banner -->
186
  <div id="emergencyBanner" class="hidden fixed top-0 left-0 w-full bg-red-600 text-white py-3 px-4 z-50 flex items-center justify-center gap-4 animate-pulse shadow-lg shadow-red-500/50">
187
  <i class="fas fa-exclamation-triangle text-xl"></i>
188
+ <span class="font-black uppercase tracking-widest text-sm sm:text-base">Major Collision Detected. Automated SOS Dispatched to Emergency Services.</span>
189
  <i class="fas fa-exclamation-triangle text-xl"></i>
190
  </div>
191
 
 
205
  </div>
206
 
207
  <div class="text-center">
208
+ <h1 class="text-3xl sm:text-5xl font-black tracking-tight leading-tight text-indigo-700 dark:text-purple-400 drop-shadow-sm transition-colors duration-500">
209
+ CrashVision AI
210
+ </h1>
211
+ <span class="text-[9px] sm:text-xs text-indigo-800/60 dark:text-purple-200 font-black tracking-[0.4em] uppercase mt-2 sm:mt-3 block opacity-90 transition-colors duration-500">
212
+ Road Safety Analytics
213
+ </span>
214
  </div>
215
  </header>
216
 
217
  <main class="relative z-10 container mx-auto pb-12 px-4 sm:px-6 lg:px-8 max-w-6xl">
218
  <div class="w-full transition-all duration-500">
219
 
220
+ <!-- SECTION 1: HOME AREA (Upload + Risk Island) -->
221
  <div id="uploadSection" class="flex flex-col gap-8 sm:gap-6">
222
+
223
+ <!-- Incident Analysis Island (Video/IP) -->
224
  <div class="ios-glass rounded-[32px] sm:rounded-[40px] px-6 py-10 sm:p-10 md:p-16 text-center shadow-lg">
225
  <div class="max-w-3xl mx-auto">
226
+ <h2 class="text-2xl sm:text-3xl font-extrabold mb-2 sm:mb-4 tracking-tight text-indigo-950 dark:text-white">
227
+ Incident Analysis
228
+ </h2>
229
+ <p class="text-indigo-800/60 dark:text-purple-100 mb-6 sm:mb-10 text-xs sm:text-base leading-relaxed font-semibold">
230
+ Input surveillance streams or connect a live IP camera.
231
+ </p>
232
 
233
  <div class="grid grid-cols-2 gap-3 sm:gap-6 justify-center">
234
+ <!-- IP Camera / Stream -->
235
  <div class="relative group cursor-pointer h-full" onclick="openIpCamModal()">
236
+ <div class="block w-full h-full py-10 px-4 sm:p-10 border-2 border-dashed border-rose-400/30 dark:border-rose-400/40 rounded-[20px] sm:rounded-[32px] ios-glass-inner hover:bg-rose-50/70 dark:hover:bg-rose-900/20 transition-all group-hover:border-rose-500/50 dark:group-hover:border-rose-400/60 flex flex-col items-center justify-center">
237
  <div class="w-16 h-16 sm:w-20 sm:h-20 bg-rose-50 dark:bg-rose-500/20 rounded-[14px] sm:rounded-3xl flex items-center justify-center mb-3 sm:mb-4 group-hover:scale-110 transition-transform duration-500 shadow-sm border border-rose-100 dark:border-rose-400/30">
238
  <i class="fas fa-satellite-dish text-2xl sm:text-3xl text-rose-600 dark:text-rose-300"></i>
239
  </div>
240
  <span class="block text-sm sm:text-xl font-black text-rose-900 dark:text-rose-100 mb-0 sm:mb-1 leading-tight">Live IP</span>
241
+ <span class="block text-[9px] sm:text-xs text-rose-600/60 dark:text-rose-300 font-bold uppercase tracking-widest hidden sm:block">Connect RTSP</span>
242
  </div>
243
  </div>
244
 
245
+ <!-- File Upload -->
246
  <form id="uploadForm" class="relative group cursor-pointer h-full">
247
  <input type="file" id="fileInput" name="file" accept="image/png, image/jpeg, image/jpg, video/mp4" class="hidden">
248
+ <label for="fileInput" class="block w-full h-full py-10 px-4 sm:p-10 border-2 border-dashed border-indigo-400/30 dark:border-purple-400/40 rounded-[20px] sm:rounded-[32px] ios-glass-inner hover:bg-white/70 dark:hover:bg-white/5 transition-all cursor-pointer group-hover:border-indigo-500/50 dark:group-hover:border-purple-300/60 flex flex-col items-center justify-center">
249
  <div class="w-16 h-16 sm:w-20 sm:h-20 bg-indigo-50 dark:bg-white/10 rounded-[14px] sm:rounded-3xl flex items-center justify-center mb-3 sm:mb-4 group-hover:scale-110 transition-transform duration-500 shadow-sm border border-indigo-100 dark:border-white/20">
250
  <i class="fas fa-arrow-up-from-bracket text-2xl sm:text-3xl text-indigo-600 dark:text-purple-200"></i>
251
  </div>
 
257
  </div>
258
  </div>
259
 
260
+ <!-- Traffic Risk Predictor Small Clickable Island -->
261
  <div class="relative group cursor-pointer mt-2 mb-2" onclick="openPredictModal()">
262
+ <div class="ios-glass p-7 sm:p-6 rounded-[32px] hover:-translate-y-1 transition-transform duration-300 shadow-sm border border-cyan-400/30 hover:border-cyan-500/50 dark:border-cyan-500/20 dark:hover:border-cyan-400/40 flex items-center justify-between bg-gradient-to-r from-transparent to-cyan-50/30 dark:to-cyan-900/10">
263
  <div class="flex items-center gap-5">
264
+ <div class="w-16 h-16 sm:w-14 sm:h-14 rounded-2xl bg-cyan-100 dark:bg-cyan-500/20 flex items-center justify-center shadow-sm group-hover:scale-110 transition-transform duration-300 border border-cyan-200/50 dark:border-cyan-400/30">
265
  <i class="fas fa-chart-line text-cyan-600 dark:text-cyan-300 text-3xl sm:text-2xl"></i>
266
  </div>
267
  <div class="text-left">
 
269
  <p class="text-[10px] sm:text-[10px] font-bold text-indigo-800/60 dark:text-purple-200 uppercase tracking-widest mt-1">Run Tabular AI Simulations</p>
270
  </div>
271
  </div>
272
+ <div class="w-12 h-12 sm:w-10 sm:h-10 rounded-full bg-indigo-900/5 dark:bg-white/5 flex items-center justify-center group-hover:bg-cyan-100 dark:group-hover:bg-cyan-500/30 transition-colors">
273
+ <i class="fas fa-arrow-right text-indigo-400 dark:text-purple-300 group-hover:text-cyan-600 dark:group-hover:text-cyan-100 text-base sm:text-sm"></i>
274
  </div>
275
  </div>
276
  </div>
277
 
278
+ <!-- 3 Columns Architecture Features -->
279
  <div class="grid grid-cols-1 md:grid-cols-3 gap-6 text-left">
280
  <div class="ios-glass p-6 rounded-[32px] hover:-translate-y-1 transition-transform duration-300 shadow-sm cursor-default">
281
+ <div class="w-12 h-12 rounded-2xl bg-indigo-100 dark:bg-white/10 flex items-center justify-center mb-5 border border-indigo-200/50 dark:border-white/10 shadow-sm">
282
+ <i class="fas fa-eye text-indigo-600 dark:text-purple-300 text-xl"></i>
283
+ </div>
284
  <h4 class="text-sm font-black uppercase tracking-wider text-indigo-950 dark:text-purple-50 mb-2">Spatial Engine</h4>
285
  <p class="text-xs text-indigo-800/70 dark:text-purple-100 leading-relaxed font-bold">YOLOv8 XAI Tracking overlays.</p>
286
  </div>
287
  <div class="ios-glass p-6 rounded-[32px] hover:-translate-y-1 transition-transform duration-300 shadow-sm cursor-default">
288
+ <div class="w-12 h-12 rounded-2xl bg-fuchsia-100 dark:bg-white/10 flex items-center justify-center mb-5 border border-fuchsia-200/50 dark:border-white/10 shadow-sm">
289
+ <i class="fas fa-layer-group text-fuchsia-600 dark:text-fuchsia-300 text-xl"></i>
290
+ </div>
291
  <h4 class="text-sm font-black uppercase tracking-wider text-indigo-950 dark:text-purple-50 mb-2">Temporal Engine</h4>
292
  <p class="text-xs text-indigo-800/70 dark:text-purple-100 leading-relaxed font-bold">3D-CNN models physical motion.</p>
293
  </div>
294
  <div class="ios-glass p-6 rounded-[32px] hover:-translate-y-1 transition-transform duration-300 shadow-sm cursor-default">
295
+ <div class="w-12 h-12 rounded-2xl bg-rose-100 dark:bg-white/10 flex items-center justify-center mb-5 border border-rose-200/50 dark:border-white/10 shadow-sm">
296
+ <i class="fas fa-bolt text-rose-600 dark:text-rose-300 text-xl"></i>
297
+ </div>
298
  <h4 class="text-sm font-black uppercase tracking-wider text-indigo-950 dark:text-purple-50 mb-2">Automated SOS</h4>
299
+ <p class="text-xs text-indigo-800/70 dark:text-purple-100 leading-relaxed font-bold">Dispatch triggered by SVM Ensemble.</p>
300
  </div>
301
  </div>
302
+
303
  </div>
304
 
305
+ <!-- SECTION 2: RESULTS DASHBOARD (Visual Detection) -->
306
  <div id="results" class="hidden ios-glass rounded-[40px] overflow-hidden shadow-2xl">
307
  <div class="grid grid-cols-1 lg:grid-cols-12 gap-0">
308
 
 
310
  <div class="lg:col-span-7 p-8 md:p-12 border-b lg:border-b-0 lg:border-r border-indigo-200/50 dark:border-white/10">
311
  <div class="flex justify-between items-center mb-6">
312
  <h3 class="text-xs font-black uppercase tracking-[0.3em] text-indigo-800/50 dark:text-purple-200">XAI Analytics Feed</h3>
313
+ <span class="px-4 py-1.5 text-[10px] font-black uppercase tracking-widest bg-white/60 dark:bg-white/10 rounded-full text-indigo-900 dark:text-white border border-indigo-200/50 dark:border-white/20 shadow-sm">Channel: CV-PRIME</span>
314
  </div>
315
 
316
+ <!-- Interactive Media Player Area (With Embedded Controls) -->
317
+ <div class="rounded-[32px] overflow-hidden shadow-2xl border border-white/50 dark:border-white/20 relative bg-black aspect-video flex items-center justify-center group">
318
+ <!-- Display Image -->
 
319
  <img id="previewImg" src="" class="w-full h-full object-contain z-10 hidden" alt="Video View">
320
 
321
  <!-- Snapshot Container Overlay -->
322
+ <div id="snapshotContainer" class="absolute inset-0 z-30 hidden bg-black flex items-center justify-center">
323
  <img id="snapshotImg" src="" class="w-full h-full object-contain">
324
+ <!-- Fullscreen / Close Controls -->
325
  <div class="absolute top-6 right-6 flex gap-3">
326
+ <button onclick="fullscreenSnapshot()" class="w-8 h-8 rounded-full bg-white/20 hover:bg-white/40 border border-white/40 text-white flex items-center justify-center transition-all shadow-lg backdrop-blur-md">
327
+ <i class="fas fa-expand"></i>
328
+ </button>
329
+ <button onclick="closeSnapshot()" class="w-8 h-8 rounded-full bg-red-500/80 hover:bg-red-500 border border-red-400 text-white flex items-center justify-center transition-all shadow-lg backdrop-blur-md">
330
+ <i class="fas fa-times"></i>
331
+ </button>
332
  </div>
333
+ <!-- Snapshot Tag -->
334
  <div class="absolute top-6 left-6 z-20">
335
  <span class="bg-black/60 backdrop-blur-xl text-white text-[10px] px-3 py-1.5 rounded-xl font-black uppercase tracking-widest border border-white/20 flex items-center gap-2">
336
  <i class="fas fa-camera text-blue-400"></i> CAPTURED SNAPSHOT
 
339
  </div>
340
 
341
  <!-- Live Tag -->
342
+ <div id="liveBadgeContainer" class="absolute top-6 left-6 z-20 transition-opacity duration-300 group-hover:opacity-0">
343
+ <span id="liveBadge" class="bg-black/60 backdrop-blur-xl text-white text-[10px] px-3 py-1.5 rounded-xl font-black uppercase tracking-widest border border-white/20 flex items-center gap-2">
344
  <span class="w-2 h-2 rounded-full bg-red-500 animate-pulse shadow-[0_0_8px_red]"></span> LIVE AI FEED
345
  </span>
346
  </div>
347
 
348
+ <!-- Integrated Video Controls Overlay -->
349
+ <div id="playerControlsOverlay" class="hidden absolute bottom-0 left-0 w-full p-4 sm:p-6 bg-gradient-to-t from-black/90 via-black/50 to-transparent z-40 transition-opacity duration-300 opacity-0 group-hover:opacity-100 flex-col gap-3">
350
 
351
  <!-- Progress Bar -->
352
+ <div class="w-full h-1.5 bg-white/30 rounded-full cursor-pointer relative" onclick="seekVideo(event)" id="progressBarContainer">
353
+ <div id="progressFill" class="absolute top-0 left-0 h-full bg-indigo-500 rounded-full pointer-events-none transition-all duration-300" style="width: 0%"></div>
354
  </div>
355
+
356
+ <!-- Bottom Control Row -->
357
+ <div class="flex items-center justify-between mt-2">
358
+ <!-- Playback -->
359
+ <div class="flex items-center gap-4">
360
+ <button onclick="skipVideo(-5)" class="text-white hover:text-indigo-400 transition-colors"><i class="fas fa-backward"></i></button>
361
+ <button onclick="togglePlayPause()" class="w-8 h-8 rounded-full bg-indigo-600 text-white flex items-center justify-center hover:scale-105 transition-transform">
362
+ <i id="playPauseIcon" class="fas fa-pause text-sm"></i>
363
+ </button>
364
+ <button onclick="skipVideo(5)" class="text-white hover:text-indigo-400 transition-colors"><i class="fas fa-forward"></i></button>
365
  </div>
366
 
367
+ <!-- Tools -->
368
+ <div class="flex items-center gap-2 sm:gap-3">
369
+ <button onclick="takeSnapshot()" class="px-3 py-1.5 rounded-lg text-[9px] sm:text-[10px] font-black uppercase text-white bg-white/20 hover:bg-white/30 backdrop-blur-md transition-all border border-white/10"><i class="fas fa-camera mr-1"></i> Snap</button>
370
+ <button onclick="goTracking()" id="tBtn" class="px-3 py-1.5 rounded-lg text-[9px] sm:text-[10px] font-black uppercase text-white bg-rose-600 shadow-lg shadow-rose-500/50 hover:bg-rose-500 transition-all opacity-50"><i class="fas fa-brain mr-1"></i> AI Box</button>
371
+ <button onclick="goOriginal()" id="oBtn" class="px-3 py-1.5 rounded-lg text-[9px] sm:text-[10px] font-black uppercase text-white bg-white/20 hover:bg-white/30 backdrop-blur-md transition-all border border-white/10"><i class="fas fa-eye mr-1"></i> Raw</button>
 
 
372
  </div>
373
  </div>
374
  </div>
 
419
  <div id="alprSection" class="hidden">
420
  <div class="flex justify-between items-end mb-3">
421
  <span class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-50 flex items-center gap-3">
422
+ <div class="w-8 h-8 rounded-xl bg-white/60 dark:bg-white/10 flex items-center justify-center border border-indigo-200/50 dark:border-white/20 shadow-sm">
423
+ <i class="fas fa-car-side text-indigo-600 dark:text-fuchsia-300 text-xs"></i>
424
+ </div>
425
  ALPR (License Plates)
426
  </span>
427
  </div>
 
431
  <div>
432
  <div class="flex justify-between items-end mb-3">
433
  <span class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-50 flex items-center gap-3">
434
+ <div class="w-8 h-8 rounded-xl bg-white/60 dark:bg-white/10 flex items-center justify-center border border-indigo-200/50 dark:border-white/20 shadow-sm">
435
+ <i class="fas fa-layer-group text-indigo-600 dark:text-fuchsia-300 text-xs"></i>
436
+ </div>
437
  Temporal (3D-CNN)
438
  </span>
439
  <span id="rcnnVal" class="font-black text-sm text-indigo-900 dark:text-white">0%</span>
 
445
  <div>
446
  <div class="flex justify-between items-end mb-3">
447
  <span class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-50 flex items-center gap-3">
448
+ <div class="w-8 h-8 rounded-xl bg-white/60 dark:bg-white/10 flex items-center justify-center border border-indigo-200/50 dark:border-white/20 shadow-sm">
449
+ <i class="fas fa-crosshairs text-amber-600 dark:text-amber-400 text-xs"></i>
450
+ </div>
451
  Spatial (YOLOv8 Max)
452
  </span>
453
  <span id="cnnVal" class="font-black text-sm text-indigo-900 dark:text-white">0%</span>
 
460
  </div>
461
 
462
  <div class="mt-8 flex gap-4">
463
+ <button onclick="resetApp()" class="flex-1 py-4 px-6 bg-indigo-950 dark:bg-purple-600 text-white rounded-2xl font-black uppercase tracking-widest transition-all active:scale-95 text-xs flex justify-center items-center gap-3 shadow-xl dark:shadow-purple-500/40 hover:opacity-90 dark:hover:bg-purple-500">
464
  <i class="fas fa-stop text-white"></i> End Session
465
  </button>
466
  </div>
 
474
  <div id="ipCamModal" class="hidden fixed inset-0 z-[60] flex items-center justify-center bg-indigo-950/60 dark:bg-black/80 backdrop-blur-md p-4">
475
  <div class="ios-glass p-8 rounded-[32px] max-w-md w-full shadow-2xl relative">
476
  <h3 class="text-2xl font-black text-indigo-950 dark:text-white mb-2">Connect IP Camera</h3>
477
+ <p class="text-sm font-bold text-indigo-800/60 dark:text-purple-200 mb-6">Enter the RTSP or HTTP stream URL for your surveillance camera.</p>
478
 
479
+ <input type="text" id="ipCamUrl" placeholder="e.g., http://192.168.1.5:8080/video" class="w-full px-5 py-4 rounded-xl border border-indigo-200 dark:border-white/20 bg-white/50 dark:bg-white/5 text-indigo-900 dark:text-white font-semibold outline-none focus:border-indigo-500 dark:focus:border-purple-400 mb-6 placeholder-indigo-300 dark:placeholder-white/30">
480
 
481
  <div class="flex gap-4">
482
+ <button onclick="closeIpCamModal()" class="flex-1 py-3 rounded-xl font-black uppercase tracking-widest text-xs bg-white dark:bg-white/10 text-indigo-900 dark:text-white border border-indigo-200 dark:border-white/20 shadow-sm hover:bg-gray-50 dark:hover:bg-white/20 transition-all">Cancel</button>
483
+ <button onclick="connectIpCam()" class="flex-1 py-3 rounded-xl font-black uppercase tracking-widest text-xs bg-rose-600 text-white shadow-lg shadow-rose-500/30 hover:bg-rose-500 transition-all">Connect</button>
484
  </div>
485
  </div>
486
  </div>
487
 
488
+ <!-- Predictive Analysis Form Modal (Overlay Screen) -->
489
  <div id="predictiveModal" class="hidden fixed inset-0 z-[60] modal-bg overflow-y-auto transition-colors duration-500">
490
+
491
+ <!-- Background Mesh & Animated Blobs to match Theme -->
492
  <div class="fixed inset-0 z-0 bg-mesh pointer-events-none"></div>
493
  <div class="fixed inset-0 z-0 overflow-hidden pointer-events-none">
494
+ <div class="absolute top-[10%] left-[20%] w-[35rem] h-[35rem] bg-cyan-400 dark:bg-cyan-500/20 rounded-full mix-blend-multiply dark:mix-blend-screen filter blur-[120px] dark:blur-[140px] opacity-20 dark:opacity-30 animate-blob"></div>
495
+ <div class="absolute bottom-[20%] right-[10%] w-[30rem] h-[30rem] bg-indigo-300 dark:bg-indigo-500/20 rounded-full mix-blend-multiply dark:mix-blend-screen filter blur-[120px] opacity-20 dark:opacity-25 animate-blob" style="animation-delay: 2s"></div>
496
  </div>
497
 
498
+ <!-- Back Button (Top Left) -->
499
+ <button onclick="closePredictModal()" class="fixed top-6 left-6 sm:top-8 sm:left-8 z-[70] w-10 h-10 rounded-full flex items-center justify-center hover:scale-105 active:scale-95 transition-all shadow-sm text-indigo-900 dark:text-purple-100 cursor-pointer bg-white/30 dark:bg-white/10 backdrop-blur-xl border border-white/40 dark:border-white/20">
500
+ <i class="fas fa-arrow-left text-sm"></i>
501
+ </button>
502
 
503
+ <!-- Main Content Wrapper -->
504
  <div class="relative z-10 min-h-screen flex flex-col">
505
+
506
+ <!-- Header (Text Outside the Island) -->
507
  <div class="pt-20 sm:pt-24 pb-8 px-4 flex flex-col items-center justify-center text-center">
508
  <div class="mb-4 sm:mb-6 flex items-center justify-center group transition-all duration-500 hover:scale-110 drop-shadow-xl">
509
+ <div class="w-14 h-14 sm:w-16 sm:h-16 rounded-2xl bg-cyan-100 dark:bg-cyan-500/20 flex items-center justify-center border border-cyan-200/50 dark:border-cyan-400/30 shadow-sm relative overflow-hidden">
510
+ <i class="fas fa-chart-line text-cyan-600 dark:text-cyan-300 text-2xl sm:text-3xl z-10"></i>
511
+ </div>
512
  </div>
513
  <h2 class="text-3xl sm:text-4xl font-black tracking-tight text-indigo-950 dark:text-white mb-3">Accident Risk Predictor</h2>
514
+ <p class="text-indigo-800/60 dark:text-purple-200 text-xs sm:text-sm font-semibold max-w-xl mx-auto px-4">
515
+ Predict the probability of an accident using our trained Tabular AI model. Adjust the parameters below to run a simulation.
516
+ </p>
517
  </div>
518
 
519
+ <!-- Island Container (Smaller: max-w-4xl) -->
520
  <div class="container mx-auto px-4 pb-16 max-w-4xl flex-grow">
521
  <div class="ios-glass p-6 sm:p-10 rounded-[32px] sm:rounded-[40px] shadow-2xl w-full">
522
+
523
+ <!-- Form View -->
524
  <div id="predictiveFormView">
525
  <form id="tabularForm" onsubmit="submitPredictiveData(event)">
526
+ <!-- Restructured Grid: 2 Columns for 4 sections -->
527
  <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-6">
528
 
529
+ <!-- Group 1: Environment Island -->
530
+ <div class="ios-glass-inner p-5 sm:p-6 rounded-[24px] shadow-sm border border-white/50 dark:border-white/10 hover:bg-white/50 dark:hover:bg-white/5 transition-colors group">
531
+ <div class="flex items-center gap-3 mb-4 border-b border-indigo-100/50 dark:border-white/10 pb-3">
532
+ <div class="w-8 h-8 rounded-xl bg-cyan-100 dark:bg-cyan-500/20 flex items-center justify-center border border-cyan-200/50 dark:border-cyan-400/30 group-hover:scale-110 transition-transform">
533
+ <i class="fas fa-cloud-sun text-cyan-600 dark:text-cyan-300 text-xs"></i>
534
+ </div>
535
+ <h4 class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-200">Conditions</h4>
536
  </div>
537
  <div class="space-y-4">
538
  <div>
539
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Weather</label>
540
+ <select id="tab_weather" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-cyan-500 focus:ring-2 focus:ring-cyan-500/20 shadow-sm cursor-pointer">
541
+ <option value="">Unknown / Leave Blank</option>
542
+ <option value="Clear">Clear</option>
543
+ <option value="Rainy">Rainy</option>
544
+ <option value="Foggy">Foggy</option>
545
+ <option value="Snowy">Snowy</option>
546
+ </select>
547
  </div>
548
  <div>
549
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Light Cond.</label>
550
+ <select id="tab_light" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-cyan-500 focus:ring-2 focus:ring-cyan-500/20 shadow-sm cursor-pointer">
551
+ <option value="">Unknown / Leave Blank</option>
552
+ <option value="Daylight">Daylight</option>
553
+ <option value="Artificial Light">Artificial Light</option>
554
+ <option value="No Light">No Light</option>
555
+ </select>
556
  </div>
557
  <div>
558
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Time of Day</label>
559
+ <select id="tab_time" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-cyan-500 focus:ring-2 focus:ring-cyan-500/20 shadow-sm cursor-pointer">
560
+ <option value="">Unknown / Leave Blank</option>
561
+ <option value="Morning">Morning</option>
562
+ <option value="Afternoon">Afternoon</option>
563
+ <option value="Evening">Evening</option>
564
+ <option value="Night">Night</option>
565
+ </select>
566
  </div>
567
  </div>
568
  </div>
569
 
570
+ <!-- Group 2: Road Specs Island -->
571
+ <div class="ios-glass-inner p-5 sm:p-6 rounded-[24px] shadow-sm border border-white/50 dark:border-white/10 hover:bg-white/50 dark:hover:bg-white/5 transition-colors group">
572
+ <div class="flex items-center gap-3 mb-4 border-b border-indigo-100/50 dark:border-white/10 pb-3">
573
+ <div class="w-8 h-8 rounded-xl bg-rose-100 dark:bg-rose-500/20 flex items-center justify-center border border-rose-200/50 dark:border-rose-400/30 group-hover:scale-110 transition-transform">
574
+ <i class="fas fa-road text-rose-600 dark:text-rose-300 text-xs"></i>
575
+ </div>
576
+ <h4 class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-200">Road Specs</h4>
577
  </div>
578
  <div class="space-y-4">
579
  <div>
580
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Road Type</label>
581
+ <select id="tab_road_type" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-rose-500 focus:ring-2 focus:ring-rose-500/20 shadow-sm cursor-pointer">
582
+ <option value="City Road">City Road</option>
583
+ <option value="Highway">Highway</option>
584
+ <option value="Rural Road">Rural Road</option>
585
+ </select>
586
  </div>
587
  <div>
588
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Surface</label>
589
+ <select id="tab_road_cond" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-rose-500 focus:ring-2 focus:ring-rose-500/20 shadow-sm cursor-pointer">
590
+ <option value="Dry">Dry</option>
591
+ <option value="Wet">Wet</option>
592
+ <option value="Icy">Icy</option>
593
+ <option value="Under Construction">Under Construction</option>
594
+ </select>
595
  </div>
596
  <div>
597
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Speed Limit</label>
598
+ <input type="number" id="tab_speed" placeholder="e.g. 60" min="10" max="250" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-rose-500 focus:ring-2 focus:ring-rose-500/20 shadow-sm">
599
  </div>
600
  </div>
601
  </div>
602
 
603
+ <!-- Group 3: Traffic Details Island -->
604
+ <div class="ios-glass-inner p-5 sm:p-6 rounded-[24px] shadow-sm border border-white/50 dark:border-white/10 hover:bg-white/50 dark:hover:bg-white/5 transition-colors group">
605
+ <div class="flex items-center gap-3 mb-4 border-b border-indigo-100/50 dark:border-white/10 pb-3">
606
+ <div class="w-8 h-8 rounded-xl bg-amber-100 dark:bg-amber-500/20 flex items-center justify-center border border-amber-200/50 dark:border-amber-400/30 group-hover:scale-110 transition-transform">
607
+ <i class="fas fa-car-side text-amber-600 dark:text-amber-300 text-xs"></i>
608
+ </div>
609
+ <h4 class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-200">Traffic Data</h4>
610
  </div>
611
  <div class="space-y-4">
612
  <div>
613
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Density (0-5)</label>
614
+ <input type="number" id="tab_density" placeholder="e.g. 2" min="0" max="5" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-amber-500 focus:ring-2 focus:ring-amber-500/20 shadow-sm">
615
  </div>
616
  <div>
617
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Vehicles Inv.</label>
618
+ <input type="number" id="tab_vehicles" placeholder="e.g. 2" min="1" max="20" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-amber-500 focus:ring-2 focus:ring-amber-500/20 shadow-sm">
619
  </div>
620
  <div>
621
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Vehicle Type</label>
622
+ <select id="tab_vehicle" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-amber-500 focus:ring-2 focus:ring-amber-500/20 shadow-sm cursor-pointer">
623
+ <option value="Car">Car</option>
624
+ <option value="Truck">Truck</option>
625
+ <option value="Bus">Bus</option>
626
+ <option value="Motorcycle">Motorcycle</option>
627
+ </select>
628
  </div>
629
  </div>
630
  </div>
631
 
632
+ <!-- Group 4: Driver Metrics Island -->
633
+ <div class="ios-glass-inner p-5 sm:p-6 rounded-[24px] shadow-sm border border-white/50 dark:border-white/10 hover:bg-white/50 dark:hover:bg-white/5 transition-colors group">
634
+ <div class="flex items-center gap-3 mb-4 border-b border-indigo-100/50 dark:border-white/10 pb-3">
635
+ <div class="w-8 h-8 rounded-xl bg-fuchsia-100 dark:bg-fuchsia-500/20 flex items-center justify-center border border-fuchsia-200/50 dark:border-fuchsia-400/30 group-hover:scale-110 transition-transform">
636
+ <i class="fas fa-user text-fuchsia-600 dark:text-fuchsia-300 text-xs"></i>
637
+ </div>
638
+ <h4 class="font-black text-[11px] uppercase tracking-widest text-indigo-900 dark:text-purple-200">Driver Profile</h4>
639
  </div>
640
  <div class="space-y-4">
641
  <div>
642
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Driver Age</label>
643
+ <input type="number" id="tab_age" placeholder="e.g. 35" min="16" max="99" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-fuchsia-500 focus:ring-2 focus:ring-fuchsia-500/20 shadow-sm">
644
  </div>
645
  <div>
646
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Experience (Yrs)</label>
647
+ <input type="number" id="tab_exp" placeholder="e.g. 5" min="0" max="80" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-fuchsia-500 focus:ring-2 focus:ring-fuchsia-500/20 shadow-sm">
648
  </div>
649
  <div>
650
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Drunk</label>
651
+ <select id="tab_alcohol" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-fuchsia-500 focus:ring-2 focus:ring-fuchsia-500/20 shadow-sm cursor-pointer">
652
+ <option value="No">No</option>
653
+ <option value="Yes">Yes</option>
654
+ </select>
655
  </div>
656
  </div>
657
  </div>
658
+
659
  </div>
660
 
661
+ <!-- Submit Area -->
662
+ <div class="mt-8 pt-6 border-t border-indigo-200/50 dark:border-white/10 flex justify-end">
663
+ <button type="submit" id="predictBtn" class="w-full sm:w-auto px-8 py-4 rounded-2xl font-black uppercase tracking-widest text-xs bg-cyan-600 text-white shadow-lg shadow-cyan-500/40 hover:bg-cyan-500 active:scale-95 transition-all flex items-center justify-center gap-3">
664
+ <span>Run Risk Simulation</span>
665
+ <i id="predictSpinner" class="fas fa-circle-notch fa-spin hidden"></i>
666
  </button>
667
  </div>
668
  </form>
669
  </div>
670
 
671
+ <!-- Tabular Results View (Hidden by default) -->
672
  <div id="predictiveResultView" class="hidden text-center animate-fade-in py-6">
673
+ <h3 class="text-xs font-black uppercase tracking-[0.3em] text-indigo-800/50 dark:text-purple-200 mb-6">Prediction Outcome</h3>
674
+
675
  <div class="flex flex-col items-center justify-center gap-6">
676
+ <div id="riskStatusCard" class="ios-glass-inner p-10 rounded-[32px] shadow-sm dark:shadow-lg relative overflow-hidden w-full max-w-sm border border-indigo-200/50 dark:border-white/20">
677
+ <div id="riskBadge" class="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl text-xs font-black mb-6 uppercase tracking-[0.2em] border shadow-sm">
678
+ <i id="riskIcon" class="fas fa-check-circle"></i>
679
+ <span id="riskLabelText">Low Risk</span>
680
+ </div>
681
+
682
+ <h4 class="text-6xl font-black tracking-tighter text-indigo-950 dark:text-white mb-2 drop-shadow-sm" id="riskLevelResult">--</h4>
683
+ <p class="text-indigo-800/60 dark:text-purple-200 text-[10px] font-black uppercase tracking-widest mt-4">Predicted Accident Severity</p>
684
  </div>
685
+
686
  <div class="flex gap-4 max-w-sm w-full mt-4">
687
+ <button onclick="resetPredictModal()" class="flex-1 py-4 px-6 bg-cyan-600 text-white rounded-2xl font-black uppercase tracking-widest transition-all active:scale-95 text-xs flex justify-center items-center gap-2 shadow-xl shadow-cyan-500/30 hover:bg-cyan-500">
688
+ <i class="fas fa-redo text-white"></i> Retry
689
+ </button>
690
+ <button onclick="closePredictModal()" class="flex-1 py-4 px-6 bg-indigo-950 dark:bg-white/10 text-white rounded-2xl font-black uppercase tracking-widest transition-all active:scale-95 text-xs flex justify-center items-center gap-2 shadow-xl hover:opacity-90 border border-indigo-200/50 dark:border-white/20">
691
+ Dashboard
692
+ </button>
693
  </div>
694
  </div>
695
  </div>
 
703
  const themeToggleBtn = document.getElementById('themeToggle');
704
  const htmlElement = document.documentElement;
705
 
706
+ if (localStorage.theme === 'dark') {
707
+ htmlElement.classList.add('dark');
708
+ } else {
709
+ htmlElement.classList.remove('dark');
710
+ localStorage.theme = 'light';
711
+ }
712
 
713
  themeToggleBtn.addEventListener('click', () => {
714
  htmlElement.classList.toggle('dark');
715
+ if (htmlElement.classList.contains('dark')) {
716
+ localStorage.theme = 'dark';
717
+ } else {
718
+ localStorage.theme = 'light';
719
+ }
720
  });
721
 
722
  window.addEventListener('load', () => {
 
725
  if(splash) {
726
  splash.style.opacity = '0';
727
  splash.style.transform = 'scale(1.05)';
728
+ setTimeout(() => {
729
+ splash.style.display = 'none';
730
+ }, 700);
731
  }
732
  }, 1800);
733
  });
 
738
 
739
  function openIpCamModal() { document.getElementById('ipCamModal').classList.remove('hidden'); }
740
  function closeIpCamModal() { document.getElementById('ipCamModal').classList.add('hidden'); }
741
+
742
+ function openPredictModal() {
743
+ document.getElementById('predictiveModal').classList.remove('hidden');
744
+ document.body.style.overflow = 'hidden';
745
+ }
746
+ function closePredictModal() {
747
+ document.getElementById('predictiveModal').classList.add('hidden');
748
+ document.body.style.overflow = '';
749
+ document.getElementById('tabularForm').reset(); // Wipe Predictor Form Data
750
+ resetPredictModal(); // Push back to form view
751
+ }
752
+ function resetPredictModal() {
753
+ document.getElementById('predictiveResultView').classList.add('hidden');
754
+ document.getElementById('predictiveFormView').classList.remove('hidden');
755
+ }
756
 
757
  async function connectIpCam() {
758
  const url = document.getElementById('ipCamUrl').value;
 
771
  async function startSession(payload, endpoint, isFormData=false) {
772
  document.getElementById('uploadSection').classList.add('hidden');
773
  document.getElementById('results').classList.remove('hidden');
774
+
775
  document.getElementById('labelText').innerText = "Initializing Stream...";
776
 
777
  const opts = { method: 'POST' };
 
782
  const data = await res.json();
783
  streamId = data.stream_id;
784
 
785
+ // Set metadata without browser fallback
786
  if(document.getElementById('vLoc')) document.getElementById('vLoc').innerText = data.location || "--";
787
  if(document.getElementById('vWx')) document.getElementById('vWx').innerText = data.weather || "--";
788
  if(document.getElementById('vTime')) document.getElementById('vTime').innerText = data.time || "--";
789
 
790
+ // Instantly start UI logic
791
  document.getElementById('previewImg').classList.remove('hidden');
792
+ document.getElementById('playerControlsOverlay').classList.remove('hidden');
793
+ document.getElementById('playerControlsOverlay').classList.add('flex');
794
 
795
+ document.getElementById('tBtn').classList.add('opacity-50');
796
+ document.getElementById('oBtn').classList.remove('opacity-50');
 
 
797
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-red-500 animate-pulse shadow-[0_0_8px_red]"></span> LIVE AI FEED';
798
 
799
  document.getElementById('previewImg').src = `/video_feed/${streamId}?loc=${encodeURIComponent(data.location)}&t=${Date.now()}`;
800
+
801
+ // Reset pause state
802
  isPaused = false;
803
+ document.getElementById('playPauseIcon').className = 'fas fa-pause text-sm';
804
 
805
  if(poller) clearInterval(poller);
806
  poller = setInterval(update, 1000);
807
  }
808
 
809
+ // Toggles AI boxes dynamically on backend via API request
810
  async function goTracking() {
811
+ document.getElementById('tBtn').classList.add('opacity-50');
812
+ document.getElementById('oBtn').classList.remove('opacity-50');
 
813
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-red-500 animate-pulse shadow-[0_0_8px_red]"></span> LIVE AI FEED';
 
814
  await fetch(`/video_control/${streamId}`, {
815
  method: 'POST',
816
  headers: {'Content-Type': 'application/json'},
 
819
  }
820
 
821
  async function goOriginal() {
822
+ document.getElementById('oBtn').classList.add('opacity-50');
823
+ document.getElementById('tBtn').classList.remove('opacity-50');
 
824
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-blue-500 shadow-[0_0_8px_blue]"></span> RAW FEED';
 
825
  await fetch(`/video_control/${streamId}`, {
826
  method: 'POST',
827
  headers: {'Content-Type': 'application/json'},
 
832
  async function togglePlayPause() {
833
  if(!streamId) return;
834
  isPaused = !isPaused;
835
+ document.getElementById('playPauseIcon').className = isPaused ? 'fas fa-play text-sm' : 'fas fa-pause text-sm';
836
  await fetch(`/video_control/${streamId}`, {
837
  method: 'POST',
838
  headers: {'Content-Type': 'application/json'},
839
+ body: JSON.stringify({action: isPaused ? 'pause' : 'play'})
840
  });
 
 
 
 
841
  }
842
 
843
  async function skipVideo(seconds) {
 
854
  const container = document.getElementById('progressBarContainer');
855
  const rect = container.getBoundingClientRect();
856
  const pos = Math.max(0, Math.min(1, (event.clientX - rect.left) / rect.width));
857
+
858
  await fetch(`/video_control/${streamId}`, {
859
  method: 'POST',
860
  headers: {'Content-Type': 'application/json'},
 
872
 
873
  document.getElementById('snapshotImg').src = c.toDataURL('image/jpeg');
874
  document.getElementById('snapshotContainer').classList.remove('hidden');
875
+ document.getElementById('previewImg').classList.add('hidden');
876
  document.getElementById('liveBadgeContainer').classList.add('hidden');
877
+ document.getElementById('playerControlsOverlay').classList.add('hidden');
878
  }
879
  }
880
 
881
  function closeSnapshot() {
882
  document.getElementById('snapshotContainer').classList.add('hidden');
883
+ document.getElementById('previewImg').classList.remove('hidden');
884
  document.getElementById('liveBadgeContainer').classList.remove('hidden');
885
+ document.getElementById('playerControlsOverlay').classList.remove('hidden');
886
  }
887
 
888
  function fullscreenSnapshot() {
 
909
  document.getElementById('severityLevel').innerText = data.severity || "--";
910
 
911
  if (data.progress !== undefined) {
912
+ document.getElementById('progressFill').style.width = `${data.progress}%`;
 
913
  }
914
 
915
  const statusCard = document.getElementById('statusCard');
 
943
  } catch(e) {}
944
  }
945
 
946
+ // Entire UI is reset completely when leaving
947
  function resetApp() {
948
  if(poller) clearInterval(poller);
949
  streamId = null;
 
953
  document.getElementById('emergencyBanner').classList.add('hidden');
954
  document.getElementById('alprSection').classList.add('hidden');
955
  document.getElementById('progressFill').style.width = "0%";
956
+ document.getElementById('playerControlsOverlay').classList.add('hidden');
957
+ document.getElementById('playerControlsOverlay').classList.remove('flex');
958
 
959
+ // Wipe Form and Upload fields completely
960
  document.getElementById('fileInput').value = "";
961
  document.getElementById('uploadForm').reset();
962
  document.getElementById('ipCamUrl').value = "";
963
 
964
+ // Reset Diagnostics View Default State
965
  document.getElementById('confVal').innerText = "0";
966
  document.getElementById('severityLevel').innerText = "--";
967
  document.getElementById('cnnBar').style.width = "0%";
 
992
  Vehicle_Type: document.getElementById('tab_vehicle').value,
993
  Driver_Age: document.getElementById('tab_age').value,
994
  Driver_Experience: document.getElementById('tab_exp').value,
995
+ // Yes=1.0, No=0.0 mapped strictly here for the AI
996
  Driver_Alcohol: document.getElementById('tab_alcohol').value === "Yes" ? 1.0 : 0.0
997
  };
998
 
 
1016
  riskCard.className = 'ios-glass-inner p-10 rounded-[32px] shadow-sm dark:shadow-lg relative overflow-hidden w-full max-w-sm border';
1017
  riskBadge.className = 'inline-flex items-center gap-2 px-5 py-2.5 rounded-xl text-xs font-black mb-6 uppercase tracking-[0.2em] border shadow-sm text-white';
1018
 
1019
+ // Displaying labels directly instead of percentages
1020
  if(data.status === "Major") {
1021
  riskCard.classList.add('border-red-500', 'bg-red-50/10', 'dark:bg-red-900/20');
1022
  riskBadge.classList.add('bg-red-500', 'border-red-400');