// === comun.jsx — piezas de play compartidas por las escenas de «El TPV: cobrar y cerrar la caja» ===
// Todo se dibuja como función de t (el motor puede saltar a cualquier segundo). Los textos de botones,
// pestañas, campos y títulos son los de play (rutas en plan.md). Paleta de wwwroot/css/var.css:
// primary #1d73e2 · success #3a8707 · danger #d04547. Iconos: Material Symbols Rounded (_Host.cshtml).

const C = {
  azul:'#1d73e2', verde:'#3a8707', rojo:'#d04547', ambar:'#f59e0b', teal:'#14a3a3',
  tinta:'#0F172A', texto:'#334155', gris:'#64748B', grisC:'#94A3B8', borde:'#E2E8F0', bordeF:'#CBD5E1',
  fondo:'#F3F5F9', panel:'#F8FAFC',
};
const ROBOTO = "'Roboto', 'IBM Plex Sans', sans-serif";

// ── Tiempo ──
const ent = (t, s, d = 0.7) => Easing.easeOutCubic(clamp((t - s) / d, 0, 1));
const sal = (t, s, d = 0.5) => 1 - Easing.easeOutCubic(clamp((t - s) / d, 0, 1));
// Resalte que entra en s y se va en e (anillo de foco, no un halo): 0..1
const foco = (t, s, e = 1e9, d = 0.45) => Math.min(clamp((t - s) / d, 0, 1), clamp((e - t) / d, 0, 1));
const anillo = (a, color = C.azul) => a > 0 ? `0 0 0 ${Math.round(2 + 2 * a)}px ${color}${Math.round(a * 200).toString(16).padStart(2, '0')}` : 'none';
// Un solo pulso (remate), sin bucle
const pulso = (t, s, d = 1.1) => (t >= s && t < s + d) ? Math.sin((t - s) / d * Math.PI) : 0;
const euros = (v) => v.toFixed(2).replace('.', ',') + ' €';

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

// Botón de Radzen (Material): filled / outlined / text
function Btn({ txt, ico, tipo = 'primary', variante = 'filled', h = 44, fs = 17, a = 0, style, children }){
  const col = { primary:C.azul, success:C.verde, danger:C.rojo, light:C.gris, warning:C.ambar }[tipo];
  const filled = variante === 'filled';
  return (
    <div style={{ display:'inline-flex', alignItems:'center', gap:8, height:h, padding: txt ? '0 18px' : '0 10px', borderRadius:6,
      background: filled ? col : (variante === 'outlined' ? '#fff' : 'transparent'),
      border: variante === 'outlined' ? `1px solid ${col}` : '1px solid transparent',
      color: filled ? '#fff' : col, fontFamily:ROBOTO, fontSize:fs, fontWeight:500, whiteSpace:'nowrap',
      boxShadow: a > 0 ? anillo(a, col) : (filled ? '0 2px 6px rgba(15,23,42,0.12)' : 'none'), ...style }}>
      {ico && <Ico n={ico} s={fs + 5} c={filled ? '#fff' : col}/>}
      {txt && <span>{txt}</span>}
      {children}
    </div>
  );
}

// Campo de formulario Radzen «Flat»: etiqueta pequeña arriba, valor debajo
function Campo({ label, valor, placeholder, w = 260, h = 58, a = 0, obli = false, children, style }){
  return (
    <div style={{ position:'relative', width:w, height:h, borderRadius:6, background:'#fff', boxSizing:'border-box',
      border:`1px solid ${obli ? C.rojo : C.bordeF}`, boxShadow:anillo(a), padding:'6px 12px', fontFamily:ROBOTO, ...style }}>
      <div style={{ fontSize:13, color:C.gris }}>{label}</div>
      <div style={{ fontSize:19, color: valor ? C.tinta : C.grisC, marginTop:2, whiteSpace:'nowrap', overflow:'hidden', display:'flex', alignItems:'center', gap:6 }}>
        {valor || placeholder}{children}
      </div>
    </div>
  );
}

function Insignia({ txt, color, fondo, style }){
  return <span style={{ display:'inline-flex', alignItems:'center', height:26, padding:'0 10px', borderRadius:13, background:fondo || color, color: fondo ? color : '#fff', fontFamily:ROBOTO, fontSize:14, fontWeight:600, ...style }}>{txt}</span>;
}

// ── Títulos de la escena (fuera de la ventana de play) ──
function Rotulo({ t, paso, titulo, s = 0 }){
  const p = ent(t, s, 0.8);
  return (
    <div style={{ position:'absolute', left:110, top:34, opacity:p, transform:`translateY(${(1 - p) * 10}px)` }}>
      <div className="f-mono" style={{ fontSize:15, fontWeight:600, letterSpacing:'2px', color:C.azul }}>{paso}</div>
      <div className="f-plex" style={{ fontSize:36, fontWeight:700, letterSpacing:'-0.02em', color:C.tinta, marginTop:6 }}>{titulo}</div>
    </div>
  );
}

function Fondo({ children }){
  return <SlideCanvas variant="light-soft" bg="#EEF2F7" grid={false}>{children}</SlideCanvas>;
}

// ── La ventana del navegador con play dentro ──
const VX = 110, VY = 136, VW = 1700, VH = 910;
function Ventana({ url, children, style }){
  return (
    <div style={{ position:'absolute', left:VX, top:VY, width:VW, height:VH, borderRadius:14, overflow:'hidden', background:C.fondo,
      border:`1px solid ${C.bordeF}`, boxShadow:'0 24px 60px rgba(15,23,42,0.12)', display:'flex', flexDirection:'column', ...style }}>
      <BrowserChrome url={url} title="Dinaup Play"/>
      <div style={{ position:'relative', flex:1, overflow:'hidden', fontFamily:ROBOTO }}>{children}</div>
    </div>
  );
}

// ── Cabecera + menú lateral de la app TPV (TPVPage.razor) ──
function AppTPV({ activo, children, aMenu = {}, sidebarOp = 1 }){
  const Item = ({ ico, txt, id, color }) => (
    <div style={{ display:'flex', alignItems:'center', gap:12, height:44, padding:'0 14px', borderRadius:8, margin:'2px 0',
      background: activo === id ? 'rgba(29,115,226,0.10)' : 'transparent', boxShadow:anillo(aMenu[id] || 0) }}>
      <Ico n={ico} s={22} c={activo === id ? C.azul : (color || '#7C8AA0')}/>
      <span style={{ fontSize:17, fontWeight: activo === id ? 600 : 400, color: activo === id ? C.azul : C.texto }}>{txt}</span>
    </div>
  );
  const Seccion = ({ txt, color }) => (
    <div style={{ display:'flex', alignItems:'center', gap:8, padding:'14px 14px 4px' }}>
      <span style={{ width:4, height:14, borderRadius:2, background:color }}/>
      <span style={{ fontSize:13, fontWeight:700, letterSpacing:'1.2px', color:'#8494A8' }}>{txt.toUpperCase()}</span>
    </div>
  );
  return (
    <div style={{ position:'absolute', inset:0 }}>
      <div style={{ position:'absolute', left:0, right:0, top:0, height:60, background:'#fff', borderBottom:`1px solid ${C.borde}`, display:'flex', alignItems:'center', padding:'0 22px', gap:18 }}>
        <DinaupLogo size={22}/>
        <span style={{ width:1, height:26, background:C.borde }}/>
        <Ico n="point_of_sale" s={24} c={C.azul}/>
        <span style={{ fontSize:20, fontWeight:600, color:C.tinta }}>TPV</span>
        <div style={{ flex:1 }}/>
        <span style={{ fontSize:15, color:C.gris }}>Ferretería Lozano, S.L.</span>
        <div style={{ width:34, height:34, borderRadius:17, background:C.azul, color:'#fff', display:'flex', alignItems:'center', justifyContent:'center', fontSize:14, fontWeight:600 }}>MR</div>
      </div>
      <div style={{ position:'absolute', left:0, top:60, bottom:0, width:300, background:'#fff', borderRight:`1px solid ${C.borde}`, padding:'0 12px', opacity:sidebarOp }}>
        <div style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:10, padding:'26px 18px 18px' }}>
          <Btn txt="Iniciar" ico="play_arrow" h={50} fs={19} a={aMenu.iniciar || 0}/>
          <Btn txt="Iniciar Pantalla Completa" ico="fullscreen" variante="outlined" h={36} fs={14} a={aMenu.iniciarPC || 0} style={{ width:'100%', justifyContent:'center', boxSizing:'border-box' }}/>
        </div>
        <Item ico="home" txt="Inicio" id="inicio"/>
        <Seccion txt="Ventas" color={C.verde}/>
        <Item ico="request_quote" txt="Presupuestos" id="presupuestos"/>
        <Item ico="shopping_cart_checkout" txt="Pedidos" id="pedidos"/>
        <Item ico="receipt_long" txt="Ventas" id="ventas"/>
        <Item ico="group" txt="Clientes" id="clientes"/>
        <Seccion txt="Cajas" color={C.teal}/>
        <Item ico="point_of_sale" txt="Cajas" id="cajas"/>
        <Item ico="lock" txt="Cierres de Caja" id="cierres"/>
      </div>
      <div style={{ position:'absolute', left:300, right:0, top:60, bottom:0, background:C.fondo, overflow:'hidden' }}>{children}</div>
    </div>
  );
}

// DnzCard: tarjeta blanca de play
function Tarjeta({ children, style, a = 0 }){
  return <div style={{ position:'absolute', background:'#fff', borderRadius:10, border:`1px solid ${C.borde}`, boxShadow: a > 0 ? `${anillo(a)}, 0 6px 18px rgba(15,23,42,0.06)` : '0 4px 14px rgba(15,23,42,0.05)', boxSizing:'border-box', ...style }}>{children}</div>;
}

// ── Pastilla de precio (PillDisplayU / PillNumericU con LabelTop) ──
function Pastilla({ label, valor, w = 110, fuerte = false, a = 0 }){
  return (
    <div style={{ width:w, borderRadius:8, border:`1px solid ${fuerte ? 'rgba(29,115,226,0.35)' : C.borde}`, background: fuerte ? 'rgba(29,115,226,0.06)' : '#fff',
      padding:'4px 10px', boxSizing:'border-box', boxShadow:anillo(a) }}>
      <div style={{ fontSize:12, color:C.gris }}>{label}</div>
      <div style={{ fontSize:18, fontWeight: fuerte ? 700 : 500, color: fuerte ? C.azul : C.tinta, whiteSpace:'nowrap' }}>{valor}</div>
    </div>
  );
}

// ── Catálogo de la ferretería de ejemplo (precios con impuestos incluidos, 21 %) ──
const PRODUCTOS = [
  { id:'guantes', nombre:'Guantes de trabajo',  precio:7.50, stock:24 },
  { id:'cinta',   nombre:'Cinta americana',     precio:6.10, stock:18 },
  { id:'pilas',   nombre:'Pilas AA (4 uds)',    precio:4.90, stock:40 },
  { id:'bridas',  nombre:'Bridas de nailon',    precio:3.20, stock:65 },
  { id:'metro',   nombre:'Cinta métrica 5 m',   precio:8.90, stock:12 },
  { id:'destor',  nombre:'Destornillador plano',precio:5.40, stock:30 },
];
const base = (v) => Math.round(v / 1.21 * 100) / 100;

function FotoProducto({ s = 46 }){
  return (
    <div style={{ width:s, height:s, borderRadius:8, background:'#EEF3FA', border:`1px solid ${C.borde}`, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
      <Ico n="inventory_2" s={s * 0.55} c="#8FA6C4"/>
    </div>
  );
}

// Tarjeta de producto del catálogo (ProductoCardUv2 sin seleccionar): botón verde +
function ProductoCatalogo({ prod, x, y, w, aMas = 0, aCard = 0, pulsado = 0 }){
  return (
    <Tarjeta a={aCard} style={{ left:x, top:y, width:w, height:150, padding:'12px 14px' }}>
      <div style={{ display:'flex', alignItems:'center', gap:12 }}>
        <FotoProducto/>
        <div style={{ flex:1, minWidth:0 }}>
          <div style={{ fontSize:18, fontWeight:600, color:C.tinta, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{prod.nombre}</div>
          <div style={{ display:'inline-flex', alignItems:'center', gap:4, marginTop:4, padding:'1px 8px', borderRadius:10, background:'#F1F5F9', fontSize:13, color:C.gris }}>
            <Ico n="inventory_2" s={14}/> {prod.stock} <span>uds</span>
          </div>
        </div>
        <div style={{ width:40, height:40, borderRadius:6, background:C.verde, display:'flex', alignItems:'center', justifyContent:'center',
          boxShadow:anillo(aMas, C.verde), transform:`scale(${1 - 0.08 * pulsado})` }}>
          <Ico n="add" s={26} c="#fff"/>
        </div>
      </div>
      <div style={{ display:'flex', gap:8, marginTop:14 }}>
        <Pastilla label="Und" valor="1" w={60}/>
        <Pastilla label="Precio" valor={euros(prod.precio)} w={104}/>
        <Pastilla label="Total" valor={euros(prod.precio)} w={104} fuerte/>
      </div>
    </Tarjeta>
  );
}

// Línea seleccionada en el ticket (ConceptoU seleccionado): × para quitar, pastillas editables
function LineaTicket({ prod, y, w, p = 1, aUnd = 0, aPrecio = 0, aTotal = 0 }){
  const e = Easing.easeOutCubic(clamp(p, 0, 1));
  return (
    <Tarjeta style={{ left:16, top:y, width:w, height:132, padding:'12px 16px', opacity:e, transform:`translateX(${(1 - e) * 30}px)` }}>
      <div style={{ display:'flex', alignItems:'center', gap:12 }}>
        <FotoProducto s={42}/>
        <div style={{ flex:1, fontSize:19, fontWeight:600, color:C.tinta }}>{prod.nombre}</div>
        <div style={{ width:36, height:36, borderRadius:6, border:`1px solid ${C.rojo}`, display:'flex', alignItems:'center', justifyContent:'center' }}>
          <Ico n="close" s={22} c={C.rojo}/>
        </div>
      </div>
      <div style={{ display:'flex', gap:10, marginTop:12, alignItems:'center' }}>
        <Pastilla label="Und" valor="1" w={70} a={aUnd}/>
        <Pastilla label="Precio" valor={euros(prod.precio)} w={116} a={aPrecio}/>
        <Ico n="chevron_right" s={22} c={C.grisC}/>
        <div style={{ flex:1 }}/>
        <Pastilla label="Subtotal" valor={euros(base(prod.precio))} w={116}/>
        <Pastilla label="Total" valor={euros(prod.precio)} w={116} fuerte a={aTotal}/>
      </div>
    </Tarjeta>
  );
}

// ── La venta a pantalla completa (TPVFullPageSubpageU + TPVU) ──
// lineas: [{ prod, p }] · r: resaltes 0..1 · totales: { sub, iva, total } o null
function PantallaVenta({ t, lineas = [], r = {}, totales = null, verdes = {}, pulsados = {} }){
  const LW = 900;                    // panel izquierdo
  return (
    <div style={{ position:'absolute', inset:0, background:C.fondo }}>
      {/* Barra superior */}
      <div style={{ position:'absolute', left:0, right:0, top:0, height:54, background:'#fff', borderBottom:`1px solid ${C.borde}`, display:'flex', alignItems:'center', padding:'0 20px', gap:16 }}>
        <DinaupLogo size={22}/>
        <span style={{ fontSize:17, fontWeight:600, color:C.texto }}>Venta</span>
        <div style={{ flex:1 }}/>
        <Btn txt="Imprimir" ico="print" variante="text" tipo="light" h={36} fs={15}/>
        <Btn txt="Flujo" ico="account_tree" variante="text" tipo="light" h={36} fs={15}/>
        <Btn txt="Salir" ico="fullscreen_exit" variante="text" tipo="light" h={36} fs={15} a={r.salir || 0}/>
      </div>
      {/* Cabecera de la venta */}
      <div style={{ position:'absolute', left:16, right:16, top:66, height:62, display:'flex', alignItems:'center', gap:12 }}>
        <Campo label="Cliente" placeholder="Selecciona un Cliente" w={250} h={58}/>
        <Campo label="Tipo Venta" valor="Ticket mostrador" w={220} h={58}/>
        <div style={{ flex:1 }}/>
        <Campo label="Estado" valor="Emitida" w={170} h={58}/>
        <Campo label="Fecha" valor="09/10/2026 17:42" w={210} h={58}/>
      </div>
      {/* Izquierda: seleccionados + barra de totales */}
      <div style={{ position:'absolute', left:16, top:140, width:LW, bottom:76, background:'#fff', borderRadius:10, border:`1px solid ${C.borde}`, boxShadow:anillo(r.lista || 0) }}>
        <div style={{ position:'absolute', left:16, top:12 }}>
          <span style={{ fontSize:13, fontWeight:600, letterSpacing:'1.4px', color:C.azul, background:'rgba(29,115,226,0.08)', padding:'4px 10px', borderRadius:4 }}>SELECCIONADOS</span>
        </div>
        {lineas.length === 0 && (
          <div style={{ position:'absolute', left:0, right:0, top:150, textAlign:'center' }}>
            <Ico n="receipt_long" s={48} c={C.grisC}/>
            <div style={{ fontSize:20, fontWeight:600, color:C.texto, marginTop:10 }}>Sin conceptos</div>
            <div style={{ fontSize:16, color:C.gris, marginTop:6 }}>Añade productos o servicios a esta operación</div>
          </div>
        )}
        <div style={{ position:'absolute', left:0, top:46, right:0 }}>
          {lineas.map((l, i) => <LineaTicket key={l.prod.id} prod={l.prod} p={l.p} y={i * 146} w={LW - 34}
            aUnd={i === 0 ? (r.und || 0) : 0} aPrecio={i === 0 ? (r.precio || 0) : 0} aTotal={i === 0 ? (r.totalLinea || 0) : 0}/>)}
        </div>
        {/* TPVSummaryBarU */}
        <div style={{ position:'absolute', left:12, right:12, bottom:12, height:62, borderRadius:8, background:C.panel, border:`1px solid ${C.borde}`, display:'flex', alignItems:'center', justifyContent:'flex-end', gap:22, padding:'0 22px', boxShadow:anillo(r.barra || 0) }}>
          {[['Sub.', totales ? euros(totales.sub) : '0,00 €', r.sub], ['IVA', totales ? euros(totales.iva) : '0,00 €', r.iva]].map(([k, v, a]) => (
            <div key={k} style={{ display:'flex', alignItems:'baseline', gap:8, padding:'4px 8px', borderRadius:6, boxShadow:anillo(a || 0) }}>
              <span style={{ fontSize:14, color:C.gris }}>{k}</span><span style={{ fontSize:19, color:C.tinta }}>{v}</span>
            </div>
          ))}
          <span style={{ width:1, height:30, background:C.borde }}/>
          <div style={{ display:'flex', alignItems:'baseline', gap:10, padding:'4px 10px', borderRadius:6, boxShadow:anillo(r.total || 0), transform:`scale(${1 + 0.06 * (r.totalPulso || 0)})` }}>
            <span style={{ fontSize:15, color:C.gris }}>Total</span>
            <span style={{ fontSize:26, fontWeight:700, color:C.tinta }}>{totales ? euros(totales.total) : '0,00 €'}</span>
          </div>
        </div>
      </div>
      {/* Derecha: TPVPanelDerechaU, pestaña Agregar */}
      <div style={{ position:'absolute', left:LW + 30, right:16, top:140, bottom:76, background:'#fff', borderRadius:10, border:`1px solid ${C.borde}`, boxShadow:anillo(r.catalogo || 0), overflow:'hidden' }}>
        <div style={{ display:'flex', gap:4, padding:'0 12px', borderBottom:`1px solid ${C.borde}`, height:48, alignItems:'flex-end' }}>
          {[['add', 'Agregar'], ['description', 'Archivo'], ['info', 'Parámetros'], ['note_stack', 'Notas'], ['receipt_long', 'Ticket'], ['account_tree', 'Flujo']].map(([i, n], k) => (
            <div key={n} style={{ display:'flex', alignItems:'center', gap:6, padding:'0 12px', height:44, borderBottom: k === 0 ? `3px solid ${C.azul}` : '3px solid transparent', color: k === 0 ? C.azul : C.gris, fontSize:15, fontWeight: k === 0 ? 600 : 400 }}>
              <Ico n={i} s={18} c={k === 0 ? C.azul : C.grisC}/>{n}
            </div>
          ))}
        </div>
        <div style={{ position:'absolute', left:18, right:60, top:62 }}>
          <div style={{ height:52, borderRadius:26, border:`1px solid ${C.bordeF}`, display:'flex', alignItems:'center', gap:10, padding:'0 18px', boxShadow:anillo(r.buscar || 0) }}>
            <Ico n="search" s={24} c={C.gris}/>
            <span style={{ fontSize:17, color:C.gris }}>¿Qué desea Vender?</span>
          </div>
        </div>
        <div style={{ position:'absolute', left:18, top:130, display:'flex', gap:18, fontSize:15 }}>
          <span style={{ display:'flex', alignItems:'center', gap:6, color:C.azul, fontWeight:600, borderBottom:`3px solid ${C.azul}`, paddingBottom:6 }}><Ico n="storefront" s={18} c={C.azul}/>Catálogo</span>
          <span style={{ display:'flex', alignItems:'center', gap:6, color:C.gris, paddingBottom:6 }}><Ico n="history" s={18} c={C.grisC}/>Recientes</span>
        </div>
        <div style={{ position:'absolute', left:18, top:176, display:'flex', alignItems:'center', gap:10 }}>
          <Insignia txt="312 productos" color={C.texto} fondo="#EEF2F6"/>
          <span style={{ fontSize:14, color:C.gris }}>Mostrando los primeros 48 · escribe arriba para buscar entre los 312</span>
        </div>
        {PRODUCTOS.slice(0, 4).map((p, i) => (
          <ProductoCatalogo key={p.id} prod={p} x={18 + (i % 2) * 362} y={218 + Math.floor(i / 2) * 164} w={348}
            aMas={verdes[p.id] || 0} pulsado={pulsados[p.id] || 0}/>
        ))}
      </div>
      {/* Pie: TPVFooterU */}
      <div style={{ position:'absolute', left:0, right:0, bottom:0, height:64, background:'#fff', borderTop:`1px solid ${C.borde}`, display:'flex', alignItems:'center', justifyContent:'flex-end', gap:12, padding:'0 22px' }}>
        <Btn txt="Cobrar" ico="payments" h={46} fs={18} a={r.cobrar || 0}/>
        <Btn txt="Aceptar" ico="check" tipo="success" variante="outlined" h={46} fs={18}/>
      </div>
    </div>
  );
}

// ── Máscara de diálogo y diálogo de Radzen ──
function Mascara({ op }){
  return <div style={{ position:'absolute', inset:0, background:`rgba(15,23,42,${0.38 * op})` }}/>;
}
function Dialogo({ x, y, w, h, titulo, p = 1, children, pie }){
  const e = Easing.easeOutCubic(clamp(p, 0, 1));
  return (
    <div style={{ position:'absolute', left:x, top:y, width:w, height:h, background:'#fff', borderRadius:12, boxShadow:'0 24px 60px rgba(15,23,42,0.25)',
      opacity:e, transform:`translateY(${(1 - e) * 20}px)`, overflow:'hidden', display:'flex', flexDirection:'column' }}>
      <div style={{ height:56, flexShrink:0, display:'flex', alignItems:'center', padding:'0 22px', borderBottom:`1px solid ${C.borde}`, gap:10 }}>
        {titulo}
        <div style={{ flex:1 }}/>
        <Ico n="close" s={24} c={C.grisC}/>
      </div>
      <div style={{ position:'relative', flex:1, background:'#fff' }}>{children}</div>
      {pie && <div style={{ height:76, flexShrink:0, borderTop:`1px solid ${C.borde}`, display:'flex', alignItems:'center', justifyContent:'center', gap:16 }}>{pie}</div>}
    </div>
  );
}

// ── La ventana «Cobro» (CobroRapidoDialog + CobrarU) ──
// metodo: 'efectivo' | 'tarjeta' · recibido: texto tecleado · vista: 'cobro' | 'ticket'
function DialogoCobro({ p = 1, total, metodo = 'efectivo', recibido = '', r = {}, tecla = null, vista = 'cobro', ticket = null, aNuevo = 0 }){
  const rec = parseFloat((recibido || '0').replace(',', '.')) || 0;
  const cambio = recibido ? rec - total : -total;
  const W = 1000, H = 640;
  const pieCobro = (
    <>
      <Btn txt="Automático" ico="auto_awesome" h={52} fs={19} a={r.automatico || 0}/>
      <Btn txt="Finalizar" ico="check" tipo="success" h={52} fs={19} a={r.finalizar || 0}/>
      <Btn txt="Cancelar" ico="close" tipo="danger" variante="outlined" h={52} fs={19}/>
    </>
  );
  const pieTicket = (
    <Btn tipo="success" h={52} fs={19} a={aNuevo} ico="add" txt="Nuevo">
      <span style={{ marginLeft:8, padding:'2px 8px', borderRadius:4, background:'rgba(255,255,255,0.9)', color:C.tinta, fontSize:13, fontWeight:600 }}>ESC</span>
    </Btn>
  );
  return (
    <Dialogo x={(VW - W) / 2} y={60} w={W} h={H} p={p} titulo={<span style={{ fontSize:20, fontWeight:600, color:C.tinta }}>Cobro</span>} pie={vista === 'cobro' ? pieCobro : pieTicket}>
      {vista === 'cobro' && (
        <div style={{ position:'absolute', inset:0, background:C.fondo, display:'flex', alignItems:'center', justifyContent:'center', gap:16 }}>
          {/* Tarjeta izquierda: método + importe + teclado */}
          <div style={{ width:420, background:'#fff', borderRadius:10, border:`1px solid ${C.borde}`, padding:'22px 24px', boxSizing:'border-box' }}>
            <div style={{ display:'flex', gap:10 }}>
              {[['efectivo', 'Efectivo'], ['tarjeta', 'Tarjeta']].map(([k, n]) => (
                <div key={k} style={{ flex:1, height:44, borderRadius:8, display:'flex', alignItems:'center', justifyContent:'center', fontSize:18,
                  background: metodo === k ? C.azul : '#fff', color: metodo === k ? '#fff' : C.tinta, border:`1px solid ${metodo === k ? C.azul : C.bordeF}`,
                  boxShadow:anillo(r[k] || 0) }}>{n}</div>
              ))}
            </div>
            {metodo === 'efectivo' ? (
              <>
                <div style={{ marginTop:18, fontSize:15, color:C.gris }}>A cobrar:</div>
                <div style={{ fontSize:28, fontWeight:700, color:C.tinta }}>{euros(total)}</div>
                <div style={{ marginTop:12, fontSize:15, color:C.gris }}>Pago recibido:</div>
                <div style={{ height:52, borderRadius:8, border:`1px solid ${(r.recibido || 0) > 0 ? C.azul : C.bordeF}`, boxShadow:anillo(r.recibido || 0), display:'flex', alignItems:'center', justifyContent:'flex-end', padding:'0 14px', fontFamily:'monospace', fontSize:28, color:C.tinta, marginTop:4 }}>{recibido}</div>
                <div style={{ display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:8, marginTop:14 }}>
                  {['1','2','3','4','5','6','7','8','9','0',',','C'].map(k => {
                    const on = tecla === k;
                    return <div key={k} style={{ height:40, borderRadius:8, display:'flex', alignItems:'center', justifyContent:'center', fontSize:19,
                      background: k === 'C' ? C.rojo : (on ? 'rgba(29,115,226,0.14)' : '#F8FAFC'), color: k === 'C' ? '#fff' : C.tinta,
                      border:`1px solid ${on ? C.azul : C.borde}`, transform:`scale(${on ? 0.96 : 1})` }}>{k}</div>;
                  })}
                </div>
              </>
            ) : (
              <div style={{ display:'flex', alignItems:'center', gap:18, padding:'40px 0 30px' }}>
                <Ico n="credit_card" s={60} c={C.azul}/>
                <div>
                  <div style={{ fontSize:18, color:C.texto }}>Procesa el pago en el datáfono.</div>
                  <div style={{ fontSize:34, fontWeight:700, color:C.tinta, marginTop:6 }}>{euros(total)}</div>
                </div>
              </div>
            )}
          </div>
          {/* Tarjeta derecha (solo en efectivo): lo que falta o lo que se devuelve */}
          {metodo === 'efectivo' && (
            <div style={{ width:250, background:'#fff', borderRadius:10, border:`1px solid ${C.borde}`, padding:'22px 18px', boxSizing:'border-box', boxShadow:anillo(r.derecha || 0), textAlign:'center' }}>
              {cambio < 0 && (<>
                <Insignia txt="Falta por cobrar" color={C.rojo}/>
                <div style={{ fontSize:32, fontWeight:600, color:C.tinta, marginTop:12 }}>{euros(-cambio)}</div>
              </>)}
              {cambio > 0 && (<>
                <Insignia txt="Devuelve" color={C.azul}/>
                <div style={{ height:52, borderRadius:8, border:`1px solid ${C.bordeF}`, display:'flex', alignItems:'center', justifyContent:'flex-end', padding:'0 14px', fontFamily:'monospace', fontSize:28, color:C.tinta, marginTop:12 }}>{cambio.toFixed(2).replace('.', ',')}</div>
              </>)}
              {cambio === 0 && <Insignia txt="Perfecto" color={C.verde}/>}
            </div>
          )}
        </div>
      )}
      {vista === 'ticket' && ticket}
    </Dialogo>
  );
}

// Ticket de ejemplo (la plantilla de impresión la pone cada empresa)
function TicketPapel({ lineas, total, entregado, cambio }){
  return (
    <div style={{ position:'absolute', inset:0, background:C.fondo, display:'flex', alignItems:'center', justifyContent:'center' }}>
      <div style={{ width:340, background:'#fff', border:`1px solid ${C.borde}`, boxShadow:'0 6px 18px rgba(15,23,42,0.08)', padding:'22px 26px', fontFamily:"'JetBrains Mono', monospace", fontSize:15, color:C.tinta }}>
        <div style={{ textAlign:'center', fontWeight:700, fontSize:17 }}>FERRETERÍA LOZANO</div>
        <div style={{ textAlign:'center', color:C.gris, fontSize:13, marginTop:2 }}>Ticket T26-001482 · 09/10/2026</div>
        <div style={{ borderTop:'1px dashed #CBD5E1', margin:'12px 0' }}/>
        {lineas.map(([n, v]) => <div key={n} style={{ display:'flex', justifyContent:'space-between', margin:'4px 0' }}><span>1 {n}</span><span>{v}</span></div>)}
        <div style={{ borderTop:'1px dashed #CBD5E1', margin:'12px 0' }}/>
        <div style={{ display:'flex', justifyContent:'space-between', fontWeight:700, fontSize:17 }}><span>TOTAL</span><span>{total}</span></div>
        {entregado && <div style={{ display:'flex', justifyContent:'space-between', marginTop:6, color:C.gris }}><span>Entregado</span><span>{entregado}</span></div>}
        {cambio && <div style={{ display:'flex', justifyContent:'space-between', marginTop:2, color:C.gris }}><span>Cambio</span><span>{cambio}</span></div>}
      </div>
    </div>
  );
}

// ── La ventana «Cierre de caja» (CierreDeCajaDialog) ──
// d: { contado, banner:'cuadra'|'faltan'|null, cerrada, aviso } · r: resaltes
function DialogoCierre({ p = 1, d = {}, r = {}, dims = {} }){
  const W = 1240, H = 820;
  const titulo = (
    <div style={{ display:'flex', alignItems:'center', gap:10 }}>
      <Ico n="lock" s={24} c={C.tinta}/>
      <span style={{ fontSize:20, fontWeight:600, color:C.tinta }}>Cierre de caja</span>
      <Insignia txt={d.cerrada ? 'Cerrada' : 'Abierta'} color={d.cerrada ? C.rojo : C.verde} fondo={d.cerrada ? 'rgba(208,69,71,0.12)' : 'rgba(58,135,7,0.12)'}/>
    </div>
  );
  const Titulo = ({ ico, txt, a }) => (
    <div style={{ display:'flex', alignItems:'center', gap:10 }}>
      <Ico n={ico} s={24} c={C.azul}/>
      <span style={{ fontSize:20, fontWeight:600, color:C.tinta, padding:'2px 6px', borderRadius:6, boxShadow:anillo(a || 0) }}>{txt}</span>
      <Ico n="info" s={18} c={C.grisC}/>
    </div>
  );
  const Kpi = ({ ico, titulo, valor, a }) => (
    <div style={{ width:250, height:84, borderRadius:10, border:`1px solid ${C.borde}`, background:'#fff', padding:'12px 16px', boxSizing:'border-box', boxShadow:anillo(a || 0) }}>
      <div style={{ display:'flex', alignItems:'center', gap:8, fontSize:15, color:C.gris }}><Ico n={ico} s={20} c={C.azul}/>{titulo}</div>
      <div style={{ fontSize:24, fontWeight:600, color:C.tinta, marginTop:6 }}>{valor}</div>
    </div>
  );
  const cajaOp = (k) => dims[k] === undefined ? 1 : dims[k];
  const bannerCol = d.banner === 'cuadra' ? C.verde : C.rojo;
  return (
    <Dialogo x={(VW - W) / 2} y={6} w={W} h={H} p={p} titulo={titulo}
      pie={<div style={{ width:'100%', display:'flex', justifyContent:'flex-end', padding:'0 22px' }}><Btn txt="Cerrar" ico="close" tipo="danger" variante="text" h={40} fs={16}/></div>}>
      <div style={{ position:'absolute', inset:0, background:C.fondo }}>
        {/* 1 · Qué caja estás cuadrando */}
        <Tarjeta a={r.b1 || 0} style={{ left:18, top:14, width:W - 36, height:142, padding:'14px 20px', opacity:cajaOp('b1') }}>
          <Titulo ico="point_of_sale" txt="1 · Qué caja estás cuadrando"/>
          <div style={{ display:'flex', gap:40, marginTop:12, alignItems:'flex-start' }}>
            <Campo label="Caja" valor="Mostrador" w={280} h={58} a={r.caja || 0}><Ico n="expand_more" s={22} style={{ marginLeft:'auto' }}/></Campo>
            <div><div style={{ fontSize:14, color:C.gris }}>Día que se cuadra</div><div style={{ fontSize:20, fontWeight:700, color:C.tinta, marginTop:4 }}>9 oct</div></div>
            <div style={{ padding:'2px 8px', borderRadius:8, boxShadow:anillo(r.saldo || 0) }}>
              <div style={{ fontSize:14, color:C.gris }}>Empieza el día con</div>
              <div style={{ fontSize:26, fontWeight:700, color:C.tinta, marginTop:2 }}>150,00 €</div>
              <div style={{ fontSize:14, color:C.gris, marginTop:2 }}>Es el saldo con el que la dejó el cierre anterior de esta caja.</div>
            </div>
          </div>
        </Tarjeta>
        {/* 2 · Lo que dicen las cuentas */}
        <Tarjeta a={r.b2 || 0} style={{ left:18, top:168, width:W - 36, height:216, padding:'14px 20px', opacity:cajaOp('b2') }}>
          <Titulo ico="calculate" txt="2 · Lo que dicen las cuentas"/>
          <div style={{ display:'flex', gap:16, marginTop:14 }}>
            <Kpi ico="south_west" titulo="Ha entrado" valor="412,80 €"/>
            <Kpi ico="north_east" titulo="Ha salido" valor="35,00 €"/>
            <Kpi ico="euro" titulo="Cobrado a clientes" valor="412,80 €" a={r.cobrado}/>
            <Kpi ico="payments" titulo="Pagado a proveedores" valor="-35,00 €" a={r.pagado}/>
          </div>
          <div style={{ display:'flex', alignItems:'center', gap:16, marginTop:16 }}>
            <div style={{ display:'flex', alignItems:'center', gap:16, padding:'2px 10px', borderRadius:8, boxShadow:anillo(r.deberia || 0) }}>
              <span style={{ fontSize:18, color:C.texto }}>En el cajón debería haber</span>
              <span style={{ fontSize:30, fontWeight:700, color:C.tinta }}>527,80 €</span>
            </div>
            <div style={{ flex:1 }}/>
            <Btn txt="Volver a calcular" ico="refresh" variante="outlined" h={44} fs={16} a={r.recalc || 0}/>
          </div>
        </Tarjeta>
        {/* 3 · Lo que hay en el cajón */}
        <Tarjeta a={r.b3 || 0} style={{ left:18, top:396, width:W - 36, height:272, padding:'14px 20px', opacity:cajaOp('b3') }}>
          <Titulo ico="lock" txt="3 · Lo que hay en el cajón"/>
          <div style={{ display:'flex', alignItems:'center', marginTop:14 }}>
            <Campo label="Dinero contado" valor={d.contado || ''} placeholder=" " w={280} h={62} a={r.contado || 0} obli={!d.contado}/>
            <div style={{ flex:1 }}/>
            <Btn txt={d.cerrada ? 'Guardar corrección' : 'Cerrar caja'} ico="lock" tipo="success" h={54} fs={19} a={r.cerrar || 0}/>
          </div>
          {d.banner && (
            <div style={{ marginTop:18, borderRadius:10, background:bannerCol, color:'#fff', padding:'16px 22px', display:'flex', gap:16, alignItems:'flex-start',
              opacity:d.bannerP === undefined ? 1 : d.bannerP, transform:`translateY(${(1 - (d.bannerP === undefined ? 1 : d.bannerP)) * 10}px)` }}>
              <Ico n={d.banner === 'cuadra' ? 'check_circle' : 'warning'} s={34} c="#fff"/>
              <div>
                <div style={{ fontSize:22, fontWeight:700 }}>{d.banner === 'cuadra' ? 'Cuadra' : 'Faltan 5,00 € en el cajón'}</div>
                <div style={{ fontSize:16, marginTop:4, opacity:0.95 }}>{d.banner === 'cuadra'
                  ? 'Lo contado es exactamente lo que dicen las cuentas.'
                  : 'Hay menos dinero del que dicen las cuentas. Cuenta otra vez antes de cerrar; si vuelve a salir lo mismo, cierra igual y queda registrado el descuadre.'}</div>
              </div>
            </div>
          )}
        </Tarjeta>
      </div>
    </Dialogo>
  );
}

// ── Cursor con clic (círculo que se abre una vez) ──
// kf: [[t, x, y], ...] · clics: [t, ...]
function Cursor({ t, kf, clics = [], op = 1 }){
  let x = kf[0][1], y = kf[0][2];
  for (let i = 1; i < kf.length; i++) {
    const [t0, x0, y0] = kf[i - 1], [t1, x1, y1] = kf[i];
    if (t >= t0 && t <= t1) { const e = Easing.easeInOutCubic((t - t0) / Math.max(t1 - t0, 0.001)); x = lerp(x0, x1, e); y = lerp(y0, y1, e); break; }
    if (t > t1) { x = x1; y = y1; }
  }
  const c = clics.find(s => t >= s && t < s + 0.6);
  const cp = c === undefined ? 0 : (t - c) / 0.6;
  const vis = op * clamp((t - kf[0][0] + 0.3) / 0.3, 0, 1);
  return (
    <div style={{ position:'absolute', left:x, top:y, opacity:vis, pointerEvents:'none', zIndex:50 }}>
      {c !== undefined && <div style={{ position:'absolute', left:-22, top:-22, width:44, height:44, borderRadius:22, border:`3px solid ${C.azul}`, opacity:1 - cp, transform:`scale(${0.4 + cp})` }}/>}
      <svg width="26" height="32" viewBox="0 0 22 28" style={{ position:'absolute', left:-3, top:-2, transform:`scale(${c !== undefined && cp < 0.3 ? 0.9 : 1})` }}>
        <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>
  );
}

// Aviso de Radzen (notificación arriba a la derecha)
function Aviso({ p, titulo, texto, color = C.verde, ico = 'check_circle', x, y }){
  const e = Easing.easeOutCubic(clamp(p, 0, 1));
  return (
    <div style={{ position:'absolute', left:x, top:y, width:420, background:'#fff', borderRadius:10, borderLeft:`6px solid ${color}`, boxShadow:'0 14px 34px rgba(15,23,42,0.18)',
      padding:'14px 18px', display:'flex', gap:14, opacity:e, transform:`translateX(${(1 - e) * 30}px)`, fontFamily:ROBOTO }}>
      <Ico n={ico} s={30} c={color}/>
      <div><div style={{ fontSize:18, fontWeight:700, color:C.tinta }}>{titulo}</div><div style={{ fontSize:15, color:C.texto, marginTop:3 }}>{texto}</div></div>
    </div>
  );
}

Object.assign(window, { C, ROBOTO, ent, sal, foco, anillo, pulso, euros, Ico, Btn, Campo, Insignia, Rotulo, Fondo, Ventana, VX, VY, VW, VH,
  AppTPV, Tarjeta, Pastilla, PRODUCTOS, base, PantallaVenta, Mascara, Dialogo, DialogoCobro, TicketPapel, DialogoCierre, Cursor, Aviso });
