// J.A.V.A · Catálogo CULINÁRIO · App principal
//
// Layout revisado no Claude Design (handoff 31/07 — docs/erpIndustrial/
// bot-chat-automatico/catalogobarras). A recriação de lá NÃO tinha o fluxo
// comercial (envio pelo site, bloco ORC do bot, validação de CNPJ/WhatsApp,
// deep links) — isso vem daqui e não deve ser substituído por ela.
const { useState, useMemo, useEffect } = React;

const PRODUCTS = window.JAVA_CUL_PRODUCTS;
const LINES = window.JAVA_CUL_LINES;
const RESTR = window.JAVA_CUL_RESTRICTIONS;
const RESTR_FILTERS = window.JAVA_CUL_RESTR_FILTERS;
const CACAU_BINS = window.JAVA_CUL_CACAU_BINS;
const PESO_BINS = window.JAVA_CUL_PESO_BINS;
const PREPARO_BINS = window.JAVA_CUL_PREPARO_BINS;
const NUTRI = window.JAVA_CUL_NUTRI || {};
const NUTRI_MAP = window.JAVA_CUL_NUTRI_MAP || {};

// Caminhos ABSOLUTOS: a página é servida tanto em /catalogoBarra/java/index.html
// quanto em /catalogoBarra/java (rewrite) — relativo quebraria na segunda forma.
const ASSETS = '/catalogo/java/assets';                        // logos, compartilhados com o varejo
const CAPA = '/catalogoBarra/java/assets/capa-culinarios.jpg'; // foto própria da linha culinária
const PDF_MOBILE = '/catalogoBarra/java/catalogo-pdf-mobile.html?print=1';

// ─── Helpers ───────────────────────────────────────────────
// Peso SEM casa decimal em todo o catálogo (2 kg, 5 kg) — o comprador food
// service raciocina na embalagem cheia; o 2,01/2,05 do cadastro só polui.
function fmtKg(kg) {
  if (kg == null) return '';
  return String(Math.round(Number(kg)));
}
function pesoLabel(size) {
  return `${fmtKg(size.kg)} kg`;
}
function packagingFor(size) {
  if (!size.embalagem) return `embalagem de ${pesoLabel(size)}`;
  return size.embalagem.replace(/[\d.,]+\s*kg/, pesoLabel(size));
}
function cacauLabelOf(p) {
  return p.cacauLabel || `${p.cacau}% cacau`;
}
// Exibição: barras/blocos ganham "BARRAS" na frente. O nome em data.js segue
// espelhando o cadastro do ERP — o prefixo é só de vitrine.
function nameOf(p) {
  return p.line === 'barras' ? `BARRAS ${p.name}` : p.name;
}
function lineLabelOf(id) {
  return LINES.find((l) => l.id === id)?.label || id;
}
// Rótulo nutricional do produto — a etiqueta da barra vale para as gotas do
// mesmo chocolate (ver JAVA_CUL_NUTRI_MAP).
function nutriFor(p) {
  return NUTRI[NUTRI_MAP[p.id]] || null;
}
function restrLabel(id) {
  return RESTR.find((x) => x.id === id)?.label || id;
}
// Branco (cacau null) vai para o fim da ordenação por teor
const cacauOrd = (p) => (p.cacau == null ? 999 : p.cacau);

const isMobile = () =>
  typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(max-width: 700px)').matches;

// No celular o "Baixar PDF" abre a folha A5 retrato; no desktop, as páginas A4
// da própria página (print-only).
function abrirPdf() {
  if (isMobile()) {
    window.open(PDF_MOBILE, '_blank', 'noopener');
    return;
  }
  window.print();
}

// Barra fixa de saída dos painéis — no celular o ✕ do canto some ao rolar.
function BarraVoltar({ onClose }) {
  return (
    <div className="sheet-topbar">
      <button className="btn ghost" type="button" onClick={onClose}>← Voltar ao catálogo</button>
      <button className="close-x" type="button" onClick={onClose} aria-label="Fechar">✕</button>
    </div>);

}

// ─── Top bar ───────────────────────────────────────────────
function TopBar({ variant, onPedidoRapido }) {
  return (
    <header className="topbar interactive-only">
      <div className="brand">
        <img
          src={`${ASSETS}/logo-brown.png`}
          alt="Java chocolates"
          className="brand-logo"
          style={{ filter: variant === 'premium' ? 'invert(1) hue-rotate(180deg)' : 'none' }} />
        <span className="brand-tag">Culinários</span>
      </div>
      <nav>
        <a href="#produtos">Catálogo</a>
        <a href="#comparador">Comparador</a>
        <a href="#contato">Contato</a>
      </nav>
      <div className="actions">
        <button className="btn ghost" type="button" onClick={abrirPdf}>Baixar PDF</button>
        <button className="btn primary" type="button" onClick={onPedidoRapido}>⚡ Orçamento rápido</button>
        <a className="btn ghost" href="#contato">Contato</a>
      </div>
    </header>);

}

// ─── Cover ─────────────────────────────────────────────────
function Cover() {
  return (
    <section className="cover" data-screen-label="01 Capa">
      <div className="cover-text">
        <div className="meta">
          <span>Linha culinária · Food service</span>
          <span>Indústria brasileira</span>
        </div>
        <div>
          <h1 className="cover-h1" style={{ fontFamily: '"Fira Sans"', lineHeight: '0.95', fontWeight: 900 }}>
            Chocolate<br />para <em style={{ fontWeight: 900 }}>produzir</em>.
          </h1>
          <p className="subtitle">
            Barras, gotas e coberturas para confeitarias, cozinhas profissionais e
            indústrias de alimentos.
            <br /><br />
            O mesmo chocolate <i>bean to bar</i> das nossas barrinhas, na escala da
            sua produção.
          </p>
        </div>
        <div className="cover-footnote">
          <span>BARRAS E GOTAS</span>
          <span>Sem glúten</span>
          <span>Sem leite</span>
        </div>
      </div>
      <div className="cover-img">
        <img
          src={CAPA}
          alt="Chocolate derretido escorrendo de uma barra"
          style={{ objectPosition: '50% 42%' }} />
      </div>
    </section>);

}

// ─── Sumário ───────────────────────────────────────────────
function Sumario() {
  return (
    <section id="sumario" className="sumario" data-screen-label="02 Sumário">
      <div className="shell">
        <div className="symbol-bar" aria-label="Certificações e atributos">
          <div className="sym">
            <svg viewBox="0 0 56 56" width="40" height="40" aria-hidden="true">
              <circle cx="28" cy="28" r="26" fill="none" stroke="currentColor" strokeWidth="2" />
              <path d="M20 18 h16 l-2 6 c2 2 3 5 3 9 v9 a4 4 0 0 1 -4 4 h-10 a4 4 0 0 1 -4 -4 v-9 c0 -4 1 -7 3 -9 z" fill="none" stroke="currentColor" strokeWidth="2" strokeLinejoin="round" />
              <line x1="10" y1="46" x2="46" y2="10" stroke="currentColor" strokeWidth="2.5" />
            </svg>
            <span>Sem leite</span>
          </div>
          <div className="sym">
            <svg viewBox="0 0 56 56" width="40" height="40" aria-hidden="true">
              <circle cx="28" cy="28" r="26" fill="none" stroke="currentColor" strokeWidth="2" />
              <path d="M28 14 v28 M22 20 c4 2 6 6 6 10 M34 20 c-4 2 -6 6 -6 10 M22 28 c4 2 6 6 6 10 M34 28 c-4 2 -6 6 -6 10" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
              <line x1="10" y1="46" x2="46" y2="10" stroke="currentColor" strokeWidth="2.5" />
            </svg>
            <span>Sem glúten</span>
          </div>
          <div className="sym">
            <svg viewBox="0 0 56 56" width="40" height="40" aria-hidden="true">
              <circle cx="28" cy="28" r="26" fill="none" stroke="currentColor" strokeWidth="2" />
              <path d="M28 18 c-8 0 -12 6 -12 12 c0 6 4 10 12 10 c8 0 12 -4 12 -10 c0 -6 -4 -12 -12 -12 z M28 18 v22 M21 28 c0 -3 2 -6 7 -6 M35 28 c0 -3 -2 -6 -7 -6" fill="none" stroke="currentColor" strokeWidth="2" strokeLinejoin="round" />
            </svg>
            <span>Vegano</span>
          </div>
        </div>
      </div>
    </section>);

}

// ─── Filters ───────────────────────────────────────────────
function Filters({ tipo, setTipo, line, setLine, cacau, setCacau, peso, setPeso, preparo, setPreparo, restr, setRestr, onlyBest, setOnlyBest, count }) {
  // "Tipo" separa chocolate nobre de cobertura fracionada — é a primeira
  // pergunta de quem compra culinário, antes até do formato.
  const tipos = [
    { id: 'all', label: 'todos' },
    { id: 'nobre', label: 'chocolate nobre' },
    { id: 'coberturas', label: 'coberturas fracionadas' }];
  // Coberturas têm seção própria — o filtro de formato cobre só o que está na grade.
  const formatos = LINES.filter((l) => l.id !== 'coberturas');

  return (
    <div className="filters">
      <div className="grp">
        <span className="grp-label">Destaques</span>
        <button
          className={`chip chip-best ${onlyBest ? 'active' : ''}`}
          onClick={() => setOnlyBest(!onlyBest)}>
          ★ mais vendidos
        </button>
      </div>
      <div className="grp">
        <span className="grp-label">Tipo</span>
        {tipos.map((t) =>
        <button
          key={t.id}
          className={`chip ${tipo === t.id ? 'active' : ''}`}
          onClick={() => {setTipo(t.id);setLine(null);}}>
            {t.label}
          </button>
        )}
      </div>
      <div className="grp">
        <span className="grp-label">Formato</span>
        <button className={`chip ${!line ? 'active' : ''}`} onClick={() => setLine(null)}>todos</button>
        {formatos.map((l) =>
        <button
          key={l.id}
          className={`chip ${line === l.id ? 'active' : ''}`}
          onClick={() => setLine(l.id)}>
            {l.label.toLowerCase()}
          </button>
        )}
      </div>
      <div className="grp">
        <span className="grp-label">% cacau</span>
        {CACAU_BINS.map((b) =>
        <button key={b.id} className={`chip ${cacau === b.id ? 'active' : ''}`} onClick={() => setCacau(b.id)}>
            {b.label}
          </button>
        )}
      </div>
      <div className="grp">
        <span className="grp-label">Embalagem</span>
        {PESO_BINS.map((b) =>
        <button key={b.id} className={`chip ${peso === b.id ? 'active' : ''}`} onClick={() => setPeso(b.id)}>
            {b.label}
          </button>
        )}
      </div>
      <div className="grp">
        <span className="grp-label">Preparo</span>
        {PREPARO_BINS.map((b) =>
        <button key={b.id} className={`chip ${preparo === b.id ? 'active' : ''}`} onClick={() => setPreparo(b.id)}>
            {b.label}
          </button>
        )}
      </div>
      <div className="grp">
        <span className="grp-label">Restrições</span>
        {RESTR_FILTERS.map((f) =>
        <button
          key={f.id}
          className={`chip ${restr.includes(f.id) ? 'active' : ''}`}
          onClick={() => setRestr(restr.includes(f.id) ? restr.filter((x) => x !== f.id) : [...restr, f.id])}>
            {f.label}
          </button>
        )}
      </div>
      <button className="reset" onClick={() => {setTipo('all');setLine(null);setCacau('all');setPeso('all');setPreparo('all');setRestr([]);setOnlyBest(false);}}>
        ↺ limpar  ·  {count} mostrados
      </button>
    </div>);

}

// ─── Card ──────────────────────────────────────────────────
function Card({ p, onOpen, compareIds, toggleCompare, orcamentoIds, toggleOrcamento }) {
  const isCompared = compareIds.includes(p.id);
  const isInOrc = orcamentoIds.includes(p.id);
  return (
    <div className="card" onClick={() => onOpen(p)} role="button" tabIndex={0}
    onKeyDown={(e) => {if (e.key === 'Enter' || e.key === ' ') {e.preventDefault();onOpen(p);}}}>
      <div
        className={`photo ${p.img ? '' : 'placeholder'}`}
        style={p.placeholder ? { '--placeholder-tone': p.placeholder.tone } : {}}>

        {p.img ?
        <img src={p.img} alt={p.name} loading="lazy" /> :
        <div className="ph-label">
          {p.placeholder?.label || p.name}
          <em className="ph-note">foto em breve</em>
        </div>}
        {p.status === 'novo' && <div className="badge-new">Novo</div>}
        {p.bestseller && <div className="badge-best" title="Mais vendido">★</div>}
        {p.temperagem === false && <div className="badge-preparo">sem temperagem</div>}
      </div>

      <div className="card-actions">
        <button
          className={`mini-btn ${isCompared ? 'active' : ''}`}
          onClick={(e) => {e.stopPropagation();toggleCompare(p.id);}}
          title="Comparar">
          {isCompared ? '✓' : '⇆'} comparar
        </button>
        <button
          className={`mini-btn primary ${isInOrc ? 'active' : ''}`}
          onClick={(e) => {e.stopPropagation();toggleOrcamento(p.id);}}
          title="Adicionar ao orçamento">
          {isInOrc ? '✓ no orçamento' : '+ orçamento'}
        </button>
      </div>

      <div>
        <div className="meta">
          <span className="pct">{cacauLabelOf(p)}</span>
        </div>
        <h3 style={{ marginTop: 6 }}>{nameOf(p)}</h3>
        <div className="family">{p.family}</div>
        <div className="sizes">
          {p.sizes.map((s) =>
          <span className="sz" key={s.label}>{pesoLabel(s)}</span>
          )}
        </div>
        {p.usos &&
        <div className="usos">
          {p.usos.slice(0, 3).map((u) => <span className="uso" key={u}>{u}</span>)}
        </div>
        }
      </div>
    </div>);

}

function GradeProdutos({ items, onOpen, cmpIds, toggleCmp, orcIds, toggleOrc, style }) {
  return (
    <div className="grid-products" style={style}>
      {items.map((p) =>
      <Card key={p.id} p={p} onOpen={onOpen}
      compareIds={cmpIds} toggleCompare={toggleCmp}
      orcamentoIds={orcIds} toggleOrcamento={toggleOrc} />
      )}
    </div>);

}

// ─── Sheet (detail) ────────────────────────────────────────
function Sheet({ product, onClose, onCompare, compareIds, onOrcamento, orcamentoIds, onVerOrcamento }) {
  const p = product;
  useEffect(() => {
    const onEsc = (e) => e.key === 'Escape' && onClose();
    window.addEventListener('keydown', onEsc);
    document.body.style.overflow = 'hidden';
    return () => {window.removeEventListener('keydown', onEsc);document.body.style.overflow = '';};
  }, []);
  const placeholderStyle = p.placeholder ? { '--placeholder-tone': p.placeholder.tone } : {};
  const nutri = nutriFor(p);

  return (
    <div className="sheet-backdrop interactive-only" onClick={onClose}>
      <aside className="sheet" onClick={(e) => e.stopPropagation()}>
        <BarraVoltar onClose={onClose} />
        <div className="sheet-head" style={placeholderStyle}>
          {p.img ? <img src={p.img} alt="" /> : <div className="placeholder">{p.placeholder?.label || p.name}</div>}
        </div>
        <div className="sheet-body">
          <div>
            <div className="pct">{cacauLabelOf(p)} · {p.family}</div>
            <h2>{nameOf(p)}</h2>
          </div>

          <p className="desc">{p.description}</p>

          <div className="ficha-grid">
            <div className="ficha-item">
              <div className="ficha-k">Preparo</div>
              <div className="ficha-v">{p.temperagem === false ? 'Não precisa temperar' : 'Requer temperagem'}</div>
            </div>
            <div className="ficha-item">
              <div className="ficha-k">Formato</div>
              <div className="ficha-v">{lineLabelOf(p.line)}</div>
            </div>
            {p.origin &&
            <div className="ficha-item">
              <div className="ficha-k">Origem</div>
              <div className="ficha-v">{p.origin}</div>
            </div>
            }
          </div>

          {p.usos &&
          <div>
            <div className="block-title">Aplicações</div>
            <div className="restrictions-list">
              {p.usos.map((u) => <span className="r" key={u}>{u}</span>)}
            </div>
          </div>
          }

          <div>
            <div className="block-title">Embalagens e códigos</div>
            <div className="skus">
              {p.sizes.map((s) =>
              <div className="sku-row" key={s.label}>
                  <span className="label">{pesoLabel(s)}</span>
                  <span className="pack">{packagingFor(s)}</span>
                  <span className="gram"><span className="cod">{s.sku}</span></span>
                </div>
              )}
            </div>
          </div>

          <div>
            <div className="block-title">Restrições</div>
            <div className="restrictions-list">
              {p.restrictions.map((r) =>
              <span className="r" key={r}>{restrLabel(r)}</span>
              )}
            </div>
          </div>

          {nutri ?
          <>
            <div>
              <div className="block-title">Ingredientes</div>
              <p className="desc" style={{ fontSize: 14, margin: 0 }}>{nutri.ingredientes}</p>
              <div style={{ fontSize: 12, color: 'var(--fg-soft)', marginTop: 8, lineHeight: 1.6 }}>
                <div>Alérgicos: {nutri.alergicos}</div>
                <div>Não contém: {nutri.naoContem}</div>
              </div>
            </div>

            <div>
              <div className="block-title">Derretimento e temperagem</div>
              <div className="ficha-grid">
                <div className="ficha-item">
                  <div className="ficha-k">Derretimento</div>
                  <div className="ficha-v">{nutri.temper.derretimento}</div>
                </div>
                <div className="ficha-item">
                  <div className="ficha-k">Temperagem</div>
                  <div className="ficha-v">{nutri.temper.temperagem}</div>
                </div>
                <div className="ficha-item">
                  <div className="ficha-k">Trabalho</div>
                  <div className="ficha-v">{nutri.temper.trabalho}</div>
                </div>
              </div>
            </div>

            <div>
              <div className="block-title">Informação nutricional</div>
              <div className="nutri">
                <div style={{ fontSize: 11, color: 'var(--fg-soft)', marginBottom: 10 }}>{nutri.porcao}</div>
                <table>
                  <thead>
                    <tr>
                      <th>Quantidade por porção</th>
                      <th style={{ textAlign: 'right' }}>100 g</th>
                      <th style={{ textAlign: 'right' }}>%VD*</th>
                    </tr>
                  </thead>
                  <tbody>
                    {nutri.rows.map((r) =>
                    <tr key={r[0]}>
                        <td>{r[0]}</td>
                        <td className="val">{r[1]}</td>
                        <td className="val">{r[2]}</td>
                      </tr>
                    )}
                  </tbody>
                </table>
                <div style={{ fontSize: 10, color: 'var(--fg-soft)', marginTop: 10, lineHeight: 1.5 }}>
                  * Valores diários com base em uma dieta de 2.000 kcal ou 8.400 kJ.
                  {' '}** Valor diário não especificado.{nutri.nota ? ` ${nutri.nota}` : ''}
                </div>
              </div>
            </div>
          </> :

          <div>
            <div className="block-title">Informação nutricional</div>
            <div style={{ padding: '16px', border: '1px dashed var(--rule)', borderRadius: 4, color: 'var(--fg-soft)', fontSize: 13, lineHeight: 1.5 }}>
              Rótulo deste item ainda não recebido. Peça a ficha completa pelo WhatsApp
              comercial ou consulte a embalagem.
            </div>
          </div>
          }

          <div className="sheet-actions">
            <button className="btn" onClick={() => onCompare(p.id)}>
              {compareIds.includes(p.id) ? '✓ no comparador' : '⇆ comparar'}
            </button>
            <button className="btn primary" onClick={() => onOrcamento(p.id)}>
              {orcamentoIds.includes(p.id) ? '✓ no orçamento' : '+ adicionar ao orçamento'}
            </button>
          </div>
        </div>
        {/* Saídas da ficha (celular): voltar ao catálogo OU ir direto ao orçamento —
            quem chegou aqui pelo link "ver no catálogo" precisa do caminho de volta. */}
        <div className="fab-dupla">
          <button className="fab fab-catalogo" type="button" onClick={onClose}>
            📖 Ver catálogo
          </button>
          {onVerOrcamento &&
            <button className="fab fab-orcamento" type="button" onClick={onVerOrcamento}
              title="Voltar ao orçamento — suas quantidades ficam guardadas">
              🧾 Ver orçamento
            </button>
          }
        </div>
      </aside>
    </div>);

}

// ─── Comparator ────────────────────────────────────────────
function Comparator({ ids, setIds }) {
  const items = ids.map((id) => PRODUCTS.find((p) => p.id === id)).filter(Boolean);
  const slots = Math.max(3, items.length);

  return (
    <section id="comparador" className="comparator interactive-only" data-screen-label="Comparador">
      <div className="shell">
        <h2>Comparador</h2>
        <p className="hint">Adicione produtos pelo botão <strong>⇆ comparar</strong> em cada card. Compare até 4 lado a lado.</p>

        <div className="table" style={{ '--cols': slots }}>
          <div className="cell field" style={{ background: 'transparent', borderBottom: '1px solid var(--rule)' }}> </div>
          {Array.from({ length: slots }).map((_, i) => {
            const p = items[i];
            if (!p) return (
              <div className="empty-slot" key={'empty' + i} style={{ borderBottom: '1px solid var(--rule)', height: '100%' }}>
                Slot vazio
              </div>);

            return (
              <div key={p.id} className="cell" style={{ padding: 0, position: 'relative' }}>
                <button className="remove" onClick={() => setIds(ids.filter((x) => x !== p.id))}>×</button>
                {p.img ?
                <img src={p.img} alt="" style={{ aspectRatio: '4/3', width: '100%', objectFit: 'cover' }} /> :
                <div className="photo ph" style={{ aspectRatio: '4/3', display: 'flex', alignItems: 'center', justifyContent: 'center', background: p.placeholder?.tone, color: 'var(--cream)', fontFamily: 'var(--font-display)', fontSize: 16, padding: 16, textAlign: 'center' }}>
                      {p.placeholder?.label || p.name}
                    </div>}
              </div>);

          })}

          {comparatorRow('Produto', items, slots, (p) =>
          <div>
              <div style={{ fontFamily: 'var(--font-display)', fontSize: 20, fontWeight: 500 }}>{nameOf(p)}</div>
              <div style={{ fontSize: 12, color: 'var(--fg-soft)', marginTop: 2 }}>{p.family}</div>
            </div>
          )}
          {comparatorRow('% Cacau', items, slots, (p) => <span style={{ fontFamily: 'var(--font-display)', fontSize: 22 }}>{p.cacauLabel || `${p.cacau}%`}</span>)}
          {comparatorRow('Formato', items, slots, (p) => lineLabelOf(p.line))}
          {comparatorRow('Preparo', items, slots, (p) => p.temperagem === false ? 'Não precisa temperar' : 'Requer temperagem')}
          {comparatorRow('Embalagens', items, slots, (p) =>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
              {p.sizes.map((s) =>
            <div key={s.label} style={{ fontSize: 12 }}>
                  <strong>{pesoLabel(s)}</strong> · <span style={{ color: 'var(--fg-soft)', fontFamily: 'ui-monospace, monospace', fontSize: 11 }}>{s.sku}</span>
                </div>
            )}
            </div>
          )}
          {comparatorRow('Aplicações', items, slots, (p) =>
          <div style={{ fontSize: 12, color: 'var(--fg-soft)' }}>{(p.usos || []).join(' · ')}</div>
          )}
          {comparatorRow('Restrições', items, slots, (p) =>
          <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
              {p.restrictions.map((r) =>
            <span key={r} style={{ fontSize: 11, padding: '3px 8px', background: 'var(--accent)', color: 'var(--bg)', borderRadius: 100 }}>{restrLabel(r)}</span>
            )}
            </div>
          )}
        </div>
      </div>
    </section>);

}
function comparatorRow(label, items, slots, render) {
  return (
    <React.Fragment>
      <div className="cell field">{label}</div>
      {Array.from({ length: slots }).map((_, i) => {
        const p = items[i];
        return <div className="cell" key={label + '-' + i}>{p ? render(p) : ''}</div>;
      })}
    </React.Fragment>);

}

// ─── Orçamento (cart + send) ───────────────────────────────
const ORC_GRUPOS = [
  { id: 'barras', label: 'Barras' },
  { id: 'gotas', label: 'Gotas' },
  { id: 'coberturas', label: 'Coberturas' }];

function OrcamentoModal({ items, qtyMap, setQty, onRemove, onClose, message, setMessage, onVerProduto }) {
  const [cnpj, setCnpj] = useState('');
  const [zap, setZap] = useState('');            // WhatsApp do cliente (obrigatório no P0)
  const [enviando, setEnviando] = useState(false);
  const [enviado, setEnviado] = useState(null);   // { numero } após o backend confirmar
  const [fallbackWa, setFallbackWa] = useState(false); // número não validado → wa.me manual
  const [formError, setFormError] = useState('');
  const [toast, setToast] = useState('');
  const [gruposFechados, setGruposFechados] = useState({});
  const cnpjRef = React.useRef(null);
  const zapRef = React.useRef(null);

  useEffect(() => { if (!toast) return; const t = setTimeout(() => setToast(''), 2400); return () => clearTimeout(t); }, [toast]);

  const flagMissing = () => {
    if (!temItens) {
      setFormError('Escolha a quantidade de pelo menos um produto para pedir o orçamento.');
      return;
    }
    if (!zapOk) setFormError('Informe o WhatsApp com DDD — é nele que o orçamento chega.');
    else setFormError('Informe um CNPJ válido (14 dígitos) — o endereço sai do cadastro.');
    const target = !zapOk ? zapRef.current : cnpjRef.current;
    if (target) { try { target.focus({ preventScroll: false }); } catch { target.focus(); } }
  };
  const formatCnpj = (v) => {
    const d = v.replace(/\D/g, '').slice(0, 14);
    if (d.length <= 2) return d;
    if (d.length <= 5) return d.replace(/^(\d{2})(\d+)/, '$1.$2');
    if (d.length <= 8) return d.replace(/^(\d{2})(\d{3})(\d+)/, '$1.$2.$3');
    if (d.length <= 12) return d.replace(/^(\d{2})(\d{3})(\d{3})(\d+)/, '$1.$2.$3/$4');
    return d.replace(/^(\d{2})(\d{3})(\d{3})(\d{4})(\d+)/, '$1.$2.$3/$4-$5');
  };
  const cnpjDigits = cnpj.replace(/\D/g, '');
  const cnpjOk = cnpjDigits.length === 14;
  const formatZap = (v) => {
    const d = v.replace(/\D/g, '').slice(0, 13);
    const semDdi = (d.length >= 12 && d.startsWith('55')) ? d.slice(2) : d;
    if (semDdi.length <= 2) return semDdi;
    if (semDdi.length <= 6) return semDdi.replace(/^(\d{2})(\d+)/, '($1) $2');
    if (semDdi.length <= 10) return semDdi.replace(/^(\d{2})(\d{4})(\d+)/, '($1) $2-$3');
    return semDdi.replace(/^(\d{2})(\d{5})(\d+)/, '($1) $2-$3');
  };
  const zapDigits = (() => {
    let d = zap.replace(/\D/g, '');
    if ((d.length === 12 || d.length === 13) && d.startsWith('55')) d = d.slice(2);
    return d;
  })();
  const zapOk = zapDigits.length === 10 || zapDigits.length === 11;
  const temItens = items.some((p) => p.sizes.some((sz) => ((qtyMap[p.id] && qtyMap[p.id][sz.label]) | 0) > 0));
  const formOk = zapOk && cnpjOk && temItens;

  // ─── Envio pelo PRÓPRIO SITE (Plano 0): o backend valida o número (conversa
  // recente = janela de 24h aberta), cria o orçamento no ERP e devolve o PDF no
  // WhatsApp informado. Sem conversa recente → fallback wa.me com a mensagem pronta.
  const enviarPeloSite = async () => {
    if (!formOk) { flagMissing(); return; }
    setEnviando(true); setFormError(''); setFallbackWa(false);
    try {
      // Culinários são vendidos por UNIDADE de embalagem (barra/saco) — a
      // quantidade digitada já é o número de embalagens (un = 1).
      const itens = [];
      items.forEach((p) => p.sizes.forEach((s) => {
        const q = getQty(p.id, s.label);
        if (!q) return;
        const codigo = s.skuUnidade || s.sku;
        if (codigo) itens.push({ sku: codigo, quantidade: q * (s.un || 1) });
      }));
      const res = await fetch('/api/public/orcamento', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          slug: 'java',
          whatsapp: '55' + zapDigits,
          cnpj: cnpjDigits,
          itens,
          observacoes: message.trim() || undefined,
        }),
      });
      const json = await res.json().catch(() => ({}));
      if (res.ok && json.ok) {
        setEnviado({ numero: json.numeroPedido || null });
      } else if (res.status === 409) {
        setFallbackWa(true);
        setFormError(json.message || 'Não encontramos uma conversa recente com esse WhatsApp. Envie a mensagem pronta pelo botão verde — respondemos por lá.');
      } else {
        setFallbackWa(true);
        setFormError(json.message || 'Não foi possível gerar o orçamento agora. Envie pelo botão verde que atendemos por lá.');
      }
    } catch {
      setFallbackWa(true);
      setFormError('Falha de conexão. Envie pelo botão verde que atendemos por lá.');
    } finally {
      setEnviando(false);
    }
  };

  useEffect(() => {
    const onEsc = (e) => e.key === 'Escape' && onClose();
    window.addEventListener('keydown', onEsc);
    document.body.style.overflow = 'hidden';
    return () => {window.removeEventListener('keydown', onEsc);document.body.style.overflow = '';};
  }, []);

  const getQty = (pid, label) => {
    const m = qtyMap[pid];
    if (!m || typeof m !== 'object') return 0;
    return m[label] | 0;
  };
  const productTotal = (p) => p.sizes.reduce((sum, s) => sum + getQty(p.id, s.label), 0);
  const nSelecionados = items.reduce((n, p) => n + p.sizes.filter((sz) => getQty(p.id, sz.label) > 0).length, 0);
  // Peso total do pedido — em food service o cliente raciocina em kg, não em peças
  const pesoTotal = items.reduce(
    (kg, p) => kg + p.sizes.reduce((s, sz) => s + getQty(p.id, sz.label) * (sz.kg || 0), 0),
    0
  );

  // Itens ordenados por teor de cacau (branco no fim) e repartidos nas três
  // categorias expansíveis — com 17 produtos no pedido rápido, a lista corrida
  // era longa demais no celular.
  const ordenados = useMemo(() => [...items].sort((a, b) => cacauOrd(a) - cacauOrd(b)), [items]);
  const grupos = ORC_GRUPOS
    .map((g) => {
      const rows = ordenados.filter((p) => p.line === g.id);
      const comQtd = rows.filter((p) => productTotal(p) > 0).length;
      const aberto = !gruposFechados[g.id];
      return {
        ...g, rows, aberto,
        caret: aberto ? '▾' : '▸',
        tip: aberto ? 'Toque para recolher' : 'Toque para expandir',
        meta: `${rows.length} ${rows.length === 1 ? 'produto' : 'produtos'}${comQtd > 0 ? ` · ${comQtd} com quantidade` : ''}`,
      };
    })
    .filter((g) => g.rows.length > 0);
  const toggleGrupo = (id) => setGruposFechados((f) => ({ ...f, [id]: !f[id] }));

  const buildMessage = () => {
    const lines = [];
    lines.push('Olá! Gostaria de orçamento da linha CULINÁRIA para os seguintes itens:');
    lines.push('');
    if (cnpj) {
      lines.push('Dados para emissão:');
      lines.push(`CNPJ: ${cnpj}`);
      lines.push('');
    }
    const orcPairs = [];
    ordenados.forEach((p) => {
      p.sizes.forEach((s) => {
        const qty = getQty(p.id, s.label);
        if (!qty) return;
        lines.push(`• ${qty} × ${nameOf(p)} — ${cacauLabelOf(p)} — ${packagingFor(s)} — cód. ${s.sku}`);
        const codigoOrc = s.skuUnidade || s.sku;
        if (codigoOrc) orcPairs.push(`${codigoOrc} x${qty * (s.un || 1)}`);
      });
    });
    if (pesoTotal > 0) { lines.push(''); lines.push(`Peso total aproximado: ${fmtKg(pesoTotal)} kg`); }
    if (message.trim()) {lines.push('');lines.push('Observações:');lines.push(message.trim());}
    // Bloco estruturado p/ o bot criar o orçamento no ERP sem interpretação de
    // texto livre (parse determinístico por SKU). Não remover.
    if (orcPairs.length) {
      lines.push('');
      lines.push('Código do pedido (uso interno — não apague):');
      lines.push(`ORC: ${orcPairs.join('; ')} | CNPJ ${cnpjDigits}`);
    }
    lines.push('');
    lines.push('— Pedido gerado pelo catálogo culinário Java 2026');
    return lines.join('\n');
  };

  const waUrl = `https://wa.me/5531973267809?text=${encodeURIComponent(buildMessage())}`;

  // Copia o texto antes de abrir — evita perder a mensagem se o WhatsApp
  // não abrir (preview embarcado, popup bloqueado etc.).
  const tryCopy = async () => {
    try {await navigator.clipboard.writeText(buildMessage());} catch {}
  };
  const copyMsg = async () => {
    try {await navigator.clipboard.writeText(buildMessage());setToast('Mensagem copiada para a área de transferência.');}
    catch {setToast('Não foi possível copiar — selecione o texto manualmente.');}
  };

  return (
    <div className="sheet-backdrop interactive-only" onClick={onClose}>
      <aside className="sheet sheet-wide" onClick={(e) => e.stopPropagation()}>
        <BarraVoltar onClose={onClose} />
        <div className="sheet-body" style={{ padding: 'clamp(24px, 3vw, 40px)' }}>
          <div>
            <div className="block-title" style={{ marginBottom: 6 }}>
              Orçamento culinário · {nSelecionados} {nSelecionados === 1 ? 'item no pedido' : 'itens no pedido'}
              {pesoTotal > 0 && ` · ${fmtKg(pesoTotal)} kg`}
            </div>
            <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 32, fontWeight: 500, margin: 0 }}>Pedir orçamento</h2>
          </div>

          <p style={{ color: 'var(--fg-soft)', fontSize: 14, marginTop: 8 }}>
            Os itens estão em três categorias — barras, gotas e coberturas — ordenados por
            teor de cacau. Ajuste as quantidades (em embalagens), informe seu WhatsApp e CNPJ
            e clique em <strong>Receber orçamento no WhatsApp</strong> — o documento em PDF
            chega na sua conversa em instantes, com os preços da sua tabela.
          </p>

          {items.length === 0 &&
          <div style={{ padding: '40px 16px', textAlign: 'center', border: '1px dashed var(--rule)', borderRadius: 4, color: 'var(--fg-soft)' }}>
              Nenhum produto adicionado ainda.<br />
              Adicione pelos cards usando <strong>+ orçamento</strong>.
            </div>
          }

          {grupos.map((g) =>
          <div className="orc-grupo" key={g.id}>
            <button type="button" className="orc-grupo-head" onClick={() => toggleGrupo(g.id)} title={g.tip}>
              <span className="orc-grupo-esq">
                <span className="orc-grupo-caret">{g.caret}</span>
                <span className="orc-grupo-label">{g.label}</span>
                <span className="orc-grupo-tip">{g.tip}</span>
              </span>
              <span className="orc-grupo-meta">{g.meta}</span>
            </button>

            {g.aberto &&
            <div className="orc-list" style={{ border: 'none' }}>
              {g.rows.map((p) => {
                const total = productTotal(p);
                const hasMulti = p.sizes.length > 1;
                const noneSelected = total === 0;
                return (
                <div className="orc-row" key={p.id}>
                  <div className="orc-thumb"
                    style={p.placeholder ? { background: p.placeholder.tone } : {}}>
                    {p.img ?
                      <img src={p.img} alt="" /> :
                      <span style={{ color: 'var(--cream)', fontSize: 11, padding: 6, textAlign: 'center' }}>{p.placeholder?.label}</span>}
                  </div>
                  <div className="orc-info">
                    <div className="orc-name">{nameOf(p)}</div>
                    {onVerProduto &&
                      <button className="orc-vercatalogo" type="button"
                        onClick={() => onVerProduto(p)}
                        title="Ver detalhes deste produto no catálogo">
                        ver no catálogo →
                      </button>
                    }
                    <div className="orc-sub">{cacauLabelOf(p)}</div>
                  </div>
                  <button className="orc-remove" onClick={() => onRemove(p.id)} title="Remover">✕</button>

                  <div className="orc-sizes">
                    {hasMulti &&
                      <div className="orc-sizes-hint">Ajuste a quantidade de cada embalagem:</div>
                    }
                    {p.sizes.map((s) => {
                      const qty = getQty(p.id, s.label);
                      const selected = qty > 0;
                      return (
                        <div className={`orc-size-row ${selected ? 'is-on' : ''}`} key={s.label}>
                          <span className="orc-size-label">
                            <span className="orc-size-line"><strong>{pesoLabel(s)}</strong></span>
                            <em className="orc-size-pack">
                              {packagingFor(s)}
                              {qty > 0 && ` · ${fmtKg(qty * s.kg)} kg`}
                            </em>
                          </span>
                          <div className="qty">
                            <button
                              type="button"
                              onClick={() => { setQty(p.id, s.label, Math.max(0, qty - 1)); if (formError) setFormError(''); }}>−</button>
                            <input
                              type="number"
                              value={qty}
                              min={0}
                              onChange={(e) => {
                                const v = Math.max(0, parseInt(e.target.value || '0', 10) || 0);
                                setQty(p.id, s.label, v);
                                if (formError) setFormError('');
                              }} />
                            <button
                              type="button"
                              onClick={() => { setQty(p.id, s.label, qty + 1); if (formError) setFormError(''); }}>+</button>
                          </div>
                        </div>);

                    })}
                    {noneSelected &&
                      <div className="orc-size-warn">Sem quantidade — este produto não entra no orçamento.</div>
                    }
                  </div>
                </div>);

              })}
            </div>
            }
          </div>
          )}

          {items.length > 0 &&
          <>
              <div className="orc-form-grid">
                <label className="orc-field">
                  <span className="orc-field-label">Seu WhatsApp (com DDD) <em>*</em></span>
                  <input
                  type="tel"
                  className={`orc-input ${(zap && !zapOk) || (formError && !zapOk) ? 'invalid' : ''}`}
                  placeholder="(31) 99999-9999"
                  inputMode="tel"
                  ref={zapRef}
                  value={zap}
                  onChange={(e) => { setZap(formatZap(e.target.value)); if (formError) setFormError(''); }}
                  required />
                  {zap && !zapOk && <span className="orc-hint">Número com DDD (10 ou 11 dígitos).</span>}
                  {!zap && formError && !zapOk && <span className="orc-hint">Campo obrigatório — o orçamento chega nele.</span>}
                </label>
                <label className="orc-field">
                  <span className="orc-field-label">CNPJ <em>*</em></span>
                  <input
                  type="text"
                  className={`orc-input ${(cnpj && !cnpjOk) || (formError && !cnpjOk) ? 'invalid' : ''}`}
                  placeholder="00.000.000/0000-00"
                  inputMode="numeric"
                  ref={cnpjRef}
                  value={cnpj}
                  onChange={(e) => { setCnpj(formatCnpj(e.target.value)); if (formError) setFormError(''); }}
                  required />
                  {cnpj && !cnpjOk && <span className="orc-hint">CNPJ deve ter 14 dígitos.</span>}
                  {!cnpj && formError && !cnpjOk && <span className="orc-hint">Campo obrigatório.</span>}
                </label>
              </div>

              <div className="block-title" style={{ marginTop: 8 }}>Observações (opcional)</div>
              <textarea
              className="orc-textarea"
              value={message}
              onChange={(e) => setMessage(e.target.value)} />


              <div className="block-title">Mensagem que será enviada</div>
              <pre className="orc-preview">{buildMessage()}</pre>

              {formError &&
              <div className="orc-error" role="alert" aria-live="assertive">
                <span className="orc-error-icon" aria-hidden="true">!</span>
                <span>{formError}</span>
              </div>
              }

              {enviado ?
              <div className="orc-error" role="status" aria-live="polite"
                style={{ background: '#EBF7EE', borderColor: '#3E7C4F', color: '#245231' }}>
                <span aria-hidden="true">✅</span>
                <span>
                  <strong>Orçamento{enviado.numero ? ` nº ${enviado.numero}` : ''} gerado!</strong>{' '}
                  O PDF chega no seu WhatsApp em instantes. Qualquer ajuste, é só responder por lá.
                </span>
              </div> :
              <div className="orc-actions">
                <button
                className={`btn whats ${!formOk || enviando ? 'is-disabled' : ''}`}
                type="button"
                onClick={() => { if (enviando) return; enviarPeloSite(); }}
                aria-disabled={!formOk || enviando}
                title={!formOk ? 'Preencha WhatsApp e CNPJ' : 'O orçamento em PDF chega no seu WhatsApp'}>
                  {enviando ? 'Gerando orçamento…' : 'Receber orçamento no WhatsApp'} <span>→</span>
                </button>
                {fallbackWa &&
                <a
                className="btn whats"
                href={waUrl}
                target="_blank"
                rel="noopener noreferrer"
                onClick={() => { tryCopy(); }}
                title="Abre o WhatsApp com a mensagem pronta">
                  Enviar mensagem pronta pelo WhatsApp <span>→</span>
                </a>
                }
                <button className="btn ghost" onClick={copyMsg}>
                  Copiar mensagem
                </button>
              </div>
              }
            </>
          }
        </div>
        {toast &&
        <div className="orc-toast" role="status" aria-live="polite">{toast}</div>
        }
        {/* Item 2: quem abre o link ?rapido=1 no celular cai direto aqui e não
            percebe que existe catálogo atrás. Fechar preserva as quantidades. */}
        <button className="fab fab-catalogo interactive-only" type="button" onClick={onClose}
          title="Ver o catálogo — suas quantidades ficam guardadas">
          📖 Ver catálogo
        </button>
      </aside>
    </div>);

}

// ─── Contato ───────────────────────────────────────────────
function Contato() {
  return (
    <section id="contato" className="contato" data-screen-label="Contato">
      <div className="shell">
        <div>
          <div className="over" style={{ color: 'rgba(255,253,237,0.6)' }}>Confeitarias · Food Service · Indústria</div>
          <h2 style={{ fontFamily: "\"Fira Sans\"", fontWeight: 900 }}>Faça seu<br />pedido.</h2>
          <p className="lead">
            Atendemos confeitarias, cozinhas profissionais, padarias e indústrias de
            alimentos em todo o Brasil. Pedido mínimo, condições e prazos sob consulta.
          </p>
          <div className="info">
            <div className="ln"><span className="lbl">WhatsApp</span><span>+55 31 97326-7809</span></div>
            <div className="ln"><span className="lbl">E-mail</span><span>comercial@javachocolates.com.br</span></div>
            <div className="ln"><span className="lbl">Site</span><span>www.javachocolates.com.br</span></div>
            <div className="ln"><span className="lbl">Fábrica</span><span>Belo Horizonte · Minas Gerais</span></div>
          </div>
          <div className="actions">
            <a className="btn primary" href="https://wa.me/5531973267809?text=Vim%20do%20cat%C3%A1logo%20culin%C3%A1rio%20e%20gostaria%20de%20pedir%20um%20or%C3%A7amento." target="_blank" rel="noreferrer">
              Pedir orçamento pelo WhatsApp <span>→</span>
            </a>
            <a className="btn" href="/catalogo/java/index.html">
              Ver catálogo de varejo <span>→</span>
            </a>
          </div>
        </div>
        <div className="logo-block">
          <img src={`${ASSETS}/logo-white.png`} alt="Java chocolates" />
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 20, fontWeight: 300 }}>
            Cacau de origem,<br />chocolate de Minas.
          </div>
          <div className="legals">
            JAVA Chocolates Ltda.<br />
            CNPJ 20.261.126/0001-27<br />
            Telefone: (31) 2520-6776<br />
            Indústria Brasileira<br />
            © 2026 — todos os direitos reservados.
          </div>
        </div>
      </div>
    </section>);

}

// ─── Print version (A4 · desktop) ──────────────────────────
function PrintVersion() {
  return (
    <div className="print-only">
      {/* Capa */}
      <div className="pdf-page" style={{ background: 'var(--brown)', color: 'var(--cream)', display: 'flex' }}>
        <div style={{ flex: 1, padding: '40mm 28mm', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
          <div style={{ fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase' }}>Catálogo 2026 · Linha Culinária</div>
          <div>
            <h1 style={{ fontFamily: 'var(--font-display)', fontSize: 64, fontWeight: 300, lineHeight: 0.95, margin: 0, letterSpacing: '-0.02em' }}>
              <strong style={{ fontWeight: 800 }}>Chocolate</strong><br />para produzir.
            </h1>
            <p style={{ fontSize: 14, maxWidth: '30ch', color: 'rgba(255,253,237,0.78)', marginTop: 24 }}>
              Barras, gotas e coberturas em 2 kg e 5 kg. Sem glúten. Sem leite.
            </p>
          </div>
          <img src={`${ASSETS}/logo-white.png`} style={{ width: 90 }} alt="" />
        </div>
        <div style={{ flex: 1, overflow: 'hidden' }}>
          <img src={CAPA} style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: '50% 40%' }} alt="" />
        </div>
      </div>

      {/* Tabela geral de SKUs — a página que o comprador food service realmente usa */}
      <div className="pdf-page" style={{ padding: '20mm 18mm' }}>
        <div style={{ fontSize: 12, letterSpacing: '0.08em', fontWeight: 700, fontFamily: 'var(--font-display)' }}>Linha culinária</div>
        <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 38, fontWeight: 400, marginTop: 8, lineHeight: 1.05 }}>
          Tabela de produtos.
        </h2>
        <table style={{ width: '100%', borderCollapse: 'collapse', marginTop: 20, fontSize: 10 }}>
          <thead>
            <tr style={{ borderBottom: '1.5px solid var(--brown)' }}>
              <th style={{ textAlign: 'left', padding: '6px 4px', fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase', color: '#888' }}>Produto</th>
              <th style={{ textAlign: 'left', padding: '6px 4px', fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase', color: '#888' }}>Cacau</th>
              <th style={{ textAlign: 'right', padding: '6px 4px', fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase', color: '#888' }}>Embalagem</th>
              <th style={{ textAlign: 'right', padding: '6px 4px', fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase', color: '#888' }}>Código</th>
            </tr>
          </thead>
          <tbody>
            {LINES.map((l) => {
              const items = PRODUCTS.filter((p) => p.line === l.id).sort((a, b) => cacauOrd(a) - cacauOrd(b));
              return (
                <React.Fragment key={l.id}>
                  <tr>
                    <td colSpan={4} style={{ padding: '12px 4px 4px', fontFamily: 'var(--font-display)', fontSize: 12, fontWeight: 600, color: 'var(--brown)' }}>
                      {l.label} — <span style={{ fontWeight: 400, color: '#888' }}>{l.sub}</span>
                    </td>
                  </tr>
                  {items.flatMap((p) => p.sizes.map((s, i) =>
                    <tr key={p.id + s.label} style={{ borderBottom: '1px solid #eee' }}>
                      <td style={{ padding: '4px' }}>{i === 0 ? nameOf(p) : ''}</td>
                      <td style={{ padding: '4px', color: '#666' }}>{i === 0 ? cacauLabelOf(p) : ''}</td>
                      <td style={{ padding: '4px', textAlign: 'right' }}>{pesoLabel(s)}</td>
                      <td style={{ padding: '4px', textAlign: 'right', fontFamily: 'ui-monospace, monospace', fontSize: 9, color: '#666' }}>{s.sku}</td>
                    </tr>
                  ))}
                </React.Fragment>);
            })}
          </tbody>
        </table>
      </div>

      {[...PRODUCTS].sort((a, b) => cacauOrd(a) - cacauOrd(b)).map((p) => <PrintProductPage key={p.id} p={p} />)}

      {/* Contato */}
      <div className="pdf-page" style={{ background: 'var(--brown)', color: 'var(--cream)', padding: '36mm 24mm', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
        <div>
          <div style={{ fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'rgba(255,253,237,0.6)' }}>Confeitarias · Food Service · Indústria</div>
          <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 56, fontWeight: 300, marginTop: 12, lineHeight: 0.98, letterSpacing: '-0.02em' }}>
            Faça seu<br />pedido.
          </h2>
          <p style={{ fontSize: 15, maxWidth: '36ch', marginTop: 24, color: 'rgba(255,253,237,0.78)' }}>
            Atendemos confeitarias, cozinhas profissionais, padarias e indústrias de alimentos em todo o Brasil.
          </p>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 32 }}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            {[['WhatsApp', '+55 31 97326-7809'], ['E-mail', 'comercial@javachocolates.com.br'], ['Site', 'javachocolates.com.br'], ['Fábrica', 'Belo Horizonte · MG']].map(([k, v]) =>
            <div key={k}>
                <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', opacity: 0.6 }}>{k}</div>
                <div style={{ fontSize: 15, marginTop: 2 }}>{v}</div>
              </div>
            )}
          </div>
          <div style={{ borderLeft: '1px solid rgba(255,253,237,0.2)', paddingLeft: 24 }}>
            <img src={`${ASSETS}/logo-white.png`} style={{ width: 110 }} alt="" />
            <div style={{ fontFamily: 'var(--font-display)', fontSize: 16, fontWeight: 300, marginTop: 16 }}>
              Cacau de origem,<br />chocolate de Minas.
            </div>
            <div style={{ fontSize: 9, lineHeight: 1.7, color: 'rgba(255,253,237,0.5)', marginTop: 16 }}>
              JAVA Chocolates Ltda.<br />
              CNPJ 20.261.126/0001-27<br />
              Telefone: (31) 2520-6776<br />
              Indústria Brasileira<br />
              © 2026 — todos os direitos reservados.
            </div>
          </div>
        </div>
      </div>
    </div>);

}

function PrintProductPage({ p }) {
  const lineLabel = lineLabelOf(p.line);
  const nutri = nutriFor(p);
  return (
    <div className="pdf-page" style={{ display: 'flex', flexDirection: 'column' }}>
      <div style={{ flex: '0 0 48%', position: 'relative', overflow: 'hidden', background: p.placeholder?.tone || 'var(--cream-warm)' }}>
        {p.img ?
        <img src={p.img} style={{ width: '100%', height: '100%', objectFit: 'cover' }} alt="" /> :
        <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--cream)', fontFamily: 'var(--font-display)', fontSize: 40, textAlign: 'center', padding: '0 20mm', background: `linear-gradient(135deg, ${p.placeholder?.tone}, #2a1a13)` }}>
              {p.placeholder?.label}
            </div>}
        <div style={{ position: 'absolute', top: '12mm', left: '12mm', color: 'var(--cream)', fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase' }}>
          {lineLabel}
        </div>
        {p.temperagem === false &&
        <div style={{ position: 'absolute', top: '12mm', right: '12mm', padding: '6px 12px', background: 'var(--cream)', color: 'var(--brown)', fontSize: 9, letterSpacing: '0.16em', textTransform: 'uppercase' }}>
            Sem temperagem
          </div>
        }
      </div>
      <div style={{ flex: '1 1 52%', padding: '12mm 18mm', display: 'flex', flexDirection: 'column' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase', color: '#888' }}>
          <span>{lineLabel}</span>
          <span style={{ color: 'var(--brown)', fontWeight: 600 }}>{cacauLabelOf(p)}</span>
        </div>
        <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 32, fontWeight: 500, lineHeight: 1.05, margin: '4px 0 2px', letterSpacing: '-0.01em' }}>
          {nameOf(p)}
        </h2>
        <div style={{ fontSize: 13, color: '#888' }}>{p.family}</div>
        <p style={{ fontSize: 12.5, lineHeight: 1.55, marginTop: 10, color: '#333' }}>{p.description}</p>

        <div style={{ display: 'grid', gridTemplateColumns: nutri ? '1fr 1fr 1.1fr' : '1fr 1fr', gap: 14, marginTop: 'auto', paddingTop: 12 }}>
          <div>
            <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#888', marginBottom: 6 }}>Aplicações</div>
            <div style={{ fontSize: 11, lineHeight: 1.6, color: '#333' }}>{(p.usos || []).join(' · ')}</div>

            <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#888', marginTop: 12, marginBottom: 6 }}>Restrições</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
              {p.restrictions.map((r) =>
              <span key={r} style={{ fontSize: 9, padding: '2px 7px', background: 'var(--brown)', color: 'var(--cream)', borderRadius: 100 }}>{restrLabel(r)}</span>
              )}
            </div>
          </div>
          <div>
            <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#888', marginBottom: 6 }}>Embalagens e códigos</div>
            <div>
              {p.sizes.map((s) =>
              <div key={s.label} style={{ padding: '6px 0', borderBottom: '1px solid #eee' }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12 }}>
                    <span style={{ fontFamily: 'var(--font-display)', fontWeight: 500 }}>{pesoLabel(s)}</span>
                    <span style={{ color: 'var(--brown)', fontWeight: 600, fontFamily: 'ui-monospace, monospace', fontSize: 10 }}>{s.sku}</span>
                  </div>
                  <div style={{ fontSize: 10, color: '#888' }}>{packagingFor(s)}</div>
                </div>
              )}
            </div>
            {p.origin &&
            <>
              <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#888', marginTop: 12, marginBottom: 4 }}>Origem</div>
              <div style={{ fontSize: 11 }}>{p.origin}</div>
            </>
            }
          </div>
          {nutri &&
          <div>
            <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#888', marginBottom: 6 }}>Ingredientes</div>
            <div style={{ fontSize: 9.5, lineHeight: 1.5, color: '#333' }}>{nutri.ingredientes}</div>
            <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#888', marginTop: 10, marginBottom: 4 }}>Informação nutricional · 100 g</div>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 8.5 }}>
              <tbody>
                {nutri.rows.map((r) =>
                <tr key={r[0]} style={{ borderBottom: '1px solid #eee' }}>
                    <td style={{ padding: '2px 0', color: '#333' }}>{r[0]}</td>
                    <td style={{ padding: '2px 0', textAlign: 'right', fontFamily: 'ui-monospace, monospace' }}>{r[1]}</td>
                    <td style={{ padding: '2px 0 2px 6px', textAlign: 'right', color: '#888' }}>{r[2]}</td>
                  </tr>
                )}
              </tbody>
            </table>
            <div style={{ fontSize: 8, color: '#888', marginTop: 6, lineHeight: 1.4 }}>
              Temperagem: derretimento {nutri.temper.derretimento} · temperagem {nutri.temper.temperagem} · trabalho {nutri.temper.trabalho}
            </div>
          </div>
          }
        </div>
      </div>
    </div>);

}

// ─── App root ─────────────────────────────────────────────
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "variant": "artesanal",
  "showCompare": true
} /*EDITMODE-END*/;

function App() {
  const [tweaks, setTweak] = window.useTweaks(TWEAK_DEFAULTS);

  const [tipo, setTipo] = useState('all');
  const [line, setLine] = useState(null);
  const [cacau, setCacau] = useState('all');
  const [peso, setPeso] = useState('all');
  const [preparo, setPreparo] = useState('all');
  const [restr, setRestr] = useState([]);
  const [onlyBest, setOnlyBest] = useState(false);
  const [open, setOpen] = useState(null);
  const [cmpIds, setCmpIds] = useState([]);
  const [orcIds, setOrcIds] = useState([]);
  const [orcQty, setOrcQty] = useState({});
  const [orcMsg, setOrcMsg] = useState('');
  const [orcOpen, setOrcOpen] = useState(false);

  // itens com quantidade escolhida — alimenta o selo do botão flutuante
  const nOrcSelecionados = Object.values(orcQty).reduce(
    (n, tamanhos) => n + Object.values(tamanhos || {}).filter((q) => (q | 0) > 0).length, 0);

  const filtered = useMemo(() => PRODUCTS.filter((p) => {
    if (tipo === 'nobre' && p.line === 'coberturas') return false;
    if (tipo === 'coberturas' && p.line !== 'coberturas') return false;
    if (line && p.line !== line) return false;
    if (cacau !== 'all') {
      const bin = CACAU_BINS.find((b) => b.id === cacau);
      if (bin && !bin.match(p)) return false;
    }
    if (peso !== 'all' && !p.sizes.some((s) => s.peso === peso)) return false;
    if (preparo === 'temperar' && p.temperagem === false) return false;
    if (preparo === 'pronto' && p.temperagem !== false) return false;
    if (onlyBest && !p.bestseller) return false;
    if (restr.length) {
      const defs = RESTR_FILTERS.filter((f) => restr.includes(f.id));
      if (!defs.every((d) => d.match(p))) return false;
    }
    return true;
  }).sort((a, b) => cacauOrd(a) - cacauOrd(b)), [tipo, line, cacau, peso, preparo, restr, onlyBest]);

  // Coberturas fracionadas saem da grade principal e ganham seção própria —
  // não são chocolate nobre e confundiam quem compara por % de cacau.
  const nobres = filtered.filter((p) => p.line !== 'coberturas');
  const coberturas = filtered.filter((p) => p.line === 'coberturas');

  const toggleCmp = (id) => {
    setCmpIds((prev) => prev.includes(id) ? prev.filter((x) => x !== id) : prev.length >= 4 ? prev : [...prev, id]);
  };
  const toggleOrc = (id) => {
    setOrcIds((prev) => {
      if (prev.includes(id)) return prev.filter((x) => x !== id);
      setOrcQty((q) => {
        if (q[id] && typeof q[id] === 'object') return q;
        const product = PRODUCTS.find((p) => p.id === id);
        if (!product) return q;
        const init = {};
        // Default: primeira embalagem com qtd 1; as demais desmarcadas (0).
        product.sizes.forEach((s, i) => { init[s.label] = i === 0 ? 1 : 0; });
        return { ...q, [id]: init };
      });
      return [...prev, id];
    });
  };
  const setQty = (id, sizeLabel, v) => setOrcQty((q) => {
    const cur = q[id] && typeof q[id] === 'object' ? q[id] : {};
    return { ...q, [id]: { ...cur, [sizeLabel]: Math.max(0, v | 0) } };
  });

  // ─── Pedido rápido ────────────────────────────────────────
  // Abre o modal com TODOS os produtos listados (qtd 0) — o cliente só sobe a
  // quantidade do que quer. `quantidades` opcional pré-preenche por código.
  const abrirPedidoRapido = (quantidades) => {
    const ids = [];
    const qty = {};
    PRODUCTS.forEach((p) => {
      const init = {};
      let preset = false;
      p.sizes.forEach((s) => {
        const codigos = [s.sku, s.skuUnidade, s.ean].filter(Boolean).map((c) => String(c).toLowerCase());
        const hit = quantidades ? codigos.find((c) => quantidades[c] != null) : null;
        init[s.label] = hit ? quantidades[hit] : 0;
        if (hit) preset = true;
      });
      if (!quantidades || preset) { ids.push(p.id); qty[p.id] = init; }
    });
    if (!ids.length) return;
    setOrcIds(ids);
    setOrcQty(qty);
    setOrcOpen(true);
  };

  // Deep links: ?rapido=1 (lista completa) · ?q=codigo:embalagens;… (pré-preenchido —
  // é a semente do "repetir último pedido" enviado pelo bot).
  useEffect(() => {
    const sp = new URLSearchParams(window.location.search);
    const q = sp.get('q');
    if (q) {
      const quantidades = {};
      q.split(';').forEach((tok) => {
        const [c, n] = tok.split(':');
        const v = Math.max(0, parseInt(n || '0', 10) || 0);
        if (c && v > 0) quantidades[c.trim().toLowerCase()] = v;
      });
      if (Object.keys(quantidades).length) { abrirPedidoRapido(quantidades); return; }
    }
    if (sp.has('rapido')) abrirPedidoRapido(null);
  }, []);

  useEffect(() => {document.body.setAttribute('data-variant', tweaks.variant);}, [tweaks.variant]);

  const orcItems = orcIds.map((id) => PRODUCTS.find((p) => p.id === id)).filter(Boolean);

  return (
    <div className="site site-culinarios" data-variant={tweaks.variant}>
      <TopBar variant={tweaks.variant} onPedidoRapido={() => abrirPedidoRapido(null)} />
      <Cover />
      <Sumario />

      <section id="produtos" data-screen-label="03 Produtos">
        <div className="shell">
          <div className="section-head">
            <div>
              <div className="label">03 · Catálogo culinário</div>
              <h2>Catálogo<br />completo.</h2>
            </div>
            <div className="right">
              Filtre por formato, teor de cacau, embalagem ou tipo de preparo.
              Adicione produtos ao <strong>orçamento</strong> ou ao <strong>comparador</strong> pelos botões em cada card.
            </div>
          </div>
          <Filters
            tipo={tipo} setTipo={setTipo}
            line={line} setLine={setLine}
            cacau={cacau} setCacau={setCacau}
            peso={peso} setPeso={setPeso}
            preparo={preparo} setPreparo={setPreparo}
            restr={restr} setRestr={setRestr}
            onlyBest={onlyBest} setOnlyBest={setOnlyBest}
            count={filtered.length} />

          <GradeProdutos items={nobres} onOpen={setOpen}
            cmpIds={cmpIds} toggleCmp={toggleCmp}
            orcIds={orcIds} toggleOrc={toggleOrc} />
        </div>
      </section>

      {coberturas.length > 0 &&
      <section
        id="coberturas"
        data-screen-label="04 Coberturas"
        style={{
          background: 'var(--bg-deep)',
          borderTop: '1px solid var(--rule)',
          borderBottom: '1px solid var(--rule)',
          padding: 'clamp(40px, 5vw, 72px) 0 clamp(48px, 6vw, 80px)',
        }}>
        <div className="shell">
          <div className="section-head" style={{ paddingTop: 0, borderBottom: 'none' }}>
            <div>
              <div className="label">04 · Coberturas fracionadas</div>
              <h2>Sem<br />temperagem.</h2>
            </div>
            <div className="right">
              Cobertura fracionada não é chocolate nobre: derreteu, usou — brilho e secagem
              rápida em banho, drageamento e casquinha de ovos. Embalagem de 5 kg.
            </div>
          </div>
          <GradeProdutos items={coberturas} onOpen={setOpen}
            cmpIds={cmpIds} toggleCmp={toggleCmp}
            orcIds={orcIds} toggleOrc={toggleOrc}
            style={{ marginBottom: 0 }} />
        </div>
      </section>
      }

      {tweaks.showCompare && cmpIds.length > 0 && <Comparator ids={cmpIds} setIds={setCmpIds} />}

      <Contato />

      {open && <Sheet product={open}
      onClose={() => setOpen(null)}
      onCompare={toggleCmp} compareIds={cmpIds}
      onOrcamento={toggleOrc} orcamentoIds={orcIds}
      onVerOrcamento={() => { setOpen(null); setOrcOpen(true); }} />}

      {/* FAB do catálogo (item 4): no celular o botão do topo some ao rolar, e a
          pessoa perde o caminho para o orçamento. Some quando o modal está aberto. */}
      {/* A bandeja "N no orçamento" já é o caminho quando há itens escolhidos —
          o FAB só aparece quando ela NÃO existe (senão sobrepõe, como em 15/08). */}
      {!orcOpen && !open && orcIds.length === 0 &&
      <button className="fab fab-orcamento interactive-only" type="button"
        onClick={() => (orcIds.length ? setOrcOpen(true) : abrirPedidoRapido(null))}
        title="Montar orçamento com os produtos do catálogo">
        🧾 Montar orçamento
        {nOrcSelecionados > 0 && <span className="fab-badge">{nOrcSelecionados}</span>}
      </button>
      }

      {orcOpen &&
      <OrcamentoModal
        items={orcItems}
        qtyMap={orcQty}
        setQty={setQty}
        onRemove={toggleOrc}
        onClose={() => setOrcOpen(false)}
        onVerProduto={(p) => { setOrcOpen(false); setOpen(p); }}
        message={orcMsg}
        setMessage={setOrcMsg} />

      }

      {/* Floating trays */}
      {(cmpIds.length > 0 || orcIds.length > 0) &&
      <div className="trays interactive-only">
          {orcIds.length > 0 &&
        <button className="tray orc-tray" onClick={() => setOrcOpen(true)}>
              <span className="lbl">🛒 {orcIds.length} no orçamento</span>
              <span className="arrow">Pedir orçamento →</span>
            </button>
        }
          {cmpIds.length > 0 &&
        <button className="tray cmp-tray" onClick={() => document.getElementById('comparador')?.scrollIntoView({ behavior: 'smooth' })}>
              <span className="lbl">⇆ {cmpIds.length} no comparador</span>
              <span className="arrow">Ver comparativo →</span>
            </button>
        }
        </div>
      }

      <window.TweaksPanel title="Tweaks · Java culinários">
        <window.TweakSection label="Direção visual">
          <window.TweakRadio
            value={tweaks.variant}
            onChange={(v) => setTweak('variant', v)}
            options={[
            { value: 'artesanal', label: 'Artesanal' },
            { value: 'editorial', label: 'Editorial' },
            { value: 'premium', label: 'Premium' }]
            } />

        </window.TweakSection>
        <window.TweakSection label="Seções">
          <window.TweakToggle label="Comparador" value={tweaks.showCompare} onChange={(v) => setTweak('showCompare', v)} />
        </window.TweakSection>
        <window.TweakSection label="Exportar">
          <window.TweakButton label="Imprimir / salvar PDF (A4)" onClick={() => window.print()} />
          <window.TweakButton label="PDF mobile (A5)" onClick={() => window.open(PDF_MOBILE, '_blank', 'noopener')} />
        </window.TweakSection>
      </window.TweaksPanel>

      <PrintVersion />
    </div>);

}

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