ltcai 2.2.1 → 2.2.7

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 (44) hide show
  1. package/README.md +183 -140
  2. package/codex_telegram_bot.py +6 -2
  3. package/docs/CHANGELOG.md +100 -23
  4. package/docs/EDITION_STRATEGY.md +8 -8
  5. package/docs/ENTERPRISE.md +5 -5
  6. package/docs/PLUGIN_SDK.md +4 -4
  7. package/docs/V2_ARCHITECTURE.md +9 -9
  8. package/docs/architecture.md +18 -17
  9. package/docs/images/admin-dashboard.png +0 -0
  10. package/docs/images/knowledge-graph.png +0 -0
  11. package/docs/images/lattice-ai-demo.gif +0 -0
  12. package/docs/images/lattice-ai-hero.png +0 -0
  13. package/docs/images/mobile-responsive.png +0 -0
  14. package/docs/images/pipeline.png +0 -0
  15. package/docs/images/workspace-dark.png +0 -0
  16. package/docs/images/workspace-light.png +0 -0
  17. package/latticeai/__init__.py +1 -1
  18. package/latticeai/api/static_routes.py +10 -0
  19. package/latticeai/core/logging_safety.py +62 -0
  20. package/latticeai/core/workspace_os.py +1 -1
  21. package/package.json +10 -5
  22. package/static/account.html +9 -4
  23. package/static/activity.html +4 -4
  24. package/static/admin.html +8 -3
  25. package/static/agents.html +4 -4
  26. package/static/chat.html +15 -10
  27. package/static/css/reference/account.css +303 -0
  28. package/static/css/reference/admin.css +610 -0
  29. package/static/css/reference/base.css +1658 -0
  30. package/static/{lattice-reference.css → css/reference/chat.css} +243 -3599
  31. package/static/css/reference/graph.css +1016 -0
  32. package/static/css/responsive.css +226 -4
  33. package/static/css/tokens.css +16 -5
  34. package/static/favicon.ico +0 -0
  35. package/static/graph.html +9 -4
  36. package/static/platform.css +1 -1
  37. package/static/plugins.html +4 -4
  38. package/static/scripts/chat.js +187 -69
  39. package/static/scripts/ux.js +1 -1
  40. package/static/sw.js +5 -3
  41. package/static/workflows.html +4 -4
  42. package/static/workspace.css +75 -14
  43. package/static/workspace.html +5 -5
  44. package/telegram_bot.py +18 -14
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ltcai",
3
- "version": "2.2.1",
4
- "description": "Lattice AI Workspace OS for local-first graph, memory, agent, workflow, and skill operations",
3
+ "version": "2.2.7",
4
+ "description": "Local-first AI workspace for knowledge graphs, AI pipelines, and multi-agent coding workflows.",
5
5
  "homepage": "https://github.com/TaeSooPark-PTS/LatticeAI#readme",
6
6
  "repository": {
7
7
  "type": "git",
@@ -20,6 +20,8 @@
20
20
  "build": "npm run build:python",
21
21
  "build:python": "python3 -m build",
22
22
  "check:python": "python3 -m py_compile ltcai_cli.py server.py latticeai/server_app.py latticeai/api/chat.py latticeai/api/computer_use.py latticeai/api/deps.py latticeai/api/garden.py latticeai/api/local_files.py latticeai/api/permissions.py latticeai/api/setup.py latticeai/api/static_routes.py latticeai/api/tools.py latticeai/api/plugins.py latticeai/api/workflow_designer.py latticeai/api/agents.py latticeai/api/realtime.py latticeai/api/marketplace.py latticeai/services/app_context.py latticeai/services/model_runtime.py latticeai/services/model_catalog.py latticeai/services/model_recommendation.py latticeai/services/tool_dispatch.py latticeai/services/upload_service.py latticeai/core/tool_registry.py latticeai/core/enterprise.py latticeai/core/enterprise_admin.py latticeai/core/agent_prompts.py latticeai/core/workspace_os.py latticeai/core/plugins.py latticeai/core/marketplace.py latticeai/core/workflow_engine.py latticeai/core/multi_agent.py latticeai/core/realtime.py knowledge_graph.py knowledge_graph_api.py local_knowledge_api.py llm_router.py p_reinforce.py telegram_bot.py tools.py codex_telegram_bot.py",
23
+ "lint": "node --check static/scripts/account.js && node --check static/scripts/admin.js && node --check static/scripts/chat.js && node --check static/scripts/graph.js && node --check static/scripts/platform.js && node --check static/scripts/ux.js && node --check static/scripts/workspace.js && node --check tests/visual/mock_server.cjs",
24
+ "typecheck": "cd vscode-extension && npm run build",
23
25
  "test": "python3 -m pytest tests/ -v",
24
26
  "test:unit": "python3 -m pytest tests/unit/ -v",
25
27
  "test:integration": "python3 -m pytest tests/integration/ -v",
@@ -39,11 +41,14 @@
39
41
  },
40
42
  "keywords": [
41
43
  "ltcai",
42
- "ai-assistant",
44
+ "ai-workspace",
45
+ "ai-pipeline",
46
+ "knowledge-graph",
43
47
  "llm",
44
48
  "mlx",
45
49
  "local-ai",
46
- "agent",
50
+ "multi-agent",
51
+ "workflow",
47
52
  "mcp",
48
53
  "rag",
49
54
  "vscode"
@@ -77,9 +82,9 @@
77
82
  "static/workflows.html",
78
83
  "static/agents.html",
79
84
  "static/activity.html",
85
+ "static/favicon.ico",
80
86
  "static/manifest.json",
81
87
  "static/sw.js",
82
- "static/lattice-reference.css",
83
88
  "static/workspace.css",
84
89
  "static/platform.css",
85
90
  "static/scripts/",
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">
6
6
  <title>Lattice AI</title>
7
- <script src="/static/scripts/ux.js?v=2.2.1"></script>
7
+ <script src="/static/scripts/ux.js?v=2.2.7"></script>
8
8
  <link rel="manifest" href="/manifest.json">
9
9
  <meta name="theme-color" content="#f3ecff">
10
10
  <meta name="apple-mobile-web-app-capable" content="yes">
@@ -14,8 +14,13 @@
14
14
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
15
15
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap">
16
16
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/tabler-icons.min.css">
17
- <link rel="stylesheet" href="/static/lattice-reference.css?v=0.3.3">
18
- <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.1">
17
+ <link rel="stylesheet" href="/static/css/tokens.css?v=2.2.7">
18
+ <link rel="stylesheet" href="/static/css/reference/base.css?v=2.2.7">
19
+ <link rel="stylesheet" href="/static/css/reference/account.css?v=2.2.7">
20
+ <link rel="stylesheet" href="/static/css/reference/admin.css?v=2.2.7">
21
+ <link rel="stylesheet" href="/static/css/reference/graph.css?v=2.2.7">
22
+ <link rel="stylesheet" href="/static/css/reference/chat.css?v=2.2.7">
23
+ <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.7">
19
24
  </head>
20
25
  <body class="lattice-ref-auth">
21
26
  <div class="orb orb-1"></div>
@@ -105,6 +110,6 @@
105
110
  <a href="#" onclick="return false;" id="privacy-link">개인정보 처리방침</a>
106
111
  </footer>
107
112
 
108
- <script src="/static/scripts/account.js?v=0.3.3"></script>
113
+ <script src="/static/scripts/account.js?v=2.2.7"></script>
109
114
  </body>
110
115
  </html>
@@ -4,10 +4,10 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content" />
6
6
  <title>Realtime Activity — Lattice AI</title>
7
- <script src="/static/scripts/ux.js?v=2.2.1"></script>
8
- <link rel="stylesheet" href="/static/css/tokens.css?v=2.2.1" />
9
- <link rel="stylesheet" href="/static/platform.css?v=2.2.1" />
10
- <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.1" />
7
+ <script src="/static/scripts/ux.js?v=2.2.7"></script>
8
+ <link rel="stylesheet" href="/static/css/tokens.css?v=2.2.7" />
9
+ <link rel="stylesheet" href="/static/platform.css?v=2.2.7" />
10
+ <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.7" />
11
11
  </head>
12
12
  <body>
13
13
  <main>
package/static/admin.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <meta charset="UTF-8">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">
7
7
  <title>Lattice AI Admin</title>
8
- <script src="/static/scripts/ux.js?v=2.2.1"></script>
8
+ <script src="/static/scripts/ux.js?v=2.2.7"></script>
9
9
  <link rel="manifest" href="/manifest.json">
10
10
  <meta name="theme-color" content="#f3ecff">
11
11
  <meta name="apple-mobile-web-app-capable" content="yes">
@@ -15,8 +15,13 @@
15
15
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
16
16
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap">
17
17
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/tabler-icons.min.css">
18
- <link rel="stylesheet" href="/static/lattice-reference.css?v=0.3.3">
19
- <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.1">
18
+ <link rel="stylesheet" href="/static/css/tokens.css?v=2.2.7">
19
+ <link rel="stylesheet" href="/static/css/reference/base.css?v=2.2.7">
20
+ <link rel="stylesheet" href="/static/css/reference/account.css?v=2.2.7">
21
+ <link rel="stylesheet" href="/static/css/reference/admin.css?v=2.2.7">
22
+ <link rel="stylesheet" href="/static/css/reference/graph.css?v=2.2.7">
23
+ <link rel="stylesheet" href="/static/css/reference/chat.css?v=2.2.7">
24
+ <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.7">
20
25
  <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
21
26
  </head>
22
27
 
@@ -4,10 +4,10 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content" />
6
6
  <title>Multi-Agent Runtime — Lattice AI</title>
7
- <script src="/static/scripts/ux.js?v=2.2.1"></script>
8
- <link rel="stylesheet" href="/static/css/tokens.css?v=2.2.1" />
9
- <link rel="stylesheet" href="/static/platform.css?v=2.2.1" />
10
- <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.1" />
7
+ <script src="/static/scripts/ux.js?v=2.2.7"></script>
8
+ <link rel="stylesheet" href="/static/css/tokens.css?v=2.2.7" />
9
+ <link rel="stylesheet" href="/static/platform.css?v=2.2.7" />
10
+ <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.7" />
11
11
  </head>
12
12
  <body>
13
13
  <main>
package/static/chat.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <meta charset="UTF-8">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">
7
7
  <title>Lattice AI — All-in-One Multimodal Workspace</title>
8
- <script src="/static/scripts/ux.js?v=2.2.1"></script>
8
+ <script src="/static/scripts/ux.js?v=2.2.7"></script>
9
9
 
10
10
  <!-- PWA -->
11
11
  <link rel="manifest" href="/manifest.json">
@@ -24,8 +24,13 @@
24
24
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
25
25
 
26
26
  <!-- ── Setup Wizard Styles ──────────────────────────────────────────── -->
27
- <link rel="stylesheet" href="/static/lattice-reference.css?v=0.3.3">
28
- <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.1">
27
+ <link rel="stylesheet" href="/static/css/tokens.css?v=2.2.7">
28
+ <link rel="stylesheet" href="/static/css/reference/base.css?v=2.2.7">
29
+ <link rel="stylesheet" href="/static/css/reference/account.css?v=2.2.7">
30
+ <link rel="stylesheet" href="/static/css/reference/admin.css?v=2.2.7">
31
+ <link rel="stylesheet" href="/static/css/reference/graph.css?v=2.2.7">
32
+ <link rel="stylesheet" href="/static/css/reference/chat.css?v=2.2.7">
33
+ <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.7">
29
34
  </head>
30
35
 
31
36
  <body class="lattice-ref-chat">
@@ -414,7 +419,7 @@
414
419
  <!-- Planning -->
415
420
  <div class="pipeline-phase-row">
416
421
  <div class="pipeline-phase-label">
417
- <span class="pipeline-phase-badge" style="background:rgba(99,102,241,0.15);color:#818cf8">📋 Planning</span>
422
+ <span class="pipeline-phase-badge" style="background:rgba(99,102,241,0.15);color:var(--accent)">📋 Planning</span>
418
423
  <span style="color:var(--muted);font-size:11px">계획 수립 · 유저와 함께 검토</span>
419
424
  </div>
420
425
  <select id="pipeline-planning-select" class="pipeline-select">
@@ -425,7 +430,7 @@
425
430
  <!-- Executing -->
426
431
  <div class="pipeline-phase-row">
427
432
  <div class="pipeline-phase-label">
428
- <span class="pipeline-phase-badge" style="background:rgba(34,197,94,0.12);color:#4ade80">⚙️ Executing</span>
433
+ <span class="pipeline-phase-badge" style="background:rgba(34,197,94,0.12);color:var(--success)">⚙️ Executing</span>
429
434
  <span style="color:var(--muted);font-size:11px">코드 작성 · 파일 생성 · 툴 호출</span>
430
435
  </div>
431
436
  <select id="pipeline-executing-select" class="pipeline-select">
@@ -436,7 +441,7 @@
436
441
  <!-- Reviewing -->
437
442
  <div class="pipeline-phase-row">
438
443
  <div class="pipeline-phase-label">
439
- <span class="pipeline-phase-badge" style="background:rgba(251,146,60,0.12);color:#fb923c">🔍 Reviewing</span>
444
+ <span class="pipeline-phase-badge" style="background:rgba(251,146,60,0.12);color:var(--warning)">🔍 Reviewing</span>
440
445
  <span style="color:var(--muted);font-size:11px">결과 검증 · 최종 답변 생성</span>
441
446
  </div>
442
447
  <select id="pipeline-reviewing-select" class="pipeline-select">
@@ -501,7 +506,7 @@
501
506
  <button class="admin-action" onclick="sendFileToChat()" style="flex:1;background:rgba(111,66,232,0.12);border-color:rgba(111,66,232,0.28)">
502
507
  <i class="ti ti-send"></i> AI에게 보내기
503
508
  </button>
504
- <button class="status-btn" onclick="closeFileEditor();document.getElementById('local-browser-overlay').style.display='flex'" style="flex:1">
509
+ <button class="status-btn" onclick="closeFileEditor();showModalLayer('local-browser-overlay')" style="flex:1">
505
510
  <i class="ti ti-arrow-left"></i> 탐색기로
506
511
  </button>
507
512
  </div>
@@ -736,7 +741,7 @@
736
741
  <div id="cu-screenshot-meta" style="font-size:11px;color:var(--faint);text-align:center"></div>
737
742
  </div>
738
743
  <!-- Controls panel -->
739
- <div style="width:280px;padding:14px;display:flex;flex-direction:column;gap:12px;overflow-y:auto">
744
+ <div class="cu-controls-panel" style="padding:14px;display:flex;flex-direction:column;gap:12px;overflow-y:auto">
740
745
  <!-- Agent task input -->
741
746
  <div>
742
747
  <div style="font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:8px">AI 자동 작업</div>
@@ -774,7 +779,7 @@
774
779
  <div id="cu-log" style="flex:1;background:var(--surface-3);border:1px solid var(--border);border-radius:8px;padding:8px;font-size:11px;font-family:monospace;color:var(--muted);overflow-y:auto;max-height:200px;min-height:80px"></div>
775
780
  </div>
776
781
  <!-- Permission note -->
777
- <div style="background:rgba(240,168,50,.07);border:1px solid rgba(240,168,50,.2);border-radius:8px;padding:9px 11px;font-size:11px;color:rgba(240,168,50,.85)">
782
+ <div style="background:rgba(240,168,50,.07);border:1px solid rgba(240,168,50,.2);border-radius:8px;padding:9px 11px;font-size:11px;color:var(--warning)">
778
783
  <i class="ti ti-alert-triangle"></i> macOS 손쉬운 사용 권한 필요<br>
779
784
  <span style="opacity:.7">시스템 설정 → 개인 정보 보호 → 손쉬운 사용</span>
780
785
  </div>
@@ -833,7 +838,7 @@
833
838
  </div>
834
839
 
835
840
 
836
- <script src="/static/scripts/chat.js?v=0.3.4"></script>
841
+ <script src="/static/scripts/chat.js?v=2.2.7"></script>
837
842
  </body>
838
843
 
839
844
  </html>
@@ -0,0 +1,303 @@
1
+ /* Lattice AI — account / auth page (account.html, body.lattice-ref-auth). Token-native. */
2
+ /* ============================================================
3
+ ACCOUNT / AUTH PAGE (account.html)
4
+ Light lavender theme — unified with chat/graph/admin pages.
5
+ ============================================================ */
6
+
7
+ * { box-sizing: border-box; margin: 0; padding: 0; }
8
+ html, body.lattice-ref-auth { height: 100%; }
9
+ body.lattice-ref-auth {
10
+ font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
11
+ color: var(--text);
12
+ background: var(--app-bg);
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ min-height: 100vh;
17
+ padding: 24px;
18
+ overflow: hidden;
19
+ position: relative;
20
+ }
21
+
22
+ body::before {
23
+ content: '';
24
+ position: fixed;
25
+ inset: 0;
26
+ background:
27
+ radial-gradient(circle, rgba(123,109,255,0.28) 1px, transparent 1.8px),
28
+ linear-gradient(rgba(123,109,255,0.08) 1px, transparent 1px),
29
+ linear-gradient(90deg, rgba(123,109,255,0.06) 1px, transparent 1px);
30
+ background-size: 82px 82px, 46px 46px, 46px 46px;
31
+ background-position: 16px 18px, 0 0, 0 0;
32
+ mask-image: linear-gradient(180deg, rgba(0,0,0,0.18), rgba(0,0,0,0.02));
33
+ pointer-events: none;
34
+ }
35
+
36
+ body::after {
37
+ content: '';
38
+ position: fixed;
39
+ inset: 0;
40
+ background:
41
+ radial-gradient(ellipse at 8% 78%, rgba(142,111,255,0.24), transparent 34%),
42
+ linear-gradient(115deg, transparent 0 35%, rgba(111,75,246,0.09) 35.2%, transparent 35.6% 100%);
43
+ pointer-events: none;
44
+ }
45
+
46
+ .orb {
47
+ display: none;
48
+ }
49
+
50
+ .login-shell {
51
+ width: min(920px, 100%);
52
+ display: grid;
53
+ grid-template-columns: minmax(280px, 400px) minmax(220px, 1fr);
54
+ align-items: center;
55
+ gap: 46px;
56
+ position: relative;
57
+ z-index: 1;
58
+ }
59
+
60
+ .brand-preview {
61
+ min-height: 360px;
62
+ border-radius: 34px;
63
+ background:
64
+ radial-gradient(circle at 54% 45%, rgba(111,75,246,0.24), transparent 18%),
65
+ linear-gradient(145deg, rgba(255,255,255,0.68), rgba(244,239,255,0.32));
66
+ border: 1px solid rgba(111,75,246,0.12);
67
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.85);
68
+ position: relative;
69
+ overflow: hidden;
70
+ }
71
+ .brand-preview::before {
72
+ content: '';
73
+ position: absolute;
74
+ inset: auto -12% 0 -8%;
75
+ height: 46%;
76
+ background: linear-gradient(135deg, rgba(111,75,246,0.24), rgba(255,255,255,0.12));
77
+ clip-path: polygon(0 62%, 18% 42%, 36% 54%, 55% 26%, 76% 44%, 100% 20%, 100% 100%, 0 100%);
78
+ filter: blur(1px);
79
+ }
80
+ .preview-node {
81
+ position: absolute;
82
+ width: 52px;
83
+ height: 52px;
84
+ border-radius: 17px;
85
+ background: var(--surface-2);
86
+ border: 1px solid rgba(111,75,246,0.18);
87
+ box-shadow: 0 18px 40px rgba(111,75,246,0.16);
88
+ }
89
+ .preview-node::after {
90
+ content: '';
91
+ position: absolute;
92
+ inset: 14px;
93
+ border-radius: 10px;
94
+ background: linear-gradient(135deg, #6f4bf6, #9f8cff);
95
+ }
96
+ .preview-node.n1 { top: 52px; left: 58px; }
97
+ .preview-node.n2 { top: 112px; right: 64px; }
98
+ .preview-node.n3 { left: 120px; bottom: 92px; }
99
+ .preview-node.n4 { right: 120px; bottom: 58px; }
100
+ .preview-line {
101
+ position: absolute;
102
+ height: 2px;
103
+ width: 150px;
104
+ background: linear-gradient(90deg, transparent, rgba(111,75,246,0.45), transparent);
105
+ transform-origin: left center;
106
+ }
107
+ .preview-line.l1 { top: 108px; left: 112px; transform: rotate(18deg); }
108
+ .preview-line.l2 { top: 186px; left: 176px; transform: rotate(112deg); }
109
+ .preview-line.l3 { bottom: 112px; left: 172px; transform: rotate(-13deg); }
110
+
111
+ .card {
112
+ width: min(400px, 100%);
113
+ background: var(--card);
114
+ border: 1px solid rgba(111,75,246,0.13);
115
+ border-radius: 14px;
116
+ padding: 38px 34px;
117
+ box-shadow: var(--shadow), inset 0 1px 0 rgba(255,255,255,0.9);
118
+ position: relative;
119
+ z-index: 1;
120
+ backdrop-filter: blur(28px);
121
+ }
122
+
123
+ .card::before {
124
+ content: '';
125
+ position: absolute;
126
+ top: 0; left: 50%;
127
+ transform: translateX(-50%);
128
+ width: 55%; height: 1px;
129
+ background: linear-gradient(90deg, transparent, rgba(111,75,246,0.65), rgba(123,109,255,0.45), transparent);
130
+ }
131
+
132
+ .logo {
133
+ width: 54px; height: 54px;
134
+ background: linear-gradient(135deg, #6f4bf6 0%, #8d7aff 100%);
135
+ border-radius: 10px;
136
+ display: flex; align-items: center; justify-content: center;
137
+ font-size: 26px; color: #fff;
138
+ margin: 0 auto 18px;
139
+ box-shadow: 0 16px 34px rgba(111,75,246,0.28);
140
+ }
141
+
142
+ .title {
143
+ text-align: center;
144
+ font-size: 23px;
145
+ font-weight: 800;
146
+ margin-bottom: 6px;
147
+ background: linear-gradient(135deg, #1f2140 35%, #6f4bf6 82%);
148
+ -webkit-background-clip: text;
149
+ -webkit-text-fill-color: transparent;
150
+ background-clip: text;
151
+ }
152
+
153
+ .subtitle {
154
+ text-align: center;
155
+ color: var(--muted);
156
+ font-size: 12.5px;
157
+ margin-bottom: 26px;
158
+ line-height: 1.5;
159
+ }
160
+
161
+ .input {
162
+ width: 100%;
163
+ padding: 12px 14px;
164
+ margin-bottom: 10px;
165
+ background: var(--surface);
166
+ border: 1px solid rgba(111,75,246,0.16);
167
+ color: var(--text);
168
+ border-radius: 8px;
169
+ outline: none;
170
+ font-size: 14px;
171
+ font-family: inherit;
172
+ transition: border-color .15s, box-shadow .15s;
173
+ }
174
+ .input:focus {
175
+ border-color: rgba(111,75,246,0.52);
176
+ box-shadow: 0 0 0 4px rgba(111,75,246,0.10);
177
+ }
178
+ .input::placeholder { color: var(--faint); }
179
+
180
+ .submit {
181
+ width: 100%;
182
+ padding: 13px;
183
+ background: linear-gradient(135deg, #6f4bf6, #7b6dff);
184
+ color: #fff;
185
+ border: none;
186
+ border-radius: 8px;
187
+ cursor: pointer;
188
+ font-weight: 800;
189
+ font-size: 14px;
190
+ font-family: inherit;
191
+ box-shadow: 0 14px 30px rgba(111,75,246,0.24);
192
+ transition: all .18s;
193
+ margin-top: 4px;
194
+ }
195
+ .submit:hover {
196
+ background: linear-gradient(135deg, #5f3ee6, #705fff);
197
+ box-shadow: 0 18px 38px rgba(111,75,246,0.30);
198
+ transform: translateY(-1px);
199
+ }
200
+ .submit:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }
201
+
202
+ .switch {
203
+ margin-top: 18px;
204
+ text-align: center;
205
+ font-size: 12.5px;
206
+ color: var(--faint);
207
+ }
208
+ .switch a { color: #6f4bf6; text-decoration: none; font-weight: 700; }
209
+ .switch a:hover { text-decoration: underline; }
210
+
211
+ .sso-divider {
212
+ display: flex; align-items: center; gap: 10px;
213
+ margin: 14px 0 10px;
214
+ color: var(--faint); font-size: 11.5px;
215
+ }
216
+ .sso-divider::before, .sso-divider::after {
217
+ content: ''; flex: 1;
218
+ height: 1px; background: rgba(111,75,246,0.12);
219
+ }
220
+ .sso-btn {
221
+ width: 100%;
222
+ padding: 12px;
223
+ background: var(--surface-2);
224
+ border: 1px solid rgba(111,75,246,0.15);
225
+ color: var(--text);
226
+ border-radius: 8px;
227
+ cursor: pointer;
228
+ font-weight: 600;
229
+ font-size: 13.5px;
230
+ font-family: inherit;
231
+ display: flex; align-items: center; justify-content: center; gap: 8px;
232
+ transition: all .18s;
233
+ }
234
+ .sso-btn:hover {
235
+ background: var(--surface);
236
+ border-color: rgba(111,75,246,0.34);
237
+ }
238
+
239
+ .msg {
240
+ font-size: 12px;
241
+ min-height: 18px;
242
+ margin-bottom: 6px;
243
+ text-align: center;
244
+ color: #d44f5c;
245
+ }
246
+ .msg.ok { color: var(--success); }
247
+
248
+ /* Lang picker */
249
+ .lang-wrap {
250
+ position: absolute;
251
+ top: 12px;
252
+ right: 12px;
253
+ z-index: 10;
254
+ }
255
+ .lang-btn {
256
+ background: var(--surface-2);
257
+ border: 1px solid rgba(111,75,246,0.18);
258
+ color: var(--text);
259
+ border-radius: 8px;
260
+ padding: 7px 12px;
261
+ font-size: 13px;
262
+ font-family: inherit;
263
+ cursor: pointer;
264
+ transition: background .15s;
265
+ box-shadow: 0 10px 28px rgba(86,70,160,0.12);
266
+ }
267
+ .lang-btn:hover { background: rgba(111,75,246,0.08); }
268
+ .lang-menu {
269
+ display: none;
270
+ position: absolute;
271
+ top: calc(100% + 6px);
272
+ right: 0;
273
+ background: var(--surface-elevated);
274
+ border: 1px solid rgba(111,75,246,0.15);
275
+ border-radius: 8px;
276
+ padding: 4px;
277
+ min-width: 130px;
278
+ box-shadow: 0 18px 44px rgba(86,70,160,0.16);
279
+ }
280
+ .lang-menu.open { display: block; }
281
+ .lang-opt {
282
+ padding: 7px 10px;
283
+ border-radius: 7px;
284
+ cursor: pointer;
285
+ font-size: 13px;
286
+ color: var(--muted);
287
+ }
288
+ .lang-opt:hover { background: rgba(111,75,246,0.07); color: var(--text); }
289
+ .lang-opt.active { color: var(--accent); font-weight: 700; }
290
+
291
+ @media (max-width: 760px) {
292
+ .login-shell { display: block; }
293
+ .brand-preview { display: none; }
294
+ }
295
+
296
+ :root[data-lt-theme="dark"] body.lattice-ref-auth .title,
297
+ :root[data-lt-theme="dark"] body.lattice-ref-auth #register-section .title {
298
+ background: none;
299
+ -webkit-background-clip: border-box;
300
+ background-clip: border-box;
301
+ -webkit-text-fill-color: currentColor;
302
+ color: var(--text);
303
+ }