// ─── Dashboard Finanzas — customizable, paralelo al Dashboard operativo ────

const LS_FIN_KEY = 'lanven.dashboard.finanzas.layout.v1';

// ── Widgets financieros ───────────────────────────────────────────────────
// Reusa <KPI> y <Spark> de widgets.jsx para mantener consistencia visual.

function FIN_curVal(k, cur, formatter = true) {
  const v = cur === 'ARS' ? k.ars : k.usd;
  return formatter ? (cur === 'ARS' ? ARS_C(v) : USD_C(v)) : (cur === 'ARS' ? ARS(v) : USD(v));
}

// Composición de gastos por área
function GastosPorArea() {
  const m = {};
  GASTOS.forEach(g => {
    const v = g.moneda === 'ARS' ? g.monto : g.monto * 1180;
    m[g.area] = (m[g.area] || 0) + v;
  });
  const total = Object.values(m).reduce((s, v) => s + v, 0) || 1;
  const rows = Object.entries(m).map(([k, v]) => ({ k, v, p: v / total })).sort((a, b) => b.v - a.v);
  return (
    <ul className="space-y-2.5">
      {rows.map(r => {
        const color = (window.AREA_COLORS || {})[r.k] || '#677A88';
        return (
          <li key={r.k}>
            <div className="flex items-center justify-between text-[12px] mb-1">
              <span className="inline-flex items-center gap-2"><span className="w-1.5 h-1.5 rounded-full" style={{ background: color }} /><span className="text-slate-700">{r.k}</span></span>
              <span className="font-mono text-slate-700">{ARS_C(r.v)} <span className="text-[10px] text-slate-400">· {Math.round(r.p*100)}%</span></span>
            </div>
            <div className="h-1.5 bg-slate-50 rounded-full overflow-hidden">
              <div className="h-full rounded-full" style={{ width: `${r.p * 100}%`, background: color }} />
            </div>
          </li>
        );
      })}
    </ul>
  );
}

// Composición de cajas
function SaldoCajas({ cajas: C = CAJAS }) {
  return (
    <ul className="space-y-3">
      {C.map(c => (
        <li key={c.id} className="flex items-center gap-3">
          <span className="w-2.5 h-2.5 rounded-full flex-shrink-0" style={{ background: c.color }} />
          <div className="flex-1 min-w-0">
            <div className="flex items-baseline justify-between">
              <span className="text-[12.5px] text-ink font-medium truncate">{c.nombre}</span>
              <span className="font-mono text-[12px] text-ink">{ARS_C(c.ars)}</span>
            </div>
            <div className="flex items-baseline justify-between mt-0.5">
              <span className="text-[10px] text-slate-400">{c.tipo === 'banco' ? c.alias || 'cuenta bancaria' : 'efectivo'}</span>
              <span className="font-mono text-[11px] text-slate-500">{USD_C(c.usd)}</span>
            </div>
          </div>
        </li>
      ))}
    </ul>
  );
}

// Mini movimientos entre cajas
function UltimosMovimientos() {
  return (
    <ul className="divide-y divide-slate-100 -mx-5">
      {MOVIMIENTOS.slice(0, 5).map(m => (
        <li key={m.id} className="px-5 py-2.5 flex items-center gap-3 hover:bg-canvas">
          <span className="font-mono text-[10px] text-slate-400 w-10">{m.fecha.slice(5)}</span>
          <div className="flex items-center gap-1.5 flex-1 min-w-0">
            <span className="inline-flex items-center gap-1 text-[11.5px] text-slate-600">
              <span className="w-1.5 h-1.5 rounded-full" style={{ background: CAJAS_BY_ID[m.origen]?.color }} />
              {CAJAS_BY_ID[m.origen]?.nombre.replace('Caja ', '')}
            </span>
            <I.Arrow size={11} className="text-slate-300" />
            <span className="inline-flex items-center gap-1 text-[11.5px] text-slate-600">
              <span className="w-1.5 h-1.5 rounded-full" style={{ background: CAJAS_BY_ID[m.destino]?.color }} />
              {CAJAS_BY_ID[m.destino]?.nombre.replace('Caja ', '')}
            </span>
          </div>
          <span className="font-mono text-[12px] text-ink">{m.mon_o === 'ARS' ? ARS_C(m.monto_o) : USD_C(m.monto_o)}</span>
        </li>
      ))}
    </ul>
  );
}

// Ingresos vs Egresos · KPI gigante mensual
function IngEgGigante({ kpis: K = KPIS }) {
  const balance = K.ingresos_brutos.ars - K.gastos.ars;
  const ratio = balance / (K.ingresos_brutos.ars || 1);
  return (
    <div>
      <div className="grid grid-cols-2 gap-4">
        <div>
          <div className="text-[10px] uppercase tracking-[0.12em] text-emerald-700 font-semibold">Ingresos · mes</div>
          <div className="font-mono text-[26px] text-emerald-700 leading-none mt-2">{ARS_C(K.ingresos_brutos.ars)}</div>
          <div className="text-[11px] text-slate-500 mt-1">≈ {USD_C(K.ingresos_brutos.usd)}</div>
        </div>
        <div>
          <div className="text-[10px] uppercase tracking-[0.12em] text-rose-700 font-semibold">Egresos · mes</div>
          <div className="font-mono text-[26px] text-rose-700 leading-none mt-2">{ARS_C(K.gastos.ars)}</div>
          <div className="text-[11px] text-slate-500 mt-1">≈ {USD_C(K.gastos.usd)}</div>
        </div>
      </div>
      <div className="mt-5 pt-5 border-t border-slate-100">
        <div className="flex items-baseline justify-between">
          <span className="text-[11px] uppercase tracking-[0.12em] text-slate-500 font-semibold">Balance neto</span>
          <span className="font-mono text-[20px] text-ink">{ARS_C(balance)}</span>
        </div>
        <div className="mt-2 flex items-center gap-2">
          <div className="h-1.5 flex-1 bg-slate-100 rounded-full overflow-hidden">
            <div className="h-full" style={{ width: `${Math.max(0, Math.min(100, ratio * 100))}%`, background: '#3F8A6B' }} />
          </div>
          <span className="text-[11px] font-mono text-slate-600">{Math.round(ratio * 100)}% margen</span>
        </div>
      </div>
    </div>
  );
}

// Comprobantes faltantes
function ComprobantesFaltantes() {
  const faltantes = GASTOS.filter(g => !g.comp);
  return (
    <div>
      <div className="flex items-baseline justify-between mb-3">
        <div className="font-mono text-[26px] text-ink">{faltantes.length}</div>
        <span className="text-[11px] text-slate-500">de {GASTOS.length} gastos</span>
      </div>
      <ul className="space-y-2">
        {faltantes.slice(0, 3).map(g => (
          <li key={g.id} className="flex items-start gap-2 text-[11.5px]">
            <span className="w-1 h-1 rounded-full bg-rose-500 mt-1.5" />
            <div className="flex-1 min-w-0">
              <div className="text-ink truncate">{g.desc}</div>
              <div className="text-slate-400 font-mono text-[10px]">{g.id} · {g.fecha}</div>
            </div>
            <span className="font-mono text-slate-600">{g.moneda === 'ARS' ? ARS_C(g.monto) : USD_C(g.monto)}</span>
          </li>
        ))}
      </ul>
      {faltantes.length === 0 && <div className="text-[11.5px] text-emerald-700 inline-flex items-center gap-1"><I.Check size={12} sw={2.5} /> Todo en regla</div>}
    </div>
  );
}

// Forma de pago en gastos del mes
function FormasPagoMes() {
  const m = {};
  GASTOS.forEach(g => {
    const v = g.moneda === 'ARS' ? g.monto : g.monto * 1180;
    m[g.forma_pago] = (m[g.forma_pago] || 0) + v;
  });
  const total = Object.values(m).reduce((s, v) => s + v, 0) || 1;
  return (
    <div className="space-y-2.5">
      <div className="flex h-2 rounded-full overflow-hidden bg-slate-50">
        {FORMAS_PAGO.map(f => {
          const v = m[f.id] || 0;
          return v > 0 ? <div key={f.id} title={`${f.label} · ${ARS_C(v)}`} style={{ width: `${v/total*100}%`, background: f.color }} /> : null;
        })}
      </div>
      <ul className="space-y-1.5">
        {FORMAS_PAGO.filter(f => m[f.id]).sort((a, b) => (m[b.id] || 0) - (m[a.id] || 0)).map(f => (
          <li key={f.id} className="flex items-center justify-between text-[11.5px]">
            <span className="inline-flex items-center gap-1.5">
              <span className="w-1.5 h-1.5 rounded-full" style={{ background: f.color }} />
              <span className="text-slate-700">{f.label}</span>
            </span>
            <span className="font-mono text-slate-700">{ARS_C(m[f.id])} <span className="text-[10px] text-slate-400">· {Math.round(m[f.id]/total*100)}%</span></span>
          </li>
        ))}
      </ul>
    </div>
  );
}

// Bar chart Ingresos vs Egresos reutilizado de widgets.jsx — pero local copia compacta
function MiniBars({ data, max = 150 }) {
  // BarChart de widgets.jsx ya existe — reutilizo
  return <BarChart data={data} max={max} h={200} />;
}

// ── Catálogo de widgets financieros ───────────────────────────────────────
const FIN_WIDGETS = [
  // KPIs primarios
  { id: 'fin_ing_brutos', group: 'Resultado', title: 'Ingresos brutos', span: 3, render: ({ cur, kpis: K = KPIS }) => (
    <KPI label="Ingresos brutos · mes" value={FIN_curVal(K.ingresos_brutos, cur)}
      secondary={cur === 'ARS' ? '≈ ' + USD_C(K.ingresos_brutos.usd) : '≈ ' + ARS_C(K.ingresos_brutos.ars)}
      delta={K.ingresos_brutos.delta} accent="#3D4F5C"
      sparkData={CHART_6M.map(d => d.ing)} />
  )},
  { id: 'fin_ing_netos', group: 'Resultado', title: 'Ingresos netos', span: 3, render: ({ cur, kpis: K = KPIS }) => (
    <KPI label="Ingresos netos · mes" value={FIN_curVal(K.ingresos_netos, cur)}
      secondary={cur === 'ARS' ? '≈ ' + USD_C(K.ingresos_netos.usd) : '≈ ' + ARS_C(K.ingresos_netos.ars)}
      delta={K.ingresos_netos.delta} accent="#3F8A6B"
      sparkData={CHART_6M.map(d => d.ing - d.eg)} sparkColor="#3F8A6B" />
  )},
  { id: 'fin_gastos', group: 'Resultado', title: 'Gastos del mes', span: 3, render: ({ cur, kpis: K = KPIS }) => (
    <KPI label="Gastos · mes" value={FIN_curVal(K.gastos, cur)}
      secondary={cur === 'ARS' ? '≈ ' + USD_C(K.gastos.usd) : '≈ ' + ARS_C(K.gastos.ars)}
      delta={K.gastos.delta} accent="#A8483F"
      sparkData={CHART_6M.map(d => d.eg)} sparkColor="#A8483F" />
  )},
  { id: 'fin_balance', group: 'Resultado', title: 'Balance del mes', span: 3, render: ({ cur, kpis: K = KPIS }) => {
    const balance = { ars: K.ingresos_brutos.ars - K.gastos.ars, usd: K.ingresos_brutos.usd - K.gastos.usd };
    return (
      <KPI label="Balance neto" value={FIN_curVal(balance, cur)}
        secondary="ingresos − gastos · sólo flujo"
        delta={+8.4} accent="#C9A961" />
    );
  }},
  { id: 'fin_com_pend', group: 'Resultado', title: 'Comisiones pendientes', span: 3, render: ({ cur }) => (
    <KPI label="Pendientes de cobro" value={FIN_curVal(KPIS.comisiones_pendientes, cur)}
      secondary={`${KPIS.comisiones_pendientes.qty} operaciones`}
      delta={KPIS.comisiones_pendientes.delta} accent="#B98A2E" hint="atención" />
  )},
  { id: 'fin_com_propias', group: 'Resultado', title: 'Comisiones propias', span: 3, render: ({ cur }) => (
    <KPI label="Comisiones propias" value={FIN_curVal(KPIS.comisiones_propias, cur)}
      secondary={`${Math.round(KPIS.comisiones_propias.usd / KPIS.ingresos_brutos.usd * 100)}% del bruto`}
      delta={KPIS.comisiones_propias.delta} accent="#C9A961" />
  )},
  { id: 'fin_ing_compart', group: 'Resultado', title: 'Compartidos', span: 3, render: ({ cur }) => (
    <KPI label="Compartidos a 3ros" value={FIN_curVal(KPIS.ingresos_compartidos, cur)}
      secondary={`${Math.round(KPIS.ingresos_compartidos.usd / KPIS.ingresos_brutos.usd * 100)}% del bruto`}
      delta={KPIS.ingresos_compartidos.delta} accent="#A88A47" />
  )},

  // Liquidez
  { id: 'fin_caja_chica', group: 'Liquidez', title: 'Caja chica', span: 3, render: ({ cajas: C = CAJAS }) => {
    const chica = C.find(c => c.id === 'chica') || CAJAS_BY_ID.chica;
    return (
      <KPI label="Caja chica" value={ARS_C(chica.ars)}
        secondary={USD_C(chica.usd)}
        accent="#3F8A6B" hint="ARS + USD" />
    );
  }},
  { id: 'fin_banco', group: 'Liquidez', title: 'Cuenta bancaria', span: 3, render: ({ cajas: C = CAJAS }) => {
    const banco = C.find(c => c.id === 'banco') || CAJAS_BY_ID.banco;
    return (
      <KPI label="Cuenta bancaria" value={ARS_C(banco.ars)}
        secondary={USD_C(banco.usd)}
        accent="#677A88" hint="Galicia" />
    );
  }},
  { id: 'fin_total_efectivo', group: 'Liquidez', title: 'Efectivo total', span: 3, render: ({ cajas: C = CAJAS }) => {
    const ars = C.filter(c => c.tipo === 'efectivo').reduce((s, c) => s + c.ars, 0);
    const usd = C.filter(c => c.tipo === 'efectivo').reduce((s, c) => s + c.usd, 0);
    return (
      <KPI label="Efectivo en cajas" value={ARS_C(ars)}
        secondary={USD_C(usd)} accent="#A88A47" hint="3 cajas" />
    );
  }},
  { id: 'fin_total_liquidez', group: 'Liquidez', title: 'Liquidez total', span: 3, render: ({ cajas: C = CAJAS }) => {
    const ars = C.reduce((s, c) => s + c.ars, 0);
    const usd = C.reduce((s, c) => s + c.usd, 0);
    return (
      <KPI label="Liquidez total" value={ARS_C(ars)}
        secondary={USD_C(usd)} accent="#3D4F5C" hint="bancos + cajas" />
    );
  }},

  // Bloques anchos
  { id: 'fin_chart', group: 'Análisis', title: 'Ingresos vs egresos (6m)', span: 8, render: () => (
    <Card title="Ingresos vs egresos · 6 meses"
      action={
        <div className="flex items-center gap-4 text-[11px] text-slate-500">
          <span className="inline-flex items-center gap-1.5"><span className="w-2 h-2 rounded-sm bg-slate-700" />Ingresos</span>
          <span className="inline-flex items-center gap-1.5"><span className="w-2 h-2 rounded-sm bg-gold" />Egresos</span>
        </div>
      }>
      <MiniBars data={CHART_6M} />
    </Card>
  )},
  { id: 'fin_balance_card', group: 'Análisis', title: 'Balance ingresos / egresos', span: 4, render: ({ kpis: K = KPIS }) => (
    <Card title="Resumen del mes"><IngEgGigante kpis={K} /></Card>
  )},
  { id: 'fin_gastos_area', group: 'Análisis', title: 'Gastos por área', span: 4, render: () => (
    <Card title="Composición de gastos · por área"><GastosPorArea /></Card>
  )},
  { id: 'fin_formas_pago', group: 'Análisis', title: 'Formas de pago', span: 4, render: () => (
    <Card title="Formas de pago · gastos"><FormasPagoMes /></Card>
  )},
  { id: 'fin_cajas', group: 'Análisis', title: 'Saldo por caja', span: 4, render: ({ cajas: C = CAJAS }) => (
    <Card title="Saldo por caja / cuenta"><SaldoCajas cajas={C} /></Card>
  )},
  { id: 'fin_movs', group: 'Análisis', title: 'Últimos movimientos', span: 8, render: () => (
    <Card title="Movimientos entre cajas"
      action={<button className="text-[11px] text-slate-500 hover:text-ink inline-flex items-center gap-1">Ver todos <I.Arrow size={12} /></button>}>
      <UltimosMovimientos />
    </Card>
  )},
  { id: 'fin_compr', group: 'Análisis', title: 'Comprobantes faltantes', span: 4, render: () => (
    <Card title="Sin comprobante"
      action={<span className="text-[11px] text-rose-700">acción requerida</span>}>
      <ComprobantesFaltantes />
    </Card>
  )},
  { id: 'fin_alertas_fin', group: 'Análisis', title: 'Alertas financieras', span: 4, render: () => (
    <Card title="Alertas">
      <ul className="space-y-3">
        {ALERTAS.filter(a => ['Comprobante','Cobranza','Vencimiento'].includes(a.tipo)).map((a, i) => {
          const sevBg = { ok: 'bg-emerald-500', warn: 'bg-amber-500', bad: 'bg-rose-500' }[a.sev];
          return (
            <li key={i} className="flex items-start gap-3">
              <span className={`mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0 ${sevBg}`} />
              <div className="flex-1 min-w-0">
                <div className="text-[10px] uppercase tracking-[0.12em] text-slate-400">{a.tipo}</div>
                <div className="text-[12.5px] text-ink mt-0.5 leading-snug">{a.texto}</div>
              </div>
              <span className="text-[11px] text-slate-400 font-mono">{a.fecha}</span>
            </li>
          );
        })}
      </ul>
    </Card>
  )},
];
const FIN_WIDGETS_BY_ID = Object.fromEntries(FIN_WIDGETS.map(w => [w.id, w]));

const FIN_DEFAULT_LAYOUT = [
  'fin_ing_brutos', 'fin_gastos', 'fin_balance', 'fin_com_pend',
  'fin_caja_chica', 'fin_banco', 'fin_total_efectivo', 'fin_total_liquidez',
  'fin_chart', 'fin_balance_card',
  'fin_gastos_area', 'fin_formas_pago', 'fin_cajas',
  'fin_movs', 'fin_compr',
];

// ── Dashboard Finanzas — reusa la mecánica drag-to-reorder y panel ─────────
function loadFinLayout() {
  try {
    const raw = localStorage.getItem(LS_FIN_KEY);
    if (raw) {
      const arr = JSON.parse(raw);
      if (Array.isArray(arr) && arr.every(id => FIN_WIDGETS_BY_ID[id])) return arr;
    }
  } catch (e) {}
  return [...FIN_DEFAULT_LAYOUT];
}
function saveFinLayout(layout) {
  try { localStorage.setItem(LS_FIN_KEY, JSON.stringify(layout)); } catch (e) {}
}

function FinanzasDashboard() {
  const [cur, setCur] = useState('ARS');
  const [layout, setLayout] = useState(loadFinLayout);
  const [editing, setEditing] = useState(false);
  const [panelOpen, setPanelOpen] = useState(false);
  const [dragId, setDragId] = useState(null);
  const { kpis: liveKpis, cajas: liveCajas } = useLiveDashboardData();

  useEffect(() => { saveFinLayout(layout); }, [layout]);

  const removeWidget = (id) => setLayout(l => l.filter(x => x !== id));
  const addWidget    = (id) => setLayout(l => l.includes(id) ? l : [...l, id]);
  const resetLayout  = () => setLayout([...FIN_DEFAULT_LAYOUT]);

  const onDragOver = (e, overId) => {
    e.preventDefault();
    if (!dragId || dragId === overId) return;
    setLayout(l => {
      const from = l.indexOf(dragId), to = l.indexOf(overId);
      if (from < 0 || to < 0) return l;
      const next = [...l];
      next.splice(from, 1);
      next.splice(to, 0, dragId);
      return next;
    });
  };

  return (
    <div className="fade-in">
      <PageHeader
        crumbs={['Inicio', 'Finanzas', 'Dashboard']}
        title="Dashboard financiero"
        sub={editing
          ? 'Modo edición · arrastrá widgets para reordenar, hacé click en × para quitar'
          : `KPIs de movimientos · mayo 2026 · ${layout.length} widgets activos`}
        actions={
          <>
            <CurrencyToggle value={cur} onChange={setCur} />
            <Button variant="outline" size="md" icon={<I.Settings size={14} />} onClick={() => { setEditing(e => !e); setPanelOpen(p => !p || !editing); }}>
              {editing ? 'Terminar' : 'Personalizar'}
            </Button>
          </>
        }
      />

      <div className={`grid grid-cols-12 gap-4 ${panelOpen ? 'pr-[336px] transition-[padding] duration-200' : 'transition-[padding] duration-200'}`}>
        {layout.length === 0 && (
          <div className="col-span-12 border-2 border-dashed border-slate-200 rounded-md py-20 flex flex-col items-center text-center">
            <div className="text-[13px] font-semibold text-ink">Dashboard vacío</div>
            <div className="text-[12px] text-slate-500 mt-1">Agregá widgets desde el panel o restablecé el layout.</div>
            <Button variant="outline" size="md" onClick={resetLayout} className="mt-4">Restablecer layout</Button>
          </div>
        )}
        {layout.map(id => {
          const w = FIN_WIDGETS_BY_ID[id];
          if (!w) return null;
          const SPAN = { 3: 'col-span-3', 4: 'col-span-4', 6: 'col-span-6', 8: 'col-span-8', 12: 'col-span-12' }[w.span];
          return (
            <div key={id}
              draggable={editing}
              onDragStart={() => setDragId(id)}
              onDragEnd={() => setDragId(null)}
              onDragOver={(e) => onDragOver(e, id)}
              className={`${SPAN} relative ${editing ? 'cursor-grab active:cursor-grabbing' : ''} ${dragId === id ? 'opacity-40' : ''}`}
              style={editing ? { outline: '1px dashed #C9A961', outlineOffset: '2px', borderRadius: '6px' } : undefined}>
              {w.render({ cur, kpis: liveKpis || KPIS, cajas: liveCajas || CAJAS })}
              {editing && (
                <button onClick={() => removeWidget(id)}
                  className="absolute -top-2 -right-2 w-6 h-6 rounded-full bg-white border border-slate-200 text-slate-500 hover:bg-rose-50 hover:border-rose-300 hover:text-rose-700 shadow-card inline-flex items-center justify-center z-10"
                  title="Quitar widget">
                  <I.X size={12} sw={2.5} />
                </button>
              )}
              {editing && (
                <div className="absolute top-2 left-2 px-1.5 py-0.5 rounded bg-white/90 backdrop-blur text-[9px] uppercase tracking-[0.1em] text-slate-500 font-medium border border-slate-100 z-10 pointer-events-none">
                  ⋮⋮ {w.title}
                </div>
              )}
            </div>
          );
        })}
      </div>

      {panelOpen && (
        <FinCustomizePanel
          layout={layout}
          onAdd={addWidget}
          onRemove={removeWidget}
          onReset={resetLayout}
          onClose={() => { setPanelOpen(false); setEditing(false); }}
        />
      )}
    </div>
  );
}

function FinCustomizePanel({ layout, onAdd, onRemove, onReset, onClose }) {
  const grouped = useMemo(() => {
    const m = {};
    FIN_WIDGETS.forEach(w => { (m[w.group] ||= []).push(w); });
    return m;
  }, []);
  const active = new Set(layout);

  return (
    <aside className="fixed top-[64px] right-0 bottom-0 w-[320px] bg-white border-l border-slate-200 shadow-pop flex flex-col z-20 fade-in">
      <div className="px-5 pt-5 pb-4 border-b border-slate-100">
        <div className="flex items-start justify-between">
          <div>
            <div className="text-[10px] uppercase tracking-[0.14em] text-slate-400 font-medium">Personalizar</div>
            <h3 className="font-serif text-[22px] text-ink leading-tight mt-1">Widgets financieros</h3>
          </div>
          <button onClick={onClose} className="p-1 -mr-1 rounded hover:bg-slate-100 text-slate-500"><I.X size={16} /></button>
        </div>
        <p className="text-[11.5px] text-slate-500 mt-2 leading-snug">
          Cada usuario guarda su propia configuración del dashboard financiero.
        </p>
      </div>

      <div className="flex-1 overflow-y-auto">
        {Object.entries(grouped).map(([group, items]) => (
          <div key={group} className="border-b border-slate-100 last:border-0">
            <div className="px-5 pt-4 pb-2 text-[10px] uppercase tracking-[0.14em] text-slate-400 font-semibold sticky top-0 bg-white/95 backdrop-blur z-10">{group}</div>
            <ul className="pb-2">
              {items.map(w => {
                const isActive = active.has(w.id);
                return (
                  <li key={w.id} className="px-5 py-2 flex items-start gap-3 hover:bg-canvas group">
                    <button
                      onClick={() => isActive ? onRemove(w.id) : onAdd(w.id)}
                      className={`mt-0.5 w-4 h-4 rounded border flex-shrink-0 flex items-center justify-center transition-colors ${isActive ? 'bg-slate-700 border-slate-700 text-white' : 'border-slate-300 bg-white group-hover:border-slate-400'}`}>
                      {isActive && <I.Check size={10} sw={3} />}
                    </button>
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center justify-between gap-2">
                        <span className="text-[12.5px] text-ink font-medium leading-tight">{w.title}</span>
                        <span className="text-[9px] uppercase tracking-[0.08em] text-slate-400 font-mono">{w.span === 3 ? 'KPI' : w.span === 4 ? 'M' : 'L'}</span>
                      </div>
                    </div>
                  </li>
                );
              })}
            </ul>
          </div>
        ))}
      </div>

      <div className="px-5 py-4 border-t border-slate-100 bg-canvas flex items-center gap-2">
        <button onClick={onReset} className="text-[11.5px] text-slate-600 hover:text-ink font-medium">Restablecer</button>
        <div className="flex-1" />
        <span className="text-[10px] text-slate-400 font-mono">{layout.length} activos · {FIN_WIDGETS.length - layout.length} disponibles</span>
      </div>
    </aside>
  );
}

window.FinanzasDashboard = FinanzasDashboard;
