// ──────────────────────────── POS / Cassa ────────────────────────────

const { useState, useEffect, useRef, useMemo } = React;

// — Striped image placeholder
const ProductThumb = ({ size = 44, label }) => (
  <div className="stripe-ph rounded-xs shrink-0" style={{ width: size, height: size }} title={label}/>
);

// — Hook: detect POS layout (auto by viewport, or forced via body[data-pos-layout])
const usePosLayout = () => {
  const [layout, setLayout] = useState('horizontal');
  useEffect(() => {
    const compute = () => {
      const forced = document.body.getAttribute('data-pos-layout') || 'auto';
      if (forced === 'horizontal') return setLayout('horizontal');
      if (forced === 'vertical')   return setLayout('vertical');
      setLayout(window.innerWidth < 1280 ? 'vertical' : 'horizontal');
    };
    compute();
    window.addEventListener('resize', compute);
    const obs = new MutationObserver(compute);
    obs.observe(document.body, { attributes: true, attributeFilter: ['data-pos-layout'] });
    return () => { window.removeEventListener('resize', compute); obs.disconnect(); };
  }, []);
  return layout;
};

// ─── Search dropdown with PAGINATION ───
const PAGE_SIZE = 6;

const SearchResults = ({ query, catalog, onPick, onClose }) => {
  const [pageCount, setPageCount] = useState(1);
  const q = query.trim().toLowerCase();
  const all = useMemo(() => {
    if (!q) return catalog.slice(0, 30);
    return catalog.filter(p =>
      p.name.toLowerCase().includes(q) ||
      p.sku.toLowerCase().includes(q) ||
      p.brand.toLowerCase().includes(q) ||
      p.color.toLowerCase().includes(q) ||
      p.cat.toLowerCase().includes(q)
    );
  }, [q, catalog]);

  useEffect(() => { setPageCount(1); }, [q]);

  const visible = all.slice(0, pageCount * PAGE_SIZE);
  const hasMore = visible.length < all.length;

  return (
    <div className="absolute left-0 right-0 top-full mt-2 z-popover bg-elevated rounded-xl shadow-popover max-h-[460px] overflow-auto">
      {all.length === 0 ? (
        <div className="p-8 text-center text-muted text-[14px]">Nessun articolo trovato per "{query}"</div>
      ) : (
        <>
          <ul className="py-1">
            {visible.map((p) => (
              <li key={p.sku}>
                <button onClick={() => { onPick(p); onClose(); }}
                  className="w-full flex items-center gap-3.5 px-4 py-2.5 hover:bg-paper text-left focus-ring">
                  <ProductThumb size={40} label={p.cat} />
                  <div className="flex-1 min-w-0">
                    <div className="flex items-center gap-2">
                      <span className="text-[14px] font-medium text-ink truncate">{p.name}</span>
                      <span className="text-[12px] text-muted">· {p.brand}</span>
                    </div>
                    <div className="flex items-center gap-2 mt-0.5 text-[12px] text-muted">
                      <span className="num">{p.sku}</span>
                      <span>·</span>
                      <span>{p.color}</span>
                      <span>·</span>
                      <span>Tg {p.size}</span>
                      <span>·</span>
                      <span className={p.stock === 0 ? 'text-neg' : p.stock <= 2 ? 'text-warn' : ''}>
                        {p.stock === 0 ? 'esaurito' : `${p.stock} disp.`}
                      </span>
                    </div>
                  </div>
                  <div className="num text-[15px] font-medium text-ink">{fmtEur(p.price)}</div>
                </button>
              </li>
            ))}
          </ul>

          {hasMore && (
            <div className="px-3 pb-2">
              <button
                onClick={() => setPageCount(p => p + 1)}
                className="w-full h-11 rounded-md border border-line bg-paper hover:bg-[var(--bg-hover)] text-[13.5px] font-medium text-ink flex items-center justify-center gap-2"
              >
                <I.ArrowD size={14}/>
                Carica altri ({all.length - visible.length} rimanenti)
              </button>
            </div>
          )}
        </>
      )}
      <div className="border-t border-line2 px-4 py-2.5 flex items-center justify-between bg-paper rounded-b-[16px] sticky bottom-0">
        <span className="text-[11.5px] text-muted">
          ↑↓ per navigare · <kbd className="num">↵</kbd> per aggiungere · <kbd className="num">esc</kbd> per chiudere
        </span>
        <span className="text-[11.5px] text-muted num">{visible.length} di {all.length}</span>
      </div>
    </div>
  );
};

// ─── Cart row ───
// Chip venditore della riga: iniziali + nome, tap per cambiarlo (tra i timbrati).
const RowSellerChip = ({ item, idx, onPickSeller }) => (
  <button onClick={(e) => { e.stopPropagation(); onPickSeller(idx); }} title="Venditore di questa riga"
    className="focus-ring inline-flex items-center gap-1.5 mt-1 h-6 pl-1 pr-2 rounded-full bg-sunken hover:bg-[var(--bg-hover)] transition-colors">
    <span className="w-4 h-4 rounded-full bg-[var(--accent-blue)] text-[var(--text-inverse)] text-[8.5px] font-semibold flex items-center justify-center shrink-0">{item.sellerInitials || '?'}</span>
    <span className="text-[11px] text-muted max-w-[110px] truncate">{item.sellerName || 'venditore'}</span>
  </button>
);

const CartRow = ({ item, idx, onQty, onRemove, onEditDiscount, onPickSeller, selected, onSelect, layout }) => {
  const isReturn = item.kind === 'return';
  const lineGross = item.price * item.qty;
  const discountAmt = !isReturn && item.discount
    ? (item.discount.type === 'percent' ? lineGross * (item.discount.value / 100) : (item.discount.value || 0))
    : 0;
  const lineNet = lineGross - discountAmt;
  const atMax = item.maxQty != null && item.qty >= item.maxQty;

  if (layout === 'vertical') {
    return (
      <div
        onClick={onSelect}
        className={`px-4 py-3 border-b border-line2 cursor-pointer transition-all duration-fast ease-standard
          ${selected ? 'bg-[var(--bg-selected)]' : isReturn ? 'bg-[var(--danger-50)] border-l-[3px] border-l-[var(--danger-500)]' : 'hover:bg-paper'}`}
      >
        <div className="flex items-start gap-3">
          {item.kind === 'giftcard'
            ? <div className="w-11 h-11 rounded-sm bg-[var(--bg-selected)] text-[var(--accent-blue)] flex items-center justify-center shrink-0"><I.Gift size={18}/></div>
            : <ProductThumb size={44}/>
          }
          <div className="min-w-0 flex-1">
            <div className="flex items-center gap-2 flex-wrap">
              <span className="text-[14px] font-medium text-ink truncate">{item.name}</span>
              {isReturn && <Pill tone="neg"><I.Return size={10}/> Reso</Pill>}
            </div>
            <div className="text-[12px] text-muted mt-0.5 truncate">
              <span className="num">{item.sku}</span>{item.color ? ` · ${item.color} · Tg ${item.size}` : ''}
            </div>
            {onPickSeller && <RowSellerChip item={item} idx={idx} onPickSeller={onPickSeller}/>}
          </div>
          <div className="text-right shrink-0">
            {isReturn ? (
              <div className="num text-[16px] font-semibold text-neg">−{fmtEur(lineNet)}</div>
            ) : (
              <>
                <div className="num text-[16px] font-semibold text-ink">{fmtEur(lineNet)}</div>
                {discountAmt > 0 && <div className="num text-[11px] text-muted line-through">{fmtEur(lineGross)}</div>}
              </>
            )}
          </div>
        </div>
        <div className="mt-2.5 flex items-center gap-2">
          <div className="flex items-center border border-line rounded-sm overflow-hidden bg-surface">
            <button onClick={(e)=>{e.stopPropagation(); onQty(idx, item.qty - 1);}} className="w-10 h-11 flex items-center justify-center hover:bg-[var(--bg-hover)] text-ink"><I.Minus size={14}/></button>
            <div className="w-12 text-center num text-[15px] font-medium text-ink">{item.qty}{isReturn && <span className="text-muted text-[12px]">/{item.maxQty}</span>}</div>
            <button onClick={(e)=>{e.stopPropagation(); onQty(idx, item.qty + 1);}} disabled={atMax} className="w-10 h-11 flex items-center justify-center hover:bg-[var(--bg-hover)] text-ink disabled:opacity-30"><I.Plus size={14}/></button>
          </div>
          {!isReturn && (
            <button onClick={(e)=>{e.stopPropagation(); onEditDiscount(idx);}}
              className="h-11 px-3 rounded-sm border border-dashed border-line hover:border-strong text-[12.5px] flex items-center gap-1.5 text-ink">
              {item.discount ? (
                <span className="num text-neg font-medium">
                  −{item.discount.type === 'percent' ? `${item.discount.value}%` : fmtEur(item.discount.value)}
                </span>
              ) : (
                <span className="text-muted">+ sconto</span>
              )}
            </button>
          )}
          {isReturn && (
            <span className="h-11 px-3 rounded-sm bg-[var(--danger-50)] text-[var(--danger-700)] text-[11.5px] font-medium flex items-center gap-1.5 num">
              <I.Return size={12}/> {item.refDoc ? 'da ' + item.refDoc : 'reso libero'}
            </span>
          )}
          <button onClick={(e)=>{e.stopPropagation(); onRemove(idx);}}
            className="ml-auto w-11 h-11 rounded-sm hover:bg-[var(--danger-50)] hover:text-[var(--danger-700)] text-muted flex items-center justify-center"
            aria-label="Rimuovi"><I.Trash size={16}/></button>
        </div>
      </div>
    );
  }

  // horizontal (desktop)
  return (
    <div
      onClick={onSelect}
      className={`row-h grid grid-cols-[40px_minmax(0,1fr)_112px_minmax(90px,128px)_minmax(96px,128px)_40px] items-center gap-2.5 px-4 sm:px-5 border-b border-line2 cursor-pointer transition-all duration-fast ease-standard
        ${selected ? 'bg-[var(--bg-selected)]' : isReturn ? 'bg-[var(--danger-50)] hover:bg-[var(--danger-50)] border-l-[3px] border-l-[var(--danger-500)]' : 'hover:bg-paper'}`}
    >
      {item.kind === 'giftcard'
        ? <div className="w-10 h-10 rounded-sm bg-[var(--bg-selected)] text-[var(--accent-blue)] flex items-center justify-center"><I.Gift size={16}/></div>
        : <ProductThumb size={40}/>
      }
      <div className="min-w-0">
        <div className="flex items-center gap-2">
          <span className="text-[14px] font-medium text-ink truncate">{item.name}</span>
          {isReturn && <Pill tone="neg"><I.Return size={10}/> Reso</Pill>}
        </div>
        <div className="text-[12px] text-muted truncate mt-0.5">
          <span className="num">{item.sku}</span>{item.color ? ` · ${item.color} · Tg ${item.size}` : ''}
        </div>
        {onPickSeller && <RowSellerChip item={item} idx={idx} onPickSeller={onPickSeller}/>}
      </div>
      <div className="flex items-center justify-self-start border border-line rounded-md overflow-hidden bg-surface">
        <button onClick={(e)=>{e.stopPropagation(); onQty(idx, item.qty - 1);}} className="w-9 h-10 flex items-center justify-center hover:bg-[var(--bg-hover)] text-ink"><I.Minus size={14}/></button>
        <div className="w-12 text-center num text-[15px] font-medium text-ink">{item.qty}{isReturn && <span className="text-muted text-[11px]">/{item.maxQty}</span>}</div>
        <button onClick={(e)=>{e.stopPropagation(); onQty(idx, item.qty + 1);}} disabled={atMax} className="w-9 h-10 flex items-center justify-center hover:bg-[var(--bg-hover)] text-ink disabled:opacity-30"><I.Plus size={14}/></button>
      </div>
      {isReturn ? (
        <div className="justify-self-start text-left px-2.5 h-9 rounded-sm bg-[var(--danger-50)] text-[var(--danger-700)] text-[11.5px] font-medium flex items-center gap-1.5">
          <I.Return size={12}/>
          <span className="num">{item.refDoc ? 'da ' + item.refDoc : 'reso libero'}</span>
        </div>
      ) : (
        <button onClick={(e)=>{e.stopPropagation(); onEditDiscount(idx);}}
          className="justify-self-start text-left px-2.5 h-9 rounded-sm border border-dashed border-line hover:border-strong hover:bg-paper transition-all duration-fast ease-standard">
          {item.discount ? (
            <>
              <div className="num text-[12.5px] font-medium text-neg">−{item.discount.type === 'percent' ? `${item.discount.value}%` : fmtEur(item.discount.value)}</div>
              <div className="text-[10.5px] text-muted -mt-0.5">{item.discount.reason || 'sconto riga'}</div>
            </>
          ) : (<span className="text-[12px] text-muted">+ sconto riga</span>)}
        </button>
      )}
      <div className="text-right">
        {isReturn ? (
          <div className="num text-[16px] font-medium text-neg">−{fmtEur(lineNet)}</div>
        ) : (
          <>
            <div className="num text-[16px] font-medium text-ink">{fmtEur(lineNet)}</div>
            {discountAmt > 0 && <div className="num text-[11.5px] text-muted line-through -mt-0.5">{fmtEur(lineGross)}</div>}
          </>
        )}
      </div>
      <button onClick={(e)=>{e.stopPropagation(); onRemove(idx);}} className="w-9 h-9 rounded-md hover:bg-[var(--danger-50)] hover:text-[var(--danger-700)] text-muted flex items-center justify-center transition-all duration-fast ease-standard">
        <I.Trash size={16}/>
      </button>
    </div>
  );
};

// ─── Action chip ───
// Palette semantica delle azioni cassa: ogni categoria ha un colore fisso, così il
// dipendente riconosce l'azione dal colore dell'icona senza leggere.
const ACTION_COLORS = {
  blue:   { fg: 'var(--accent-blue)',   bg: 'rgba(0,122,255,0.12)' },
  purple: { fg: 'var(--accent-purple)', bg: 'rgba(175,82,222,0.13)' },
  green:  { fg: 'var(--success-700)',   bg: 'var(--success-50)' },
  gray:   { fg: 'var(--text-secondary)', bg: 'var(--bg-hover)' },
};
const ActionChip = ({ icon, label, sub, onClick, color = 'gray', active = false }) => {
  const Ico = I[icon];
  const c = ACTION_COLORS[color] || ACTION_COLORS.gray;
  return (
    <button onClick={onClick}
      className="focus-ring text-left px-3 py-2.5 rounded-lg border transition-all duration-fast ease-standard flex items-center gap-3 min-w-0 bg-surface hover:shadow-sm active:scale-[0.99]"
      style={active ? { borderColor: c.fg, boxShadow: `inset 0 0 0 1px ${c.fg}` } : { borderColor: 'var(--border-default)' }}>
      <span className="w-9 h-9 rounded-lg flex items-center justify-center shrink-0" style={{ background: c.bg, color: c.fg }}>
        <Ico size={18} />
      </span>
      <div className="min-w-0">
        <div className="text-[13px] font-semibold leading-tight text-ink">{label}</div>
        {sub && <div className="text-[11px] mt-0.5 truncate" style={active ? { color: c.fg } : { color: 'var(--text-tertiary)' }}>{sub}</div>}
      </div>
    </button>
  );
};

// ─── Customer chip ───
const CustomerChip = ({ customer, onPick, onClear }) => (
  customer ? (
    <div className="bg-surface border border-line rounded-md p-3.5 flex items-center gap-3">
      <Initials name={customer.name} size={40}/>
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-2">
          <span className="text-[14px] font-medium text-ink truncate">{customer.name}</span>
          {customer.tier === 'Top Client' && <Pill tone="accent">★</Pill>}
        </div>
        <div className="text-[11.5px] text-muted">{customer.points.toLocaleString('it-IT')} pt fedeltà</div>
      </div>
      <button onClick={onClear} className="w-9 h-9 rounded hover:bg-[var(--bg-hover)] flex items-center justify-center text-muted"><I.X size={14}/></button>
    </div>
  ) : (
    <button onClick={onPick}
      className="w-full h-12 rounded-lg border border-dashed transition-all duration-fast ease-standard flex items-center justify-center gap-2 text-[13.5px] font-medium hover:bg-[var(--bg-hover)]"
      style={{ borderColor: 'var(--accent-blue)', color: 'var(--accent-blue)' }}>
      <I.User size={16}/> Associa cliente
    </button>
  )
);

// ─── Totals block — tre stati: da incassare / pari / saldo a favore cliente ───
const TotalsBlock = ({ totals, coupon, onClearCoupon, customer }) => {
  const { saleSubtotal, rowDiscounts, couponDiscount, returnSubtotal, saleTotal, netBalance, tax } = totals;
  const hasSales = saleSubtotal > 0;
  const hasReturns = returnSubtotal > 0;
  const outcomeType = Math.abs(netBalance) < 0.01 ? 'even' : netBalance > 0 ? 'pay' : 'refund';

  return (
    <>
      <dl className="space-y-2.5 text-[14px]">
        {hasSales && (
          <>
            <div className="flex justify-between">
              <dt className="text-muted">{hasReturns ? 'Vendita' : 'Subtotale'}</dt>
              <dd className="num text-ink">{fmtEur(saleSubtotal)}</dd>
            </div>
            {rowDiscounts > 0 && (
              <div className="flex justify-between">
                <dt className="text-muted">Sconti di riga</dt>
                <dd className="num text-neg">−{fmtEur(rowDiscounts)}</dd>
              </div>
            )}
            {coupon && (
              <div className="flex justify-between items-baseline">
                <dt className="text-muted flex items-center gap-1.5">
                  Coupon
                  <span className="num text-[11px] bg-line2 px-1.5 py-0.5 rounded text-ink">{coupon.code}</span>
                  <button onClick={onClearCoupon} className="text-muted hover:text-neg"><I.X size={12}/></button>
                </dt>
                <dd className="num text-neg">−{fmtEur(couponDiscount)}</dd>
              </div>
            )}
          </>
        )}

        {hasReturns && (
          <div className={`flex justify-between ${hasSales ? 'border-t border-line pt-2.5 mt-1' : ''}`}>
            <dt className="text-muted flex items-center gap-1.5">
              <I.Return size={12}/> Resi
            </dt>
            <dd className="num text-neg">−{fmtEur(returnSubtotal)}</dd>
          </div>
        )}
      </dl>

      {saleTotal > 0.01 && (
        <div className="flex justify-between mt-2.5 text-[13px]">
          <span className="text-muted">IVA inclusa (22%)</span>
          <span className="num text-muted">{fmtEur(tax)}</span>
        </div>
      )}

      {/* Totale */}
      <div className="mt-5 pt-4 border-t-2 border-strong">
        <div className="flex items-baseline justify-between">
          <span className="text-[12px] uppercase tracking-[0.1em] text-muted font-medium">Totale</span>
          <span className={`num text-[36px] leading-none font-semibold tracking-tight ${
            outcomeType === 'even' ? 'text-muted' :
            outcomeType === 'refund' ? 'text-neg' : 'text-ink'
          }`}>
            {outcomeType === 'even' ? '—' :
             outcomeType === 'refund' ? `−${fmtEur(Math.abs(netBalance))}` :
             fmtEur(netBalance)}
          </span>
        </div>
        {outcomeType === 'even' && (
          <div className="text-[12px] text-muted mt-1">Pari · nulla da pagare</div>
        )}
        {outcomeType === 'refund' && (
          <div className="text-[12px] text-muted mt-1">Saldo a favore cliente · Al checkout: buono negozio o rimborso</div>
        )}
      </div>

      {customer && outcomeType === 'pay' && (
        <div className="mt-3 text-[12px] text-muted flex items-center justify-between">
          <span>Punti che guadagnerà</span>
          <span className="num text-ink font-medium">+ {Math.round(netBalance / 10)} pt</span>
        </div>
      )}
    </>
  );
};

// ────────────────────────────── Main POS ──────────────────────────────
const POS = ({ session, onOpenCassa, onCloseCassa, activeStoreId = STORE.id }) => {
  const layout = usePosLayout();
  const activeStore = STORES.find(s => s.id === activeStoreId) || STORE;
  const storeCatalog = useMemo(() => buildCatalog(activeStoreId), [activeStoreId]);
  const [cart, setCart] = useState([]);
  const [search, setSearch] = useState('');
  const [searchOpen, setSearchOpen] = useState(false);
  const [customer, setCustomer] = useState(null);
  const [coupon, setCoupon] = useState(null);
  const [selectedRow, setSelectedRow] = useState(null);
  const [modal, setModal] = useState(null);
  const [completed, setCompleted] = useState(null);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [freeReturnMode, setFreeReturnMode] = useState(false);
  const [nota, setNota] = useState('');
  // Venditore corrente della postazione (default = operatore loggato). Cambiabile per vendita.
  // Venditore "corrente" (default per le nuove righe): all'avvio l'operatore di sessione.
  const [seller, setSeller] = useState(() => window.__SESSION__?.op || null);
  const [sellerPickRow, setSellerPickRow] = useState(null); // null = venditore corrente; numero = quella riga
  const searchRef = useRef(null);

  useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'F2') { e.preventDefault(); searchRef.current?.focus(); }
      if (e.key === 'Escape') { setSearchOpen(false); setModal(null); setDrawerOpen(false); }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  // ─── Totals: somma algebrica vendite - resi ───
  const totals = useMemo(() => {
    let saleSubtotal = 0, rowDiscounts = 0, returnSubtotal = 0;
    cart.forEach(i => {
      if (i.kind === 'return') {
        returnSubtotal += i.price * i.qty;
      } else {
        const gross = i.price * i.qty;
        saleSubtotal += gross;
        if (i.discount) {
          rowDiscounts += i.discount.type === 'percent'
            ? gross * (i.discount.value / 100)
            : i.discount.value;
        }
      }
    });
    const afterRow = saleSubtotal - rowDiscounts;
    const couponDiscount = coupon
      ? (coupon.type === 'percent' ? afterRow * (coupon.value / 100) : Math.min(afterRow, coupon.value))
      : 0;
    const saleTotal = afterRow - couponDiscount;
    const netBalance = saleTotal - returnSubtotal;
    const tax = saleTotal > 0.01 ? saleTotal - saleTotal / 1.22 : 0;
    const count = cart.reduce((s, i) => s + i.qty, 0);
    return { saleSubtotal, rowDiscounts, couponDiscount, returnSubtotal, saleTotal, netBalance, tax, count };
  }, [cart, coupon]);

  const outcomeType = Math.abs(totals.netBalance) < 0.01 ? 'even'
    : totals.netBalance > 0 ? 'pay'
    : 'refund';

  // Venditore da assegnare a una NUOVA riga: eredita dall'ultima riga del carrello,
  // altrimenti usa il venditore corrente (chip in alto).
  const lineSellerFields = (prev) => {
    const last = prev.length ? prev[prev.length - 1] : null;
    const s = (last && last.sellerId)
      ? { id: last.sellerId, name: last.sellerName, initials: last.sellerInitials }
      : seller;
    return s ? { sellerId: s.id, sellerName: s.name, sellerInitials: s.initials } : {};
  };

  const addItem = (p) => {
    if (freeReturnMode) {
      setCart(prev => {
        const idx = prev.findIndex(x => x.sku === p.sku && x.kind === 'return' && !x.refDoc);
        if (idx >= 0) {
          const next = [...prev];
          next[idx] = { ...next[idx], qty: next[idx].qty + 1 };
          return next;
        }
        return [...prev, { ...p, qty: 1, discount: null, kind: 'return', refDoc: null, maxQty: null, ...lineSellerFields(prev) }];
      });
      setSearch(''); setSearchOpen(false);
      return;
    }
    setCart(prev => {
      const idx = prev.findIndex(x => x.sku === p.sku && x.kind !== 'return');
      if (idx >= 0) {
        const next = [...prev];
        next[idx] = { ...next[idx], qty: next[idx].qty + 1 };
        return next;
      }
      return [...prev, { ...p, qty: 1, discount: null, ...lineSellerFields(prev) }];
    });
    setSearch(''); setSearchOpen(false);
  };

  // Cambia il venditore di una singola riga (dal chip sulla riga)
  const setRowSeller = (idx, op) => setCart(prev => prev.map((x, i) => i === idx
    ? { ...x, sellerId: op.id, sellerName: op.name, sellerInitials: op.initials } : x));

  // Esito del selettore venditore: se stiamo assegnando una riga → quella; altrimenti
  // imposta il venditore "corrente" (default per le prossime righe).
  const handleSellerSelect = (op) => {
    if (sellerPickRow != null) { setRowSeller(sellerPickRow, op); setSellerPickRow(null); }
    else setSeller(op);
  };

  const setQty = (idx, q) => {
    if (q <= 0) return setCart(prev => prev.filter((_,i)=>i!==idx));
    setCart(prev => prev.map((x,i)=> {
      if (i !== idx) return x;
      const max = x.maxQty != null ? x.maxQty : Infinity;
      return { ...x, qty: Math.min(q, max) };
    }));
  };

  const removeRow = (idx) => setCart(prev => prev.filter((_,i)=>i!==idx));
  const setRowDiscount = (idx, d) => setCart(prev => prev.map((x,i)=> i===idx ? { ...x, discount: d } : x));

  const newSale = () => {
    setCart([]); setCustomer(null); setCoupon(null); setSelectedRow(null);
    setSearch(''); setCompleted(null); setFreeReturnMode(false); setNota('');
  };
  // ── Scontrini SOSPESI (parcheggia e riprendi) — salvati davvero sul server ──
  const [heldCount, setHeldCount] = useState(0);
  const refreshHeld = async () => {
    if (!window.__API__ || !window.__API__.get) return;
    const r = await window.__API__.get('/api/held-sales?storeId=' + encodeURIComponent(activeStoreId));
    if (r && r.ok) setHeldCount((r.held || []).length);
  };
  useEffect(() => { refreshHeld(); }, [activeStoreId]);

  const hold = async () => {
    if (cart.length === 0) { if (window.__toast) window.__toast('Carrello vuoto: niente da sospendere', 'info'); return; }
    if (window.__API__) {
      try {
        await window.__API__.post('/api/held-sales', {
          storeId: activeStoreId,
          total: totals.netBalance, items: cart.reduce((s, i) => s + i.qty, 0),
          customerName: customer ? customer.name : null,
          data: { cart, customer, seller, nota, coupon, freeReturnMode },
        });
        if (window.__toast) window.__toast('Scontrino sospeso · lo ritrovi in “In sospeso”', 'success');
        newSale(); refreshHeld();
      } catch (e) { /* il client mostra già un toast d'errore */ }
    }
  };
  // Riprende uno scontrino sospeso: ricarica carrello/cliente/venditore e lo rimuove dal server.
  const resumeHeld = async (h) => {
    const d = h.data || {};
    setCart(d.cart || []); setCustomer(d.customer || null); setSeller(d.seller || seller);
    setNota(d.nota || ''); setCoupon(d.coupon || null); setFreeReturnMode(!!d.freeReturnMode);
    setSelectedRow(null); setCompleted(null);
    if (window.__API__) { try { await fetch('/api/held-sales/' + encodeURIComponent(h.id), { method: 'DELETE', credentials: 'same-origin' }); } catch (e) {} }
    setModal(null); refreshHeld();
    if (window.__toast) window.__toast('Scontrino ripreso', 'success');
  };

  const onIssueGiftCard = ({ amount, code, recipient, design }) => {
    const item = {
      sku: `GC-${code.replace(/\s/g, '')}`,
      name: `Gift Card · ${fmtEur(amount)}${recipient ? ` (${recipient})` : ''}`,
      brand: 'Maison Ardent',
      cat: 'Gift Card',
      color: design,
      size: '—',
      price: amount,
      stock: 1,
      qty: 1,
      discount: null,
      kind: 'giftcard',
      gift: { code, recipient, design, amount },
    };
    setCart(prev => [...prev, item]);
  };

  // ─── Aggiunge righe di reso al carrello (non sostituisce) ───
  const onConfirmReturn = (doc, selection) => {
    const newLines = doc.lines
      .filter(l => (selection[l.sku] || 0) > 0)
      .map(l => {
        const cat = storeCatalog.find(c => c.sku === l.sku);
        return {
          sku: l.sku,
          name: l.name,
          brand: cat?.brand || '—',
          cat: cat?.cat || '—',
          color: cat?.color || '',
          size: cat?.size || '',
          stock: cat?.stock ?? 0,
          price: l.price,
          qty: selection[l.sku],
          maxQty: l.qty,
          discount: null,
          kind: 'return',
          refDoc: doc.id,
        };
      });

    setCart(prev => {
      const next = [...prev];
      newLines.forEach(nl => {
        const existIdx = next.findIndex(x => x.kind === 'return' && x.sku === nl.sku && x.refDoc === nl.refDoc);
        if (existIdx >= 0) {
          next[existIdx] = { ...next[existIdx], qty: Math.min(nl.qty, nl.maxQty) };
        } else {
          next.push(nl);
        }
      });
      return next;
    });

    if (doc.customerId && !customer) {
      const c = CUSTOMERS.find(cc => cc.id === doc.customerId);
      if (c) setCustomer(c);
    }
  };

  const onConfirmAcconto = ({ target, amount, method, remaining }) => {
    if (window.__API__) {
      const lines = target === 'current'
        ? cart.filter(i => i.kind !== 'return').map(i => ({ sku: i.sku, name: i.name, qty: i.qty, price: i.price, discount: i.discount || null }))
        : undefined;
      window.__API__.mutate('/api/sales/acconto', {
        storeId: activeStoreId, customerId: customer ? customer.id : null, target, amount, method, lines,
      }).then(() => { if (window.__toast) window.__toast('Acconto registrato', 'success'); }).catch(() => {});
    }
    setCompleted({ kind: 'acconto', amount, method, remaining, target });
    if (target === 'current') {
      setCart([]); setCoupon(null); setSelectedRow(null);
    }
  };

  const hasReturnsInCart = cart.some(i => i.kind === 'return');

  // ─── Banner stato cassa ───
  // Chiusa → invito ad aprire (fondo). Aperta → accesso diretto alla chiusura giornata
  // (conteggio contante + rendiconto), così la postazione può chiudere e spegnere da qui.
  const CassaBanner = session?.fondo == null ? (
    <div className="px-5 sm:px-7 py-3 bg-[var(--warning-50)] border-b border-[var(--warning-700)] border-opacity-30 flex flex-wrap items-center justify-between gap-2">
      <div className="flex items-center gap-2 min-w-0 text-[var(--warning-700)] text-[13px] sm:text-[13.5px] font-medium">
        <I.Wallet size={16} className="shrink-0"/>
        <span className="truncate"><span className="font-semibold">Cassa non aperta</span><span className="hidden sm:inline"> · dichiara il fondo iniziale prima di procedere con le vendite</span></span>
      </div>
      {onOpenCassa && (
        <button onClick={onOpenCassa} className="h-8 px-3 rounded-md border border-[var(--warning-700)] text-[var(--warning-700)] text-[12px] font-medium hover:bg-[var(--warning-50)] shrink-0">
          Apri cassa
        </button>
      )}
    </div>
  ) : (
    <div className="px-5 sm:px-7 py-3 bg-[var(--success-50)] border-b border-[var(--success-500)] border-opacity-30 flex flex-wrap items-center justify-between gap-2">
      <div className="flex items-center gap-2 min-w-0 text-[var(--success-700)] text-[13px] sm:text-[13.5px] font-medium">
        <I.Wallet size={16} className="shrink-0"/>
        <span className="truncate"><span className="font-semibold">Cassa aperta</span><span className="hidden sm:inline"> · fondo {fmtEur(session.fondo)} · a fine giornata chiudi e fai il rendiconto</span></span>
      </div>
      {onCloseCassa && (
        <button onClick={onCloseCassa} className="h-8 px-3 rounded-md bg-[var(--success-500)] text-[var(--text-inverse)] text-[12px] font-medium hover:opacity-90 shrink-0 flex items-center gap-1.5">
          <I.EOD size={14}/> Chiudi cassa
        </button>
      )}
    </div>
  );

  // ─── Free return mode banner ───
  const FreeReturnBanner = freeReturnMode ? (
    <div className="px-5 sm:px-7 py-2.5 bg-[var(--danger-50)] border-b border-[var(--danger-500)] flex items-center justify-between">
      <div className="flex items-center gap-2 text-[var(--danger-700)] text-[13.5px] font-medium">
        <I.Return size={16}/> Modalità reso libero · cerca un articolo per aggiungerlo come reso
      </div>
      <button onClick={()=>setFreeReturnMode(false)} className="h-8 px-3 rounded-md border border-[var(--danger-500)] text-[var(--danger-700)] text-[12px] font-medium hover:bg-[var(--danger-50)]">Esci</button>
    </div>
  ) : null;

  // ─── Header ───
  const Header = (
    <header className="hairline bg-paper px-5 sm:px-7 pt-4 pb-3 flex items-center justify-between gap-3 flex-wrap">
      <div className="min-w-0">
        <div className="text-[11px] uppercase tracking-[0.1em] text-muted font-medium">Punto cassa · {activeStore.name}</div>
        <div className="flex items-baseline gap-3 mt-0.5 flex-wrap">
          <h1 className="text-[20px] sm:text-[22px] font-semibold tracking-tight text-ink">
            Nuovo scontrino
          </h1>
          {(() => {
            // serie scontrini dalla numerazione reale (impostazioni); il numero esatto
            // viene assegnato dal server alla conferma. Niente più numero finto fisso.
            const dn = (window.__BI_DOCNUM__ || []).find(r => r.tipo === 'Scontrino');
            return dn ? <span className="num text-[13px] sm:text-[14px] text-muted">serie {dn.prefisso}</span> : null;
          })()}
          {hasReturnsInCart && (
            <Pill tone="neg"><I.Return size={11}/> reso incluso</Pill>
          )}
        </div>
      </div>
      <div className="flex items-center gap-2 flex-wrap">
        <button onClick={() => { setSellerPickRow(null); setModal('seller'); }} title="Venditore predefinito (per le prossime righe)"
          className="focus-ring inline-flex items-center gap-2 h-11 pl-2 pr-3 rounded-lg bg-sunken text-ink shadow-[inset_0_0_0_0.5px_var(--border-default)] hover:shadow-[inset_0_0_0_0.5px_var(--border-strong)] transition-shadow">
          <span className="w-7 h-7 rounded-md bg-[var(--accent-blue)] text-[var(--text-inverse)] text-[11px] font-semibold flex items-center justify-center shrink-0">{(seller && seller.initials) || '—'}</span>
          <span className="text-left leading-tight">
            <span className="block text-[10px] uppercase tracking-[0.06em] text-muted">Venditore</span>
            <span className="block text-[13px] font-medium text-ink max-w-[120px] truncate">{(seller && seller.name) || 'Seleziona'}</span>
          </span>
        </button>
        <button onClick={()=>setModal('returnSource')}
          className="focus-ring inline-flex items-center gap-2 h-11 px-3.5 rounded-lg text-[13.5px] font-medium transition-all duration-fast ease-standard hover:bg-[var(--danger-50)]"
          style={{ color: 'var(--danger-700)', boxShadow: 'inset 0 0 0 1px var(--danger-500)' }}>
          <I.Return size={16}/> Aggiungi reso
        </button>
        <Btn variant="outline" size="md" leading={<I.Pause size={16}/>} onClick={hold}>Sospendi</Btn>
        {heldCount > 0 && (
          <button onClick={() => setModal('held')} title="Scontrini in sospeso"
            className="focus-ring inline-flex items-center gap-2 h-11 px-3.5 rounded-lg text-[13.5px] font-medium text-ink bg-sunken hover:bg-[var(--bg-hover)] transition-colors">
            <I.Pause size={15}/> In sospeso
            <span className="num text-[11px] min-w-[18px] h-[18px] px-1 rounded-full bg-[var(--accent-blue)] text-[var(--text-inverse)] font-semibold flex items-center justify-center">{heldCount}</span>
          </button>
        )}
        <button onClick={newSale} title="Annulla scontrino"
          className="focus-ring inline-flex items-center gap-2 h-11 px-3.5 rounded-lg text-[13.5px] font-medium text-[var(--danger-700)] hover:bg-[var(--danger-50)] transition-colors">
          <I.Trash size={16}/> Annulla
        </button>
      </div>
    </header>
  );

  // ─── Search bar ───
  const SearchBar = (
    <div className="px-5 sm:px-7 py-4 hairline bg-paper relative">
      <div className="relative">
        <I.Search size={20} className="absolute left-4 top-1/2 -translate-y-1/2 text-muted"/>
        <input
          ref={searchRef}
          value={search}
          onChange={(e)=>{setSearch(e.target.value); setSearchOpen(true);}}
          onFocus={()=>setSearchOpen(true)}
          onKeyDown={(e)=>{
            if (e.key === 'Enter' && search) {
              const q = search.toLowerCase();
              const hit = storeCatalog.find(p => p.sku.toLowerCase() === q) ||
                          storeCatalog.find(p => p.name.toLowerCase().includes(q));
              if (hit) addItem(hit);
            }
          }}
          placeholder="Cerca articolo, scansiona barcode o digita SKU…"
          className="w-full h-14 sm:h-16 pl-12 pr-32 rounded-md border border-line bg-surface text-[15px] sm:text-[16px] focus:border-strong transition-all duration-fast ease-standard shadow-soft"
        />
        <div className="absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-2">
          <button
            onClick={()=>{ searchRef.current?.focus(); setSearchOpen(true); if (window.__toast) window.__toast('Scansiona o digita il barcode', 'info'); }}
            className="h-11 px-3 rounded-md hover:bg-[var(--bg-hover)] flex items-center gap-2 text-muted">
            <I.Barcode size={20}/>
            <span className="hidden sm:inline text-[12px] num">Scansiona</span>
          </button>
          <kbd className="hidden lg:inline-block num text-[11px] text-muted bg-line2 px-2 py-1 rounded">F2</kbd>
        </div>
        {searchOpen && (
          <SearchResults query={search} catalog={storeCatalog} onPick={addItem} onClose={()=>setSearchOpen(false)}/>
        )}
      </div>
    </div>
  );

  // ─── Cart list ───
  const CartList = (
    <div className="flex-1 min-h-0 overflow-auto bg-surface">
      {cart.length === 0 ? (
        <div className="h-full flex flex-col items-center justify-center text-center px-8 py-16">
          <div className="w-16 h-16 rounded-full bg-line2 text-muted flex items-center justify-center">
            <I.Cash size={28}/>
          </div>
          <h3 className="mt-4 text-[18px] font-semibold text-ink">Carrello vuoto</h3>
          <p className="mt-1 text-[14px] text-muted max-w-[360px]">
            Cerca un articolo o scansiona un barcode per iniziare la vendita.
            {layout === 'horizontal' && <> Premi <kbd className="num bg-line2 px-1.5 py-0.5 rounded text-[11px] text-ink">F2</kbd> per la ricerca.</>}
            {' '}Per aggiungere un reso usa <strong className="text-ink font-medium">Aggiungi reso</strong>.
          </p>
        </div>
      ) : (
        <>
          {layout === 'horizontal' && (
            <div className="grid grid-cols-[40px_minmax(0,1fr)_112px_minmax(90px,128px)_minmax(96px,128px)_40px] gap-2.5 px-4 sm:px-5 h-10 items-center text-[11px] uppercase tracking-[0.08em] text-muted font-medium hairline">
              <div></div><div>Articolo</div><div>Quantità</div><div className="truncate">Sconto / Reso</div><div className="text-right">Totale riga</div><div></div>
            </div>
          )}
          {cart.map((item, idx) => (
            <CartRow
              key={idx} item={item} idx={idx}
              layout={layout}
              selected={selectedRow === idx}
              onSelect={()=>setSelectedRow(idx)}
              onQty={setQty}
              onRemove={removeRow}
              onEditDiscount={(i)=>{setSelectedRow(i); setModal('rowDiscount');}}
              onPickSeller={(i)=>{ setSellerPickRow(i); setModal('seller'); }}
            />
          ))}
        </>
      )}
    </div>
  );

  // ─── Side panel content ───
  const SidePanelContent = (
    <>
      <div className="p-5 hairline">
        <div className="text-[11px] uppercase tracking-[0.08em] text-muted font-medium mb-2">Cliente</div>
        <CustomerChip customer={customer} onPick={()=>setModal('customer')} onClear={()=>setCustomer(null)}/>
      </div>
      <div className="p-5 hairline">
        <div className="text-[11px] uppercase tracking-[0.08em] text-muted font-medium mb-2.5">Azioni</div>
        <div className="grid grid-cols-2 gap-2">
          <ActionChip icon="Ticket" label="Coupon" sub={coupon ? coupon.label : 'codice promo'} color="purple" active={!!coupon} onClick={()=>setModal('coupon')} />
          <ActionChip icon="Gift"   label="Gift card" sub="emetti carta regalo" color="green" onClick={()=>setModal('giftcard')} />
          <ActionChip icon="Wallet" label="Acconto" sub="incasso parziale" color="green" onClick={()=>setModal('acconto')} />
          <ActionChip icon="Edit" label="Nota" sub={nota || 'aggiungi nota vendita'} color="gray" active={!!nota} onClick={()=>setModal('nota')} />
        </div>
      </div>
      <div className="p-5 flex-1 min-h-0 overflow-auto">
        <div className="text-[11px] uppercase tracking-[0.08em] text-muted font-medium mb-3">Totali</div>
        <TotalsBlock totals={totals} coupon={coupon} onClearCoupon={()=>setCoupon(null)} customer={customer}/>
      </div>
    </>
  );

  // ─── Checkout button ───
  const checkoutBtn = (
    <button
      onClick={()=>setModal('checkout')}
      disabled={cart.length === 0}
      className={`w-full h-[68px] rounded-xl font-bold text-[18px] sm:text-[19px] flex items-center justify-between px-5 sm:px-6 disabled:opacity-30 disabled:cursor-not-allowed transition-all duration-fast ease-standard shadow-soft active:scale-[0.99] text-[var(--text-inverse)]
        ${outcomeType === 'refund'
          ? 'bg-[var(--danger-500)] hover:brightness-105'
          : 'hover:brightness-105'}`}
      style={outcomeType === 'refund' ? null : { background: 'var(--success-500)' }}
    >
      <span className="flex items-center gap-2.5">
        <I.Check size={22}/>
        {outcomeType === 'refund' ? 'Rimborsa cliente'
         : outcomeType === 'even' ? 'Conferma operazione'
         : 'Incassa'}
      </span>
      <span className="num">
        {outcomeType === 'refund'
          ? `−${fmtEur(Math.abs(totals.netBalance))}`
          : outcomeType === 'even'
          ? '—'
          : fmtEur(totals.netBalance)}
      </span>
    </button>
  );

  const handleCheckout = async (payload) => {
    const hasReturns = cart.some(i => i.kind === 'return');
    const hasSales = cart.some(i => i.kind !== 'return');
    const kind = hasReturns && hasSales ? 'mixed' : hasReturns ? 'return-only' : 'sell';
    let res = null;
    if (window.__API__) {
      try {
        res = await window.__API__.mutate('/api/sales/checkout', {
          storeId: activeStoreId,
          customerId: customer ? customer.id : null,
          sellerId: seller ? seller.id : null,
          nota,
          coupon: coupon ? { code: coupon.code, type: coupon.type, value: coupon.value } : null,
          payment: payload,
          lines: cart.map(i => ({ sku: i.sku, name: i.name, qty: i.qty, price: i.price, discount: i.discount || null, kind: i.kind || 'sale', color: i.color, size: i.size, articleId: i.articleId, gift: i.gift || null, refDoc: i.refDoc || null, sellerId: i.sellerId || null, sellerName: i.sellerName || null })),
        });
        if (!res || res.ok === false) return; // non mostrare "completato" se non ha salvato
      } catch (e) {
        // il client mostra già un toast d'errore: NON mostrare "completato" se non ha salvato
        return;
      }
    }
    if (window.__toast) window.__toast(kind === 'return-only' ? 'Reso registrato' : 'Vendita registrata', 'success');
    // numero documento REALE assegnato dal server (es. "SC 2026-0145" → "2026-0145")
    const docNum = res && Array.isArray(res.documents) && res.documents[0]
      ? String(res.documents[0]).replace(/^SC\s+/, '') : null;
    setCompleted({
      ...payload,
      kind,
      docNum,
      netBalance: totals.netBalance,
      saleTotal: totals.saleTotal,
      returnSubtotal: totals.returnSubtotal,
    });
    setModal(null);
  };

  // ─── Layout: HORIZONTAL ───
  if (layout === 'horizontal') {
    return (
      <div className="flex flex-col h-full">
        {Header}
        {CassaBanner}
        {FreeReturnBanner}
        <div className="flex-1 min-h-0 grid grid-cols-[minmax(0,1fr)_minmax(320px,380px)] gap-0">
          <div className="flex flex-col min-h-0 min-w-0 border-r border-line">
            {SearchBar}
            {CartList}
            <div className="px-7 h-12 hairline bg-paper flex items-center justify-between text-[12.5px] text-muted">
              <span><span className="num text-ink font-medium">{totals.count}</span> pezzi · <span className="num text-ink font-medium">{cart.length}</span> righe</span>
              <span>Cassa: <span className="text-ink font-medium">{(seller && seller.name) || (session && session.op && session.op.name) || '—'}</span></span>
            </div>
          </div>
          <aside className="flex flex-col min-h-0 bg-paper">
            {SidePanelContent}
            <div className="p-5 border-t border-line bg-surface">
              {checkoutBtn}
              <div className="mt-2 flex items-center justify-center gap-2 text-[11.5px] text-muted">
                <kbd className="num bg-line2 px-1.5 py-0.5 rounded text-ink">F9</kbd>
                per andare al checkout
              </div>
            </div>
          </aside>
        </div>
        <PosModalsBundle
          modal={modal} setModal={setModal}
          customer={customer} setCustomer={setCustomer}
          cart={cart} setRowDiscount={setRowDiscount} selectedRow={selectedRow}
          setCoupon={setCoupon}
          onIssueGiftCard={onIssueGiftCard}
          onConfirmAcconto={onConfirmAcconto}
          onConfirmReturn={onConfirmReturn}
          onNoDoc={() => setFreeReturnMode(true)}
          totals={totals}
          onCheckout={handleCheckout}
          nota={nota} onSaveNota={setNota} setSeller={handleSellerSelect} storeId={activeStoreId} onResumeHeld={resumeHeld}
        />
        {completed && <CompletedView payload={completed} onNew={newSale}/>}
      </div>
    );
  }

  // ─── Layout: VERTICAL (tablet portrait) ───
  return (
    <div className="flex flex-col h-full">
      {Header}
      {CassaBanner}
      {FreeReturnBanner}
      {SearchBar}

      <div className="flex-1 min-h-0 flex flex-col bg-surface">
        <div className="px-5 py-3 hairline bg-paper space-y-2.5">
          <CustomerChip customer={customer} onPick={()=>setModal('customer')} onClear={()=>setCustomer(null)}/>
          <div className="grid grid-cols-4 gap-1.5">
            <CompactAction icon="Ticket" label="Coupon" active={!!coupon} onClick={()=>setModal('coupon')}/>
            <CompactAction icon="Gift"   label="Gift card" onClick={()=>setModal('giftcard')}/>
            <CompactAction icon="Wallet" label="Acconto" onClick={()=>setModal('acconto')}/>
            <CompactAction icon="Return" label="Reso" active={hasReturnsInCart} onClick={()=>setModal('returnSource')}/>
          </div>
        </div>

        <div className="flex-1 min-h-0 overflow-auto">
          {cart.length === 0 ? (
            <div className="h-full flex flex-col items-center justify-center text-center px-8 py-12">
              <div className="w-16 h-16 rounded-full bg-line2 text-muted flex items-center justify-center">
                <I.Cash size={28}/>
              </div>
              <h3 className="mt-4 text-[17px] font-semibold text-ink">Carrello vuoto</h3>
              <p className="mt-1 text-[13.5px] text-muted max-w-[280px]">
                Cerca un articolo o usa <strong className="text-ink">Reso</strong> per aggiungere resi.
              </p>
            </div>
          ) : cart.map((item, idx) => (
            <CartRow key={idx} item={item} idx={idx} layout="vertical"
              selected={selectedRow === idx}
              onSelect={()=>setSelectedRow(idx)}
              onQty={setQty} onRemove={removeRow}
              onEditDiscount={(i)=>{setSelectedRow(i); setModal('rowDiscount');}}
              onPickSeller={(i)=>{ setSellerPickRow(i); setModal('seller'); }}/>
          ))}
        </div>
      </div>

      {/* Pinned totals + checkout */}
      <div className="border-t border-line bg-surface px-5 pt-4 pb-5 shadow-lg">
        <button onClick={()=>setDrawerOpen(o=>!o)}
          className="w-full flex items-center justify-between mb-3">
          <div className="text-left">
            <div className="text-[11px] uppercase tracking-[0.08em] text-muted font-medium">
              {totals.count} pezzi · {cart.length} righe
            </div>
            <div className="flex items-baseline gap-2">
              <span className={`num text-[28px] leading-none font-semibold
                ${outcomeType === 'refund' ? 'text-neg' : outcomeType === 'even' ? 'text-muted' : 'text-ink'}`}>
                {outcomeType === 'even' ? '—'
                 : outcomeType === 'refund' ? `−${fmtEur(Math.abs(totals.netBalance))}`
                 : fmtEur(totals.netBalance)}
              </span>
              <span className="text-[11px] text-muted">
                {outcomeType === 'even' ? 'pareggiato'
                 : outcomeType === 'refund' ? 'a favore cliente'
                 : 'IVA inclusa'}
              </span>
            </div>
          </div>
          <div className="w-10 h-10 rounded-md hover:bg-[var(--bg-hover)] flex items-center justify-center text-muted">
            {drawerOpen ? <I.ArrowD size={18} className="rotate-180"/> : <I.ArrowU size={18} className="rotate-180"/>}
          </div>
        </button>
        {drawerOpen && (
          <div className="mb-3 p-3.5 rounded-md bg-paper border border-line">
            <TotalsBlock totals={totals} coupon={coupon} onClearCoupon={()=>setCoupon(null)} customer={customer}/>
          </div>
        )}
        {checkoutBtn}
      </div>

      <PosModalsBundle
        modal={modal} setModal={setModal}
        customer={customer} setCustomer={setCustomer}
        cart={cart} setRowDiscount={setRowDiscount} selectedRow={selectedRow}
        setCoupon={setCoupon}
        onIssueGiftCard={onIssueGiftCard}
        onConfirmAcconto={onConfirmAcconto}
        onConfirmReturn={onConfirmReturn}
        onNoDoc={() => setFreeReturnMode(true)}
        totals={totals}
        onCheckout={handleCheckout}
        nota={nota} onSaveNota={setNota} setSeller={handleSellerSelect} storeId={activeStoreId} onResumeHeld={resumeHeld}
      />
      {completed && <CompletedView payload={completed} onNew={newSale}/>}
    </div>
  );
};

// ─── Compact action (vertical layout) ───
const CompactAction = ({ icon, label, active, onClick }) => {
  const Ico = I[icon];
  return (
    <button onClick={onClick}
      className={`flex flex-col items-center justify-center gap-1 h-14 rounded-md border text-[11.5px] font-medium transition-all duration-fast ease-standard
        ${active ? 'bg-[var(--bg-selected)] text-[var(--accent-blue)] shadow-[inset_0_0_0_1px_var(--accent-blue)]' : 'border-line bg-surface text-ink hover:border-strong'}`}>
      <Ico size={16}/>
      {label}
    </button>
  );
};

// ─── Modal bundle ───
const PosModalsBundle = ({ modal, setModal, customer, setCustomer, cart, setRowDiscount, selectedRow, setCoupon, onIssueGiftCard, onConfirmAcconto, onConfirmReturn, onNoDoc, totals, onCheckout, nota, onSaveNota, setSeller, storeId, onResumeHeld }) => (
  <>
    <CustomerModal open={modal === 'customer'} onClose={()=>setModal(null)} onPick={setCustomer}/>
    <SellerModal open={modal === 'seller'} onClose={()=>setModal(null)} onSelect={setSeller} storeId={storeId}/>
    <HeldSalesModal open={modal === 'held'} onClose={()=>setModal(null)} onResume={onResumeHeld} storeId={storeId}/>
    <RowDiscountModal
      open={modal === 'rowDiscount'} onClose={()=>setModal(null)}
      current={selectedRow != null ? cart[selectedRow]?.discount : null}
      onApply={(d) => selectedRow != null && setRowDiscount(selectedRow, d)}
    />
    <CouponModal open={modal === 'coupon'} onClose={()=>setModal(null)} onApply={setCoupon}/>
    <GiftCardModal open={modal === 'giftcard'} onClose={()=>setModal(null)} onIssue={onIssueGiftCard}/>
    <AccontoModal open={modal === 'acconto'} onClose={()=>setModal(null)} totals={totals} onConfirm={onConfirmAcconto}/>
    <ReturnSourceModal
      open={modal === 'returnSource'} onClose={()=>setModal(null)}
      onConfirm={onConfirmReturn}
      onNoDoc={onNoDoc}
    />
    <CheckoutModal
      open={modal === 'checkout'} onClose={()=>setModal(null)}
      totals={totals} customer={customer}
      onComplete={onCheckout}
    />
    <NotaModal open={modal === 'nota'} onClose={()=>setModal(null)} value={nota} onSave={onSaveNota}/>
  </>
);

Object.assign(window, { POS, ProductThumb });
