ltcai 2.2.7 → 3.1.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.
- package/README.md +72 -34
- package/docs/CHANGELOG.md +119 -0
- package/docs/V3_BACKEND_ARCHITECTURE.md +138 -0
- package/docs/V3_FRONTEND.md +139 -0
- package/knowledge_graph.py +649 -21
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/admin.py +47 -0
- package/latticeai/api/agents.py +54 -31
- package/latticeai/api/auth.py +5 -2
- package/latticeai/api/chat.py +10 -2
- package/latticeai/api/search.py +240 -0
- package/latticeai/api/static_routes.py +11 -2
- package/latticeai/core/config.py +18 -0
- package/latticeai/core/embedding_providers.py +625 -0
- package/latticeai/core/local_embeddings.py +86 -0
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/server_app.py +65 -1
- package/latticeai/services/agent_runtime.py +245 -0
- package/latticeai/services/search_service.py +346 -0
- package/package.json +13 -6
- package/scripts/build_v3_assets.mjs +164 -0
- package/scripts/capture/README.md +28 -0
- package/scripts/capture/capture_enterprise.js +8 -0
- package/scripts/capture/capture_graph.js +8 -0
- package/scripts/capture/capture_onboarding.js +8 -0
- package/scripts/capture/capture_page.js +43 -0
- package/scripts/capture/capture_release_media.js +125 -0
- package/scripts/capture/capture_skills.js +8 -0
- package/scripts/capture/capture_workspace.js +8 -0
- package/scripts/generate_diagrams.py +513 -0
- package/scripts/lint_v3.mjs +33 -0
- package/scripts/release-0.3.1.sh +105 -0
- package/scripts/take_screenshots.js +69 -0
- package/scripts/validate_release_artifacts.py +167 -0
- package/static/account.html +9 -9
- package/static/activity.html +4 -4
- package/static/admin.html +8 -8
- package/static/agents.html +4 -4
- package/static/chat.html +10 -10
- package/static/css/reference/account.css +137 -1
- package/static/css/reference/chat.css +31 -37
- package/static/css/responsive.css +42 -0
- package/static/css/tokens.5a595671.css +260 -0
- package/static/css/tokens.css +125 -130
- package/static/graph.html +9 -9
- package/static/manifest.json +3 -3
- package/static/plugins.html +4 -4
- package/static/scripts/account.js +4 -4
- package/static/scripts/chat.js +40 -8
- package/static/scripts/workspace.js +78 -0
- package/static/sw.js +3 -1
- package/static/v3/asset-manifest.json +47 -0
- package/static/v3/css/lattice.base.css +128 -0
- package/static/v3/css/lattice.base.e4cdd05d.css +128 -0
- package/static/v3/css/lattice.components.011e988b.css +447 -0
- package/static/v3/css/lattice.components.css +447 -0
- package/static/v3/css/lattice.shell.4920f42d.css +407 -0
- package/static/v3/css/lattice.shell.css +407 -0
- package/static/v3/css/lattice.tokens.c597ff81.css +132 -0
- package/static/v3/css/lattice.tokens.css +132 -0
- package/static/v3/css/lattice.views.3ee19d4e.css +277 -0
- package/static/v3/css/lattice.views.css +277 -0
- package/static/v3/index.html +69 -0
- package/static/v3/js/app.46fb61d9.js +26 -0
- package/static/v3/js/app.js +26 -0
- package/static/v3/js/core/api.22a41d42.js +344 -0
- package/static/v3/js/core/api.js +344 -0
- package/static/v3/js/core/components.4c83e0a9.js +222 -0
- package/static/v3/js/core/components.js +222 -0
- package/static/v3/js/core/dom.a2773eb0.js +148 -0
- package/static/v3/js/core/dom.js +148 -0
- package/static/v3/js/core/router.584570f2.js +37 -0
- package/static/v3/js/core/router.js +37 -0
- package/static/v3/js/core/routes.f935dd50.js +78 -0
- package/static/v3/js/core/routes.js +78 -0
- package/static/v3/js/core/shell.1b6199d6.js +363 -0
- package/static/v3/js/core/shell.js +363 -0
- package/static/v3/js/core/store.34ebd5e6.js +113 -0
- package/static/v3/js/core/store.js +113 -0
- package/static/v3/js/views/admin-audit.660a1fb1.js +185 -0
- package/static/v3/js/views/admin-audit.js +185 -0
- package/static/v3/js/views/admin-permissions.a7ae5f09.js +177 -0
- package/static/v3/js/views/admin-permissions.js +177 -0
- package/static/v3/js/views/admin-policies.3658fd86.js +102 -0
- package/static/v3/js/views/admin-policies.js +102 -0
- package/static/v3/js/views/admin-private-vpc.7d342d36.js +135 -0
- package/static/v3/js/views/admin-private-vpc.js +135 -0
- package/static/v3/js/views/admin-security.07c66b72.js +180 -0
- package/static/v3/js/views/admin-security.js +180 -0
- package/static/v3/js/views/admin-users.03bac88c.js +168 -0
- package/static/v3/js/views/admin-users.js +168 -0
- package/static/v3/js/views/agents.14e48bdd.js +193 -0
- package/static/v3/js/views/agents.js +193 -0
- package/static/v3/js/views/chat.718144ce.js +449 -0
- package/static/v3/js/views/chat.js +449 -0
- package/static/v3/js/views/files.4935197e.js +186 -0
- package/static/v3/js/views/files.js +186 -0
- package/static/v3/js/views/home.cdde3b32.js +119 -0
- package/static/v3/js/views/home.js +119 -0
- package/static/v3/js/views/hybrid-search.b22b97e0.js +195 -0
- package/static/v3/js/views/hybrid-search.js +195 -0
- package/static/v3/js/views/knowledge-graph.a14ea7e7.js +237 -0
- package/static/v3/js/views/knowledge-graph.js +237 -0
- package/static/v3/js/views/models.a1ffa147.js +256 -0
- package/static/v3/js/views/models.js +256 -0
- package/static/v3/js/views/my-computer.1b2ff621.js +237 -0
- package/static/v3/js/views/my-computer.js +237 -0
- package/static/v3/js/views/pipeline.c522f1ce.js +157 -0
- package/static/v3/js/views/pipeline.js +157 -0
- package/static/v3/js/views/settings.4f777210.js +250 -0
- package/static/v3/js/views/settings.js +250 -0
- package/static/workflows.html +4 -4
- package/static/workspace.css +340 -2
- package/static/workspace.html +43 -24
- package/docs/images/tmp_frames/frame_00.png +0 -0
- package/docs/images/tmp_frames/frame_01.png +0 -0
- package/docs/images/tmp_frames/frame_02.png +0 -0
- package/docs/images/tmp_frames/frame_03.png +0 -0
- package/docs/images/tmp_frames/hero_00.png +0 -0
- package/docs/images/tmp_frames/hero_01.png +0 -0
- package/docs/images/tmp_frames/hero_02.png +0 -0
- package/docs/images/tmp_frames/hero_03.png +0 -0
|
@@ -15,6 +15,8 @@ const state = {
|
|
|
15
15
|
|
|
16
16
|
// Skills that match common workspace needs are surfaced under "Recommended".
|
|
17
17
|
const RECOMMENDED_SKILL_HINTS = ["code", "review", "doc", "test", "security", "research", "changelog", "refactor", "debug"];
|
|
18
|
+
const MODE_KEY = "ltcai_workspace_mode";
|
|
19
|
+
const LANG_KEY = "ltcai_lang";
|
|
18
20
|
|
|
19
21
|
function $(id) {
|
|
20
22
|
return document.getElementById(id);
|
|
@@ -51,6 +53,61 @@ function toast(message) {
|
|
|
51
53
|
node._timer = setTimeout(() => node.classList.remove("show"), 2200);
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
function adminAvailableForWorkspace(workspace) {
|
|
57
|
+
const storedAdmin = (() => {
|
|
58
|
+
try { return localStorage.getItem("ltcai_is_admin") === "true"; } catch { return false; }
|
|
59
|
+
})();
|
|
60
|
+
const role = String(workspace?.your_role || "").toLowerCase();
|
|
61
|
+
return storedAdmin || role === "owner" || role === "admin";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function currentWorkspaceMode() {
|
|
65
|
+
try {
|
|
66
|
+
const mode = localStorage.getItem(MODE_KEY);
|
|
67
|
+
return ["basic", "advanced", "admin"].includes(mode) ? mode : "basic";
|
|
68
|
+
} catch {
|
|
69
|
+
return "basic";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function applyWorkspaceMode(mode, { adminAvailable = false } = {}) {
|
|
74
|
+
if (mode === "admin" && !adminAvailable) mode = "basic";
|
|
75
|
+
const shell = document.querySelector(".workspace-shell");
|
|
76
|
+
if (shell) shell.dataset.workspaceMode = mode;
|
|
77
|
+
document.querySelectorAll("[data-workspace-mode]").forEach((button) => {
|
|
78
|
+
if (button.matches("button")) {
|
|
79
|
+
const active = button.dataset.workspaceMode === mode;
|
|
80
|
+
button.classList.toggle("active", active);
|
|
81
|
+
button.setAttribute("aria-selected", active ? "true" : "false");
|
|
82
|
+
button.disabled = button.dataset.workspaceMode === "admin" && !adminAvailable;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
try { localStorage.setItem(MODE_KEY, mode); } catch {}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function updateWorkspaceChrome(activeWorkspace) {
|
|
89
|
+
const shell = document.querySelector(".workspace-shell");
|
|
90
|
+
const adminAvailable = adminAvailableForWorkspace(activeWorkspace);
|
|
91
|
+
if (shell) shell.dataset.adminAvailable = adminAvailable ? "true" : "false";
|
|
92
|
+
applyWorkspaceMode(currentWorkspaceMode(), { adminAvailable });
|
|
93
|
+
const lang = (() => {
|
|
94
|
+
try { return localStorage.getItem(LANG_KEY) || "en"; } catch { return "en"; }
|
|
95
|
+
})();
|
|
96
|
+
document.documentElement.lang = lang;
|
|
97
|
+
const langSelect = $("workspace-language");
|
|
98
|
+
if (langSelect) langSelect.value = lang;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function logoutWorkspace() {
|
|
102
|
+
try { await api("/logout", { method: "POST" }); } catch (_) {}
|
|
103
|
+
try {
|
|
104
|
+
localStorage.removeItem("ltcai_user_email");
|
|
105
|
+
localStorage.removeItem("ltcai_user_nickname");
|
|
106
|
+
localStorage.removeItem("ltcai_is_admin");
|
|
107
|
+
} catch (_) {}
|
|
108
|
+
window.location.href = "/account";
|
|
109
|
+
}
|
|
110
|
+
|
|
54
111
|
function renderMetrics(os) {
|
|
55
112
|
const counts = os?.counts || {};
|
|
56
113
|
const graph = os?.graph || {};
|
|
@@ -363,6 +420,7 @@ function renderWorkspaceRegistry(registry, edition) {
|
|
|
363
420
|
`).join("");
|
|
364
421
|
}
|
|
365
422
|
const active = workspaces.find((ws) => ws.workspace_id === state.activeWorkspace);
|
|
423
|
+
updateWorkspaceChrome(active);
|
|
366
424
|
const rolePill = $("workspace-role");
|
|
367
425
|
if (rolePill) rolePill.textContent = active ? (active.your_role || "—") : "";
|
|
368
426
|
if (edition) {
|
|
@@ -837,6 +895,26 @@ document.addEventListener("change", async (event) => {
|
|
|
837
895
|
});
|
|
838
896
|
|
|
839
897
|
document.addEventListener("DOMContentLoaded", () => {
|
|
898
|
+
document.querySelectorAll("[data-workspace-mode]").forEach((button) => {
|
|
899
|
+
if (!button.matches("button")) return;
|
|
900
|
+
button.addEventListener("click", () => {
|
|
901
|
+
const shell = document.querySelector(".workspace-shell");
|
|
902
|
+
const adminAvailable = shell?.dataset.adminAvailable === "true";
|
|
903
|
+
applyWorkspaceMode(button.dataset.workspaceMode, { adminAvailable });
|
|
904
|
+
});
|
|
905
|
+
});
|
|
906
|
+
const language = $("workspace-language");
|
|
907
|
+
if (language) {
|
|
908
|
+
language.value = (() => {
|
|
909
|
+
try { return localStorage.getItem(LANG_KEY) || "en"; } catch { return "en"; }
|
|
910
|
+
})();
|
|
911
|
+
language.addEventListener("change", () => {
|
|
912
|
+
try { localStorage.setItem(LANG_KEY, language.value); } catch (_) {}
|
|
913
|
+
document.documentElement.lang = language.value;
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
const logoutButton = $("workspace-logout");
|
|
917
|
+
if (logoutButton) logoutButton.addEventListener("click", () => logoutWorkspace());
|
|
840
918
|
$("refresh-btn").addEventListener("click", () => refreshAll().catch((err) => toast(err.message)));
|
|
841
919
|
$("snapshot-now").addEventListener("click", () => createSnapshot().catch((err) => toast(err.message)));
|
|
842
920
|
$("create-snapshot").addEventListener("click", () => createSnapshot().catch((err) => toast(err.message)));
|
package/static/sw.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// Lattice AI Service Worker — enables PWA install on Android/iOS
|
|
2
2
|
// Strategy: network-first for API, cache-first for static assets.
|
|
3
|
-
const CACHE = "ltcai-
|
|
3
|
+
const CACHE = "ltcai-v310";
|
|
4
4
|
const STATIC = [
|
|
5
5
|
"/",
|
|
6
|
+
"/app",
|
|
6
7
|
"/workspace",
|
|
8
|
+
"/static/v3/asset-manifest.json",
|
|
7
9
|
"/static/css/tokens.css",
|
|
8
10
|
"/static/css/reference/base.css",
|
|
9
11
|
"/static/css/reference/chat.css",
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "3.1.0",
|
|
3
|
+
"generated_at": "deterministic",
|
|
4
|
+
"entrypoints": {
|
|
5
|
+
"app": "/static/v3/js/app.46fb61d9.js",
|
|
6
|
+
"styles": [
|
|
7
|
+
"/static/css/tokens.5a595671.css",
|
|
8
|
+
"/static/v3/css/lattice.tokens.c597ff81.css",
|
|
9
|
+
"/static/v3/css/lattice.base.e4cdd05d.css",
|
|
10
|
+
"/static/v3/css/lattice.components.011e988b.css",
|
|
11
|
+
"/static/v3/css/lattice.shell.4920f42d.css",
|
|
12
|
+
"/static/v3/css/lattice.views.3ee19d4e.css"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"assets": {
|
|
16
|
+
"static/css/tokens.css": "/static/css/tokens.5a595671.css",
|
|
17
|
+
"static/v3/css/lattice.tokens.css": "/static/v3/css/lattice.tokens.c597ff81.css",
|
|
18
|
+
"static/v3/css/lattice.base.css": "/static/v3/css/lattice.base.e4cdd05d.css",
|
|
19
|
+
"static/v3/css/lattice.components.css": "/static/v3/css/lattice.components.011e988b.css",
|
|
20
|
+
"static/v3/css/lattice.shell.css": "/static/v3/css/lattice.shell.4920f42d.css",
|
|
21
|
+
"static/v3/css/lattice.views.css": "/static/v3/css/lattice.views.3ee19d4e.css",
|
|
22
|
+
"static/v3/js/app.js": "/static/v3/js/app.46fb61d9.js",
|
|
23
|
+
"static/v3/js/core/api.js": "/static/v3/js/core/api.22a41d42.js",
|
|
24
|
+
"static/v3/js/core/components.js": "/static/v3/js/core/components.4c83e0a9.js",
|
|
25
|
+
"static/v3/js/core/dom.js": "/static/v3/js/core/dom.a2773eb0.js",
|
|
26
|
+
"static/v3/js/core/router.js": "/static/v3/js/core/router.584570f2.js",
|
|
27
|
+
"static/v3/js/core/routes.js": "/static/v3/js/core/routes.f935dd50.js",
|
|
28
|
+
"static/v3/js/core/shell.js": "/static/v3/js/core/shell.1b6199d6.js",
|
|
29
|
+
"static/v3/js/core/store.js": "/static/v3/js/core/store.34ebd5e6.js",
|
|
30
|
+
"static/v3/js/views/admin-audit.js": "/static/v3/js/views/admin-audit.660a1fb1.js",
|
|
31
|
+
"static/v3/js/views/admin-permissions.js": "/static/v3/js/views/admin-permissions.a7ae5f09.js",
|
|
32
|
+
"static/v3/js/views/admin-policies.js": "/static/v3/js/views/admin-policies.3658fd86.js",
|
|
33
|
+
"static/v3/js/views/admin-private-vpc.js": "/static/v3/js/views/admin-private-vpc.7d342d36.js",
|
|
34
|
+
"static/v3/js/views/admin-security.js": "/static/v3/js/views/admin-security.07c66b72.js",
|
|
35
|
+
"static/v3/js/views/admin-users.js": "/static/v3/js/views/admin-users.03bac88c.js",
|
|
36
|
+
"static/v3/js/views/agents.js": "/static/v3/js/views/agents.14e48bdd.js",
|
|
37
|
+
"static/v3/js/views/chat.js": "/static/v3/js/views/chat.718144ce.js",
|
|
38
|
+
"static/v3/js/views/files.js": "/static/v3/js/views/files.4935197e.js",
|
|
39
|
+
"static/v3/js/views/home.js": "/static/v3/js/views/home.cdde3b32.js",
|
|
40
|
+
"static/v3/js/views/hybrid-search.js": "/static/v3/js/views/hybrid-search.b22b97e0.js",
|
|
41
|
+
"static/v3/js/views/knowledge-graph.js": "/static/v3/js/views/knowledge-graph.a14ea7e7.js",
|
|
42
|
+
"static/v3/js/views/models.js": "/static/v3/js/views/models.a1ffa147.js",
|
|
43
|
+
"static/v3/js/views/my-computer.js": "/static/v3/js/views/my-computer.1b2ff621.js",
|
|
44
|
+
"static/v3/js/views/pipeline.js": "/static/v3/js/views/pipeline.c522f1ce.js",
|
|
45
|
+
"static/v3/js/views/settings.js": "/static/v3/js/views/settings.4f777210.js"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Lattice AI v3 — Base layer (reset + element defaults + lattice backdrop)
|
|
3
|
+
* Token-native: no themed hex values, everything via var(--*).
|
|
4
|
+
* ========================================================================== */
|
|
5
|
+
|
|
6
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
7
|
+
|
|
8
|
+
html, body { height: 100%; }
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
margin: 0;
|
|
12
|
+
font-family: var(--lt3-font-sans);
|
|
13
|
+
font-size: var(--lt3-text-md);
|
|
14
|
+
line-height: var(--lt3-leading-normal);
|
|
15
|
+
color: var(--text);
|
|
16
|
+
background: var(--bg);
|
|
17
|
+
-webkit-font-smoothing: antialiased;
|
|
18
|
+
text-rendering: optimizeLegibility;
|
|
19
|
+
overflow: hidden; /* shell owns scroll regions */
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* The signature lattice backdrop — a faint structural mesh of nodes+edges.
|
|
23
|
+
Sits behind the whole app; reinforces the "lattice" identity without noise. */
|
|
24
|
+
.lt3-app::before {
|
|
25
|
+
content: "";
|
|
26
|
+
position: fixed;
|
|
27
|
+
inset: 0;
|
|
28
|
+
z-index: 0;
|
|
29
|
+
pointer-events: none;
|
|
30
|
+
background:
|
|
31
|
+
radial-gradient(circle at center, var(--lt3-mesh-node) 0.9px, transparent 1.1px),
|
|
32
|
+
linear-gradient(var(--lt3-mesh-line) 1px, transparent 1px),
|
|
33
|
+
linear-gradient(90deg, var(--lt3-mesh-line) 1px, transparent 1px),
|
|
34
|
+
var(--app-bg);
|
|
35
|
+
background-size:
|
|
36
|
+
var(--lt3-mesh-size) var(--lt3-mesh-size),
|
|
37
|
+
var(--lt3-mesh-size) var(--lt3-mesh-size),
|
|
38
|
+
var(--lt3-mesh-size) var(--lt3-mesh-size),
|
|
39
|
+
cover;
|
|
40
|
+
background-position: center;
|
|
41
|
+
mask-image: radial-gradient(ellipse 120% 90% at 50% -10%, #000 55%, transparent 100%);
|
|
42
|
+
opacity: 0.9;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
h1, h2, h3, h4, p, figure { margin: 0; }
|
|
46
|
+
|
|
47
|
+
a { color: inherit; text-decoration: none; }
|
|
48
|
+
|
|
49
|
+
button {
|
|
50
|
+
font: inherit;
|
|
51
|
+
color: inherit;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
border: none;
|
|
54
|
+
background: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
input, select, textarea { font: inherit; color: inherit; }
|
|
58
|
+
|
|
59
|
+
textarea { resize: vertical; }
|
|
60
|
+
|
|
61
|
+
img, svg { display: block; max-width: 100%; }
|
|
62
|
+
|
|
63
|
+
code, pre, kbd, samp { font-family: var(--lt3-font-mono); }
|
|
64
|
+
|
|
65
|
+
:root[data-lt-icons="fallback"] .ti {
|
|
66
|
+
display: inline-grid;
|
|
67
|
+
place-items: center;
|
|
68
|
+
min-width: 1em;
|
|
69
|
+
min-height: 1em;
|
|
70
|
+
font-family: var(--lt3-font-mono);
|
|
71
|
+
font-size: 0.72em;
|
|
72
|
+
font-style: normal;
|
|
73
|
+
font-weight: 800;
|
|
74
|
+
line-height: 1;
|
|
75
|
+
text-transform: uppercase;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
:root[data-lt-icons="fallback"] .ti::before {
|
|
79
|
+
content: attr(data-fallback);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:focus-visible {
|
|
83
|
+
outline: 2px solid var(--focus-ring);
|
|
84
|
+
outline-offset: 2px;
|
|
85
|
+
border-radius: var(--lt3-radius-xs);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
::-webkit-scrollbar { width: 8px; height: 8px; }
|
|
89
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
90
|
+
::-webkit-scrollbar-thumb {
|
|
91
|
+
background: color-mix(in srgb, var(--border-strong) 60%, transparent);
|
|
92
|
+
border-radius: 99px;
|
|
93
|
+
border: 2px solid transparent;
|
|
94
|
+
background-clip: padding-box;
|
|
95
|
+
}
|
|
96
|
+
::-webkit-scrollbar-thumb:hover { background: var(--border-strong); background-clip: padding-box; }
|
|
97
|
+
|
|
98
|
+
/* Accessible visually-hidden utility */
|
|
99
|
+
.lt3-sr {
|
|
100
|
+
position: absolute !important;
|
|
101
|
+
width: 1px; height: 1px;
|
|
102
|
+
padding: 0; margin: -1px;
|
|
103
|
+
overflow: hidden; clip: rect(0,0,0,0);
|
|
104
|
+
white-space: nowrap; border: 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.lt3-skip {
|
|
108
|
+
position: fixed;
|
|
109
|
+
top: var(--lt3-space-3);
|
|
110
|
+
left: var(--lt3-space-3);
|
|
111
|
+
z-index: var(--lt3-z-toast);
|
|
112
|
+
padding: var(--lt3-space-2) var(--lt3-space-4);
|
|
113
|
+
background: var(--accent);
|
|
114
|
+
color: #fff;
|
|
115
|
+
border-radius: var(--lt3-radius-sm);
|
|
116
|
+
transform: translateY(-200%);
|
|
117
|
+
transition: transform var(--lt3-dur-2) var(--lt3-ease);
|
|
118
|
+
}
|
|
119
|
+
.lt3-skip:focus { transform: translateY(0); }
|
|
120
|
+
|
|
121
|
+
@media (prefers-reduced-motion: reduce) {
|
|
122
|
+
*, *::before, *::after {
|
|
123
|
+
animation-duration: 0.001ms !important;
|
|
124
|
+
animation-iteration-count: 1 !important;
|
|
125
|
+
transition-duration: 0.001ms !important;
|
|
126
|
+
scroll-behavior: auto !important;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Lattice AI v3 — Base layer (reset + element defaults + lattice backdrop)
|
|
3
|
+
* Token-native: no themed hex values, everything via var(--*).
|
|
4
|
+
* ========================================================================== */
|
|
5
|
+
|
|
6
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
7
|
+
|
|
8
|
+
html, body { height: 100%; }
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
margin: 0;
|
|
12
|
+
font-family: var(--lt3-font-sans);
|
|
13
|
+
font-size: var(--lt3-text-md);
|
|
14
|
+
line-height: var(--lt3-leading-normal);
|
|
15
|
+
color: var(--text);
|
|
16
|
+
background: var(--bg);
|
|
17
|
+
-webkit-font-smoothing: antialiased;
|
|
18
|
+
text-rendering: optimizeLegibility;
|
|
19
|
+
overflow: hidden; /* shell owns scroll regions */
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* The signature lattice backdrop — a faint structural mesh of nodes+edges.
|
|
23
|
+
Sits behind the whole app; reinforces the "lattice" identity without noise. */
|
|
24
|
+
.lt3-app::before {
|
|
25
|
+
content: "";
|
|
26
|
+
position: fixed;
|
|
27
|
+
inset: 0;
|
|
28
|
+
z-index: 0;
|
|
29
|
+
pointer-events: none;
|
|
30
|
+
background:
|
|
31
|
+
radial-gradient(circle at center, var(--lt3-mesh-node) 0.9px, transparent 1.1px),
|
|
32
|
+
linear-gradient(var(--lt3-mesh-line) 1px, transparent 1px),
|
|
33
|
+
linear-gradient(90deg, var(--lt3-mesh-line) 1px, transparent 1px),
|
|
34
|
+
var(--app-bg);
|
|
35
|
+
background-size:
|
|
36
|
+
var(--lt3-mesh-size) var(--lt3-mesh-size),
|
|
37
|
+
var(--lt3-mesh-size) var(--lt3-mesh-size),
|
|
38
|
+
var(--lt3-mesh-size) var(--lt3-mesh-size),
|
|
39
|
+
cover;
|
|
40
|
+
background-position: center;
|
|
41
|
+
mask-image: radial-gradient(ellipse 120% 90% at 50% -10%, #000 55%, transparent 100%);
|
|
42
|
+
opacity: 0.9;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
h1, h2, h3, h4, p, figure { margin: 0; }
|
|
46
|
+
|
|
47
|
+
a { color: inherit; text-decoration: none; }
|
|
48
|
+
|
|
49
|
+
button {
|
|
50
|
+
font: inherit;
|
|
51
|
+
color: inherit;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
border: none;
|
|
54
|
+
background: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
input, select, textarea { font: inherit; color: inherit; }
|
|
58
|
+
|
|
59
|
+
textarea { resize: vertical; }
|
|
60
|
+
|
|
61
|
+
img, svg { display: block; max-width: 100%; }
|
|
62
|
+
|
|
63
|
+
code, pre, kbd, samp { font-family: var(--lt3-font-mono); }
|
|
64
|
+
|
|
65
|
+
:root[data-lt-icons="fallback"] .ti {
|
|
66
|
+
display: inline-grid;
|
|
67
|
+
place-items: center;
|
|
68
|
+
min-width: 1em;
|
|
69
|
+
min-height: 1em;
|
|
70
|
+
font-family: var(--lt3-font-mono);
|
|
71
|
+
font-size: 0.72em;
|
|
72
|
+
font-style: normal;
|
|
73
|
+
font-weight: 800;
|
|
74
|
+
line-height: 1;
|
|
75
|
+
text-transform: uppercase;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
:root[data-lt-icons="fallback"] .ti::before {
|
|
79
|
+
content: attr(data-fallback);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:focus-visible {
|
|
83
|
+
outline: 2px solid var(--focus-ring);
|
|
84
|
+
outline-offset: 2px;
|
|
85
|
+
border-radius: var(--lt3-radius-xs);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
::-webkit-scrollbar { width: 8px; height: 8px; }
|
|
89
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
90
|
+
::-webkit-scrollbar-thumb {
|
|
91
|
+
background: color-mix(in srgb, var(--border-strong) 60%, transparent);
|
|
92
|
+
border-radius: 99px;
|
|
93
|
+
border: 2px solid transparent;
|
|
94
|
+
background-clip: padding-box;
|
|
95
|
+
}
|
|
96
|
+
::-webkit-scrollbar-thumb:hover { background: var(--border-strong); background-clip: padding-box; }
|
|
97
|
+
|
|
98
|
+
/* Accessible visually-hidden utility */
|
|
99
|
+
.lt3-sr {
|
|
100
|
+
position: absolute !important;
|
|
101
|
+
width: 1px; height: 1px;
|
|
102
|
+
padding: 0; margin: -1px;
|
|
103
|
+
overflow: hidden; clip: rect(0,0,0,0);
|
|
104
|
+
white-space: nowrap; border: 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.lt3-skip {
|
|
108
|
+
position: fixed;
|
|
109
|
+
top: var(--lt3-space-3);
|
|
110
|
+
left: var(--lt3-space-3);
|
|
111
|
+
z-index: var(--lt3-z-toast);
|
|
112
|
+
padding: var(--lt3-space-2) var(--lt3-space-4);
|
|
113
|
+
background: var(--accent);
|
|
114
|
+
color: #fff;
|
|
115
|
+
border-radius: var(--lt3-radius-sm);
|
|
116
|
+
transform: translateY(-200%);
|
|
117
|
+
transition: transform var(--lt3-dur-2) var(--lt3-ease);
|
|
118
|
+
}
|
|
119
|
+
.lt3-skip:focus { transform: translateY(0); }
|
|
120
|
+
|
|
121
|
+
@media (prefers-reduced-motion: reduce) {
|
|
122
|
+
*, *::before, *::after {
|
|
123
|
+
animation-duration: 0.001ms !important;
|
|
124
|
+
animation-iteration-count: 1 !important;
|
|
125
|
+
transition-duration: 0.001ms !important;
|
|
126
|
+
scroll-behavior: auto !important;
|
|
127
|
+
}
|
|
128
|
+
}
|