vibespot 0.7.1 → 0.9.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/dist/index.js +160 -99
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
- package/ui/chat.js +175 -7
- package/ui/index.html +58 -31
- package/ui/settings.js +456 -238
- package/ui/setup.js +205 -18
- package/ui/styles.css +343 -0
- package/ui/upload-panel.js +99 -35
package/ui/setup.js
CHANGED
|
@@ -101,10 +101,8 @@ async function initSetup() {
|
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
document.getElementById("section-fetch").classList.remove("hidden");
|
|
107
|
-
}
|
|
104
|
+
// Reset panel state
|
|
105
|
+
remoteThemesLoaded = false;
|
|
108
106
|
|
|
109
107
|
} catch (err) {
|
|
110
108
|
showError("Could not connect to server. Is vibeSpot running?");
|
|
@@ -853,35 +851,226 @@ function hideError() {
|
|
|
853
851
|
document.getElementById("setup-error").classList.add("hidden");
|
|
854
852
|
}
|
|
855
853
|
|
|
854
|
+
// ---------------------------------------------------------------------------
|
|
855
|
+
// Action button panel toggling
|
|
856
|
+
// ---------------------------------------------------------------------------
|
|
857
|
+
|
|
858
|
+
let activePanel = null;
|
|
859
|
+
let remoteThemesLoaded = false;
|
|
860
|
+
|
|
861
|
+
function togglePanel(action) {
|
|
862
|
+
const panels = document.querySelectorAll(".setup__panel");
|
|
863
|
+
const buttons = document.querySelectorAll(".setup__action-btn");
|
|
864
|
+
|
|
865
|
+
// Close if same panel clicked
|
|
866
|
+
if (activePanel === action) {
|
|
867
|
+
panels.forEach((p) => p.classList.add("hidden"));
|
|
868
|
+
buttons.forEach((b) => b.classList.remove("active"));
|
|
869
|
+
activePanel = null;
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// Hide all, show target
|
|
874
|
+
panels.forEach((p) => p.classList.add("hidden"));
|
|
875
|
+
buttons.forEach((b) => b.classList.remove("active"));
|
|
876
|
+
|
|
877
|
+
const panelMap = { new: "panel-new", continue: "panel-continue", download: "panel-download", convert: "panel-convert" };
|
|
878
|
+
const panel = document.getElementById(panelMap[action]);
|
|
879
|
+
if (panel) {
|
|
880
|
+
panel.classList.remove("hidden");
|
|
881
|
+
activePanel = action;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// Mark button active
|
|
885
|
+
const btn = document.querySelector(`.setup__action-btn[data-action="${action}"]`);
|
|
886
|
+
if (btn) btn.classList.add("active");
|
|
887
|
+
|
|
888
|
+
// Focus input if applicable
|
|
889
|
+
if (action === "new") setTimeout(() => document.getElementById("new-theme-name")?.focus(), 50);
|
|
890
|
+
if (action === "convert") setTimeout(() => document.getElementById("import-url")?.focus(), 50);
|
|
891
|
+
|
|
892
|
+
// Load remote themes on first open
|
|
893
|
+
if (action === "download" && !remoteThemesLoaded) loadDownloadPanel();
|
|
894
|
+
|
|
895
|
+
// Populate continue panel
|
|
896
|
+
if (action === "continue") populateContinuePanel();
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
function populateContinuePanel() {
|
|
900
|
+
const container = document.getElementById("continue-projects");
|
|
901
|
+
const empty = document.getElementById("continue-empty");
|
|
902
|
+
if (!container) return;
|
|
903
|
+
|
|
904
|
+
// Gather projects from the rail
|
|
905
|
+
const railItems = document.querySelectorAll(".project-rail__item");
|
|
906
|
+
if (railItems.length === 0) {
|
|
907
|
+
container.innerHTML = "";
|
|
908
|
+
empty.classList.remove("hidden");
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
empty.classList.add("hidden");
|
|
913
|
+
container.innerHTML = "";
|
|
914
|
+
|
|
915
|
+
railItems.forEach((item) => {
|
|
916
|
+
const name = item.dataset.name || item.querySelector(".project-rail__name")?.textContent || "";
|
|
917
|
+
const sessionId = item.dataset.sessionId || "";
|
|
918
|
+
const meta = item.querySelector(".project-rail__meta")?.textContent || "";
|
|
919
|
+
|
|
920
|
+
const pill = document.createElement("button");
|
|
921
|
+
pill.className = "setup__pill";
|
|
922
|
+
pill.innerHTML = `<span>${esc(name)}</span>${meta ? `<span class="setup__pill__meta">${esc(meta)}</span>` : ""}`;
|
|
923
|
+
pill.addEventListener("click", () => {
|
|
924
|
+
if (sessionId) {
|
|
925
|
+
resumeSession(sessionId);
|
|
926
|
+
} else {
|
|
927
|
+
openTheme(name);
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
container.appendChild(pill);
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
async function loadDownloadPanel() {
|
|
935
|
+
const accountEl = document.getElementById("dl-account");
|
|
936
|
+
const accountName = document.getElementById("dl-account-name");
|
|
937
|
+
const switchArea = document.getElementById("dl-account-switch");
|
|
938
|
+
const inputRow = document.getElementById("dl-input-row");
|
|
939
|
+
const hint = document.getElementById("dl-hint");
|
|
940
|
+
const noAccount = document.getElementById("dl-no-account");
|
|
941
|
+
|
|
942
|
+
accountEl.classList.add("hidden");
|
|
943
|
+
switchArea.classList.add("hidden");
|
|
944
|
+
inputRow.classList.add("hidden");
|
|
945
|
+
hint.classList.add("hidden");
|
|
946
|
+
noAccount.classList.add("hidden");
|
|
947
|
+
|
|
948
|
+
// Fetch active account info to show portal name
|
|
949
|
+
try {
|
|
950
|
+
const statusRes = await fetch("/api/settings/status");
|
|
951
|
+
const statusData = await statusRes.json();
|
|
952
|
+
const accounts = statusData.config?.hubspotAccounts || [];
|
|
953
|
+
const activeId = statusData.config?.activeHubSpotAccount;
|
|
954
|
+
const active = accounts.find((a) => a.portalId === activeId) || accounts[0];
|
|
955
|
+
|
|
956
|
+
if (active) {
|
|
957
|
+
accountName.textContent = `${active.portalName || active.portalId} (${active.portalId})`;
|
|
958
|
+
accountEl.classList.remove("hidden");
|
|
959
|
+
inputRow.classList.remove("hidden");
|
|
960
|
+
hint.classList.remove("hidden");
|
|
961
|
+
|
|
962
|
+
// Wire up change button
|
|
963
|
+
initDlAccountSwitch(accounts, activeId);
|
|
964
|
+
remoteThemesLoaded = true;
|
|
965
|
+
} else {
|
|
966
|
+
noAccount.classList.remove("hidden");
|
|
967
|
+
}
|
|
968
|
+
} catch {
|
|
969
|
+
noAccount.classList.remove("hidden");
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function initDlAccountSwitch(accounts, activeId) {
|
|
974
|
+
const changeBtn = document.getElementById("dl-account-change");
|
|
975
|
+
const switchArea = document.getElementById("dl-account-switch");
|
|
976
|
+
|
|
977
|
+
// Remove old listener by replacing the element
|
|
978
|
+
const newBtn = changeBtn.cloneNode(true);
|
|
979
|
+
changeBtn.parentNode.replaceChild(newBtn, changeBtn);
|
|
980
|
+
|
|
981
|
+
newBtn.addEventListener("click", () => {
|
|
982
|
+
if (!switchArea.classList.contains("hidden")) { switchArea.classList.add("hidden"); return; }
|
|
983
|
+
switchArea.classList.remove("hidden");
|
|
984
|
+
|
|
985
|
+
let html = '<div style="display:flex;flex-direction:column;gap:6px">';
|
|
986
|
+
for (const acct of accounts) {
|
|
987
|
+
const isActive = acct.portalId === activeId;
|
|
988
|
+
html += `<button class="btn btn--${isActive ? "primary" : "secondary"} dl-acct-btn" data-portal="${esc(acct.portalId)}" style="text-align:left;padding:6px 12px;font-size:13px">${esc(acct.portalName || acct.portalId)} (${esc(acct.portalId)})${isActive ? " ✓" : ""}</button>`;
|
|
989
|
+
}
|
|
990
|
+
html += `<button class="btn btn--secondary dl-acct-btn" data-portal="__new" style="text-align:left;padding:6px 12px;font-size:13px">+ Add another account</button>`;
|
|
991
|
+
html += '</div>';
|
|
992
|
+
switchArea.innerHTML = html;
|
|
993
|
+
|
|
994
|
+
switchArea.querySelectorAll(".dl-acct-btn").forEach((btn) => {
|
|
995
|
+
btn.addEventListener("click", async () => {
|
|
996
|
+
const pid = btn.dataset.portal;
|
|
997
|
+
if (pid === "__new") {
|
|
998
|
+
switchArea.classList.add("hidden");
|
|
999
|
+
if (typeof openSettings === "function") openSettings();
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
if (pid === activeId) { switchArea.classList.add("hidden"); return; }
|
|
1003
|
+
await fetch("/api/settings/hs-switch", {
|
|
1004
|
+
method: "POST",
|
|
1005
|
+
headers: { "Content-Type": "application/json" },
|
|
1006
|
+
body: JSON.stringify({ portalId: pid }),
|
|
1007
|
+
});
|
|
1008
|
+
switchArea.classList.add("hidden");
|
|
1009
|
+
// Reload themes for the new account
|
|
1010
|
+
remoteThemesLoaded = false;
|
|
1011
|
+
loadDownloadPanel();
|
|
1012
|
+
});
|
|
1013
|
+
});
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
async function downloadThemeByName() {
|
|
1018
|
+
const input = document.getElementById("dl-theme-name");
|
|
1019
|
+
const name = input.value.trim();
|
|
1020
|
+
if (!name) { showError("Enter a theme name."); return; }
|
|
1021
|
+
|
|
1022
|
+
showLoading(`Downloading ${name} from HubSpot...`);
|
|
1023
|
+
|
|
1024
|
+
try {
|
|
1025
|
+
const res = await fetch("/api/setup/fetch", {
|
|
1026
|
+
method: "POST",
|
|
1027
|
+
headers: { "Content-Type": "application/json" },
|
|
1028
|
+
body: JSON.stringify({ name }),
|
|
1029
|
+
});
|
|
1030
|
+
const data = await res.json();
|
|
1031
|
+
|
|
1032
|
+
if (data.error) { showError(data.error); return; }
|
|
1033
|
+
showApp(data.themeName);
|
|
1034
|
+
} catch (err) {
|
|
1035
|
+
showError("Failed to download theme: " + err.message);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
856
1039
|
// ---------------------------------------------------------------------------
|
|
857
1040
|
// Event listeners
|
|
858
1041
|
// ---------------------------------------------------------------------------
|
|
859
1042
|
|
|
1043
|
+
// Action buttons
|
|
1044
|
+
document.querySelectorAll(".setup__action-btn").forEach((btn) => {
|
|
1045
|
+
btn.addEventListener("click", () => togglePanel(btn.dataset.action));
|
|
1046
|
+
});
|
|
1047
|
+
|
|
1048
|
+
// New theme
|
|
860
1049
|
document.getElementById("btn-create-theme").addEventListener("click", createTheme);
|
|
861
1050
|
document.getElementById("new-theme-name").addEventListener("keydown", (e) => {
|
|
862
1051
|
if (e.key === "Enter") { e.preventDefault(); createTheme(); }
|
|
863
1052
|
});
|
|
864
1053
|
|
|
865
|
-
|
|
866
|
-
document.getElementById("fetch-theme
|
|
867
|
-
|
|
1054
|
+
// Download from HubSpot
|
|
1055
|
+
document.getElementById("btn-fetch-theme").addEventListener("click", downloadThemeByName);
|
|
1056
|
+
document.getElementById("dl-theme-name").addEventListener("keydown", (e) => {
|
|
1057
|
+
if (e.key === "Enter") { e.preventDefault(); downloadThemeByName(); }
|
|
868
1058
|
});
|
|
869
1059
|
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
});
|
|
1060
|
+
// Settings link in download panel
|
|
1061
|
+
const dlSettingsLink = document.getElementById("dl-open-settings");
|
|
1062
|
+
if (dlSettingsLink) {
|
|
1063
|
+
dlSettingsLink.addEventListener("click", (e) => { e.preventDefault(); openSettings(); });
|
|
1064
|
+
}
|
|
876
1065
|
|
|
877
|
-
// Import from GitHub
|
|
1066
|
+
// Import from GitHub / Lovable
|
|
878
1067
|
document.getElementById("import-btn").addEventListener("click", async () => {
|
|
879
1068
|
const urlInput = document.getElementById("import-url");
|
|
880
1069
|
const url = urlInput.value.trim();
|
|
881
1070
|
if (!url) return;
|
|
882
1071
|
|
|
883
1072
|
// Extract repo name to use as theme name
|
|
884
|
-
const repoMatch = url.match(/github\.com\/[\w.-]+\/([\w.-]+)/);
|
|
1073
|
+
const repoMatch = url.match(/(?:github\.com|lovable\.dev)\/[\w.-]+\/([\w.-]+)/);
|
|
885
1074
|
const themeName = repoMatch ? repoMatch[1].replace(/\.git$/, "") : "imported-project";
|
|
886
1075
|
|
|
887
1076
|
showLoading(`Importing ${themeName}...`);
|
|
@@ -893,7 +1082,7 @@ document.getElementById("import-btn").addEventListener("click", async () => {
|
|
|
893
1082
|
const setupRes = await fetch("/api/setup/create", {
|
|
894
1083
|
method: "POST",
|
|
895
1084
|
headers: { "Content-Type": "application/json" },
|
|
896
|
-
body: JSON.stringify({ themeName }),
|
|
1085
|
+
body: JSON.stringify({ name: themeName }),
|
|
897
1086
|
});
|
|
898
1087
|
const setupData = await setupRes.json();
|
|
899
1088
|
if (setupData.error) {
|
|
@@ -932,8 +1121,6 @@ document.getElementById("import-url").addEventListener("keydown", (e) => {
|
|
|
932
1121
|
if (e.key === "Enter") { e.preventDefault(); document.getElementById("import-btn").click(); }
|
|
933
1122
|
});
|
|
934
1123
|
|
|
935
|
-
// API key is now handled in the settings panel (settings.js)
|
|
936
|
-
|
|
937
1124
|
// ---------------------------------------------------------------------------
|
|
938
1125
|
// Helpers
|
|
939
1126
|
// ---------------------------------------------------------------------------
|
package/ui/styles.css
CHANGED
|
@@ -270,6 +270,124 @@ body { display: flex; }
|
|
|
270
270
|
margin-top: 6px;
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
+
/* Action buttons grid */
|
|
274
|
+
.setup__actions {
|
|
275
|
+
display: grid;
|
|
276
|
+
grid-template-columns: repeat(4, 1fr);
|
|
277
|
+
gap: 10px;
|
|
278
|
+
margin-bottom: 16px;
|
|
279
|
+
}
|
|
280
|
+
.setup__action-btn {
|
|
281
|
+
position: relative;
|
|
282
|
+
display: flex;
|
|
283
|
+
flex-direction: column;
|
|
284
|
+
align-items: center;
|
|
285
|
+
gap: 6px;
|
|
286
|
+
padding: 16px 8px;
|
|
287
|
+
background: var(--bg-input);
|
|
288
|
+
border: 1px solid var(--border);
|
|
289
|
+
border-radius: var(--radius);
|
|
290
|
+
color: var(--text);
|
|
291
|
+
font-family: var(--font);
|
|
292
|
+
font-size: 13px;
|
|
293
|
+
cursor: pointer;
|
|
294
|
+
transition: border-color 0.2s, background 0.2s;
|
|
295
|
+
}
|
|
296
|
+
.setup__action-btn:hover {
|
|
297
|
+
border-color: var(--accent);
|
|
298
|
+
background: var(--bg-card);
|
|
299
|
+
}
|
|
300
|
+
.setup__action-btn.active {
|
|
301
|
+
border-color: var(--accent);
|
|
302
|
+
background: var(--accent-bg, rgba(232, 97, 58, 0.08));
|
|
303
|
+
}
|
|
304
|
+
.setup__action-icon {
|
|
305
|
+
font-size: 20px;
|
|
306
|
+
line-height: 1;
|
|
307
|
+
opacity: 0.7;
|
|
308
|
+
}
|
|
309
|
+
.setup__action-btn.active .setup__action-icon { opacity: 1; }
|
|
310
|
+
.setup__action-badge {
|
|
311
|
+
position: absolute;
|
|
312
|
+
top: -6px;
|
|
313
|
+
right: -6px;
|
|
314
|
+
font-size: 9px;
|
|
315
|
+
font-weight: 600;
|
|
316
|
+
text-transform: uppercase;
|
|
317
|
+
letter-spacing: 0.5px;
|
|
318
|
+
padding: 1px 6px;
|
|
319
|
+
border-radius: 8px;
|
|
320
|
+
background: var(--accent);
|
|
321
|
+
color: #fff;
|
|
322
|
+
line-height: 1.4;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/* Expandable panels */
|
|
326
|
+
.setup__panel {
|
|
327
|
+
padding: 12px 0;
|
|
328
|
+
animation: panelSlideIn 0.15s ease-out;
|
|
329
|
+
}
|
|
330
|
+
@keyframes panelSlideIn {
|
|
331
|
+
from { opacity: 0; transform: translateY(-6px); }
|
|
332
|
+
to { opacity: 1; transform: translateY(0); }
|
|
333
|
+
}
|
|
334
|
+
.setup__panel-account {
|
|
335
|
+
font-size: 13px;
|
|
336
|
+
color: var(--text-muted);
|
|
337
|
+
margin-bottom: 10px;
|
|
338
|
+
}
|
|
339
|
+
.setup__panel-account span { color: var(--text); font-weight: 500; }
|
|
340
|
+
.setup__panel-loading {
|
|
341
|
+
display: flex;
|
|
342
|
+
align-items: center;
|
|
343
|
+
gap: 8px;
|
|
344
|
+
color: var(--text-muted);
|
|
345
|
+
font-size: 13px;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* Theme pills for Continue panel */
|
|
349
|
+
.setup__pills {
|
|
350
|
+
display: flex;
|
|
351
|
+
flex-wrap: wrap;
|
|
352
|
+
gap: 8px;
|
|
353
|
+
}
|
|
354
|
+
.setup__pill {
|
|
355
|
+
display: flex;
|
|
356
|
+
align-items: center;
|
|
357
|
+
gap: 6px;
|
|
358
|
+
padding: 8px 14px;
|
|
359
|
+
background: var(--bg-input);
|
|
360
|
+
border: 1px solid var(--border);
|
|
361
|
+
border-radius: 20px;
|
|
362
|
+
color: var(--text);
|
|
363
|
+
font-size: 13px;
|
|
364
|
+
cursor: pointer;
|
|
365
|
+
transition: border-color 0.2s, background 0.2s;
|
|
366
|
+
}
|
|
367
|
+
.setup__pill:hover {
|
|
368
|
+
border-color: var(--accent);
|
|
369
|
+
background: var(--bg-card);
|
|
370
|
+
}
|
|
371
|
+
.setup__pill__meta {
|
|
372
|
+
font-size: 11px;
|
|
373
|
+
color: var(--text-muted);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/* Select dropdown */
|
|
377
|
+
.setup__select {
|
|
378
|
+
flex: 1;
|
|
379
|
+
padding: 10px 14px;
|
|
380
|
+
background: var(--bg-input);
|
|
381
|
+
border: 1px solid var(--border);
|
|
382
|
+
border-radius: var(--radius);
|
|
383
|
+
color: var(--text);
|
|
384
|
+
font-family: var(--font);
|
|
385
|
+
font-size: 14px;
|
|
386
|
+
outline: none;
|
|
387
|
+
cursor: pointer;
|
|
388
|
+
}
|
|
389
|
+
.setup__select:focus { border-color: var(--accent-glow); }
|
|
390
|
+
|
|
273
391
|
.setup__cards {
|
|
274
392
|
display: flex;
|
|
275
393
|
flex-wrap: wrap;
|
|
@@ -1017,6 +1135,18 @@ body { display: flex; }
|
|
|
1017
1135
|
gap: 8px;
|
|
1018
1136
|
}
|
|
1019
1137
|
|
|
1138
|
+
.btn-link {
|
|
1139
|
+
background: none;
|
|
1140
|
+
border: none;
|
|
1141
|
+
color: var(--accent);
|
|
1142
|
+
cursor: pointer;
|
|
1143
|
+
font-size: 12px;
|
|
1144
|
+
padding: 0;
|
|
1145
|
+
margin-left: 6px;
|
|
1146
|
+
text-decoration: underline;
|
|
1147
|
+
}
|
|
1148
|
+
.btn-link:hover { opacity: 0.8; }
|
|
1149
|
+
|
|
1020
1150
|
/* HubSpot setup dialog (deferred install/auth) */
|
|
1021
1151
|
.hs-setup__steps {
|
|
1022
1152
|
margin: 12px 0 16px;
|
|
@@ -1686,6 +1816,130 @@ body { display: flex; }
|
|
|
1686
1816
|
padding: 12px 16px;
|
|
1687
1817
|
border-top: 1px solid var(--border);
|
|
1688
1818
|
background: var(--bg-panel-solid);
|
|
1819
|
+
position: relative;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
/* File chips (pending attachments) */
|
|
1823
|
+
.chat__file-chips {
|
|
1824
|
+
display: none;
|
|
1825
|
+
flex-wrap: wrap;
|
|
1826
|
+
gap: 6px;
|
|
1827
|
+
margin-bottom: 8px;
|
|
1828
|
+
}
|
|
1829
|
+
.chat__file-chips.visible {
|
|
1830
|
+
display: flex;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
.file-chip {
|
|
1834
|
+
display: inline-flex;
|
|
1835
|
+
align-items: center;
|
|
1836
|
+
gap: 5px;
|
|
1837
|
+
padding: 3px 8px;
|
|
1838
|
+
border-radius: 6px;
|
|
1839
|
+
font-size: 11px;
|
|
1840
|
+
line-height: 1.4;
|
|
1841
|
+
}
|
|
1842
|
+
.file-chip--image {
|
|
1843
|
+
background: rgba(74, 255, 74, 0.1);
|
|
1844
|
+
border: 1px solid rgba(74, 255, 74, 0.3);
|
|
1845
|
+
color: #4aff4a;
|
|
1846
|
+
}
|
|
1847
|
+
.file-chip--doc {
|
|
1848
|
+
background: rgba(180, 120, 255, 0.1);
|
|
1849
|
+
border: 1px solid rgba(180, 120, 255, 0.3);
|
|
1850
|
+
color: #b478ff;
|
|
1851
|
+
}
|
|
1852
|
+
.file-chip__icon { font-size: 13px; }
|
|
1853
|
+
.file-chip__name {
|
|
1854
|
+
max-width: 120px;
|
|
1855
|
+
overflow: hidden;
|
|
1856
|
+
text-overflow: ellipsis;
|
|
1857
|
+
white-space: nowrap;
|
|
1858
|
+
}
|
|
1859
|
+
.file-chip__size {
|
|
1860
|
+
color: var(--text-muted);
|
|
1861
|
+
font-size: 10px;
|
|
1862
|
+
}
|
|
1863
|
+
.file-chip__remove {
|
|
1864
|
+
background: none;
|
|
1865
|
+
border: none;
|
|
1866
|
+
color: #ff6b6b;
|
|
1867
|
+
cursor: pointer;
|
|
1868
|
+
font-size: 14px;
|
|
1869
|
+
padding: 0 2px;
|
|
1870
|
+
line-height: 1;
|
|
1871
|
+
}
|
|
1872
|
+
.file-chip__remove:hover { color: #ff4444; }
|
|
1873
|
+
|
|
1874
|
+
.file-chip--sent {
|
|
1875
|
+
padding: 3px 8px;
|
|
1876
|
+
font-size: 11px;
|
|
1877
|
+
background: rgba(255, 255, 255, 0.1);
|
|
1878
|
+
border-color: rgba(255, 255, 255, 0.25);
|
|
1879
|
+
color: var(--text);
|
|
1880
|
+
}
|
|
1881
|
+
.file-chip--sent.file-chip--image {
|
|
1882
|
+
background: rgba(74, 255, 74, 0.12);
|
|
1883
|
+
border-color: rgba(74, 255, 74, 0.35);
|
|
1884
|
+
color: #5cff5c;
|
|
1885
|
+
}
|
|
1886
|
+
.file-chip--sent.file-chip--doc {
|
|
1887
|
+
background: rgba(180, 120, 255, 0.12);
|
|
1888
|
+
border-color: rgba(180, 120, 255, 0.35);
|
|
1889
|
+
color: #c49aff;
|
|
1890
|
+
}
|
|
1891
|
+
.file-chip--sent .file-chip__icon { font-size: 12px; }
|
|
1892
|
+
.file-chip--sent .file-chip__name {
|
|
1893
|
+
max-width: 150px;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
.chat-msg__files {
|
|
1897
|
+
display: flex;
|
|
1898
|
+
flex-wrap: wrap;
|
|
1899
|
+
gap: 5px;
|
|
1900
|
+
margin-bottom: 6px;
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
/* Drop overlay */
|
|
1904
|
+
.chat__drop-overlay {
|
|
1905
|
+
position: absolute;
|
|
1906
|
+
inset: 0;
|
|
1907
|
+
background: rgba(74, 158, 255, 0.08);
|
|
1908
|
+
border: 2px dashed var(--accent);
|
|
1909
|
+
border-radius: 12px;
|
|
1910
|
+
display: flex;
|
|
1911
|
+
align-items: center;
|
|
1912
|
+
justify-content: center;
|
|
1913
|
+
z-index: 10;
|
|
1914
|
+
}
|
|
1915
|
+
.chat__drop-overlay.hidden { display: none; }
|
|
1916
|
+
.chat__drop-overlay-content {
|
|
1917
|
+
display: flex;
|
|
1918
|
+
flex-direction: column;
|
|
1919
|
+
align-items: center;
|
|
1920
|
+
gap: 8px;
|
|
1921
|
+
color: var(--accent);
|
|
1922
|
+
font-size: 14px;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
/* Toast notification */
|
|
1926
|
+
.toast {
|
|
1927
|
+
position: fixed;
|
|
1928
|
+
bottom: 20px;
|
|
1929
|
+
left: 50%;
|
|
1930
|
+
transform: translateX(-50%) translateY(20px);
|
|
1931
|
+
background: #333;
|
|
1932
|
+
color: #fff;
|
|
1933
|
+
padding: 8px 16px;
|
|
1934
|
+
border-radius: 8px;
|
|
1935
|
+
font-size: 13px;
|
|
1936
|
+
opacity: 0;
|
|
1937
|
+
transition: opacity 0.3s, transform 0.3s;
|
|
1938
|
+
z-index: 9999;
|
|
1939
|
+
}
|
|
1940
|
+
.toast.visible {
|
|
1941
|
+
opacity: 1;
|
|
1942
|
+
transform: translateX(-50%) translateY(0);
|
|
1689
1943
|
}
|
|
1690
1944
|
|
|
1691
1945
|
.chat__input-wrapper {
|
|
@@ -1997,6 +2251,95 @@ body { display: flex; }
|
|
|
1997
2251
|
}
|
|
1998
2252
|
.settings__close:hover { background: var(--bg-hover); color: var(--text); }
|
|
1999
2253
|
|
|
2254
|
+
.settings__tabs {
|
|
2255
|
+
display: flex;
|
|
2256
|
+
border-bottom: 1px solid var(--border);
|
|
2257
|
+
padding: 0 20px;
|
|
2258
|
+
flex-shrink: 0;
|
|
2259
|
+
}
|
|
2260
|
+
.settings__tab {
|
|
2261
|
+
padding: 10px 16px;
|
|
2262
|
+
background: none;
|
|
2263
|
+
border: none;
|
|
2264
|
+
color: var(--text-muted);
|
|
2265
|
+
cursor: pointer;
|
|
2266
|
+
border-bottom: 2px solid transparent;
|
|
2267
|
+
font-size: 13px;
|
|
2268
|
+
font-weight: 500;
|
|
2269
|
+
transition: color 0.15s, border-color 0.15s;
|
|
2270
|
+
}
|
|
2271
|
+
.settings__tab:hover { color: var(--text); }
|
|
2272
|
+
.settings__tab.active { color: var(--accent); border-bottom-color: var(--accent); }
|
|
2273
|
+
|
|
2274
|
+
.settings__description {
|
|
2275
|
+
color: var(--text-muted);
|
|
2276
|
+
font-size: 12px;
|
|
2277
|
+
margin: 4px 0 12px;
|
|
2278
|
+
line-height: 1.4;
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
.settings__toggle-row {
|
|
2282
|
+
display: flex;
|
|
2283
|
+
align-items: center;
|
|
2284
|
+
justify-content: space-between;
|
|
2285
|
+
padding: 8px 0;
|
|
2286
|
+
}
|
|
2287
|
+
.settings__toggle-label {
|
|
2288
|
+
font-size: 13px;
|
|
2289
|
+
color: var(--text);
|
|
2290
|
+
}
|
|
2291
|
+
.settings__toggle-label-sub {
|
|
2292
|
+
font-size: 11px;
|
|
2293
|
+
color: var(--text-muted);
|
|
2294
|
+
margin-top: 2px;
|
|
2295
|
+
}
|
|
2296
|
+
.settings__toggle {
|
|
2297
|
+
position: relative;
|
|
2298
|
+
width: 36px;
|
|
2299
|
+
height: 20px;
|
|
2300
|
+
background: var(--border);
|
|
2301
|
+
border-radius: 10px;
|
|
2302
|
+
border: none;
|
|
2303
|
+
cursor: pointer;
|
|
2304
|
+
transition: background 0.2s;
|
|
2305
|
+
flex-shrink: 0;
|
|
2306
|
+
}
|
|
2307
|
+
.settings__toggle.active { background: var(--accent); }
|
|
2308
|
+
.settings__toggle::after {
|
|
2309
|
+
content: "";
|
|
2310
|
+
position: absolute;
|
|
2311
|
+
top: 2px;
|
|
2312
|
+
left: 2px;
|
|
2313
|
+
width: 16px;
|
|
2314
|
+
height: 16px;
|
|
2315
|
+
background: white;
|
|
2316
|
+
border-radius: 50%;
|
|
2317
|
+
transition: transform 0.2s;
|
|
2318
|
+
}
|
|
2319
|
+
.settings__toggle.active::after { transform: translateX(16px); }
|
|
2320
|
+
|
|
2321
|
+
.settings__mode-pills {
|
|
2322
|
+
display: flex;
|
|
2323
|
+
gap: 0;
|
|
2324
|
+
border: 1px solid var(--border);
|
|
2325
|
+
border-radius: var(--radius);
|
|
2326
|
+
overflow: hidden;
|
|
2327
|
+
margin-bottom: 12px;
|
|
2328
|
+
}
|
|
2329
|
+
.settings__mode-pill {
|
|
2330
|
+
flex: 1;
|
|
2331
|
+
padding: 8px 16px;
|
|
2332
|
+
background: none;
|
|
2333
|
+
border: none;
|
|
2334
|
+
color: var(--text-muted);
|
|
2335
|
+
font-size: 12px;
|
|
2336
|
+
cursor: pointer;
|
|
2337
|
+
transition: background 0.15s, color 0.15s;
|
|
2338
|
+
}
|
|
2339
|
+
.settings__mode-pill:not(:last-child) { border-right: 1px solid var(--border); }
|
|
2340
|
+
.settings__mode-pill:hover { background: var(--bg-hover); color: var(--text); }
|
|
2341
|
+
.settings__mode-pill.active { background: var(--accent); color: white; }
|
|
2342
|
+
|
|
2000
2343
|
.settings__body {
|
|
2001
2344
|
overflow-y: auto;
|
|
2002
2345
|
padding: 20px;
|