ltcai 4.0.1 → 4.2.0

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 (192) hide show
  1. package/README.md +33 -24
  2. package/desktop/electron/main.cjs +44 -0
  3. package/docs/CHANGELOG.md +84 -0
  4. package/docs/V4_1_FRONTEND_ARCHITECTURE_REVIEW.md +65 -0
  5. package/docs/V4_1_FRONTEND_MIGRATION_REPORT.md +70 -0
  6. package/docs/V4_1_VALIDATION_REPORT.md +47 -0
  7. package/docs/V4_2_BRAIN_CORE_ARCHITECTURE.md +97 -0
  8. package/docs/V4_2_STORAGE_MIGRATION_REPORT.md +91 -0
  9. package/docs/V4_2_VALIDATION_REPORT.md +89 -0
  10. package/docs/V4_DIGITAL_BRAIN_RECOVERY.md +31 -26
  11. package/frontend/index.html +24 -0
  12. package/frontend/openapi.json +14436 -0
  13. package/frontend/src/App.tsx +184 -0
  14. package/frontend/src/api/client.ts +320 -0
  15. package/frontend/src/api/openapi.ts +16921 -0
  16. package/frontend/src/components/primitives.tsx +204 -0
  17. package/frontend/src/components/ui/badge.tsx +27 -0
  18. package/frontend/src/components/ui/button.tsx +37 -0
  19. package/frontend/src/components/ui/card.tsx +22 -0
  20. package/frontend/src/components/ui/input.tsx +16 -0
  21. package/frontend/src/components/ui/textarea.tsx +16 -0
  22. package/frontend/src/lib/utils.ts +33 -0
  23. package/frontend/src/main.tsx +23 -0
  24. package/frontend/src/pages/Act.tsx +245 -0
  25. package/frontend/src/pages/Ask.tsx +200 -0
  26. package/frontend/src/pages/Brain.tsx +267 -0
  27. package/frontend/src/pages/Capture.tsx +158 -0
  28. package/frontend/src/pages/Library.tsx +187 -0
  29. package/frontend/src/pages/System.tsx +378 -0
  30. package/frontend/src/routes.ts +85 -0
  31. package/frontend/src/store/appStore.ts +54 -0
  32. package/frontend/src/styles.css +107 -0
  33. package/kg_schema.py +1 -1
  34. package/knowledge_graph.py +4 -4
  35. package/lattice_brain/__init__.py +70 -0
  36. package/lattice_brain/_kg_common.py +1 -0
  37. package/lattice_brain/archive.py +133 -0
  38. package/lattice_brain/context.py +3 -0
  39. package/lattice_brain/conversations.py +3 -0
  40. package/lattice_brain/core.py +82 -0
  41. package/lattice_brain/discovery.py +1 -0
  42. package/lattice_brain/documents.py +1 -0
  43. package/lattice_brain/embeddings.py +82 -0
  44. package/lattice_brain/identity.py +13 -0
  45. package/lattice_brain/ingest.py +1 -0
  46. package/lattice_brain/memory.py +3 -0
  47. package/lattice_brain/network.py +1 -0
  48. package/lattice_brain/projection.py +1 -0
  49. package/lattice_brain/provenance.py +1 -0
  50. package/lattice_brain/retrieval.py +1 -0
  51. package/lattice_brain/schema.py +1 -0
  52. package/lattice_brain/storage/__init__.py +22 -0
  53. package/lattice_brain/storage/base.py +72 -0
  54. package/lattice_brain/storage/docker.py +105 -0
  55. package/lattice_brain/storage/factory.py +31 -0
  56. package/lattice_brain/storage/migration.py +190 -0
  57. package/lattice_brain/storage/postgres.py +123 -0
  58. package/lattice_brain/storage/sqlite.py +128 -0
  59. package/lattice_brain/store.py +3 -0
  60. package/lattice_brain/write_master.py +1 -0
  61. package/latticeai/__init__.py +1 -1
  62. package/latticeai/api/portability.py +69 -0
  63. package/latticeai/api/setup.py +5 -4
  64. package/latticeai/api/static_routes.py +4 -4
  65. package/latticeai/app_factory.py +17 -10
  66. package/latticeai/brain/__init__.py +6 -6
  67. package/latticeai/brain/_kg_common.py +1 -1
  68. package/latticeai/brain/network.py +1 -1
  69. package/latticeai/brain/retrieval.py +15 -0
  70. package/latticeai/brain/store.py +22 -6
  71. package/latticeai/core/config.py +8 -0
  72. package/latticeai/core/marketplace.py +1 -1
  73. package/latticeai/core/multi_agent.py +1 -1
  74. package/latticeai/core/workspace_os.py +1 -1
  75. package/latticeai/services/kg_portability.py +82 -1
  76. package/package.json +55 -15
  77. package/scripts/build_frontend_assets.mjs +38 -0
  78. package/scripts/bump_version.py +4 -1
  79. package/scripts/export_openapi.py +31 -0
  80. package/scripts/lint_frontend.mjs +91 -0
  81. package/scripts/migrate_brain_storage.py +53 -0
  82. package/scripts/run_python.mjs +47 -0
  83. package/scripts/wheel_smoke.py +3 -0
  84. package/src-tauri/Cargo.lock +4833 -0
  85. package/src-tauri/Cargo.toml +19 -0
  86. package/src-tauri/build.rs +3 -0
  87. package/src-tauri/capabilities/default.json +7 -0
  88. package/src-tauri/src/main.rs +78 -0
  89. package/src-tauri/tauri.conf.json +39 -0
  90. package/static/app/asset-manifest.json +32 -0
  91. package/static/app/assets/core-CwxXejkd.js +2 -0
  92. package/static/app/assets/core-CwxXejkd.js.map +1 -0
  93. package/static/app/assets/index-CDjiH_se.css +2 -0
  94. package/static/app/assets/index-C_HAkbAg.js +333 -0
  95. package/static/app/assets/index-C_HAkbAg.js.map +1 -0
  96. package/static/app/index.html +25 -0
  97. package/static/manifest.json +2 -2
  98. package/static/sw.js +4 -4
  99. package/scripts/build_v3_assets.mjs +0 -170
  100. package/scripts/lint_v3.mjs +0 -120
  101. package/static/v3/asset-manifest.json +0 -63
  102. package/static/v3/css/lattice.base.49deefb5.css +0 -128
  103. package/static/v3/css/lattice.base.css +0 -128
  104. package/static/v3/css/lattice.components.cde18231.css +0 -472
  105. package/static/v3/css/lattice.components.css +0 -472
  106. package/static/v3/css/lattice.shell.29d36d85.css +0 -452
  107. package/static/v3/css/lattice.shell.css +0 -452
  108. package/static/v3/css/lattice.tokens.304cbc40.css +0 -135
  109. package/static/v3/css/lattice.tokens.css +0 -135
  110. package/static/v3/css/lattice.views.0a18b6c5.css +0 -360
  111. package/static/v3/css/lattice.views.css +0 -360
  112. package/static/v3/index.html +0 -68
  113. package/static/v3/js/app.c5c80c46.js +0 -26
  114. package/static/v3/js/app.js +0 -26
  115. package/static/v3/js/core/api.ba0fbf14.js +0 -625
  116. package/static/v3/js/core/api.js +0 -625
  117. package/static/v3/js/core/components.f25b3b93.js +0 -230
  118. package/static/v3/js/core/components.js +0 -230
  119. package/static/v3/js/core/dom.a2773eb0.js +0 -148
  120. package/static/v3/js/core/dom.js +0 -148
  121. package/static/v3/js/core/i18n.880e1fec.js +0 -575
  122. package/static/v3/js/core/i18n.js +0 -575
  123. package/static/v3/js/core/router.584570f2.js +0 -37
  124. package/static/v3/js/core/router.js +0 -37
  125. package/static/v3/js/core/routes.37522821.js +0 -101
  126. package/static/v3/js/core/routes.js +0 -101
  127. package/static/v3/js/core/shell.e3f6bbfa.js +0 -420
  128. package/static/v3/js/core/shell.js +0 -420
  129. package/static/v3/js/core/store.7b2aa044.js +0 -123
  130. package/static/v3/js/core/store.js +0 -123
  131. package/static/v3/js/views/account.eff40715.js +0 -143
  132. package/static/v3/js/views/account.js +0 -143
  133. package/static/v3/js/views/activity.0d271ef9.js +0 -67
  134. package/static/v3/js/views/activity.js +0 -67
  135. package/static/v3/js/views/admin-audit.660a1fb1.js +0 -185
  136. package/static/v3/js/views/admin-audit.js +0 -185
  137. package/static/v3/js/views/admin-permissions.a7ae5f09.js +0 -177
  138. package/static/v3/js/views/admin-permissions.js +0 -177
  139. package/static/v3/js/views/admin-policies.3658fd86.js +0 -102
  140. package/static/v3/js/views/admin-policies.js +0 -102
  141. package/static/v3/js/views/admin-private-vpc.7d342d36.js +0 -135
  142. package/static/v3/js/views/admin-private-vpc.js +0 -135
  143. package/static/v3/js/views/admin-security.07c66b72.js +0 -180
  144. package/static/v3/js/views/admin-security.js +0 -180
  145. package/static/v3/js/views/admin-users.f7ac7b43.js +0 -166
  146. package/static/v3/js/views/admin-users.js +0 -166
  147. package/static/v3/js/views/agents.17c5288d.js +0 -564
  148. package/static/v3/js/views/agents.js +0 -564
  149. package/static/v3/js/views/chat.e250e2cc.js +0 -624
  150. package/static/v3/js/views/chat.js +0 -624
  151. package/static/v3/js/views/files.adad14c1.js +0 -365
  152. package/static/v3/js/views/files.js +0 -365
  153. package/static/v3/js/views/graph-canvas.17c15d65.js +0 -509
  154. package/static/v3/js/views/graph-canvas.js +0 -509
  155. package/static/v3/js/views/home.24f8b8ae.js +0 -200
  156. package/static/v3/js/views/home.js +0 -200
  157. package/static/v3/js/views/hooks.37895880.js +0 -220
  158. package/static/v3/js/views/hooks.js +0 -220
  159. package/static/v3/js/views/hybrid-search.2fb63ed9.js +0 -194
  160. package/static/v3/js/views/hybrid-search.js +0 -194
  161. package/static/v3/js/views/knowledge-graph.4d09c537.js +0 -529
  162. package/static/v3/js/views/knowledge-graph.js +0 -529
  163. package/static/v3/js/views/marketplace.ab0583d4.js +0 -141
  164. package/static/v3/js/views/marketplace.js +0 -141
  165. package/static/v3/js/views/mcp.99b5c6a7.js +0 -114
  166. package/static/v3/js/views/mcp.js +0 -114
  167. package/static/v3/js/views/memory.4ebdf474.js +0 -147
  168. package/static/v3/js/views/memory.js +0 -147
  169. package/static/v3/js/views/models.a1ffa147.js +0 -256
  170. package/static/v3/js/views/models.js +0 -256
  171. package/static/v3/js/views/my-computer.d9d9ae1c.js +0 -463
  172. package/static/v3/js/views/my-computer.js +0 -463
  173. package/static/v3/js/views/network.52a4f181.js +0 -97
  174. package/static/v3/js/views/network.js +0 -97
  175. package/static/v3/js/views/pipeline.c522f1ce.js +0 -157
  176. package/static/v3/js/views/pipeline.js +0 -157
  177. package/static/v3/js/views/planning.4876fd77.js +0 -174
  178. package/static/v3/js/views/planning.js +0 -174
  179. package/static/v3/js/views/runs.b63b2afa.js +0 -144
  180. package/static/v3/js/views/runs.js +0 -144
  181. package/static/v3/js/views/settings.b7140634.js +0 -317
  182. package/static/v3/js/views/settings.js +0 -317
  183. package/static/v3/js/views/skills.c6c2f965.js +0 -109
  184. package/static/v3/js/views/skills.js +0 -109
  185. package/static/v3/js/views/snapshots.6f5db095.js +0 -135
  186. package/static/v3/js/views/snapshots.js +0 -135
  187. package/static/v3/js/views/tools.e4f11276.js +0 -108
  188. package/static/v3/js/views/tools.js +0 -108
  189. package/static/v3/js/views/workflows.7752225a.js +0 -213
  190. package/static/v3/js/views/workflows.js +0 -213
  191. package/static/v3/js/views/workspace-admin.c466029b.js +0 -156
  192. package/static/v3/js/views/workspace-admin.js +0 -156
@@ -1,472 +0,0 @@
1
- /* ============================================================================
2
- * Lattice AI v3 — Component primitives
3
- * The shared vocabulary every view composes from. Token-native, theme-aware.
4
- * ========================================================================== */
5
-
6
- /* ── Layout primitives ──────────────────────────────────────────────────── */
7
- .lt3-stack { display: flex; flex-direction: column; gap: var(--lt3-space-4); }
8
- .lt3-stack-2 { display: flex; flex-direction: column; gap: var(--lt3-space-2); }
9
- .lt3-stack-3 { display: flex; flex-direction: column; gap: var(--lt3-space-3); }
10
- .lt3-stack-6 { display: flex; flex-direction: column; gap: var(--lt3-space-6); }
11
- .lt3-row { display: flex; align-items: center; gap: var(--lt3-space-3); }
12
- .lt3-row-2 { display: flex; align-items: center; gap: var(--lt3-space-2); }
13
- .lt3-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--lt3-space-2); }
14
- .lt3-spacer { flex: 1 1 auto; }
15
- .lt3-grid { display: grid; gap: var(--lt3-space-4); }
16
- .lt3-grid-auto {
17
- display: grid;
18
- gap: var(--lt3-space-4);
19
- grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
20
- }
21
- .lt3-grid-2 { display: grid; gap: var(--lt3-space-5); grid-template-columns: repeat(2, minmax(0, 1fr)); }
22
- .lt3-grid-3 { display: grid; gap: var(--lt3-space-4); grid-template-columns: repeat(3, minmax(0, 1fr)); }
23
-
24
- /* ── Eyebrow / labels ───────────────────────────────────────────────────── */
25
- .lt3-eyebrow {
26
- font-size: var(--lt3-text-2xs);
27
- font-weight: var(--lt3-weight-semi);
28
- letter-spacing: var(--lt3-tracking-caps);
29
- text-transform: uppercase;
30
- color: var(--faint);
31
- }
32
- .lt3-muted { color: var(--muted); }
33
- .lt3-faint { color: var(--faint); }
34
- .lt3-mono { font-family: var(--lt3-font-mono); font-size: 0.92em; }
35
-
36
- /* ── Card / Panel ───────────────────────────────────────────────────────── */
37
- .lt3-card,
38
- .lt3-panel {
39
- position: relative;
40
- background: var(--card);
41
- border: 1px solid var(--border);
42
- border-radius: var(--lt3-radius-md);
43
- box-shadow: var(--lt3-elev-1);
44
- }
45
- .lt3-panel { padding: var(--lt3-space-5); }
46
- .lt3-card { padding: var(--lt3-space-4); }
47
- .lt3-card--flat { box-shadow: none; background: var(--surface-2); }
48
- .lt3-card--ghost { background: transparent; border-style: dashed; box-shadow: none; }
49
- .lt3-card--interactive { transition: transform var(--lt3-dur-2) var(--lt3-ease), border-color var(--lt3-dur-2) var(--lt3-ease), box-shadow var(--lt3-dur-2) var(--lt3-ease), background var(--lt3-dur-2) var(--lt3-ease); }
50
- .lt3-card--interactive:hover {
51
- transform: translateY(-1px);
52
- border-color: color-mix(in srgb, var(--accent) 42%, var(--border));
53
- background: var(--surface);
54
- box-shadow: var(--lt3-elev-1);
55
- }
56
-
57
- .lt3-panel__head {
58
- display: flex;
59
- align-items: flex-start;
60
- justify-content: space-between;
61
- gap: var(--lt3-space-3);
62
- margin-bottom: var(--lt3-space-4);
63
- }
64
- .lt3-panel__title {
65
- font-size: var(--lt3-text-md);
66
- font-weight: var(--lt3-weight-semi);
67
- letter-spacing: var(--lt3-tracking-tight);
68
- }
69
- .lt3-panel__sub { font-size: var(--lt3-text-sm); color: var(--muted); }
70
-
71
- /* ── Buttons ────────────────────────────────────────────────────────────── */
72
- .lt3-btn {
73
- display: inline-flex;
74
- align-items: center;
75
- justify-content: center;
76
- gap: var(--lt3-space-2);
77
- height: 36px;
78
- padding: 0 var(--lt3-space-4);
79
- border-radius: var(--lt3-radius-sm);
80
- border: 1px solid transparent;
81
- font-size: var(--lt3-text-sm);
82
- font-weight: var(--lt3-weight-semi);
83
- white-space: nowrap;
84
- transition: background var(--lt3-dur-2) var(--lt3-ease), border-color var(--lt3-dur-2) var(--lt3-ease), transform var(--lt3-dur-1) var(--lt3-ease), color var(--lt3-dur-2) var(--lt3-ease);
85
- }
86
- .lt3-btn:active { transform: translateY(1px); }
87
- .lt3-btn[disabled] { opacity: 0.5; pointer-events: none; }
88
- .lt3-btn .ti { font-size: 1.05rem; }
89
-
90
- .lt3-btn--primary { background: var(--accent); color: var(--lt3-on-accent); box-shadow: var(--lt3-elev-1); }
91
- .lt3-btn--primary:hover { background: var(--accent-deep); }
92
- .lt3-btn--ghost { background: var(--surface-2); border-color: var(--border); color: var(--text); }
93
- .lt3-btn--ghost:hover { border-color: var(--border-strong); background: var(--surface-3); }
94
- .lt3-btn--subtle { background: transparent; color: var(--muted); }
95
- .lt3-btn--subtle:hover { background: var(--surface-2); color: var(--text); }
96
- .lt3-btn--danger { background: var(--lt3-err-soft); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
97
- .lt3-btn--danger:hover { background: color-mix(in srgb, var(--danger) 24%, transparent); }
98
- .lt3-btn--sm { height: 30px; padding: 0 var(--lt3-space-3); font-size: var(--lt3-text-xs); }
99
- .lt3-btn--lg { height: 42px; padding: 0 var(--lt3-space-5); font-size: var(--lt3-text-sm); }
100
- .lt3-btn--block { width: 100%; }
101
-
102
- .lt3-iconbtn {
103
- display: inline-flex;
104
- align-items: center;
105
- justify-content: center;
106
- width: 36px;
107
- height: 36px;
108
- border-radius: var(--lt3-radius-sm);
109
- color: var(--muted);
110
- transition: background var(--lt3-dur-2) var(--lt3-ease), color var(--lt3-dur-2) var(--lt3-ease);
111
- }
112
- .lt3-iconbtn:hover { background: var(--surface-2); color: var(--text); }
113
- .lt3-iconbtn .ti { font-size: 1.2rem; }
114
- .lt3-iconbtn--sm { width: 30px; height: 30px; }
115
-
116
- /* ── Inputs ─────────────────────────────────────────────────────────────── */
117
- .lt3-input, .lt3-select, .lt3-textarea {
118
- width: 100%;
119
- height: 38px;
120
- padding: 0 var(--lt3-space-3);
121
- background: var(--input);
122
- border: 1px solid var(--border);
123
- border-radius: var(--lt3-radius-sm);
124
- color: var(--text);
125
- font-size: var(--lt3-text-sm);
126
- transition: border-color var(--lt3-dur-2) var(--lt3-ease), box-shadow var(--lt3-dur-2) var(--lt3-ease);
127
- }
128
- .lt3-textarea { height: auto; min-height: 96px; padding: var(--lt3-space-3) var(--lt3-space-4); line-height: var(--lt3-leading-snug); }
129
- .lt3-input::placeholder, .lt3-textarea::placeholder { color: var(--faint); }
130
- .lt3-input:focus, .lt3-select:focus, .lt3-textarea:focus {
131
- outline: none;
132
- border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
133
- box-shadow: 0 0 0 3px var(--accent-soft);
134
- }
135
- .lt3-field { display: flex; flex-direction: column; gap: var(--lt3-space-2); }
136
- .lt3-label { font-size: var(--lt3-text-xs); font-weight: var(--lt3-weight-medium); color: var(--muted); }
137
- .lt3-help { font-size: var(--lt3-text-xs); color: var(--faint); }
138
-
139
- .lt3-search {
140
- display: flex;
141
- align-items: center;
142
- gap: var(--lt3-space-2);
143
- height: 40px;
144
- padding: 0 var(--lt3-space-4);
145
- background: var(--input);
146
- border: 1px solid var(--border);
147
- border-radius: var(--lt3-radius-pill);
148
- }
149
- .lt3-search .ti { color: var(--faint); font-size: 1.15rem; }
150
- .lt3-search input { flex: 1; height: 100%; background: none; border: none; outline: none; font-size: var(--lt3-text-md); }
151
-
152
- /* ── Pills / badges / chips ─────────────────────────────────────────────── */
153
- .lt3-pill {
154
- display: inline-flex;
155
- align-items: center;
156
- gap: var(--lt3-space-1);
157
- height: 24px;
158
- padding: 0 var(--lt3-space-3);
159
- border-radius: var(--lt3-radius-pill);
160
- font-size: var(--lt3-text-2xs);
161
- font-weight: var(--lt3-weight-semi);
162
- letter-spacing: var(--lt3-tracking-wide);
163
- background: var(--surface-2);
164
- color: var(--muted);
165
- border: 1px solid var(--border);
166
- }
167
- .lt3-pill--ok { background: var(--lt3-ok-soft); color: var(--success); border-color: transparent; }
168
- .lt3-pill--warn { background: var(--lt3-warn-soft); color: var(--warning); border-color: transparent; }
169
- .lt3-pill--err { background: var(--lt3-err-soft); color: var(--danger); border-color: transparent; }
170
- .lt3-pill--info { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
171
- .lt3-pill--dot::before {
172
- content: ""; width: 6px; height: 6px; border-radius: 99px;
173
- background: currentColor; display: inline-block;
174
- }
175
-
176
- .lt3-chip {
177
- display: inline-flex;
178
- align-items: center;
179
- gap: var(--lt3-space-2);
180
- height: 30px;
181
- padding: 0 var(--lt3-space-3);
182
- border-radius: var(--lt3-radius-pill);
183
- background: var(--surface-2);
184
- border: 1px solid var(--border);
185
- font-size: var(--lt3-text-xs);
186
- font-weight: var(--lt3-weight-medium);
187
- color: var(--text);
188
- transition: border-color var(--lt3-dur-2) var(--lt3-ease), background var(--lt3-dur-2) var(--lt3-ease);
189
- }
190
- .lt3-chip[data-active="true"] { border-color: color-mix(in srgb, var(--accent) 55%, transparent); background: var(--accent-soft); color: var(--accent); }
191
- .lt3-chip:hover { border-color: var(--border-strong); }
192
-
193
- .lt3-kbd {
194
- display: inline-flex;
195
- align-items: center;
196
- height: 20px;
197
- padding: 0 6px;
198
- border-radius: 5px;
199
- background: var(--surface-3);
200
- border: 1px solid var(--border);
201
- border-bottom-width: 2px;
202
- font-family: var(--lt3-font-mono);
203
- font-size: var(--lt3-text-2xs);
204
- color: var(--muted);
205
- }
206
-
207
- /* Data-provenance tag: clearly marks unavailable vs live data */
208
- .lt3-source {
209
- display: inline-flex;
210
- align-items: center;
211
- gap: var(--lt3-space-1);
212
- height: 20px;
213
- padding: 0 var(--lt3-space-2);
214
- border-radius: var(--lt3-radius-pill);
215
- font-size: var(--lt3-text-2xs);
216
- font-weight: var(--lt3-weight-semi);
217
- letter-spacing: var(--lt3-tracking-wide);
218
- text-transform: uppercase;
219
- }
220
- .lt3-source--unavailable { background: var(--lt3-warn-soft); color: var(--warning); }
221
- .lt3-source--live { background: var(--lt3-ok-soft); color: var(--success); }
222
- .lt3-source--pending { background: var(--surface-2); color: var(--faint); }
223
-
224
- /* ── Stat tile ──────────────────────────────────────────────────────────── */
225
- .lt3-stat {
226
- display: grid;
227
- grid-template-columns: minmax(0, 1fr) auto;
228
- align-items: start;
229
- gap: var(--lt3-space-2);
230
- min-height: 88px;
231
- padding: var(--lt3-space-4);
232
- background: var(--card);
233
- border: 1px solid var(--border);
234
- border-radius: var(--lt3-radius-md);
235
- }
236
- .lt3-stat__label {
237
- grid-column: 1 / -1;
238
- font-size: var(--lt3-text-xs);
239
- color: var(--muted);
240
- display: flex;
241
- align-items: center;
242
- gap: var(--lt3-space-2);
243
- }
244
- .lt3-stat__label .ti {
245
- display: inline-grid;
246
- place-items: center;
247
- width: 24px;
248
- height: 24px;
249
- border-radius: var(--lt3-radius-xs);
250
- background: var(--surface-2);
251
- color: var(--accent);
252
- }
253
- .lt3-stat__value { font-size: var(--lt3-text-2xl); font-weight: var(--lt3-weight-bold); letter-spacing: var(--lt3-tracking-tight); line-height: 1.1; }
254
- .lt3-stat__delta { justify-self: end; font-size: var(--lt3-text-2xs); color: var(--muted); }
255
- .lt3-stat__delta--up { color: var(--success); }
256
- .lt3-stat__delta--down { color: var(--danger); }
257
-
258
- /* ── Tables ─────────────────────────────────────────────────────────────── */
259
- .lt3-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--lt3-text-sm); }
260
- .lt3-table th {
261
- text-align: left;
262
- font-size: var(--lt3-text-2xs);
263
- font-weight: var(--lt3-weight-semi);
264
- letter-spacing: var(--lt3-tracking-caps);
265
- text-transform: uppercase;
266
- color: var(--faint);
267
- padding: var(--lt3-space-3) var(--lt3-space-4);
268
- border-bottom: 1px solid var(--border);
269
- position: sticky; top: 0; background: var(--surface-elevated); z-index: 1;
270
- }
271
- .lt3-table td {
272
- padding: var(--lt3-space-3) var(--lt3-space-4);
273
- border-bottom: 1px solid var(--line);
274
- vertical-align: middle;
275
- }
276
- .lt3-table tr:last-child td { border-bottom: none; }
277
- .lt3-table tbody tr { transition: background var(--lt3-dur-1) var(--lt3-ease); }
278
- .lt3-table tbody tr:hover { background: var(--surface-2); }
279
- .lt3-table--clip { border: 1px solid var(--border); border-radius: var(--lt3-radius-md); overflow: hidden; background: var(--card); }
280
-
281
- /* ── List rows ──────────────────────────────────────────────────────────── */
282
- .lt3-list { display: flex; flex-direction: column; }
283
- .lt3-list__item {
284
- display: flex;
285
- align-items: center;
286
- gap: var(--lt3-space-3);
287
- padding: var(--lt3-space-3) var(--lt3-space-1);
288
- border-bottom: 1px solid var(--line);
289
- }
290
- .lt3-list__item:last-child { border-bottom: none; }
291
- .lt3-list__body { flex: 1; min-width: 0; }
292
- .lt3-list__title { font-weight: var(--lt3-weight-medium); font-size: var(--lt3-text-sm); }
293
- .lt3-list__meta { font-size: var(--lt3-text-xs); color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
294
-
295
- /* ── Tabs / segmented ───────────────────────────────────────────────────── */
296
- .lt3-tabs { display: inline-flex; gap: var(--lt3-space-1); border-bottom: 1px solid var(--border); }
297
- .lt3-tab {
298
- padding: var(--lt3-space-3) var(--lt3-space-4);
299
- font-size: var(--lt3-text-sm);
300
- font-weight: var(--lt3-weight-medium);
301
- color: var(--muted);
302
- border-bottom: 2px solid transparent;
303
- margin-bottom: -1px;
304
- transition: color var(--lt3-dur-2) var(--lt3-ease), border-color var(--lt3-dur-2) var(--lt3-ease);
305
- }
306
- .lt3-tab[data-active="true"] { color: var(--text); border-bottom-color: var(--accent); }
307
- .lt3-tab:hover { color: var(--text); }
308
-
309
- .lt3-seg {
310
- display: inline-flex;
311
- padding: 3px;
312
- gap: 2px;
313
- background: var(--surface-2);
314
- border: 1px solid var(--border);
315
- border-radius: var(--lt3-radius-md);
316
- }
317
- .lt3-seg button {
318
- padding: var(--lt3-space-2) var(--lt3-space-3);
319
- border-radius: var(--lt3-radius-sm);
320
- font-size: var(--lt3-text-xs);
321
- font-weight: var(--lt3-weight-semi);
322
- color: var(--muted);
323
- transition: background var(--lt3-dur-2) var(--lt3-ease), color var(--lt3-dur-2) var(--lt3-ease);
324
- }
325
- .lt3-seg button[data-active="true"] { background: var(--surface); color: var(--text); box-shadow: var(--lt3-elev-1); }
326
-
327
- /* ── Toggle switch ──────────────────────────────────────────────────────── */
328
- .lt3-switch { position: relative; display: inline-flex; width: 42px; height: 24px; flex: none; }
329
- .lt3-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
330
- .lt3-switch span {
331
- position: absolute; inset: 0;
332
- background: var(--surface-3);
333
- border: 1px solid var(--border);
334
- border-radius: 99px;
335
- transition: background var(--lt3-dur-2) var(--lt3-ease);
336
- }
337
- .lt3-switch span::after {
338
- content: ""; position: absolute; top: 2px; left: 2px;
339
- width: 18px; height: 18px; border-radius: 99px;
340
- background: var(--surface); box-shadow: var(--lt3-elev-1);
341
- transition: transform var(--lt3-dur-2) var(--lt3-ease);
342
- }
343
- .lt3-switch input:checked + span { background: var(--accent); border-color: transparent; }
344
- .lt3-switch input:checked + span::after { transform: translateX(18px); }
345
-
346
- /* ── Meter / progress ───────────────────────────────────────────────────── */
347
- .lt3-meter { height: 8px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
348
- .lt3-meter__fill { height: 100%; border-radius: 99px; background: var(--accent); transition: width var(--lt3-dur-4) var(--lt3-ease); }
349
- .lt3-meter__fill--vector { background: var(--lt3-pillar-vector); }
350
- .lt3-meter__fill--graph { background: var(--lt3-pillar-graph); }
351
- .lt3-meter__fill--hybrid { background: var(--lt3-pillar-hybrid); }
352
- .lt3-meter__fill--ok { background: var(--success); }
353
- .lt3-meter__fill--warn { background: var(--warning); }
354
-
355
- /* ── Avatar ─────────────────────────────────────────────────────────────── */
356
- .lt3-avatar {
357
- display: inline-flex; align-items: center; justify-content: center;
358
- width: 32px; height: 32px; flex: none;
359
- border-radius: var(--lt3-radius-sm);
360
- background: var(--accent-soft);
361
- color: var(--accent);
362
- font-size: var(--lt3-text-xs);
363
- font-weight: var(--lt3-weight-bold);
364
- text-transform: uppercase;
365
- }
366
-
367
- /* ── States: empty / loading / error ────────────────────────────────────── */
368
- .lt3-empty {
369
- display: flex; flex-direction: column; align-items: center; justify-content: center;
370
- gap: var(--lt3-space-3);
371
- min-height: 220px;
372
- padding: var(--lt3-space-7) var(--lt3-space-5);
373
- text-align: center;
374
- color: var(--muted);
375
- background:
376
- linear-gradient(180deg, color-mix(in srgb, var(--surface-2) 64%, transparent), transparent);
377
- border: 1px dashed var(--border);
378
- border-radius: var(--lt3-radius-md);
379
- }
380
- .lt3-empty__icon {
381
- display: grid; place-items: center;
382
- width: 44px; height: 44px;
383
- border-radius: var(--lt3-radius-md);
384
- background: var(--surface-2);
385
- border: 1px solid var(--border);
386
- color: var(--faint);
387
- }
388
- .lt3-empty__icon .ti { font-size: 1.35rem; }
389
- .lt3-empty__title { font-size: var(--lt3-text-md); font-weight: var(--lt3-weight-semi); color: var(--text); }
390
- .lt3-empty__body { font-size: var(--lt3-text-sm); max-width: 38ch; }
391
-
392
- .lt3-skel {
393
- border-radius: var(--lt3-radius-sm);
394
- background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
395
- background-size: 400% 100%;
396
- animation: lt3-shimmer 1.4s var(--lt3-ease) infinite;
397
- }
398
- .lt3-skel--line { height: 12px; margin: 6px 0; }
399
- .lt3-skel--block { height: 84px; }
400
- @keyframes lt3-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
401
-
402
- .lt3-spinner {
403
- width: 18px; height: 18px;
404
- border: 2px solid var(--border);
405
- border-top-color: var(--accent);
406
- border-radius: 99px;
407
- animation: lt3-spin 0.7s linear infinite;
408
- }
409
- @keyframes lt3-spin { to { transform: rotate(360deg); } }
410
-
411
- .lt3-banner {
412
- display: flex; align-items: flex-start; gap: var(--lt3-space-3);
413
- padding: var(--lt3-space-3) var(--lt3-space-4);
414
- border-radius: var(--lt3-radius-md);
415
- font-size: var(--lt3-text-sm);
416
- border: 1px solid var(--border);
417
- background: var(--surface-2);
418
- }
419
- .lt3-banner--info { background: var(--accent-soft); border-color: transparent; color: var(--text); }
420
- .lt3-banner--warn { background: var(--lt3-warn-soft); border-color: transparent; }
421
- .lt3-banner--err { background: var(--lt3-err-soft); border-color: transparent; }
422
- .lt3-banner .ti { font-size: 1.15rem; margin-top: 1px; }
423
-
424
- /* ── Toolbar ────────────────────────────────────────────────────────────── */
425
- .lt3-toolbar {
426
- display: flex;
427
- align-items: center;
428
- gap: var(--lt3-space-3);
429
- flex-wrap: wrap;
430
- }
431
-
432
- /* ── Code block ─────────────────────────────────────────────────────────── */
433
- .lt3-code {
434
- font-family: var(--lt3-font-mono);
435
- font-size: var(--lt3-text-xs);
436
- background: var(--surface-2);
437
- border: 1px solid var(--border);
438
- border-radius: var(--lt3-radius-sm);
439
- padding: var(--lt3-space-3) var(--lt3-space-4);
440
- overflow: auto;
441
- white-space: pre;
442
- color: var(--text);
443
- }
444
-
445
- /* ── Divider ────────────────────────────────────────────────────────────── */
446
- .lt3-divider { height: 1px; background: var(--border); border: none; margin: var(--lt3-space-2) 0; }
447
-
448
- /* ── Toast ──────────────────────────────────────────────────────────────── */
449
- .lt3-toasts {
450
- position: fixed;
451
- bottom: var(--lt3-space-5);
452
- right: var(--lt3-space-5);
453
- z-index: var(--lt3-z-toast);
454
- display: flex; flex-direction: column; gap: var(--lt3-space-2);
455
- pointer-events: none;
456
- }
457
- .lt3-toast {
458
- pointer-events: auto;
459
- display: flex; align-items: center; gap: var(--lt3-space-3);
460
- min-width: 240px; max-width: 380px;
461
- padding: var(--lt3-space-3) var(--lt3-space-4);
462
- background: var(--surface-elevated);
463
- border: 1px solid var(--border);
464
- border-radius: var(--lt3-radius-md);
465
- box-shadow: var(--lt3-elev-2);
466
- font-size: var(--lt3-text-sm);
467
- animation: lt3-toast-in var(--lt3-dur-3) var(--lt3-ease-out);
468
- }
469
- .lt3-toast--ok { border-left: 3px solid var(--success); }
470
- .lt3-toast--err { border-left: 3px solid var(--danger); }
471
- .lt3-toast--info { border-left: 3px solid var(--accent); }
472
- @keyframes lt3-toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }