// Sisyphus — Analisis & Mas screens v2
const seed2 = window.SisyphusSeed;
const S2 = window.S;
const Icon2 = window.Icon;
const { Card: Card2, SectionHeader: SH2, CatChip: CC2 } = window;
const { useState: useState2, useMemo: useMemo2, useEffect: useEffect2, useRef: useRef2 } = React;

// ─── ANÁLISIS ─────────────────────────────────────────────────────────────────
function AnalisisScreen({ ccy, isDesktop, spentState, budgets, onBudgetsChange, embedded, sueldo, onSueldoChange, sueldoDia, onSueldoDiaChange, extraIngresos, onExtraIngresosChange }) {
  const [tab, setTab] = useState2('donut');

  // Compute effectiveSpent from movimientos — more accurate than spentState alone
  const effectiveSpent = useMemo2(() => {
    const NS = 'sisyphus.v1.';
    let stored = [];
    try { stored = JSON.parse(localStorage.getItem(NS + 'movimientos') || '[]'); } catch {}
    // Also check SisyStore
    let sisMovs = [];
    try { sisMovs = window.SisyStore?.getMovs?.() || []; } catch {}
    const seenIds = new Set(stored.map(m => m.id));
    const all = [...stored, ...sisMovs.filter(m => !seenIds.has(m.id))];
    const computed = {};
    all.forEach(m => {
      if (m.kind === 'ingreso' || !m.cat) return;
      computed[m.cat] = (computed[m.cat] || 0) + Math.abs(m.amount || 0);
    });
    const propTotal     = Object.values(spentState || {}).reduce((a,b) => a+(b||0), 0);
    const computedTotal = Object.values(computed).reduce((a,b) => a+b, 0);
    return computedTotal >= propTotal ? computed : (spentState || {});
  }, [spentState]);

  const dist = (S2 && seed2) ? S2.distribucion(effectiveSpent, budgets) : [];
  const totalEgr = dist.filter(d => seed2.grupoPorId[d.group]?.id !== 'ahorro').reduce((a,b) => a+b.spent, 0);

  const tabs2 = isDesktop
    ? [{ id:'donut', label:'Distribución' }, { id:'trend', label:'Histórico' }]
    : [
        { id:'donut',   label:'Donut' },
        { id:'sliders', label:'Sliders' },
        { id:'fx',      label:'FX' },
        { id:'trend',   label:'Histórico' },
      ];

  // When embedded inside MovScreen, skip outer padding + header (MovScreen owns those)
  const outerPad = embedded ? 0 : (isDesktop ? '20px 28px 44px' : 'var(--sp) var(--sp) var(--sp-bottom)');

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16, padding: outerPad }}>
      {!embedded && (
        <div>
          <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize: isDesktop ? 22 : 26, fontWeight:600, letterSpacing:'-0.02em', marginBottom:4 }}>Análisis</div>
          <div style={{ fontSize:12.5, color:'var(--text-3)' }}>Distribución, presupuesto y conversión</div>
        </div>
      )}

      <div style={{ display:'flex', padding:4, background:'var(--card)', border:'1px solid var(--border)', borderRadius:12, gap:2 }}>
        {tabs2.map(t => (
          <button key={t.id} onClick={() => setTab(t.id)} style={{
            flex:1, padding:'9px 0', borderRadius:9,
            background: tab===t.id ? 'var(--accent-dim)' : 'transparent',
            color: tab===t.id ? 'var(--accent-bright)' : 'var(--text-2)',
            border:'none', cursor:'pointer', fontFamily:'inherit',
            fontSize:12.5, fontWeight:600,
            transition:'background 0.14s, color 0.14s',
          }}>{t.label}</button>
        ))}
      </div>

      {tab === 'donut'   && <DonutPane   dist={dist} totalEgr={totalEgr} ccy={ccy} isDesktop={isDesktop} />}
      {tab === 'sliders' && <SlidersPane ccy={ccy} spentState={effectiveSpent} budgets={budgets} onBudgetsChange={onBudgetsChange || (() => {})} sueldo={sueldo} onSueldoChange={onSueldoChange} sueldoDia={sueldoDia} onSueldoDiaChange={onSueldoDiaChange} extraIngresos={extraIngresos} onExtraIngresosChange={onExtraIngresosChange} />}
      {tab === 'fx'      && <FXPane />}
      {tab === 'trend'   && <TrendPane   ccy={ccy} />}
    </div>
  );
}

function DonutPane({ dist, totalEgr, ccy, isDesktop }) {
  const [hover, setHover] = useState2(null);
  const fmt = n => S2.fmtMoney(ccy === 'USD' ? n / seed2.fxBlue : n, ccy);

  const byGroup = seed2.groups.map(g => {
    const items = dist.filter(d => d.group === g.id);
    return { ...g, total: items.reduce((a,b) => a+b.spent, 0), items };
  });
  const gTotal = byGroup.reduce((a,b) => a+b.total, 0);
  const segColors = ['var(--accent-bright)', 'var(--accent)', 'var(--accent-deep)', '#6366f1'];

  // Guard: nothing spent yet
  if (gTotal === 0) {
    return (
      <div style={{ textAlign:'center', padding:'48px 20px', color:'var(--text-3)', fontSize:14 }}>
        <div style={{ width:52, height:52, borderRadius:16, background:'var(--accent-dim)', display:'flex', alignItems:'center', justifyContent:'center', margin:'0 auto 14px', color:'var(--accent-bright)' }}>
          <Icon2 name="pie" size={24} strokeWidth={1.6} />
        </div>
        Sin gastos registrados aún
      </div>
    );
  }

  const radius = 88, stroke = 28, cx = 110, cy = 110;
  const circ = 2 * Math.PI * radius;
  let offset = 0;
  const segs = byGroup.map((g, i) => {
    const portion = g.total / gTotal;
    const len = circ * portion;
    const seg = { ...g, len, offset, color: segColors[i] };
    offset += len;
    return seg;
  });

  const selected = hover != null ? byGroup[hover] : null;
  const centerLabel = selected ? selected.name : 'Total egresos';
  const centerValue = selected ? fmt(selected.total) : fmt(totalEgr);
  const centerSub   = selected ? `${Math.round(selected.total/gTotal*100)}% del total` : 'mes corriente';

  const donutSvg = (
    <div style={{ width:220, height:220, position:'relative', flexShrink:0 }}>
      <svg width="220" height="220" viewBox="0 0 220 220" style={{ transform:'rotate(-90deg)' }}>
        <circle cx={cx} cy={cy} r={radius} fill="none" stroke="rgba(255,255,255,0.05)" strokeWidth={stroke} />
        {segs.map((s, i) => (
          <circle key={s.id} cx={cx} cy={cy} r={radius} fill="none"
            stroke={s.color} strokeWidth={stroke}
            strokeDasharray={`${s.len} ${circ - s.len}`}
            strokeDashoffset={-s.offset}
            style={{ cursor:'pointer', opacity: hover != null && hover !== i ? 0.32 : 1, transition:'opacity 0.2s, filter 0.2s', filter: hover===i ? 'drop-shadow(0 0 12px currentColor)' : 'none' }}
            onMouseEnter={() => setHover(i)} onMouseLeave={() => setHover(null)}
            onClick={() => setHover(h => h===i ? null : i)}
          />
        ))}
      </svg>
      <div style={{ position:'absolute', inset:0, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', textAlign:'center', pointerEvents:'none' }}>
        <div style={{ fontSize:10.5, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600 }}>{centerLabel}</div>
        <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:22, fontWeight:600, letterSpacing:'-0.02em', marginTop:6, fontVariantNumeric:'tabular-nums' }}>{centerValue}</div>
        <div style={{ fontSize:11, color:'var(--text-3)', marginTop:4 }}>{centerSub}</div>
      </div>
    </div>
  );

  const legend = (
    <div style={{ display:'flex', flexDirection:'column', gap:6, flex:1 }}>
      {byGroup.map((g, i) => (
        <div key={g.id} onClick={() => setHover(h => h===i ? null : i)} style={{
          padding:'12px 14px', borderRadius:12, cursor:'pointer',
          background: hover===i ? 'var(--card)' : 'transparent',
          border:`1px solid ${hover===i ? 'var(--border-strong)' : 'transparent'}`,
          transition:'all 0.15s',
        }}>
          <div style={{ display:'flex', alignItems:'center', gap:10 }}>
            <div style={{ width:10, height:10, borderRadius:3, background:segs[i].color, flexShrink:0 }} />
            <div style={{ flex:1, fontSize:13.5, fontWeight:600 }}>{g.name}</div>
            <div style={{ fontSize:13, fontWeight:600, fontVariantNumeric:'tabular-nums' }}>{fmt(g.total)}</div>
            <div style={{ fontSize:11.5, color:'var(--text-3)', minWidth:36, textAlign:'right', fontVariantNumeric:'tabular-nums' }}>{Math.round(g.total/gTotal*100)}%</div>
          </div>
          {hover===i && (
            <div style={{ marginTop:10, paddingTop:10, borderTop:'1px solid var(--border)', display:'flex', flexDirection:'column', gap:6 }}>
              {g.items.map(it => (
                <div key={it.id} style={{ display:'flex', alignItems:'center', gap:10, fontSize:12.5 }}>
                  <CC2 cat={it} size={22} />
                  <div style={{ flex:1, color:'var(--text-2)' }}>{it.name}</div>
                  <div style={{ fontVariantNumeric:'tabular-nums', color: it.pct > 1 ? 'var(--red)' : 'var(--text)' }}>{fmt(it.spent)}</div>
                  <div style={{ fontSize:10.5, color: it.pct > 1 ? 'var(--red)' : 'var(--text-3)', minWidth:32, textAlign:'right' }}>{Math.round(it.pct*100)}%</div>
                </div>
              ))}
            </div>
          )}
        </div>
      ))}
    </div>
  );

  if (isDesktop) {
    return (
      <div style={{ display:'flex', gap:28, alignItems:'flex-start' }}>
        <Card2 padding={28} style={{ display:'flex', flexDirection:'column', alignItems:'center', flexShrink:0 }}>
          {donutSvg}
        </Card2>
        <div style={{ flex:1, minWidth:0 }}>
          <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:15, fontWeight:600, letterSpacing:'-0.01em', padding:'0 4px 10px' }}>Por grupo</div>
          {legend}
        </div>
      </div>
    );
  }

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
      <Card2 padding={20} style={{ display:'flex', flexDirection:'column', alignItems:'center' }}>
        {donutSvg}
      </Card2>
      {legend}
    </div>
  );
}

function DayPicker({ value, onChange }) {
  const days = Array.from({ length: 31 }, (_, i) => i + 1);
  return (
    <div style={{ display:'grid', gridTemplateColumns:'repeat(7, 1fr)', gap:4, marginTop:10 }}>
      {days.map(d => (
        <button key={d} onClick={() => onChange(d)} style={{
          padding:'6px 0', borderRadius:7, border:'none', cursor:'pointer', fontFamily:'Space Grotesk, sans-serif',
          fontSize:12, fontWeight: d === value ? 700 : 400,
          background: d === value ? 'var(--accent)' : 'rgba(255,255,255,0.04)',
          color: d === value ? 'var(--on-accent)' : 'var(--text-2)',
          transition:'all 0.12s',
        }}>{d}</button>
      ))}
    </div>
  );
}

// Helper: read a number from localStorage
function _lsNum(key, fallback = 0) {
  try { const v = JSON.parse(localStorage.getItem(key)); return (v != null && !isNaN(+v)) ? +v : fallback; } catch { return fallback; }
}
// Format number with es-AR thousands separator
function _fmtNum(n) {
  return new Intl.NumberFormat('es-AR', { maximumFractionDigits: 0 }).format(Math.round(n || 0));
}
// Parse formatted number back to integer
function _parseNum(s) {
  return Math.max(0, parseInt((s || '0').replace(/\./g, '').replace(/,/g, '.')) || 0);
}

function SlidersPane({ ccy, spentState, budgets: budgetsProp, onBudgetsChange, extraIngresos, onExtraIngresosChange, sueldo: sueldoProp, onSueldoChange, sueldoDia: sueldoDiaProp, onSueldoDiaChange }) {
  const [localBudgets, setLocalBudgets] = useState2(() => Object.fromEntries(seed2.categories.map(c => [c.id, c.budget])));
  const budgets = budgetsProp || localBudgets;
  const setBudgets = onBudgetsChange || setLocalBudgets;
  const fmt = n => S2.fmtMoney(ccy === 'USD' ? n / seed2.fxBlue : n, ccy);

  // Deleted seed cat IDs + custom cats — persisted in localStorage
  const [deletedCats, setDeletedCats] = useState2(() => {
    try { return JSON.parse(localStorage.getItem('sis.deleted_cats') || '[]'); } catch { return []; }
  });
  const [customCats, setCustomCats] = useState2(() => {
    try { return JSON.parse(localStorage.getItem('sis.custom_cats') || '[]'); } catch { return []; }
  });

  // New category form
  const [showNewCat, setShowNewCat] = useState2(false);
  const [newName,    setNewName]    = useState2('');
  const [newIcon,    setNewIcon]    = useState2('star');
  const [newColor,   setNewColor]   = useState2('#8b5cf6');
  const [newBudget,  setNewBudget]  = useState2('');

  // Save button feedback
  const [savedAnim, setSavedAnim] = useState2(false);

  // Income state — fall back to localStorage when not provided as prop
  const NS = 'sisyphus.v1.';
  const sueldoBase = sueldoProp != null ? sueldoProp : _lsNum(NS + 'sueldo', 0);
  const sueldoDia  = sueldoDiaProp != null ? sueldoDiaProp : _lsNum(NS + 'sueldo_dia', 25);
  const extraBase  = extraIngresos != null ? extraIngresos : _lsNum(NS + 'extra_ing', 0);

  // Track whether user is actively editing (show raw) or viewing (show formatted)
  const [sueldoRaw,    setSueldoRaw]    = useState2(false);
  const [extraRaw,     setExtraRaw]     = useState2(false);
  const [sueldoInput,  setSueldoInput]  = useState2(_fmtNum(sueldoBase));
  const [extraInput,   setExtraInput]   = useState2(_fmtNum(extraBase));
  const [showDayPicker, setShowDayPicker] = useState2(false);

  // Sync inputs when props change from outside (e.g. onboarding sets value)
  const { useEffect: useE2 } = React;
  useE2(() => {
    if (!sueldoRaw) setSueldoInput(_fmtNum(sueldoBase));
  }, [sueldoBase]);
  useE2(() => {
    if (!extraRaw) setExtraInput(_fmtNum(extraBase));
  }, [extraBase]);

  const totalIng = sueldoBase + extraBase;

  // All visible categories = seed (minus deleted) + custom
  const seedList   = seed2.categories.filter(c => c.group !== 'ahorro' && !deletedCats.includes(c.id));
  const allCats    = [...seedList, ...customCats];
  const total      = allCats.reduce((a, c) => a + (budgets[c.id] || 0), 0);
  const surplus    = totalIng - total;

  function persistDeleted(arr) { setDeletedCats(arr); localStorage.setItem('sis.deleted_cats', JSON.stringify(arr)); window.SisyStorage?.schedulePush?.(); }
  function persistCustom(arr)  { setCustomCats(arr);  localStorage.setItem('sis.custom_cats',  JSON.stringify(arr)); window.SisyStorage?.schedulePush?.(); }

  function deleteCategory(id, isCustom) {
    if (isCustom) {
      persistCustom(customCats.filter(c => c.id !== id));
      setBudgets(b => { const n = { ...b }; delete n[id]; return n; });
    } else {
      persistDeleted([...deletedCats, id]);
    }
  }

  function addCustomCat() {
    if (!newName.trim()) return;
    const id  = 'custom_' + Date.now();
    const amt = Math.max(0, parseInt((newBudget || '0').replace(/\./g,'').replace(/,/g,'')) || 0);
    const cat = { id, name: newName.trim(), icon: newIcon, color: newColor, budget: amt };
    persistCustom([...customCats, cat]);
    setBudgets(b => ({ ...b, [id]: amt }));
    setNewName(''); setNewIcon('star'); setNewBudget(''); setShowNewCat(false);
  }

  function commitSueldo() {
    const n = _parseNum(sueldoInput);
    setSueldoInput(_fmtNum(n));
    setSueldoRaw(false);
    if (onSueldoChange) onSueldoChange(n);
    else { try { localStorage.setItem(NS + 'sueldo', JSON.stringify(n)); } catch {} }
  }
  function commitExtra() {
    const n = _parseNum(extraInput);
    setExtraInput(_fmtNum(n));
    setExtraRaw(false);
    if (onExtraIngresosChange) onExtraIngresosChange(n);
    else { try { localStorage.setItem(NS + 'extra_ing', JSON.stringify(n)); } catch {} }
  }
  function handleSaveAll() {
    commitSueldo();
    commitExtra();
    setSavedAnim(true);
    setTimeout(() => setSavedAnim(false), 2000);
  }

  const incomeInputStyle = {
    width:'100%', padding:'8px 10px', borderRadius:9,
    background:'rgba(255,255,255,0.05)', border:'1px solid var(--border)',
    color:'var(--text)', fontFamily:'Space Grotesk, sans-serif',
    fontSize:16, fontWeight:700, outline:'none',
    transition:'border-color 0.14s', boxSizing:'border-box',
  };

  // Icon picker options
  const ICON_OPTIONS = ['home','cart','bolt','car','heart','fork','coffee','bag','play','dollar','trend','shield','gift','paw','briefcase','laptop','bell','calendar','star','user','wallet','pie','mic','key','spark','arrowUp','arrowDown','swap','settings'];
  const COLOR_OPTIONS = ['#8b5cf6','#818cf8','#38bdf8','#4ade80','#fbbf24','#f87171','#f472b6','#34d399','#fb923c','#a78bfa'];

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>

      {/* ── Income cards ── */}
      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
        <Card2 padding={14}>
          <div style={{ fontSize:10.5, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:700, marginBottom:10 }}>Sueldo</div>
          <input type="text" inputMode="numeric"
            value={sueldoRaw ? sueldoInput : _fmtNum(_parseNum(sueldoInput))}
            onChange={e => { setSueldoRaw(true); setSueldoInput(e.target.value); }}
            onFocus={e => { setSueldoRaw(true); setSueldoInput(String(_parseNum(sueldoInput))); e.target.select(); e.target.style.borderColor='var(--accent)'; }}
            onBlur={e => { commitSueldo(); e.target.style.borderColor='var(--border)'; }}
            onKeyDown={e => e.key === 'Enter' && commitSueldo()}
            style={incomeInputStyle} />
          <div style={{ marginTop:10 }}>
            <div style={{ fontSize:11, color:'var(--text-3)', marginBottom:6 }}>Día de cobro</div>
            <button onClick={() => setShowDayPicker(o => !o)} style={{
              width:'100%', padding:'8px 0', borderRadius:9, textAlign:'center',
              border:`1px solid ${showDayPicker ? 'var(--accent)' : 'var(--border)'}`,
              background: showDayPicker ? 'var(--accent-dim)' : 'rgba(255,255,255,0.05)',
              color: showDayPicker ? 'var(--accent-bright)' : 'var(--text)',
              fontFamily:'Space Grotesk, sans-serif', fontSize:20, fontWeight:700,
              cursor:'pointer', transition:'all 0.14s',
            }}>{sueldoDia}</button>
          </div>
          {showDayPicker && (
            <div style={{ marginTop:10, animation:'fadeSlide 0.15s ease' }}>
              <DayPicker value={sueldoDia} onChange={d => { if (onSueldoDiaChange) onSueldoDiaChange(d); setShowDayPicker(false); }} />
            </div>
          )}
        </Card2>

        <Card2 padding={14}>
          <div style={{ fontSize:10.5, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:700, marginBottom:10 }}>Adicionales</div>
          <input type="text" inputMode="numeric" placeholder="0"
            value={extraRaw ? extraInput : _fmtNum(_parseNum(extraInput))}
            onChange={e => { setExtraRaw(true); setExtraInput(e.target.value); }}
            onFocus={e => { setExtraRaw(true); setExtraInput(String(_parseNum(extraInput))); e.target.select(); e.target.style.borderColor='var(--accent)'; }}
            onBlur={e => { commitExtra(); e.target.style.borderColor='var(--border)'; }}
            onKeyDown={e => e.key === 'Enter' && commitExtra()}
            style={incomeInputStyle} />
          <div style={{ marginTop:10, padding:'10px 12px', borderRadius:9, background:'rgba(255,255,255,0.03)', border:'1px solid var(--border)' }}>
            <div style={{ fontSize:10.5, color:'var(--text-3)', marginBottom:3 }}>Total ingresos</div>
            <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:15, fontWeight:700, color:'var(--text)', fontVariantNumeric:'tabular-nums', wordBreak:'break-all' }}>{fmt(totalIng)}</div>
          </div>
        </Card2>
      </div>

      {/* ── Save button ── */}
      <button onClick={handleSaveAll} style={{
        display:'flex', alignItems:'center', justifyContent:'center', gap:8,
        padding:'11px 0', borderRadius:12, fontFamily:'inherit', fontSize:13.5, fontWeight:600,
        cursor:'pointer', transition:'all 0.18s',
        background: savedAnim ? 'rgba(74,222,128,0.12)' : 'var(--accent)',
        color:      savedAnim ? '#4ade80' : 'var(--on-accent)',
        border:     savedAnim ? '1px solid rgba(74,222,128,0.3)' : 'none',
      }}>
        <Icon2 name={savedAnim ? 'check' : 'shield'} size={15} strokeWidth={2.2} />
        {savedAnim ? 'Presupuesto guardado ✓' : 'Guardar presupuesto'}
      </button>

      {/* ── Budget bar ── */}
      <Card2 padding={12}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'baseline', marginBottom:8 }}>
          <div style={{ fontSize:12, color:'var(--text-3)' }}>Asignado: <strong style={{ color:'var(--text)', fontFamily:'Space Grotesk, sans-serif' }}>{fmt(total)}</strong></div>
          <div style={{ fontSize:11, fontWeight:600, color: surplus>=0 ? 'var(--accent-bright)' : 'var(--red)' }}>
            {surplus>=0 ? `Libre ${fmt(surplus)}` : `Excede ${fmt(-surplus)}`}
          </div>
        </div>
        <div style={{ height:5, background:'rgba(255,255,255,0.05)', borderRadius:999, overflow:'hidden' }}>
          <div style={{ height:'100%', width:`${Math.min(total/Math.max(totalIng,1)*100,100)}%`, background: surplus>=0 ? 'linear-gradient(90deg, var(--accent-deep), var(--accent-bright))' : 'var(--red)', borderRadius:999, transition:'width 0.4s' }} />
        </div>
      </Card2>

      {/* ── Category list ── */}
      <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
        {allCats.map(c => {
          const isCustom = !!c.id?.startsWith('custom_');
          const v     = budgets[c.id] || 0;
          const spent = (spentState || seed2.spent)[c.id] || 0;
          const pct   = v > 0 ? spent / v : 0;
          const over  = pct > 1;
          return (
            <Card2 key={c.id} padding={12}>
              <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                <CC2 cat={c} size={30} />
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontSize:13, fontWeight:500 }}>{c.name}</div>
                  <div style={{ fontSize:11, color:'var(--text-3)', marginTop:1 }}>
                    Gastado {fmt(spent)} · {Math.round(pct*100)}%
                    {over && <span style={{ color:'var(--red)', fontWeight:600, marginLeft:4 }}>· Superado</span>}
                  </div>
                </div>
                {/* Budget input — no slider */}
                <div style={{ display:'flex', alignItems:'center', gap:3, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border)', borderRadius:8, padding:'5px 10px', flexShrink:0 }}>
                  <span style={{ fontSize:11, color:'var(--text-3)' }}>$</span>
                  <input
                    type="text" inputMode="numeric"
                    value={new Intl.NumberFormat('es-AR').format(v)}
                    onFocus={e => e.target.select()}
                    onChange={e => {
                      const raw = parseInt(e.target.value.replace(/\./g,'').replace(/,/g,'')) || 0;
                      setBudgets(b => ({ ...b, [c.id]: Math.max(0, raw) }));
                    }}
                    style={{ width:80, background:'transparent', border:'none', outline:'none', color:'var(--text)', fontFamily:'Space Grotesk, sans-serif', fontSize:13, fontWeight:600, textAlign:'right', fontVariantNumeric:'tabular-nums' }}
                  />
                </div>
                {/* Delete button */}
                <button onClick={() => deleteCategory(c.id, isCustom)} title="Eliminar categoría"
                  style={{ width:26, height:26, borderRadius:7, background:'transparent', border:'none', color:'var(--text-3)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', opacity:0.5, flexShrink:0, transition:'opacity 0.15s, color 0.15s' }}
                  onMouseEnter={e => { e.currentTarget.style.opacity='1'; e.currentTarget.style.color='var(--red)'; }}
                  onMouseLeave={e => { e.currentTarget.style.opacity='0.5'; e.currentTarget.style.color='var(--text-3)'; }}>
                  <Icon2 name="x" size={13} strokeWidth={2} />
                </button>
              </div>
              {/* Spent bar */}
              <div style={{ height:3, background:'rgba(255,255,255,0.06)', borderRadius:999, overflow:'hidden', marginTop:8 }}>
                <div style={{ height:'100%', width:`${Math.min(pct,1)*100}%`, background: over ? 'var(--red)' : (c.color || 'var(--accent-bright)'), borderRadius:999, transition:'width 0.4s' }} />
              </div>
            </Card2>
          );
        })}

        {/* ── Nueva categoría ── */}
        {!showNewCat ? (
          <button onClick={() => setShowNewCat(true)} style={{
            display:'flex', alignItems:'center', justifyContent:'center', gap:8,
            padding:'11px 0', borderRadius:12, background:'transparent',
            border:'1px dashed rgba(167,139,250,0.3)', color:'var(--accent-bright)',
            fontFamily:'inherit', fontSize:13, fontWeight:600, cursor:'pointer',
            transition:'background 0.15s, border-color 0.15s',
          }}
            onMouseEnter={e => { e.currentTarget.style.background='var(--accent-dim)'; e.currentTarget.style.borderColor='var(--border-strong)'; }}
            onMouseLeave={e => { e.currentTarget.style.background='transparent'; e.currentTarget.style.borderColor='rgba(167,139,250,0.3)'; }}
          >
            <Icon2 name="plus" size={14} strokeWidth={2.5} /> Nueva categoría
          </button>
        ) : (
          <Card2 padding={14} style={{ animation:'fadeSlide 0.15s ease' }}>
            <div style={{ fontSize:11.5, fontWeight:700, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', marginBottom:12 }}>Nueva categoría</div>

            {/* Name */}
            <input
              type="text" placeholder="Nombre (ej: Mascotas)"
              value={newName} onChange={e => setNewName(e.target.value)}
              onKeyDown={e => e.key === 'Enter' && addCustomCat()}
              style={{ width:'100%', padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.05)', border:'1px solid var(--border)', color:'var(--text)', fontFamily:'inherit', fontSize:13, outline:'none', boxSizing:'border-box', marginBottom:10 }}
              onFocus={e => e.target.style.borderColor='var(--accent)'}
              onBlur={e => e.target.style.borderColor='var(--border)'}
            />

            {/* Color picker */}
            <div style={{ fontSize:11, color:'var(--text-3)', marginBottom:6 }}>Color</div>
            <div style={{ display:'flex', gap:6, flexWrap:'wrap', marginBottom:10 }}>
              {COLOR_OPTIONS.map(col => (
                <button key={col} onClick={() => setNewColor(col)} style={{
                  width:24, height:24, borderRadius:'50%', background:col, border:`2px solid ${newColor===col ? 'white' : 'transparent'}`,
                  cursor:'pointer', flexShrink:0, transition:'border-color 0.1s',
                }} />
              ))}
            </div>

            {/* Icon picker */}
            <div style={{ fontSize:11, color:'var(--text-3)', marginBottom:6 }}>Ícono</div>
            <div style={{ display:'grid', gridTemplateColumns:'repeat(8, 1fr)', gap:4, marginBottom:10 }}>
              {ICON_OPTIONS.map(ic => (
                <button key={ic} onClick={() => setNewIcon(ic)} style={{
                  padding:'6px 0', borderRadius:8, background: newIcon===ic ? newColor+'28' : 'rgba(255,255,255,0.04)',
                  border:`1px solid ${newIcon===ic ? newColor+'88' : 'var(--border)'}`,
                  color: newIcon===ic ? newColor : 'var(--text-3)', cursor:'pointer',
                  display:'flex', alignItems:'center', justifyContent:'center',
                  transition:'all 0.1s',
                }}>
                  <Icon2 name={ic} size={14} strokeWidth={1.8} />
                </button>
              ))}
            </div>

            {/* Budget */}
            <div style={{ fontSize:11, color:'var(--text-3)', marginBottom:6 }}>Presupuesto mensual</div>
            <div style={{ display:'flex', alignItems:'center', gap:3, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border)', borderRadius:8, padding:'7px 12px', marginBottom:12 }}
              onFocus={() => {}} >
              <span style={{ fontSize:12, color:'var(--text-3)', marginRight:4 }}>$</span>
              <input
                type="text" inputMode="numeric" placeholder="0"
                value={newBudget} onChange={e => setNewBudget(e.target.value)}
                onKeyDown={e => e.key === 'Enter' && addCustomCat()}
                style={{ flex:1, background:'transparent', border:'none', outline:'none', color:'var(--text)', fontFamily:'Space Grotesk, sans-serif', fontSize:15, fontWeight:600, fontVariantNumeric:'tabular-nums' }}
              />
            </div>

            {/* Preview + actions */}
            <div style={{ display:'flex', gap:8, alignItems:'center' }}>
              <div style={{ width:32, height:32, borderRadius:9, background:newColor+'28', color:newColor, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
                <Icon2 name={newIcon} size={16} strokeWidth={1.8} />
              </div>
              <span style={{ fontSize:13, fontWeight:500, flex:1, color: newName ? 'var(--text)' : 'var(--text-3)' }}>{newName || 'Sin nombre'}</span>
              <button onClick={() => { setShowNewCat(false); setNewName(''); setNewBudget(''); }} style={{ padding:'7px 14px', borderRadius:8, background:'transparent', border:'1px solid var(--border)', color:'var(--text-3)', fontFamily:'inherit', fontSize:12, cursor:'pointer' }}>Cancelar</button>
              <button onClick={addCustomCat} disabled={!newName.trim()} style={{ padding:'7px 16px', borderRadius:8, background: newName.trim() ? 'var(--accent)' : 'var(--accent-dim)', color: newName.trim() ? 'var(--on-accent)' : 'var(--text-3)', border:'none', fontFamily:'inherit', fontSize:12, fontWeight:600, cursor: newName.trim() ? 'pointer' : 'default', transition:'all 0.13s' }}>Crear</button>
            </div>
          </Card2>
        )}
      </div>
    </div>
  );
}

function FXPane() {
  // ── formula-aware inputs (like Excel: supports +, -, *, /) ─────────────────
  function evalExpr(str) {
    try {
      const clean = String(str).replace(/,/g, '.').replace(/[^0-9\+\-\*\/\.\s\(\)]/g, '').trim();
      if (!clean) return 0;
      // eslint-disable-next-line no-new-func
      const result = Function('"use strict"; return (' + clean + ')')();
      return isFinite(result) && !isNaN(result) ? Math.abs(result) : 0;
    } catch { return 0; }
  }

  const [amountStr, setAmountStr]   = useState2('100.000');
  const [amountInput, setAmountInput] = useState2(100000);
  const [rateStr, setRateStr]       = useState2(String(seed2.fxBlue));
  const [rate, setRate]             = useState2(seed2.fxBlue);
  const [direction, setDirection]   = useState2('ARS-USD');
  const [focused, setFocused]       = useState2(null); // 'amount' | 'rate'

  const ars = direction === 'ARS-USD' ? amountInput : amountInput * rate;
  const usd = direction === 'ARS-USD' ? amountInput / rate : amountInput;

  function commitAmount() {
    const n = evalExpr(amountStr);
    setAmountInput(n);
    setAmountStr(new Intl.NumberFormat('es-AR', { maximumFractionDigits:0 }).format(Math.round(n)));
    setFocused(null);
  }
  function commitRate() {
    const n = evalExpr(rateStr);
    const r = n || seed2.fxBlue;
    setRate(r);
    setRateStr(String(Math.round(r)));
    setFocused(null);
  }
  function applyPreset(v) {
    setRate(v);
    setRateStr(String(v));
  }

  const inputStyle = { flex:1, background:'transparent', border:'none', outline:'none', color:'var(--text)', fontFamily:'Space Grotesk, sans-serif', fontSize:26, fontWeight:600, fontVariantNumeric:'tabular-nums', minWidth:0 };

  const presets = [
    { l:'Blue',   v: seed2.fxBlue },
    { l:'MEP',    v: 1421 },
    { l:'CCL',    v: 1456 },
    { l:'Oficial',v: 1185 },
  ];

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Card2 padding={20}>
        <div style={{ fontSize:11, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.14em', fontWeight:600, marginBottom:16 }}>Calculadora ARS · USD</div>

        {/* Input row */}
        <div style={{ display:'flex', alignItems:'baseline', gap:10, padding:'14px 16px', background:'var(--surface)', border:`1px solid ${focused==='amount' ? 'var(--accent)' : 'var(--border)'}`, borderRadius:12, transition:'border-color 0.15s' }}>
          <div style={{ fontSize:11, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, width:36, flexShrink:0 }}>{direction==='ARS-USD' ? 'ARS' : 'USD'}</div>
          <input
            type="text"
            value={focused==='amount' ? amountStr : new Intl.NumberFormat('es-AR', { maximumFractionDigits:0 }).format(Math.round(amountInput))}
            onChange={e => setAmountStr(e.target.value)}
            onFocus={() => { setFocused('amount'); setAmountStr(String(amountInput)); }}
            onBlur={commitAmount}
            onKeyDown={e => { if (e.key === 'Enter') { e.currentTarget.blur(); } }}
            placeholder="Ej: 100000*2"
            style={{ ...inputStyle }}
          />
        </div>

        {/* Swap button */}
        <div style={{ display:'flex', justifyContent:'center', margin:'10px 0' }}>
          <button
            onClick={() => setDirection(d => d==='ARS-USD' ? 'USD-ARS' : 'ARS-USD')}
            style={{ width:36, height:36, borderRadius:'50%', background:'var(--surface-3, rgba(34,22,56,0.82))', border:'1px solid var(--border-strong)', color:'var(--text-2)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', transition:'transform 0.22s cubic-bezier(0.34,1.56,0.64,1)' }}
            onMouseEnter={e => e.currentTarget.style.transform='rotate(180deg)'}
            onMouseLeave={e => e.currentTarget.style.transform='rotate(0deg)'}
          >
            <Icon2 name="swap" size={14} />
          </button>
        </div>

        {/* Result row (read-only) */}
        <div style={{ display:'flex', alignItems:'baseline', gap:10, padding:'14px 16px', background:'var(--accent-dim)', border:'1px solid var(--border-strong)', borderRadius:12 }}>
          <div style={{ fontSize:11, color:'var(--accent-bright)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, width:36, flexShrink:0 }}>{direction==='ARS-USD' ? 'USD' : 'ARS'}</div>
          <div style={{ flex:1, fontFamily:'Space Grotesk, sans-serif', fontSize:26, fontWeight:600, color:'var(--accent-bright)', fontVariantNumeric:'tabular-nums' }}>
            {direction==='ARS-USD'
              ? new Intl.NumberFormat('en-US', { minimumFractionDigits:2, maximumFractionDigits:2 }).format(usd)
              : new Intl.NumberFormat('es-AR', { maximumFractionDigits:0 }).format(Math.round(ars))
            }
          </div>
        </div>

        {/* Rate row */}
        <div style={{ marginTop:14, padding:'10px 14px', background:'var(--surface)', borderRadius:10, display:'flex', alignItems:'center', gap:10, justifyContent:'space-between', border:`1px solid ${focused==='rate' ? 'var(--accent)' : 'transparent'}`, transition:'border-color 0.15s' }}>
          <div style={{ fontSize:11, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:600 }}>Tipo de cambio</div>
          <div style={{ display:'flex', alignItems:'center', gap:4 }}>
            <span style={{ fontSize:12, color:'var(--text-3)' }}>$</span>
            <input
              type="text"
              value={focused==='rate' ? rateStr : String(Math.round(rate))}
              onChange={e => setRateStr(e.target.value)}
              onFocus={() => { setFocused('rate'); setRateStr(String(Math.round(rate))); }}
              onBlur={commitRate}
              onKeyDown={e => { if (e.key === 'Enter') e.currentTarget.blur(); }}
              style={{ background:'transparent', border:'none', color:'var(--accent-bright)', outline:'none', fontFamily:'inherit', fontWeight:600, fontVariantNumeric:'tabular-nums', textAlign:'right', width:72, fontSize:15 }}
            />
          </div>
        </div>
      </Card2>

      {/* Preset rates */}
      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:8 }}>
        {presets.map((p, i) => (
          <button key={i} onClick={() => applyPreset(p.v)} className="card-hov" style={{
            padding:'12px 14px', borderRadius:12,
            background: rate===p.v ? 'var(--accent-dim)' : 'var(--card)',
            border:`1px solid ${rate===p.v ? 'var(--border-strong)' : 'var(--border)'}`,
            cursor:'pointer', fontFamily:'inherit', color:'inherit', textAlign:'left',
            transition:'background 0.15s, border-color 0.15s',
          }}>
            <div style={{ fontSize:11, color: rate===p.v ? 'var(--accent-bright)' : 'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, marginBottom:4 }}>{p.l}</div>
            <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:17, fontWeight:600, fontVariantNumeric:'tabular-nums', color: rate===p.v ? 'var(--accent-bright)' : 'var(--text)' }}>$ {p.v.toLocaleString('es-AR')}</div>
          </button>
        ))}
      </div>
    </div>
  );
}

function TrendPane({ ccy }) {
  const h = seed2.history;
  const max = Math.max(...h.map(x => Math.max(x.ingTotal||0, x.egrTotal||0)));
  const fmt = n => S2.fmtMoneyCompact(ccy === 'USD' ? n / seed2.fxBlue : n, ccy);
  const fmtFull = n => S2.fmtMoney(ccy === 'USD' ? n / seed2.fxBlue : n, ccy);
  const [hovered, setHovered] = useState2(null);
  const [selected, setSelected] = useState2(null);

  const safeMax = max > 0 ? max : 1; // guard division by zero
  const W = 340, H = 180, PAD_L = 20, PAD_R = 10, PAD_T = 20, BAR_H = 140;
  const colW = (W - PAD_L - PAD_R) / (h.length || 1);

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Card2 padding={20}>
        <div style={{ fontSize:11.5, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, marginBottom:14 }}>Últimos 6 meses · clic para detallar</div>
        <svg viewBox={`0 0 ${W} ${H}`} style={{ width:'100%', height:H, overflow:'visible', cursor:'pointer' }}>
          {[0, 0.25, 0.5, 0.75, 1].map(p => (
            <line key={p} x1={PAD_L} y1={PAD_T + p*BAR_H} x2={W-PAD_R} y2={PAD_T + p*BAR_H} stroke="rgba(255,255,255,0.04)" />
          ))}
          {h.map((m, i) => {
            const cx = PAD_L + i * colW + colW / 2;
            const ingH = ((m.ingTotal||0) / safeMax) * BAR_H;
            const egrH = ((m.egrTotal||0) / safeMax) * BAR_H;
            const isHov = hovered === i;
            const isSel = selected === i;
            const isLast = i === h.length - 1;
            const barW = Math.min(colW * 0.35, 16);
            const ingColor = isLast ? 'var(--accent-bright)' : 'rgba(196,181,253,0.55)';
            const egrColor = isLast ? 'rgba(248,113,113,0.85)' : 'rgba(248,113,113,0.45)';
            return (
              <g key={i}
                onMouseEnter={() => setHovered(i)}
                onMouseLeave={() => setHovered(null)}
                onClick={() => setSelected(s => s === i ? null : i)}
                style={{ cursor:'pointer' }}
              >
                {/* hover highlight bg */}
                <rect x={cx - colW*0.45} y={PAD_T} width={colW*0.9} height={BAR_H+10} rx={6}
                  fill={isHov || isSel ? 'rgba(167,139,250,0.08)' : 'transparent'}
                  style={{ transition:'fill 0.15s' }}
                />
                {/* ingreso bar */}
                <rect x={cx - barW - 1} y={PAD_T + BAR_H - ingH} width={barW} height={ingH}
                  fill={ingColor} rx={3}
                  opacity={hovered !== null && !isHov ? 0.4 : 1}
                  style={{ transition:'opacity 0.15s, y 0.2s, height 0.2s' }}
                />
                {/* egreso bar */}
                <rect x={cx + 1} y={PAD_T + BAR_H - egrH} width={barW} height={egrH}
                  fill={egrColor} rx={3}
                  opacity={hovered !== null && !isHov ? 0.4 : 1}
                  style={{ transition:'opacity 0.15s' }}
                />
                <text x={cx} y={PAD_T + BAR_H + 14} fill={isSel ? 'var(--accent-bright)' : 'var(--text-3)'} fontSize="10" textAnchor="middle" fontFamily="Inter, sans-serif" fontWeight={isSel ? '700' : '400'}>{(m.monthName||m.m||'?').slice(0,3)}</text>

                {/* Tooltip on hover */}
                {isHov && (
                  <g>
                    <rect x={Math.min(cx - 56, W - 120)} y={PAD_T + BAR_H - Math.max(ingH, egrH) - 72} width={112} height={66} rx={8} fill="rgba(20,12,40,0.97)" stroke="rgba(167,139,250,0.3)" strokeWidth={1} />
                    <text x={Math.min(cx - 56, W - 120) + 10} y={PAD_T + BAR_H - Math.max(ingH, egrH) - 52} fill="var(--text-3)" fontSize="9" fontFamily="Inter, sans-serif" textTransform="uppercase">{(m.monthName||m.m||'?').slice(0,3)}</text>
                    <text x={Math.min(cx - 56, W - 120) + 10} y={PAD_T + BAR_H - Math.max(ingH, egrH) - 36} fill="rgba(196,181,253,0.9)" fontSize="10" fontFamily="Inter, sans-serif">↑ {fmt(m.ingTotal||0)}</text>
                    <text x={Math.min(cx - 56, W - 120) + 10} y={PAD_T + BAR_H - Math.max(ingH, egrH) - 20} fill="rgba(248,113,113,0.9)" fontSize="10" fontFamily="Inter, sans-serif">↓ {fmt(m.egrTotal||0)}</text>
                    <text x={Math.min(cx - 56, W - 120) + 10} y={PAD_T + BAR_H - Math.max(ingH, egrH) - 4} fill={(m.ingTotal||0) - (m.egrTotal||0) >= 0 ? 'var(--accent-bright)' : 'var(--red)'} fontSize="10" fontFamily="Inter, sans-serif" fontWeight="600">= {fmt((m.ingTotal||0) - (m.egrTotal||0))}</text>
                  </g>
                )}
              </g>
            );
          })}
        </svg>
        <div style={{ display:'flex', gap:14, marginTop:10, fontSize:11.5 }}>
          <div style={{ display:'flex', alignItems:'center', gap:6 }}><span style={{ width:8, height:8, borderRadius:2, background:'var(--accent-bright)' }} /> Ingresos</div>
          <div style={{ display:'flex', alignItems:'center', gap:6 }}><span style={{ width:8, height:8, borderRadius:2, background:'rgba(248,113,113,0.7)' }} /> Egresos</div>
        </div>
      </Card2>
      <Card2 padding={0}>
        {h.slice().reverse().map((m, i) => {
          const neto = (m.ingTotal||m.ing||0) - (m.egrTotal||m.egr||0) - (m.ahoTotal||m.aho||0);
          const positive = neto >= 0;
          const isSelected = selected === (h.length - 1 - i);
          return (
            <div key={i} onClick={() => setSelected(s => s === (h.length-1-i) ? null : (h.length-1-i))}
              style={{ display:'grid', gridTemplateColumns:'auto 1fr auto', alignItems:'center', gap:12, padding:'14px 18px', borderTop: i===0 ? 'none' : '1px solid var(--border)', background: isSelected ? 'rgba(167,139,250,0.07)' : 'transparent', cursor:'pointer', transition:'background 0.15s' }}>
              <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:13, fontWeight:600, width:36, color: isSelected ? 'var(--accent-bright)' : i===0 ? 'var(--accent-bright)' : 'var(--text-2)' }}>{(m.monthName||m.m||'?').slice(0,3)}</div>
              <div style={{ display:'flex', flexDirection:'column', gap:3 }}>
                <div style={{ fontSize:12, color:'var(--text-3)' }}>
                  {isSelected ? `↑ ${fmtFull(m.ingTotal||m.ing||0)}  ↓ ${fmtFull(m.egrTotal||m.egr||0)}` : 'Neto del mes'}
                </div>
                <div style={{ fontSize:14, fontWeight:600, fontVariantNumeric:'tabular-nums', color: positive ? 'var(--accent-bright)' : 'var(--red)' }}>{fmt(neto)}</div>
              </div>
              <div style={{ textAlign:'right' }}>
                <div style={{ fontSize:11, color:'var(--text-3)' }}>ahorrado</div>
                <div style={{ fontSize:13, fontWeight:500, fontVariantNumeric:'tabular-nums' }}>{fmt(m.ahoTotal||m.aho||0)}</div>
              </div>
            </div>
          );
        })}
      </Card2>
    </div>
  );
}

// ─── MÁS ──────────────────────────────────────────────────────────────────────
function MasScreen({ ccy, isDesktop, activeNotifs, onDismissNotif, onToast, cuentasState, onUpdateCuenta, onAddCuenta, onDeleteCuenta, tarjetasState, onAddTarjeta, onUpdateTarjeta, onDeleteTarjeta, initialTab, spentState, budgets, onBudgetsChange, userName, onUserNameChange, profilePhoto, onProfileChange, extraIngresos, onExtraIngresosChange, photoPos, onPhotoPosChange, sueldo, onSueldoChange, sueldoDia, onSueldoDiaChange }) {
  // ALL hooks must be declared before any conditional return (React Rules of Hooks)
  const [tab,    setTab]    = useState2(initialTab || 'notifs');
  const [masTab, setMasTab] = useState2('cuentas'); // phone tabs
  const conv = n => ccy === 'USD' ? n / seed2.fxBlue : n;
  const fmt  = n => S2.fmtMoney(conv(n), ccy);

  const tabs3 = [
    { id:'notifs',   label:'Avisos',   count: activeNotifs.length },
    { id:'config',   label:'Config',   count: 0 },
    { id:'cuentas',  label:'Cuentas',  count: 0 },
    { id:'cierre',   label:'Cierre',   count: 0 },
  ];

  const sectionTitle = { notifs:'Avisos', cuentas:'Cuentas', cierre:'Cierre de mes', config:'Configuración' };
  const sectionSub   = { notifs:'Notificaciones y alertas activas', cuentas:'Saldos y cuentas vinculadas', cierre:'Revisión y cierre del mes', config:'Perfil, presupuestos y sincronización' };

  const kindColor = { urgent:'var(--red)', warn:'var(--amber)', info:'var(--accent-bright)' };
  const kindBg    = { urgent:'rgba(248,113,113,0.08)', warn:'rgba(251,191,36,0.08)', info:'var(--accent-dim)' };
  const kindBorder= { urgent:'rgba(248,113,113,0.28)', warn:'rgba(251,191,36,0.22)', info:'var(--border)' };
  const kindIcon  = { urgent:'bell', warn:'spark', info:'pin' };

  // On desktop: the sidebar already exposes Avisos/Cuentas/Cierre as separate items,
  // so we skip the internal tab navigation and render the content section directly.
  if (isDesktop) {
    return (
      <div style={{ display:'flex', flexDirection:'column', gap:16, padding:'20px 28px 44px', maxWidth:760, margin:'0 auto', width:'100%' }}>
        <div>
          <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:22, fontWeight:600, letterSpacing:'-0.02em', marginBottom:4 }}>{sectionTitle[tab] || 'Más'}</div>
          <div style={{ fontSize:12.5, color:'var(--text-3)' }}>{sectionSub[tab] || ''}</div>
        </div>
        {/* Content only — no left-panel tabs */}
        <div>

      {/* NOTIFS */}
      {tab === 'notifs' && (
        <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
          {activeNotifs.length === 0 && (
            <Card2 padding={32} style={{ textAlign:'center' }}>
              <div style={{ width:52, height:52, borderRadius:16, background:'var(--accent-dim)', display:'flex', alignItems:'center', justifyContent:'center', margin:'0 auto 12px', color:'var(--accent-bright)' }}>
                <Icon2 name="check" size={24} strokeWidth={1.8} />
              </div>
              <div style={{ fontSize:14, fontWeight:500, color:'var(--text-2)' }}>Todo al dia</div>
              <div style={{ fontSize:12, color:'var(--text-3)', marginTop:4 }}>Sin notificaciones pendientes</div>
            </Card2>
          )}
          {activeNotifs.map((n, idx) => (
            <div key={n.id} style={{
              padding:'10px 12px', borderRadius:12,
              background: kindBg[n.kind] || 'var(--card)',
              border:`1px solid ${kindBorder[n.kind] || 'var(--border)'}`,
              position:'relative',
              animation:`slideInRight 0.18s ease ${idx*0.04}s both`,
            }}>
              <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                <div style={{
                  width:30, height:30, borderRadius:8, flexShrink:0,
                  background: n.kind==='urgent' ? 'rgba(248,113,113,0.14)' : n.kind==='warn' ? 'rgba(251,191,36,0.14)' : 'rgba(167,139,250,0.14)',
                  color: kindColor[n.kind] || 'var(--accent-bright)',
                  display:'flex', alignItems:'center', justifyContent:'center',
                }}>
                  <Icon2 name={kindIcon[n.kind] || 'bell'} size={14} />
                </div>
                <div style={{ flex:1, minWidth:0, paddingRight:20 }}>
                  <div style={{ fontSize:12.5, fontWeight:500, lineHeight:1.3 }}>{n.title}</div>
                  <div style={{ fontSize:11, color:'var(--text-3)', marginTop:2, display:'flex', alignItems:'center', gap:8 }}>
                    <span>{n.meta}</span>
                    {n.amount != null && <span style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:12, fontWeight:600, color: n.kind==='urgent' ? 'var(--red)' : 'var(--accent-bright)', fontVariantNumeric:'tabular-nums' }}>$ {new Intl.NumberFormat('es-AR').format(n.amount)}</span>}
                  </div>
                </div>
              </div>
              <button onClick={() => onDismissNotif(n.id)} style={{ position:'absolute', top:8, right:8, width:20, height:20, borderRadius:6, background:'rgba(255,255,255,0.07)', border:'none', color:'var(--text-3)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', transition:'background 0.14s' }}
                onMouseEnter={e => e.currentTarget.style.background='rgba(255,255,255,0.14)'}
                onMouseLeave={e => e.currentTarget.style.background='rgba(255,255,255,0.07)'}
              >
                <Icon2 name="x" size={10} />
              </button>
            </div>
          ))}
        </div>
      )}

      {/* CIERRE */}
      {tab === 'cierre' && <CierreMesTab onToast={onToast} />}

      {/* CUENTAS */}
      {tab === 'cuentas' && (
        <CuentasTab ccy={ccy} cuentasState={cuentasState} onUpdateCuenta={onUpdateCuenta} onAddCuenta={onAddCuenta} onDeleteCuenta={onDeleteCuenta} tarjetasState={tarjetasState} onAddTarjeta={onAddTarjeta} onUpdateTarjeta={onUpdateTarjeta} onDeleteTarjeta={onDeleteTarjeta} conv={conv} fmt={fmt} />
      )}
        </div>{/* end content */}
      </div>
    );
  }

  // ── MOBILE: 3 tabs ───────────────────────────────────────────────────────────
  const masTabs = [
    { id:'cuentas',  label:'Cuentas' },
    { id:'tarjetas', label:'Tarjetas' },
    { id:'cierre',   label:'Cerrar mes' },
  ];

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:14, padding:'var(--sp) var(--sp) var(--sp-bottom)' }}>

      {/* ── Tabs ── */}
      <div className="si-0" style={{ display:'flex', padding:4, background:'var(--card)', border:'1px solid var(--border)', borderRadius:12, gap:2 }}>
        {masTabs.map(t => (
          <button key={t.id} onClick={() => setMasTab(t.id)} style={{
            flex:1, padding:'9px 0', borderRadius:9,
            background: masTab===t.id ? 'var(--accent-dim)' : 'transparent',
            color: masTab===t.id ? 'var(--accent-bright)' : 'var(--text-2)',
            border:'none', cursor:'pointer', fontFamily:'inherit',
            fontSize:12, fontWeight:600,
            transition:'background 0.14s, color 0.14s',
          }}>{t.label}</button>
        ))}
      </div>

      {/* ── Tab content ── */}
      <div className="si-2" key={masTab} style={{ animation:'tabEnter 0.18s ease' }}>
        {masTab === 'cuentas'  && <CuentasTab ccy={ccy} cuentasState={cuentasState} onUpdateCuenta={onUpdateCuenta} onAddCuenta={onAddCuenta} onDeleteCuenta={onDeleteCuenta} tarjetasState={tarjetasState} onAddTarjeta={onAddTarjeta} onUpdateTarjeta={onUpdateTarjeta} onDeleteTarjeta={onDeleteTarjeta} conv={conv} fmt={fmt} />}
        {masTab === 'tarjetas' && <TarjetasTab tarjetasState={tarjetasState} onAddTarjeta={onAddTarjeta} onUpdateTarjeta={onUpdateTarjeta} onDeleteTarjeta={onDeleteTarjeta} fmt={fmt} />}
        {masTab === 'cierre'   && <CierreMesTab onToast={onToast} />}
      </div>
    </div>
  );
}

function GmailTabOld({ onToast }) {
  // ── CONNECTED / DISCONNECTED ──
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>

      {/* Status card */}
      <Card2 padding={0} style={{ overflow:'hidden', borderColor: connected ? 'rgba(52,211,153,0.25)' : 'var(--border)' }}>
        {connected && (
          <div style={{ padding:'12px 16px', background:'rgba(52,211,153,0.07)', borderBottom:'1px solid rgba(52,211,153,0.15)', display:'flex', alignItems:'center', gap:8 }}>
            <span style={{ width:8, height:8, borderRadius:'50%', background:'#34d399', flexShrink:0, boxShadow:'0 0 6px rgba(52,211,153,0.6)' }} />
            <span style={{ fontSize:12, fontWeight:600, color:'#34d399' }}>Cuenta correctamente vinculada</span>
          </div>
        )}
        <div style={{ padding:16 }}>
        <div style={{ display:'flex', alignItems:'center', gap:12 }}>
          <div style={{ width:40, height:40, borderRadius:11, background: connected ? 'rgba(52,211,153,0.12)' : 'rgba(255,255,255,0.05)', border:`1px solid ${connected ? 'rgba(52,211,153,0.25)' : 'var(--border)'}`, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M20 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V6a2 2 0 00-2-2z" stroke={connected ? '#34d399' : 'rgba(237,233,254,0.4)'} strokeWidth="1.6" strokeLinecap="round"/><path d="M2 6l10 7 10-7" stroke={connected ? '#34d399' : 'rgba(237,233,254,0.4)'} strokeWidth="1.6" strokeLinecap="round"/></svg>
          </div>
          <div style={{ flex:1, minWidth:0 }}>
            <div style={{ fontSize:13.5, fontWeight:600 }}>{connected ? 'adolforafaellang@gmail.com' : 'Sin cuenta vinculada'}</div>
            <div style={{ fontSize:11.5, color:'var(--text-3)', marginTop:2, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
              {connected
                ? (lastSyncLabel ? 'Última sincronización: ' + lastSyncLabel : 'Lista para sincronizar')
                : 'Vinculá tu cuenta para importar movimientos automáticamente'}
            </div>
          </div>
        </div>

        {connectError && (
          <div style={{ marginTop:10, padding:'9px 12px', borderRadius:9, background:'rgba(248,113,113,0.1)', border:'1px solid rgba(248,113,113,0.25)', fontSize:12, color:'var(--red)' }}>
            {connectError}
          </div>
        )}

        <div style={{ display:'flex', gap:8, marginTop:12 }}>
          {!connected ? (
            <button onClick={handleConnect} className="btn-accent-hov" style={{ flex:1, padding:'10px 0', borderRadius:10, background:'var(--accent)', color:'var(--on-accent)', border:'none', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600, display:'flex', alignItems:'center', justifyContent:'center', gap:7 }}>
              <Icon2 name="key" size={14} /> Conectar con Google
            </button>
          ) : (
            <>
              <button
                onClick={handleSync}
                disabled={syncing}
                className="btn-accent-hov"
                style={{ flex:1, padding:'10px 0', borderRadius:10, background: syncing ? 'var(--accent-dim)' : 'var(--accent)', color: syncing ? 'var(--accent-bright)' : 'var(--on-accent)', border: syncing ? '1px solid var(--border-strong)' : 'none', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600, display:'flex', alignItems:'center', justifyContent:'center', gap:7, transition:'all 0.15s' }}
              >
                {syncing ? (
                  <>
                    <span style={{ display:'inline-block', width:14, height:14, border:'2px solid currentColor', borderTopColor:'transparent', borderRadius:'50%', animation:'spin 0.8s linear infinite' }} />
                    {syncProgress.total > 0 ? syncProgress.fetched + ' / ' + syncProgress.total : 'Sincronizando...'}
                  </>
                ) : (
                  <><Icon2 name="swap" size={14} /> Sincronizar correos</>
                )}
              </button>
              <button onClick={handleDisconnect} style={{ width:44, padding:'10px 0', borderRadius:10, background:'var(--card)', border:'1px solid var(--border)', color:'var(--text-3)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', transition:'color 0.14s' }}
                onMouseEnter={e => { e.currentTarget.style.color='var(--red)'; e.currentTarget.style.borderColor='rgba(248,113,113,0.3)'; }}
                onMouseLeave={e => { e.currentTarget.style.color='var(--text-3)'; e.currentTarget.style.borderColor='var(--border)'; }}
              >
                <Icon2 name="x" size={14} />
              </button>
            </>
          )}
        </div>

        {syncResult && !syncResult.error && (
          <div style={{ marginTop:10, padding:'9px 12px', borderRadius:9, background:'rgba(52,211,153,0.08)', border:'1px solid rgba(52,211,153,0.2)', fontSize:12, color:'#34d399', display:'flex', alignItems:'center', gap:7 }}>
            <Icon2 name="check" size={13} strokeWidth={2.5} />
            +{syncResult.added} movimientos nuevos · {syncResult.total} en total
          </div>
        )}
        {syncResult?.error && (
          <div style={{ marginTop:10, padding:'9px 12px', borderRadius:9, background:'rgba(248,113,113,0.08)', border:'1px solid rgba(248,113,113,0.2)', fontSize:12, color:'var(--red)' }}>
            {syncResult.error}
          </div>
        )}
        {/* Vincular otro correo */}
        {connected && (
          <button onClick={() => setShowSetup(true)} style={{ marginTop:12, width:'100%', padding:'8px 0', borderRadius:9, background:'transparent', border:'1px solid var(--border)', color:'var(--text-3)', cursor:'pointer', fontFamily:'inherit', fontSize:12, fontWeight:500, transition:'color 0.14s, border-color 0.14s' }}
            onMouseEnter={e => { e.currentTarget.style.color='var(--text-2)'; e.currentTarget.style.borderColor='var(--border-strong)'; }}
            onMouseLeave={e => { e.currentTarget.style.color='var(--text-3)'; e.currentTarget.style.borderColor='var(--border)'; }}
          >
            Vincular otro correo electrónico
          </button>
        )}
        </div>{/* end padding div */}
      </Card2>

      {/* Transactions list */}
      {recentTxns.length > 0 && (
        <div>
          <div style={{ fontSize:11, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, padding:'0 4px 8px' }}>
            Importados de Gmail · {txns.length} total
          </div>
          <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
            {recentTxns.map((tx, i) => {
              const cat   = seed2.catPorId[tx.cat] || seed2.catPorId['compras'];
              const isInc = tx.type === 'ingreso';
              const dateStr = new Date(tx.date).toLocaleDateString('es-AR', { day:'numeric', month:'short' });
              const amtStr = (tx.ccy === 'USD' ? 'US$ ' : '$ ') + new Intl.NumberFormat(tx.ccy==='USD'?'en-US':'es-AR', { maximumFractionDigits:0 }).format(Math.round(tx.amount));
              return (
                <Card2 key={tx.id || i} padding={12} style={{ animation:'tabEnter 0.15s ease ' + (i*0.03) + 's both' }}>
                  <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                    <div style={{ width:34, height:34, borderRadius:9, background: isInc ? 'rgba(52,211,153,0.12)' : 'rgba(167,139,250,0.12)', border:`1px solid ${isInc ? 'rgba(52,211,153,0.2)' : 'rgba(167,139,250,0.15)'}`, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0, color: isInc ? '#34d399' : (cat?.color || 'var(--accent)') }}>
                      <Icon2 name={isInc ? 'arrowDown' : (cat?.icon || 'spark')} size={14} strokeWidth={2} />
                    </div>
                    <div style={{ flex:1, minWidth:0 }}>
                      <div style={{ fontSize:13, fontWeight:500, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{tx.merchant}</div>
                      <div style={{ fontSize:11, color:'var(--text-3)', marginTop:1 }}>{tx.source} · {dateStr}</div>
                    </div>
                    <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:14, fontWeight:600, fontVariantNumeric:'tabular-nums', color: isInc ? '#34d399' : 'var(--text)', flexShrink:0 }}>
                      {isInc ? '+' : '-'}{amtStr}
                    </div>
                  </div>
                </Card2>
              );
            })}
          </div>
        </div>
      )}

      {recentTxns.length === 0 && connected && !syncing && (
        <Card2 padding={28} style={{ textAlign:'center' }}>
          <div style={{ width:48, height:48, borderRadius:14, background:'var(--accent-dim)', display:'flex', alignItems:'center', justifyContent:'center', margin:'0 auto 12px', color:'var(--accent-bright)' }}>
            <Icon2 name="swap" size={22} strokeWidth={1.8} />
          </div>
          <div style={{ fontSize:13.5, fontWeight:500, color:'var(--text-2)' }}>Sin movimientos importados</div>
          <div style={{ fontSize:12, color:'var(--text-3)', marginTop:4 }}>Tocá "Sincronizar correos" para importar transacciones de tus bancos</div>
        </Card2>
      )}

      {/* Cierre de mes */}
      <Card2 padding={18} style={{ background:'rgba(139,92,246,0.06)', borderColor:'rgba(139,92,246,0.22)' }}>
        <div style={{ display:'flex', alignItems:'flex-start', gap:12 }}>
          <div style={{ width:40, height:40, borderRadius:11, background:'var(--accent-dim)', border:'1px solid var(--border-strong)', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0, color:'var(--accent-bright)' }}>
            <Icon2 name="calendar" size={17} strokeWidth={1.7} />
          </div>
          <div style={{ flex:1, minWidth:0 }}>
            <div style={{ fontSize:14, fontWeight:600, marginBottom:3 }}>Cerrar el mes</div>
            <div style={{ fontSize:12, color:'var(--text-3)', lineHeight:1.55 }}>
              Archiva los datos del mes actual, calcula estadísticas y te envía un resumen por correo.
            </div>
          </div>
        </div>

        {mesStats && (
          <div style={{ marginTop:12, padding:'12px 14px', borderRadius:10, background:'rgba(52,211,153,0.07)', border:'1px solid rgba(52,211,153,0.18)' }}>
            <div style={{ fontSize:12.5, fontWeight:600, color:'#34d399', marginBottom:6 }}>✓ {mesStats.monthName} cerrado</div>
            <div style={{ fontSize:12, color:'var(--text-2)', lineHeight:1.6 }}>
              Neto: <strong>{mesStats.neto >= 0 ? '+' : ''}{new Intl.NumberFormat('es-AR').format(Math.round(mesStats.neto))}</strong> ARS
              {mesStats.savingsDelta !== null && (
                <> · Ahorro {mesStats.savingsDelta >= 0 ? '+' : ''}{mesStats.savingsDelta}% vs mes anterior</>
              )}
            </div>
            {mesStats.overBudget?.length > 0 && (
              <div style={{ fontSize:11.5, color:'rgba(248,113,113,0.8)', marginTop:4 }}>
                ⚠ {mesStats.overBudget.length} {mesStats.overBudget.length===1?'categoría excedida':'categorías excedidas'}: {mesStats.overBudget.slice(0,2).map(c=>c.name).join(', ')}
              </div>
            )}
          </div>
        )}

        <button
          onClick={handleCerrarMes}
          disabled={cerrandoMes}
          className="btn-accent-hov"
          style={{ marginTop:12, width:'100%', padding:'11px 0', borderRadius:10, background:'var(--accent-dim)', color:'var(--accent-bright)', border:'1px solid var(--border-strong)', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600, display:'flex', alignItems:'center', justifyContent:'center', gap:8, transition:'all 0.15s' }}
        >
          {cerrandoMes ? (
            <><span style={{ display:'inline-block', width:14, height:14, border:'2px solid currentColor', borderTopColor:'transparent', borderRadius:'50%', animation:'spin 0.8s linear infinite' }} /> Cerrando el mes...</>
          ) : (
            <><Icon2 name="check" size={14} strokeWidth={2.2} /> Cerrar {new Date().toLocaleDateString('es-AR', { month:'long' })}</>
          )}
        </button>
      </Card2>

    </div>
  );
}


// ─── EditableBalance — module-level to avoid single-char bug (nested components re-mount on every render) ──
function EditableBalance({ c, onUpdateCuenta, conv, ccy, fmt }) {
  const [editing, setEditing] = useState2(false);
  const [raw, setRaw] = useState2('');
  const inputRef = useRef2(null);

  function startEdit() {
    setRaw(String(c.balance));
    setEditing(true);
    setTimeout(() => inputRef.current?.select(), 30);
  }
  function commit() {
    const n = parseFloat(raw.replace(/[^0-9.]/g, ''));
    if (!isNaN(n) && n >= 0 && onUpdateCuenta) onUpdateCuenta(c.id, n);
    setEditing(false);
  }
  function onKey(e) {
    if (e.key === 'Enter')  commit();
    if (e.key === 'Escape') setEditing(false);
  }

  const displayARS = c.type === 'USD'
    ? 'US$ ' + new Intl.NumberFormat('en-US', { maximumFractionDigits:0 }).format(c.balance)
    : S2.fmtMoney(conv(c.balance), ccy);

  return (
    <div style={{ textAlign:'right' }}>
      {editing ? (
        <div style={{ display:'flex', alignItems:'center', gap:4, justifyContent:'flex-end' }}>
          <span style={{ fontSize:12, color:'var(--text-3)' }}>{c.type === 'USD' ? 'US$' : '$'}</span>
          <input
            ref={inputRef}
            type="number"
            value={raw}
            onChange={e => setRaw(e.target.value)}
            onBlur={commit}
            onKeyDown={onKey}
            style={{ width:100, background:'rgba(255,255,255,0.07)', border:'1px solid var(--accent)', borderRadius:8, padding:'4px 8px', color:'var(--accent-bright)', fontFamily:'Space Grotesk, sans-serif', fontSize:15, fontWeight:600, textAlign:'right', outline:'none' }}
          />
        </div>
      ) : (
        <button
          onClick={startEdit}
          style={{ background:'none', border:'none', cursor:'pointer', fontFamily:'Space Grotesk, sans-serif', fontSize:16, fontWeight:600, fontVariantNumeric:'tabular-nums', color:'var(--text)', textAlign:'right', padding:0, display:'flex', flexDirection:'column', alignItems:'flex-end', gap:2 }}
          title="Clic para editar"
        >
          <span style={{ borderBottom:'1px dashed rgba(167,139,250,0.35)', paddingBottom:1 }}>{displayARS}</span>
          {c.type === 'USD' && (
            <span style={{ fontSize:10.5, color:'var(--text-3)', fontWeight:400 }}>≈ {fmt(c.balance * seed2.fxBlue)}</span>
          )}
        </button>
      )}
    </div>
  );
}

// ─── Cuentas Tab (editable) ────────────────────────────────────────────────────
function CuentasTab({ ccy, cuentasState, onUpdateCuenta, onAddCuenta, onDeleteCuenta, tarjetasState, onAddTarjeta, onUpdateTarjeta, onDeleteTarjeta, conv, fmt }) {
  const cuentas = cuentasState || seed2.cuentas;
  const [showAdd, setShowAdd] = useState2(false);
  const [confirmDelete, setConfirmDelete] = useState2(null); // id of account pending delete
  const [newCuenta, setNewCuenta] = useState2({ name:'', bank:'', type:'ARS', balance:0 });

  const patrimonioTotal = cuentas.reduce((a, c) => a + (c.type === 'USD' ? c.balance * seed2.fxBlue : c.balance), 0);

  function submitAdd() {
    if (!newCuenta.name.trim()) return;
    const bal = parseFloat(String(newCuenta.balance).replace(/[^0-9.]/g, '')) || 0;
    if (onAddCuenta) onAddCuenta({ name: newCuenta.name.trim(), bank: newCuenta.bank.trim() || newCuenta.name.trim(), type: newCuenta.type, balance: bal });
    setNewCuenta({ name:'', bank:'', type:'ARS', balance:0 });
    setShowAdd(false);
  }

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
      {/* Patrimonio hero */}
      <Card2 padding={18} style={{ background:'var(--accent-dim)', borderColor:'var(--border-strong)' }}>
        <div style={{ fontSize:11.5, color:'var(--text-2)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, marginBottom:4 }}>Patrimonio total</div>
        <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:30, fontWeight:600, letterSpacing:'-0.025em', fontVariantNumeric:'tabular-nums' }}>
          {fmt(patrimonioTotal)}
        </div>
        <div style={{ fontSize:11.5, color:'var(--text-3)', marginTop:4 }}>Tocá cualquier saldo para editarlo</div>
      </Card2>

      {/* Account list */}
      {cuentas.map(c => (
        <Card2 key={c.id} padding={12}>
          <div style={{ display:'flex', alignItems:'center', gap:10 }}>
            <div style={{ width:34, height:34, borderRadius:9, background:'var(--surface)', border:'1px solid var(--border)', display:'flex', alignItems:'center', justifyContent:'center', color:'var(--accent-bright)', flexShrink:0 }}>
              <Icon2 name={c.type === 'USD' ? 'dollar' : 'wallet'} size={14} />
            </div>
            <div style={{ flex:1, minWidth:0 }}>
              <div style={{ fontSize:13.5, fontWeight:500 }}>{c.name}</div>
              <div style={{ fontSize:11.5, color:'var(--text-3)', marginTop:2 }}>
                <span style={{ display:'inline-block', padding:'1px 7px', borderRadius:999, background: c.type === 'USD' ? 'rgba(99,102,241,0.15)' : 'rgba(167,139,250,0.12)', color: c.type === 'USD' ? '#818cf8' : 'var(--accent-bright)', fontSize:10, fontWeight:700, letterSpacing:'0.08em' }}>{c.type}</span>
              </div>
            </div>
            <EditableBalance c={c} onUpdateCuenta={onUpdateCuenta} conv={conv} ccy={ccy} fmt={fmt} />
            {/* Delete button */}
            {confirmDelete === c.id ? (
              <div style={{ display:'flex', gap:4, alignItems:'center', marginLeft:6 }}>
                <button onClick={() => { if (onDeleteCuenta) onDeleteCuenta(c.id); setConfirmDelete(null); }} style={{ padding:'4px 10px', borderRadius:7, background:'rgba(248,113,113,0.15)', border:'1px solid rgba(248,113,113,0.35)', color:'var(--red)', fontSize:11, fontWeight:700, cursor:'pointer', fontFamily:'inherit' }}>Eliminar</button>
                <button onClick={() => setConfirmDelete(null)} style={{ padding:'4px 8px', borderRadius:7, background:'transparent', border:'1px solid var(--border)', color:'var(--text-3)', fontSize:11, cursor:'pointer', fontFamily:'inherit' }}>Cancelar</button>
              </div>
            ) : (
              <button onClick={() => setConfirmDelete(c.id)} title="Eliminar cuenta" style={{ width:28, height:28, borderRadius:7, background:'transparent', border:'1px solid transparent', color:'rgba(255,255,255,0.18)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0, transition:'color 0.15s, background 0.15s, border-color 0.15s', marginLeft:4 }}
                onMouseEnter={e => { e.currentTarget.style.color='var(--red)'; e.currentTarget.style.background='rgba(248,113,113,0.1)'; e.currentTarget.style.borderColor='rgba(248,113,113,0.25)'; }}
                onMouseLeave={e => { e.currentTarget.style.color='rgba(255,255,255,0.18)'; e.currentTarget.style.background='transparent'; e.currentTarget.style.borderColor='transparent'; }}
              >
                <Icon2 name="x" size={12} strokeWidth={2.2} />
              </button>
            )}
          </div>
        </Card2>
      ))}

      {/* Add account form */}
      {showAdd ? (
        <Card2 padding={16} style={{ borderColor:'var(--border-strong)', animation:'fadeSlide 0.15s ease' }}>
          <div style={{ fontSize:12, fontWeight:600, color:'var(--accent-bright)', marginBottom:12, textTransform:'uppercase', letterSpacing:'0.1em' }}>Nueva cuenta</div>
          <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
            <input
              placeholder="Nombre (ej: Brubank · ahorro)"
              value={newCuenta.name}
              onChange={e => setNewCuenta(p => ({ ...p, name: e.target.value }))}
              style={{ padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'inherit', fontSize:13, outline:'none', transition:'border-color 0.14s' }}
              onFocus={e => e.target.style.borderColor='var(--accent)'}
              onBlur={e => e.target.style.borderColor='var(--border-strong)'}
            />
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:8 }}>
              <select
                value={newCuenta.type}
                onChange={e => setNewCuenta(p => ({ ...p, type: e.target.value }))}
                style={{ padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'inherit', fontSize:13, outline:'none', cursor:'pointer' }}
              >
                <option value="ARS">ARS</option>
                <option value="USD">USD</option>
              </select>
              <input
                type="number"
                placeholder="Saldo actual"
                value={newCuenta.balance || ''}
                onChange={e => setNewCuenta(p => ({ ...p, balance: e.target.value }))}
                style={{ padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'inherit', fontSize:13, outline:'none', transition:'border-color 0.14s' }}
                onFocus={e => e.target.style.borderColor='var(--accent)'}
                onBlur={e => e.target.style.borderColor='var(--border-strong)'}
              />
            </div>
            <div style={{ display:'flex', gap:8, marginTop:2 }}>
              <button onClick={submitAdd} disabled={!newCuenta.name.trim()} style={{ flex:1, padding:'10px 0', borderRadius:9, background:'var(--accent)', color:'var(--on-accent)', border:'none', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600, opacity: newCuenta.name.trim() ? 1 : 0.4 }}>
                Agregar cuenta
              </button>
              <button onClick={() => { setShowAdd(false); setNewCuenta({ name:'', bank:'', type:'ARS', balance:0 }); }} style={{ padding:'10px 16px', borderRadius:9, background:'transparent', border:'1px solid var(--border)', color:'var(--text-3)', cursor:'pointer', fontFamily:'inherit', fontSize:13 }}>
                Cancelar
              </button>
            </div>
          </div>
        </Card2>
      ) : (
        <button onClick={() => setShowAdd(true)} style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:8, padding:'11px 0', borderRadius:12, background:'transparent', border:`1px dashed rgba(167,139,250,0.3)`, color:'var(--accent-bright)', fontFamily:'inherit', fontSize:13, fontWeight:600, cursor:'pointer', transition:'background 0.15s, border-color 0.15s' }}
          onMouseEnter={e => { e.currentTarget.style.background='var(--accent-dim)'; e.currentTarget.style.borderColor='var(--border-strong)'; }}
          onMouseLeave={e => { e.currentTarget.style.background='transparent'; e.currentTarget.style.borderColor='rgba(167,139,250,0.3)'; }}
        >
          <Icon2 name="plus" size={14} strokeWidth={2.5} /> Agregar cuenta
        </button>
      )}
    </div>
  );
}

// ─── Module-level card constants (moved out to avoid re-mount bug) ──────────────
const _netGrad = {
  VISA:       'linear-gradient(135deg, #1a1a6e 0%, #312e81 40%, #4c1d95 100%)',
  AMEX:       'linear-gradient(135deg, #0c4a6e 0%, #075985 40%, #0369a1 100%)',
  Mastercard: 'linear-gradient(135deg, #7f1d1d 0%, #991b1b 40%, #b91c1c 100%)',
};
const _netAccent = { VISA:'#818cf8', AMEX:'#38bdf8', Mastercard:'#f87171' };

// ─── CreditCard — module-level to avoid single-char bug ──────────────────────
function CreditCard({ t, idx, isActive, onClick, editingId, setEditingId, onUpdateTarjeta, fmt, resumen, cardWidth }) {
    const res = resumen ? resumen(t) : { acumulado: t.acumulado||0, diasCierre:'—', diasVencimiento:'—' };
    const grad = _netGrad[t.network] || _netGrad.VISA;
    const accent = _netAccent[t.network] || '#818cf8';
    const isEditing = editingId === t.id;
    const w = cardWidth || 300;
    const h = Math.round(w * 0.593); // maintain credit card aspect ratio

    return (
      <div
        onClick={onClick}
        style={{
          position:'relative', flexShrink:0,
          width: w, height: h,
          borderRadius: 20,
          background: grad,
          boxShadow: isActive
            ? `0 20px 60px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.12), 0 0 40px ${accent}33`
            : '0 8px 24px rgba(0,0,0,0.4)',
          cursor: 'pointer',
          transition: 'all 0.3s cubic-bezier(0.2,0.8,0.2,1)',
          transform: isActive ? 'scale(1)' : 'scale(0.93)',
          opacity: t.active ? 1 : 0.55,
          overflow: 'hidden',
          padding: '20px 22px',
          display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
        }}
      >
        {/* Decorative circles */}
        <div style={{ position:'absolute', top:-40, right:-40, width:160, height:160, borderRadius:'50%', background:'rgba(255,255,255,0.05)', pointerEvents:'none' }} />
        <div style={{ position:'absolute', bottom:-30, left:-20, width:120, height:120, borderRadius:'50%', background:'rgba(255,255,255,0.04)', pointerEvents:'none' }} />

        {/* Top row: bank name + chip */}
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', position:'relative', zIndex:1 }}>
          <div style={{ fontSize:13, fontWeight:700, color:'rgba(255,255,255,0.9)', letterSpacing:'0.04em' }}>{t.bank || t.name}</div>
          {/* Chip */}
          <div style={{ width:34, height:26, borderRadius:5, background:'linear-gradient(135deg, #d4af37, #f5e17a)', border:'1px solid rgba(212,175,55,0.5)', display:'flex', alignItems:'center', justifyContent:'center' }}>
            <div style={{ width:20, height:14, borderRadius:3, border:'1px solid rgba(0,0,0,0.2)', background:'linear-gradient(135deg, #c9a227, #e8d080)', display:'grid', gridTemplateColumns:'1fr 1fr', gap:1, padding:2 }}>
              {[0,1,2,3].map(i => <div key={i} style={{ background:'rgba(0,0,0,0.15)', borderRadius:1 }} />)}
            </div>
          </div>
        </div>

        {/* Card number placeholder */}
        <div style={{ fontFamily:'Space Grotesk, monospace', fontSize:15, letterSpacing:'0.2em', color:'rgba(255,255,255,0.7)', position:'relative', zIndex:1 }}>
          •••• •••• •••• ••••
        </div>

        {/* Bottom row */}
        <div style={{ display:'flex', alignItems:'flex-end', justifyContent:'space-between', position:'relative', zIndex:1 }}>
          <div>
            <div style={{ fontSize:9, color:'rgba(255,255,255,0.5)', textTransform:'uppercase', letterSpacing:'0.1em', marginBottom:2 }}>Acumulado</div>
            <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:18, fontWeight:700, color:'#fff', fontVariantNumeric:'tabular-nums' }}>
              {fmt(res.acumulado)}
            </div>
            {isEditing ? (
              <div style={{ display:'flex', gap:6, marginTop:6, alignItems:'center' }}>
                <span style={{ fontSize:9, color:'rgba(255,255,255,0.5)' }}>Cierre</span>
                <input type="number" min="1" max="31" defaultValue={t.fechaCierre}
                  onBlur={e => { if(onUpdateTarjeta) onUpdateTarjeta(t.id,{fechaCierre:Math.min(31,Math.max(1,+e.target.value))}); setEditingId(null); }}
                  onClick={e=>e.stopPropagation()}
                  style={{ width:36, padding:'2px 4px', borderRadius:4, background:'rgba(255,255,255,0.2)', border:'1px solid rgba(255,255,255,0.4)', color:'#fff', fontFamily:'inherit', fontSize:11, fontWeight:700, outline:'none', textAlign:'center' }} />
                <span style={{ fontSize:9, color:'rgba(255,255,255,0.5)' }}>Vto</span>
                <input type="number" min="1" max="31" defaultValue={t.fechaVencimiento}
                  onBlur={e => { if(onUpdateTarjeta) onUpdateTarjeta(t.id,{fechaVencimiento:Math.min(31,Math.max(1,+e.target.value))}); }}
                  onClick={e=>e.stopPropagation()}
                  style={{ width:36, padding:'2px 4px', borderRadius:4, background:'rgba(255,255,255,0.2)', border:'1px solid rgba(255,255,255,0.4)', color:'#fff', fontFamily:'inherit', fontSize:11, fontWeight:700, outline:'none', textAlign:'center' }} />
              </div>
            ) : (
              <div style={{ fontSize:10, color:'rgba(255,255,255,0.5)', marginTop:3 }}>
                Cierre día {t.fechaCierre}
                {typeof res.diasCierre === 'number' && <span style={{ marginLeft:4, color:'rgba(255,255,255,0.35)' }}>({res.diasCierre}d)</span>}
                {' · '}Vto día {t.fechaVencimiento}
              </div>
            )}
          </div>

          {/* Network logo */}
          <div style={{ textAlign:'right' }}>
            {t.network === 'Mastercard' ? (
              <div style={{ display:'flex', alignItems:'center', gap:-6 }}>
                <div style={{ width:28, height:28, borderRadius:'50%', background:'#eb001b', opacity:0.9 }} />
                <div style={{ width:28, height:28, borderRadius:'50%', background:'#f79e1b', opacity:0.9, marginLeft:-12 }} />
              </div>
            ) : (
              <div style={{ fontSize:15, fontWeight:900, color:'rgba(255,255,255,0.9)', letterSpacing:'0.05em', textShadow:'0 1px 4px rgba(0,0,0,0.3)' }}>
                {t.network}
              </div>
            )}
            <div style={{ fontSize:9, color:'rgba(255,255,255,0.4)', marginTop:3 }}>{t.name}</div>
          </div>
        </div>
      </div>
    );
  }

// ─── Tarjetas Tab ──────────────────────────────────────────────────────────────
function TarjetasTab({ tarjetasState, onAddTarjeta, onUpdateTarjeta, onDeleteTarjeta, fmt: fmtProp }) {
  const fmt = fmtProp || (n => '$ ' + new Intl.NumberFormat('es-AR').format(Math.round(n||0)));
  const tarjetas = tarjetasState || [];
  const [showAdd,       setShowAdd]       = useState2(false);
  const [confirmDelete, setConfirmDelete] = useState2(null);
  const [activeIdx,     setActiveIdx]     = useState2(0);
  const [editingId,     setEditingId]     = useState2(null);
  const carouselRef = useRef2(null);

  // Scroll carousel to active card when arrows are clicked
  useEffect2(() => {
    const el = carouselRef.current;
    if (!el) return;
    const cards = el.querySelectorAll('[data-card]');
    if (cards[activeIdx]) {
      cards[activeIdx].scrollIntoView({ behavior:'smooth', inline:'center', block:'nearest' });
    }
  }, [activeIdx]);
  const [newT, setNewT] = useState2({ name:'', bank:'', network:'VISA', fechaCierre:15, fechaVencimiento:5, limite:500000 });

  const NETWORKS = ['VISA','AMEX','Mastercard'];
  const resumen = window.TarjetasEngine?.resumen;
  const totalAcumulado = tarjetas.filter(t=>t.active).reduce((a,t)=>a+(t.acumulado||0),0);

  function submitAdd() {
    if (!newT.name.trim()) return;
    if (onAddTarjeta) onAddTarjeta({ ...newT, name: newT.name.trim(), bank: newT.bank.trim() || newT.name.trim() });
    setNewT({ name:'', bank:'', network:'VISA', fechaCierre:15, fechaVencimiento:5 });
    setShowAdd(false);
  }

  // ── Carousel dots ─────────────────────────────────────────────────────────
  const Dots = () => (
    <div style={{ display:'flex', justifyContent:'center', gap:6, marginTop:12 }}>
      {tarjetas.map((_,i) => (
        <button key={i} onClick={() => setActiveIdx(i)} style={{
          width: i === activeIdx ? 20 : 6, height:6, borderRadius:999,
          background: i === activeIdx ? 'var(--accent-bright)' : 'rgba(255,255,255,0.2)',
          border:'none', cursor:'pointer', padding:0,
          transition:'all 0.25s cubic-bezier(0.2,0.8,0.2,1)',
        }} />
      ))}
    </div>
  );

  const activeT = tarjetas[activeIdx];
  const activeRes = activeT && resumen ? resumen(activeT) : null;
  // Responsive card width: 300 on desktop, nearly full-width on phone
  const cardW = typeof window !== 'undefined' && window.innerWidth < 1024
    ? Math.min(300, window.innerWidth - 64)
    : 300;

  return (
    <div style={{ marginTop:0, display:'flex', flexDirection:'column', gap:14 }}>
      {/* Header */}
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <div>
          <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:18, fontWeight:600, letterSpacing:'-0.02em' }}>Tarjetas</div>
          <div style={{ fontSize:12, color:'var(--text-3)', marginTop:2 }}>
            {tarjetas.filter(t=>t.active).length} activas
            {totalAcumulado > 0 && <> · <span style={{ fontFamily:'Space Grotesk, sans-serif', fontVariantNumeric:'tabular-nums' }}>{fmt(totalAcumulado)}</span> acumulado</>}
          </div>
        </div>
        <button onClick={() => setShowAdd(s=>!s)} style={{ padding:'8px 16px', borderRadius:10, background:'var(--accent-dim)', border:'1px solid var(--border-strong)', color:'var(--accent-bright)', fontSize:12.5, fontWeight:600, cursor:'pointer', fontFamily:'inherit', display:'flex', alignItems:'center', gap:6 }}>
          <Icon2 name="plus" size={13} strokeWidth={2.5} /> Nueva tarjeta
        </button>
      </div>

      {/* Total hero (shown when there's acumulado) */}
      {totalAcumulado > 0 && (
        <Card2 padding={16} style={{ background:'linear-gradient(135deg, rgba(99,102,241,0.15), rgba(139,92,246,0.1))', borderColor:'rgba(99,102,241,0.3)' }}>
          <div style={{ fontSize:11, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, marginBottom:4 }}>Total acumulado en tarjetas</div>
          <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:28, fontWeight:700, fontVariantNumeric:'tabular-nums', color:'#818cf8' }}>{fmt(totalAcumulado)}</div>
          <div style={{ fontSize:11.5, color:'var(--text-3)', marginTop:4 }}>en {tarjetas.filter(t=>(t.acumulado||0)>0).length} tarjeta(s)</div>
        </Card2>
      )}

      {/* Carousel */}
      {tarjetas.length > 0 && (
        <div style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:0, position:'relative' }}>
          {/* Arrow buttons for desktop */}
          {tarjetas.length > 1 && (
            <>
              <button
                onClick={() => setActiveIdx(i => Math.max(0, i - 1))}
                disabled={activeIdx === 0}
                style={{ position:'absolute', left:0, top:'50%', transform:'translateY(-60%)', zIndex:10,
                  width:32, height:32, borderRadius:'50%', border:'1px solid var(--border-strong)',
                  background:'rgba(20,12,40,0.92)', color: activeIdx===0 ? 'rgba(255,255,255,0.2)' : 'var(--accent-bright)',
                  cursor: activeIdx===0 ? 'default' : 'pointer', display:'flex', alignItems:'center', justifyContent:'center',
                  backdropFilter:'blur(8px)', transition:'all 0.15s',
                }}>
                <Icon2 name="chevronLeft" size={14} strokeWidth={2.5} />
              </button>
              <button
                onClick={() => setActiveIdx(i => Math.min(tarjetas.length - 1, i + 1))}
                disabled={activeIdx === tarjetas.length - 1}
                style={{ position:'absolute', right:0, top:'50%', transform:'translateY(-60%)', zIndex:10,
                  width:32, height:32, borderRadius:'50%', border:'1px solid var(--border-strong)',
                  background:'rgba(20,12,40,0.92)', color: activeIdx===tarjetas.length-1 ? 'rgba(255,255,255,0.2)' : 'var(--accent-bright)',
                  cursor: activeIdx===tarjetas.length-1 ? 'default' : 'pointer', display:'flex', alignItems:'center', justifyContent:'center',
                  backdropFilter:'blur(8px)', transition:'all 0.15s',
                }}>
                <Icon2 name="chevronRight" size={14} strokeWidth={2.5} />
              </button>
            </>
          )}
          {/* Cards strip */}
          <div ref={carouselRef} style={{
            display:'flex', gap:16, overflowX:'auto', scrollSnapType:'x mandatory',
            scrollbarWidth:'none', msOverflowStyle:'none',
            padding: `12px ${tarjetas.length > 1 ? 40 : 0}px`,
            width:'100%', boxSizing:'border-box',
            justifyContent: tarjetas.length === 1 ? 'center' : 'flex-start',
          }}>
            {tarjetas.map((t, i) => (
              <div key={t.id} data-card={i} style={{ scrollSnapAlign:'center', flexShrink:0 }}>
                <CreditCard t={t} idx={i} isActive={activeIdx===i} onClick={() => setActiveIdx(i)} editingId={editingId} setEditingId={setEditingId} onUpdateTarjeta={onUpdateTarjeta} fmt={fmt} resumen={resumen} cardWidth={cardW} />
              </div>
            ))}
          </div>
          {Dots()}
        </div>
      )}

      {/* Active card detail panel */}
      {activeT && (
        <Card2 padding={14} style={{ animation:'fadeSlide 0.2s ease' }}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
            <div>
              <div style={{ fontSize:13.5, fontWeight:600 }}>{activeT.name}</div>
              <div style={{ fontSize:11.5, color:'var(--text-3)', marginTop:3 }}>
                Cierre día {activeT.fechaCierre} · Vto día {activeT.fechaVencimiento}
                {activeRes && typeof activeRes.diasCierre === 'number' && <span style={{ marginLeft:6, color:'var(--amber)' }}>· {activeRes.diasCierre}d para cierre</span>}
              </div>
            </div>
            <div style={{ display:'flex', gap:4 }}>
              {/* Activar/desactivar */}
              <button onClick={() => onUpdateTarjeta && onUpdateTarjeta(activeT.id, { active: !activeT.active })} title={activeT.active?'Desactivar':'Activar'} style={{ width:28, height:28, borderRadius:7, background: activeT.active ? 'rgba(74,222,128,0.1)' : 'rgba(255,255,255,0.05)', border:`1px solid ${activeT.active ? 'rgba(74,222,128,0.3)' : 'var(--border)'}`, color: activeT.active ? '#4ade80' : 'var(--text-3)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center' }}>
                <Icon2 name={activeT.active?'check':'x'} size={11} strokeWidth={2.5} />
              </button>
              {/* Editar fechas */}
              <button onClick={() => setEditingId(editingId === activeT.id ? null : activeT.id)} title="Editar fechas" style={{ width:28, height:28, borderRadius:7, background: editingId===activeT.id ? 'var(--accent-dim)' : 'rgba(255,255,255,0.05)', border:`1px solid ${editingId===activeT.id ? 'var(--border-strong)' : 'var(--border)'}`, color: editingId===activeT.id ? 'var(--accent-bright)' : 'var(--text-3)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center' }}>
                <Icon2 name="settings" size={12} strokeWidth={1.8} />
              </button>
              {/* Eliminar */}
              {confirmDelete === activeT.id ? (
                <div style={{ display:'flex', gap:3 }}>
                  <button onClick={() => { if(onDeleteTarjeta) onDeleteTarjeta(activeT.id); setConfirmDelete(null); setActiveIdx(Math.max(0,activeIdx-1)); }} style={{ padding:'4px 8px', borderRadius:6, background:'rgba(248,113,113,0.15)', border:'1px solid rgba(248,113,113,0.35)', color:'var(--red)', fontSize:10, fontWeight:700, cursor:'pointer', fontFamily:'inherit' }}>Eliminar</button>
                  <button onClick={()=>setConfirmDelete(null)} style={{ padding:'4px 6px', borderRadius:6, background:'transparent', border:'1px solid var(--border)', color:'var(--text-3)', fontSize:10, cursor:'pointer', fontFamily:'inherit' }}>No</button>
                </div>
              ) : (
                <button onClick={()=>setConfirmDelete(activeT.id)} title="Eliminar" style={{ width:28, height:28, borderRadius:7, background:'transparent', border:'1px solid transparent', color:'rgba(255,255,255,0.18)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', transition:'all 0.13s' }}
                  onMouseEnter={e=>{e.currentTarget.style.color='var(--red)';e.currentTarget.style.background='rgba(248,113,113,0.1)';e.currentTarget.style.borderColor='rgba(248,113,113,0.25)';}}
                  onMouseLeave={e=>{e.currentTarget.style.color='rgba(255,255,255,0.18)';e.currentTarget.style.background='transparent';e.currentTarget.style.borderColor='transparent';}}>
                  <Icon2 name="x" size={12} strokeWidth={2.2} />
                </button>
              )}
            </div>
          </div>
        </Card2>
      )}

      {/* Add form */}
      {showAdd && (
        <Card2 padding={16} style={{ borderColor:'var(--border-strong)', animation:'fadeSlide 0.15s ease' }}>
          <div style={{ fontSize:11, fontWeight:700, color:'var(--accent-bright)', textTransform:'uppercase', letterSpacing:'0.1em', marginBottom:12 }}>Nueva tarjeta</div>
          <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
            {[['Nombre','name','Ej: Santander VISA'],['Banco','bank','Ej: Santander']].map(([label,key,ph]) => (
              <div key={key}>
                <div style={{ fontSize:10, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:600, marginBottom:5 }}>{label}</div>
                <input value={newT[key]} onChange={e=>setNewT(p=>({...p,[key]:e.target.value}))} placeholder={ph}
                  style={{ width:'100%', padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.05)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'inherit', fontSize:13, outline:'none' }} />
              </div>
            ))}
            <div>
              <div style={{ fontSize:10, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:600, marginBottom:6 }}>Red</div>
              <div style={{ display:'flex', gap:6 }}>
                {NETWORKS.map(n => (
                  <button key={n} onClick={()=>setNewT(p=>({...p,network:n}))} style={{ flex:1, padding:'8px 0', borderRadius:9, cursor:'pointer', fontFamily:'inherit', fontSize:12, fontWeight:700,
                    background: newT.network===n ? (n==='VISA'?'rgba(99,102,241,0.2)':n==='AMEX'?'rgba(14,165,233,0.2)':'rgba(239,68,68,0.2)') : 'rgba(255,255,255,0.04)',
                    border:`1px solid ${newT.network===n ? (n==='VISA'?'rgba(99,102,241,0.5)':n==='AMEX'?'rgba(14,165,233,0.5)':'rgba(239,68,68,0.5)') : 'var(--border)'}`,
                    color: newT.network===n ? (n==='VISA'?'#818cf8':n==='AMEX'?'#38bdf8':'#f87171') : 'var(--text-3)', transition:'all 0.13s' }}>{n}</button>
                ))}
              </div>
            </div>
            {/* Preview de la nueva tarjeta */}
            <div style={{ display:'flex', justifyContent:'center', padding:'8px 0' }}>
              <CreditCard t={{ ...newT, name: newT.name||'Nueva tarjeta', bank: newT.bank||'Banco', acumulado:0, active:true }} idx={0} isActive={true} onClick={()=>{}} fmt={fmt} />
            </div>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:8 }}>
              {[['Día de cierre','fechaCierre'],['Día de vencimiento','fechaVencimiento']].map(([label,key]) => (
                <div key={key}>
                  <div style={{ fontSize:10, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:600, marginBottom:5 }}>{label}</div>
                  <input type="number" min="1" max="31" value={newT[key]}
                    onChange={e=>setNewT(p=>({...p,[key]:Math.min(31,Math.max(1,+e.target.value))}))}
                    style={{ width:'100%', padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.05)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'inherit', fontSize:16, fontWeight:700, outline:'none', textAlign:'center' }} />
                </div>
              ))}
              <div>
                <div style={{ fontSize:10, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:600, marginBottom:5 }}>Límite</div>
                <input type="number" min="0" value={newT.limite}
                  onChange={e=>setNewT(p=>({...p,limite:Math.max(0,+e.target.value)}))}
                  style={{ width:'100%', padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.05)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'inherit', fontSize:14, fontWeight:700, outline:'none', textAlign:'center' }} />
              </div>
            </div>
            <div style={{ display:'flex', gap:8, marginTop:4 }}>
              <button onClick={submitAdd} disabled={!newT.name.trim()} style={{ flex:1, padding:'11px 0', borderRadius:10, background:'var(--accent)', color:'var(--on-accent)', border:'none', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600, opacity:newT.name.trim()?1:0.4 }}>Agregar tarjeta</button>
              <button onClick={()=>setShowAdd(false)} style={{ padding:'11px 14px', borderRadius:10, background:'transparent', border:'1px solid var(--border)', color:'var(--text-3)', cursor:'pointer', fontFamily:'inherit', fontSize:13 }}>Cancelar</button>
            </div>
          </div>
        </Card2>
      )}

      {/* ── Lista de tarjetas con barra de progreso ──────────────────────── */}
      {tarjetas.length > 0 && (
        <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
          <div style={{ fontSize:11, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:700, padding:'4px 2px 2px' }}>
            Detalle por tarjeta
          </div>
          {tarjetas.map(t => {
            const acum   = t.acumulado || 0;
            const limite = t.limite || 0;
            const pct    = limite > 0 ? Math.min(acum / limite, 1) : 0;
            const over   = limite > 0 && acum > limite;
            const barColor = over ? 'var(--red)' : pct > 0.8 ? 'var(--amber)' : _netAccent[t.network] || 'var(--accent-bright)';
            const netBg = { VISA:'rgba(99,102,241,0.12)', AMEX:'rgba(14,165,233,0.12)', Mastercard:'rgba(239,68,68,0.12)' };
            return (
              <Card2 key={t.id} padding={14}
                onClick={() => setActiveIdx(tarjetas.indexOf(t))}
                style={{ opacity: t.active ? 1 : 0.5, cursor:'pointer',
                  borderColor: activeIdx === tarjetas.indexOf(t) ? 'var(--border-strong)' : 'var(--border)',
                  background: activeIdx === tarjetas.indexOf(t) ? 'rgba(167,139,250,0.06)' : 'var(--card)',
                  transition:'border-color 0.2s, background 0.2s',
                }}>
                <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:10 }}>
                  {/* Network badge */}
                  <div style={{ width:36, height:36, borderRadius:9, flexShrink:0, background: netBg[t.network]||'var(--accent-dim)', display:'flex', alignItems:'center', justifyContent:'center' }}>
                    {t.network === 'Mastercard' ? (
                      <div style={{ position:'relative', width:22, height:15 }}>
                        <div style={{ position:'absolute', left:0, width:14, height:14, borderRadius:'50%', background:'#eb001b', opacity:0.85 }} />
                        <div style={{ position:'absolute', right:0, width:14, height:14, borderRadius:'50%', background:'#f79e1b', opacity:0.85 }} />
                      </div>
                    ) : (
                      <span style={{ fontSize:8, fontWeight:900, color: _netAccent[t.network]||'var(--accent-bright)', letterSpacing:'0.04em' }}>{t.network}</span>
                    )}
                  </div>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ fontSize:13.5, fontWeight:600, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{t.name}</div>
                    <div style={{ display:'flex', alignItems:'center', gap:6, marginTop:4, flexWrap:'wrap' }}>
                      <span style={{ fontSize:10.5, color:'var(--text-3)' }}>Cierre día</span>
                      <input type="number" min="1" max="31"
                        value={t.fechaCierre}
                        onChange={e => onUpdateTarjeta && onUpdateTarjeta(t.id, { fechaCierre: Math.min(31,Math.max(1,+e.target.value||1)) })}
                        onClick={e => e.stopPropagation()}
                        style={{ width:38, padding:'2px 6px', borderRadius:6, background:'rgba(251,191,36,0.1)', border:'1px solid rgba(251,191,36,0.3)', color:'var(--amber)', fontFamily:'Space Grotesk, sans-serif', fontSize:12, fontWeight:700, outline:'none', textAlign:'center' }}
                      />
                      <span style={{ fontSize:10.5, color:'var(--text-3)' }}>· Vto día</span>
                      <input type="number" min="1" max="31"
                        value={t.fechaVencimiento}
                        onChange={e => onUpdateTarjeta && onUpdateTarjeta(t.id, { fechaVencimiento: Math.min(31,Math.max(1,+e.target.value||1)) })}
                        onClick={e => e.stopPropagation()}
                        style={{ width:38, padding:'2px 6px', borderRadius:6, background:'rgba(74,222,128,0.08)', border:'1px solid rgba(74,222,128,0.25)', color:'#4ade80', fontFamily:'Space Grotesk, sans-serif', fontSize:12, fontWeight:700, outline:'none', textAlign:'center' }}
                      />
                    </div>
                  </div>
                  <div style={{ textAlign:'right', flexShrink:0 }} onClick={e => e.stopPropagation()}>
                    <div style={{ display:'flex', alignItems:'center', gap:3 }}>
                      <span style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:13, fontWeight:600, color: over?'var(--red)':'var(--text-3)' }}>$</span>
                      <input
                        type="number" min="0"
                        value={acum}
                        onChange={e => onUpdateTarjeta && onUpdateTarjeta(t.id, { acumulado: Math.max(0, +e.target.value||0) })}
                        style={{ width:72, padding:'3px 6px', borderRadius:7, background:'rgba(255,255,255,0.06)', border:`1px solid ${over?'rgba(248,113,113,0.4)':'var(--border-strong)'}`, color: over?'var(--red)':'var(--text)', fontFamily:'Space Grotesk, sans-serif', fontSize:14, fontWeight:700, outline:'none', textAlign:'right', fontVariantNumeric:'tabular-nums' }}
                      />
                    </div>
                    {limite > 0 && (
                      <div style={{ fontSize:10, color:'var(--text-3)', marginTop:2, textAlign:'right' }}>de {fmt(limite)}</div>
                    )}
                  </div>
                </div>
                {/* Progress bar */}
                {limite > 0 && (
                  <>
                    <div style={{ height:6, background:'rgba(255,255,255,0.06)', borderRadius:999, overflow:'hidden' }}>
                      <div style={{
                        height:'100%', borderRadius:999,
                        width: `${Math.min(pct * 100, 100)}%`,
                        background: over
                          ? 'var(--red)'
                          : pct > 0.8
                            ? 'linear-gradient(90deg, var(--amber), #fb923c)'
                            : `linear-gradient(90deg, ${barColor}cc, ${barColor})`,
                        transition: 'width 0.8s cubic-bezier(0.34,1.56,0.64,1)',
                        boxShadow: `0 0 8px ${barColor}66`,
                      }} />
                    </div>
                    <div style={{ display:'flex', justifyContent:'space-between', marginTop:5, fontSize:10.5, color:'var(--text-3)' }}>
                      <span style={{ color: over ? 'var(--red)' : pct > 0.8 ? 'var(--amber)' : 'var(--text-3)', fontWeight: pct > 0.8 ? 600 : 400 }}>
                        {Math.round(pct * 100)}% usado{over ? ' ⚠ Sobre límite' : ''}
                      </span>
                      <span>{Math.round(pct * 100)}% de {fmt(limite)}</span>
                    </div>
                  </>
                )}
              </Card2>
            );
          })}
        </div>
      )}

      {tarjetas.length === 0 && !showAdd && (
        <div style={{ textAlign:'center', padding:'32px 0', color:'var(--text-3)', fontSize:13 }}>Sin tarjetas — agregá una con + Nueva</div>
      )}
    </div>
  );
}

// ─── Bandeja Item (with category selector) ────────────────────────────────────
function BandejaItem({ b, fmt, onConfirm, onDiscard }) {
  const [catId, setCatId] = useState2(b.suggested);
  const [catOpen, setCatOpen] = useState2(false);
  const cat = seed2.catPorId[catId];
  const dropRef = useRef2(null);

  // Close dropdown on outside click
  useEffect2(() => {
    if (!catOpen) return;
    const handler = e => {
      if (dropRef.current && !dropRef.current.contains(e.target)) setCatOpen(false);
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [catOpen]);

  return (
    <Card2 padding={12} style={{ animation:'tabEnter 0.2s ease' }}>
      <div style={{ display:'flex', alignItems:'center', gap:10 }}>
        <CC2 cat={cat} size={30} />
        <div style={{ flex:1, minWidth:0 }}>
          <div style={{ fontSize:13, fontWeight:500 }}>{b.merchant}</div>
          <div style={{ fontSize:11, color:'var(--text-3)', marginTop:1 }}>
            {b.source} · {new Date(b.date).toLocaleDateString('es-AR', { day:'numeric', month:'short' })}
          </div>
        </div>
        <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:14, fontWeight:600, fontVariantNumeric:'tabular-nums' }}>
          {fmt(-b.amount)}
        </div>
      </div>

      {/* Category selector */}
      <div style={{ marginTop:12, position:'relative' }} ref={dropRef}>
        <button
          onClick={() => setCatOpen(o => !o)}
          style={{
            width:'100%', padding:'9px 12px', borderRadius:10,
            background:'rgba(255,255,255,0.04)', border:`1px solid ${cat.color}40`,
            cursor:'pointer', fontFamily:'inherit', color:'inherit',
            display:'flex', alignItems:'center', gap:8,
            transition:'border-color 0.15s, background 0.15s',
          }}
        >
          <span style={{ color:cat.color, display:'inline-flex' }}><Icon2 name={cat.icon} size={14} /></span>
          <span style={{ flex:1, textAlign:'left', fontSize:13, fontWeight:500, color:'var(--text-2)' }}>{cat.name}</span>
          <span style={{ fontSize:10, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:600 }}>Cambiar</span>
          <Icon2 name={catOpen ? 'chevDown' : 'chevRight'} size={13} style={{ color:'var(--text-3)' }} />
        </button>

        {catOpen && (
          <div style={{
            position:'absolute', top:'calc(100% + 4px)', left:0, right:0, zIndex:20,
            background:'rgba(14,8,28,0.98)', border:'1px solid var(--border-strong)',
            borderRadius:14, padding:8, maxHeight:240, overflowY:'auto',
            backdropFilter:'blur(24px)',
            boxShadow:'0 20px 40px rgba(0,0,0,0.5)',
            animation:'fadeSlide 0.15s ease',
          }}>
            <div style={{ fontSize:10, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, padding:'4px 10px 8px' }}>Seleccionar categoria</div>
            {seed2.categories.map(c => (
              <button key={c.id} onClick={() => { setCatId(c.id); setCatOpen(false); }} style={{
                width:'100%', padding:'8px 10px', borderRadius:9,
                background: c.id===catId ? 'var(--accent-dim)' : 'transparent',
                border:'none', cursor:'pointer', fontFamily:'inherit',
                display:'flex', alignItems:'center', gap:9,
                color: c.id===catId ? 'var(--accent-bright)' : 'var(--text-2)',
                fontSize:13, fontWeight: c.id===catId ? 600 : 400,
                transition:'background 0.12s',
              }}>
                <span style={{ color:c.color, display:'inline-flex' }}><Icon2 name={c.icon} size={14} /></span>
                <span style={{ flex:1, textAlign:'left' }}>{c.name}</span>
                {c.id===catId && <Icon2 name="check" size={13} strokeWidth={2.5} />}
              </button>
            ))}
          </div>
        )}
      </div>

      <div style={{ display:'flex', gap:8, marginTop:10 }}>
        <button
          onClick={() => onConfirm(b.id, catId)}
          className="btn-accent-hov"
          style={{ flex:1, padding:'10px 8px', borderRadius:10, fontSize:12.5, fontWeight:600, background:'var(--accent)', color:'var(--on-accent)', border:'none', cursor:'pointer', fontFamily:'inherit', display:'flex', alignItems:'center', justifyContent:'center', gap:6 }}
        >
          <Icon2 name="check" size={14} strokeWidth={2.4} /> Confirmar
        </button>
        <button
          onClick={() => onDiscard(b.id)}
          style={{ width:44, padding:'10px 0', borderRadius:10, background:'var(--card)', color:'var(--text-3)', border:'1px solid var(--border)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', transition:'color 0.14s, border-color 0.14s' }}
          onMouseEnter={e => { e.currentTarget.style.color='var(--red)'; e.currentTarget.style.borderColor='rgba(248,113,113,0.35)'; }}
          onMouseLeave={e => { e.currentTarget.style.color='var(--text-3)'; e.currentTarget.style.borderColor='var(--border)'; }}
        >
          <Icon2 name="x" size={14} />
        </button>
      </div>
    </Card2>
  );
}

// ─── CIERRE DE MES TAB ────────────────────────────────────────────────────────
function CierreMesTab({ onToast, compact }) {
  const [cerrando, setCerrando] = useState2(false);
  const [stats,    setStats]    = useState2(null);
  const [history,  setHistory]  = useState2([]);
  const NS = 'sisyphus.v1.';
  // confirmedIngresos: { [id]: true } — persisted so it survives navigation
  const [confirmedIngs, setConfirmedIngs] = useState2(() => {
    try { return JSON.parse(localStorage.getItem(NS + 'confirmed_ings') || '{}'); } catch { return {}; }
  });
  function confirmIngreso(id) {
    const next = { ...confirmedIngs, [id]: true };
    setConfirmedIngs(next);
    localStorage.setItem(NS + 'confirmed_ings', JSON.stringify(next));
    if (onToast) onToast('Ingreso confirmado ✓');
  }
  function unconfirmIngreso(id) {
    const next = { ...confirmedIngs };
    delete next[id];
    setConfirmedIngs(next);
    localStorage.setItem(NS + 'confirmed_ings', JSON.stringify(next));
  }
  // Build ingresos from persisted sueldo/extra_ing instead of hardcoded seed
  const ingresos = (() => {
    const s = parseFloat(localStorage.getItem('sisyphus.v1.sueldo')) || 0;
    const e = parseFloat(localStorage.getItem('sisyphus.v1.extra_ing')) || 0;
    const list = [];
    if (s > 0) list.push({ id: 'ing-sueldo',    name: 'Sueldo',    amount: s });
    if (e > 0) list.push({ id: 'ing-adicional',  name: 'Adicional', amount: e });
    return list;
  })();
  const allConfirmed = ingresos.length > 0 && ingresos.every(i => confirmedIngs[i.id]);

  // Load history in effect — avoids crash if MonthClose isn't ready yet
  useEffect2(() => {
    try { setHistory(window.MonthClose?.getHistory() || []); } catch(e) { console.error('getHistory:', e); }
  }, [stats]); // reload after a close

  async function handleCerrar() {
    if (cerrando) return;
    if (!window.MonthClose) {
      if (onToast) onToast('Módulo de cierre no disponible — recargá la página');
      return;
    }
    setCerrando(true);
    try {
      const s = await window.MonthClose.cerrarMes(() => {});
      if (s) {
        setStats(s);
        const emailSent = window.GmailAPI?.isConnected?.();
        if (onToast) onToast(emailSent ? 'Mes cerrado · resumen enviado por email' : 'Mes cerrado · archivado localmente');
      } else {
        if (onToast) onToast('Error al procesar el cierre');
      }
    } catch(e) {
      console.error('cerrarMes error:', e);
      if (onToast) onToast('Error al cerrar el mes');
    } finally { setCerrando(false); }
  }

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      {/* ── Ingresos del mes ──────────────────────────────────── */}
      <Card2 padding={0} style={{ overflow:'hidden' }}>
        <div style={{ padding:'12px 16px', borderBottom:'1px solid var(--border)', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
          <div style={{ fontSize:13, fontWeight:600 }}>Ingresos del mes</div>
          {allConfirmed && (
            <span style={{ fontSize:10, fontWeight:700, padding:'2px 8px', borderRadius:999, background:'rgba(74,222,128,0.15)', color:'#4ade80' }}>TODO CONFIRMADO</span>
          )}
        </div>
        {ingresos.map(ing => {
          const confirmed = !!confirmedIngs[ing.id];
          return (
            <div key={ing.id} style={{ display:'flex', alignItems:'center', gap:12, padding:'13px 16px', borderBottom:'1px solid var(--border)', background: confirmed ? 'rgba(74,222,128,0.04)' : 'transparent', transition:'background 0.2s' }}>
              <div style={{ width:38, height:38, borderRadius:10, background: confirmed ? 'rgba(74,222,128,0.12)' : 'var(--accent-dim)', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
                <Icon2 name={confirmed ? 'check' : 'dollar'} size={17} strokeWidth={confirmed ? 2.5 : 1.8} style={{ color: confirmed ? '#4ade80' : 'var(--accent-bright)' }} />
              </div>
              <div style={{ flex:1 }}>
                <div style={{ fontSize:13.5, fontWeight:500, color: confirmed ? 'var(--text)' : 'var(--text)' }}>{ing.name}</div>
                <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:15, fontWeight:700, fontVariantNumeric:'tabular-nums', marginTop:2 }}>
                  $ {new Intl.NumberFormat('es-AR').format(ing.amount)}
                </div>
              </div>
              <button
                onClick={() => confirmed ? unconfirmIngreso(ing.id) : confirmIngreso(ing.id)}
                style={{
                  padding:'7px 14px', borderRadius:999, border:'none', cursor:'pointer',
                  fontFamily:'inherit', fontSize:11.5, fontWeight:700,
                  background: confirmed ? 'rgba(74,222,128,0.12)' : 'var(--accent-dim)',
                  color: confirmed ? '#4ade80' : 'var(--accent-bright)',
                  transition:'all 0.15s',
                }}
              >
                {confirmed ? '✓ Recibido' : 'Confirmar'}
              </button>
            </div>
          );
        })}
      </Card2>

      {/* ── Cerrar el mes ─────────────────────────────────────────── */}
      <Card2 padding={20} style={{ textAlign:'center', display:'flex', flexDirection:'column', alignItems:'center', gap:16 }}>
        <div style={{ width:56, height:56, borderRadius:16, background:'var(--accent-dim)', border:'1px solid var(--border-strong)', display:'flex', alignItems:'center', justifyContent:'center', color:'var(--accent-bright)' }}>
          <Icon2 name="calendar" size={26} strokeWidth={1.6} />
        </div>
        <div>
          <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:18, fontWeight:600, letterSpacing:'-0.01em' }}>Cerrar el mes</div>
          <div style={{ fontSize:12.5, color:'var(--text-3)', marginTop:4, lineHeight:1.5 }}>Archiva los datos del mes, calcula estadísticas comparativas y te envía un resumen por email.</div>
        </div>
        <button onClick={handleCerrar} disabled={cerrando} className="btn-accent-hov"
          style={{ width:'100%', padding:'13px 0', borderRadius:12, background: cerrando ? 'var(--card)' : 'linear-gradient(145deg, var(--accent-bright), var(--accent-deep))', color: cerrando ? 'var(--text-3)' : 'var(--on-accent)', border:'none', cursor: cerrando ? 'not-allowed' : 'pointer', fontFamily:'inherit', fontSize:14, fontWeight:600, display:'flex', alignItems:'center', justifyContent:'center', gap:8, transition:'all 0.15s' }}>
          {cerrando ? <><span style={{ width:14, height:14, borderRadius:'50%', border:'2px solid var(--text-3)', borderTopColor:'transparent', animation:'spin 0.7s linear infinite', display:'inline-block' }} /> Procesando…</> : '✓ Cerrar mes y enviar resumen'}
        </button>
      </Card2>

      {/* Export CSV */}
      <button
        onClick={() => {
          const exportStats = stats || (window.MonthClose ? window.MonthClose.buildStats() : null);
          if (!exportStats) { if (onToast) onToast('No se pudieron calcular las estadísticas'); return; }
          if (!stats) setStats(exportStats);
          const rows = [
            ['Categoría','Gastado','Presupuesto','Diferencia'],
            ...(exportStats.cats || []).map(c => [c.name, c.spent, c.budget, c.budget - c.spent]),
            [],
            ['','Ingresos',exportStats.ingTotal,''],
            ['','Egresos',exportStats.egrTotal,''],
            ['','Ahorro',exportStats.ahoTotal,''],
            ['','Neto',exportStats.neto,''],
          ];
          const csv = rows.map(r => r.map(v => `"${v}"`).join(',')).join('\n');
          const blob = new Blob([csv], { type:'text/csv;charset=utf-8;' });
          const url = URL.createObjectURL(blob);
          const a = document.createElement('a');
          a.href = url; a.download = `sisyphus-${new Date().toISOString().slice(0,7)}.csv`;
          a.click(); URL.revokeObjectURL(url);
          if (onToast) onToast('CSV exportado correctamente');
        }}
        style={{ width:'100%', padding:'12px 0', borderRadius:12, background:'rgba(99,102,241,0.12)', border:'1px solid rgba(99,102,241,0.3)', color:'#818cf8', fontFamily:'inherit', fontSize:13, fontWeight:600, cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', gap:8 }}
      >
        <Icon2 name="arrowDown" size={14} strokeWidth={2.5} /> Exportar resumen CSV
      </button>

      {stats && (
        <Card2 padding={16}>
          <div style={{ fontSize:11, color:'var(--accent-bright)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, marginBottom:10 }}>Resumen del mes cerrado</div>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
            {[['Ingresos', stats.ingTotal], ['Egresos', stats.egrTotal], ['Ahorro', stats.ahoTotal], ['Neto', stats.neto]].map(([l,v]) => (
              <div key={l} style={{ padding:'10px 12px', borderRadius:10, background:'rgba(255,255,255,0.03)', border:'1px solid var(--border)' }}>
                <div style={{ fontSize:10.5, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:600 }}>{l}</div>
                <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:16, fontWeight:600, marginTop:4, fontVariantNumeric:'tabular-nums', color: l==='Neto' && v<0 ? 'var(--red)' : 'var(--text)' }}>$ {new Intl.NumberFormat('es-AR').format(Math.round(v))}</div>
              </div>
            ))}
          </div>
        </Card2>
      )}
      {history.length > 0 && (
        <div>
          <div style={{ fontSize:11.5, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, padding:'8px 4px' }}>Historial de cierres</div>
          {history.slice().reverse().slice(0,3).map((h,i) => (
            <Card2 key={i} padding={14} style={{ marginBottom:8 }}>
              <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center' }}>
                <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:14, fontWeight:600 }}>
                  {h.monthName || (h.closedAt ? new Date(h.closedAt).toLocaleDateString('es-AR', { month:'long', year:'numeric' }) : '—')}
                </div>
                <div style={{ fontSize:12.5, color: (h.neto||0)>=0 ? 'var(--accent-bright)' : 'var(--red)', fontVariantNumeric:'tabular-nums' }}>$ {new Intl.NumberFormat('es-AR').format(Math.round(h.neto||0))}</div>
              </div>
            </Card2>
          ))}
        </div>
      )}
    </div>
  );
}

// ─── CONFIGURACIÓN ────────────────────────────────────────────────────────────
function PerfilTab({ profilePhoto, onProfileChange, onToast, userName, onUserNameChange, photoPos, onPhotoPosChange }) {
  const fileRef = useRef2(null);
  const [name, setName] = useState2(userName || 'Adolfo');
  const [saved, setSaved] = useState2(false);
  // Photo repositioning — controlled from App so position persists across nav
  const pos = photoPos || { x:50, y:50 };
  const setPos = p => { if (onPhotoPosChange) onPhotoPosChange(typeof p === 'function' ? p(pos) : p); };
  const [dragging, setDragging] = useState2(false);
  const [dragStart, setDragStart] = useState2(null);
  const [editingName, setEditingName] = useState2(false);
  const [nameInput,   setNameInput]   = useState2(userName || '');

  // ── Drag to reposition photo ──────────────────────────────────────────────
  function onMouseDown(e) {
    setDragging(true);
    setDragStart({ mx: e.clientX, my: e.clientY, ox: pos.x, oy: pos.y });
  }
  function onMouseMove(e) {
    if (!dragging || !dragStart) return;
    const el = e.currentTarget;
    const r  = el.getBoundingClientRect();
    const dx = e.clientX - dragStart.mx;
    const dy = e.clientY - dragStart.my;
    setPos({
      x: Math.max(0, Math.min(100, dragStart.ox + (dx / r.width)  * 100)),
      y: Math.max(0, Math.min(100, dragStart.oy + (dy / r.height) * 100)),
    });
  }
  function onMouseUp() { setDragging(false); setDragStart(null); }

  function onTouchStart(e) {
    const t = e.touches[0];
    setDragging(true);
    setDragStart({ mx: t.clientX, my: t.clientY, ox: pos.x, oy: pos.y });
  }
  function onTouchMove(e) {
    if (!dragging || !dragStart) return;
    const t  = e.touches[0];
    const el = e.currentTarget;
    const r  = el.getBoundingClientRect();
    const dx = t.clientX - dragStart.mx;
    const dy = t.clientY - dragStart.my;
    setPos({
      x: Math.max(0, Math.min(100, dragStart.ox + (dx / r.width)  * 100)),
      y: Math.max(0, Math.min(100, dragStart.oy + (dy / r.height) * 100)),
    });
  }

  const hasPhoto = !!profilePhoto;

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
      {/* Avatar */}
      <div style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:12, padding:'20px 0 10px' }}>
        <div
          style={{ width:96, height:96, borderRadius:'50%', overflow:'hidden', background:'var(--accent-dim)', border:'2px solid var(--border-strong)', cursor: hasPhoto ? 'grab' : 'default', userSelect:'none', flexShrink:0, position:'relative' }}
          onMouseDown={hasPhoto ? onMouseDown : undefined}
          onMouseMove={hasPhoto ? onMouseMove : undefined}
          onMouseUp={hasPhoto ? onMouseUp : undefined}
          onMouseLeave={hasPhoto ? onMouseUp : undefined}
          onTouchStart={hasPhoto ? onTouchStart : undefined}
          onTouchMove={hasPhoto ? onTouchMove : undefined}
          onTouchEnd={hasPhoto ? onMouseUp : undefined}
        >
          {hasPhoto
            ? <img src={profilePhoto} alt="Perfil" style={{ width:'100%', height:'100%', objectFit:'cover', objectPosition:`${pos.x}% ${pos.y}%`, pointerEvents:'none' }} />
            : <div style={{ width:'100%', height:'100%', display:'flex', alignItems:'center', justifyContent:'center', color:'var(--accent-bright)', fontSize:32, fontWeight:700 }}>{(userName||'?').charAt(0).toUpperCase()}</div>
          }
        </div>
        <label style={{ cursor:'pointer', fontSize:12, color:'var(--accent-bright)', fontWeight:600, padding:'6px 14px', borderRadius:999, background:'var(--accent-dim)', border:'1px solid var(--border-strong)' }}>
          {hasPhoto ? 'Cambiar foto' : 'Subir foto'}
          <input type="file" accept="image/*" style={{ display:'none' }} onChange={e => {
            const file = e.target.files?.[0];
            if (!file) return;
            const reader = new FileReader();
            reader.onload = ev => { if (onProfileChange) onProfileChange(ev.target.result); };
            reader.readAsDataURL(file);
          }} />
        </label>
        {hasPhoto && <div style={{ fontSize:11, color:'var(--text-3)' }}>Arrastrá para reencuadrar</div>}
      </div>

      {/* Name */}
      <div>
        <div style={{ fontSize:10.5, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600, marginBottom:8 }}>Nombre</div>
        {editingName ? (
          <div style={{ display:'flex', gap:8 }}>
            <input
              value={nameInput}
              onChange={e => setNameInput(e.target.value)}
              autoFocus
              onKeyDown={e => {
                if (e.key === 'Enter') { if (onUserNameChange) onUserNameChange(nameInput.trim() || userName); setEditingName(false); }
                if (e.key === 'Escape') setEditingName(false);
              }}
              style={{ flex:1, padding:'10px 12px', borderRadius:10, background:'rgba(255,255,255,0.05)', border:'1px solid var(--accent)', color:'var(--text)', fontFamily:'inherit', fontSize:14, outline:'none' }}
            />
            <button onClick={() => { if (onUserNameChange) onUserNameChange(nameInput.trim() || userName); setEditingName(false); }} style={{ padding:'10px 16px', borderRadius:10, background:'var(--accent)', color:'var(--on-accent)', border:'none', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600 }}>OK</button>
          </div>
        ) : (
          <button onClick={() => { setNameInput(userName || ''); setEditingName(true); }} style={{ width:'100%', padding:'11px 14px', borderRadius:10, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border)', color:'var(--text)', fontFamily:'inherit', fontSize:14, textAlign:'left', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
            <span>{userName || 'Sin nombre'}</span>
            <Icon2 name="settings" size={14} style={{ color:'var(--text-3)' }} />
          </button>
        )}
      </div>
    </div>
  );
}

// ─── Apariencia Tab ────────────────────────────────────────────────────────────
function AparienciaTab({ onToast }) {
  const [theme, setTheme] = useState2(() => document.documentElement.getAttribute('data-theme') || 'dark');
  const [accent, setAccent] = useState2(() => document.documentElement.getAttribute('data-accent') || 'violet');

  function applyTheme(t) {
    setTheme(t);
    if (t === 'light') {
      document.documentElement.setAttribute('data-theme', 'light');
    } else {
      document.documentElement.removeAttribute('data-theme');
    }
    localStorage.setItem('sisyphus.v1.theme', t);
    if (onToast) onToast('Tema actualizado');
  }

  const themes = [
    { id:'dark',  label:'Oscuro',  icon:'🌑', desc:'El original — fondo negro profundo' },
    { id:'light', label:'Claro',   icon:'☀️',  desc:'Fondo lavanda suave' },
  ];

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
      <div style={{ fontSize:11, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.12em', fontWeight:600 }}>Tema de color</div>
      {themes.map(t => (
        <div key={t.id} onClick={() => applyTheme(t.id)} style={{
          display:'flex', alignItems:'center', gap:14, padding:'16px 18px', borderRadius:14, cursor:'pointer',
          background: theme===t.id ? 'var(--accent-dim)' : 'rgba(255,255,255,0.03)',
          border:`1px solid ${theme===t.id ? 'var(--border-strong)' : 'var(--border)'}`,
          transition:'all 0.15s',
        }}>
          <div style={{ fontSize:28, lineHeight:1 }}>{t.icon}</div>
          <div style={{ flex:1 }}>
            <div style={{ fontSize:14, fontWeight:600, color: theme===t.id ? 'var(--accent-bright)' : 'var(--text)' }}>{t.label}</div>
            <div style={{ fontSize:12, color:'var(--text-3)', marginTop:3 }}>{t.desc}</div>
          </div>
          <div style={{ width:20, height:20, borderRadius:'50%', border:`2px solid ${theme===t.id ? 'var(--accent)' : 'rgba(255,255,255,0.2)'}`, background: theme===t.id ? 'var(--accent)' : 'transparent', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
            {theme===t.id && <Icon2 name="check" size={11} strokeWidth={3} />}
          </div>
        </div>
      ))}
      <div style={{ marginTop:8, padding:'14px 16px', borderRadius:12, background:'rgba(167,139,250,0.07)', border:'1px solid var(--border)', fontSize:12.5, color:'var(--text-3)', lineHeight:1.6 }}>
        El tema se guarda automáticamente y se aplica al recargar la página.
      </div>
    </div>
  );
}


// ─── Gmail Tab ─────────────────────────────────────────────────────────────────
function GmailTabInline({ onToast }) {
  const [clientIdInput, setClientIdInput] = useState2('');
  const [saved, setSaved] = useState2(false);

  const existing = localStorage.getItem('sisyphus.v1.gmail_client_id') || '';

  function handleSave() {
    const id = clientIdInput.trim();
    if (!id) return;
    localStorage.setItem('sisyphus.v1.gmail_client_id', id);
    setSaved(true);
    if (onToast) onToast('Client ID guardado');
  }

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
      <div style={{ padding:'14px 16px', borderRadius:12, background:'rgba(66,133,244,0.07)', border:'1px solid rgba(66,133,244,0.2)' }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:10 }}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M20 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V6a2 2 0 00-2-2z" stroke="#4285f4" strokeWidth="1.6" strokeLinecap="round"/><path d="M2 6l10 7 10-7" stroke="#4285f4" strokeWidth="1.6" strokeLinecap="round"/></svg>
          <div style={{ fontSize:14, fontWeight:600 }}>Conectar Gmail</div>
        </div>
        <div style={{ fontSize:12, color:'var(--text-3)', lineHeight:1.6 }}>
          Importa transacciones bancarias automáticamente desde tus correos.
          Necesitás un Google Cloud OAuth Client ID.
        </div>
      </div>
      {existing && (
        <div style={{ padding:'10px 14px', borderRadius:10, background:'rgba(74,222,128,0.07)', border:'1px solid rgba(74,222,128,0.2)', fontSize:12, color:'#4ade80' }}>
          ✓ Client ID configurado
        </div>
      )}
      <div>
        <div style={{ fontSize:11, color:'var(--text-3)', marginBottom:6, textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:600 }}>OAuth Client ID</div>
        <input
          type="text"
          placeholder="xxxxxx.apps.googleusercontent.com"
          defaultValue={existing}
          onChange={e => setClientIdInput(e.target.value)}
          style={{ width:'100%', padding:'11px 14px', borderRadius:10, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'monospace', fontSize:12, outline:'none', boxSizing:'border-box' }}
        />
      </div>
      <button
        onClick={handleSave}
        style={{ padding:'11px 0', borderRadius:10, background:'var(--accent)', color:'var(--on-accent)', border:'none', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600 }}
      >
        {saved ? '✓ Guardado' : 'Guardar Client ID'}
      </button>
    </div>
  );
}


// ─── HistorialTab ─────────────────────────────────────────────────────────────
function HistorialTab({ ccy }) {
  const fmt = n => S2.fmtMoney(ccy === 'USD' ? n / seed2.fxBlue : n, ccy);
  let history = [];
  try { history = JSON.parse(localStorage.getItem('sis_month_history') || '[]'); } catch {}
  const months = [...history].reverse(); // newest first

  if (months.length === 0) {
    return (
      <Card2 padding={32} style={{ textAlign:'center' }}>
        <div style={{ width:52, height:52, borderRadius:16, background:'var(--accent-dim)', display:'flex', alignItems:'center', justifyContent:'center', margin:'0 auto 12px', color:'var(--accent-bright)' }}>
          <Icon2 name="calendar" size={22} strokeWidth={1.6} />
        </div>
        <div style={{ fontSize:14, fontWeight:500, color:'var(--text-2)' }}>Sin meses cerrados aún</div>
        <div style={{ fontSize:12, color:'var(--text-3)', marginTop:4 }}>El historial aparece acá después de tu primer cierre de mes.</div>
      </Card2>
    );
  }

  const maxEgr = Math.max(...months.map(m => m.egrTotal || 0), 1);

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
      {/* Trend bar chart */}
      <Card2 padding={16}>
        <div style={{ fontSize:12, fontWeight:600, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', marginBottom:14 }}>Egresos — últimos {months.length} meses</div>
        <div style={{ display:'flex', alignItems:'flex-end', gap:6, height:64 }}>
          {[...months].reverse().slice(-12).map((m, i) => {
            const pct = (m.egrTotal || 0) / maxEgr;
            const overIncome = m.neto < 0;
            return (
              <div key={i} style={{ flex:1, display:'flex', flexDirection:'column', alignItems:'center', gap:4 }}>
                <div style={{ width:'100%', background: overIncome ? 'rgba(248,113,113,0.25)' : 'rgba(167,139,250,0.2)', borderRadius:4, height:Math.round(pct * 56) || 3, minHeight:3, transition:'height 0.4s' }} />
                <div style={{ fontSize:9, color:'var(--text-3)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis', maxWidth:32, textAlign:'center' }}>
                  {(m.monthName || '').slice(0,3)}
                </div>
              </div>
            );
          })}
        </div>
      </Card2>

      {/* Month cards */}
      {months.map((m, i) => {
        const positive = m.neto >= 0;
        const savingsRate = m.ingTotal > 0 ? Math.round((m.ahoTotal / m.ingTotal) * 100) : 0;
        return (
          <Card2 key={i} padding={14}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10 }}>
              <div>
                <div style={{ fontSize:14, fontWeight:600 }}>{m.monthName || 'Mes cerrado'}</div>
                {m.closedAt && <div style={{ fontSize:11, color:'var(--text-3)', marginTop:2 }}>Cerrado el {new Date(m.closedAt).toLocaleDateString('es-AR', { day:'numeric', month:'short' })}</div>}
              </div>
              <div style={{ textAlign:'right' }}>
                <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:16, fontWeight:700, fontVariantNumeric:'tabular-nums', color: positive ? 'var(--text)' : 'var(--red)' }}>
                  <span style={{ color: positive ? '#4ade80' : 'var(--red)', marginRight:2 }}>$</span>
                  {new Intl.NumberFormat('es-AR').format(Math.abs(Math.round(m.neto || 0)))}
                </div>
                <div style={{ fontSize:10.5, color:'var(--text-3)', marginTop:1 }}>{positive ? 'neto positivo' : 'neto negativo'}</div>
              </div>
            </div>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:8 }}>
              {[
                { l:'Ingresos', v: m.ingTotal, color:'var(--accent-bright)' },
                { l:'Egresos',  v: m.egrTotal, color:'var(--red)' },
                { l:'Ahorro',   v: m.ahoTotal, color:'#4ade80' },
              ].map(k => (
                <div key={k.l} style={{ padding:'8px 10px', borderRadius:9, background:'rgba(255,255,255,0.03)', border:'1px solid var(--border)' }}>
                  <div style={{ fontSize:10, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.08em', marginBottom:4 }}>{k.l}</div>
                  <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize:13, fontWeight:600, fontVariantNumeric:'tabular-nums', color:'var(--text)' }}>
                    <span style={{ color:k.color, marginRight:1 }}>$</span>
                    {new Intl.NumberFormat('es-AR').format(Math.round(Math.abs(k.v || 0)))}
                  </div>
                </div>
              ))}
            </div>
            {savingsRate > 0 && (
              <div style={{ marginTop:8, fontSize:11.5, color:'var(--text-3)' }}>
                Tasa de ahorro: <strong style={{ color: savingsRate >= 20 ? '#4ade80' : 'var(--amber)' }}>{savingsRate}%</strong>
              </div>
            )}
          </Card2>
        );
      })}
    </div>
  );
}

// ─── DatosTab ─────────────────────────────────────────────────────────────────
const CF_URL_KEY   = 'sis.cf_worker_url';
const CF_TOKEN_KEY = 'sis.cf_token';

function DatosTab({ onToast }) {
  const [importing,  setImporting]  = useState2(false);
  const [cfSyncing,  setCfSyncing]  = useState2(false);
  const [cfStatus,   setCfStatus]   = useState2('');
  const [cfUrl,      setCfUrl]      = useState2(() => localStorage.getItem(CF_URL_KEY) || '');
  const [cfToken,    setCfToken]    = useState2(() => localStorage.getItem(CF_TOKEN_KEY) || '');
  const [showCfConfig, setShowCfConfig] = useState2(false);

  const notifPerm = window.SisNotif?.getPermission?.() || 'unsupported';
  const [, forceNotif] = useState2(0);

  const lastSync = localStorage.getItem('sis.cf_last_sync');
  const cfReady  = cfUrl.trim() && cfToken.trim();

  function saveCfConfig() {
    localStorage.setItem(CF_URL_KEY,   cfUrl.trim());
    localStorage.setItem(CF_TOKEN_KEY, cfToken.trim());
    setShowCfConfig(false);
    onToast('Configuración guardada ✓');
  }

  function buildBackup() {
    const NS = 'sisyphus.v1.';
    const data = { _savedAt: new Date().toISOString(), _version: '1.0' };
    for (let i = 0; i < localStorage.length; i++) {
      const k = localStorage.key(i);
      if (k && (k.startsWith(NS) || k.startsWith('sis.'))) {
        try { data[k] = JSON.parse(localStorage.getItem(k)); } catch { data[k] = localStorage.getItem(k); }
      }
    }
    return JSON.stringify(data, null, 2);
  }

  async function handleCfSave() {
    if (!cfReady) { setShowCfConfig(true); return; }
    setCfSyncing(true); setCfStatus('');
    try {
      const body = buildBackup();
      const r = await fetch(cfUrl.trim().replace(/\/$/, '') + '/sync', {
        method: 'PUT',
        headers: { 'Authorization': 'Bearer ' + cfToken.trim(), 'Content-Type': 'application/json' },
        body,
      });
      if (!r.ok) throw new Error('HTTP ' + r.status);
      const res = await r.json();
      const ts  = new Date(res.savedAt).toLocaleString('es-AR', { day:'numeric', month:'short', hour:'2-digit', minute:'2-digit' });
      localStorage.setItem('sis.cf_last_sync', res.savedAt);
      setCfStatus('✓ Guardado · ' + ts);
      onToast('Sync guardado en Cloudflare ✓');
    } catch(e) {
      setCfStatus('Error: ' + e.message);
      onToast('Error al sincronizar — ' + e.message);
    } finally { setCfSyncing(false); }
  }

  async function handleCfRestore() {
    if (!cfReady) { setShowCfConfig(true); return; }
    if (!confirm('¿Restaurar datos desde Cloudflare? Se sobreescribirán los datos actuales.')) return;
    setCfSyncing(true); setCfStatus('');
    try {
      const r = await fetch(cfUrl.trim().replace(/\/$/, '') + '/sync', {
        headers: { 'Authorization': 'Bearer ' + cfToken.trim() },
      });
      if (r.status === 404) throw new Error('sin_backup');
      if (!r.ok) throw new Error('HTTP ' + r.status);
      const raw  = await r.text();
      const data = JSON.parse(raw);
      Object.entries(data).forEach(([k, v]) => {
        if (k.startsWith('sisyphus.v1.') || k.startsWith('sis.')) {
          localStorage.setItem(k, typeof v === 'string' ? v : JSON.stringify(v));
        }
      });
      setCfStatus('✓ Restaurado · ' + (data._savedAt ? new Date(data._savedAt).toLocaleString('es-AR') : ''));
      onToast('Restaurado ✓ — recargando...');
      setTimeout(() => window.location.reload(), 1000);
    } catch(e) {
      if (e.message === 'sin_backup') { setCfStatus('Sin backup previo en Cloudflare'); onToast('No encontré backup en Cloudflare'); }
      else { setCfStatus('Error: ' + e.message); onToast('Error al restaurar'); }
    } finally { setCfSyncing(false); }
  }

  const btn = (accent, disabled) => ({
    flex:1, padding:'10px 0', borderRadius:10, cursor: disabled ? 'default' : 'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600,
    background: accent ? (disabled ? 'var(--accent-dim)' : 'var(--accent)') : 'rgba(255,255,255,0.05)',
    color: accent ? (disabled ? 'var(--text-3)' : 'var(--on-accent)') : 'var(--text-2)',
    border: accent ? 'none' : '1px solid var(--border)',
    opacity: disabled ? 0.6 : 1, transition:'opacity 0.14s',
    display:'flex', alignItems:'center', justifyContent:'center', gap:7,
  });

  const fieldStyle = { width:'100%', padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'inherit', fontSize:13, outline:'none', boxSizing:'border-box' };

  const NS = 'sisyphus.v1.';
  const [syncToken, setSyncToken] = useState2(() => localStorage.getItem(NS + 'auth_token') || '');
  const [syncSaved, setSyncSaved] = useState2(false);

  function saveSyncToken() {
    const t = syncToken.trim();
    if (!t) return;
    localStorage.setItem(NS + 'auth_token', t);
    setSyncSaved(true);
    onToast('Token guardado — sincronizando...');
    window.SisyStorage?.schedulePush?.();
    setTimeout(() => setSyncSaved(false), 2000);
  }

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>

      {/* Token de sync */}
      <Card2 padding={14}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:10 }}>
          <div style={{ width:34, height:34, borderRadius:10, background:'rgba(99,102,241,0.15)', display:'flex', alignItems:'center', justifyContent:'center', color:'var(--accent-bright)', flexShrink:0 }}>
            <Icon2 name="key" size={15} />
          </div>
          <div>
            <div style={{ fontSize:13, fontWeight:600 }}>Token de sincronización</div>
            <div style={{ fontSize:11.5, color:'var(--text-3)', marginTop:1 }}>
              {syncToken ? '● Configurado' : 'Ingresá tu token para sincronizar entre dispositivos'}
            </div>
          </div>
        </div>
        <div style={{ display:'flex', gap:8 }}>
          <input
            value={syncToken}
            onChange={e => setSyncToken(e.target.value)}
            type="password"
            placeholder="sisyphus-finance-pri-2026"
            style={{ flex:1, padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'inherit', fontSize:13, outline:'none' }}
          />
          <button onClick={saveSyncToken} style={{ padding:'9px 16px', borderRadius:9, background: syncSaved ? 'rgba(74,222,128,0.2)' : 'var(--accent-dim)', border:'1px solid var(--border-strong)', color: syncSaved ? '#4ade80' : 'var(--accent-bright)', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:700, whiteSpace:'nowrap' }}>
            {syncSaved ? '✓ Listo' : 'Guardar'}
          </button>
        </div>
      </Card2>

      {/* Notificaciones */}
      {notifPerm !== 'unsupported' && (
        <Card2 padding={14}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
            <div>
              <div style={{ fontSize:13, fontWeight:600 }}>Notificaciones</div>
              <div style={{ fontSize:11.5, color:'var(--text-3)', marginTop:2 }}>
                {notifPerm === 'granted' ? '✓ Activadas' : 'Alertas de pagos por vencer'}
              </div>
            </div>
            {notifPerm !== 'granted' && (
              <button onClick={async () => { await window.SisNotif.requestPermission(); forceNotif(n => n+1); onToast('Notificaciones activadas ✓'); }}
                style={{ padding:'7px 14px', borderRadius:9, background:'var(--accent-dim)', border:'1px solid var(--border-strong)', color:'var(--accent-bright)', cursor:'pointer', fontFamily:'inherit', fontSize:12.5, fontWeight:600 }}>
                Activar
              </button>
            )}
          </div>
        </Card2>
      )}

      {/* Cloudflare Sync — la estrella del show */}
      <Card2 padding={16} style={{ borderColor: cfReady ? 'rgba(249,115,22,0.35)' : 'var(--border)', background: cfReady ? 'rgba(249,115,22,0.04)' : undefined }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:12 }}>
          <div style={{ width:36, height:36, borderRadius:10, background:'rgba(249,115,22,0.15)', display:'flex', alignItems:'center', justifyContent:'center', color:'#fb923c', flexShrink:0 }}>
            <Icon2 name="swap" size={16} />
          </div>
          <div style={{ flex:1 }}>
            <div style={{ fontSize:13.5, fontWeight:600 }}>Cloudflare Sync</div>
            <div style={{ fontSize:11.5, color:'var(--text-3)', marginTop:1 }}>
              {cfReady
                ? (lastSync ? `Último sync: ${new Date(lastSync).toLocaleString('es-AR', { day:'numeric', month:'short', hour:'2-digit', minute:'2-digit' })}` : 'Listo · sin sync previo')
                : 'Configurá tu Worker URL y token para activar'
              }
            </div>
          </div>
          <button onClick={() => setShowCfConfig(s => !s)} style={{ padding:'5px 10px', borderRadius:7, background:'transparent', border:'1px solid var(--border)', color:'var(--text-3)', cursor:'pointer', fontFamily:'inherit', fontSize:11.5 }}>
            {showCfConfig ? 'Cerrar' : 'Configurar'}
          </button>
        </div>

        {/* Config fields */}
        {showCfConfig && (
          <div style={{ marginBottom:12, display:'flex', flexDirection:'column', gap:8, animation:'fadeSlide 0.15s ease' }}>
            <div>
              <div style={{ fontSize:10.5, color:'var(--text-3)', marginBottom:4 }}>Worker URL (ej: https://sisyphus.pages.dev)</div>
              <input value={cfUrl} onChange={e => setCfUrl(e.target.value)} placeholder="https://tu-app.pages.dev" style={fieldStyle}
                onFocus={e => e.target.style.borderColor='var(--accent)'} onBlur={e => e.target.style.borderColor='var(--border-strong)'} />
            </div>
            <div>
              <div style={{ fontSize:10.5, color:'var(--text-3)', marginBottom:4 }}>Token secreto (AUTH_TOKEN de Cloudflare)</div>
              <input value={cfToken} onChange={e => setCfToken(e.target.value)} type="password" placeholder="tu-token-secreto" style={fieldStyle}
                onFocus={e => e.target.style.borderColor='var(--accent)'} onBlur={e => e.target.style.borderColor='var(--border-strong)'} />
            </div>
            <button onClick={saveCfConfig} style={{ padding:'9px 0', borderRadius:9, background:'var(--accent)', color:'var(--on-accent)', border:'none', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600 }}>
              Guardar configuración
            </button>
          </div>
        )}

        {cfStatus && (
          <div style={{ marginBottom:10, padding:'7px 10px', borderRadius:8, background:'rgba(255,255,255,0.04)', fontSize:12, color: cfStatus.startsWith('✓') ? '#4ade80' : 'var(--red)' }}>{cfStatus}</div>
        )}

        <div style={{ display:'flex', gap:8 }}>
          <button onClick={handleCfSave} disabled={cfSyncing} style={btn(true, cfSyncing)}>
            {cfSyncing ? 'Guardando...' : <><Icon2 name="arrowUp" size={13} /> Guardar sync</>}
          </button>
          <button onClick={handleCfRestore} disabled={cfSyncing} style={btn(false, cfSyncing)}>
            <Icon2 name="arrowDown" size={13} /> Restaurar
          </button>
        </div>
      </Card2>

      {/* Export */}
      <Card2 padding={14}>
        <div style={{ fontSize:11.5, fontWeight:700, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', marginBottom:10 }}>Exportar</div>
        <div style={{ display:'flex', gap:8 }}>
          <button onClick={() => { window.SisExport?.csv(); onToast('CSV descargado ✓'); }}
            style={{ flex:1, padding:'9px 0', borderRadius:9, background:'rgba(255,255,255,0.05)', border:'1px solid var(--border)', color:'var(--text-2)', cursor:'pointer', fontFamily:'inherit', fontSize:12.5, fontWeight:600, display:'flex', alignItems:'center', justifyContent:'center', gap:6 }}>
            <Icon2 name="arrowDown" size={13} /> CSV
          </button>
          <button onClick={() => { window.SisExport?.backup(); onToast('Backup descargado ✓'); }}
            style={{ flex:1, padding:'9px 0', borderRadius:9, background:'rgba(255,255,255,0.05)', border:'1px solid var(--border)', color:'var(--text-2)', cursor:'pointer', fontFamily:'inherit', fontSize:12.5, fontWeight:600, display:'flex', alignItems:'center', justifyContent:'center', gap:6 }}>
            <Icon2 name="shield" size={13} /> Backup JSON
          </button>
        </div>
      </Card2>

      {/* Import */}
      <Card2 padding={14}>
        <div style={{ fontSize:11.5, fontWeight:700, color:'var(--text-3)', textTransform:'uppercase', letterSpacing:'0.1em', marginBottom:10 }}>Importar backup</div>
        <label style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:7, padding:'10px 0', borderRadius:9, cursor:'pointer', fontFamily:'inherit', fontSize:12.5, fontWeight:600, background:'rgba(255,255,255,0.04)', border:'1px dashed rgba(167,139,250,0.3)', color:'var(--accent-bright)', transition:'background 0.14s' }}>
          <input type="file" accept=".json" style={{ display:'none' }} onChange={e => {
            const f = e.target.files?.[0]; if (!f) return;
            setImporting(true);
            window.SisExport?.restore(f, err => { setImporting(false); onToast(err ? 'JSON inválido' : 'Restaurando...'); });
            e.target.value = '';
          }} />
          <Icon2 name="arrowDown" size={13} /> {importing ? 'Importando...' : 'Seleccionar .json'}
        </label>
        <div style={{ marginTop:6, fontSize:11, color:'var(--red)', opacity:0.7 }}>⚠ Sobreescribe todos los datos actuales.</div>
      </Card2>
    </div>
  );
}

// ─── MetasTab ─────────────────────────────────────────────────────────────────
function MetasTab({ metas = [], onAddMeta, onUpdateMeta, onDeleteMeta, ccy }) {
  const fmt = n => S2.fmtMoney(ccy === 'USD' ? n / seed2.fxBlue : n, ccy);
  const [showNew, setShowNew] = useState2(false);
  const [editId,  setEditId]  = useState2(null);
  const [nombre,  setNombre]  = useState2('');
  const [objetivo,setObjetivo]= useState2('');
  const [actual,  setActual]  = useState2('');
  const [color,   setColor]   = useState2('#8b5cf6');
  const [icono,   setIcono]   = useState2('star');
  const [fecha,   setFecha]   = useState2('');

  const ICONS  = ['star','shield','heart','dollar','trend','gift','home','bolt','bag','laptop','pie','wallet'];
  const COLORS = ['#8b5cf6','#818cf8','#38bdf8','#4ade80','#fbbf24','#f87171','#f472b6','#34d399','#fb923c'];

  function resetForm() { setNombre(''); setObjetivo(''); setActual(''); setColor('#8b5cf6'); setIcono('star'); setFecha(''); setShowNew(false); setEditId(null); }

  function handleSave() {
    const obj = parseInt((objetivo||'0').replace(/\./g,'')) || 0;
    const act = parseInt((actual||'0').replace(/\./g,'')) || 0;
    if (!nombre.trim() || obj <= 0) return;
    const data = { nombre: nombre.trim(), objetivo: obj, actual: act, color, icono, fechaLimite: fecha };
    if (editId) { onUpdateMeta(editId, data); }
    else { onAddMeta(data); }
    resetForm();
  }

  function startEdit(m) {
    setNombre(m.nombre); setObjetivo(String(m.objetivo)); setActual(String(m.actual || 0));
    setColor(m.color || '#8b5cf6'); setIcono(m.icono || 'star'); setFecha(m.fechaLimite || '');
    setEditId(m.id); setShowNew(true);
  }

  const inputStyle = { width:'100%', padding:'9px 12px', borderRadius:9, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border-strong)', color:'var(--text)', fontFamily:'inherit', fontSize:13, outline:'none', boxSizing:'border-box' };

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
      {metas.map(m => {
        const pct = m.objetivo > 0 ? Math.min(m.actual / m.objetivo, 1) : 0;
        const daysLeft = m.fechaLimite ? Math.ceil((new Date(m.fechaLimite) - new Date()) / 86400000) : null;
        const done = pct >= 1;
        return (
          <Card2 key={m.id} padding={14}>
            <div style={{ display:'flex', alignItems:'center', gap:12, marginBottom:10 }}>
              <div style={{ width:40, height:40, borderRadius:11, background:(m.color||'#8b5cf6')+'22', color:m.color||'#8b5cf6', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
                <Icon2 name={m.icono||'star'} size={18} strokeWidth={1.8} />
              </div>
              <div style={{ flex:1 }}>
                <div style={{ fontSize:14, fontWeight:600 }}>{m.nombre}</div>
                <div style={{ fontSize:11.5, color:'var(--text-3)', marginTop:2 }}>
                  {fmt(m.actual || 0)} de {fmt(m.objetivo)}
                  {daysLeft !== null && daysLeft > 0 && <span style={{ marginLeft:8 }}>· {daysLeft}d restantes</span>}
                  {daysLeft !== null && daysLeft <= 0 && <span style={{ marginLeft:8, color:'var(--red)' }}>· Fecha límite alcanzada</span>}
                </div>
              </div>
              <div style={{ display:'flex', gap:4 }}>
                <button onClick={() => startEdit(m)} style={{ width:26, height:26, borderRadius:7, background:'transparent', border:'none', color:'var(--text-3)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center' }}>
                  <Icon2 name="settings" size={12} />
                </button>
                <button onClick={() => onDeleteMeta(m.id)} style={{ width:26, height:26, borderRadius:7, background:'transparent', border:'none', color:'var(--text-3)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center' }}
                  onMouseEnter={e => e.currentTarget.style.color='var(--red)'} onMouseLeave={e => e.currentTarget.style.color='var(--text-3)'}>
                  <Icon2 name="x" size={12} />
                </button>
              </div>
            </div>
            <div style={{ height:8, background:'rgba(255,255,255,0.06)', borderRadius:999, overflow:'hidden' }}>
              <div style={{ height:'100%', width:`${pct*100}%`, background: done ? '#4ade80' : (m.color||'var(--accent-bright)'), borderRadius:999, transition:'width 0.5s' }} />
            </div>
            <div style={{ display:'flex', justifyContent:'space-between', marginTop:5, fontSize:11, color:'var(--text-3)' }}>
              <span>{Math.round(pct*100)}% completado</span>
              {done && <span style={{ color:'#4ade80', fontWeight:600 }}>✓ Meta alcanzada</span>}
            </div>
          </Card2>
        );
      })}

      {/* New/edit form */}
      {showNew ? (
        <Card2 padding={14} style={{ animation:'fadeSlide 0.15s ease' }}>
          <div style={{ fontSize:12, fontWeight:700, color:'var(--accent-bright)', textTransform:'uppercase', letterSpacing:'0.1em', marginBottom:12 }}>{editId ? 'Editar meta' : 'Nueva meta'}</div>
          <input placeholder="Nombre de la meta" value={nombre} onChange={e=>setNombre(e.target.value)} style={{...inputStyle, marginBottom:8}} />
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:8, marginBottom:8 }}>
            <div>
              <div style={{ fontSize:10.5, color:'var(--text-3)', marginBottom:4 }}>Objetivo $</div>
              <input type="text" inputMode="numeric" placeholder="500000" value={objetivo} onChange={e=>setObjetivo(e.target.value)} style={inputStyle} />
            </div>
            <div>
              <div style={{ fontSize:10.5, color:'var(--text-3)', marginBottom:4 }}>Actual $</div>
              <input type="text" inputMode="numeric" placeholder="0" value={actual} onChange={e=>setActual(e.target.value)} style={inputStyle} />
            </div>
          </div>
          <div style={{ marginBottom:8 }}>
            <div style={{ fontSize:10.5, color:'var(--text-3)', marginBottom:4 }}>Fecha límite (opcional)</div>
            <input type="date" value={fecha} onChange={e=>setFecha(e.target.value)} style={{...inputStyle, colorScheme:'dark'}} />
          </div>
          <div style={{ marginBottom:8 }}>
            <div style={{ fontSize:10.5, color:'var(--text-3)', marginBottom:6 }}>Color</div>
            <div style={{ display:'flex', gap:6 }}>
              {COLORS.map(c => <button key={c} onClick={()=>setColor(c)} style={{ width:22, height:22, borderRadius:'50%', background:c, border:`2px solid ${color===c?'white':'transparent'}`, cursor:'pointer' }} />)}
            </div>
          </div>
          <div style={{ marginBottom:12 }}>
            <div style={{ fontSize:10.5, color:'var(--text-3)', marginBottom:6 }}>Ícono</div>
            <div style={{ display:'flex', gap:5, flexWrap:'wrap' }}>
              {ICONS.map(ic => <button key={ic} onClick={()=>setIcono(ic)} style={{ width:32, height:32, borderRadius:8, background: icono===ic ? color+'28' : 'rgba(255,255,255,0.04)', border:`1px solid ${icono===ic ? color+'66' : 'var(--border)'}`, color: icono===ic ? color : 'var(--text-3)', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center' }}><Icon2 name={ic} size={14} /></button>)}
            </div>
          </div>
          <div style={{ display:'flex', gap:8 }}>
            <button onClick={resetForm} style={{ flex:1, padding:'9px 0', borderRadius:9, background:'transparent', border:'1px solid var(--border)', color:'var(--text-3)', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600 }}>Cancelar</button>
            <button onClick={handleSave} disabled={!nombre.trim()} style={{ flex:2, padding:'9px 0', borderRadius:9, background:'var(--accent)', color:'var(--on-accent)', border:'none', cursor:'pointer', fontFamily:'inherit', fontSize:13, fontWeight:600 }}>Guardar</button>
          </div>
        </Card2>
      ) : (
        <button onClick={() => setShowNew(true)} style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:8, padding:'11px 0', borderRadius:12, background:'transparent', border:'1px dashed rgba(167,139,250,0.3)', color:'var(--accent-bright)', fontFamily:'inherit', fontSize:13, fontWeight:600, cursor:'pointer' }}
          onMouseEnter={e=>{e.currentTarget.style.background='var(--accent-dim)';e.currentTarget.style.borderColor='var(--border-strong)';}}
          onMouseLeave={e=>{e.currentTarget.style.background='transparent';e.currentTarget.style.borderColor='rgba(167,139,250,0.3)';}}>
          <Icon2 name="plus" size={14} strokeWidth={2.5} /> Nueva meta de ahorro
        </button>
      )}
    </div>
  );
}

// ─── ConfigScreen ─────────────────────────────────────────────────────────────
function ConfigScreen({ ccy, isDesktop, budgets, onBudgetsChange, profilePhoto, onProfileChange, onToast, spentState, userName, onUserNameChange, photoPos, onPhotoPosChange, extraIngresos, onExtraIngresosChange, sueldo, onSueldoChange, sueldoDia, onSueldoDiaChange, metas, onAddMeta, onUpdateMeta, onDeleteMeta, movimientos }) {
  const [tab, setTab] = useState2('perfil');

  const tabs = [
    { id:'perfil',       label:'Perfil' },
    { id:'presupuestos', label:'Presupuestos' },
    { id:'metas',        label:'Metas' },
    { id:'historial',    label:'Historial' },
    { id:'datos',        label:'Datos' },
    { id:'gmail',        label:'Gmail' },
  ];

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16, padding: isDesktop ? '20px 28px 44px' : 'var(--sp) var(--sp) var(--sp-bottom)', maxWidth: isDesktop ? 700 : undefined, margin: isDesktop ? '0 auto' : undefined, width:'100%' }}>
      <div>
        <div style={{ fontFamily:'Space Grotesk, sans-serif', fontSize: isDesktop ? 22 : 26, fontWeight:600, letterSpacing:'-0.02em', marginBottom:4 }}>Configuración</div>
        <div style={{ fontSize:12.5, color:'var(--text-3)' }}>Perfil, presupuestos y sincronización</div>
      </div>

      <div style={{ display:'flex', padding:4, background:'var(--card)', border:'1px solid var(--border)', borderRadius:12, gap:2 }}>
        {tabs.map(t => (
          <button key={t.id} onClick={() => setTab(t.id)} style={{
            flex:1, padding:'9px 0', borderRadius:9,
            background: tab===t.id ? 'var(--accent-dim)' : 'transparent',
            color: tab===t.id ? 'var(--accent-bright)' : 'var(--text-2)',
            border:'none', cursor:'pointer', fontFamily:'inherit',
            fontSize:12.5, fontWeight:600,
            transition:'background 0.14s, color 0.14s',
          }}>{t.label}</button>
        ))}
      </div>

      {tab === 'perfil'       && <PerfilTab profilePhoto={profilePhoto} onProfileChange={onProfileChange} onToast={onToast} userName={userName} onUserNameChange={onUserNameChange} photoPos={photoPos} onPhotoPosChange={onPhotoPosChange} />}
      {tab === 'presupuestos' && <SlidersPane ccy={ccy} spentState={spentState} budgets={budgets} onBudgetsChange={onBudgetsChange} extraIngresos={extraIngresos} onExtraIngresosChange={onExtraIngresosChange} sueldo={sueldo} onSueldoChange={onSueldoChange} sueldoDia={sueldoDia} onSueldoDiaChange={onSueldoDiaChange} />}
      {tab === 'metas'        && <MetasTab metas={metas||[]} onAddMeta={onAddMeta} onUpdateMeta={onUpdateMeta} onDeleteMeta={onDeleteMeta} ccy={ccy} />}
      {tab === 'historial'    && <HistorialTab ccy={ccy} />}
      {tab === 'datos'        && <DatosTab onToast={onToast} movimientos={movimientos} />}
      {tab === 'gmail'        && <GmailTabInline onToast={onToast} />}
    </div>
  );
}

Object.assign(window, { AnalisisScreen, MasScreen, ConfigScreen, FXPane, BandejaItem, DonutPane, TrendPane, SlidersPane });
window.BandejaItem = BandejaItem;
