// ---- Adapter: DB row → UI shape ----
const toUiProduct = (row) => ({
  ...row,
  min:       row.min_stock,
  lastPrice: row.last_price ?? 0,
  avgPrice:  row.avg_price ?? row.last_price ?? 0,
  photo:     row.photo_url,
  supplier:  row.preferred_supplier?.name || '—',
});

function ScreenProducts({ setRoute }) {
  const { CATEGORIES, BRL } = window.SCP;
  const [q, setQ] = useState('');
  const [cat, setCat] = useState('todas');
  const [openProd, setOpenProd] = useState(null);
  const [rows, setRows] = useState([]);
  const [suppliers, setSuppliers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [loadErr, setLoadErr] = useState(null);
  const [editing, setEditing] = useState(null); // null | 'new' | productObject
  const [highlightId, setHighlightId] = useState(null);

  useEffect(() => {
    let mounted = true;
    (async () => {
      try {
        const [prods, sups] = await Promise.all([
          window.scpDb.products.list(),
          window.scpDb.suppliers.list(),
        ]);
        if (!mounted) return;
        setRows(prods.map(toUiProduct));
        setSuppliers(sups);
      } catch (e) {
        if (mounted) setLoadErr(e.message || 'Falha ao carregar produtos');
      } finally {
        if (mounted) setLoading(false);
      }
    })();
    return () => { mounted = false; };
  }, []);

  const list = rows.filter(p =>
    (cat === 'todas' || p.cat === cat) &&
    (!q || (p.name + (p.code || '') + (p.brand || '')).toLowerCase().includes(q.toLowerCase()))
  );

  const kpis = useMemo(() => {
    const total = rows.length;
    const lowStock = rows.filter(p => Number(p.stock) < Number(p.min)).length;
    const validPrices = rows.filter(p => p.lastPrice > 0);
    const avg = validPrices.length
      ? validPrices.reduce((s, p) => s + Number(p.lastPrice), 0) / validPrices.length
      : 0;
    const supSet = new Set(rows.map(p => p.preferred_supplier_id).filter(Boolean));
    const catSet = new Set(rows.map(p => p.cat).filter(Boolean));
    return { total, lowStock, avg, sups: supSet.size, cats: catSet.size };
  }, [rows]);

  const handleDuplicate = async (p) => {
    try {
      const payload = {
        code: (p.code || '78' + Date.now()) + '-D',
        name: p.name + ' (cópia)',
        brand: p.brand,
        cat: p.cat,
        unit: p.unit,
        stock: 0,
        min_stock: p.min,
        last_price: p.lastPrice,
        avg_price: p.avgPrice,
        preferred_supplier_id: p.preferred_supplier_id || null,
        photo_url: p.photo,
      };
      const created = await window.scpDb.products.create(payload);
      const ui = toUiProduct(created);
      setRows(prev => [ui, ...prev]);
      setOpenProd(null);
      setHighlightId(ui.id);
      window.scpToast('Produto duplicado', { kind: 'emerald', sub: ui.name });
      setTimeout(() => setHighlightId(null), 2400);
    } catch (e) {
      window.scpToast('Erro ao duplicar', { kind: 'coral', sub: e.message });
    }
  };

  const handleAddToQuote = (p) => {
    setOpenProd(null);
    window.scpToast(`Adicionado à nova cotação`, { kind: 'emerald', sub: p.name });
    setTimeout(() => setRoute && setRoute('newQuotation'), 500);
  };

  const handleSave = async (data) => {
    try {
      const payload = {
        code: data.code || '78' + Date.now(),
        name: data.name,
        brand: data.brand || null,
        cat: data.cat,
        unit: data.unit || 'un',
        stock: Number(data.stock) || 0,
        min_stock: Number(data.min) || 0,
        last_price: data.lastPrice ? Number(data.lastPrice) : null,
        avg_price: data.lastPrice ? Number(data.lastPrice) : null,
        preferred_supplier_id: data.supplier_id || null,
        photo_url: data.photo_url || null,
      };
      const isEdit = editing && editing !== 'new';
      const saved = isEdit
        ? await window.scpDb.products.update(editing.id, payload)
        : await window.scpDb.products.create(payload);
      const ui = toUiProduct(saved);
      setRows(prev => isEdit
        ? prev.map(p => p.id === ui.id ? ui : p)
        : [ui, ...prev]);
      setEditing(null);
      setHighlightId(ui.id);
      window.scpToast(isEdit ? 'Produto atualizado' : 'Produto cadastrado', { kind: 'emerald', sub: ui.name });
      setTimeout(() => setHighlightId(null), 2400);
    } catch (e) {
      window.scpToast('Erro ao salvar', { kind: 'coral', sub: e.message });
    }
  };

  const handleDelete = async (p) => {
    if (!confirm(`Remover "${p.name}"? O produto ficará oculto da lista.`)) return;
    try {
      await window.scpDb.products.remove(p.id);
      setRows(prev => prev.filter(x => x.id !== p.id));
      setOpenProd(null);
      window.scpToast('Produto removido', { kind: 'amber', sub: p.name });
    } catch (e) {
      window.scpToast('Erro ao remover', { kind: 'coral', sub: e.message });
    }
  };

  return (
    <div className="scp-screen scp-fade-in">
      <div className="scp-dash-grid">
        <Stat label="Produtos cadastrados" value={String(kpis.total)} sub={`${kpis.cats} categoria${kpis.cats === 1 ? '' : 's'} · ${kpis.sups} fornecedor${kpis.sups === 1 ? '' : 'es'}`} icon={<Icon.Product size={16}/>}/>
        <Stat label="Abaixo do mínimo" value={String(kpis.lowStock)} sub={kpis.lowStock > 0 ? 'Sugerir cotação' : 'Tudo em dia'} delta={kpis.lowStock > 0 ? 'reposição' : 'ok'} deltaTone={kpis.lowStock > 0 ? 'amber' : 'emerald'} icon={<Icon.Warning size={16}/>}/>
        <Stat label="Preço médio (cesta)" value={BRL(kpis.avg)} sub="Média do último preço pago" icon={<Icon.TrendDown size={16}/>}/>
        <Stat label="Listas salvas" value="0" sub="Templates reutilizáveis · em construção" icon={<Icon.Copy size={16}/>}/>
      </div>

      {loadErr && (
        <Card style={{ padding: 14, borderColor: 'oklch(0.42 0.10 25 / .55)', background: 'oklch(0.26 0.08 25 / .25)' }}>
          <strong style={{ color: 'oklch(0.88 0.14 25)' }}>Falha ao carregar produtos:</strong>{' '}
          <span style={{ color: 'var(--fg-2)', fontSize: 13 }}>{loadErr}</span>
          <div style={{ fontSize: 11.5, color: 'var(--fg-3)', marginTop: 6 }}>
            Verifique se o schema, seed-suppliers, seed-products e storage.sql foram rodados.
          </div>
        </Card>
      )}

      <Card style={{ padding: 0, overflow: 'hidden' }}>
        <div className="scp-list-head">
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            <button className={cls('scp-chip', cat === 'todas' && 'active')} onClick={() => setCat('todas')}>Todas</button>
            {CATEGORIES.map(c => (
              <button key={c.key} className={cls('scp-chip', cat === c.key && 'active')} onClick={() => setCat(c.key)}>{c.label}</button>
            ))}
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            <Input icon={<Icon.Search size={16}/>} placeholder="Buscar produto, código de barras…" value={q} onChange={e => setQ(e.target.value)} />
            <Btn kind="ghost" icon={<Icon.Camera size={16}/>} onClick={() => window.scpToast('Câmera não disponível em demo', { kind: 'amber', sub: 'Aponte para o código de barras na versão final' })}>Ler código</Btn>
            <Btn kind="ghost" icon={<Icon.Upload size={16}/>} onClick={() => window.scpToast('Pronto para receber planilha', { kind: 'sky', sub: 'Aceita .xlsx, .csv e .ods com até 5MB' })}>Importar</Btn>
            <Btn kind="primary" icon={<Icon.Plus size={16}/>} onClick={() => setEditing('new')}>Novo Produto</Btn>
          </div>
        </div>

        <table className="scp-table">
          <thead>
            <tr>
              <th>Produto</th>
              <th>Categoria</th>
              <th>Unidade</th>
              <th style={{ textAlign: 'right' }}>Estoque</th>
              <th style={{ textAlign: 'right' }}>Mínimo</th>
              <th style={{ textAlign: 'right' }}>Últ. preço</th>
              <th style={{ textAlign: 'right' }}>Preço médio</th>
              <th>Melhor fornecedor</th>
              <th>Tendência (90d)</th>
              <th style={{ width: 40 }}></th>
            </tr>
          </thead>
          <tbody>
            {loading && (
              <tr><td colSpan={10} style={{ padding: 40, textAlign: 'center', color: 'var(--fg-3)' }}>Carregando produtos…</td></tr>
            )}
            {!loading && list.length === 0 && (
              <tr><td colSpan={10} style={{ padding: 40, textAlign: 'center', color: 'var(--fg-3)' }}>
                {rows.length === 0 ? 'Nenhum produto cadastrado ainda.' : 'Nenhum produto com este filtro.'}
              </td></tr>
            )}
            {!loading && list.map(p => {
              const c = CATEGORIES.find(c => c.key === p.cat);
              const low = p.stock < p.min;
              const ratio = p.stock / p.min;
              const seed = parseInt(p.id.slice(-3), 10) || 0;
              const spark = [80, 88, 84, 92, 86, 82, 90, 87, 85, 80].map((v, i) => v + ((seed * (i+1)) % 9) - 4);
              return (
                <tr key={p.id} className={cls('clickable', highlightId === p.id && 'just-added')} onClick={() => setOpenProd(p)}>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <span className="scp-prod-photo">
                        {p.photo ? <img src={p.photo} alt={p.name}/> : <Icon.Product size={18}/>}
                      </span>
                      <div style={{ minWidth: 0 }}>
                        <div className="em">{p.name}</div>
                        <div className="num" style={{ fontSize: 11, color: 'var(--fg-3)' }}>
                          {p.code} · {p.id}{p.brand && p.brand !== '—' ? ` · ${p.brand}` : ''}
                        </div>
                      </div>
                    </div>
                  </td>
                  <td><Badge tone={c.tone}>{c.label}</Badge></td>
                  <td style={{ color: 'var(--fg-3)' }}>{p.unit}</td>
                  <td className="num" style={{ textAlign: 'right' }}>
                    <span style={{ color: low ? 'oklch(0.84 0.14 78)' : 'var(--fg)', fontWeight: 600 }}>{p.stock}</span>
                    <div style={{ width: 60, height: 4, background: 'var(--surface-2)', borderRadius: 999, marginLeft: 'auto', marginTop: 4, overflow: 'hidden' }}>
                      <div style={{ width: Math.min(100, ratio * 100) + '%', height: '100%', background: low ? 'oklch(0.78 0.14 78)' : 'oklch(0.74 0.16 160)' }} />
                    </div>
                  </td>
                  <td className="num" style={{ textAlign: 'right', color: 'var(--fg-3)' }}>{p.min}</td>
                  <td className="num em" style={{ textAlign: 'right' }}>{BRL(p.lastPrice)}</td>
                  <td className="num" style={{ textAlign: 'right', color: 'var(--fg-3)' }}>{BRL(p.avgPrice)}</td>
                  <td style={{ color: 'var(--fg-2)', fontSize: 12 }}>{p.supplier}</td>
                  <td><Sparkline values={spark} width={80} height={26}/></td>
                  <td><IconBtn icon={<Icon.Chevron size={14}/>} size="sm"/></td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </Card>

      {editing && (
        <ProductFormModal
          mode={editing === 'new' ? 'new' : 'edit'}
          initial={editing === 'new' ? null : editing}
          onClose={() => setEditing(null)}
          onSave={handleSave}
          categories={CATEGORIES}
          suppliers={suppliers}
        />
      )}

      <Drawer
        open={!!openProd}
        onClose={() => setOpenProd(null)}
        eyebrow={openProd?.code}
        title={openProd?.name || ''}
        headerRight={openProd && (() => {
          const c = CATEGORIES.find(x => x.key === openProd.cat);
          return c ? <Badge tone={c.tone}>{c.label}</Badge> : null;
        })()}
        footer={openProd && (
          <>
            <Btn kind="ghost" icon={<Icon.Trash size={14}/>} onClick={() => handleDelete(openProd)} style={{ color: 'oklch(0.82 0.14 25)', marginRight: 'auto' }}>Excluir</Btn>
            <Btn kind="ghost" icon={<Icon.Edit size={14}/>} onClick={() => { setEditing(openProd); setOpenProd(null); }}>Editar</Btn>
            <Btn kind="secondary" icon={<Icon.Copy size={14}/>} onClick={() => handleDuplicate(openProd)}>Duplicar</Btn>
            <Btn kind="primary" icon={<Icon.Quote size={14}/>} onClick={() => handleAddToQuote(openProd)}>Adicionar à cotação</Btn>
          </>
        )}
      >
        {openProd && <ProductDetail product={openProd} categories={CATEGORIES} />}
      </Drawer>
    </div>
  );
}

function ProductDetail({ product: p, categories }) {
  const { BRL } = window.SCP;
  const c = categories.find(x => x.key === p.cat);
  const low = Number(p.stock) < Number(p.min);
  const ratio = p.min > 0 ? Math.min(100, (Number(p.stock) / Number(p.min)) * 100) : 0;
  const diff = (p.lastPrice || 0) - (p.avgPrice || 0);
  const diffPct = p.avgPrice ? ((diff / p.avgPrice) * 100).toFixed(1) : '0.0';
  const supplier = p.preferred_supplier; // já vem populado do join
  const seed = parseInt(p.id.slice(-3), 10) || 0;
  const spark = [80, 88, 84, 92, 86, 82, 90, 87, 85, 80].map((v, i) => v + ((seed * (i+1)) % 9) - 4);

  return (
    <>
      <div className="scp-detail-hero" style={{ background: 'oklch(0.20 0.012 250 / .5)', border: '1px solid var(--border-soft)' }}>
        <div style={{
          width: 64, height: 64, borderRadius: 12,
          display: 'grid', placeItems: 'center', overflow: 'hidden',
          background: p.photo ? 'transparent' : 'oklch(0.30 0.04 160)',
          color: 'oklch(0.92 0.14 160)',
          border: p.photo ? '1px solid var(--border-soft)' : 'none',
        }}>
          {p.photo ? <img src={p.photo} alt={p.name} style={{ width: '100%', height: '100%', objectFit: 'cover' }}/> : <Icon.Product size={28}/>}
        </div>
        <div style={{ minWidth: 0 }}>
          <div className="name">{p.name}</div>
          <div className="meta">{p.code} · {p.id} · {p.unit}{p.brand && p.brand !== '—' ? ` · marca ${p.brand}` : ''}</div>
          <div style={{ marginTop: 8 }}>
            {c && <Pill tone={c.tone}>{c.label}</Pill>}
          </div>
        </div>
      </div>

      <div className="scp-detail-section">
        <h4>Preço</h4>
        <div className="scp-detail-metrics">
          <div className="scp-detail-metric">
            <span className="l">Último preço</span>
            <span className="v em">{BRL(p.lastPrice)}</span>
            <span className="s">{p.unit}</span>
          </div>
          <div className="scp-detail-metric">
            <span className="l">Preço médio (90d)</span>
            <span className="v">{BRL(p.avgPrice)}</span>
            <span className="s" style={{ color: diff < 0 ? 'oklch(0.86 0.14 160)' : 'oklch(0.84 0.14 78)' }}>
              {diff < 0 ? '↓' : '↑'} {Math.abs(diffPct)}% vs. médio
            </span>
          </div>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 14px', background: 'var(--surface-2)', border: '1px solid var(--border-soft)', borderRadius: 10 }}>
          <Sparkline values={spark} width={120} height={36}/>
          <div style={{ fontSize: 11.5, color: 'var(--fg-3)' }}>Tendência 90 dias</div>
        </div>
      </div>

      <div className="scp-detail-section">
        <h4>Estoque</h4>
        <div className="scp-detail-metrics">
          <div className="scp-detail-metric">
            <span className="l">Atual</span>
            <span className="v" style={{ color: low ? 'oklch(0.86 0.14 78)' : 'var(--fg)' }}>{p.stock} {p.unit}</span>
            <span className="s">{low ? 'Abaixo do mínimo' : 'Saudável'}</span>
          </div>
          <div className="scp-detail-metric">
            <span className="l">Mínimo</span>
            <span className="v">{p.min}</span>
            <span className="s">Limite para reposição</span>
          </div>
        </div>
        <div style={{ height: 8, background: 'var(--surface-2)', borderRadius: 999, overflow: 'hidden', border: '1px solid var(--border-soft)' }}>
          <div style={{
            width: ratio + '%', height: '100%',
            background: low ? 'oklch(0.78 0.14 78)' : 'linear-gradient(90deg, oklch(0.74 0.16 160), oklch(0.65 0.14 230))',
            transition: 'width .3s ease',
          }}/>
        </div>
        <span style={{ fontSize: 11.5, color: 'var(--fg-3)' }}>{ratio.toFixed(0)}% do mínimo</span>
      </div>

      <div className="scp-detail-section">
        <h4>Fornecedor preferencial</h4>
        {supplier ? (
          <div className="scp-detail-list">
            <div className="scp-detail-list-row">
              <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <Avatar name={supplier.name} size={32}/>
                <div>
                  <div className="n">{supplier.name}</div>
                  <div className="s">{supplier.city || '—'} · score {supplier.score}</div>
                </div>
              </div>
              <span className="v">{supplier.avg_delivery || '—'}</span>
            </div>
          </div>
        ) : (
          <div className="scp-detail-empty">Nenhum fornecedor preferencial definido.</div>
        )}
      </div>
    </>
  );
}

function ProductFormModal({ mode, initial, onClose, onSave, categories, suppliers }) {
  const isEdit = mode === 'edit';
  const [name, setName] = useState(initial?.name || '');
  const [code, setCode] = useState(initial?.code || '');
  const [brand, setBrand] = useState(initial?.brand || '');
  const [cat, setCat] = useState(initial?.cat || 'secos');
  const [unit, setUnit] = useState(initial?.unit || 'un');
  const [stock, setStock] = useState(initial?.stock ?? '');
  const [min, setMin] = useState(initial?.min ?? '');
  const [lastPrice, setLastPrice] = useState(initial?.lastPrice ?? '');
  const [supplierId, setSupplierId] = useState(initial?.preferred_supplier_id || '');
  const [photoUrl, setPhotoUrl] = useState(initial?.photo || null);
  const [previewUrl, setPreviewUrl] = useState(initial?.photo || null);
  const [uploading, setUploading] = useState(false);
  const [saving, setSaving] = useState(false);

  const canSubmit = name.trim().length >= 2 && !uploading && !saving;

  const onPhoto = async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    // Preview imediato
    const reader = new FileReader();
    reader.onload = (ev) => setPreviewUrl(ev.target.result);
    reader.readAsDataURL(file);
    // Upload no Storage
    setUploading(true);
    try {
      const url = await window.scpDb.products.uploadPhoto(file, code || name);
      setPhotoUrl(url);
      window.scpToast('Foto enviada', { kind: 'emerald' });
    } catch (err) {
      window.scpToast('Falha no upload', { kind: 'coral', sub: err.message });
      setPreviewUrl(photoUrl); // volta ao anterior
    } finally {
      setUploading(false);
    }
  };

  const submit = async () => {
    if (!canSubmit) return;
    setSaving(true);
    try {
      await onSave({
        name: name.trim(), code: code.trim(), brand: brand.trim(),
        cat, unit: unit.trim(),
        stock, min, lastPrice,
        supplier_id: supplierId || null,
        photo_url: photoUrl,
      });
    } finally {
      setSaving(false);
    }
  };

  return ReactDOM.createPortal((
    <div className="scp-modal-mask" onClick={onClose}>
      <div className="scp-modal" style={{ width: 640 }} onClick={e => e.stopPropagation()}>
        <div className="scp-modal-head">
          <h3>{isEdit ? 'Editar Produto' : 'Novo Produto'}</h3>
          <IconBtn icon={<Icon.X size={14}/>} size="sm" onClick={onClose}/>
        </div>
        <div className="scp-modal-body" style={{ padding: '18px 22px' }}>
          <div className="scp-wfield-list">
            <div style={{ display: 'grid', gridTemplateColumns: '96px 1fr', gap: 14, alignItems: 'start' }}>
              <label className="scp-photo-upload" style={{ cursor: uploading ? 'wait' : 'pointer' }}>
                {previewUrl ? (
                  <img src={previewUrl} alt="Produto" />
                ) : (
                  <>
                    <Icon.Camera size={20}/>
                    <span>{uploading ? 'Enviando…' : 'Foto'}</span>
                  </>
                )}
                <input type="file" accept="image/*" onChange={onPhoto} disabled={uploading} style={{ display: 'none' }} />
              </label>
              <div className="scp-field" style={{ minWidth: 0 }}>
                <span>Nome do produto <em style={{ color: 'oklch(0.74 0.18 25)', fontStyle: 'normal' }}>*</em></span>
                <Input placeholder="Ex.: Queijo Parmesão Ralado 200g" value={name} onChange={e => setName(e.target.value)} autoFocus />
              </div>
            </div>
            <div className="scp-field-row">
              <div className="scp-field">
                <span>Marca</span>
                <Input placeholder="Ex.: Tirolez, Heineken, In natura" value={brand} onChange={e => setBrand(e.target.value)} />
              </div>
              <div className="scp-field">
                <span>Código de barras</span>
                <Input placeholder="789000000000" value={code} onChange={e => setCode(e.target.value)} />
              </div>
            </div>
            <div className="scp-field-row">
              <div className="scp-field">
                <span>Unidade</span>
                <Input placeholder="kg · un · cx 12" value={unit} onChange={e => setUnit(e.target.value)} />
              </div>
              <div className="scp-field">
                <span>Categoria</span>
                <select className="scp-select" value={cat} onChange={e => setCat(e.target.value)}>
                  {categories.map(c => <option key={c.key} value={c.key}>{c.label}</option>)}
                </select>
              </div>
            </div>
            <div className="scp-field-row">
              <div className="scp-field">
                <span>Estoque atual</span>
                <Input placeholder="0" type="number" value={stock} onChange={e => setStock(e.target.value)} />
              </div>
              <div className="scp-field">
                <span>Estoque mínimo</span>
                <Input placeholder="10" type="number" value={min} onChange={e => setMin(e.target.value)} />
              </div>
            </div>
            <div className="scp-field-row">
              <div className="scp-field">
                <span>Último preço (R$)</span>
                <Input placeholder="0,00" type="number" step="0.01" value={lastPrice} onChange={e => setLastPrice(e.target.value)} />
              </div>
              <div className="scp-field">
                <span>Fornecedor preferencial</span>
                <select className="scp-select" value={supplierId} onChange={e => setSupplierId(e.target.value)}>
                  <option value="">— sem fornecedor preferencial —</option>
                  {suppliers.map(s => (
                    <option key={s.id} value={s.id}>{s.name}{s.city ? ` · ${s.city}` : ''}</option>
                  ))}
                </select>
              </div>
            </div>
          </div>
        </div>
        <div className="scp-modal-foot">
          <span>
            {uploading ? 'Enviando foto…' :
             saving ? 'Salvando…' :
             isEdit ? 'As alterações serão aplicadas ao produto.' : 'Preencha o nome para habilitar o cadastro.'}
          </span>
          <div style={{ display: 'flex', gap: 8 }}>
            <Btn kind="ghost" onClick={onClose}>Cancelar</Btn>
            <Btn kind="primary" disabled={!canSubmit} onClick={submit} icon={<Icon.Check size={14}/>}>
              {isEdit ? 'Salvar alterações' : 'Cadastrar produto'}
            </Btn>
          </div>
        </div>
      </div>
    </div>
  ), document.body);
}

(function() {
  if (document.getElementById('scp-products-css')) return;
  const s = document.createElement('style'); s.id = 'scp-products-css';
  s.textContent = `
    .scp-table tbody tr.just-added td { background: oklch(0.26 0.06 160 / .35); animation: justAddedPulseRow 2.4s ease-out; }
    @keyframes justAddedPulseRow {
      0%   { background: oklch(0.34 0.10 160 / .55); box-shadow: inset 3px 0 0 oklch(0.78 0.16 160); }
      100% { background: oklch(0.205 0.012 250); box-shadow: inset 3px 0 0 transparent; }
    }
    .scp-photo-upload {
      width: 96px; height: 96px; border-radius: 12px;
      display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
      background: var(--surface-2); border: 2px dashed var(--border-strong);
      color: var(--fg-3); font-size: 11px; font-weight: 600;
      transition: border-color .15s, color .15s;
      overflow: hidden;
    }
    .scp-photo-upload:hover { border-color: oklch(0.55 0.10 160); color: var(--fg-2); }
    .scp-photo-upload img { width: 100%; height: 100%; object-fit: cover; }
    .scp-prod-photo {
      width: 38px; height: 38px; border-radius: 8px;
      background: var(--surface-2); border: 1px solid var(--border-soft);
      display: grid; place-items: center; color: var(--fg-3);
      overflow: hidden; flex-shrink: 0;
    }
    .scp-prod-photo img { width: 100%; height: 100%; object-fit: cover; }
  `;
  document.head.appendChild(s);
})();

window.ScreenProducts = ScreenProducts;
