Lucasrds commited on
Commit
84a8c4d
·
verified ·
1 Parent(s): f783160

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +1046 -19
index.html CHANGED
@@ -1,19 +1,1046 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Obramax Flyer Gen - Gerador de Flyers de Promoções</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
9
+ <style>
10
+ :root {
11
+ --primary: #e63946;
12
+ --secondary: #f4a261;
13
+ --accent: #2a9d8f;
14
+ --dark: #1d3557;
15
+ --light: #f1faee;
16
+ --bg: #f8f9fa;
17
+ --glass: rgba(255, 255, 255, 0.85);
18
+ --shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
19
+ --radius: 16px;
20
+ --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
21
+ }
22
+
23
+ * {
24
+ margin: 0;
25
+ padding: 0;
26
+ box-sizing: border-box;
27
+ }
28
+
29
+ body {
30
+ font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
31
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
32
+ min-height: 100vh;
33
+ color: var(--dark);
34
+ }
35
+
36
+ /* Header */
37
+ .header {
38
+ background: linear-gradient(90deg, var(--dark) 0%, #2c3e50 100%);
39
+ color: white;
40
+ padding: 1rem 2rem;
41
+ display: flex;
42
+ justify-content: space-between;
43
+ align-items: center;
44
+ box-shadow: 0 4px 20px rgba(0,0,0,0.15);
45
+ position: sticky;
46
+ top: 0;
47
+ z-index: 100;
48
+ flex-wrap: wrap;
49
+ gap: 1rem;
50
+ }
51
+
52
+ .header-brand {
53
+ display: flex;
54
+ align-items: center;
55
+ gap: 12px;
56
+ font-size: 1.5rem;
57
+ font-weight: 800;
58
+ letter-spacing: -0.5px;
59
+ }
60
+
61
+ .header-brand i {
62
+ color: var(--secondary);
63
+ font-size: 1.8rem;
64
+ }
65
+
66
+ .header-link {
67
+ color: rgba(255,255,255,0.85);
68
+ text-decoration: none;
69
+ font-size: 0.85rem;
70
+ font-weight: 500;
71
+ padding: 6px 12px;
72
+ border: 1px solid rgba(255,255,255,0.3);
73
+ border-radius: 20px;
74
+ transition: var(--transition);
75
+ }
76
+
77
+ .header-link:hover {
78
+ background: rgba(255,255,255,0.15);
79
+ color: white;
80
+ transform: translateY(-1px);
81
+ }
82
+
83
+ /* Layout Principal */
84
+ .app-container {
85
+ display: grid;
86
+ grid-template-columns: 380px 1fr;
87
+ max-width: 1400px;
88
+ margin: 2rem auto;
89
+ padding: 0 1.5rem;
90
+ gap: 2rem;
91
+ min-height: calc(100vh - 100px);
92
+ }
93
+
94
+ /* Painel de Controle */
95
+ .controls-panel {
96
+ background: var(--glass);
97
+ backdrop-filter: blur(12px);
98
+ -webkit-backdrop-filter: blur(12px);
99
+ border-radius: var(--radius);
100
+ padding: 1.5rem;
101
+ box-shadow: var(--shadow);
102
+ border: 1px solid rgba(255,255,255,0.5);
103
+ height: fit-content;
104
+ position: sticky;
105
+ top: 90px;
106
+ overflow-y: auto;
107
+ max-height: calc(100vh - 110px);
108
+ }
109
+
110
+ .panel-title {
111
+ font-size: 1.25rem;
112
+ font-weight: 700;
113
+ margin-bottom: 1.5rem;
114
+ display: flex;
115
+ align-items: center;
116
+ gap: 8px;
117
+ color: var(--dark);
118
+ padding-bottom: 0.75rem;
119
+ border-bottom: 2px solid var(--secondary);
120
+ }
121
+
122
+ .form-group {
123
+ margin-bottom: 1.25rem;
124
+ }
125
+
126
+ .form-group label {
127
+ display: block;
128
+ font-weight: 600;
129
+ font-size: 0.85rem;
130
+ margin-bottom: 0.5rem;
131
+ color: var(--dark);
132
+ opacity: 0.9;
133
+ }
134
+
135
+ .form-control {
136
+ width: 100%;
137
+ padding: 0.75rem 1rem;
138
+ border: 2px solid #e2e8f0;
139
+ border-radius: 10px;
140
+ font-family: inherit;
141
+ font-size: 0.9rem;
142
+ transition: var(--transition);
143
+ background: rgba(255,255,255,0.9);
144
+ }
145
+
146
+ .form-control:focus {
147
+ outline: none;
148
+ border-color: var(--accent);
149
+ box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.15);
150
+ }
151
+
152
+ input[type="color"].form-control {
153
+ height: 42px;
154
+ padding: 4px;
155
+ cursor: pointer;
156
+ }
157
+
158
+ .color-row {
159
+ display: grid;
160
+ grid-template-columns: 1fr 1fr;
161
+ gap: 1rem;
162
+ }
163
+
164
+ .btn {
165
+ display: inline-flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ gap: 8px;
169
+ padding: 0.75rem 1.25rem;
170
+ border: none;
171
+ border-radius: 10px;
172
+ font-family: inherit;
173
+ font-weight: 600;
174
+ font-size: 0.9rem;
175
+ cursor: pointer;
176
+ transition: var(--transition);
177
+ }
178
+
179
+ .btn-primary {
180
+ background: linear-gradient(135deg, var(--primary), #d62839);
181
+ color: white;
182
+ box-shadow: 0 4px 15px rgba(230, 57, 70, 0.3);
183
+ width: 100%;
184
+ margin-top: 0.5rem;
185
+ }
186
+
187
+ .btn-primary:hover {
188
+ transform: translateY(-2px);
189
+ box-shadow: 0 6px 20px rgba(230, 57, 70, 0.4);
190
+ }
191
+
192
+ .btn-secondary {
193
+ background: linear-gradient(135deg, var(--dark), #2c3e50);
194
+ color: white;
195
+ width: 100%;
196
+ margin-top: 1rem;
197
+ padding: 1rem;
198
+ font-size: 1rem;
199
+ }
200
+
201
+ .btn-secondary:hover {
202
+ transform: translateY(-2px);
203
+ box-shadow: 0 6px 20px rgba(29, 53, 87, 0.3);
204
+ }
205
+
206
+ .btn-small {
207
+ padding: 0.4rem 0.8rem;
208
+ font-size: 0.8rem;
209
+ background: var(--primary);
210
+ color: white;
211
+ border-radius: 6px;
212
+ }
213
+
214
+ .btn-danger {
215
+ background: #e63946;
216
+ color: white;
217
+ padding: 0.4rem;
218
+ border-radius: 6px;
219
+ width: 32px;
220
+ height: 32px;
221
+ }
222
+
223
+ /* Lista de Produtos no Painel */
224
+ .products-list {
225
+ display: flex;
226
+ flex-direction: column;
227
+ gap: 1rem;
228
+ margin-top: 1rem;
229
+ }
230
+
231
+ .product-editor {
232
+ background: white;
233
+ border: 2px solid #edf2f7;
234
+ border-radius: 12px;
235
+ padding: 1rem;
236
+ position: relative;
237
+ transition: var(--transition);
238
+ }
239
+
240
+ .product-editor:hover {
241
+ border-color: var(--secondary);
242
+ box-shadow: 0 4px 12px rgba(0,0,0,0.05);
243
+ }
244
+
245
+ .product-header {
246
+ display: flex;
247
+ justify-content: space-between;
248
+ align-items: center;
249
+ margin-bottom: 0.75rem;
250
+ }
251
+
252
+ .product-header span {
253
+ font-weight: 700;
254
+ font-size: 0.85rem;
255
+ color: var(--dark);
256
+ }
257
+
258
+ .product-fields {
259
+ display: grid;
260
+ gap: 0.5rem;
261
+ }
262
+
263
+ .layout-selector {
264
+ display: grid;
265
+ grid-template-columns: 1fr 1fr;
266
+ gap: 0.75rem;
267
+ margin-top: 0.5rem;
268
+ }
269
+
270
+ .layout-option {
271
+ border: 2px solid #e2e8f0;
272
+ border-radius: 10px;
273
+ padding: 0.75rem;
274
+ text-align: center;
275
+ cursor: pointer;
276
+ transition: var(--transition);
277
+ background: white;
278
+ }
279
+
280
+ .layout-option.active {
281
+ border-color: var(--accent);
282
+ background: rgba(42, 157, 143, 0.05);
283
+ color: var(--accent);
284
+ }
285
+
286
+ .layout-option:hover:not(.active) {
287
+ border-color: #cbd5e0;
288
+ }
289
+
290
+ .layout-option i {
291
+ font-size: 1.25rem;
292
+ margin-bottom: 4px;
293
+ display: block;
294
+ }
295
+
296
+ .layout-option span {
297
+ font-size: 0.75rem;
298
+ font-weight: 600;
299
+ }
300
+
301
+ /* Preview Area */
302
+ .preview-area {
303
+ display: flex;
304
+ flex-direction: column;
305
+ align-items: center;
306
+ gap: 1.5rem;
307
+ }
308
+
309
+ .preview-wrapper {
310
+ background: white;
311
+ padding: 2rem;
312
+ border-radius: var(--radius);
313
+ box-shadow: var(--shadow);
314
+ width: 100%;
315
+ max-width: 600px;
316
+ display: flex;
317
+ justify-content: center;
318
+ align-items: flex-start;
319
+ position: relative;
320
+ overflow: hidden;
321
+ }
322
+
323
+ /* O Flyer em si */
324
+ #flyer-canvas {
325
+ width: 100%;
326
+ max-width: 550px;
327
+ aspect-ratio: 3/4;
328
+ background: white;
329
+ position: relative;
330
+ overflow: hidden;
331
+ box-shadow: 0 20px 60px rgba(0,0,0,0.15);
332
+ display: flex;
333
+ flex-direction: column;
334
+ }
335
+
336
+ /* Flyer Header */
337
+ .flyer-header {
338
+ padding: 2rem;
339
+ text-align: center;
340
+ position: relative;
341
+ overflow: hidden;
342
+ }
343
+
344
+ .flyer-header::before {
345
+ content: '';
346
+ position: absolute;
347
+ top: -50%;
348
+ left: -50%;
349
+ width: 200%;
350
+ height: 200%;
351
+ background: radial-gradient(circle, rgba(255,255,255,0.2) 0%, transparent 60%);
352
+ pointer-events: none;
353
+ }
354
+
355
+ .flyer-logo {
356
+ font-size: 2rem;
357
+ font-weight: 900;
358
+ letter-spacing: 2px;
359
+ margin-bottom: 0.5rem;
360
+ position: relative;
361
+ z-index: 1;
362
+ text-transform: uppercase;
363
+ }
364
+
365
+ .flyer-title {
366
+ font-size: 2.5rem;
367
+ font-weight: 900;
368
+ margin-bottom: 0.5rem;
369
+ position: relative;
370
+ z-index: 1;
371
+ line-height: 1.1;
372
+ text-transform: uppercase;
373
+ letter-spacing: -1px;
374
+ }
375
+
376
+ .flyer-subtitle {
377
+ font-size: 1.1rem;
378
+ font-weight: 600;
379
+ opacity: 0.95;
380
+ position: relative;
381
+ z-index: 1;
382
+ }
383
+
384
+ /* Flyer Body */
385
+ .flyer-body {
386
+ flex: 1;
387
+ padding: 1.5rem;
388
+ display: grid;
389
+ gap: 1rem;
390
+ align-content: start;
391
+ overflow: hidden;
392
+ }
393
+
394
+ .flyer-body.grid-layout {
395
+ grid-template-columns: repeat(2, 1fr);
396
+ }
397
+
398
+ .flyer-body.list-layout {
399
+ grid-template-columns: 1fr;
400
+ }
401
+
402
+ /* Product Card */
403
+ .flyer-product {
404
+ background: white;
405
+ border-radius: 12px;
406
+ overflow: hidden;
407
+ box-shadow: 0 4px 15px rgba(0,0,0,0.08);
408
+ display: flex;
409
+ flex-direction: column;
410
+ position: relative;
411
+ border: 2px solid transparent;
412
+ transition: transform 0.2s;
413
+ }
414
+
415
+ .grid-layout .flyer-product {
416
+ aspect-ratio: 1/1.2;
417
+ }
418
+
419
+ .list-layout .flyer-product {
420
+ flex-direction: row;
421
+ align-items: center;
422
+ height: 120px;
423
+ }
424
+
425
+ .flyer-product:hover {
426
+ transform: scale(1.02);
427
+ }
428
+
429
+ .product-badge {
430
+ position: absolute;
431
+ top: 8px;
432
+ right: 8px;
433
+ background: #e63946;
434
+ color: white;
435
+ font-weight: 800;
436
+ font-size: 0.75rem;
437
+ padding: 4px 8px;
438
+ border-radius: 20px;
439
+ z-index: 2;
440
+ box-shadow: 0 2px 8px rgba(0,0,0,0.15);
441
+ }
442
+
443
+ .product-image {
444
+ width: 100%;
445
+ height: 60%;
446
+ object-fit: cover;
447
+ background: #f1f5f9;
448
+ display: flex;
449
+ align-items: center;
450
+ justify-content: center;
451
+ color: #94a3b8;
452
+ font-size: 2.5rem;
453
+ }
454
+
455
+ .list-layout .product-image {
456
+ width: 120px;
457
+ height: 100%;
458
+ }
459
+
460
+ .product-info {
461
+ padding: 0.75rem;
462
+ flex: 1;
463
+ display: flex;
464
+ flex-direction: column;
465
+ justify-content: center;
466
+ }
467
+
468
+ .product-name {
469
+ font-weight: 700;
470
+ font-size: 0.9rem;
471
+ color: #1e293b;
472
+ margin-bottom: 0.25rem;
473
+ line-height: 1.2;
474
+ display: -webkit-box;
475
+ -webkit-line-clamp: 2;
476
+ -webkit-box-orient: vertical;
477
+ overflow: hidden;
478
+ }
479
+
480
+ .list-layout .product-name {
481
+ font-size: 1.1rem;
482
+ -webkit-line-clamp: 1;
483
+ }
484
+
485
+ .prices {
486
+ display: flex;
487
+ align-items: baseline;
488
+ gap: 0.5rem;
489
+ flex-wrap: wrap;
490
+ }
491
+
492
+ .old-price {
493
+ text-decoration: line-through;
494
+ color: #94a3b8;
495
+ font-size: 0.8rem;
496
+ }
497
+
498
+ .new-price {
499
+ font-size: 1.3rem;
500
+ font-weight: 900;
501
+ color: #e63946;
502
+ }
503
+
504
+ .list-layout .new-price {
505
+ font-size: 1.5rem;
506
+ }
507
+
508
+ .discount-tag {
509
+ display: inline-block;
510
+ background: #dcfce7;
511
+ color: #166534;
512
+ font-size: 0.7rem;
513
+ font-weight: 700;
514
+ padding: 2px 6px;
515
+ border-radius: 4px;
516
+ }
517
+
518
+ /* Flyer Footer */
519
+ .flyer-footer {
520
+ padding: 1.25rem;
521
+ text-align: center;
522
+ font-weight: 700;
523
+ color: white;
524
+ font-size: 1rem;
525
+ position: relative;
526
+ }
527
+
528
+ .flyer-footer::before {
529
+ content: '';
530
+ position: absolute;
531
+ inset: 0;
532
+ background: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23ffffff' fill-opacity='0.1' fill-rule='evenodd'%3E%3Ccircle cx='3' cy='3' r='3'/%3E%3Ccircle cx='13' cy='13' r='3'/%3E%3C/g%3E%3C/svg%3E");
533
+ opacity: 0.3;
534
+ }
535
+
536
+ .flyer-footer span {
537
+ position: relative;
538
+ z-index: 1;
539
+ }
540
+
541
+ /* Decorative elements */
542
+ .deco-circle {
543
+ position: absolute;
544
+ border-radius: 50%;
545
+ opacity: 0.15;
546
+ pointer-events: none;
547
+ }
548
+
549
+ /* Responsividade */
550
+ @media (max-width: 968px) {
551
+ .app-container {
552
+ grid-template-columns: 1fr;
553
+ max-width: 700px;
554
+ }
555
+
556
+ .controls-panel {
557
+ position: relative;
558
+ top: 0;
559
+ max-height: none;
560
+ order: 2;
561
+ }
562
+
563
+ .preview-area {
564
+ order: 1;
565
+ }
566
+
567
+ #flyer-canvas {
568
+ max-width: 100%;
569
+ }
570
+ }
571
+
572
+ @media (max-width: 480px) {
573
+ .header {
574
+ padding: 1rem;
575
+ }
576
+
577
+ .header-brand {
578
+ font-size: 1.2rem;
579
+ }
580
+
581
+ .preview-wrapper {
582
+ padding: 1rem;
583
+ }
584
+
585
+ .flyer-title {
586
+ font-size: 1.8rem;
587
+ }
588
+
589
+ .flyer-header {
590
+ padding: 1.5rem;
591
+ }
592
+
593
+ .flyer-body {
594
+ padding: 1rem;
595
+ }
596
+ }
597
+
598
+ /* Loading e Toast */
599
+ .toast {
600
+ position: fixed;
601
+ bottom: 2rem;
602
+ right: 2rem;
603
+ background: var(--dark);
604
+ color: white;
605
+ padding: 1rem 1.5rem;
606
+ border-radius: 12px;
607
+ box-shadow: 0 10px 30px rgba(0,0,0,0.2);
608
+ transform: translateY(150%);
609
+ transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
610
+ z-index: 1000;
611
+ font-weight: 600;
612
+ display: flex;
613
+ align-items: center;
614
+ gap: 0.75rem;
615
+ }
616
+
617
+ .toast.show {
618
+ transform: translateY(0);
619
+ }
620
+
621
+ .loading-overlay {
622
+ position: absolute;
623
+ inset: 0;
624
+ background: rgba(255,255,255,0.9);
625
+ display: flex;
626
+ align-items: center;
627
+ justify-content: center;
628
+ z-index: 50;
629
+ border-radius: var(--radius);
630
+ opacity: 0;
631
+ pointer-events: none;
632
+ transition: opacity 0.3s;
633
+ }
634
+
635
+ .loading-overlay.active {
636
+ opacity: 1;
637
+ pointer-events: all;
638
+ }
639
+
640
+ .spinner {
641
+ width: 40px;
642
+ height: 40px;
643
+ border: 4px solid #e2e8f0;
644
+ border-top-color: var(--accent);
645
+ border-radius: 50%;
646
+ animation: spin 0.8s linear infinite;
647
+ }
648
+
649
+ @keyframes spin {
650
+ to { transform: rotate(360deg); }
651
+ }
652
+
653
+ /* Scrollbar customizada */
654
+ .controls-panel::-webkit-scrollbar {
655
+ width: 6px;
656
+ }
657
+
658
+ .controls-panel::-webkit-scrollbar-track {
659
+ background: transparent;
660
+ }
661
+
662
+ .controls-panel::-webkit-scrollbar-thumb {
663
+ background-color: #cbd5e0;
664
+ border-radius: 20px;
665
+ }
666
+
667
+ /* Animations */
668
+ @keyframes float {
669
+ 0%, 100% { transform: translateY(0px); }
670
+ 50% { transform: translateY(-10px); }
671
+ }
672
+
673
+ .animate-float {
674
+ animation: float 6s ease-in-out infinite;
675
+ }
676
+
677
+ .section-divider {
678
+ height: 1px;
679
+ background: linear-gradient(90deg, transparent, #e2e8f0, transparent);
680
+ margin: 1.5rem 0;
681
+ }
682
+ </style>
683
+ </head>
684
+ <body>
685
+
686
+ <header class="header">
687
+ <div class="header-brand">
688
+ <i class="fa-solid fa-bullhorn"></i>
689
+ <span>Obramax Flyer Gen</span>
690
+ </div>
691
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="header-link">
692
+ <i class="fa-solid fa-code"></i> Built with anycoder
693
+ </a>
694
+ </header>
695
+
696
+ <main class="app-container">
697
+ <!-- Painel de Controles -->
698
+ <aside class="controls-panel">
699
+ <div class="panel-title">
700
+ <i class="fa-solid fa-sliders"></i>
701
+ Configurações do Flyer
702
+ </div>
703
+
704
+ <div class="form-group">
705
+ <label>Título da Promoção</label>
706
+ <input type="text" class="form-control" id="input-title" value="MEGA PROMOÇÃO" maxlength="25">
707
+ </div>
708
+
709
+ <div class="form-group">
710
+ <label>Subtítulo / Descrição</label>
711
+ <input type="text" class="form-control" id="input-subtitle" value="Ofertas imperdíveis para você!" maxlength="40">
712
+ </div>
713
+
714
+ <div class="form-group">
715
+ <label>Validade da Oferta</label>
716
+ <input type="text" class="form-control" id="input-validity" value="Válido até 30/12/2024" maxlength="30">
717
+ </div>
718
+
719
+ <div class="color-row">
720
+ <div class="form-group" style="margin-bottom:0">
721
+ <label>Cor Principal</label>
722
+ <input type="color" class="form-control" id="input-primary" value="#e63946">
723
+ </div>
724
+ <div class="form-group" style="margin-bottom:0">
725
+ <label>Cor Secundária</label>
726
+ <input type="color" class="form-control" id="input-secondary" value="#f4a261">
727
+ </div>
728
+ </div>
729
+
730
+ <div class="section-divider"></div>
731
+
732
+ <div class="form-group">
733
+ <label>Layout dos Produtos</label>
734
+ <div class="layout-selector">
735
+ <div class="layout-option active" data-layout="grid" onclick="setLayout('grid')">
736
+ <i class="fa-solid fa-border-all"></i>
737
+ <span>Grade</span>
738
+ </div>
739
+ <div class="layout-option" data-layout="list" onclick="setLayout('list')">
740
+ <i class="fa-solid fa-list"></i>
741
+ <span>Lista</span>
742
+ </div>
743
+ </div>
744
+ </div>
745
+
746
+ <div class="section-divider"></div>
747
+
748
+ <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.5rem">
749
+ <label style="margin:0">Produtos</label>
750
+ <span style="font-size:0.8rem; color:#64748b" id="product-count">3/6</span>
751
+ </div>
752
+
753
+ <div class="products-list" id="products-list">
754
+ <!-- Produtos inseridos via JS -->
755
+ </div>
756
+
757
+ <button class="btn btn-primary" onclick="addProduct()" id="btn-add-product">
758
+ <i class="fa-solid fa-plus"></i> Adicionar Produto
759
+ </button>
760
+
761
+ <div class="section-divider"></div>
762
+
763
+ <button class="btn btn-secondary" onclick="downloadFlyer()">
764
+ <i class="fa-solid fa-download"></i> Baixar Flyer (PNG)
765
+ </button>
766
+ </aside>
767
+
768
+ <!-- Área de Preview -->
769
+ <section class="preview-area">
770
+ <div class="preview-wrapper" id="preview-wrapper">
771
+ <div class="loading-overlay" id="loading-overlay">
772
+ <div class="spinner"></div>
773
+ </div>
774
+
775
+ <!-- O Flyer -->
776
+ <div id="flyer-canvas">
777
+ <div class="flyer-header" id="flyer-header">
778
+ <div class="deco-circle animate-float" style="width:120px;height:120px;background:white;top:-20px;left:-20px;"></div>
779
+ <div class="deco-circle" style="width:80px;height:80px;background:white;opacity:0.1;bottom:10px;right:20px;"></div>
780
+ <div class="flyer-logo">obramax.com.br</div>
781
+ <div class="flyer-title" id="flyer-title">MEGA PROMOÇÃO</div>
782
+ <div class="flyer-subtitle" id="flyer-subtitle">Ofertas imperdíveis para você!</div>
783
+ </div>
784
+
785
+ <div class="flyer-body grid-layout" id="flyer-body">
786
+ <!-- Produtos no flyer -->
787
+ </div>
788
+
789
+ <div class="flyer-footer" id="flyer-footer">
790
+ <span><i class="fa-solid fa-clock" style="margin-right:6px"></i> <span id="flyer-validity">Válido até 30/12/2024</span></span>
791
+ </div>
792
+ </div>
793
+ </div>
794
+
795
+ <p style="color:#64748b; font-size:0.85rem; text-align:center; max-width:500px">
796
+ <i class="fa-solid fa-circle-info"></i> O preview atualiza automaticamente. Clique em "Baixar Flyer" para exportar em alta resolução.
797
+ </p>
798
+ </section>
799
+ </main>
800
+
801
+ <div class="toast" id="toast">
802
+ <i class="fa-solid fa-check-circle"></i>
803
+ <span id="toast-message">Flyer baixado com sucesso!</span>
804
+ </div>
805
+
806
+ <script>
807
+ // Estado da aplicação
808
+ const state = {
809
+ title: 'MEGA PROMOÇÃO',
810
+ subtitle: 'Ofertas imperdíveis para você!',
811
+ validity: 'Válido até 30/12/2024',
812
+ primary: '#e63946',
813
+ secondary: '#f4a261',
814
+ layout: 'grid',
815
+ products: [
816
+ { id: 1, name: 'Cimento CP II 50kg', oldPrice: 'R$ 39,90', newPrice: 'R$ 29,90', image: 'https://images.unsplash.com/photo-1530124566582-a618bc2615dc?w=400&h=400&fit=crop' },
817
+ { id: 2, name: 'Tinta Acrílica 18L', oldPrice: 'R$ 189,00', newPrice: 'R$ 149,00', image: 'https://images.unsplash.com/photo-1589939705384-5185137a7f0f?w=400&h=400&fit=crop' },
818
+ { id: 3, name: 'Furadeira 650W', oldPrice: 'R$ 259,00', newPrice: 'R$ 199,00', image: 'https://images.unsplash.com/photo-1504148455328-c376907d081c?w=400&h=400&fit=crop' }
819
+ ]
820
+ };
821
+
822
+ let nextId = 4;
823
+
824
+ // Referências DOM
825
+ const els = {
826
+ inputTitle: document.getElementById('input-title'),
827
+ inputSubtitle: document.getElementById('input-subtitle'),
828
+ inputValidity: document.getElementById('input-validity'),
829
+ inputPrimary: document.getElementById('input-primary'),
830
+ inputSecondary: document.getElementById('input-secondary'),
831
+ productsList: document.getElementById('products-list'),
832
+ flyerTitle: document.getElementById('flyer-title'),
833
+ flyerSubtitle: document.getElementById('flyer-subtitle'),
834
+ flyerValidity: document.getElementById('flyer-validity'),
835
+ flyerBody: document.getElementById('flyer-body'),
836
+ flyerHeader: document.getElementById('flyer-header'),
837
+ flyerFooter: document.getElementById('flyer-footer'),
838
+ toast: document.getElementById('toast'),
839
+ toastMsg: document.getElementById('toast-message'),
840
+ loading: document.getElementById('loading-overlay'),
841
+ productCount: document.getElementById('product-count'),
842
+ btnAdd: document.getElementById('btn-add-product')
843
+ };
844
+
845
+ // Inicialização
846
+ function init() {
847
+ bindEvents();
848
+ renderProductEditors();
849
+ updateFlyer();
850
+ }
851
+
852
+ function bindEvents() {
853
+ els.inputTitle.addEventListener('input', (e) => { state.title = e.target.value; updateFlyer(); });
854
+ els.inputSubtitle.addEventListener('input', (e) => { state.subtitle = e.target.value; updateFlyer(); });
855
+ els.inputValidity.addEventListener('input', (e) => { state.validity = e.target.value; updateFlyer(); });
856
+ els.inputPrimary.addEventListener('input', (e) => { state.primary = e.target.value; updateFlyer(); });
857
+ els.inputSecondary.addEventListener('input', (e) => { state.secondary = e.target.value; updateFlyer(); });
858
+ }
859
+
860
+ function setLayout(layout) {
861
+ state.layout = layout;
862
+ document.querySelectorAll('.layout-option').forEach(el => {
863
+ el.classList.toggle('active', el.dataset.layout === layout);
864
+ });
865
+ updateFlyer();
866
+ }
867
+
868
+ function addProduct() {
869
+ if (state.products.length >= 6) {
870
+ showToast('Limite máximo de 6 produtos atingido!', 'warning');
871
+ return;
872
+ }
873
+ state.products.push({
874
+ id: nextId++,
875
+ name: 'Novo Produto',
876
+ oldPrice: 'R$ 0,00',
877
+ newPrice: 'R$ 0,00',
878
+ image: ''
879
+ });
880
+ renderProductEditors();
881
+ updateFlyer();
882
+ }
883
+
884
+ function removeProduct(id) {
885
+ if (state.products.length <= 1) {
886
+ showToast('Adicione pelo menos 1 produto!', 'warning');
887
+ return;
888
+ }
889
+ state.products = state.products.filter(p => p.id !== id);
890
+ renderProductEditors();
891
+ updateFlyer();
892
+ }
893
+
894
+ function updateProduct(id, field, value) {
895
+ const product = state.products.find(p => p.id === id);
896
+ if (product) {
897
+ product[field] = value;
898
+ updateFlyer();
899
+ }
900
+ }
901
+
902
+ function renderProductEditors() {
903
+ els.productsList.innerHTML = '';
904
+ els.productCount.textContent = `${state.products.length}/6`;
905
+ els.btnAdd.disabled = state.products.length >= 6;
906
+ els.btnAdd.style.opacity = state.products.length >= 6 ? '0.5' : '1';
907
+
908
+ state.products.forEach((p, index) => {
909
+ const div = document.createElement('div');
910
+ div.className = 'product-editor';
911
+ div.innerHTML = `
912
+ <div class="product-header">
913
+ <span><i class="fa-solid fa-tag" style="color:var(--secondary); margin-right:4px"></i> Produto ${index + 1}</span>
914
+ <button class="btn btn-danger" onclick="removeProduct(${p.id})" title="Remover">
915
+ <i class="fa-solid fa-trash"></i>
916
+ </button>
917
+ </div>
918
+ <div class="product-fields">
919
+ <input type="text" class="form-control" placeholder="Nome do produto" value="${p.name}"
920
+ oninput="updateProduct(${p.id}, 'name', this.value)" maxlength="30">
921
+ <div style="display:grid; grid-template-columns: 1fr 1fr; gap:0.5rem">
922
+ <input type="text" class="form-control" placeholder="Preço antigo" value="${p.oldPrice}"
923
+ oninput="updateProduct(${p.id}, 'oldPrice', this.value)">
924
+ <input type="text" class="form-control" placeholder="Preço novo" value="${p.newPrice}"
925
+ oninput="updateProduct(${p.id}, 'newPrice', this.value)">
926
+ </div>
927
+ <input type="text" class="form-control" placeholder="URL da imagem (opcional)" value="${p.image}"
928
+ oninput="updateProduct(${p.id}, 'image', this.value)">
929
+ </div>
930
+ `;
931
+ els.productsList.appendChild(div);
932
+ });
933
+ }
934
+
935
+ function calcDiscount(oldP, newP) {
936
+ try {
937
+ const oldVal = parseFloat(oldP.replace(/[^0-9,]/g, '').replace(',', '.'));
938
+ const newVal = parseFloat(newP.replace(/[^0-9,]/g, '').replace(',', '.'));
939
+ if (oldVal && newVal && oldVal > newVal) {
940
+ return Math.round((1 - newVal / oldVal) * 100) + '% OFF';
941
+ }
942
+ } catch(e) {}
943
+ return '';
944
+ }
945
+
946
+ function updateFlyer() {
947
+ // Atualizar textos
948
+ els.flyerTitle.textContent = state.title || 'PROMOÇÃO';
949
+ els.flyerSubtitle.textContent = state.subtitle;
950
+ els.flyerValidity.textContent = state.validity;
951
+
952
+ // Aplicar cores
953
+ els.flyerHeader.style.background = `linear-gradient(135deg, ${state.primary}, ${state.secondary})`;
954
+ els.flyerHeader.style.color = 'white';
955
+ els.flyerFooter.style.background = state.dark || '#1d3557';
956
+ els.flyerFooter.style.background = `linear-gradient(90deg, ${state.primary}, ${adjustColor(state.primary, -20)})`;
957
+
958
+ // Layout
959
+ els.flyerBody.className = `flyer-body ${state.layout}-layout`;
960
+
961
+ // Renderizar produtos no flyer
962
+ els.flyerBody.innerHTML = state.products.map(p => {
963
+ const discount = calcDiscount(p.oldPrice, p.newPrice);
964
+ const imgContent = p.image
965
+ ? `<img src="${p.image}" class="product-image" alt="" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
966
+ <div class="product-image" style="display:none"><i class="fa-solid fa-box-open"></i></div>`
967
+ : `<div class="product-image"><i class="fa-solid fa-box-open"></i></div>`;
968
+
969
+ return `
970
+ <div class="flyer-product">
971
+ ${discount ? `<div class="product-badge">${discount}</div>` : ''}
972
+ ${imgContent}
973
+ <div class="product-info">
974
+ <div class="product-name">${p.name}</div>
975
+ <div class="prices">
976
+ <span class="old-price">${p.oldPrice}</span>
977
+ <span class="new-price">${p.newPrice}</span>
978
+ </div>
979
+ </div>
980
+ </div>
981
+ `;
982
+ }).join('');
983
+ }
984
+
985
+ function adjustColor(hex, amount) {
986
+ // Função simples para escurecer/clarear cor hex
987
+ let color = hex.replace('#', '');
988
+ if (color.length === 3) color = color.split('').map(c => c+c).join('');
989
+ const num = parseInt(color, 16);
990
+ let r = (num >> 16) + amount;
991
+ let g = ((num >> 8) & 0x00FF) + amount;
992
+ let b = (num & 0x00FF) + amount;
993
+ r = r < 0 ? 0 : r > 255 ? 255 : r;
994
+ g = g < 0 ? 0 : g > 255 ? 255 : g;
995
+ b = b < 0 ? 0 : b > 255 ? 255 : b;
996
+ return `rgb(${r},${g},${b})`;
997
+ }
998
+
999
+ async function downloadFlyer() {
1000
+ els.loading.classList.add('active');
1001
+
1002
+ try {
1003
+ const canvas = await html2canvas(document.getElementById('flyer-canvas'), {
1004
+ scale: 2,
1005
+ useCORS: true,
1006
+ allowTaint: true,
1007
+ backgroundColor: '#ffffff',
1008
+ logging: false
1009
+ });
1010
+
1011
+ const link = document.createElement('a');
1012
+ link.download = `obramax-flyer-${Date.now()}.png`;
1013
+ link.href = canvas.toDataURL('image/png');
1014
+ link.click();
1015
+
1016
+ showToast('Flyer baixado com sucesso!');
1017
+ } catch (err) {
1018
+ console.error(err);
1019
+ showToast('Erro ao gerar imagem. Tente novamente.', 'error');
1020
+ } finally {
1021
+ setTimeout(() => els.loading.classList.remove('active'), 500);
1022
+ }
1023
+ }
1024
+
1025
+ function showToast(msg, type = 'success') {
1026
+ els.toastMsg.textContent = msg;
1027
+ const icon = els.toast.querySelector('i');
1028
+ if (type === 'error') {
1029
+ icon.className = 'fa-solid fa-circle-xmark';
1030
+ els.toast.style.background = '#e63946';
1031
+ } else if (type === 'warning') {
1032
+ icon.className = 'fa-solid fa-triangle-exclamation';
1033
+ els.toast.style.background = '#f4a261';
1034
+ } else {
1035
+ icon.className = 'fa-solid fa-check-circle';
1036
+ els.toast.style.background = '#1d3557';
1037
+ }
1038
+ els.toast.classList.add('show');
1039
+ setTimeout(() => els.toast.classList.remove('show'), 3000);
1040
+ }
1041
+
1042
+ // Iniciar app
1043
+ init();
1044
+ </script>
1045
+ </body>
1046
+ </html>