// ========== Goals, Subs, Assets, Monthly, Tags ==========
const { Avatar, Icon, Sparkline, TagPill, Currency,
        fmtBRL, fmtBRLShort, pct, pctFine, MONTH_NAMES_PT } = window.FinUtils;

const parseCentsM = (str) =>
  Math.round(parseFloat((str || '').replace(/\./g, '').replace(',', '.')) * 100) || 0;
const centsToStrM = (cents) =>
  (cents / 100).toFixed(2).replace('.', ',');

// ========== GOAL MODAL ==========
const GOAL_ICONS  = ['✈️','🏠','🚗','🛡️','💻','📱','🎓','💍','🏖️','💰','🎯','🌍'];
const GOAL_COLORS = ['#4FA8A0','#E8A94A','#63B87A','#4A90C2','#D97056','#C264A0','#8F6FD6','#5A8DB8','#A48454','#4CAF50'];

function GoalModal({ goal, state, setState, onClose }) {
  const isEdit = !!goal;
  const [name,     setName]     = React.useState(goal?.name     || '');
  const [icon,     setIcon]     = React.useState(goal?.icon     || '🎯');
  const [color,    setColor]    = React.useState(goal?.color    || '#4FA8A0');
  const [target,   setTarget]   = React.useState(goal ? centsToStrM(goal.target) : '');
  const [current,  setCurrent]  = React.useState(goal ? centsToStrM(goal.current) : '0,00');
  const [deadline, setDeadline] = React.useState(goal?.deadline || '');
  const [saving,   setSaving]   = React.useState(false);

  const save = () => {
    const targetCents  = parseCentsM(target);
    const currentCents = parseCentsM(current);
    if (!name || !targetCents || !deadline || saving) return;
    setSaving(true);
    const body   = { name, icon, color, target: targetCents, current: currentCents, deadline };
    const url    = isEdit ? `/api/goals/${goal.id}` : '/api/goals';
    const method = isEdit ? 'PUT' : 'POST';
    fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
      .then(r => r.json())
      .then(saved => {
        setState(s => ({
          ...s,
          goals: isEdit ? s.goals.map(g => g.id === saved.id ? saved : g) : [...s.goals, saved],
        }));
        onClose();
      })
      .catch(() => setSaving(false));
  };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="hstack" style={{ justifyContent: 'space-between', marginBottom: 20 }}>
          <h2 className="display" style={{ fontSize: 24, margin: 0 }}>{isEdit ? 'Editar meta' : 'Nova meta'}</h2>
          <button onClick={onClose} style={{ padding: 8, borderRadius: 8, color: 'var(--text-mute)' }}><Icon name="x" size={18}/></button>
        </div>

        <div className="field">
          <label>Nome</label>
          <input className="input" placeholder="Ex: Viagem Europa, Apartamento..." value={name} onChange={e => setName(e.target.value)} autoFocus/>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <div className="field">
            <label>Ícone</label>
            <div className="tag-picker" style={{ flexWrap: 'wrap' }}>
              {GOAL_ICONS.map(ic => (
                <button key={ic} className={`tag-option ${icon === ic ? 'selected' : ''}`}
                        style={{ fontSize: 18, padding: '4px 8px' }} onClick={() => setIcon(ic)}>{ic}</button>
              ))}
            </div>
          </div>
          <div className="field">
            <label>Cor</label>
            <div className="hstack" style={{ flexWrap: 'wrap', gap: 8 }}>
              {GOAL_COLORS.map(c => (
                <button key={c} onClick={() => setColor(c)}
                        style={{ width: 28, height: 28, borderRadius: 6, background: c, flexShrink: 0,
                                 border: color === c ? '3px solid var(--text)' : '2px solid transparent' }}/>
              ))}
            </div>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <div className="field">
            <label>Meta (R$)</label>
            <input className="input" type="text" inputMode="decimal" placeholder="0,00" value={target} onChange={e => setTarget(e.target.value)}/>
          </div>
          {!isEdit && (
            <div className="field">
              <label>Já guardado (R$)</label>
              <input className="input" type="text" inputMode="decimal" placeholder="0,00" value={current} onChange={e => setCurrent(e.target.value)}/>
            </div>
          )}
          <div className="field">
            <label>Prazo</label>
            <input className="input" type="date" value={deadline} onChange={e => setDeadline(e.target.value)}/>
          </div>
        </div>

        <div className="hstack" style={{ justifyContent: 'flex-end', gap: 10, marginTop: 8 }}>
          <button className="btn btn-ghost" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary btn-lg" onClick={save}
                  disabled={!name || !parseCentsM(target) || !deadline || saving}>
            <Icon name="check" size={14}/> {isEdit ? 'Salvar' : 'Criar meta'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ========== DEPOSIT MODAL ==========
function DepositModal({ goal, state, setState, onClose }) {
  const [amount, setAmount] = React.useState('');
  const [saving, setSaving] = React.useState(false);
  const cents = parseCentsM(amount);

  const save = () => {
    if (!cents || saving) return;
    setSaving(true);
    fetch(`/api/goals/${goal.id}/deposit`, {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ amount: cents }),
    })
      .then(r => r.json())
      .then(saved => {
        setState(s => ({ ...s, goals: s.goals.map(g => g.id === saved.id ? saved : g) }));
        onClose();
      })
      .catch(() => setSaving(false));
  };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" style={{ maxWidth: 400 }} onClick={e => e.stopPropagation()}>
        <div className="hstack" style={{ justifyContent: 'space-between', marginBottom: 20 }}>
          <h2 className="display" style={{ fontSize: 24, margin: 0 }}>Adicionar à meta</h2>
          <button onClick={onClose} style={{ padding: 8, borderRadius: 8, color: 'var(--text-mute)' }}><Icon name="x" size={18}/></button>
        </div>
        <div style={{ textAlign: 'center', marginBottom: 20 }}>
          <div style={{ fontSize: 32, marginBottom: 4 }}>{goal.icon}</div>
          <div style={{ fontWeight: 600 }}>{goal.name}</div>
          <div className="muted" style={{ fontSize: 13 }}>{fmtBRL(goal.current)} de {fmtBRL(goal.target)}</div>
        </div>
        <div className="field">
          <label>Valor a adicionar (R$)</label>
          <div className="hstack" style={{ alignItems: 'baseline', gap: 8 }}>
            <span className="display" style={{ fontSize: 24, color: 'var(--text-mute)' }}>R$</span>
            <input className="input-lg" type="text" inputMode="decimal" placeholder="0,00"
                   value={amount} onChange={e => setAmount(e.target.value)} autoFocus style={{ flex: 1 }}/>
          </div>
        </div>
        <div className="hstack" style={{ justifyContent: 'flex-end', gap: 10, marginTop: 8 }}>
          <button className="btn btn-ghost" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary btn-lg" onClick={save} disabled={!cents || saving}>
            <Icon name="check" size={14}/> Confirmar
          </button>
        </div>
      </div>
    </div>
  );
}

// ========== SUBSCRIPTION MODAL ==========
function SubModal({ sub, state, setState, onClose }) {
  const { tags, users, user } = state;
  const isEdit = !!sub;
  const [name,   setName]   = React.useState(sub?.name   || '');
  const [amount, setAmount] = React.useState(sub ? centsToStrM(sub.amount) : '');
  const [day,    setDay]    = React.useState(sub?.day    || 1);
  const [tagId,  setTagId]  = React.useState(sub?.tag    || (tags[0]?.id));
  const [shared,     setShared]     = React.useState(sub?.shared     || false);
  const [cardLinked, setCardLinked] = React.useState(sub?.cardLinked === true);
  const [active,     setActive]     = React.useState(sub?.active !== undefined ? sub.active : true);
  const [saving,     setSaving]     = React.useState(false);

  const otherUser    = users.find(u => u.id !== user.id);
  const parsedAmount = parseCentsM(amount);

  const save = () => {
    if (!name || !parsedAmount || saving) return;
    setSaving(true);
    const body   = { name, amount: parsedAmount, day: +day, tag: tagId, ownerId: sub?.ownerId || user.id, active, shared, cardLinked };
    const url    = isEdit ? `/api/subscriptions/${sub.id}` : '/api/subscriptions';
    const method = isEdit ? 'PUT' : 'POST';
    fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
      .then(r => r.json())
      .then(saved => {
        setState(s => ({
          ...s,
          subs: isEdit ? s.subs.map(x => x.id === saved.id ? saved : x) : [...s.subs, saved],
        }));
        onClose();
      })
      .catch(() => setSaving(false));
  };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="hstack" style={{ justifyContent: 'space-between', marginBottom: 20 }}>
          <h2 className="display" style={{ fontSize: 24, margin: 0 }}>{isEdit ? 'Editar assinatura' : 'Nova assinatura'}</h2>
          <button onClick={onClose} style={{ padding: 8, borderRadius: 8, color: 'var(--text-mute)' }}><Icon name="x" size={18}/></button>
        </div>

        <div className="field">
          <label>Nome</label>
          <input className="input" placeholder="Ex: Netflix, Spotify, Academia..." value={name} onChange={e => setName(e.target.value)} autoFocus/>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <div className="field">
            <label>Valor mensal (R$)</label>
            <div className="hstack" style={{ alignItems: 'baseline', gap: 8 }}>
              <span style={{ color: 'var(--text-mute)', fontWeight: 500 }}>R$</span>
              <input className="input" type="text" inputMode="decimal" placeholder="0,00"
                     value={amount} onChange={e => setAmount(e.target.value)} style={{ flex: 1 }}/>
            </div>
          </div>
          <div className="field">
            <label>Dia de cobrança</label>
            <input className="input" type="number" min="1" max="31" value={day} onChange={e => setDay(e.target.value)}/>
          </div>
        </div>

        <div className="field">
          <label>Categoria</label>
          <div className="tag-picker">
            {tags.map(t => (
              <button key={t.id} className={`tag-option ${tagId === t.id ? 'selected' : ''}`}
                      style={{ color: tagId === t.id ? t.color : undefined }}
                      onClick={() => setTagId(t.id)}>
                <span>{t.icon}</span> {t.name}
              </button>
            ))}
          </div>
        </div>

        <div className="toggle-row">
          <div>
            <div style={{ fontWeight: 500, fontSize: 13 }}>Compartilhada com {otherUser ? otherUser.name : 'outro usuário'}</div>
            <div className="muted" style={{ fontSize: 11 }}>Aparece para os dois · só o dono edita.</div>
          </div>
          <button className={`toggle ${shared ? 'on' : ''}`} onClick={() => setShared(!shared)} />
        </div>

        <div className="toggle-row">
          <div>
            <div style={{ fontWeight: 500, fontSize: 13 }}>Vinculada a cartão 💳</div>
            <div className="muted" style={{ fontSize: 11 }}>Ative se essa cobrança aparece na fatura do cartão. Não deduz das despesas diretas.</div>
          </div>
          <button className={`toggle ${cardLinked ? 'on' : ''}`} onClick={() => setCardLinked(c => !c)} type="button"/>
        </div>

        {isEdit && (
          <div className="toggle-row" style={{ borderBottom: '1px solid var(--border)', marginBottom: 20 }}>
            <div>
              <div style={{ fontWeight: 500, fontSize: 13 }}>Assinatura ativa</div>
              <div className="muted" style={{ fontSize: 11 }}>Desative para pausar sem excluir.</div>
            </div>
            <button className={`toggle ${active ? 'on' : ''}`} onClick={() => setActive(!active)} />
          </div>
        )}

        <div className="hstack" style={{ justifyContent: 'flex-end', gap: 10, marginTop: 8 }}>
          <button className="btn btn-ghost" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary btn-lg" onClick={save} disabled={!name || !parsedAmount || saving}>
            <Icon name="check" size={14}/> {isEdit ? 'Salvar' : 'Criar assinatura'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ========== ASSET MODAL ==========
const ASSET_TYPES = [
  { id: 'bank_account', name: 'Conta',        icon: 'wallet'   },
  { id: 'investment',   name: 'Investimento', icon: 'trend'    },
  { id: 'property',     name: 'Imóvel',       icon: 'home'     },
  { id: 'other',        name: 'Outro',        icon: 'sparkles' },
];

function AssetModal({ asset, state, setState, onClose }) {
  const { users, user } = state;
  const isEdit = !!asset;
  const [name,    setName]    = React.useState(asset?.name    || '');
  const [type,    setType]    = React.useState(asset?.type    || 'bank_account');
  const [value,   setValue]   = React.useState(asset ? centsToStrM(asset.value) : '');
  const [ownerId, setOwnerId] = React.useState(asset?.ownerId || user.id);
  const [saving,  setSaving]  = React.useState(false);

  const parsedValue = parseCentsM(value);

  const save = () => {
    if (!name || !parsedValue || saving) return;
    setSaving(true);
    const body   = { name, type, value: parsedValue, ownerId };
    const url    = isEdit ? `/api/assets/${asset.id}` : '/api/assets';
    const method = isEdit ? 'PUT' : 'POST';
    fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
      .then(r => r.json())
      .then(saved => {
        setState(s => ({
          ...s,
          assets: isEdit ? s.assets.map(a => a.id === saved.id ? saved : a) : [...s.assets, saved],
        }));
        onClose();
      })
      .catch(() => setSaving(false));
  };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="hstack" style={{ justifyContent: 'space-between', marginBottom: 20 }}>
          <h2 className="display" style={{ fontSize: 24, margin: 0 }}>{isEdit ? 'Editar ativo' : 'Novo ativo'}</h2>
          <button onClick={onClose} style={{ padding: 8, borderRadius: 8, color: 'var(--text-mute)' }}><Icon name="x" size={18}/></button>
        </div>

        <div className="field">
          <label>Nome</label>
          <input className="input" placeholder="Ex: Conta Nubank, CDB BTG..." value={name} onChange={e => setName(e.target.value)} autoFocus/>
        </div>

        <div className="field">
          <label>Tipo</label>
          <div className="chip-select" style={{ width: '100%' }}>
            {ASSET_TYPES.map(t => (
              <button key={t.id} className={type === t.id ? 'active' : ''} onClick={() => setType(t.id)} style={{ flex: 1 }}>
                <Icon name={t.icon} size={14}/> {t.name}
              </button>
            ))}
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <div className="field">
            <label>Valor atual (R$)</label>
            <div className="hstack" style={{ alignItems: 'baseline', gap: 8 }}>
              <span style={{ color: 'var(--text-mute)', fontWeight: 500 }}>R$</span>
              <input className="input" type="text" inputMode="decimal" placeholder="0,00"
                     value={value} onChange={e => setValue(e.target.value)} style={{ flex: 1 }}/>
            </div>
          </div>
          <div className="field">
            <label>Dono</label>
            <div className="chip-select" style={{ width: '100%' }}>
              {users.map(u => (
                <button key={u.id} className={ownerId === u.id ? 'active' : ''} onClick={() => setOwnerId(u.id)} style={{ flex: 1 }}>
                  {u.name}
                </button>
              ))}
            </div>
          </div>
        </div>

        <div className="hstack" style={{ justifyContent: 'flex-end', gap: 10, marginTop: 8 }}>
          <button className="btn btn-ghost" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary btn-lg" onClick={save} disabled={!name || !parsedValue || saving}>
            <Icon name="check" size={14}/> {isEdit ? 'Salvar' : 'Criar ativo'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ========== TAG MODAL ==========
const TAG_ICONS   = ['●','🏠','🛒','🍽️','🚗','🩺','🎬','📺','📚','🐾','💡','✈️','💼','🎁','🏋️','💊','🎓','🌿'];
const TAG_COLORS  = ['#8A8A93','#E8A94A','#63B87A','#D97056','#4A90C2','#C264A0','#8F6FD6','#5A8DB8','#A48454','#4FA8A0','#4CAF50','#E91E63'];

function TagModal({ tag, state, setState, onClose }) {
  const isEdit = !!tag;
  const [name,  setName]  = React.useState(tag?.name  || '');
  const [icon,  setIcon]  = React.useState(tag?.icon  || '●');
  const [color, setColor] = React.useState(tag?.color || '#8A8A93');
  const [saving, setSaving] = React.useState(false);

  const save = () => {
    if (!name || saving) return;
    setSaving(true);
    const body   = { name, icon, color };
    const url    = isEdit ? `/api/tags/${tag.id}` : '/api/tags';
    const method = isEdit ? 'PUT' : 'POST';
    fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
      .then(r => r.json())
      .then(saved => {
        setState(s => ({
          ...s,
          tags: isEdit ? s.tags.map(t => t.id === saved.id ? saved : t) : [...s.tags, saved],
        }));
        onClose();
      })
      .catch(() => setSaving(false));
  };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" style={{ maxWidth: 420 }} onClick={e => e.stopPropagation()}>
        <div className="hstack" style={{ justifyContent: 'space-between', marginBottom: 20 }}>
          <h2 className="display" style={{ fontSize: 24, margin: 0 }}>{isEdit ? 'Editar categoria' : 'Nova categoria'}</h2>
          <button onClick={onClose} style={{ padding: 8, borderRadius: 8, color: 'var(--text-mute)' }}><Icon name="x" size={18}/></button>
        </div>

        <div className="field">
          <label>Nome</label>
          <input className="input" placeholder="Ex: Saúde, Lazer, Pets..." value={name} onChange={e => setName(e.target.value)} autoFocus/>
        </div>

        <div className="field">
          <label>Ícone</label>
          <div className="tag-picker" style={{ flexWrap: 'wrap' }}>
            {TAG_ICONS.map(ic => (
              <button key={ic} className={`tag-option ${icon === ic ? 'selected' : ''}`}
                      style={{ fontSize: 16, padding: '4px 8px' }} onClick={() => setIcon(ic)}>{ic}</button>
            ))}
          </div>
        </div>

        <div className="field">
          <label>Cor</label>
          <div className="hstack" style={{ flexWrap: 'wrap', gap: 8 }}>
            {TAG_COLORS.map(c => (
              <button key={c} onClick={() => setColor(c)}
                      style={{ width: 28, height: 28, borderRadius: 6, background: c, flexShrink: 0,
                               border: color === c ? '3px solid var(--text)' : '2px solid transparent' }}/>
            ))}
          </div>
        </div>

        <div style={{ marginBottom: 20 }}>
          <div className="muted" style={{ fontSize: 12, marginBottom: 8 }}>Prévia</div>
          <TagPill tag={{ name, icon, color }}/>
        </div>

        <div className="hstack" style={{ justifyContent: 'flex-end', gap: 10 }}>
          <button className="btn btn-ghost" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary btn-lg" onClick={save} disabled={!name || saving}>
            <Icon name="check" size={14}/> {isEdit ? 'Salvar' : 'Criar categoria'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ========== TAGS MANAGER MODAL ==========
function TagsManagerModal({ state, setState, onClose }) {
  const { tags } = state;
  const [modal, setModal] = React.useState(null);

  const deleteTag = (t) => {
    if (!window.confirm(`Excluir categoria "${t.name}"?`)) return;
    fetch(`/api/tags/${t.id}`, { method: 'DELETE' })
      .then(() => setState(s => ({ ...s, tags: s.tags.filter(x => x.id !== t.id) })));
  };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="hstack" style={{ justifyContent: 'space-between', marginBottom: 20 }}>
          <h2 className="display" style={{ fontSize: 24, margin: 0 }}>Categorias</h2>
          <button onClick={onClose} style={{ padding: 8, borderRadius: 8, color: 'var(--text-mute)' }}><Icon name="x" size={18}/></button>
        </div>

        <div className="vstack" style={{ gap: 8, marginBottom: 20 }}>
          {tags.map(t => (
            <div key={t.id} className="hstack" style={{ justifyContent: 'space-between', padding: '8px 12px', borderRadius: 10, background: 'var(--bg-sunken)' }}>
              <TagPill tag={t}/>
              <div className="hstack" style={{ gap: 4 }}>
                <button title="Editar" onClick={() => setModal(t)}
                        style={{ padding: 4, borderRadius: 6, color: 'var(--text-mute)' }}>
                  <Icon name="edit" size={14}/>
                </button>
                <button title="Excluir" onClick={() => deleteTag(t)}
                        style={{ padding: 4, borderRadius: 6, color: 'var(--expense)' }}>
                  <Icon name="trash" size={14}/>
                </button>
              </div>
            </div>
          ))}
        </div>

        <button className="btn btn-primary" style={{ width: '100%' }} onClick={() => setModal('create')}>
          <Icon name="plus" size={14}/> Nova categoria
        </button>

        {modal !== null && (
          <TagModal tag={modal === 'create' ? null : modal} state={state} setState={setState} onClose={() => setModal(null)} />
        )}
      </div>
    </div>
  );
}

// ========== GOALS ==========
function Goals({ state, setState }) {
  const { goals, savingsTarget, investmentTarget } = state;
  const [modal,   setModal]   = React.useState(null);
  const [deposit, setDeposit] = React.useState(null);

  // Spending target (R$)
  const [spendEdit,   setSpendEdit]   = React.useState(false);
  const [spendInput,  setSpendInput]  = React.useState('');
  const [spendSaving, setSpendSaving] = React.useState(false);

  // Investment target (%)
  const [invEdit,   setInvEdit]   = React.useState(false);
  const [invInput,  setInvInput]  = React.useState('');
  const [invSaving, setInvSaving] = React.useState(false);

  const saveSpend = () => {
    const amount = Math.round(parseFloat((spendInput || '').replace(/\./g, '').replace(',', '.')) * 100);
    if (!amount || spendSaving) return;
    setSpendSaving(true);
    fetch('/api/savings-target', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ amount }) })
      .then(r => r.json())
      .then(d => { setState(s => ({ ...s, savingsTarget: d.savingsTarget })); setSpendEdit(false); setSpendSaving(false); })
      .catch(() => setSpendSaving(false));
  };

  const saveInv = () => {
    const pct = parseFloat((invInput || '').replace(',', '.')) / 100;
    if (isNaN(pct) || invSaving) return;
    setInvSaving(true);
    fetch('/api/investment-target', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ pct }) })
      .then(r => r.json())
      .then(d => { setState(s => ({ ...s, investmentTarget: d.investmentTarget })); setInvEdit(false); setInvSaving(false); })
      .catch(() => setInvSaving(false));
  };

  const deleteGoal = (g) => {
    if (!window.confirm(`Excluir a meta "${g.name}"?`)) return;
    fetch(`/api/goals/${g.id}`, { method: 'DELETE' })
      .then(() => setState(s => ({ ...s, goals: s.goals.filter(x => x.id !== g.id) })));
  };

  return (
    <div>
      <div className="page-head">
        <div>
          <div className="dim" style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em' }}>metas de economia</div>
          <h1 className="page-title">Onde vocês estão indo</h1>
          <div className="page-subtitle">{goals.length} metas cadastradas</div>
        </div>
        <button className="btn btn-primary" onClick={() => setModal('create')}><Icon name="plus" size={14}/> Nova meta</button>
      </div>

      <div className="card" style={{ marginBottom: 'var(--s5)' }}>
        <div className="muted" style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 16 }}>Metas mensais</div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
          <div>
            <div style={{ fontWeight: 500, fontSize: 13, marginBottom: 4 }}>Meta de gastos mensal</div>
            <div className="muted" style={{ fontSize: 11, marginBottom: 10 }}>Limite de despesas por mês</div>
            {spendEdit ? (
              <div className="hstack" style={{ gap: 8 }}>
                <div className="hstack" style={{ alignItems: 'baseline', gap: 4, flex: 1 }}>
                  <span style={{ color: 'var(--text-mute)', fontSize: 12 }}>R$</span>
                  <input className="input" type="text" inputMode="decimal" autoFocus
                         value={spendInput} onChange={e => setSpendInput(e.target.value)}
                         onKeyDown={e => e.key === 'Enter' && saveSpend()} style={{ flex: 1 }}/>
                </div>
                <button className="btn btn-primary" onClick={saveSpend} disabled={spendSaving}><Icon name="check" size={13}/></button>
                <button className="btn btn-ghost" onClick={() => setSpendEdit(false)}><Icon name="x" size={13}/></button>
              </div>
            ) : (
              <div className="hstack" style={{ alignItems: 'baseline', gap: 10 }}>
                <span className="display num" style={{ fontSize: 28 }}>{fmtBRL(savingsTarget || 0)}</span>
                <button className="btn btn-ghost" style={{ padding: '2px 8px', fontSize: 11 }}
                        onClick={() => { setSpendInput(savingsTarget ? ((savingsTarget/100).toFixed(2).replace('.',',')) : ''); setSpendEdit(true); }}>
                  editar
                </button>
              </div>
            )}
          </div>
          <div>
            <div style={{ fontWeight: 500, fontSize: 13, marginBottom: 4 }}>Meta de investimento mensal</div>
            <div className="muted" style={{ fontSize: 11, marginBottom: 10 }}>% da renda a investir por mês</div>
            {invEdit ? (
              <div className="hstack" style={{ gap: 8 }}>
                <div className="hstack" style={{ alignItems: 'baseline', gap: 4, flex: 1 }}>
                  <input className="input" type="text" inputMode="decimal" autoFocus
                         value={invInput} onChange={e => setInvInput(e.target.value)}
                         onKeyDown={e => e.key === 'Enter' && saveInv()} style={{ flex: 1 }}/>
                  <span style={{ color: 'var(--text-mute)', fontSize: 12 }}>%</span>
                </div>
                <button className="btn btn-primary" onClick={saveInv} disabled={invSaving}><Icon name="check" size={13}/></button>
                <button className="btn btn-ghost" onClick={() => setInvEdit(false)}><Icon name="x" size={13}/></button>
              </div>
            ) : (
              <div className="hstack" style={{ alignItems: 'baseline', gap: 10 }}>
                <span className="display num" style={{ fontSize: 28 }}>{Math.round((investmentTarget || 0) * 100)}%</span>
                <button className="btn btn-ghost" style={{ padding: '2px 8px', fontSize: 11 }}
                        onClick={() => { setInvInput(String(Math.round((investmentTarget || 0) * 100))); setInvEdit(true); }}>
                  editar
                </button>
              </div>
            )}
          </div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 16 }}>
        {goals.map(g => {
          const ratio      = Math.min(1, g.current / g.target);
          const deadline   = new Date(g.deadline);
          const monthsLeft = Math.max(1, Math.ceil((deadline - new Date()) / (1000 * 60 * 60 * 24 * 30)));
          const needed     = Math.max(0, (g.target - g.current) / monthsLeft);
          return (
            <div key={g.id} className="goal-card">
              <div style={{ position: 'absolute', top: 0, right: 0, width: 120, height: 120, background: `radial-gradient(circle, ${g.color}22, transparent 70%)`, pointerEvents: 'none' }}/>
              <div className="goal-head">
                <div className="goal-icon" style={{ background: `color-mix(in oklch, ${g.color} 18%, white)` }}>{g.icon}</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 600, fontSize: 15 }}>{g.name}</div>
                  <div className="muted" style={{ fontSize: 11 }}>até {deadline.toLocaleDateString('pt-BR', { month: 'short', year: 'numeric' })}</div>
                </div>
                <div className="hstack" style={{ gap: 2 }}>
                  <button title="Adicionar valor" onClick={() => setDeposit(g)}
                          style={{ padding: 4, borderRadius: 6, color: 'var(--income)', background: 'var(--income-bg)' }}>
                    <Icon name="plus" size={13}/>
                  </button>
                  <button title="Editar" onClick={() => setModal(g)}
                          style={{ padding: 4, borderRadius: 6, color: 'var(--text-mute)' }}>
                    <Icon name="edit" size={13}/>
                  </button>
                  <button title="Excluir" onClick={() => deleteGoal(g)}
                          style={{ padding: 4, borderRadius: 6, color: 'var(--expense)' }}>
                    <Icon name="trash" size={13}/>
                  </button>
                </div>
              </div>
              <div className="hstack" style={{ justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 12 }}>
                <Currency cents={g.current} />
                <span className="muted num" style={{ fontSize: 13 }}>de {fmtBRLShort(g.target)}</span>
              </div>
              <div className="progress" style={{ height: 10, marginBottom: 12 }}>
                <div className="progress-fill" style={{ width: `${ratio * 100}%`, background: g.color }}/>
              </div>
              <div className="hstack" style={{ justifyContent: 'space-between', fontSize: 11 }}>
                <span className="muted">{pct(ratio)} completo</span>
                <span className="num" style={{ fontWeight: 600, color: g.color }}>{fmtBRL(needed)}/mês</span>
              </div>
            </div>
          );
        })}

        {goals.length === 0 && (
          <div style={{ textAlign: 'center', padding: '48px 24px', color: 'var(--text-mute)', gridColumn: '1 / -1' }}>
            <div style={{ fontSize: 32, marginBottom: 12 }}>🎯</div>
            <div style={{ fontWeight: 500 }}>Nenhuma meta ainda</div>
            <div style={{ fontSize: 12, marginTop: 4 }}>Crie sua primeira meta acima.</div>
          </div>
        )}
      </div>

      {modal !== null && (
        <GoalModal goal={modal === 'create' ? null : modal} state={state} setState={setState} onClose={() => setModal(null)} />
      )}
      {deposit && (
        <DepositModal goal={deposit} state={state} setState={setState} onClose={() => setDeposit(null)} />
      )}
    </div>
  );
}

// ========== SUBSCRIPTIONS ==========
function Subs({ state, setState }) {
  const { subs, tags, users, user } = state;
  const [modal, setModal] = React.useState(null);

  const visible    = subs.filter(s => s.ownerId === user.id || s.shared);
  const active     = visible.filter(s => s.active);
  const monthly    = active.reduce((t, s) => t + s.amount, 0);
  const yearly     = monthly * 12;
  const viaCartao  = active.filter(s => s.cardLinked).reduce((t, s) => t + s.amount, 0);

  const deleteSub = (s) => {
    if (!window.confirm(`Excluir "${s.name}"?`)) return;
    fetch(`/api/subscriptions/${s.id}`, { method: 'DELETE' })
      .then(() => setState(st => ({ ...st, subs: st.subs.filter(x => x.id !== s.id) })));
  };

  const toggleSub = (s) => {
    fetch(`/api/subscriptions/${s.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...s, active: !s.active }),
    })
      .then(r => r.json())
      .then(saved => setState(st => ({ ...st, subs: st.subs.map(x => x.id === saved.id ? saved : x) })));
  };

  return (
    <div>
      <div className="page-head">
        <div>
          <div className="dim" style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em' }}>assinaturas recorrentes</div>
          <h1 className="page-title">O que se repete</h1>
          <div className="page-subtitle">{active.length} ativas · geradas automaticamente no fluxo</div>
        </div>
        <button className="btn btn-primary" onClick={() => setModal('create')}><Icon name="plus" size={14}/> Nova assinatura</button>
      </div>

      <div className="kpi-grid" style={{ gridTemplateColumns: 'repeat(3, 1fr)' }}>
        <div className="kpi">
          <div className="kpi-label"><span className="kpi-dot" style={{ background: 'var(--c-assinaturas)' }}/> Gasto mensal</div>
          <div className="kpi-value"><Currency cents={monthly} /></div>
          <div className="kpi-meta">
            {active.length} ativas
            {viaCartao > 0 && <span className="muted"> · 💳 {fmtBRL(viaCartao)} via cartão</span>}
          </div>
        </div>
        <div className="kpi">
          <div className="kpi-label"><span className="kpi-dot" style={{ background: 'var(--c-lazer)' }}/> Projeção anual</div>
          <div className="kpi-value"><Currency cents={yearly} /></div>
          <div className="kpi-meta">se nada mudar</div>
        </div>
        <div className="kpi">
          <div className="kpi-label"><span className="kpi-dot" style={{ background: 'var(--c-outros)' }}/> Inativas</div>
          <div className="kpi-value display num" style={{ fontSize: 46 }}>{visible.length - active.length}</div>
          <div className="kpi-meta">pausadas ou canceladas</div>
        </div>
      </div>

      <div className="card" style={{ padding: 0 }}>
        {visible.length === 0 ? (
          <div style={{ textAlign: 'center', padding: '48px 24px', color: 'var(--text-mute)' }}>
            <div style={{ fontSize: 32, marginBottom: 12 }}>📺</div>
            <div style={{ fontWeight: 500 }}>Nenhuma assinatura</div>
            <div style={{ fontSize: 12, marginTop: 4 }}>Adicione sua primeira assinatura acima.</div>
          </div>
        ) : (
          <table className="tx-table">
            <thead>
              <tr>
                <th></th>
                <th>Nome</th>
                <th className="col-tags">Categoria</th>
                <th>Dono</th>
                <th>Cobrança</th>
                <th style={{ textAlign: 'right' }}>Valor</th>
                <th style={{ textAlign: 'right' }}>Status</th>
                <th style={{ width: 64 }}></th>
              </tr>
            </thead>
            <tbody>
              {visible.map(s => {
                const tag     = tags.find(t => t.id === s.tag);
                const owner   = users.find(u => u.id === s.ownerId);
                if (!tag || !owner) return null;
                const isOwner = s.ownerId === user.id;
                return (
                  <tr key={s.id} style={{ opacity: s.active ? 1 : 0.5 }}>
                    <td>
                      <div style={{ width: 28, height: 28, borderRadius: 8, background: `color-mix(in oklch, ${tag.color} 16%, white)`, display: 'grid', placeItems: 'center' }}>{tag.icon}</div>
                    </td>
                    <td style={{ fontWeight: 500 }}>
                      {s.name}
                      {s.shared && <span style={{ marginLeft: 6, fontSize: 10, opacity: 0.6 }}>🔗</span>}
                      {s.cardLinked && <span title="Vinculada a cartão" style={{ marginLeft: 4, fontSize: 12, opacity: 0.7 }}>💳</span>}
                    </td>
                    <td className="col-tags"><TagPill tag={tag}/></td>
                    <td>
                      <span className="hstack" style={{ gap: 6 }}>
                        <Avatar user={owner} size="xs"/>
                        <span style={{ fontSize: 11, color: 'var(--text-mute)' }}>{owner.name}</span>
                      </span>
                    </td>
                    <td className="num" style={{ fontSize: 12, color: 'var(--text-dim)' }}>dia {s.day}/mês</td>
                    <td className="tx-amount">{fmtBRL(s.amount, { noPrefix: true })}</td>
                    <td style={{ textAlign: 'right' }}>
                      {isOwner ? (
                        <button onClick={() => toggleSub(s)}
                                style={{ fontSize: 11, fontWeight: 600, padding: '3px 8px', borderRadius: 999, cursor: 'pointer', border: 'none',
                                         background: s.active ? 'var(--income-bg)' : 'var(--bg-sunken)',
                                         color: s.active ? 'var(--income)' : 'var(--text-mute)' }}>
                          {s.active ? 'ativa' : 'pausada'}
                        </button>
                      ) : (
                        <span style={{ fontSize: 11, fontWeight: 600, padding: '3px 8px', borderRadius: 999,
                                       background: s.active ? 'var(--income-bg)' : 'var(--bg-sunken)',
                                       color: s.active ? 'var(--income)' : 'var(--text-mute)' }}>
                          {s.active ? 'ativa' : 'pausada'}
                        </span>
                      )}
                    </td>
                    <td>
                      {isOwner && (
                        <div className="hstack" style={{ gap: 2, justifyContent: 'flex-end' }}>
                          <button title="Editar" onClick={() => setModal(s)}
                                  style={{ padding: 4, borderRadius: 6, color: 'var(--text-mute)' }}>
                            <Icon name="edit" size={14}/>
                          </button>
                          <button title="Excluir" onClick={() => deleteSub(s)}
                                  style={{ padding: 4, borderRadius: 6, color: 'var(--expense)' }}>
                            <Icon name="trash" size={14}/>
                          </button>
                        </div>
                      )}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </div>

      {modal !== null && (
        <SubModal sub={modal === 'create' ? null : modal} state={state} setState={setState} onClose={() => setModal(null)} />
      )}
    </div>
  );
}

// ========== ASSETS / PATRIMÔNIO ==========
function Assets({ state, setState }) {
  const { assets, users, user } = state;
  const [modal, setModal] = React.useState(null);

  const total    = assets.reduce((s, a) => s + a.value, 0);
  const byType   = assets.reduce((acc, a) => { acc[a.type] = (acc[a.type] || 0) + a.value; return acc; }, {});
  const typeColors = { bank_account: 'var(--c-mercado)', investment: 'var(--c-moradia)', property: 'var(--c-transporte)', other: 'var(--c-outros)' };
  const typeNames  = { bank_account: 'Contas', investment: 'Investimentos', property: 'Imóveis', other: 'Outros' };
  const totalHistory = assets[0] ? assets[0].history.map((_, i) => assets.reduce((s, a) => s + (a.history[i] || 0), 0)) : [];

  const deleteAsset = (a) => {
    if (!window.confirm(`Excluir "${a.name}"?`)) return;
    fetch(`/api/assets/${a.id}`, { method: 'DELETE' })
      .then(() => setState(s => ({ ...s, assets: s.assets.filter(x => x.id !== a.id) })));
  };

  return (
    <div>
      <div className="page-head">
        <div>
          <div className="dim" style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em' }}>patrimônio</div>
          <h1 className="page-title">Seu net worth</h1>
          <div className="page-subtitle">Últimos 6 meses de evolução · todos os ativos somados</div>
        </div>
        <button className="btn btn-primary" onClick={() => setModal('create')}><Icon name="plus" size={14}/> Novo ativo</button>
      </div>

      <div className="card" style={{ marginBottom: 'var(--s5)' }}>
        <div className="hstack" style={{ justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 24 }}>
          <div>
            <div className="muted" style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em' }}>total líquido</div>
            <div style={{ marginTop: 8 }}><Currency cents={total} /></div>
            <div className="hstack" style={{ marginTop: 10, fontSize: 12 }}>
              <span className="delta up"><Icon name="arrowUp" size={10}/> últimos 6 meses</span>
              <span className="muted">+{totalHistory.length > 1 ? fmtBRL(total - totalHistory[0]) : fmtBRL(0)}</span>
            </div>
          </div>
          <div className="chip-select">
            <button>1M</button><button>3M</button><button className="active">6M</button><button>1A</button>
          </div>
        </div>
        <LineChart data={totalHistory} color="var(--c-moradia)" />
      </div>

      <div className="grid-2">
        <div className="card">
          <div className="card-head"><h3 className="card-title-lg">Ativos</h3></div>
          <div className="vstack" style={{ gap: 12 }}>
            {assets.map(a => {
              const owner  = users.find(u => u.id === a.ownerId);
              const growth = a.history.length > 1 ? (a.value - a.history[0]) / a.history[0] : 0;
              return (
                <div key={a.id} className="hstack" style={{ justifyContent: 'space-between', padding: '10px 0', borderBottom: '1px solid var(--border)', alignItems: 'center' }}>
                  <div className="hstack" style={{ flex: 1 }}>
                    <div style={{ width: 36, height: 36, borderRadius: 10, background: `color-mix(in oklch, ${typeColors[a.type] || 'var(--c-outros)'} 15%, white)`, display: 'grid', placeItems: 'center', color: typeColors[a.type] || 'var(--c-outros)' }}>
                      <Icon name={a.type === 'investment' ? 'trend' : a.type === 'property' ? 'home' : 'wallet'} size={18}/>
                    </div>
                    <div>
                      <div style={{ fontWeight: 500, fontSize: 13 }}>{a.name}</div>
                      <div className="muted" style={{ fontSize: 11 }}>{typeNames[a.type] || 'Outros'} · {owner ? owner.name : '?'}</div>
                    </div>
                  </div>
                  <div style={{ textAlign: 'right', marginRight: 8 }}>
                    <div className="num" style={{ fontWeight: 600 }}>{fmtBRL(a.value)}</div>
                    <div style={{ fontSize: 11, color: growth >= 0 ? 'var(--income)' : 'var(--expense)' }}>
                      {growth >= 0 ? '+' : ''}{pctFine(growth)}
                    </div>
                  </div>
                  <div className="hstack" style={{ gap: 2 }}>
                    <button title="Editar" onClick={() => setModal(a)}
                            style={{ padding: 4, borderRadius: 6, color: 'var(--text-mute)' }}>
                      <Icon name="edit" size={14}/>
                    </button>
                    <button title="Excluir" onClick={() => deleteAsset(a)}
                            style={{ padding: 4, borderRadius: 6, color: 'var(--expense)' }}>
                      <Icon name="trash" size={14}/>
                    </button>
                  </div>
                </div>
              );
            })}
            {assets.length === 0 && (
              <div style={{ textAlign: 'center', padding: '32px 0', color: 'var(--text-mute)' }}>
                <div style={{ fontWeight: 500 }}>Nenhum ativo cadastrado</div>
              </div>
            )}
          </div>
        </div>
        <div className="card">
          <div className="card-head"><h3 className="card-title-lg">Alocação</h3></div>
          <div className="vstack" style={{ gap: 14 }}>
            {total === 0 ? (
              <p className="muted" style={{ fontSize: 13, textAlign: 'center', padding: '16px 0' }}>Sem ativos</p>
            ) : Object.entries(byType).map(([type, val]) => {
              const share = val / total;
              return (
                <div key={type}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 6 }}>
                    <span style={{ fontWeight: 500, fontSize: 13 }}>{typeNames[type] || type}</span>
                    <span className="num" style={{ fontWeight: 600 }}>{fmtBRL(val)}</span>
                  </div>
                  <div className="progress" style={{ height: 8 }}>
                    <div className="progress-fill" style={{ width: `${share * 100}%`, background: typeColors[type] || 'var(--c-outros)' }}/>
                  </div>
                  <div className="muted" style={{ fontSize: 11, marginTop: 4 }}>{pctFine(share)} do patrimônio</div>
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {modal !== null && (
        <AssetModal asset={modal === 'create' ? null : modal} state={state} setState={setState} onClose={() => setModal(null)} />
      )}
    </div>
  );
}

function LineChart({ data, color = 'var(--accent)' }) {
  if (!data || data.length < 2) return null;
  const W = 800, H = 220, P = 20;
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const points = data.map((v, i) => {
    const x = P + (i / (data.length - 1)) * (W - P * 2);
    const y = H - P - ((v - min) / range) * (H - P * 2);
    return [x, y];
  });
  const path = points.map(([x,y], i) => (i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`)).join(' ');
  const area = `${path} L ${W - P} ${H - P} L ${P} ${H - P} Z`;
  const now = new Date();
  const months = Array.from({ length: 6 }, (_, i) => {
    const d = new Date(now.getFullYear(), now.getMonth() - 5 + i, 1);
    return MONTH_NAMES_PT[d.getMonth()];
  });
  return (
    <svg viewBox={`0 0 ${W} ${H + 20}`} width="100%" style={{ display: 'block' }}>
      <defs>
        <linearGradient id="areagrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.25"/>
          <stop offset="100%" stopColor={color} stopOpacity="0"/>
        </linearGradient>
      </defs>
      {[0.25, 0.5, 0.75].map(f => (
        <line key={f} x1={P} x2={W-P} y1={P + f*(H-P*2)} y2={P + f*(H-P*2)} stroke="var(--border)" strokeDasharray="2 4"/>
      ))}
      <path d={area} fill="url(#areagrad)"/>
      <path d={path} fill="none" stroke={color} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
      {points.map(([x,y], i) => (
        <circle key={i} cx={x} cy={y} r={i === points.length - 1 ? 5 : 3} fill={color} stroke="white" strokeWidth="2"/>
      ))}
      {months.map((m, i) => {
        const x = P + (i / (months.length - 1)) * (W - P * 2);
        return <text key={i} x={x} y={H + 12} textAnchor="middle" fill="var(--text-mute)" fontSize="11" fontFamily="var(--f-ui)">{m}</text>;
      })}
    </svg>
  );
}

// ========== MONTHLY SUMMARY ==========
function Monthly({ state }) {
  const { history, txs, user, assets } = state;
  const currentMonth = new Date().toISOString().slice(0, 7);
  const monthTxs = txs.filter(t => t.date.startsWith(currentMonth) && (t.userId === user.id || t.shared));
  const bars = [
    ...history,
    {
      month:    currentMonth,
      income:   monthTxs.filter(t => t.type === 'income').reduce((s,t) => s + t.amount, 0),
      expenses: monthTxs.filter(t => t.type === 'expense').reduce((s,t) => s + t.amount, 0),
    },
  ];

  // 12-month projection based on last 3 complete months
  const completeHistory = bars.slice(0, bars.length - 1);
  const last3 = completeHistory.slice(-3);
  const avgIncome   = last3.length > 0 ? last3.reduce((s, b) => s + (b.income || 0), 0) / last3.length : 0;
  const avgExpenses = last3.length > 0 ? last3.reduce((s, b) => s + (b.expenses || 0), 0) / last3.length : 0;
  const avgSavings  = avgIncome - avgExpenses;
  const currentPatrimony = (assets || []).reduce((s, a) => s + a.value, 0);

  const nextMonths = Array.from({ length: 12 }, (_, i) => {
    const d = new Date();
    d.setDate(1);
    d.setMonth(d.getMonth() + i + 1);
    return {
      month:     d.toISOString().slice(0, 7),
      income:    avgIncome,
      expenses:  avgExpenses,
      savings:   avgSavings,
      patrimony: currentPatrimony + avgSavings * (i + 1),
    };
  });

  return (
    <div>
      <div className="page-head">
        <div>
          <div className="dim" style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em' }}>resumo mensal</div>
          <h1 className="page-title">6 meses lado a lado</h1>
          <div className="page-subtitle">Comparação de receita, despesa e economia ao longo dos meses</div>
        </div>
      </div>
      <div className="card" style={{ padding: 0, overflow: 'hidden', marginBottom: 'var(--s5)' }}>
        <table className="tx-table">
          <thead>
            <tr>
              <th>Mês</th>
              <th style={{ textAlign: 'right' }}>Entradas</th>
              <th style={{ textAlign: 'right' }}>Saídas</th>
              <th style={{ textAlign: 'right' }}>Economia</th>
              <th style={{ textAlign: 'right' }}>% economia</th>
              <th style={{ textAlign: 'right' }}>% gasto</th>
            </tr>
          </thead>
          <tbody>
            {bars.slice().reverse().map((b, i) => {
              const [y, m] = (b.month || '').split('-');
              const savings  = (b.income || 0) - (b.expenses || 0);
              const rate     = b.income > 0 ? Math.max(0, savings / b.income) : 0;
              const exprate  = b.income > 0 ? b.expenses / b.income : 0;
              const isCurrent = i === 0;
              return (
                <tr key={b.month} style={isCurrent ? { background: 'var(--accent-bg)' } : {}}>
                  <td style={{ fontWeight: 600, textTransform: 'capitalize' }}>
                    {m ? MONTH_NAMES_PT[+m - 1] : ''} / {y}
                    {isCurrent && <span style={{ marginLeft: 8, fontSize: 10, padding: '2px 6px', borderRadius: 4, background: 'var(--accent)', color: 'white', fontWeight: 600 }}>atual</span>}
                  </td>
                  <td className="tx-amount income">{fmtBRL(b.income || 0, { noPrefix: true })}</td>
                  <td className="tx-amount">{fmtBRL(b.expenses || 0, { noPrefix: true })}</td>
                  <td className="tx-amount" style={{ color: savings >= 0 ? 'var(--income)' : 'var(--expense)' }}>
                    {savings >= 0 ? '+' : '−'} {fmtBRL(Math.abs(savings), { noPrefix: true })}
                  </td>
                  <td className="balance-cell" style={{ color: rate >= 0.2 ? 'var(--income)' : 'var(--text-dim)' }}>{pctFine(rate)}</td>
                  <td className="balance-cell">{pctFine(exprate)}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      {last3.length >= 1 && (
        <div>
          <div className="page-head" style={{ marginBottom: 'var(--s4)' }}>
            <div>
              <div className="dim" style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em' }}>projeção</div>
              <h2 className="page-title" style={{ fontSize: 28 }}>Próximos 12 meses</h2>
              <div className="page-subtitle">
                Baseado na média dos últimos {last3.length} {last3.length === 1 ? 'mês completo' : 'meses completos'} ·
                média mensal: <strong>{fmtBRL(avgIncome)}</strong> entrada / <strong>{fmtBRL(avgExpenses)}</strong> saída
              </div>
            </div>
          </div>
          <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
            <table className="tx-table">
              <thead>
                <tr>
                  <th>Mês</th>
                  <th style={{ textAlign: 'right' }}>Renda prevista</th>
                  <th style={{ textAlign: 'right' }}>Despesas previstas</th>
                  <th style={{ textAlign: 'right' }}>Economia</th>
                  <th style={{ textAlign: 'right', background: 'var(--accent-bg)' }}>Patrimônio est.</th>
                </tr>
              </thead>
              <tbody>
                {nextMonths.map((b, i) => {
                  const [y, m] = b.month.split('-');
                  return (
                    <tr key={b.month}>
                      <td style={{ fontWeight: 500, textTransform: 'capitalize' }}>
                        {MONTH_NAMES_PT[+m - 1]} / {y}
                      </td>
                      <td className="tx-amount income">{fmtBRL(b.income, { noPrefix: true })}</td>
                      <td className="tx-amount">{fmtBRL(b.expenses, { noPrefix: true })}</td>
                      <td className="tx-amount" style={{ color: b.savings >= 0 ? 'var(--income)' : 'var(--expense)' }}>
                        {b.savings >= 0 ? '+' : '−'} {fmtBRL(Math.abs(b.savings), { noPrefix: true })}
                      </td>
                      <td className="balance-cell num" style={{ background: 'var(--accent-bg)', fontWeight: 600, color: i === 11 ? 'var(--accent)' : undefined }}>
                        {fmtBRL(b.patrimony)}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          <p className="muted" style={{ fontSize: 11, marginTop: 10, textAlign: 'center' }}>
            Projeção linear baseada na média histórica. Não considera inflação, variações de renda ou emergências.
          </p>
        </div>
      )}
    </div>
  );
}

window.Goals           = Goals;
window.Subs            = Subs;
window.Assets          = Assets;
window.Monthly         = Monthly;
window.TagsManagerModal = TagsManagerModal;
