copilot-liku-cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/ARCHITECTURE.md +411 -0
  2. package/CONFIGURATION.md +302 -0
  3. package/CONTRIBUTING.md +225 -0
  4. package/ELECTRON_README.md +121 -0
  5. package/INSTALLATION.md +350 -0
  6. package/LICENSE.md +1 -0
  7. package/PROJECT_STATUS.md +229 -0
  8. package/QUICKSTART.md +255 -0
  9. package/README.md +167 -0
  10. package/TESTING.md +274 -0
  11. package/package.json +61 -0
  12. package/scripts/start.js +30 -0
  13. package/src/assets/tray-icon.png +0 -0
  14. package/src/cli/commands/agent.js +327 -0
  15. package/src/cli/commands/click.js +108 -0
  16. package/src/cli/commands/drag.js +85 -0
  17. package/src/cli/commands/find.js +109 -0
  18. package/src/cli/commands/keys.js +132 -0
  19. package/src/cli/commands/mouse.js +79 -0
  20. package/src/cli/commands/repl.js +290 -0
  21. package/src/cli/commands/screenshot.js +72 -0
  22. package/src/cli/commands/scroll.js +74 -0
  23. package/src/cli/commands/start.js +67 -0
  24. package/src/cli/commands/type.js +57 -0
  25. package/src/cli/commands/wait.js +84 -0
  26. package/src/cli/commands/window.js +104 -0
  27. package/src/cli/liku.js +249 -0
  28. package/src/cli/util/output.js +174 -0
  29. package/src/main/agents/base-agent.js +410 -0
  30. package/src/main/agents/builder.js +484 -0
  31. package/src/main/agents/index.js +62 -0
  32. package/src/main/agents/orchestrator.js +362 -0
  33. package/src/main/agents/researcher.js +511 -0
  34. package/src/main/agents/state-manager.js +344 -0
  35. package/src/main/agents/supervisor.js +365 -0
  36. package/src/main/agents/verifier.js +452 -0
  37. package/src/main/ai-service.js +1633 -0
  38. package/src/main/index.js +2208 -0
  39. package/src/main/inspect-service.js +467 -0
  40. package/src/main/system-automation.js +1186 -0
  41. package/src/main/ui-automation/config.js +76 -0
  42. package/src/main/ui-automation/core/helpers.js +41 -0
  43. package/src/main/ui-automation/core/index.js +15 -0
  44. package/src/main/ui-automation/core/powershell.js +82 -0
  45. package/src/main/ui-automation/elements/finder.js +274 -0
  46. package/src/main/ui-automation/elements/index.js +14 -0
  47. package/src/main/ui-automation/elements/wait.js +66 -0
  48. package/src/main/ui-automation/index.js +164 -0
  49. package/src/main/ui-automation/interactions/element-click.js +211 -0
  50. package/src/main/ui-automation/interactions/high-level.js +230 -0
  51. package/src/main/ui-automation/interactions/index.js +47 -0
  52. package/src/main/ui-automation/keyboard/index.js +15 -0
  53. package/src/main/ui-automation/keyboard/input.js +179 -0
  54. package/src/main/ui-automation/mouse/click.js +186 -0
  55. package/src/main/ui-automation/mouse/drag.js +88 -0
  56. package/src/main/ui-automation/mouse/index.js +30 -0
  57. package/src/main/ui-automation/mouse/movement.js +51 -0
  58. package/src/main/ui-automation/mouse/scroll.js +116 -0
  59. package/src/main/ui-automation/screenshot.js +183 -0
  60. package/src/main/ui-automation/window/index.js +23 -0
  61. package/src/main/ui-automation/window/manager.js +305 -0
  62. package/src/main/utils/time.js +62 -0
  63. package/src/main/visual-awareness.js +597 -0
  64. package/src/renderer/chat/chat.js +671 -0
  65. package/src/renderer/chat/index.html +725 -0
  66. package/src/renderer/chat/preload.js +112 -0
  67. package/src/renderer/overlay/index.html +648 -0
  68. package/src/renderer/overlay/overlay.js +782 -0
  69. package/src/renderer/overlay/preload.js +90 -0
  70. package/src/shared/grid-math.js +82 -0
  71. package/src/shared/inspect-types.js +230 -0
@@ -0,0 +1,648 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';">
7
+ <title>Overlay</title>
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ body {
16
+ width: 100vw;
17
+ height: 100vh;
18
+ overflow: hidden;
19
+ background: transparent;
20
+ cursor: default;
21
+ -webkit-user-select: none;
22
+ user-select: none;
23
+ -webkit-app-region: no-drag;
24
+ }
25
+
26
+ /* Container must have pointer-events: none for click-through to work.
27
+ Individual dots have pointer-events: auto to still receive clicks.
28
+ This is required because we use setIgnoreMouseEvents(true, { forward: true })
29
+ so mouse events pass through transparent areas to background apps. */
30
+ #overlay-container {
31
+ width: 100%;
32
+ height: 100%;
33
+ position: relative;
34
+ pointer-events: none;
35
+ }
36
+
37
+ /* Dots container also needs pointer-events: none so clicks pass through gaps */
38
+ #dots-container {
39
+ pointer-events: none;
40
+ }
41
+
42
+ /* ===== ACTIVE OVERLAY BORDER ===== */
43
+ #overlay-border {
44
+ position: fixed;
45
+ top: 0;
46
+ left: 0;
47
+ right: 0;
48
+ bottom: 0;
49
+ pointer-events: none;
50
+ opacity: 0;
51
+ transition: opacity 0.3s ease;
52
+ z-index: 9999;
53
+ }
54
+
55
+ #overlay-border.active {
56
+ opacity: 1;
57
+ }
58
+
59
+ #overlay-border::before {
60
+ content: '';
61
+ position: absolute;
62
+ top: 4px;
63
+ left: 4px;
64
+ right: 4px;
65
+ bottom: 4px;
66
+ border: 2px solid rgba(0, 122, 255, 0.6);
67
+ border-radius: 8px;
68
+ animation: border-pulse 2s ease-in-out infinite;
69
+ }
70
+
71
+ #overlay-border::after {
72
+ content: '';
73
+ position: absolute;
74
+ top: 8px;
75
+ left: 8px;
76
+ right: 8px;
77
+ bottom: 8px;
78
+ border: 1px dashed rgba(0, 122, 255, 0.3);
79
+ border-radius: 6px;
80
+ }
81
+
82
+ @keyframes border-pulse {
83
+ 0%, 100% {
84
+ border-color: rgba(0, 122, 255, 0.6);
85
+ box-shadow: 0 0 10px rgba(0, 122, 255, 0.2), inset 0 0 10px rgba(0, 122, 255, 0.1);
86
+ }
87
+ 50% {
88
+ border-color: rgba(0, 200, 255, 0.8);
89
+ box-shadow: 0 0 20px rgba(0, 200, 255, 0.3), inset 0 0 20px rgba(0, 200, 255, 0.1);
90
+ }
91
+ }
92
+
93
+ /* ===== CORNER INDICATORS ===== */
94
+ .corner-indicator {
95
+ position: fixed;
96
+ width: 40px;
97
+ height: 40px;
98
+ pointer-events: none;
99
+ opacity: 0;
100
+ transition: opacity 0.3s ease;
101
+ }
102
+
103
+ .corner-indicator.active {
104
+ opacity: 1;
105
+ }
106
+
107
+ .corner-indicator::before,
108
+ .corner-indicator::after {
109
+ content: '';
110
+ position: absolute;
111
+ background: rgba(0, 122, 255, 0.8);
112
+ }
113
+
114
+ .corner-indicator::before {
115
+ width: 20px;
116
+ height: 3px;
117
+ }
118
+
119
+ .corner-indicator::after {
120
+ width: 3px;
121
+ height: 20px;
122
+ }
123
+
124
+ #corner-tl { top: 8px; left: 8px; }
125
+ #corner-tl::before { top: 0; left: 0; }
126
+ #corner-tl::after { top: 0; left: 0; }
127
+
128
+ #corner-tr { top: 8px; right: 8px; }
129
+ #corner-tr::before { top: 0; right: 0; }
130
+ #corner-tr::after { top: 0; right: 0; }
131
+
132
+ #corner-bl { bottom: 8px; left: 8px; }
133
+ #corner-bl::before { bottom: 0; left: 0; }
134
+ #corner-bl::after { bottom: 0; left: 0; }
135
+
136
+ #corner-br { bottom: 8px; right: 8px; }
137
+ #corner-br::before { bottom: 0; right: 0; }
138
+ #corner-br::after { bottom: 0; right: 0; }
139
+
140
+ /* Canvas for drawing dots - pointer-events: none for click-through */
141
+ #dot-canvas {
142
+ position: absolute;
143
+ top: 0;
144
+ left: 0;
145
+ width: 100%;
146
+ height: 100%;
147
+ pointer-events: none;
148
+ }
149
+
150
+ /* ===== COARSE GRID DOTS (always visible) ===== */
151
+ /* CRITICAL: dots must have pointer-events: auto to be clickable
152
+ while the rest of the overlay is click-through */
153
+ .dot {
154
+ position: absolute;
155
+ width: 12px;
156
+ height: 12px;
157
+ background: rgba(0, 122, 255, 0.85);
158
+ border: 2px solid rgba(255, 255, 255, 0.95);
159
+ border-radius: 50%;
160
+ cursor: pointer;
161
+ pointer-events: auto !important;
162
+ transition: all 0.15s ease;
163
+ transform: translate(-50%, -50%);
164
+ box-shadow: 0 0 8px rgba(0, 122, 255, 0.5);
165
+ z-index: 100;
166
+ }
167
+
168
+ .dot:hover {
169
+ background: rgba(0, 180, 255, 1);
170
+ width: 16px;
171
+ height: 16px;
172
+ border: 2px solid rgba(255, 255, 255, 1);
173
+ box-shadow: 0 0 12px rgba(0, 180, 255, 0.6);
174
+ z-index: 100;
175
+ }
176
+
177
+ .dot.selected {
178
+ background: rgba(255, 45, 85, 0.9);
179
+ border: 3px solid rgba(255, 255, 255, 1);
180
+ box-shadow: 0 0 15px rgba(255, 45, 85, 0.6);
181
+ animation: dot-selected 0.3s ease;
182
+ }
183
+
184
+ @keyframes dot-selected {
185
+ 0% { transform: translate(-50%, -50%) scale(1); }
186
+ 50% { transform: translate(-50%, -50%) scale(1.5); }
187
+ 100% { transform: translate(-50%, -50%) scale(1); }
188
+ }
189
+
190
+ /* ===== FINE GRID DOTS (appear on zoom/interaction) ===== */
191
+ .dot.fine {
192
+ width: 6px;
193
+ height: 6px;
194
+ background: rgba(100, 180, 255, 0.5);
195
+ border: 1px solid rgba(255, 255, 255, 0.6);
196
+ opacity: 0;
197
+ pointer-events: none;
198
+ transition: opacity 0.2s ease, width 0.15s ease, height 0.15s ease;
199
+ box-shadow: 0 0 4px rgba(100, 180, 255, 0.3);
200
+ }
201
+
202
+ .dot.fine.visible {
203
+ opacity: 1;
204
+ pointer-events: auto;
205
+ }
206
+
207
+ .dot.fine:hover {
208
+ width: 10px;
209
+ height: 10px;
210
+ background: rgba(100, 200, 255, 0.9);
211
+ border: 1px solid rgba(255, 255, 255, 1);
212
+ }
213
+
214
+ /* ===== ZOOM INDICATOR ===== */
215
+ #zoom-indicator {
216
+ position: fixed;
217
+ bottom: 20px;
218
+ left: 50%;
219
+ transform: translateX(-50%);
220
+ background: rgba(0, 0, 0, 0.8);
221
+ color: white;
222
+ padding: 8px 20px;
223
+ border-radius: 20px;
224
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
225
+ font-size: 12px;
226
+ pointer-events: none;
227
+ opacity: 0;
228
+ transition: opacity 0.2s ease;
229
+ z-index: 10000;
230
+ display: flex;
231
+ align-items: center;
232
+ gap: 8px;
233
+ }
234
+
235
+ #zoom-indicator.visible {
236
+ opacity: 1;
237
+ }
238
+
239
+ #zoom-indicator .zoom-level {
240
+ font-weight: 600;
241
+ color: #00bfff;
242
+ }
243
+
244
+ /* Label for dots */
245
+ .dot-label {
246
+ position: absolute;
247
+ background: rgba(0, 0, 0, 0.85);
248
+ color: white;
249
+ padding: 3px 8px;
250
+ border-radius: 4px;
251
+ font-size: 11px;
252
+ font-family: 'SF Mono', 'Monaco', 'Menlo', monospace;
253
+ font-weight: 500;
254
+ pointer-events: none;
255
+ transform: translate(-50%, -130%);
256
+ white-space: nowrap;
257
+ border: 1px solid rgba(0, 122, 255, 0.3);
258
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
259
+ }
260
+
261
+ .dot-label.fine-label {
262
+ font-size: 9px;
263
+ padding: 2px 5px;
264
+ background: rgba(0, 0, 0, 0.75);
265
+ opacity: 0;
266
+ transition: opacity 0.2s ease;
267
+ }
268
+
269
+ .dot-label.fine-label.visible {
270
+ opacity: 1;
271
+ }
272
+
273
+ /* Mode indicator */
274
+ #mode-indicator {
275
+ position: fixed;
276
+ top: 20px;
277
+ right: 20px;
278
+ background: rgba(0, 0, 0, 0.85);
279
+ color: white;
280
+ padding: 10px 20px;
281
+ border-radius: 8px;
282
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
283
+ font-size: 13px;
284
+ pointer-events: none;
285
+ opacity: 0;
286
+ transition: opacity 0.3s ease;
287
+ border: 1px solid rgba(0, 122, 255, 0.4);
288
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
289
+ z-index: 10000;
290
+ }
291
+
292
+ #mode-indicator.visible {
293
+ opacity: 1;
294
+ }
295
+
296
+ #mode-indicator .mode-icon {
297
+ display: inline-block;
298
+ width: 8px;
299
+ height: 8px;
300
+ border-radius: 50%;
301
+ margin-right: 8px;
302
+ background: #00ff88;
303
+ animation: mode-pulse 1.5s ease-in-out infinite;
304
+ }
305
+
306
+ @keyframes mode-pulse {
307
+ 0%, 100% { opacity: 1; }
308
+ 50% { opacity: 0.5; }
309
+ }
310
+
311
+ /* ===== INTERACTION REGION HIGHLIGHT ===== */
312
+ #interaction-region {
313
+ position: fixed;
314
+ pointer-events: none;
315
+ border: 2px solid rgba(0, 255, 136, 0.6);
316
+ background: rgba(0, 255, 136, 0.05);
317
+ border-radius: 4px;
318
+ opacity: 0;
319
+ transition: opacity 0.2s ease, all 0.15s ease;
320
+ z-index: 9998;
321
+ }
322
+
323
+ #interaction-region.visible {
324
+ opacity: 1;
325
+ }
326
+
327
+ /* Highlight layer */
328
+ .highlight {
329
+ position: absolute;
330
+ border: 2px solid rgba(0, 122, 255, 0.8);
331
+ background: rgba(0, 122, 255, 0.1);
332
+ pointer-events: none;
333
+ border-radius: 4px;
334
+ }
335
+
336
+ /* ===== STATUS BAR ===== */
337
+ #status-bar {
338
+ position: fixed;
339
+ top: 8px;
340
+ left: 50%;
341
+ transform: translateX(-50%);
342
+ background: rgba(0, 0, 0, 0.85);
343
+ color: #888;
344
+ padding: 6px 16px;
345
+ border-radius: 20px;
346
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
347
+ font-size: 11px;
348
+ pointer-events: none;
349
+ opacity: 0;
350
+ transition: opacity 0.3s ease;
351
+ z-index: 10000;
352
+ display: flex;
353
+ align-items: center;
354
+ gap: 16px;
355
+ border: 1px solid rgba(255, 255, 255, 0.1);
356
+ }
357
+
358
+ #status-bar.visible {
359
+ opacity: 1;
360
+ }
361
+
362
+ #status-bar .status-item {
363
+ display: flex;
364
+ align-items: center;
365
+ gap: 6px;
366
+ }
367
+
368
+ #status-bar .status-dot {
369
+ width: 6px;
370
+ height: 6px;
371
+ border-radius: 50%;
372
+ background: #00ff88;
373
+ }
374
+
375
+ #status-bar .status-dot.recording {
376
+ background: #ff4444;
377
+ animation: recording-pulse 1s ease-in-out infinite;
378
+ }
379
+
380
+ @keyframes recording-pulse {
381
+ 0%, 100% { opacity: 1; transform: scale(1); }
382
+ 50% { opacity: 0.7; transform: scale(1.2); }
383
+ }
384
+
385
+ /* ===== INSPECT MODE STYLES ===== */
386
+
387
+ /* Inspect regions container */
388
+ #inspect-container {
389
+ position: absolute;
390
+ top: 0;
391
+ left: 0;
392
+ width: 100%;
393
+ height: 100%;
394
+ pointer-events: none;
395
+ z-index: 50;
396
+ }
397
+
398
+ /* Inspect region box */
399
+ .inspect-region {
400
+ position: absolute;
401
+ border: 2px solid rgba(0, 255, 255, 0.8);
402
+ background: rgba(0, 255, 255, 0.05);
403
+ pointer-events: auto;
404
+ cursor: pointer;
405
+ transition: all 0.15s ease;
406
+ box-sizing: border-box;
407
+ }
408
+
409
+ .inspect-region:hover {
410
+ border-color: rgba(0, 255, 255, 1);
411
+ background: rgba(0, 255, 255, 0.15);
412
+ box-shadow: 0 0 12px rgba(0, 255, 255, 0.5);
413
+ }
414
+
415
+ .inspect-region.selected {
416
+ border-color: rgba(255, 200, 0, 1);
417
+ background: rgba(255, 200, 0, 0.15);
418
+ box-shadow: 0 0 15px rgba(255, 200, 0, 0.6);
419
+ border-width: 3px;
420
+ }
421
+
422
+ .inspect-region.low-confidence {
423
+ border-style: dashed;
424
+ opacity: 0.7;
425
+ }
426
+
427
+ /* Inspect region label */
428
+ .inspect-region-label {
429
+ position: absolute;
430
+ top: -20px;
431
+ left: 0;
432
+ background: rgba(0, 255, 255, 0.9);
433
+ color: #000;
434
+ padding: 2px 6px;
435
+ font-size: 10px;
436
+ font-family: 'SF Mono', 'Monaco', monospace;
437
+ font-weight: 600;
438
+ border-radius: 3px;
439
+ white-space: nowrap;
440
+ pointer-events: none;
441
+ max-width: 150px;
442
+ overflow: hidden;
443
+ text-overflow: ellipsis;
444
+ }
445
+
446
+ .inspect-region.selected .inspect-region-label {
447
+ background: rgba(255, 200, 0, 0.95);
448
+ }
449
+
450
+ /* Inspect tooltip */
451
+ #inspect-tooltip {
452
+ position: fixed;
453
+ background: rgba(0, 0, 0, 0.92);
454
+ color: white;
455
+ padding: 10px 14px;
456
+ border-radius: 6px;
457
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
458
+ font-size: 12px;
459
+ pointer-events: none;
460
+ z-index: 10001;
461
+ max-width: 300px;
462
+ opacity: 0;
463
+ transition: opacity 0.15s ease;
464
+ border: 1px solid rgba(0, 255, 255, 0.4);
465
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);
466
+ }
467
+
468
+ #inspect-tooltip.visible {
469
+ opacity: 1;
470
+ }
471
+
472
+ #inspect-tooltip .tooltip-header {
473
+ display: flex;
474
+ align-items: center;
475
+ gap: 8px;
476
+ margin-bottom: 8px;
477
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
478
+ padding-bottom: 6px;
479
+ }
480
+
481
+ #inspect-tooltip .tooltip-role {
482
+ background: rgba(0, 255, 255, 0.2);
483
+ color: #00ffff;
484
+ padding: 2px 6px;
485
+ border-radius: 3px;
486
+ font-size: 10px;
487
+ text-transform: uppercase;
488
+ font-weight: 600;
489
+ }
490
+
491
+ #inspect-tooltip .tooltip-label {
492
+ font-weight: 600;
493
+ color: #fff;
494
+ }
495
+
496
+ #inspect-tooltip .tooltip-row {
497
+ display: flex;
498
+ align-items: center;
499
+ gap: 8px;
500
+ margin-top: 4px;
501
+ font-size: 11px;
502
+ }
503
+
504
+ #inspect-tooltip .tooltip-key {
505
+ color: #888;
506
+ min-width: 65px;
507
+ }
508
+
509
+ #inspect-tooltip .tooltip-value {
510
+ color: #fff;
511
+ font-family: 'SF Mono', 'Monaco', monospace;
512
+ }
513
+
514
+ #inspect-tooltip .tooltip-confidence {
515
+ display: flex;
516
+ align-items: center;
517
+ gap: 6px;
518
+ }
519
+
520
+ #inspect-tooltip .confidence-bar {
521
+ width: 60px;
522
+ height: 6px;
523
+ background: rgba(255, 255, 255, 0.2);
524
+ border-radius: 3px;
525
+ overflow: hidden;
526
+ }
527
+
528
+ #inspect-tooltip .confidence-fill {
529
+ height: 100%;
530
+ background: linear-gradient(90deg, #ff4444, #ffaa00, #00ff88);
531
+ border-radius: 3px;
532
+ transition: width 0.2s ease;
533
+ }
534
+
535
+ /* Inspect mode indicator */
536
+ #inspect-indicator {
537
+ position: fixed;
538
+ top: 20px;
539
+ left: 20px;
540
+ background: rgba(0, 255, 255, 0.15);
541
+ color: #00ffff;
542
+ padding: 8px 16px;
543
+ border-radius: 6px;
544
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
545
+ font-size: 12px;
546
+ font-weight: 600;
547
+ pointer-events: none;
548
+ opacity: 0;
549
+ transition: opacity 0.3s ease;
550
+ border: 1px solid rgba(0, 255, 255, 0.4);
551
+ z-index: 10000;
552
+ display: flex;
553
+ align-items: center;
554
+ gap: 8px;
555
+ }
556
+
557
+ #inspect-indicator.visible {
558
+ opacity: 1;
559
+ }
560
+
561
+ #inspect-indicator .inspect-icon {
562
+ width: 8px;
563
+ height: 8px;
564
+ border-radius: 50%;
565
+ background: #00ffff;
566
+ animation: inspect-pulse 1.5s ease-in-out infinite;
567
+ }
568
+
569
+ @keyframes inspect-pulse {
570
+ 0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(0, 255, 255, 0.7); }
571
+ 50% { opacity: 0.8; box-shadow: 0 0 0 4px rgba(0, 255, 255, 0); }
572
+ }
573
+
574
+ #inspect-indicator .region-count {
575
+ background: rgba(0, 255, 255, 0.3);
576
+ padding: 2px 6px;
577
+ border-radius: 10px;
578
+ font-size: 10px;
579
+ }
580
+ </style>
581
+ </head>
582
+ <body>
583
+ <div id="overlay-container">
584
+ <!-- Active overlay border -->
585
+ <div id="overlay-border"></div>
586
+
587
+ <!-- Corner indicators -->
588
+ <div id="corner-tl" class="corner-indicator"></div>
589
+ <div id="corner-tr" class="corner-indicator"></div>
590
+ <div id="corner-bl" class="corner-indicator"></div>
591
+ <div id="corner-br" class="corner-indicator"></div>
592
+
593
+ <!-- Inspect regions container -->
594
+ <div id="inspect-container"></div>
595
+
596
+ <!-- Main canvas and dots -->
597
+ <canvas id="dot-canvas"></canvas>
598
+ <div id="dots-container"></div>
599
+
600
+ <!-- Interaction region highlight -->
601
+ <div id="interaction-region"></div>
602
+
603
+ <!-- Status indicators -->
604
+ <div id="status-bar">
605
+ <span class="status-item"><span class="status-dot"></span> Active</span>
606
+ <span class="status-item" id="grid-status">Grid: Coarse</span>
607
+ <span class="status-item" id="coords-status">---, ---</span>
608
+ </div>
609
+
610
+ <div id="mode-indicator"><span class="mode-icon"></span>Selection Mode</div>
611
+ <div id="zoom-indicator">Zoom: <span class="zoom-level">1x</span> | Scroll to adjust</div>
612
+
613
+ <!-- Inspect mode indicator -->
614
+ <div id="inspect-indicator">
615
+ <span class="inspect-icon"></span>
616
+ Inspect Mode
617
+ <span class="region-count" id="region-count">0</span>
618
+ </div>
619
+
620
+ <!-- Inspect tooltip -->
621
+ <div id="inspect-tooltip">
622
+ <div class="tooltip-header">
623
+ <span class="tooltip-role">button</span>
624
+ <span class="tooltip-label">Label</span>
625
+ </div>
626
+ <div class="tooltip-row">
627
+ <span class="tooltip-key">Text:</span>
628
+ <span class="tooltip-value" id="tooltip-text">-</span>
629
+ </div>
630
+ <div class="tooltip-row">
631
+ <span class="tooltip-key">Position:</span>
632
+ <span class="tooltip-value" id="tooltip-position">0, 0</span>
633
+ </div>
634
+ <div class="tooltip-row">
635
+ <span class="tooltip-key">Confidence:</span>
636
+ <span class="tooltip-confidence">
637
+ <div class="confidence-bar">
638
+ <div class="confidence-fill" id="tooltip-confidence-bar" style="width: 50%"></div>
639
+ </div>
640
+ <span class="tooltip-value" id="tooltip-confidence">50%</span>
641
+ </span>
642
+ </div>
643
+ </div>
644
+ </div>
645
+
646
+ <script src="./overlay.js"></script>
647
+ </body>
648
+ </html>