/* ============================================================
   THE DUCKS — CARDÁPIO PÚBLICO (cliente final)
   React sem build (Babel @7). Depende de config.js.
   ============================================================ */

const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ---------------------------- helpers ---------------------------- */
const money = (n) => 'R$ ' + (Number(n) || 0).toFixed(2).replace('.', ',');
const norm  = (s) => (s == null ? '' : String(s)).normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase().trim();
const onlyDigits = (s) => (s || '').replace(/\D/g, '');

const DIAS = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
const DIAS_PT = {
  sunday: 'Domingo', monday: 'Segunda', tuesday: 'Terça', wednesday: 'Quarta',
  thursday: 'Quinta', friday: 'Sexta', saturday: 'Sábado',
};

const toMin = (t) => {
  const p = String(t || '00:00').split(':');
  return (parseInt(p[0], 10) || 0) * 60 + (parseInt(p[1], 10) || 0);
};

/* Suporta fechamento depois da meia-noite (close < open) */
function isOpenNow(hours) {
  if (!hours) return true;
  const now = new Date();
  const mins = now.getHours() * 60 + now.getMinutes();

  const hoje = hours[DIAS[now.getDay()]];
  if (hoje && !hoje.closed) {
    const o = toMin(hoje.open), c = toMin(hoje.close);
    if (c > o ? (mins >= o && mins < c) : mins >= o) return true;
  }
  const ontem = hours[DIAS[(now.getDay() + 6) % 7]];
  if (ontem && !ontem.closed) {
    const o = toMin(ontem.open), c = toMin(ontem.close);
    if (c <= o && mins < c) return true;
  }
  return false;
}

function proximaAbertura(hours) {
  if (!hours) return '';
  const now = new Date();
  for (let i = 0; i < 8; i++) {
    const d = new Date(now.getTime() + i * 86400000);
    const h = hours[DIAS[d.getDay()]];
    if (!h || h.closed) continue;
    if (i === 0 && now.getHours() * 60 + now.getMinutes() >= toMin(h.open)) continue;
    return (i === 0 ? 'hoje' : i === 1 ? 'amanhã' : DIAS_PT[DIAS[d.getDay()]]) + ' às ' + h.open;
  }
  return '';
}

/* ---------------------------- estilos ----------------------------
   Identidade fixa, conteúdo repintado a cada troca de tema (onTema),
   igual ao app.jsx. */
const card = {};
const inp = {};
const lbl = {};
const btnPrim = {};

function _pintarEstilos() {
  Object.assign(card, { background: T.surface, border: '1px solid ' + T.border, borderRadius: 12 });
  Object.assign(inp, {
    width: '100%', padding: '12px 14px', borderRadius: 10, border: '1px solid ' + T.border,
    background: T.surface2, color: T.text, outline: 'none', fontSize: 16,
  });
  Object.assign(lbl, {
    fontSize: 12, fontWeight: 700, color: T.muted, marginBottom: 6, display: 'block', letterSpacing: .3,
  });
  Object.assign(btnPrim, {
    background: T.accent, color: T.escuro ? '#0E0F12' : '#FFFFFF', padding: '15px 18px',
    borderRadius: 12, fontWeight: 800, fontSize: 15, width: '100%',
  });
}
_pintarEstilos();
onTema(_pintarEstilos);

function useTema() {
  const [tema, setTema] = useState(temaSalvo());
  useEffect(() => onTema(setTema), []);
  return tema;
}

/* Mesmas regras do app.jsx: contain numa caixa quadrada (nunca corta nem
   estica) e o fundo branco do PNG derrubado por blend — multiply no claro,
   invert + screen no escuro. Trocar de logo é só trocar logo.png. */
function Logo({ size, style }) {
  const [ok, setOk] = useState(true);
  const s = size || 50;
  if (!ok) return <div style={Object.assign({ fontSize: s, lineHeight: 1 }, style)}>🦆</div>;
  return (
    <img src="./logo.png" alt="The Ducks" onError={() => setOk(false)}
      style={Object.assign({
        width: s, height: s, objectFit: 'contain', display: 'block', margin: '0 auto',
        mixBlendMode: T.escuro ? 'screen' : 'multiply',
        filter: T.escuro ? 'invert(1) hue-rotate(180deg)' : 'none',
      }, style)} />
  );
}

/* ------------------------- monte o seu -------------------------
   Um produto com `montavel` preenchido é um construtor: o preço dele é
   a base e a ficha técnica dele é o que já vem incluso. Os extras
   ofertados saem da união das fichas dos produtos da mesma família —
   ou seja, o que já é usado nos lanches prontos é o que dá pra montar.
   Só entram insumos com preco_venda > 0: preço zerado significa
   "não oferecer", e não "de graça". */
const FAMILIAS = {
  xis:    (nome) => /\bxis\b/.test(norm(nome)),
  burger: (nome) => /(burger|hamburgue)/.test(norm(nome)),
};

function extrasDoMontavel(prod, prods, fichas, insumos) {
  const familia = FAMILIAS[prod.montavel];
  if (!familia) return { inclusos: [], extras: [] };

  const idsFamilia = prods.filter((p) => familia(p.nome)).map((p) => p.id);
  const inclusosIds = fichas.filter((f) => f.product_id === prod.id).map((f) => f.stock_item_id);

  const usados = {};
  fichas.forEach((f) => {
    if (idsFamilia.indexOf(f.product_id) >= 0) usados[f.stock_item_id] = true;
  });

  const porId = {};
  insumos.forEach((i) => { porId[i.id] = i; });

  const inclusos = inclusosIds.map((id) => porId[id]).filter(Boolean);
  const extras = Object.keys(usados)
    .map((id) => porId[id])
    .filter((i) => i && Number(i.preco_venda) > 0 && inclusosIds.indexOf(i.id) < 0)
    .sort((a, b) => a.nome.localeCompare(b.nome, 'pt-BR'));

  return { inclusos, extras };
}

/* ---------------------------- dados ---------------------------- */
function useCardapio() {
  const [cats, setCats]   = useState([]);
  const [prods, setProds] = useState([]);
  const [bairros, setBairros] = useState([]);
  const [cfg, setCfg] = useState({});
  const [fichas, setFichas] = useState([]);
  const [insumos, setInsumos] = useState([]);
  const [loading, setLoading] = useState(true);
  const timer = useRef(null);

  const load = useCallback(async () => {
    try {
      /* fichas e insumos alimentam o "Monte o seu". Só as colunas necessárias:
         custo de insumo não é da conta do cliente, preco_venda é. */
      const [c, p, b, s, f, i] = await Promise.all([
        supabase.from('categories').select('*').eq('ativo', true).order('ordem'),
        supabase.from('products').select('*').eq('ativo', true).order('ordem'),
        supabase.from('bairros').select('*').eq('ativo', true).order('nome'),
        supabase.from('settings').select('*'),
        supabase.from('product_recipe').select('product_id,stock_item_id,qtd'),
        supabase.from('stock_items').select('id,nome,unidade,preco_venda').order('nome'),
      ]);
      if (c.data) setCats(c.data);
      if (p.data) setProds(p.data);
      if (b.data) setBairros(b.data);
      if (f.data) setFichas(f.data);
      if (i.data) setInsumos(i.data);
      if (s.data) {
        const o = {};
        s.data.forEach((r) => { o[r.key] = r.value || {}; });
        setCfg(o);
      }
    } catch (e) {
      console.error('[cardapio] load', e);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    load();
    const debounced = () => {
      clearTimeout(timer.current);
      timer.current = setTimeout(load, 400);
    };
    const ch = supabase.channel('cardapio-pub')
      .on('postgres_changes', { event: '*', schema: 'public', table: 'products'   }, debounced)
      .on('postgres_changes', { event: '*', schema: 'public', table: 'categories' }, debounced)
      .on('postgres_changes', { event: '*', schema: 'public', table: 'bairros'    }, debounced)
      .on('postgres_changes', { event: '*', schema: 'public', table: 'settings'   }, debounced)
      .subscribe();
    /* fallback: bloqueio de emergência reflete em até 30s mesmo sem realtime */
    const iv = setInterval(load, 30000);
    return () => { clearTimeout(timer.current); clearInterval(iv); supabase.removeChannel(ch); };
  }, [load]);

  return { cats, prods, bairros, cfg, fichas, insumos, loading, reload: load };
}

/* ---------------------------- carrinho ---------------------------- */
const CART_KEY = 'theducks_cart_v1';

function useCart() {
  const [items, setItems] = useState(() => {
    try { return JSON.parse(localStorage.getItem(CART_KEY) || '[]'); } catch (e) { return []; }
  });
  useEffect(() => {
    try { localStorage.setItem(CART_KEY, JSON.stringify(items)); } catch (e) {}
  }, [items]);

  const add = (it) => setItems((prev) => {
    const i = prev.findIndex((x) => x.key === it.key);
    if (i >= 0) {
      const cp = prev.slice();
      cp[i] = Object.assign({}, cp[i], { qtd: cp[i].qtd + it.qtd });
      return cp;
    }
    return prev.concat([it]);
  });
  const setQtd = (key, q) => setItems((prev) =>
    q <= 0 ? prev.filter((x) => x.key !== key)
           : prev.map((x) => (x.key === key ? Object.assign({}, x, { qtd: q }) : x)));
  const clear = () => setItems([]);
  const subtotal = items.reduce((a, x) => a + x.preco * x.qtd, 0);
  const count = items.reduce((a, x) => a + x.qtd, 0);
  return { items, add, setQtd, clear, subtotal, count };
}

/* ---------------------------- UI base ---------------------------- */
function Sheet({ open, onClose, children, title }) {
  useEffect(() => {
    document.body.style.overflow = open ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [open]);
  if (!open) return null;
  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(0,0,0,.72)', zIndex: 200,
      display: 'flex', alignItems: 'flex-end', justifyContent: 'center', backdropFilter: 'blur(2px)',
    }}>
      <div className="fadeup" onClick={(e) => e.stopPropagation()} style={{
        background: T.bg, width: '100%', maxWidth: 520, maxHeight: '92vh', overflowY: 'auto',
        borderRadius: '18px 18px 0 0', border: '1px solid ' + T.border, borderBottom: 'none',
      }}>
        <div style={{
          position: 'sticky', top: 0, background: T.bg, zIndex: 2, padding: '14px 16px',
          borderBottom: '1px solid ' + T.border, display: 'flex', alignItems: 'center', gap: 12,
        }}>
          <div className="display" style={{ fontSize: 24, flex: 1 }}>{title}</div>
          <button onClick={onClose} style={{
            background: T.surface2, color: T.text, width: 34, height: 34, borderRadius: 10, fontSize: 18,
          }}>×</button>
        </div>
        <div style={{ padding: 16 }}>{children}</div>
      </div>
    </div>
  );
}

function Field({ label, children }) {
  return <div style={{ marginBottom: 12 }}><label style={lbl}>{label}</label>{children}</div>;
}

/* ---------------------------- produto ---------------------------- */
function ProductModal({ prod, onClose, onAdd, prods, fichas, insumos }) {
  const [qtd, setQtd] = useState(1);
  const [obs, setObs] = useState('');
  const [ads, setAds] = useState([]);
  if (!prod) return null;

  const monta = prod.montavel
    ? extrasDoMontavel(prod, prods || [], fichas || [], insumos || [])
    : null;

  const lista = Array.isArray(prod.adicionais) ? prod.adicionais : [];
  const extra = ads.reduce((a, x) => a + Number(x.preco || 0), 0);
  const unit  = Number(prod.preco || 0) + extra;

  const toggle = (a) => setAds((prev) =>
    prev.some((x) => x.nome === a.nome) ? prev.filter((x) => x.nome !== a.nome) : prev.concat([a]));

  const confirmar = () => {
    onAdd({
      key: prod.id + '|' + ads.map((a) => a.nome).sort().join(',') + '|' + norm(obs),
      product_id: prod.id,
      nome: prod.nome,
      preco: unit,
      custo: Number(prod.custo || 0),
      qtd, obs,
      adicionais: ads,
    });
    onClose();
  };

  return (
    <Sheet open onClose={onClose} title={prod.nome}>
      {prod.imagem_url ? (
        <img src={prod.imagem_url} alt={prod.nome} style={{
          width: '100%', height: 190, objectFit: 'cover', borderRadius: 12, marginBottom: 14,
        }} />
      ) : null}
      {prod.descricao ? (
        <div style={{ color: T.muted, fontSize: 14, lineHeight: 1.55, marginBottom: 16 }}>{prod.descricao}</div>
      ) : null}

      {monta && (
        <div style={{ marginBottom: 18 }}>
          {monta.inclusos.length > 0 && (
            <div style={{
              background: T.surface2, borderRadius: 11, padding: '11px 13px', marginBottom: 14,
              fontSize: 13, lineHeight: 1.6,
            }}>
              <b style={{ color: T.text }}>Já vem com</b>
              <div style={{ color: T.muted, marginTop: 3 }}>
                {monta.inclusos.map((i) => i.nome).join(' · ')}
              </div>
            </div>
          )}

          <div style={lbl}>MONTE DO SEU JEITO</div>

          {monta.extras.length === 0 ? (
            <div style={{ color: T.muted, fontSize: 13, lineHeight: 1.55, marginBottom: 8 }}>
              Ainda não há ingredientes liberados para montagem.
            </div>
          ) : monta.extras.map((i) => {
            const on = ads.some((x) => x.stock_item_id === i.id);
            return (
              <button key={i.id}
                onClick={() => setAds((prev) => on
                  ? prev.filter((x) => x.stock_item_id !== i.id)
                  /* qtd 1 = uma unidade da medida do insumo; é o que o trigger baixa */
                  : prev.concat([{ nome: i.nome, preco: Number(i.preco_venda), stock_item_id: i.id, qtd: 1 }]))}
                style={Object.assign({}, card, {
                  width: '100%', display: 'flex', alignItems: 'center', gap: 10, padding: '12px 14px',
                  marginBottom: 8, color: T.text, textAlign: 'left',
                  borderColor: on ? T.accent : T.border,
                  background: on ? 'rgba(184,122,0,.08)' : T.surface,
                })}>
                <div style={{
                  width: 20, height: 20, borderRadius: 6, border: '2px solid ' + (on ? T.accent : T.border),
                  background: on ? T.accent : 'transparent', color: '#fff', fontSize: 13,
                  display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 900,
                }}>{on ? '✓' : ''}</div>
                <span style={{ flex: 1, fontSize: 14, fontWeight: 600 }}>{i.nome}</span>
                <span style={{ color: T.accent, fontSize: 13, fontWeight: 700 }}>+{money(i.preco_venda)}</span>
              </button>
            );
          })}
        </div>
      )}

      {lista.length > 0 && (
        <div style={{ marginBottom: 16 }}>
          <div style={lbl}>ADICIONAIS</div>
          {lista.map((a, i) => {
            const on = ads.some((x) => x.nome === a.nome);
            return (
              <button key={i} onClick={() => toggle(a)} style={Object.assign({}, card, {
                width: '100%', display: 'flex', alignItems: 'center', gap: 10, padding: '12px 14px',
                marginBottom: 8, color: T.text, textAlign: 'left',
                borderColor: on ? T.accent : T.border, background: on ? 'rgba(245,179,1,.08)' : T.surface,
              })}>
                <div style={{
                  width: 20, height: 20, borderRadius: 6, border: '2px solid ' + (on ? T.accent : T.border),
                  background: on ? T.accent : 'transparent', color: '#0E0F12', fontSize: 13,
                  display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 900,
                }}>{on ? '✓' : ''}</div>
                <span style={{ flex: 1, fontSize: 14, fontWeight: 600 }}>{a.nome}</span>
                <span style={{ color: T.accent, fontSize: 13, fontWeight: 700 }}>+{money(a.preco)}</span>
              </button>
            );
          })}
        </div>
      )}

      <Field label="OBSERVAÇÃO (opcional)">
        <input style={inp} value={obs} onChange={(e) => setObs(e.target.value)} placeholder="Ex: sem cebola, ponto da carne…" />
      </Field>

      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 16 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, background: T.surface2, borderRadius: 12, padding: 4 }}>
          <button onClick={() => setQtd((q) => Math.max(1, q - 1))} style={{
            width: 38, height: 38, borderRadius: 9, background: T.surface, color: T.text, fontSize: 20,
          }}>−</button>
          <div style={{ minWidth: 28, textAlign: 'center', fontWeight: 800, fontSize: 16 }}>{qtd}</div>
          <button onClick={() => setQtd((q) => q + 1)} style={{
            width: 38, height: 38, borderRadius: 9, background: T.surface, color: T.text, fontSize: 20,
          }}>+</button>
        </div>
        <button onClick={confirmar} style={Object.assign({}, btnPrim, { flex: 1 })}>
          Adicionar • {money(unit * qtd)}
        </button>
      </div>
    </Sheet>
  );
}

/* ---------------------------- checkout ---------------------------- */
function Checkout({ cart, cfg, bairros, onClose, onDone }) {
  const entrega = cfg.entrega || {};
  const pagamentos = cfg.pagamentos || { pix: true, dinheiro: true, credito: true, debito: true };

  const tiposDisp = [
    entrega.aceita_entrega !== false && { id: 'entrega', label: 'Entrega', emoji: '🛵' },
    entrega.aceita_retirada !== false && { id: 'retirada', label: 'Retirada', emoji: '🥡' },
    entrega.aceita_mesa !== false && { id: 'mesa', label: 'Mesa', emoji: '🪑' },
  ].filter(Boolean);

  const [tipo, setTipo] = useState(tiposDisp.length ? tiposDisp[0].id : 'entrega');
  const [f, setF] = useState(() => {
    try { return JSON.parse(localStorage.getItem('theducks_cliente') || '{}'); }
    catch (e) { return {}; }
  });
  const [bairroId, setBairroId] = useState(f.bairro_id || '');
  const [pag, setPag] = useState('pix');
  const [troco, setTroco] = useState('');
  const [obs, setObs] = useState('');
  const [cepLoading, setCepLoading] = useState(false);
  const [erro, setErro] = useState('');
  const [enviando, setEnviando] = useState(false);

  const set = (k) => (e) => setF((p) => Object.assign({}, p, { [k]: e.target.value }));

  /* auto-match do bairro digitado livremente */
  useEffect(() => {
    if (bairroId || !f.bairro) return;
    const m = bairros.find((b) => norm(b.nome) === norm(f.bairro));
    if (m) setBairroId(m.id);
  }, [f.bairro, bairros, bairroId]);

  /* ViaCEP */
  const onCep = (e) => {
    const v = onlyDigits(e.target.value).slice(0, 8);
    setF((p) => Object.assign({}, p, { cep: v }));
    if (v.length !== 8) return;
    setCepLoading(true);
    fetch('https://viacep.com.br/ws/' + v + '/json/')
      .then((r) => r.json())
      .then((d) => {
        if (d && !d.erro) {
          setF((p) => Object.assign({}, p, { endereco: d.logradouro || p.endereco, bairro: d.bairro || p.bairro }));
          const m = bairros.find((b) => norm(b.nome) === norm(d.bairro));
          if (m) setBairroId(m.id);
        }
      })
      .catch(() => {})
      .finally(() => setCepLoading(false));
  };

  const bairroSel = bairros.find((b) => b.id === bairroId);
  const taxa = tipo === 'entrega' ? Number((bairroSel && bairroSel.taxa_cliente) || 0) : 0;
  const total = cart.subtotal + taxa;
  const minimo = Number(entrega.pedido_minimo || 0);

  const enviar = async () => {
    setErro('');
    if (!f.nome || f.nome.trim().length < 2) return setErro('Informe seu nome.');
    if (tipo !== 'mesa' && onlyDigits(f.telefone).length < 10) return setErro('Informe um WhatsApp válido com DDD.');
    if (tipo === 'mesa' && !f.mesa) return setErro('Informe o número da mesa.');
    if (tipo === 'entrega') {
      if (!f.endereco) return setErro('Informe o endereço.');
      if (!f.numero_end) return setErro('Informe o número.');
      if (!bairroId && !f.bairro) return setErro('Informe o bairro.');
    }
    if (minimo > 0 && cart.subtotal < minimo) return setErro('Pedido mínimo de ' + money(minimo) + '.');

    setEnviando(true);
    try {
      const payload = {
        tipo, status: 'preparando', origem: 'cardapio',
        mesa: tipo === 'mesa' ? String(f.mesa || '') : '',
        cliente_nome: f.nome.trim(),
        cliente_tel: onlyDigits(f.telefone || ''),
        cep: f.cep || '',
        endereco: tipo === 'entrega' ? (f.endereco || '') : '',
        numero_end: tipo === 'entrega' ? (f.numero_end || '') : '',
        complemento: tipo === 'entrega' ? (f.complemento || '') : '',
        bairro: tipo === 'entrega' ? ((bairroSel && bairroSel.nome) || f.bairro || '') : '',
        bairro_id: tipo === 'entrega' ? (bairroId || null) : null,
        referencia: f.referencia || '',
        subtotal: cart.subtotal,
        taxa_entrega: taxa,
        desconto: 0,
        total,
        pagamento: pag,
        troco_para: pag === 'dinheiro' ? Number(String(troco).replace(',', '.')) || 0 : 0,
        obs: obs || '',
      };

      const ins = await supabase.from('orders').insert(payload).select().single();
      if (ins.error) throw ins.error;
      const ordem = ins.data;

      const itens = cart.items.map((x) => ({
        order_id: ordem.id,
        product_id: x.product_id,
        nome: x.nome,
        qtd: x.qtd,
        preco_unit: x.preco,
        custo_unit: x.custo || 0,
        adicionais: x.adicionais || [],
        obs: x.obs || '',
      }));
      const insItens = await supabase.from('order_items').insert(itens);
      if (insItens.error) throw insItens.error;

      /* cliente (não bloqueia o pedido se falhar) */
      if (payload.cliente_tel) {
        supabase.from('customers').upsert({
          nome: payload.cliente_nome, telefone: payload.cliente_tel, cep: payload.cep,
          endereco: payload.endereco, numero: payload.numero_end, complemento: payload.complemento,
          bairro: payload.bairro, bairro_id: payload.bairro_id, referencia: payload.referencia,
        }, { onConflict: 'telefone' }).then(function () {}, function () {});
      }

      try {
        localStorage.setItem('theducks_cliente', JSON.stringify(
          Object.assign({}, f, { bairro_id: bairroId, bairro: payload.bairro })
        ));
      } catch (e) {}

      onDone(ordem);
    } catch (e) {
      console.error('[checkout]', e);
      setErro('Não foi possível enviar: ' + (e.message || 'erro desconhecido'));
      setEnviando(false);
    }
  };

  const pagOpts = [
    pagamentos.pix !== false && { id: 'pix', label: 'PIX', emoji: '⚡' },
    pagamentos.dinheiro !== false && { id: 'dinheiro', label: 'Dinheiro', emoji: '💵' },
    pagamentos.credito !== false && { id: 'credito', label: 'Crédito', emoji: '💳' },
    pagamentos.debito !== false && { id: 'debito', label: 'Débito', emoji: '💳' },
  ].filter(Boolean);

  const chip = (on) => ({
    flex: 1, minWidth: 92, padding: '12px 8px', borderRadius: 10, fontWeight: 700, fontSize: 13,
    background: on ? T.accent : T.surface2, color: on ? '#0E0F12' : T.text,
    border: '1px solid ' + (on ? T.accent : T.border),
  });

  return (
    <Sheet open onClose={onClose} title="Finalizar pedido">
      <div style={{ display: 'flex', gap: 8, marginBottom: 18, flexWrap: 'wrap' }}>
        {tiposDisp.map((t) => (
          <button key={t.id} onClick={() => setTipo(t.id)} style={chip(tipo === t.id)}>
            {t.emoji} {t.label}
          </button>
        ))}
      </div>

      <Field label="SEU NOME *">
        <input style={inp} value={f.nome || ''} onChange={set('nome')} placeholder="Nome e sobrenome" />
      </Field>

      {tipo !== 'mesa' && (
        <Field label="WHATSAPP *">
          <input style={inp} inputMode="numeric" value={f.telefone || ''}
            onChange={(e) => setF((p) => Object.assign({}, p, { telefone: onlyDigits(e.target.value).slice(0, 11) }))}
            placeholder="51999998888" />
        </Field>
      )}

      {tipo === 'mesa' && (
        <Field label="MESA *">
          <input style={inp} inputMode="numeric" value={f.mesa || ''} onChange={set('mesa')} placeholder="Ex: 12" />
        </Field>
      )}

      {tipo === 'entrega' && (
        <div style={{ borderLeft: '3px solid ' + T.roxo, paddingLeft: 12, marginBottom: 4 }}>
          <Field label={'CEP (opcional)' + (cepLoading ? ' — buscando…' : '')}>
            <input style={inp} inputMode="numeric" value={f.cep || ''} onChange={onCep} placeholder="90000000" />
          </Field>
          <Field label="RUA *">
            <input style={inp} value={f.endereco || ''} onChange={set('endereco')} placeholder="Rua / Avenida" />
          </Field>
          <div style={{ display: 'flex', gap: 10 }}>
            <div style={{ width: 110 }}>
              <Field label="Nº *">
                <input style={inp} value={f.numero_end || ''} onChange={set('numero_end')} placeholder="123" />
              </Field>
            </div>
            <div style={{ flex: 1 }}>
              <Field label="COMPLEMENTO">
                <input style={inp} value={f.complemento || ''} onChange={set('complemento')} placeholder="Apto 302" />
              </Field>
            </div>
          </div>
          <Field label="BAIRRO *">
            <select style={inp} value={bairroId} onChange={(e) => setBairroId(e.target.value)}>
              <option value="">Selecione o bairro…</option>
              {bairros.map((b) => (
                <option key={b.id} value={b.id}>{b.nome} — {money(b.taxa_cliente)}</option>
              ))}
            </select>
            {!bairroId && (
              <input style={Object.assign({}, inp, { marginTop: 8 })} value={f.bairro || ''}
                onChange={set('bairro')} placeholder="Ou digite o bairro" />
            )}
          </Field>
          <Field label="PONTO DE REFERÊNCIA">
            <input style={inp} value={f.referencia || ''} onChange={set('referencia')} placeholder="Perto de…" />
          </Field>
        </div>
      )}

      <div style={lbl}>PAGAMENTO</div>
      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 12 }}>
        {pagOpts.map((p) => (
          <button key={p.id} onClick={() => setPag(p.id)} style={chip(pag === p.id)}>{p.emoji} {p.label}</button>
        ))}
      </div>

      {pag === 'dinheiro' && (
        <Field label="TROCO PARA">
          <input style={inp} inputMode="decimal" value={troco} onChange={(e) => setTroco(e.target.value)} placeholder="Ex: 100" />
        </Field>
      )}

      <Field label="OBSERVAÇÕES DO PEDIDO">
        <textarea style={Object.assign({}, inp, { minHeight: 72, resize: 'vertical' })}
          value={obs} onChange={(e) => setObs(e.target.value)} placeholder="Alguma observação geral?" />
      </Field>

      <div style={Object.assign({}, card, { padding: 14, marginTop: 6, marginBottom: 14 })}>
        <Linha k="Subtotal" v={money(cart.subtotal)} />
        {tipo === 'entrega' && (
          <Linha k="Taxa de entrega" v={bairroId ? money(taxa) : 'selecione o bairro'} />
        )}
        <div style={{ height: 1, background: T.border, margin: '10px 0' }} />
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span style={{ fontWeight: 800 }}>Total</span>
          <span className="display" style={{ fontSize: 26, color: T.accent }}>{money(total)}</span>
        </div>
      </div>

      {erro ? (
        <div style={{
          background: 'rgba(220,38,38,.12)', border: '1px solid ' + T.danger, color: '#FCA5A5',
          padding: 12, borderRadius: 10, fontSize: 13, marginBottom: 12,
        }}>{erro}</div>
      ) : null}

      <button disabled={enviando} onClick={enviar} style={Object.assign({}, btnPrim, {
        opacity: enviando ? .6 : 1, marginBottom: 8,
      })}>
        {enviando ? 'Enviando…' : '🦆 Enviar pedido'}
      </button>
    </Sheet>
  );
}

function Linha({ k, v }) {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 14, color: T.muted, marginBottom: 6 }}>
      <span>{k}</span><span style={{ color: T.text, fontWeight: 600 }}>{v}</span>
    </div>
  );
}

/* ---------------------------- sucesso ---------------------------- */
function Sucesso({ ordem, cfg, onClose }) {
  const neg = cfg.negocio || {};
  const tel = onlyDigits(neg.telefone || '');
  const msg = encodeURIComponent(
    'Olá! Acabei de enviar o pedido #' + ordem.numero + ' pelo cardápio 🦆 (' + ordem.cliente_nome + ')'
  );
  return (
    <Sheet open onClose={onClose} title="Pedido enviado!">
      <div style={{ textAlign: 'center', padding: '10px 0 4px' }}>
        <Logo size={84} />
        <div className="display" style={{ fontSize: 30, marginTop: 6 }}>PEDIDO #{ordem.numero}</div>
        <div style={{ color: T.muted, fontSize: 14, marginTop: 6, lineHeight: 1.6 }}>
          Recebemos seu pedido e já mandamos pra cozinha.<br />
          {ordem.tipo === 'entrega'
            ? 'Previsão: ' + ((cfg.entrega || {}).tempo_entrega || '40-60 min')
            : ordem.tipo === 'retirada'
              ? 'Pronto para retirada em ' + ((cfg.entrega || {}).tempo_retirada || '20-30 min')
              : 'Já estamos preparando na mesa ' + ordem.mesa}
        </div>
      </div>
      <div style={Object.assign({}, card, { padding: 14, margin: '16px 0' })}>
        <Linha k="Total" v={money(ordem.total)} />
        <Linha k="Pagamento" v={String(ordem.pagamento || '').toUpperCase()} />
        {ordem.pagamento === 'pix' && neg.pix ? <Linha k="Chave PIX" v={neg.pix} /> : null}
      </div>
      {tel ? (
        <a href={'https://wa.me/55' + tel + '?text=' + msg} target="_blank" rel="noreferrer"
          style={Object.assign({}, btnPrim, {
            display: 'block', textAlign: 'center', textDecoration: 'none', background: '#25D366', color: '#062E14',
          })}>
          💬 Falar no WhatsApp
        </a>
      ) : null}
      <button onClick={onClose} style={{
        width: '100%', marginTop: 10, padding: 14, borderRadius: 12,
        background: T.surface2, color: T.text, fontWeight: 700,
      }}>Fazer outro pedido</button>
    </Sheet>
  );
}

/* ---------------------------- app ---------------------------- */
function App() {
  useTema(); // o cardápio é travado no claro; o hook só mantém o contrato do config.js
  const { cats, prods, bairros, cfg, fichas, insumos, loading } = useCardapio();
  const cart = useCart();
  const [busca, setBusca] = useState('');
  const [catSel, setCatSel] = useState('');
  const [prodSel, setProdSel] = useState(null);
  const [verCarrinho, setVerCarrinho] = useState(false);
  const [verCheckout, setVerCheckout] = useState(false);
  const [sucesso, setSucesso] = useState(null);

  useEffect(() => {
    if (loading) return;
    const b = document.getElementById('boot');
    if (b) b.remove();
  }, [loading]);

  const emerg = cfg.emergencia || {};
  const aberto = !emerg.fechado && isOpenNow(cfg.business_hours);
  const banner = cfg.banner || {};
  const neg = cfg.negocio || {};

  const grupos = useMemo(() => {
    const q = norm(busca);
    return cats
      .filter((c) => !catSel || c.id === catSel)
      .map((c) => ({
        cat: c,
        itens: prods.filter((p) =>
          p.categoria_id === c.id && (!q || norm(p.nome).includes(q) || norm(p.descricao).includes(q))),
      }))
      .filter((g) => g.itens.length > 0);
  }, [cats, prods, busca, catSel]);

  const destaques = useMemo(() => prods.filter((p) => p.destaque).slice(0, 6), [prods]);

  if (loading) return null;

  return (
    <div className="wrap" style={{ paddingBottom: cart.count ? 96 : 28 }}>
      {/* HERO */}
      <div className="hero-pad" style={{
        background: T.escuro
          ? 'linear-gradient(160deg,#1A1C22 0%,#0E0F12 100%)'
          : 'linear-gradient(160deg,#FFFFFF 0%,#E9ECF2 100%)',
        borderBottom: '1px solid ' + T.border, textAlign: 'center',
      }}>
        <Logo size={96} />
        <div className="display" style={{ fontSize: 42, marginTop: 6, color: T.accent }}>
          {(neg.nome || NOME_NEGOCIO).toUpperCase()}
        </div>
        <div style={{ color: T.muted, fontSize: 13, letterSpacing: 2, textTransform: 'uppercase' }}>
          {neg.slogan || 'Pub & Burgers'}
        </div>
        <div style={{
          display: 'inline-flex', alignItems: 'center', gap: 7, marginTop: 14,
          background: aberto ? 'rgba(22,163,74,.14)' : 'rgba(220,38,38,.14)',
          border: '1px solid ' + (aberto ? T.ok : T.danger),
          color: aberto ? '#4ADE80' : '#FCA5A5',
          padding: '7px 14px', borderRadius: 999, fontSize: 12, fontWeight: 800,
        }}>
          <span style={{
            width: 7, height: 7, borderRadius: 99, background: aberto ? T.ok : T.danger,
          }} className={aberto ? 'pulse' : ''} />
          {aberto ? 'ABERTO AGORA' : 'FECHADO'}
        </div>
        {!aberto && (
          <div style={{ color: T.muted, fontSize: 12, marginTop: 8 }}>
            {emerg.fechado
              ? (emerg.motivo || 'Fechado temporariamente')
              : (proximaAbertura(cfg.business_hours) ? 'Abrimos ' + proximaAbertura(cfg.business_hours) : '')}
          </div>
        )}
        {neg.endereco ? (
          <div style={{ color: T.muted, fontSize: 12, marginTop: 10 }}>📍 {neg.endereco}</div>
        ) : null}
      </div>

      {banner.ativo && banner.texto ? (
        <div style={{
          background: banner.cor || T.accent, color: '#0E0F12', padding: '11px 16px',
          fontSize: 13, fontWeight: 700, textAlign: 'center',
        }}>{banner.texto}</div>
      ) : null}

      {/* BUSCA + CATEGORIAS */}
      <div className="busca-pad" style={{
        position: 'sticky', top: 0, zIndex: 30, background: T.bg,
        borderBottom: '1px solid ' + T.border,
      }}>
        <input style={Object.assign({}, inp, { marginBottom: 10 })} value={busca}
          onChange={(e) => setBusca(e.target.value)} placeholder="🔍 Buscar no cardápio…" />
        <div className="noscroll" style={{ display: 'flex', gap: 8, overflowX: 'auto' }}>
          <Chip on={!catSel} onClick={() => setCatSel('')}>Tudo</Chip>
          {cats.map((c) => (
            <Chip key={c.id} on={catSel === c.id} onClick={() => setCatSel(catSel === c.id ? '' : c.id)}>
              {c.emoji} {c.nome}
            </Chip>
          ))}
        </div>
      </div>

      {/* DESTAQUES */}
      {!busca && !catSel && destaques.length > 0 && (
        <div style={{ padding: '18px 0 4px' }}>
          <div className="display" style={{ fontSize: 22, padding: '0 16px 10px' }}>⭐ DESTAQUES</div>
          <div className="noscroll" style={{ display: 'flex', gap: 12, overflowX: 'auto', padding: '0 16px 6px' }}>
            {destaques.map((p) => (
              <button key={p.id} onClick={() => setProdSel(p)} style={Object.assign({}, card, {
                minWidth: 168, width: 168, padding: 0, overflow: 'hidden', color: T.text, textAlign: 'left',
              })}>
                <div style={{
                  height: 100, background: p.imagem_url ? 'url(' + p.imagem_url + ') center/cover' : T.surface2,
                  display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 34,
                }}>{p.imagem_url ? '' : '🍔'}</div>
                <div style={{ padding: 11 }}>
                  <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 4 }}>{p.nome}</div>
                  <div style={{ color: T.accent, fontWeight: 800, fontSize: 15 }}>{money(p.preco)}</div>
                </div>
              </button>
            ))}
          </div>
        </div>
      )}

      {/* LISTA */}
      <div className="lista-pad">
        {grupos.length === 0 && (
          <div style={{ textAlign: 'center', color: T.muted, padding: '50px 20px' }}>
            <div style={{ fontSize: 40 }}>🦆</div>
            <div style={{ marginTop: 8, fontSize: 14 }}>Nada encontrado por aqui.</div>
          </div>
        )}
        {grupos.map((g) => (
          <div key={g.cat.id} style={{ marginBottom: 26 }}>
            <div className="display" style={{ fontSize: 24, marginBottom: 10 }}>
              {g.cat.emoji} {g.cat.nome.toUpperCase()}
            </div>
            <div className="grade-produtos">
            {g.itens.map((p) => (
              <button key={p.id} onClick={() => setProdSel(p)} style={Object.assign({}, card, {
                width: '100%', display: 'flex', gap: 12, padding: 12,
                color: T.text, textAlign: 'left', alignItems: 'center',
              })}>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 700, fontSize: 15, marginBottom: 4 }}>{p.nome}</div>
                  {p.descricao ? (
                    <div style={{
                      color: T.muted, fontSize: 12.5, lineHeight: 1.45, marginBottom: 7,
                      display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden',
                    }}>{p.descricao}</div>
                  ) : null}
                  <div style={{ color: T.accent, fontWeight: 800, fontSize: 16 }}>{money(p.preco)}</div>
                </div>
                <div style={{
                  width: 84, height: 84, borderRadius: 10, flexShrink: 0,
                  background: p.imagem_url ? 'url(' + p.imagem_url + ') center/cover' : T.surface2,
                  display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 30,
                }}>{p.imagem_url ? '' : '🍔'}</div>
              </button>
            ))}
            </div>
          </div>
        ))}
      </div>

      <div style={{ textAlign: 'center', color: T.muted, fontSize: 11, padding: '20px 16px 30px' }}>
        {(neg.nome || NOME_NEGOCIO)} • v{APP_VERSION}
      </div>

      {/* BARRA CARRINHO */}
      {cart.count > 0 && (
        <div className="fadeup" style={{
          position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: 60, padding: 12,
          background: T.escuro
            ? 'linear-gradient(0deg,#0E0F12 70%,rgba(14,15,18,0))'
            : 'linear-gradient(0deg,#F3F4F7 70%,rgba(243,244,247,0))',
        }}>
          <button className="barra-carrinho" onClick={() => setVerCarrinho(true)} style={{
            margin: '0 auto', width: '100%', display: 'flex', alignItems: 'center', gap: 12,
            background: T.accent, color: T.escuro ? '#0E0F12' : '#FFFFFF',
            padding: '14px 18px', borderRadius: 14, fontWeight: 800,
          }}>
            <span style={{
              background: T.escuro ? '#0E0F12' : 'rgba(255,255,255,.25)',
              color: T.escuro ? T.accent : '#FFFFFF',
              borderRadius: 9, padding: '4px 10px', fontSize: 14,
            }}>{cart.count}</span>
            <span style={{ flex: 1, textAlign: 'left', fontSize: 15 }}>Ver carrinho</span>
            <span style={{ fontSize: 16 }}>{money(cart.subtotal)}</span>
          </button>
        </div>
      )}

      {prodSel && (
        <ProductModal prod={prodSel} onClose={() => setProdSel(null)} onAdd={cart.add}
          prods={prods} fichas={fichas} insumos={insumos} />
      )}

      <Sheet open={verCarrinho} onClose={() => setVerCarrinho(false)} title="Seu carrinho">
        {cart.items.map((x) => (
          <div key={x.key} style={Object.assign({}, card, { padding: 12, marginBottom: 10 })}>
            <div style={{ display: 'flex', gap: 10 }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontWeight: 700, fontSize: 14 }}>{x.nome}</div>
                {x.adicionais && x.adicionais.length > 0 && (
                  <div style={{ color: T.accent, fontSize: 11.5, marginTop: 3 }}>
                    + {x.adicionais.map((a) => a.nome).join(', ')}
                  </div>
                )}
                {x.obs ? (
                  <div style={{
                    color: T.warn, fontSize: 11.5, marginTop: 4, borderLeft: '2px solid ' + T.warn, paddingLeft: 7,
                  }}>{x.obs}</div>
                ) : null}
                <div style={{ color: T.muted, fontSize: 12, marginTop: 5 }}>{money(x.preco)} un</div>
              </div>
              <div style={{ textAlign: 'right' }}>
                <div style={{ fontWeight: 800, marginBottom: 8 }}>{money(x.preco * x.qtd)}</div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 5, justifyContent: 'flex-end' }}>
                  <button onClick={() => cart.setQtd(x.key, x.qtd - 1)} style={{
                    width: 30, height: 30, borderRadius: 8, background: T.surface2, color: T.text, fontSize: 17,
                  }}>−</button>
                  <span style={{ minWidth: 20, textAlign: 'center', fontWeight: 700 }}>{x.qtd}</span>
                  <button onClick={() => cart.setQtd(x.key, x.qtd + 1)} style={{
                    width: 30, height: 30, borderRadius: 8, background: T.surface2, color: T.text, fontSize: 17,
                  }}>+</button>
                </div>
              </div>
            </div>
          </div>
        ))}
        {cart.items.length === 0 && (
          <div style={{ textAlign: 'center', color: T.muted, padding: 30 }}>Carrinho vazio 🦆</div>
        )}
        {cart.items.length > 0 && (
          <div>
            <div style={{
              display: 'flex', justifyContent: 'space-between', alignItems: 'center', margin: '14px 2px 14px',
            }}>
              <span style={{ color: T.muted, fontSize: 13 }}>Subtotal</span>
              <span className="display" style={{ fontSize: 26, color: T.accent }}>{money(cart.subtotal)}</span>
            </div>
            {!aberto && (
              <div style={{
                background: 'rgba(220,38,38,.12)', border: '1px solid ' + T.danger, color: '#FCA5A5',
                padding: 12, borderRadius: 10, fontSize: 13, marginBottom: 12, textAlign: 'center',
              }}>
                Estamos fechados no momento{emerg.fechado && emerg.motivo ? ' — ' + emerg.motivo : ''}.
              </div>
            )}
            <button disabled={!aberto} onClick={() => { setVerCarrinho(false); setVerCheckout(true); }}
              style={Object.assign({}, btnPrim, { opacity: aberto ? 1 : .45 })}>
              {aberto ? 'Finalizar pedido' : 'Fechado'}
            </button>
            <button onClick={() => { cart.clear(); setVerCarrinho(false); }} style={{
              width: '100%', marginTop: 10, padding: 13, borderRadius: 12,
              background: 'transparent', color: T.muted, fontSize: 13,
            }}>Esvaziar carrinho</button>
          </div>
        )}
      </Sheet>

      {verCheckout && (
        <Checkout cart={cart} cfg={cfg} bairros={bairros}
          onClose={() => setVerCheckout(false)}
          onDone={(ordem) => { cart.clear(); setVerCheckout(false); setSucesso(ordem); }} />
      )}

      {sucesso && <Sucesso ordem={sucesso} cfg={cfg} onClose={() => setSucesso(null)} />}
    </div>
  );
}

function Chip({ on, onClick, children }) {
  return (
    <button onClick={onClick} style={{
      whiteSpace: 'nowrap', padding: '9px 15px', borderRadius: 999, fontSize: 13, fontWeight: 700,
      background: on ? T.accent : T.surface2, color: on ? '#0E0F12' : T.text,
      border: '1px solid ' + (on ? T.accent : T.border),
    }}>{children}</button>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
