@cremini/skillpack 1.0.9 → 1.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 +4 -4
- package/dist/cli.js +4 -0
- package/package.json +4 -3
- package/runtime/README.md +11 -1
- package/runtime/server/dist/adapters/markdown.js +74 -0
- package/runtime/server/dist/adapters/markdown.js.map +1 -0
- package/runtime/server/dist/adapters/slack.js +369 -0
- package/runtime/server/dist/adapters/slack.js.map +1 -0
- package/runtime/server/dist/adapters/telegram.js +199 -0
- package/runtime/server/dist/adapters/telegram.js.map +1 -0
- package/runtime/server/dist/adapters/types.js +2 -0
- package/runtime/server/dist/adapters/types.js.map +1 -0
- package/runtime/server/dist/adapters/web.js +201 -0
- package/runtime/server/dist/adapters/web.js.map +1 -0
- package/runtime/server/dist/agent.js +223 -0
- package/runtime/server/dist/agent.js.map +1 -0
- package/runtime/server/dist/config.js +73 -0
- package/runtime/server/dist/config.js.map +1 -0
- package/runtime/server/dist/index.js +146 -0
- package/runtime/server/dist/index.js.map +1 -0
- package/runtime/server/dist/lifecycle.js +85 -0
- package/runtime/server/dist/lifecycle.js.map +1 -0
- package/runtime/server/dist/memory.js +195 -0
- package/runtime/server/dist/memory.js.map +1 -0
- package/runtime/server/package-lock.json +4028 -244
- package/runtime/server/package.json +13 -3
- package/runtime/start.bat +40 -4
- package/runtime/start.sh +30 -2
- package/runtime/web/index.html +145 -18
- package/runtime/web/js/api-key-dialog.js +153 -0
- package/runtime/web/js/api.js +25 -0
- package/runtime/web/js/chat-apps-dialog.js +192 -0
- package/runtime/web/{app.js → js/chat.js} +112 -193
- package/runtime/web/js/config.js +16 -0
- package/runtime/web/js/main.js +56 -0
- package/runtime/web/js/settings.js +205 -0
- package/runtime/web/styles.css +301 -10
- package/runtime/server/chat-proxy.js +0 -229
- package/runtime/server/index.js +0 -63
- package/runtime/server/routes.js +0 -104
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { state } from "./config.js";
|
|
2
|
+
import { restartRuntime, saveConfigData } from "./api.js";
|
|
3
|
+
|
|
4
|
+
// DOM Elements
|
|
5
|
+
let dialog;
|
|
6
|
+
let settingsBtn;
|
|
7
|
+
let closeBtn;
|
|
8
|
+
let saveBtn;
|
|
9
|
+
let providerSelect;
|
|
10
|
+
let apiKeyInput;
|
|
11
|
+
let telegramTokenInput;
|
|
12
|
+
let slackBotTokenInput;
|
|
13
|
+
let slackAppTokenInput;
|
|
14
|
+
let keyStatus;
|
|
15
|
+
let restartBtn;
|
|
16
|
+
|
|
17
|
+
export function initSettings() {
|
|
18
|
+
dialog = document.getElementById("settings-dialog");
|
|
19
|
+
settingsBtn = document.getElementById("open-settings-btn");
|
|
20
|
+
closeBtn = document.getElementById("close-settings-btn");
|
|
21
|
+
saveBtn = document.getElementById("save-settings-btn");
|
|
22
|
+
|
|
23
|
+
providerSelect = document.getElementById("provider-select");
|
|
24
|
+
apiKeyInput = document.getElementById("api-key-input");
|
|
25
|
+
telegramTokenInput = document.getElementById("telegram-token-input");
|
|
26
|
+
slackBotTokenInput = document.getElementById("slack-bot-token-input");
|
|
27
|
+
slackAppTokenInput = document.getElementById("slack-app-token-input");
|
|
28
|
+
keyStatus = document.getElementById("key-status");
|
|
29
|
+
restartBtn = document.getElementById("restart-service-btn");
|
|
30
|
+
|
|
31
|
+
if (!dialog) return;
|
|
32
|
+
|
|
33
|
+
// Open/Close dialog
|
|
34
|
+
if (settingsBtn) {
|
|
35
|
+
settingsBtn.addEventListener("click", () => {
|
|
36
|
+
populateForm();
|
|
37
|
+
dialog.showModal();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (closeBtn) {
|
|
42
|
+
closeBtn.addEventListener("click", () => {
|
|
43
|
+
dialog.close();
|
|
44
|
+
keyStatus.textContent = ""; // clear status on close
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Save Settings
|
|
49
|
+
if (saveBtn) {
|
|
50
|
+
saveBtn.addEventListener("click", handleSave);
|
|
51
|
+
}
|
|
52
|
+
if (restartBtn) {
|
|
53
|
+
restartBtn.addEventListener("click", handleRestart);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Placeholder logic
|
|
57
|
+
if (providerSelect) {
|
|
58
|
+
providerSelect.addEventListener("change", updatePlaceholder);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function updatePlaceholder() {
|
|
63
|
+
const p = providerSelect.value;
|
|
64
|
+
if (p === "openai") apiKeyInput.placeholder = "sk-proj-...";
|
|
65
|
+
else if (p === "anthropic") apiKeyInput.placeholder = "sk-ant-api03-...";
|
|
66
|
+
else apiKeyInput.placeholder = "sk-...";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function populateForm() {
|
|
70
|
+
const config = state.config;
|
|
71
|
+
if (!config) return;
|
|
72
|
+
|
|
73
|
+
if (state.restartRequired) {
|
|
74
|
+
setStatus(
|
|
75
|
+
config.runtimeControl?.canManagedRestart
|
|
76
|
+
? "Settings saved. Restart service to apply changes."
|
|
77
|
+
: "Settings saved. Restart the service manually to apply changes.",
|
|
78
|
+
"warning",
|
|
79
|
+
);
|
|
80
|
+
updateRestartButton(true);
|
|
81
|
+
} else {
|
|
82
|
+
setStatus("", "");
|
|
83
|
+
updateRestartButton(false);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (config.hasApiKey && config.apiKey) {
|
|
87
|
+
apiKeyInput.value = config.apiKey;
|
|
88
|
+
} else if (config.hasApiKey) {
|
|
89
|
+
apiKeyInput.value = "***************************************************";
|
|
90
|
+
} else {
|
|
91
|
+
apiKeyInput.value = "";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (config.provider) {
|
|
95
|
+
providerSelect.value = config.provider;
|
|
96
|
+
}
|
|
97
|
+
updatePlaceholder();
|
|
98
|
+
|
|
99
|
+
const adapters = config.adapters || {};
|
|
100
|
+
if (adapters.telegram && adapters.telegram.token) {
|
|
101
|
+
telegramTokenInput.value = adapters.telegram.token;
|
|
102
|
+
} else {
|
|
103
|
+
telegramTokenInput.value = "";
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (adapters.slack) {
|
|
107
|
+
slackBotTokenInput.value = adapters.slack.botToken || "";
|
|
108
|
+
slackAppTokenInput.value = adapters.slack.appToken || "";
|
|
109
|
+
} else {
|
|
110
|
+
slackBotTokenInput.value = "";
|
|
111
|
+
slackAppTokenInput.value = "";
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function handleSave() {
|
|
116
|
+
const key = apiKeyInput.value.trim();
|
|
117
|
+
const provider = providerSelect.value;
|
|
118
|
+
const telegramToken = telegramTokenInput.value.trim();
|
|
119
|
+
const slackBotToken = slackBotTokenInput.value.trim();
|
|
120
|
+
const slackAppToken = slackAppTokenInput.value.trim();
|
|
121
|
+
|
|
122
|
+
const adapters = {};
|
|
123
|
+
if (telegramToken) adapters.telegram = { token: telegramToken };
|
|
124
|
+
if (slackBotToken || slackAppToken) {
|
|
125
|
+
adapters.slack = {
|
|
126
|
+
botToken: slackBotToken || undefined,
|
|
127
|
+
appToken: slackAppToken || undefined
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const updates = { provider, adapters };
|
|
132
|
+
if (key && key !== "***************************************************" && key !== state.config.apiKey) {
|
|
133
|
+
updates.key = key;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
const res = await saveConfigData(updates);
|
|
138
|
+
|
|
139
|
+
// Update local config
|
|
140
|
+
state.config.provider = res.provider;
|
|
141
|
+
state.config.adapters = res.adapters;
|
|
142
|
+
state.config.runtimeControl = res.runtimeControl;
|
|
143
|
+
if (updates.key) {
|
|
144
|
+
state.config.hasApiKey = true;
|
|
145
|
+
state.config.apiKey = updates.key;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (state.config.hasApiKey && state.config.apiKey) {
|
|
149
|
+
apiKeyInput.value = state.config.apiKey;
|
|
150
|
+
} else if (state.config.hasApiKey) {
|
|
151
|
+
apiKeyInput.value = "***************************************************";
|
|
152
|
+
} else {
|
|
153
|
+
apiKeyInput.value = "";
|
|
154
|
+
}
|
|
155
|
+
state.restartRequired = !!res.requiresRestart;
|
|
156
|
+
|
|
157
|
+
if (res.requiresRestart) {
|
|
158
|
+
setStatus(
|
|
159
|
+
res.runtimeControl.canManagedRestart
|
|
160
|
+
? "Settings saved. Restart service to apply changes."
|
|
161
|
+
: "Settings saved. Restart the service manually to apply changes.",
|
|
162
|
+
"warning",
|
|
163
|
+
);
|
|
164
|
+
updateRestartButton(res.runtimeControl.canManagedRestart);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
setStatus("Settings saved", "success");
|
|
169
|
+
updateRestartButton(false);
|
|
170
|
+
|
|
171
|
+
} catch (err) {
|
|
172
|
+
setStatus("Save failed: " + err.message, "error");
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async function handleRestart() {
|
|
177
|
+
if (!restartBtn) return;
|
|
178
|
+
|
|
179
|
+
restartBtn.disabled = true;
|
|
180
|
+
if (saveBtn) saveBtn.disabled = true;
|
|
181
|
+
setStatus("Restarting service...", "warning");
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
await restartRuntime();
|
|
185
|
+
setTimeout(() => {
|
|
186
|
+
window.location.reload();
|
|
187
|
+
}, 6000);
|
|
188
|
+
} catch (err) {
|
|
189
|
+
if (saveBtn) saveBtn.disabled = false;
|
|
190
|
+
restartBtn.disabled = false;
|
|
191
|
+
setStatus("Restart failed: " + err.message, "error");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function updateRestartButton(show) {
|
|
196
|
+
if (!restartBtn) return;
|
|
197
|
+
restartBtn.hidden = !show;
|
|
198
|
+
restartBtn.disabled = false;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function setStatus(message, status) {
|
|
202
|
+
if (!keyStatus) return;
|
|
203
|
+
keyStatus.textContent = message;
|
|
204
|
+
keyStatus.className = status ? `status-text ${status}` : "status-text";
|
|
205
|
+
}
|
package/runtime/web/styles.css
CHANGED
|
@@ -55,7 +55,8 @@ body {
|
|
|
55
55
|
.sidebar-header {
|
|
56
56
|
padding: 24px 20px;
|
|
57
57
|
border-bottom: 1px solid var(--border-color);
|
|
58
|
-
background:
|
|
58
|
+
background: transparent;
|
|
59
|
+
flex-shrink: 0;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
.sidebar-header h1 {
|
|
@@ -71,12 +72,20 @@ body {
|
|
|
71
72
|
line-height: 1.4;
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
.sidebar-section {
|
|
75
|
+
.sidebar-settings-section {
|
|
75
76
|
padding: 16px 20px;
|
|
76
|
-
border-
|
|
77
|
+
border-top: 1px solid var(--border-color);
|
|
78
|
+
background: var(--bg-secondary);
|
|
79
|
+
flex-shrink: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.sidebar-skills-section {
|
|
83
|
+
padding: 16px 20px;
|
|
84
|
+
flex: 1;
|
|
85
|
+
overflow-y: auto;
|
|
77
86
|
}
|
|
78
87
|
|
|
79
|
-
.sidebar-section h3 {
|
|
88
|
+
.sidebar-skills-section h3 {
|
|
80
89
|
font-size: 11px;
|
|
81
90
|
font-weight: 600;
|
|
82
91
|
text-transform: uppercase;
|
|
@@ -85,23 +94,26 @@ body {
|
|
|
85
94
|
margin-bottom: 10px;
|
|
86
95
|
}
|
|
87
96
|
|
|
88
|
-
.sidebar-section ul {
|
|
97
|
+
.sidebar-skills-section ul {
|
|
89
98
|
list-style: none;
|
|
90
99
|
}
|
|
91
100
|
|
|
92
|
-
.sidebar-section li {
|
|
93
|
-
padding:
|
|
101
|
+
.sidebar-skills-section li {
|
|
102
|
+
padding: 12px;
|
|
94
103
|
font-size: 13px;
|
|
95
104
|
color: var(--text-primary);
|
|
96
105
|
background: var(--bg-tertiary);
|
|
106
|
+
border: 1px solid transparent;
|
|
97
107
|
border-radius: var(--radius-sm);
|
|
98
|
-
margin-bottom:
|
|
108
|
+
margin-bottom: 8px;
|
|
99
109
|
cursor: default;
|
|
100
110
|
transition: all 0.2s;
|
|
101
111
|
}
|
|
102
112
|
|
|
103
|
-
.sidebar-section li:hover {
|
|
104
|
-
background: var(--
|
|
113
|
+
.sidebar-skills-section li:hover {
|
|
114
|
+
background: var(--bg-secondary);
|
|
115
|
+
border-color: var(--border-color);
|
|
116
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.03);
|
|
105
117
|
}
|
|
106
118
|
|
|
107
119
|
.skill-name {
|
|
@@ -198,6 +210,9 @@ body {
|
|
|
198
210
|
.status-text.success {
|
|
199
211
|
color: var(--success);
|
|
200
212
|
}
|
|
213
|
+
.status-text.warning {
|
|
214
|
+
color: var(--accent);
|
|
215
|
+
}
|
|
201
216
|
.status-text.error {
|
|
202
217
|
color: var(--error);
|
|
203
218
|
}
|
|
@@ -772,3 +787,279 @@ body {
|
|
|
772
787
|
.thinking-content p:last-child {
|
|
773
788
|
margin-bottom: 0;
|
|
774
789
|
}
|
|
790
|
+
|
|
791
|
+
/* ---- Sidebar Action Buttons ---- */
|
|
792
|
+
.sidebar-actions-group {
|
|
793
|
+
padding: 24px 20px;
|
|
794
|
+
border-bottom: 1px solid var(--border-color);
|
|
795
|
+
display: flex;
|
|
796
|
+
flex-direction: column;
|
|
797
|
+
gap: 12px;
|
|
798
|
+
flex-shrink: 0;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
.action-btn {
|
|
802
|
+
display: flex;
|
|
803
|
+
align-items: center;
|
|
804
|
+
justify-content: center;
|
|
805
|
+
gap: 8px;
|
|
806
|
+
width: 100%;
|
|
807
|
+
padding: 9px 16px;
|
|
808
|
+
border-radius: var(--radius-sm);
|
|
809
|
+
font-size: 14px;
|
|
810
|
+
font-weight: 500;
|
|
811
|
+
cursor: pointer;
|
|
812
|
+
transition: all 0.25s ease;
|
|
813
|
+
font-family: inherit;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/* Default (not connected) state — outline style */
|
|
817
|
+
.action-btn.chatapps-btn {
|
|
818
|
+
background: var(--bg-tertiary);
|
|
819
|
+
border: 1px solid var(--border-color);
|
|
820
|
+
color: var(--text-primary);
|
|
821
|
+
}
|
|
822
|
+
.action-btn.chatapps-btn:hover {
|
|
823
|
+
border-color: var(--accent);
|
|
824
|
+
background: var(--bg-secondary);
|
|
825
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.04);
|
|
826
|
+
transform: translateY(-1px);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/* Connected state — green filled */
|
|
830
|
+
.action-btn.chatapps-btn.connected {
|
|
831
|
+
background: var(--accent);
|
|
832
|
+
border: 1px solid var(--accent);
|
|
833
|
+
color: #fff;
|
|
834
|
+
opacity: 0.85;
|
|
835
|
+
}
|
|
836
|
+
.action-btn.chatapps-btn.connected:hover {
|
|
837
|
+
opacity: 1;
|
|
838
|
+
box-shadow: 0 4px 16px var(--accent-glow);
|
|
839
|
+
transform: translateY(-1px);
|
|
840
|
+
}
|
|
841
|
+
.action-btn.chatapps-btn.connected .action-btn-icon {
|
|
842
|
+
stroke: #fff;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/* API Key button — always outline style */
|
|
846
|
+
.action-btn.apikey-btn {
|
|
847
|
+
background: var(--bg-tertiary);
|
|
848
|
+
border: 1px solid var(--border-color);
|
|
849
|
+
color: var(--text-primary);
|
|
850
|
+
}
|
|
851
|
+
.action-btn.apikey-btn:hover {
|
|
852
|
+
border-color: var(--accent);
|
|
853
|
+
background: var(--bg-secondary);
|
|
854
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.04);
|
|
855
|
+
transform: translateY(-1px);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/* API Key configured state */
|
|
859
|
+
.action-btn.apikey-btn.connected {
|
|
860
|
+
border-color: var(--accent);
|
|
861
|
+
color: var(--accent);
|
|
862
|
+
background: var(--bg-secondary);
|
|
863
|
+
}
|
|
864
|
+
.action-btn.apikey-btn.connected .action-btn-icon {
|
|
865
|
+
stroke: var(--accent);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
.action-btn-icon {
|
|
869
|
+
flex-shrink: 0;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/* ---- Compact Modal Variant ---- */
|
|
873
|
+
.compact-modal {
|
|
874
|
+
width: 440px;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
/* ---- Settings Modal ---- */
|
|
878
|
+
.settings-trigger-btn {
|
|
879
|
+
display: flex;
|
|
880
|
+
align-items: center;
|
|
881
|
+
justify-content: center;
|
|
882
|
+
gap: 8px;
|
|
883
|
+
width: 100%;
|
|
884
|
+
padding: 12px;
|
|
885
|
+
background: var(--bg-tertiary);
|
|
886
|
+
border: 1px solid var(--border-color);
|
|
887
|
+
border-radius: var(--radius-sm);
|
|
888
|
+
color: var(--text-primary);
|
|
889
|
+
font-weight: 500;
|
|
890
|
+
cursor: pointer;
|
|
891
|
+
transition: all 0.2s ease;
|
|
892
|
+
}
|
|
893
|
+
.settings-trigger-btn:hover {
|
|
894
|
+
background: #ebebeb;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
.settings-modal {
|
|
898
|
+
margin: auto;
|
|
899
|
+
padding: 0;
|
|
900
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
901
|
+
border-radius: 16px;
|
|
902
|
+
background: var(--bg-secondary);
|
|
903
|
+
width: 520px;
|
|
904
|
+
max-width: 90vw;
|
|
905
|
+
box-shadow: 0 20px 40px rgba(0,0,0,0.1), 0 0 0 1px var(--border-color);
|
|
906
|
+
font-family: inherit;
|
|
907
|
+
color: var(--text-primary);
|
|
908
|
+
opacity: 0;
|
|
909
|
+
transform: scale(0.95) translateY(10px);
|
|
910
|
+
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
911
|
+
}
|
|
912
|
+
.settings-modal[open] {
|
|
913
|
+
opacity: 1;
|
|
914
|
+
transform: scale(1) translateY(0);
|
|
915
|
+
}
|
|
916
|
+
.settings-modal::backdrop {
|
|
917
|
+
background: rgba(0, 0, 0, 0.2);
|
|
918
|
+
backdrop-filter: blur(4px);
|
|
919
|
+
-webkit-backdrop-filter: blur(4px);
|
|
920
|
+
opacity: 0;
|
|
921
|
+
transition: opacity 0.3s ease;
|
|
922
|
+
}
|
|
923
|
+
.settings-modal[open]::backdrop {
|
|
924
|
+
opacity: 1;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
.settings-modal-header {
|
|
928
|
+
display: flex;
|
|
929
|
+
justify-content: space-between;
|
|
930
|
+
align-items: center;
|
|
931
|
+
padding: 24px 24px 12px 24px;
|
|
932
|
+
background: transparent;
|
|
933
|
+
border-top-left-radius: 16px;
|
|
934
|
+
border-top-right-radius: 16px;
|
|
935
|
+
}
|
|
936
|
+
.settings-modal-header h2 { font-size: 18px; font-weight: 600; margin: 0; color: var(--text-primary); letter-spacing: -0.01em; }
|
|
937
|
+
.close-btn {
|
|
938
|
+
background: var(--bg-tertiary);
|
|
939
|
+
border: 1px solid var(--border-color);
|
|
940
|
+
border-radius: 8px;
|
|
941
|
+
width: 32px;
|
|
942
|
+
height: 32px;
|
|
943
|
+
display: flex;
|
|
944
|
+
align-items: center;
|
|
945
|
+
justify-content: center;
|
|
946
|
+
font-size: 18px;
|
|
947
|
+
cursor: pointer;
|
|
948
|
+
color: var(--text-secondary);
|
|
949
|
+
transition: all 0.2s ease;
|
|
950
|
+
}
|
|
951
|
+
.close-btn:hover {
|
|
952
|
+
background: var(--bg-primary);
|
|
953
|
+
color: var(--text-primary);
|
|
954
|
+
border-color: var(--text-secondary);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
.settings-sections {
|
|
958
|
+
padding: 24px;
|
|
959
|
+
max-height: calc(85vh - 140px);
|
|
960
|
+
overflow-y: auto;
|
|
961
|
+
}
|
|
962
|
+
.settings-section {
|
|
963
|
+
margin-bottom: 28px;
|
|
964
|
+
padding-bottom: 28px;
|
|
965
|
+
border-bottom: 1px solid var(--border-color);
|
|
966
|
+
}
|
|
967
|
+
.settings-section:last-child {
|
|
968
|
+
margin-bottom: 0;
|
|
969
|
+
padding-bottom: 0;
|
|
970
|
+
border-bottom: none;
|
|
971
|
+
}
|
|
972
|
+
.section-title {
|
|
973
|
+
font-size: 14px;
|
|
974
|
+
font-weight: 600;
|
|
975
|
+
color: var(--text-primary);
|
|
976
|
+
margin-top: 0;
|
|
977
|
+
margin-bottom: 16px;
|
|
978
|
+
text-transform: uppercase;
|
|
979
|
+
letter-spacing: 0.5px;
|
|
980
|
+
opacity: 0.8;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
.form-group { margin-bottom: 16px; }
|
|
984
|
+
.form-group:last-child { margin-bottom: 0; }
|
|
985
|
+
.form-group label { display: block; font-size: 13px; font-weight: 500; margin-bottom: 8px; color: var(--text-primary); }
|
|
986
|
+
.form-input {
|
|
987
|
+
width: 100%;
|
|
988
|
+
padding: 12px 14px;
|
|
989
|
+
background: var(--bg-tertiary);
|
|
990
|
+
border: 1px solid var(--border-color);
|
|
991
|
+
border-radius: var(--radius-sm);
|
|
992
|
+
font-size: 14px;
|
|
993
|
+
outline: none;
|
|
994
|
+
color: var(--text-primary);
|
|
995
|
+
transition: all 0.2s ease;
|
|
996
|
+
}
|
|
997
|
+
.form-input:focus {
|
|
998
|
+
border-color: var(--accent);
|
|
999
|
+
background: var(--bg-secondary);
|
|
1000
|
+
box-shadow: 0 0 0 3px var(--accent-glow);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/* Specific to provider-select in Settings Modal to match form-input */
|
|
1004
|
+
.settings-modal .provider-select-wrapper select {
|
|
1005
|
+
padding: 12px 14px;
|
|
1006
|
+
font-size: 14px;
|
|
1007
|
+
transition: all 0.2s ease;
|
|
1008
|
+
}
|
|
1009
|
+
.settings-modal .provider-select-wrapper select:focus {
|
|
1010
|
+
border-color: var(--accent);
|
|
1011
|
+
background: var(--bg-secondary);
|
|
1012
|
+
box-shadow: 0 0 0 3px var(--accent-glow);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
.settings-modal-footer {
|
|
1016
|
+
padding: 16px 24px 24px 24px;
|
|
1017
|
+
background: transparent;
|
|
1018
|
+
border-bottom-left-radius: 16px;
|
|
1019
|
+
border-bottom-right-radius: 16px;
|
|
1020
|
+
display: flex;
|
|
1021
|
+
justify-content: flex-end;
|
|
1022
|
+
align-items: center;
|
|
1023
|
+
gap: 12px;
|
|
1024
|
+
}
|
|
1025
|
+
.secondary-btn {
|
|
1026
|
+
padding: 10px 20px;
|
|
1027
|
+
background: transparent;
|
|
1028
|
+
color: var(--text-primary);
|
|
1029
|
+
border: 1px solid var(--border-color);
|
|
1030
|
+
border-radius: var(--radius-sm);
|
|
1031
|
+
font-weight: 500;
|
|
1032
|
+
font-size: 14px;
|
|
1033
|
+
cursor: pointer;
|
|
1034
|
+
transition: all 0.2s ease;
|
|
1035
|
+
}
|
|
1036
|
+
.secondary-btn:hover {
|
|
1037
|
+
border-color: var(--accent);
|
|
1038
|
+
color: var(--accent);
|
|
1039
|
+
}
|
|
1040
|
+
.primary-btn {
|
|
1041
|
+
padding: 10px 20px;
|
|
1042
|
+
background: var(--accent);
|
|
1043
|
+
color: #fff;
|
|
1044
|
+
border: none;
|
|
1045
|
+
border-radius: var(--radius-sm);
|
|
1046
|
+
font-weight: 500;
|
|
1047
|
+
font-size: 14px;
|
|
1048
|
+
cursor: pointer;
|
|
1049
|
+
transition: all 0.2s ease;
|
|
1050
|
+
}
|
|
1051
|
+
.primary-btn:hover {
|
|
1052
|
+
background: var(--accent-hover);
|
|
1053
|
+
box-shadow: 0 4px 12px var(--accent-glow);
|
|
1054
|
+
transform: translateY(-1px);
|
|
1055
|
+
}
|
|
1056
|
+
.primary-btn:active {
|
|
1057
|
+
transform: translateY(0);
|
|
1058
|
+
}
|
|
1059
|
+
.primary-btn:disabled,
|
|
1060
|
+
.secondary-btn:disabled {
|
|
1061
|
+
opacity: 0.6;
|
|
1062
|
+
cursor: not-allowed;
|
|
1063
|
+
transform: none;
|
|
1064
|
+
box-shadow: none;
|
|
1065
|
+
}
|