// === comun.jsx — piezas de play compartidas por las escenas de «Emitir una factura de venta» ===
// Todo se dibuja en coordenadas de play (una pantalla lógica de 1200×600, letra de 13-14 px como en
// play) y se amplía ×1,5 sobre el lienzo de 1920×1080: así el aspecto es el de la app y el texto se lee.
// Textos, iconos y colores salen de los .razor de play.dinaup.com (ver plan.md) y de var.css / DinaZen.
// Todo es función de t: nada de estado ni aleatoriedad.

const UI = {
  primary:'#1d73e2', success:'#3a8707', danger:'#d04547', text:'#1b1d20', label:'#6b7280',
  border:'#dfe5ec', hb:'#eef1f5', raised:'#f8fafb', faint:'#9ca3af', page:'#f3f6f9',
  okBg:'#f0fdf4', okBorder:'#bbf7d0', ok:'#16a34a', red:'#dc2626',
};
const ESC = 1.5, OX = 60, OY = 140;              // la pantalla lógica en el lienzo
const enLienzo = (lx, ly) => ({ x: OX + lx * ESC, y: OY + ly * ESC });
const ap = (t, t0, d = 0.6) => Easing.easeOutCubic(clamp((t - t0) / d, 0, 1));
const entre = (t, a, b, d = 0.4) => clamp((t - a) / d, 0, 1) * (1 - clamp((t - b) / d, 0, 1));
const FONT = "Roboto, system-ui, 'Segoe UI', Arial, sans-serif";
const eur = (v) => v.toLocaleString('es-ES', { minimumFractionDigits:2, maximumFractionDigits:2 }) + ' €';

function Ico({ n, s = 16, c = UI.label, style }){
  return <span className="material-icons" style={{ fontSize:s, color:c, lineHeight:1, width:s, height:s, display:'inline-block', overflow:'hidden', flexShrink:0, ...style }}>{n}</span>;
}

// ── Lienzo de la escena: fondo liso, rótulo arriba a la izquierda, pantalla de play ampliada ──
function Escena({ t, eyebrow, titulo, children, fuera }){
  const e = ap(t, 0.1, 0.7);
  return (
    <SlideCanvas variant="light" bg="#EEF2F6" grid={false}>
      <div style={{ position:'absolute', left:OX, top:34, opacity:e, transform:`translateY(${(1 - e) * 10}px)` }}>
        <div className="f-mono" style={{ fontSize:17, fontWeight:600, letterSpacing:'2px', color:'#0085FF' }}>{eyebrow}</div>
        <div className="f-plex" style={{ fontSize:38, fontWeight:700, letterSpacing:'-0.02em', color:'#0F172A', marginTop:4 }}>{titulo}</div>
      </div>
      <div style={{ position:'absolute', right:OX, top:52, opacity:0.55 * e }}><DinaupLogo size={30}/></div>
      <div style={{ position:'absolute', left:OX, top:OY, width:1200, height:600, transform:`scale(${ESC})`, transformOrigin:'0 0',
                    fontFamily:FONT, color:UI.text, borderRadius:8, overflow:'hidden', boxShadow:'0 20px 50px rgba(15,23,42,0.14)' }}>
        {children}
      </div>
      {fuera}
    </SlideCanvas>
  );
}

// Recuadro que señala lo que la voz nombra (en coordenadas de play). Sin halo: un trazo y ya.
function Marca({ x, y, w, h, p, color = UI.primary, r = 8 }){
  if (p <= 0) return null;
  return <div style={{ position:'absolute', left:x - 4, top:y - 4, width:w + 8, height:h + 8, borderRadius:r, border:`2.5px solid ${color}`,
                        opacity:p, transform:`scale(${lerp(1.04, 1, p)})`, pointerEvents:'none', zIndex:40 }}/>;
}

// Nota en el lienzo (fuera de la pantalla ampliada): pocas palabras, letra grande.
function Nota({ x, y, p, children, color = '#0F172A', ancla = 'left' }){
  if (p <= 0) return null;
  return (
    <div className="f-plex" style={{ position:'absolute', left:ancla === 'left' ? x : undefined, right:ancla === 'right' ? 1920 - x : undefined, top:y,
      padding:'12px 22px', background:'#fff', border:'1px solid #E2E8F0', borderRadius:12, boxShadow:'0 10px 28px rgba(15,23,42,0.12)',
      fontSize:28, fontWeight:600, color, opacity:p, transform:`translateY(${(1 - p) * 12}px)`, whiteSpace:'nowrap', zIndex:60 }}>
      {children}
    </div>
  );
}

// Cursor con clic visible, todo desde t (el render desactiva las animaciones CSS).
function Cursor({ t, frames, clicks = [], desde = 0, hasta = 1e9 }){
  if (t < desde || t > hasta + 0.4) return null;
  const pl = cursorPathAt(frames, t), c = enLienzo(pl.x, pl.y);
  const k = clicks.find(ct => t >= ct && t < ct + 0.6);
  const kp = k === undefined ? 0 : (t - k) / 0.6;
  return (
    <div style={{ position:'absolute', left:0, top:0, transform:`translate(${c.x}px, ${c.y}px)`, zIndex:80, pointerEvents:'none', opacity:ap(t, desde, 0.4) * (1 - ap(t, hasta, 0.4)) }}>
      {kp > 0 && <div style={{ position:'absolute', left:-22, top:-22, width:44, height:44, borderRadius:100, border:'2.5px solid #0085FF',
                               transform:`scale(${lerp(0.3, 1.3, kp)})`, opacity:1 - kp }}/>}
      <svg width="30" height="38" viewBox="0 0 22 28" style={{ transform:`scale(${k === undefined ? 1 : 0.9})`, transformOrigin:'0 0' }}>
        <path d="M2 2 L2 22 L8 17 L11 24 L14 22 L11 16 L19 16 Z" fill="#fff" stroke="#111" strokeWidth="1.3" strokeLinejoin="round"/>
      </svg>
    </div>
  );
}

// ── Controles con el aspecto de DinaZen ──
function Campo({ x, y, w, label, value, placeholder, disabled, drop = true, icon, foco = 0, req = false }){
  return (
    <div style={{ position:'absolute', left:x, top:y, width:w }}>
      <div style={{ fontSize:12, color:UI.label, marginBottom:3, whiteSpace:'nowrap' }}>{label}{req && <span style={{ color:UI.red }}> *</span>}</div>
      <div style={{ height:30, borderRadius:6, border:`1px solid ${foco > 0 ? UI.primary : UI.border}`, background:disabled ? '#fafafa' : '#fff',
                    boxShadow: foco > 0 ? `0 0 0 3px rgba(52,129,229,${0.15 * foco})` : '0 1px 2px rgba(0,0,0,.04)',
                    display:'flex', alignItems:'center', gap:6, padding:'0 8px', boxSizing:'border-box' }}>
        {icon && <Ico n={icon} s={15}/>}
        <span style={{ flex:1, fontSize:13, color:value ? (disabled ? '#8b8b8b' : UI.text) : '#bdbdbd', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{value || placeholder || ''}</span>
        {drop && <Ico n="expand_more" s={16} c={UI.faint}/>}
      </div>
    </div>
  );
}

function Boton({ x, y, txt, icon, tipo = 'success', variante = 'filled', h = 32, fs = 13.5, w }){
  const col = { success:UI.success, primary:UI.primary, danger:UI.danger, secondary:'#45494f' }[tipo];
  const lleno = variante === 'filled';
  return (
    <div style={{ position:'absolute', left:x, top:y, height:h, width:w, display:'inline-flex', alignItems:'center', justifyContent:'center', gap:6,
                  padding:'0 12px', borderRadius:4, boxSizing:'border-box', whiteSpace:'nowrap',
                  background:lleno ? col : 'transparent', border:variante === 'outlined' ? `1px solid ${col}` : '1px solid transparent',
                  color:lleno ? '#fff' : col, fontSize:fs, fontWeight:500, letterSpacing:'0.02em',
                  boxShadow:lleno ? '0 1px 3px rgba(0,0,0,0.16)' : 'none' }}>
      {icon && <Ico n={icon} s={fs + 3} c={lleno ? '#fff' : col}/>}{txt}
    </div>
  );
}

function Pastilla({ x, y, txt, estado = 'ok' }){
  const s = { ok:[UI.okBg, UI.okBorder, UI.ok, 'check_circle'], err:['#fef2f2', '#fca5a5', UI.red, 'error'] }[estado];
  return (
    <div style={{ position:'absolute', left:x, top:y, height:24, padding:'0 9px', borderRadius:100, background:s[0], border:`1px solid ${s[1]}`,
                  display:'flex', alignItems:'center', gap:4, color:s[2], fontSize:12.5, fontWeight:600 }}>
      <Ico n={s[3]} s={15} c={s[2]}/>{txt}
    </div>
  );
}

// ── La ventana de venta (TPVDialog + TPVU) ──
// Coordenadas fijas en la pantalla lógica: las escenas señalan con ellas (FV.*).
const FV = {
  cliente:{ x:16, y:42, w:200 }, df:{ x:226, y:42, w:170 }, tipo:{ x:406, y:42, w:130 }, envio:{ x:546, y:42, w:140 },
  estado:{ x:790, y:42, w:120 }, fecha:{ x:920, y:42, w:170 }, pill:{ x:1104, y:61, w:62, h:24 },
  linea:{ x:8, y:96, w:1184, h:22 },
  izq:{ x:14, y:124, w:638, h:376 }, resumen:{ x:14, y:506, w:638, h:38 },
  der:{ x:660, y:124, w:530, h:420 }, tabs:{ y:128, h:36 }, contenido:{ y:168 },
  pie:{ y:552 },
  cobrar:{ x:868, y:560, w:92, h:32 }, aceptar:{ x:1004, y:560, w:96, h:32 }, imprimir:{ x:12, y:560, w:96, h:32 },
};
const TABS_DER = [['Agregar','add'], ['Archivo','description'], ['Parámetros','info'], ['Notas','note_stack'], ['Ticket','receipt_long'], ['Flujo','account_tree']];
const tabX = (i) => FV.der.x + 12 + [0, 92, 180, 290, 370, 450][i];

function BarraTitulo({ titulo, icono }){
  return (
    <div style={{ position:'absolute', left:0, top:0, right:0, height:32, background:'#fff', borderBottom:'1px solid rgba(0,0,0,.06)',
                  display:'flex', alignItems:'center', gap:8, padding:'0 0 0 12px' }}>
      <Ico n={icono} s={16} c="#45494f"/>
      <span style={{ fontSize:13, fontWeight:500, color:UI.text }}>{titulo}</span>
      <div style={{ flex:1 }}/>
      {['remove', 'crop_square', 'close'].map(n => <div key={n} style={{ width:44, height:32, display:'flex', alignItems:'center', justifyContent:'center' }}><Ico n={n} s={14} c="#45494f"/></div>)}
    </div>
  );
}

function LineaCard({ x, y, w, nombre, servicio = true, texto = false, und, precio, total, aparece = 1, foco = {}, bloqueada = false }){
  const e = Easing.easeOutCubic(clamp(aparece, 0, 1));
  const Pill = ({ lx, lw, label, val, hi, f }) => (
    <div style={{ position:'absolute', left:lx, top:50, width:lw }}>
      <div style={{ fontSize:10, color:UI.label, marginBottom:2 }}>{label}</div>
      <div style={{ height:24, borderRadius:6, border:`1px solid ${f ? UI.primary : (hi ? '#bbf7d0' : UI.border)}`, background:hi ? UI.okBg : '#fff',
                    display:'flex', alignItems:'center', justifyContent:'flex-end', padding:'0 7px', fontSize:13, fontWeight:hi ? 700 : 400, color:UI.text }}>{val}</div>
    </div>
  );
  return (
    <div style={{ position:'absolute', left:x, top:y, width:w, height:92, borderRadius:8, border:`1px solid ${UI.border}`, background:'#fff',
                  boxShadow:'0 1px 3px rgba(0,0,0,.06)', opacity:e, transform:`translateX(${(1 - e) * 24}px)` }}>
      <div style={{ position:'absolute', left:10, top:8, width:34, height:34, borderRadius:6, background:'#eef4fb', display:'flex', alignItems:'center', justifyContent:'center' }}>
        <Ico n={texto ? 'short_text' : (servicio ? 'design_services' : 'inventory_2')} s={20} c="#7aa7d8"/>
      </div>
      <div style={{ position:'absolute', left:54, top:texto ? 15 : 7, fontSize:13.5, fontWeight:600 }}>{nombre}</div>
      {!texto && <div style={{ position:'absolute', left:54, top:26, display:'flex', alignItems:'center', gap:4, fontSize:11, color:UI.label }}>
        <Ico n="all_inclusive" s={13}/>Sin control de stock
      </div>}
      {!bloqueada && <div style={{ position:'absolute', right:10, top:9, width:28, height:28, borderRadius:4, border:`1px solid ${UI.danger}`, display:'flex', alignItems:'center', justifyContent:'center' }}>
        <Ico n="close" s={16} c={UI.danger}/>
      </div>}
      <Pill lx={10} lw={58} label="Und" val={und} f={foco.und}/>
      <Pill lx={76} lw={92} label="Precio" val={precio} f={foco.precio}/>
      <div style={{ position:'absolute', left:174, top:66, color:UI.faint }}><Ico n="chevron_right" s={16} c={UI.faint}/></div>
      <Pill lx={w - 290} lw={92} label="Subtotal" val={total}/>
      <Pill lx={w - 190} lw={66} label="Impuestos" val="21 %"/>
      <Pill lx={w - 116} lw={104} label="Total" val={total} hi/>
    </div>
  );
}

// estado: { cliente, df, envio, fecha, numeroVisible, pill, pillEstado, tab, lineas:[{nombre,und,precio,total,aparece,foco}],
//           sub, iva, total, aceptar:'ok'|'err', emitida, derecha (ReactNode), resumenFoco }
function VentanaVenta(s){
  const lineas = s.lineas || [];
  return (
    <div style={{ position:'absolute', inset:0, background:'#fff' }}>
      <BarraTitulo titulo="Venta / Ingreso" icono="point_of_sale"/>
      {/* Barra de arriba (TPVHeaderBarU) */}
      <div style={{ position:'absolute', left:0, right:0, top:32, height:62, background:UI.raised, borderBottom:`1px solid ${UI.hb}` }}/>
      <Campo {...FV.cliente} label="Cliente" value={s.cliente} placeholder="Selecciona un Cliente" req foco={s.focoCliente || 0} disabled={s.emitida}/>
      <Campo {...FV.df} label="Datos fiscales" value={s.df} disabled={s.emitida}/>
      <Campo {...FV.tipo} label="Tipo Venta" value="Factura" disabled={s.emitida}/>
      <Campo {...FV.envio} label="Envío" value={s.envio} disabled={s.emitida}/>
      {s.numero ? <>
        <Campo x={700} y={42} w={100} label="Estado" value={s.estado}/>
        <Campo x={810} y={42} w={100} label="Número" value={s.numero} drop={false} disabled/>
      </> : <Campo {...FV.estado} label="Estado" value={s.estado}/>}
      <Campo {...FV.fecha} label="Fecha" value={s.fecha} drop={false} icon="calendar_today" disabled={s.emitida}/>
      {s.df && <Pastilla x={FV.pill.x} y={FV.pill.y} txt={s.pill || '5/5'} estado={s.pillEstado || 'ok'}/>}
      {/* Línea de datos fiscales (TPVHeader_QuickDatosFiscalesyEnvioBarU) */}
      {s.lineaDF > 0 && (
        <div style={{ position:'absolute', left:FV.linea.x, top:FV.linea.y, width:FV.linea.w, height:FV.linea.h, borderRadius:8, border:`1px solid ${UI.hb}`, background:'#fff',
                      display:'flex', alignItems:'center', gap:5, padding:'0 12px', fontSize:11, opacity:s.lineaDF, boxSizing:'border-box' }}>
          <Ico n="contact_page" s={13} c="rgba(0,0,0,0.35)"/>
          <span style={{ fontWeight:600 }}>B50123456</span>
          <span style={{ color:UI.label }}>C/ Mayor 12, 50001 Zaragoza (Zaragoza)</span>
          <span style={{ color:UI.label, marginLeft:6 }}>976 123 456</span>
        </div>
      )}
      {/* Izquierda: Seleccionados */}
      <div style={{ position:'absolute', left:FV.izq.x, top:FV.izq.y, width:FV.izq.w, height:FV.izq.h, border:`1px solid ${UI.hb}`, borderRadius:6, background:'#fff', overflow:'hidden' }}>
        <span style={{ position:'absolute', left:8, top:8, fontSize:10.5, fontWeight:600, letterSpacing:'0.08em', textTransform:'uppercase', padding:'3px 8px',
                       background:UI.raised, border:`1px solid ${UI.hb}`, borderRadius:5 }}>Seleccionados</span>
        {lineas.length === 0 && !s.ocultaVacio && (
          <div style={{ position:'absolute', left:0, right:0, top:130, textAlign:'center' }}>
            <div style={{ fontSize:15, fontWeight:600 }}>Sin conceptos</div>
            <div style={{ fontSize:12.5, color:UI.label, marginTop:4 }}>Añade productos o servicios a esta operación</div>
          </div>
        )}
        {lineas.map((l, i) => <LineaCard key={i} x={8} y={38 + i * 100} w={FV.izq.w - 18} bloqueada={!!s.emitida} {...l}/>)}
      </div>
      {/* Barra de resumen (TPVSummaryBarU) */}
      <div style={{ position:'absolute', left:FV.resumen.x, top:FV.resumen.y, width:FV.resumen.w, height:FV.resumen.h, borderRadius:8, border:`1px solid ${UI.hb}`,
                    background:'#fff', display:'flex', alignItems:'center', justifyContent:'flex-end', gap:10, padding:'0 14px', boxSizing:'border-box' }}>
        <span style={{ fontSize:12, color:UI.label, fontWeight:500 }}>Sub.</span><span style={{ fontSize:15 }}>{eur(s.sub || 0)}</span>
        <span style={{ width:1, height:18, background:UI.hb }}/>
        <span style={{ fontSize:12, color:UI.label, fontWeight:500 }}>IVA</span><span style={{ fontSize:15 }}>{eur(s.iva || 0)}</span>
        <span style={{ width:1, height:18, background:UI.hb }}/>
        <span style={{ fontSize:12, color:UI.label, fontWeight:500 }}>Total</span><span style={{ fontSize:18, fontWeight:700 }}>{eur(s.total || 0)}</span>
      </div>
      {/* Derecha: pestañas (TPVPanelDerechaU) */}
      <div style={{ position:'absolute', left:FV.der.x, top:FV.der.y, width:FV.der.w, height:FV.der.h, borderRadius:8, border:`1px solid ${UI.hb}`, background:'#fff',
                    boxShadow:'0 1px 3px rgba(0,0,0,.06)', overflow:'hidden' }}>
        <div style={{ position:'absolute', left:0, right:0, top:40, height:1, background:UI.hb }}/>
        {TABS_DER.map(([txt, ic], i) => {
          const on = (s.tab || 'Agregar') === txt;
          return (
            <div key={txt} style={{ position:'absolute', left:tabX(i) - FV.der.x, top:4, height:36, display:'flex', alignItems:'center', gap:5, padding:'0 6px',
                                    color:on ? UI.primary : '#45494f', fontSize:12.5, fontWeight:on ? 600 : 400, borderBottom:on ? `2px solid ${UI.primary}` : '2px solid transparent', boxSizing:'border-box' }}>
              <Ico n={ic} s={16} c={on ? UI.primary : '#6b7280'}/>{txt}
            </div>
          );
        })}
        <div style={{ position:'absolute', left:0, top:44, right:0, bottom:0, overflow:'hidden' }}>{s.derecha}</div>
      </div>
      {/* Pie (TPVFooterU dentro de TPVDialog) */}
      <div style={{ position:'absolute', left:0, right:0, top:FV.pie.y, height:48, borderTop:`1px solid ${UI.hb}`, background:'#fff' }}/>
      <Boton x={FV.imprimir.x} y={FV.imprimir.y} txt="Imprimir" icon="print" tipo="secondary" variante="text"/>
      <Boton x={108} y={560} txt="Flujo" icon="account_tree" tipo="secondary" variante="text"/>
      <Boton x={FV.cobrar.x} y={FV.cobrar.y} w={FV.cobrar.w} txt="Cobrar" icon="payments" tipo="primary"/>
      <div style={{ position:'absolute', left:966, top:566, height:20, padding:'0 6px', borderRadius:4, border:`1px solid ${UI.border}`, fontSize:11, fontWeight:600,
                    color:'#45494f', display:'flex', alignItems:'center' }}>F4</div>
      <Boton x={FV.aceptar.x} y={FV.aceptar.y} w={FV.aceptar.w} txt="Aceptar" icon={s.aceptar === 'err' ? 'error' : 'check'} tipo={s.aceptar === 'err' ? 'danger' : 'success'}/>
      <Boton x={1108} y={560} txt="Cerrar" icon="close" tipo="danger" variante="text" w={84}/>
      {s.encima}
    </div>
  );
}

// Tarjeta de producto del catálogo (ConceptoU sin seleccionar)
function ProductoCat({ x, y, w, nombre, precio, foco = 0 }){
  return (
    <div style={{ position:'absolute', left:x, top:y, width:w, height:54, borderRadius:8, border:`1px solid ${foco > 0 ? UI.primary : UI.border}`, background:'#fff' }}>
      <div style={{ position:'absolute', left:10, top:10, width:34, height:34, borderRadius:6, background:'#eef4fb', display:'flex', alignItems:'center', justifyContent:'center' }}>
        <Ico n="design_services" s={20} c="#7aa7d8"/>
      </div>
      <div style={{ position:'absolute', left:54, top:9, fontSize:13.5, fontWeight:600 }}>{nombre}</div>
      <div style={{ position:'absolute', left:54, top:29, display:'flex', alignItems:'center', gap:4, fontSize:11, color:UI.label }}><Ico n="all_inclusive" s={13}/>Sin control de stock</div>
      <div style={{ position:'absolute', right:52, top:17, fontSize:13.5 }}>{precio}</div>
      <div style={{ position:'absolute', right:10, top:13, width:28, height:28, borderRadius:4, background:UI.success, display:'flex', alignItems:'center', justifyContent:'center' }}>
        <Ico n="add" s={18} c="#fff"/>
      </div>
    </div>
  );
}

// Pestaña «Agregar» (BuscadorConceptosGaleriaU) en coordenadas relativas al contenido del panel
function PanelAgregar({ busqueda = '', sub = 'Catálogo', productos = [], focoBuscar = 0, resultado }){
  const W = FV.der.w;
  return (
    <div style={{ position:'absolute', inset:0 }}>
      <div style={{ position:'absolute', left:14, top:10, width:W - 28, height:44, borderRadius:4, background:'#f3f6f9',
                    border:`1px solid ${focoBuscar > 0 ? UI.primary : 'transparent'}`, borderBottom:`1px solid ${focoBuscar > 0 ? UI.primary : '#c4ccda'}` }}>
        <div style={{ position:'absolute', left:12, top:13 }}><Ico n="search" s={18}/></div>
        <div style={{ position:'absolute', left:38, top:busqueda ? 4 : 13, fontSize:busqueda ? 10.5 : 13.5, color:focoBuscar > 0 ? UI.primary : UI.label }}>¿Qué desea Vender?</div>
        {busqueda && <div style={{ position:'absolute', left:38, top:20, fontSize:13.5 }}>{busqueda}</div>}
      </div>
      {resultado ? resultado : (
        <>
          {[['Catálogo', 'storefront'], ['Recientes', 'history']].map(([txt, ic], i) => {
            const on = sub === txt;
            return <div key={txt} style={{ position:'absolute', left:14 + i * 104, top:64, height:30, display:'flex', alignItems:'center', gap:5, padding:'0 6px',
                                           fontSize:12.5, color:on ? UI.primary : '#45494f', fontWeight:on ? 600 : 400, borderBottom:on ? `2px solid ${UI.primary}` : '2px solid transparent' }}>
                     <Ico n={ic} s={16} c={on ? UI.primary : UI.label}/>{txt}</div>;
          })}
          <div style={{ position:'absolute', left:14, right:14, top:95, height:1, background:UI.hb }}/>
          {sub === 'Catálogo' ? (
            <>
              <div style={{ position:'absolute', left:20, top:106, display:'flex', alignItems:'center', gap:8 }}>
                <span style={{ fontSize:11, fontWeight:600, padding:'2px 8px', borderRadius:10, background:'#e3eaf2' }}>4 productos</span>
                <span style={{ fontSize:11.5, color:UI.label }}>Escribe arriba para buscar un producto concreto.</span>
              </div>
              {productos.map((p, i) => <ProductoCat key={p.nombre} x={20} y={132 + i * 60} w={W - 40} {...p}/>)}
            </>
          ) : (
            <div style={{ position:'absolute', left:20, top:108, right:20, height:236, border:'1px dashed #9829B6', borderRadius:6 }}>
              <span style={{ position:'absolute', left:8, top:8, fontSize:10.5, fontWeight:600, letterSpacing:'0.08em', textTransform:'uppercase', color:'#fff',
                             background:'#9829B6', borderRadius:5, padding:'3px 6px', display:'flex', alignItems:'center', gap:3 }}><Ico n="search" s={11} c="#fff"/>Recientes</span>
              {productos.slice(0, 2).map((p, i) => <ProductoCat key={p.nombre} x={8} y={40 + i * 60} w={W - 58} {...p}/>)}
            </div>
          )}
        </>
      )}
    </div>
  );
}

// ── Facturas Emitidas (PymesPage + FacturasEmitidasSubpage) ──
const MENU_PYMES = [
  { txt:'Inicio', ic:'home' }, { txt:'Empresa', ic:'business' },
  { sec:'Preventa', col:'#085786' }, { txt:'Presupuestos', ic:'request_quote' }, { txt:'Pedidos', ic:'shopping_cart_checkout' },
  { sec:'Ventas & Ingresos', col:UI.success }, { txt:'Facturas Emitidas', ic:'receipt_long', on:true }, { txt:'Otros Ingresos', ic:'trending_up' },
  { sec:'Compras & Gastos', col:UI.danger }, { txt:'Facturas Recibidas', ic:'assignment_returned' }, { txt:'Otros Gastos', ic:'trending_down' }, { txt:'Nóminas', ic:'universal_currency' },
  { sec:'Entidades', col:'#9c75f0' }, { txt:'Clientes', ic:'group' }, { txt:'Proveedores', ic:'work' },
];
const FACTURAS = [
  { n:'F2026-0042', f:'07/10/2026', c:'Distribuciones Moncayo, S.L.', tot:'1.210,00 €' },
  { n:'F2026-0041', f:'02/10/2026', c:'Talleres Ebro, S.L.', tot:'363,00 €' },
  { n:'F2026-0040', f:'30/09/2026', c:'Clínica Dental Delicias', tot:'544,50 €' },
  { n:'F2026-0039', f:'26/09/2026', c:'Hostal El Pilar', tot:'217,80 €' },
];
const FILA0 = 196;   // y de la primera fila de la lista

function PantallaFacturas({ tab = 'Facturas emitidas', menuFoco = 0, botonFoco = 0, nueva, cobros, dimMenu = 0 }){
  const filas = nueva ? [nueva, ...FACTURAS] : FACTURAS;
  return (
    <div style={{ position:'absolute', inset:0, background:UI.page }}>
      {/* Cabecera */}
      <div style={{ position:'absolute', left:0, right:0, top:0, height:44, background:'#fff', boxShadow:'0 1px 4px rgba(0,0,0,0.08)', display:'flex', alignItems:'center', gap:12, padding:'0 14px' }}>
        <Ico n="menu" s={20} c="#343a40"/><span style={{ fontSize:16, fontWeight:500, color:'#343a40' }}>Pymes</span>
        <div style={{ flex:1 }}/>
        <div style={{ width:28, height:28, borderRadius:100, background:'#e3eaf2', color:'#45494f', fontSize:12, fontWeight:700, display:'flex', alignItems:'center', justifyContent:'center' }}>MJ</div>
      </div>
      {/* Menú lateral */}
      <div style={{ position:'absolute', left:0, top:44, bottom:0, width:230, background:'#fff', borderRight:`1px solid ${UI.hb}`, paddingTop:8 }}>
        {MENU_PYMES.map((m, i) => m.sec ? (
          <div key={m.sec} style={{ fontSize:11, fontWeight:700, letterSpacing:'0.06em', textTransform:'uppercase', color:m.col, padding:'10px 18px 4px', opacity:1 - dimMenu * 0.5 }}>{m.sec}</div>
        ) : (
          <div key={m.txt} style={{ display:'flex', alignItems:'center', gap:12, height:30, margin:'0 8px', padding:'0 10px', borderRadius:4,
                                    background:m.on ? 'rgba(0,111,255,0.10)' : 'transparent', color:m.on ? UI.primary : '#45494f', fontSize:13.5, fontWeight:m.on ? 500 : 400,
                                    outline:m.on && menuFoco > 0 ? `2px solid rgba(29,115,226,${menuFoco})` : 'none', opacity:m.on ? 1 : 1 - dimMenu * 0.5 }}>
            <Ico n={m.ic} s={18} c={m.on ? UI.primary : '#6b7280'}/>{m.txt}
          </div>
        ))}
      </div>
      {/* Cuerpo: pestañas + lista */}
      <div style={{ position:'absolute', left:246, top:58, right:16, bottom:16, background:'#fff', borderRadius:8, border:`1px solid ${UI.hb}`, overflow:'hidden' }}>
        {[['Facturas emitidas', 'receipt_long'], ['Conceptos', 'list_alt'], ['Cobros', 'paid']].map(([txt, ic], i) => {
          const on = tab === txt;
          return <div key={txt} style={{ position:'absolute', left:[12, 186, 316][i], top:4, height:38, display:'flex', alignItems:'center', gap:6, padding:'0 8px', fontSize:13,
                                         color:on ? UI.primary : '#45494f', fontWeight:on ? 600 : 400, borderBottom:on ? `2px solid ${UI.primary}` : '2px solid transparent', boxSizing:'border-box' }}>
                   <Ico n={ic} s={17} c={on ? UI.primary : UI.label}/>{txt}</div>;
        })}
        <div style={{ position:'absolute', left:0, right:0, top:42, height:1, background:UI.hb }}/>
        {tab === 'Cobros' ? cobros : (
          <>
            {/* Barra de la lista: un botón verde por tipo de venta (ToolBarsVentaU) */}
            <div style={{ position:'absolute', left:16, top:56, display:'flex', gap:8 }}>
              {['Factura', 'Factura simplificada'].map((txt, i) => (
                <div key={txt} style={{ height:26, padding:'0 10px', borderRadius:4, background:UI.success, color:'#fff', fontSize:12, fontWeight:500, display:'flex', alignItems:'center', gap:4,
                                        boxShadow:'0 1px 3px rgba(0,0,0,0.16)', outline:i === 0 && botonFoco > 0 ? `2.5px solid rgba(29,115,226,${botonFoco})` : 'none', outlineOffset:3 }}>
                  <Ico n="add" s={15} c="#fff"/>{txt}
                </div>
              ))}
            </div>
            <Tabla cols={[['Número', 16], ['Fecha', 150], ['Cliente', 270], ['Total', 600]]} filas={filas.map(f => [f.n, f.f, f.c, f.tot])} resalta={nueva ? 0 : -1} y0={FILA0 - 58 - 34}/>
          </>
        )}
      </div>
    </div>
  );
}

function Tabla({ cols, filas, resalta = -1, y0 = 102, pRes = 1 }){
  return (
    <div style={{ position:'absolute', left:0, right:0, top:y0 }}>
      <div style={{ position:'relative', height:34, background:UI.raised, borderTop:`1px solid ${UI.hb}`, borderBottom:`1px solid ${UI.hb}` }}>
        {cols.map(([c, x]) => <span key={c} style={{ position:'absolute', left:x, top:9, fontSize:12, fontWeight:600, color:UI.label }}>{c}</span>)}
      </div>
      {filas.map((f, i) => (
        <div key={i} style={{ position:'relative', height:36, borderBottom:`1px solid ${UI.hb}`, background:i === resalta ? `rgba(29,115,226,${0.08 * pRes})` : '#fff' }}>
          {f.map((v, j) => <span key={j} style={{ position:'absolute', left:cols[j][1], top:9, fontSize:13, fontWeight:i === resalta && j === 0 ? 700 : 400 }}>{v}</span>)}
        </div>
      ))}
    </div>
  );
}

// Rótulo final con la Única Cosa: tres frases, cada una cuando la voz la dice.
function UnicaCosa({ t, tA, tB, tC, top = 380 }){
  const fr = [['Arriba, a quién.', tA], ['A la derecha, qué.', tB], ['Abajo, Aceptar.', tC]];
  return (
    <div style={{ position:'absolute', left:0, right:0, top, textAlign:'center', zIndex:70 }}>
      {fr.map(([txt, t0], i) => {
        const e = ap(t, t0, 0.6);
        return <div key={i} className="f-plex" style={{ fontSize:66, fontWeight:700, letterSpacing:'-0.02em', lineHeight:1.25,
                     color:i === 2 ? UI.success : '#0F172A', opacity:e, transform:`translateY(${(1 - e) * 14}px)` }}>{txt}</div>;
      })}
    </div>
  );
}

Object.assign(window, { UI, ESC, OX, OY, enLienzo, ap, entre, eur, Ico, Escena, Marca, Nota, Cursor, Campo, Boton, Pastilla, FV, TABS_DER, tabX,
  VentanaVenta, LineaCard, ProductoCat, PanelAgregar, PantallaFacturas, Tabla, FACTURAS, FILA0, UnicaCosa });
