/* global React, ReactDOM, Sidebar, Topbar, Login, Dashboard, Projects, ProjectView, Tasks, Clients, Finance, Budgets, Briefings, Calendar, Reports, Pages, Messages, Settings, NewProject, Services, Leads, TweaksPanel, useTweaks, TweakSection, TweakRadio, TweakColor, TweakToggle, sb, GoogleIntegrationSettings */
const { useState, useEffect, useRef, useCallback } = React;

// (ServicesContainer removed — App component handles services-ready event directly)

// ─── Calculator ──────────────────────────────────────────────────────────────
const CALC_INP = { width:'100%', padding:'9px 12px', borderRadius:8, border:'1px solid var(--border-subtle)', background:'var(--bg-elevated)', color:'var(--fg-primary)', fontFamily:'inherit', fontSize:13, outline:'none', boxSizing:'border-box' };
const CALC_LBL = { fontFamily:'var(--font-display)', fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.06em', color:'var(--fg-muted)', display:'block', marginBottom:6 };
const CALC_CLR = { alignSelf:'flex-start', padding:'6px 14px', borderRadius:8, border:'1px solid var(--border-subtle)', background:'transparent', color:'var(--fg-muted)', cursor:'pointer', fontSize:12, fontFamily:'inherit' };

function calcFmtBRL(n) {
  if (!n || isNaN(n) || !isFinite(n)) return 'R$ 0,00';
  return 'R$ ' + Number(n).toLocaleString('pt-BR', { minimumFractionDigits:2, maximumFractionDigits:2 });
}

function CalcNumInput({ label, value, onChange, hint, suffix, step=1, min=0 }) {
  return (
    <div>
      <label style={CALC_LBL}>{label}</label>
      <div style={{ position:'relative', display:'flex', alignItems:'center' }}>
        <input type="number" value={value||''} min={min} step={step}
          onChange={e => onChange(parseFloat(e.target.value)||0)}
          style={{ ...CALC_INP, paddingRight: suffix ? 44 : 12 }} />
        {suffix && <span style={{ position:'absolute', right:12, fontSize:11, color:'var(--fg-muted)', pointerEvents:'none', whiteSpace:'nowrap' }}>{suffix}</span>}
      </div>
      {hint && <div style={{ fontSize:11, color:'var(--fg-muted)', marginTop:4 }}>{hint}</div>}
    </div>
  );
}

function CalcResultRow({ label, value, accent, muted }) {
  return (
    <div style={{ display:'flex', justifyContent:'space-between', alignItems:'baseline', padding:'7px 0', borderBottom: muted ? 'none' : '1px solid var(--border-subtle)' }}>
      <span style={{ fontSize: muted?11:13, color: muted?'var(--fg-muted)':'var(--fg-secondary)' }}>{label}</span>
      <span style={{ fontFamily:'var(--font-display)', fontWeight:600, fontSize:13, color: accent||'var(--fg-primary)' }}>{value}</span>
    </div>
  );
}

function CalcMargemBar({ pct }) {
  const safe = (isNaN(pct)||!isFinite(pct)) ? 0 : Math.max(0, Math.min(100, pct));
  const color = safe>=30 ? '#22C55E' : safe>=15 ? '#FADB14' : '#FF6A6A';
  const lbl   = safe>=30 ? 'Saudavel' : safe>=15 ? 'Aceitavel' : 'Baixa';
  return (
    <div style={{ marginTop:14 }}>
      <div style={{ display:'flex', justifyContent:'space-between', marginBottom:6, fontSize:11 }}>
        <span style={{ color:'var(--fg-muted)' }}>Margem liquida</span>
        <span style={{ color, fontWeight:700 }}>{Math.round(safe)}% - {lbl}</span>
      </div>
      <div style={{ height:6, borderRadius:999, background:'var(--bg-surface)', overflow:'hidden' }}>
        <div style={{ height:'100%', width:safe+'%', background:color, borderRadius:999, transition:'width 200ms ease,background 200ms ease' }} />
      </div>
    </div>
  );
}

function CalcTaxaAlert({ valorHora, overheadMes, horasMes }) {
  if (!overheadMes||!horasMes) return null;
  const taxaMin = overheadMes/horasMes;
  const ok = valorHora >= taxaMin;
  return (
    <div style={{ marginTop:6, fontSize:11, padding:'4px 10px', borderRadius:6, display:'inline-flex', alignItems:'center', gap:5, background: ok?'#22C55E18':'#FF6A6A18', color: ok?'#22C55E':'#FF6A6A', border:`1px solid ${ok?'#22C55E44':'#FF6A6A44'}` }}>
      {ok ? 'Acima da taxa minima' : ('Min. viavel: '+calcFmtBRL(taxaMin)+'/h')}
    </div>
  );
}

function CalcResultPanel({ precoFinal, rows, margemEfetiva, onGerar }) {
  const validRows = (rows||[]).filter(r => !!r);
  return (
    <div style={{ background:'var(--bg-elevated)', borderRadius:12, padding:'18px 20px', display:'flex', flexDirection:'column' }}>
      <div style={{ fontFamily:'var(--font-display)', fontSize:10, fontWeight:700, letterSpacing:'0.06em', textTransform:'uppercase', color:'var(--fg-muted)', marginBottom:12 }}>Resultado estimado</div>
      <div style={{ fontFamily:'var(--font-display)', fontSize:36, fontWeight:700, letterSpacing:'-0.03em', color:'var(--fg-primary)', marginBottom:14 }}>{calcFmtBRL(precoFinal)}</div>
      {validRows.map((r,i) => <CalcResultRow key={i} label={r.label} value={r.value} accent={r.accent} muted={r.muted} />)}
      <CalcMargemBar pct={margemEfetiva} />
      <button onClick={onGerar} disabled={precoFinal<=0}
        style={{ marginTop:16, width:'100%', padding:'10px 0', borderRadius:8, background: precoFinal>0?'var(--primary)':'var(--bg-elevated)', color: precoFinal>0?'#fff':'var(--fg-muted)', border:'none', cursor: precoFinal>0?'pointer':'default', fontWeight:700, fontSize:13, fontFamily:'inherit', transition:'all 160ms' }}>
        Gerar Orcamento
      </button>
    </div>
  );
}

function CalcPorHora({ onGerar }) {
  const [valorHora,   setValorHora]   = useState(0);
  const [horas,       setHoras]       = useState(0);
  const [overheadMes, setOverheadMes] = useState(0);
  const [horasMes,    setHorasMes]    = useState(160);
  const [margem,      setMargem]      = useState(30);

  const ohPorHora   = horasMes>0 ? overheadMes/horasMes : 0;
  const custoServ   = valorHora*horas;
  const custoOh     = ohPorHora*horas;
  const custoBase   = custoServ+custoOh;
  const vlrMargem   = custoBase*(margem/100);
  const precoFinal  = custoBase+vlrMargem;
  const margemEf    = precoFinal>0 ? (vlrMargem/precoFinal*100) : 0;

  return (
    <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:24 }}>
      <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
        <div>
          <CalcNumInput label="Valor por hora" value={valorHora} onChange={setValorHora} suffix="R$/h" step={10} />
          <CalcTaxaAlert valorHora={valorHora} overheadMes={overheadMes} horasMes={horasMes} />
        </div>
        <CalcNumInput label="Horas estimadas" value={horas} onChange={setHoras} suffix="h" step={1} />
        <CalcNumInput label="Overhead mensal" value={overheadMes} onChange={setOverheadMes} suffix="R$" step={100}
          hint={horasMes>0&&overheadMes>0 ? ('~ '+calcFmtBRL(ohPorHora)+'/h') : 'Ferramentas, assinaturas, etc.'} />
        <CalcNumInput label="Horas disponiveis/mes" value={horasMes} onChange={setHorasMes} suffix="h/mes" step={8} />
        <CalcNumInput label="Margem de lucro" value={margem} onChange={setMargem} suffix="%" step={5} />
        <button style={CALC_CLR} onClick={() => { setValorHora(0); setHoras(0); setOverheadMes(0); setHorasMes(160); setMargem(30); }}>Limpar</button>
      </div>
      <CalcResultPanel
        precoFinal={precoFinal} margemEfetiva={margemEf}
        rows={[
          { label:'Servico (horas)', value:calcFmtBRL(custoServ) },
          { label:'Overhead',        value:calcFmtBRL(custoOh) },
          { label:'Margem',          value:calcFmtBRL(vlrMargem), accent:'#22C55E' },
        ]}
        onGerar={() => onGerar({ title:'Projeto - '+horas+'h x R$'+valorHora+'/h', value:precoFinal })}
      />
    </div>
  );
}

function CalcPorPacote({ onGerar }) {
  const [nome,    setNome]    = useState('');
  const [items,   setItems]   = useState([{ d:'', q:1, p:0 }]);
  const [desc,    setDesc]    = useState(0);
  const [oh,      setOh]      = useState(0);
  const [margem,  setMargem]  = useState(30);

  const addItem = () => setItems(prev => [...prev, { d:'', q:1, p:0 }]);
  const remItem = i => setItems(prev => prev.filter((_,idx) => idx!==i));
  const setItem = (i,k,v) => setItems(prev => prev.map((it,idx) => idx===i ? {...it,[k]:v} : it));

  const subtotal   = items.reduce((s,it) => s+(it.q||0)*(it.p||0), 0);
  const comOh      = subtotal+oh;
  const comMargem  = margem<100 ? comOh/(1-margem/100) : comOh;
  const vlrMargem  = comMargem-comOh;
  const precoFinal = comMargem*(1-desc/100);
  const margemEf   = precoFinal>0 ? (vlrMargem/precoFinal*100) : 0;

  return (
    <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:24 }}>
      <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
        <div>
          <label style={CALC_LBL}>Nome do pacote</label>
          <input value={nome} onChange={e => setNome(e.target.value)} placeholder="Ex: Identidade Visual Completa" style={CALC_INP} />
        </div>
        <div>
          <label style={CALC_LBL}>Itens do pacote</label>
          <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
            {items.map((it,i) => (
              <div key={i} style={{ display:'grid', gridTemplateColumns:'1fr 52px 90px 28px', gap:6, alignItems:'center' }}>
                <input value={it.d} onChange={e => setItem(i,'d',e.target.value)} placeholder="Descricao" style={{ ...CALC_INP, fontSize:12 }} />
                <input type="number" value={it.q||''} onChange={e => setItem(i,'q',parseFloat(e.target.value)||1)} min={1} placeholder="Qtd" style={{ ...CALC_INP, fontSize:12, textAlign:'center', padding:'9px 6px' }} />
                <input type="number" value={it.p||''} onChange={e => setItem(i,'p',parseFloat(e.target.value)||0)} min={0} placeholder="R$" style={{ ...CALC_INP, fontSize:12 }} />
                <button onClick={() => remItem(i)} style={{ width:28, height:28, borderRadius:6, border:'1px solid var(--border-subtle)', background:'transparent', color:'var(--fg-muted)', cursor:'pointer', fontSize:14, display:'flex', alignItems:'center', justifyContent:'center' }}>x</button>
              </div>
            ))}
          </div>
          <button onClick={addItem} style={{ marginTop:6, fontSize:12, color:'var(--geek-blue-300)', background:'transparent', border:'none', cursor:'pointer', fontFamily:'inherit', padding:0, fontWeight:600 }}>+ Adicionar item</button>
        </div>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:10 }}>
          <CalcNumInput label="Desconto" value={desc}   onChange={setDesc}   suffix="%" step={5} />
          <CalcNumInput label="Overhead" value={oh}     onChange={setOh}     suffix="R$" step={50} />
          <CalcNumInput label="Margem"   value={margem} onChange={setMargem} suffix="%" step={5} />
        </div>
        <button style={CALC_CLR} onClick={() => { setNome(''); setItems([{d:'',q:1,p:0}]); setDesc(0); setOh(0); setMargem(30); }}>Limpar</button>
      </div>
      <CalcResultPanel
        precoFinal={precoFinal} margemEfetiva={margemEf}
        rows={[
          { label:'Subtotal dos itens', value:calcFmtBRL(subtotal) },
          oh>0   ? { label:'Overhead',               value:calcFmtBRL(oh) } : null,
          { label:'Margem',             value:calcFmtBRL(vlrMargem), accent:'#22C55E' },
          desc>0 ? { label:'Desconto ('+desc+'%)',    value:'- '+calcFmtBRL(comMargem*desc/100), accent:'#FF6A6A' } : null,
        ]}
        onGerar={() => onGerar({ title: nome||'Pacote de servicos', value:precoFinal, items:items.filter(it=>it.d).map(it=>({d:it.d,q:it.q,p:it.p})) })}
      />
    </div>
  );
}

const CALC_ESCOPOS = {
  pequeno:     { label:'Pequeno',       horas:20   },
  medio:       { label:'Medio',         horas:60   },
  grande:      { label:'Grande',        horas:160  },
  customizado: { label:'Personalizado', horas:null },
};

function CalcPorProjeto({ onGerar }) {
  const [escopo,    setEscopo]    = useState('medio');
  const [horas,     setHoras]     = useState(60);
  const [valorHora, setValorHora] = useState(0);
  const [extras,    setExtras]    = useState(0);
  const [oh,        setOh]        = useState(0);
  const [meses,     setMeses]     = useState(1);
  const [margem,    setMargem]    = useState(30);

  const onEscopo = key => { setEscopo(key); if (CALC_ESCOPOS[key].horas!==null) setHoras(CALC_ESCOPOS[key].horas); };

  const custoMO    = horas*valorHora;
  const custoOh    = oh*meses;
  const custoTotal = custoMO+extras+custoOh;
  const precoFinal = margem<100 ? custoTotal/(1-margem/100) : custoTotal;
  const vlrMargem  = precoFinal-custoTotal;
  const margemEf   = precoFinal>0 ? (vlrMargem/precoFinal*100) : 0;
  const equivHora  = horas>0 ? precoFinal/horas : 0;

  return (
    <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:24 }}>
      <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
        <div>
          <label style={CALC_LBL}>Escopo do projeto</label>
          <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
            {Object.entries(CALC_ESCOPOS).map(([key,{label}]) => {
              const active = escopo===key;
              return (
                <button key={key} onClick={() => onEscopo(key)} style={{ padding:'7px 14px', borderRadius:8, fontSize:12, fontWeight:600, fontFamily:'inherit', cursor:'pointer', background: active?'var(--primary-soft)':'var(--bg-elevated)', color: active?'var(--geek-blue-200)':'var(--fg-secondary)', border:`1px solid ${active?'var(--geek-blue-a40)':'var(--border-subtle)'}`, transition:'all 120ms' }}>
                  {label}
                </button>
              );
            })}
          </div>
        </div>
        <CalcNumInput label="Horas estimadas"  value={horas}     onChange={setHoras}     suffix="h"     step={8} />
        <CalcNumInput label="Valor por hora"   value={valorHora} onChange={setValorHora} suffix="R$/h"  step={10} />
        <CalcNumInput label="Custos adicionais" value={extras}   onChange={setExtras}    suffix="R$"    step={100} hint="Ferramentas, terceiros, licencas" />
        <CalcNumInput label="Overhead mensal"  value={oh}        onChange={setOh}        suffix="R$"    step={100} />
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
          <CalcNumInput label="Duracao (meses)"  value={meses}  onChange={setMeses}  suffix="meses" step={0.5} min={0.5} />
          <CalcNumInput label="Margem desejada"  value={margem} onChange={setMargem} suffix="%"     step={5} />
        </div>
        <button style={CALC_CLR} onClick={() => { setEscopo('medio'); setHoras(60); setValorHora(0); setExtras(0); setOh(0); setMeses(1); setMargem(30); }}>Limpar</button>
      </div>
      <CalcResultPanel
        precoFinal={precoFinal} margemEfetiva={margemEf}
        rows={[
          { label:'Mao de obra',     value:calcFmtBRL(custoMO) },
          { label:'Overhead',        value:calcFmtBRL(custoOh) },
          extras>0 ? { label:'Custos adicionais', value:calcFmtBRL(extras) } : null,
          { label:'Margem',          value:calcFmtBRL(vlrMargem), accent:'#22C55E' },
          { label:'Equivalente/hora', value:calcFmtBRL(equivHora)+'/h', muted:true },
        ]}
        onGerar={() => onGerar({ title:'Projeto '+CALC_ESCOPOS[escopo].label+' - '+horas+'h', value:precoFinal })}
      />
    </div>
  );
}

function CalculatorPanel({ onClose, onGerarOrcamento }) {
  const [tab, setTab] = useState('hora');
  const tabs = [
    { id:'hora',    label:'Por Hora'    },
    { id:'pacote',  label:'Por Pacote'  },
    { id:'projeto', label:'Por Projeto' },
  ];
  return (
    <div onClick={onClose} style={{ position:'fixed', inset:0, background:'rgba(7,11,28,0.72)', backdropFilter:'blur(6px)', display:'grid', placeItems:'center', zIndex:300, padding:24 }}>
      <div onClick={e => e.stopPropagation()} style={{ width:'min(760px,100%)', background:'var(--bg-surface)', border:'1px solid var(--border-strong)', borderRadius:18, boxShadow:'0 30px 80px rgba(0,0,0,0.55)', overflow:'hidden', display:'flex', flexDirection:'column', maxHeight:'92vh' }}>
        <div style={{ padding:'18px 24px', borderBottom:'1px solid var(--border-subtle)', display:'flex', alignItems:'center', justifyContent:'space-between', flexShrink:0 }}>
          <div>
            <div style={{ fontFamily:'var(--font-display)', fontSize:10, fontWeight:700, letterSpacing:'0.06em', textTransform:'uppercase', color:'var(--geek-blue-300)' }}>Ferramenta</div>
            <h2 style={{ margin:'3px 0 0', fontSize:18, fontWeight:700 }}>Calculadora de Servicos</h2>
          </div>
          <button onClick={onClose} style={{ background:'transparent', border:'1px solid var(--border-subtle)', color:'var(--fg-secondary)', width:34, height:34, borderRadius:8, cursor:'pointer', fontSize:18 }}>x</button>
        </div>
        <div style={{ display:'flex', gap:4, padding:'12px 24px 0', borderBottom:'1px solid var(--border-subtle)', flexShrink:0 }}>
          {tabs.map(tb => {
            const active = tab===tb.id;
            return (
              <button key={tb.id} onClick={() => setTab(tb.id)} style={{ padding:'8px 20px', borderRadius:'8px 8px 0 0', fontSize:13, fontWeight:600, cursor:'pointer', fontFamily:'inherit', background: active?'var(--bg-elevated)':'transparent', color: active?'var(--fg-primary)':'var(--fg-muted)', border: active?'1px solid var(--border-subtle)':'1px solid transparent', borderBottom: active?'1px solid var(--bg-elevated)':'1px solid transparent', marginBottom: active?-1:0, transition:'all 140ms' }}>
                {tb.label}
              </button>
            );
          })}
        </div>
        <div style={{ padding:'22px 24px', overflowY:'auto', flex:1 }}>
          {tab==='hora'    && <CalcPorHora    onGerar={onGerarOrcamento} />}
          {tab==='pacote'  && <CalcPorPacote  onGerar={onGerarOrcamento} />}
          {tab==='projeto' && <CalcPorProjeto onGerar={onGerarOrcamento} />}
        </div>
      </div>
    </div>
  );
}
// ─── End Calculator ───────────────────────────────────────────────────────────

// ─── Grid de Preview ──────────────────────────────────────────────────────────
const GP_ARTS = [
  { id:'a01', title:'Post Verao 2025',      client:'Agencia Sol',  campaign:'Verao 2025',   status:'aprovado',  color:'linear-gradient(135deg,#1D39C4 0%,#36CFC9 100%)', caption:'Aproveite o verao com a gente!', tags:['verao','social'], date:'2026-05-20', notes:'' },
  { id:'a02', title:'Story Promocao',       client:'Agencia Sol',  campaign:'Verao 2025',   status:'agendado',  color:'linear-gradient(135deg,#FA541C 0%,#FADB14 100%)', caption:'Promocao especial so hoje!',     tags:['promo','story'],  date:'2026-05-21', notes:'' },
  { id:'a03', title:'Carrossel Produtos',   client:'Studio Flex',  campaign:'Lancamento',   status:'rascunho',  color:'linear-gradient(135deg,#7C3AED 0%,#1D39C4 100%)', caption:'Confira nossa nova linha',       tags:['carrossel'],      date:'2026-05-22', notes:'Aguardando aprovacao' },
  { id:'a04', title:'Banner Black Friday',  client:'Loja Nova',    campaign:'Black Friday', status:'aprovado',  color:'linear-gradient(135deg,#111 0%,#3F3F46 100%)',     caption:'As melhores ofertas do ano',     tags:['blackfriday'],    date:'2026-11-28', notes:'' },
  { id:'a05', title:'Post Institucional',   client:'Studio Flex',  campaign:'Branding',     status:'publicado', color:'linear-gradient(135deg,#22C55E 0%,#16A34A 100%)', caption:'Somos parceiros de verdade',      tags:['branding'],       date:'2026-05-10', notes:'' },
  { id:'a06', title:'Reels Bastidores',     client:'Agencia Sol',  campaign:'Engajamento',  status:'rascunho',  color:'linear-gradient(135deg,#F472B6 0%,#7C3AED 100%)', caption:'Nos bastidores da criacao',      tags:['reels'],          date:'2026-05-25', notes:'Editar musica' },
  { id:'a07', title:'Depoimento Cliente',   client:'Loja Nova',    campaign:'Social Proof', status:'aprovado',  color:'linear-gradient(135deg,#0EA5E9 0%,#1D39C4 100%)', caption:'O que nossos clientes dizem',    tags:['depoimento'],     date:'2026-05-18', notes:'' },
  { id:'a08', title:'Lancamento Produto X', client:'Studio Flex',  campaign:'Lancamento',   status:'agendado',  color:'linear-gradient(135deg,#F59E0B 0%,#FA541C 100%)', caption:'Produto X chegou. Prepare-se!', tags:['lancamento'],     date:'2026-05-30', notes:'' },
  { id:'a09', title:'Dica da Semana',       client:'Agencia Sol',  campaign:'Educativo',    status:'publicado', color:'linear-gradient(135deg,#36CFC9 0%,#22C55E 100%)', caption:'Dica 42: Como crescer no IG',   tags:['dica'],           date:'2026-05-08', notes:'' },
  { id:'a10', title:'Post Feriado',         client:'Loja Nova',    campaign:'Datas',        status:'rascunho',  color:'linear-gradient(135deg,#EF4444 0%,#F97316 100%)', caption:'Boas festas a todos!',          tags:['feriado'],        date:'2026-06-12', notes:'' },
  { id:'a11', title:'Sorteio Instagram',    client:'Agencia Sol',  campaign:'Engajamento',  status:'aprovado',  color:'linear-gradient(135deg,#FADB14 0%,#F59E0B 100%)', caption:'SORTEIO! Participe e concorra', tags:['sorteio'],        date:'2026-05-28', notes:'' },
  { id:'a12', title:'Collab Parceiro',      client:'Studio Flex',  campaign:'Parceria',     status:'agendado',  color:'linear-gradient(135deg,#A78BFA 0%,#F472B6 100%)', caption:'Uma parceria incrivel',         tags:['collab'],         date:'2026-06-01', notes:'' },
];
const GP_STATUS = {
  rascunho:  { label:'Rascunho',  bg:'#3F3F4640', color:'#A1A1AA', border:'#52525B' },
  aprovado:  { label:'Aprovado',  bg:'#22C55E18', color:'#22C55E', border:'#22C55E44' },
  agendado:  { label:'Agendado',  bg:'#0EA5E918', color:'#0EA5E9', border:'#0EA5E944' },
  publicado: { label:'Publicado', bg:'#7C3AED18', color:'#A78BFA', border:'#7C3AED44' },
};
function GpBadge({ status, small }) {
  const c = GP_STATUS[status] || GP_STATUS.rascunho;
  return (
    <span style={{ display:'inline-flex', alignItems:'center', gap:4, padding: small ? '2px 7px' : '3px 9px', borderRadius:999, fontSize: small ? 10 : 11, fontWeight:600, background:c.bg, color:c.color, border:`1px solid ${c.border}` }}>
      <span style={{ width:5, height:5, borderRadius:'50%', background:c.color, flexShrink:0 }} />
      {c.label}
    </span>
  );
}
function GpKpi({ label, value, color }) {
  return (
    <div style={{ background:'var(--bg-surface)', border:'1px solid var(--border-subtle)', borderRadius:12, padding:'14px 18px', flex:1, minWidth:110 }}>
      <div style={{ fontSize:26, fontWeight:700, fontFamily:'var(--font-display)', color: color || 'var(--fg-primary)', lineHeight:1 }}>{value}</div>
      <div style={{ fontSize:11, color:'var(--fg-muted)', marginTop:4 }}>{label}</div>
    </div>
  );
}
function GpCell({ art, idx, mode, dragRef, onDrop, onRemove, selected, onClick }) {
  const [over, setOver] = useState(false);
  const [hov,  setHov]  = useState(false);
  return (
    <div
      draggable={!!art}
      onClick={() => art && onClick(art.id)}
      onDragStart={art ? e => { dragRef.current = { source:'grid', artId:art.id, fromIdx:idx }; e.dataTransfer.effectAllowed='move'; } : undefined}
      onDragOver={e => { e.preventDefault(); setOver(true); }}
      onDragLeave={() => setOver(false)}
      onDrop={e => { e.preventDefault(); setOver(false); onDrop(idx); }}
      onMouseEnter={() => setHov(true)}
      onMouseLeave={() => setHov(false)}
      style={{ aspectRatio:'1/1', borderRadius:4, overflow:'hidden', position:'relative', background: !art ? 'var(--bg-elevated)' : art.color, border: over ? '2px dashed var(--primary)' : (selected && art && selected===art.id) ? '2px solid var(--primary)' : !art ? '1.5px dashed var(--border-subtle)' : '2px solid transparent', cursor: art ? 'pointer' : 'default', transition:'border-color 120ms', boxSizing:'border-box' }}
    >
      {art && art.imageUrl && <img src={art.imageUrl} alt={art.title} style={{ position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover' }} />}
      {!art && (
        <div style={{ width:'100%', height:'100%', display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:6, opacity:0.4 }}>
          <svg viewBox="0 0 24 24" width={22} height={22} fill="none" stroke="var(--fg-muted)" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
          <span style={{ fontSize:10, color:'var(--fg-muted)' }}>Arraste aqui</span>
        </div>
      )}
      {art && mode==='plan' && !hov && (
        <div style={{ position:'absolute', top:5, left:5 }}><GpBadge status={art.status} small /></div>
      )}
      {art && mode==='plan' && hov && (
        <div style={{ position:'absolute', inset:0, background:'rgba(0,0,0,0.6)', display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:8, padding:8 }}>
          <div style={{ fontSize:11, fontWeight:700, color:'#fff', textAlign:'center', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', maxWidth:'100%' }}>{art.title}</div>
          <GpBadge status={art.status} small />
          <button onClick={e => { e.stopPropagation(); onRemove(idx); }} style={{ marginTop:2, padding:'4px 10px', borderRadius:6, background:'rgba(239,68,68,0.25)', border:'1px solid rgba(239,68,68,0.5)', color:'#FCA5A5', fontSize:11, cursor:'pointer', fontFamily:'inherit', fontWeight:600 }}>Remover</button>
        </div>
      )}
    </div>
  );
}
function GpArtCard({ art, dragRef, onDelete }) {
  const [hov, setHov] = useState(false);
  return (
    <div draggable
      onDragStart={e => { dragRef.current = { source:'library', artId:art.id }; e.dataTransfer.effectAllowed='move'; }}
      onMouseEnter={() => setHov(true)} onMouseLeave={() => setHov(false)}
      style={{ display:'flex', gap:10, alignItems:'center', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border-subtle)', background: hov ? 'var(--bg-elevated)' : 'var(--bg-surface)', cursor:'grab', transition:'background 140ms', userSelect:'none', position:'relative' }}
    >
      <div style={{ width:40, height:40, borderRadius:6, background:art.color, flexShrink:0, overflow:'hidden', position:'relative' }}>
        {art.imageUrl && <img src={art.imageUrl} alt={art.title} style={{ width:'100%', height:'100%', objectFit:'cover' }} />}
      </div>
      <div style={{ minWidth:0, flex:1 }}>
        <div style={{ fontSize:12, fontWeight:600, color:'var(--fg-primary)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{art.title}</div>
        <div style={{ fontSize:11, color:'var(--fg-muted)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{art.client}</div>
        <div style={{ marginTop:4 }}><GpBadge status={art.status} small /></div>
      </div>
      {hov && (
        <button
          onClick={e => { e.stopPropagation(); onDelete(art.id); }}
          title="Apagar arte"
          style={{ position:'absolute', top:6, right:6, width:20, height:20, borderRadius:4, border:'none', background:'rgba(239,68,68,0.18)', color:'#FCA5A5', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', padding:0, flexShrink:0 }}
        >
          <svg viewBox="0 0 24 24" width={12} height={12} fill="none" stroke="currentColor" strokeWidth={2.5} strokeLinecap="round"><path d="M18 6L6 18M6 6l12 12"/></svg>
        </button>
      )}
    </div>
  );
}
function GpLibrary({ arts, dragRef, search, setSearch, filter, setFilter, onDelete }) {
  const visible = arts.filter(a => {
    const q = search.toLowerCase();
    return (!q || a.title.toLowerCase().includes(q) || a.client.toLowerCase().includes(q)) && (filter==='all' || a.status===filter);
  });
  return (
    <div style={{ width:224, flexShrink:0, display:'flex', flexDirection:'column', gap:10, background:'var(--bg-surface)', border:'1px solid var(--border-subtle)', borderRadius:12, padding:14, minHeight:0 }}>
      <div style={{ fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.07em', color:'var(--fg-muted)' }}>Biblioteca de Artes</div>
      <input value={search} onChange={e => setSearch(e.target.value)} placeholder="Buscar arte..." style={{ width:'100%', padding:'7px 10px', borderRadius:8, border:'1px solid var(--border-subtle)', background:'var(--bg-elevated)', color:'var(--fg-primary)', fontSize:12, fontFamily:'inherit', outline:'none', boxSizing:'border-box' }} />
      <select value={filter} onChange={e => setFilter(e.target.value)} style={{ width:'100%', padding:'7px 10px', borderRadius:8, border:'1px solid var(--border-subtle)', background:'var(--bg-elevated)', color:'var(--fg-secondary)', fontSize:12, fontFamily:'inherit', outline:'none', cursor:'pointer' }}>
        <option value="all">Todos os status</option>
        <option value="rascunho">Rascunho</option>
        <option value="aprovado">Aprovado</option>
        <option value="agendado">Agendado</option>
        <option value="publicado">Publicado</option>
      </select>
      <div style={{ flex:1, overflowY:'auto', display:'flex', flexDirection:'column', gap:6 }}>
        {visible.length===0 && <div style={{ textAlign:'center', color:'var(--fg-muted)', fontSize:12, paddingTop:20 }}>Nenhuma arte encontrada</div>}
        {visible.map(art => <GpArtCard key={art.id} art={art} dragRef={dragRef} onDelete={onDelete} />)}
      </div>
      <button onClick={() => window.__toast && window.__toast('Funcionalidade em breve!', { tone:'info' })} style={{ width:'100%', padding:'8px 0', borderRadius:8, border:'1px solid var(--border-subtle)', background:'transparent', color:'var(--geek-blue-300)', fontSize:12, fontWeight:600, fontFamily:'inherit', cursor:'pointer' }}>
        Usar artes das tarefas
      </button>
    </div>
  );
}
function GpDetails({ art, onRemove, onUpdateStatus }) {
  if (!art) return (
    <div style={{ width:236, flexShrink:0, background:'var(--bg-surface)', border:'1px solid var(--border-subtle)', borderRadius:12, padding:20, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:12, color:'var(--fg-muted)' }}>
      <svg viewBox="0 0 24 24" width={32} height={32} fill="none" stroke="currentColor" strokeWidth={1} strokeLinecap="round" strokeLinejoin="round" style={{ opacity:0.3 }}><path d="M19 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2zM8.5 10a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM21 15l-5-5L5 21"/></svg>
      <div style={{ fontSize:13, textAlign:'center', lineHeight:1.5 }}>Selecione um post no grid para ver os detalhes</div>
    </div>
  );
  const isUserArt = art.id?.startsWith('u_');
  const statuses = ['rascunho', 'aprovado', 'agendado', 'publicado'];
  return (
    <div style={{ width:236, flexShrink:0, background:'var(--bg-surface)', border:'1px solid var(--border-subtle)', borderRadius:12, overflow:'hidden', display:'flex', flexDirection:'column' }}>
      <div style={{ height:150, background:art.color, flexShrink:0, overflow:'hidden', position:'relative' }}>
        {art.imageUrl && <img src={art.imageUrl} alt={art.title} style={{ width:'100%', height:'100%', objectFit:'cover' }} />}
      </div>
      <div style={{ padding:14, display:'flex', flexDirection:'column', gap:10, flex:1, overflowY:'auto' }}>
        <div>
          <div style={{ fontSize:14, fontWeight:700, color:'var(--fg-primary)', lineHeight:1.3, marginBottom:5 }}>{art.title}</div>
          <GpBadge status={art.status} />
        </div>
        {/* Status selector — apenas para artes do usuário */}
        {isUserArt && onUpdateStatus && (
          <div>
            <div style={{ fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.07em', color:'var(--fg-muted)', marginBottom:5 }}>Alterar status</div>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:4 }}>
              {statuses.map(s => {
                const c = GP_STATUS[s];
                const active = art.status === s;
                return (
                  <button key={s} onClick={() => onUpdateStatus(art.id, s)} style={{ padding:'5px 0', borderRadius:6, fontSize:11, fontWeight:600, fontFamily:'inherit', cursor: active ? 'default' : 'pointer', border: active ? `1.5px solid ${c.border}` : '1px solid var(--border-subtle)', background: active ? c.bg : 'transparent', color: active ? c.color : 'var(--fg-muted)', transition:'all 120ms' }}>
                    {c.label}
                  </button>
                );
              })}
            </div>
          </div>
        )}
        {[['Cliente',art.client],['Campanha',art.campaign],['Data',art.date||'—']].map(([l,v]) => (
          <div key={l} style={{ display:'flex', gap:8, alignItems:'baseline' }}>
            <span style={{ fontSize:11, color:'var(--fg-muted)', minWidth:56 }}>{l}</span>
            <span style={{ fontSize:12, color:'var(--fg-secondary)', flex:1, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{v||'—'}</span>
          </div>
        ))}
        {art.caption && (
          <div>
            <div style={{ fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.07em', color:'var(--fg-muted)', marginBottom:5 }}>Legenda</div>
            <div style={{ fontSize:12, color:'var(--fg-secondary)', lineHeight:1.5, background:'var(--bg-elevated)', borderRadius:8, padding:'8px 10px' }}>{art.caption}</div>
          </div>
        )}
        {art.tags && art.tags.length > 0 && (
          <div style={{ display:'flex', flexWrap:'wrap', gap:4 }}>
            {art.tags.map(t => <span key={t} style={{ fontSize:11, padding:'2px 8px', borderRadius:999, background:'var(--bg-elevated)', color:'var(--fg-secondary)', border:'1px solid var(--border-subtle)' }}>#{t}</span>)}
          </div>
        )}
        <button onClick={onRemove} style={{ marginTop:'auto', width:'100%', padding:'8px 0', borderRadius:8, background:'rgba(239,68,68,0.08)', border:'1px solid rgba(239,68,68,0.25)', color:'#FCA5A5', fontSize:12, fontWeight:600, fontFamily:'inherit', cursor:'pointer' }}>Remover do grid</button>
      </div>
    </div>
  );
}
function GridPreview() {
  // ── Persistência ──────────────────────────────────────────────────────────
  const [userId,      setUserId]      = useState('anon');
  const [loaded,      setLoaded]      = useState(false);
  // ── Clientes (Supabase) ───────────────────────────────────────────────────
  const [clients,     setClients]     = useState([{ id:'default', name:'Geral' }]);
  const [activeId,    setActiveId]    = useState('default');
  // ── Múltiplos grids por cliente ───────────────────────────────────────────
  // clientGrids: { [clientId]: [{ id, name }] }
  // activeGId:   { [clientId]: gridId }
  // gridsData:   { [gridId]: { cells, gridSize, userArts, hiddenIds } }
  const [clientGrids, setClientGrids] = useState({});
  const [activeGId,   setActiveGId]   = useState({});
  const [gridsData,   setGridsData]   = useState({});
  // ── UI ────────────────────────────────────────────────────────────────────
  const [selected,    setSelected]    = useState(null);
  const [search,      setSearch]      = useState('');
  const [filter,      setFilter]      = useState('all');
  const [mode,        setMode]        = useState('plan');
  const dragRef                       = useRef(null);
  const fileInputRef                  = useRef(null);

  // ── Load ──────────────────────────────────────────────────────────────────
  useEffect(() => {
    (async () => {
      try {
        // getSession() lê do localStorage — sem chamada de rede, sempre rápido
        const { data: { session } } = await sb.auth.getSession();
        const uid = session?.user?.id || 'anon';
        setUserId(uid);

        let savedActiveId = 'default';
        let savedCG = {}, savedAGId = {}, savedGD = {};

        try {
          // Tenta v3 (novo formato)
          const v3 = JSON.parse(localStorage.getItem('inbrivvo_grid_v3_' + uid) || 'null');
          if (v3) {
            savedActiveId = v3.activeId    || 'default';
            savedCG       = v3.clientGrids || {};
            savedAGId     = v3.activeGId   || {};
            savedGD       = v3.gridsData   || {};
          } else {
            // Migra v2 → v3 (formato antigo: gridsData[clientId] = { cells, ... })
            const v2 = JSON.parse(localStorage.getItem('inbrivvo_grid_v2_' + uid) || 'null');
            if (v2?.gridsData) {
              savedActiveId = v2.activeId || 'default';
              Object.entries(v2.gridsData).forEach(([clientId, data]) => {
                if (data && Array.isArray(data.cells)) {
                  const gid = 'g_' + clientId + '_mig';
                  savedCG[clientId]   = [{ id: gid, name: 'Grid 1' }];
                  savedAGId[clientId] = gid;
                  savedGD[gid]        = data;
                }
              });
            }
          }
        } catch(e) {}

        // Busca clientes do Supabase
        try {
          const { data: cd } = await sb.from('clients').select('id, name').order('name');
          const real = [{ id:'default', name:'Geral' }, ...(cd || [])];
          setClients(real);
          setActiveId(real.find(c => c.id === savedActiveId) ? savedActiveId : 'default');
        } catch(e) {
          setClients([{ id:'default', name:'Geral' }]);
          setActiveId('default');
        }

        setClientGrids(savedCG);
        setActiveGId(savedAGId);
        setGridsData(savedGD);
      } catch(e) { setUserId('anon'); }
      finally     { setLoaded(true); }
    })();
  }, []);

  // ── Save ──────────────────────────────────────────────────────────────────
  useEffect(() => {
    if (!loaded) return;
    try {
      localStorage.setItem('inbrivvo_grid_v3_' + userId,
        JSON.stringify({ activeId, clientGrids, activeGId, gridsData }));
    } catch(e) {}
  }, [loaded, userId, activeId, clientGrids, activeGId, gridsData]);

  // ── Garante que o cliente ativo tem pelo menos 1 grid ─────────────────────
  useEffect(() => {
    if (!loaded) return;
    const grids = clientGrids[activeId];
    if (!grids || grids.length === 0) {
      const gid = 'g_' + activeId + '_' + Date.now();
      setClientGrids(prev => ({ ...prev, [activeId]: [{ id: gid, name: 'Grid 1' }] }));
      setActiveGId(prev => ({ ...prev, [activeId]: gid }));
    } else if (!activeGId[activeId] || !grids.find(g => g.id === activeGId[activeId])) {
      setActiveGId(prev => ({ ...prev, [activeId]: grids[0].id }));
    }
  }, [activeId, loaded]);

  // ── Derived state ─────────────────────────────────────────────────────────
  const myGrids  = clientGrids[activeId] || [];
  const curGId   = activeGId[activeId] || myGrids[0]?.id || null;
  const cur      = curGId ? (gridsData[curGId] || { cells:[], gridSize:'3x3', userArts:[], hiddenIds:[] })
                           : { cells:[], gridSize:'3x3', userArts:[], hiddenIds:[] };
  const { cells, gridSize, userArts, hiddenIds } = cur;
  const hiddenSet = new Set(hiddenIds || []);
  const allArts   = [...(userArts || []), ...GP_ARTS].filter(a => !hiddenSet.has(a.id));
  const artMap    = Object.fromEntries(allArts.map(a => [a.id, a]));
  const rows      = { '3x3':3, '3x4':4, '3x5':5 }[gridSize] || 3;
  const total     = 3 * rows;
  const gridCells = Array.from({ length:total }, (_, i) => (cells||[])[i] || null);
  const filled    = gridCells.filter(Boolean);
  const selArt    = selected ? artMap[selected] : null;
  const kpiRasc   = filled.filter(id => artMap[id]?.status==='rascunho').length;
  const kpiAgen   = filled.filter(id => artMap[id]?.status==='agendado').length;
  const kpiPub    = filled.filter(id => artMap[id]?.status==='publicado').length;

  // ── Grid helpers ──────────────────────────────────────────────────────────
  function patchGrid(fn) {
    if (!curGId) return;
    setGridsData(prev => {
      const c = prev[curGId] || { cells:[], gridSize:'3x3', userArts:[], hiddenIds:[] };
      return { ...prev, [curGId]: typeof fn === 'function' ? fn(c) : { ...c, ...fn } };
    });
  }

  function addGrid() {
    const gid  = 'g_' + activeId + '_' + Date.now();
    const name = 'Grid ' + ((clientGrids[activeId]?.length || 0) + 1);
    setClientGrids(prev => ({ ...prev, [activeId]: [...(prev[activeId] || []), { id: gid, name }] }));
    setActiveGId(prev => ({ ...prev, [activeId]: gid }));
    setSelected(null);
  }

  function deleteGrid(gid) {
    const grids = clientGrids[activeId] || [];
    if (grids.length <= 1) { window.__toast?.('Precisa ter pelo menos 1 grid por cliente', { tone:'warning' }); return; }
    const rem = grids.filter(g => g.id !== gid);
    setClientGrids(prev => ({ ...prev, [activeId]: rem }));
    setGridsData(prev => { const n = {...prev}; delete n[gid]; return n; });
    if (activeGId[activeId] === gid) { setActiveGId(prev => ({ ...prev, [activeId]: rem[0].id })); setSelected(null); }
  }

  function handleDrop(toIdx) {
    if (!dragRef.current) return;
    const { source, artId, fromIdx } = dragRef.current;
    dragRef.current = null;
    patchGrid(c => {
      const t = 3 * ({ '3x3':3, '3x4':4, '3x5':5 }[c.gridSize] || 3);
      const next = Array.from({ length:t }, (_, i) => (c.cells||[])[i] || null);
      if (source==='library') { const ex=next.findIndex(id=>id===artId); if(ex!==-1)next[ex]=null; next[toIdx]=artId; }
      else { const tmp=next[toIdx]; next[toIdx]=next[fromIdx]; next[fromIdx]=tmp; }
      return { ...c, cells:next };
    });
  }

  function handleRemoveIdx(idx) {
    patchGrid(c => {
      const t = 3 * ({ '3x3':3, '3x4':4, '3x5':5 }[c.gridSize] || 3);
      const next = Array.from({ length:t }, (_, i) => (c.cells||[])[i] || null);
      next[idx] = null; return { ...c, cells:next };
    });
    setSelected(null);
  }

  function handleRemoveSel() {
    if (!selected) return;
    patchGrid(c => ({ ...c, cells:(c.cells||[]).map(id=>id===selected?null:id) }));
    setSelected(null);
  }

  function handleDeleteArt(artId) {
    patchGrid(c => ({
      ...c,
      userArts:  (c.userArts||[]).filter(a=>a.id!==artId),
      hiddenIds: [...(c.hiddenIds||[]), artId],
      cells:     (c.cells||[]).map(id=>id===artId?null:id),
    }));
    if (selected===artId) setSelected(null);
  }

  function updateArtStatus(artId, newStatus) {
    patchGrid(c => ({ ...c, userArts:(c.userArts||[]).map(a=>a.id===artId?{...a,status:newStatus}:a) }));
  }

  function handleFileUpload(e) {
    const files = Array.from(e.target.files);
    if (!files.length) return;
    Promise.all(files.map((file, i) => new Promise(resolve => {
      const reader = new FileReader();
      reader.onload = ev => resolve({
        id: 'u_' + Date.now() + '_' + i,
        title: file.name.replace(/\.[^.]+$/, ''),
        client: clients.find(c=>c.id===activeId)?.name || '',
        campaign:'', status:'rascunho', color:'var(--bg-elevated)',
        imageUrl: ev.target.result, caption:'', tags:[], date:'', notes:'',
      });
      reader.readAsDataURL(file);
    }))).then(newArts => patchGrid(c => ({ ...c, userArts:[...newArts, ...(c.userArts||[])] })));
    e.target.value = '';
  }

  const SIZES = ['3x3','3x4','3x5'];
  const MODES = [{ id:'plan', label:'Planejamento' }, { id:'preview', label:'Preview real' }];

  if (!loaded) return <div style={{ padding:40, textAlign:'center', color:'var(--fg-muted)', fontSize:14 }}>Carregando...</div>;

  return (
    <div style={{ padding:'24px 28px', display:'flex', flexDirection:'column', gap:16, height:'100%', boxSizing:'border-box', overflow:'auto' }}>

      {/* Header */}
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', flexWrap:'wrap', gap:12 }}>
        <div>
          <h1 style={{ margin:0, fontSize:22, fontWeight:800, fontFamily:'var(--font-display)', color:'var(--fg-primary)' }}>Grid de Preview</h1>
          <p style={{ margin:'4px 0 0', fontSize:13, color:'var(--fg-muted)' }}>Visualize e organize o feed por cliente antes de publicar</p>
        </div>
        <div style={{ display:'flex', gap:8 }}>
          <button onClick={() => { patchGrid(c=>({...c,cells:[]})); setSelected(null); }} style={{ padding:'8px 16px', borderRadius:8, border:'1px solid var(--border-subtle)', background:'transparent', color:'var(--fg-secondary)', fontSize:13, fontWeight:600, fontFamily:'inherit', cursor:'pointer' }}>Limpar Grid</button>
          <input ref={fileInputRef} type="file" accept="image/*" multiple style={{ display:'none' }} onChange={handleFileUpload} />
          <button onClick={() => fileInputRef.current?.click()} style={{ padding:'8px 16px', borderRadius:8, border:'1px solid var(--border-subtle)', background:'var(--bg-elevated)', color:'var(--fg-primary)', fontSize:13, fontWeight:600, fontFamily:'inherit', cursor:'pointer' }}>Importar Artes</button>
          <button onClick={() => window.__toast?.('Em breve!', { tone:'info' })} style={{ padding:'8px 16px', borderRadius:8, border:'none', background:'var(--primary)', color:'#fff', fontSize:13, fontWeight:600, fontFamily:'inherit', cursor:'pointer' }}>Exportar Preview</button>
        </div>
      </div>

      {/* Abas de clientes */}
      <div style={{ display:'flex', alignItems:'center', gap:6, flexWrap:'wrap' }}>
        {clients.map(c => (
          <button key={c.id} onClick={() => { setActiveId(c.id); setSelected(null); }} style={{ padding:'7px 14px', fontSize:13, fontWeight:600, fontFamily:'inherit', cursor:'pointer', borderRadius:8, border:`1px solid ${activeId===c.id?'var(--geek-blue-a40)':'var(--border-subtle)'}`, background:activeId===c.id?'var(--primary-soft)':'var(--bg-elevated)', color:activeId===c.id?'var(--geek-blue-200)':'var(--fg-secondary)' }}>{c.name}</button>
        ))}
        <span style={{ fontSize:11, color:'var(--fg-muted)', marginLeft:4 }}>· Sincronizados do módulo Clientes</span>
      </div>

      {/* Sub-abas: grids do cliente ativo */}
      <div style={{ display:'flex', alignItems:'center', gap:5, borderBottom:'1px solid var(--border-subtle)', paddingBottom:10, marginTop:-4 }}>
        <span style={{ fontSize:11, fontWeight:600, color:'var(--fg-muted)', marginRight:2 }}>Feeds:</span>
        {myGrids.map(g => (
          <div key={g.id} style={{ display:'inline-flex', alignItems:'center', borderRadius:6, border:`1px solid ${curGId===g.id?'var(--geek-blue-a40)':'var(--border-subtle)'}`, background:curGId===g.id?'var(--primary-wash)':'transparent', overflow:'hidden' }}>
            <button onClick={() => { setActiveGId(prev=>({...prev,[activeId]:g.id})); setSelected(null); }} style={{ padding:'4px 12px', fontSize:12, fontWeight:600, fontFamily:'inherit', cursor:'pointer', background:'transparent', border:'none', color:curGId===g.id?'var(--geek-blue-200)':'var(--fg-secondary)' }}>{g.name}</button>
            {myGrids.length > 1 && (
              <button onClick={() => deleteGrid(g.id)} style={{ padding:'0 7px 0 0', background:'transparent', border:'none', color:'var(--fg-muted)', cursor:'pointer', fontSize:15, lineHeight:'26px' }} title="Excluir feed">×</button>
            )}
          </div>
        ))}
        <button onClick={addGrid} style={{ padding:'4px 11px', borderRadius:6, border:'1px dashed var(--border-subtle)', background:'transparent', color:'var(--geek-blue-300)', fontSize:11, fontFamily:'inherit', cursor:'pointer', fontWeight:600 }}>+ Novo feed</button>
      </div>

      {/* KPI Cards */}
      <div style={{ display:'flex', gap:12, flexWrap:'wrap' }}>
        <GpKpi label="Posts no grid" value={filled.length} color="#1D39C4" />
        <GpKpi label="Rascunhos"     value={kpiRasc}       color="#71717A" />
        <GpKpi label="Agendados"     value={kpiAgen}       color="#0EA5E9" />
        <GpKpi label="Publicados"    value={kpiPub}        color="#7C3AED" />
      </div>

      {/* Toolbar */}
      <div style={{ display:'flex', alignItems:'center', gap:10, flexWrap:'wrap' }}>
        <span style={{ fontSize:12, color:'var(--fg-muted)', fontWeight:500 }}>Tamanho:</span>
        {SIZES.map(sz => <button key={sz} onClick={() => patchGrid(c=>({...c,gridSize:sz}))} style={{ padding:'5px 12px', borderRadius:6, fontSize:12, fontWeight:600, fontFamily:'inherit', cursor:'pointer', background:gridSize===sz?'var(--primary-soft)':'var(--bg-elevated)', color:gridSize===sz?'var(--geek-blue-200)':'var(--fg-secondary)', border:`1px solid ${gridSize===sz?'var(--geek-blue-a40)':'var(--border-subtle)'}` }}>{sz}</button>)}
        <div style={{ flex:1 }} />
        <div style={{ display:'flex', background:'var(--bg-elevated)', borderRadius:8, border:'1px solid var(--border-subtle)', overflow:'hidden' }}>
          {MODES.map(m => <button key={m.id} onClick={() => setMode(m.id)} style={{ padding:'6px 16px', fontSize:12, fontWeight:600, fontFamily:'inherit', cursor:'pointer', background:mode===m.id?'var(--primary)':'transparent', color:mode===m.id?'#fff':'var(--fg-muted)', border:'none', transition:'all 140ms' }}>{m.label}</button>)}
        </div>
      </div>

      {/* Layout 3 colunas */}
      <div style={{ display:'flex', gap:14, flex:1, minHeight:0, alignItems:'flex-start' }}>
        <GpLibrary arts={allArts} dragRef={dragRef} search={search} setSearch={setSearch} filter={filter} setFilter={setFilter} onDelete={handleDeleteArt} />
        <div style={{ flex:1, minWidth:0, background:mode==='preview'?'#fff':'var(--bg-surface)', borderRadius:12, border:'1px solid var(--border-subtle)', padding:mode==='preview'?2:8 }}>
          <div style={{ display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:mode==='preview'?2:6 }}>
            {gridCells.map((artId, idx) => (
              <GpCell key={idx} idx={idx} art={artId?artMap[artId]:null} mode={mode} dragRef={dragRef} onDrop={handleDrop} onRemove={handleRemoveIdx} selected={selected} onClick={setSelected} />
            ))}
          </div>
        </div>
        <GpDetails art={selArt} onRemove={handleRemoveSel} onUpdateStatus={updateArtStatus} />
      </div>
    </div>
  );
}
// ─── End Grid de Preview ──────────────────────────────────────────────────────

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "dark",
  "accent": "#1D39C4",
  "density": "confortavel",
  "showWelcome": true
}/*EDITMODE-END*/;

// ─── Paywall ─────────────────────────────────────────────────────────────────
const CAKTO_URL_MENSAL = 'https://pay.cakto.com.br/38vm695_679341';
const CAKTO_URL_ANUAL  = 'https://pay.cakto.com.br/us3762i';

function Paywall({ onLogout, onRefresh }) {
  const [checking, setChecking] = React.useState(false);
  const [noSub,    setNoSub]    = React.useState(false); // feedback após verificar sem assinatura ativa

  async function handleRefresh() {
    setChecking(true);
    setNoSub(false);
    try {
      const isActive = await onRefresh(); // onRefresh retorna true se ativou
      if (!isActive) setNoSub(true);      // sem assinatura: mostra aviso
    } catch (e) {
      setNoSub(true); // erro de rede: trata como "não encontrado"
    } finally {
      setChecking(false);
    }
  }

  return (
    <div style={{ minHeight:'100vh', display:'grid', placeItems:'center', background:'var(--bg-app)', padding:24 }}>
      <div style={{ width:'100%', maxWidth:520, display:'flex', flexDirection:'column', gap:24 }}>
        {/* Logo */}
        <div style={{ textAlign:'center' }}>
          <div style={{ display:'inline-flex', alignItems:'center', gap:10, marginBottom:8 }}>
            <div style={{ width:40, height:40, borderRadius:10, background:'var(--primary)', display:'grid', placeItems:'center', flexShrink:0 }}>
              <span style={{ color:'#fff', fontWeight:800, fontSize:16 }}>in</span>
            </div>
            <span style={{ fontSize:22, fontWeight:800, letterSpacing:'-0.02em' }}>inBrivvo</span>
          </div>
        </div>

        {/* Card */}
        <div style={{ background:'var(--bg-surface)', border:'1px solid var(--border-subtle)', borderRadius:16, padding:'36px 32px', display:'flex', flexDirection:'column', gap:20 }}>
          <div style={{ textAlign:'center' }}>
            <div style={{ fontSize:32, marginBottom:12 }}>🔒</div>
            <h2 style={{ margin:'0 0 8px', fontSize:22, fontWeight:800 }}>Assine para acessar</h2>
            <p style={{ margin:0, fontSize:14, color:'var(--fg-secondary)', lineHeight:1.6 }}>
              Sua conta está criada. Para acessar o inBrivvo, escolha um plano abaixo.
              Você garante o preço de fundador para sempre.
            </p>
          </div>

          {/* Aviso: sem assinatura ativa após verificação */}
          {noSub && (
            <div style={{ display:'flex', gap:12, alignItems:'flex-start', padding:'14px 16px', borderRadius:10, background:'rgba(255,190,0,0.08)', border:'1px solid rgba(255,190,0,0.25)' }}>
              <span style={{ fontSize:18, flexShrink:0 }}>⚠️</span>
              <div>
                <div style={{ fontSize:13, fontWeight:700, color:'#FAAD14', marginBottom:4 }}>Assinatura não encontrada</div>
                <div style={{ fontSize:13, color:'var(--fg-secondary)', lineHeight:1.5 }}>
                  Não identificamos uma assinatura ativa para este e-mail. Se você acabou de pagar, aguarde alguns segundos e tente novamente. Se o problema persistir, entre em contato pelo suporte.
                </div>
              </div>
            </div>
          )}

          {/* Mensal */}
          <a href={CAKTO_URL_MENSAL} target="_blank" rel="noopener noreferrer"
            style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'18px 20px', borderRadius:12, border:'1px solid var(--border-strong)', background:'var(--bg-elevated)', textDecoration:'none' }}>
            <div>
              <div style={{ fontSize:15, fontWeight:700, color:'var(--fg-primary)' }}>Mensal</div>
              <div style={{ fontSize:12, color:'var(--fg-muted)', marginTop:2 }}>Cancele quando quiser</div>
            </div>
            <div style={{ display:'flex', alignItems:'center', gap:14 }}>
              <span style={{ fontSize:20, fontWeight:800, color:'var(--fg-primary)' }}>R$47<span style={{ fontSize:12, fontWeight:400, color:'var(--fg-muted)' }}>/mês</span></span>
              <span style={{ padding:'8px 16px', borderRadius:8, background:'var(--bg-surface)', border:'1px solid var(--border-subtle)', fontSize:13, fontWeight:600, color:'var(--fg-secondary)' }}>Assinar →</span>
            </div>
          </a>

          {/* Anual */}
          <a href={CAKTO_URL_ANUAL} target="_blank" rel="noopener noreferrer"
            style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'18px 20px', borderRadius:12, border:'2px solid var(--primary)', background:'linear-gradient(135deg,rgba(29,57,196,0.1),transparent)', textDecoration:'none', position:'relative' }}>
            <div style={{ position:'absolute', top:-1, right:14, background:'var(--primary)', color:'#fff', fontSize:9, fontWeight:800, padding:'3px 10px', borderRadius:'0 0 7px 7px', textTransform:'uppercase', letterSpacing:'0.06em' }}>MELHOR OFERTA</div>
            <div>
              <div style={{ fontSize:15, fontWeight:700, color:'var(--geek-blue-200)' }}>Anual</div>
              <div style={{ fontSize:12, color:'var(--fg-muted)', marginTop:2 }}>≈ R$33/mês · economize R$167</div>
            </div>
            <div style={{ display:'flex', alignItems:'center', gap:14 }}>
              <span style={{ fontSize:20, fontWeight:800, color:'var(--geek-blue-200)' }}>R$397<span style={{ fontSize:12, fontWeight:400, color:'var(--fg-muted)' }}>/ano</span></span>
              <span style={{ padding:'8px 16px', borderRadius:8, background:'var(--primary)', fontSize:13, fontWeight:700, color:'#fff' }}>Assinar →</span>
            </div>
          </a>

          <p style={{ margin:0, fontSize:11, color:'var(--fg-muted)', textAlign:'center' }}>
            Pagamento seguro via Cakto · PIX, cartão de crédito e boleto
          </p>

          {/* Já paguei */}
          <button onClick={handleRefresh} disabled={checking}
            style={{ width:'100%', padding:'12px 0', borderRadius:10, border:'1px solid var(--border-subtle)', background:'transparent', color: checking ? 'var(--fg-muted)' : 'var(--fg-secondary)', fontSize:13, fontWeight:600, cursor: checking ? 'default' : 'pointer', fontFamily:'inherit', transition:'color 150ms' }}>
            {checking ? 'Verificando…' : '✓ Já assinei — verificar acesso'}
          </button>
        </div>

        <button onClick={onLogout}
          style={{ background:'transparent', border:'none', color:'var(--fg-muted)', fontSize:12, cursor:'pointer', textAlign:'center', fontFamily:'inherit' }}>
          Sair da conta
        </button>
      </div>
    </div>
  );
}

// ── Public Budget Viewer ──────────────────────────────────────────────────────
// ─── Public Assinatura Page ───────────────────────────────────────────────────
function PublicAssinaturaPage({ budget, num, COR1, COR2, GRD, onBack, onDone }) {
  const [nome,    setNome]    = React.useState('');
  const [empresa, setEmpresa] = React.useState('');
  const [doc,     setDoc]     = React.useState('');
  const [email,   setEmail]   = React.useState('');
  const [cel,     setCel]     = React.useState('');
  const [hasSig,  setHasSig]  = React.useState(false);
  const [saving,  setSaving]  = React.useState(false);
  const canvasRef = React.useRef(null);
  const drawing   = React.useRef(false);
  const fmtBRL = v => v ? 'R$ ' + Number(v).toLocaleString('pt-BR', {minimumFractionDigits:2,maximumFractionDigits:2}) : '—';
  const total  = Number(budget.total) || (budget.items||[]).reduce((a,i)=>a+(i.q||1)*(i.p||0),0);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const rect = canvas.getBoundingClientRect();
    canvas.width  = rect.width  * (window.devicePixelRatio||1);
    canvas.height = rect.height * (window.devicePixelRatio||1);
    const ctx = canvas.getContext('2d');
    ctx.scale(window.devicePixelRatio||1, window.devicePixelRatio||1);
  }, []);

  function getPos(e) {
    const canvas = canvasRef.current;
    const rect   = canvas.getBoundingClientRect();
    const src    = e.touches ? e.touches[0] : e;
    return { x: src.clientX - rect.left, y: src.clientY - rect.top };
  }
  function startDraw(e) { e.preventDefault(); const ctx = canvasRef.current.getContext('2d'); const p = getPos(e); ctx.beginPath(); ctx.moveTo(p.x, p.y); drawing.current = true; }
  function drawSig(e)   { if (!drawing.current) return; e.preventDefault(); const ctx = canvasRef.current.getContext('2d'); const p = getPos(e); ctx.lineTo(p.x, p.y); ctx.strokeStyle='#111'; ctx.lineWidth=2.5; ctx.lineCap='round'; ctx.lineJoin='round'; ctx.stroke(); if (!hasSig) setHasSig(true); }
  function endDraw()    { drawing.current = false; }
  function clearCanvas(){ const c = canvasRef.current; c.getContext('2d').clearRect(0,0,c.width,c.height); setHasSig(false); }

  async function aprovar() {
    if (!nome.trim() || !doc.trim() || !hasSig) { alert('Preencha nome, CPF/CNPJ e realize a assinatura.'); return; }
    setSaving(true);
    try {
      const sigData = canvasRef.current.toDataURL('image/png');
      const dbNum   = num.startsWith('#') ? num : '#' + num;
      await sb.from('budgets').update({
        status:         'aprovado',
        approved_by:    [nome, empresa, doc, email, cel].filter(Boolean).join(' · '),
        approved_at:    new Date().toISOString(),
        signature_data: sigData,
      }).eq('budget_num', dbNum);
      onDone();
    } catch(err) { alert('Erro ao salvar: ' + err.message); } finally { setSaving(false); }
  }

  const INP = { width:'100%', padding:'12px 14px', borderRadius:10, border:'1px solid rgba(255,255,255,0.12)', background:'rgba(255,255,255,0.06)', color:'#fff', fontSize:14, fontFamily:'inherit', outline:'none', boxSizing:'border-box' };
  const LBL = { fontSize:12, color:'rgba(255,255,255,0.45)', marginBottom:6, fontWeight:600, display:'block' };

  return (
    <div style={{ minHeight:'100vh', background:'#080C18', color:'#fff', fontFamily:'system-ui,-apple-system,sans-serif', padding:'0 0 60px', position:'relative', overflow:'hidden' }}>
      {/* bg blob */}
      <div style={{ position:'fixed', top:'-10%', right:'-5%', width:'40%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle,${COR1}30 0%,transparent 70%)`, filter:'blur(80px)', pointerEvents:'none', zIndex:0 }}/>
      {/* Header */}
      <div style={{ position:'sticky', top:0, zIndex:10, display:'flex', alignItems:'center', justifyContent:'space-between', padding:'16px 28px', background:'rgba(8,12,24,0.9)', backdropFilter:'blur(12px)', borderBottom:'1px solid rgba(255,255,255,0.07)' }}>
        <div style={{ display:'flex', alignItems:'center', gap:10 }}>
          <div style={{ width:28,height:28,borderRadius:7,background:GRD,display:'flex',alignItems:'center',justifyContent:'center' }}><span style={{ fontSize:12,fontWeight:900,color:'#fff' }}>iB</span></div>
          <span style={{ fontSize:14,fontWeight:700 }}>inBrivvo</span>
        </div>
        <button onClick={onBack} style={{ background:'transparent', border:'1px solid rgba(255,255,255,0.15)', color:'rgba(255,255,255,0.6)', padding:'7px 16px', borderRadius:8, fontSize:13, cursor:'pointer', fontFamily:'inherit' }}>← Voltar</button>
      </div>

      <div style={{ maxWidth:700, margin:'0 auto', padding:'32px 24px 0', position:'relative', zIndex:1 }}>
        {/* Hero */}
        <div style={{ textAlign:'center', marginBottom:32 }}>
          <div style={{ display:'inline-flex', alignItems:'center', gap:6, padding:'4px 14px', borderRadius:999, border:`1px solid ${COR1}50`, background:`${COR1}15`, marginBottom:16 }}>
            <span style={{ fontSize:11, fontWeight:700, color:COR1, letterSpacing:'0.07em', textTransform:'uppercase' }}>Proposta Comercial · {'#'+num.replace(/^#/,'')}</span>
          </div>
          <h1 style={{ margin:'0 0 8px', fontSize:26, fontWeight:900 }}>{budget.title || 'Proposta de Serviço'}</h1>
          <div style={{ fontSize:14, color:'rgba(255,255,255,0.4)' }}>Valor: <strong style={{ color:'#fff' }}>{fmtBRL(total)}</strong></div>
        </div>

        {/* Detalhes do projeto */}
        {budget.budget_desc && (
          <div style={{ padding:'18px 20px', borderRadius:12, border:'1px solid rgba(255,255,255,0.07)', background:'rgba(255,255,255,0.03)', marginBottom:16 }}>
            <div style={{ fontSize:13, fontWeight:700, color:'rgba(255,255,255,0.7)', marginBottom:8, display:'flex', alignItems:'center', gap:8 }}>📄 Detalhes do projeto</div>
            <p style={{ margin:0, fontSize:13, color:'rgba(255,255,255,0.55)', lineHeight:1.6 }}>{budget.budget_desc}</p>
          </div>
        )}

        {/* Serviços + Condições */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr 260px', gap:14, marginBottom:16 }}>
          <div style={{ padding:'18px 20px', borderRadius:12, border:'1px solid rgba(255,255,255,0.07)', background:'rgba(255,255,255,0.03)' }}>
            <div style={{ fontSize:13, fontWeight:700, color:'rgba(255,255,255,0.7)', marginBottom:12, display:'flex', alignItems:'center', gap:8 }}>✅ Serviços incluídos ({(budget.items||[]).filter(it=>it.p>0).length})</div>
            {(budget.items||[]).filter(it=>it.p>0).map((it,i)=>(
              <div key={i} style={{ padding:'8px 12px', borderRadius:8, background:'rgba(255,255,255,0.04)', marginBottom:6, display:'flex', justifyContent:'space-between', alignItems:'flex-start' }}>
                <div>
                  <div style={{ fontSize:13, fontWeight:600, color:'#fff' }}>{it.d||it.desc}</div>
                  <div style={{ fontSize:11, color:'rgba(255,255,255,0.35)', marginTop:2 }}>{it.q||1} × {fmtBRL(it.p)}</div>
                </div>
                <div style={{ fontSize:13, fontWeight:700, color:'rgba(255,255,255,0.7)', whiteSpace:'nowrap', marginLeft:12 }}>{fmtBRL((it.q||1)*it.p)}</div>
              </div>
            ))}
            <div style={{ display:'flex', justifyContent:'space-between', padding:'10px 0 0', borderTop:'1px solid rgba(255,255,255,0.07)', marginTop:4 }}>
              <span style={{ fontSize:14, fontWeight:700 }}>Total:</span>
              <span style={{ fontSize:18, fontWeight:900, color:COR1 }}>{fmtBRL(total)}</span>
            </div>
          </div>
          <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
            <div style={{ padding:'16px 18px', borderRadius:12, border:'1px solid rgba(255,255,255,0.07)', background:'rgba(255,255,255,0.03)' }}>
              <div style={{ fontSize:13, fontWeight:700, color:'rgba(255,255,255,0.7)', marginBottom:10 }}>💰 Condições</div>
              {[['Forma', (budget.pay_method||'PIX').toUpperCase()], ['Condições', budget.pay_terms||'—'], ['Prazo', `${budget.delivery_days||30} dias`]].map(([l,v])=>(
                <div key={l} style={{ marginBottom:8 }}>
                  <div style={{ fontSize:11, color:'rgba(255,255,255,0.35)' }}>{l}:</div>
                  <div style={{ fontSize:13, fontWeight:600, color:'#fff' }}>{v}</div>
                </div>
              ))}
            </div>
          </div>
        </div>

        {/* Assinatura Digital */}
        <div style={{ padding:'24px', borderRadius:14, border:`1px solid ${COR1}30`, background:'rgba(255,255,255,0.03)' }}>
          <div style={{ fontSize:14, fontWeight:700, color:'#fff', marginBottom:20, display:'flex', alignItems:'center', gap:8 }}>✍️ Assinatura Digital</div>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12, marginBottom:12 }}>
            <div><label style={LBL}>Nome completo *</label><input value={nome} onChange={e=>setNome(e.target.value)} placeholder="Seu nome completo" style={INP}/></div>
            <div><label style={LBL}>Empresa</label><input value={empresa} onChange={e=>setEmpresa(e.target.value)} placeholder="Nome da empresa" style={INP}/></div>
          </div>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12, marginBottom:12 }}>
            <div><label style={LBL}>CPF ou CNPJ *</label><input value={doc} onChange={e=>setDoc(e.target.value)} placeholder="000.000.000-00" style={INP}/></div>
            <div><label style={LBL}>Email</label><input value={email} onChange={e=>setEmail(e.target.value)} placeholder="seu@email.com" style={INP}/></div>
          </div>
          <div style={{ marginBottom:16 }}>
            <label style={LBL}>Celular</label>
            <input value={cel} onChange={e=>setCel(e.target.value)} placeholder="(00) 00000-0000" style={{ ...INP, maxWidth:240 }}/>
          </div>
          <div style={{ marginBottom:20 }}>
            <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:8 }}>
              <label style={{ ...LBL, margin:0 }}>Assinatura * <span style={{ opacity:0.5, fontWeight:400 }}>(mouse, dedo ou caneta)</span></label>
              {hasSig && <button onClick={clearCanvas} style={{ background:'transparent', border:'none', color:'rgba(255,255,255,0.35)', cursor:'pointer', fontSize:12, fontFamily:'inherit', padding:0 }}>Limpar</button>}
            </div>
            <div style={{ borderRadius:12, overflow:'hidden', border: hasSig ? `2px solid ${COR1}` : '2px dashed rgba(255,255,255,0.15)', background:'#fff', position:'relative', boxShadow: hasSig ? `0 0 20px ${COR1}35` : 'none' }}>
              <canvas ref={canvasRef} style={{ display:'block', width:'100%', height:150, cursor:'crosshair', touchAction:'none' }}
                onMouseDown={startDraw} onMouseMove={drawSig} onMouseUp={endDraw} onMouseLeave={endDraw}
                onTouchStart={startDraw} onTouchMove={drawSig} onTouchEnd={endDraw}/>
              {!hasSig && <div style={{ position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center', pointerEvents:'none', color:'rgba(0,0,0,0.18)', fontSize:14, fontStyle:'italic' }}>Assine aqui</div>}
            </div>
          </div>
          <button onClick={aprovar} disabled={saving} style={{ width:'100%', padding:'15px 0', borderRadius:12, background:GRD, border:'none', color:'#fff', fontSize:15, fontWeight:800, cursor:saving?'not-allowed':'pointer', fontFamily:'inherit', opacity:saving?0.7:1, boxShadow:`0 8px 24px ${COR1}45`, letterSpacing:'-0.01em' }}>
            {saving ? 'Salvando assinatura…' : '✓ Confirmar aprovação da proposta'}
          </button>
          <div style={{ marginTop:12, fontSize:12, color:'rgba(255,255,255,0.25)', textAlign:'center' }}>Ao aprovar, você concorda com os termos desta proposta.</div>
        </div>
      </div>
    </div>
  );
}

// ─── Slides Public View ───────────────────────────────────────────────────────
function SlidesPublicView({ budget, num, approved, setApproved }) {
  const cfg   = budget.slide_config || {};
  const COR1  = cfg.cor1     || '#FF6A6A';
  const COR2  = cfg.cor2     || '#FA8C16';
  const TITLE = cfg.title    || budget.title || 'Proposta de Serviço';
  const SUBT  = cfg.subtitle || budget.client_name || 'Para você';
  const BG    = '#080C18';
  const GRD   = `linear-gradient(135deg,${COR1},${COR2})`;

  const [slide,          setSlide]          = React.useState(0);
  const [showAssinatura, setShowAssinatura] = React.useState(false);

  const fmtBRL = v => v ? 'R$ ' + Number(v).toLocaleString('pt-BR', { minimumFractionDigits:2, maximumFractionDigits:2 }) : '—';
  const rawItems = budget.items || [];
  const items    = Array.isArray(rawItems) ? rawItems : (typeof rawItems === 'string' ? (() => { try { return JSON.parse(rawItems); } catch(_) { return []; } })() : []);
  const total    = Number(budget.total) || items.reduce((a,i)=>a+(Number(i.q)||1)*(Number(i.p)||0),0);
  const validDate = budget.valid_until ? new Date(budget.valid_until).toLocaleDateString('pt-BR') : null;
  const INTRO    = cfg.intro    || budget.budget_desc || null;
  const PROBLEMA = cfg.problema || null;
  const SOLUCAO  = cfg.solucao  || null;
  const itemDesc = it => (it && (it.d || it.desc || it.description || it.name || '')) || '';

  const slides = [
    { id:'cover' },
    { id:'intro' },
    { id:'problema' },
    { id:'solucao' },
    ...(items.length > 0 ? [{ id:'entregaveis' }] : []),
    { id:'preco' },
    ...(budget.delivery_days ? [{ id:'timeline' }] : []),
    { id:'cta' },
  ];
  const N   = slides.length;
  const cur = slides[slide];

  const goNext = () => setSlide(s => Math.min(s+1, N-1));
  const goPrev = () => setSlide(s => Math.max(s-1, 0));

  React.useEffect(() => {
    const handler = e => {
      if (e.key==='ArrowRight'||e.key==='ArrowDown') goNext();
      if (e.key==='ArrowLeft' ||e.key==='ArrowUp')   goPrev();
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [slide]);

  // Se está na página de assinatura, renderiza ela
  if (showAssinatura && !approved) {
    return <PublicAssinaturaPage
      budget={budget} num={num} COR1={COR1} COR2={COR2} GRD={GRD}
      onBack={() => setShowAssinatura(false)}
      onDone={() => { setApproved(true); setShowAssinatura(false); }}
    />;
  }

  // ── Slide wrapper ────────────────────────────────────────────────────────
  const NavBar = () => (
    <div style={{ position:'fixed', bottom:0, left:0, right:0, height:64, display:'flex', alignItems:'center', justifyContent:'space-between', padding:'0 32px', background:'rgba(8,12,24,0.92)', backdropFilter:'blur(16px)', borderTop:`1px solid ${COR1}22`, zIndex:10 }}>
      <button onClick={goPrev} disabled={slide===0} style={{ padding:'8px 22px', borderRadius:8, border:`1px solid ${slide===0?'rgba(255,255,255,0.1)':'rgba(255,255,255,0.2)'}`, background:'transparent', color:slide===0?'rgba(255,255,255,0.2)':'#fff', fontSize:13, fontWeight:600, cursor:slide===0?'default':'pointer', fontFamily:'inherit' }}>← Anterior</button>
      <div style={{ display:'flex', gap:7, alignItems:'center' }}>
        {slides.map((_,i) => (
          <div key={i} onClick={()=>setSlide(i)} style={{ width:i===slide?28:8, height:8, borderRadius:999, background:i===slide?COR1:'rgba(255,255,255,0.18)', cursor:'pointer', transition:'all 220ms ease' }}/>
        ))}
      </div>
      {slide < N-1
        ? <button onClick={goNext} style={{ padding:'8px 22px', borderRadius:8, border:'none', background:GRD, color:'#fff', fontSize:13, fontWeight:700, cursor:'pointer', fontFamily:'inherit', boxShadow:`0 4px 16px ${COR1}55` }}>Próximo →</button>
        : <div style={{ width:100 }}/>
      }
    </div>
  );

  const TopBar = () => (
    <div style={{ position:'fixed', top:0, left:0, right:0, height:56, display:'flex', alignItems:'center', justifyContent:'space-between', padding:'0 28px', background:'rgba(8,12,24,0.85)', backdropFilter:'blur(12px)', borderBottom:'1px solid rgba(255,255,255,0.06)', zIndex:10 }}>
      <div style={{ display:'flex', alignItems:'center', gap:10 }}>
        <div style={{ width:28, height:28, borderRadius:7, background:GRD, display:'flex', alignItems:'center', justifyContent:'center' }}><span style={{ fontSize:12, fontWeight:900, color:'#fff' }}>iB</span></div>
        <span style={{ fontSize:14, fontWeight:700, color:'#fff' }}>inBrivvo</span>
      </div>
      <span style={{ fontSize:12, color:'rgba(255,255,255,0.35)', fontFamily:'monospace' }}>{'#'+num.replace(/^#/,'')}</span>
    </div>
  );

  const SlideWrap = ({ children, bg }) => (
    <div style={{ minHeight:'100vh', background: bg || BG, color:'#fff', fontFamily:'system-ui,-apple-system,sans-serif', position:'relative', overflow:'hidden' }}>
      <TopBar/>
      <div style={{ paddingTop:56, paddingBottom:80, minHeight:'100vh', display:'flex', alignItems:'center', justifyContent:'center', boxSizing:'border-box' }}>
        <div style={{ width:'100%', maxWidth:760, padding:'0 32px' }}>
          {children}
        </div>
      </div>
      <NavBar/>
    </div>
  );

  // ── SLIDE 1 — Cover ─────────────────────────────────────────────────────
  if (cur.id === 'cover') return (
    <SlideWrap>
      {/* Background blobs */}
      <div style={{ position:'fixed', inset:0, pointerEvents:'none', overflow:'hidden', zIndex:0 }}>
        <div style={{ position:'absolute', top:'-10%', left:'-10%', width:'55%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle, ${COR1}40 0%, transparent 70%)`, filter:'blur(60px)' }}/>
        <div style={{ position:'absolute', bottom:'-10%', right:'-5%', width:'45%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle, ${COR2}35 0%, transparent 70%)`, filter:'blur(80px)' }}/>
      </div>
      <div style={{ position:'relative', zIndex:1, textAlign:'center' }}>
        <div style={{ display:'inline-flex', alignItems:'center', gap:6, padding:'5px 16px', borderRadius:999, border:`1px solid ${COR1}60`, background:`${COR1}18`, marginBottom:28 }}>
          <span style={{ fontSize:11, fontWeight:700, color:COR1, letterSpacing:'0.08em', textTransform:'uppercase' }}>Proposta Comercial</span>
        </div>
        <h1 style={{ margin:'0 0 18px', fontSize:52, fontWeight:900, lineHeight:1.05, letterSpacing:'-0.03em', background:GRD, WebkitBackgroundClip:'text', WebkitTextFillColor:'transparent' }}>{TITLE}</h1>
        <p style={{ margin:'0 0 48px', fontSize:18, color:'rgba(255,255,255,0.5)', lineHeight:1.6 }}>
          Para <strong style={{ color:'rgba(255,255,255,0.85)' }}>{SUBT}</strong>
          {validDate && <> · Válida até <strong style={{ color:'rgba(255,255,255,0.85)' }}>{validDate}</strong></>}
        </p>
        {/* Stats strip */}
        <div style={{ display:'inline-flex', gap:0, borderRadius:16, overflow:'hidden', border:`1px solid ${COR1}30`, background:'rgba(255,255,255,0.03)' }}>
          {[
            ['Investimento', fmtBRL(total), true],
            ...(budget.delivery_days ? [['Prazo', `${budget.delivery_days} dias`, false]] : []),
            ...(budget.pay_method    ? [['Pagamento', budget.pay_method.toUpperCase(), false]] : []),
          ].map(([l,v,accent], i, arr) => (
            <div key={i} style={{ padding:'18px 28px', textAlign:'center', borderRight: i<arr.length-1 ? `1px solid ${COR1}20` : 'none' }}>
              <div style={{ fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.08em', color:'rgba(255,255,255,0.35)', marginBottom:6 }}>{l}</div>
              <div style={{ fontSize:accent?22:18, fontWeight:900, color:accent?COR1:'#fff' }}>{v}</div>
            </div>
          ))}
        </div>
        <div style={{ marginTop:36, fontSize:13, color:'rgba(255,255,255,0.25)' }}>Use ← → para navegar · {N} slides</div>
      </div>
    </SlideWrap>
  );

  // ── SLIDE 2 — Intro ─────────────────────────────────────────────────────
  if (cur.id === 'intro') return (
    <SlideWrap>
      <div style={{ position:'fixed', inset:0, pointerEvents:'none', zIndex:0 }}>
        <div style={{ position:'absolute', top:'15%', left:'-8%', width:'45%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle,${COR1}30 0%,transparent 70%)`, filter:'blur(70px)' }}/>
        <div style={{ position:'absolute', bottom:'10%', right:'-5%', width:'35%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle,${COR2}25 0%,transparent 70%)`, filter:'blur(80px)' }}/>
      </div>
      <div style={{ position:'relative', zIndex:1 }}>
        <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.09em', color:COR1, marginBottom:16 }}>Sobre esta proposta</div>
        <h2 style={{ margin:'0 0 10px', fontSize:42, fontWeight:900, lineHeight:1.1, letterSpacing:'-0.02em' }}>{TITLE}</h2>
        <p style={{ margin:'0 0 36px', fontSize:16, color:'rgba(255,255,255,0.45)', lineHeight:1.7, maxWidth:580 }}>
          {INTRO || 'Esta proposta foi elaborada com dedicação e atenção a cada detalhe do seu projeto. Cada entregável foi pensado para gerar o máximo de resultado para o seu negócio.'}
        </p>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:12 }}>
          {[
            ['🎯', 'Projeto', TITLE],
            ['👤', 'Cliente', SUBT],
            ['📦', 'Entregas', `${items.length} ${items.length === 1 ? 'item' : 'itens'}`],
          ].map(([ic,l,v],i) => (
            <div key={i} style={{ padding:'20px 18px', borderRadius:14, background:'rgba(255,255,255,0.04)', border:`1px solid rgba(255,255,255,0.08)`, textAlign:'center' }}>
              <div style={{ fontSize:26, marginBottom:8 }}>{ic}</div>
              <div style={{ fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.07em', color:'rgba(255,255,255,0.35)', marginBottom:6 }}>{l}</div>
              <div style={{ fontSize:14, fontWeight:700, color:'#fff' }}>{v}</div>
            </div>
          ))}
        </div>
        {validDate && (
          <div style={{ marginTop:16, padding:'12px 20px', borderRadius:12, background:`${COR1}15`, border:`1px solid ${COR1}30`, display:'inline-flex', alignItems:'center', gap:8 }}>
            <span style={{ fontSize:13 }}>📅</span>
            <span style={{ fontSize:13, color:'rgba(255,255,255,0.7)' }}>Proposta válida até <strong style={{ color:'#fff' }}>{validDate}</strong></span>
          </div>
        )}
      </div>
    </SlideWrap>
  );

  // ── SLIDE 3 — Problema ───────────────────────────────────────────────────
  if (cur.id === 'problema') return (
    <SlideWrap>
      <div style={{ position:'fixed', inset:0, pointerEvents:'none', zIndex:0 }}>
        <div style={{ position:'absolute', top:'25%', right:'-8%', width:'42%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle,${COR1}22 0%,transparent 70%)`, filter:'blur(80px)' }}/>
      </div>
      <div style={{ position:'relative', zIndex:1 }}>
        <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.09em', color:COR1, marginBottom:16 }}>O desafio</div>
        <h2 style={{ margin:'0 0 12px', fontSize:40, fontWeight:900, lineHeight:1.1, letterSpacing:'-0.02em' }}>Por que você precisa disso?</h2>
        {PROBLEMA ? (
          <>
            <p style={{ margin:'0 0 36px', fontSize:16, color:'rgba(255,255,255,0.55)', lineHeight:1.75, maxWidth:580 }}>{PROBLEMA}</p>
          </>
        ) : (
          <>
            <p style={{ margin:'0 0 28px', fontSize:16, color:'rgba(255,255,255,0.45)', lineHeight:1.7, maxWidth:580 }}>
              {INTRO
                ? `Para o projeto "${TITLE}", identificamos os seguintes pontos críticos que esta proposta resolve:`
                : `Para "${TITLE}", estruturamos uma solução que endereça os principais desafios do projeto:`}
            </p>
            <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
              {items.length > 0
                ? items.slice(0,3).map((it,i) => {
                    const d = itemDesc(it);
                    return d ? (
                      <div key={i} style={{ display:'flex', gap:14, padding:'16px 20px', borderRadius:14, background:'rgba(255,255,255,0.03)', border:`1px solid rgba(255,255,255,0.07)` }}>
                        <div style={{ width:28, height:28, borderRadius:8, background:`${COR1}28`, border:`1px solid ${COR1}40`, display:'flex', alignItems:'center', justifyContent:'center', fontSize:13, flexShrink:0, color:COR1, fontWeight:700 }}>{i+1}</div>
                        <div style={{ fontSize:14, color:'rgba(255,255,255,0.65)', lineHeight:1.6, paddingTop:3 }}>{d}</div>
                      </div>
                    ) : null;
                  })
                : [
                    ['⚡', 'Tempo e organização', 'Estruturar processos que gerem mais resultado com menos esforço.'],
                    ['📈', 'Crescimento estratégico', 'Atingir os objetivos de negócio com uma abordagem consistente.'],
                    ['🎯', 'Resultado concreto', 'Entregas claras, mensuráveis e alinhadas com a sua visão.'],
                  ].map(([ic,t,d],i) => (
                    <div key={i} style={{ display:'flex', gap:14, padding:'16px 20px', borderRadius:14, background:'rgba(255,255,255,0.03)', border:`1px solid rgba(255,255,255,0.07)` }}>
                      <div style={{ fontSize:22, flexShrink:0 }}>{ic}</div>
                      <div>
                        <div style={{ fontSize:14, fontWeight:700, color:'#fff', marginBottom:3 }}>{t}</div>
                        <div style={{ fontSize:13, color:'rgba(255,255,255,0.4)', lineHeight:1.6 }}>{d}</div>
                      </div>
                    </div>
                  ))
              }
            </div>
          </>
        )}
      </div>
    </SlideWrap>
  );

  // ── SLIDE 4 — Solução ────────────────────────────────────────────────────
  if (cur.id === 'solucao') return (
    <SlideWrap>
      <div style={{ position:'fixed', inset:0, pointerEvents:'none', zIndex:0 }}>
        <div style={{ position:'absolute', bottom:'15%', left:'-5%', width:'42%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle,${COR2}28 0%,transparent 70%)`, filter:'blur(80px)' }}/>
      </div>
      <div style={{ position:'relative', zIndex:1 }}>
        <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.09em', color:COR1, marginBottom:16 }}>A solução</div>
        <h2 style={{ margin:'0 0 12px', fontSize:40, fontWeight:900, lineHeight:1.1, letterSpacing:'-0.02em' }}>O que vamos fazer por você</h2>
        <p style={{ margin:'0 0 28px', fontSize:16, color:'rgba(255,255,255,0.45)', lineHeight:1.7, maxWidth:580 }}>
          {SOLUCAO || (items.length > 0
            ? `Uma proposta personalizada com ${items.length} ${items.length===1?'entregável':'entregáveis'} pensados especialmente para ${SUBT}.`
            : 'Uma abordagem personalizada e estruturada para transformar o seu objetivo em resultado real.'
          )}
        </p>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12 }}>
          {(items.length > 0 ? items.slice(0,4) : []).map((it,i) => {
            const d = itemDesc(it);
            return (
              <div key={i} style={{ padding:'18px 20px', borderRadius:14, background:`linear-gradient(135deg,${COR1}12,${COR2}08)`, border:`1px solid ${COR1}25`, display:'flex', alignItems:'center', gap:12 }}>
                <div style={{ width:36, height:36, borderRadius:10, background:GRD, display:'flex', alignItems:'center', justifyContent:'center', fontSize:15, fontWeight:900, color:'#fff', flexShrink:0, boxShadow:`0 4px 14px ${COR1}40` }}>✓</div>
                <div style={{ fontSize:13, fontWeight:600, color:'rgba(255,255,255,0.85)', lineHeight:1.45 }}>{d || `Entregável ${i+1}`}</div>
              </div>
            );
          })}
          {items.length === 0 && [
            'Planejamento estratégico', 'Execução especializada',
            'Monitoramento contínuo',   'Entrega com qualidade',
          ].map((txt,i) => (
            <div key={i} style={{ padding:'18px 20px', borderRadius:14, background:`linear-gradient(135deg,${COR1}12,${COR2}08)`, border:`1px solid ${COR1}25`, display:'flex', alignItems:'center', gap:12 }}>
              <div style={{ width:36, height:36, borderRadius:10, background:GRD, display:'flex', alignItems:'center', justifyContent:'center', fontSize:15, fontWeight:900, color:'#fff', flexShrink:0, boxShadow:`0 4px 14px ${COR1}40` }}>✓</div>
              <div style={{ fontSize:13, fontWeight:600, color:'rgba(255,255,255,0.85)', lineHeight:1.45 }}>{txt}</div>
            </div>
          ))}
        </div>
      </div>
    </SlideWrap>
  );

  // ── SLIDE 5 — Entregáveis ────────────────────────────────────────────────
  if (cur.id === 'entregaveis') return (
    <SlideWrap>
      <div style={{ position:'fixed', inset:0, pointerEvents:'none', zIndex:0 }}>
        <div style={{ position:'absolute', top:'30%', right:'-8%', width:'40%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle, ${COR2}28 0%, transparent 70%)`, filter:'blur(70px)' }}/>
      </div>
      <div style={{ position:'relative', zIndex:1 }}>
        <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.09em', color:COR1, marginBottom:12 }}>O que vai ser entregue</div>
        <h2 style={{ margin:'0 0 32px', fontSize:40, fontWeight:900, lineHeight:1.1, letterSpacing:'-0.02em' }}>Escopo do projeto</h2>
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {items.map((it,i) => (
            <div key={i} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'16px 20px', borderRadius:14, background:'rgba(255,255,255,0.04)', border:`1px solid ${i===0?COR1+'40':'rgba(255,255,255,0.07)'}`, transition:'border-color 200ms' }}>
              <div style={{ display:'flex', alignItems:'center', gap:14 }}>
                <div style={{ width:34, height:34, borderRadius:9, background:GRD, display:'flex', alignItems:'center', justifyContent:'center', fontSize:14, fontWeight:900, color:'#fff', flexShrink:0, boxShadow:`0 4px 14px ${COR1}40` }}>{i+1}</div>
                <div>
                  <div style={{ fontSize:15, fontWeight:700 }}>{itemDesc(it) || `Item ${i+1}`}</div>
                  {Number(it.q) > 1 && <div style={{ fontSize:12, color:'rgba(255,255,255,0.35)', marginTop:2 }}>Quantidade: {it.q}</div>}
                </div>
              </div>
              <div style={{ fontSize:15, fontWeight:700, color:Number(it.p) > 0 ? 'rgba(255,255,255,0.8)' : 'rgba(255,255,255,0.3)', whiteSpace:'nowrap', marginLeft:20 }}>
                {Number(it.p) > 0 ? fmtBRL((Number(it.q)||1)*(Number(it.p)||0)) : '—'}
              </div>
            </div>
          ))}
        </div>
        {/* Total strip */}
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginTop:16, padding:'16px 20px', borderRadius:14, background:GRD, boxShadow:`0 8px 24px ${COR1}40` }}>
          <span style={{ fontSize:15, fontWeight:700, color:'rgba(255,255,255,0.85)' }}>Total do projeto</span>
          <span style={{ fontSize:22, fontWeight:900, color:'#fff' }}>{fmtBRL(total)}</span>
        </div>
      </div>
    </SlideWrap>
  );

  // ── SLIDE 6 — Preço ─────────────────────────────────────────────────────
  if (cur.id === 'preco') return (
    <SlideWrap>
      <div style={{ position:'fixed', inset:0, pointerEvents:'none', zIndex:0 }}>
        <div style={{ position:'absolute', bottom:'20%', left:'-5%', width:'40%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle, ${COR1}28 0%, transparent 70%)`, filter:'blur(60px)' }}/>
      </div>
      <div style={{ position:'relative', zIndex:1 }}>
        <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.09em', color:COR1, marginBottom:12 }}>Resumo financeiro</div>
        <h2 style={{ margin:'0 0 32px', fontSize:40, fontWeight:900, lineHeight:1.1, letterSpacing:'-0.02em' }}>Investimento</h2>
        {/* Big value highlight */}
        <div style={{ padding:'28px 32px', borderRadius:16, background:`linear-gradient(135deg,${COR1}20,${COR2}15)`, border:`1px solid ${COR1}40`, marginBottom:20, textAlign:'center', boxShadow:`0 12px 40px ${COR1}25` }}>
          <div style={{ fontSize:13, color:'rgba(255,255,255,0.45)', marginBottom:8, textTransform:'uppercase', letterSpacing:'0.06em', fontWeight:600 }}>Valor total do projeto</div>
          <div style={{ fontSize:48, fontWeight:900, background:GRD, WebkitBackgroundClip:'text', WebkitTextFillColor:'transparent', lineHeight:1 }}>{fmtBRL(total)}</div>
        </div>
        {/* Details grid */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10, marginBottom: budget.budget_desc ? 16 : 0 }}>
          {[
            ['Prazo de entrega', budget.delivery_days ? `${budget.delivery_days} dias úteis` : '—'],
            ['Forma de pagamento', (budget.pay_method||'PIX').toUpperCase()],
            ...(budget.pay_terms ? [['Condições de pagamento', budget.pay_terms]] : []),
            ...(validDate ? [['Proposta válida até', validDate]] : []),
          ].map(([l,v],i) => (
            <div key={i} style={{ padding:'16px 18px', borderRadius:12, background:'rgba(255,255,255,0.04)', border:'1px solid rgba(255,255,255,0.07)' }}>
              <div style={{ fontSize:11, color:'rgba(255,255,255,0.35)', marginBottom:6, fontWeight:600, textTransform:'uppercase', letterSpacing:'0.05em' }}>{l}</div>
              <div style={{ fontSize:15, fontWeight:700, color:'#fff' }}>{v}</div>
            </div>
          ))}
        </div>
        {budget.budget_desc && (
          <div style={{ padding:'16px 20px', borderRadius:12, background:'rgba(255,255,255,0.03)', border:'1px solid rgba(255,255,255,0.06)', fontSize:14, color:'rgba(255,255,255,0.55)', lineHeight:1.7 }}>
            {budget.budget_desc}
          </div>
        )}
      </div>
    </SlideWrap>
  );

  // ── SLIDE 7 — Timeline ───────────────────────────────────────────────────
  if (cur.id === 'timeline') return (
    <SlideWrap>
      <div style={{ position:'fixed', inset:0, pointerEvents:'none', zIndex:0 }}>
        <div style={{ position:'absolute', top:'20%', right:'-8%', width:'40%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle,${COR2}28 0%,transparent 70%)`, filter:'blur(80px)' }}/>
      </div>
      <div style={{ position:'relative', zIndex:1 }}>
        <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.09em', color:COR1, marginBottom:16 }}>Cronograma</div>
        <h2 style={{ margin:'0 0 10px', fontSize:40, fontWeight:900, lineHeight:1.1, letterSpacing:'-0.02em' }}>Timeline do projeto</h2>
        <p style={{ margin:'0 0 36px', fontSize:15, color:'rgba(255,255,255,0.4)', lineHeight:1.6 }}>
          Prazo total estimado: <strong style={{ color:'#fff' }}>{budget.delivery_days} dias úteis</strong>
          {budget.pay_terms && <> · Condições: <strong style={{ color:'#fff' }}>{budget.pay_terms}</strong></>}
        </p>
        {(() => {
          const d = Number(budget.delivery_days) || 30;
          const phases = [
            { label:'Kickoff & Briefing', days: Math.round(d*0.1)||1, icon:'🚀', desc:'Alinhamento de expectativas, entrega de materiais e início formal do projeto.' },
            { label:'Desenvolvimento', days: Math.round(d*0.5)||15, icon:'⚙️', desc:'Execução das entregas planejadas com revisões periódicas de progresso.' },
            { label:'Revisão & Ajustes', days: Math.round(d*0.25)||7, icon:'🔍', desc:'Ciclo de feedback, ajustes finos e refinamento dos entregáveis.' },
            { label:'Entrega Final', days: Math.round(d*0.15)||2, icon:'🎁', desc:'Aprovação final, entrega dos arquivos e handoff completo.' },
          ];
          let acc = 0;
          return (
            <div style={{ display:'flex', flexDirection:'column', gap:0 }}>
              {phases.map((ph, i) => {
                const start = acc + 1;
                acc += ph.days;
                const isLast = i === phases.length - 1;
                return (
                  <div key={i} style={{ display:'flex', gap:0, alignItems:'stretch' }}>
                    {/* Line + dot column */}
                    <div style={{ display:'flex', flexDirection:'column', alignItems:'center', width:48, flexShrink:0 }}>
                      <div style={{ width:40, height:40, borderRadius:'50%', background: i===0 ? GRD : `${COR1}25`, border:`2px solid ${i===0?COR1:COR1+'40'}`, display:'flex', alignItems:'center', justifyContent:'center', fontSize:18, flexShrink:0, boxShadow: i===0 ? `0 4px 18px ${COR1}50` : 'none' }}>{ph.icon}</div>
                      {!isLast && <div style={{ width:2, flex:1, background:`${COR1}20`, margin:'4px 0' }}/>}
                    </div>
                    {/* Content */}
                    <div style={{ padding:`0 0 ${isLast?0:24}px 16px`, flex:1 }}>
                      <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:4, marginTop:8 }}>
                        <span style={{ fontSize:14, fontWeight:700, color:'#fff' }}>{ph.label}</span>
                        <span style={{ fontSize:11, fontWeight:600, color:COR1, background:`${COR1}18`, padding:'2px 8px', borderRadius:999, border:`1px solid ${COR1}30` }}>
                          Dia {start}–{acc}
                        </span>
                      </div>
                      <p style={{ margin:0, fontSize:13, color:'rgba(255,255,255,0.38)', lineHeight:1.6 }}>{ph.desc}</p>
                    </div>
                  </div>
                );
              })}
            </div>
          );
        })()}
      </div>
    </SlideWrap>
  );

  // ── SLIDE 8 — CTA ────────────────────────────────────────────────────────
  if (cur.id === 'cta') return (
    <SlideWrap>
      <div style={{ position:'fixed', inset:0, pointerEvents:'none', zIndex:0 }}>
        <div style={{ position:'absolute', top:'-5%', right:'-5%', width:'50%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle,${COR1}30 0%,transparent 70%)`, filter:'blur(80px)' }}/>
        <div style={{ position:'absolute', bottom:'-10%', left:'-5%', width:'40%', aspectRatio:'1', borderRadius:'50%', background:`radial-gradient(circle,${COR2}25 0%,transparent 70%)`, filter:'blur(80px)' }}/>
      </div>
      <div style={{ position:'relative', zIndex:1, textAlign:'center' }}>
        {approved ? (
          <>
            <div style={{ width:88, height:88, borderRadius:'50%', background:'rgba(34,197,94,0.15)', border:'2px solid #22C55E', display:'flex', alignItems:'center', justifyContent:'center', margin:'0 auto 28px' }}>
              <span style={{ fontSize:38, color:'#22C55E' }}>✓</span>
            </div>
            <h2 style={{ margin:'0 0 14px', fontSize:36, fontWeight:900 }}>Proposta aprovada!</h2>
            <p style={{ margin:0, fontSize:16, color:'rgba(255,255,255,0.5)', lineHeight:1.65, maxWidth:400, marginLeft:'auto', marginRight:'auto' }}>
              Sua assinatura foi registrada. O profissional será notificado e entrará em contato em breve.
            </p>
          </>
        ) : (
          <>
            <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.09em', color:COR1, marginBottom:16 }}>Próximos passos</div>
            <h2 style={{ margin:'0 0 14px', fontSize:42, fontWeight:900, lineHeight:1.1, letterSpacing:'-0.02em' }}>Pronto para começar?</h2>
            <p style={{ margin:'0 0 40px', fontSize:16, color:'rgba(255,255,255,0.45)', lineHeight:1.65, maxWidth:480, marginLeft:'auto', marginRight:'auto' }}>
              Gostou da proposta? Clique em assinar para registrar sua aprovação com assinatura digital e dar o primeiro passo no projeto.
            </p>
            <div style={{ display:'inline-block', padding:'20px 36px', borderRadius:16, background:`linear-gradient(135deg,${COR1}18,${COR2}12)`, border:`1px solid ${COR1}35`, marginBottom:36 }}>
              <div style={{ fontSize:12, color:'rgba(255,255,255,0.4)', marginBottom:6, textTransform:'uppercase', letterSpacing:'0.06em', fontWeight:600 }}>Investimento total</div>
              <div style={{ fontSize:38, fontWeight:900, background:GRD, WebkitBackgroundClip:'text', WebkitTextFillColor:'transparent', lineHeight:1 }}>{fmtBRL(total)}</div>
            </div>
            <br/>
            <button onClick={() => setShowAssinatura(true)} style={{ padding:'18px 52px', borderRadius:14, background:GRD, border:'none', color:'#fff', fontSize:16, fontWeight:800, cursor:'pointer', fontFamily:'inherit', letterSpacing:'-0.01em', boxShadow:`0 10px 32px ${COR1}50` }}>
              ✍️ Assinar proposta
            </button>
            <div style={{ marginTop:14, fontSize:13, color:'rgba(255,255,255,0.25)' }}>Você será redirecionada para o formulário de assinatura digital</div>
          </>
        )}
      </div>
    </SlideWrap>
  );

  return null;
}

// ─── Public Budget View ───────────────────────────────────────────────────────
function PublicBudgetView({ num }) {
  const [budget, setBudget] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [approved, setApproved] = React.useState(false);

  React.useEffect(() => {
    (async () => {
      try {
        // num comes from URL without '#' (e.g. '0003') — reattach '#' for DB lookup
        const dbNum = num.startsWith('#') ? num : '#' + num;
        const { data } = await sb.from('budgets').select('*').eq('budget_num', dbNum).maybeSingle();
        setBudget(data || null);
      } catch(_) {}
      setLoading(false);
    })();
  }, [num]);

  const fmtBRL = v => v ? 'R$ ' + Number(v).toLocaleString('pt-BR', { minimumFractionDigits:2, maximumFractionDigits:2 }) : '—';
  const total = budget ? (Number(budget.total) || (budget.items||[]).reduce((a,i) => a+(i.q||1)*(i.p||0), 0)) : 0;
  const validDate = budget?.valid_until ? new Date(budget.valid_until).toLocaleDateString('pt-BR') : null;

  // Render slide presentation if format === 'slides'
  if (!loading && budget && budget.format === 'slides') {
    return <SlidesPublicView budget={budget} num={num} approved={approved} setApproved={setApproved} />;
  }

  return (
    <div style={{ minHeight:'100vh', background:'#080C18', color:'#fff', fontFamily:'system-ui,-apple-system,sans-serif', padding:'0 0 80px' }}>
      {/* Header bar */}
      <div style={{ borderBottom:'1px solid rgba(255,255,255,0.08)', padding:'16px 32px', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <div style={{ display:'flex', alignItems:'center', gap:10 }}>
          <div style={{ width:30, height:30, borderRadius:8, background:'linear-gradient(135deg,#1D39C4,#36CFC9)', display:'flex', alignItems:'center', justifyContent:'center' }}>
            <span style={{ fontSize:13, fontWeight:900, color:'#fff' }}>iB</span>
          </div>
          <span style={{ fontSize:15, fontWeight:700, color:'#fff' }}>inBrivvo</span>
        </div>
        {!loading && budget && (
          <div style={{ display:'flex', alignItems:'center', gap:6, padding:'5px 14px', borderRadius:999, background:'rgba(34,197,94,0.15)', border:'1px solid rgba(34,197,94,0.3)' }}>
            <div style={{ width:6, height:6, borderRadius:'50%', background:'#22C55E' }}/>
            <span style={{ fontSize:12, fontWeight:600, color:'#22C55E' }}>Proposta ativa</span>
          </div>
        )}
      </div>

      <div style={{ maxWidth:640, margin:'0 auto', padding:'48px 24px 0' }}>
        {loading && (
          <div style={{ textAlign:'center', padding:'80px 0', color:'rgba(255,255,255,0.4)', fontSize:15 }}>Carregando proposta…</div>
        )}

        {!loading && !budget && (
          <div style={{ textAlign:'center', padding:'80px 0' }}>
            <div style={{ fontSize:48, marginBottom:16 }}>🔍</div>
            <div style={{ fontSize:20, fontWeight:700, marginBottom:8 }}>Proposta não encontrada</div>
            <div style={{ fontSize:14, color:'rgba(255,255,255,0.5)', lineHeight:1.6 }}>Este link pode ter expirado ou a proposta foi removida.<br/>Entre em contato com o profissional para obter um novo link.</div>
          </div>
        )}

        {!loading && budget && !approved && (
          <>
            {/* Hero */}
            <div style={{ textAlign:'center', marginBottom:40 }}>
              <div style={{ display:'inline-flex', alignItems:'center', gap:6, padding:'5px 14px', borderRadius:999, background:'rgba(29,57,196,0.2)', border:'1px solid rgba(29,57,196,0.35)', marginBottom:18 }}>
                <span style={{ fontSize:11, fontWeight:700, color:'#36CFC9', letterSpacing:'0.07em', textTransform:'uppercase' }}>Proposta Comercial · {'#' + num.replace(/^#/,'')}</span>
              </div>
              <h1 style={{ margin:'0 0 10px', fontSize:30, fontWeight:900, lineHeight:1.15, letterSpacing:'-0.02em' }}>{budget.title || 'Proposta de Serviço'}</h1>
              <p style={{ margin:0, fontSize:15, color:'rgba(255,255,255,0.55)', lineHeight:1.65 }}>
                Preparada especialmente para <strong style={{ color:'rgba(255,255,255,0.85)' }}>{budget.client_name || 'você'}</strong>
                {validDate && <> · Válida até <strong style={{ color:'rgba(255,255,255,0.85)' }}>{validDate}</strong></>}
              </p>
            </div>

            {/* Summary card */}
            <div style={{ borderRadius:16, border:'1px solid rgba(255,255,255,0.1)', background:'rgba(255,255,255,0.04)', padding:'28px 28px', marginBottom:20 }}>
              <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.08em', color:'rgba(255,255,255,0.4)', marginBottom:20 }}>Resumo da proposta</div>
              {[
                ['Cliente',    budget.client_name || '—'],
                ['Investimento', fmtBRL(total)],
                ['Prazo',      budget.delivery_days ? `${budget.delivery_days} dias úteis` : '—'],
                ['Pagamento',  budget.pay_method || 'PIX'],
                ...(budget.pay_terms ? [['Condições', budget.pay_terms]] : []),
                ...(validDate ? [['Validade da proposta', validDate]] : []),
              ].map(([l,v],i,arr) => (
                <div key={i} style={{ display:'flex', justifyContent:'space-between', alignItems:'center', padding:'12px 0', borderBottom:i<arr.length-1?'1px solid rgba(255,255,255,0.07)':'none' }}>
                  <span style={{ fontSize:14, color:'rgba(255,255,255,0.5)' }}>{l}</span>
                  <span style={{ fontSize:14, fontWeight:700, color:l==='Investimento'?'#36CFC9':'#fff' }}>{v}</span>
                </div>
              ))}
            </div>

            {/* Items */}
            {(budget.items||[]).length > 0 && (
              <div style={{ borderRadius:16, border:'1px solid rgba(255,255,255,0.1)', background:'rgba(255,255,255,0.04)', padding:'28px 28px', marginBottom:20 }}>
                <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.08em', color:'rgba(255,255,255,0.4)', marginBottom:18 }}>Itens incluídos</div>
                {(budget.items||[]).map((it,i) => (
                  <div key={i} style={{ display:'flex', justifyContent:'space-between', alignItems:'center', padding:'10px 0', borderBottom:i<budget.items.length-1?'1px solid rgba(255,255,255,0.07)':'none' }}>
                    <div>
                      <div style={{ fontSize:14, fontWeight:600, color:'#fff' }}>{it.d||it.desc||'Item'}</div>
                      {it.q > 1 && <div style={{ fontSize:12, color:'rgba(255,255,255,0.4)', marginTop:2 }}>Qtd: {it.q}</div>}
                    </div>
                    <span style={{ fontSize:14, fontWeight:700, color:'rgba(255,255,255,0.7)' }}>{fmtBRL((it.q||1)*(it.p||0))}</span>
                  </div>
                ))}
                <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', padding:'16px 0 0', marginTop:8, borderTop:'1px solid rgba(255,255,255,0.12)' }}>
                  <span style={{ fontSize:15, fontWeight:700, color:'#fff' }}>Total</span>
                  <span style={{ fontSize:18, fontWeight:900, color:'#36CFC9' }}>{fmtBRL(total)}</span>
                </div>
              </div>
            )}

            {/* Description */}
            {budget.budget_desc && (
              <div style={{ borderRadius:16, border:'1px solid rgba(255,255,255,0.1)', background:'rgba(255,255,255,0.04)', padding:'24px 28px', marginBottom:20 }}>
                <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.08em', color:'rgba(255,255,255,0.4)', marginBottom:12 }}>Observações</div>
                <p style={{ margin:0, fontSize:14, color:'rgba(255,255,255,0.7)', lineHeight:1.7 }}>{budget.budget_desc}</p>
              </div>
            )}

            {/* CTA */}
            <div style={{ borderRadius:16, border:'1px solid rgba(29,57,196,0.4)', background:'linear-gradient(135deg,rgba(29,57,196,0.15),rgba(54,207,201,0.1))', padding:'32px 28px', textAlign:'center' }}>
              <div style={{ fontSize:20, fontWeight:800, marginBottom:8 }}>Gostou da proposta?</div>
              <div style={{ fontSize:14, color:'rgba(255,255,255,0.55)', marginBottom:24 }}>Clique em aprovar para dar o primeiro passo no seu projeto.</div>
              <button
                onClick={() => setApproved(true)}
                style={{ padding:'16px 48px', borderRadius:12, background:'linear-gradient(135deg,#1D39C4,#36CFC9)', border:'none', color:'#fff', fontSize:15, fontWeight:800, cursor:'pointer', fontFamily:'inherit', letterSpacing:'-0.01em' }}>
                ✓ Aprovar proposta
              </button>
              <div style={{ marginTop:16, fontSize:12, color:'rgba(255,255,255,0.3)' }}>Ao aprovar, você concorda com os termos desta proposta.</div>
            </div>
          </>
        )}

        {!loading && budget && approved && (
          <div style={{ textAlign:'center', padding:'60px 24px' }}>
            <div style={{ width:72, height:72, borderRadius:'50%', background:'rgba(34,197,94,0.2)', border:'2px solid #22C55E', display:'flex', alignItems:'center', justifyContent:'center', margin:'0 auto 24px' }}>
              <span style={{ fontSize:30, color:'#22C55E' }}>✓</span>
            </div>
            <div style={{ fontSize:26, fontWeight:900, marginBottom:10 }}>Proposta aprovada!</div>
            <div style={{ fontSize:15, color:'rgba(255,255,255,0.55)', lineHeight:1.65, maxWidth:380, margin:'0 auto' }}>
              Ótima escolha! O profissional será notificado e entrará em contato em breve para os próximos passos.
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

function App() {
  const [authed, setAuthed] = useState(false);
  const [authLoading, setAuthLoading] = useState(true);
  const [view, setView] = useState('home');
  const [toasts, setToasts] = useState([]);

  // Session bootstrap
  useEffect(() => {
    sb.auth.getSession().then(({ data: { session } }) => {
      setAuthed(!!session);
      setAuthLoading(false);
    });
    const { data: { subscription } } = sb.auth.onAuthStateChange((_event, session) => {
      setAuthed(!!session);
    });
    return () => subscription.unsubscribe();
  }, []);

  useEffect(() => {
    window.__onAvatarUpdate = (url) => setUser(u => u ? { ...u, avatarUrl: url } : u);
    window.__toast = (msg, opts = {}) => {
      const id = Date.now() + Math.random();
      setToasts(t => [...t, { id, msg, tone: opts.tone || 'info' }]);
      setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 2400);
    };
    // ── Notification store ──────────────────────────────────────────────────
    const NOTIF_KEY = 'inbrivvo.notifs.v1';
    const _loadN = () => { try { return JSON.parse(localStorage.getItem(NOTIF_KEY)) || []; } catch { return []; } };
    const _saveN = n => { try { localStorage.setItem(NOTIF_KEY, JSON.stringify(n.slice(0,80))); } catch {} };
    window.__getNotifs  = () => _loadN();
    window.__clearNotifs = () => { _saveN([]); window.__notifRefresh?.(); };
    window.__pushNotif  = (notif) => {
      const n = {
        id:     Date.now() + Math.random(),
        who:    notif.who    || 'Sistema',
        what:   notif.what   || '',
        target: notif.target || '',
        tone:   notif.tone   || 'brand',
        kind:   notif.kind   || 'atividade',
        when:   'agora',
        unread: true,
        ts:     Date.now(),
      };
      const prev = _loadN();
      _saveN([n, ...prev]);
      window.__notifRefresh?.();
    };
    window.__setTheme = (v) => setTweak('theme', v);
    window.__openProject = (p) => { setProject(p); setView('project'); };
    window.__openGoogleSettings = () => setGoogleSettingsOpen(true);
    const onServicesReady = () => setServicesTick(n => n + 1);
    window.addEventListener('services-ready', onServicesReady, { once: true });
    const onLeadsReady = () => setLeadsTick(n => n + 1);
    window.addEventListener('leads-ready', onLeadsReady, { once: true });
    if (!window.Leads) {
      fetch('/src/Leads.jsx?v=1')
        .then(r => r.text())
        .then(src => { const code = window.Babel.transform(src, { presets: ['react'] }).code; eval(code); })
        .catch(() => { const id = setInterval(() => { if (window.Leads) { setLeadsTick(n => n + 1); clearInterval(id); } }, 300); });
    }
    if (!window.Services) {
      // Services.jsx not loaded via HTML — inject it dynamically
      fetch('/src/Services.jsx?v=9')
        .then(r => r.text())
        .then(src => {
          const code = window.Babel.transform(src, { presets: ['react'] }).code;
          // eslint-disable-next-line no-eval
          eval(code);
        })
        .catch(() => {
          // Fallback polling in case fetch fails
          const id = setInterval(() => { if (window.Services) { setServicesTick(n => n + 1); clearInterval(id); } }, 300);
        });
    }
    if (!window.Legal) {
      fetch('/src/Legal.jsx?v=1')
        .then(r => r.text())
        .then(src => {
          const code = window.Babel.transform(src, { presets: ['react'] }).code;
          // eslint-disable-next-line no-eval
          eval(code);
        })
        .catch(() => {});
    }
    return () => { window.removeEventListener('services-ready', onServicesReady); window.removeEventListener('leads-ready', onLeadsReady); };
  }, []);

  const [user, setUser] = useState(null);
  const [subStatus, setSubStatus] = useState(null); // null=carregando, 'active', 'inactive', etc.

  useEffect(() => {
    if (!authed) { setUser(null); setSubStatus(null); return; }
    (async () => {
      const { data: { user: authUser } } = await sb.auth.getUser();
      if (!authUser) return;
      const { data: profile } = await sb.from('profiles').select('name, studio, avatar_url, appearance, subscription_status, onboarding_welcomed, checklist_dismissed').eq('id', authUser.id).single();
      const name = profile?.name || authUser.user_metadata?.full_name || authUser.email?.split('@')[0] || 'Usuário';
      setSubStatus(profile?.subscription_status || 'inactive');
      setUser({ name, studio: profile?.studio || '', email: authUser.email, avatarUrl: profile?.avatar_url || null, onboardingWelcomed: profile?.onboarding_welcomed ?? false, checklistDismissed: profile?.checklist_dismissed ?? false });
      identify(authUser.id, { name, email: authUser.email, plan: profile?.subscription_plan || 'none', subscription_status: profile?.subscription_status || 'inactive' });
      const app = profile?.appearance;
      if (app) {
        document.documentElement.setAttribute('data-theme', app.theme || 'dark');
        document.body.className = `ds-root theme-${app.theme || 'dark'}`;
        if (app.primary)    document.documentElement.style.setProperty('--primary',        app.primary);
        if (app.secondary)  document.documentElement.style.setProperty('--primary-hover',  app.secondary);
        if (app.accent)     document.documentElement.style.setProperty('--accent-success', app.accent);
        if (app.sidebar)    document.documentElement.style.setProperty('--bg-app',         app.sidebar);
        if (app.background) document.documentElement.style.setProperty('--bg-surface',     app.background);
        if (app.text)       document.documentElement.style.setProperty('--fg-primary',     app.text);
        // Mark saved appearance so tweaks effect doesn't override
        if (app.primary) window.__savedAppearance = app;
      }
    })();
  }, [authed]);

  const [project, setProject] = useState(null);
  const [collapsed, setCollapsed] = useState(false);
  const [tweaksOn, setTweaksOn] = useState(false);
  const [creating, setCreating] = useState(false);
  const [creatingTask, setCreatingTask] = useState(false);
  const [notifOpen, setNotifOpen] = useState(false);
  const [calcOpen, setCalcOpen] = useState(false);
  const [budgetPrefill, setBudgetPrefill] = useState(null);
  const [googleSettingsOpen, setGoogleSettingsOpen] = useState(false);
  const [, setServicesTick] = useState(0);
  const [, setLeadsTick]    = useState(0);
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // Apply theme tokens — but always respect user's saved custom appearance
  useEffect(() => {
    // If user has a saved theme, don't override it with tweaks default
    if (!window.__savedAppearance?.theme) {
      document.documentElement.setAttribute('data-theme', t.theme);
      document.body.className = `ds-root theme-${t.theme}`;
    }
    // Only apply tweaks accent if there is no saved custom primary color
    if (!window.__savedAppearance?.primary) {
      document.documentElement.style.setProperty('--primary', t.accent);
      document.documentElement.style.setProperty('--primary-hover', t.accent);
    }
  }, [t.theme, t.accent]);

  useEffect(() => {
    const onMsg = (e) => {
      if (e.data?.type === '__activate_edit_mode') setTweaksOn(true);
      if (e.data?.type === '__deactivate_edit_mode') setTweaksOn(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);

  // Expõe navegação globalmente (usado por módulos como Mensagens e ProjectView)
  React.useEffect(() => {
    window.__navigateTo = (id) => setView(id);
    window.__navigateToGrid = () => setView('grid');
  }, []);

  async function handleLogout() {
    resetAnalytics();
    await sb.auth.signOut();
    setAuthed(false);
    setView('home');
  }

  // ── Public budget route (/o/:num) — no auth required ──────────────────────
  const publicBudgetNum = (() => {
    const m = window.location.pathname.match(/^\/o\/(.+)$/);
    return m ? decodeURIComponent(m[1]) : null;
  })();
  if (publicBudgetNum) return <PublicBudgetView num={publicBudgetNum} />;

  if (authLoading) {
    return (
      <div style={{ minHeight:'100vh', display:'grid', placeItems:'center', background:'var(--bg-app)', color:'var(--fg-muted)', fontSize:14 }}>
        Carregando…
      </div>
    );
  }

  if (!authed) return <Login onLogin={() => setAuthed(true)} />;

  // Ainda carregando status da assinatura — aguarda antes de mostrar qualquer coisa
  if (authed && subStatus === null) {
    return (
      <div style={{ minHeight:'100vh', display:'grid', placeItems:'center', background:'var(--bg-app)', color:'var(--fg-muted)', fontSize:14 }}>
        Carregando…
      </div>
    );
  }

  // Paywall — bloqueia dashboard se não tiver assinatura ativa
  if (authed && subStatus !== 'active') {
    return <Paywall onLogout={handleLogout} onRefresh={async () => {
      const { data: authData } = await sb.auth.getUser();
      const authUser = authData?.user;
      if (!authUser) return false;
      const { data: profile } = await sb.from('profiles').select('subscription_status').eq('id', authUser.id).single();
      const s = profile?.subscription_status || 'inactive';
      setSubStatus(s);
      if (s === 'active') { setView('home'); return true; }
      return false; // sem assinatura ativa — Paywall exibe aviso
    }}/>;
  }

  const titles = {
    home:      ['Dashboard',           'Visão geral de métricas e atividades'],
    projects:  ['Projetos',            'Gestão de projetos com Kanban'],
    project:   [project?.name || 'Projeto', project?.client || 'Visão detalhada'],
    tasks:     ['Tarefas',             'Suas tarefas e da equipe'],
    clients:   ['Clientes',            'CRM completo'],
    calendar:  ['Agenda',              'Reuniões, entregas e horários públicos'],
    messages:  ['Mensagens',           'Conversas com clientes e equipe'],
    finance:   ['Financeiro',          'Receitas, despesas e fluxo de caixa'],
    budgets:   ['Orçamentos',          'Propostas, contratos e personalização'],
    leads:     ['Pipeline de Leads',    'Gerencie seus leads do primeiro contato ao fechamento'],
    briefings: ['Briefings',           'Levantamento de necessidades dos clientes'],
    services:  ['Meus Serviços',       'Catálogo de serviços e preços'],
    reports:   ['Relatórios',          'Performance e produtividade'],
    grid:      ['Grid de Preview',     'Visualize e organize seu feed antes de publicar'],
    pages:     ['Páginas públicas',    'Portfolios, bio links, formulários e mais'],
    settings:  ['Configurações',       'Sua conta, organização, equipe e plano'],
    legal:     ['Documentos Legais',   'Termos de uso, privacidade, reembolso e cookies'],
  };
  const components = {
    home:      <Dashboard onOpenProject={(p) => { setProject(p); setView('project'); }} onAddTask={() => setCreatingTask(true)} onNav={(id) => setView(id)} user={user} />,
    projects:  <Projects onOpenProject={(p) => { setProject(p); setView('project'); }} />,
    project:   <ProjectView project={project} onBack={() => setView('projects')} />,
    tasks:     <Tasks onNewTask={() => setCreatingTask(true)} />,
    clients:   <Clients onNav={(id)=>setView(id)} />,
    calendar:  <Calendar onNav={(id)=>setView(id)} />,
    messages:  <Messages onNav={(id) => setView(id)} />,
    leads:     window.Leads ? React.createElement(window.Leads) : React.createElement('div', { style:{ padding:40, textAlign:'center', color:'var(--fg-muted)', fontSize:14 } }, 'Carregando pipeline…'),
    finance:   <Finance/>,
    budgets:   <Budgets onNav={(id)=>setView(id)} prefill={budgetPrefill} onUsedPrefill={() => setBudgetPrefill(null)} />,
    briefings: <Briefings onNav={(id)=>setView(id)} />,
    services:  window.Services ? React.createElement(window.Services, { onNav: id=>setView(id) }) : React.createElement('div', { style:{ padding:40, textAlign:'center', color:'var(--fg-muted)', fontSize:14 } }, 'Carregando módulo de Serviços…'),
    reports:   <Reports/>,
    grid:      <GridPreview />,
    pages:     <Pages onNav={(id)=>setView(id)} />,
    settings:  <Settings/>,
    legal:     window.Legal ? React.createElement(window.Legal, null) : React.createElement('div', { style:{ padding:40, textAlign:'center', color:'var(--fg-muted)', fontSize:14 } }, 'Carregando…'),
  };
  const [title, subtitle] = titles[view] || titles.home;

  return (
    <div style={{ display:'flex', height:'100vh', overflow:'hidden', background:'var(--bg-app)' }}>
      <Sidebar
        active={view === 'project' ? 'projects' : view}
        onNav={(id) => {
          if (id === 'calculator') { setCalcOpen(true); return; }
          setView(id);
        }}
        collapsed={collapsed}
        onToggle={() => setCollapsed(c => !c)}
        onLogout={handleLogout}
        user={user}
      />
      <main style={{ flex:1, minWidth:0, display:'flex', flexDirection:'column' }}>
        <Topbar title={title} subtitle={subtitle} onAction={() => setCreating(true)} onBell={() => setNotifOpen(true)} onNav={(id) => setView(id)} user={user} />
        <div style={{ flex:1, overflow:'auto', display:'flex', flexDirection:'column' }}>{components[view]}</div>
      </main>

      {creating && (
        <NewProject
          onClose={() => setCreating(false)}
          onCreate={(p) => { setCreating(false); setProject({ id: p.id, name: p.name || 'Novo projeto', client: p.client, deadline: p.deadline, budget: p.budget }); setView('project'); }}
        />
      )}

      {creatingTask && (
        <NewTask
          onClose={() => setCreatingTask(false)}
          onCreate={async (p) => {
            const statusMap = { 'a fazer': 'todo', 'em andamento': 'doing', 'em revisão': 'review', 'concluído': 'done' };
            const tagColors = ['#36CFC9', '#FF7875', '#FFC069', '#95DE64', '#B37FEB'];
            const tagIdx = p.tags?.length ? ['design', 'copy', 'social', 'motion', 'estratégia'].indexOf(p.tags[0].toLowerCase()) : -1;
            const { data: { user: authUser } } = await sb.auth.getUser();
            const { data, error } = await sb.from('tasks').insert({
              user_id: authUser.id,
              title: p.title,
              description: p.desc || null,
              project_name: p.project || null,
              priority: p.priority || 'média',
              kanban_col: statusMap[p.status] || 'todo',
              due_date: p.due || null,
              assignee: p.assignee?.trim() || null,
              tag_label: p.tags?.length ? p.tags[0].toUpperCase() : 'TASK',
              tag_color: tagIdx >= 0 ? tagColors[tagIdx] : '#36CFC9',
              done: false,
            }).select().single();
            if (error) { window.__toast?.(error.message, { tone: 'danger' }); return; }
            window.__toast?.('Tarefa criada!', { tone: 'success' });
            if (data && window.__addExternalTask) {
              const due = data.due_date ? data.due_date.slice(8,10) + '/' + data.due_date.slice(5,7) : null;
              window.__addExternalTask({ id: data.id, t: data.title, proj: data.project_name, tg: data.tag_label, tc: data.tag_color, col: data.kanban_col || 'todo', pri: data.priority, due, who: data.assignee, desc: data.description, done: false });
            }
            setCreatingTask(false);
            setView('tasks');
          }}
        />
      )}

      {notifOpen && <Notifications onClose={() => setNotifOpen(false)} />}

      {calcOpen && (
        <CalculatorPanel
          onClose={() => setCalcOpen(false)}
          onGerarOrcamento={(data) => {
            setCalcOpen(false);
            setBudgetPrefill(data);
            setView('budgets');
          }}
        />
      )}

      {toasts.length > 0 && (
        <div style={{ position:'fixed', bottom:24, left:'50%', transform:'translateX(-50%)', zIndex:500, display:'flex', flexDirection:'column', gap:8, alignItems:'center', pointerEvents:'none' }}>
          {toasts.map(tt => (
            <div key={tt.id} style={{
              background:'var(--bg-surface)', color:'var(--fg-primary)', border:'1px solid var(--border-strong)',
              padding:'10px 16px', borderRadius:8, fontSize:13, fontWeight:500,
              boxShadow:'0 12px 32px rgba(0,0,0,0.45)', display:'flex', alignItems:'center', gap:8,
            }}>
              <span style={{ width:6, height:6, borderRadius:'50%', background: tt.tone==='success' ? 'var(--accent-success)' : tt.tone==='danger' ? 'var(--accent-danger)' : 'var(--accent-primary)' }}/>
              {tt.msg}
            </div>
          ))}
        </div>
      )}

      {googleSettingsOpen && window.GoogleIntegrationSettings && React.createElement(window.GoogleIntegrationSettings, { onClose: () => setGoogleSettingsOpen(false) })}
      {tweaksOn && (
        <TweaksPanel title="Tweaks" onClose={() => setTweaksOn(false)}>
          <TweakSection title="Tema">
            <TweakRadio
              label="Modo"
              value={t.theme}
              onChange={(v) => setTweak('theme', v)}
              options={[{ value:'dark', label:'Escuro' }, { value:'light', label:'Claro' }]}
            />
          </TweakSection>
          <TweakSection title="Cor de destaque">
            <TweakColor
              label="Primária"
              value={t.accent}
              onChange={(v) => setTweak('accent', v)}
              options={['#1D39C4','#36CFC9','#FA541C','#7C3AED','#22C55E']}
            />
          </TweakSection>
          <TweakSection title="Layout">
            <TweakToggle
              label="Sidebar compacta"
              value={collapsed}
              onChange={setCollapsed}
            />
            <TweakRadio
              label="Densidade"
              value={t.density}
              onChange={(v) => setTweak('density', v)}
              options={[{ value:'compacto', label:'Compacto' },{ value:'confortavel', label:'Confortável' }]}
            />
          </TweakSection>
          <TweakSection title="Atalhos">
            <button onClick={() => sb.auth.signOut()} style={{ width:'100%', padding:10, border:'1px solid var(--border-subtle)', background:'var(--bg-elevated)', color:'var(--fg-primary)', borderRadius:8, cursor:'pointer', fontFamily:'inherit', fontSize:13 }}>Ver tela de login</button>
          </TweakSection>
        </TweaksPanel>
      )}
    </div>
  );
}

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