Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save sebastianjnuwu/95dd894f71befdca5ceb0239af5689e4 to your computer and use it in GitHub Desktop.

Select an option

Save sebastianjnuwu/95dd894f71befdca5ceb0239af5689e4 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="loja-id" content="ecf68475-0fe1-4224-a2f3-cb1cd3311d84" />
<!-- HTML Meta Tags -->
<title>Theme Light Shop | Template de Loja Virtual Moderna</title>
<meta name="description"
content="Template moderno para e-commerce com visual claro, performance elevada, SEO otimizado e experiência premium para lojas virtuais.">
<!-- Facebook Meta Tags -->
<meta property="og:url" content="https://demo-theme-light-shop-web.cabrapi.com.br/">
<meta property="og:type" content="website">
<meta property="og:title" content="Theme Light Shop | Template de Loja Virtual Moderna">
<meta property="og:description"
content="Template moderno para e-commerce com visual claro, performance elevada, SEO otimizado e experiência premium para lojas virtuais.">
<meta property="og:image"
content="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download">
<!-- Twitter Meta Tags -->
<meta name="twitter:card" content="summary_large_image">
<meta property="twitter:domain" content="demo-theme-light-shop-web.cabrapi.com.br">
<meta property="twitter:url" content="https://demo-theme-light-shop-web.cabrapi.com.br/">
<meta name="twitter:title" content="Theme Light Shop | Template de Loja Virtual Moderna">
<meta name="twitter:description"
content="Template moderno para e-commerce com visual claro, performance elevada, SEO otimizado e experiência premium para lojas virtuais.">
<meta name="twitter:image"
content="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download">
<link rel="icon" href="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download"
sizes="32x32">
<link rel="icon" href="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download"
sizes="192x192">
<link rel="apple-touch-icon"
href="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download">
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=DM+Serif+Display&display=swap"
rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<style>
:root {
--c-bg: #f8f7f4;
--c-surface: #ffffff;
--c-border: #e8e4df;
--c-ink: #1a1714;
--c-ink-muted: #6b6560;
--c-ink-subtle: #a09a94;
--c-accent: #c8502a;
--c-accent-light: #fef3ec;
--c-green: #2d7a4f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: 'DM Sans', sans-serif;
background: var(--c-bg);
color: var(--c-ink);
}
a {
text-decoration: none;
color: inherit;
}
img {
max-width: 100%;
height: auto;
}
button {
font-family: inherit;
cursor: pointer;
}
section img {
pointer-events: none;
}
</style>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script type="module">
import { caBRAPI as p } from "https://cdn.jsdelivr.net/npm/@cabrapi/sdk/dist/index.js";
var l = {
CART_STORAGE_KEY: "cabrapi_theme_light_shop_cart",
PRODUCTS_PAGE: 1,
PRODUCTS_LIMIT: 3,
PRODUCT_IMAGE_FIT_DEFAULT: "cover",
BUTTON_FEEDBACK_MS: 1400,
COPY_FEEDBACK_MS: 1800
}, m = {
PIX: "MERCADOPAGO_SERVICE_PIX",
CARD: "MERCADOPAGO_SERVICE_CARD"
}, b = class {
#t;
#e;
constructor(t, e) {
this.#t = new t({
type: "public",
config: {}
}), this.#e = e;
}
async getProducts(t = l.PRODUCTS_PAGE) {
const e = await this.#t.products.get(this.#e, {
page: t,
limit: l.PRODUCTS_LIMIT
});
if (!e?.status && e?.error) throw new Error(e?.message || "Erro ao buscar produtos.");
return {
products: Array.isArray(e?.products) ? e.products : [],
pagination: {
page: Number(e?.pagination?.page || t || 1),
limit: Number(e?.pagination?.limit || l.PRODUCTS_LIMIT),
total: Number(e?.pagination?.total || 0),
totalPages: Number(e?.pagination?.totalPages || 1)
}
};
}
async getCategories() {
const t = await this.#t.categories.get(this.#e, {
page: 1,
limit: 100
});
if (!t?.status && t?.error) throw new Error(t?.message || "Erro ao buscar categorias.");
return Array.isArray(t?.categories) ? t.categories : [];
}
async validateCoupon(t) {
return await this.#t.coupons.getByCode(this.#e, t);
}
async createPayment(t) {
return await this.#t.payments.post(this.#e, t);
}
}, C = class {
#t = null;
getItems() {
if (this.#t) return this.#t;
try {
const t = localStorage.getItem(l.CART_STORAGE_KEY);
this.#t = t ? JSON.parse(t) : [];
} catch {
this.#t = [];
}
return this.#t;
}
#e(t) {
this.#t = Array.isArray(t) ? t : [], localStorage.setItem(l.CART_STORAGE_KEY, JSON.stringify(this.#t));
}
addProduct(t) {
const e = this.getItems(), o = String(t.id), s = e.find((i) => String(i.id) === o), a = t.stock === null || t.stock === void 0 ? null : Number(t.stock);
if (a !== null && a <= 0) return e;
if (s) {
const i = s.stock === null || s.stock === void 0 ? null : Number(s.stock);
if (i !== null && s.qty >= i) return e;
s.qty += 1;
} else e.push({
id: o,
name: String(t.name || "Produto"),
image: t.image || null,
price: Number(t.price || 0),
qty: 1,
stock: a
});
return this.#e(e), e;
}
removeProduct(t) {
const e = String(t), o = this.getItems().filter((s) => String(s.id) !== e);
return this.#e(o), o;
}
changeQuantity(t, e) {
const o = String(t), s = this.getItems(), a = s.find((n) => String(n.id) === o);
if (!a) return s;
const i = a.stock === null || a.stock === void 0 ? null : Number(a.stock);
if (e > 0 && i !== null && a.qty >= i) return s;
if (a.qty += e, a.qty <= 0) return this.removeProduct(t);
const c = s.filter((n) => n.qty > 0);
return this.#e(c), c;
}
clear() {
this.#e([]);
}
getTotalItems() {
return this.getItems().reduce((t, e) => t + Number(e.qty || 0), 0);
}
getTotalPrice() {
return this.getItems().reduce((t, e) => t + Number(e.price || 0) * Number(e.qty || 0), 0);
}
};
function x(t) {
return String(t || "").trim().length >= 3;
}
function y(t) {
const e = String(t || "").trim();
return e ? e.length >= 4 && e.length <= 32 : !0;
}
function v(t) {
return String(t || "").replace(/\D/g, "").length === 11;
}
function k(t) {
const e = String(t || "").trim();
return e ? /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e) : !1;
}
function w(t) {
return Array.isArray(t) && t.length > 0;
}
function S(t, e, o = 1400) {
const s = t.html();
t.prop("disabled", !0).html(e), setTimeout(() => {
t.prop("disabled", !1).html(s);
}, o);
}
function d(t, e) {
if (e) {
t.removeClass("opacity-0 pointer-events-none");
return;
}
t.addClass("opacity-0 pointer-events-none");
}
function r(t) {
return String(t || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\"/g, "&quot;").replace(/'/g, "&#039;");
}
var P = class {
constructor({ onCategoryChange: t }) {
this.$filters = $("#category-filters"), this.onCategoryChange = t, this.categories = [], this.activeCategory = "all", this.#t();
}
#t() {
$(document).on("click", ".category-filter-btn", (t) => {
const e = String($(t.currentTarget).data("category") || "all");
e !== this.activeCategory && (this.activeCategory = e, this.render(), typeof this.onCategoryChange == "function" && this.onCategoryChange(e));
});
}
setCategories(t) {
this.categories = (Array.isArray(t) ? t : []).filter((e) => e?.name).map((e) => ({
id: String(e.id || e.name),
name: String(e.name)
})), this.render();
}
setActiveCategory(t) {
this.activeCategory = String(t || "all"), this.render();
}
render() {
const t = [`<button class="category-filter-btn px-4 py-2 rounded-full text-sm font-medium transition-all ${this.activeCategory === "all" ? "bg-[#c8502a] text-white" : "bg-white text-[#6b6560] border border-[#e8e4df]"}" data-category="all">Todos</button>`];
for (const e of this.categories) {
const o = this.activeCategory === e.name ? "bg-[#c8502a] text-white" : "bg-white text-[#6b6560] border border-[#e8e4df] hover:border-[#c8502a] hover:text-[#c8502a]";
t.push(`<button class="category-filter-btn px-4 py-2 rounded-full text-sm font-medium transition-all ${o}" data-category="${r(e.name)}">${r(e.name)}</button>`);
}
this.$filters.html(t.join(""));
}
};
function h(t) {
return new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL"
}).format(Number(t || 0));
}
function A(t = "Produto") {
return `https://placehold.co/600x420/F0EDE8/9CA3AF?text=${encodeURIComponent(t)}`;
}
var I = class {
constructor({ onAddToCart: t, onPageChange: e }) {
this.$list = $("#products-list"), this.$pagination = $("#products-pagination"), this.onAddToCart = t, this.onPageChange = e, this.products = [], this.activeCategory = "all", this.pagination = {
page: 1,
totalPages: 1,
total: 0
}, this.#t();
}
#t() {
$(document).on("click", ".product-add-btn", (t) => {
const e = $(t.currentTarget);
if (e.prop("disabled") || e.hasClass("cursor-not-allowed")) return;
const o = String(e.data("id")), s = this.products.find((a) => String(a.id) === o);
s && this.onAddToCart(s) !== !1 && S(e, '<i class="fas fa-check mr-2"></i> Adicionado', l.BUTTON_FEEDBACK_MS);
}), $(document).on("click", ".products-page-btn", (t) => {
const e = Number($(t.currentTarget).data("page"));
!e || e === this.pagination.page || typeof this.onPageChange == "function" && this.onPageChange(e);
});
}
#e() {
this.$list.find(".product-card-image").each((t, e) => {
$(e).css({
width: "100%",
height: "100%",
"object-fit": "cover",
"object-position": "center",
display: "block"
});
});
}
setProducts(t) {
const e = Array.isArray(t?.products) ? t.products : [];
this.pagination = {
page: Number(t?.pagination?.page || 1),
totalPages: Number(t?.pagination?.totalPages || 1),
total: Number(t?.pagination?.total || e.length)
}, this.products = e.filter((o) => !o.disabled), this.#o(), this.#a();
}
setActiveCategory(t) {
this.activeCategory = String(t || "all"), this.#o();
}
#s() {
return this.activeCategory === "all" ? this.products : this.products.filter((t) => (t.categories || []).some((e) => String(e.name) === this.activeCategory));
}
#o() {
const t = this.#s();
if (!t.length) {
this.$list.html(`
<div class="col-span-full text-center py-20 text-[#6b6560]">
<i class="fas fa-box-open text-5xl mb-4 block opacity-20"></i>
<p>Nenhum produto encontrado.</p>
</div>
`);
return;
}
const e = t.map((o) => {
const s = r(o.image || A(o.name)), a = Number(o.stock), i = !(!Number.isNaN(a) && a > 0);
return `
<article class="group bg-white rounded-3xl border border-[#e8e4df] overflow-hidden hover:shadow-xl transition-all duration-300 flex flex-col h-full">
<div class="product-card-image-frame relative overflow-hidden bg-[#f8f7f4]" style="aspect-ratio: 4/3; width: 100%;">
<img src="${s}"
alt="${r(o.name)}"
class="product-card-image transition-transform duration-700 group-hover:scale-110"
style="width: 100% !important; height: 100% !important; object-fit: cover !important; object-position: center !important; display: block !important;"
/>
<div class="absolute inset-0 bg-gradient-to-t from-[#1a1714]/10 to-transparent pointer-events-none"></div>
</div>
<div class="p-5 flex flex-col flex-1">
<div class="flex-1">
<h3 class="font-bold text-[#1a1714] text-lg mb-1 line-clamp-2 leading-tight">
${r(o.name)}
</h3>
<p class="text-sm text-[#6b6560] mb-4 line-clamp-2 leading-relaxed">
${r(o.description || "Asset digital exclusivo.")}
</p>
</div>
<div class="mt-auto">
<div class="mb-4">
<span class="text-[10px] text-[#6b6560] font-bold uppercase tracking-widest">Valor</span>
<div class="text-2xl text-[#c8502a] font-black leading-none">
${h(o.price)}
</div>
</div>
<button class="product-add-btn w-full py-3.5 bg-[#1a1714] text-white font-bold rounded-2xl hover:bg-[#c8502a] transition-all flex items-center justify-center gap-2 shadow-sm disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-[#1a1714]"
${i ? 'disabled aria-disabled="true"' : ""}
data-id="${r(o.id)}"
data-stock="${r(o.stock)}">
<i class="fas fa-shopping-bag text-sm"></i>
<span>${i ? "ESGOTADO" : "ADICIONAR"}</span>
</button>
</div>
</div>
</article>
`;
});
this.$list.html(`
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
${e.join("")}
</div>
`), this.#e();
}
#a() {
const { page: t, totalPages: e } = this.pagination;
if (e <= 1) {
this.$pagination.html("");
return;
}
let o = "";
for (let s = 1; s <= e; s++) s === 1 || s === e || s >= t - 1 && s <= t + 1 ? o += `
<button class="products-page-btn w-10 h-10 md:w-12 md:h-12 ${s === t ? "flex" : "hidden md:flex"} items-center justify-center rounded-xl border-2 transition-all font-bold ${s === t ? "bg-[#1a1714] border-[#1a1714] text-white active-page shadow-lg" : "border-[#e8e4df] text-[#1a1714] hover:border-[#1a1714]"}" data-page="${s}">
${s}
</button>
` : (s === t - 2 || s === t + 2) && (o += '<span class="text-[#e8e4df] hidden md:inline">...</span>');
this.$pagination.html(`
<div class="flex items-center justify-between gap-2 mt-12 mb-8 p-3 md:p-6 bg-white rounded-2xl md:rounded-[2rem] border border-[#e8e4df] mx-2">
<button class="products-page-btn flex items-center justify-center w-10 h-10 md:w-auto md:px-6 md:py-3 rounded-xl font-bold border-2 border-[#e8e4df] transition-all ${t <= 1 ? "opacity-20 cursor-not-allowed" : "text-[#1a1714] hover:bg-[#f8f7f4]"}"
${t <= 1 ? "disabled" : ""} data-page="${t - 1}">
<i class="fas fa-chevron-left text-xs"></i>
<span class="hidden md:inline ml-2">Anterior</span>
</button>
<div class="flex items-center gap-1 md:gap-2">
${o}
<span class="md:hidden text-xs font-bold text-[#6b6560] ml-2">de ${e}</span>
</div>
<button class="products-page-btn flex items-center justify-center w-10 h-10 md:w-auto md:px-6 md:py-3 rounded-xl font-bold border-2 border-[#e8e4df] transition-all ${t >= e ? "opacity-20 cursor-not-allowed" : "text-[#1a1714] hover:bg-[#f8f7f4]"}"
${t >= e ? "disabled" : ""} data-page="${t + 1}">
<span class="hidden md:inline mr-2">Próxima</span>
<i class="fas fa-chevron-right text-xs"></i>
</button>
</div>
`);
}
updateButtonsStates(t) {
$(".product-add-btn").each((e, o) => {
const s = $(o), a = s.data("id"), i = t.find((f) => String(f.id) === String(a)), c = Number(s.data("stock")), n = i ? i.stock : isNaN(c) ? null : c, g = i ? i.qty : 0, u = n !== null && n <= 0 || n > 0 && g >= n;
u ? s.prop("disabled", !0).attr("disabled", "disabled").addClass("opacity-50 cursor-not-allowed") : s.prop("disabled", !1).removeAttr("disabled").removeClass("opacity-50 cursor-not-allowed"), s.find("span").text(u ? "ESGOTADO" : "ADICIONAR");
});
}
}, T = class {
constructor() {
this.$drawer = $("#checkout"), this.$openButton = $("#cart-toggle"), this.$closeButton = $("#checkout-close"), this.$count = $("#cart-count");
}
bindEvents() {
this.$openButton.on("click", (t) => {
t.preventDefault(), this.open();
}), this.$closeButton.on("click", () => this.close()), this.$drawer.on("click", (t) => {
$(t.target).is(this.$drawer) && this.close();
});
}
open() {
d(this.$drawer, !0);
}
close() {
d(this.$drawer, !1);
}
setCount(t) {
this.$count.text(String(Number(t || 0)));
}
}, E = class {
constructor(t) {
this.handlers = t, this.$items = $("#checkout-items"), this.$total = $("#checkout-total"), this.$message = $("#checkout-message"), this.$couponStatus = $("#checkout-coupon-status"), this.$couponInput = $("#checkout-coupon"), this.$cpfInput = $("#checkout-cpf"), this.$submitButton = $("#checkout-submit"), this.$couponButton = $("#checkout-apply-coupon"), this.$fieldErrors = {
name: $("#checkout-name-error"),
cpf: $("#checkout-cpf-error"),
email: $("#checkout-email-error"),
nickname: $("#checkout-nickname-error")
}, this.#t();
}
#t() {
this.$items.on("click", ".checkout-remove-btn", (t) => {
const e = String($(t.currentTarget).data("id"));
this.handlers.onRemoveItem(e);
}), this.$items.on("click", ".checkout-qty-btn", (t) => {
const e = $(t.currentTarget), o = String(e.data("id")), s = Number(e.data("delta"));
this.handlers.onQuantityChange(o, s);
}), this.$couponButton.on("click", async () => {
await this.handlers.onApplyCoupon();
}), this.$couponInput.on("input", () => {
this.setCouponStatus(null);
}), this.$cpfInput.on("input", (t) => {
const e = $(t.currentTarget), o = this.#e(e.val());
e.val() !== o && e.val(o);
}), $('input[name="payment_method"]').on("change", (t) => {
this.handlers.onPaymentMethodChange(String($(t.currentTarget).val()));
}), $("#checkout-form").on("submit", async (t) => {
t.preventDefault(), await this.handlers.onSubmit();
});
}
renderItems(t) {
if (!t.length) {
this.$items.html('<p class="text-center py-8 text-[#6b6560]">Carrinho vazio</p>');
return;
}
const e = t.map((o) => `
<div class="flex items-center gap-2 p-2 bg-[#f8f7f4] rounded-xl">
<img src="${r(o.image || "https://placehold.co/64x64/F0EDE8/9CA3AF")}" alt="${r(o.name)}" class="w-12 h-12 rounded-lg object-cover shrink-0" />
<div class="flex-1 min-w-0">
<p class="font-medium text-xs text-[#1a1714] truncate">${r(o.name)}</p>
<p class="text-[#6b6560] text-xs">${h(o.price)}</p>
</div>
<div class="flex items-center gap-1 shrink-0">
<button class="checkout-qty-btn w-7 h-7 rounded-lg bg-white border border-[#e8e4df] text-[#1a1714] hover:bg-[#f8f7f4] disabled:opacity-50 disabled:cursor-not-allowed" ${Number(o.qty) <= 1 ? "disabled" : ""} data-id="${r(o.id)}" data-delta="-1">
<i class="fas fa-minus text-xs"></i>
</button>
<span class="w-6 text-center text-sm font-bold">${Number(o.qty)}</span>
<button class="checkout-qty-btn w-7 h-7 rounded-lg bg-white border border-[#e8e4df] text-[#1a1714] hover:bg-[#f8f7f4] disabled:opacity-50 disabled:cursor-not-allowed" ${o.stock !== null && Number(o.stock) > 0 && Number(o.qty) >= Number(o.stock) ? "disabled" : ""} data-id="${r(o.id)}" data-delta="1">
<i class="fas fa-plus text-xs"></i>
</button>
</div>
<button class="checkout-remove-btn text-red-500 hover:text-red-700 p-1 shrink-0 disabled:opacity-50 disabled:cursor-not-allowed" data-id="${r(o.id)}">
<i class="fas fa-trash text-xs"></i>
</button>
</div>
`).join("");
this.$items.html(e);
}
setTotal(t) {
this.$total.text(h(t));
}
getFormData() {
return {
name: String($("#checkout-name").val() || "").trim(),
nickname: String($("#checkout-nickname").val() || "").trim(),
email: String($("#checkout-email").val() || "").trim(),
cpf: String($("#checkout-cpf").val() || "").replace(/\D/g, ""),
note: String($("#checkout-note").val() || "").trim(),
coupon: String($("#checkout-coupon").val() || "").trim(),
paymentMethod: String($('input[name="payment_method"]:checked').val() || "PIX")
};
}
setFieldError(t, e) {
const o = this.$fieldErrors[t];
if (!(!o || !o.length)) {
if (!e) {
o.addClass("hidden").text("");
return;
}
o.removeClass("hidden").text(e);
}
}
clearFieldErrors() {
Object.keys(this.$fieldErrors).forEach((t) => {
this.setFieldError(t, "");
});
}
#e(t) {
const e = String(t || "").replace(/\D/g, "").slice(0, 11), o = [];
e.length > 0 && o.push(e.slice(0, 3)), e.length > 3 && o.push(e.slice(3, 6)), e.length > 6 && o.push(e.slice(6, 9));
let s = o.join(".");
return e.length > 9 && (s += `-${e.slice(9, 11)}`), s;
}
setSubmitLabel(t) {
const e = t === "CARD" ? '<i class="fas fa-credit-card mr-2"></i> Pagar com Cartão' : '<i class="fas fa-qrcode mr-2"></i> Pagar com PIX';
this.$submitButton.html(e);
}
setSubmitLoading(t, e) {
if (t) {
this.$submitButton.prop("disabled", !0).html('<i class="fas fa-spinner fa-spin mr-2"></i> Processando...');
return;
}
this.$submitButton.prop("disabled", !1), this.setSubmitLabel(e);
}
setCouponLoading(t) {
if (t) {
this.$couponButton.prop("disabled", !0).html('<i class="fas fa-spinner fa-spin mr-2"></i> Validando...');
return;
}
this.$couponButton.prop("disabled", !1).html('<i class="fas fa-ticket mr-2"></i> Aplicar');
}
showMessage(t, e) {
this.messageTimer && (clearTimeout(this.messageTimer), this.messageTimer = null), this.$message.removeClass("hidden bg-green-100 text-green-700 bg-red-100 text-red-700").addClass(t === "success" ? "bg-green-100 text-green-700" : "bg-red-100 text-red-700").text(e), this.messageTimer = setTimeout(() => {
this.hideMessage();
}, 3500);
}
hideMessage() {
this.messageTimer && (clearTimeout(this.messageTimer), this.messageTimer = null), this.$message.addClass("hidden").text("");
}
setCouponStatus(t) {
if (!t) {
this.$couponStatus.addClass("hidden").text("").removeClass("text-green-700 text-red-600");
return;
}
this.$couponStatus.removeClass("hidden text-green-700 text-red-600").addClass(t.type === "success" ? "text-green-700" : "text-red-600").text(t.text);
}
resetForm() {
const t = $("#checkout-form")[0];
t && t.reset(), this.setSubmitLabel("PIX"), this.setCouponStatus(null);
}
}, N = class {
constructor() {
this.$pixModal = $("#pix-modal"), this.$pixPanel = $("#pix-modal-panel"), this.$cardModal = $("#card-modal"), this.$cardPanel = $("#card-modal-panel");
}
showFromPaymentResponse(t) {
const e = t?.data?.payment || {};
if (e?.qr_code) {
this.#t(e);
return;
}
this.#e(e);
}
#t(t) {
const e = t?.qr_code || {};
let o = e.image || "";
o && !String(o).startsWith("data:") && !String(o).startsWith("http") && (o = `data:image/png;base64,${o}`), this.$pixPanel.html(`
<div class="mb-5">
<i class="fas fa-qrcode text-4xl text-[#c8502a] mb-3 block"></i>
<h3 class="text-xl font-bold text-[#1a1714]">Pagamento PIX</h3>
<p class="text-[#6b6560] text-sm mt-1">Escaneie o QR Code com seu banco.</p>
</div>
${o ? `<img src="${r(o)}" alt="QR Code PIX" class="w-48 h-48 mx-auto mb-4 rounded-xl border-2 border-[#e8e4df] p-2">` : ""}
${e.base_64 ? `
<div class="flex gap-2 mb-4">
<input id="pix-code" readonly value="${r(e.base_64)}" class="flex-1 px-3 py-2 bg-[#f8f7f4] border border-[#e8e4df] rounded-lg text-xs font-mono min-w-0" />
<button id="pix-copy" class="px-3 py-2 bg-[#1a1714] text-white rounded-lg hover:bg-[#c8502a] transition-colors shrink-0" title="Copiar codigo PIX">
<i class="fas fa-copy"></i>
</button>
</div>
` : ""}
<button id="pix-close" class="w-full py-3 border-2 border-[#e8e4df] text-[#6b6560] font-semibold rounded-xl hover:border-[#1a1714] hover:text-[#1a1714] transition-all">
Concluir
</button>
`), d(this.$pixModal, !0), $("#pix-copy").off("click").on("click", async () => {
try {
await navigator.clipboard.writeText(String(e.base_64 || ""));
const s = $("#pix-copy");
s.html('<i class="fas fa-check"></i>'), setTimeout(() => {
s.html('<i class="fas fa-copy"></i>');
}, l.COPY_FEEDBACK_MS);
} catch {
}
}), $("#pix-close").off("click").on("click", () => {
d(this.$pixModal, !1);
});
}
#e(t) {
this.$cardPanel.html(`
<div class="text-center p-8 bg-white rounded-[2.5rem] shadow-2xl border border-[#e8e4df]">
<div class="inline-flex items-center justify-center w-20 h-20 bg-[#1a1714] rounded-full mb-6 shadow-lg">
<i class="fas fa-credit-card text-2xl text-white"></i>
</div>
<h3 class="text-2xl font-black text-[#1a1714] tracking-tighter mb-2">Pagamento com Cartão</h3>
<p class="text-[#6b6560] text-sm mb-8 leading-relaxed max-w-[240px] mx-auto">
Método de pagamento: cartão. Clique abaixo para abrir o portal seguro.
</p>
${t.url ? `
<a href="${r(t.url)}"
target="_blank"
rel="noopener"
class="block w-full py-5 bg-[#1a1714] text-white font-black rounded-2xl text-center mb-4 hover:bg-[#000000] active:scale-[0.97] transition-all shadow-xl shadow-black/20 uppercase tracking-[0.15em] text-[11px]">
<span class="text-white !opacity-100">FINALIZAR PAGAMENTO</span>
</a>
` : ""}
${t.uuid ? `
<div class="inline-block bg-[#f8f7f4] rounded-full px-4 py-1.5 mb-8 border border-[#e8e4df]">
<p class="text-[#6b6560] text-[9px] font-bold tracking-widest uppercase">
REF: <span class="text-[#1a1714] font-black">${r(t.uuid.split("-")[0])}</span>
</p>
</div>
` : ""}
<button id="card-close" class="w-full py-3 border-2 border-[#e8e4df] text-[#6b6560] font-semibold rounded-xl hover:border-[#1a1714] hover:text-[#1a1714] transition-all">
Concluir
</button>
</div>
`), d(this.$cardModal, !0), $("#card-close").off("click").on("click", () => {
d(this.$cardModal, !1);
});
}
}, D = class {
constructor() {
this.apiService = null, this.cartStorage = new C(), this.productsComponent = null, this.categoriesComponent = null, this.cartDrawer = null, this.checkoutComponent = null, this.paymentModal = new N(), this.appliedCouponCode = null, this.storeId = "", this.currentPage = 1, this.activeCategory = "all";
}
async init() {
if (!window.jQuery) {
setTimeout(() => this.init(), 80);
return;
}
if (!p) {
setTimeout(() => this.init(), 100);
return;
}
if (this.storeId = String($("meta[name='loja-id']").attr("content") || "").trim(), !this.storeId) {
$("#products-list").html(`
<div class="text-center py-12 text-red-600">
<i class="fas fa-triangle-exclamation text-4xl mb-3 block"></i>
<p>Meta loja-id nao encontrada no HTML.</p>
</div>
`);
return;
}
this.apiService = new b(p, this.storeId), this.productsComponent = new I({
onAddToCart: (t) => this.handleAddToCart(t),
onPageChange: (t) => this.handlePageChange(t)
}), this.categoriesComponent = new P({ onCategoryChange: (t) => this.handleCategoryChange(t) }), this.cartDrawer = new T(), this.cartDrawer.bindEvents(), this.checkoutComponent = new E({
onRemoveItem: (t) => this.handleRemoveItem(t),
onQuantityChange: (t, e) => this.handleQuantityChange(t, e),
onApplyCoupon: async () => {
await this.handleApplyCoupon();
},
onSubmit: async () => {
await this.handleCheckoutSubmit();
},
onPaymentMethodChange: (t) => {
this.checkoutComponent.setSubmitLabel(t === "CARD" ? "CARD" : "PIX");
}
}), this.syncCartUI(), await this.loadCategories(), await this.loadProducts();
}
async loadCategories() {
try {
const t = await this.apiService.getCategories();
this.categoriesComponent.setCategories(t), this.categoriesComponent.setActiveCategory(this.activeCategory);
} catch {
this.categoriesComponent.setCategories([]), this.categoriesComponent.setActiveCategory("all");
}
}
async loadProducts(t = 1) {
try {
this.currentPage = t;
const e = await this.apiService.getProducts(t), o = this.cartStorage.getItems(), s = e.products.map((a) => {
const i = o.find((c) => String(c.id) === String(a.id));
return {
...a,
inCartQty: i ? i.qty : 0
};
});
this.productsComponent.setProducts({
...e,
products: s
}), this.productsComponent.setActiveCategory(this.activeCategory);
} catch (e) {
$("#products-list").html(`
<div class="text-center py-12 text-red-600">
<i class="fas fa-triangle-exclamation text-4xl mb-3 block"></i>
<p>Falha ao carregar produtos.</p>
<p class="text-sm text-[#6b6560] mt-2">${String(e?.message || "Erro desconhecido")}</p>
</div>
`);
}
}
handlePageChange(t) {
this.loadProducts(t), $("#shop")[0]?.scrollIntoView({
behavior: "smooth",
block: "start"
});
}
handleCategoryChange(t) {
this.activeCategory = String(t || "all"), this.productsComponent.setActiveCategory(this.activeCategory);
}
handleAddToCart(t) {
const e = t.stock === null || t.stock === void 0 ? null : Number(t.stock);
return e !== null && e <= 0 ? (this.checkoutComponent.showMessage("error", "Este produto esta sem estoque."), !1) : (this.cartStorage.addProduct(t), this.syncCartUI(), !0);
}
handleRemoveItem(t) {
this.cartStorage.removeProduct(t), this.syncCartUI();
}
handleQuantityChange(t, e) {
this.cartStorage.changeQuantity(t, e), this.syncCartUI();
}
syncCartUI() {
const t = this.cartStorage.getItems();
this.cartDrawer.setCount(this.cartStorage.getTotalItems()), this.checkoutComponent.renderItems(t), this.checkoutComponent.setTotal(this.cartStorage.getTotalPrice()), this.productsComponent.updateButtonsStates(t);
}
async handleApplyCoupon() {
this.checkoutComponent.hideMessage();
const { coupon: t } = this.checkoutComponent.getFormData();
if (!t)
return this.appliedCouponCode = null, this.checkoutComponent.setCouponStatus({
type: "error",
text: "Digite um cupom para aplicar."
}), !1;
this.checkoutComponent.setCouponLoading(!0);
try {
const e = await this.apiService.validateCoupon(t), o = e?.coupon;
if (!e?.status || !o?.code) throw new Error("Cupom invalido ou indisponivel.");
return this.appliedCouponCode = String(o.code), this.checkoutComponent.setCouponStatus({
type: "success",
text: `Cupom aplicado: ${String(o.code).toUpperCase()} (-${Number(o.discount || 0)}%)`
}), !0;
} catch {
return this.appliedCouponCode = null, this.checkoutComponent.setCouponStatus({
type: "error",
text: "Cupom invalido, expirado ou indisponivel para esta loja."
}), !1;
} finally {
this.checkoutComponent.setCouponLoading(!1);
}
}
async handleCheckoutSubmit() {
this.checkoutComponent.hideMessage();
const t = this.cartStorage.getItems();
if (!w(t)) {
this.checkoutComponent.showMessage("error", "Seu carrinho esta vazio.");
return;
}
const e = this.checkoutComponent.getFormData();
if (this.checkoutComponent.clearFieldErrors(), !x(e.name)) {
this.checkoutComponent.setFieldError("name", "Informe um nome valido com pelo menos 3 caracteres."), this.checkoutComponent.showMessage("error", "Corrija os campos destacados.");
return;
}
if (!y(e.nickname)) {
this.checkoutComponent.setFieldError("nickname", "O apelido deve ter entre 4 e 32 caracteres."), this.checkoutComponent.showMessage("error", "Corrija os campos destacados.");
return;
}
if (!k(e.email)) {
this.checkoutComponent.setFieldError("email", "Informe um e-mail valido."), this.checkoutComponent.showMessage("error", "Corrija os campos destacados.");
return;
}
if (e.cpf && !v(e.cpf)) {
this.checkoutComponent.setFieldError("cpf", "O CPF deve ter 11 numeros."), this.checkoutComponent.showMessage("error", "Corrija os campos destacados.");
return;
}
if (e.coupon && !this.appliedCouponCode && !await this.handleApplyCoupon())
return;
e.coupon || (this.appliedCouponCode = null, this.checkoutComponent.setCouponStatus(null));
const o = e.paymentMethod === "CARD" ? "CARD" : "PIX", s = {
name: e.name,
email: e.email,
cpf: e.cpf || void 0,
gateway: o === "CARD" ? m.CARD : m.PIX,
coupon: this.appliedCouponCode || void 0,
metadata: e.note || e.nickname ? {
...e.note ? { observation: e.note } : {},
...e.nickname ? { nickname: e.nickname } : {}
} : void 0,
items: t.map((a) => ({
productId: String(a.id),
quantity: Number(a.qty)
}))
};
this.checkoutComponent.setSubmitLoading(!0, o);
try {
const a = await this.apiService.createPayment(s);
if (!a?.status) throw new Error(a?.message || "Falha ao criar pagamento.");
this.paymentModal.showFromPaymentResponse(a), this.cartStorage.clear(), this.syncCartUI(), this.appliedCouponCode = null, this.checkoutComponent.resetForm(), this.checkoutComponent.showMessage("success", "Pagamento criado com sucesso.");
} catch (a) {
this.checkoutComponent.showMessage("error", String(a?.message || "Erro ao processar pagamento."));
} finally {
this.checkoutComponent.setSubmitLoading(!1, o);
}
}
};
new D().init();
</script>
</head>
<body class="bg-[#f8f7f4] text-[#1a1714] min-h-screen flex flex-col">
<!-- Navbar -->
<nav class="sticky top-0 z-[200] bg-[#f8f7f4]/95 backdrop-blur-md border-b border-[#e8e4df] shadow-sm">
<div class="max-w-6xl mx-auto px-4">
<!-- Toggle -->
<input type="checkbox" id="menu-toggle" class="peer hidden">
<div class="flex items-center justify-between h-16 md:h-[68px]">
<!-- Logo -->
<a href="#" class="flex items-center gap-3 hover:opacity-80 transition-opacity">
<div
class="w-10 h-10 bg-[#1a1714] rounded-xl flex items-center justify-center text-white shadow-md">
<i class="fas fa-store-alt text-lg"></i>
</div>
<span class="text-lg font-medium tracking-tight text-[#1a1714]">
Loja <strong class="font-bold text-[#c8502a]">Virtual</strong>
</span>
</a>
<!-- Desktop Menu -->
<ul class="hidden md:flex items-center gap-2 list-none m-0 p-0">
<li>
<a href="#"
class="group relative flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all duration-300">
<i class="fas fa-house text-xs"></i>
Início
<span
class="absolute left-4 bottom-1 w-0 h-[2px] bg-[#c8502a] rounded-full transition-all duration-300 group-hover:w-[55%]"></span>
</a>
</li>
<li>
<a href="#shop"
class="group relative flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all duration-300">
<i class="fas fa-store text-xs"></i>
Loja
<span
class="absolute left-4 bottom-1 w-0 h-[2px] bg-[#c8502a] rounded-full transition-all duration-300 group-hover:w-[45%]"></span>
</a>
</li>
<li>
<a href="#"
class="group relative flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all duration-300">
<i class="fab fa-discord text-xs"></i>
Discord
<span
class="absolute left-4 bottom-1 w-0 h-[2px] bg-[#c8502a] rounded-full transition-all duration-300 group-hover:w-[65%]"></span>
</a>
</li>
</ul>
<!-- Actions -->
<div class="flex items-center gap-3">
<!-- Cart -->
<a href="#" id="cart-toggle" aria-label="Abrir carrinho"
class="group relative w-11 h-11 rounded-xl border border-[#e8e4df] bg-white flex items-center justify-center text-[#1a1714] shadow-sm hover:bg-[#1a1714] hover:border-[#1a1714] transition-all duration-300">
<i
class="fas fa-bag-shopping text-lg transition-colors duration-300 group-hover:text-white"></i>
<span id="cart-count"
class="absolute -top-1 -right-1 min-w-5 h-5 px-1.5 bg-[#c8502a] text-white text-[0.65rem] rounded-full flex items-center justify-center font-bold border-2 border-white">
0
</span>
</a>
<!-- Mobile Button -->
<label for="menu-toggle"
class="md:hidden w-11 h-11 rounded-xl border border-[#e8e4df] bg-white flex items-center justify-center cursor-pointer text-[#1a1714] hover:bg-[#f0ede8] transition-all duration-300">
<i class="fas fa-bars text-lg"></i>
</label>
</div>
</div>
<!-- Mobile Menu -->
<div class="hidden peer-checked:block md:hidden border-t border-[#e8e4df] py-4">
<div class="flex flex-col gap-2">
<a href="#"
class="flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all">
<i class="fas fa-house w-4 text-center"></i>
Início
</a>
<a href="#shop"
class="flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all">
<i class="fas fa-store w-4 text-center"></i>
Loja
</a>
<a href="#"
class="flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all">
<i class="fab fa-discord w-4 text-center"></i>
Discord
</a>
</div>
</div>
</div>
</nav>
<header id="hero" class="relative overflow-hidden py-20 md:py-28 px-4">
<!-- Background -->
<div class="absolute inset-0 bg-gradient-to-b from-[#f8f7f4] via-[#faf8f6] to-[#f4f1ed] -z-10"></div>
<!-- Blur Effects -->
<div
class="absolute top-[-120px] right-[-80px] w-[320px] h-[320px] bg-[#c8502a]/10 rounded-full blur-3xl -z-10">
</div>
<div
class="absolute bottom-[-100px] left-[-80px] w-[260px] h-[260px] bg-[#1a1714]/5 rounded-full blur-3xl -z-10">
</div>
<div class="max-w-7xl mx-auto">
<div class="grid md:grid-cols-2 gap-14 items-center">
<!-- Left Content -->
<div>
<!-- Badge -->
<div
class="inline-flex items-center gap-2 px-4 py-2 bg-white border border-[#ebe5df] rounded-full mb-6 shadow-sm">
<span class="w-2 h-2 bg-[#c8502a] rounded-full animate-pulse"></span>
<span class="text-sm font-medium text-[#4f4a46]">
Loja online • Entrega expressa
</span>
</div>
<!-- Title -->
<h1 class="text-4xl md:text-6xl leading-[1.05] font-bold tracking-tight text-[#1a1714] mb-6"
style="font-family:'DM Serif Display', serif;">
Sua loja virtual
<span class="block text-[#c8502a]">
moderna e completa
</span>
</h1>
<!-- Description -->
<p class="text-lg text-[#6b6560] leading-relaxed max-w-xl mb-8">
Produtos selecionados, preços acessíveis e uma experiência premium para quem busca
qualidade, velocidade e praticidade.
</p>
<!-- Buttons -->
<div class="flex flex-wrap gap-4 mb-10">
<!-- Produtos -->
<a href="#shop"
class="group inline-flex items-center gap-3 px-7 py-4 rounded-2xl bg-white border border-[#e8e4df] text-[#1a1714] font-semibold shadow-sm transition-all duration-300 hover:border-[#c8502a] hover:-translate-y-1 hover:shadow-lg">
<i
class="fas fa-store transition-all duration-300 group-hover:scale-110 group-hover:text-[#c8502a]"></i>
<span class="transition-colors duration-300 group-hover:text-[#c8502a]">
Ver produtos
</span>
</a>
<!-- Discord -->
<a href="#"
class="group inline-flex items-center gap-3 px-7 py-4 rounded-2xl bg-white border border-[#e8e4df] text-[#1a1714] font-semibold shadow-sm transition-all duration-300 hover:border-[#c8502a] hover:-translate-y-1 hover:shadow-lg">
<i
class="fab fa-discord transition-all duration-300 group-hover:scale-110 group-hover:text-[#c8502a]"></i>
<span class="transition-colors duration-300 group-hover:text-[#c8502a]">
Discord
</span>
</a>
</div>
<!-- Stats -->
<div class="flex flex-wrap gap-8">
<div>
<strong class="block text-2xl font-bold text-[#1a1714]">
+12k
</strong>
<span class="text-sm text-[#6b6560]">
Clientes ativos
</span>
</div>
<div>
<strong class="block text-2xl font-bold text-[#1a1714]">
24h
</strong>
<span class="text-sm text-[#6b6560]">
Entrega rápida
</span>
</div>
<div>
<strong class="block text-2xl font-bold text-[#1a1714]">
4.9★
</strong>
<span class="text-sm text-[#6b6560]">
Avaliação média
</span>
</div>
</div>
</div>
<div class="relative hidden md:block">
<!-- Fundo decorativo -->
<div class="absolute -top-8 -right-8 w-40 h-40 bg-[#c8502a]/10 rounded-full blur-3xl">
</div>
<!-- Container da imagem -->
<div
class="relative overflow-hidden rounded-[32px] shadow-[0_35px_80px_rgba(0,0,0,0.14)]">
<img src="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download"
alt="Produto em destaque"
class="w-full h-[540px] object-cover rounded-[32px] transition-transform duration-500 hover:scale-[1.03]" />
<!-- Overlay suave -->
<div
class="absolute inset-0 bg-gradient-to-t from-black/10 to-transparent rounded-[32px]">
</div>
</div>
<!-- Card flutuante -->
<div
class="absolute bottom-6 left-6 bg-white/95 backdrop-blur-md px-5 py-4 rounded-2xl shadow-[0_15px_40px_rgba(0,0,0,0.12)] flex items-center gap-4 border border-[#e8e4df]">
<div
class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center flex-shrink-0 shadow-sm">
<i class="fas fa-bolt text-[#c8502a] text-xl"></i>
</div>
<div>
<strong class="text-sm block text-[#1a1714] font-semibold">
Entrega instantânea
</strong>
<span class="text-xs text-[#6b6560]">
Receba em minutos
</span>
</div>
</div>
</div>
</div>
</div>
</header>
<section class="py-16 px-4 bg-white">
<div class="max-w-6xl mx-auto">
<div class="text-center mb-12">
<p class="text-[#c8502a] text-sm font-semibold uppercase tracking-wider mb-2"><i
class="fas fa-shield-halved mr-2"></i> Diferenciais</p>
<h2 class="text-3xl md:text-4xl font-bold mb-3" style="font-family:'DM Serif Display',serif;">
Por que comprar aqui?</h2>
<p class="text-[#6b6560]">Segurança, rapidez e confiança em cada pedido</p>
</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-6">
<div class="bg-[#f8f7f4] p-6 rounded-2xl hover:shadow-lg transition-shadow">
<div class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center mb-4"><i
class="fas fa-bolt text-[#c8502a] text-2xl"></i></div>
<h3 class="font-bold mb-2">Entrega rápida</h3>
<p class="text-sm text-[#6b6560]">Receba seu produto em minutos ou de forma totalmente
automática após o pagamento.</p>
</div>
<div class="bg-[#f8f7f4] p-6 rounded-2xl hover:shadow-lg transition-shadow">
<div class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center mb-4"><i
class="fas fa-lock text-[#c8502a] text-2xl"></i></div>
<h3 class="font-bold mb-2">Pagamento seguro</h3>
<p class="text-sm text-[#6b6560]">Transações protegidas com criptografia e validação em
tempo real.</p>
</div>
<div class="bg-[#f8f7f4] p-6 rounded-2xl hover:shadow-lg transition-shadow">
<div class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center mb-4"><i
class="fas fa-headset text-[#c8502a] text-2xl"></i></div>
<h3 class="font-bold mb-2">Suporte ativo</h3>
<p class="text-sm text-[#6b6560]">Atendimento ágil via Discord ou chat para qualquer
dúvida ou problema.</p>
</div>
<div class="bg-[#f8f7f4] p-6 rounded-2xl hover:shadow-lg transition-shadow">
<div class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center mb-4"><i
class="fas fa-tag text-[#c8502a] text-2xl"></i></div>
<h3 class="font-bold mb-2">Melhor preço</h3>
<p class="text-sm text-[#6b6560]">Produtos acessíveis com promoções constantes para
economizar sempre.</p>
</div>
</div>
</div>
</section>
<div class="max-w-6xl mx-auto px-4">
<div class="border-t border-[#e8e4df]"></div>
</div>
<section id="shop" class="py-16 px-4">
<div class="max-w-6xl mx-auto">
<div class="flex flex-col md:flex-row md:items-end justify-between mb-10 gap-4">
<div>
<p class="text-[#c8502a] text-sm font-semibold uppercase tracking-wider mb-2"><i
class="fas fa-store mr-2"></i> Catálogo</p>
<h2 class="text-3xl md:text-4xl font-bold" style="font-family:'DM Serif Display',serif;">
Nossos produtos</h2>
</div>
</div>
<div id="category-filters" class="flex flex-wrap gap-2 mb-8"></div>
<div id="products-list">
<div class="text-center py-16 text-[#6b6560]"><i
class="fas fa-spinner fa-spin text-3xl mb-4 block"></i>
<p>Carregando produtos…</p>
</div>
</div>
<div id="products-pagination"></div>
</div>
</section>
<div class="max-w-6xl mx-auto px-4">
<div class="border-t border-[#e8e4df]"></div>
</div>
<section class="py-16 px-4">
<div class="max-w-6xl mx-auto">
<div class="text-center mb-12">
<p class="text-[#c8502a] text-sm font-semibold uppercase tracking-wider mb-2"><i
class="fas fa-chart-line mr-2"></i> Resultados</p>
<h2 class="text-3xl md:text-4xl font-bold mb-3" style="font-family:'DM Serif Display',serif;">
Transparência em números</h2>
<p class="text-[#6b6560]">Dados reais de quem já comprou com a gente</p>
</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-6">
<div
class="bg-white p-6 rounded-2xl border border-[#e8e4df] text-center hover:shadow-lg transition-shadow">
<div
class="w-14 h-14 bg-[#f8f7f4] rounded-2xl flex items-center justify-center mx-auto mb-4">
<i class="fas fa-shopping-cart text-[#1a1714] text-2xl"></i>
</div>
<div class="text-3xl font-bold">+1.200</div>
<div class="text-sm text-[#6b6560] mt-1">Vendas realizadas</div>
</div>
<div
class="bg-white p-6 rounded-2xl border border-[#e8e4df] text-center hover:shadow-lg transition-shadow">
<div
class="w-14 h-14 bg-[#f8f7f4] rounded-2xl flex items-center justify-center mx-auto mb-4">
<i class="fas fa-users text-[#1a1714] text-2xl"></i>
</div>
<div class="text-3xl font-bold">+500</div>
<div class="text-sm text-[#6b6560] mt-1">Clientes ativos</div>
</div>
<div
class="bg-white p-6 rounded-2xl border border-[#e8e4df] text-center hover:shadow-lg transition-shadow">
<div
class="w-14 h-14 bg-[#f8f7f4] rounded-2xl flex items-center justify-center mx-auto mb-4">
<i class="fas fa-star text-[#1a1714] text-2xl"></i>
</div>
<div class="text-3xl font-bold">99%</div>
<div class="text-sm text-[#6b6560] mt-1">Satisfação</div>
</div>
<div
class="bg-white p-6 rounded-2xl border border-[#e8e4df] text-center hover:shadow-lg transition-shadow">
<div
class="w-14 h-14 bg-[#f8f7f4] rounded-2xl flex items-center justify-center mx-auto mb-4">
<i class="fas fa-headset text-[#1a1714] text-2xl"></i>
</div>
<div class="text-3xl font-bold">24h</div>
<div class="text-sm text-[#6b6560] mt-1">Suporte ativo</div>
</div>
</div>
</div>
</section>
<div class="max-w-6xl mx-auto px-4">
<div class="border-t border-[#e8e4df]"></div>
</div>
<section class="py-16 px-4">
<div class="max-w-4xl mx-auto">
<div class="bg-[#1a1714] rounded-3xl p-10 md:p-14 text-center text-white relative overflow-hidden">
<div class="absolute inset-0 opacity-5"
style="background-image:radial-gradient(circle at 20% 50%, #c8502a 1px, transparent 1px);background-size:30px 30px;">
</div>
<p class="text-xs font-bold uppercase tracking-[0.2em] text-[#a09a94] mb-3 relative z-10">
Atendimento</p>
<h2 class="text-3xl md:text-4xl font-bold mb-4 relative z-10"
style="font-family:'DM Serif Display',serif;">Precisa de ajuda?</h2>
<p class="text-[#a09a94] mb-8 max-w-lg mx-auto relative z-10">Fale com nosso suporte em segundos
— estamos sempre disponíveis.</p>
<a href="#"
class="inline-flex items-center gap-2 px-6 py-3.5 bg-[#5865F2] text-white font-semibold rounded-xl hover:bg-[#4752C4] transition-all relative z-10 shadow-lg"><i
class="fab fa-discord text-lg"></i> Abrir suporte no Discord</a>
</div>
</div>
</section>
<section class="py-16 px-4 bg-white">
<div class="max-w-3xl mx-auto">
<div class="text-center mb-12">
<p class="text-[#c8502a] text-sm font-semibold uppercase tracking-wider mb-2"><i
class="fas fa-circle-question mr-2"></i> Dúvidas</p>
<h2 class="text-3xl md:text-4xl font-bold mb-3" style="font-family:'DM Serif Display',serif;">
Perguntas frequentes</h2>
<p class="text-[#6b6560]">As respostas que você precisa antes de comprar</p>
</div>
<div class="space-y-3">
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i
class="fas fa-shopping-cart mr-3 text-[#6b6560]"></i>Como funciona a
compra?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">Você escolhe o produto, finaliza o
pagamento via PIX e recebe automaticamente as instruções ou acesso no seu e-mail
logo após a confirmação.</p>
</details>
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i
class="fas fa-shield-halved mr-3 text-[#6b6560]"></i>É seguro comprar
aqui?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">Sim. Utilizamos sistemas seguros de
pagamento e validação para proteger todas as transações. Seus dados são
criptografados.</p>
</details>
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i class="fas fa-clock mr-3 text-[#6b6560]"></i>Quanto
tempo demora para receber?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">A maioria das entregas é
instantânea ou feita em poucos minutos após a confirmação do pagamento. Produtos
físicos têm prazo estimado no momento da compra.</p>
</details>
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i class="fas fa-headset mr-3 text-[#6b6560]"></i>Como
funciona o suporte?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">Oferecemos suporte via Discord e
e-mail. Nossa equipe responde rapidamente durante todo o dia para resolver qualquer
dúvida ou problema.</p>
</details>
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i
class="fas fa-rotate-left mr-3 text-[#6b6560]"></i>Posso pedir
reembolso?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">Sim, em casos de problema no
produto ou não entrega. Entre em contato com nosso suporte e avaliaremos seu caso o
mais rápido possível.</p>
</details>
</div>
</div>
</section>
<div id="checkout" role="dialog" aria-modal="true" aria-label="Carrinho e pagamento"
class="fixed inset-0 z-[300] bg-[#1a1714]/70 backdrop-blur-sm flex items-end md:items-center justify-center p-0 md:p-4 opacity-0 pointer-events-none transition-all duration-300">
<div id="checkout-panel"
class="bg-white w-full max-w-[860px] rounded-t-3xl md:rounded-3xl max-h-[95vh] md:max-h-[92vh] overflow-y-auto p-4 md:p-8 pb-24 md:pb-8">
<div class="flex items-center justify-between mb-6 pb-5 border-b border-[#e8e4df]">
<div>
<h2 class="text-xl font-bold"><i class="fas fa-bag-shopping mr-2"></i> Carrinho e
pagamento</h2>
<p class="text-[#6b6560] text-sm mt-1">Revise seu pedido e finalize via PIX em segundos.
</p>
</div>
<button id="checkout-close" aria-label="Fechar carrinho"
class="w-10 h-10 rounded-xl border border-[#e8e4df] flex items-center justify-center hover:bg-[#f8f7f4] transition-colors"><i
class="fas fa-xmark"></i></button>
</div>
<div id="checkout-message" class="hidden p-3 rounded-xl text-sm mb-4"></div>
<div class="grid md:grid-cols-2 gap-8">
<div>
<p class="text-sm font-bold uppercase tracking-wider text-[#6b6560] mb-4"><i
class="fas fa-receipt mr-2"></i> Resumo do pedido</p>
<div id="checkout-items" class="flex flex-col gap-3"></div>
<div class="flex justify-between items-center pt-5 mt-5 border-t border-[#e8e4df]">
<span class="font-semibold">Total</span>
<strong id="checkout-total" class="text-2xl font-bold text-[#c8502a]">R$
0,00</strong>
</div>
</div>
<form id="checkout-form" novalidate class="flex flex-col gap-4">
<div class="flex flex-col gap-1.5">
<label for="checkout-name" class="text-sm font-semibold"><i
class="fas fa-user mr-2 text-[#6b6560]"></i>Nome completo</label>
<input id="checkout-name" name="name" placeholder="Seu nome completo"
autocomplete="name"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<p id="checkout-name-error" class="hidden text-xs font-medium text-red-600"></p>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-nickname" class="text-sm font-semibold"><i
class="fas fa-at mr-2 text-[#6b6560]"></i>Nickname <span
class="text-[#a09a94] font-normal">(opcional)</span></label>
<input id="checkout-nickname" name="nickname" placeholder="Seu apelido"
maxlength="32" autocomplete="nickname"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<p class="text-xs text-[#a09a94]">De 4 a 32 caracteres.</p>
<p id="checkout-nickname-error" class="hidden text-xs font-medium text-red-600"></p>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-email" class="text-sm font-semibold"><i
class="fas fa-envelope mr-2 text-[#6b6560]"></i>E-mail</label>
<input id="checkout-email" name="email" type="email" placeholder="voce@email.com"
autocomplete="email"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<p id="checkout-email-error" class="hidden text-xs font-medium text-red-600"></p>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-cpf" class="text-sm font-semibold"><i
class="fas fa-id-card mr-2 text-[#6b6560]"></i>CPF <span
class="text-[#a09a94] font-normal">(opcional)</span></label>
<input id="checkout-cpf" name="cpf" placeholder="000.000.000-00" inputmode="numeric"
maxlength="14"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<p id="checkout-cpf-error" class="hidden text-xs font-medium text-red-600"></p>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-note" class="text-sm font-semibold"><i
class="fas fa-comment mr-2 text-[#6b6560]"></i>Observação <span
class="text-[#a09a94] font-normal">(opcional)</span></label>
<textarea id="checkout-note" name="note" rows="2" placeholder="Algo a informar?"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all resize-none"></textarea>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-coupon" class="text-sm font-semibold"><i
class="fas fa-ticket mr-2 text-[#6b6560]"></i>Cupom <span
class="text-[#a09a94] font-normal">(opcional)</span></label>
<div class="flex gap-2">
<input id="checkout-coupon" name="coupon" placeholder="Ex: BEMVINDO10"
class="flex-1 px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<button id="checkout-apply-coupon" type="button"
class="px-4 py-3 bg-white border border-[#e8e4df] text-[#1a1714] font-semibold rounded-xl hover:border-[#c8502a] hover:text-[#c8502a] disabled:opacity-60 transition-all whitespace-nowrap">
<i class="fas fa-ticket mr-2"></i> Aplicar
</button>
</div>
<p id="checkout-coupon-status" class="hidden text-xs font-medium"></p>
</div>
<div class="flex flex-col gap-3">
<label class="text-sm font-semibold"><i
class="fas fa-credit-card mr-2 text-[#6b6560]"></i>Forma de
pagamento</label>
<div class="grid grid-cols-2 gap-3">
<label class="cursor-pointer">
<input type="radio" name="payment_method" value="PIX" checked
class="peer sr-only" />
<div
class="p-3 border-2 border-[#e8e4df] rounded-xl peer-checked:border-[#c8502a] peer-checked:bg-[#fef3ec] hover:border-[#c8502a] transition-all text-center">
<i class="fas fa-qrcode text-xl text-[#6b6560]"></i>
<p class="font-semibold text-xs mt-1">PIX</p>
</div>
</label>
<label class="cursor-pointer">
<input type="radio" name="payment_method" value="CARD"
class="peer sr-only" />
<div
class="p-3 border-2 border-[#e8e4df] rounded-xl peer-checked:border-[#c8502a] peer-checked:bg-[#fef3ec] hover:border-[#c8502a] transition-all text-center">
<i class="fas fa-credit-card text-xl text-[#6b6560]"></i>
<p class="font-semibold text-xs mt-1">Cartão</p>
</div>
</label>
</div>
</div>
<button id="checkout-submit" type="submit"
class="w-full py-3 bg-[#1a1714] text-white font-semibold rounded-lg hover:bg-[#c8502a] disabled:opacity-50 transition-all shadow-sm"><i
class="fas fa-qrcode mr-2"></i> Pagar com PIX</button>
</form>
</div>
<div id="checkout-result" class="hidden mt-6 pt-5 border-t border-[#e8e4df]"></div>
</div>
</div>
<div id="pix-modal" role="dialog" aria-modal="true" aria-label="Pagamento PIX"
class="fixed inset-0 z-[400] bg-[#1a1714]/80 backdrop-blur-sm flex items-end md:items-center justify-center p-0 md:p-4 opacity-0 pointer-events-none transition-all duration-300">
<div id="pix-modal-panel"
class="bg-white w-full max-w-sm rounded-t-3xl md:rounded-2xl p-6 md:p-8 text-center pb-20 md:pb-8">
</div>
</div>
<div id="card-modal" role="dialog" aria-modal="true" aria-label="Pagamento Cartão"
class="fixed inset-0 z-[400] bg-[#1a1714]/80 backdrop-blur-sm flex items-end md:items-center justify-center p-0 md:p-4 opacity-0 pointer-events-none transition-all duration-300">
<div id="card-modal-panel"
class="bg-white w-full max-w-sm rounded-t-3xl md:rounded-2xl p-6 md:p-8 text-center pb-20 md:pb-8">
</div>
</div>
<footer class="bg-[#1a1714] text-white py-12 px-4 mt-auto">
<div class="max-w-6xl mx-auto">
<div class="flex flex-col md:flex-row justify-between items-center gap-8">
<div class="flex flex-col items-center md:items-start gap-4">
<a href="#" class="text-lg font-semibold">Loja <span
class="text-[#c8502a]">Virtual</span></a>
<div
class="flex flex-wrap justify-center md:justify-start gap-4 md:gap-6 text-sm text-[#a09a94]">
<a href="#" class="hover:text-white transition-colors"><i
class="fas fa-house mr-1"></i> Início</a>
<a href="#shop" class="hover:text-white transition-colors"><i
class="fas fa-store mr-1"></i> Loja</a>
<a href="#" class="hover:text-[#5865F2] transition-all"><i
class="fab fa-discord mr-1"></i> Discord</a>
</div>
</div>
<div class="flex gap-3">
<a href="#" aria-label="Instagram"
class="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center text-[#a09a94] hover:text-white hover:bg-white/20 transition-all"><i
class="fab fa-instagram"></i></a>
<a href="#" aria-label="YouTube"
class="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center text-[#a09a94] hover:text-white hover:bg-white/20 transition-all"><i
class="fab fa-youtube"></i></a>
<a href="#" aria-label="TikTok"
class="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center text-[#a09a94] hover:text-white hover:bg-white/20 transition-all"><i
class="fab fa-tiktok"></i></a>
<a href="#" aria-label="Discord"
class="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center text-[#a09a94] hover:text-[#5865F2] hover:bg-white/20 transition-all"><i
class="fab fa-discord"></i></a>
</div>
</div>
<div
class="flex flex-col md:flex-row justify-between items-center gap-3 pt-6 mt-6 border-t border-white/10 text-sm text-[#a09a94]">
<span>© 2026 Loja Virtual · Todos os direitos reservados</span>
<div class="flex items-center gap-2"><i class="fas fa-code text-xs"></i><span>Powered
by</span><span class="text-[#c8502a] font-semibold">caBRAPI</span></div>
</div>
</div>
</footer>
</body>
</html>
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="loja-id" content="ecf68475-0fe1-4224-a2f3-cb1cd3311d84" />
<!-- HTML Meta Tags -->
<title>Theme Light Shop | Template de Loja Virtual Moderna</title>
<meta name="description"
content="Template moderno para e-commerce com visual claro, performance elevada, SEO otimizado e experiência premium para lojas virtuais.">
<!-- Facebook Meta Tags -->
<meta property="og:url" content="https://demo-theme-light-shop-web.cabrapi.com.br/">
<meta property="og:type" content="website">
<meta property="og:title" content="Theme Light Shop | Template de Loja Virtual Moderna">
<meta property="og:description"
content="Template moderno para e-commerce com visual claro, performance elevada, SEO otimizado e experiência premium para lojas virtuais.">
<meta property="og:image"
content="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download">
<!-- Twitter Meta Tags -->
<meta name="twitter:card" content="summary_large_image">
<meta property="twitter:domain" content="demo-theme-light-shop-web.cabrapi.com.br">
<meta property="twitter:url" content="https://demo-theme-light-shop-web.cabrapi.com.br/">
<meta name="twitter:title" content="Theme Light Shop | Template de Loja Virtual Moderna">
<meta name="twitter:description"
content="Template moderno para e-commerce com visual claro, performance elevada, SEO otimizado e experiência premium para lojas virtuais.">
<meta name="twitter:image"
content="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download">
<link rel="icon" href="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download"
sizes="32x32">
<link rel="icon" href="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download"
sizes="192x192">
<link rel="apple-touch-icon"
href="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download">
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=DM+Serif+Display&display=swap"
rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<style>
:root {
--c-bg: #f8f7f4;
--c-surface: #ffffff;
--c-border: #e8e4df;
--c-ink: #1a1714;
--c-ink-muted: #6b6560;
--c-ink-subtle: #a09a94;
--c-accent: #c8502a;
--c-accent-light: #fef3ec;
--c-green: #2d7a4f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: 'DM Sans', sans-serif;
background: var(--c-bg);
color: var(--c-ink);
}
a {
text-decoration: none;
color: inherit;
}
img {
max-width: 100%;
height: auto;
}
button {
font-family: inherit;
cursor: pointer;
}
section img {
pointer-events: none;
}
</style>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script type="module">
import { caBRAPI as p } from "https://cdn.jsdelivr.net/npm/@cabrapi/sdk/dist/index.js";
var l = {
CART_STORAGE_KEY: "cabrapi_theme_light_shop_cart",
PRODUCTS_PAGE: 1,
PRODUCTS_LIMIT: 3,
PRODUCT_IMAGE_FIT_DEFAULT: "cover",
BUTTON_FEEDBACK_MS: 1400,
COPY_FEEDBACK_MS: 1800
}, m = {
PIX: "MERCADOPAGO_SERVICE_PIX",
CARD: "MERCADOPAGO_SERVICE_CARD"
}, b = class {
#t;
#e;
constructor(t, e) {
this.#t = new t({
type: "public",
config: {}
}), this.#e = e;
}
async getProducts(t = l.PRODUCTS_PAGE) {
const e = await this.#t.products.get(this.#e, {
page: t,
limit: l.PRODUCTS_LIMIT
});
if (!e?.status && e?.error) throw new Error(e?.message || "Erro ao buscar produtos.");
return {
products: Array.isArray(e?.products) ? e.products : [],
pagination: {
page: Number(e?.pagination?.page || t || 1),
limit: Number(e?.pagination?.limit || l.PRODUCTS_LIMIT),
total: Number(e?.pagination?.total || 0),
totalPages: Number(e?.pagination?.totalPages || 1)
}
};
}
async getCategories() {
const t = await this.#t.categories.get(this.#e, {
page: 1,
limit: 100
});
if (!t?.status && t?.error) throw new Error(t?.message || "Erro ao buscar categorias.");
return Array.isArray(t?.categories) ? t.categories : [];
}
async validateCoupon(t) {
return await this.#t.coupons.getByCode(this.#e, t);
}
async createPayment(t) {
return await this.#t.payments.post(this.#e, t);
}
}, C = class {
#t = null;
getItems() {
if (this.#t) return this.#t;
try {
const t = localStorage.getItem(l.CART_STORAGE_KEY);
this.#t = t ? JSON.parse(t) : [];
} catch {
this.#t = [];
}
return this.#t;
}
#e(t) {
this.#t = Array.isArray(t) ? t : [], localStorage.setItem(l.CART_STORAGE_KEY, JSON.stringify(this.#t));
}
addProduct(t) {
const e = this.getItems(), o = String(t.id), s = e.find((i) => String(i.id) === o), a = t.stock === null || t.stock === void 0 ? null : Number(t.stock);
if (a !== null && a <= 0) return e;
if (s) {
const i = s.stock === null || s.stock === void 0 ? null : Number(s.stock);
if (i !== null && s.qty >= i) return e;
s.qty += 1;
} else e.push({
id: o,
name: String(t.name || "Produto"),
image: t.image || null,
price: Number(t.price || 0),
qty: 1,
stock: a
});
return this.#e(e), e;
}
removeProduct(t) {
const e = String(t), o = this.getItems().filter((s) => String(s.id) !== e);
return this.#e(o), o;
}
changeQuantity(t, e) {
const o = String(t), s = this.getItems(), a = s.find((n) => String(n.id) === o);
if (!a) return s;
const i = a.stock === null || a.stock === void 0 ? null : Number(a.stock);
if (e > 0 && i !== null && a.qty >= i) return s;
if (a.qty += e, a.qty <= 0) return this.removeProduct(t);
const c = s.filter((n) => n.qty > 0);
return this.#e(c), c;
}
clear() {
this.#e([]);
}
getTotalItems() {
return this.getItems().reduce((t, e) => t + Number(e.qty || 0), 0);
}
getTotalPrice() {
return this.getItems().reduce((t, e) => t + Number(e.price || 0) * Number(e.qty || 0), 0);
}
};
function x(t) {
return String(t || "").trim().length >= 3;
}
function y(t) {
const e = String(t || "").trim();
return e ? e.length >= 4 && e.length <= 32 : !0;
}
function v(t) {
return String(t || "").replace(/\D/g, "").length === 11;
}
function k(t) {
const e = String(t || "").trim();
return e ? /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e) : !1;
}
function w(t) {
return Array.isArray(t) && t.length > 0;
}
function S(t, e, o = 1400) {
const s = t.html();
t.prop("disabled", !0).html(e), setTimeout(() => {
t.prop("disabled", !1).html(s);
}, o);
}
function d(t, e) {
if (e) {
t.removeClass("opacity-0 pointer-events-none");
return;
}
t.addClass("opacity-0 pointer-events-none");
}
function r(t) {
return String(t || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\"/g, "&quot;").replace(/'/g, "&#039;");
}
var P = class {
constructor({ onCategoryChange: t }) {
this.$filters = $("#category-filters"), this.onCategoryChange = t, this.categories = [], this.activeCategory = "all", this.#t();
}
#t() {
$(document).on("click", ".category-filter-btn", (t) => {
const e = String($(t.currentTarget).data("category") || "all");
e !== this.activeCategory && (this.activeCategory = e, this.render(), typeof this.onCategoryChange == "function" && this.onCategoryChange(e));
});
}
setCategories(t) {
this.categories = (Array.isArray(t) ? t : []).filter((e) => e?.name).map((e) => ({
id: String(e.id || e.name),
name: String(e.name)
})), this.render();
}
setActiveCategory(t) {
this.activeCategory = String(t || "all"), this.render();
}
render() {
const t = [`<button class="category-filter-btn px-4 py-2 rounded-full text-sm font-medium transition-all ${this.activeCategory === "all" ? "bg-[#c8502a] text-white" : "bg-white text-[#6b6560] border border-[#e8e4df]"}" data-category="all">Todos</button>`];
for (const e of this.categories) {
const o = this.activeCategory === e.name ? "bg-[#c8502a] text-white" : "bg-white text-[#6b6560] border border-[#e8e4df] hover:border-[#c8502a] hover:text-[#c8502a]";
t.push(`<button class="category-filter-btn px-4 py-2 rounded-full text-sm font-medium transition-all ${o}" data-category="${r(e.name)}">${r(e.name)}</button>`);
}
this.$filters.html(t.join(""));
}
};
function h(t) {
return new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL"
}).format(Number(t || 0));
}
function A(t = "Produto") {
return `https://placehold.co/600x420/F0EDE8/9CA3AF?text=${encodeURIComponent(t)}`;
}
var I = class {
constructor({ onAddToCart: t, onPageChange: e }) {
this.$list = $("#products-list"), this.$pagination = $("#products-pagination"), this.onAddToCart = t, this.onPageChange = e, this.products = [], this.activeCategory = "all", this.pagination = {
page: 1,
totalPages: 1,
total: 0
}, this.#t();
}
#t() {
$(document).on("click", ".product-add-btn", (t) => {
const e = $(t.currentTarget);
if (e.prop("disabled") || e.hasClass("cursor-not-allowed")) return;
const o = String(e.data("id")), s = this.products.find((a) => String(a.id) === o);
s && this.onAddToCart(s) !== !1 && S(e, '<i class="fas fa-check mr-2"></i> Adicionado', l.BUTTON_FEEDBACK_MS);
}), $(document).on("click", ".products-page-btn", (t) => {
const e = Number($(t.currentTarget).data("page"));
!e || e === this.pagination.page || typeof this.onPageChange == "function" && this.onPageChange(e);
});
}
#e() {
this.$list.find(".product-card-image").each((t, e) => {
$(e).css({
width: "100%",
height: "100%",
"object-fit": "cover",
"object-position": "center",
display: "block"
});
});
}
setProducts(t) {
const e = Array.isArray(t?.products) ? t.products : [];
this.pagination = {
page: Number(t?.pagination?.page || 1),
totalPages: Number(t?.pagination?.totalPages || 1),
total: Number(t?.pagination?.total || e.length)
}, this.products = e.filter((o) => !o.disabled), this.#o(), this.#a();
}
setActiveCategory(t) {
this.activeCategory = String(t || "all"), this.#o();
}
#s() {
return this.activeCategory === "all" ? this.products : this.products.filter((t) => (t.categories || []).some((e) => String(e.name) === this.activeCategory));
}
#o() {
const t = this.#s();
if (!t.length) {
this.$list.html(`
<div class="col-span-full text-center py-20 text-[#6b6560]">
<i class="fas fa-box-open text-5xl mb-4 block opacity-20"></i>
<p>Nenhum produto encontrado.</p>
</div>
`);
return;
}
const e = t.map((o) => {
const s = r(o.image || A(o.name)), a = Number(o.stock), i = !(!Number.isNaN(a) && a > 0);
return `
<article class="group bg-white rounded-3xl border border-[#e8e4df] overflow-hidden hover:shadow-xl transition-all duration-300 flex flex-col h-full">
<div class="product-card-image-frame relative overflow-hidden bg-[#f8f7f4]" style="aspect-ratio: 4/3; width: 100%;">
<img src="${s}"
alt="${r(o.name)}"
class="product-card-image transition-transform duration-700 group-hover:scale-110"
style="width: 100% !important; height: 100% !important; object-fit: cover !important; object-position: center !important; display: block !important;"
/>
<div class="absolute inset-0 bg-gradient-to-t from-[#1a1714]/10 to-transparent pointer-events-none"></div>
</div>
<div class="p-5 flex flex-col flex-1">
<div class="flex-1">
<h3 class="font-bold text-[#1a1714] text-lg mb-1 line-clamp-2 leading-tight">
${r(o.name)}
</h3>
<p class="text-sm text-[#6b6560] mb-4 line-clamp-2 leading-relaxed">
${r(o.description || "Asset digital exclusivo.")}
</p>
</div>
<div class="mt-auto">
<div class="mb-4">
<span class="text-[10px] text-[#6b6560] font-bold uppercase tracking-widest">Valor</span>
<div class="text-2xl text-[#c8502a] font-black leading-none">
${h(o.price)}
</div>
</div>
<button class="product-add-btn w-full py-3.5 bg-[#1a1714] text-white font-bold rounded-2xl hover:bg-[#c8502a] transition-all flex items-center justify-center gap-2 shadow-sm disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-[#1a1714]"
${i ? 'disabled aria-disabled="true"' : ""}
data-id="${r(o.id)}"
data-stock="${r(o.stock)}">
<i class="fas fa-shopping-bag text-sm"></i>
<span>${i ? "ESGOTADO" : "ADICIONAR"}</span>
</button>
</div>
</div>
</article>
`;
});
this.$list.html(`
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
${e.join("")}
</div>
`), this.#e();
}
#a() {
const { page: t, totalPages: e } = this.pagination;
if (e <= 1) {
this.$pagination.html("");
return;
}
let o = "";
for (let s = 1; s <= e; s++) s === 1 || s === e || s >= t - 1 && s <= t + 1 ? o += `
<button class="products-page-btn w-10 h-10 md:w-12 md:h-12 ${s === t ? "flex" : "hidden md:flex"} items-center justify-center rounded-xl border-2 transition-all font-bold ${s === t ? "bg-[#1a1714] border-[#1a1714] text-white active-page shadow-lg" : "border-[#e8e4df] text-[#1a1714] hover:border-[#1a1714]"}" data-page="${s}">
${s}
</button>
` : (s === t - 2 || s === t + 2) && (o += '<span class="text-[#e8e4df] hidden md:inline">...</span>');
this.$pagination.html(`
<div class="flex items-center justify-between gap-2 mt-12 mb-8 p-3 md:p-6 bg-white rounded-2xl md:rounded-[2rem] border border-[#e8e4df] mx-2">
<button class="products-page-btn flex items-center justify-center w-10 h-10 md:w-auto md:px-6 md:py-3 rounded-xl font-bold border-2 border-[#e8e4df] transition-all ${t <= 1 ? "opacity-20 cursor-not-allowed" : "text-[#1a1714] hover:bg-[#f8f7f4]"}"
${t <= 1 ? "disabled" : ""} data-page="${t - 1}">
<i class="fas fa-chevron-left text-xs"></i>
<span class="hidden md:inline ml-2">Anterior</span>
</button>
<div class="flex items-center gap-1 md:gap-2">
${o}
<span class="md:hidden text-xs font-bold text-[#6b6560] ml-2">de ${e}</span>
</div>
<button class="products-page-btn flex items-center justify-center w-10 h-10 md:w-auto md:px-6 md:py-3 rounded-xl font-bold border-2 border-[#e8e4df] transition-all ${t >= e ? "opacity-20 cursor-not-allowed" : "text-[#1a1714] hover:bg-[#f8f7f4]"}"
${t >= e ? "disabled" : ""} data-page="${t + 1}">
<span class="hidden md:inline mr-2">Próxima</span>
<i class="fas fa-chevron-right text-xs"></i>
</button>
</div>
`);
}
updateButtonsStates(t) {
$(".product-add-btn").each((e, o) => {
const s = $(o), a = s.data("id"), i = t.find((f) => String(f.id) === String(a)), c = Number(s.data("stock")), n = i ? i.stock : isNaN(c) ? null : c, g = i ? i.qty : 0, u = n !== null && n <= 0 || n > 0 && g >= n;
u ? s.prop("disabled", !0).attr("disabled", "disabled").addClass("opacity-50 cursor-not-allowed") : s.prop("disabled", !1).removeAttr("disabled").removeClass("opacity-50 cursor-not-allowed"), s.find("span").text(u ? "ESGOTADO" : "ADICIONAR");
});
}
}, T = class {
constructor() {
this.$drawer = $("#checkout"), this.$openButton = $("#cart-toggle"), this.$closeButton = $("#checkout-close"), this.$count = $("#cart-count");
}
bindEvents() {
this.$openButton.on("click", (t) => {
t.preventDefault(), this.open();
}), this.$closeButton.on("click", () => this.close()), this.$drawer.on("click", (t) => {
$(t.target).is(this.$drawer) && this.close();
});
}
open() {
d(this.$drawer, !0);
}
close() {
d(this.$drawer, !1);
}
setCount(t) {
this.$count.text(String(Number(t || 0)));
}
}, E = class {
constructor(t) {
this.handlers = t, this.$items = $("#checkout-items"), this.$total = $("#checkout-total"), this.$message = $("#checkout-message"), this.$couponStatus = $("#checkout-coupon-status"), this.$couponInput = $("#checkout-coupon"), this.$cpfInput = $("#checkout-cpf"), this.$submitButton = $("#checkout-submit"), this.$couponButton = $("#checkout-apply-coupon"), this.$fieldErrors = {
name: $("#checkout-name-error"),
cpf: $("#checkout-cpf-error"),
email: $("#checkout-email-error"),
nickname: $("#checkout-nickname-error")
}, this.#t();
}
#t() {
this.$items.on("click", ".checkout-remove-btn", (t) => {
const e = String($(t.currentTarget).data("id"));
this.handlers.onRemoveItem(e);
}), this.$items.on("click", ".checkout-qty-btn", (t) => {
const e = $(t.currentTarget), o = String(e.data("id")), s = Number(e.data("delta"));
this.handlers.onQuantityChange(o, s);
}), this.$couponButton.on("click", async () => {
await this.handlers.onApplyCoupon();
}), this.$couponInput.on("input", () => {
this.setCouponStatus(null);
}), this.$cpfInput.on("input", (t) => {
const e = $(t.currentTarget), o = this.#e(e.val());
e.val() !== o && e.val(o);
}), $('input[name="payment_method"]').on("change", (t) => {
this.handlers.onPaymentMethodChange(String($(t.currentTarget).val()));
}), $("#checkout-form").on("submit", async (t) => {
t.preventDefault(), await this.handlers.onSubmit();
});
}
renderItems(t) {
if (!t.length) {
this.$items.html('<p class="text-center py-8 text-[#6b6560]">Carrinho vazio</p>');
return;
}
const e = t.map((o) => `
<div class="flex items-center gap-2 p-2 bg-[#f8f7f4] rounded-xl">
<img src="${r(o.image || "https://placehold.co/64x64/F0EDE8/9CA3AF")}" alt="${r(o.name)}" class="w-12 h-12 rounded-lg object-cover shrink-0" />
<div class="flex-1 min-w-0">
<p class="font-medium text-xs text-[#1a1714] truncate">${r(o.name)}</p>
<p class="text-[#6b6560] text-xs">${h(o.price)}</p>
</div>
<div class="flex items-center gap-1 shrink-0">
<button class="checkout-qty-btn w-7 h-7 rounded-lg bg-white border border-[#e8e4df] text-[#1a1714] hover:bg-[#f8f7f4] disabled:opacity-50 disabled:cursor-not-allowed" ${Number(o.qty) <= 1 ? "disabled" : ""} data-id="${r(o.id)}" data-delta="-1">
<i class="fas fa-minus text-xs"></i>
</button>
<span class="w-6 text-center text-sm font-bold">${Number(o.qty)}</span>
<button class="checkout-qty-btn w-7 h-7 rounded-lg bg-white border border-[#e8e4df] text-[#1a1714] hover:bg-[#f8f7f4] disabled:opacity-50 disabled:cursor-not-allowed" ${o.stock !== null && Number(o.stock) > 0 && Number(o.qty) >= Number(o.stock) ? "disabled" : ""} data-id="${r(o.id)}" data-delta="1">
<i class="fas fa-plus text-xs"></i>
</button>
</div>
<button class="checkout-remove-btn text-red-500 hover:text-red-700 p-1 shrink-0 disabled:opacity-50 disabled:cursor-not-allowed" data-id="${r(o.id)}">
<i class="fas fa-trash text-xs"></i>
</button>
</div>
`).join("");
this.$items.html(e);
}
setTotal(t) {
this.$total.text(h(t));
}
getFormData() {
return {
name: String($("#checkout-name").val() || "").trim(),
nickname: String($("#checkout-nickname").val() || "").trim(),
email: String($("#checkout-email").val() || "").trim(),
cpf: String($("#checkout-cpf").val() || "").replace(/\D/g, ""),
note: String($("#checkout-note").val() || "").trim(),
coupon: String($("#checkout-coupon").val() || "").trim(),
paymentMethod: String($('input[name="payment_method"]:checked').val() || "PIX")
};
}
setFieldError(t, e) {
const o = this.$fieldErrors[t];
if (!(!o || !o.length)) {
if (!e) {
o.addClass("hidden").text("");
return;
}
o.removeClass("hidden").text(e);
}
}
clearFieldErrors() {
Object.keys(this.$fieldErrors).forEach((t) => {
this.setFieldError(t, "");
});
}
#e(t) {
const e = String(t || "").replace(/\D/g, "").slice(0, 11), o = [];
e.length > 0 && o.push(e.slice(0, 3)), e.length > 3 && o.push(e.slice(3, 6)), e.length > 6 && o.push(e.slice(6, 9));
let s = o.join(".");
return e.length > 9 && (s += `-${e.slice(9, 11)}`), s;
}
setSubmitLabel(t) {
const e = t === "CARD" ? '<i class="fas fa-credit-card mr-2"></i> Pagar com Cartão' : '<i class="fas fa-qrcode mr-2"></i> Pagar com PIX';
this.$submitButton.html(e);
}
setSubmitLoading(t, e) {
if (t) {
this.$submitButton.prop("disabled", !0).html('<i class="fas fa-spinner fa-spin mr-2"></i> Processando...');
return;
}
this.$submitButton.prop("disabled", !1), this.setSubmitLabel(e);
}
setCouponLoading(t) {
if (t) {
this.$couponButton.prop("disabled", !0).html('<i class="fas fa-spinner fa-spin mr-2"></i> Validando...');
return;
}
this.$couponButton.prop("disabled", !1).html('<i class="fas fa-ticket mr-2"></i> Aplicar');
}
showMessage(t, e) {
this.messageTimer && (clearTimeout(this.messageTimer), this.messageTimer = null), this.$message.removeClass("hidden bg-green-100 text-green-700 bg-red-100 text-red-700").addClass(t === "success" ? "bg-green-100 text-green-700" : "bg-red-100 text-red-700").text(e), this.messageTimer = setTimeout(() => {
this.hideMessage();
}, 3500);
}
hideMessage() {
this.messageTimer && (clearTimeout(this.messageTimer), this.messageTimer = null), this.$message.addClass("hidden").text("");
}
setCouponStatus(t) {
if (!t) {
this.$couponStatus.addClass("hidden").text("").removeClass("text-green-700 text-red-600");
return;
}
this.$couponStatus.removeClass("hidden text-green-700 text-red-600").addClass(t.type === "success" ? "text-green-700" : "text-red-600").text(t.text);
}
resetForm() {
const t = $("#checkout-form")[0];
t && t.reset(), this.setSubmitLabel("PIX"), this.setCouponStatus(null);
}
}, N = class {
constructor() {
this.$pixModal = $("#pix-modal"), this.$pixPanel = $("#pix-modal-panel"), this.$cardModal = $("#card-modal"), this.$cardPanel = $("#card-modal-panel");
}
showFromPaymentResponse(t) {
const e = t?.data?.payment || {};
if (e?.qr_code) {
this.#t(e);
return;
}
this.#e(e);
}
#t(t) {
const e = t?.qr_code || {};
let o = e.image || "";
o && !String(o).startsWith("data:") && !String(o).startsWith("http") && (o = `data:image/png;base64,${o}`), this.$pixPanel.html(`
<div class="mb-5">
<i class="fas fa-qrcode text-4xl text-[#c8502a] mb-3 block"></i>
<h3 class="text-xl font-bold text-[#1a1714]">Pagamento PIX</h3>
<p class="text-[#6b6560] text-sm mt-1">Escaneie o QR Code com seu banco.</p>
</div>
${o ? `<img src="${r(o)}" alt="QR Code PIX" class="w-48 h-48 mx-auto mb-4 rounded-xl border-2 border-[#e8e4df] p-2">` : ""}
${e.base_64 ? `
<div class="flex gap-2 mb-4">
<input id="pix-code" readonly value="${r(e.base_64)}" class="flex-1 px-3 py-2 bg-[#f8f7f4] border border-[#e8e4df] rounded-lg text-xs font-mono min-w-0" />
<button id="pix-copy" class="px-3 py-2 bg-[#1a1714] text-white rounded-lg hover:bg-[#c8502a] transition-colors shrink-0" title="Copiar codigo PIX">
<i class="fas fa-copy"></i>
</button>
</div>
` : ""}
<button id="pix-close" class="w-full py-3 border-2 border-[#e8e4df] text-[#6b6560] font-semibold rounded-xl hover:border-[#1a1714] hover:text-[#1a1714] transition-all">
Concluir
</button>
`), d(this.$pixModal, !0), $("#pix-copy").off("click").on("click", async () => {
try {
await navigator.clipboard.writeText(String(e.base_64 || ""));
const s = $("#pix-copy");
s.html('<i class="fas fa-check"></i>'), setTimeout(() => {
s.html('<i class="fas fa-copy"></i>');
}, l.COPY_FEEDBACK_MS);
} catch {
}
}), $("#pix-close").off("click").on("click", () => {
d(this.$pixModal, !1);
});
}
#e(t) {
this.$cardPanel.html(`
<div class="text-center p-8 bg-white rounded-[2.5rem] shadow-2xl border border-[#e8e4df]">
<div class="inline-flex items-center justify-center w-20 h-20 bg-[#1a1714] rounded-full mb-6 shadow-lg">
<i class="fas fa-credit-card text-2xl text-white"></i>
</div>
<h3 class="text-2xl font-black text-[#1a1714] tracking-tighter mb-2">Pagamento com Cartão</h3>
<p class="text-[#6b6560] text-sm mb-8 leading-relaxed max-w-[240px] mx-auto">
Método de pagamento: cartão. Clique abaixo para abrir o portal seguro.
</p>
${t.url ? `
<a href="${r(t.url)}"
target="_blank"
rel="noopener"
class="block w-full py-5 bg-[#1a1714] text-white font-black rounded-2xl text-center mb-4 hover:bg-[#000000] active:scale-[0.97] transition-all shadow-xl shadow-black/20 uppercase tracking-[0.15em] text-[11px]">
<span class="text-white !opacity-100">FINALIZAR PAGAMENTO</span>
</a>
` : ""}
${t.uuid ? `
<div class="inline-block bg-[#f8f7f4] rounded-full px-4 py-1.5 mb-8 border border-[#e8e4df]">
<p class="text-[#6b6560] text-[9px] font-bold tracking-widest uppercase">
REF: <span class="text-[#1a1714] font-black">${r(t.uuid.split("-")[0])}</span>
</p>
</div>
` : ""}
<button id="card-close" class="w-full py-3 border-2 border-[#e8e4df] text-[#6b6560] font-semibold rounded-xl hover:border-[#1a1714] hover:text-[#1a1714] transition-all">
Concluir
</button>
</div>
`), d(this.$cardModal, !0), $("#card-close").off("click").on("click", () => {
d(this.$cardModal, !1);
});
}
}, D = class {
constructor() {
this.apiService = null, this.cartStorage = new C(), this.productsComponent = null, this.categoriesComponent = null, this.cartDrawer = null, this.checkoutComponent = null, this.paymentModal = new N(), this.appliedCouponCode = null, this.storeId = "", this.currentPage = 1, this.activeCategory = "all";
}
async init() {
if (!window.jQuery) {
setTimeout(() => this.init(), 80);
return;
}
if (!p) {
setTimeout(() => this.init(), 100);
return;
}
if (this.storeId = String($("meta[name='loja-id']").attr("content") || "").trim(), !this.storeId) {
$("#products-list").html(`
<div class="text-center py-12 text-red-600">
<i class="fas fa-triangle-exclamation text-4xl mb-3 block"></i>
<p>Meta loja-id nao encontrada no HTML.</p>
</div>
`);
return;
}
this.apiService = new b(p, this.storeId), this.productsComponent = new I({
onAddToCart: (t) => this.handleAddToCart(t),
onPageChange: (t) => this.handlePageChange(t)
}), this.categoriesComponent = new P({ onCategoryChange: (t) => this.handleCategoryChange(t) }), this.cartDrawer = new T(), this.cartDrawer.bindEvents(), this.checkoutComponent = new E({
onRemoveItem: (t) => this.handleRemoveItem(t),
onQuantityChange: (t, e) => this.handleQuantityChange(t, e),
onApplyCoupon: async () => {
await this.handleApplyCoupon();
},
onSubmit: async () => {
await this.handleCheckoutSubmit();
},
onPaymentMethodChange: (t) => {
this.checkoutComponent.setSubmitLabel(t === "CARD" ? "CARD" : "PIX");
}
}), this.syncCartUI(), await this.loadCategories(), await this.loadProducts();
}
async loadCategories() {
try {
const t = await this.apiService.getCategories();
this.categoriesComponent.setCategories(t), this.categoriesComponent.setActiveCategory(this.activeCategory);
} catch {
this.categoriesComponent.setCategories([]), this.categoriesComponent.setActiveCategory("all");
}
}
async loadProducts(t = 1) {
try {
this.currentPage = t;
const e = await this.apiService.getProducts(t), o = this.cartStorage.getItems(), s = e.products.map((a) => {
const i = o.find((c) => String(c.id) === String(a.id));
return {
...a,
inCartQty: i ? i.qty : 0
};
});
this.productsComponent.setProducts({
...e,
products: s
}), this.productsComponent.setActiveCategory(this.activeCategory);
} catch (e) {
$("#products-list").html(`
<div class="text-center py-12 text-red-600">
<i class="fas fa-triangle-exclamation text-4xl mb-3 block"></i>
<p>Falha ao carregar produtos.</p>
<p class="text-sm text-[#6b6560] mt-2">${String(e?.message || "Erro desconhecido")}</p>
</div>
`);
}
}
handlePageChange(t) {
this.loadProducts(t), $("#shop")[0]?.scrollIntoView({
behavior: "smooth",
block: "start"
});
}
handleCategoryChange(t) {
this.activeCategory = String(t || "all"), this.productsComponent.setActiveCategory(this.activeCategory);
}
handleAddToCart(t) {
const e = t.stock === null || t.stock === void 0 ? null : Number(t.stock);
return e !== null && e <= 0 ? (this.checkoutComponent.showMessage("error", "Este produto esta sem estoque."), !1) : (this.cartStorage.addProduct(t), this.syncCartUI(), !0);
}
handleRemoveItem(t) {
this.cartStorage.removeProduct(t), this.syncCartUI();
}
handleQuantityChange(t, e) {
this.cartStorage.changeQuantity(t, e), this.syncCartUI();
}
syncCartUI() {
const t = this.cartStorage.getItems();
this.cartDrawer.setCount(this.cartStorage.getTotalItems()), this.checkoutComponent.renderItems(t), this.checkoutComponent.setTotal(this.cartStorage.getTotalPrice()), this.productsComponent.updateButtonsStates(t);
}
async handleApplyCoupon() {
this.checkoutComponent.hideMessage();
const { coupon: t } = this.checkoutComponent.getFormData();
if (!t)
return this.appliedCouponCode = null, this.checkoutComponent.setCouponStatus({
type: "error",
text: "Digite um cupom para aplicar."
}), !1;
this.checkoutComponent.setCouponLoading(!0);
try {
const e = await this.apiService.validateCoupon(t), o = e?.coupon;
if (!e?.status || !o?.code) throw new Error("Cupom invalido ou indisponivel.");
return this.appliedCouponCode = String(o.code), this.checkoutComponent.setCouponStatus({
type: "success",
text: `Cupom aplicado: ${String(o.code).toUpperCase()} (-${Number(o.discount || 0)}%)`
}), !0;
} catch {
return this.appliedCouponCode = null, this.checkoutComponent.setCouponStatus({
type: "error",
text: "Cupom invalido, expirado ou indisponivel para esta loja."
}), !1;
} finally {
this.checkoutComponent.setCouponLoading(!1);
}
}
async handleCheckoutSubmit() {
this.checkoutComponent.hideMessage();
const t = this.cartStorage.getItems();
if (!w(t)) {
this.checkoutComponent.showMessage("error", "Seu carrinho esta vazio.");
return;
}
const e = this.checkoutComponent.getFormData();
if (this.checkoutComponent.clearFieldErrors(), !x(e.name)) {
this.checkoutComponent.setFieldError("name", "Informe um nome valido com pelo menos 3 caracteres."), this.checkoutComponent.showMessage("error", "Corrija os campos destacados.");
return;
}
if (!y(e.nickname)) {
this.checkoutComponent.setFieldError("nickname", "O apelido deve ter entre 4 e 32 caracteres."), this.checkoutComponent.showMessage("error", "Corrija os campos destacados.");
return;
}
if (!k(e.email)) {
this.checkoutComponent.setFieldError("email", "Informe um e-mail valido."), this.checkoutComponent.showMessage("error", "Corrija os campos destacados.");
return;
}
if (e.cpf && !v(e.cpf)) {
this.checkoutComponent.setFieldError("cpf", "O CPF deve ter 11 numeros."), this.checkoutComponent.showMessage("error", "Corrija os campos destacados.");
return;
}
if (e.coupon && !this.appliedCouponCode && !await this.handleApplyCoupon())
return;
e.coupon || (this.appliedCouponCode = null, this.checkoutComponent.setCouponStatus(null));
const o = e.paymentMethod === "CARD" ? "CARD" : "PIX", s = {
name: e.name,
email: e.email,
cpf: e.cpf || void 0,
gateway: o === "CARD" ? m.CARD : m.PIX,
coupon: this.appliedCouponCode || void 0,
metadata: e.note || e.nickname ? {
...e.note ? { observation: e.note } : {},
...e.nickname ? { nickname: e.nickname } : {}
} : void 0,
items: t.map((a) => ({
productId: String(a.id),
quantity: Number(a.qty)
}))
};
this.checkoutComponent.setSubmitLoading(!0, o);
try {
const a = await this.apiService.createPayment(s);
if (!a?.status) throw new Error(a?.message || "Falha ao criar pagamento.");
this.paymentModal.showFromPaymentResponse(a), this.cartStorage.clear(), this.syncCartUI(), this.appliedCouponCode = null, this.checkoutComponent.resetForm(), this.checkoutComponent.showMessage("success", "Pagamento criado com sucesso.");
} catch (a) {
this.checkoutComponent.showMessage("error", String(a?.message || "Erro ao processar pagamento."));
} finally {
this.checkoutComponent.setSubmitLoading(!1, o);
}
}
};
new D().init();
</script>
</head>
<body class="bg-[#f8f7f4] text-[#1a1714] min-h-screen flex flex-col">
<!-- Navbar -->
<nav class="sticky top-0 z-[200] bg-[#f8f7f4]/95 backdrop-blur-md border-b border-[#e8e4df] shadow-sm">
<div class="max-w-6xl mx-auto px-4">
<!-- Toggle -->
<input type="checkbox" id="menu-toggle" class="peer hidden">
<div class="flex items-center justify-between h-16 md:h-[68px]">
<!-- Logo -->
<a href="#" class="flex items-center gap-3 hover:opacity-80 transition-opacity">
<div
class="w-10 h-10 bg-[#1a1714] rounded-xl flex items-center justify-center text-white shadow-md">
<i class="fas fa-store-alt text-lg"></i>
</div>
<span class="text-lg font-medium tracking-tight text-[#1a1714]">
Loja <strong class="font-bold text-[#c8502a]">Virtual</strong>
</span>
</a>
<!-- Desktop Menu -->
<ul class="hidden md:flex items-center gap-2 list-none m-0 p-0">
<li>
<a href="#"
class="group relative flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all duration-300">
<i class="fas fa-house text-xs"></i>
Início
<span
class="absolute left-4 bottom-1 w-0 h-[2px] bg-[#c8502a] rounded-full transition-all duration-300 group-hover:w-[55%]"></span>
</a>
</li>
<li>
<a href="#shop"
class="group relative flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all duration-300">
<i class="fas fa-store text-xs"></i>
Loja
<span
class="absolute left-4 bottom-1 w-0 h-[2px] bg-[#c8502a] rounded-full transition-all duration-300 group-hover:w-[45%]"></span>
</a>
</li>
<li>
<a href="#"
class="group relative flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all duration-300">
<i class="fab fa-discord text-xs"></i>
Discord
<span
class="absolute left-4 bottom-1 w-0 h-[2px] bg-[#c8502a] rounded-full transition-all duration-300 group-hover:w-[65%]"></span>
</a>
</li>
</ul>
<!-- Actions -->
<div class="flex items-center gap-3">
<!-- Cart -->
<a href="#" id="cart-toggle" aria-label="Abrir carrinho"
class="group relative w-11 h-11 rounded-xl border border-[#e8e4df] bg-white flex items-center justify-center text-[#1a1714] shadow-sm hover:bg-[#1a1714] hover:border-[#1a1714] transition-all duration-300">
<i
class="fas fa-bag-shopping text-lg transition-colors duration-300 group-hover:text-white"></i>
<span id="cart-count"
class="absolute -top-1 -right-1 min-w-5 h-5 px-1.5 bg-[#c8502a] text-white text-[0.65rem] rounded-full flex items-center justify-center font-bold border-2 border-white">
0
</span>
</a>
<!-- Mobile Button -->
<label for="menu-toggle"
class="md:hidden w-11 h-11 rounded-xl border border-[#e8e4df] bg-white flex items-center justify-center cursor-pointer text-[#1a1714] hover:bg-[#f0ede8] transition-all duration-300">
<i class="fas fa-bars text-lg"></i>
</label>
</div>
</div>
<!-- Mobile Menu -->
<div class="hidden peer-checked:block md:hidden border-t border-[#e8e4df] py-4">
<div class="flex flex-col gap-2">
<a href="#"
class="flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all">
<i class="fas fa-house w-4 text-center"></i>
Início
</a>
<a href="#shop"
class="flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all">
<i class="fas fa-store w-4 text-center"></i>
Loja
</a>
<a href="#"
class="flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-medium text-[#6b6560] hover:bg-white hover:text-[#1a1714] transition-all">
<i class="fab fa-discord w-4 text-center"></i>
Discord
</a>
</div>
</div>
</div>
</nav>
<header id="hero" class="relative overflow-hidden py-20 md:py-28 px-4">
<!-- Background -->
<div class="absolute inset-0 bg-gradient-to-b from-[#f8f7f4] via-[#faf8f6] to-[#f4f1ed] -z-10"></div>
<!-- Blur Effects -->
<div
class="absolute top-[-120px] right-[-80px] w-[320px] h-[320px] bg-[#c8502a]/10 rounded-full blur-3xl -z-10">
</div>
<div
class="absolute bottom-[-100px] left-[-80px] w-[260px] h-[260px] bg-[#1a1714]/5 rounded-full blur-3xl -z-10">
</div>
<div class="max-w-7xl mx-auto">
<div class="grid md:grid-cols-2 gap-14 items-center">
<!-- Left Content -->
<div>
<!-- Badge -->
<div
class="inline-flex items-center gap-2 px-4 py-2 bg-white border border-[#ebe5df] rounded-full mb-6 shadow-sm">
<span class="w-2 h-2 bg-[#c8502a] rounded-full animate-pulse"></span>
<span class="text-sm font-medium text-[#4f4a46]">
Loja online • Entrega expressa
</span>
</div>
<!-- Title -->
<h1 class="text-4xl md:text-6xl leading-[1.05] font-bold tracking-tight text-[#1a1714] mb-6"
style="font-family:'DM Serif Display', serif;">
Sua loja virtual
<span class="block text-[#c8502a]">
moderna e completa
</span>
</h1>
<!-- Description -->
<p class="text-lg text-[#6b6560] leading-relaxed max-w-xl mb-8">
Produtos selecionados, preços acessíveis e uma experiência premium para quem busca
qualidade, velocidade e praticidade.
</p>
<!-- Buttons -->
<div class="flex flex-wrap gap-4 mb-10">
<!-- Produtos -->
<a href="#shop"
class="group inline-flex items-center gap-3 px-7 py-4 rounded-2xl bg-white border border-[#e8e4df] text-[#1a1714] font-semibold shadow-sm transition-all duration-300 hover:border-[#c8502a] hover:-translate-y-1 hover:shadow-lg">
<i
class="fas fa-store transition-all duration-300 group-hover:scale-110 group-hover:text-[#c8502a]"></i>
<span class="transition-colors duration-300 group-hover:text-[#c8502a]">
Ver produtos
</span>
</a>
<!-- Discord -->
<a href="#"
class="group inline-flex items-center gap-3 px-7 py-4 rounded-2xl bg-white border border-[#e8e4df] text-[#1a1714] font-semibold shadow-sm transition-all duration-300 hover:border-[#c8502a] hover:-translate-y-1 hover:shadow-lg">
<i
class="fab fa-discord transition-all duration-300 group-hover:scale-110 group-hover:text-[#c8502a]"></i>
<span class="transition-colors duration-300 group-hover:text-[#c8502a]">
Discord
</span>
</a>
</div>
<!-- Stats -->
<div class="flex flex-wrap gap-8">
<div>
<strong class="block text-2xl font-bold text-[#1a1714]">
+12k
</strong>
<span class="text-sm text-[#6b6560]">
Clientes ativos
</span>
</div>
<div>
<strong class="block text-2xl font-bold text-[#1a1714]">
24h
</strong>
<span class="text-sm text-[#6b6560]">
Entrega rápida
</span>
</div>
<div>
<strong class="block text-2xl font-bold text-[#1a1714]">
4.9★
</strong>
<span class="text-sm text-[#6b6560]">
Avaliação média
</span>
</div>
</div>
</div>
<div class="relative hidden md:block">
<!-- Fundo decorativo -->
<div class="absolute -top-8 -right-8 w-40 h-40 bg-[#c8502a]/10 rounded-full blur-3xl">
</div>
<!-- Container da imagem -->
<div
class="relative overflow-hidden rounded-[32px] shadow-[0_35px_80px_rgba(0,0,0,0.14)]">
<img src="https://blob.cabrapi.com.br/blob/808ff623-b490-414a-8b82-abeadeb87b0d/download"
alt="Produto em destaque"
class="w-full h-[540px] object-cover rounded-[32px] transition-transform duration-500 hover:scale-[1.03]" />
<!-- Overlay suave -->
<div
class="absolute inset-0 bg-gradient-to-t from-black/10 to-transparent rounded-[32px]">
</div>
</div>
<!-- Card flutuante -->
<div
class="absolute bottom-6 left-6 bg-white/95 backdrop-blur-md px-5 py-4 rounded-2xl shadow-[0_15px_40px_rgba(0,0,0,0.12)] flex items-center gap-4 border border-[#e8e4df]">
<div
class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center flex-shrink-0 shadow-sm">
<i class="fas fa-bolt text-[#c8502a] text-xl"></i>
</div>
<div>
<strong class="text-sm block text-[#1a1714] font-semibold">
Entrega instantânea
</strong>
<span class="text-xs text-[#6b6560]">
Receba em minutos
</span>
</div>
</div>
</div>
</div>
</div>
</header>
<section class="py-16 px-4 bg-white">
<div class="max-w-6xl mx-auto">
<div class="text-center mb-12">
<p class="text-[#c8502a] text-sm font-semibold uppercase tracking-wider mb-2"><i
class="fas fa-shield-halved mr-2"></i> Diferenciais</p>
<h2 class="text-3xl md:text-4xl font-bold mb-3" style="font-family:'DM Serif Display',serif;">
Por que comprar aqui?</h2>
<p class="text-[#6b6560]">Segurança, rapidez e confiança em cada pedido</p>
</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-6">
<div class="bg-[#f8f7f4] p-6 rounded-2xl hover:shadow-lg transition-shadow">
<div class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center mb-4"><i
class="fas fa-bolt text-[#c8502a] text-2xl"></i></div>
<h3 class="font-bold mb-2">Entrega rápida</h3>
<p class="text-sm text-[#6b6560]">Receba seu produto em minutos ou de forma totalmente
automática após o pagamento.</p>
</div>
<div class="bg-[#f8f7f4] p-6 rounded-2xl hover:shadow-lg transition-shadow">
<div class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center mb-4"><i
class="fas fa-lock text-[#c8502a] text-2xl"></i></div>
<h3 class="font-bold mb-2">Pagamento seguro</h3>
<p class="text-sm text-[#6b6560]">Transações protegidas com criptografia e validação em
tempo real.</p>
</div>
<div class="bg-[#f8f7f4] p-6 rounded-2xl hover:shadow-lg transition-shadow">
<div class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center mb-4"><i
class="fas fa-headset text-[#c8502a] text-2xl"></i></div>
<h3 class="font-bold mb-2">Suporte ativo</h3>
<p class="text-sm text-[#6b6560]">Atendimento ágil via Discord ou chat para qualquer
dúvida ou problema.</p>
</div>
<div class="bg-[#f8f7f4] p-6 rounded-2xl hover:shadow-lg transition-shadow">
<div class="w-14 h-14 bg-[#fef3ec] rounded-2xl flex items-center justify-center mb-4"><i
class="fas fa-tag text-[#c8502a] text-2xl"></i></div>
<h3 class="font-bold mb-2">Melhor preço</h3>
<p class="text-sm text-[#6b6560]">Produtos acessíveis com promoções constantes para
economizar sempre.</p>
</div>
</div>
</div>
</section>
<div class="max-w-6xl mx-auto px-4">
<div class="border-t border-[#e8e4df]"></div>
</div>
<section id="shop" class="py-16 px-4">
<div class="max-w-6xl mx-auto">
<div class="flex flex-col md:flex-row md:items-end justify-between mb-10 gap-4">
<div>
<p class="text-[#c8502a] text-sm font-semibold uppercase tracking-wider mb-2"><i
class="fas fa-store mr-2"></i> Catálogo</p>
<h2 class="text-3xl md:text-4xl font-bold" style="font-family:'DM Serif Display',serif;">
Nossos produtos</h2>
</div>
</div>
<div id="category-filters" class="flex flex-wrap gap-2 mb-8"></div>
<div id="products-list">
<div class="text-center py-16 text-[#6b6560]"><i
class="fas fa-spinner fa-spin text-3xl mb-4 block"></i>
<p>Carregando produtos…</p>
</div>
</div>
<div id="products-pagination"></div>
</div>
</section>
<div class="max-w-6xl mx-auto px-4">
<div class="border-t border-[#e8e4df]"></div>
</div>
<section class="py-16 px-4">
<div class="max-w-6xl mx-auto">
<div class="text-center mb-12">
<p class="text-[#c8502a] text-sm font-semibold uppercase tracking-wider mb-2"><i
class="fas fa-chart-line mr-2"></i> Resultados</p>
<h2 class="text-3xl md:text-4xl font-bold mb-3" style="font-family:'DM Serif Display',serif;">
Transparência em números</h2>
<p class="text-[#6b6560]">Dados reais de quem já comprou com a gente</p>
</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-6">
<div
class="bg-white p-6 rounded-2xl border border-[#e8e4df] text-center hover:shadow-lg transition-shadow">
<div
class="w-14 h-14 bg-[#f8f7f4] rounded-2xl flex items-center justify-center mx-auto mb-4">
<i class="fas fa-shopping-cart text-[#1a1714] text-2xl"></i>
</div>
<div class="text-3xl font-bold">+1.200</div>
<div class="text-sm text-[#6b6560] mt-1">Vendas realizadas</div>
</div>
<div
class="bg-white p-6 rounded-2xl border border-[#e8e4df] text-center hover:shadow-lg transition-shadow">
<div
class="w-14 h-14 bg-[#f8f7f4] rounded-2xl flex items-center justify-center mx-auto mb-4">
<i class="fas fa-users text-[#1a1714] text-2xl"></i>
</div>
<div class="text-3xl font-bold">+500</div>
<div class="text-sm text-[#6b6560] mt-1">Clientes ativos</div>
</div>
<div
class="bg-white p-6 rounded-2xl border border-[#e8e4df] text-center hover:shadow-lg transition-shadow">
<div
class="w-14 h-14 bg-[#f8f7f4] rounded-2xl flex items-center justify-center mx-auto mb-4">
<i class="fas fa-star text-[#1a1714] text-2xl"></i>
</div>
<div class="text-3xl font-bold">99%</div>
<div class="text-sm text-[#6b6560] mt-1">Satisfação</div>
</div>
<div
class="bg-white p-6 rounded-2xl border border-[#e8e4df] text-center hover:shadow-lg transition-shadow">
<div
class="w-14 h-14 bg-[#f8f7f4] rounded-2xl flex items-center justify-center mx-auto mb-4">
<i class="fas fa-headset text-[#1a1714] text-2xl"></i>
</div>
<div class="text-3xl font-bold">24h</div>
<div class="text-sm text-[#6b6560] mt-1">Suporte ativo</div>
</div>
</div>
</div>
</section>
<div class="max-w-6xl mx-auto px-4">
<div class="border-t border-[#e8e4df]"></div>
</div>
<section class="py-16 px-4">
<div class="max-w-4xl mx-auto">
<div class="bg-[#1a1714] rounded-3xl p-10 md:p-14 text-center text-white relative overflow-hidden">
<div class="absolute inset-0 opacity-5"
style="background-image:radial-gradient(circle at 20% 50%, #c8502a 1px, transparent 1px);background-size:30px 30px;">
</div>
<p class="text-xs font-bold uppercase tracking-[0.2em] text-[#a09a94] mb-3 relative z-10">
Atendimento</p>
<h2 class="text-3xl md:text-4xl font-bold mb-4 relative z-10"
style="font-family:'DM Serif Display',serif;">Precisa de ajuda?</h2>
<p class="text-[#a09a94] mb-8 max-w-lg mx-auto relative z-10">Fale com nosso suporte em segundos
— estamos sempre disponíveis.</p>
<a href="#"
class="inline-flex items-center gap-2 px-6 py-3.5 bg-[#5865F2] text-white font-semibold rounded-xl hover:bg-[#4752C4] transition-all relative z-10 shadow-lg"><i
class="fab fa-discord text-lg"></i> Abrir suporte no Discord</a>
</div>
</div>
</section>
<section class="py-16 px-4 bg-white">
<div class="max-w-3xl mx-auto">
<div class="text-center mb-12">
<p class="text-[#c8502a] text-sm font-semibold uppercase tracking-wider mb-2"><i
class="fas fa-circle-question mr-2"></i> Dúvidas</p>
<h2 class="text-3xl md:text-4xl font-bold mb-3" style="font-family:'DM Serif Display',serif;">
Perguntas frequentes</h2>
<p class="text-[#6b6560]">As respostas que você precisa antes de comprar</p>
</div>
<div class="space-y-3">
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i
class="fas fa-shopping-cart mr-3 text-[#6b6560]"></i>Como funciona a
compra?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">Você escolhe o produto, finaliza o
pagamento via PIX e recebe automaticamente as instruções ou acesso no seu e-mail
logo após a confirmação.</p>
</details>
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i
class="fas fa-shield-halved mr-3 text-[#6b6560]"></i>É seguro comprar
aqui?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">Sim. Utilizamos sistemas seguros de
pagamento e validação para proteger todas as transações. Seus dados são
criptografados.</p>
</details>
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i class="fas fa-clock mr-3 text-[#6b6560]"></i>Quanto
tempo demora para receber?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">A maioria das entregas é
instantânea ou feita em poucos minutos após a confirmação do pagamento. Produtos
físicos têm prazo estimado no momento da compra.</p>
</details>
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i class="fas fa-headset mr-3 text-[#6b6560]"></i>Como
funciona o suporte?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">Oferecemos suporte via Discord e
e-mail. Nossa equipe responde rapidamente durante todo o dia para resolver qualquer
dúvida ou problema.</p>
</details>
<details class="group bg-[#f8f7f4] rounded-2xl p-5">
<summary class="flex items-center justify-between cursor-pointer list-none"><span
class="font-semibold"><i
class="fas fa-rotate-left mr-3 text-[#6b6560]"></i>Posso pedir
reembolso?</span><i
class="fas fa-chevron-down text-[#6b6560] group-open:rotate-180 transition-transform"></i>
</summary>
<p class="mt-4 text-[#6b6560] text-sm leading-relaxed">Sim, em casos de problema no
produto ou não entrega. Entre em contato com nosso suporte e avaliaremos seu caso o
mais rápido possível.</p>
</details>
</div>
</div>
</section>
<div id="checkout" role="dialog" aria-modal="true" aria-label="Carrinho e pagamento"
class="fixed inset-0 z-[300] bg-[#1a1714]/70 backdrop-blur-sm flex items-end md:items-center justify-center p-0 md:p-4 opacity-0 pointer-events-none transition-all duration-300">
<div id="checkout-panel"
class="bg-white w-full max-w-[860px] rounded-t-3xl md:rounded-3xl max-h-[95vh] md:max-h-[92vh] overflow-y-auto p-4 md:p-8 pb-24 md:pb-8">
<div class="flex items-center justify-between mb-6 pb-5 border-b border-[#e8e4df]">
<div>
<h2 class="text-xl font-bold"><i class="fas fa-bag-shopping mr-2"></i> Carrinho e
pagamento</h2>
<p class="text-[#6b6560] text-sm mt-1">Revise seu pedido e finalize via PIX em segundos.
</p>
</div>
<button id="checkout-close" aria-label="Fechar carrinho"
class="w-10 h-10 rounded-xl border border-[#e8e4df] flex items-center justify-center hover:bg-[#f8f7f4] transition-colors"><i
class="fas fa-xmark"></i></button>
</div>
<div id="checkout-message" class="hidden p-3 rounded-xl text-sm mb-4"></div>
<div class="grid md:grid-cols-2 gap-8">
<div>
<p class="text-sm font-bold uppercase tracking-wider text-[#6b6560] mb-4"><i
class="fas fa-receipt mr-2"></i> Resumo do pedido</p>
<div id="checkout-items" class="flex flex-col gap-3"></div>
<div class="flex justify-between items-center pt-5 mt-5 border-t border-[#e8e4df]">
<span class="font-semibold">Total</span>
<strong id="checkout-total" class="text-2xl font-bold text-[#c8502a]">R$
0,00</strong>
</div>
</div>
<form id="checkout-form" novalidate class="flex flex-col gap-4">
<div class="flex flex-col gap-1.5">
<label for="checkout-name" class="text-sm font-semibold"><i
class="fas fa-user mr-2 text-[#6b6560]"></i>Nome completo</label>
<input id="checkout-name" name="name" placeholder="Seu nome completo"
autocomplete="name"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<p id="checkout-name-error" class="hidden text-xs font-medium text-red-600"></p>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-nickname" class="text-sm font-semibold"><i
class="fas fa-at mr-2 text-[#6b6560]"></i>Nickname <span
class="text-[#a09a94] font-normal">(opcional)</span></label>
<input id="checkout-nickname" name="nickname" placeholder="Seu apelido"
maxlength="32" autocomplete="nickname"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<p class="text-xs text-[#a09a94]">De 4 a 32 caracteres.</p>
<p id="checkout-nickname-error" class="hidden text-xs font-medium text-red-600"></p>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-email" class="text-sm font-semibold"><i
class="fas fa-envelope mr-2 text-[#6b6560]"></i>E-mail</label>
<input id="checkout-email" name="email" type="email" placeholder="voce@email.com"
autocomplete="email"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<p id="checkout-email-error" class="hidden text-xs font-medium text-red-600"></p>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-cpf" class="text-sm font-semibold"><i
class="fas fa-id-card mr-2 text-[#6b6560]"></i>CPF <span
class="text-[#a09a94] font-normal">(opcional)</span></label>
<input id="checkout-cpf" name="cpf" placeholder="000.000.000-00" inputmode="numeric"
maxlength="14"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<p id="checkout-cpf-error" class="hidden text-xs font-medium text-red-600"></p>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-note" class="text-sm font-semibold"><i
class="fas fa-comment mr-2 text-[#6b6560]"></i>Observação <span
class="text-[#a09a94] font-normal">(opcional)</span></label>
<textarea id="checkout-note" name="note" rows="2" placeholder="Algo a informar?"
class="px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all resize-none"></textarea>
</div>
<div class="flex flex-col gap-1.5">
<label for="checkout-coupon" class="text-sm font-semibold"><i
class="fas fa-ticket mr-2 text-[#6b6560]"></i>Cupom <span
class="text-[#a09a94] font-normal">(opcional)</span></label>
<div class="flex gap-2">
<input id="checkout-coupon" name="coupon" placeholder="Ex: BEMVINDO10"
class="flex-1 px-4 py-3.5 border border-[#e8e4df] rounded-xl focus:ring-2 focus:ring-[#c8502a] focus:border-transparent outline-none transition-all" />
<button id="checkout-apply-coupon" type="button"
class="px-4 py-3 bg-white border border-[#e8e4df] text-[#1a1714] font-semibold rounded-xl hover:border-[#c8502a] hover:text-[#c8502a] disabled:opacity-60 transition-all whitespace-nowrap">
<i class="fas fa-ticket mr-2"></i> Aplicar
</button>
</div>
<p id="checkout-coupon-status" class="hidden text-xs font-medium"></p>
</div>
<div class="flex flex-col gap-3">
<label class="text-sm font-semibold"><i
class="fas fa-credit-card mr-2 text-[#6b6560]"></i>Forma de
pagamento</label>
<div class="grid grid-cols-2 gap-3">
<label class="cursor-pointer">
<input type="radio" name="payment_method" value="PIX" checked
class="peer sr-only" />
<div
class="p-3 border-2 border-[#e8e4df] rounded-xl peer-checked:border-[#c8502a] peer-checked:bg-[#fef3ec] hover:border-[#c8502a] transition-all text-center">
<i class="fas fa-qrcode text-xl text-[#6b6560]"></i>
<p class="font-semibold text-xs mt-1">PIX</p>
</div>
</label>
<label class="cursor-pointer">
<input type="radio" name="payment_method" value="CARD"
class="peer sr-only" />
<div
class="p-3 border-2 border-[#e8e4df] rounded-xl peer-checked:border-[#c8502a] peer-checked:bg-[#fef3ec] hover:border-[#c8502a] transition-all text-center">
<i class="fas fa-credit-card text-xl text-[#6b6560]"></i>
<p class="font-semibold text-xs mt-1">Cartão</p>
</div>
</label>
</div>
</div>
<button id="checkout-submit" type="submit"
class="w-full py-3 bg-[#1a1714] text-white font-semibold rounded-lg hover:bg-[#c8502a] disabled:opacity-50 transition-all shadow-sm"><i
class="fas fa-qrcode mr-2"></i> Pagar com PIX</button>
</form>
</div>
<div id="checkout-result" class="hidden mt-6 pt-5 border-t border-[#e8e4df]"></div>
</div>
</div>
<div id="pix-modal" role="dialog" aria-modal="true" aria-label="Pagamento PIX"
class="fixed inset-0 z-[400] bg-[#1a1714]/80 backdrop-blur-sm flex items-end md:items-center justify-center p-0 md:p-4 opacity-0 pointer-events-none transition-all duration-300">
<div id="pix-modal-panel"
class="bg-white w-full max-w-sm rounded-t-3xl md:rounded-2xl p-6 md:p-8 text-center pb-20 md:pb-8">
</div>
</div>
<div id="card-modal" role="dialog" aria-modal="true" aria-label="Pagamento Cartão"
class="fixed inset-0 z-[400] bg-[#1a1714]/80 backdrop-blur-sm flex items-end md:items-center justify-center p-0 md:p-4 opacity-0 pointer-events-none transition-all duration-300">
<div id="card-modal-panel"
class="bg-white w-full max-w-sm rounded-t-3xl md:rounded-2xl p-6 md:p-8 text-center pb-20 md:pb-8">
</div>
</div>
<footer class="bg-[#1a1714] text-white py-12 px-4 mt-auto">
<div class="max-w-6xl mx-auto">
<div class="flex flex-col md:flex-row justify-between items-center gap-8">
<div class="flex flex-col items-center md:items-start gap-4">
<a href="#" class="text-lg font-semibold">Loja <span
class="text-[#c8502a]">Virtual</span></a>
<div
class="flex flex-wrap justify-center md:justify-start gap-4 md:gap-6 text-sm text-[#a09a94]">
<a href="#" class="hover:text-white transition-colors"><i
class="fas fa-house mr-1"></i> Início</a>
<a href="#shop" class="hover:text-white transition-colors"><i
class="fas fa-store mr-1"></i> Loja</a>
<a href="#" class="hover:text-[#5865F2] transition-all"><i
class="fab fa-discord mr-1"></i> Discord</a>
</div>
</div>
<div class="flex gap-3">
<a href="#" aria-label="Instagram"
class="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center text-[#a09a94] hover:text-white hover:bg-white/20 transition-all"><i
class="fab fa-instagram"></i></a>
<a href="#" aria-label="YouTube"
class="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center text-[#a09a94] hover:text-white hover:bg-white/20 transition-all"><i
class="fab fa-youtube"></i></a>
<a href="#" aria-label="TikTok"
class="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center text-[#a09a94] hover:text-white hover:bg-white/20 transition-all"><i
class="fab fa-tiktok"></i></a>
<a href="#" aria-label="Discord"
class="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center text-[#a09a94] hover:text-[#5865F2] hover:bg-white/20 transition-all"><i
class="fab fa-discord"></i></a>
</div>
</div>
<div
class="flex flex-col md:flex-row justify-between items-center gap-3 pt-6 mt-6 border-t border-white/10 text-sm text-[#a09a94]">
<span>© 2026 Loja Virtual · Todos os direitos reservados</span>
<div class="flex items-center gap-2"><i class="fas fa-code text-xs"></i><span>Powered
by</span><span class="text-[#c8502a] font-semibold">caBRAPI</span></div>
</div>
</div>
</footer>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment