// ─── Finanzas · Recibo (fuente: expediente | standalone) ──────────────────
// FUSIÓN del corazón de P8 (mismo tratamiento que factura.jsx — ver su
// header para el detalle completo del porqué): antes ReciboScreen (screens/
// docs/recibo.jsx, P7 — ligado a expediente, guarda con saveDocOnExp) y
// ReciboFinScreen (screens-finanzas-nuevo.jsx — standalone, guarda con
// MicosStore.create/update) eran casi el mismo componente reescrito dos
// veces; ambas terminan en la MISMA tabla `recibos`. Se fusionan en UN
// componente parametrizado por fuente (expediente si viene la prop
// `expediente`, standalone si no) — la bifurcación que antes vivía en
// core/app.jsx (finanzas-doc-detail kind 'recibo') pasa a un solo destino.
//
// Diferencias reales entre fuentes que se preservan:
//   - Resolución: expediente lee exp.recibo (1:1); standalone resuelve por
//     id sobre window.RECIBOS.
//   - Persistencia: expediente usa saveDocOnExp (avanza el pipeline);
//     standalone usa MicosStore.create/update directo.
//   - Cliente: expediente lo fija (paciente/entidad del expediente, sin
//     picker); standalone lo elige con PartySelectorModal.
//   - ImputacionCard: unificado al criterio MÁS correcto de los dos
//     originales — en isCreate usa modo BORRADOR (value/onChange sobre el
//     draft, recién persiste al guardar el recibo); ya creado usa modo STORE
//     (collection/recordId). El ReciboScreen de expediente original SIEMPRE
//     usaba modo store con `recordId=original.id`, que en isCreate es
//     undefined — hueco preexistente (PATCH a /api/recibos/undefined si se
//     intentaba imputar ANTES de guardar) que esta fusión evita usando el
//     mismo criterio ya correcto de ReciboFinScreen para los dos orígenes.
//   - Borrado: expediente delega en `onDelete` (modal central de app.jsx);
//     standalone maneja su propio ConfirmDeleteModal.
// FIX addenda arquitecto (hallazgo P7 #3): `exp.particular.nombre` sin
// guarda crasheaba con F5 sin expediente en memoria — `exp?.particular?.nombre`.
// FIX addenda arquitecto (hallazgo P11, "Recibo undefined" en el visor de
// impresión): `numeroComprobante` NO es una columna real de `recibos`
// (src/lib/api/serializers/recibos.ts, RECIBO_COLUMNS) — un recibo real
// persistido (no creado en esta sesión) llega sin ese campo. `bigId` y el
// título del visor de impresión ahora caen a `publicId` y, en último caso, a
// "Recibo sin número" en vez de interpolar `undefined`.
// Expone a window: ReciboScreen, InstrumentosTable (INSTRUMENTO_TIPOS/
// LABELS: se muda acá desde screens/docs/recibo.jsx — P7 ya documentaba que
// Finanzas la reusaba tal cual por global de window; ahora convive con su
// pantalla dueña en el mismo archivo, sin cruzar carpetas). Consume window.
// resolveDocExp (compartido.jsx de screens/docs/), DocumentShell/DocCard/
// PartyBlock/Totals/MedicalContextCard/ObservacionesCard/buildEmisorFields/
// buildClienteFields (ui/doc-kit-shell.jsx), buildClienteFieldsCompacto
// (screens/finanzas/compartido.jsx), DocMetaStrip (ui/doc-kit-meta.jsx),
// useDocEdit/buildDocActions/ConfirmDeleteModal (ui/doc-kit-edit.jsx),
// ImputacionCard (screens/finanzas/imputacion.jsx, carga después en el HTML
// — funciona porque JSX no se ejecuta hasta el render), emptyRecibo/
// saveDocOnExp (dominio/expediente-docs.js), MicosNextSeqId (dominio/
// secuencias.js), numeroDePublicId (dominio/formato.js, fix H1 post-review
// P15), MicosStore, MicosDocRecibo/openPrintDoc.
//
// EXCEPCIÓN AL TECHO DE ~250 LÍNEAS (regla de la compuerta, P7 §3): fusiona 2
// pantallas + InstrumentosTable en un solo tema cohesivo ("Recibo, las dos
// fuentes"); no se separa InstrumentosTable a un archivo propio por la misma
// razón que documentaba P7 — es infra de UNA sola pantalla dueña, partirla
// dejaría un archivo de una función sin otro consumidor interno.

function resolverRecibo(id) { return (window.RECIBOS || []).find((r) => r.id === id) || null; }
function makeBlankRecibo() {
  // `numero` BARE (sin prefijo): MicosNextSeqId recibe un extractor que le
  // saca el número antes de escanear.
  // FIX (P15, hallazgo H1 de la review): antes hacía `.replace(/^REC-/, '')`,
  // que solo saca EL prefijo "REC-" — con los 41 recibos hoy en `L-REC-…`
  // (namespace legacy) esa regex no matchea, devuelve el id ENTERO, y
  // MicosNextSeqId lo vuelve a sniffear como prefijo ("L-REC-"), garblando
  // el resultado en "REC-L-REC-00000042". `numeroDePublicId` (dominio/
  // formato.js) toma el bloque numérico FINAL — mismo criterio que
  // `numeroFromPublicId` (src/lib/api/rest.ts) — y funciona igual para
  // nativos y legacy.
  const numero = MicosNextSeqId(window.RECIBOS || [], (r) => numeroDePublicId(r.publicId), '', 8);
  return {
    id: 'rec-' + Date.now(),
    publicId: 'REC-' + numero,
    numeroComprobante: 'REC-0012-' + numero,
    expedienteId: null, entidadId: null,
    fechaCobro: MicosTodayISO(), observaciones: '', importeLetras: '',
    cliente: null, instrumentos: [], imputaciones: [], total: 0,
  };
}

// Número a mostrar como "gran ID" / en el visor de impresión: numeroComprobante
// (invento de sesión, solo lo tienen los recibos creados en esta ventana) con
// fallback a publicId (real, SIEMPRE existe) y por último un texto honesto —
// nunca interpolar `undefined` (FIX hallazgo P11).
function numeroReciboMostrar(rec) {
  return rec.numeroComprobante || rec.publicId || 'Recibo sin número';
}

function ReciboScreen({
  // Fuente 'expediente'
  expediente,
  // Fuente 'standalone'
  reciboId, isCreate = false, onSaved,
  // Comunes
  onBack, backLabel, onDelete,
}) {
  const esStandalone = !expediente;
  const co = COMPANY_CONFIG;

  const exp = expediente ? resolveDocExp(expediente) : null;
  const existingExp = exp ? (exp.recibo || null) : null;

  const standaloneBlank = React.useMemo(
    () => (esStandalone && isCreate ? makeBlankRecibo() : null),
    [esStandalone, isCreate]
  );
  const standaloneRec = esStandalone ? (isCreate ? standaloneBlank : resolverRecibo(reciboId)) : null;

  const isCreateEff = esStandalone ? isCreate : !existingExp;
  const original = React.useMemo(() => {
    if (esStandalone) return standaloneRec;
    return existingExp || emptyRecibo(exp);
  }, [esStandalone, standaloneRec, existingExp]);

  const [toast, setToast] = React.useState(null);
  const [confirmDel, setConfirmDel] = React.useState(false);
  const [clientePicker, setClientePicker] = React.useState(false);

  const { editing, draft, setDraft, enterEdit, discardEdit, saveEdit, patch } = useDocEdit(() => ({
    numeroComprobante: original.numeroComprobante,
    fechaCobro: original.fechaCobro,
    observaciones: original.observaciones || '',
    importeLetras: original.importeLetras || '',
    cliente: original.cliente || null,
    instrumentos: (original.instrumentos || []).map((it) => ({ ...it })),
    imputaciones: (original.imputaciones || []).map((it) => ({ ...it })),
  }), {
    startEditing: isCreateEff,
    onCancel: () => { if (isCreateEff) onBack && onBack(); },
    onSave: (d) => {
      if (esStandalone) {
        const hasInstrumentos = (d.instrumentos || []).length > 0;
        const total = hasInstrumentos
          ? (d.instrumentos || []).reduce((s, i) => s + (Number(i.importe) || 0), 0)
          : (Number(original.total) || 0);
        const upd = {
          numeroComprobante: d.numeroComprobante,
          fechaCobro: d.fechaCobro,
          observaciones: d.observaciones || '',
          importeLetras: d.importeLetras || '',
          cliente: d.cliente || null,
          entidadId: (d.cliente && d.cliente.id) || original.entidadId || null,
          instrumentos: (d.instrumentos || []).map((it) => ({ ...it })),
          total,
        };
        // imputaciones (P8b): SOLO en alta. En edición de un recibo YA existente,
        // ImputacionCard corre en modo store (collection/recordId, ver imputacionCard
        // más abajo) y persiste cada asociar/desasociar directo contra la DB en el
        // momento del click (su propio `persist()`) — ajeno a este draft. Si acá
        // mandáramos `d.imputaciones` (una foto tomada al entrar a editar, nunca
        // actualizada por la card) pisaríamos con datos viejos lo que la card ya
        // guardó (bug encontrado en verificación: asociar → guardar → quedaba
        // resucitada la versión vieja). Recién en isCreateEff la card está en modo
        // BORRADOR (value/onChange sobre el draft) y este es el ÚNICO punto que la persiste.
        if (isCreateEff) upd.imputaciones = (d.imputaciones || []).map((it) => ({ ...it }));
        if (isCreateEff) {
          MicosStore.create('recibos', { ...original, ...upd, __nuevo: true });
          onSaved && onSaved(original.id);
        } else {
          if (window.MicosStore) MicosStore.update('recibos', original.id, upd);
          Object.assign(original, upd);
          setToast(`Recibo ${numeroReciboMostrar(upd)} guardado`);
          setTimeout(() => setToast(null), 3600);
        }
        return;
      }
      const docObj = {
        ...original,
        fechaCobro: d.fechaCobro,
        observaciones: d.observaciones || '',
        importeLetras: d.importeLetras || '',
        instrumentos: (d.instrumentos || []).map((it) => ({ ...it })),
      };
      // Mismo criterio que la rama standalone de arriba: imputaciones solo viaja acá
      // en ALTA (card en modo borrador); en edición la card store-mode ya persistió
      // sola — `...original` de la línea de arriba trae su `imputaciones` vieja, hay
      // que sacarla explícito para no reenviarla.
      if (isCreateEff) docObj.imputaciones = (d.imputaciones || []).map((it) => ({ ...it }));
      else delete docObj.imputaciones;
      saveDocOnExp(exp, 'recibo', docObj);
      setToast(`Recibo ${numeroReciboMostrar(docObj)} ${isCreateEff ? 'creado' : 'guardado'}`);
      setTimeout(() => setToast(null), 3600);
    },
  });

  if (esStandalone && !original) {
    return (
      <div className="space-y-6 pt-2">
        <button onClick={onBack} className="flex items-center gap-2 text-[11px] font-bold uppercase tracking-[0.12em] cursor-pointer" style={{ color: 'var(--muted-foreground)' }}><IconArrowLeft size={13} />{backLabel || 'Volver a Finanzas'}</button>
        <p className="text-[14px] font-semibold" style={{ color: 'var(--muted-foreground)' }}>No se encontró el recibo.</p>
      </div>
    );
  }

  const rec = editing && draft ? draft : original;
  const patchInstrumento = (idx, field, value) => setDraft((d) => ({ ...d, instrumentos: d.instrumentos.map((it, i) => i === idx ? { ...it, [field]: value } : it) }));
  const addInstrumento = () => setDraft((d) => ({ ...d, instrumentos: [...d.instrumentos, { tipo: 'EFECTIVO', banco: '', numero: '', fechaEmision: '', fechaCobro: '', importe: 0 }] }));
  const removeInstrumento = (idx) => setDraft((d) => ({ ...d, instrumentos: d.instrumentos.filter((_, i) => i !== idx) }));
  const totalCobrado = (rec.instrumentos || []).reduce((s, i) => s + (Number(i.importe) || 0), 0);

  const onPrint = () => {
    const live = esStandalone ? (resolverRecibo(original.id) || original) : (resolveDocExp(expediente).recibo || rec);
    const mod = MicosDocRecibo;
    if (esStandalone) {
      if (!mod || !window.openPrintDoc) return;
      const fakeExp = { entidad: live.cliente || {}, publicId: '' };
      openPrintDoc(mod.fromExpediente(fakeExp, co, live), {
        mod, title: `Recibo ${numeroReciboMostrar(live)}`,
        subtitle: (live.cliente && live.cliente.razonSocial) || '',
      });
      return;
    }
    const fresh = resolveDocExp(expediente);
    const data = mod.fromExpediente(fresh, co, live);
    openPrintDoc(data, {
      mod, title: `Recibo ${numeroReciboMostrar(live)}`,
      subtitle: `${fresh.publicId}${fresh.entidad?.razonSocial ? ' · ' + fresh.entidad.razonSocial : ''}`,
    });
  };
  // Puente ERP→CRM (carril B-erp): "Enviar por mail" con este recibo adjunto.
  // `doc` = numeroComprobante || publicId (= código del recibo en el CRM). Datos
  // SIEMPRE del `original` (persistido). Standalone no vincula expediente.
  const onEmail = window.buildDocEmailAction && window.buildDocEmailAction({
    tipo: 'Recibo',
    docId: numeroReciboMostrar(original),
    expPublicId: esStandalone ? '' : exp.publicId,
    fields: esStandalone ? buildClienteFieldsCompacto(original.cliente) : buildClienteFields(exp),
  });
  const actions = buildDocActions({
    editing, enterEdit, discardEdit, saveEdit, onPrint, onEmail,
    onDelete: esStandalone
      ? ((!isCreateEff && editing) ? () => setConfirmDel(true) : undefined)
      : (editing && onDelete ? onDelete : undefined),
  });

  const clienteNombre = esStandalone
    ? ((rec.cliente && rec.cliente.razonSocial) || (editing ? '— elegí cliente —' : 'Consumidor Final'))
    : (exp.entidad?.razonSocial || (exp.particular?.nombre ? `${exp.particular.nombre} ${exp.particular.apellido || ''}`.trim() : '—'));
  const clienteSub = esStandalone
    ? ((rec.cliente && rec.cliente.condicionIva) || 'Consumidor Final')
    : (exp.entidad?.condicionIva || 'Consumidor Final');
  const clienteFields = esStandalone ? buildClienteFieldsCompacto(rec.cliente) : buildClienteFields(exp);

  // ImputacionCard: en isCreate arranca en modo borrador (value/onChange
  // sobre el draft) para las dos fuentes — ver header, evita el PATCH a un
  // recordId undefined que tenía el ReciboScreen de expediente original.
  const imputacionCard = isCreateEff
    ? <ImputacionCard lado="cobro" total={totalCobrado} value={draft ? draft.imputaciones : []} onChange={(next) => patch('imputaciones', next)} />
    : <ImputacionCard collection="recibos" recordId={original.id} lado="cobro" total={totalCobrado} editing={editing} />;

  const subtitle = esStandalone ? (
    <React.Fragment>
      <span className="font-bold" style={{ color: 'var(--foreground)' }}>{clienteNombre}</span>
      <span className="mx-1.5 opacity-50">·</span>
      <span style={{ color: 'var(--muted-foreground)' }}>Cobrado el {formatDateLong(rec.fechaCobro)}</span>
    </React.Fragment>
  ) : undefined;

  return (
    <DocumentShell
      onBack={onBack}
      backLabel={backLabel || (esStandalone ? 'Volver a Finanzas' : 'Volver al expediente')}
      eyebrow="Recibo"
      statusLabel={esStandalone ? undefined : (editing ? 'Editando' : 'Cobrado')}
      statusPill={esStandalone ? undefined : 'pill-recibo'}
      bigId={numeroReciboMostrar(original)}
      expedienteId={esStandalone ? undefined : exp.publicId}
      fechaEmision={rec.fechaCobro}
      subtitle={subtitle}
      editing={editing}
      isCreate={isCreateEff}
      toast={toast}
      actions={actions}
    >
      {!esStandalone && <MedicalContextCard exp={exp} />}

      <DocMetaStrip editing={editing} items={esStandalone ? [
        { label: 'Comprobante', value: editing ? draft.numeroComprobante : numeroReciboMostrar(original), mono: true, accent: true, editable: editing, placeholder: 'Número de comprobante', onChange: (v) => patch('numeroComprobante', v) },
        { label: 'Fecha de cobro', value: editing ? draft.fechaCobro : formatDate(original.fechaCobro), mono: true, editable: editing, inputType: 'date', onChange: (v) => patch('fechaCobro', v) },
        { label: 'ID', value: original.publicId, mono: true, accent: true },
        { label: 'Total cobrado', value: formatMoney(totalCobrado), mono: true, accent: true },
        { label: 'Moneda', value: 'Pesos argentinos' },
      ] : [
        { label: 'Comprobante', value: numeroReciboMostrar(original), mono: true, accent: true },
        { label: 'Fecha de cobro', value: editing ? draft.fechaCobro : formatDate(original.fechaCobro), mono: true, editable: editing, inputType: 'date', onChange: (v) => patch('fechaCobro', v) },
        { label: 'Expediente', value: exp.publicId, mono: true, accent: true },
        { label: 'Total cobrado', value: formatMoney(totalCobrado), mono: true, accent: true },
      ]} />

      <DocCard className="relative">
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
          <PartyBlock
            eyebrow="Emisor"
            name={co.nombre}
            sub={co.situacionIva}
            fields={buildEmisorFields(co)}
          />
          <PartyBlock
            eyebrow="Cliente"
            name={clienteNombre}
            sub={clienteSub}
            fields={clienteFields}
          />
        </div>
        {/* Fuente expediente: el cliente lo fija el expediente (sin picker, ver el header de
            este archivo). Antes el ícono se mostraba SIEMPRE con `editing`, aunque en la rama
            de expediente no tuviera ningún efecto (hallazgo BAJA, AUDITORIA-ui-decorativa;
            gemelo del mismo fix en factura.jsx). */}
        {editing && esStandalone && (
          <button onClick={() => setClientePicker(true)} title="Cambiar cliente" className="party-edit-btn absolute" style={{ top: 16, right: 16 }} type="button">
            <IconPencil size={13} />
          </button>
        )}
      </DocCard>

      {imputacionCard}

      {/* Instrumentos de cobro */}
      <DocCard editing={editing}>
        <div className="flex items-center justify-between mb-5">
          <p className="text-[11px] font-bold uppercase tracking-[0.2em]" style={{ color: 'var(--accent)' }}>
            Instrumentos de cobro
          </p>
          <p className="text-[11.5px] font-bold uppercase tracking-[0.1em]" style={{ color: 'var(--muted-foreground)' }}>
            {rec.instrumentos.length} {rec.instrumentos.length === 1 ? 'instrumento' : 'instrumentos'}
          </p>
        </div>
        <InstrumentosTable
          instrumentos={rec.instrumentos}
          editing={editing}
          onChange={patchInstrumento}
          onRemove={removeInstrumento}
          onAdd={addInstrumento}
        />

        {/* Total banner */}
        <div className="mt-8 rounded-xl px-6 py-5"
          style={{ background: 'var(--card)', border: '1px solid color-mix(in oklab, var(--border) 55%, transparent)' }}>
          <div className="flex flex-wrap items-end justify-between gap-3">
            <div className="space-y-1">
              <p className="text-[11px] font-bold uppercase tracking-[0.2em]" style={{ color: 'var(--foreground)' }}>
                Total cobrado
              </p>
              {(editing ? draft.importeLetras : original.importeLetras) &&
                <p className="text-[11.5px] leading-snug max-w-[44ch]" style={{ color: 'var(--muted-foreground)' }}>
                  {editing ? draft.importeLetras : original.importeLetras}
                </p>
              }
            </div>
            <p className="text-[clamp(32px,4.6vw,42px)] font-extrabold tabular-nums tracking-[-0.02em] leading-none" style={{ color: 'var(--accent)' }}>
              {formatMoney(totalCobrado)}
            </p>
          </div>
        </div>
      </DocCard>

      <ObservacionesCard editing={editing} value={editing ? draft.observaciones : original.observaciones} onChange={(v) => patch('observaciones', v)} />

      {esStandalone && clientePicker && window.PartySelectorModal && (
        <window.PartySelectorModal type="entidad" open={true} onClose={() => setClientePicker(false)}
          onPick={(obj) => {
            if (obj && !obj.__sinEntidad) setDraft((d) => ({ ...d, cliente: {
              id: obj.id, razonSocial: obj.razonSocial || obj.nombre || '',
              condicionIva: obj.condicionIva || 'Responsable Inscripto', cuit: obj.cuit || '',
              domicilio: obj.domicilio || '', localidad: obj.localidad || '',
              condicionVenta: obj.condicionVenta || 'Cuenta corriente',
            } }));
            setClientePicker(false);
          }} />
      )}
      {esStandalone && confirmDel && window.ConfirmDeleteModal && (
        <window.ConfirmDeleteModal title="¿Eliminar recibo?" itemName={numeroReciboMostrar(original)}
          description="Se va a borrar este recibo de Finanzas. Esta acción no se puede deshacer."
          confirmLabel="Sí, eliminar" onCancel={() => setConfirmDel(false)}
          onConfirm={() => { if (window.MicosStore) MicosStore.remove('recibos', original.id); setConfirmDel(false); onBack(); }} />
      )}
    </DocumentShell>
  );
}

// ─── Instrumentos table (Recibo) ──────────────────
const INSTRUMENTO_TIPOS = [
  { value: 'EFECTIVO', label: 'Efectivo' },
  { value: 'CHEQUE', label: 'Cheque' },
  { value: 'TRANSFERENCIA', label: 'Transferencia' },
  { value: 'TARJETA', label: 'Tarjeta' },
  { value: 'OTRO', label: 'Otro' },
];
const INSTRUMENTO_LABELS = Object.fromEntries(INSTRUMENTO_TIPOS.map(t => [t.value, t.label]));

function InstrumentosTable({ instrumentos, editing, onChange, onRemove, onAdd }) {
  const template = editing
    ? '140px 1fr 130px 130px 130px 140px 36px'
    : '140px 1fr 130px 130px 130px 140px';
  const minWidth = editing ? 880 : 820;

  return (
    <div className="rounded-xl overflow-hidden" style={{ border: '1px solid color-mix(in oklab, var(--border) 55%, transparent)' }}>
      <div style={{ overflowX: 'auto' }}>
        <div style={{ minWidth: `${minWidth}px` }}>
          <div className="grid gap-4 px-5 py-4 text-[10.5px] font-bold uppercase tracking-[0.12em]"
            style={{
              gridTemplateColumns: template,
              color: 'var(--muted-foreground)',
              background: 'color-mix(in oklab, var(--surface) 55%, transparent)',
              borderBottom: '1px solid color-mix(in oklab, var(--border) 55%, transparent)',
            }}>
            <div>Tipo</div>
            <div>Banco / Detalle</div>
            <div>Número</div>
            <div>Fecha emisión</div>
            <div>Fecha cobro</div>
            <div className="text-right">Importe</div>
            {editing && <div />}
          </div>
          {instrumentos.map((it, i) =>
            <div key={i}
              className={`grid gap-4 px-5 py-4 items-center text-[14px] ${editing ? 'item-row--editing' : ''}`}
              style={{
                gridTemplateColumns: template,
                borderBottom: i < instrumentos.length - 1 || editing ? '1px solid color-mix(in oklab, var(--border) 40%, transparent)' : 'none',
              }}>
              <div>
                {editing ? (
                  <select value={it.tipo}
                    onChange={(e) => onChange(i, 'tipo', e.target.value)}
                    className="edit-input edit-input--cell w-full text-[13px] font-bold uppercase tracking-wide"
                    style={{ color: 'var(--accent)' }}>
                    {INSTRUMENTO_TIPOS.map(t => <option key={t.value} value={t.value}>{t.label}</option>)}
                  </select>
                ) : (
                  <span className="text-[12px] font-bold uppercase tracking-[0.1em]" style={{ color: 'var(--accent)' }}>
                    {INSTRUMENTO_LABELS[it.tipo] || it.tipo}
                  </span>
                )}
              </div>
              <div className="min-w-0">
                {editing ? (
                  <input value={it.banco || ''}
                    onChange={(e) => onChange(i, 'banco', e.target.value)}
                    placeholder="Banco o detalle"
                    className="edit-input edit-input--cell w-full font-bold" />
                ) : (
                  <p className="font-bold truncate" style={{ color: 'var(--foreground)' }}>{it.banco || '—'}</p>
                )}
              </div>
              <div className="font-mono text-[12.5px]" style={{ color: 'var(--muted-foreground)' }}>
                {editing ? (
                  <input value={it.numero || ''}
                    onChange={(e) => onChange(i, 'numero', e.target.value)}
                    placeholder="N°"
                    className="edit-input edit-input--cell w-full font-mono text-[12.5px]" />
                ) : (it.numero || '—')}
              </div>
              <div className="font-mono text-[12.5px] tabular-nums" style={{ color: 'var(--muted-foreground)' }}>
                {editing ? (
                  <input type="date" value={it.fechaEmision || ''}
                    onChange={(e) => onChange(i, 'fechaEmision', e.target.value)}
                    className="edit-input edit-input--cell w-full font-mono text-[12.5px] tabular-nums" />
                ) : (it.fechaEmision ? formatDate(it.fechaEmision) : '—')}
              </div>
              <div className="font-mono text-[12.5px] tabular-nums" style={{ color: 'var(--muted-foreground)' }}>
                {editing ? (
                  <input type="date" value={it.fechaCobro || ''}
                    onChange={(e) => onChange(i, 'fechaCobro', e.target.value)}
                    className="edit-input edit-input--cell w-full font-mono text-[12.5px] tabular-nums" />
                ) : (it.fechaCobro ? formatDate(it.fechaCobro) : '—')}
              </div>
              <div className="text-right font-extrabold tabular-nums" style={{ color: 'var(--foreground)' }}>
                {editing ? (
                  <input type="number" value={it.importe}
                    onChange={(e) => onChange(i, 'importe', Number(e.target.value) || 0)}
                    className="edit-input edit-input--cell w-full text-right tabular-nums font-extrabold" />
                ) : formatMoney(it.importe)}
              </div>
              {editing &&
                <button onClick={() => onRemove(i)}
                  className="flex items-center justify-center rounded-md transition-colors cursor-pointer"
                  style={{ width: 28, height: 28, color: 'var(--destructive)', background: 'color-mix(in oklab, var(--destructive) 8%, transparent)' }}
                  onMouseEnter={(e) => { e.currentTarget.style.background = 'color-mix(in oklab, var(--destructive) 18%, transparent)'; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = 'color-mix(in oklab, var(--destructive) 8%, transparent)'; }}
                  title="Eliminar instrumento">
                  <IconTrash size={14} />
                </button>
              }
            </div>
          )}
          {editing &&
            <button onClick={onAdd}
              className="flex items-center justify-center gap-2 w-full px-5 py-4 text-[13px] font-bold uppercase tracking-[0.1em] transition-colors cursor-pointer"
              style={{ color: 'var(--accent)' }}
              onMouseEnter={(e) => e.currentTarget.style.background = 'color-mix(in oklab, var(--accent) 7%, transparent)'}
              onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
              <IconPlus size={14} />
              Agregar instrumento
            </button>
          }
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { ReciboScreen, InstrumentosTable, numeroReciboMostrar });
