/* global React, ReactDOM */ const { useState, useEffect, useMemo } = React; // Resource resolver: in the standalone-bundled file, window.__resources[id] // holds an inlined blob URL; otherwise we fall back to the on-disk path. const __RES = (typeof window !== "undefined" && window.__resources) || {}; const asset = (id, path) => __RES[id] || path; // ────────────────────────────────────────────────────────── // Tweak defaults // ────────────────────────────────────────────────────────── const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "palette": "japonesa", "displayFont": "provicali", "cardStyle": "editorial", "featureLastCard": true, "showCoupon": true, "showFaq": true, "headline": "Sabores que reúnem pessoas." }/*EDITMODE-END*/; // ────────────────────────────────────────────────────────── // Icons // ────────────────────────────────────────────────────────── const I = { whatsapp: ( ), menu: ( ), delivery: ( ), instagram: ( ), arrow: ( ), copy: ( ), check: ( ), plus: ( ), insta: ( ), wa: ( ), waMark: ( ), mail: ( ), }; // ────────────────────────────────────────────────────────── // Brand data // ────────────────────────────────────────────────────────── const BRANDS = [ { id: "ela", klass: "b-ela", num: "01", cat: "Pizzaria pop / Forno alto", name: "Ela Pizza", pitch: "Pizza pop, massa fininha e sabor que grita. A pizzaria que virou cultura de bairro — e ninguém pediu silêncio.", placeholderTag: "Food shot · ela pizza", logoImg: asset("logoEla", "assets/logo-ela.jpg"), foodImg: asset("foodEla", "assets/food-ela.jpg"), links: { whatsapp: "https://wa.me/5566999022274?text=Ol%C3%A1%20vim%20pelo%20Instagram%20e%20gostaria%20de%20mais%20informa%C3%A7%C3%B5es!%F0%9F%8D%95", menu: "https://elapizzadelivery.pedir.online/#/", instagram: "https://www.instagram.com/elapizzadelivery?igsh=bzllYXdxd3dsNjE0", }, }, { id: "maki", klass: "b-maki", num: "02", cat: "Sushi & Temakeria · NOVO", name: "Maki Maki", pitch: "Sushi e temaki para dividir (ou não). Combinados generosos, molhos da casa e aquele wasabi que respeita quem pede.", placeholderTag: "Food shot · temaki + combinado", logoImg: asset("logoMaki", "assets/logo-maki.jpg"), foodImg: asset("foodMaki", "assets/food-maki.jpg"), links: { whatsapp: "https://wa.me/5566996651183?text=Ol%C3%A1%20vim%20pelo%20Instagram%20e%20gostaria%20de%20mais%20informa%C3%A7%C3%B5es!%F0%9F%8D%A3", menu: "https://makimaki.pedir.online/#/", instagram: "https://www.instagram.com/makimaki_sushietemaki?igsh=MW03ZmU4OGQ2NTdncQ==", }, }, { id: "riso", klass: "b-riso", num: "03", cat: "Pizzaria clássica / Forno a lenha", name: "Riso Pizza", pitch: "A pizzaria que abraça. Receitas da nonna, ingredientes simples e aquele cheirinho que faz a casa parar.", placeholderTag: "Food shot · pizza margherita", logoImg: asset("logoRiso", "assets/logo-riso.jpg"), foodImg: asset("foodRiso", "assets/food-riso.jpg"), links: { whatsapp: "https://wa.me/5566996105078?text=Ol%C3%A1%20vim%20pelo%20Instagram%20e%20gostaria%20de%20mais%20informa%C3%A7%C3%B5es!%F0%9F%8D%95", menu: "https://risopizza.pedir.online/#/", instagram: "https://www.instagram.com/riso.pizza.delivery?igsh=NnN6cml2cmNnc3Jp", }, }, { id: "baita", klass: "b-baita", num: "04", cat: "Espetos / Fogo alto", name: "Baita Espeto", pitch: "Espeto de boteco com gente grande na brasa. Tempero forte, ponto exato, embalagem que aguenta o trajeto.", placeholderTag: "Food shot · espeto na brasa", logoImg: asset("logoBaita", "assets/logo-baita.jpg"), foodImg: asset("foodBaita", "assets/food-baita.jpg"), links: { whatsapp: "https://wa.me/5566996709916?text=Ol%C3%A1%20vim%20pelo%20Instagram%20e%20gostaria%20de%20saber%20mais%20informa%C3%A7%C3%B5es!%20%F0%9F%8D%96", menu: "https://baitaespeto.pedir.online/#/", instagram: "https://www.instagram.com/baita.espeto?igsh=OGdoY2F3N3c1MWYx", }, }, { id: "kare", klass: "b-kare", num: "05", cat: "Sushi premium / Omakasê", name: "Kare Sushi", pitch: "Sushi premium para ocasiões que merecem. Peixe selecionado, corte limpo e tempero feito com a calma de quem leva o ofício a sério.", placeholderTag: "Food shot · nigiri premium", logoImg: asset("logoKare", "assets/logo-kare.jpg"), foodImg: asset("foodKare", "assets/food-kare.jpg"), links: { whatsapp: "https://wa.me/5566997191255?text=Ol%C3%A1%20vim%20pelo%20Instagram%20e%20gostaria%20de%20mais%20informa%C3%A7%C3%B5es!%F0%9F%8D%A3", menu: "https://karesushi.pedir.online/#/off", instagram: "https://www.instagram.com/kare.sushi.sorriso?igsh=MW0yeTk3dmp6ZHF4NA==", }, }, ]; const FAQS = [ { q: "Preciso baixar algum aplicativo?", a: "Não. Tudo funciona direto no navegador do celular. É rápido, leve, e não ocupa memória." }, { q: "Funciona bem pelo link da bio do Instagram?", a: "Sim. O site foi otimizado exatamente para quem chega pelo link da bio. Toques largos, carregamento rápido e atalhos para cada marca." }, { q: "Cada marca tem WhatsApp próprio?", a: "Sim. Ao escolher a marca, você fala direto com o atendimento especializado dela — sem central, sem intermediário." }, { q: "Como uso o cupom CHEF?", a: "Copie o cupom no topo da página, escolha a marca e cole no momento do pedido. Vale para a primeira compra em qualquer operação do grupo." }, { q: "Vocês entregam em toda a cidade?", a: "Atendemos as principais regiões. Cada marca tem sua área de cobertura — confira antes de fechar o pedido." }, ]; // ────────────────────────────────────────────────────────── // Subcomponents // ────────────────────────────────────────────────────────── function Topbar() { return (
Panela Company
); } function QuickPick() { return (
{BRANDS.map(b => ( {b.num} {b.name} ))}
); } function MobileCTABar({ onOpenSheet }) { const [visible, setVisible] = useState(false); useEffect(() => { const onScroll = () => setVisible(window.scrollY > 360); onScroll(); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); return (
); } function BrandSheet({ open, onClose }) { useEffect(() => { if (!open) return; const prev = document.body.style.overflow; document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = prev; }; }, [open]); return (
{ if (e.target === e.currentTarget) onClose(); }} role="dialog" aria-modal="true" >

Escolha sua marca

Toque para abrir o WhatsApp da operação.

{BRANDS.map(b => ( {b.num} {b.name} {b.cat} ))}
); } function VerticalVideoGallery() { // In the standalone bundle, only the videos that were actually inlined are // available; drop any slot whose video wasn't bundled. In the normal project // file (__RES empty) all 8 slots play from disk. const allSlots = [1, 2, 3, 4, 5, 6, 7, 8]; const isBundled = Object.keys(__RES).length > 0; const slots = isBundled ? allSlots.filter((n) => __RES["vid" + n]) : allSlots; // duplicate once for seamless loop const items = [...slots, ...slots]; const frameRef = React.useRef(null); const trackRef = React.useRef(null); const [activeDot, setActiveDot] = React.useState(0); React.useEffect(() => { const frame = frameRef.current; if (!frame) return; const cards = Array.from(frame.querySelectorAll(".vgallery-card")); // Lazy-load videos only as their card enters (or nears) the visible area. // This is what keeps the initial mobile payload small — the poster JPG // (~50-100KB) shows immediately, the MP4 (~1-15MB) only downloads on demand. const io = new IntersectionObserver((entries) => { entries.forEach((e) => { const card = e.target; const v = card.querySelector("video"); if (!v) return; if (e.isIntersecting) { // Lazy-attach src on first reveal if (!v.src && v.dataset.src) { v.src = v.dataset.src; v.load(); } const p = v.play(); if (p && p.catch) p.catch(() => {}); // Fade out poster once frame data is ready v.addEventListener("loadeddata", () => card.classList.add("is-loaded"), { once: true }); } else if (!v.paused) { v.pause(); } }); }, { root: frame, rootMargin: "30% 30% 30% 30%", threshold: 0.01 }); cards.forEach((c) => io.observe(c)); // Track scroll position for dot pagination (mobile only — when horizontal) let raf = 0; const onScroll = () => { cancelAnimationFrame(raf); raf = requestAnimationFrame(() => { const isHorizontal = frame.scrollWidth > frame.clientWidth + 10; if (!isHorizontal) return; const card = frame.querySelector(".vgallery-card"); if (!card) return; const cardW = card.getBoundingClientRect().width + 12; // gap const idx = Math.round(frame.scrollLeft / cardW) % slots.length; setActiveDot(Math.max(0, idx)); }); }; frame.addEventListener("scroll", onScroll, { passive: true }); onScroll(); return () => { io.disconnect(); frame.removeEventListener("scroll", onScroll); }; }, [slots.length]); const jumpTo = (i) => { const frame = frameRef.current; if (!frame) return; const card = frame.querySelector(".vgallery-card"); if (!card) return; const cardW = card.getBoundingClientRect().width + 12; frame.scrollTo({ left: cardW * i, behavior: "smooth" }); }; // Mobile marquee: JS-driven horizontal auto-scroll (bulletproof across // devices — does not rely on CSS animation timelines). React.useEffect(() => { const frame = frameRef.current; const track = trackRef.current; if (!frame || !track) return; const mq = window.matchMedia("(max-width: 720px)"); let raf = 0; let offset = 0; let last = 0; const SPEED = 36; // px per second const isMobile = () => mq.matches; const step = (ts) => { if (!last) last = ts; const dt = (ts - last) / 1000; last = ts; // half = width of one full (non-duplicated) set of cards const half = track.scrollWidth / 2; if (half > 0) { offset += SPEED * dt; if (offset >= half) offset -= half; track.style.transform = "translateX(" + (-offset) + "px)"; } raf = requestAnimationFrame(step); }; const start = () => { if (raf) return; // Disable the CSS keyframe animation; JS owns the transform now. track.style.animation = "none"; last = 0; raf = requestAnimationFrame(step); }; const stop = () => { cancelAnimationFrame(raf); raf = 0; track.style.transform = ""; track.style.animation = ""; }; const sync = () => { if (isMobile()) start(); else stop(); }; sync(); const onVis = () => { if (document.hidden) { cancelAnimationFrame(raf); raf = 0; } else if (isMobile()) { last = 0; if (!raf) raf = requestAnimationFrame(step); } }; document.addEventListener("visibilitychange", onVis); mq.addEventListener ? mq.addEventListener("change", sync) : mq.addListener(sync); return () => { stop(); document.removeEventListener("visibilitychange", onVis); mq.removeEventListener ? mq.removeEventListener("change", sync) : mq.removeListener(sync); }; }, [slots.length]); return (
{items.map((n, i) => (
))}
); } function Hero({ headline }) { // Pre-split headline at first period if any const [main, ...rest] = headline.split(/(?<=\.)\s+/); return (
● Panela Company · Desde 2022

Sabores que reúnem
pessoas.

Cinco marcas, uma cozinha-mãe. Reunimos pizzarias, espetaria e sushi sob a mesma obsessão por sabor, consistência e atendimento de gente que cozinha de verdade.

05
Marcas
4+
Anos
50K+
Pedidos
98%
Aprovação
); } function Coupon() { const [copied, setCopied] = useState(false); const copy = () => { try { navigator.clipboard?.writeText("CHEF"); } catch (e) {} setCopied(true); setTimeout(() => setCopied(false), 1600); }; return (
Desconto exclusivo · primeira compra
15% de boas-vindas em qualquer marca do grupo
Pedido direto, sem intermediários. Pontos acumulam para trocar por produtos.
CHEF
); } function BrandCard({ brand, featured }) { return (
{brand.foodImg ? {brand.name : ▢ {brand.placeholderTag}}
{brand.name} {brand.num}
{brand.cat}

{brand.pitch}

{I.waMark} Peça pelo WhatsApp {I.menu} Cardápio {I.instagram} Instagram
); } function BrandsSection({ featureLastCard }) { return (
● Nossas marcas

Escolha sua marca,
fale direto com a cozinha.

Cada operação tem seu próprio WhatsApp, cardápio e identidade — porque cada marca cozinha o que sabe fazer melhor.

05 marcas ativas
Pedido direto · sem app
Resposta em minutos
{BRANDS.map((b, i) => ( ))}
); } function About() { return (
Pedro e Gaby, fundadores da Panela Company Pedro & Gaby · Fundadores
● Quem somos

Somos Pedro e Gaby — um casal movido pelo mesmo propósito:
cozinha, marca e gente.

Nossa história no empreendedorismo começou em 2022, quando decidimos transformar uma paixão em algo maior. Desde então, não construímos apenas restaurantes — desenvolvemos marcas com identidade, padrão e visão de crescimento.

Atuamos no universo do delivery com diferentes operações: pizzas, espetos e sushis. Cada marca nasce com um conceito claro, foco extremo em qualidade e um compromisso inegociável com a experiência do cliente — do pedido à última mordida.

Nosso sonho é grande — e é só o começo. Queremos levar nossas marcas para todo o Brasil e nos tornar referência nacional em comida delivery, provando que é possível crescer sem perder identidade, qualidade e propósito.

05
Marcas
4+
Anos de estrada
50K+
Pedidos entregues
98%
Aprovação dos clientes
); } function OwnerStrip() { return (
● Fale direto com o dono

Dúvidas, sugestões, críticas
ou parcerias?

Estamos sempre ouvindo. A resposta vem do Pedro ou da Gaby — sem central, sem robô.

{I.waMark} Falar no WhatsApp
— Pedro & Gaby
); } function FAQ() { const [open, setOpen] = useState(0); return (
● Perguntas frequentes

O essencial,
sem rodeios.

{FAQS.map((f, i) => (
setOpen(open === i ? -1 : i)} >
{f.q} {I.plus}
{f.a}
))}
); } function Footer() { return ( ); } // ────────────────────────────────────────────────────────── // Tweaks panel // ────────────────────────────────────────────────────────── function PanelaTweaks({ t, setTweak }) { return ( setTweak("palette", v)} /> setTweak("displayFont", v)} /> setTweak("featureLastCard", v)} /> setTweak("showCoupon", v)} /> setTweak("headline", v)} /> ); } // ────────────────────────────────────────────────────────── // App // ────────────────────────────────────────────────────────── function App() { const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS); const [sheetOpen, setSheetOpen] = useState(false); // Apply palette + font via root CSS vars useEffect(() => { const root = document.documentElement; const palettes = { japonesa: { "--ink": "#0E0E0E", "--ink-2": "#1A1614", "--paper": "#F6F1E7", "--paper-2": "#EFE7D6", "--line-soft": "#E2D9C5", "--red": "#8B1A1A", "--red-deep": "#6B0F0F", "--gold": "#C9A24A", "--gold-soft": "#E2C275", }, terracota: { "--ink": "#1A120E", "--ink-2": "#26170F", "--paper": "#F4EADC", "--paper-2": "#ECDFCC", "--line-soft": "#DCC9AE", "--red": "#A6321C", "--red-deep": "#7E2310", "--gold": "#D9A35A", "--gold-soft": "#EBC388", }, "ônix": { "--ink": "#0A0A0A", "--ink-2": "#141414", "--paper": "#EFEDE7", "--paper-2": "#E5E2D9", "--line-soft": "#D6D2C6", "--red": "#7A0E0E", "--red-deep": "#560808", "--gold": "#B89556", "--gold-soft": "#D3B47C", }, }; const fonts = { provicali: '"Provicali", "Shippori Mincho", serif', shippori: '"Shippori Mincho", "Provicali", serif', cormorant: '"Cormorant Garamond", "Provicali", serif', fraunces: '"Fraunces", "Provicali", serif', }; const p = palettes[t.palette] || palettes.japonesa; Object.entries(p).forEach(([k, v]) => root.style.setProperty(k, v)); root.style.setProperty("--font-display", fonts[t.displayFont] || fonts.shippori); }, [t.palette, t.displayFont]); return ( <> {t.showCoupon && }