opentwig 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opentwig",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "opentwig 🌿 is an open source link in bio page generator.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -0,0 +1,94 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>OpenTwig Live Editor</title>
7
+ <link rel="stylesheet" href="/live-ui/styles.css">
8
+ </head>
9
+ <body>
10
+ <div class="app-container">
11
+ <header class="app-header">
12
+ <div class="header-left">
13
+ <h1>🌿 OpenTwig Live Editor</h1>
14
+ <span class="status-indicator" id="statusIndicator">
15
+ <span class="status-dot"></span>
16
+ <span class="status-text">Connecting...</span>
17
+ </span>
18
+ </div>
19
+ <div class="header-right">
20
+ <button class="btn btn-primary" id="saveBtn">
21
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
22
+ <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
23
+ <polyline points="17 21 17 13 7 13 7 21"></polyline>
24
+ <polyline points="7 3 7 8 15 8"></polyline>
25
+ </svg>
26
+ Save
27
+ </button>
28
+ <button class="btn btn-secondary" id="exportBtn">
29
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
30
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
31
+ <polyline points="7 10 12 15 17 10"></polyline>
32
+ <line x1="12" y1="15" x2="12" y2="3"></line>
33
+ </svg>
34
+ Export
35
+ </button>
36
+ </div>
37
+ </header>
38
+
39
+ <div class="main-content">
40
+ <div class="preview-container">
41
+ <div class="preview-toolbar">
42
+ <span class="preview-title">Preview</span>
43
+ <button class="refresh-btn" id="refreshBtn" title="Refresh preview">
44
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
45
+ <polyline points="23 4 23 10 17 10"></polyline>
46
+ <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path>
47
+ </svg>
48
+ </button>
49
+ </div>
50
+ <div class="preview-frame">
51
+ <iframe id="previewFrame" src="/index.html" title="Preview"></iframe>
52
+ </div>
53
+ </div>
54
+
55
+ <aside class="sidebar">
56
+ <div class="sidebar-header">
57
+ <h2>Configuration</h2>
58
+ <button class="toggle-sidebar" id="toggleSidebar" title="Toggle sidebar">
59
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
60
+ <line x1="18" y1="6" x2="6" y2="18"></line>
61
+ <line x1="6" y1="6" x2="18" y2="18"></line>
62
+ </svg>
63
+ </button>
64
+ </div>
65
+
66
+ <div class="sidebar-content">
67
+ <div class="config-section" id="configForm">
68
+ <!-- Dynamic form content will be injected here -->
69
+ </div>
70
+ </div>
71
+
72
+ <div class="sidebar-footer">
73
+ <div class="auto-save-toggle">
74
+ <label class="toggle-switch">
75
+ <input type="checkbox" id="autoSave" checked>
76
+ <span class="slider"></span>
77
+ </label>
78
+ <span>Auto-save</span>
79
+ </div>
80
+ <div class="last-saved">
81
+ Last saved: <span id="lastSaved">Never</span>
82
+ </div>
83
+ </div>
84
+ </aside>
85
+ </div>
86
+
87
+ <div class="notification-container" id="notificationContainer"></div>
88
+ </div>
89
+
90
+ <script src="/live-ui/preview.js"></script>
91
+ <script src="/live-ui/editor.js"></script>
92
+ <script src="/live-ui/sidebar.js"></script>
93
+ </body>
94
+ </html>
@@ -0,0 +1,578 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ body {
8
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
9
+ background: #f5f5f5;
10
+ color: #333;
11
+ overflow: hidden;
12
+ }
13
+
14
+ .app-container {
15
+ display: flex;
16
+ flex-direction: column;
17
+ height: 100vh;
18
+ overflow: hidden;
19
+ }
20
+
21
+ .header {
22
+ display: flex;
23
+ justify-content: space-between;
24
+ align-items: center;
25
+ padding: 12px 24px;
26
+ background: #fff;
27
+ border-bottom: 1px solid #e5e5e5;
28
+ }
29
+
30
+ .app-header {
31
+ display: flex;
32
+ justify-content: space-between;
33
+ align-items: center;
34
+ padding: 12px 24px;
35
+ background: #fff;
36
+ border-bottom: 1px solid #e5e5e5;
37
+ height: 60px;
38
+ flex-shrink: 0;
39
+ }
40
+
41
+ .header-left {
42
+ display: flex;
43
+ align-items: center;
44
+ gap: 16px;
45
+ }
46
+
47
+ .app-header h1 {
48
+ font-size: 18px;
49
+ font-weight: 600;
50
+ color: #2c3e50;
51
+ }
52
+
53
+ .status-indicator {
54
+ display: flex;
55
+ align-items: center;
56
+ gap: 6px;
57
+ font-size: 13px;
58
+ color: #666;
59
+ }
60
+
61
+ .status-dot {
62
+ width: 8px;
63
+ height: 8px;
64
+ border-radius: 50%;
65
+ background: #ccc;
66
+ animation: pulse 2s infinite;
67
+ }
68
+
69
+ .status-dot.connected {
70
+ background: #52c41a;
71
+ }
72
+
73
+ .status-dot.disconnected {
74
+ background: #f5222d;
75
+ }
76
+
77
+ @keyframes pulse {
78
+ 0%, 100% {
79
+ opacity: 1;
80
+ }
81
+ 50% {
82
+ opacity: 0.5;
83
+ }
84
+ }
85
+
86
+ .header-right {
87
+ display: flex;
88
+ gap: 8px;
89
+ }
90
+
91
+ .btn {
92
+ display: inline-flex;
93
+ align-items: center;
94
+ gap: 6px;
95
+ padding: 8px 16px;
96
+ border: none;
97
+ border-radius: 6px;
98
+ font-size: 14px;
99
+ font-weight: 500;
100
+ cursor: pointer;
101
+ transition: all 0.2s;
102
+ }
103
+
104
+ .btn-primary {
105
+ background: #2c3e50;
106
+ color: #fff;
107
+ }
108
+
109
+ .btn-primary:hover {
110
+ background: #1a252f;
111
+ transform: translateY(-1px);
112
+ }
113
+
114
+ .btn-secondary {
115
+ background: #fff;
116
+ color: #2c3e50;
117
+ border: 1px solid #d9d9d9;
118
+ }
119
+
120
+ .btn-secondary:hover {
121
+ background: #f5f5f5;
122
+ border-color: #40a9ff;
123
+ }
124
+
125
+ .main-content {
126
+ display: flex;
127
+ flex: 1;
128
+ overflow: hidden;
129
+ }
130
+
131
+ .preview-container {
132
+ flex: 1;
133
+ display: flex;
134
+ flex-direction: column;
135
+ overflow: hidden;
136
+ }
137
+
138
+ .preview-toolbar {
139
+ display: flex;
140
+ justify-content: space-between;
141
+ align-items: center;
142
+ padding: 8px 16px;
143
+ background: #fff;
144
+ border-bottom: 1px solid #e5e5e5;
145
+ }
146
+
147
+ .preview-title {
148
+ font-size: 13px;
149
+ font-weight: 500;
150
+ color: #666;
151
+ }
152
+
153
+ .refresh-btn {
154
+ display: inline-flex;
155
+ align-items: center;
156
+ justify-content: center;
157
+ padding: 6px;
158
+ border: none;
159
+ background: #f5f5f5;
160
+ border-radius: 4px;
161
+ cursor: pointer;
162
+ transition: all 0.2s;
163
+ }
164
+
165
+ .refresh-btn:hover {
166
+ background: #e8e8e8;
167
+ }
168
+
169
+ .refresh-btn svg {
170
+ stroke: #666;
171
+ }
172
+
173
+ .preview-frame {
174
+ flex: 1;
175
+ background: #f0f2f5;
176
+ overflow: hidden;
177
+ }
178
+
179
+ #previewFrame {
180
+ width: 100%;
181
+ height: 100%;
182
+ border: none;
183
+ background: #fff;
184
+ }
185
+
186
+ .sidebar {
187
+ width: 400px;
188
+ display: flex;
189
+ flex-direction: column;
190
+ background: #fff;
191
+ border-left: 1px solid #e5e5e5;
192
+ overflow: hidden;
193
+ transition: width 0.3s ease;
194
+ }
195
+
196
+ .sidebar.collapsed {
197
+ width: 0;
198
+ }
199
+
200
+ .sidebar-header {
201
+ display: flex;
202
+ justify-content: space-between;
203
+ align-items: center;
204
+ padding: 16px;
205
+ border-bottom: 1px solid #e5e5e5;
206
+ background: #fafafa;
207
+ }
208
+
209
+ .sidebar-header h2 {
210
+ font-size: 14px;
211
+ font-weight: 600;
212
+ color: #2c3e50;
213
+ }
214
+
215
+ .toggle-sidebar {
216
+ display: inline-flex;
217
+ align-items: center;
218
+ justify-content: center;
219
+ padding: 4px;
220
+ border: none;
221
+ background: transparent;
222
+ cursor: pointer;
223
+ border-radius: 4px;
224
+ transition: all 0.2s;
225
+ }
226
+
227
+ .toggle-sidebar:hover {
228
+ background: #e8e8e8;
229
+ }
230
+
231
+ .toggle-sidebar svg {
232
+ stroke: #666;
233
+ }
234
+
235
+ .sidebar-content {
236
+ flex: 1;
237
+ overflow-y: auto;
238
+ padding: 16px;
239
+ }
240
+
241
+ .config-section {
242
+ display: flex;
243
+ flex-direction: column;
244
+ gap: 20px;
245
+ }
246
+
247
+ .section-title {
248
+ font-size: 12px;
249
+ font-weight: 600;
250
+ text-transform: uppercase;
251
+ color: #666;
252
+ margin-bottom: 12px;
253
+ letter-spacing: 0.5px;
254
+ }
255
+
256
+ .form-group {
257
+ margin-bottom: 16px;
258
+ }
259
+
260
+ .form-group label {
261
+ display: block;
262
+ font-size: 13px;
263
+ font-weight: 500;
264
+ color: #333;
265
+ margin-bottom: 6px;
266
+ }
267
+
268
+ .form-group input[type="text"],
269
+ .form-group input[type="url"],
270
+ .form-group textarea,
271
+ .form-group select {
272
+ width: 100%;
273
+ padding: 8px 12px;
274
+ border: 1px solid #d9d9d9;
275
+ border-radius: 6px;
276
+ font-size: 13px;
277
+ transition: all 0.2s;
278
+ }
279
+
280
+ .form-group textarea {
281
+ min-height: 80px;
282
+ resize: vertical;
283
+ font-family: inherit;
284
+ }
285
+
286
+ .form-group input:focus,
287
+ .form-group textarea:focus,
288
+ .form-group select:focus {
289
+ outline: none;
290
+ border-color: #40a9ff;
291
+ box-shadow: 0 0 0 2px rgba(64, 169, 255, 0.1);
292
+ }
293
+
294
+ .link-item {
295
+ background: #f5f5f5;
296
+ border: 1px solid #e5e5e5;
297
+ border-radius: 6px;
298
+ padding: 12px;
299
+ margin-bottom: 8px;
300
+ }
301
+
302
+ .link-item-header {
303
+ display: flex;
304
+ justify-content: space-between;
305
+ align-items: center;
306
+ margin-bottom: 8px;
307
+ }
308
+
309
+ .link-item-title {
310
+ font-size: 12px;
311
+ font-weight: 500;
312
+ color: #666;
313
+ }
314
+
315
+ .link-item-actions {
316
+ display: flex;
317
+ gap: 4px;
318
+ }
319
+
320
+ .link-item-actions button {
321
+ display: inline-flex;
322
+ align-items: center;
323
+ justify-content: center;
324
+ padding: 4px;
325
+ border: none;
326
+ background: transparent;
327
+ cursor: pointer;
328
+ border-radius: 4px;
329
+ transition: all 0.2s;
330
+ }
331
+
332
+ .link-item-actions button:hover {
333
+ background: #e8e8e8;
334
+ }
335
+
336
+ .link-item-actions button svg {
337
+ width: 14px;
338
+ height: 14px;
339
+ stroke: #666;
340
+ }
341
+
342
+ .add-link-btn {
343
+ width: 100%;
344
+ padding: 8px;
345
+ border: 1px dashed #d9d9d9;
346
+ border-radius: 6px;
347
+ background: transparent;
348
+ color: #40a9ff;
349
+ font-size: 13px;
350
+ font-weight: 500;
351
+ cursor: pointer;
352
+ transition: all 0.2s;
353
+ }
354
+
355
+ .add-link-btn:hover {
356
+ background: rgba(64, 169, 255, 0.05);
357
+ border-color: #40a9ff;
358
+ }
359
+
360
+ .theme-grid {
361
+ display: grid;
362
+ grid-template-columns: repeat(2, 1fr);
363
+ gap: 8px;
364
+ }
365
+
366
+ .theme-card {
367
+ padding: 12px;
368
+ border: 1px solid #d9d9d9;
369
+ border-radius: 6px;
370
+ cursor: pointer;
371
+ transition: all 0.2s;
372
+ text-align: center;
373
+ }
374
+
375
+ .theme-card:hover {
376
+ border-color: #40a9ff;
377
+ background: rgba(64, 169, 255, 0.05);
378
+ }
379
+
380
+ .theme-card.active {
381
+ border-color: #40a9ff;
382
+ background: rgba(64, 169, 255, 0.1);
383
+ }
384
+
385
+ .theme-card-name {
386
+ font-size: 12px;
387
+ font-weight: 500;
388
+ color: #333;
389
+ }
390
+
391
+ .avatar-upload {
392
+ display: flex;
393
+ align-items: center;
394
+ gap: 12px;
395
+ padding: 12px;
396
+ border: 2px dashed #d9d9d9;
397
+ border-radius: 6px;
398
+ cursor: pointer;
399
+ transition: all 0.2s;
400
+ }
401
+
402
+ .avatar-upload:hover {
403
+ border-color: #40a9ff;
404
+ background: rgba(64, 169, 255, 0.05);
405
+ }
406
+
407
+ .avatar-preview {
408
+ width: 48px;
409
+ height: 48px;
410
+ border-radius: 50%;
411
+ background: #f5f5f5;
412
+ object-fit: cover;
413
+ }
414
+
415
+ .avatar-upload-text {
416
+ flex: 1;
417
+ font-size: 12px;
418
+ color: #666;
419
+ }
420
+
421
+ .sidebar-footer {
422
+ padding: 16px;
423
+ border-top: 1px solid #e5e5e5;
424
+ background: #fafafa;
425
+ }
426
+
427
+ .auto-save-toggle {
428
+ display: flex;
429
+ align-items: center;
430
+ gap: 8px;
431
+ margin-bottom: 8px;
432
+ }
433
+
434
+ .toggle-switch {
435
+ position: relative;
436
+ display: inline-block;
437
+ width: 36px;
438
+ height: 20px;
439
+ }
440
+
441
+ .toggle-switch input {
442
+ opacity: 0;
443
+ width: 0;
444
+ height: 0;
445
+ }
446
+
447
+ .slider {
448
+ position: absolute;
449
+ cursor: pointer;
450
+ top: 0;
451
+ left: 0;
452
+ right: 0;
453
+ bottom: 0;
454
+ background-color: #ccc;
455
+ transition: .4s;
456
+ border-radius: 20px;
457
+ }
458
+
459
+ .slider:before {
460
+ position: absolute;
461
+ content: "";
462
+ height: 14px;
463
+ width: 14px;
464
+ left: 3px;
465
+ bottom: 3px;
466
+ background-color: white;
467
+ transition: .4s;
468
+ border-radius: 50%;
469
+ }
470
+
471
+ input:checked + .slider {
472
+ background-color: #2c3e50;
473
+ }
474
+
475
+ input:checked + .slider:before {
476
+ transform: translateX(16px);
477
+ }
478
+
479
+ .auto-save-toggle span:last-child {
480
+ font-size: 12px;
481
+ color: #666;
482
+ }
483
+
484
+ .last-saved {
485
+ font-size: 11px;
486
+ color: #999;
487
+ }
488
+
489
+ .notification-container {
490
+ position: fixed;
491
+ top: 20px;
492
+ right: 20px;
493
+ z-index: 9999;
494
+ display: flex;
495
+ flex-direction: column;
496
+ gap: 8px;
497
+ }
498
+
499
+ .notification {
500
+ display: flex;
501
+ align-items: center;
502
+ gap: 8px;
503
+ padding: 12px 16px;
504
+ border-radius: 6px;
505
+ background: #fff;
506
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
507
+ font-size: 13px;
508
+ animation: slideIn 0.3s ease-out;
509
+ max-width: 300px;
510
+ }
511
+
512
+ .notification.success {
513
+ border-left: 4px solid #52c41a;
514
+ }
515
+
516
+ .notification.error {
517
+ border-left: 4px solid #f5222d;
518
+ }
519
+
520
+ .notification.info {
521
+ border-left: 4px solid #40a9ff;
522
+ }
523
+
524
+ @keyframes slideIn {
525
+ from {
526
+ transform: translateX(100%);
527
+ opacity: 0;
528
+ }
529
+ to {
530
+ transform: translateX(0);
531
+ opacity: 1;
532
+ }
533
+ }
534
+
535
+ @media (max-width: 1024px) {
536
+ .sidebar {
537
+ position: fixed;
538
+ right: 0;
539
+ top: 60px;
540
+ bottom: 0;
541
+ z-index: 1000;
542
+ box-shadow: -4px 0 12px rgba(0, 0, 0, 0.15);
543
+ }
544
+
545
+ .sidebar.collapsed {
546
+ right: -400px;
547
+ }
548
+
549
+ .preview-toolbar {
550
+ padding: 8px 12px;
551
+ }
552
+ }
553
+
554
+ .loading {
555
+ display: flex;
556
+ align-items: center;
557
+ justify-content: center;
558
+ padding: 40px;
559
+ font-size: 13px;
560
+ color: #666;
561
+ }
562
+
563
+ .loading::after {
564
+ content: "";
565
+ width: 20px;
566
+ height: 20px;
567
+ margin-left: 12px;
568
+ border: 2px solid #e5e5e5;
569
+ border-top-color: #40a9ff;
570
+ border-radius: 50%;
571
+ animation: spin 0.8s linear infinite;
572
+ }
573
+
574
+ @keyframes spin {
575
+ to {
576
+ transform: rotate(360deg);
577
+ }
578
+ }
@@ -0,0 +1,11 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ %sveltekit.head%
7
+ </head>
8
+ <body data-sveltekit-preload-data="hover">
9
+ <div style="display: contents">%sveltekit.body%</div>
10
+ </body>
11
+ </html>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#16a34a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2
+ <path d="M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z"/>
3
+ <path d="M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12"/>
4
+ </svg>
@@ -0,0 +1,199 @@
1
+ @import "tailwindcss";
2
+
3
+ @import "tw-animate-css";
4
+
5
+ @custom-variant dark (&:is(.dark *));
6
+
7
+ :root {
8
+ --radius: 0.75rem;
9
+ --background: #f8faf8;
10
+ --foreground: #1a2e1a;
11
+ --card: #ffffff;
12
+ --card-foreground: #1a2e1a;
13
+ --popover: #ffffff;
14
+ --popover-foreground: #1a2e1a;
15
+ --primary: #2d5a3d;
16
+ --primary-foreground: #ffffff;
17
+ --secondary: #e8f0e8;
18
+ --secondary-foreground: #2d5a3d;
19
+ --muted: #e8f0e8;
20
+ --muted-foreground: #5a7a5a;
21
+ --accent: #4a7c59;
22
+ --accent-foreground: #ffffff;
23
+ --destructive: #dc2626;
24
+ --border: #d4e4d4;
25
+ --input: #d4e4d4;
26
+ --ring: #4a7c59;
27
+ --chart-1: #2d5a3d;
28
+ --chart-2: #4a7c59;
29
+ --chart-3: #6b9b7a;
30
+ --chart-4: #8cb89a;
31
+ --chart-5: #c8e0c8;
32
+ --sidebar: #f0f7f0;
33
+ --sidebar-foreground: #1a2e1a;
34
+ --sidebar-primary: #2d5a3d;
35
+ --sidebar-primary-foreground: #ffffff;
36
+ --sidebar-accent: #e8f0e8;
37
+ --sidebar-accent-foreground: #2d5a3d;
38
+ --sidebar-border: #d4e4d4;
39
+ --sidebar-ring: #4a7c59;
40
+ }
41
+
42
+ .dark {
43
+ --background: #0d1f12;
44
+ --foreground: #e8f0e8;
45
+ --card: #1a3320;
46
+ --card-foreground: #e8f0e8;
47
+ --popover: #1a3320;
48
+ --popover-foreground: #e8f0e8;
49
+ --primary: #6b9b7a;
50
+ --primary-foreground: #0d1f12;
51
+ --secondary: #2d4a35;
52
+ --secondary-foreground: #e8f0e8;
53
+ --muted: #2d4a35;
54
+ --muted-foreground: #8cb89a;
55
+ --accent: #4a7c59;
56
+ --accent-foreground: #ffffff;
57
+ --destructive: #ef4444;
58
+ --border: #2d4a35;
59
+ --input: #2d4a35;
60
+ --ring: #6b9b7a;
61
+ --chart-1: #6b9b7a;
62
+ --chart-2: #4a7c59;
63
+ --chart-3: #8cb89a;
64
+ --chart-4: #a8d4a8;
65
+ --chart-5: #2d5a3d;
66
+ --sidebar: #1a3320;
67
+ --sidebar-foreground: #e8f0e8;
68
+ --sidebar-primary: #6b9b7a;
69
+ --sidebar-primary-foreground: #0d1f12;
70
+ --sidebar-accent: #2d4a35;
71
+ --sidebar-accent-foreground: #e8f0e8;
72
+ --sidebar-border: #2d4a35;
73
+ --sidebar-ring: #6b9b7a;
74
+ }
75
+
76
+ @theme inline {
77
+ --radius-sm: calc(var(--radius) - 4px);
78
+ --radius-md: calc(var(--radius) - 2px);
79
+ --radius-lg: var(--radius);
80
+ --radius-xl: calc(var(--radius) + 4px);
81
+ --color-background: var(--background);
82
+ --color-foreground: var(--foreground);
83
+ --color-card: var(--card);
84
+ --color-card-foreground: var(--card-foreground);
85
+ --color-popover: var(--popover);
86
+ --color-popover-foreground: var(--popover-foreground);
87
+ --color-primary: var(--primary);
88
+ --color-primary-foreground: var(--primary-foreground);
89
+ --color-secondary: var(--secondary);
90
+ --color-secondary-foreground: var(--secondary-foreground);
91
+ --color-muted: var(--muted);
92
+ --color-muted-foreground: var(--muted-foreground);
93
+ --color-accent: var(--accent);
94
+ --color-accent-foreground: var(--accent-foreground);
95
+ --color-destructive: var(--destructive);
96
+ --color-border: var(--border);
97
+ --color-input: var(--input);
98
+ --color-ring: var(--ring);
99
+ --color-chart-1: var(--chart-1);
100
+ --color-chart-2: var(--chart-2);
101
+ --color-chart-3: var(--chart-3);
102
+ --color-chart-4: var(--chart-4);
103
+ --color-chart-5: var(--chart-5);
104
+ --color-sidebar: var(--sidebar);
105
+ --color-sidebar-foreground: var(--sidebar-foreground);
106
+ --color-sidebar-primary: var(--sidebar-primary);
107
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
108
+ --color-sidebar-accent: var(--sidebar-accent);
109
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
110
+ --color-sidebar-border: var(--sidebar-border);
111
+ --color-sidebar-ring: var(--sidebar-ring);
112
+ }
113
+
114
+ @layer base {
115
+ * {
116
+ @apply border-border outline-ring/50;
117
+ }
118
+ body {
119
+ @apply bg-background text-foreground antialiased;
120
+ font-feature-settings: "rlig" 1, "calt" 1;
121
+ }
122
+ html {
123
+ scroll-behavior: smooth;
124
+ }
125
+ }
126
+
127
+ @layer utilities {
128
+ .text-balance {
129
+ text-wrap: balance;
130
+ }
131
+ .gradient-text {
132
+ background: linear-gradient(135deg, #2d5a3d 0%, #4a7c59 50%, #6b9b7a 100%);
133
+ -webkit-background-clip: text;
134
+ -webkit-text-fill-color: transparent;
135
+ background-clip: text;
136
+ }
137
+ .gradient-border {
138
+ background: linear-gradient(135deg, #d4e4d4 0%, #c8e0c8 50%, #b8d4b8 100%);
139
+ padding: 1px;
140
+ border-radius: var(--radius);
141
+ }
142
+ .leaf-pattern {
143
+ background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M30 5c-2 5-8 10-15 10 7 0 13 5 15 10 2-5 8-10 15-10-7 0-13-5-15-10z' fill='%234a7c59' fill-opacity='0.03'/%3E%3C/svg%3E");
144
+ }
145
+ .animate-float {
146
+ animation: float 6s ease-in-out infinite;
147
+ }
148
+ .animate-float-delayed {
149
+ animation: float 6s ease-in-out infinite;
150
+ animation-delay: 2s;
151
+ }
152
+ .animate-float-delayed-2 {
153
+ animation: float 6s ease-in-out infinite;
154
+ animation-delay: 4s;
155
+ }
156
+ @keyframes float {
157
+ 0%, 100% { transform: translateY(0px); }
158
+ 50% { transform: translateY(-20px); }
159
+ }
160
+ }
161
+
162
+ /* Custom scrollbar */
163
+ ::-webkit-scrollbar {
164
+ width: 8px;
165
+ height: 8px;
166
+ }
167
+
168
+ ::-webkit-scrollbar-track {
169
+ background: var(--secondary);
170
+ }
171
+
172
+ ::-webkit-scrollbar-thumb {
173
+ background: var(--muted-foreground);
174
+ border-radius: 4px;
175
+ }
176
+
177
+ ::-webkit-scrollbar-thumb:hover {
178
+ background: var(--primary);
179
+ }
180
+
181
+ /* Code block styling */
182
+ pre {
183
+ background: #1a3320 !important;
184
+ border-radius: var(--radius);
185
+ padding: 1.5rem;
186
+ overflow-x: auto;
187
+ }
188
+
189
+ code {
190
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
191
+ font-size: 0.875rem;
192
+ line-height: 1.7;
193
+ }
194
+
195
+ /* Selection styling */
196
+ ::selection {
197
+ background: rgba(74, 124, 89, 0.3);
198
+ color: inherit;
199
+ }
Binary file
Binary file
Binary file
Binary file