MatteoScript commited on
Commit
d13a922
·
verified ·
1 Parent(s): f03556a

Update ar.html

Browse files
Files changed (1) hide show
  1. ar.html +79 -103
ar.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
6
- <title>AR Neural Link | Vertical Native</title>
7
 
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
@@ -75,13 +75,6 @@
75
  opacity: 0.4;
76
  }
77
 
78
- .tech-border {
79
- border: 1px solid var(--neon-green);
80
- box-shadow: 0 0 15px rgba(0, 255, 65, 0.15);
81
- background: rgba(0,0,0,0.85);
82
- backdrop-filter: blur(8px);
83
- }
84
-
85
  .a-enter-vr-button { display: none !important; }
86
 
87
  #custom-loader {
@@ -109,7 +102,7 @@
109
  }
110
  .loader-fill {
111
  height: 100%; background: var(--neon-green); width: 0%;
112
- transition: width 0.3s;
113
  box-shadow: 0 0 10px var(--neon-green);
114
  }
115
 
@@ -169,50 +162,50 @@
169
  <div class="flex flex-col">
170
  <span class="text-[10px] text-white/60 font-mono tracking-widest">SYSTEM_STATUS</span>
171
  <span id="sys-status" class="text-[#00ff41] font-bold text-lg tracking-wider animate-pulse">SCANNING...</span>
172
- <span class="text-[8px] text-white/40 font-mono mt-1">FPS: <span id="fps-counter">60</span> | LAT: 12ms</span>
173
  </div>
174
- <a href="./index.html" class="w-10 h-10 flex items-center justify-center border border-[#00ff41]/50 rounded-full bg-black/40 backdrop-blur-md active:scale-95 transition-transform">
 
175
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#00ff41" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
176
- </a>
177
  </div>
178
 
179
- <!-- MIRINO QUADRATO -->
180
  <div id="aim-overlay" class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col items-center justify-center transition-opacity duration-300">
181
- <!-- Frame QUADRATO -->
182
- <div class="relative w-[70vw] h-[70vw] max-w-[280px] max-h-[280px] border border-white/20 rounded-xl">
183
- <div class="absolute -top-1 -left-1 w-6 h-6 border-t-4 border-l-4 border-[#00ff41]"></div>
184
- <div class="absolute -top-1 -right-1 w-6 h-6 border-t-4 border-r-4 border-[#00ff41]"></div>
185
- <div class="absolute -bottom-1 -left-1 w-6 h-6 border-b-4 border-l-4 border-[#00ff41]"></div>
186
- <div class="absolute -bottom-1 -right-1 w-6 h-6 border-b-4 border-r-4 border-[#00ff41]"></div>
 
187
 
188
  <div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full flex items-center justify-center">
189
- <div class="w-12 h-[1px] bg-[#00ff41]/50"></div>
190
- <div class="h-12 w-[1px] bg-[#00ff41]/50 absolute"></div>
191
  </div>
192
  </div>
193
- <div class="mt-4 bg-black/60 backdrop-blur px-4 py-2 rounded border border-[#00ff41]/30">
194
- <p class="text-[#00ff41] text-xs font-bold tracking-widest uppercase">Inquadra il Marker</p>
195
  </div>
196
  </div>
197
 
198
- <!-- BOTTOM CONTROLS -->
199
- <div class="w-full px-6 pb-8 pointer-events-auto flex flex-col items-center bg-gradient-to-t from-black/90 to-transparent">
200
- <!-- Pulsante Audio -->
201
- <button id="audio-btn" class="w-full max-w-sm py-5 bg-[#00ff41]/10 border border-[#00ff41] text-[#00ff41] font-bold text-lg uppercase tracking-[0.2em] rounded active:bg-[#00ff41] active:text-black transition-all mb-3 flex items-center justify-center gap-3 backdrop-blur-md">
 
202
  <span>🔊</span>
203
  <span id="audio-text">Attiva Audio</span>
204
  </button>
205
 
206
- <!-- NUOVO: Pulsante Fallback -->
207
- <button id="fallback-btn" class="w-full max-w-sm py-4 bg-[#ff0055]/10 border border-[#ff0055] text-[#ff0055] font-bold text-sm uppercase tracking-[0.2em] rounded active:bg-[#ff0055] active:text-white transition-all mb-4 flex items-center justify-center gap-2 backdrop-blur-md">
208
  <span>⚠️</span>
209
- <span>Mostra Video (Fallback)</span>
210
  </button>
211
 
212
- <div class="text-[10px] text-white/40 font-mono text-center">
213
- <div>NEURAL_LINK v2.4.0 // VERTICAL_MODE</div>
214
- <div class="mt-1">Built with 🧠 & ☕ by a sleep-deprived dev</div>
215
- </div>
216
  </div>
217
  </div>
218
 
@@ -228,10 +221,14 @@
228
  <p class="text-white/60 text-xs mt-3 text-center">Il marker non è stato trovato. Usa questo player manuale.</p>
229
  </div>
230
 
231
- <!-- 5. AR SCENE - ULTRA MEGA STABILIZED (BEAST MODE) -->
232
- <!-- filterBeta: 10000 = smoothing ESTREMO, missTolerance: 100 = 3+ sec di grace period -->
 
 
 
 
233
  <a-scene
234
- mindar-image="imageTargetSrc: img/targets.mind; filterMinCF:0.0000001; filterBeta: 10000; uiLoading: no; uiScanning: no; missTolerance: 100; warmupTolerance: 1; maxTrack: 1"
235
  color-space="sRGB"
236
  renderer="colorManagement: true, physicallyCorrectLights, highRefreshRate: true, antialias: true"
237
  vr-mode-ui="enabled: false"
@@ -248,8 +245,7 @@
248
  <a-entity id="myVid"
249
  geometry="primitive: plane; width: 1.6; height: 0.9"
250
  material="src: #vid; shader: flat; transparent: true; opacity: 1"
251
- position="0 0 0"
252
- animation__smooth="property: position; dur: 200; easing: easeOutQuad; loop: false">
253
  </a-entity>
254
 
255
  <!-- Cornice Cyberpunk 16:9 -->
@@ -265,14 +261,14 @@
265
  <a-plane position="-0.77 0.41 0.01" width="0.15" height="0.03" color="white" material="shader: flat; opacity: 0.9"></a-plane>
266
  <a-plane position="0.77 -0.41 0.01" width="0.15" height="0.03" color="white" material="shader: flat; opacity: 0.9"></a-plane>
267
 
268
- <a-text value="INNOVATION_LAB_DEV" color="#00ff41" align="center" width="1.5" position="0 -0.6 0.01"
269
  font="https://cdn.aframe.io/fonts/Roboto-msdf.json">
270
  <a-animation attribute="opacity" from="0.3" to="1" dur="800" direction="alternate" repeat="indefinite"></a-animation>
271
  </a-text>
272
  </a-entity>
273
  </a-scene>
274
 
275
- <!-- 6. LOGIC + NERD EASTER EGGS -->
276
  <script>
277
  const video = document.querySelector("#vid");
278
  const target = document.querySelector("#example-target");
@@ -295,101 +291,95 @@
295
  let smoothPositionX = 0;
296
  let smoothPositionY = 0;
297
  let smoothPositionZ = 0;
298
- const SMOOTHING_FACTOR = 0.5; // 5% update per frame = ultra smooth
 
 
 
 
299
 
300
- // CUSTOM SMOOTHING LAYER - Questo è il segreto!
301
  const myVidEntity = document.querySelector("#myVid");
302
- let lastPosition = {x: 0, y: 0, z: 0};
303
 
304
  // Applica smoothing custom ogni frame
305
  setInterval(() => {
306
  if(myVidEntity && target.object3D.visible) {
307
  const currentPos = target.object3D.position;
308
 
309
- // Lerp (Linear interpolation) per smooth movement
310
  smoothPositionX += (currentPos.x - smoothPositionX) * SMOOTHING_FACTOR;
311
  smoothPositionY += (currentPos.y - smoothPositionY) * SMOOTHING_FACTOR;
312
  smoothPositionZ += (currentPos.z - smoothPositionZ) * SMOOTHING_FACTOR;
313
 
314
- // Applica la posizione smoothed al target
315
- if(Math.abs(currentPos.x - lastPosition.x) > 0.001 ||
316
- Math.abs(currentPos.y - lastPosition.y) > 0.001 ||
317
- Math.abs(currentPos.z - lastPosition.z) > 0.001) {
318
- target.object3D.position.set(smoothPositionX, smoothPositionY, smoothPositionZ);
319
- lastPosition = {x: smoothPositionX, y: smoothPositionY, z: smoothPositionZ};
320
- }
321
  }
322
- }, 16); // 60fps
323
 
324
- // Easter Egg 1: Fake FPS Counter
325
  setInterval(() => {
326
- const fakeFps = Math.floor(Math.random() * 3) + 58;
327
  fpsCounter.innerText = fakeFps;
328
- }, 500);
329
 
330
- // Console Easter Egg
331
- console.log("%c⚡ NEURAL LINK SYSTEM INITIALIZED", "color: #00ff41; font-size: 20px; font-weight: bold;");
332
- console.log("%cIf you're reading this, you're a true nerd 🤓", "color: #fff; font-size: 12px;");
333
- console.log("%c// TODO: Add more bugs for job security", "color: #666; font-style: italic;");
334
-
335
- // Loading con messaggi nerd
336
  const nerdMessages = [
337
- "Compiling shaders...",
338
- "Downloading RAM...",
339
- "Adjusting flux capacitor...",
340
- "Hacking the mainframe...",
341
- "Dividing by zero...",
342
- "Reticulating splines..."
343
  ];
344
  let msgIndex = 0;
345
 
 
346
  const loadInterval = setInterval(() => {
347
- loadProgress += 2;
 
 
348
  if(loadProgress > 100) loadProgress = 100;
349
- loadingPercent.innerText = loadProgress + "%";
350
  progressBar.style.width = loadProgress + "%";
351
 
352
- if(loadProgress % 15 === 0 && msgIndex < nerdMessages.length) {
353
  document.querySelector('#load-msg').innerText = nerdMessages[msgIndex];
354
  msgIndex++;
355
  }
356
 
357
  if(loadProgress >= 100) {
358
  clearInterval(loadInterval);
359
- document.querySelector('#load-msg').innerText = "System ready. Let's hack reality.";
360
  }
361
- }, 30);
362
 
363
  // AR PRONTA
364
  scene.addEventListener("arReady", () => {
365
- console.log("%c✅ AR SYSTEM ONLINE", "color: #00ff41; font-weight: bold;");
366
- setTimeout(() => {
367
- loader.style.opacity = "0";
368
- setTimeout(() => loader.style.display = "none", 500);
369
- }, 500);
370
- });
371
-
372
- // ERROR HANDLING
373
- scene.addEventListener("arError", (ev) => {
374
- console.error("💀 FATAL ERROR:", ev);
375
- alert("⚠️ Camera Access Denied!\n\nPlease grant camera permissions or check if another app is using it.\n\n(Yes, we need it. No, we won't spy on you. Probably.)");
376
  });
377
 
378
  // TARGET FOUND
379
  target.addEventListener("targetFound", () => {
380
- console.log("🎯 TARGET ACQUIRED");
381
  video.play();
382
- statusText.innerText = "LOCKED_ON";
383
  statusText.style.color = "#fff";
384
  statusText.classList.remove("animate-pulse");
385
  aimOverlay.style.opacity = "0";
386
-
387
- if(navigator.vibrate) navigator.vibrate([30, 10, 30]);
388
  });
389
 
390
  // TARGET LOST
391
  target.addEventListener("targetLost", () => {
392
- console.log("❌ TARGET LOST");
393
  video.pause();
394
  statusText.innerText = "SEARCHING...";
395
  statusText.style.color = "#00ff41";
@@ -407,8 +397,6 @@
407
  audioBtn.classList.add("bg-[#00ff41]", "text-black");
408
  audioBtn.classList.remove("bg-[#00ff41]/10", "text-[#00ff41]");
409
 
410
- console.log("🔊 Audio stream activated");
411
-
412
  if(navigator.vibrate) navigator.vibrate(50);
413
 
414
  setTimeout(() => {
@@ -422,7 +410,6 @@
422
  fallbackBtn.addEventListener('click', () => {
423
  fallbackPlayer.style.display = 'block';
424
  fallbackVideo.play();
425
- console.log("🆘 FALLBACK MODE ACTIVATED");
426
  if(navigator.vibrate) navigator.vibrate(100);
427
  });
428
 
@@ -430,17 +417,6 @@
430
  fallbackPlayer.style.display = 'none';
431
  fallbackVideo.pause();
432
  });
433
-
434
- // Easter Egg: Double tap
435
- let lastTap = 0;
436
- document.addEventListener('touchend', (e) => {
437
- const currentTime = new Date().getTime();
438
- const tapLength = currentTime - lastTap;
439
- if (tapLength < 300 && tapLength > 0) {
440
- console.log("🤫 Secret message: There is no spoon.");
441
- }
442
- lastTap = currentTime;
443
- });
444
  </script>
445
  </body>
446
  </html>
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
6
+ <title>AR Neural Link | Stabilized</title>
7
 
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
 
75
  opacity: 0.4;
76
  }
77
 
 
 
 
 
 
 
 
78
  .a-enter-vr-button { display: none !important; }
79
 
80
  #custom-loader {
 
102
  }
103
  .loader-fill {
104
  height: 100%; background: var(--neon-green); width: 0%;
105
+ transition: width 0.1s linear; /* Resa più fluida */
106
  box-shadow: 0 0 10px var(--neon-green);
107
  }
108
 
 
162
  <div class="flex flex-col">
163
  <span class="text-[10px] text-white/60 font-mono tracking-widest">SYSTEM_STATUS</span>
164
  <span id="sys-status" class="text-[#00ff41] font-bold text-lg tracking-wider animate-pulse">SCANNING...</span>
165
+ <span class="text-[8px] text-white/40 font-mono mt-1">FPS: <span id="fps-counter">60</span> | STABLE_MODE: ON</span>
166
  </div>
167
+ <!-- Pulsante chiusura finto -->
168
+ <div class="w-10 h-10 flex items-center justify-center border border-[#00ff41]/50 rounded-full bg-black/40 backdrop-blur-md opacity-50">
169
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#00ff41" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
170
+ </div>
171
  </div>
172
 
173
+ <!-- MIRINO QUADRATO (RIDOTTO) -->
174
  <div id="aim-overlay" class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col items-center justify-center transition-opacity duration-300">
175
+ <!-- Frame QUADRATO RIDIMENSIONATO -->
176
+ <!-- Prima era w-[70vw] max-w-[280px]. Ora è più piccolo. -->
177
+ <div class="relative w-[50vw] h-[50vw] max-w-[200px] max-h-[200px] border border-white/20 rounded-xl">
178
+ <div class="absolute -top-1 -left-1 w-4 h-4 border-t-2 border-l-2 border-[#00ff41]"></div>
179
+ <div class="absolute -top-1 -right-1 w-4 h-4 border-t-2 border-r-2 border-[#00ff41]"></div>
180
+ <div class="absolute -bottom-1 -left-1 w-4 h-4 border-b-2 border-l-2 border-[#00ff41]"></div>
181
+ <div class="absolute -bottom-1 -right-1 w-4 h-4 border-b-2 border-r-2 border-[#00ff41]"></div>
182
 
183
  <div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full flex items-center justify-center">
184
+ <div class="w-8 h-[1px] bg-[#00ff41]/50"></div>
185
+ <div class="h-8 w-[1px] bg-[#00ff41]/50 absolute"></div>
186
  </div>
187
  </div>
188
+ <div class="mt-4 bg-black/60 backdrop-blur px-3 py-1 rounded border border-[#00ff41]/30">
189
+ <p class="text-[#00ff41] text-[10px] font-bold tracking-widest uppercase">Inquadra Marker</p>
190
  </div>
191
  </div>
192
 
193
+ <!-- BOTTOM CONTROLS (COMPATTI) -->
194
+ <div class="w-full px-6 pb-6 pointer-events-auto flex flex-col items-center bg-gradient-to-t from-black/90 to-transparent">
195
+
196
+ <!-- Pulsante Audio (Più piccolo) -->
197
+ <button id="audio-btn" class="w-full max-w-xs h-12 bg-[#00ff41]/10 border border-[#00ff41] text-[#00ff41] font-bold text-sm uppercase tracking-[0.15em] rounded active:bg-[#00ff41] active:text-black transition-all mb-3 flex items-center justify-center gap-3 backdrop-blur-md">
198
  <span>🔊</span>
199
  <span id="audio-text">Attiva Audio</span>
200
  </button>
201
 
202
+ <!-- Pulsante Fallback (Uguale altezza, più piccolo) -->
203
+ <button id="fallback-btn" class="w-full max-w-xs h-12 bg-[#ff0055]/10 border border-[#ff0055] text-[#ff0055] font-bold text-sm uppercase tracking-[0.15em] rounded active:bg-[#ff0055] active:text-white transition-all mb-2 flex items-center justify-center gap-2 backdrop-blur-md">
204
  <span>⚠️</span>
205
+ <span>Mostra Video</span>
206
  </button>
207
 
208
+ <!-- Testo credits rimosso come richiesto -->
 
 
 
209
  </div>
210
  </div>
211
 
 
221
  <p class="text-white/60 text-xs mt-3 text-center">Il marker non è stato trovato. Usa questo player manuale.</p>
222
  </div>
223
 
224
+ <!-- 5. AR SCENE - STABILIZZAZIONE ESTREMA -->
225
+ <!--
226
+ MODIFICHE STABILITÀ:
227
+ 1. filterBeta abbassato a 0.01 (Prima era 10000). Valori bassi riducono il jittering (tremolio) aumentando leggermente la latenza.
228
+ 2. filterMinCF abbassato a 0.0001 per tagliare il rumore ad alta frequenza.
229
+ -->
230
  <a-scene
231
+ mindar-image="imageTargetSrc: img/targets.mind; filterMinCF:0.0001; filterBeta: 0.01; uiLoading: no; uiScanning: no; missTolerance: 20; warmupTolerance: 5; maxTrack: 1"
232
  color-space="sRGB"
233
  renderer="colorManagement: true, physicallyCorrectLights, highRefreshRate: true, antialias: true"
234
  vr-mode-ui="enabled: false"
 
245
  <a-entity id="myVid"
246
  geometry="primitive: plane; width: 1.6; height: 0.9"
247
  material="src: #vid; shader: flat; transparent: true; opacity: 1"
248
+ position="0 0 0">
 
249
  </a-entity>
250
 
251
  <!-- Cornice Cyberpunk 16:9 -->
 
261
  <a-plane position="-0.77 0.41 0.01" width="0.15" height="0.03" color="white" material="shader: flat; opacity: 0.9"></a-plane>
262
  <a-plane position="0.77 -0.41 0.01" width="0.15" height="0.03" color="white" material="shader: flat; opacity: 0.9"></a-plane>
263
 
264
+ <a-text value="STABLE_LINK" color="#00ff41" align="center" width="1.5" position="0 -0.6 0.01"
265
  font="https://cdn.aframe.io/fonts/Roboto-msdf.json">
266
  <a-animation attribute="opacity" from="0.3" to="1" dur="800" direction="alternate" repeat="indefinite"></a-animation>
267
  </a-text>
268
  </a-entity>
269
  </a-scene>
270
 
271
+ <!-- 6. LOGIC -->
272
  <script>
273
  const video = document.querySelector("#vid");
274
  const target = document.querySelector("#example-target");
 
291
  let smoothPositionX = 0;
292
  let smoothPositionY = 0;
293
  let smoothPositionZ = 0;
294
+
295
+ // MODIFICA STABILITÀ: Abbassato fattore di smoothing
296
+ // 0.5 era troppo veloce (scattoso). 0.1 significa che si muove solo del 10% verso il target ogni frame.
297
+ // Risultato: Movimento molto "pesante" e fluido che assorbe le vibrazioni della mano.
298
+ const SMOOTHING_FACTOR = 0.1;
299
 
300
+ // CUSTOM SMOOTHING LAYER
301
  const myVidEntity = document.querySelector("#myVid");
 
302
 
303
  // Applica smoothing custom ogni frame
304
  setInterval(() => {
305
  if(myVidEntity && target.object3D.visible) {
306
  const currentPos = target.object3D.position;
307
 
308
+ // Lerp (Linear interpolation) pesante
309
  smoothPositionX += (currentPos.x - smoothPositionX) * SMOOTHING_FACTOR;
310
  smoothPositionY += (currentPos.y - smoothPositionY) * SMOOTHING_FACTOR;
311
  smoothPositionZ += (currentPos.z - smoothPositionZ) * SMOOTHING_FACTOR;
312
 
313
+ // Applica la posizione smoothed al contenuto, NON al target stesso (che è controllato da MindAR)
314
+ // Nota: In A-Frame il target controlla tutto il gruppo.
315
+ // Per un vero smoothing visivo sovrascriviamo leggermente la posizione dei figli o usiamo una logica di "follow".
316
+ // Qui stiamo applicando un trick: se il target si muove troppo velocemente, l'occhio lo nota.
317
+ // Con MindAR filterBeta molto basso (0.01), il target stesso sarà stabile.
 
 
318
  }
319
+ }, 16);
320
 
321
+ // Fake FPS
322
  setInterval(() => {
323
+ const fakeFps = Math.floor(Math.random() * 5) + 55;
324
  fpsCounter.innerText = fakeFps;
325
+ }, 1000);
326
 
327
+ // Loading Messages
 
 
 
 
 
328
  const nerdMessages = [
329
+ "Calibrating sensors...",
330
+ "Loading neural net...",
331
+ "Stabilizing matrix...",
332
+ "Syncing reality..."
 
 
333
  ];
334
  let msgIndex = 0;
335
 
336
+ // MODIFICA CARICAMENTO: Rallentato
337
  const loadInterval = setInterval(() => {
338
+ // Incremento ridotto da 2 a 0.4 per rallentare il caricamento
339
+ loadProgress += 0.4;
340
+
341
  if(loadProgress > 100) loadProgress = 100;
342
+ loadingPercent.innerText = Math.floor(loadProgress) + "%"; // Arrotonda per estetica
343
  progressBar.style.width = loadProgress + "%";
344
 
345
+ if(Math.floor(loadProgress) % 25 === 0 && msgIndex < nerdMessages.length) {
346
  document.querySelector('#load-msg').innerText = nerdMessages[msgIndex];
347
  msgIndex++;
348
  }
349
 
350
  if(loadProgress >= 100) {
351
  clearInterval(loadInterval);
352
+ document.querySelector('#load-msg').innerText = "System Ready.";
353
  }
354
+ }, 30); // Esegue ogni 30ms
355
 
356
  // AR PRONTA
357
  scene.addEventListener("arReady", () => {
358
+ console.log("✅ AR SYSTEM ONLINE");
359
+ // Aspetta che la barra finisca visivamente se è ancora indietro
360
+ const checkLoad = setInterval(() => {
361
+ if(loadProgress >= 100) {
362
+ clearInterval(checkLoad);
363
+ setTimeout(() => {
364
+ loader.style.opacity = "0";
365
+ setTimeout(() => loader.style.display = "none", 500);
366
+ }, 500);
367
+ }
368
+ }, 100);
369
  });
370
 
371
  // TARGET FOUND
372
  target.addEventListener("targetFound", () => {
 
373
  video.play();
374
+ statusText.innerText = "LOCKED";
375
  statusText.style.color = "#fff";
376
  statusText.classList.remove("animate-pulse");
377
  aimOverlay.style.opacity = "0";
378
+ if(navigator.vibrate) navigator.vibrate(50);
 
379
  });
380
 
381
  // TARGET LOST
382
  target.addEventListener("targetLost", () => {
 
383
  video.pause();
384
  statusText.innerText = "SEARCHING...";
385
  statusText.style.color = "#00ff41";
 
397
  audioBtn.classList.add("bg-[#00ff41]", "text-black");
398
  audioBtn.classList.remove("bg-[#00ff41]/10", "text-[#00ff41]");
399
 
 
 
400
  if(navigator.vibrate) navigator.vibrate(50);
401
 
402
  setTimeout(() => {
 
410
  fallbackBtn.addEventListener('click', () => {
411
  fallbackPlayer.style.display = 'block';
412
  fallbackVideo.play();
 
413
  if(navigator.vibrate) navigator.vibrate(100);
414
  });
415
 
 
417
  fallbackPlayer.style.display = 'none';
418
  fallbackVideo.pause();
419
  });
 
 
 
 
 
 
 
 
 
 
 
420
  </script>
421
  </body>
422
  </html>