anycoder-e74f9146 / index.html
Lucasrds's picture
Upload folder using huggingface_hub
84a8c4d verified
Raw History Blame Contribute Delete
34.3 kB
<!DOCTYPE html> <html lang="pt-BR"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Obramax Flyer Gen - Gerador de Flyers de Promoções</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script> <style> :root { --primary: #e63946; --secondary: #f4a261; --accent: #2a9d8f; --dark: #1d3557; --light: #f1faee; --bg: #f8f9fa; --glass: rgba(255, 255, 255, 0.85); --shadow: 0 8px 32px rgba(0, 0, 0, 0.1); --radius: 16px; --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); min-height: 100vh; color: var(--dark); } /* Header */ .header { background: linear-gradient(90deg, var(--dark) 0%, #2c3e50 100%); color: white; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 4px 20px rgba(0,0,0,0.15); position: sticky; top: 0; z-index: 100; flex-wrap: wrap; gap: 1rem; } .header-brand { display: flex; align-items: center; gap: 12px; font-size: 1.5rem; font-weight: 800; letter-spacing: -0.5px; } .header-brand i { color: var(--secondary); font-size: 1.8rem; } .header-link { color: rgba(255,255,255,0.85); text-decoration: none; font-size: 0.85rem; font-weight: 500; padding: 6px 12px; border: 1px solid rgba(255,255,255,0.3); border-radius: 20px; transition: var(--transition); } .header-link:hover { background: rgba(255,255,255,0.15); color: white; transform: translateY(-1px); } /* Layout Principal */ .app-container { display: grid; grid-template-columns: 380px 1fr; max-width: 1400px; margin: 2rem auto; padding: 0 1.5rem; gap: 2rem; min-height: calc(100vh - 100px); } /* Painel de Controle */ .controls-panel { background: var(--glass); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-radius: var(--radius); padding: 1.5rem; box-shadow: var(--shadow); border: 1px solid rgba(255,255,255,0.5); height: fit-content; position: sticky; top: 90px; overflow-y: auto; max-height: calc(100vh - 110px); } .panel-title { font-size: 1.25rem; font-weight: 700; margin-bottom: 1.5rem; display: flex; align-items: center; gap: 8px; color: var(--dark); padding-bottom: 0.75rem; border-bottom: 2px solid var(--secondary); } .form-group { margin-bottom: 1.25rem; } .form-group label { display: block; font-weight: 600; font-size: 0.85rem; margin-bottom: 0.5rem; color: var(--dark); opacity: 0.9; } .form-control { width: 100%; padding: 0.75rem 1rem; border: 2px solid #e2e8f0; border-radius: 10px; font-family: inherit; font-size: 0.9rem; transition: var(--transition); background: rgba(255,255,255,0.9); } .form-control:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.15); } input[type="color"].form-control { height: 42px; padding: 4px; cursor: pointer; } .color-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; } .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 0.75rem 1.25rem; border: none; border-radius: 10px; font-family: inherit; font-weight: 600; font-size: 0.9rem; cursor: pointer; transition: var(--transition); } .btn-primary { background: linear-gradient(135deg, var(--primary), #d62839); color: white; box-shadow: 0 4px 15px rgba(230, 57, 70, 0.3); width: 100%; margin-top: 0.5rem; } .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(230, 57, 70, 0.4); } .btn-secondary { background: linear-gradient(135deg, var(--dark), #2c3e50); color: white; width: 100%; margin-top: 1rem; padding: 1rem; font-size: 1rem; } .btn-secondary:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(29, 53, 87, 0.3); } .btn-small { padding: 0.4rem 0.8rem; font-size: 0.8rem; background: var(--primary); color: white; border-radius: 6px; } .btn-danger { background: #e63946; color: white; padding: 0.4rem; border-radius: 6px; width: 32px; height: 32px; } /* Lista de Produtos no Painel */ .products-list { display: flex; flex-direction: column; gap: 1rem; margin-top: 1rem; } .product-editor { background: white; border: 2px solid #edf2f7; border-radius: 12px; padding: 1rem; position: relative; transition: var(--transition); } .product-editor:hover { border-color: var(--secondary); box-shadow: 0 4px 12px rgba(0,0,0,0.05); } .product-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; } .product-header span { font-weight: 700; font-size: 0.85rem; color: var(--dark); } .product-fields { display: grid; gap: 0.5rem; } .layout-selector { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; margin-top: 0.5rem; } .layout-option { border: 2px solid #e2e8f0; border-radius: 10px; padding: 0.75rem; text-align: center; cursor: pointer; transition: var(--transition); background: white; } .layout-option.active { border-color: var(--accent); background: rgba(42, 157, 143, 0.05); color: var(--accent); } .layout-option:hover:not(.active) { border-color: #cbd5e0; } .layout-option i { font-size: 1.25rem; margin-bottom: 4px; display: block; } .layout-option span { font-size: 0.75rem; font-weight: 600; } /* Preview Area */ .preview-area { display: flex; flex-direction: column; align-items: center; gap: 1.5rem; } .preview-wrapper { background: white; padding: 2rem; border-radius: var(--radius); box-shadow: var(--shadow); width: 100%; max-width: 600px; display: flex; justify-content: center; align-items: flex-start; position: relative; overflow: hidden; } /* O Flyer em si */ #flyer-canvas { width: 100%; max-width: 550px; aspect-ratio: 3/4; background: white; position: relative; overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,0.15); display: flex; flex-direction: column; } /* Flyer Header */ .flyer-header { padding: 2rem; text-align: center; position: relative; overflow: hidden; } .flyer-header::before { content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: radial-gradient(circle, rgba(255,255,255,0.2) 0%, transparent 60%); pointer-events: none; } .flyer-logo { font-size: 2rem; font-weight: 900; letter-spacing: 2px; margin-bottom: 0.5rem; position: relative; z-index: 1; text-transform: uppercase; } .flyer-title { font-size: 2.5rem; font-weight: 900; margin-bottom: 0.5rem; position: relative; z-index: 1; line-height: 1.1; text-transform: uppercase; letter-spacing: -1px; } .flyer-subtitle { font-size: 1.1rem; font-weight: 600; opacity: 0.95; position: relative; z-index: 1; } /* Flyer Body */ .flyer-body { flex: 1; padding: 1.5rem; display: grid; gap: 1rem; align-content: start; overflow: hidden; } .flyer-body.grid-layout { grid-template-columns: repeat(2, 1fr); } .flyer-body.list-layout { grid-template-columns: 1fr; } /* Product Card */ .flyer-product { background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.08); display: flex; flex-direction: column; position: relative; border: 2px solid transparent; transition: transform 0.2s; } .grid-layout .flyer-product { aspect-ratio: 1/1.2; } .list-layout .flyer-product { flex-direction: row; align-items: center; height: 120px; } .flyer-product:hover { transform: scale(1.02); } .product-badge { position: absolute; top: 8px; right: 8px; background: #e63946; color: white; font-weight: 800; font-size: 0.75rem; padding: 4px 8px; border-radius: 20px; z-index: 2; box-shadow: 0 2px 8px rgba(0,0,0,0.15); } .product-image { width: 100%; height: 60%; object-fit: cover; background: #f1f5f9; display: flex; align-items: center; justify-content: center; color: #94a3b8; font-size: 2.5rem; } .list-layout .product-image { width: 120px; height: 100%; } .product-info { padding: 0.75rem; flex: 1; display: flex; flex-direction: column; justify-content: center; } .product-name { font-weight: 700; font-size: 0.9rem; color: #1e293b; margin-bottom: 0.25rem; line-height: 1.2; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .list-layout .product-name { font-size: 1.1rem; -webkit-line-clamp: 1; } .prices { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; } .old-price { text-decoration: line-through; color: #94a3b8; font-size: 0.8rem; } .new-price { font-size: 1.3rem; font-weight: 900; color: #e63946; } .list-layout .new-price { font-size: 1.5rem; } .discount-tag { display: inline-block; background: #dcfce7; color: #166534; font-size: 0.7rem; font-weight: 700; padding: 2px 6px; border-radius: 4px; } /* Flyer Footer */ .flyer-footer { padding: 1.25rem; text-align: center; font-weight: 700; color: white; font-size: 1rem; position: relative; } .flyer-footer::before { content: ''; position: absolute; inset: 0; 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"); opacity: 0.3; } .flyer-footer span { position: relative; z-index: 1; } /* Decorative elements */ .deco-circle { position: absolute; border-radius: 50%; opacity: 0.15; pointer-events: none; } /* Responsividade */ @media (max-width: 968px) { .app-container { grid-template-columns: 1fr; max-width: 700px; } .controls-panel { position: relative; top: 0; max-height: none; order: 2; } .preview-area { order: 1; } #flyer-canvas { max-width: 100%; } } @media (max-width: 480px) { .header { padding: 1rem; } .header-brand { font-size: 1.2rem; } .preview-wrapper { padding: 1rem; } .flyer-title { font-size: 1.8rem; } .flyer-header { padding: 1.5rem; } .flyer-body { padding: 1rem; } } /* Loading e Toast */ .toast { position: fixed; bottom: 2rem; right: 2rem; background: var(--dark); color: white; padding: 1rem 1.5rem; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); transform: translateY(150%); transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); z-index: 1000; font-weight: 600; display: flex; align-items: center; gap: 0.75rem; } .toast.show { transform: translateY(0); } .loading-overlay { position: absolute; inset: 0; background: rgba(255,255,255,0.9); display: flex; align-items: center; justify-content: center; z-index: 50; border-radius: var(--radius); opacity: 0; pointer-events: none; transition: opacity 0.3s; } .loading-overlay.active { opacity: 1; pointer-events: all; } .spinner { width: 40px; height: 40px; border: 4px solid #e2e8f0; border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Scrollbar customizada */ .controls-panel::-webkit-scrollbar { width: 6px; } .controls-panel::-webkit-scrollbar-track { background: transparent; } .controls-panel::-webkit-scrollbar-thumb { background-color: #cbd5e0; border-radius: 20px; } /* Animations */ @keyframes float { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-10px); } } .animate-float { animation: float 6s ease-in-out infinite; } .section-divider { height: 1px; background: linear-gradient(90deg, transparent, #e2e8f0, transparent); margin: 1.5rem 0; } </style> </head> <body> <header class="header"> <div class="header-brand"> <i class="fa-solid fa-bullhorn"></i> <span>Obramax Flyer Gen</span> </div> <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="header-link"> <i class="fa-solid fa-code"></i> Built with anycoder </a> </header> <main class="app-container"> <!-- Painel de Controles --> <aside class="controls-panel"> <div class="panel-title"> <i class="fa-solid fa-sliders"></i> Configurações do Flyer </div> <div class="form-group"> <label>Título da Promoção</label> <input type="text" class="form-control" id="input-title" value="MEGA PROMOÇÃO" maxlength="25"> </div> <div class="form-group"> <label>Subtítulo / Descrição</label> <input type="text" class="form-control" id="input-subtitle" value="Ofertas imperdíveis para você!" maxlength="40"> </div> <div class="form-group"> <label>Validade da Oferta</label> <input type="text" class="form-control" id="input-validity" value="Válido até 30/12/2024" maxlength="30"> </div> <div class="color-row"> <div class="form-group" style="margin-bottom:0"> <label>Cor Principal</label> <input type="color" class="form-control" id="input-primary" value="#e63946"> </div> <div class="form-group" style="margin-bottom:0"> <label>Cor Secundária</label> <input type="color" class="form-control" id="input-secondary" value="#f4a261"> </div> </div> <div class="section-divider"></div> <div class="form-group"> <label>Layout dos Produtos</label> <div class="layout-selector"> <div class="layout-option active" data-layout="grid" onclick="setLayout('grid')"> <i class="fa-solid fa-border-all"></i> <span>Grade</span> </div> <div class="layout-option" data-layout="list" onclick="setLayout('list')"> <i class="fa-solid fa-list"></i> <span>Lista</span> </div> </div> </div> <div class="section-divider"></div> <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.5rem"> <label style="margin:0">Produtos</label> <span style="font-size:0.8rem; color:#64748b" id="product-count">3/6</span> </div> <div class="products-list" id="products-list"> <!-- Produtos inseridos via JS --> </div> <button class="btn btn-primary" onclick="addProduct()" id="btn-add-product"> <i class="fa-solid fa-plus"></i> Adicionar Produto </button> <div class="section-divider"></div> <button class="btn btn-secondary" onclick="downloadFlyer()"> <i class="fa-solid fa-download"></i> Baixar Flyer (PNG) </button> </aside> <!-- Área de Preview --> <section class="preview-area"> <div class="preview-wrapper" id="preview-wrapper"> <div class="loading-overlay" id="loading-overlay"> <div class="spinner"></div> </div> <!-- O Flyer --> <div id="flyer-canvas"> <div class="flyer-header" id="flyer-header"> <div class="deco-circle animate-float" style="width:120px;height:120px;background:white;top:-20px;left:-20px;"></div> <div class="deco-circle" style="width:80px;height:80px;background:white;opacity:0.1;bottom:10px;right:20px;"></div> <div class="flyer-logo">obramax.com.br</div> <div class="flyer-title" id="flyer-title">MEGA PROMOÇÃO</div> <div class="flyer-subtitle" id="flyer-subtitle">Ofertas imperdíveis para você!</div> </div> <div class="flyer-body grid-layout" id="flyer-body"> <!-- Produtos no flyer --> </div> <div class="flyer-footer" id="flyer-footer"> <span><i class="fa-solid fa-clock" style="margin-right:6px"></i> <span id="flyer-validity">Válido até 30/12/2024</span></span> </div> </div> </div> <p style="color:#64748b; font-size:0.85rem; text-align:center; max-width:500px"> <i class="fa-solid fa-circle-info"></i> O preview atualiza automaticamente. Clique em "Baixar Flyer" para exportar em alta resolução. </p> </section> </main> <div class="toast" id="toast"> <i class="fa-solid fa-check-circle"></i> <span id="toast-message">Flyer baixado com sucesso!</span> </div> <script> // Estado da aplicação const state = { title: 'MEGA PROMOÇÃO', subtitle: 'Ofertas imperdíveis para você!', validity: 'Válido até 30/12/2024', primary: '#e63946', secondary: '#f4a261', layout: 'grid', products: [ { 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' }, { 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' }, { 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' } ] }; let nextId = 4; // Referências DOM const els = { inputTitle: document.getElementById('input-title'), inputSubtitle: document.getElementById('input-subtitle'), inputValidity: document.getElementById('input-validity'), inputPrimary: document.getElementById('input-primary'), inputSecondary: document.getElementById('input-secondary'), productsList: document.getElementById('products-list'), flyerTitle: document.getElementById('flyer-title'), flyerSubtitle: document.getElementById('flyer-subtitle'), flyerValidity: document.getElementById('flyer-validity'), flyerBody: document.getElementById('flyer-body'), flyerHeader: document.getElementById('flyer-header'), flyerFooter: document.getElementById('flyer-footer'), toast: document.getElementById('toast'), toastMsg: document.getElementById('toast-message'), loading: document.getElementById('loading-overlay'), productCount: document.getElementById('product-count'), btnAdd: document.getElementById('btn-add-product') }; // Inicialização function init() { bindEvents(); renderProductEditors(); updateFlyer(); } function bindEvents() { els.inputTitle.addEventListener('input', (e) => { state.title = e.target.value; updateFlyer(); }); els.inputSubtitle.addEventListener('input', (e) => { state.subtitle = e.target.value; updateFlyer(); }); els.inputValidity.addEventListener('input', (e) => { state.validity = e.target.value; updateFlyer(); }); els.inputPrimary.addEventListener('input', (e) => { state.primary = e.target.value; updateFlyer(); }); els.inputSecondary.addEventListener('input', (e) => { state.secondary = e.target.value; updateFlyer(); }); } function setLayout(layout) { state.layout = layout; document.querySelectorAll('.layout-option').forEach(el => { el.classList.toggle('active', el.dataset.layout === layout); }); updateFlyer(); } function addProduct() { if (state.products.length >= 6) { showToast('Limite máximo de 6 produtos atingido!', 'warning'); return; } state.products.push({ id: nextId++, name: 'Novo Produto', oldPrice: 'R$ 0,00', newPrice: 'R$ 0,00', image: '' }); renderProductEditors(); updateFlyer(); } function removeProduct(id) { if (state.products.length <= 1) { showToast('Adicione pelo menos 1 produto!', 'warning'); return; } state.products = state.products.filter(p => p.id !== id); renderProductEditors(); updateFlyer(); } function updateProduct(id, field, value) { const product = state.products.find(p => p.id === id); if (product) { product[field] = value; updateFlyer(); } } function renderProductEditors() { els.productsList.innerHTML = ''; els.productCount.textContent = `${state.products.length}/6`; els.btnAdd.disabled = state.products.length >= 6; els.btnAdd.style.opacity = state.products.length >= 6 ? '0.5' : '1'; state.products.forEach((p, index) => { const div = document.createElement('div'); div.className = 'product-editor'; div.innerHTML = ` <div class="product-header"> <span><i class="fa-solid fa-tag" style="color:var(--secondary); margin-right:4px"></i> Produto ${index + 1}</span> <button class="btn btn-danger" onclick="removeProduct(${p.id})" title="Remover"> <i class="fa-solid fa-trash"></i> </button> </div> <div class="product-fields"> <input type="text" class="form-control" placeholder="Nome do produto" value="${p.name}" oninput="updateProduct(${p.id}, 'name', this.value)" maxlength="30"> <div style="display:grid; grid-template-columns: 1fr 1fr; gap:0.5rem"> <input type="text" class="form-control" placeholder="Preço antigo" value="${p.oldPrice}" oninput="updateProduct(${p.id}, 'oldPrice', this.value)"> <input type="text" class="form-control" placeholder="Preço novo" value="${p.newPrice}" oninput="updateProduct(${p.id}, 'newPrice', this.value)"> </div> <input type="text" class="form-control" placeholder="URL da imagem (opcional)" value="${p.image}" oninput="updateProduct(${p.id}, 'image', this.value)"> </div> `; els.productsList.appendChild(div); }); } function calcDiscount(oldP, newP) { try { const oldVal = parseFloat(oldP.replace(/[^0-9,]/g, '').replace(',', '.')); const newVal = parseFloat(newP.replace(/[^0-9,]/g, '').replace(',', '.')); if (oldVal && newVal && oldVal > newVal) { return Math.round((1 - newVal / oldVal) * 100) + '% OFF'; } } catch(e) {} return ''; } function updateFlyer() { // Atualizar textos els.flyerTitle.textContent = state.title || 'PROMOÇÃO'; els.flyerSubtitle.textContent = state.subtitle; els.flyerValidity.textContent = state.validity; // Aplicar cores els.flyerHeader.style.background = `linear-gradient(135deg, ${state.primary}, ${state.secondary})`; els.flyerHeader.style.color = 'white'; els.flyerFooter.style.background = state.dark || '#1d3557'; els.flyerFooter.style.background = `linear-gradient(90deg, ${state.primary}, ${adjustColor(state.primary, -20)})`; // Layout els.flyerBody.className = `flyer-body ${state.layout}-layout`; // Renderizar produtos no flyer els.flyerBody.innerHTML = state.products.map(p => { const discount = calcDiscount(p.oldPrice, p.newPrice); const imgContent = p.image ? `<img src="${p.image}" class="product-image" alt="" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"> <div class="product-image" style="display:none"><i class="fa-solid fa-box-open"></i></div>` : `<div class="product-image"><i class="fa-solid fa-box-open"></i></div>`; return ` <div class="flyer-product"> ${discount ? `<div class="product-badge">${discount}</div>` : ''} ${imgContent} <div class="product-info"> <div class="product-name">${p.name}</div> <div class="prices"> <span class="old-price">${p.oldPrice}</span> <span class="new-price">${p.newPrice}</span> </div> </div> </div> `; }).join(''); } function adjustColor(hex, amount) { // Função simples para escurecer/clarear cor hex let color = hex.replace('#', ''); if (color.length === 3) color = color.split('').map(c => c+c).join(''); const num = parseInt(color, 16); let r = (num >> 16) + amount; let g = ((num >> 8) & 0x00FF) + amount; let b = (num & 0x00FF) + amount; r = r < 0 ? 0 : r > 255 ? 255 : r; g = g < 0 ? 0 : g > 255 ? 255 : g; b = b < 0 ? 0 : b > 255 ? 255 : b; return `rgb(${r},${g},${b})`; } async function downloadFlyer() { els.loading.classList.add('active'); try { const canvas = await html2canvas(document.getElementById('flyer-canvas'), { scale: 2, useCORS: true, allowTaint: true, backgroundColor: '#ffffff', logging: false }); const link = document.createElement('a'); link.download = `obramax-flyer-${Date.now()}.png`; link.href = canvas.toDataURL('image/png'); link.click(); showToast('Flyer baixado com sucesso!'); } catch (err) { console.error(err); showToast('Erro ao gerar imagem. Tente novamente.', 'error'); } finally { setTimeout(() => els.loading.classList.remove('active'), 500); } } function showToast(msg, type = 'success') { els.toastMsg.textContent = msg; const icon = els.toast.querySelector('i'); if (type === 'error') { icon.className = 'fa-solid fa-circle-xmark'; els.toast.style.background = '#e63946'; } else if (type === 'warning') { icon.className = 'fa-solid fa-triangle-exclamation'; els.toast.style.background = '#f4a261'; } else { icon.className = 'fa-solid fa-check-circle'; els.toast.style.background = '#1d3557'; } els.toast.classList.add('show'); setTimeout(() => els.toast.classList.remove('show'), 3000); } // Iniciar app init(); </script> </body> </html>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Obramax Flyer Gen - Gerador de Flyers de Promoções</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<style>
:root {
--primary: #e63946;
--secondary: #f4a261;
--accent: #2a9d8f;
--dark: #1d3557;
--light: #f1faee;
--bg: #f8f9fa;
--glass: rgba(255, 255, 255, 0.85);
--shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
--radius: 16px;
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
color: var(--dark);
}
/* Header */
.header {
background: linear-gradient(90deg, var(--dark) 0%, #2c3e50 100%);
color: white;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
position: sticky;
top: 0;
z-index: 100;
flex-wrap: wrap;
gap: 1rem;
}
.header-brand {
display: flex;
align-items: center;
gap: 12px;
font-size: 1.5rem;
font-weight: 800;
letter-spacing: -0.5px;
}
.header-brand i {
color: var(--secondary);
font-size: 1.8rem;
}
.header-link {
color: rgba(255,255,255,0.85);
text-decoration: none;
font-size: 0.85rem;
font-weight: 500;
padding: 6px 12px;
border: 1px solid rgba(255,255,255,0.3);
border-radius: 20px;
transition: var(--transition);
}
.header-link:hover {
background: rgba(255,255,255,0.15);
color: white;
transform: translateY(-1px);
}
/* Layout Principal */
.app-container {
display: grid;
grid-template-columns: 380px 1fr;
max-width: 1400px;
margin: 2rem auto;
padding: 0 1.5rem;
gap: 2rem;
min-height: calc(100vh - 100px);
}
/* Painel de Controle */
.controls-panel {
background: var(--glass);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border-radius: var(--radius);
padding: 1.5rem;