ngx-xtroedge-cms 1.1.0 → 1.2.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.mjs CHANGED
@@ -6,32 +6,32 @@ var CMS_STYLES = `
6
6
  .lcms-loader-overlay {
7
7
  position: fixed; inset: 0; z-index: 10003;
8
8
  display: flex; align-items: center; justify-content: center;
9
- background: rgba(5, 20, 10, 0.45);
9
+ background: rgba(8, 8, 15, 0.45);
10
10
  backdrop-filter: blur(12px) saturate(1.4);
11
11
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
12
12
  }
13
13
  .lcms-loader-content { display: flex; flex-direction: column; align-items: center; gap: 28px; }
14
14
  .lcms-orbit-loader { position: relative; width: 90px; height: 90px; }
15
15
  .lcms-orbit { position: absolute; inset: 0; border-radius: 50%; border: 1px solid transparent; }
16
- .lcms-orbit-1 { border-top-color: rgba(0,200,83,0.5); animation: lcmsSpin 2.4s linear infinite; }
17
- .lcms-orbit-2 { inset: 10px; border-right-color: rgba(76,175,80,0.5); animation: lcmsSpin 3.2s linear infinite reverse; }
18
- .lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(129,199,132,0.5); animation: lcmsSpin 4.2s linear infinite; }
16
+ .lcms-orbit-1 { border-top-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); animation: lcmsSpin 2.4s linear infinite; }
17
+ .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; }
18
+ .lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); animation: lcmsSpin 4.2s linear infinite; }
19
19
  .lcms-particle {
20
20
  position: absolute; width: 8px; height: 8px; border-radius: 50%; top: -4px; left: 50%; margin-left: -4px;
21
21
  box-shadow: 0 0 12px 3px currentColor;
22
22
  }
23
- .lcms-orbit-1 .lcms-particle { background: #00C853; color: #00C853; }
24
- .lcms-orbit-2 .lcms-particle { background: #4CAF50; color: #4CAF50; top: 50%; left: auto; right: -4px; margin-left: 0; margin-top: -4px; }
25
- .lcms-orbit-3 .lcms-particle { background: #81C784; color: #81C784; top: auto; bottom: -4px; }
23
+ .lcms-orbit-1 .lcms-particle { background: var(--lcms-primary, #00C853); color: var(--lcms-primary, #00C853); }
24
+ .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; }
25
+ .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; }
26
26
  .lcms-core-glow {
27
27
  position: absolute; width: 30px; height: 30px; top: 50%; left: 50%; transform: translate(-50%,-50%);
28
- border-radius: 50%; background: radial-gradient(circle, rgba(0,200,83,0.4), transparent 70%);
28
+ border-radius: 50%; background: radial-gradient(circle, rgba(var(--lcms-primary-rgb, 0,200,83),0.4), transparent 70%);
29
29
  animation: lcmsPulse 2s ease-in-out infinite;
30
30
  }
31
31
  .lcms-core {
32
32
  position: absolute; width: 12px; height: 12px; top: 50%; left: 50%; transform: translate(-50%,-50%);
33
- border-radius: 50%; background: linear-gradient(135deg, #00C853, #81C784);
34
- box-shadow: 0 0 20px rgba(0,200,83,0.6);
33
+ border-radius: 50%; background: linear-gradient(135deg, var(--lcms-primary, #00C853), rgba(var(--lcms-primary-rgb, 0,200,83),0.6));
34
+ box-shadow: 0 0 20px rgba(var(--lcms-primary-rgb, 0,200,83),0.6);
35
35
  }
36
36
  .lcms-loader-text {
37
37
  font-family: system-ui, -apple-system, sans-serif; font-size: 12px; font-weight: 600;
@@ -48,10 +48,10 @@ var CMS_STYLES = `
48
48
  padding: 10px 20px; border-radius: 10px; font-size: 13px; font-weight: 600;
49
49
  font-family: system-ui, -apple-system, sans-serif; color: white;
50
50
  display: flex; align-items: center; gap: 8px;
51
- box-shadow: 0 8px 32px rgba(0,200,83,0.25);
51
+ box-shadow: 0 8px 32px rgba(var(--lcms-primary-rgb, 0,200,83),0.25);
52
52
  animation: lcmsToastIn 0.3s ease, lcmsToastOut 0.3s ease 2.7s forwards; white-space: nowrap;
53
53
  }
54
- .lcms-toast-success { background: linear-gradient(135deg, #00C853, #2E7D32); }
54
+ .lcms-toast-success { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); }
55
55
  .lcms-toast-error { background: linear-gradient(135deg, #dc2626, #ef4444); }
56
56
  @keyframes lcmsToastIn { from { opacity: 0; transform: translateX(-50%) translateY(-12px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
57
57
  @keyframes lcmsToastOut { from { opacity: 1; transform: translateX(-50%) translateY(0); } to { opacity: 0; transform: translateX(-50%) translateY(-12px); } }
@@ -60,15 +60,15 @@ var CMS_STYLES = `
60
60
  .lcms-fab { position: fixed; z-index: 10001; user-select: none; touch-action: none; }
61
61
  .lcms-fab-btn {
62
62
  width: 52px; height: 52px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.2);
63
- background: rgba(0,200,83,0.35); color: white;
63
+ background: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); color: white;
64
64
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
65
65
  cursor: grab; display: flex; align-items: center; justify-content: center;
66
- box-shadow: 0 4px 20px rgba(0,200,83,0.3), inset 0 1px 0 rgba(255,255,255,0.15);
66
+ 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);
67
67
  transition: transform 0.2s, box-shadow 0.2s, background 0.2s; position: relative;
68
68
  }
69
- .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); }
70
- .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); }
71
- .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); }
69
+ .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); }
70
+ .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); }
71
+ .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); }
72
72
  .lcms-badge {
73
73
  position: absolute; top: -4px; right: -4px; background: #ef4444; color: white;
74
74
  font-size: 11px; font-weight: 700; width: 20px; height: 20px; border-radius: 50%;
@@ -77,27 +77,44 @@ var CMS_STYLES = `
77
77
 
78
78
  /* PANEL */
79
79
  .lcms-panel {
80
- background: rgba(10,30,15,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
81
- border: 1px solid rgba(76,175,80,0.25); border-radius: 16px; padding: 16px; min-width: 230px;
80
+ background: rgba(12,12,18,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
81
+ border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-radius: 16px; padding: 16px; min-width: 230px;
82
82
  box-shadow: 0 8px 32px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.06);
83
83
  color: white; font-family: system-ui, -apple-system, sans-serif;
84
84
  animation: lcmsPanelIn 0.25s ease; position: absolute;
85
85
  }
86
86
  @keyframes lcmsPanelIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }
87
87
 
88
+ /* SITE IDENTIFIER */
89
+ .lcms-site-id {
90
+ display: flex; align-items: center; gap: 5px;
91
+ font-size: 10px; color: rgba(255,255,255,0.4);
92
+ padding: 0 0 8px; margin-bottom: 8px;
93
+ border-bottom: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12);
94
+ font-family: system-ui, -apple-system, sans-serif;
95
+ letter-spacing: 0.3px;
96
+ }
97
+ .lcms-site-id-icon { font-size: 12px; opacity: 0.7; }
98
+ .lcms-site-id-text {
99
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px;
100
+ font-weight: 500;
101
+ }
102
+
88
103
  /* BRANDING */
89
104
  .lcms-branding {
90
105
  display: flex; align-items: center; gap: 6px; padding: 8px 0 4px;
91
- border-top: 1px solid rgba(76,175,80,0.15); margin-top: 10px;
106
+ border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); margin-top: 10px;
107
+ cursor: pointer; transition: opacity 0.2s; user-select: none;
92
108
  }
109
+ .lcms-branding:hover { opacity: 0.8; }
93
110
  .lcms-branding-logo {
94
- width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, #00C853, #2E7D32);
111
+ width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));
95
112
  display: flex; align-items: center; justify-content: center;
96
113
  }
97
114
  .lcms-branding-text {
98
115
  font-size: 10px; font-weight: 600; color: rgba(255,255,255,0.35); letter-spacing: 0.5px;
99
116
  }
100
- .lcms-branding-text span { color: #00C853; font-weight: 700; }
117
+ .lcms-branding-text span { color: var(--lcms-primary, #00C853); font-weight: 700; }
101
118
 
102
119
  .lcms-panel-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
103
120
  .lcms-toggle { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
@@ -110,53 +127,84 @@ var CMS_STYLES = `
110
127
  content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%;
111
128
  top: 2px; left: 2px; background: rgba(255,255,255,0.6); transition: transform 0.25s, background 0.25s;
112
129
  }
113
- .lcms-toggle input:checked + .lcms-toggle-slider { background: #00C853; }
130
+ .lcms-toggle input:checked + .lcms-toggle-slider { background: var(--lcms-primary, #00C853); }
114
131
  .lcms-toggle input:checked + .lcms-toggle-slider::after { transform: translateX(16px); background: white; }
115
132
  .lcms-toggle-label { font-size: 12px; font-weight: 700; color: rgba(255,255,255,0.5); letter-spacing: 0.5px; transition: color 0.25s; }
116
- .lcms-toggle input:checked ~ .lcms-toggle-label { color: #81C784; }
117
- .lcms-lang-switch { display: flex; border: 1px solid rgba(0,200,83,0.4); border-radius: 6px; overflow: hidden; margin-left: auto; }
133
+ .lcms-toggle input:checked ~ .lcms-toggle-label { color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); }
134
+ .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; }
118
135
  .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; }
119
- .lcms-lang-btn.active { background: #00C853; color: white; }
120
- .lcms-lang-btn:hover:not(.active) { color: white; background: rgba(0,200,83,0.2); }
136
+ .lcms-lang-btn.active { background: var(--lcms-primary, #00C853); color: white; }
137
+ .lcms-lang-btn:hover:not(.active) { color: white; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); }
121
138
  .lcms-close-btn { background: transparent; border: none; color: rgba(255,255,255,0.4); cursor: pointer; padding: 2px; display: flex; transition: color 0.2s; }
122
139
  .lcms-close-btn:hover { color: white; }
123
- .lcms-changes-info { font-size: 12px; color: #81C784; margin-bottom: 10px; padding-left: 2px; }
140
+ .lcms-changes-info { font-size: 12px; color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); margin-bottom: 10px; padding-left: 2px; }
124
141
 
125
142
  .lcms-undo-row { display: flex; gap: 6px; margin-bottom: 12px; }
126
143
  .lcms-icon-btn {
127
- width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(0,200,83,0.3);
128
- background: rgba(0,200,83,0.1); color: rgba(255,255,255,0.8); cursor: pointer;
144
+ width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.3);
145
+ background: rgba(var(--lcms-primary-rgb, 0,200,83),0.1); color: rgba(255,255,255,0.8); cursor: pointer;
129
146
  display: flex; align-items: center; justify-content: center; transition: all 0.2s;
130
147
  }
131
- .lcms-icon-btn:hover:not(:disabled) { background: rgba(0,200,83,0.25); border-color: rgba(0,200,83,0.5); color: white; }
148
+ .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; }
132
149
  .lcms-icon-btn:disabled { opacity: 0.25; cursor: not-allowed; }
133
150
 
151
+ /* COLOR THEME PICKER */
152
+ .lcms-theme-row {
153
+ display: flex; align-items: center; gap: 8px; margin-bottom: 12px;
154
+ padding: 6px 0;
155
+ }
156
+ .lcms-theme-label {
157
+ font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.45);
158
+ text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap;
159
+ }
160
+ .lcms-theme-colors {
161
+ display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
162
+ }
163
+ .lcms-theme-swatch {
164
+ width: 20px; height: 20px; border-radius: 50%; border: 2px solid transparent;
165
+ cursor: pointer; transition: all 0.2s; position: relative;
166
+ }
167
+ .lcms-theme-swatch:hover { transform: scale(1.15); }
168
+ .lcms-theme-swatch.active { border-color: white; box-shadow: 0 0 8px rgba(255,255,255,0.3); }
169
+ .lcms-theme-custom {
170
+ width: 20px; height: 20px; border-radius: 50%; border: 1px dashed rgba(255,255,255,0.3);
171
+ cursor: pointer; overflow: hidden; position: relative;
172
+ }
173
+ .lcms-theme-custom input {
174
+ position: absolute; inset: -4px; width: 28px; height: 28px; border: none;
175
+ background: transparent; cursor: pointer; opacity: 0;
176
+ }
177
+ .lcms-theme-custom-preview {
178
+ width: 100%; height: 100%; border-radius: 50%;
179
+ background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);
180
+ }
181
+
134
182
  .lcms-history-btn {
135
183
  width: 100%; padding: 7px 12px; border-radius: 8px;
136
- border: 1px dashed rgba(76,175,80,0.35); background: rgba(0,200,83,0.08);
184
+ border: 1px dashed rgba(var(--lcms-primary-rgb, 0,200,83),0.35); background: rgba(var(--lcms-primary-rgb, 0,200,83),0.08);
137
185
  color: rgba(255,255,255,0.6); font-size: 12px; font-weight: 500; cursor: pointer;
138
186
  display: flex; align-items: center; justify-content: center; gap: 6px;
139
187
  transition: all 0.2s; margin-bottom: 12px; font-family: system-ui, -apple-system, sans-serif;
140
188
  }
141
- .lcms-history-btn:hover { background: rgba(0,200,83,0.18); border-color: rgba(76,175,80,0.5); color: white; }
142
- .lcms-history-btn.active { background: rgba(0,200,83,0.25); border-color: #00C853; border-style: solid; color: white; }
189
+ .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; }
190
+ .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; }
143
191
 
144
- .lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(76,175,80,0.15); padding-top: 10px; }
192
+ .lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); padding-top: 10px; }
145
193
  .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; }
146
194
  .lcms-history-empty { font-size: 12px; color: rgba(255,255,255,0.3); text-align: center; padding: 12px 0; }
147
195
  .lcms-history-list { max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
148
196
  .lcms-history-list::-webkit-scrollbar { width: 4px; }
149
197
  .lcms-history-list::-webkit-scrollbar-track { background: transparent; }
150
- .lcms-history-list::-webkit-scrollbar-thumb { background: rgba(0,200,83,0.3); border-radius: 4px; }
198
+ .lcms-history-list::-webkit-scrollbar-thumb { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); border-radius: 4px; }
151
199
  .lcms-history-item {
152
- width: 100%; text-align: left; background: rgba(0,200,83,0.06);
153
- border: 1px solid rgba(0,200,83,0.12); border-radius: 8px; padding: 8px 10px;
200
+ width: 100%; text-align: left; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.06);
201
+ border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12); border-radius: 8px; padding: 8px 10px;
154
202
  cursor: pointer; transition: all 0.2s; color: white; font-family: system-ui, -apple-system, sans-serif;
155
203
  }
156
- .lcms-history-item:hover { background: rgba(0,200,83,0.15); border-color: rgba(0,200,83,0.3); }
204
+ .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); }
157
205
  .lcms-history-label { font-size: 12px; font-weight: 500; margin-bottom: 2px; }
158
206
  .lcms-history-meta { font-size: 10px; color: rgba(255,255,255,0.4); display: flex; align-items: center; gap: 6px; }
159
- .lcms-history-lang { background: rgba(0,200,83,0.2); padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 600; color: #81C784; }
207
+ .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); }
160
208
 
161
209
  .lcms-actions { display: flex; flex-direction: column; gap: 6px; }
162
210
  .lcms-actions button {
@@ -164,14 +212,14 @@ var CMS_STYLES = `
164
212
  cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; gap: 6px; border: none;
165
213
  font-family: system-ui, -apple-system, sans-serif;
166
214
  }
167
- .lcms-btn-save { background: #00C853; color: white; }
168
- .lcms-btn-save:hover { background: #00E676; }
169
- .lcms-btn-save:disabled { background: rgba(0,200,83,0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; }
215
+ .lcms-btn-save { background: var(--lcms-primary, #00C853); color: white; }
216
+ .lcms-btn-save:hover { background: var(--lcms-primary, #00C853); filter: brightness(1.15); }
217
+ .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; }
170
218
  .lcms-btn-publish { background: linear-gradient(135deg, #2196F3, #1976D2); color: white; }
171
219
  .lcms-btn-publish:hover { background: linear-gradient(135deg, #1976D2, #1565C0); }
172
- .lcms-btn-publish:disabled { background: rgba(0,200,83,0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; }
173
- .lcms-btn-cancel { background: transparent; color: rgba(255,255,255,0.5); border: 1px solid rgba(0,200,83,0.25) !important; }
174
- .lcms-btn-cancel:hover { color: white; border-color: rgba(0,200,83,0.5) !important; background: rgba(0,200,83,0.08); }
220
+ .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; }
221
+ .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; }
222
+ .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); }
175
223
  .lcms-btn-cancel:disabled { opacity: 0.3; cursor: not-allowed; }
176
224
 
177
225
  .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; }
@@ -180,14 +228,14 @@ var CMS_STYLES = `
180
228
  .lcms-img-upload-overlay {
181
229
  position: fixed; inset: 0; z-index: 10005;
182
230
  display: flex; align-items: center; justify-content: center;
183
- background: rgba(5, 20, 10, 0.5); backdrop-filter: blur(8px);
231
+ background: rgba(8, 8, 15, 0.5); backdrop-filter: blur(8px);
184
232
  }
185
233
  .lcms-img-upload-content {
186
234
  display: flex; flex-direction: column; align-items: center; gap: 16px;
187
235
  color: white; font-family: system-ui, -apple-system, sans-serif;
188
236
  font-size: 13px; font-weight: 600;
189
237
  }
190
- .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; }
238
+ .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; }
191
239
 
192
240
  /* HIDDEN ELEMENTS */
193
241
  .lcms-hidden { display: none !important; }
@@ -233,6 +281,8 @@ var DEFAULT_EDITABLE_TAGS = [
233
281
  var XtroedgeCMS = class _XtroedgeCMS {
234
282
  constructor(config) {
235
283
  this.brandingEl = null;
284
+ this.siteIdentifier = "";
285
+ this.siteIdEl = null;
236
286
  // ===== State =====
237
287
  this.editMode = false;
238
288
  this.currentLang = "en";
@@ -319,6 +369,9 @@ var XtroedgeCMS = class _XtroedgeCMS {
319
369
  this.highlightColor = this.config.highlightColor || "#00C853";
320
370
  this.historyRetentionMs = (this.config.historyRetentionDays || 7) * 24 * 60 * 60 * 1e3;
321
371
  this.currentLang = this.defaultLanguage;
372
+ this.siteIdentifier = this.resolveSiteIdentifier();
373
+ const savedColor = localStorage.getItem("xtroedge_theme_color");
374
+ if (savedColor) this.highlightColor = savedColor;
322
375
  this.boundMouseMove = (e) => this.onDragMove(e);
323
376
  this.boundMouseUp = () => this.onDragEnd();
324
377
  this.boundTouchMove = (e) => this.onTouchMove(e);
@@ -332,6 +385,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
332
385
  init() {
333
386
  this.posY = window.innerHeight - 72;
334
387
  this.injectStyles();
388
+ this.applyThemeColor(this.highlightColor);
335
389
  this.buildUI();
336
390
  this.interceptNavigation();
337
391
  this.observer = new MutationObserver(() => {
@@ -503,6 +557,10 @@ var XtroedgeCMS = class _XtroedgeCMS {
503
557
  });
504
558
  header.appendChild(closeBtn);
505
559
  this.panelEl.appendChild(header);
560
+ this.siteIdEl = this.createElement("div", "lcms-site-id");
561
+ const isDomain = this.siteIdentifier.includes(".");
562
+ 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>`;
563
+ this.panelEl.appendChild(this.siteIdEl);
506
564
  this.editModeContent = this.createElement("div", "lcms-hidden");
507
565
  this.changesInfoEl = this.createElement("div", "lcms-changes-info lcms-hidden");
508
566
  this.editModeContent.appendChild(this.changesInfoEl);
@@ -526,6 +584,37 @@ var XtroedgeCMS = class _XtroedgeCMS {
526
584
  undoRow.appendChild(this.undoBtn);
527
585
  undoRow.appendChild(this.redoBtn);
528
586
  this.editModeContent.appendChild(undoRow);
587
+ const themeRow = this.createElement("div", "lcms-theme-row");
588
+ const themeLabel = this.createElement("span", "lcms-theme-label");
589
+ themeLabel.textContent = "Theme";
590
+ themeRow.appendChild(themeLabel);
591
+ const themeColors = this.createElement("div", "lcms-theme-colors");
592
+ const presetColors = ["#00C853", "#6722FB", "#2196F3", "#FF5722", "#E91E63", "#FFD600"];
593
+ for (const color of presetColors) {
594
+ const swatch = this.createElement("div", "lcms-theme-swatch");
595
+ swatch.style.background = color;
596
+ swatch.dataset.color = color;
597
+ if (color === this.highlightColor) swatch.classList.add("active");
598
+ swatch.addEventListener("click", (e) => {
599
+ e.stopPropagation();
600
+ this.applyThemeColor(color);
601
+ });
602
+ themeColors.appendChild(swatch);
603
+ }
604
+ const customSwatch = this.createElement("div", "lcms-theme-custom");
605
+ const customPreview = this.createElement("div", "lcms-theme-custom-preview");
606
+ const customInput = document.createElement("input");
607
+ customInput.type = "color";
608
+ customInput.value = this.highlightColor;
609
+ customInput.addEventListener("input", (e) => {
610
+ e.stopPropagation();
611
+ this.applyThemeColor(e.target.value);
612
+ });
613
+ customSwatch.appendChild(customPreview);
614
+ customSwatch.appendChild(customInput);
615
+ themeColors.appendChild(customSwatch);
616
+ themeRow.appendChild(themeColors);
617
+ this.editModeContent.appendChild(themeRow);
529
618
  this.historyBtnEl = document.createElement("button");
530
619
  this.historyBtnEl.className = "lcms-history-btn";
531
620
  this.historyBtnEl.innerHTML = `${ICON.history} History (7 days)`;
@@ -570,6 +659,10 @@ var XtroedgeCMS = class _XtroedgeCMS {
570
659
  this.panelEl.appendChild(this.editModeContent);
571
660
  this.brandingEl = this.createElement("div", "lcms-branding");
572
661
  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>`;
662
+ this.brandingEl.addEventListener("click", (e) => {
663
+ e.stopPropagation();
664
+ window.open("https://xtro.vercel.app/", "_blank");
665
+ });
573
666
  this.panelEl.appendChild(this.brandingEl);
574
667
  }
575
668
  buildLangButtons() {
@@ -1122,7 +1215,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1122
1215
  this.setLoading(true);
1123
1216
  this.cleanOldHistory();
1124
1217
  try {
1125
- const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=${status}`);
1218
+ const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=${status}&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);
1126
1219
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
1127
1220
  const page = await res.json();
1128
1221
  const texts = page?.published_content?.texts || page?.content?.texts;
@@ -1152,7 +1245,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1152
1245
  async loadPublishedContent() {
1153
1246
  this.setLoading(true);
1154
1247
  try {
1155
- const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=published`);
1248
+ const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=published&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);
1156
1249
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
1157
1250
  const page = await res.json();
1158
1251
  const texts = page?.published_content?.texts;
@@ -1211,6 +1304,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1211
1304
  const payload = {
1212
1305
  slug: this.currentSlug,
1213
1306
  title: this.currentTitle,
1307
+ site_identifier: this.siteIdentifier,
1214
1308
  content: { texts: this.pageTexts, images: this.pageImages }
1215
1309
  };
1216
1310
  try {
@@ -1242,6 +1336,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1242
1336
  const payload = {
1243
1337
  slug: this.currentSlug,
1244
1338
  title: this.currentTitle,
1339
+ site_identifier: this.siteIdentifier,
1245
1340
  published_content: { texts: this.pageTexts, images: this.pageImages }
1246
1341
  };
1247
1342
  try {
@@ -1518,6 +1613,59 @@ var XtroedgeCMS = class _XtroedgeCMS {
1518
1613
  return `${months[d.getMonth()]} ${d.getDate()}, ${h12}:${m} ${ampm}`;
1519
1614
  }
1520
1615
  // ===============================================
1616
+ // SITE IDENTIFIER
1617
+ // ===============================================
1618
+ resolveSiteIdentifier() {
1619
+ const hostname = window.location.hostname;
1620
+ if (hostname && hostname !== "localhost" && hostname !== "127.0.0.1" && !hostname.startsWith("192.168.")) {
1621
+ return hostname;
1622
+ }
1623
+ let id = localStorage.getItem("xtroedge_site_id");
1624
+ if (!id) {
1625
+ id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
1626
+ const r = Math.random() * 16 | 0;
1627
+ return (c === "x" ? r : r & 3 | 8).toString(16);
1628
+ });
1629
+ localStorage.setItem("xtroedge_site_id", id);
1630
+ }
1631
+ return id;
1632
+ }
1633
+ // ===============================================
1634
+ // THEME COLOR
1635
+ // ===============================================
1636
+ hexToRgb(hex) {
1637
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1638
+ if (!result) return "0,200,83";
1639
+ return `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`;
1640
+ }
1641
+ getDarkerColor(hex) {
1642
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1643
+ if (!result) return "#2E7D32";
1644
+ const r = Math.max(0, Math.floor(parseInt(result[1], 16) * 0.6));
1645
+ const g = Math.max(0, Math.floor(parseInt(result[2], 16) * 0.6));
1646
+ const b = Math.max(0, Math.floor(parseInt(result[3], 16) * 0.6));
1647
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
1648
+ }
1649
+ applyThemeColor(color) {
1650
+ this.highlightColor = color;
1651
+ document.documentElement.style.setProperty("--lcms-primary", color);
1652
+ document.documentElement.style.setProperty("--lcms-primary-rgb", this.hexToRgb(color));
1653
+ document.documentElement.style.setProperty("--lcms-primary-dark", this.getDarkerColor(color));
1654
+ if (this.editMode) {
1655
+ for (const [el] of this.managedElements) {
1656
+ el.style.borderBottom = `2px dashed ${color}`;
1657
+ }
1658
+ for (const [img] of this.managedImages) {
1659
+ img.style.outline = `2px dashed ${color}`;
1660
+ }
1661
+ }
1662
+ const swatches = this.panelEl?.querySelectorAll(".lcms-theme-swatch");
1663
+ swatches?.forEach((s) => {
1664
+ s.classList.toggle("active", s.dataset.color === color);
1665
+ });
1666
+ localStorage.setItem("xtroedge_theme_color", color);
1667
+ }
1668
+ // ===============================================
1521
1669
  // STATIC CONVENIENCE
1522
1670
  // ===============================================
1523
1671
  /** Quick init - create and start CMS in one call */