abdullahalioo commited on
Commit
6390fb3
·
verified ·
1 Parent(s): d7e7e53

Upload 9 files

Browse files
Files changed (9) hide show
  1. README.md +12 -11
  2. admin.css +1493 -0
  3. admin.html +416 -0
  4. admin.js +1055 -0
  5. blog.html +308 -0
  6. blogs.html +260 -0
  7. index.html +334 -0
  8. script.js +83 -0
  9. style.css +269 -0
README.md CHANGED
@@ -1,11 +1,12 @@
1
- ---
2
- title: Unfiltered
3
- emoji: 🏢
4
- colorFrom: yellow
5
- colorTo: purple
6
- sdk: static
7
- pinned: false
8
- license: mit
9
- ---
10
-
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
+ ---
2
+ title: Mubashra Portfolio
3
+ emoji: 🚀
4
+ colorFrom: green
5
+ colorTo: blue
6
+ sdk: static
7
+ pinned: false
8
+ ---
9
+
10
+ # Mubashra Portfolio
11
+
12
+ This is a static portfolio website built with HTML, CSS (Tailwind), and JavaScript.
admin.css ADDED
@@ -0,0 +1,1493 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ===== Mubashra Studio - Premium Admin Editor ===== */
2
+
3
+ :root {
4
+ --primary: #2D6A4F;
5
+ --primary-light: #40916C;
6
+ --primary-dark: #1B4332;
7
+ --accent: #52B788;
8
+
9
+ /* Pastel Theme */
10
+ --bg-main: #F7FAF9;
11
+ --bg-canvas: #FFFFFF;
12
+ --bg-sidebar: #FFFFFF;
13
+ --bg-header: rgba(255, 255, 255, 0.95);
14
+
15
+ /* Pastel accents */
16
+ --pastel-green: #D8E9E1;
17
+ --pastel-green-light: #E8F3EE;
18
+ --pastel-mint: #E2EFDE;
19
+
20
+ /* Text Colors */
21
+ --text-primary: #111418;
22
+ --text-secondary: #4A5568;
23
+ --text-muted: #718096;
24
+
25
+ /* Borders */
26
+ --border-light: #E2E8F0;
27
+ --border-medium: #CBD5E0;
28
+
29
+ /* Shadows */
30
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
31
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
32
+ --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.12);
33
+ --shadow-primary: 0 4px 20px rgba(45, 106, 79, 0.25);
34
+
35
+ /* Sizing */
36
+ --header-height: 60px;
37
+ --sidebar-width: 260px;
38
+ --mobile-toolbar-height: 56px;
39
+
40
+ /* Transitions */
41
+ --transition-fast: 0.15s ease;
42
+ --transition-normal: 0.25s ease;
43
+ --transition-slow: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
44
+ }
45
+
46
+ * {
47
+ margin: 0;
48
+ padding: 0;
49
+ box-sizing: border-box;
50
+ }
51
+
52
+ body {
53
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
54
+ background: var(--bg-main);
55
+ color: var(--text-primary);
56
+ overflow: hidden;
57
+ -webkit-tap-highlight-color: transparent;
58
+ }
59
+
60
+ /* ===== Auth Overlay ===== */
61
+ .auth-overlay {
62
+ position: fixed;
63
+ inset: 0;
64
+ z-index: 9999;
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ background: var(--bg-main);
69
+ padding: 1rem;
70
+ }
71
+
72
+ .auth-overlay.hidden {
73
+ display: none;
74
+ }
75
+
76
+ .auth-background {
77
+ position: absolute;
78
+ inset: 0;
79
+ overflow: hidden;
80
+ }
81
+
82
+ .blob {
83
+ position: absolute;
84
+ border-radius: 50%;
85
+ filter: blur(100px);
86
+ animation: float 15s infinite ease-in-out;
87
+ }
88
+
89
+ .blob-1 {
90
+ top: -10%;
91
+ left: 10%;
92
+ width: 45%;
93
+ height: 45%;
94
+ background: var(--pastel-green);
95
+ }
96
+
97
+ .blob-2 {
98
+ bottom: -5%;
99
+ right: 5%;
100
+ width: 50%;
101
+ height: 50%;
102
+ background: var(--pastel-mint);
103
+ animation-delay: 2s;
104
+ }
105
+
106
+ .blob-3 {
107
+ top: 20%;
108
+ right: 15%;
109
+ width: 30%;
110
+ height: 30%;
111
+ background: var(--pastel-green-light);
112
+ animation-delay: 4s;
113
+ }
114
+
115
+ @keyframes float {
116
+ 0% {
117
+ transform: translate(0, 0) scale(1);
118
+ }
119
+
120
+ 33% {
121
+ transform: translate(30px, -50px) scale(1.1);
122
+ }
123
+
124
+ 66% {
125
+ transform: translate(-20px, 20px) scale(0.9);
126
+ }
127
+
128
+ 100% {
129
+ transform: translate(0, 0) scale(1);
130
+ }
131
+ }
132
+
133
+ .auth-card {
134
+ position: relative;
135
+ z-index: 1;
136
+ background: var(--bg-canvas);
137
+ padding: 2rem;
138
+ border-radius: 24px;
139
+ border: 1px solid var(--border-light);
140
+ box-shadow: var(--shadow-lg);
141
+ text-align: center;
142
+ width: 100%;
143
+ max-width: 420px;
144
+ }
145
+
146
+ @media (min-width: 768px) {
147
+ .auth-card {
148
+ padding: 3rem;
149
+ }
150
+ }
151
+
152
+ .auth-logo {
153
+ width: 48px;
154
+ height: 48px;
155
+ margin: 0 auto 1.5rem;
156
+ color: var(--primary);
157
+ }
158
+
159
+ .auth-logo svg {
160
+ width: 100%;
161
+ height: 100%;
162
+ }
163
+
164
+ .auth-title {
165
+ font-size: 1.5rem;
166
+ font-weight: 700;
167
+ color: var(--text-primary);
168
+ margin-bottom: 0.5rem;
169
+ }
170
+
171
+ @media (min-width: 768px) {
172
+ .auth-title {
173
+ font-size: 1.75rem;
174
+ }
175
+ }
176
+
177
+ .auth-subtitle {
178
+ font-size: 0.9rem;
179
+ color: var(--text-muted);
180
+ margin-bottom: 1.5rem;
181
+ }
182
+
183
+ @media (min-width: 768px) {
184
+ .auth-subtitle {
185
+ font-size: 0.95rem;
186
+ margin-bottom: 2rem;
187
+ }
188
+ }
189
+
190
+ .auth-input-group {
191
+ position: relative;
192
+ margin-bottom: 1.5rem;
193
+ }
194
+
195
+ .auth-input-group .material-symbols-outlined {
196
+ position: absolute;
197
+ left: 1rem;
198
+ top: 50%;
199
+ transform: translateY(-50%);
200
+ color: var(--text-muted);
201
+ font-size: 1.25rem;
202
+ }
203
+
204
+ .auth-input-group input {
205
+ width: 100%;
206
+ padding: 1rem 1rem 1rem 3rem;
207
+ font-size: 1rem;
208
+ font-family: inherit;
209
+ border: 1px solid var(--border-light);
210
+ border-radius: 12px;
211
+ background: var(--pastel-green-light);
212
+ color: var(--text-primary);
213
+ transition: var(--transition-fast);
214
+ }
215
+
216
+ .auth-input-group input:focus {
217
+ outline: none;
218
+ border-color: var(--primary);
219
+ box-shadow: 0 0 0 3px rgba(45, 106, 79, 0.1);
220
+ }
221
+
222
+ .auth-btn {
223
+ width: 100%;
224
+ padding: 1rem 2rem;
225
+ font-size: 1rem;
226
+ font-weight: 600;
227
+ font-family: inherit;
228
+ background: var(--primary);
229
+ color: white;
230
+ border: none;
231
+ border-radius: 12px;
232
+ cursor: pointer;
233
+ display: flex;
234
+ align-items: center;
235
+ justify-content: center;
236
+ gap: 0.5rem;
237
+ transition: var(--transition-normal);
238
+ }
239
+
240
+ .auth-btn:hover {
241
+ background: var(--primary-light);
242
+ box-shadow: var(--shadow-primary);
243
+ }
244
+
245
+ .auth-btn:active {
246
+ transform: scale(0.98);
247
+ }
248
+
249
+ .error-msg {
250
+ color: #E53E3E;
251
+ font-size: 0.875rem;
252
+ margin-top: 1rem;
253
+ min-height: 1.25rem;
254
+ }
255
+
256
+ /* ===== Admin Workspace ===== */
257
+ .admin-workspace {
258
+ width: 100%;
259
+ height: 100vh;
260
+ height: 100dvh;
261
+ display: flex;
262
+ flex-direction: column;
263
+ }
264
+
265
+ .admin-workspace.hidden {
266
+ display: none;
267
+ }
268
+
269
+ /* ===== Studio Header ===== */
270
+ .studio-header {
271
+ height: var(--header-height);
272
+ background: var(--bg-header);
273
+ backdrop-filter: blur(12px);
274
+ border-bottom: 1px solid var(--border-light);
275
+ display: flex;
276
+ align-items: center;
277
+ justify-content: space-between;
278
+ padding: 0 0.75rem;
279
+ position: relative;
280
+ z-index: 100;
281
+ flex-shrink: 0;
282
+ }
283
+
284
+ @media (min-width: 768px) {
285
+ .studio-header {
286
+ padding: 0 1.25rem;
287
+ }
288
+ }
289
+
290
+ .header-left,
291
+ .header-right {
292
+ display: flex;
293
+ align-items: center;
294
+ gap: 0.5rem;
295
+ }
296
+
297
+ @media (min-width: 768px) {
298
+
299
+ .header-left,
300
+ .header-right {
301
+ gap: 0.75rem;
302
+ }
303
+ }
304
+
305
+ .menu-toggle {
306
+ display: flex;
307
+ align-items: center;
308
+ justify-content: center;
309
+ width: 40px;
310
+ height: 40px;
311
+ background: transparent;
312
+ border: none;
313
+ border-radius: 8px;
314
+ cursor: pointer;
315
+ color: var(--text-secondary);
316
+ }
317
+
318
+ .menu-toggle:hover {
319
+ background: var(--pastel-green-light);
320
+ }
321
+
322
+ @media (min-width: 992px) {
323
+ .menu-toggle {
324
+ display: none;
325
+ }
326
+ }
327
+
328
+ .header-center {
329
+ display: none;
330
+ }
331
+
332
+ @media (min-width: 768px) {
333
+ .header-center {
334
+ display: block;
335
+ position: absolute;
336
+ left: 50%;
337
+ transform: translateX(-50%);
338
+ }
339
+ }
340
+
341
+ .logo {
342
+ display: flex;
343
+ align-items: center;
344
+ gap: 0.5rem;
345
+ color: var(--primary);
346
+ font-weight: 700;
347
+ font-size: 1rem;
348
+ }
349
+
350
+ @media (min-width: 768px) {
351
+ .logo {
352
+ font-size: 1.1rem;
353
+ }
354
+ }
355
+
356
+ .logo svg {
357
+ width: 24px;
358
+ height: 24px;
359
+ }
360
+
361
+ @media (min-width: 768px) {
362
+ .logo svg {
363
+ width: 28px;
364
+ height: 28px;
365
+ }
366
+ }
367
+
368
+ .logo-text {
369
+ display: none;
370
+ }
371
+
372
+ @media (min-width: 640px) {
373
+ .logo-text {
374
+ display: inline;
375
+ }
376
+ }
377
+
378
+ .title-input {
379
+ font-size: 1rem;
380
+ font-weight: 600;
381
+ font-family: inherit;
382
+ background: transparent;
383
+ border: 1px solid transparent;
384
+ padding: 0.5rem 1rem;
385
+ border-radius: 8px;
386
+ text-align: center;
387
+ color: var(--text-primary);
388
+ min-width: 200px;
389
+ transition: var(--transition-fast);
390
+ }
391
+
392
+ .title-input:hover {
393
+ background: var(--pastel-green-light);
394
+ }
395
+
396
+ .title-input:focus {
397
+ outline: none;
398
+ background: var(--pastel-green-light);
399
+ border-color: var(--primary);
400
+ }
401
+
402
+ /* Zoom Controls */
403
+ .zoom-controls {
404
+ display: none;
405
+ align-items: center;
406
+ gap: 0.25rem;
407
+ background: var(--pastel-green-light);
408
+ border-radius: 8px;
409
+ padding: 0.25rem;
410
+ margin-right: 0.5rem;
411
+ }
412
+
413
+ @media (min-width: 768px) {
414
+ .zoom-controls {
415
+ display: flex;
416
+ }
417
+ }
418
+
419
+ .zoom-btn {
420
+ width: 32px;
421
+ height: 32px;
422
+ display: flex;
423
+ align-items: center;
424
+ justify-content: center;
425
+ background: transparent;
426
+ border: none;
427
+ border-radius: 6px;
428
+ cursor: pointer;
429
+ color: var(--text-secondary);
430
+ transition: var(--transition-fast);
431
+ }
432
+
433
+ .zoom-btn:hover {
434
+ background: var(--pastel-green);
435
+ color: var(--primary);
436
+ }
437
+
438
+ .zoom-btn .material-symbols-outlined {
439
+ font-size: 1.1rem;
440
+ }
441
+
442
+ .zoom-level {
443
+ font-size: 0.75rem;
444
+ font-weight: 600;
445
+ color: var(--text-secondary);
446
+ min-width: 40px;
447
+ text-align: center;
448
+ }
449
+
450
+ .header-btn {
451
+ display: flex;
452
+ align-items: center;
453
+ justify-content: center;
454
+ gap: 0.5rem;
455
+ padding: 0.5rem;
456
+ font-size: 0.875rem;
457
+ font-weight: 600;
458
+ font-family: inherit;
459
+ border-radius: 8px;
460
+ cursor: pointer;
461
+ transition: var(--transition-fast);
462
+ text-decoration: none;
463
+ min-width: 40px;
464
+ min-height: 40px;
465
+ }
466
+
467
+ @media (min-width: 768px) {
468
+ .header-btn {
469
+ padding: 0.5rem 1rem;
470
+ }
471
+ }
472
+
473
+ .btn-text {
474
+ display: none;
475
+ }
476
+
477
+ @media (min-width: 768px) {
478
+ .btn-text {
479
+ display: inline;
480
+ }
481
+ }
482
+
483
+ .header-btn.primary {
484
+ background: var(--primary);
485
+ color: white;
486
+ border: none;
487
+ }
488
+
489
+ .header-btn.primary:hover {
490
+ background: var(--primary-light);
491
+ box-shadow: var(--shadow-primary);
492
+ }
493
+
494
+ .header-btn.secondary {
495
+ background: var(--pastel-green-light);
496
+ color: var(--primary);
497
+ border: 1px solid var(--pastel-green);
498
+ }
499
+
500
+ .header-btn.secondary:hover {
501
+ background: var(--pastel-green);
502
+ }
503
+
504
+ .header-btn.ghost {
505
+ background: transparent;
506
+ color: var(--text-muted);
507
+ border: none;
508
+ }
509
+
510
+ .header-btn.ghost:hover {
511
+ background: var(--pastel-green-light);
512
+ color: var(--text-primary);
513
+ }
514
+
515
+ .header-btn .material-symbols-outlined {
516
+ font-size: 1.25rem;
517
+ }
518
+
519
+ /* ===== Mobile Toolbar ===== */
520
+ .mobile-toolbar {
521
+ display: flex;
522
+ align-items: center;
523
+ justify-content: space-around;
524
+ height: var(--mobile-toolbar-height);
525
+ background: var(--bg-sidebar);
526
+ border-bottom: 1px solid var(--border-light);
527
+ padding: 0 0.5rem;
528
+ flex-shrink: 0;
529
+ }
530
+
531
+ @media (min-width: 992px) {
532
+ .mobile-toolbar {
533
+ display: none;
534
+ }
535
+ }
536
+
537
+ .mobile-tool-btn {
538
+ display: flex;
539
+ align-items: center;
540
+ justify-content: center;
541
+ width: 44px;
542
+ height: 44px;
543
+ background: var(--pastel-green-light);
544
+ border: none;
545
+ border-radius: 12px;
546
+ cursor: pointer;
547
+ color: var(--primary);
548
+ transition: var(--transition-fast);
549
+ }
550
+
551
+ .mobile-tool-btn:hover,
552
+ .mobile-tool-btn:active {
553
+ background: var(--pastel-green);
554
+ }
555
+
556
+ .mobile-tool-btn .material-symbols-outlined {
557
+ font-size: 1.5rem;
558
+ }
559
+
560
+ /* ===== Studio Layout ===== */
561
+ .studio-layout {
562
+ display: flex;
563
+ height: calc(100vh - var(--header-height) - var(--mobile-toolbar-height));
564
+ height: calc(100dvh - var(--header-height) - var(--mobile-toolbar-height));
565
+ overflow: hidden;
566
+ position: relative;
567
+ }
568
+
569
+ @media (min-width: 992px) {
570
+ .studio-layout {
571
+ height: calc(100vh - var(--header-height));
572
+ height: calc(100dvh - var(--header-height));
573
+ }
574
+ }
575
+
576
+ /* ===== Sidebars ===== */
577
+ .sidebar {
578
+ width: var(--sidebar-width);
579
+ background: var(--bg-sidebar);
580
+ overflow-y: auto;
581
+ flex-shrink: 0;
582
+ position: fixed;
583
+ top: var(--header-height);
584
+ height: calc(100vh - var(--header-height));
585
+ height: calc(100dvh - var(--header-height));
586
+ z-index: 200;
587
+ transition: var(--transition-normal);
588
+ }
589
+
590
+ .sidebar-left {
591
+ left: 0;
592
+ border-right: 1px solid var(--border-light);
593
+ transform: translateX(-100%);
594
+ }
595
+
596
+ .sidebar-left.open {
597
+ transform: translateX(0);
598
+ }
599
+
600
+ .sidebar-right {
601
+ right: 0;
602
+ border-left: 1px solid var(--border-light);
603
+ transform: translateX(100%);
604
+ }
605
+
606
+ .sidebar-right.open {
607
+ transform: translateX(0);
608
+ }
609
+
610
+ @media (min-width: 992px) {
611
+ .sidebar {
612
+ position: relative;
613
+ top: auto;
614
+ height: auto;
615
+ transform: none !important;
616
+ }
617
+ }
618
+
619
+ .sidebar-header {
620
+ display: flex;
621
+ align-items: center;
622
+ justify-content: space-between;
623
+ padding: 1rem 1.25rem;
624
+ border-bottom: 1px solid var(--border-light);
625
+ }
626
+
627
+ @media (min-width: 992px) {
628
+ .sidebar-header {
629
+ display: none;
630
+ }
631
+ }
632
+
633
+ .sidebar-header h3 {
634
+ font-size: 1rem;
635
+ font-weight: 600;
636
+ }
637
+
638
+ .close-sidebar {
639
+ display: flex;
640
+ align-items: center;
641
+ justify-content: center;
642
+ width: 36px;
643
+ height: 36px;
644
+ background: transparent;
645
+ border: none;
646
+ border-radius: 8px;
647
+ cursor: pointer;
648
+ color: var(--text-muted);
649
+ }
650
+
651
+ .close-sidebar:hover {
652
+ background: var(--pastel-green-light);
653
+ }
654
+
655
+ .sidebar-overlay {
656
+ display: none;
657
+ position: fixed;
658
+ inset: 0;
659
+ background: rgba(0, 0, 0, 0.3);
660
+ z-index: 150;
661
+ }
662
+
663
+ .sidebar-overlay.visible {
664
+ display: block;
665
+ }
666
+
667
+ @media (min-width: 992px) {
668
+ .sidebar-overlay {
669
+ display: none !important;
670
+ }
671
+ }
672
+
673
+ .sidebar-section {
674
+ padding: 1.25rem;
675
+ border-bottom: 1px solid var(--border-light);
676
+ }
677
+
678
+ .sidebar-section:last-child {
679
+ border-bottom: none;
680
+ }
681
+
682
+ .sidebar-title {
683
+ font-size: 0.7rem;
684
+ font-weight: 700;
685
+ text-transform: uppercase;
686
+ letter-spacing: 0.08em;
687
+ color: var(--text-muted);
688
+ margin-bottom: 1rem;
689
+ }
690
+
691
+ /* ===== Element Grid ===== */
692
+ .element-grid {
693
+ display: grid;
694
+ grid-template-columns: repeat(2, 1fr);
695
+ gap: 0.5rem;
696
+ }
697
+
698
+ .element-btn {
699
+ display: flex;
700
+ flex-direction: column;
701
+ align-items: center;
702
+ gap: 0.5rem;
703
+ padding: 1rem 0.5rem;
704
+ background: var(--pastel-green-light);
705
+ border: 1px solid transparent;
706
+ border-radius: 12px;
707
+ cursor: pointer;
708
+ transition: var(--transition-fast);
709
+ font-family: inherit;
710
+ }
711
+
712
+ .element-btn:hover,
713
+ .element-btn:active {
714
+ background: var(--pastel-green);
715
+ border-color: var(--primary);
716
+ }
717
+
718
+ .element-btn .material-symbols-outlined {
719
+ font-size: 1.5rem;
720
+ color: var(--primary);
721
+ }
722
+
723
+ .element-btn span:last-child {
724
+ font-size: 0.75rem;
725
+ font-weight: 500;
726
+ color: var(--text-secondary);
727
+ }
728
+
729
+ /* ===== Layers List ===== */
730
+ .layers-list {
731
+ max-height: 200px;
732
+ overflow-y: auto;
733
+ }
734
+
735
+ .empty-layers,
736
+ .empty-properties {
737
+ font-size: 0.85rem;
738
+ color: var(--text-muted);
739
+ text-align: center;
740
+ padding: 1rem;
741
+ }
742
+
743
+ .layer-item {
744
+ display: flex;
745
+ align-items: center;
746
+ gap: 0.75rem;
747
+ padding: 0.75rem;
748
+ background: var(--pastel-green-light);
749
+ border-radius: 8px;
750
+ margin-bottom: 0.5rem;
751
+ cursor: pointer;
752
+ transition: var(--transition-fast);
753
+ font-size: 0.85rem;
754
+ }
755
+
756
+ .layer-item:hover {
757
+ background: var(--pastel-green);
758
+ }
759
+
760
+ .layer-item.active {
761
+ background: var(--primary);
762
+ color: white;
763
+ }
764
+
765
+ /* ===== Properties Panel ===== */
766
+ .property-group {
767
+ margin-bottom: 1rem;
768
+ }
769
+
770
+ .property-group label {
771
+ display: block;
772
+ font-size: 0.75rem;
773
+ font-weight: 600;
774
+ color: var(--text-secondary);
775
+ margin-bottom: 0.5rem;
776
+ }
777
+
778
+ .property-row {
779
+ display: flex;
780
+ gap: 0.75rem;
781
+ }
782
+
783
+ .property-group.half {
784
+ flex: 1;
785
+ }
786
+
787
+ .property-select {
788
+ width: 100%;
789
+ padding: 0.625rem 0.75rem;
790
+ font-size: 0.875rem;
791
+ font-family: inherit;
792
+ border: 1px solid var(--border-light);
793
+ border-radius: 8px;
794
+ background: var(--pastel-green-light);
795
+ color: var(--text-primary);
796
+ cursor: pointer;
797
+ }
798
+
799
+ .property-select:focus {
800
+ outline: none;
801
+ border-color: var(--primary);
802
+ }
803
+
804
+ .input-with-unit {
805
+ display: flex;
806
+ align-items: center;
807
+ background: var(--pastel-green-light);
808
+ border: 1px solid var(--border-light);
809
+ border-radius: 8px;
810
+ overflow: hidden;
811
+ }
812
+
813
+ .input-with-unit input {
814
+ width: 100%;
815
+ padding: 0.625rem 0.75rem;
816
+ font-size: 0.875rem;
817
+ font-family: inherit;
818
+ border: none;
819
+ background: transparent;
820
+ color: var(--text-primary);
821
+ }
822
+
823
+ .input-with-unit input:focus {
824
+ outline: none;
825
+ }
826
+
827
+ .input-with-unit span {
828
+ padding-right: 0.75rem;
829
+ font-size: 0.75rem;
830
+ color: var(--text-muted);
831
+ }
832
+
833
+ .color-picker-row {
834
+ display: flex;
835
+ align-items: center;
836
+ gap: 0.75rem;
837
+ }
838
+
839
+ .color-picker-row input[type="color"] {
840
+ width: 40px;
841
+ height: 40px;
842
+ padding: 0;
843
+ border: none;
844
+ border-radius: 8px;
845
+ cursor: pointer;
846
+ background: none;
847
+ }
848
+
849
+ .color-picker-row input[type="color"]::-webkit-color-swatch-wrapper {
850
+ padding: 0;
851
+ }
852
+
853
+ .color-picker-row input[type="color"]::-webkit-color-swatch {
854
+ border: 2px solid var(--border-light);
855
+ border-radius: 8px;
856
+ }
857
+
858
+ .color-hex-input {
859
+ flex: 1;
860
+ padding: 0.625rem 0.75rem;
861
+ font-size: 0.875rem;
862
+ font-family: inherit;
863
+ border: 1px solid var(--border-light);
864
+ border-radius: 8px;
865
+ background: var(--pastel-green-light);
866
+ color: var(--text-primary);
867
+ text-transform: uppercase;
868
+ }
869
+
870
+ .slider-row {
871
+ display: flex;
872
+ align-items: center;
873
+ gap: 0.75rem;
874
+ }
875
+
876
+ .slider-row input[type="range"] {
877
+ flex: 1;
878
+ -webkit-appearance: none;
879
+ height: 6px;
880
+ background: var(--pastel-green);
881
+ border-radius: 3px;
882
+ outline: none;
883
+ }
884
+
885
+ .slider-row input[type="range"]::-webkit-slider-thumb {
886
+ -webkit-appearance: none;
887
+ width: 16px;
888
+ height: 16px;
889
+ background: var(--primary);
890
+ border-radius: 50%;
891
+ cursor: pointer;
892
+ }
893
+
894
+ .slider-row span {
895
+ font-size: 0.75rem;
896
+ font-weight: 500;
897
+ color: var(--text-muted);
898
+ min-width: 40px;
899
+ text-align: right;
900
+ }
901
+
902
+ .button-group {
903
+ display: flex;
904
+ gap: 0.25rem;
905
+ }
906
+
907
+ .icon-btn {
908
+ width: 40px;
909
+ height: 40px;
910
+ display: flex;
911
+ align-items: center;
912
+ justify-content: center;
913
+ background: var(--pastel-green-light);
914
+ border: 1px solid transparent;
915
+ border-radius: 8px;
916
+ cursor: pointer;
917
+ transition: var(--transition-fast);
918
+ }
919
+
920
+ .icon-btn:hover {
921
+ background: var(--pastel-green);
922
+ }
923
+
924
+ .icon-btn.active {
925
+ background: var(--primary);
926
+ color: white;
927
+ }
928
+
929
+ .property-divider {
930
+ height: 1px;
931
+ background: var(--border-light);
932
+ margin: 1rem 0;
933
+ }
934
+
935
+ .upload-btn {
936
+ display: flex;
937
+ align-items: center;
938
+ justify-content: center;
939
+ gap: 0.5rem;
940
+ width: 100%;
941
+ padding: 0.75rem 1rem;
942
+ background: var(--pastel-green-light);
943
+ border: 2px dashed var(--pastel-green);
944
+ border-radius: 12px;
945
+ cursor: pointer;
946
+ font-size: 0.85rem;
947
+ font-weight: 500;
948
+ color: var(--text-secondary);
949
+ }
950
+
951
+ .upload-btn:hover {
952
+ background: var(--pastel-green);
953
+ border-color: var(--primary);
954
+ color: var(--primary);
955
+ }
956
+
957
+ .delete-btn {
958
+ width: 100%;
959
+ display: flex;
960
+ align-items: center;
961
+ justify-content: center;
962
+ gap: 0.5rem;
963
+ padding: 0.75rem 1rem;
964
+ background: #FED7D7;
965
+ color: #C53030;
966
+ border: none;
967
+ border-radius: 8px;
968
+ font-size: 0.875rem;
969
+ font-weight: 600;
970
+ font-family: inherit;
971
+ cursor: pointer;
972
+ }
973
+
974
+ .delete-btn:hover {
975
+ background: #FEB2B2;
976
+ }
977
+
978
+ /* ===== Canvas Area ===== */
979
+ .canvas-area {
980
+ flex: 1;
981
+ overflow: auto;
982
+ background:
983
+ linear-gradient(90deg, var(--border-light) 1px, transparent 1px),
984
+ linear-gradient(var(--border-light) 1px, transparent 1px);
985
+ background-size: 20px 20px;
986
+ display: flex;
987
+ align-items: flex-start;
988
+ justify-content: center;
989
+ padding: 1rem;
990
+ min-width: 0;
991
+ }
992
+
993
+ @media (min-width: 768px) {
994
+ .canvas-area {
995
+ padding: 2rem;
996
+ }
997
+ }
998
+
999
+ .canvas-wrapper {
1000
+ position: relative;
1001
+ transform-origin: center top;
1002
+ transition: transform 0.2s ease;
1003
+ }
1004
+
1005
+ .blog-canvas {
1006
+ width: 100%;
1007
+ max-width: 900px;
1008
+ min-width: 320px;
1009
+ min-height: 600px;
1010
+ background: var(--bg-canvas);
1011
+ box-shadow: var(--shadow-lg);
1012
+ border-radius: 8px;
1013
+ position: relative;
1014
+ overflow: visible;
1015
+ touch-action: none;
1016
+ }
1017
+
1018
+ @media (min-width: 768px) {
1019
+ .blog-canvas {
1020
+ width: 900px;
1021
+ min-height: 1200px;
1022
+ }
1023
+ }
1024
+
1025
+ .canvas-placeholder {
1026
+ position: absolute;
1027
+ inset: 0;
1028
+ display: flex;
1029
+ flex-direction: column;
1030
+ align-items: center;
1031
+ justify-content: center;
1032
+ color: var(--text-muted);
1033
+ pointer-events: none;
1034
+ padding: 2rem;
1035
+ text-align: center;
1036
+ }
1037
+
1038
+ .canvas-placeholder .material-symbols-outlined {
1039
+ font-size: 3rem;
1040
+ margin-bottom: 1rem;
1041
+ color: var(--pastel-green);
1042
+ }
1043
+
1044
+ @media (min-width: 768px) {
1045
+ .canvas-placeholder .material-symbols-outlined {
1046
+ font-size: 4rem;
1047
+ }
1048
+ }
1049
+
1050
+ .canvas-placeholder p {
1051
+ font-size: 0.9rem;
1052
+ line-height: 1.6;
1053
+ }
1054
+
1055
+ @media (min-width: 768px) {
1056
+ .canvas-placeholder p {
1057
+ font-size: 1rem;
1058
+ }
1059
+ }
1060
+
1061
+ .canvas-placeholder.hidden {
1062
+ display: none;
1063
+ }
1064
+
1065
+ /* ===== Draggable Elements ===== */
1066
+ .draggable-element {
1067
+ position: absolute;
1068
+ cursor: move;
1069
+ user-select: none;
1070
+ min-width: 50px;
1071
+ min-height: 30px;
1072
+ touch-action: none;
1073
+ }
1074
+
1075
+ .draggable-element:hover {
1076
+ outline: 2px solid var(--accent);
1077
+ outline-offset: 2px;
1078
+ }
1079
+
1080
+ .draggable-element.selected {
1081
+ outline: 2px solid var(--primary);
1082
+ outline-offset: 2px;
1083
+ }
1084
+
1085
+ .draggable-element.dragging {
1086
+ opacity: 0.8;
1087
+ cursor: grabbing;
1088
+ z-index: 1000;
1089
+ }
1090
+
1091
+ /* Resize Handles */
1092
+ .resize-handle {
1093
+ position: absolute;
1094
+ width: 16px;
1095
+ height: 16px;
1096
+ background: var(--primary);
1097
+ border: 2px solid white;
1098
+ border-radius: 4px;
1099
+ z-index: 10;
1100
+ opacity: 0;
1101
+ pointer-events: none;
1102
+ transition: var(--transition-fast);
1103
+ }
1104
+
1105
+ .draggable-element.selected .resize-handle {
1106
+ opacity: 1;
1107
+ pointer-events: auto;
1108
+ }
1109
+
1110
+ .resize-handle.nw {
1111
+ top: -8px;
1112
+ left: -8px;
1113
+ cursor: nwse-resize;
1114
+ }
1115
+
1116
+ .resize-handle.ne {
1117
+ top: -8px;
1118
+ right: -8px;
1119
+ cursor: nesw-resize;
1120
+ }
1121
+
1122
+ .resize-handle.sw {
1123
+ bottom: -8px;
1124
+ left: -8px;
1125
+ cursor: nesw-resize;
1126
+ }
1127
+
1128
+ .resize-handle.se {
1129
+ bottom: -8px;
1130
+ right: -8px;
1131
+ cursor: nwse-resize;
1132
+ }
1133
+
1134
+ .resize-handle.n {
1135
+ top: -8px;
1136
+ left: 50%;
1137
+ transform: translateX(-50%);
1138
+ cursor: ns-resize;
1139
+ }
1140
+
1141
+ .resize-handle.s {
1142
+ bottom: -8px;
1143
+ left: 50%;
1144
+ transform: translateX(-50%);
1145
+ cursor: ns-resize;
1146
+ }
1147
+
1148
+ .resize-handle.e {
1149
+ right: -8px;
1150
+ top: 50%;
1151
+ transform: translateY(-50%);
1152
+ cursor: ew-resize;
1153
+ }
1154
+
1155
+ .resize-handle.w {
1156
+ left: -8px;
1157
+ top: 50%;
1158
+ transform: translateY(-50%);
1159
+ cursor: ew-resize;
1160
+ }
1161
+
1162
+ /* Element Content Styles */
1163
+ .draggable-element .element-content {
1164
+ width: 100%;
1165
+ height: 100%;
1166
+ padding: 0.5rem;
1167
+ }
1168
+
1169
+ .draggable-element h1,
1170
+ .draggable-element h2,
1171
+ .draggable-element h3,
1172
+ .draggable-element p {
1173
+ margin: 0;
1174
+ outline: none;
1175
+ cursor: text;
1176
+ }
1177
+
1178
+ .draggable-element h1 {
1179
+ font-size: 2rem;
1180
+ font-weight: 700;
1181
+ font-family: 'Playfair Display', serif;
1182
+ }
1183
+
1184
+ @media (min-width: 768px) {
1185
+ .draggable-element h1 {
1186
+ font-size: 2.5rem;
1187
+ }
1188
+ }
1189
+
1190
+ .draggable-element h2 {
1191
+ font-size: 1.5rem;
1192
+ font-weight: 600;
1193
+ }
1194
+
1195
+ @media (min-width: 768px) {
1196
+ .draggable-element h2 {
1197
+ font-size: 2rem;
1198
+ }
1199
+ }
1200
+
1201
+ .draggable-element h3 {
1202
+ font-size: 1.25rem;
1203
+ font-weight: 600;
1204
+ }
1205
+
1206
+ @media (min-width: 768px) {
1207
+ .draggable-element h3 {
1208
+ font-size: 1.5rem;
1209
+ }
1210
+ }
1211
+
1212
+ .draggable-element p {
1213
+ font-size: 1rem;
1214
+ line-height: 1.7;
1215
+ }
1216
+
1217
+ .draggable-element blockquote {
1218
+ margin: 0;
1219
+ padding: 1rem 1.5rem;
1220
+ border-left: 4px solid var(--primary);
1221
+ background: var(--pastel-green-light);
1222
+ font-style: italic;
1223
+ font-size: 1.1rem;
1224
+ }
1225
+
1226
+ .draggable-element img {
1227
+ width: 100%;
1228
+ height: 100%;
1229
+ object-fit: cover;
1230
+ display: block;
1231
+ pointer-events: none;
1232
+ }
1233
+
1234
+ .draggable-element .element-divider {
1235
+ width: 100%;
1236
+ height: 2px;
1237
+ background: linear-gradient(90deg, transparent, var(--primary), transparent);
1238
+ margin: 1rem 0;
1239
+ }
1240
+
1241
+ .draggable-element .element-button {
1242
+ display: inline-block;
1243
+ padding: 0.75rem 1.5rem;
1244
+ background: var(--primary);
1245
+ color: white;
1246
+ font-weight: 600;
1247
+ border-radius: 8px;
1248
+ cursor: pointer;
1249
+ outline: none;
1250
+ }
1251
+
1252
+ /* Image element specific */
1253
+ .draggable-element[data-type="image"] {
1254
+ cursor: move;
1255
+ overflow: hidden;
1256
+ }
1257
+
1258
+ .draggable-element[data-type="image"] .element-content {
1259
+ padding: 0;
1260
+ width: 100%;
1261
+ height: 100%;
1262
+ }
1263
+
1264
+ /* ===== Modal ===== */
1265
+ .modal {
1266
+ position: fixed;
1267
+ inset: 0;
1268
+ z-index: 9999;
1269
+ display: flex;
1270
+ align-items: center;
1271
+ justify-content: center;
1272
+ padding: 1rem;
1273
+ }
1274
+
1275
+ .modal.hidden {
1276
+ display: none;
1277
+ }
1278
+
1279
+ .modal-backdrop {
1280
+ position: absolute;
1281
+ inset: 0;
1282
+ background: rgba(0, 0, 0, 0.5);
1283
+ backdrop-filter: blur(4px);
1284
+ }
1285
+
1286
+ .modal-content {
1287
+ position: relative;
1288
+ background: white;
1289
+ border-radius: 20px;
1290
+ width: 100%;
1291
+ max-width: 500px;
1292
+ max-height: 90vh;
1293
+ overflow-y: auto;
1294
+ box-shadow: var(--shadow-lg);
1295
+ }
1296
+
1297
+ .modal-header {
1298
+ display: flex;
1299
+ align-items: center;
1300
+ justify-content: space-between;
1301
+ padding: 1.25rem 1.5rem;
1302
+ border-bottom: 1px solid var(--border-light);
1303
+ }
1304
+
1305
+ .modal-header h2 {
1306
+ font-size: 1.25rem;
1307
+ font-weight: 700;
1308
+ }
1309
+
1310
+ .modal-close {
1311
+ display: flex;
1312
+ align-items: center;
1313
+ justify-content: center;
1314
+ width: 36px;
1315
+ height: 36px;
1316
+ background: transparent;
1317
+ border: none;
1318
+ border-radius: 8px;
1319
+ cursor: pointer;
1320
+ color: var(--text-muted);
1321
+ }
1322
+
1323
+ .modal-close:hover {
1324
+ background: var(--pastel-green-light);
1325
+ }
1326
+
1327
+ .modal-body {
1328
+ padding: 1.5rem;
1329
+ }
1330
+
1331
+ .form-group {
1332
+ margin-bottom: 1.5rem;
1333
+ }
1334
+
1335
+ .form-group label {
1336
+ display: block;
1337
+ font-size: 0.875rem;
1338
+ font-weight: 600;
1339
+ color: var(--text-secondary);
1340
+ margin-bottom: 0.5rem;
1341
+ }
1342
+
1343
+ .form-group input[type="text"] {
1344
+ width: 100%;
1345
+ padding: 0.75rem 1rem;
1346
+ font-size: 1rem;
1347
+ font-family: inherit;
1348
+ border: 1px solid var(--border-light);
1349
+ border-radius: 10px;
1350
+ background: var(--pastel-green-light);
1351
+ color: var(--text-primary);
1352
+ }
1353
+
1354
+ .form-group input[type="text"]:focus {
1355
+ outline: none;
1356
+ border-color: var(--primary);
1357
+ }
1358
+
1359
+ .cover-upload-area {
1360
+ width: 100%;
1361
+ min-height: 200px;
1362
+ border: 2px dashed var(--pastel-green);
1363
+ border-radius: 12px;
1364
+ overflow: hidden;
1365
+ cursor: pointer;
1366
+ transition: var(--transition-fast);
1367
+ }
1368
+
1369
+ .cover-upload-area:hover {
1370
+ border-color: var(--primary);
1371
+ background: var(--pastel-green-light);
1372
+ }
1373
+
1374
+ .upload-placeholder {
1375
+ display: flex;
1376
+ flex-direction: column;
1377
+ align-items: center;
1378
+ justify-content: center;
1379
+ height: 200px;
1380
+ color: var(--text-muted);
1381
+ }
1382
+
1383
+ .upload-placeholder .material-symbols-outlined {
1384
+ font-size: 3rem;
1385
+ color: var(--primary);
1386
+ margin-bottom: 0.5rem;
1387
+ }
1388
+
1389
+ .upload-placeholder p {
1390
+ font-weight: 500;
1391
+ }
1392
+
1393
+ .upload-hint {
1394
+ font-size: 0.75rem;
1395
+ margin-top: 0.25rem;
1396
+ }
1397
+
1398
+ .upload-preview {
1399
+ position: relative;
1400
+ width: 100%;
1401
+ }
1402
+
1403
+ .upload-preview img {
1404
+ width: 100%;
1405
+ height: 200px;
1406
+ object-fit: cover;
1407
+ }
1408
+
1409
+ .remove-cover {
1410
+ position: absolute;
1411
+ top: 0.5rem;
1412
+ right: 0.5rem;
1413
+ width: 32px;
1414
+ height: 32px;
1415
+ display: flex;
1416
+ align-items: center;
1417
+ justify-content: center;
1418
+ background: rgba(0, 0, 0, 0.5);
1419
+ color: white;
1420
+ border: none;
1421
+ border-radius: 50%;
1422
+ cursor: pointer;
1423
+ }
1424
+
1425
+ .remove-cover:hover {
1426
+ background: rgba(0, 0, 0, 0.7);
1427
+ }
1428
+
1429
+ .modal-footer {
1430
+ display: flex;
1431
+ gap: 1rem;
1432
+ padding: 1rem 1.5rem;
1433
+ border-top: 1px solid var(--border-light);
1434
+ }
1435
+
1436
+ .modal-btn {
1437
+ flex: 1;
1438
+ display: flex;
1439
+ align-items: center;
1440
+ justify-content: center;
1441
+ gap: 0.5rem;
1442
+ padding: 0.875rem 1.5rem;
1443
+ font-size: 1rem;
1444
+ font-weight: 600;
1445
+ font-family: inherit;
1446
+ border-radius: 10px;
1447
+ cursor: pointer;
1448
+ transition: var(--transition-fast);
1449
+ }
1450
+
1451
+ .modal-btn.primary {
1452
+ background: var(--primary);
1453
+ color: white;
1454
+ border: none;
1455
+ }
1456
+
1457
+ .modal-btn.primary:hover {
1458
+ background: var(--primary-light);
1459
+ }
1460
+
1461
+ .modal-btn.secondary {
1462
+ background: transparent;
1463
+ color: var(--text-secondary);
1464
+ border: 1px solid var(--border-light);
1465
+ }
1466
+
1467
+ .modal-btn.secondary:hover {
1468
+ background: var(--pastel-green-light);
1469
+ }
1470
+
1471
+ /* Hidden class */
1472
+ .hidden {
1473
+ display: none !important;
1474
+ }
1475
+
1476
+ /* ===== Scrollbar ===== */
1477
+ ::-webkit-scrollbar {
1478
+ width: 8px;
1479
+ height: 8px;
1480
+ }
1481
+
1482
+ ::-webkit-scrollbar-track {
1483
+ background: var(--pastel-green-light);
1484
+ }
1485
+
1486
+ ::-webkit-scrollbar-thumb {
1487
+ background: var(--pastel-green);
1488
+ border-radius: 4px;
1489
+ }
1490
+
1491
+ ::-webkit-scrollbar-thumb:hover {
1492
+ background: var(--primary-light);
1493
+ }
admin.html ADDED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
7
+ <title>Studio Editor | Mubashra</title>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link
11
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=Playfair+Display:ital,wght@0,400;0,700;1,400&display=swap"
12
+ rel="stylesheet">
13
+ <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap"
14
+ rel="stylesheet">
15
+ <link rel="stylesheet" href="admin.css">
16
+ </head>
17
+
18
+ <body>
19
+ <!-- Auth Overlay -->
20
+ <div id="authOverlay" class="auth-overlay">
21
+ <div class="auth-background">
22
+ <div class="blob blob-1"></div>
23
+ <div class="blob blob-2"></div>
24
+ <div class="blob blob-3"></div>
25
+ </div>
26
+ <div class="auth-card">
27
+ <div class="auth-logo">
28
+ <svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
29
+ <path
30
+ d="M42.4379 44C42.4379 44 36.0744 33.9038 41.1692 24C46.8624 12.9336 42.2078 4 42.2078 4L7.01134 4C7.01134 4 11.6577 12.932 5.96912 23.9969C0.876273 33.9029 7.27094 44 7.27094 44L42.4379 44Z"
31
+ fill="currentColor"></path>
32
+ </svg>
33
+ </div>
34
+ <h1 class="auth-title">Welcome Back</h1>
35
+ <p class="auth-subtitle">Enter your password to access the Studio</p>
36
+ <div class="auth-input-group">
37
+ <span class="material-symbols-outlined">lock</span>
38
+ <input type="password" id="passwordInput" placeholder="Enter password">
39
+ </div>
40
+ <button id="loginBtn" class="auth-btn">
41
+ <span>Continue to Studio</span>
42
+ <span class="material-symbols-outlined">arrow_forward</span>
43
+ </button>
44
+ <p id="errorMsg" class="error-msg"></p>
45
+ </div>
46
+ </div>
47
+
48
+ <!-- Admin Workspace -->
49
+ <div id="adminWorkspace" class="admin-workspace hidden">
50
+ <!-- Top Header -->
51
+ <header class="studio-header">
52
+ <div class="header-left">
53
+ <button id="menuToggle" class="menu-toggle">
54
+ <span class="material-symbols-outlined">menu</span>
55
+ </button>
56
+ <div class="logo">
57
+ <svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
58
+ <path
59
+ d="M42.4379 44C42.4379 44 36.0744 33.9038 41.1692 24C46.8624 12.9336 42.2078 4 42.2078 4L7.01134 4C7.01134 4 11.6577 12.932 5.96912 23.9969C0.876273 33.9029 7.27094 44 7.27094 44L42.4379 44Z"
60
+ fill="currentColor"></path>
61
+ </svg>
62
+ <span class="logo-text">Mubashra Studio</span>
63
+ </div>
64
+ </div>
65
+ <div class="header-center">
66
+ <input type="text" id="blogTitle" placeholder="Untitled Blog" class="title-input">
67
+ </div>
68
+ <div class="header-right">
69
+ <!-- Zoom Controls -->
70
+ <div class="zoom-controls">
71
+ <button id="zoomOut" class="zoom-btn" title="Zoom Out">
72
+ <span class="material-symbols-outlined">remove</span>
73
+ </button>
74
+ <span id="zoomLevel" class="zoom-level">100%</span>
75
+ <button id="zoomIn" class="zoom-btn" title="Zoom In">
76
+ <span class="material-symbols-outlined">add</span>
77
+ </button>
78
+ <button id="zoomReset" class="zoom-btn" title="Reset Zoom">
79
+ <span class="material-symbols-outlined">fit_screen</span>
80
+ </button>
81
+ </div>
82
+ <button id="previewBtn" class="header-btn secondary">
83
+ <span class="material-symbols-outlined">visibility</span>
84
+ <span class="btn-text">Preview</span>
85
+ </button>
86
+ <button id="postBtn" class="header-btn primary">
87
+ <span class="material-symbols-outlined">publish</span>
88
+ <span class="btn-text">Publish</span>
89
+ </button>
90
+ <a href="index.html" class="header-btn ghost">
91
+ <span class="material-symbols-outlined">close</span>
92
+ </a>
93
+ </div>
94
+ </header>
95
+
96
+ <!-- Mobile Toolbar -->
97
+ <div class="mobile-toolbar" id="mobileToolbar">
98
+ <button class="mobile-tool-btn" data-type="h1">
99
+ <span class="material-symbols-outlined">title</span>
100
+ </button>
101
+ <button class="mobile-tool-btn" data-type="p">
102
+ <span class="material-symbols-outlined">notes</span>
103
+ </button>
104
+ <button class="mobile-tool-btn" data-type="image">
105
+ <span class="material-symbols-outlined">image</span>
106
+ </button>
107
+ <button class="mobile-tool-btn" data-type="quote">
108
+ <span class="material-symbols-outlined">format_quote</span>
109
+ </button>
110
+ <button class="mobile-tool-btn" id="mobilePropsBtn">
111
+ <span class="material-symbols-outlined">tune</span>
112
+ </button>
113
+ </div>
114
+
115
+ <!-- Main Layout -->
116
+ <div class="studio-layout">
117
+ <!-- Left Sidebar - Add Elements -->
118
+ <aside class="sidebar sidebar-left" id="sidebarLeft">
119
+ <div class="sidebar-header">
120
+ <h3>Elements</h3>
121
+ <button class="close-sidebar" id="closeSidebarLeft">
122
+ <span class="material-symbols-outlined">close</span>
123
+ </button>
124
+ </div>
125
+ <div class="sidebar-section">
126
+ <h3 class="sidebar-title">Add Elements</h3>
127
+ <div class="element-grid">
128
+ <button class="element-btn" data-type="h1">
129
+ <span class="material-symbols-outlined">title</span>
130
+ <span>Heading 1</span>
131
+ </button>
132
+ <button class="element-btn" data-type="h2">
133
+ <span class="material-symbols-outlined">format_h2</span>
134
+ <span>Heading 2</span>
135
+ </button>
136
+ <button class="element-btn" data-type="h3">
137
+ <span class="material-symbols-outlined">format_h3</span>
138
+ <span>Heading 3</span>
139
+ </button>
140
+ <button class="element-btn" data-type="p">
141
+ <span class="material-symbols-outlined">notes</span>
142
+ <span>Paragraph</span>
143
+ </button>
144
+ <button class="element-btn" data-type="image">
145
+ <span class="material-symbols-outlined">image</span>
146
+ <span>Image</span>
147
+ </button>
148
+ <button class="element-btn" data-type="quote">
149
+ <span class="material-symbols-outlined">format_quote</span>
150
+ <span>Quote</span>
151
+ </button>
152
+ <button class="element-btn" data-type="divider">
153
+ <span class="material-symbols-outlined">horizontal_rule</span>
154
+ <span>Divider</span>
155
+ </button>
156
+ <button class="element-btn" data-type="button">
157
+ <span class="material-symbols-outlined">smart_button</span>
158
+ <span>Button</span>
159
+ </button>
160
+ </div>
161
+ </div>
162
+ <div class="sidebar-section">
163
+ <h3 class="sidebar-title">Layers</h3>
164
+ <div id="layersList" class="layers-list">
165
+ <p class="empty-layers">No elements yet</p>
166
+ </div>
167
+ </div>
168
+ </aside>
169
+
170
+ <!-- Sidebar Overlay -->
171
+ <div class="sidebar-overlay" id="sidebarOverlay"></div>
172
+
173
+ <!-- Canvas Area -->
174
+ <main class="canvas-area" id="canvasArea">
175
+ <div class="canvas-wrapper" id="canvasWrapper">
176
+ <div id="blogCanvas" class="blog-canvas">
177
+ <div class="canvas-placeholder" id="canvasPlaceholder">
178
+ <span class="material-symbols-outlined">add_circle</span>
179
+ <p>Click an element from the left sidebar<br>or drag elements here</p>
180
+ </div>
181
+ </div>
182
+ </div>
183
+ </main>
184
+
185
+ <!-- Right Sidebar - Properties -->
186
+ <aside class="sidebar sidebar-right" id="sidebarRight">
187
+ <div class="sidebar-header">
188
+ <h3>Properties</h3>
189
+ <button class="close-sidebar" id="closeSidebarRight">
190
+ <span class="material-symbols-outlined">close</span>
191
+ </button>
192
+ </div>
193
+ <div class="sidebar-section">
194
+ <h3 class="sidebar-title">Properties</h3>
195
+ <div id="propertiesPanel" class="properties-panel">
196
+ <p class="empty-properties">Select an element to edit its properties</p>
197
+ </div>
198
+ </div>
199
+
200
+ <!-- Text Properties -->
201
+ <div id="textProperties" class="sidebar-section hidden">
202
+ <h3 class="sidebar-title">Typography</h3>
203
+
204
+ <div class="property-group">
205
+ <label>Font Family</label>
206
+ <select id="fontFamily" class="property-select">
207
+ <option value="'Inter', sans-serif">Inter</option>
208
+ <option value="'Playfair Display', serif">Playfair Display</option>
209
+ <option value="Georgia, serif">Georgia</option>
210
+ <option value="monospace">Monospace</option>
211
+ </select>
212
+ </div>
213
+
214
+ <div class="property-row">
215
+ <div class="property-group half">
216
+ <label>Size</label>
217
+ <div class="input-with-unit">
218
+ <input type="number" id="fontSize" min="8" max="200" value="16">
219
+ <span>px</span>
220
+ </div>
221
+ </div>
222
+ <div class="property-group half">
223
+ <label>Weight</label>
224
+ <select id="fontWeight" class="property-select">
225
+ <option value="300">Light</option>
226
+ <option value="400">Regular</option>
227
+ <option value="500">Medium</option>
228
+ <option value="600">Semibold</option>
229
+ <option value="700">Bold</option>
230
+ <option value="800">Extra Bold</option>
231
+ <option value="900">Black</option>
232
+ </select>
233
+ </div>
234
+ </div>
235
+
236
+ <div class="property-group">
237
+ <label>Color</label>
238
+ <div class="color-picker-row">
239
+ <input type="color" id="textColor" value="#111418">
240
+ <input type="text" id="textColorHex" value="#111418" class="color-hex-input">
241
+ </div>
242
+ </div>
243
+
244
+ <div class="property-row">
245
+ <div class="property-group half">
246
+ <label>Letter Spacing</label>
247
+ <div class="input-with-unit">
248
+ <input type="number" id="letterSpacing" min="-10" max="50" value="0" step="0.5">
249
+ <span>px</span>
250
+ </div>
251
+ </div>
252
+ <div class="property-group half">
253
+ <label>Line Height</label>
254
+ <div class="input-with-unit">
255
+ <input type="number" id="lineHeight" min="0.5" max="5" value="1.5" step="0.1">
256
+ <span>em</span>
257
+ </div>
258
+ </div>
259
+ </div>
260
+
261
+ <div class="property-group">
262
+ <label>Text Align</label>
263
+ <div class="button-group">
264
+ <button class="icon-btn" data-align="left" title="Align Left">
265
+ <span class="material-symbols-outlined">format_align_left</span>
266
+ </button>
267
+ <button class="icon-btn" data-align="center" title="Align Center">
268
+ <span class="material-symbols-outlined">format_align_center</span>
269
+ </button>
270
+ <button class="icon-btn" data-align="right" title="Align Right">
271
+ <span class="material-symbols-outlined">format_align_right</span>
272
+ </button>
273
+ <button class="icon-btn" data-align="justify" title="Justify">
274
+ <span class="material-symbols-outlined">format_align_justify</span>
275
+ </button>
276
+ </div>
277
+ </div>
278
+ </div>
279
+
280
+ <!-- Image Properties -->
281
+ <div id="imageProperties" class="sidebar-section hidden">
282
+ <h3 class="sidebar-title">Image Settings</h3>
283
+
284
+ <div class="property-group">
285
+ <label>Replace Image</label>
286
+ <label class="upload-btn">
287
+ <span class="material-symbols-outlined">upload</span>
288
+ <span>Upload New Image</span>
289
+ <input type="file" id="replaceImage" accept="image/*" hidden>
290
+ </label>
291
+ </div>
292
+
293
+ <div class="property-group">
294
+ <label>Border Radius</label>
295
+ <div class="slider-row">
296
+ <input type="range" id="imageBorderRadius" min="0" max="50" value="0">
297
+ <span id="borderRadiusValue">0px</span>
298
+ </div>
299
+ </div>
300
+
301
+ <div class="property-group">
302
+ <label>Opacity</label>
303
+ <div class="slider-row">
304
+ <input type="range" id="imageOpacity" min="0" max="100" value="100">
305
+ <span id="opacityValue">100%</span>
306
+ </div>
307
+ </div>
308
+ </div>
309
+
310
+ <!-- Position & Size -->
311
+ <div id="positionProperties" class="sidebar-section hidden">
312
+ <h3 class="sidebar-title">Position & Size</h3>
313
+
314
+ <div class="property-row">
315
+ <div class="property-group half">
316
+ <label>X Position</label>
317
+ <div class="input-with-unit">
318
+ <input type="number" id="posX" value="0">
319
+ <span>px</span>
320
+ </div>
321
+ </div>
322
+ <div class="property-group half">
323
+ <label>Y Position</label>
324
+ <div class="input-with-unit">
325
+ <input type="number" id="posY" value="0">
326
+ <span>px</span>
327
+ </div>
328
+ </div>
329
+ </div>
330
+
331
+ <div class="property-row">
332
+ <div class="property-group half">
333
+ <label>Width</label>
334
+ <div class="input-with-unit">
335
+ <input type="number" id="elWidth" min="20">
336
+ <span>px</span>
337
+ </div>
338
+ </div>
339
+ <div class="property-group half">
340
+ <label>Height</label>
341
+ <div class="input-with-unit">
342
+ <input type="number" id="elHeight" min="20">
343
+ <span>px</span>
344
+ </div>
345
+ </div>
346
+ </div>
347
+
348
+ <div class="property-group">
349
+ <label>Rotation</label>
350
+ <div class="slider-row">
351
+ <input type="range" id="elRotation" min="0" max="360" value="0">
352
+ <span id="rotationValue">0°</span>
353
+ </div>
354
+ </div>
355
+
356
+ <div class="property-divider"></div>
357
+
358
+ <button id="deleteElement" class="delete-btn">
359
+ <span class="material-symbols-outlined">delete</span>
360
+ <span>Delete Element</span>
361
+ </button>
362
+ </div>
363
+ </aside>
364
+ </div>
365
+ </div>
366
+
367
+ <!-- Publish Modal -->
368
+ <div id="publishModal" class="modal hidden">
369
+ <div class="modal-backdrop"></div>
370
+ <div class="modal-content">
371
+ <div class="modal-header">
372
+ <h2>Publish Your Blog</h2>
373
+ <button class="modal-close" id="closeModal">
374
+ <span class="material-symbols-outlined">close</span>
375
+ </button>
376
+ </div>
377
+ <div class="modal-body">
378
+ <div class="form-group">
379
+ <label>Blog Title</label>
380
+ <input type="text" id="modalBlogTitle" placeholder="Enter blog title">
381
+ </div>
382
+ <div class="form-group">
383
+ <label>Cover Image (Optional)</label>
384
+ <div class="cover-upload-area" id="coverUploadArea">
385
+ <input type="file" id="coverImageInput" accept="image/*" hidden>
386
+ <div class="upload-placeholder" id="uploadPlaceholder">
387
+ <span class="material-symbols-outlined">add_photo_alternate</span>
388
+ <p>Click to upload cover image</p>
389
+ <span class="upload-hint">Recommended: 1200x630px</span>
390
+ </div>
391
+ <div class="upload-preview hidden" id="uploadPreview">
392
+ <img id="coverPreviewImg" src="" alt="Cover Preview">
393
+ <button class="remove-cover" id="removeCover">
394
+ <span class="material-symbols-outlined">close</span>
395
+ </button>
396
+ </div>
397
+ </div>
398
+ </div>
399
+ </div>
400
+ <div class="modal-footer">
401
+ <button class="modal-btn secondary" id="cancelPublish">Cancel</button>
402
+ <button class="modal-btn primary" id="confirmPublish">
403
+ <span class="material-symbols-outlined">publish</span>
404
+ Publish Now
405
+ </button>
406
+ </div>
407
+ </div>
408
+ </div>
409
+
410
+ <!-- Hidden file input -->
411
+ <input type="file" id="imageUpload" accept="image/*" hidden>
412
+
413
+ <script src="admin.js"></script>
414
+ </body>
415
+
416
+ </html>
admin.js ADDED
@@ -0,0 +1,1055 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // ===== Mubashra Studio - Advanced Drag & Drop Editor =====
2
+
3
+ const CORRECT_PASSWORD = "inshaaAllah";
4
+
5
+ // DOM Elements
6
+ const authOverlay = document.getElementById('authOverlay');
7
+ const adminWorkspace = document.getElementById('adminWorkspace');
8
+ const passwordInput = document.getElementById('passwordInput');
9
+ const loginBtn = document.getElementById('loginBtn');
10
+ const errorMsg = document.getElementById('errorMsg');
11
+ const blogCanvas = document.getElementById('blogCanvas');
12
+ const canvasWrapper = document.getElementById('canvasWrapper');
13
+ const canvasArea = document.getElementById('canvasArea');
14
+ const canvasPlaceholder = document.getElementById('canvasPlaceholder');
15
+ const blogTitleInput = document.getElementById('blogTitle');
16
+ const postBtn = document.getElementById('postBtn');
17
+ const previewBtn = document.getElementById('previewBtn');
18
+
19
+ // Sidebars
20
+ const sidebarLeft = document.getElementById('sidebarLeft');
21
+ const sidebarRight = document.getElementById('sidebarRight');
22
+ const sidebarOverlay = document.getElementById('sidebarOverlay');
23
+ const menuToggle = document.getElementById('menuToggle');
24
+ const closeSidebarLeft = document.getElementById('closeSidebarLeft');
25
+ const closeSidebarRight = document.getElementById('closeSidebarRight');
26
+ const mobilePropsBtn = document.getElementById('mobilePropsBtn');
27
+
28
+ // Zoom Controls
29
+ const zoomIn = document.getElementById('zoomIn');
30
+ const zoomOut = document.getElementById('zoomOut');
31
+ const zoomReset = document.getElementById('zoomReset');
32
+ const zoomLevelDisplay = document.getElementById('zoomLevel');
33
+
34
+ // Modal Elements
35
+ const publishModal = document.getElementById('publishModal');
36
+ const closeModal = document.getElementById('closeModal');
37
+ const cancelPublish = document.getElementById('cancelPublish');
38
+ const confirmPublish = document.getElementById('confirmPublish');
39
+ const modalBlogTitle = document.getElementById('modalBlogTitle');
40
+ const coverUploadArea = document.getElementById('coverUploadArea');
41
+ const coverImageInput = document.getElementById('coverImageInput');
42
+ const uploadPlaceholder = document.getElementById('uploadPlaceholder');
43
+ const uploadPreview = document.getElementById('uploadPreview');
44
+ const coverPreviewImg = document.getElementById('coverPreviewImg');
45
+ const removeCover = document.getElementById('removeCover');
46
+
47
+ // Element buttons (both sidebar and mobile)
48
+ const elementBtns = document.querySelectorAll('.element-btn');
49
+ const mobileToolBtns = document.querySelectorAll('.mobile-tool-btn[data-type]');
50
+ const layersList = document.getElementById('layersList');
51
+ const propertiesPanel = document.getElementById('propertiesPanel');
52
+
53
+ // Property Panels
54
+ const textProperties = document.getElementById('textProperties');
55
+ const imageProperties = document.getElementById('imageProperties');
56
+ const positionProperties = document.getElementById('positionProperties');
57
+
58
+ // Property Inputs
59
+ const fontFamily = document.getElementById('fontFamily');
60
+ const fontSize = document.getElementById('fontSize');
61
+ const fontWeight = document.getElementById('fontWeight');
62
+ const textColor = document.getElementById('textColor');
63
+ const textColorHex = document.getElementById('textColorHex');
64
+ const letterSpacing = document.getElementById('letterSpacing');
65
+ const lineHeight = document.getElementById('lineHeight');
66
+ const posX = document.getElementById('posX');
67
+ const posY = document.getElementById('posY');
68
+ const elWidth = document.getElementById('elWidth');
69
+ const elHeight = document.getElementById('elHeight');
70
+ const elRotation = document.getElementById('elRotation');
71
+ const rotationValue = document.getElementById('rotationValue');
72
+ const deleteElement = document.getElementById('deleteElement');
73
+
74
+ // Image Properties
75
+ const replaceImage = document.getElementById('replaceImage');
76
+ const imageBorderRadius = document.getElementById('imageBorderRadius');
77
+ const borderRadiusValue = document.getElementById('borderRadiusValue');
78
+ const imageOpacity = document.getElementById('imageOpacity');
79
+ const opacityValue = document.getElementById('opacityValue');
80
+
81
+ // Image Upload Input
82
+ const imageUpload = document.getElementById('imageUpload');
83
+
84
+ // State
85
+ let selectedElement = null;
86
+ let isDragging = false;
87
+ let isResizing = false;
88
+ let resizeDirection = '';
89
+ let dragStartX = 0;
90
+ let dragStartY = 0;
91
+ let initialX = 0;
92
+ let initialY = 0;
93
+ let initialWidth = 0;
94
+ let initialHeight = 0;
95
+ let elementCounter = 0;
96
+ let currentZoom = 1;
97
+ let coverImageData = null;
98
+ const ZOOM_STEP = 0.1;
99
+ const MIN_ZOOM = 0.25;
100
+ const MAX_ZOOM = 2;
101
+
102
+ // ===== Authentication =====
103
+ loginBtn.addEventListener('click', checkPassword);
104
+ passwordInput.addEventListener('keypress', (e) => {
105
+ if (e.key === 'Enter') checkPassword();
106
+ });
107
+
108
+ function checkPassword() {
109
+ if (passwordInput.value === CORRECT_PASSWORD) {
110
+ authOverlay.classList.add('hidden');
111
+ adminWorkspace.classList.remove('hidden');
112
+ } else {
113
+ errorMsg.textContent = "Incorrect password. Please try again.";
114
+ passwordInput.value = "";
115
+ passwordInput.focus();
116
+ }
117
+ }
118
+
119
+ // ===== Mobile Sidebar Controls =====
120
+ menuToggle?.addEventListener('click', () => {
121
+ sidebarLeft.classList.add('open');
122
+ sidebarOverlay.classList.add('visible');
123
+ });
124
+
125
+ closeSidebarLeft?.addEventListener('click', closeSidebars);
126
+ closeSidebarRight?.addEventListener('click', closeSidebars);
127
+ sidebarOverlay?.addEventListener('click', closeSidebars);
128
+
129
+ mobilePropsBtn?.addEventListener('click', () => {
130
+ sidebarRight.classList.add('open');
131
+ sidebarOverlay.classList.add('visible');
132
+ });
133
+
134
+ function closeSidebars() {
135
+ sidebarLeft.classList.remove('open');
136
+ sidebarRight.classList.remove('open');
137
+ sidebarOverlay.classList.remove('visible');
138
+ }
139
+
140
+ // ===== Zoom Controls =====
141
+ zoomIn?.addEventListener('click', () => {
142
+ if (currentZoom < MAX_ZOOM) {
143
+ currentZoom = Math.min(currentZoom + ZOOM_STEP, MAX_ZOOM);
144
+ applyZoom();
145
+ }
146
+ });
147
+
148
+ zoomOut?.addEventListener('click', () => {
149
+ if (currentZoom > MIN_ZOOM) {
150
+ currentZoom = Math.max(currentZoom - ZOOM_STEP, MIN_ZOOM);
151
+ applyZoom();
152
+ }
153
+ });
154
+
155
+ zoomReset?.addEventListener('click', () => {
156
+ currentZoom = 1;
157
+ applyZoom();
158
+ });
159
+
160
+ function applyZoom() {
161
+ canvasWrapper.style.transform = `scale(${currentZoom})`;
162
+ if (zoomLevelDisplay) {
163
+ zoomLevelDisplay.textContent = `${Math.round(currentZoom * 100)}%`;
164
+ }
165
+ }
166
+
167
+ // Mouse wheel zoom
168
+ canvasArea?.addEventListener('wheel', (e) => {
169
+ if (e.ctrlKey) {
170
+ e.preventDefault();
171
+ if (e.deltaY < 0 && currentZoom < MAX_ZOOM) {
172
+ currentZoom = Math.min(currentZoom + ZOOM_STEP, MAX_ZOOM);
173
+ } else if (e.deltaY > 0 && currentZoom > MIN_ZOOM) {
174
+ currentZoom = Math.max(currentZoom - ZOOM_STEP, MIN_ZOOM);
175
+ }
176
+ applyZoom();
177
+ }
178
+ }, { passive: false });
179
+
180
+ // ===== Element Creation =====
181
+ elementBtns.forEach(btn => {
182
+ btn.addEventListener('click', () => {
183
+ const type = btn.dataset.type;
184
+ createElement(type);
185
+ closeSidebars();
186
+ });
187
+ });
188
+
189
+ mobileToolBtns.forEach(btn => {
190
+ btn.addEventListener('click', () => {
191
+ const type = btn.dataset.type;
192
+ if (type) createElement(type);
193
+ });
194
+ });
195
+
196
+ function createElement(type, x = 50, y = 50) {
197
+ elementCounter++;
198
+
199
+ const element = document.createElement('div');
200
+ element.classList.add('draggable-element');
201
+ element.id = `element-${elementCounter}`;
202
+ element.dataset.type = type;
203
+ element.style.left = `${x}px`;
204
+ element.style.top = `${y}px`;
205
+
206
+ // Create resize handles
207
+ const handles = ['nw', 'ne', 'sw', 'se', 'n', 's', 'e', 'w'];
208
+ handles.forEach(dir => {
209
+ const handle = document.createElement('div');
210
+ handle.classList.add('resize-handle', dir);
211
+ handle.dataset.direction = dir;
212
+ element.appendChild(handle);
213
+ });
214
+
215
+ // Create content based on type
216
+ const content = document.createElement('div');
217
+ content.classList.add('element-content');
218
+
219
+ switch (type) {
220
+ case 'h1':
221
+ content.innerHTML = '<h1 contenteditable="true">Heading 1</h1>';
222
+ element.style.width = '300px';
223
+ element.style.minHeight = '60px';
224
+ break;
225
+ case 'h2':
226
+ content.innerHTML = '<h2 contenteditable="true">Heading 2</h2>';
227
+ element.style.width = '280px';
228
+ element.style.minHeight = '50px';
229
+ break;
230
+ case 'h3':
231
+ content.innerHTML = '<h3 contenteditable="true">Heading 3</h3>';
232
+ element.style.width = '250px';
233
+ element.style.minHeight = '40px';
234
+ break;
235
+ case 'p':
236
+ content.innerHTML = '<p contenteditable="true">Enter your paragraph text here. You can type anything you want.</p>';
237
+ element.style.width = '350px';
238
+ element.style.minHeight = '80px';
239
+ break;
240
+ case 'image':
241
+ // Trigger file upload
242
+ const uploadHandler = (e) => {
243
+ const file = e.target.files[0];
244
+ if (file) {
245
+ const reader = new FileReader();
246
+ reader.onload = (event) => {
247
+ content.innerHTML = `<img src="${event.target.result}" alt="Uploaded Image" draggable="false">`;
248
+ element.style.width = '300px';
249
+ element.style.height = '200px';
250
+ element.appendChild(content);
251
+ blogCanvas.appendChild(element);
252
+ setupElementEvents(element);
253
+ selectElement(element);
254
+ updateLayersList();
255
+ hidePlaceholder();
256
+ };
257
+ reader.readAsDataURL(file);
258
+ }
259
+ imageUpload.value = '';
260
+ imageUpload.removeEventListener('change', uploadHandler);
261
+ };
262
+ imageUpload.addEventListener('change', uploadHandler);
263
+ imageUpload.click();
264
+ return;
265
+ case 'quote':
266
+ content.innerHTML = '<blockquote contenteditable="true">"Add your inspiring quote here." - Author</blockquote>';
267
+ element.style.width = '350px';
268
+ element.style.minHeight = '100px';
269
+ break;
270
+ case 'divider':
271
+ content.innerHTML = '<div class="element-divider"></div>';
272
+ element.style.width = '300px';
273
+ element.style.height = '30px';
274
+ break;
275
+ case 'button':
276
+ content.innerHTML = '<span class="element-button" contenteditable="true">Click Me</span>';
277
+ element.style.width = '120px';
278
+ element.style.height = '50px';
279
+ break;
280
+ }
281
+
282
+ element.appendChild(content);
283
+ blogCanvas.appendChild(element);
284
+
285
+ setupElementEvents(element);
286
+ selectElement(element);
287
+ updateLayersList();
288
+ hidePlaceholder();
289
+ }
290
+
291
+ function setupElementEvents(element) {
292
+ const type = element.dataset.type;
293
+
294
+ // Helper function to get pointer position
295
+ const getPointerPos = (e) => {
296
+ if (e.touches && e.touches.length > 0) {
297
+ return { x: e.touches[0].clientX, y: e.touches[0].clientY };
298
+ }
299
+ return { x: e.clientX, y: e.clientY };
300
+ };
301
+
302
+ // Mouse/Touch down for dragging
303
+ const handlePointerDown = (e) => {
304
+ // Check if it's a resize handle
305
+ if (e.target.classList.contains('resize-handle')) {
306
+ startResize(e);
307
+ return;
308
+ }
309
+
310
+ selectElement(element);
311
+
312
+ // For text elements, check if we should allow editing
313
+ const editableEl = e.target.closest('[contenteditable="true"]');
314
+ if (editableEl && document.activeElement === editableEl) {
315
+ return; // Allow text editing
316
+ }
317
+
318
+ // Start dragging
319
+ startDrag(e, element);
320
+ };
321
+
322
+ element.addEventListener('mousedown', handlePointerDown);
323
+ element.addEventListener('touchstart', handlePointerDown, { passive: false });
324
+
325
+ // Double click/tap to edit text
326
+ element.addEventListener('dblclick', () => {
327
+ const editable = element.querySelector('[contenteditable="true"]');
328
+ if (editable) {
329
+ editable.focus();
330
+ const selection = window.getSelection();
331
+ const range = document.createRange();
332
+ range.selectNodeContents(editable);
333
+ selection.removeAllRanges();
334
+ selection.addRange(range);
335
+ }
336
+ });
337
+
338
+ // Resize handles - both mouse and touch
339
+ const handles = element.querySelectorAll('.resize-handle');
340
+ handles.forEach(handle => {
341
+ handle.addEventListener('mousedown', startResize);
342
+ handle.addEventListener('touchstart', startResize, { passive: false });
343
+ });
344
+
345
+ // Update layers on text input
346
+ const editables = element.querySelectorAll('[contenteditable="true"]');
347
+ editables.forEach(ed => {
348
+ ed.addEventListener('input', () => {
349
+ updateLayersList();
350
+ });
351
+ });
352
+ }
353
+
354
+ // ===== Drag Functionality =====
355
+ function startDrag(e, element) {
356
+ if (isResizing) return;
357
+
358
+ e.preventDefault();
359
+ isDragging = true;
360
+ selectedElement = element;
361
+ element.classList.add('dragging');
362
+
363
+ const pos = getEventPos(e);
364
+ dragStartX = pos.x;
365
+ dragStartY = pos.y;
366
+ initialX = element.offsetLeft;
367
+ initialY = element.offsetTop;
368
+
369
+ document.addEventListener('mousemove', drag);
370
+ document.addEventListener('mouseup', stopDrag);
371
+ document.addEventListener('touchmove', drag, { passive: false });
372
+ document.addEventListener('touchend', stopDrag);
373
+ }
374
+
375
+ function drag(e) {
376
+ if (!isDragging || !selectedElement) return;
377
+ e.preventDefault();
378
+
379
+ const pos = getEventPos(e);
380
+ const dx = (pos.x - dragStartX) / currentZoom;
381
+ const dy = (pos.y - dragStartY) / currentZoom;
382
+
383
+ let newX = initialX + dx;
384
+ let newY = initialY + dy;
385
+
386
+ // Keep element within canvas bounds
387
+ newX = Math.max(0, newX);
388
+ newY = Math.max(0, newY);
389
+
390
+ selectedElement.style.left = `${newX}px`;
391
+ selectedElement.style.top = `${newY}px`;
392
+
393
+ // Update position inputs
394
+ if (posX) posX.value = Math.round(newX);
395
+ if (posY) posY.value = Math.round(newY);
396
+ }
397
+
398
+ function stopDrag() {
399
+ if (selectedElement) {
400
+ selectedElement.classList.remove('dragging');
401
+ }
402
+ isDragging = false;
403
+ document.removeEventListener('mousemove', drag);
404
+ document.removeEventListener('mouseup', stopDrag);
405
+ document.removeEventListener('touchmove', drag);
406
+ document.removeEventListener('touchend', stopDrag);
407
+ }
408
+
409
+ // ===== Resize Functionality =====
410
+ function startResize(e) {
411
+ e.stopPropagation();
412
+ e.preventDefault();
413
+
414
+ isResizing = true;
415
+ resizeDirection = e.target.dataset.direction;
416
+
417
+ const element = e.target.closest('.draggable-element');
418
+ selectedElement = element;
419
+
420
+ const pos = getEventPos(e);
421
+ dragStartX = pos.x;
422
+ dragStartY = pos.y;
423
+ initialX = element.offsetLeft;
424
+ initialY = element.offsetTop;
425
+ initialWidth = element.offsetWidth;
426
+ initialHeight = element.offsetHeight;
427
+
428
+ document.addEventListener('mousemove', resize);
429
+ document.addEventListener('mouseup', stopResize);
430
+ document.addEventListener('touchmove', resize, { passive: false });
431
+ document.addEventListener('touchend', stopResize);
432
+ }
433
+
434
+ function resize(e) {
435
+ if (!isResizing || !selectedElement) return;
436
+ e.preventDefault();
437
+
438
+ const pos = getEventPos(e);
439
+ const dx = (pos.x - dragStartX) / currentZoom;
440
+ const dy = (pos.y - dragStartY) / currentZoom;
441
+
442
+ let newWidth = initialWidth;
443
+ let newHeight = initialHeight;
444
+ let newX = initialX;
445
+ let newY = initialY;
446
+
447
+ if (resizeDirection.includes('e')) {
448
+ newWidth = Math.max(50, initialWidth + dx);
449
+ }
450
+ if (resizeDirection.includes('w')) {
451
+ newWidth = Math.max(50, initialWidth - dx);
452
+ newX = initialX + (initialWidth - newWidth);
453
+ }
454
+ if (resizeDirection.includes('s')) {
455
+ newHeight = Math.max(30, initialHeight + dy);
456
+ }
457
+ if (resizeDirection.includes('n')) {
458
+ newHeight = Math.max(30, initialHeight - dy);
459
+ newY = initialY + (initialHeight - newHeight);
460
+ }
461
+
462
+ selectedElement.style.width = `${newWidth}px`;
463
+ selectedElement.style.height = `${newHeight}px`;
464
+ selectedElement.style.left = `${newX}px`;
465
+ selectedElement.style.top = `${newY}px`;
466
+
467
+ if (elWidth) elWidth.value = Math.round(newWidth);
468
+ if (elHeight) elHeight.value = Math.round(newHeight);
469
+ if (posX) posX.value = Math.round(newX);
470
+ if (posY) posY.value = Math.round(newY);
471
+ }
472
+
473
+ function stopResize() {
474
+ isResizing = false;
475
+ resizeDirection = '';
476
+ document.removeEventListener('mousemove', resize);
477
+ document.removeEventListener('mouseup', stopResize);
478
+ document.removeEventListener('touchmove', resize);
479
+ document.removeEventListener('touchend', stopResize);
480
+ }
481
+
482
+ // Helper to get event position for both mouse and touch
483
+ function getEventPos(e) {
484
+ if (e.touches && e.touches.length > 0) {
485
+ return { x: e.touches[0].clientX, y: e.touches[0].clientY };
486
+ }
487
+ return { x: e.clientX, y: e.clientY };
488
+ }
489
+
490
+ // ===== Selection =====
491
+ function selectElement(element) {
492
+ if (selectedElement && selectedElement !== element) {
493
+ selectedElement.classList.remove('selected');
494
+ }
495
+
496
+ selectedElement = element;
497
+ element.classList.add('selected');
498
+ showPropertiesFor(element);
499
+ updateLayersList();
500
+ }
501
+
502
+ function deselectAll() {
503
+ if (selectedElement) {
504
+ selectedElement.classList.remove('selected');
505
+ selectedElement = null;
506
+ }
507
+ hideAllPropertyPanels();
508
+ }
509
+
510
+ blogCanvas.addEventListener('click', (e) => {
511
+ if (e.target === blogCanvas || e.target === canvasPlaceholder) {
512
+ deselectAll();
513
+ }
514
+ });
515
+
516
+ // ===== Properties Panel =====
517
+ function showPropertiesFor(element) {
518
+ const type = element.dataset.type;
519
+
520
+ hideAllPropertyPanels();
521
+
522
+ if (positionProperties) positionProperties.classList.remove('hidden');
523
+
524
+ if (posX) posX.value = Math.round(element.offsetLeft);
525
+ if (posY) posY.value = Math.round(element.offsetTop);
526
+ if (elWidth) elWidth.value = Math.round(element.offsetWidth);
527
+ if (elHeight) elHeight.value = Math.round(element.offsetHeight);
528
+
529
+ const transform = element.style.transform;
530
+ const rotateMatch = transform.match(/rotate\((\d+)deg\)/);
531
+ if (elRotation) elRotation.value = rotateMatch ? parseInt(rotateMatch[1]) : 0;
532
+ if (rotationValue) rotationValue.textContent = `${elRotation?.value || 0}°`;
533
+
534
+ if (['h1', 'h2', 'h3', 'p', 'quote', 'button'].includes(type)) {
535
+ if (textProperties) textProperties.classList.remove('hidden');
536
+
537
+ const editable = element.querySelector('[contenteditable="true"]') ||
538
+ element.querySelector('.element-button');
539
+
540
+ if (editable) {
541
+ const style = window.getComputedStyle(editable);
542
+
543
+ if (fontSize) fontSize.value = parseInt(style.fontSize);
544
+ if (fontWeight) fontWeight.value = style.fontWeight;
545
+
546
+ const color = rgbToHex(style.color);
547
+ if (textColor) textColor.value = color;
548
+ if (textColorHex) textColorHex.value = color;
549
+
550
+ const ls = parseFloat(style.letterSpacing);
551
+ if (letterSpacing) letterSpacing.value = isNaN(ls) ? 0 : ls;
552
+
553
+ const lh = parseFloat(style.lineHeight) / parseFloat(style.fontSize);
554
+ if (lineHeight) lineHeight.value = isNaN(lh) ? 1.5 : lh.toFixed(1);
555
+ }
556
+ } else if (type === 'image') {
557
+ if (imageProperties) imageProperties.classList.remove('hidden');
558
+
559
+ const br = parseInt(element.style.borderRadius) || 0;
560
+ if (imageBorderRadius) imageBorderRadius.value = br;
561
+ if (borderRadiusValue) borderRadiusValue.textContent = `${br}px`;
562
+
563
+ const op = parseFloat(element.style.opacity);
564
+ const opacityPercent = isNaN(op) ? 100 : op * 100;
565
+ if (imageOpacity) imageOpacity.value = opacityPercent;
566
+ if (opacityValue) opacityValue.textContent = `${Math.round(opacityPercent)}%`;
567
+ }
568
+
569
+ if (propertiesPanel) {
570
+ const emptyMsg = propertiesPanel.querySelector('.empty-properties');
571
+ if (emptyMsg) emptyMsg.style.display = 'none';
572
+ }
573
+ }
574
+
575
+ function hideAllPropertyPanels() {
576
+ if (textProperties) textProperties.classList.add('hidden');
577
+ if (imageProperties) imageProperties.classList.add('hidden');
578
+ if (positionProperties) positionProperties.classList.add('hidden');
579
+ if (propertiesPanel) {
580
+ const emptyMsg = propertiesPanel.querySelector('.empty-properties');
581
+ if (emptyMsg) emptyMsg.style.display = 'block';
582
+ }
583
+ }
584
+
585
+ // ===== Property Change Handlers =====
586
+ fontFamily?.addEventListener('change', () => {
587
+ if (!selectedElement) return;
588
+ const editable = getEditableElement();
589
+ if (editable) editable.style.fontFamily = fontFamily.value;
590
+ });
591
+
592
+ fontSize?.addEventListener('input', () => {
593
+ if (!selectedElement) return;
594
+ const editable = getEditableElement();
595
+ if (editable) editable.style.fontSize = `${fontSize.value}px`;
596
+ });
597
+
598
+ fontWeight?.addEventListener('change', () => {
599
+ if (!selectedElement) return;
600
+ const editable = getEditableElement();
601
+ if (editable) editable.style.fontWeight = fontWeight.value;
602
+ });
603
+
604
+ textColor?.addEventListener('input', () => {
605
+ if (!selectedElement) return;
606
+ const editable = getEditableElement();
607
+ if (editable) editable.style.color = textColor.value;
608
+ if (textColorHex) textColorHex.value = textColor.value;
609
+ });
610
+
611
+ textColorHex?.addEventListener('input', () => {
612
+ if (!selectedElement) return;
613
+ const hex = textColorHex.value;
614
+ if (/^#[0-9A-Fa-f]{6}$/.test(hex)) {
615
+ if (textColor) textColor.value = hex;
616
+ const editable = getEditableElement();
617
+ if (editable) editable.style.color = hex;
618
+ }
619
+ });
620
+
621
+ letterSpacing?.addEventListener('input', () => {
622
+ if (!selectedElement) return;
623
+ const editable = getEditableElement();
624
+ if (editable) editable.style.letterSpacing = `${letterSpacing.value}px`;
625
+ });
626
+
627
+ lineHeight?.addEventListener('input', () => {
628
+ if (!selectedElement) return;
629
+ const editable = getEditableElement();
630
+ if (editable) editable.style.lineHeight = lineHeight.value;
631
+ });
632
+
633
+ document.querySelectorAll('[data-align]').forEach(btn => {
634
+ btn.addEventListener('click', () => {
635
+ if (!selectedElement) return;
636
+ const editable = getEditableElement();
637
+ if (editable) editable.style.textAlign = btn.dataset.align;
638
+
639
+ document.querySelectorAll('[data-align]').forEach(b => b.classList.remove('active'));
640
+ btn.classList.add('active');
641
+ });
642
+ });
643
+
644
+ posX?.addEventListener('input', () => {
645
+ if (selectedElement) selectedElement.style.left = `${posX.value}px`;
646
+ });
647
+
648
+ posY?.addEventListener('input', () => {
649
+ if (selectedElement) selectedElement.style.top = `${posY.value}px`;
650
+ });
651
+
652
+ elWidth?.addEventListener('input', () => {
653
+ if (selectedElement) selectedElement.style.width = `${elWidth.value}px`;
654
+ });
655
+
656
+ elHeight?.addEventListener('input', () => {
657
+ if (selectedElement) selectedElement.style.height = `${elHeight.value}px`;
658
+ });
659
+
660
+ elRotation?.addEventListener('input', () => {
661
+ if (selectedElement) {
662
+ selectedElement.style.transform = `rotate(${elRotation.value}deg)`;
663
+ if (rotationValue) rotationValue.textContent = `${elRotation.value}°`;
664
+ }
665
+ });
666
+
667
+ imageBorderRadius?.addEventListener('input', () => {
668
+ if (selectedElement) {
669
+ selectedElement.style.borderRadius = `${imageBorderRadius.value}px`;
670
+ selectedElement.style.overflow = 'hidden';
671
+ if (borderRadiusValue) borderRadiusValue.textContent = `${imageBorderRadius.value}px`;
672
+ }
673
+ });
674
+
675
+ imageOpacity?.addEventListener('input', () => {
676
+ if (selectedElement) {
677
+ selectedElement.style.opacity = imageOpacity.value / 100;
678
+ if (opacityValue) opacityValue.textContent = `${imageOpacity.value}%`;
679
+ }
680
+ });
681
+
682
+ replaceImage?.addEventListener('change', (e) => {
683
+ if (!selectedElement || selectedElement.dataset.type !== 'image') return;
684
+
685
+ const file = e.target.files[0];
686
+ if (file) {
687
+ const reader = new FileReader();
688
+ reader.onload = (event) => {
689
+ const img = selectedElement.querySelector('img');
690
+ if (img) img.src = event.target.result;
691
+ };
692
+ reader.readAsDataURL(file);
693
+ }
694
+ replaceImage.value = '';
695
+ });
696
+
697
+ deleteElement?.addEventListener('click', () => {
698
+ if (selectedElement) {
699
+ selectedElement.remove();
700
+ selectedElement = null;
701
+ hideAllPropertyPanels();
702
+ updateLayersList();
703
+ checkPlaceholder();
704
+ }
705
+ });
706
+
707
+ // ===== Layers List =====
708
+ function updateLayersList() {
709
+ const elements = blogCanvas.querySelectorAll('.draggable-element');
710
+
711
+ if (elements.length === 0) {
712
+ layersList.innerHTML = '<p class="empty-layers">No elements yet</p>';
713
+ return;
714
+ }
715
+
716
+ layersList.innerHTML = '';
717
+
718
+ elements.forEach((el) => {
719
+ const type = el.dataset.type;
720
+ const icon = getIconForType(type);
721
+ const label = getLabelForElement(el, type);
722
+
723
+ const layerItem = document.createElement('div');
724
+ layerItem.classList.add('layer-item');
725
+ if (el === selectedElement) {
726
+ layerItem.classList.add('active');
727
+ }
728
+
729
+ layerItem.innerHTML = `
730
+ <span class="material-symbols-outlined">${icon}</span>
731
+ <span>${label}</span>
732
+ `;
733
+
734
+ layerItem.addEventListener('click', () => {
735
+ selectElement(el);
736
+ closeSidebars();
737
+ });
738
+
739
+ layersList.appendChild(layerItem);
740
+ });
741
+ }
742
+
743
+ function getIconForType(type) {
744
+ const icons = {
745
+ 'h1': 'title', 'h2': 'format_h2', 'h3': 'format_h3',
746
+ 'p': 'notes', 'image': 'image', 'quote': 'format_quote',
747
+ 'divider': 'horizontal_rule', 'button': 'smart_button'
748
+ };
749
+ return icons[type] || 'crop_square';
750
+ }
751
+
752
+ function getLabelForElement(el, type) {
753
+ const labels = {
754
+ 'h1': 'Heading 1', 'h2': 'Heading 2', 'h3': 'Heading 3',
755
+ 'p': 'Paragraph', 'image': 'Image', 'quote': 'Quote',
756
+ 'divider': 'Divider', 'button': 'Button'
757
+ };
758
+
759
+ const editable = el.querySelector('[contenteditable="true"]');
760
+ if (editable) {
761
+ const text = editable.textContent.trim();
762
+ if (text.length > 15) return text.substring(0, 15) + '...';
763
+ return text || labels[type];
764
+ }
765
+
766
+ return labels[type] || 'Element';
767
+ }
768
+
769
+ // ===== Helper Functions =====
770
+ function getEditableElement() {
771
+ if (!selectedElement) return null;
772
+ return selectedElement.querySelector('[contenteditable="true"]') ||
773
+ selectedElement.querySelector('.element-button') ||
774
+ selectedElement.querySelector('blockquote');
775
+ }
776
+
777
+ function rgbToHex(rgb) {
778
+ if (!rgb) return '#000000';
779
+ if (rgb.startsWith('#')) return rgb;
780
+
781
+ const match = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
782
+ if (!match) return '#000000';
783
+
784
+ const r = parseInt(match[1]).toString(16).padStart(2, '0');
785
+ const g = parseInt(match[2]).toString(16).padStart(2, '0');
786
+ const b = parseInt(match[3]).toString(16).padStart(2, '0');
787
+
788
+ return `#${r}${g}${b}`;
789
+ }
790
+
791
+ function hidePlaceholder() {
792
+ if (canvasPlaceholder) canvasPlaceholder.classList.add('hidden');
793
+ }
794
+
795
+ function checkPlaceholder() {
796
+ const elements = blogCanvas.querySelectorAll('.draggable-element');
797
+ if (canvasPlaceholder) {
798
+ canvasPlaceholder.classList.toggle('hidden', elements.length > 0);
799
+ }
800
+ }
801
+
802
+ // ===== Keyboard Shortcuts =====
803
+ document.addEventListener('keydown', (e) => {
804
+ if (!selectedElement) return;
805
+
806
+ const isEditing = document.activeElement.getAttribute('contenteditable') === 'true' ||
807
+ document.activeElement.tagName === 'INPUT';
808
+
809
+ if ((e.key === 'Delete' || e.key === 'Backspace') && !isEditing) {
810
+ selectedElement.remove();
811
+ selectedElement = null;
812
+ hideAllPropertyPanels();
813
+ updateLayersList();
814
+ checkPlaceholder();
815
+ e.preventDefault();
816
+ }
817
+
818
+ if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key) && !isEditing) {
819
+ const step = e.shiftKey ? 10 : 1;
820
+
821
+ switch (e.key) {
822
+ case 'ArrowUp':
823
+ selectedElement.style.top = `${selectedElement.offsetTop - step}px`;
824
+ break;
825
+ case 'ArrowDown':
826
+ selectedElement.style.top = `${selectedElement.offsetTop + step}px`;
827
+ break;
828
+ case 'ArrowLeft':
829
+ selectedElement.style.left = `${selectedElement.offsetLeft - step}px`;
830
+ break;
831
+ case 'ArrowRight':
832
+ selectedElement.style.left = `${selectedElement.offsetLeft + step}px`;
833
+ break;
834
+ }
835
+
836
+ if (posX) posX.value = Math.round(selectedElement.offsetLeft);
837
+ if (posY) posY.value = Math.round(selectedElement.offsetTop);
838
+ e.preventDefault();
839
+ }
840
+ });
841
+
842
+ // ===== Publish Modal =====
843
+ postBtn?.addEventListener('click', () => {
844
+ const elements = blogCanvas.querySelectorAll('.draggable-element');
845
+
846
+ if (elements.length === 0) {
847
+ alert('Canvas is empty! Add some elements before publishing.');
848
+ return;
849
+ }
850
+
851
+ // Show modal
852
+ if (modalBlogTitle) modalBlogTitle.value = blogTitleInput?.value || '';
853
+ publishModal.classList.remove('hidden');
854
+ });
855
+
856
+ closeModal?.addEventListener('click', closePublishModal);
857
+ cancelPublish?.addEventListener('click', closePublishModal);
858
+
859
+ publishModal?.querySelector('.modal-backdrop')?.addEventListener('click', closePublishModal);
860
+
861
+ function closePublishModal() {
862
+ publishModal.classList.add('hidden');
863
+ coverImageData = null;
864
+ if (uploadPlaceholder) uploadPlaceholder.classList.remove('hidden');
865
+ if (uploadPreview) uploadPreview.classList.add('hidden');
866
+ }
867
+
868
+ // Cover Image Upload
869
+ coverUploadArea?.addEventListener('click', () => {
870
+ coverImageInput?.click();
871
+ });
872
+
873
+ coverImageInput?.addEventListener('change', (e) => {
874
+ const file = e.target.files[0];
875
+ if (file) {
876
+ const reader = new FileReader();
877
+ reader.onload = (event) => {
878
+ coverImageData = event.target.result;
879
+ if (coverPreviewImg) coverPreviewImg.src = coverImageData;
880
+ if (uploadPlaceholder) uploadPlaceholder.classList.add('hidden');
881
+ if (uploadPreview) uploadPreview.classList.remove('hidden');
882
+ };
883
+ reader.readAsDataURL(file);
884
+ }
885
+ });
886
+
887
+ removeCover?.addEventListener('click', (e) => {
888
+ e.stopPropagation();
889
+ coverImageData = null;
890
+ if (coverImageInput) coverImageInput.value = '';
891
+ if (uploadPlaceholder) uploadPlaceholder.classList.remove('hidden');
892
+ if (uploadPreview) uploadPreview.classList.add('hidden');
893
+ });
894
+
895
+ // Confirm Publish
896
+ confirmPublish?.addEventListener('click', () => {
897
+ const title = modalBlogTitle?.value || blogTitleInput?.value || 'Untitled Blog';
898
+
899
+ // Clone canvas for saving
900
+ const clone = blogCanvas.cloneNode(true);
901
+
902
+ // Clean up cloned elements
903
+ clone.querySelectorAll('.draggable-element').forEach(el => {
904
+ el.classList.remove('selected', 'dragging');
905
+ el.querySelectorAll('.resize-handle').forEach(h => h.remove());
906
+ el.querySelectorAll('[contenteditable]').forEach(c => {
907
+ c.removeAttribute('contenteditable');
908
+ });
909
+ el.style.cursor = 'default';
910
+ });
911
+
912
+ const placeholder = clone.querySelector('.canvas-placeholder');
913
+ if (placeholder) placeholder.remove();
914
+
915
+ // Create blog data
916
+ const blogData = {
917
+ id: Date.now(),
918
+ title: title,
919
+ date: new Date().toISOString(),
920
+ content: clone.innerHTML,
921
+ coverImage: coverImageData || null,
922
+ backgroundColor: '#FFFFFF'
923
+ };
924
+
925
+ // Save to localStorage
926
+ // Save to localStorage
927
+ const blogs = JSON.parse(localStorage.getItem('mubashra_blogs_v2')) || [];
928
+ blogs.unshift(blogData);
929
+ localStorage.setItem('mubashra_blogs_v2', JSON.stringify(blogs));
930
+
931
+ alert('Blog published successfully!');
932
+
933
+ // Clear canvas
934
+ blogCanvas.querySelectorAll('.draggable-element').forEach(el => el.remove());
935
+ if (blogTitleInput) blogTitleInput.value = '';
936
+ selectedElement = null;
937
+ hideAllPropertyPanels();
938
+ updateLayersList();
939
+ checkPlaceholder();
940
+ closePublishModal();
941
+ });
942
+
943
+ // Preview
944
+ previewBtn?.addEventListener('click', () => {
945
+ const elements = blogCanvas.querySelectorAll('.draggable-element');
946
+
947
+ if (elements.length === 0) {
948
+ alert('Canvas is empty! Add some elements to preview.');
949
+ return;
950
+ }
951
+
952
+ const clone = blogCanvas.cloneNode(true);
953
+
954
+ clone.querySelectorAll('.draggable-element').forEach(el => {
955
+ el.classList.remove('selected', 'dragging');
956
+ el.querySelectorAll('.resize-handle').forEach(h => h.remove());
957
+ el.querySelectorAll('[contenteditable]').forEach(c => {
958
+ c.removeAttribute('contenteditable');
959
+ });
960
+ el.style.cursor = 'default';
961
+ });
962
+
963
+ const placeholder = clone.querySelector('.canvas-placeholder');
964
+ if (placeholder) placeholder.remove();
965
+
966
+ const previewWindow = window.open('', '_blank');
967
+ previewWindow.document.write(`
968
+ <!DOCTYPE html>
969
+ <html>
970
+ <head>
971
+ <title>Preview - ${blogTitleInput?.value || 'Untitled Blog'}</title>
972
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
973
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=Playfair+Display:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">
974
+ <style>
975
+ * { margin: 0; padding: 0; box-sizing: border-box; }
976
+ body {
977
+ font-family: 'Inter', sans-serif;
978
+ background: #F7FAF9;
979
+ min-height: 100vh;
980
+ padding: 1rem;
981
+ }
982
+ @media (min-width: 768px) {
983
+ body { padding: 2rem; display: flex; justify-content: center; }
984
+ }
985
+ .blog-content {
986
+ width: 100%;
987
+ max-width: 800px;
988
+ margin: 0 auto;
989
+ padding: 1.5rem;
990
+ background: white;
991
+ border-radius: 16px;
992
+ box-shadow: 0 10px 40px rgba(0,0,0,0.12);
993
+ }
994
+ @media (min-width: 768px) {
995
+ .blog-content { padding: 2rem; }
996
+ }
997
+ .draggable-element {
998
+ position: relative !important;
999
+ left: auto !important;
1000
+ top: auto !important;
1001
+ width: 100% !important;
1002
+ max-width: 100% !important;
1003
+ height: auto !important;
1004
+ min-height: auto !important;
1005
+ margin-bottom: 1.5rem;
1006
+ }
1007
+ .element-content { padding: 0; }
1008
+ h1, h2, h3, p { margin: 0; word-wrap: break-word; }
1009
+ h1 { font-size: clamp(1.75rem, 5vw, 2.5rem); font-weight: 700; font-family: 'Playfair Display', serif; margin-bottom: 1rem; line-height: 1.2; }
1010
+ h2 { font-size: clamp(1.5rem, 4vw, 2rem); font-weight: 600; margin-bottom: 0.75rem; line-height: 1.3; }
1011
+ h3 { font-size: clamp(1.25rem, 3vw, 1.5rem); font-weight: 600; margin-bottom: 0.5rem; line-height: 1.4; }
1012
+ p { font-size: clamp(0.95rem, 2.5vw, 1.1rem); line-height: 1.8; margin-bottom: 1rem; color: #4A5568; }
1013
+ blockquote {
1014
+ margin: 1.5rem 0;
1015
+ padding: 1rem 1.5rem;
1016
+ border-left: 4px solid #2D6A4F;
1017
+ background: #E8F3EE;
1018
+ font-style: italic;
1019
+ border-radius: 0 8px 8px 0;
1020
+ }
1021
+ img {
1022
+ width: 100%;
1023
+ max-width: 100%;
1024
+ height: auto !important;
1025
+ object-fit: cover;
1026
+ display: block;
1027
+ border-radius: 12px;
1028
+ margin: 1rem 0;
1029
+ }
1030
+ .element-divider {
1031
+ width: 100%;
1032
+ height: 2px;
1033
+ background: linear-gradient(90deg, transparent, #2D6A4F, transparent);
1034
+ margin: 2rem 0;
1035
+ }
1036
+ .element-button {
1037
+ display: inline-block;
1038
+ padding: 0.75rem 1.5rem;
1039
+ background: #2D6A4F;
1040
+ color: white;
1041
+ font-weight: 600;
1042
+ border-radius: 8px;
1043
+ }
1044
+ </style>
1045
+ </head>
1046
+ <body>
1047
+ <div class="blog-content">${clone.innerHTML}</div>
1048
+ </body>
1049
+ </html>
1050
+ `);
1051
+ previewWindow.document.close();
1052
+ });
1053
+
1054
+ // Initialize
1055
+ updateLayersList();
blog.html ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html class="light" lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta content="width=device-width, initial-scale=1.0" name="viewport" />
7
+ <title>Blog Post - Mubashra</title>
8
+
9
+ <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
10
+ <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap"
11
+ rel="stylesheet" />
12
+ <link
13
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&family=Playfair+Display:wght@700&display=swap"
14
+ rel="stylesheet" />
15
+
16
+ <script>
17
+ tailwind.config = {
18
+ darkMode: "class",
19
+ theme: {
20
+ extend: {
21
+ colors: {
22
+ "primary": "#2D6A4F",
23
+ "pastel-green-light": "#F0F7F4",
24
+ "pastel-green-accent": "#D8E9E1",
25
+ "background-light": "#f5f7f8",
26
+ "background-dark": "#101922",
27
+ },
28
+ fontFamily: {
29
+ "display": ["Inter", "sans-serif"],
30
+ "serif": ["Playfair Display", "serif"]
31
+ },
32
+ },
33
+ },
34
+ }
35
+ </script>
36
+ <style>
37
+ /* Responsive Blog Content Styles */
38
+ .blog-content {
39
+ width: 100%;
40
+ max-width: 800px;
41
+ margin: 0 auto;
42
+ padding: 2rem 1.5rem;
43
+ }
44
+
45
+ /* Convert absolute positioning to normal flow */
46
+ .blog-content .draggable-element {
47
+ position: relative !important;
48
+ left: auto !important;
49
+ top: auto !important;
50
+ width: 100% !important;
51
+ max-width: 100% !important;
52
+ height: auto !important;
53
+ min-height: auto !important;
54
+ margin-bottom: 1.5rem;
55
+ cursor: default !important;
56
+ }
57
+
58
+ .blog-content .element-content {
59
+ padding: 0;
60
+ }
61
+
62
+ .blog-content h1 {
63
+ font-size: clamp(1.75rem, 5vw, 2.5rem);
64
+ font-weight: 700;
65
+ font-family: 'Playfair Display', serif;
66
+ margin: 0 0 1rem 0;
67
+ line-height: 1.2;
68
+ word-wrap: break-word;
69
+ }
70
+
71
+ .blog-content h2 {
72
+ font-size: clamp(1.5rem, 4vw, 2rem);
73
+ font-weight: 600;
74
+ margin: 0 0 0.75rem 0;
75
+ line-height: 1.3;
76
+ word-wrap: break-word;
77
+ }
78
+
79
+ .blog-content h3 {
80
+ font-size: clamp(1.25rem, 3vw, 1.5rem);
81
+ font-weight: 600;
82
+ margin: 0 0 0.5rem 0;
83
+ line-height: 1.4;
84
+ word-wrap: break-word;
85
+ }
86
+
87
+ .blog-content p {
88
+ font-size: clamp(0.95rem, 2.5vw, 1.1rem);
89
+ line-height: 1.8;
90
+ margin: 0 0 1rem 0;
91
+ word-wrap: break-word;
92
+ color: #4A5568;
93
+ }
94
+
95
+ .blog-content blockquote {
96
+ margin: 1.5rem 0;
97
+ padding: 1rem 1.5rem;
98
+ border-left: 4px solid #2D6A4F;
99
+ background: #E8F3EE;
100
+ font-style: italic;
101
+ font-size: clamp(1rem, 2.5vw, 1.1rem);
102
+ border-radius: 0 8px 8px 0;
103
+ }
104
+
105
+ .blog-content img {
106
+ width: 100%;
107
+ max-width: 100%;
108
+ height: auto !important;
109
+ object-fit: cover;
110
+ display: block;
111
+ border-radius: 12px;
112
+ margin: 1rem 0;
113
+ }
114
+
115
+ .blog-content .element-divider {
116
+ width: 100%;
117
+ height: 2px;
118
+ background: linear-gradient(90deg, transparent, #2D6A4F, transparent);
119
+ margin: 2rem 0;
120
+ }
121
+
122
+ .blog-content .element-button {
123
+ display: inline-block;
124
+ padding: 0.75rem 1.5rem;
125
+ background: #2D6A4F;
126
+ color: white;
127
+ font-weight: 600;
128
+ border-radius: 8px;
129
+ text-decoration: none;
130
+ }
131
+
132
+ /* Cover Image */
133
+ .cover-image {
134
+ width: 100%;
135
+ max-height: 400px;
136
+ object-fit: cover;
137
+ border-radius: 16px;
138
+ margin-bottom: 2rem;
139
+ }
140
+ </style>
141
+ </head>
142
+
143
+ <body class="font-display bg-background-light dark:bg-background-dark text-[#111418] dark:text-white">
144
+
145
+ <!-- Header -->
146
+ <header
147
+ class="sticky top-0 z-50 w-full border-b border-solid border-[#f0f2f5] dark:border-[#2a343f] bg-white/80 dark:bg-background-dark/80 backdrop-blur-md px-4 md:px-20 py-3">
148
+ <div class="max-w-[1200px] mx-auto flex items-center justify-between">
149
+ <a href="index.html" class="flex items-center gap-2 md:gap-4 text-primary">
150
+ <div class="size-6">
151
+ <svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
152
+ <path
153
+ d="M42.4379 44C42.4379 44 36.0744 33.9038 41.1692 24C46.8624 12.9336 42.2078 4 42.2078 4L7.01134 4C7.01134 4 11.6577 12.932 5.96912 23.9969C0.876273 33.9029 7.27094 44 7.27094 44L42.4379 44Z"
154
+ fill="currentColor"></path>
155
+ </svg>
156
+ </div>
157
+ <h2
158
+ class="text-[#111418] dark:text-white text-lg md:text-xl font-bold leading-tight tracking-[-0.015em]">
159
+ Mubashra</h2>
160
+ </a>
161
+ <div class="flex items-center gap-4">
162
+ <nav class="hidden md:flex items-center gap-9">
163
+ <a class="text-[#111418] dark:text-white text-sm font-medium hover:text-primary transition-colors"
164
+ href="index.html">Home</a>
165
+ <a class="text-[#111418] dark:text-white text-sm font-medium hover:text-primary transition-colors"
166
+ href="blogs.html">Blogs</a>
167
+ <a class="text-[#111418] dark:text-white text-sm font-medium hover:text-primary transition-colors"
168
+ href="portfolio.html">Portfolio</a>
169
+ </nav>
170
+ <a href="blogs.html"
171
+ class="flex items-center gap-1 md:gap-2 text-primary font-medium hover:underline text-sm">
172
+ <span class="material-symbols-outlined text-lg">arrow_back</span>
173
+ <span class="hidden sm:inline">Back</span>
174
+ </a>
175
+ </div>
176
+ </div>
177
+ </header>
178
+
179
+ <main class="min-h-screen">
180
+ <!-- Blog Header -->
181
+ <section class="bg-[#F7FAF9] dark:bg-[#0D1510] py-10 md:py-16 px-4 md:px-6">
182
+ <div class="max-w-[800px] mx-auto">
183
+ <div class="flex items-center gap-3 text-[#60758a] dark:text-gray-400 text-sm font-medium mb-4">
184
+ <span id="blogDate">Loading...</span>
185
+ <span class="size-1 rounded-full bg-gray-300"></span>
186
+ <span id="blogReadTime">5 min read</span>
187
+ </div>
188
+ <h1 id="blogTitle"
189
+ class="text-[#111418] dark:text-white text-3xl md:text-4xl lg:text-5xl font-serif mb-6 leading-tight">
190
+ Loading...
191
+ </h1>
192
+ <div class="flex items-center gap-4">
193
+ <div
194
+ class="w-10 h-10 md:w-12 md:h-12 rounded-full bg-primary/20 flex items-center justify-center text-primary font-bold">
195
+ M
196
+ </div>
197
+ <div>
198
+ <p class="font-semibold text-[#111418] dark:text-white text-sm md:text-base">Mubashra</p>
199
+ <p class="text-xs md:text-sm text-gray-500 dark:text-gray-400">Creative Developer & Writer</p>
200
+ </div>
201
+ </div>
202
+ </div>
203
+ </section>
204
+
205
+ <!-- Cover Image -->
206
+ <section id="coverImageSection" class="hidden px-4 md:px-6 -mt-4">
207
+ <div class="max-w-[800px] mx-auto">
208
+ <img id="coverImage" class="cover-image" src="" alt="Cover Image">
209
+ </div>
210
+ </section>
211
+
212
+ <!-- Blog Content -->
213
+ <section class="py-8 md:py-12 px-4 md:px-6">
214
+ <div id="blogContent" class="blog-content bg-white dark:bg-[#1a2332] shadow-lg rounded-2xl overflow-hidden">
215
+ <!-- Blog content will be loaded here -->
216
+ </div>
217
+ </section>
218
+
219
+ <!-- Back to Blogs -->
220
+ <section class="py-8 md:py-12 px-4 md:px-6">
221
+ <div class="max-w-[800px] mx-auto text-center">
222
+ <a href="blogs.html"
223
+ class="inline-flex items-center gap-2 px-6 md:px-8 py-3 md:py-4 bg-primary text-white font-bold rounded-full hover:shadow-xl hover:shadow-primary/20 transition-all transform hover:-translate-y-1 text-sm md:text-base">
224
+ <span class="material-symbols-outlined">arrow_back</span>
225
+ View All Blogs
226
+ </a>
227
+ </div>
228
+ </section>
229
+ </main>
230
+
231
+ <!-- Footer -->
232
+ <footer class="border-t border-gray-100 dark:border-gray-800 py-8 md:py-12 px-4 md:px-20">
233
+ <div class="max-w-[1200px] mx-auto flex flex-col md:flex-row justify-between items-center gap-4 md:gap-6">
234
+ <div class="flex items-center gap-2">
235
+ <div class="size-5 text-primary">
236
+ <svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
237
+ <path
238
+ d="M42.4379 44C42.4379 44 36.0744 33.9038 41.1692 24C46.8624 12.9336 42.2078 4 42.2078 4L7.01134 4C7.01134 4 11.6577 12.932 5.96912 23.9969C0.876273 33.9029 7.27094 44 7.27094 44L42.4379 44Z"
239
+ fill="currentColor"></path>
240
+ </svg>
241
+ </div>
242
+ <span class="font-bold">Mubashra</span>
243
+ </div>
244
+ <p class="text-xs md:text-sm text-gray-500 dark:text-gray-400">© 2024 Mubashra Portfolio. Built with
245
+ passion.</p>
246
+ </div>
247
+ </footer>
248
+
249
+ <script>
250
+ // Get blog ID from URL
251
+ function getBlogId() {
252
+ const params = new URLSearchParams(window.location.search);
253
+ return params.get('id');
254
+ }
255
+
256
+ // Load blog content
257
+ function loadBlog() {
258
+ const blogId = getBlogId();
259
+ const blogs = JSON.parse(localStorage.getItem('mubashra_blogs_v2')) || [];
260
+
261
+ const blog = blogs.find(b => b.id == blogId);
262
+
263
+ if (!blog) {
264
+ document.getElementById('blogTitle').textContent = 'Blog Not Found';
265
+ document.getElementById('blogContent').innerHTML = `
266
+ <div class="flex flex-col items-center justify-center py-20 px-4">
267
+ <span class="material-symbols-outlined text-6xl text-gray-300 mb-4">error</span>
268
+ <p class="text-gray-500 text-lg text-center">The blog post you're looking for doesn't exist.</p>
269
+ <a href="blogs.html" class="mt-6 text-primary font-bold hover:underline">Go back to blogs</a>
270
+ </div>
271
+ `;
272
+ return;
273
+ }
274
+
275
+ // Update page title
276
+ document.title = `${blog.title} - Mubashra`;
277
+
278
+ // Update header info
279
+ const date = new Date(blog.date);
280
+ document.getElementById('blogDate').textContent = date.toLocaleDateString('en-US', {
281
+ month: 'long',
282
+ day: 'numeric',
283
+ year: 'numeric'
284
+ });
285
+
286
+ // Get title from content or use blog title
287
+ const tempDiv = document.createElement('div');
288
+ tempDiv.innerHTML = blog.content;
289
+ const headingEl = tempDiv.querySelector('h1, h2, h3');
290
+ const title = headingEl ? headingEl.textContent : blog.title;
291
+ document.getElementById('blogTitle').textContent = title;
292
+
293
+ // Show cover image if exists
294
+ if (blog.coverImage) {
295
+ document.getElementById('coverImageSection').classList.remove('hidden');
296
+ document.getElementById('coverImage').src = blog.coverImage;
297
+ }
298
+
299
+ // Load the actual content
300
+ document.getElementById('blogContent').innerHTML = blog.content;
301
+ }
302
+
303
+ // Load on page ready
304
+ document.addEventListener('DOMContentLoaded', loadBlog);
305
+ </script>
306
+ </body>
307
+
308
+ </html>
blogs.html ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html class="light" lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta content="width=device-width, initial-scale=1.0" name="viewport" />
7
+ <title>All Blogs - Mubashra</title>
8
+
9
+ <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
10
+ <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap"
11
+ rel="stylesheet" />
12
+ <link
13
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&family=Playfair+Display:wght@700&display=swap"
14
+ rel="stylesheet" />
15
+
16
+ <script>
17
+ tailwind.config = {
18
+ darkMode: "class",
19
+ theme: {
20
+ extend: {
21
+ colors: {
22
+ "primary": "#2D6A4F",
23
+ "pastel-green-light": "#F0F7F4",
24
+ "pastel-green-accent": "#D8E9E1",
25
+ "background-light": "#f5f7f8",
26
+ "background-dark": "#101922",
27
+ },
28
+ fontFamily: {
29
+ "display": ["Inter", "sans-serif"],
30
+ "serif": ["Playfair Display", "serif"]
31
+ },
32
+ },
33
+ },
34
+ }
35
+ </script>
36
+ <style>
37
+ .line-clamp-2 {
38
+ display: -webkit-box;
39
+ -webkit-line-clamp: 2;
40
+ -webkit-box-orient: vertical;
41
+ overflow: hidden;
42
+ }
43
+
44
+ @keyframes float {
45
+ 0% {
46
+ transform: translate(0, 0) scale(1);
47
+ }
48
+
49
+ 33% {
50
+ transform: translate(30px, -50px) scale(1.1);
51
+ }
52
+
53
+ 66% {
54
+ transform: translate(-20px, 20px) scale(0.9);
55
+ }
56
+
57
+ 100% {
58
+ transform: translate(0, 0) scale(1);
59
+ }
60
+ }
61
+
62
+ .animate-blob {
63
+ animation: float 15s infinite ease-in-out;
64
+ }
65
+
66
+ .animation-delay-2000 {
67
+ animation-delay: 2s;
68
+ }
69
+ </style>
70
+ </head>
71
+
72
+ <body class="font-display bg-background-light dark:bg-background-dark text-[#111418] dark:text-white">
73
+
74
+ <!-- Header -->
75
+ <header
76
+ class="sticky top-0 z-50 w-full border-b border-solid border-[#f0f2f5] dark:border-[#2a343f] bg-white/80 dark:bg-background-dark/80 backdrop-blur-md px-6 md:px-20 py-3">
77
+ <div class="max-w-[1200px] mx-auto flex items-center justify-between">
78
+ <a href="index.html" class="flex items-center gap-4 text-primary">
79
+ <div class="size-6">
80
+ <svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
81
+ <path
82
+ d="M42.4379 44C42.4379 44 36.0744 33.9038 41.1692 24C46.8624 12.9336 42.2078 4 42.2078 4L7.01134 4C7.01134 4 11.6577 12.932 5.96912 23.9969C0.876273 33.9029 7.27094 44 7.27094 44L42.4379 44Z"
83
+ fill="currentColor"></path>
84
+ </svg>
85
+ </div>
86
+ <h2 class="text-[#111418] dark:text-white text-xl font-bold leading-tight tracking-[-0.015em]">Mubashra
87
+ </h2>
88
+ </a>
89
+ <div class="flex flex-1 justify-end gap-8 items-center">
90
+ <nav class="hidden md:flex items-center gap-9">
91
+ <a class="text-[#111418] dark:text-white text-sm font-medium hover:text-primary transition-colors"
92
+ href="index.html">Home</a>
93
+ <a class="text-primary text-sm font-medium" href="blogs.html">Blogs</a>
94
+ <a class="text-[#111418] dark:text-white text-sm font-medium hover:text-primary transition-colors"
95
+ href="portfolio.html">Portfolio</a>
96
+ </nav>
97
+ <a href="admin.html"
98
+ class="flex min-w-[84px] cursor-pointer items-center justify-center rounded-lg h-10 px-5 bg-primary text-white text-sm font-bold hover:bg-primary/90 transition-all shadow-sm">
99
+ <span class="truncate">Login</span>
100
+ </a>
101
+ </div>
102
+ </div>
103
+ </header>
104
+
105
+ <main class="min-h-screen">
106
+ <!-- Hero Section -->
107
+ <section class="relative py-20 overflow-hidden bg-[#F7FAF9] dark:bg-[#0D1510]">
108
+ <div class="absolute inset-0 z-0">
109
+ <div
110
+ class="absolute top-[-10%] left-[10%] w-[35%] h-[35%] rounded-full bg-[#D1E7DD] dark:bg-[#1A3328] blur-[100px] animate-blob">
111
+ </div>
112
+ <div
113
+ class="absolute bottom-[-5%] right-[5%] w-[40%] h-[40%] rounded-full bg-[#E2EFDE] dark:bg-[#142A1F] blur-[120px] animate-blob animation-delay-2000">
114
+ </div>
115
+ </div>
116
+ <div class="relative z-10 max-w-[1200px] mx-auto px-6 md:px-20 text-center">
117
+ <h1 class="text-[#111418] dark:text-white text-5xl md:text-6xl font-serif mb-6 leading-tight">
118
+ All <span class="text-primary italic">Stories</span>
119
+ </h1>
120
+ <p class="text-[#4A5568] dark:text-gray-300 text-lg max-w-2xl mx-auto leading-relaxed">
121
+ Explore my thoughts on design, development, and the creative process.
122
+ </p>
123
+ </div>
124
+ </section>
125
+
126
+ <!-- All Blogs Grid -->
127
+ <section class="max-w-[1200px] mx-auto px-6 md:px-20 py-16">
128
+ <div id="blogGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
129
+ <!-- Blog posts will be loaded here dynamically -->
130
+ </div>
131
+ <div id="noBlogsMessage" class="hidden text-center py-20">
132
+ <span class="material-symbols-outlined text-8xl text-gray-300 dark:text-gray-600 mb-6">article</span>
133
+ <h2 class="text-2xl font-bold text-gray-400 mb-2">No Blog Posts Yet</h2>
134
+ <p class="text-gray-500 dark:text-gray-400 text-lg mb-8">Check back soon for new stories and insights!
135
+ </p>
136
+ <a href="admin.html"
137
+ class="inline-flex items-center gap-2 px-6 py-3 bg-primary text-white font-bold rounded-lg hover:bg-primary/90 transition-all">
138
+ <span class="material-symbols-outlined">add</span>
139
+ Create First Blog
140
+ </a>
141
+ </div>
142
+ </section>
143
+ </main>
144
+
145
+ <!-- Footer -->
146
+ <footer class="border-t border-gray-100 dark:border-gray-800 py-12 px-6 md:px-20">
147
+ <div class="max-w-[1200px] mx-auto flex flex-col md:flex-row justify-between items-center gap-6">
148
+ <div class="flex items-center gap-2">
149
+ <div class="size-5 text-primary">
150
+ <svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
151
+ <path
152
+ d="M42.4379 44C42.4379 44 36.0744 33.9038 41.1692 24C46.8624 12.9336 42.2078 4 42.2078 4L7.01134 4C7.01134 4 11.6577 12.932 5.96912 23.9969C0.876273 33.9029 7.27094 44 7.27094 44L42.4379 44Z"
153
+ fill="currentColor"></path>
154
+ </svg>
155
+ </div>
156
+ <span class="font-bold">Mubashra</span>
157
+ </div>
158
+ <p class="text-sm text-gray-500 dark:text-gray-400">© 2024 Mubashra Portfolio. Built with passion.</p>
159
+ <div class="flex gap-6">
160
+ <a class="text-gray-400 hover:text-primary transition-colors" href="#">
161
+ <span class="material-symbols-outlined">alternate_email</span>
162
+ </a>
163
+ <a class="text-gray-400 hover:text-primary transition-colors" href="#">
164
+ <span class="material-symbols-outlined">person</span>
165
+ </a>
166
+ <a class="text-gray-400 hover:text-primary transition-colors" href="#">
167
+ <span class="material-symbols-outlined">share</span>
168
+ </a>
169
+ </div>
170
+ </div>
171
+ </footer>
172
+
173
+ <script>
174
+ // Load and display all blog posts
175
+ function loadBlogs() {
176
+ const blogs = JSON.parse(localStorage.getItem('mubashra_blogs_v2')) || [];
177
+ const blogGrid = document.getElementById('blogGrid');
178
+ const noBlogsMessage = document.getElementById('noBlogsMessage');
179
+
180
+ if (blogs.length === 0) {
181
+ blogGrid.classList.add('hidden');
182
+ noBlogsMessage.classList.remove('hidden');
183
+ return;
184
+ }
185
+
186
+ blogGrid.classList.remove('hidden');
187
+ noBlogsMessage.classList.add('hidden');
188
+
189
+ blogGrid.innerHTML = blogs.map((blog, index) => {
190
+ const date = new Date(blog.date);
191
+ const formattedDate = date.toLocaleDateString('en-US', {
192
+ month: 'short',
193
+ day: 'numeric',
194
+ year: 'numeric'
195
+ });
196
+
197
+ // Extract first text content for preview
198
+ const tempDiv = document.createElement('div');
199
+ tempDiv.innerHTML = blog.content;
200
+ const textContent = tempDiv.textContent || tempDiv.innerText || '';
201
+ const preview = textContent.substring(0, 120) + (textContent.length > 120 ? '...' : '');
202
+
203
+ // Get first heading for title
204
+ const headingEl = tempDiv.querySelector('h1, h2, h3');
205
+ const title = headingEl ? headingEl.textContent : blog.title;
206
+
207
+ // Categories
208
+ const categories = ['Design', 'Development', 'Minimalism', 'Technology', 'Lifestyle'];
209
+ const category = categories[index % categories.length];
210
+
211
+ // Placeholder images
212
+ const images = [
213
+ 'https://images.unsplash.com/photo-1499951360447-b19be8fe80f5?w=600&h=400&fit=crop',
214
+ 'https://images.unsplash.com/photo-1461749280684-dccba630e2f6?w=600&h=400&fit=crop',
215
+ 'https://images.unsplash.com/photo-1493119508027-2b584f234d6c?w=600&h=400&fit=crop',
216
+ 'https://images.unsplash.com/photo-1555949963-aa79dcee981c?w=600&h=400&fit=crop',
217
+ 'https://images.unsplash.com/photo-1486312338219-ce68d2c6f44d?w=600&h=400&fit=crop',
218
+ 'https://images.unsplash.com/photo-1517694712202-14dd9538aa97?w=600&h=400&fit=crop'
219
+ ];
220
+ const image = images[index % images.length];
221
+
222
+ return `
223
+ <article class="group flex flex-col gap-4 cursor-pointer" onclick="viewBlog(${blog.id})">
224
+ <div class="relative w-full aspect-[16/10] overflow-hidden rounded-xl bg-gray-100 dark:bg-gray-800">
225
+ <div class="absolute inset-0 bg-center bg-cover transition-transform duration-500 group-hover:scale-110"
226
+ style="background-image: url('${image}');">
227
+ </div>
228
+ <div class="absolute top-4 left-4">
229
+ <span class="px-3 py-1 rounded-full bg-white/90 dark:bg-background-dark/90 text-primary text-xs font-bold shadow-sm">${category}</span>
230
+ </div>
231
+ </div>
232
+ <div class="flex flex-col gap-2">
233
+ <div class="flex items-center gap-3 text-[#60758a] dark:text-gray-400 text-xs font-medium">
234
+ <span>${formattedDate}</span>
235
+ <span class="size-1 rounded-full bg-gray-300"></span>
236
+ <span>5 min read</span>
237
+ </div>
238
+ <h3 class="text-[#111418] dark:text-white text-xl font-bold leading-snug group-hover:text-primary transition-colors">
239
+ ${title}
240
+ </h3>
241
+ <p class="text-[#60758a] dark:text-gray-400 text-sm leading-relaxed line-clamp-2">
242
+ ${preview}
243
+ </p>
244
+ </div>
245
+ </article>
246
+ `;
247
+ }).join('');
248
+ }
249
+
250
+ // Navigate to blog view page
251
+ function viewBlog(blogId) {
252
+ window.location.href = `blog.html?id=${blogId}`;
253
+ }
254
+
255
+ // Load blogs on page load
256
+ document.addEventListener('DOMContentLoaded', loadBlogs);
257
+ </script>
258
+ </body>
259
+
260
+ </html>
index.html ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html class="light" lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta content="width=device-width, initial-scale=1.0" name="viewport" />
7
+ <title>Mubashra Portfolio - Creative Developer & Writer</title>
8
+ <meta name="description"
9
+ content="Mubashra - Creative Developer & Writer specializing in building sophisticated digital experiences and sharing insights on the future of technology.">
10
+
11
+ <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
12
+ <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap"
13
+ rel="stylesheet" />
14
+ <link
15
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&family=Playfair+Display:wght@700&display=swap"
16
+ rel="stylesheet" />
17
+
18
+ <script>
19
+ tailwind.config = {
20
+ darkMode: "class",
21
+ theme: {
22
+ extend: {
23
+ colors: {
24
+ "primary": "#2D6A4F",
25
+ "pastel-green-light": "#F0F7F4",
26
+ "pastel-green-accent": "#D8E9E1",
27
+ "background-light": "#f5f7f8",
28
+ "background-dark": "#101922",
29
+ },
30
+ fontFamily: {
31
+ "display": ["Inter", "sans-serif"],
32
+ "serif": ["Playfair Display", "serif"]
33
+ },
34
+ borderRadius: { "DEFAULT": "0.25rem", "lg": "0.5rem", "xl": "0.75rem", "full": "9999px" },
35
+ },
36
+ },
37
+ }
38
+ </script>
39
+ <style>
40
+ @keyframes float {
41
+ 0% {
42
+ transform: translate(0, 0) scale(1);
43
+ }
44
+
45
+ 33% {
46
+ transform: translate(30px, -50px) scale(1.1);
47
+ }
48
+
49
+ 66% {
50
+ transform: translate(-20px, 20px) scale(0.9);
51
+ }
52
+
53
+ 100% {
54
+ transform: translate(0, 0) scale(1);
55
+ }
56
+ }
57
+
58
+ .animate-blob {
59
+ animation: float 15s infinite ease-in-out;
60
+ }
61
+
62
+ .animation-delay-2000 {
63
+ animation-delay: 2s;
64
+ }
65
+
66
+ .animation-delay-4000 {
67
+ animation-delay: 4s;
68
+ }
69
+
70
+ .line-clamp-2 {
71
+ display: -webkit-box;
72
+ -webkit-line-clamp: 2;
73
+ -webkit-box-orient: vertical;
74
+ overflow: hidden;
75
+ }
76
+ </style>
77
+ </head>
78
+
79
+ <body
80
+ class="font-display bg-background-light dark:bg-background-dark text-[#111418] dark:text-white transition-colors duration-300">
81
+
82
+ <!-- Header -->
83
+ <header
84
+ class="sticky top-0 z-50 w-full border-b border-solid border-[#f0f2f5] dark:border-[#2a343f] bg-white/80 dark:bg-background-dark/80 backdrop-blur-md px-6 md:px-20 py-3">
85
+ <div class="max-w-[1200px] mx-auto flex items-center justify-between">
86
+ <div class="flex items-center gap-4 text-primary">
87
+ <div class="size-6">
88
+ <svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
89
+ <path
90
+ d="M42.4379 44C42.4379 44 36.0744 33.9038 41.1692 24C46.8624 12.9336 42.2078 4 42.2078 4L7.01134 4C7.01134 4 11.6577 12.932 5.96912 23.9969C0.876273 33.9029 7.27094 44 7.27094 44L42.4379 44Z"
91
+ fill="currentColor"></path>
92
+ </svg>
93
+ </div>
94
+ <h2 class="text-[#111418] dark:text-white text-xl font-bold leading-tight tracking-[-0.015em]">Mubashra
95
+ </h2>
96
+ </div>
97
+ <div class="flex flex-1 justify-end gap-8 items-center">
98
+ <nav class="hidden md:flex items-center gap-9">
99
+ <a class="text-[#111418] dark:text-white text-sm font-medium hover:text-primary transition-colors"
100
+ href="index.html">Home</a>
101
+ <a class="text-[#111418] dark:text-white text-sm font-medium hover:text-primary transition-colors"
102
+ href="blogs.html">Blogs</a>
103
+ <a class="text-[#111418] dark:text-white text-sm font-medium hover:text-primary transition-colors"
104
+ href="portfolio.html">Portfolio</a>
105
+ </nav>
106
+ <a href="admin.html"
107
+ class="flex min-w-[84px] cursor-pointer items-center justify-center rounded-lg h-10 px-5 bg-primary text-white text-sm font-bold hover:bg-primary/90 transition-all shadow-sm">
108
+ <span class="truncate">Login</span>
109
+ </a>
110
+ </div>
111
+ </div>
112
+ </header>
113
+
114
+ <main>
115
+ <!-- Hero Section -->
116
+ <section
117
+ class="relative h-[85vh] min-h-[650px] w-full flex items-center justify-center overflow-hidden bg-[#F7FAF9] dark:bg-[#0D1510]">
118
+ <div class="absolute inset-0 z-0">
119
+ <div
120
+ class="absolute top-[-10%] left-[10%] w-[45%] h-[45%] rounded-full bg-[#D1E7DD] dark:bg-[#1A3328] blur-[100px] animate-blob">
121
+ </div>
122
+ <div
123
+ class="absolute bottom-[-5%] right-[5%] w-[50%] h-[50%] rounded-full bg-[#E2EFDE] dark:bg-[#142A1F] blur-[120px] animate-blob animation-delay-2000">
124
+ </div>
125
+ <div
126
+ class="absolute top-[20%] right-[15%] w-[30%] h-[30%] rounded-full bg-[#ECF3F0] dark:bg-[#0D1F16] blur-[80px] animate-blob animation-delay-4000">
127
+ </div>
128
+ </div>
129
+ <div class="relative z-10 max-w-[960px] px-6 text-center">
130
+ <div
131
+ class="mb-8 inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-primary/10 border border-primary/20 text-primary text-xs font-bold uppercase tracking-[0.15em]">
132
+ <span class="relative flex h-2 w-2">
133
+ <span
134
+ class="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
135
+ <span class="relative inline-flex rounded-full h-2 w-2 bg-primary"></span>
136
+ </span>
137
+ Available for projects
138
+ </div>
139
+ <h1
140
+ class="text-[#111418] dark:text-white text-6xl md:text-8xl font-serif mb-8 leading-[1.1] tracking-tight">
141
+ Hello, I am <span class="text-primary italic">Mubashra</span>
142
+ </h1>
143
+ <p
144
+ class="text-[#4A5568] dark:text-gray-300 text-lg md:text-2xl font-normal mb-12 max-w-2xl mx-auto leading-relaxed">
145
+ Creative Developer & Writer specializing in building sophisticated digital experiences and sharing
146
+ insights on the future of technology.
147
+ </p>
148
+ <div class="flex flex-col sm:flex-row items-center justify-center gap-5">
149
+ <a href="portfolio.html"
150
+ class="w-full sm:w-auto flex items-center justify-center rounded-full h-16 px-10 bg-primary text-white text-base font-bold tracking-wide hover:shadow-xl hover:shadow-primary/20 transition-all transform hover:-translate-y-1">
151
+ Explore My Work
152
+ </a>
153
+ <a href="blogs.html"
154
+ class="w-full sm:w-auto flex items-center justify-center rounded-full h-16 px-10 bg-white/40 dark:bg-white/5 border border-[#E2E8F0] dark:border-white/10 text-[#111418] dark:text-white text-base font-bold backdrop-blur-sm hover:bg-white/60 dark:hover:bg-white/10 transition-all">
155
+ Read My Blog
156
+ </a>
157
+ </div>
158
+ </div>
159
+ <div class="absolute bottom-10 left-1/2 -translate-x-1/2 text-primary/40 flex flex-col items-center gap-2">
160
+ <span class="text-[10px] font-bold uppercase tracking-[0.3em]">Scroll</span>
161
+ <span class="material-symbols-outlined text-xl animate-bounce">keyboard_double_arrow_down</span>
162
+ </div>
163
+ </section>
164
+
165
+ <!-- Latest Blog Posts Section -->
166
+ <section class="max-w-[1200px] mx-auto px-6 md:px-20 pt-20">
167
+ <div class="flex items-end justify-between border-b border-gray-200 dark:border-gray-800 pb-6">
168
+ <div>
169
+ <h2 class="text-[#111418] dark:text-white text-3xl font-bold tracking-tight">Latest Insights &
170
+ Stories</h2>
171
+ <p class="text-gray-500 dark:text-gray-400 mt-2">Thoughts on design, code, and everything in
172
+ between.</p>
173
+ </div>
174
+ <a class="text-primary font-bold text-sm flex items-center gap-1 hover:underline" href="blogs.html">
175
+ View All Posts <span class="material-symbols-outlined text-sm">arrow_forward</span>
176
+ </a>
177
+ </div>
178
+ </section>
179
+
180
+ <section class="max-w-[1200px] mx-auto px-6 md:px-20 py-10">
181
+ <div id="blogGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
182
+ <!-- Blog posts will be loaded here dynamically -->
183
+ </div>
184
+ <div id="noBlogsMessage" class="hidden text-center py-16">
185
+ <span class="material-symbols-outlined text-6xl text-gray-300 dark:text-gray-600 mb-4">article</span>
186
+ <p class="text-gray-500 dark:text-gray-400 text-lg">No blog posts yet. Check back soon!</p>
187
+ </div>
188
+ </section>
189
+
190
+ <!-- CTA Section -->
191
+ <section class="bg-white dark:bg-[#151f2b] py-24 px-6 md:px-20 mt-10">
192
+ <div
193
+ class="max-w-[1200px] mx-auto bg-primary/5 dark:bg-primary/10 rounded-3xl p-10 md:p-20 border border-primary/10 flex flex-col items-center text-center">
194
+ <div class="size-16 rounded-2xl bg-primary/20 flex items-center justify-center text-primary mb-8">
195
+ <span class="material-symbols-outlined text-4xl">dashboard_customize</span>
196
+ </div>
197
+ <h2
198
+ class="text-[#111418] dark:text-white text-3xl md:text-5xl font-black mb-6 max-w-[720px] leading-tight">
199
+ Build your own vision
200
+ </h2>
201
+ <p class="text-[#111418] dark:text-gray-300 text-lg mb-10 max-w-[600px] opacity-80">
202
+ Ready to take control? Manage your content with our powerful drag-and-drop admin builder. Simple,
203
+ fast, and completely customizable.
204
+ </p>
205
+ <div class="flex flex-col sm:flex-row gap-4 w-full justify-center">
206
+ <a href="admin.html"
207
+ class="flex min-w-[200px] cursor-pointer items-center justify-center rounded-xl h-14 px-8 bg-primary text-white text-base font-bold shadow-lg shadow-primary/20 hover:scale-[1.02] transition-transform">
208
+ Open Admin Editor
209
+ </a>
210
+ <button
211
+ class="flex min-w-[200px] cursor-pointer items-center justify-center rounded-xl h-14 px-8 border-2 border-primary/20 text-primary text-base font-bold hover:bg-primary/5 transition-colors">
212
+ Documentation
213
+ </button>
214
+ </div>
215
+ </div>
216
+ </section>
217
+ </main>
218
+
219
+ <!-- Footer -->
220
+ <footer class="border-t border-gray-100 dark:border-gray-800 py-12 px-6 md:px-20">
221
+ <div class="max-w-[1200px] mx-auto flex flex-col md:flex-row justify-between items-center gap-6">
222
+ <div class="flex items-center gap-2">
223
+ <div class="size-5 text-primary">
224
+ <svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
225
+ <path
226
+ d="M42.4379 44C42.4379 44 36.0744 33.9038 41.1692 24C46.8624 12.9336 42.2078 4 42.2078 4L7.01134 4C7.01134 4 11.6577 12.932 5.96912 23.9969C0.876273 33.9029 7.27094 44 7.27094 44L42.4379 44Z"
227
+ fill="currentColor"></path>
228
+ </svg>
229
+ </div>
230
+ <span class="font-bold">Mubashra</span>
231
+ </div>
232
+ <p class="text-sm text-gray-500 dark:text-gray-400">© 2024 Mubashra Portfolio. Built with passion.</p>
233
+ <div class="flex gap-6">
234
+ <a class="text-gray-400 hover:text-primary transition-colors" href="#">
235
+ <span class="material-symbols-outlined">alternate_email</span>
236
+ </a>
237
+ <a class="text-gray-400 hover:text-primary transition-colors" href="#">
238
+ <span class="material-symbols-outlined">person</span>
239
+ </a>
240
+ <a class="text-gray-400 hover:text-primary transition-colors" href="#">
241
+ <span class="material-symbols-outlined">share</span>
242
+ </a>
243
+ </div>
244
+ </div>
245
+ </footer>
246
+
247
+ <script>
248
+ // Load and display blog posts
249
+ function loadBlogs() {
250
+ const blogs = JSON.parse(localStorage.getItem('mubashra_blogs_v2')) || [];
251
+ const blogGrid = document.getElementById('blogGrid');
252
+ const noBlogsMessage = document.getElementById('noBlogsMessage');
253
+
254
+ if (blogs.length === 0) {
255
+ blogGrid.classList.add('hidden');
256
+ noBlogsMessage.classList.remove('hidden');
257
+ return;
258
+ }
259
+
260
+ blogGrid.classList.remove('hidden');
261
+ noBlogsMessage.classList.add('hidden');
262
+
263
+ // Show only latest 3 blogs on homepage
264
+ const latestBlogs = blogs.slice(0, 3);
265
+
266
+ blogGrid.innerHTML = latestBlogs.map((blog, index) => {
267
+ const date = new Date(blog.date);
268
+ const formattedDate = date.toLocaleDateString('en-US', {
269
+ month: 'short',
270
+ day: 'numeric',
271
+ year: 'numeric'
272
+ });
273
+
274
+ // Extract first text content for preview
275
+ const tempDiv = document.createElement('div');
276
+ tempDiv.innerHTML = blog.content;
277
+ const textContent = tempDiv.textContent || tempDiv.innerText || '';
278
+ const preview = textContent.substring(0, 120) + (textContent.length > 120 ? '...' : '');
279
+
280
+ // Get first heading for title
281
+ const headingEl = tempDiv.querySelector('h1, h2, h3');
282
+ const title = headingEl ? headingEl.textContent : blog.title;
283
+
284
+ // Categories based on content
285
+ const categories = ['Design', 'Development', 'Minimalism', 'Technology', 'Lifestyle'];
286
+ const category = categories[index % categories.length];
287
+
288
+ // Image HTML - Only show if coverImage exists
289
+ let imageHtml = '';
290
+ if (blog.coverImage) {
291
+ imageHtml = `
292
+ <div class="relative w-full aspect-[16/10] overflow-hidden rounded-xl bg-gray-100 dark:bg-gray-800">
293
+ <div class="absolute inset-0 bg-center bg-cover transition-transform duration-500 group-hover:scale-110"
294
+ style="background-image: url('${blog.coverImage}');">
295
+ </div>
296
+ <div class="absolute top-4 left-4">
297
+ <span class="px-3 py-1 rounded-full bg-white/90 dark:bg-background-dark/90 text-primary text-xs font-bold shadow-sm">${category}</span>
298
+ </div>
299
+ </div>
300
+ `;
301
+ }
302
+
303
+ return `
304
+ <article class="group flex flex-col gap-4 cursor-pointer" onclick="viewBlog(${blog.id})">
305
+ ${imageHtml}
306
+ <div class="flex flex-col gap-2">
307
+ <div class="flex items-center gap-3 text-[#60758a] dark:text-gray-400 text-xs font-medium">
308
+ <span>${formattedDate}</span>
309
+ <span class="size-1 rounded-full bg-gray-300"></span>
310
+ <span>5 min read</span>
311
+ </div>
312
+ <h3 class="text-[#111418] dark:text-white text-xl font-bold leading-snug group-hover:text-primary transition-colors">
313
+ ${title}
314
+ </h3>
315
+ <p class="text-[#60758a] dark:text-gray-400 text-sm leading-relaxed line-clamp-2">
316
+ ${preview}
317
+ </p>
318
+ </div>
319
+ </article>
320
+ `;
321
+ }).join('');
322
+ }
323
+
324
+ // Navigate to blog view page
325
+ function viewBlog(blogId) {
326
+ window.location.href = `blog.html?id=${blogId}`;
327
+ }
328
+
329
+ // Load blogs on page load
330
+ document.addEventListener('DOMContentLoaded', loadBlogs);
331
+ </script>
332
+ </body>
333
+
334
+ </html>
script.js ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ loadBlogs();
3
+ });
4
+
5
+ function loadBlogs() {
6
+ const blogsContainer = document.getElementById('blogsContainer');
7
+ const blogs = JSON.parse(localStorage.getItem('mubashra_blogs_v2')) || [];
8
+
9
+ if (blogs.length > 0) {
10
+ blogsContainer.innerHTML = ''; // Clear empty state
11
+
12
+ blogs.forEach((blog, index) => {
13
+ const card = document.createElement('div');
14
+ card.classList.add('blog-card');
15
+
16
+ // For this version, since the admin creates a free-form "canvas",
17
+ // the safest way to "preview" it is to render the HTML structure.
18
+ // However, to prevent styles from breaking the card, we might scale it or similar.
19
+ // A simple approach: specific card layout.
20
+ // But the user said "place it like canva".
21
+ // So the blog is likely absolute positioned elements on a fixed size canvas.
22
+ // We will render a mini version of that canvas.
23
+
24
+ const previewScale = 0.3; // Scale down for card
25
+
26
+ card.innerHTML = `
27
+ <div class="blog-preview-wrapper" style="position: relative; width: 100%; padding-top: 75%; overflow: hidden; background: ${blog.backgroundColor || 'transparent'};">
28
+ <div class="blog-content-scaler" style="
29
+ position: absolute;
30
+ top: 0;
31
+ left: 0;
32
+ width: 100%;
33
+ transform-origin: top left;
34
+ transform: scale(${previewScale});
35
+ width: ${100 / previewScale}%;
36
+ height: ${100 / previewScale}%;
37
+ pointer-events: none; /* Make it non-interactive in preview */
38
+ ">
39
+ ${blog.content}
40
+ </div>
41
+ </div>
42
+ <div style="padding: 1rem; background: rgba(0,0,0,0.2);">
43
+ <h3 style="margin-bottom: 0.5rem; font-family: var(--font-heading);">${blog.title || 'Untitled Blog'}</h3>
44
+ <p style="font-size: 0.8rem; opacity: 0.7;">${new Date(blog.date).toLocaleDateString()}</p>
45
+ </div>
46
+ `;
47
+
48
+ // Optional: Click to view full blog (Modal or separate page).
49
+ // For now, let's just create a simple 'View' modal logic or leave as cards.
50
+ // The user didn't explicitly ask for a 'View' page, just 'show all blogs'.
51
+ // But 'show' usually implies readability.
52
+
53
+ card.addEventListener('click', () => openBlogModal(blog));
54
+
55
+ blogsContainer.appendChild(card);
56
+ });
57
+ }
58
+ }
59
+
60
+ function openBlogModal(blog) {
61
+ // fast modal implementation
62
+ const modal = document.createElement('div');
63
+ modal.style.cssText = `
64
+ position: fixed; top: 0; left: 0; width: 100%; height: 100%;
65
+ background: rgba(0,0,0,0.9); z-index: 2000; display: flex;
66
+ justify-content: center; align-items: center; overflow: auto;
67
+ padding: 2rem;
68
+ `;
69
+
70
+ // The "Canvas" logic from Admin will likely use a fixed width container.
71
+ // We need to match that. Assuming standard web 1000px or similar.
72
+
73
+ modal.innerHTML = `
74
+ <div style="position: relative; width: 100%; max-width: 1000px; min-height: 80vh; background: ${blog.backgroundColor || '#1a1a2e'}; border-radius: 10px; box-shadow: 0 0 50px rgba(0,0,0,0.5); padding: 2rem; overflow: hidden;">
75
+ <button onclick="this.parentElement.parentElement.remove()" style="position: absolute; top: 1rem; right: 1rem; background: red; border: none; color: white; width: 30px; height: 30px; border-radius: 50%; cursor: pointer; z-index: 100;">X</button>
76
+ <div style="position: relative; width: 100%; height: 100%;">
77
+ ${blog.content}
78
+ </div>
79
+ </div>
80
+ `;
81
+
82
+ document.body.appendChild(modal);
83
+ }
style.css ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --bg-color: #0f0c29;
3
+ --text-color: #ffffff;
4
+ --accent-color: #ff00cc;
5
+ --accent-secondary: #333399;
6
+ --glass-bg: rgba(255, 255, 255, 0.05);
7
+ --glass-border: rgba(255, 255, 255, 0.1);
8
+ --font-heading: 'Playfair Display', serif;
9
+ --font-body: 'Outfit', sans-serif;
10
+ }
11
+
12
+ * {
13
+ margin: 0;
14
+ padding: 0;
15
+ box-sizing: border-box;
16
+ scroll-behavior: smooth;
17
+ }
18
+
19
+ body {
20
+ background-color: var(--bg-color);
21
+ color: var(--text-color);
22
+ font-family: var(--font-body);
23
+ overflow-x: hidden;
24
+ min-height: 100vh;
25
+ }
26
+
27
+ /* Animated Background */
28
+ .background-container {
29
+ position: fixed;
30
+ top: 0;
31
+ left: 0;
32
+ width: 100%;
33
+ height: 100%;
34
+ z-index: -1;
35
+ overflow: hidden;
36
+ }
37
+
38
+ .orb {
39
+ position: absolute;
40
+ border-radius: 50%;
41
+ filter: blur(80px);
42
+ opacity: 0.6;
43
+ animation: float 20s infinite ease-in-out;
44
+ }
45
+
46
+ .orb-1 {
47
+ width: 400px;
48
+ height: 400px;
49
+ background: var(--accent-color);
50
+ top: -100px;
51
+ left: -100px;
52
+ animation-delay: 0s;
53
+ }
54
+
55
+ .orb-2 {
56
+ width: 500px;
57
+ height: 500px;
58
+ background: var(--accent-secondary);
59
+ bottom: -150px;
60
+ right: -150px;
61
+ animation-delay: -5s;
62
+ }
63
+
64
+ .orb-3 {
65
+ width: 300px;
66
+ height: 300px;
67
+ background: #00d4ff;
68
+ top: 40%;
69
+ left: 40%;
70
+ animation-delay: -10s;
71
+ }
72
+
73
+ @keyframes float {
74
+ 0% { transform: translate(0, 0) scale(1); }
75
+ 33% { transform: translate(30px, -50px) scale(1.1); }
76
+ 66% { transform: translate(-20px, 20px) scale(0.9); }
77
+ 100% { transform: translate(0, 0) scale(1); }
78
+ }
79
+
80
+ /* Navigation */
81
+ .glass-nav {
82
+ position: fixed;
83
+ top: 0;
84
+ width: 100%;
85
+ padding: 1.5rem 5%;
86
+ display: flex;
87
+ justify-content: space-between;
88
+ align-items: center;
89
+ background: rgba(15, 12, 41, 0.6);
90
+ backdrop-filter: blur(10px);
91
+ border-bottom: 1px solid var(--glass-border);
92
+ z-index: 1000;
93
+ }
94
+
95
+ .logo {
96
+ font-family: var(--font-heading);
97
+ font-size: 1.8rem;
98
+ font-weight: 700;
99
+ letter-spacing: 1px;
100
+ background: linear-gradient(45deg, #fff, var(--accent-color));
101
+ -webkit-background-clip: text;
102
+ -webkit-text-fill-color: transparent;
103
+ }
104
+
105
+ .nav-links {
106
+ list-style: none;
107
+ display: flex;
108
+ gap: 2rem;
109
+ }
110
+
111
+ .nav-links a {
112
+ text-decoration: none;
113
+ color: var(--text-color);
114
+ font-weight: 600;
115
+ transition: color 0.3s;
116
+ font-size: 1rem;
117
+ }
118
+
119
+ .nav-links a:hover, .nav-links a.admin-link:hover {
120
+ color: var(--accent-color);
121
+ }
122
+
123
+ /* Hero Section */
124
+ .hero-section {
125
+ height: 100vh;
126
+ display: flex;
127
+ justify-content: center;
128
+ align-items: center;
129
+ text-align: center;
130
+ padding: 0 1rem;
131
+ }
132
+
133
+ .hero-content h2 {
134
+ font-size: 2rem;
135
+ font-weight: 300;
136
+ margin-bottom: 1rem;
137
+ opacity: 0.9;
138
+ }
139
+
140
+ .hero-content h1 {
141
+ font-family: var(--font-heading);
142
+ font-size: 5rem;
143
+ margin-bottom: 1rem;
144
+ line-height: 1.1;
145
+ }
146
+
147
+ .gradient-text {
148
+ background: linear-gradient(90deg, #fff, var(--accent-color), #00d4ff);
149
+ background-size: 200% auto;
150
+ -webkit-background-clip: text;
151
+ -webkit-text-fill-color: transparent;
152
+ animation: gradientText 5s linear infinite;
153
+ }
154
+
155
+ @keyframes gradientText {
156
+ 0% { background-position: 0% 50%; }
157
+ 50% { background-position: 100% 50%; }
158
+ 100% { background-position: 0% 50%; }
159
+ }
160
+
161
+ .hero-content p {
162
+ font-size: 1.2rem;
163
+ color: #ccc;
164
+ margin-bottom: 2.5rem;
165
+ }
166
+
167
+ .cta-button {
168
+ display: inline-block;
169
+ padding: 1rem 2.5rem;
170
+ background: var(--accent-color);
171
+ color: white;
172
+ text-decoration: none;
173
+ border-radius: 50px;
174
+ font-weight: 600;
175
+ box-shadow: 0 10px 20px rgba(255, 0, 204, 0.3);
176
+ transition: transform 0.3s, box-shadow 0.3s;
177
+ }
178
+
179
+ .cta-button:hover {
180
+ transform: translateY(-3px);
181
+ box-shadow: 0 15px 30px rgba(255, 0, 204, 0.5);
182
+ }
183
+
184
+ /* Entry Animations */
185
+ .fade-in {
186
+ opacity: 0;
187
+ animation: fadeIn 1s ease-out forwards;
188
+ }
189
+
190
+ .slide-up {
191
+ opacity: 0;
192
+ transform: translateY(30px);
193
+ animation: slideUp 1s ease-out 0.3s forwards;
194
+ }
195
+
196
+ .slide-up-delay {
197
+ opacity: 0;
198
+ transform: translateY(30px);
199
+ animation: slideUp 1s ease-out 0.6s forwards;
200
+ }
201
+
202
+ @keyframes fadeIn { to { opacity: 1; } }
203
+ @keyframes slideUp { to { opacity: 1; transform: translateY(0); } }
204
+
205
+ /* Blogs Section */
206
+ .blogs-section {
207
+ padding: 5rem 5%;
208
+ min-height: 80vh;
209
+ }
210
+
211
+ .section-title {
212
+ font-family: var(--font-heading);
213
+ font-size: 3rem;
214
+ margin-bottom: 3rem;
215
+ text-align: center;
216
+ }
217
+
218
+ .blogs-container {
219
+ display: grid;
220
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
221
+ gap: 2rem;
222
+ }
223
+
224
+ /* Blog Card Styles (Dynamic) */
225
+ .blog-card {
226
+ background: var(--glass-bg);
227
+ border: 1px solid var(--glass-border);
228
+ backdrop-filter: blur(10px);
229
+ border-radius: 16px;
230
+ overflow: hidden;
231
+ transition: transform 0.3s;
232
+ position: relative;
233
+ min-height: 300px; /* Placeholder Aspect Ratio */
234
+ display: flex;
235
+ flex-direction: column;
236
+ }
237
+
238
+ .blog-card:hover {
239
+ transform: translateY(-10px);
240
+ border-color: rgba(255, 255, 255, 0.3);
241
+ }
242
+
243
+ .blog-preview {
244
+ padding: 1rem;
245
+ color: #eee;
246
+ /* Since the blog content is free-form canvas, we might just scale it down or grab a screenshot/thumbnail representation.
247
+ For now, we'll try to just show a preview container. */
248
+ flex-grow: 1;
249
+ overflow: hidden;
250
+ position: relative;
251
+ }
252
+
253
+ .empty-state {
254
+ grid-column: 1 / -1;
255
+ text-align: center;
256
+ padding: 3rem;
257
+ color: rgba(255,255,255,0.5);
258
+ font-size: 1.2rem;
259
+ border: 2px dashed rgba(255,255,255,0.1);
260
+ border-radius: 16px;
261
+ }
262
+
263
+ footer {
264
+ padding: 2rem;
265
+ text-align: center;
266
+ background: rgba(0,0,0,0.3);
267
+ color: rgba(255,255,255,0.5);
268
+ margin-top: auto;
269
+ }