mudra-skills 3.0.2 → 3.0.4

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 (146) hide show
  1. package/package.json +1 -1
  2. package/skills/mudra-master/SKILL.md +0 -196
  3. package/skills/mudra-master/mudra-preview/SKILL.md +0 -150
  4. package/skills/mudra-master/mudra-preview/assets/ar-menu.html +0 -382
  5. package/skills/mudra-master/mudra-preview/assets/document-scroller.html +0 -468
  6. package/skills/mudra-master/mudra-preview/assets/drum-machine.html +0 -788
  7. package/skills/mudra-master/mudra-preview/assets/emg-visualizer.html +0 -390
  8. package/skills/mudra-master/mudra-preview/assets/generative-art.html +0 -408
  9. package/skills/mudra-master/mudra-preview/assets/gesture-assistant.html +0 -342
  10. package/skills/mudra-master/mudra-preview/assets/gesture-speech.html +0 -444
  11. package/skills/mudra-master/mudra-preview/assets/hands-free-desktop.html +0 -376
  12. package/skills/mudra-master/mudra-preview/assets/model-rotator.html +0 -365
  13. package/skills/mudra-master/mudra-preview/assets/mudra-duel.html +0 -3200
  14. package/skills/mudra-master/mudra-preview/assets/mudra-monitor.html +0 -1451
  15. package/skills/mudra-master/mudra-preview/assets/mudra-ultimate-template.html +0 -891
  16. package/skills/mudra-master/mudra-preview/assets/music-sequencer.html +0 -455
  17. package/skills/mudra-master/mudra-preview/assets/neural-pong.html +0 -380
  18. package/skills/mudra-master/mudra-preview/assets/neural-snake.html +0 -364
  19. package/skills/mudra-master/mudra-preview/assets/presentation-controller.html +0 -345
  20. package/skills/mudra-master/mudra-preview/assets/pressure-painter.html +0 -285
  21. package/skills/mudra-master/mudra-preview/assets/runner.html +0 -1812
  22. package/skills/mudra-master/mudra-preview/assets/smart-home.html +0 -461
  23. package/skills/mudra-master/mudra-preview/assets/space-invaders.html +0 -1154
  24. package/skills/mudra-master/mudra-preview/assets/waterful-ring-toss.html +0 -1624
  25. package/skills/mudra-master/mudra-preview/references/agent_protocol.json +0 -634
  26. package/skills/mudra-master/mudra-preview/references/prompt.md +0 -16746
  27. package/skills/mudra-master/mudra-xr/SKILL.md +0 -245
  28. package/skills/mudra-master/mudra-xr/assets/demos/3dgs-walkthrough.html +0 -242
  29. package/skills/mudra-master/mudra-xr/assets/demos/aisimulator.html +0 -792
  30. package/skills/mudra-master/mudra-xr/assets/demos/balloonpop.html +0 -422
  31. package/skills/mudra-master/mudra-xr/assets/demos/ballpit.html +0 -284
  32. package/skills/mudra-master/mudra-xr/assets/demos/drone.html +0 -41
  33. package/skills/mudra-master/mudra-xr/assets/demos/gemini-icebreakers.html +0 -338
  34. package/skills/mudra-master/mudra-xr/assets/demos/gemini-xrobject.html +0 -302
  35. package/skills/mudra-master/mudra-xr/assets/demos/math3d.html +0 -188
  36. package/skills/mudra-master/mudra-xr/assets/demos/measure.html +0 -247
  37. package/skills/mudra-master/mudra-xr/assets/demos/occlusion.html +0 -251
  38. package/skills/mudra-master/mudra-xr/assets/demos/rain.html +0 -498
  39. package/skills/mudra-master/mudra-xr/assets/demos/screenwiper.html +0 -432
  40. package/skills/mudra-master/mudra-xr/assets/demos/splash.html +0 -519
  41. package/skills/mudra-master/mudra-xr/assets/demos/webcam_gestures.html +0 -253
  42. package/skills/mudra-master/mudra-xr/assets/demos/xremoji.html +0 -833
  43. package/skills/mudra-master/mudra-xr/assets/demos/xrpoet.html +0 -151
  44. package/skills/mudra-master/mudra-xr/assets/samples/depthmap.html +0 -266
  45. package/skills/mudra-master/mudra-xr/assets/samples/depthmesh.html +0 -100
  46. package/skills/mudra-master/mudra-xr/assets/samples/game_rps.html +0 -1099
  47. package/skills/mudra-master/mudra-xr/assets/samples/gestures_custom.html +0 -467
  48. package/skills/mudra-master/mudra-xr/assets/samples/gestures_heuristic.html +0 -256
  49. package/skills/mudra-master/mudra-xr/assets/samples/lighting.html +0 -163
  50. package/skills/mudra-master/mudra-xr/assets/samples/mesh_detection.html +0 -46
  51. package/skills/mudra-master/mudra-xr/assets/samples/modelviewer.html +0 -183
  52. package/skills/mudra-master/mudra-xr/assets/samples/paint.html +0 -133
  53. package/skills/mudra-master/mudra-xr/assets/samples/planar-vst.html +0 -45
  54. package/skills/mudra-master/mudra-xr/assets/samples/reticle.html +0 -95
  55. package/skills/mudra-master/mudra-xr/assets/samples/skybox_agent.html +0 -384
  56. package/skills/mudra-master/mudra-xr/assets/samples/sound.html +0 -390
  57. package/skills/mudra-master/mudra-xr/assets/samples/ui.html +0 -496
  58. package/skills/mudra-master/mudra-xr/assets/samples/virtual-screens.html +0 -808
  59. package/skills/mudra-master/mudra-xr/assets/templates/0_basic.html +0 -64
  60. package/skills/mudra-master/mudra-xr/assets/templates/1_ui.html +0 -107
  61. package/skills/mudra-master/mudra-xr/assets/templates/2_hands.html +0 -183
  62. package/skills/mudra-master/mudra-xr/assets/templates/3_depth.html +0 -89
  63. package/skills/mudra-master/mudra-xr/assets/templates/4_stereo.html +0 -84
  64. package/skills/mudra-master/mudra-xr/assets/templates/5_camera.html +0 -117
  65. package/skills/mudra-master/mudra-xr/assets/templates/6_ai.html +0 -154
  66. package/skills/mudra-master/mudra-xr/assets/templates/7_ai_live.html +0 -253
  67. package/skills/mudra-master/mudra-xr/assets/templates/8_objects.html +0 -95
  68. package/skills/mudra-master/mudra-xr/assets/templates/9_xr-toggle.html +0 -90
  69. package/skills/mudra-master/mudra-xr/assets/templates/heuristic_hand_gestures.html +0 -102
  70. package/skills/mudra-master/mudra-xr/assets/templates/meshes.html +0 -47
  71. package/skills/mudra-master/mudra-xr/assets/templates/planes.html +0 -47
  72. package/skills/mudra-master/mudra-xr/assets/templates/uikit.html +0 -187
  73. package/skills/mudra-master/mudra-xr/references/agent_protocol.json +0 -865
  74. package/skills/mudra-master/mudra-xr/references/prompt.md +0 -1605
  75. package/skills/mudra-preview/SKILL.md +0 -159
  76. package/skills/mudra-preview/assets/ar-menu.html +0 -382
  77. package/skills/mudra-preview/assets/document-scroller.html +0 -468
  78. package/skills/mudra-preview/assets/drum-machine.html +0 -788
  79. package/skills/mudra-preview/assets/emg-visualizer.html +0 -390
  80. package/skills/mudra-preview/assets/generative-art.html +0 -408
  81. package/skills/mudra-preview/assets/gesture-assistant.html +0 -342
  82. package/skills/mudra-preview/assets/gesture-speech.html +0 -444
  83. package/skills/mudra-preview/assets/hands-free-desktop.html +0 -376
  84. package/skills/mudra-preview/assets/model-rotator.html +0 -365
  85. package/skills/mudra-preview/assets/mudra-duel.html +0 -3200
  86. package/skills/mudra-preview/assets/mudra-monitor.html +0 -1451
  87. package/skills/mudra-preview/assets/mudra-ultimate-template.html +0 -997
  88. package/skills/mudra-preview/assets/music-sequencer.html +0 -455
  89. package/skills/mudra-preview/assets/neural-pong.html +0 -380
  90. package/skills/mudra-preview/assets/neural-snake.html +0 -364
  91. package/skills/mudra-preview/assets/presentation-controller.html +0 -345
  92. package/skills/mudra-preview/assets/pressure-painter.html +0 -285
  93. package/skills/mudra-preview/assets/runner.html +0 -1812
  94. package/skills/mudra-preview/assets/smart-home.html +0 -461
  95. package/skills/mudra-preview/assets/space-invaders.html +0 -1154
  96. package/skills/mudra-preview/assets/waterful-ring-toss.html +0 -1624
  97. package/skills/mudra-preview/references/agent_protocol.json +0 -701
  98. package/skills/mudra-preview/references/prompt.md +0 -16731
  99. package/skills/mudra-xr/SKILL.md +0 -245
  100. package/skills/mudra-xr/assets/demos/3dgs-walkthrough.html +0 -242
  101. package/skills/mudra-xr/assets/demos/aisimulator.html +0 -792
  102. package/skills/mudra-xr/assets/demos/balloonpop.html +0 -422
  103. package/skills/mudra-xr/assets/demos/ballpit.html +0 -284
  104. package/skills/mudra-xr/assets/demos/drone.html +0 -41
  105. package/skills/mudra-xr/assets/demos/gemini-icebreakers.html +0 -338
  106. package/skills/mudra-xr/assets/demos/gemini-xrobject.html +0 -302
  107. package/skills/mudra-xr/assets/demos/math3d.html +0 -188
  108. package/skills/mudra-xr/assets/demos/measure.html +0 -247
  109. package/skills/mudra-xr/assets/demos/occlusion.html +0 -251
  110. package/skills/mudra-xr/assets/demos/rain.html +0 -498
  111. package/skills/mudra-xr/assets/demos/screenwiper.html +0 -432
  112. package/skills/mudra-xr/assets/demos/splash.html +0 -519
  113. package/skills/mudra-xr/assets/demos/webcam_gestures.html +0 -253
  114. package/skills/mudra-xr/assets/demos/xremoji.html +0 -833
  115. package/skills/mudra-xr/assets/demos/xrpoet.html +0 -151
  116. package/skills/mudra-xr/assets/samples/depthmap.html +0 -266
  117. package/skills/mudra-xr/assets/samples/depthmesh.html +0 -100
  118. package/skills/mudra-xr/assets/samples/game_rps.html +0 -1099
  119. package/skills/mudra-xr/assets/samples/gestures_custom.html +0 -467
  120. package/skills/mudra-xr/assets/samples/gestures_heuristic.html +0 -256
  121. package/skills/mudra-xr/assets/samples/lighting.html +0 -163
  122. package/skills/mudra-xr/assets/samples/mesh_detection.html +0 -46
  123. package/skills/mudra-xr/assets/samples/modelviewer.html +0 -183
  124. package/skills/mudra-xr/assets/samples/paint.html +0 -133
  125. package/skills/mudra-xr/assets/samples/planar-vst.html +0 -45
  126. package/skills/mudra-xr/assets/samples/reticle.html +0 -95
  127. package/skills/mudra-xr/assets/samples/skybox_agent.html +0 -384
  128. package/skills/mudra-xr/assets/samples/sound.html +0 -390
  129. package/skills/mudra-xr/assets/samples/ui.html +0 -496
  130. package/skills/mudra-xr/assets/samples/virtual-screens.html +0 -808
  131. package/skills/mudra-xr/assets/templates/0_basic.html +0 -64
  132. package/skills/mudra-xr/assets/templates/1_ui.html +0 -107
  133. package/skills/mudra-xr/assets/templates/2_hands.html +0 -183
  134. package/skills/mudra-xr/assets/templates/3_depth.html +0 -89
  135. package/skills/mudra-xr/assets/templates/4_stereo.html +0 -84
  136. package/skills/mudra-xr/assets/templates/5_camera.html +0 -117
  137. package/skills/mudra-xr/assets/templates/6_ai.html +0 -154
  138. package/skills/mudra-xr/assets/templates/7_ai_live.html +0 -253
  139. package/skills/mudra-xr/assets/templates/8_objects.html +0 -95
  140. package/skills/mudra-xr/assets/templates/9_xr-toggle.html +0 -90
  141. package/skills/mudra-xr/assets/templates/heuristic_hand_gestures.html +0 -102
  142. package/skills/mudra-xr/assets/templates/meshes.html +0 -47
  143. package/skills/mudra-xr/assets/templates/planes.html +0 -47
  144. package/skills/mudra-xr/assets/templates/uikit.html +0 -187
  145. package/skills/mudra-xr/references/agent_protocol.json +0 -865
  146. package/skills/mudra-xr/references/prompt.md +0 -1605
@@ -1,468 +0,0 @@
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">
6
- <title>Document Scroller — Mudra Studio</title>
7
- <style>
8
- @media (prefers-reduced-motion: reduce) {
9
- *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
10
- }
11
-
12
- :root {
13
- --bg: #ffffff; --card: #f1f5f9; --primary: #0d9488; --accent: #14b8a6;
14
- --text: #0f172a; --text-secondary: #475569; --success: #16a34a;
15
- --warning: #ca8a04; --error: #dc2626;
16
- --border: rgba(15,23,42,0.12); --surface: rgba(0,0,0,0.04);
17
- }
18
-
19
- * { margin: 0; padding: 0; box-sizing: border-box; }
20
- body { background: var(--bg); color: var(--text); font-family: 'Poppins', system-ui, sans-serif; overflow: hidden; height: 100vh; display: flex; flex-direction: column; }
21
-
22
- .header { display: flex; align-items: center; justify-content: space-between; padding: 10px 16px; background: var(--card); border-bottom: 1px solid var(--border); z-index: 100; flex-shrink: 0; gap: 8px; flex-wrap: wrap; }
23
- .header-left, .header-right { display: flex; align-items: center; gap: 10px; }
24
- .brand { font-weight: 700; font-size: 14px; } .brand span { color: var(--primary); }
25
- .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--warning); box-shadow: 0 0 0 3px rgba(234,179,8,0.15); transition: all 150ms; }
26
- .dot.live { background: var(--success); box-shadow: 0 0 0 3px rgba(34,197,94,0.18); }
27
- .conn-label { font-size: 12px; color: var(--text-secondary); }
28
-
29
- .btn { background: var(--surface); border: 1px solid var(--border); color: var(--text-secondary); padding: 5px 12px; border-radius: 8px; font-size: 12px; cursor: pointer; font-family: inherit; transition: border-color 150ms, color 150ms; white-space: nowrap; }
30
- .btn:hover { border-color: var(--primary); color: var(--primary); }
31
- .btn.primary-btn { background: var(--primary); color: #072f33; border-color: transparent; font-weight: 600; }
32
- .btn.primary-btn:hover { opacity: 0.9; }
33
-
34
- /* Layout */
35
- .layout { flex: 1; display: flex; overflow: hidden; position: relative; }
36
-
37
- /* Table of contents sidebar */
38
- .toc { width: 220px; background: var(--card); border-right: 1px solid var(--border); overflow-y: auto; padding: 16px 12px; flex-shrink: 0; }
39
- .toc-title { font-size: 11px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--text-secondary); margin-bottom: 12px; font-weight: 600; }
40
- .toc-item { display: block; padding: 7px 10px; font-size: 12px; color: var(--text-secondary); text-decoration: none; border-radius: 6px; margin-bottom: 2px; transition: all 150ms; cursor: pointer; border: 1px solid transparent; line-height: 1.4; }
41
- .toc-item:hover { color: var(--text); background: var(--surface); }
42
- .toc-item.active { color: var(--primary); background: rgba(119,234,233,0.06); border-color: rgba(119,234,233,0.2); }
43
-
44
- /* Document area */
45
- .doc-area { flex: 1; position: relative; overflow: hidden; display: flex; flex-direction: column; }
46
- .doc-scroll { flex: 1; overflow-y: auto; scroll-behavior: smooth; padding: 32px 40px; }
47
-
48
- /* Scan mode */
49
- .doc-scroll.scan-mode .section h2 { font-size: 17px; }
50
- .doc-scroll.scan-mode .section p { font-size: 12px; line-height: 1.5; color: var(--text-secondary); }
51
- .doc-scroll.scan-mode .section .callout { border-color: var(--primary); background: rgba(119,234,233,0.1); }
52
- .doc-scroll.scan-mode .section { margin-bottom: 24px; }
53
-
54
- /* Content sections */
55
- .section { margin-bottom: 44px; }
56
- .section h2 { font-size: 22px; font-weight: 700; margin-bottom: 14px; color: var(--text); scroll-margin-top: 20px; }
57
- .section h2 .num { color: var(--primary); margin-right: 8px; font-variant-numeric: tabular-nums; }
58
- .section p { font-size: 15px; line-height: 1.8; color: var(--text-secondary); margin-bottom: 12px; }
59
- .section .callout { background: var(--surface); border-left: 3px solid var(--accent); padding: 14px 18px; border-radius: 0 10px 10px 0; margin: 14px 0; font-size: 14px; color: var(--text-secondary); line-height: 1.7; }
60
-
61
- /* Custom scrollbar track */
62
- .scrollbar-track { position: absolute; right: 0; top: 0; bottom: 0; width: 14px; background: var(--card); border-left: 1px solid var(--border); z-index: 10; }
63
- .scroll-thumb { position: absolute; right: 2px; width: 10px; background: var(--text-secondary); opacity: 0.3; border-radius: 5px; min-height: 30px; transition: background 150ms, opacity 150ms; cursor: pointer; }
64
- .scroll-thumb:hover { opacity: 0.6; background: var(--primary); }
65
- .bookmark-marker { position: absolute; right: 0; width: 14px; height: 4px; background: var(--primary); border-radius: 2px; pointer-events: none; z-index: 2; }
66
-
67
- /* Bottom toolbar */
68
- .toolbar { display: flex; align-items: center; gap: 14px; padding: 10px 16px; background: var(--card); border-top: 1px solid var(--border); z-index: 100; flex-shrink: 0; flex-wrap: wrap; }
69
- .section-name { font-size: 13px; color: var(--primary); font-weight: 600; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
70
- .meter { display: flex; align-items: center; gap: 8px; }
71
- .meter-label { font-size: 12px; color: var(--text-secondary); }
72
- .meter-bar { width: 60px; height: 8px; background: var(--surface); border-radius: 999px; overflow: hidden; border: 1px solid var(--border); }
73
- .meter-fill { height: 100%; background: linear-gradient(90deg, var(--accent), var(--primary)); border-radius: 999px; transition: width 75ms linear; width: 0%; }
74
- .bm-count { font-size: 12px; color: var(--text-secondary); white-space: nowrap; }
75
- .mode-badge { font-size: 11px; padding: 4px 10px; border-radius: 20px; background: var(--surface); border: 1px solid var(--border); color: var(--text-secondary); cursor: pointer; transition: all 150ms; white-space: nowrap; }
76
- .mode-badge.scan { border-color: var(--primary); color: var(--primary); }
77
- .hint { font-size: 11px; color: var(--text-secondary); opacity: 0.6; }
78
-
79
- .mudra-badge { position: fixed; bottom: 12px; right: 12px; font-size: 11px; color: var(--text-secondary); opacity: 0.7; letter-spacing: 0.02em; pointer-events: none; z-index: 200; }
80
-
81
- @media (max-width: 640px) {
82
- .header { padding: 8px 10px; }
83
- .toc { display: none; }
84
- .doc-scroll { padding: 20px 16px; }
85
- .toolbar { gap: 8px; padding: 8px 10px; }
86
- .hint { display: none; }
87
- .meter-bar { width: 40px; }
88
- }
89
- </style>
90
- </head>
91
- <body>
92
-
93
- <div class="header">
94
- <div class="header-left">
95
- <div class="brand"><span>Mudra</span> Document Scroller</div>
96
- <span class="dot" id="dot"></span>
97
- <span class="conn-label" id="connLabel">Connecting&hellip;</span>
98
- </div>
99
- <div class="header-right">
100
- <a href="/gallery" class="btn" style="text-decoration:none;">&#8592; Gallery</a>
101
- <button class="btn" id="simTap">Bookmark</button>
102
- <button class="btn" id="simScan">Toggle Scan</button>
103
- </div>
104
- </div>
105
-
106
- <div class="layout">
107
- <div class="toc" id="toc">
108
- <div class="toc-title">Contents</div>
109
- </div>
110
- <div class="doc-area">
111
- <div class="doc-scroll" id="docScroll"></div>
112
- <div class="scrollbar-track" id="scrollbarTrack">
113
- <div class="scroll-thumb" id="scrollThumb"></div>
114
- </div>
115
- </div>
116
- </div>
117
-
118
- <div class="toolbar">
119
- <span class="section-name" id="sectionName">Introduction</span>
120
- <div class="meter">
121
- <span class="meter-label">Speed</span>
122
- <div class="meter-bar"><div class="meter-fill" id="speedFill"></div></div>
123
- </div>
124
- <span class="bm-count" id="bmCount">0 bookmarks</span>
125
- <span class="mode-badge" id="modeBadge">Reading</span>
126
- <span class="hint">&uarr;&darr; scroll &middot; B bookmark &middot; N next &middot; S scan &middot; [ ] speed</span>
127
- </div>
128
-
129
- <div class="mudra-badge">Created by Mudra</div>
130
-
131
- <script>
132
- /* ── Mudra Protocol Connection (v2) ────────────────────────── */
133
- const WS_URL = 'ws://127.0.0.1:8766';
134
- const SIGNALS = ['navigation', 'gesture', 'pressure'];
135
-
136
- let ws, reconnectTimer, simTimer;
137
- let wsOpen = false, deviceReady = false, simulating = true;
138
- const bus = {};
139
-
140
- function on(ev, fn) { (bus[ev] ??= []).push(fn); }
141
- function emit(ev, d) { (bus[ev] || []).forEach(fn => fn(d)); }
142
- function send(p) { if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(p)); }
143
-
144
- function connect() {
145
- try {
146
- ws = new WebSocket(WS_URL);
147
- ws.onopen = () => {
148
- wsOpen = true; stopSim(); updateStatus();
149
- SIGNALS.forEach(s => send({ command: 'subscribe', signal: s }));
150
- };
151
- ws.onmessage = (e) => {
152
- try {
153
- const msg = JSON.parse(e.data);
154
- if (msg.type === 'connection_status') {
155
- deviceReady = msg.data?.status === 'connected';
156
- updateStatus(); return;
157
- }
158
- emit(msg.type, msg.data);
159
- } catch {}
160
- };
161
- ws.onclose = () => {
162
- wsOpen = false; deviceReady = false; updateStatus();
163
- startSim();
164
- clearTimeout(reconnectTimer);
165
- reconnectTimer = setTimeout(connect, 1500);
166
- };
167
- ws.onerror = () => ws?.close();
168
- } catch {
169
- wsOpen = false; startSim();
170
- clearTimeout(reconnectTimer);
171
- reconnectTimer = setTimeout(connect, 1500);
172
- }
173
- }
174
-
175
- function triggerGesture(type) {
176
- if (wsOpen) send({ command: 'trigger_gesture', data: { type } });
177
- else emit('gesture', { type, confidence: 0.95, timestamp: Date.now() });
178
- }
179
-
180
- /* ── Simulation (when Companion not reachable) ─────────────── */
181
- function startSim() {
182
- if (simTimer) return;
183
- simulating = true;
184
- let t = 0;
185
- simTimer = setInterval(() => {
186
- t += 0.05;
187
- /* gentle auto-scroll via navigation */
188
- const dy = Math.round(1.5 + Math.sin(t * 0.2) * 1);
189
- emit('navigation', { delta_x: 0, delta_y: dy, timestamp: Date.now() });
190
- /* pressure for scroll speed */
191
- const n = Math.max(0, Math.min(1, 0.3 + 0.15 * Math.sin(t * 0.4) + (Math.random() - 0.5) * 0.05));
192
- emit('pressure', { value: Math.round(n * 100), normalized: n, timestamp: Date.now() });
193
- /* occasional bookmark */
194
- if (Math.random() < 0.002) {
195
- emit('gesture', { type: 'tap', confidence: 0.9, timestamp: Date.now() });
196
- }
197
- }, 60);
198
- }
199
-
200
- function stopSim() { clearInterval(simTimer); simTimer = null; simulating = false; }
201
-
202
- /* ── Status UI ─────────────────────────────────────────────── */
203
- const dotEl = document.getElementById('dot');
204
- const connEl = document.getElementById('connLabel');
205
-
206
- function updateStatus() {
207
- if (wsOpen && deviceReady) { dotEl.className = 'dot live'; connEl.textContent = 'Connected'; }
208
- else if (wsOpen) { dotEl.className = 'dot'; connEl.textContent = 'Waiting for Mudra Band\u2026'; }
209
- else { dotEl.className = 'dot'; connEl.textContent = simulating ? 'Simulated' : 'Disconnected'; }
210
- }
211
-
212
- /* ── Document Content ──────────────────────────────────────── */
213
- const sections = [
214
- {
215
- title: 'Introduction to Neural Computing',
216
- paragraphs: [
217
- 'Neural computing represents one of the most profound shifts in human-computer interaction. By capturing the faintest electrical signals from the nervous system, devices like the Mudra wristband translate intention into action, bypassing traditional input methods entirely.',
218
- 'The fundamental premise is elegant: when you think about moving your fingers, your brain sends electrical signals through motor neurons to the muscles in your forearm. These signals, known as electromyographic (EMG) signals, can be detected and decoded before the movement is even completed.'
219
- ],
220
- callout: 'Neural input does not require actual physical movement. The signals can be captured from the intention alone, opening up entirely new paradigms for accessibility and hands-free interaction.'
221
- },
222
- {
223
- title: 'Electromyography Fundamentals',
224
- paragraphs: [
225
- 'Electromyography (EMG) is the recording and analysis of electrical activity produced by skeletal muscles. When a motor neuron fires, it generates an action potential that propagates along the muscle fiber, creating a measurable electrical field.',
226
- 'Surface EMG sensors, like those in the Mudra wristband, detect these signals non-invasively through the skin. The raw signal is a complex interference pattern of many motor unit action potentials overlapping in time and space.',
227
- 'Signal processing pipelines typically include bandpass filtering (20-500 Hz), rectification, and envelope detection. Advanced systems use machine learning classifiers trained on labeled gesture data to recognize specific hand poses and movements.'
228
- ],
229
- callout: 'The Mudra Protocol v2 WebSocket interface streams processed neural data including pressure, navigation deltas, IMU readings, and discrete gesture events in real-time JSON packets at configurable frequencies.'
230
- },
231
- {
232
- title: 'Gesture Recognition Pipeline',
233
- paragraphs: [
234
- 'Converting raw EMG signals into discrete gestures involves several processing stages. The first stage is signal acquisition and preprocessing, where noise from power lines, motion artifacts, and other sources is filtered out.',
235
- 'Feature extraction follows, where time-domain features (mean absolute value, zero crossings, waveform length) and frequency-domain features (power spectral density, median frequency) are computed over sliding windows of typically 150 to 300 milliseconds.',
236
- 'Classification algorithms then map feature vectors to gesture labels. The Mudra system recognizes gestures including tap, double tap, twist, and double twist with associated confidence scores.',
237
- 'Latency is critical for real-time interaction. End-to-end latency from muscle activation to gesture output should remain below 100 milliseconds for the interaction to feel instantaneous.'
238
- ],
239
- callout: null
240
- },
241
- {
242
- title: 'Accelerometer and IMU Fusion',
243
- paragraphs: [
244
- 'Beyond EMG, the Mudra wristband incorporates a tri-axis accelerometer and gyroscope forming an inertial measurement unit. These sensors track the orientation and movement of the wrist in three-dimensional space.',
245
- 'Sensor fusion algorithms combine accelerometer, gyroscope, and EMG data to provide a richer understanding of user intent. The navigation signal provides continuous delta values for smooth pointing and scrolling.',
246
- 'Calibration is important for navigation-based control. The neutral wrist position defines the zero point, and sensitivity can be adjusted based on the range of comfortable motion for each user.'
247
- ],
248
- callout: 'The navigation signal provides continuous analog control like a joystick, while EMG gestures provide discrete events like button presses. This combination enables rich, expressive interaction without touching any surface.'
249
- },
250
- {
251
- title: 'WebSocket Protocol v2',
252
- paragraphs: [
253
- 'The Mudra Companion application exposes a WebSocket server on localhost port 8766. Client applications connect and subscribe to specific signals they need: gesture, pressure, navigation, imu_acc, imu_gyro, snc, button, and battery.',
254
- 'Each signal is subscribed individually using the command format. Data arrives as typed JSON messages with the signal type and a data payload containing the relevant values and a timestamp.',
255
- 'Connection management follows standard WebSocket patterns with automatic reconnection. Applications should implement simulation mode to generate realistic synthetic data for development without a physical device.',
256
- 'The protocol supports bidirectional communication. The trigger_gesture command allows applications to programmatically trigger gesture events, useful for testing and accessibility features.'
257
- ],
258
- callout: null
259
- },
260
- {
261
- title: 'Accessibility Applications',
262
- paragraphs: [
263
- 'Neural input technology has transformative potential for accessibility. People with limited mobility, speech difficulties, or conditions like ALS can use subtle muscle signals to communicate and control devices.',
264
- 'The gesture-to-speech paradigm maps neural gestures to spoken phrases, enabling communication through minimal physical effort. As the technology matures, the vocabulary and expressiveness of such systems will expand dramatically.',
265
- 'Environmental control systems allow users to operate smart home devices, navigate wheelchair controls, and interact with computers entirely through neural input. The low-latency, always-available nature of wrist-worn neural sensors makes them ideal for continuous assistive use.'
266
- ],
267
- callout: 'Unlike eye-tracking or head-tracking systems, neural input works regardless of lighting conditions, head position, or whether the user is looking at a screen. It is truly eyes-free and hands-free interaction.'
268
- },
269
- {
270
- title: 'Creative and Musical Applications',
271
- paragraphs: [
272
- 'Artists and musicians are discovering novel expressive possibilities with neural input. The continuous nature of pressure and navigation signals maps naturally to musical parameters like volume, pitch bend, and filter cutoff.',
273
- 'Step sequencers controlled by neural input allow musicians to compose beats using gestures for step selection and navigation deltas for parameter movement. The physical subtlety of the interaction opens up performance possibilities impossible with traditional controllers.',
274
- 'Visual artists can control generative art parameters in real-time, creating a feedback loop between neural intention and visual output. Pressure controls brush size, navigation drives spatial transformations, and gestures trigger discrete creative actions.'
275
- ],
276
- callout: null
277
- },
278
- {
279
- title: 'Future Directions',
280
- paragraphs: [
281
- 'The field of neural computing is advancing rapidly. Next-generation sensors will offer higher spatial resolution, capturing signals from individual motor units rather than aggregate muscle activity.',
282
- 'Machine learning models are becoming more personalized, adapting to individual users over time and recognizing an ever-growing vocabulary of gestures. Transfer learning techniques reduce the calibration burden for new users.',
283
- 'Integration with augmented and virtual reality systems represents a compelling frontier. Neural input provides the missing interaction modality for spatial computing, where traditional keyboards and mice are impractical.',
284
- 'As developers, we have the opportunity to shape this emerging interaction paradigm. The Mudra SDK and WebSocket protocol provide the foundation. What you build with it is limited only by imagination.'
285
- ],
286
- callout: 'The ultimate vision is a seamless neural interface where the boundary between thought and digital action dissolves entirely. The technology in your hands today is the first step toward that future.'
287
- }
288
- ];
289
-
290
- /* ── Build Document ────────────────────────────────────────── */
291
- const docScroll = document.getElementById('docScroll');
292
- const tocEl = document.getElementById('toc');
293
- const sectionEls = [];
294
- const tocItems = [];
295
-
296
- sections.forEach((sec, i) => {
297
- /* Document section */
298
- const div = document.createElement('div');
299
- div.className = 'section';
300
- div.id = 'sec-' + i;
301
-
302
- const h2 = document.createElement('h2');
303
- const numSpan = document.createElement('span');
304
- numSpan.className = 'num';
305
- numSpan.textContent = String(i + 1).padStart(2, '0');
306
- h2.appendChild(numSpan);
307
- h2.appendChild(document.createTextNode(sec.title));
308
- div.appendChild(h2);
309
-
310
- sec.paragraphs.forEach(text => {
311
- const p = document.createElement('p');
312
- p.textContent = text;
313
- div.appendChild(p);
314
- });
315
-
316
- if (sec.callout) {
317
- const co = document.createElement('div');
318
- co.className = 'callout';
319
- co.textContent = sec.callout;
320
- div.appendChild(co);
321
- }
322
-
323
- docScroll.appendChild(div);
324
- sectionEls.push(div);
325
-
326
- /* TOC entry */
327
- const tocItem = document.createElement('div');
328
- tocItem.className = 'toc-item' + (i === 0 ? ' active' : '');
329
- tocItem.textContent = sec.title;
330
- tocItem.addEventListener('click', () => {
331
- div.scrollIntoView({ behavior: 'smooth' });
332
- });
333
- tocEl.appendChild(tocItem);
334
- tocItems.push(tocItem);
335
- });
336
-
337
- /* ── Scrollbar ─────────────────────────────────────────────── */
338
- const scrollbarTrack = document.getElementById('scrollbarTrack');
339
- const scrollThumb = document.getElementById('scrollThumb');
340
- let bookmarks = [];
341
- let scanMode = false;
342
- let scrollSpeedMult = 0.3;
343
-
344
- function updateScrollbar() {
345
- const el = docScroll;
346
- const scrollH = el.scrollHeight;
347
- const clientH = el.clientHeight;
348
- if (scrollH <= clientH) { scrollThumb.style.display = 'none'; return; }
349
- scrollThumb.style.display = 'block';
350
- const ratio = clientH / scrollH;
351
- const thumbH = Math.max(30, ratio * clientH);
352
- scrollThumb.style.height = thumbH + 'px';
353
- const scrollRatio = el.scrollTop / (scrollH - clientH);
354
- scrollThumb.style.top = scrollRatio * (clientH - thumbH) + 'px';
355
- }
356
-
357
- function updateCurrentSection() {
358
- const scrollTop = docScroll.scrollTop + 60;
359
- let current = 0;
360
- sectionEls.forEach((el, i) => {
361
- if (el.offsetTop <= scrollTop) current = i;
362
- });
363
- tocItems.forEach((item, i) => item.classList.toggle('active', i === current));
364
- document.getElementById('sectionName').textContent = sections[current].title;
365
- }
366
-
367
- docScroll.addEventListener('scroll', () => { updateScrollbar(); updateCurrentSection(); });
368
- window.addEventListener('resize', updateScrollbar);
369
- setTimeout(updateScrollbar, 100);
370
-
371
- function addBookmark() {
372
- const scrollH = docScroll.scrollHeight;
373
- const clientH = docScroll.clientHeight;
374
- if (scrollH <= clientH) return;
375
- const pos = docScroll.scrollTop / (scrollH - clientH);
376
- bookmarks.push({ pos, scrollTop: docScroll.scrollTop });
377
- bookmarks.sort((a, b) => a.scrollTop - b.scrollTop);
378
- /* render marker */
379
- const marker = document.createElement('div');
380
- marker.className = 'bookmark-marker';
381
- marker.style.top = (pos * clientH) + 'px';
382
- scrollbarTrack.appendChild(marker);
383
- document.getElementById('bmCount').textContent = bookmarks.length + ' bookmark' + (bookmarks.length !== 1 ? 's' : '');
384
- }
385
-
386
- function jumpToNextBookmark() {
387
- if (bookmarks.length === 0) return;
388
- const current = docScroll.scrollTop;
389
- const next = bookmarks.find(b => b.scrollTop > current + 10);
390
- if (next) docScroll.scrollTo({ top: next.scrollTop, behavior: 'smooth' });
391
- else docScroll.scrollTo({ top: bookmarks[0].scrollTop, behavior: 'smooth' });
392
- }
393
-
394
- function clearBookmarks() {
395
- bookmarks = [];
396
- scrollbarTrack.querySelectorAll('.bookmark-marker').forEach(m => m.remove());
397
- document.getElementById('bmCount').textContent = '0 bookmarks';
398
- }
399
-
400
- function toggleScanMode() {
401
- scanMode = !scanMode;
402
- docScroll.classList.toggle('scan-mode', scanMode);
403
- const badge = document.getElementById('modeBadge');
404
- badge.textContent = scanMode ? 'Scan' : 'Reading';
405
- badge.classList.toggle('scan', scanMode);
406
- }
407
-
408
- /* ── Signal Handlers ───────────────────────────────────────── */
409
- let scrollAccY = 0;
410
-
411
- on('navigation', (d) => {
412
- const dy = d.delta_y || 0;
413
- /* smooth scroll: accumulate and apply */
414
- const speed = 2 + scrollSpeedMult * 8;
415
- docScroll.scrollTop += dy * speed;
416
- updateScrollbar();
417
- updateCurrentSection();
418
- });
419
-
420
- on('gesture', (d) => {
421
- const type = d.type || 'unknown';
422
- if (type === 'tap') addBookmark();
423
- if (type === 'double_tap') toggleScanMode();
424
- if (type === 'twist') jumpToNextBookmark();
425
- if (type === 'double_twist') clearBookmarks();
426
- });
427
-
428
- on('pressure', (d) => {
429
- scrollSpeedMult = Math.max(0, Math.min(1, d.normalized ?? d.value / 100));
430
- document.getElementById('speedFill').style.width = Math.round(scrollSpeedMult * 100) + '%';
431
- });
432
-
433
- /* ── Keyboard Fallback ─────────────────────────────────────── */
434
- let kbSpeed = 0.3;
435
- document.addEventListener('keydown', (e) => {
436
- if (e.code === 'ArrowDown') {
437
- e.preventDefault();
438
- docScroll.scrollTop += 40 + scrollSpeedMult * 60;
439
- updateScrollbar(); updateCurrentSection();
440
- }
441
- if (e.code === 'ArrowUp') {
442
- e.preventDefault();
443
- docScroll.scrollTop -= 40 + scrollSpeedMult * 60;
444
- updateScrollbar(); updateCurrentSection();
445
- }
446
- if (e.code === 'KeyB') addBookmark();
447
- if (e.code === 'KeyN') jumpToNextBookmark();
448
- if (e.code === 'KeyS') toggleScanMode();
449
- if (e.key === ']') {
450
- kbSpeed = Math.min(1, kbSpeed + 0.1);
451
- emit('pressure', { value: Math.round(kbSpeed * 100), normalized: kbSpeed, timestamp: Date.now() });
452
- }
453
- if (e.key === '[') {
454
- kbSpeed = Math.max(0, kbSpeed - 0.1);
455
- emit('pressure', { value: Math.round(kbSpeed * 100), normalized: kbSpeed, timestamp: Date.now() });
456
- }
457
- });
458
-
459
- /* ── Buttons ───────────────────────────────────────────────── */
460
- document.getElementById('simTap').addEventListener('click', () => triggerGesture('tap'));
461
- document.getElementById('simScan').addEventListener('click', () => triggerGesture('double_tap'));
462
- document.getElementById('modeBadge').addEventListener('click', toggleScanMode);
463
-
464
- /* ── Start ─────────────────────────────────────────────────── */
465
- connect();
466
- </script>
467
- </body>
468
- </html>