ngx-xtroedge-cms 1.1.0 → 1.3.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 CHANGED
@@ -32,32 +32,32 @@ var CMS_STYLES = `
32
32
  .lcms-loader-overlay {
33
33
  position: fixed; inset: 0; z-index: 10003;
34
34
  display: flex; align-items: center; justify-content: center;
35
- background: rgba(5, 20, 10, 0.45);
35
+ background: rgba(8, 8, 15, 0.45);
36
36
  backdrop-filter: blur(12px) saturate(1.4);
37
37
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
38
38
  }
39
39
  .lcms-loader-content { display: flex; flex-direction: column; align-items: center; gap: 28px; }
40
40
  .lcms-orbit-loader { position: relative; width: 90px; height: 90px; }
41
41
  .lcms-orbit { position: absolute; inset: 0; border-radius: 50%; border: 1px solid transparent; }
42
- .lcms-orbit-1 { border-top-color: rgba(0,200,83,0.5); animation: lcmsSpin 2.4s linear infinite; }
43
- .lcms-orbit-2 { inset: 10px; border-right-color: rgba(76,175,80,0.5); animation: lcmsSpin 3.2s linear infinite reverse; }
44
- .lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(129,199,132,0.5); animation: lcmsSpin 4.2s linear infinite; }
42
+ .lcms-orbit-1 { border-top-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); animation: lcmsSpin 2.4s linear infinite; }
43
+ .lcms-orbit-2 { inset: 10px; border-right-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.4); animation: lcmsSpin 3.2s linear infinite reverse; }
44
+ .lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); animation: lcmsSpin 4.2s linear infinite; }
45
45
  .lcms-particle {
46
46
  position: absolute; width: 8px; height: 8px; border-radius: 50%; top: -4px; left: 50%; margin-left: -4px;
47
47
  box-shadow: 0 0 12px 3px currentColor;
48
48
  }
49
- .lcms-orbit-1 .lcms-particle { background: #00C853; color: #00C853; }
50
- .lcms-orbit-2 .lcms-particle { background: #4CAF50; color: #4CAF50; top: 50%; left: auto; right: -4px; margin-left: 0; margin-top: -4px; }
51
- .lcms-orbit-3 .lcms-particle { background: #81C784; color: #81C784; top: auto; bottom: -4px; }
49
+ .lcms-orbit-1 .lcms-particle { background: var(--lcms-primary, #00C853); color: var(--lcms-primary, #00C853); }
50
+ .lcms-orbit-2 .lcms-particle { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.8); color: rgba(var(--lcms-primary-rgb, 0,200,83),0.8); top: 50%; left: auto; right: -4px; margin-left: 0; margin-top: -4px; }
51
+ .lcms-orbit-3 .lcms-particle { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.6); color: rgba(var(--lcms-primary-rgb, 0,200,83),0.6); top: auto; bottom: -4px; }
52
52
  .lcms-core-glow {
53
53
  position: absolute; width: 30px; height: 30px; top: 50%; left: 50%; transform: translate(-50%,-50%);
54
- border-radius: 50%; background: radial-gradient(circle, rgba(0,200,83,0.4), transparent 70%);
54
+ border-radius: 50%; background: radial-gradient(circle, rgba(var(--lcms-primary-rgb, 0,200,83),0.4), transparent 70%);
55
55
  animation: lcmsPulse 2s ease-in-out infinite;
56
56
  }
57
57
  .lcms-core {
58
58
  position: absolute; width: 12px; height: 12px; top: 50%; left: 50%; transform: translate(-50%,-50%);
59
- border-radius: 50%; background: linear-gradient(135deg, #00C853, #81C784);
60
- box-shadow: 0 0 20px rgba(0,200,83,0.6);
59
+ border-radius: 50%; background: linear-gradient(135deg, var(--lcms-primary, #00C853), rgba(var(--lcms-primary-rgb, 0,200,83),0.6));
60
+ box-shadow: 0 0 20px rgba(var(--lcms-primary-rgb, 0,200,83),0.6);
61
61
  }
62
62
  .lcms-loader-text {
63
63
  font-family: system-ui, -apple-system, sans-serif; font-size: 12px; font-weight: 600;
@@ -74,10 +74,10 @@ var CMS_STYLES = `
74
74
  padding: 10px 20px; border-radius: 10px; font-size: 13px; font-weight: 600;
75
75
  font-family: system-ui, -apple-system, sans-serif; color: white;
76
76
  display: flex; align-items: center; gap: 8px;
77
- box-shadow: 0 8px 32px rgba(0,200,83,0.25);
77
+ box-shadow: 0 8px 32px rgba(var(--lcms-primary-rgb, 0,200,83),0.25);
78
78
  animation: lcmsToastIn 0.3s ease, lcmsToastOut 0.3s ease 2.7s forwards; white-space: nowrap;
79
79
  }
80
- .lcms-toast-success { background: linear-gradient(135deg, #00C853, #2E7D32); }
80
+ .lcms-toast-success { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); }
81
81
  .lcms-toast-error { background: linear-gradient(135deg, #dc2626, #ef4444); }
82
82
  @keyframes lcmsToastIn { from { opacity: 0; transform: translateX(-50%) translateY(-12px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
83
83
  @keyframes lcmsToastOut { from { opacity: 1; transform: translateX(-50%) translateY(0); } to { opacity: 0; transform: translateX(-50%) translateY(-12px); } }
@@ -86,15 +86,15 @@ var CMS_STYLES = `
86
86
  .lcms-fab { position: fixed; z-index: 10001; user-select: none; touch-action: none; }
87
87
  .lcms-fab-btn {
88
88
  width: 52px; height: 52px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.2);
89
- background: rgba(0,200,83,0.35); color: white;
89
+ background: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); color: white;
90
90
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
91
91
  cursor: grab; display: flex; align-items: center; justify-content: center;
92
- box-shadow: 0 4px 20px rgba(0,200,83,0.3), inset 0 1px 0 rgba(255,255,255,0.15);
92
+ box-shadow: 0 4px 20px rgba(var(--lcms-primary-rgb, 0,200,83),0.3), inset 0 1px 0 rgba(255,255,255,0.15);
93
93
  transition: transform 0.2s, box-shadow 0.2s, background 0.2s; position: relative;
94
94
  }
95
- .lcms-fab-btn:not(.lcms-fab-active) { background: rgba(0,200,83,0.25); box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.1); }
96
- .lcms-fab-btn.lcms-fab-active { background: rgba(0,200,83,0.4); box-shadow: 0 4px 24px rgba(0,200,83,0.4), 0 0 16px rgba(0,200,83,0.2), inset 0 1px 0 rgba(255,255,255,0.2); }
97
- .lcms-fab-btn:hover { transform: scale(1.08); background: rgba(0,200,83,0.5); box-shadow: 0 6px 28px rgba(0,200,83,0.4), inset 0 1px 0 rgba(255,255,255,0.2); }
95
+ .lcms-fab-btn:not(.lcms-fab-active) { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.25); box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.1); }
96
+ .lcms-fab-btn.lcms-fab-active { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.4); box-shadow: 0 4px 24px rgba(var(--lcms-primary-rgb, 0,200,83),0.4), 0 0 16px rgba(var(--lcms-primary-rgb, 0,200,83),0.2), inset 0 1px 0 rgba(255,255,255,0.2); }
97
+ .lcms-fab-btn:hover { transform: scale(1.08); background: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); box-shadow: 0 6px 28px rgba(var(--lcms-primary-rgb, 0,200,83),0.4), inset 0 1px 0 rgba(255,255,255,0.2); }
98
98
  .lcms-badge {
99
99
  position: absolute; top: -4px; right: -4px; background: #ef4444; color: white;
100
100
  font-size: 11px; font-weight: 700; width: 20px; height: 20px; border-radius: 50%;
@@ -103,27 +103,44 @@ var CMS_STYLES = `
103
103
 
104
104
  /* PANEL */
105
105
  .lcms-panel {
106
- background: rgba(10,30,15,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
107
- border: 1px solid rgba(76,175,80,0.25); border-radius: 16px; padding: 16px; min-width: 230px;
106
+ background: rgba(12,12,18,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
107
+ border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-radius: 16px; padding: 16px; min-width: 230px;
108
108
  box-shadow: 0 8px 32px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.06);
109
109
  color: white; font-family: system-ui, -apple-system, sans-serif;
110
110
  animation: lcmsPanelIn 0.25s ease; position: absolute;
111
111
  }
112
112
  @keyframes lcmsPanelIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }
113
113
 
114
+ /* SITE IDENTIFIER */
115
+ .lcms-site-id {
116
+ display: flex; align-items: center; gap: 5px;
117
+ font-size: 10px; color: rgba(255,255,255,0.4);
118
+ padding: 0 0 8px; margin-bottom: 8px;
119
+ border-bottom: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12);
120
+ font-family: system-ui, -apple-system, sans-serif;
121
+ letter-spacing: 0.3px;
122
+ }
123
+ .lcms-site-id-icon { font-size: 12px; opacity: 0.7; }
124
+ .lcms-site-id-text {
125
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px;
126
+ font-weight: 500;
127
+ }
128
+
114
129
  /* BRANDING */
115
130
  .lcms-branding {
116
131
  display: flex; align-items: center; gap: 6px; padding: 8px 0 4px;
117
- border-top: 1px solid rgba(76,175,80,0.15); margin-top: 10px;
132
+ border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); margin-top: 10px;
133
+ cursor: pointer; transition: opacity 0.2s; user-select: none;
118
134
  }
135
+ .lcms-branding:hover { opacity: 0.8; }
119
136
  .lcms-branding-logo {
120
- width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, #00C853, #2E7D32);
137
+ width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));
121
138
  display: flex; align-items: center; justify-content: center;
122
139
  }
123
140
  .lcms-branding-text {
124
141
  font-size: 10px; font-weight: 600; color: rgba(255,255,255,0.35); letter-spacing: 0.5px;
125
142
  }
126
- .lcms-branding-text span { color: #00C853; font-weight: 700; }
143
+ .lcms-branding-text span { color: var(--lcms-primary, #00C853); font-weight: 700; }
127
144
 
128
145
  .lcms-panel-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
129
146
  .lcms-toggle { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
@@ -136,53 +153,84 @@ var CMS_STYLES = `
136
153
  content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%;
137
154
  top: 2px; left: 2px; background: rgba(255,255,255,0.6); transition: transform 0.25s, background 0.25s;
138
155
  }
139
- .lcms-toggle input:checked + .lcms-toggle-slider { background: #00C853; }
156
+ .lcms-toggle input:checked + .lcms-toggle-slider { background: var(--lcms-primary, #00C853); }
140
157
  .lcms-toggle input:checked + .lcms-toggle-slider::after { transform: translateX(16px); background: white; }
141
158
  .lcms-toggle-label { font-size: 12px; font-weight: 700; color: rgba(255,255,255,0.5); letter-spacing: 0.5px; transition: color 0.25s; }
142
- .lcms-toggle input:checked ~ .lcms-toggle-label { color: #81C784; }
143
- .lcms-lang-switch { display: flex; border: 1px solid rgba(0,200,83,0.4); border-radius: 6px; overflow: hidden; margin-left: auto; }
159
+ .lcms-toggle input:checked ~ .lcms-toggle-label { color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); }
160
+ .lcms-lang-switch { display: flex; border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.4); border-radius: 6px; overflow: hidden; margin-left: auto; }
144
161
  .lcms-lang-btn { background: transparent; border: none; color: rgba(255,255,255,0.45); padding: 3px 12px; font-size: 11px; font-weight: 600; cursor: pointer; transition: all 0.2s; }
145
- .lcms-lang-btn.active { background: #00C853; color: white; }
146
- .lcms-lang-btn:hover:not(.active) { color: white; background: rgba(0,200,83,0.2); }
162
+ .lcms-lang-btn.active { background: var(--lcms-primary, #00C853); color: white; }
163
+ .lcms-lang-btn:hover:not(.active) { color: white; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); }
147
164
  .lcms-close-btn { background: transparent; border: none; color: rgba(255,255,255,0.4); cursor: pointer; padding: 2px; display: flex; transition: color 0.2s; }
148
165
  .lcms-close-btn:hover { color: white; }
149
- .lcms-changes-info { font-size: 12px; color: #81C784; margin-bottom: 10px; padding-left: 2px; }
166
+ .lcms-changes-info { font-size: 12px; color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); margin-bottom: 10px; padding-left: 2px; }
150
167
 
151
168
  .lcms-undo-row { display: flex; gap: 6px; margin-bottom: 12px; }
152
169
  .lcms-icon-btn {
153
- width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(0,200,83,0.3);
154
- background: rgba(0,200,83,0.1); color: rgba(255,255,255,0.8); cursor: pointer;
170
+ width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.3);
171
+ background: rgba(var(--lcms-primary-rgb, 0,200,83),0.1); color: rgba(255,255,255,0.8); cursor: pointer;
155
172
  display: flex; align-items: center; justify-content: center; transition: all 0.2s;
156
173
  }
157
- .lcms-icon-btn:hover:not(:disabled) { background: rgba(0,200,83,0.25); border-color: rgba(0,200,83,0.5); color: white; }
174
+ .lcms-icon-btn:hover:not(:disabled) { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); color: white; }
158
175
  .lcms-icon-btn:disabled { opacity: 0.25; cursor: not-allowed; }
159
176
 
177
+ /* COLOR THEME PICKER */
178
+ .lcms-theme-row {
179
+ display: flex; align-items: center; gap: 8px; margin-bottom: 12px;
180
+ padding: 6px 0;
181
+ }
182
+ .lcms-theme-label {
183
+ font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.45);
184
+ text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap;
185
+ }
186
+ .lcms-theme-colors {
187
+ display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
188
+ }
189
+ .lcms-theme-swatch {
190
+ width: 20px; height: 20px; border-radius: 50%; border: 2px solid transparent;
191
+ cursor: pointer; transition: all 0.2s; position: relative;
192
+ }
193
+ .lcms-theme-swatch:hover { transform: scale(1.15); }
194
+ .lcms-theme-swatch.active { border-color: white; box-shadow: 0 0 8px rgba(255,255,255,0.3); }
195
+ .lcms-theme-custom {
196
+ width: 20px; height: 20px; border-radius: 50%; border: 1px dashed rgba(255,255,255,0.3);
197
+ cursor: pointer; overflow: hidden; position: relative;
198
+ }
199
+ .lcms-theme-custom input {
200
+ position: absolute; inset: -4px; width: 28px; height: 28px; border: none;
201
+ background: transparent; cursor: pointer; opacity: 0;
202
+ }
203
+ .lcms-theme-custom-preview {
204
+ width: 100%; height: 100%; border-radius: 50%;
205
+ background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);
206
+ }
207
+
160
208
  .lcms-history-btn {
161
209
  width: 100%; padding: 7px 12px; border-radius: 8px;
162
- border: 1px dashed rgba(76,175,80,0.35); background: rgba(0,200,83,0.08);
210
+ border: 1px dashed rgba(var(--lcms-primary-rgb, 0,200,83),0.35); background: rgba(var(--lcms-primary-rgb, 0,200,83),0.08);
163
211
  color: rgba(255,255,255,0.6); font-size: 12px; font-weight: 500; cursor: pointer;
164
212
  display: flex; align-items: center; justify-content: center; gap: 6px;
165
213
  transition: all 0.2s; margin-bottom: 12px; font-family: system-ui, -apple-system, sans-serif;
166
214
  }
167
- .lcms-history-btn:hover { background: rgba(0,200,83,0.18); border-color: rgba(76,175,80,0.5); color: white; }
168
- .lcms-history-btn.active { background: rgba(0,200,83,0.25); border-color: #00C853; border-style: solid; color: white; }
215
+ .lcms-history-btn:hover { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.18); border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); color: white; }
216
+ .lcms-history-btn.active { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-color: var(--lcms-primary, #00C853); border-style: solid; color: white; }
169
217
 
170
- .lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(76,175,80,0.15); padding-top: 10px; }
218
+ .lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); padding-top: 10px; }
171
219
  .lcms-history-title { font-size: 11px; font-weight: 700; color: rgba(255,255,255,0.5); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; }
172
220
  .lcms-history-empty { font-size: 12px; color: rgba(255,255,255,0.3); text-align: center; padding: 12px 0; }
173
221
  .lcms-history-list { max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
174
222
  .lcms-history-list::-webkit-scrollbar { width: 4px; }
175
223
  .lcms-history-list::-webkit-scrollbar-track { background: transparent; }
176
- .lcms-history-list::-webkit-scrollbar-thumb { background: rgba(0,200,83,0.3); border-radius: 4px; }
224
+ .lcms-history-list::-webkit-scrollbar-thumb { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); border-radius: 4px; }
177
225
  .lcms-history-item {
178
- width: 100%; text-align: left; background: rgba(0,200,83,0.06);
179
- border: 1px solid rgba(0,200,83,0.12); border-radius: 8px; padding: 8px 10px;
226
+ width: 100%; text-align: left; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.06);
227
+ border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12); border-radius: 8px; padding: 8px 10px;
180
228
  cursor: pointer; transition: all 0.2s; color: white; font-family: system-ui, -apple-system, sans-serif;
181
229
  }
182
- .lcms-history-item:hover { background: rgba(0,200,83,0.15); border-color: rgba(0,200,83,0.3); }
230
+ .lcms-history-item:hover { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.15); border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); }
183
231
  .lcms-history-label { font-size: 12px; font-weight: 500; margin-bottom: 2px; }
184
232
  .lcms-history-meta { font-size: 10px; color: rgba(255,255,255,0.4); display: flex; align-items: center; gap: 6px; }
185
- .lcms-history-lang { background: rgba(0,200,83,0.2); padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 600; color: #81C784; }
233
+ .lcms-history-lang { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 600; color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); }
186
234
 
187
235
  .lcms-actions { display: flex; flex-direction: column; gap: 6px; }
188
236
  .lcms-actions button {
@@ -190,14 +238,14 @@ var CMS_STYLES = `
190
238
  cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; gap: 6px; border: none;
191
239
  font-family: system-ui, -apple-system, sans-serif;
192
240
  }
193
- .lcms-btn-save { background: #00C853; color: white; }
194
- .lcms-btn-save:hover { background: #00E676; }
195
- .lcms-btn-save:disabled { background: rgba(0,200,83,0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; }
196
- .lcms-btn-publish { background: linear-gradient(135deg, #2196F3, #1976D2); color: white; }
197
- .lcms-btn-publish:hover { background: linear-gradient(135deg, #1976D2, #1565C0); }
198
- .lcms-btn-publish:disabled { background: rgba(0,200,83,0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; }
199
- .lcms-btn-cancel { background: transparent; color: rgba(255,255,255,0.5); border: 1px solid rgba(0,200,83,0.25) !important; }
200
- .lcms-btn-cancel:hover { color: white; border-color: rgba(0,200,83,0.5) !important; background: rgba(0,200,83,0.08); }
241
+ .lcms-btn-save { background: var(--lcms-primary, #00C853); color: white; }
242
+ .lcms-btn-save:hover { background: var(--lcms-primary, #00C853); filter: brightness(1.15); }
243
+ .lcms-btn-save:disabled { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; filter: none; }
244
+ .lcms-btn-publish { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); color: white; }
245
+ .lcms-btn-publish:hover { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); filter: brightness(1.1); }
246
+ .lcms-btn-publish:disabled { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; filter: none; }
247
+ .lcms-btn-cancel { background: transparent; color: rgba(255,255,255,0.5); border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.25) !important; }
248
+ .lcms-btn-cancel:hover { color: white; border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5) !important; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.08); }
201
249
  .lcms-btn-cancel:disabled { opacity: 0.3; cursor: not-allowed; }
202
250
 
203
251
  .lcms-spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.3); border-top-color: white; border-radius: 50%; animation: lcmsSpin 0.6s linear infinite; }
@@ -206,14 +254,14 @@ var CMS_STYLES = `
206
254
  .lcms-img-upload-overlay {
207
255
  position: fixed; inset: 0; z-index: 10005;
208
256
  display: flex; align-items: center; justify-content: center;
209
- background: rgba(5, 20, 10, 0.5); backdrop-filter: blur(8px);
257
+ background: rgba(8, 8, 15, 0.5); backdrop-filter: blur(8px);
210
258
  }
211
259
  .lcms-img-upload-content {
212
260
  display: flex; flex-direction: column; align-items: center; gap: 16px;
213
261
  color: white; font-family: system-ui, -apple-system, sans-serif;
214
262
  font-size: 13px; font-weight: 600;
215
263
  }
216
- .lcms-spinner-lg { width: 36px; height: 36px; border: 3px solid rgba(255,255,255,0.2); border-top-color: #00C853; border-radius: 50%; animation: lcmsSpin 0.6s linear infinite; }
264
+ .lcms-spinner-lg { width: 36px; height: 36px; border: 3px solid rgba(255,255,255,0.2); border-top-color: var(--lcms-primary, #00C853); border-radius: 50%; animation: lcmsSpin 0.6s linear infinite; }
217
265
 
218
266
  /* HIDDEN ELEMENTS */
219
267
  .lcms-hidden { display: none !important; }
@@ -254,11 +302,14 @@ var DEFAULT_EDITABLE_TAGS = [
254
302
  "small",
255
303
  "blockquote",
256
304
  "td",
257
- "th"
305
+ "th",
306
+ "div"
258
307
  ];
259
308
  var XtroedgeCMS = class _XtroedgeCMS {
260
309
  constructor(config) {
261
310
  this.brandingEl = null;
311
+ this.siteIdentifier = "";
312
+ this.siteIdEl = null;
262
313
  // ===== State =====
263
314
  this.editMode = false;
264
315
  this.currentLang = "en";
@@ -345,6 +396,9 @@ var XtroedgeCMS = class _XtroedgeCMS {
345
396
  this.highlightColor = this.config.highlightColor || "#00C853";
346
397
  this.historyRetentionMs = (this.config.historyRetentionDays || 7) * 24 * 60 * 60 * 1e3;
347
398
  this.currentLang = this.defaultLanguage;
399
+ this.siteIdentifier = this.resolveSiteIdentifier();
400
+ const savedColor = localStorage.getItem("xtroedge_theme_color");
401
+ if (savedColor) this.highlightColor = savedColor;
348
402
  this.boundMouseMove = (e) => this.onDragMove(e);
349
403
  this.boundMouseUp = () => this.onDragEnd();
350
404
  this.boundTouchMove = (e) => this.onTouchMove(e);
@@ -358,6 +412,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
358
412
  init() {
359
413
  this.posY = window.innerHeight - 72;
360
414
  this.injectStyles();
415
+ this.applyThemeColor(this.highlightColor);
361
416
  this.buildUI();
362
417
  this.interceptNavigation();
363
418
  this.observer = new MutationObserver(() => {
@@ -529,6 +584,10 @@ var XtroedgeCMS = class _XtroedgeCMS {
529
584
  });
530
585
  header.appendChild(closeBtn);
531
586
  this.panelEl.appendChild(header);
587
+ this.siteIdEl = this.createElement("div", "lcms-site-id");
588
+ const isDomain = this.siteIdentifier.includes(".");
589
+ this.siteIdEl.innerHTML = `<span class="lcms-site-id-icon">${isDomain ? "\u{1F310}" : "\u{1F511}"}</span><span class="lcms-site-id-text">${isDomain ? this.siteIdentifier : this.siteIdentifier.substring(0, 8)}</span>`;
590
+ this.panelEl.appendChild(this.siteIdEl);
532
591
  this.editModeContent = this.createElement("div", "lcms-hidden");
533
592
  this.changesInfoEl = this.createElement("div", "lcms-changes-info lcms-hidden");
534
593
  this.editModeContent.appendChild(this.changesInfoEl);
@@ -552,6 +611,37 @@ var XtroedgeCMS = class _XtroedgeCMS {
552
611
  undoRow.appendChild(this.undoBtn);
553
612
  undoRow.appendChild(this.redoBtn);
554
613
  this.editModeContent.appendChild(undoRow);
614
+ const themeRow = this.createElement("div", "lcms-theme-row");
615
+ const themeLabel = this.createElement("span", "lcms-theme-label");
616
+ themeLabel.textContent = "Theme";
617
+ themeRow.appendChild(themeLabel);
618
+ const themeColors = this.createElement("div", "lcms-theme-colors");
619
+ const presetColors = ["#00C853", "#6722FB", "#2196F3", "#FF5722", "#E91E63", "#FFD600"];
620
+ for (const color of presetColors) {
621
+ const swatch = this.createElement("div", "lcms-theme-swatch");
622
+ swatch.style.background = color;
623
+ swatch.dataset.color = color;
624
+ if (color === this.highlightColor) swatch.classList.add("active");
625
+ swatch.addEventListener("click", (e) => {
626
+ e.stopPropagation();
627
+ this.applyThemeColor(color);
628
+ });
629
+ themeColors.appendChild(swatch);
630
+ }
631
+ const customSwatch = this.createElement("div", "lcms-theme-custom");
632
+ const customPreview = this.createElement("div", "lcms-theme-custom-preview");
633
+ const customInput = document.createElement("input");
634
+ customInput.type = "color";
635
+ customInput.value = this.highlightColor;
636
+ customInput.addEventListener("input", (e) => {
637
+ e.stopPropagation();
638
+ this.applyThemeColor(e.target.value);
639
+ });
640
+ customSwatch.appendChild(customPreview);
641
+ customSwatch.appendChild(customInput);
642
+ themeColors.appendChild(customSwatch);
643
+ themeRow.appendChild(themeColors);
644
+ this.editModeContent.appendChild(themeRow);
555
645
  this.historyBtnEl = document.createElement("button");
556
646
  this.historyBtnEl.className = "lcms-history-btn";
557
647
  this.historyBtnEl.innerHTML = `${ICON.history} History (7 days)`;
@@ -596,6 +686,10 @@ var XtroedgeCMS = class _XtroedgeCMS {
596
686
  this.panelEl.appendChild(this.editModeContent);
597
687
  this.brandingEl = this.createElement("div", "lcms-branding");
598
688
  this.brandingEl.innerHTML = `<div class="lcms-branding-logo"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg></div><div class="lcms-branding-text">Powered by <span>XtroEdge</span></div>`;
689
+ this.brandingEl.addEventListener("click", (e) => {
690
+ e.stopPropagation();
691
+ window.open("https://xtro.vercel.app/", "_blank");
692
+ });
599
693
  this.panelEl.appendChild(this.brandingEl);
600
694
  }
601
695
  buildLangButtons() {
@@ -1148,7 +1242,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1148
1242
  this.setLoading(true);
1149
1243
  this.cleanOldHistory();
1150
1244
  try {
1151
- const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=${status}`);
1245
+ const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=${status}&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);
1152
1246
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
1153
1247
  const page = await res.json();
1154
1248
  const texts = page?.published_content?.texts || page?.content?.texts;
@@ -1178,7 +1272,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1178
1272
  async loadPublishedContent() {
1179
1273
  this.setLoading(true);
1180
1274
  try {
1181
- const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=published`);
1275
+ const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=published&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);
1182
1276
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
1183
1277
  const page = await res.json();
1184
1278
  const texts = page?.published_content?.texts;
@@ -1237,6 +1331,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1237
1331
  const payload = {
1238
1332
  slug: this.currentSlug,
1239
1333
  title: this.currentTitle,
1334
+ site_identifier: this.siteIdentifier,
1240
1335
  content: { texts: this.pageTexts, images: this.pageImages }
1241
1336
  };
1242
1337
  try {
@@ -1268,6 +1363,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1268
1363
  const payload = {
1269
1364
  slug: this.currentSlug,
1270
1365
  title: this.currentTitle,
1366
+ site_identifier: this.siteIdentifier,
1271
1367
  published_content: { texts: this.pageTexts, images: this.pageImages }
1272
1368
  };
1273
1369
  try {
@@ -1544,6 +1640,59 @@ var XtroedgeCMS = class _XtroedgeCMS {
1544
1640
  return `${months[d.getMonth()]} ${d.getDate()}, ${h12}:${m} ${ampm}`;
1545
1641
  }
1546
1642
  // ===============================================
1643
+ // SITE IDENTIFIER
1644
+ // ===============================================
1645
+ resolveSiteIdentifier() {
1646
+ const hostname = window.location.hostname;
1647
+ if (hostname && hostname !== "localhost" && hostname !== "127.0.0.1" && !hostname.startsWith("192.168.")) {
1648
+ return hostname;
1649
+ }
1650
+ let id = localStorage.getItem("xtroedge_site_id");
1651
+ if (!id) {
1652
+ id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
1653
+ const r = Math.random() * 16 | 0;
1654
+ return (c === "x" ? r : r & 3 | 8).toString(16);
1655
+ });
1656
+ localStorage.setItem("xtroedge_site_id", id);
1657
+ }
1658
+ return id;
1659
+ }
1660
+ // ===============================================
1661
+ // THEME COLOR
1662
+ // ===============================================
1663
+ hexToRgb(hex) {
1664
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1665
+ if (!result) return "0,200,83";
1666
+ return `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`;
1667
+ }
1668
+ getDarkerColor(hex) {
1669
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1670
+ if (!result) return "#2E7D32";
1671
+ const r = Math.max(0, Math.floor(parseInt(result[1], 16) * 0.6));
1672
+ const g = Math.max(0, Math.floor(parseInt(result[2], 16) * 0.6));
1673
+ const b = Math.max(0, Math.floor(parseInt(result[3], 16) * 0.6));
1674
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
1675
+ }
1676
+ applyThemeColor(color) {
1677
+ this.highlightColor = color;
1678
+ document.documentElement.style.setProperty("--lcms-primary", color);
1679
+ document.documentElement.style.setProperty("--lcms-primary-rgb", this.hexToRgb(color));
1680
+ document.documentElement.style.setProperty("--lcms-primary-dark", this.getDarkerColor(color));
1681
+ if (this.editMode) {
1682
+ for (const [el] of this.managedElements) {
1683
+ el.style.borderBottom = `2px dashed ${color}`;
1684
+ }
1685
+ for (const [img] of this.managedImages) {
1686
+ img.style.outline = `2px dashed ${color}`;
1687
+ }
1688
+ }
1689
+ const swatches = this.panelEl?.querySelectorAll(".lcms-theme-swatch");
1690
+ swatches?.forEach((s) => {
1691
+ s.classList.toggle("active", s.dataset.color === color);
1692
+ });
1693
+ localStorage.setItem("xtroedge_theme_color", color);
1694
+ }
1695
+ // ===============================================
1547
1696
  // STATIC CONVENIENCE
1548
1697
  // ===============================================
1549
1698
  /** Quick init - create and start CMS in one call */