superlocalmemory 3.4.18 → 3.4.21

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 (172) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +42 -34
  3. package/bin/slm +11 -0
  4. package/bin/slm.bat +12 -0
  5. package/package.json +4 -3
  6. package/pyproject.toml +3 -2
  7. package/scripts/build-slm-hook.ps1 +40 -0
  8. package/scripts/build-slm-hook.sh +45 -0
  9. package/scripts/build_entry.py +452 -0
  10. package/scripts/ci/stage5b_gate.sh +50 -0
  11. package/scripts/postinstall/validation.js +187 -0
  12. package/scripts/postinstall-interactive.js +756 -0
  13. package/scripts/postinstall_binary.js +287 -0
  14. package/scripts/release_manifest.py +273 -0
  15. package/scripts/slm-hook.spec +56 -0
  16. package/skills/slm-build-graph/SKILL.md +423 -0
  17. package/skills/slm-list-recent/SKILL.md +348 -0
  18. package/skills/slm-recall/SKILL.md +343 -0
  19. package/skills/slm-remember/SKILL.md +194 -0
  20. package/skills/slm-show-patterns/SKILL.md +224 -0
  21. package/skills/slm-status/SKILL.md +363 -0
  22. package/skills/slm-switch-profile/SKILL.md +442 -0
  23. package/src/superlocalmemory/cli/commands.py +219 -79
  24. package/src/superlocalmemory/cli/context_commands.py +192 -0
  25. package/src/superlocalmemory/cli/daemon.py +15 -1
  26. package/src/superlocalmemory/cli/db_migrate.py +80 -0
  27. package/src/superlocalmemory/cli/escape_hatch.py +220 -0
  28. package/src/superlocalmemory/cli/main.py +72 -1
  29. package/src/superlocalmemory/core/context_cache.py +397 -0
  30. package/src/superlocalmemory/core/embeddings.py +8 -2
  31. package/src/superlocalmemory/core/engine.py +38 -2
  32. package/src/superlocalmemory/core/engine_wiring.py +1 -1
  33. package/src/superlocalmemory/core/ram_lock.py +111 -0
  34. package/src/superlocalmemory/core/recall_pipeline.py +433 -3
  35. package/src/superlocalmemory/core/recall_worker.py +8 -3
  36. package/src/superlocalmemory/core/security_primitives.py +635 -0
  37. package/src/superlocalmemory/core/shadow_router.py +319 -0
  38. package/src/superlocalmemory/core/slm_disabled.py +87 -0
  39. package/src/superlocalmemory/core/slmignore.py +125 -0
  40. package/src/superlocalmemory/core/topic_signature.py +143 -0
  41. package/src/superlocalmemory/core/worker_pool.py +14 -3
  42. package/src/superlocalmemory/encoding/cognitive_consolidator.py +2 -2
  43. package/src/superlocalmemory/evolution/budget.py +321 -0
  44. package/src/superlocalmemory/evolution/llm_dispatch.py +508 -0
  45. package/src/superlocalmemory/evolution/skill_evolver.py +144 -94
  46. package/src/superlocalmemory/hooks/_outcome_common.py +506 -0
  47. package/src/superlocalmemory/hooks/adapter_base.py +317 -0
  48. package/src/superlocalmemory/hooks/antigravity_adapter.py +192 -0
  49. package/src/superlocalmemory/hooks/claude_code_hooks.py +33 -1
  50. package/src/superlocalmemory/hooks/context_payload.py +312 -0
  51. package/src/superlocalmemory/hooks/copilot_adapter.py +154 -0
  52. package/src/superlocalmemory/hooks/cross_platform_connector.py +90 -0
  53. package/src/superlocalmemory/hooks/cursor_adapter.py +195 -0
  54. package/src/superlocalmemory/hooks/hook_handlers.py +109 -8
  55. package/src/superlocalmemory/hooks/ide_connector.py +25 -2
  56. package/src/superlocalmemory/hooks/post_tool_async_hook.py +165 -0
  57. package/src/superlocalmemory/hooks/post_tool_outcome_hook.py +223 -0
  58. package/src/superlocalmemory/hooks/prewarm_auth.py +170 -0
  59. package/src/superlocalmemory/hooks/session_registry.py +186 -0
  60. package/src/superlocalmemory/hooks/stop_outcome_hook.py +134 -0
  61. package/src/superlocalmemory/hooks/sync_loop.py +114 -0
  62. package/src/superlocalmemory/hooks/user_prompt_hook.py +128 -0
  63. package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +202 -0
  64. package/src/superlocalmemory/infra/backup.py +3 -3
  65. package/src/superlocalmemory/infra/cloud_backup.py +2 -2
  66. package/src/superlocalmemory/infra/event_bus.py +2 -2
  67. package/src/superlocalmemory/infra/webhook_dispatcher.py +3 -3
  68. package/src/superlocalmemory/learning/arm_catalog.py +99 -0
  69. package/src/superlocalmemory/learning/bandit.py +526 -0
  70. package/src/superlocalmemory/learning/bandit_cache.py +133 -0
  71. package/src/superlocalmemory/learning/behavioral.py +53 -1
  72. package/src/superlocalmemory/learning/consolidation_cycle.py +381 -0
  73. package/src/superlocalmemory/learning/consolidation_worker.py +188 -520
  74. package/src/superlocalmemory/learning/database.py +256 -0
  75. package/src/superlocalmemory/learning/dedup_hnsw.py +413 -0
  76. package/src/superlocalmemory/learning/ensemble.py +300 -0
  77. package/src/superlocalmemory/learning/fact_outcome_joins.py +207 -0
  78. package/src/superlocalmemory/learning/forgetting_scheduler.py +55 -0
  79. package/src/superlocalmemory/learning/hnsw_dedup.py +69 -0
  80. package/src/superlocalmemory/learning/labeler.py +87 -0
  81. package/src/superlocalmemory/learning/legacy_migration.py +277 -0
  82. package/src/superlocalmemory/learning/memory_merge.py +160 -0
  83. package/src/superlocalmemory/learning/model_cache.py +269 -0
  84. package/src/superlocalmemory/learning/model_rollback.py +278 -0
  85. package/src/superlocalmemory/learning/outcome_queue.py +284 -0
  86. package/src/superlocalmemory/learning/pattern_miner.py +415 -0
  87. package/src/superlocalmemory/learning/pattern_miner_constants.py +47 -0
  88. package/src/superlocalmemory/learning/ranker.py +225 -81
  89. package/src/superlocalmemory/learning/ranker_common.py +163 -0
  90. package/src/superlocalmemory/learning/ranker_retrain_legacy.py +202 -0
  91. package/src/superlocalmemory/learning/ranker_retrain_online.py +411 -0
  92. package/src/superlocalmemory/learning/reward.py +777 -0
  93. package/src/superlocalmemory/learning/reward_archive.py +210 -0
  94. package/src/superlocalmemory/learning/reward_boost.py +201 -0
  95. package/src/superlocalmemory/learning/reward_proxy.py +326 -0
  96. package/src/superlocalmemory/learning/shadow_test.py +524 -0
  97. package/src/superlocalmemory/learning/signal_worker.py +270 -0
  98. package/src/superlocalmemory/learning/signals.py +314 -0
  99. package/src/superlocalmemory/learning/trigram_index.py +547 -0
  100. package/src/superlocalmemory/mcp/server.py +5 -5
  101. package/src/superlocalmemory/mcp/tools_context.py +183 -0
  102. package/src/superlocalmemory/mcp/tools_core.py +92 -27
  103. package/src/superlocalmemory/parameterization/soft_prompt_generator.py +13 -0
  104. package/src/superlocalmemory/retrieval/engine.py +52 -0
  105. package/src/superlocalmemory/retrieval/reranker.py +4 -2
  106. package/src/superlocalmemory/server/api.py +2 -2
  107. package/src/superlocalmemory/server/bandit_loops.py +140 -0
  108. package/src/superlocalmemory/server/middleware/__init__.py +11 -0
  109. package/src/superlocalmemory/server/middleware/security_headers.py +144 -0
  110. package/src/superlocalmemory/server/routes/backup.py +36 -13
  111. package/src/superlocalmemory/server/routes/behavioral.py +50 -19
  112. package/src/superlocalmemory/server/routes/brain.py +1234 -0
  113. package/src/superlocalmemory/server/routes/data_io.py +4 -4
  114. package/src/superlocalmemory/server/routes/events.py +2 -2
  115. package/src/superlocalmemory/server/routes/helpers.py +1 -1
  116. package/src/superlocalmemory/server/routes/learning.py +192 -7
  117. package/src/superlocalmemory/server/routes/memories.py +189 -1
  118. package/src/superlocalmemory/server/routes/prewarm.py +171 -0
  119. package/src/superlocalmemory/server/routes/profiles.py +3 -3
  120. package/src/superlocalmemory/server/routes/token.py +88 -0
  121. package/src/superlocalmemory/server/routes/ws.py +5 -5
  122. package/src/superlocalmemory/server/security_middleware.py +13 -7
  123. package/src/superlocalmemory/server/ui.py +2 -2
  124. package/src/superlocalmemory/server/unified_daemon.py +335 -3
  125. package/src/superlocalmemory/storage/migration_runner.py +545 -0
  126. package/src/superlocalmemory/storage/migrations/M001_add_signal_features_columns.py +67 -0
  127. package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +132 -0
  128. package/src/superlocalmemory/storage/migrations/M003_migration_log.py +38 -0
  129. package/src/superlocalmemory/storage/migrations/M004_cross_platform_sync_log.py +46 -0
  130. package/src/superlocalmemory/storage/migrations/M005_bandit_tables.py +75 -0
  131. package/src/superlocalmemory/storage/migrations/M006_action_outcomes_reward.py +75 -0
  132. package/src/superlocalmemory/storage/migrations/M007_pending_outcomes.py +63 -0
  133. package/src/superlocalmemory/storage/migrations/M009_model_lineage.py +54 -0
  134. package/src/superlocalmemory/storage/migrations/M010_evolution_config.py +75 -0
  135. package/src/superlocalmemory/storage/migrations/M011_archive_and_merge.py +87 -0
  136. package/src/superlocalmemory/storage/migrations/M012_shadow_observations.py +72 -0
  137. package/src/superlocalmemory/storage/migrations/M013_bi_temporal_columns.py +55 -0
  138. package/src/superlocalmemory/storage/migrations/__init__.py +81 -0
  139. package/src/superlocalmemory/storage/models.py +4 -0
  140. package/src/superlocalmemory/ui/css/brain.css +409 -0
  141. package/src/superlocalmemory/ui/css/legacy-dashboard.css +645 -0
  142. package/src/superlocalmemory/ui/index.html +459 -1345
  143. package/src/superlocalmemory/ui/js/brain.js +1321 -0
  144. package/src/superlocalmemory/ui/js/clusters.js +123 -4
  145. package/src/superlocalmemory/ui/js/init.js +48 -39
  146. package/src/superlocalmemory/ui/js/memories.js +88 -2
  147. package/src/superlocalmemory/ui/js/modal.js +71 -1
  148. package/src/superlocalmemory/ui/js/ng-shell.js +101 -88
  149. package/src/superlocalmemory/ui/js/trust-dashboard.js +168 -25
  150. package/src/superlocalmemory/ui/vendor/bootstrap-icons/bootstrap-icons.css +2018 -0
  151. package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff +0 -0
  152. package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 +0 -0
  153. package/src/superlocalmemory/ui/vendor/bootstrap.bundle.min.js +7 -0
  154. package/src/superlocalmemory/ui/vendor/bootstrap.min.css +6 -0
  155. package/src/superlocalmemory/ui/vendor/d3.v7.min.js +2 -0
  156. package/src/superlocalmemory/ui/vendor/graphology-library.min.js +2 -0
  157. package/src/superlocalmemory/ui/vendor/graphology.umd.min.js +2 -0
  158. package/src/superlocalmemory/ui/vendor/inter-ui/inter-variable.min.css +8 -0
  159. package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable-Italic.woff2 +0 -0
  160. package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable.woff2 +0 -0
  161. package/src/superlocalmemory/ui/vendor/sigma.min.js +1 -0
  162. package/src/superlocalmemory/ui/js/behavioral.js +0 -447
  163. package/src/superlocalmemory/ui/js/graph-core.js +0 -447
  164. package/src/superlocalmemory/ui/js/graph-interactions.js +0 -351
  165. package/src/superlocalmemory/ui/js/learning.js +0 -435
  166. package/src/superlocalmemory/ui/js/patterns.js +0 -93
  167. package/src/superlocalmemory.egg-info/PKG-INFO +0 -647
  168. package/src/superlocalmemory.egg-info/SOURCES.txt +0 -335
  169. package/src/superlocalmemory.egg-info/dependency_links.txt +0 -1
  170. package/src/superlocalmemory.egg-info/entry_points.txt +0 -2
  171. package/src/superlocalmemory.egg-info/requires.txt +0 -58
  172. package/src/superlocalmemory.egg-info/top_level.txt +0 -1
@@ -0,0 +1,645 @@
1
+ /*
2
+ * Legacy dashboard styles — extracted from index.html inline <style>
3
+ * block in v3.4.21 (Phase F). No rule deletion in this pass; the purge of
4
+ * unused rules is a separate visual-audit cycle. Moving these 630 lines
5
+ * out of index.html means:
6
+ * - index.html drops from 1,814 → 1,184 lines (35% leaner)
7
+ * - CSP strict-src stays happy (external file under /static/css/)
8
+ * - Browser can cache the CSS independently of the HTML
9
+ *
10
+ * Live panes currently depend on: .stat-card*, #graph-container, .memory-*,
11
+ * .sortable, .cluster-card, .entity-badge, .profile-select, .theme-toggle,
12
+ * .backup-stat, .score-*, footer, plus the three @media blocks. Audit
13
+ * before deleting any rule from this file.
14
+ */
15
+
16
+ :root {
17
+ --slm-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
18
+ --slm-gradient-success: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
19
+ --slm-gradient-info: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
20
+ --slm-gradient-warning: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
21
+ }
22
+
23
+ html {
24
+ scroll-behavior: smooth;
25
+ }
26
+
27
+ body {
28
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
29
+ overflow-x: auto;
30
+ overflow-y: scroll;
31
+ min-width: min-content;
32
+ }
33
+
34
+ [data-bs-theme="light"] body,
35
+ [data-bs-theme="light"] {
36
+ background: #f8f9fa;
37
+ }
38
+
39
+ .navbar {
40
+ background: var(--slm-gradient);
41
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
42
+ }
43
+
44
+ /* Cloud account widget — sidebar (v3.4.10) */
45
+ #ng-account-widget:hover { background: rgba(255,255,255,0.06) !important; }
46
+ .account-dest-item { padding: 6px 0; display: flex; align-items: center; gap: 8px; }
47
+ .account-dest-badge { font-size: 10px; padding: 1px 6px; border-radius: 4px; }
48
+ .account-dest-badge.synced { background: rgba(0,212,170,0.15); color: #00D4AA; }
49
+ .account-dest-badge.failed { background: rgba(255,71,87,0.15); color: #ff4757; }
50
+ .account-dest-badge.never { background: rgba(255,255,255,0.06); color: #888; }
51
+
52
+ /* Stat cards with gradient backgrounds */
53
+ .stat-card {
54
+ border: none;
55
+ border-radius: 12px;
56
+ box-shadow: 0 4px 15px rgba(0,0,0,0.08);
57
+ transition: transform 0.2s, box-shadow 0.2s;
58
+ overflow: hidden;
59
+ position: relative;
60
+ }
61
+
62
+ .stat-card:hover {
63
+ transform: translateY(-5px);
64
+ box-shadow: 0 8px 25px rgba(0,0,0,0.12);
65
+ }
66
+
67
+ .stat-card .stat-bg {
68
+ position: absolute;
69
+ top: 0; left: 0; right: 0; bottom: 0;
70
+ opacity: 0.08;
71
+ border-radius: 12px;
72
+ }
73
+
74
+ .stat-card-memories .stat-bg { background: var(--slm-gradient); }
75
+ .stat-card-clusters .stat-bg { background: var(--slm-gradient-success); }
76
+ .stat-card-nodes .stat-bg { background: var(--slm-gradient-info); }
77
+ .stat-card-edges .stat-bg { background: var(--slm-gradient-warning); }
78
+
79
+ .stat-icon {
80
+ font-size: 2rem;
81
+ opacity: 0.8;
82
+ }
83
+
84
+ .stat-value {
85
+ font-size: 1.75rem;
86
+ font-weight: 700;
87
+ margin: 0;
88
+ }
89
+
90
+ .tab-content {
91
+ min-height: 700px;
92
+ overflow-x: auto;
93
+ overflow-y: visible;
94
+ }
95
+
96
+ .tab-pane {
97
+ overflow-x: auto;
98
+ overflow-y: visible;
99
+ }
100
+
101
+ #graph-container {
102
+ background: var(--bs-body-bg);
103
+ border-radius: 10px;
104
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
105
+ height: 600px !important;
106
+ max-height: 600px;
107
+ width: 100% !important;
108
+ position: relative;
109
+ overflow: hidden;
110
+ /* Mobile touch support - prevent default gestures */
111
+ touch-action: none;
112
+ -webkit-user-select: none;
113
+ -moz-user-select: none;
114
+ -ms-user-select: none;
115
+ user-select: none;
116
+ }
117
+
118
+ #graph-container canvas {
119
+ max-width: 100% !important;
120
+ max-height: 100% !important;
121
+ }
122
+
123
+ .node {
124
+ cursor: pointer;
125
+ stroke: #fff;
126
+ stroke-width: 2px;
127
+ }
128
+
129
+ .link {
130
+ stroke: #999;
131
+ stroke-opacity: 0.6;
132
+ }
133
+
134
+ .node-label {
135
+ font-size: 10px;
136
+ pointer-events: none;
137
+ fill: #333;
138
+ }
139
+
140
+ /* Memory table styling */
141
+ .memory-table {
142
+ font-size: 0.9rem;
143
+ }
144
+
145
+ .memory-table tbody tr {
146
+ cursor: pointer;
147
+ transition: background-color 0.15s;
148
+ }
149
+
150
+ .memory-table tbody tr:hover {
151
+ background-color: rgba(102, 126, 234, 0.08) !important;
152
+ }
153
+
154
+ .memory-content {
155
+ max-width: 350px;
156
+ overflow: hidden;
157
+ text-overflow: ellipsis;
158
+ white-space: nowrap;
159
+ }
160
+
161
+ .badge-importance {
162
+ min-width: 30px;
163
+ }
164
+
165
+ .search-box {
166
+ border-radius: 20px;
167
+ }
168
+
169
+ .cluster-card {
170
+ border-left: 4px solid;
171
+ margin-bottom: 1rem;
172
+ }
173
+
174
+ .entity-badge {
175
+ margin: 2px;
176
+ font-size: 0.8rem;
177
+ }
178
+
179
+ /* Loading spinner */
180
+ .loading {
181
+ text-align: center;
182
+ padding: 60px 40px;
183
+ color: #888;
184
+ }
185
+
186
+ .loading .spinner-border {
187
+ width: 2rem;
188
+ height: 2rem;
189
+ margin-bottom: 12px;
190
+ }
191
+
192
+ /* Empty state */
193
+ .empty-state {
194
+ text-align: center;
195
+ padding: 60px 40px;
196
+ color: #888;
197
+ }
198
+
199
+ .empty-state i {
200
+ font-size: 3rem;
201
+ opacity: 0.3;
202
+ margin-bottom: 12px;
203
+ }
204
+
205
+ .tooltip-custom {
206
+ position: absolute;
207
+ padding: 10px;
208
+ background: rgba(0,0,0,0.8);
209
+ color: white;
210
+ border-radius: 5px;
211
+ pointer-events: none;
212
+ font-size: 12px;
213
+ z-index: 1000;
214
+ max-width: 300px;
215
+ }
216
+
217
+ .timeline-chart {
218
+ min-height: 300px;
219
+ }
220
+
221
+ /* Score bar for search results */
222
+ .score-bar-container {
223
+ width: 80px;
224
+ display: inline-block;
225
+ vertical-align: middle;
226
+ }
227
+
228
+ .score-bar {
229
+ height: 8px;
230
+ border-radius: 4px;
231
+ background: #e9ecef;
232
+ overflow: hidden;
233
+ }
234
+
235
+ .score-bar-fill {
236
+ height: 100%;
237
+ border-radius: 4px;
238
+ transition: width 0.4s ease;
239
+ }
240
+
241
+ .score-label {
242
+ font-size: 0.75rem;
243
+ font-weight: 600;
244
+ min-width: 36px;
245
+ display: inline-block;
246
+ text-align: right;
247
+ margin-right: 6px;
248
+ vertical-align: middle;
249
+ }
250
+
251
+ /* Project select in navbar */
252
+ .profile-select {
253
+ background: rgba(255,255,255,0.15);
254
+ border: 1px solid rgba(255,255,255,0.3);
255
+ color: white;
256
+ border-radius: 20px;
257
+ padding: 2px 28px 2px 10px;
258
+ font-size: 0.85rem;
259
+ min-width: 120px;
260
+ cursor: pointer;
261
+ }
262
+
263
+ .profile-select option {
264
+ background: var(--bs-body-bg);
265
+ color: var(--bs-body-color);
266
+ }
267
+
268
+ /* Sortable table headers */
269
+ .sortable {
270
+ cursor: pointer;
271
+ user-select: none;
272
+ position: relative;
273
+ padding-right: 18px !important;
274
+ }
275
+
276
+ .sortable:hover {
277
+ background-color: rgba(102, 126, 234, 0.08);
278
+ }
279
+
280
+ .sortable::after {
281
+ content: '\F282';
282
+ font-family: 'bootstrap-icons';
283
+ position: absolute;
284
+ right: 4px;
285
+ opacity: 0.3;
286
+ font-size: 0.7rem;
287
+ }
288
+
289
+ .sortable.sort-asc::after {
290
+ content: '\F235';
291
+ opacity: 0.8;
292
+ }
293
+
294
+ .sortable.sort-desc::after {
295
+ content: '\F229';
296
+ opacity: 0.8;
297
+ }
298
+
299
+ /* Confidence bar for patterns */
300
+ .confidence-bar {
301
+ height: 6px;
302
+ border-radius: 3px;
303
+ background: var(--bs-border-color);
304
+ overflow: hidden;
305
+ margin-top: 4px;
306
+ }
307
+
308
+ .confidence-fill {
309
+ height: 100%;
310
+ border-radius: 3px;
311
+ transition: width 0.6s ease;
312
+ }
313
+
314
+ /* Backup status cards */
315
+ .backup-stat {
316
+ padding: 12px;
317
+ border-radius: 8px;
318
+ background: var(--bs-tertiary-bg);
319
+ text-align: center;
320
+ }
321
+
322
+ .backup-stat .value {
323
+ font-size: 1.3rem;
324
+ font-weight: 700;
325
+ }
326
+
327
+ .backup-stat .label {
328
+ font-size: 0.75rem;
329
+ color: var(--bs-secondary-color);
330
+ text-transform: uppercase;
331
+ }
332
+
333
+ /* Project delete button */
334
+ .btn-delete-profile {
335
+ padding: 2px 8px;
336
+ font-size: 0.75rem;
337
+ }
338
+
339
+ /* Dark mode toggle button */
340
+ .theme-toggle {
341
+ background: none;
342
+ border: 1px solid rgba(255,255,255,0.3);
343
+ color: white;
344
+ border-radius: 20px;
345
+ padding: 4px 12px;
346
+ font-size: 0.9rem;
347
+ cursor: pointer;
348
+ transition: background 0.2s;
349
+ }
350
+
351
+ .theme-toggle:hover {
352
+ background: rgba(255,255,255,0.15);
353
+ }
354
+
355
+ /* Modal content formatting */
356
+ .memory-detail-content {
357
+ white-space: pre-wrap;
358
+ word-break: break-word;
359
+ font-size: 0.95rem;
360
+ line-height: 1.6;
361
+ max-height: 400px;
362
+ overflow-y: auto;
363
+ padding: 16px;
364
+ background: var(--bs-tertiary-bg);
365
+ border-radius: 8px;
366
+ }
367
+
368
+ .memory-detail-meta dt {
369
+ font-weight: 600;
370
+ color: var(--bs-secondary-color);
371
+ font-size: 0.8rem;
372
+ text-transform: uppercase;
373
+ letter-spacing: 0.5px;
374
+ }
375
+
376
+ .memory-detail-meta dd {
377
+ margin-bottom: 12px;
378
+ }
379
+
380
+ /* Export dropdown */
381
+ .export-dropdown .dropdown-menu {
382
+ min-width: 200px;
383
+ }
384
+
385
+ /* Tab badge */
386
+ .tab-count {
387
+ font-size: 0.7rem;
388
+ vertical-align: super;
389
+ margin-left: 2px;
390
+ }
391
+
392
+ /* Footer */
393
+ footer {
394
+ text-align: center;
395
+ padding: 20px;
396
+ margin-top: 40px;
397
+ border-top: 1px solid var(--bs-border-color);
398
+ color: var(--bs-secondary-color);
399
+ }
400
+
401
+ footer a {
402
+ color: #667eea;
403
+ }
404
+
405
+ [data-bs-theme="dark"] footer a {
406
+ color: #8fa4ff;
407
+ }
408
+
409
+ /* ========================================
410
+ MOBILE & TABLET RESPONSIVE STYLES
411
+ ======================================== */
412
+
413
+ /* Tablet (768px and below) */
414
+ @media (max-width: 768px) {
415
+ .navbar-brand {
416
+ font-size: 1rem;
417
+ }
418
+
419
+ #navbar-subtitle {
420
+ display: none !important;
421
+ }
422
+
423
+ .stat-card {
424
+ margin-bottom: 12px;
425
+ }
426
+
427
+ .stat-value {
428
+ font-size: 1.4rem;
429
+ }
430
+
431
+ .stat-icon {
432
+ font-size: 1.5rem;
433
+ }
434
+
435
+ /* Graph container - smaller on tablet */
436
+ #graph-container {
437
+ height: 450px !important;
438
+ max-height: 450px;
439
+ }
440
+
441
+ /* Stack controls vertically on tablet */
442
+ .tab-pane .row > .col-md-6,
443
+ .tab-pane .row > .col-md-8,
444
+ .tab-pane .row > .col-md-4 {
445
+ margin-bottom: 10px;
446
+ }
447
+
448
+ /* Smaller buttons on mobile */
449
+ .btn-sm {
450
+ font-size: 0.8rem;
451
+ padding: 4px 8px;
452
+ }
453
+
454
+ /* Memory table - hide less important columns */
455
+ .memory-table th:nth-child(4),
456
+ .memory-table td:nth-child(4),
457
+ .memory-table th:nth-child(5),
458
+ .memory-table td:nth-child(5) {
459
+ display: none;
460
+ }
461
+
462
+ .memory-content {
463
+ max-width: 200px;
464
+ }
465
+ }
466
+
467
+ /* Mobile (480px and below) */
468
+ @media (max-width: 480px) {
469
+ body {
470
+ font-size: 0.9rem;
471
+ }
472
+
473
+ .navbar-brand {
474
+ font-size: 0.9rem;
475
+ }
476
+
477
+ .container-fluid {
478
+ padding-left: 10px;
479
+ padding-right: 10px;
480
+ }
481
+
482
+ /* Stat cards - 2 per row on mobile */
483
+ .col-6.mb-3 {
484
+ padding-left: 5px;
485
+ padding-right: 5px;
486
+ }
487
+
488
+ .stat-card {
489
+ padding: 12px 8px !important;
490
+ }
491
+
492
+ .stat-value {
493
+ font-size: 1.2rem;
494
+ }
495
+
496
+ .stat-icon {
497
+ font-size: 1.2rem;
498
+ }
499
+
500
+ .stat-card small {
501
+ font-size: 0.7rem;
502
+ }
503
+
504
+ /* Graph container - even smaller on mobile */
505
+ #graph-container {
506
+ height: 350px !important;
507
+ max-height: 350px;
508
+ border-radius: 6px;
509
+ }
510
+
511
+ /* Tabs - smaller text */
512
+ .nav-tabs .nav-link {
513
+ font-size: 0.8rem;
514
+ padding: 8px 10px;
515
+ }
516
+
517
+ .nav-tabs .nav-link i {
518
+ display: none;
519
+ }
520
+
521
+ /* Search controls - stack vertically */
522
+ #memories-pane .row > div {
523
+ margin-bottom: 8px;
524
+ }
525
+
526
+ /* Memory table - show only essentials */
527
+ .memory-table {
528
+ font-size: 0.8rem;
529
+ }
530
+
531
+ .memory-table th:nth-child(3),
532
+ .memory-table td:nth-child(3),
533
+ .memory-table th:nth-child(4),
534
+ .memory-table td:nth-child(4),
535
+ .memory-table th:nth-child(5),
536
+ .memory-table td:nth-child(5) {
537
+ display: none;
538
+ }
539
+
540
+ .memory-content {
541
+ max-width: 150px;
542
+ font-size: 0.75rem;
543
+ }
544
+
545
+ /* Modal - full screen on mobile */
546
+ .modal-dialog {
547
+ margin: 0;
548
+ max-width: 100%;
549
+ height: 100vh;
550
+ }
551
+
552
+ .modal-content {
553
+ height: 100%;
554
+ border-radius: 0;
555
+ }
556
+
557
+ /* Dropdown controls */
558
+ .form-select-sm {
559
+ font-size: 0.8rem;
560
+ padding: 4px 8px;
561
+ }
562
+
563
+ /* Project select - smaller */
564
+ .profile-select {
565
+ min-width: 90px;
566
+ font-size: 0.75rem;
567
+ padding: 2px 24px 2px 8px;
568
+ }
569
+
570
+ /* Theme toggle - smaller */
571
+ .theme-toggle {
572
+ font-size: 0.8rem;
573
+ padding: 3px 10px;
574
+ }
575
+
576
+ /* Footer - smaller text */
577
+ footer {
578
+ font-size: 0.75rem;
579
+ padding: 15px;
580
+ margin-top: 20px;
581
+ }
582
+
583
+ /* Graph controls - stack vertically on mobile */
584
+ #graph-pane .card .row > div {
585
+ margin-bottom: 10px;
586
+ }
587
+
588
+ /* Hide "Show All Memories" button text on mobile, icon only */
589
+ #graph-status-filtered .btn span {
590
+ display: none;
591
+ }
592
+
593
+ #graph-status-filtered .btn i::after {
594
+ content: ' All';
595
+ }
596
+ }
597
+
598
+ /* Landscape mobile (small height) */
599
+ @media (max-height: 500px) and (orientation: landscape) {
600
+ #graph-container {
601
+ height: 250px !important;
602
+ max-height: 250px;
603
+ }
604
+
605
+ .stat-card {
606
+ padding: 8px !important;
607
+ }
608
+
609
+ .stat-value {
610
+ font-size: 1rem;
611
+ }
612
+
613
+ .navbar {
614
+ padding: 5px 0;
615
+ }
616
+ }
617
+
618
+ /* Touch feedback for interactive elements */
619
+ @media (hover: none) and (pointer: coarse) {
620
+ /* This targets touch devices only */
621
+ .btn:active,
622
+ .nav-link:active,
623
+ .sortable:active {
624
+ opacity: 0.7;
625
+ transform: scale(0.98);
626
+ }
627
+
628
+ /* Larger tap targets on touch devices */
629
+ .btn {
630
+ min-height: 44px;
631
+ min-width: 44px;
632
+ }
633
+
634
+ .nav-tabs .nav-link {
635
+ min-height: 44px;
636
+ }
637
+
638
+ /* Prevent accidental double-tap zoom on buttons */
639
+ .btn,
640
+ .nav-link,
641
+ .form-control,
642
+ .form-select {
643
+ touch-action: manipulation;
644
+ }
645
+ }