function Builder({ sectorId, sectors, onFinish, onBack, accent, showRecs, initialSelections }) {
  const sector = (sectors || []).find(s => s.id === sectorId) || (sectors || [])[0] || { id: 'burger', label: 'Packaging' };
  const [products, setProducts] = React.useState(null);
  const [selections, setSelections] = React.useState(initialSelections || {});
  const [lastAdded, setLastAdded] = React.useState(null);
  const [dismissed, setDismissed] = React.useState({});
  const isMobile = useMedia('(max-width: 900px)');
  const [mobileTab, setMobileTab] = React.useState('panel'); // panel | scene

  React.useEffect(() => {
    setProducts(null);
    api.get('/api/products?sector=' + encodeURIComponent(sector.id)).then(setProducts);
  }, [sector.id]);

  const selectedList = React.useMemo(() => (
    Object.entries(selections).map(([pid, v]) => {
      const p = (products || []).find(x => x.id === pid);
      return p ? { ...p, ...v } : null;
    }).filter(Boolean)
  ), [selections, products]);

  const activePairs = React.useMemo(() => {
    const ids = new Set(selectedList.map(s => s.id));
    const recs = new Set();
    selectedList.forEach(s => s.pairs?.forEach(p => { if (!ids.has(p) && !dismissed[p]) recs.add(p); }));
    return [...recs].map(id => (products || []).find(p => p.id === id)).filter(Boolean);
  }, [selections, dismissed, products, selectedList]);

  const getUnit = (p, qty) => {
    const tiers = [...(p.pricing || [])].sort((a,b) => a.qty - b.qty);
    let unit = tiers[0]?.unit ?? 0;
    for (const t of tiers) if (qty >= t.qty) unit = t.unit;
    return unit;
  };

  const addProduct = (productId) => {
    const p = (products || []).find(x => x.id === productId);
    if (!p) return;
    const v = p.variants.find(x => x.recommended) || p.variants[0];
    setSelections(prev => ({ ...prev, [productId]: { variantId: v.id, qty: p.moq } }));
    setLastAdded(productId);
    setTimeout(() => setLastAdded(null), 1400);
  };

  const removeProduct = (productId) => {
    setSelections(prev => { const next = { ...prev }; delete next[productId]; return next; });
  };

  const updateQty = (productId, qty) =>
    setSelections(prev => ({ ...prev, [productId]: { ...prev[productId], qty } }));

  const updateVariant = (productId, variantId) =>
    setSelections(prev => ({ ...prev, [productId]: { ...prev[productId], variantId } }));

  const total = selectedList.reduce((sum, s) => sum + getUnit(s, s.qty) * s.qty, 0);
  const totalUnits = selectedList.reduce((s, x) => s + x.qty, 0);

  if (!products) return <PageLoading />;

  return (
    <div style={{ minHeight: '100vh', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      <TopBar
        step={1}
        onLogo={onBack}
        stepLabels={['Sector', 'Build', 'Review', 'Contact']}
        right={<>
          <button onClick={onBack} style={{
            background: 'transparent', border: 0, color: 'var(--muted)',
            fontSize: 12.5, display: 'inline-flex', alignItems: 'center', gap: 6, cursor: 'pointer',
          }}>
            <svg width="10" height="10" viewBox="0 0 16 16" fill="none"><path d="M13 8 L3 8 M7 4 L3 8 L7 12" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round"/></svg>
            <span className="hide-mobile">Change sector</span>
          </button>
          <span className="hide-mobile" style={{ width: 1, height: 12, background: 'var(--line-2)' }} />
          <span className="mono hide-mobile" style={{ fontSize: 11, letterSpacing: '0.05em', textTransform: 'uppercase' }}>
            {sector.label}
          </span>
        </>}
      />

      {isMobile && (
        <div style={{
          display: 'flex', gap: 4, padding: '10px 16px',
          background: 'var(--paper)', borderBottom: '.5px solid var(--line)',
        }}>
          {[
            ['panel', 'Catalogue', products.length],
            ['scene', 'Set', selectedList.length],
          ].map(([k, l, n]) => (
            <button
              key={k}
              onClick={() => setMobileTab(k)}
              style={{
                flex: 1, padding: '9px 12px', borderRadius: 8, border: 0,
                background: mobileTab === k ? 'var(--ink)' : 'transparent',
                color: mobileTab === k ? 'var(--paper)' : 'var(--ink)',
                fontSize: 13, fontWeight: 500,
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
              }}
            >
              {l}
              <span className="mono" style={{ fontSize: 10, opacity: 0.65 }}>{n}</span>
            </button>
          ))}
        </div>
      )}

      <div className="two-col-135" style={{ flex: 1, overflow: 'hidden' }}>
        {(!isMobile || mobileTab === 'scene') && (
          <Scene
            selectedList={selectedList}
            lastAdded={lastAdded}
            onRemove={removeProduct}
            total={total}
            totalUnits={totalUnits}
            onFinish={() => onFinish(selections)}
            sector={sector}
            products={products}
            getUnit={getUnit}
            accent={accent}
            isMobile={isMobile}
          />
        )}

        {(!isMobile || mobileTab === 'panel') && (
          <ProductPanel
            products={products}
            selections={selections}
            addProduct={addProduct}
            removeProduct={removeProduct}
            updateQty={updateQty}
            updateVariant={updateVariant}
            activePairs={activePairs}
            getUnit={getUnit}
            accent={accent}
            showRecs={showRecs}
            dismissRec={(id) => setDismissed(d => ({...d, [id]: true}))}
          />
        )}
      </div>

      {isMobile && selectedList.length >= 1 && (
        <div style={{
          position: 'sticky', bottom: 0, zIndex: 30,
          padding: '12px 16px',
          background: 'rgba(245,243,238,.9)',
          backdropFilter: 'blur(12px)',
          borderTop: '.5px solid var(--line)',
          display: 'flex', gap: 10, alignItems: 'center',
        }}>
          <div style={{ flex: 1 }}>
            <div className="mono" style={{ fontSize: 10, color: 'var(--muted)', letterSpacing: '0.04em' }}>
              {selectedList.length} items · {totalUnits.toLocaleString('en-GB')} units
            </div>
            <div style={{ fontSize: 15, fontWeight: 500 }}>
              £{total.toLocaleString('en-GB', { maximumFractionDigits: 0 })}
            </div>
          </div>
          <Button
            variant={selectedList.length >= 2 ? 'primary' : 'quiet'}
            size="md"
            disabled={selectedList.length < 2}
            iconRight={<ArrowRight size={13}/>}
            onClick={() => onFinish(selections)}
          >
            Finish
          </Button>
        </div>
      )}
    </div>
  );
}

function Scene({ selectedList, lastAdded, onRemove, total, totalUnits, onFinish, sector, products, getUnit, accent, isMobile }) {
  const cols = selectedList.length <= 3 ? Math.max(1, selectedList.length) : selectedList.length <= 6 ? 3 : 4;

  return (
    <section className="pad-lg" style={{
      position: 'relative',
      background: 'var(--bg-2)',
      borderRight: isMobile ? 'none' : '.5px solid var(--line)',
      display: 'flex', flexDirection: 'column', overflow: 'hidden',
      minHeight: isMobile ? '60vh' : undefined,
    }}>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start',
        padding: isMobile ? '18px 20px 12px' : '28px 40px 20px',
        gap: 16, flexWrap: 'wrap',
      }}>
        <div>
          <div className="mono" style={{ fontSize: 10.5, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--muted)', marginBottom: 6 }}>
            Your Packaging Set · {sector.label}
          </div>
          <h2 className="responsive-h2" style={{
            fontFamily: 'var(--font-serif)', fontStyle: 'italic',
            fontSize: 34, fontWeight: 400, margin: 0, letterSpacing: '-0.015em',
          }}>
            {selectedList.length === 0 ? 'An empty table.' : selectedList.length === 1 ? 'A beginning.' : `${selectedList.length} pieces, assembled.`}
          </h2>
        </div>
        <div style={{ display: 'flex', gap: 24, alignItems: 'flex-start' }}>
          <Metric label="Items" value={selectedList.length.toString().padStart(2, '0')} align="right" />
          <Metric label="Units" value={totalUnits.toLocaleString('en-GB')} align="right" />
          <Metric label="Est." value={`£${total.toLocaleString('en-GB', { maximumFractionDigits: 0 })}`} align="right" />
        </div>
      </div>

      <div style={{
        flex: 1, position: 'relative',
        margin: isMobile ? '0 16px' : '0 40px',
        borderRadius: 20,
        background: 'radial-gradient(ellipse at 50% 55%, #FCFAF5 0%, #F2EEE4 60%, #E8E2D2 100%)',
        border: '.5px solid var(--line)',
        overflow: 'hidden',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        minHeight: 280,
      }}>
        <svg width="100%" height="100%" style={{ position: 'absolute', inset: 0, opacity: 0.25 }}>
          <defs>
            <pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
              <path d="M 40 0 L 0 0 L 0 40" fill="none" stroke="rgba(21,19,14,.06)" strokeWidth="0.5"/>
            </pattern>
          </defs>
          <rect width="100%" height="100%" fill="url(#grid)"/>
        </svg>

        <div style={{
          position: 'absolute', left: '10%', right: '10%', top: '60%',
          height: 1, background: 'linear-gradient(90deg, transparent, rgba(21,19,14,.1), transparent)',
        }} />

        {selectedList.length === 0 ? (
          <EmptyScene />
        ) : (
          <div style={{
            display: 'grid',
            gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))`,
            gap: 8, padding: isMobile ? 24 : 40,
            maxWidth: '90%', width: '100%',
          }}>
            {selectedList.map((item, i) => {
              const variant = item.variants.find(v => v.id === item.variantId);
              const unit = getUnit(item, item.qty);
              return (
                <SceneItem
                  key={item.id}
                  product={item}
                  variant={variant}
                  qty={item.qty}
                  unit={unit}
                  isNew={lastAdded === item.id}
                  onRemove={() => onRemove(item.id)}
                  index={i}
                />
              );
            })}
          </div>
        )}

        {!isMobile && ['tl','tr','bl','br'].map(c => (
          <div key={c} className="mono" style={{
            position: 'absolute',
            top: c.startsWith('t') ? 16 : 'auto',
            bottom: c.startsWith('b') ? 16 : 'auto',
            left: c.endsWith('l') ? 16 : 'auto',
            right: c.endsWith('r') ? 16 : 'auto',
            fontSize: 10, color: 'var(--muted)', letterSpacing: '0.08em',
            opacity: 0.6,
          }}>
            {c === 'tl' && '┌ STAGE'}
            {c === 'tr' && '1920×1080 ┐'}
            {c === 'bl' && '└ v1.0'}
            {c === 'br' && `ISO 30° ┘`}
          </div>
        ))}
      </div>

      {!isMobile && (
        <div style={{
          display: 'flex', justifyContent: 'space-between', alignItems: 'center',
          padding: '24px 40px', gap: 12, flexWrap: 'wrap',
        }}>
          <span className="mono" style={{ fontSize: 11, letterSpacing: '0.04em', color: 'var(--muted)' }}>
            {selectedList.length === 0 ? 'Add your first item →' :
             selectedList.length < 3 ? `${3 - selectedList.length} more for a complete set` :
             'Looking good. Ready to review?'}
          </span>
          <div style={{ display: 'flex', gap: 10 }}>
            <Button variant="ghost" size="md" disabled={selectedList.length === 0}>Save draft</Button>
            <Button
              variant={selectedList.length >= 2 ? 'primary' : 'quiet'}
              size="md"
              disabled={selectedList.length < 2}
              iconRight={<ArrowRight size={13}/>}
              onClick={onFinish}
            >
              Finish your set
            </Button>
          </div>
        </div>
      )}
    </section>
  );
}

function EmptyScene() {
  return (
    <div style={{
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      gap: 16, color: 'var(--muted)', textAlign: 'center', padding: 40,
    }}>
      <svg width="80" height="80" viewBox="0 0 140 140" style={{ opacity: 0.3 }}>
        <ellipse cx="70" cy="118" rx="40" ry="5" fill="rgba(21,19,14,1)" opacity="0.1" />
        <path d="M30 80 L70 58 L110 80 L70 102 Z" fill="none" stroke="rgba(21,19,14,.4)" strokeWidth="1" strokeDasharray="3 3"/>
        <path d="M30 80 L30 92 L70 114 L70 102 Z" fill="none" stroke="rgba(21,19,14,.4)" strokeWidth="1" strokeDasharray="3 3"/>
        <path d="M110 80 L110 92 L70 114 L70 102 Z" fill="none" stroke="rgba(21,19,14,.4)" strokeWidth="1" strokeDasharray="3 3"/>
      </svg>
      <div style={{ fontFamily: 'var(--font-serif)', fontStyle: 'italic', fontSize: 20, color: 'var(--ink-2)' }}>
        Your stage is set.
      </div>
      <div style={{ fontSize: 13, maxWidth: 280 }}>
        Start adding items from the panel. We'll arrange them here for you to review.
      </div>
    </div>
  );
}

function SceneItem({ product, variant, qty, unit, isNew, onRemove, index }) {
  const [hover, setHover] = React.useState(false);

  return (
    <div
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        position: 'relative', aspectRatio: '1 / 1',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        animation: isNew ? 'drop .6s cubic-bezier(.2,1.6,.5,1) both' : `fadeIn .4s ${index*0.05}s both`,
        transition: 'transform .3s',
        transform: hover ? 'translateY(-3px)' : 'translateY(0)',
      }}
    >
      <ProductScenePicture product={product} />

      <div style={{
        position: 'absolute', bottom: 4, left: '50%', transform: 'translateX(-50%)',
        display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
        opacity: hover ? 1 : 0.85, transition: 'opacity .2s', pointerEvents: 'none',
      }}>
        <span style={{
          fontSize: 11.5, fontWeight: 500, letterSpacing: '-0.01em',
          background: 'rgba(250,248,243,.9)', padding: '3px 9px', borderRadius: 20,
          border: '.5px solid var(--line-2)', backdropFilter: 'blur(4px)',
          whiteSpace: 'nowrap',
        }}>
          {product.name} · {variant?.size}
        </span>
        <span className="mono" style={{ fontSize: 10, color: 'var(--muted)' }}>
          {qty.toLocaleString('en-GB')} × £{unit.toFixed(3)}
        </span>
      </div>

      {hover && (
        <button
          onClick={onRemove}
          className="fade-in"
          style={{
            position: 'absolute', top: 4, right: 4,
            width: 24, height: 24, borderRadius: '50%',
            border: 0, background: 'var(--ink)', color: 'var(--paper)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            cursor: 'pointer',
          }}
        >
          <svg width="10" height="10" viewBox="0 0 16 16"><path d="M4 4 L12 12 M12 4 L4 12" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/></svg>
        </button>
      )}
    </div>
  );
}

function ProductPanel({ products, selections, addProduct, removeProduct, updateQty, updateVariant, activePairs, getUnit, accent, showRecs, dismissRec }) {
  const [filter, setFilter] = React.useState('all');

  const displayed = filter === 'selected'
    ? products.filter(p => selections[p.id])
    : filter === 'suggested' ? activePairs : products;

  return (
    <aside style={{ background: 'var(--paper)', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      <div style={{ padding: '20px 20px 16px', borderBottom: '.5px solid var(--line)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 14, flexWrap: 'wrap', gap: 6 }}>
          <h3 style={{ margin: 0, fontSize: 18, fontWeight: 500, letterSpacing: '-0.015em' }}>Catalogue</h3>
          <span className="mono" style={{ fontSize: 11, color: 'var(--muted)' }}>
            {products.length} items · tiered pricing
          </span>
        </div>

        <div style={{ display: 'flex', gap: 4, background: 'rgba(21,19,14,.04)', padding: 3, borderRadius: 10, width: 'fit-content' }}>
          {[
            ['all', 'All', products.length],
            ['selected', 'In set', Object.keys(selections).length],
            ['suggested', 'Suggested', activePairs.length],
          ].map(([k, l, n]) => (
            <button
              key={k}
              onClick={() => setFilter(k)}
              style={{
                padding: '6px 12px', fontSize: 12, borderRadius: 7, border: 0,
                background: filter === k ? 'var(--paper)' : 'transparent',
                color: filter === k ? 'var(--ink)' : 'var(--muted)',
                boxShadow: filter === k ? '0 1px 2px rgba(21,19,14,.08)' : 'none',
                display: 'inline-flex', alignItems: 'center', gap: 6, cursor: 'pointer',
              }}
            >
              {l}
              <span className="mono" style={{ fontSize: 10, opacity: 0.6 }}>{n}</span>
            </button>
          ))}
        </div>
      </div>

      {showRecs && activePairs.length > 0 && filter !== 'suggested' && (
        <div className="fade-in" style={{
          margin: '12px 16px 0', padding: '12px 14px',
          background: 'linear-gradient(135deg, rgba(212,83,42,.08), rgba(212,83,42,.02))',
          border: '.5px solid rgba(212,83,42,.25)',
          borderRadius: 12,
          display: 'flex', flexDirection: 'column', gap: 10,
        }}>
          <span className="mono" style={{ fontSize: 10.5, letterSpacing: '0.08em', textTransform: 'uppercase', color: accent }}>
            ◇ Pairs well with your set
          </span>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            {activePairs.slice(0, 4).map(p => (
              <button
                key={p.id}
                onClick={() => addProduct(p.id)}
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 8,
                  padding: '6px 10px 6px 6px', borderRadius: 20,
                  background: 'var(--paper)', border: '.5px solid var(--line-2)',
                  fontSize: 12, color: 'var(--ink)', cursor: 'pointer',
                }}
              >
                <span style={{ width: 24, height: 24, borderRadius: 6, overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <ProductImage product={p} size={24}/>
                </span>
                <span>{p.name}</span>
                <Plus size={10}/>
              </button>
            ))}
          </div>
        </div>
      )}

      <div className="scroll" style={{ flex: 1, overflowY: 'auto', padding: '12px 16px 24px' }}>
        {displayed.length === 0 ? (
          <div style={{ padding: '60px 20px', textAlign: 'center', color: 'var(--muted)', fontSize: 13 }}>
            {filter === 'selected' ? 'Nothing in your set yet.' : 'No suggestions — keep adding items.'}
          </div>
        ) : displayed.map((p, i) => (
          <ProductRow
            key={p.id}
            product={p}
            selection={selections[p.id]}
            addProduct={addProduct}
            removeProduct={removeProduct}
            updateQty={updateQty}
            updateVariant={updateVariant}
            getUnit={getUnit}
            first={i === 0}
          />
        ))}
      </div>
    </aside>
  );
}

function ProductRow({ product, selection, addProduct, removeProduct, updateQty, updateVariant, getUnit, first }) {
  const selected = !!selection;
  const currentVariant = selected
    ? product.variants.find(v => v.id === selection.variantId)
    : (product.variants.find(v => v.recommended) || product.variants[0]);
  const qty = selection?.qty ?? product.moq;
  const unit = getUnit(product, qty);
  const subtotal = unit * qty;
  const tiers = [...product.pricing].sort((a,b) => a.qty - b.qty);
  const [expanded, setExpanded] = React.useState(false);

  return (
    <div style={{ borderTop: first ? 'none' : '.5px solid var(--line)', padding: '16px 0' }}>
      <div style={{ display: 'grid', gridTemplateColumns: '48px 1fr auto', gap: 14, alignItems: 'center' }}>
        <div style={{
          width: 48, height: 48, borderRadius: 10, overflow: 'hidden',
          background: selected ? 'var(--bg-2)' : 'rgba(21,19,14,.03)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          border: selected ? `.5px solid var(--line-2)` : '.5px solid transparent',
        }}>
          <ProductImage product={product} size={48}/>
        </div>
        <div style={{ minWidth: 0, display: 'flex', flexDirection: 'column', gap: 3 }}>
          <span style={{ fontSize: 14.5, fontWeight: 500, letterSpacing: '-0.01em', lineHeight: 1.2 }}>
            {product.name}
          </span>
          <span className="mono" style={{ fontSize: 10.5, color: 'var(--muted)', lineHeight: 1.2, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {currentVariant?.size} · {currentVariant?.dims} · MOQ {product.moq.toLocaleString('en-GB')}
          </span>
          <span style={{ fontSize: 11.5, color: 'var(--muted)', marginTop: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', lineHeight: 1.2 }}>
            {product.blurb}
          </span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <div style={{ textAlign: 'right' }}>
            <div style={{ fontSize: 13, fontWeight: 500, fontFamily: 'var(--font-mono)', letterSpacing: '-0.01em' }}>
              £{unit.toFixed(3)}
            </div>
            <div className="mono" style={{ fontSize: 10, color: 'var(--muted)' }}>per unit</div>
          </div>
          {selected ? (
            <button
              onClick={() => setExpanded(e => !e)}
              style={{
                width: 32, height: 32, borderRadius: 8, border: '.5px solid var(--line-2)',
                background: 'var(--paper)', color: 'var(--ink)',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                transform: expanded ? 'rotate(180deg)' : 'rotate(0)', transition: 'transform .2s',
                cursor: 'pointer',
              }}
            >
              <svg width="10" height="10" viewBox="0 0 16 16"><path d="M3 6 L8 11 L13 6" stroke="currentColor" strokeWidth="1.4" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </button>
          ) : (
            <button
              onClick={() => { addProduct(product.id); setExpanded(true); }}
              style={{
                height: 32, padding: '0 14px', borderRadius: 8, border: 0,
                background: 'var(--ink)', color: 'var(--paper)',
                display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, fontWeight: 500, cursor: 'pointer',
              }}
            >
              <Plus size={11}/> Add
            </button>
          )}
        </div>
      </div>

      {selected && expanded && (
        <div className="fade-in" style={{
          marginTop: 14, padding: 14, background: 'var(--bg-2)', borderRadius: 12,
          display: 'flex', flexDirection: 'column', gap: 14,
        }}>
          {product.variants.length > 1 && (
            <div>
              <div className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--muted)', marginBottom: 8 }}>
                Size
              </div>
              <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                {product.variants.map(v => {
                  const active = v.id === selection.variantId;
                  return (
                    <button
                      key={v.id}
                      onClick={() => updateVariant(product.id, v.id)}
                      style={{
                        padding: '8px 12px', borderRadius: 8, fontSize: 12,
                        background: active ? 'var(--ink)' : 'var(--paper)',
                        color: active ? 'var(--paper)' : 'var(--ink)',
                        border: active ? 'none' : '.5px solid var(--line-2)',
                        display: 'inline-flex', flexDirection: 'column', gap: 2, alignItems: 'flex-start',
                        cursor: 'pointer',
                      }}
                    >
                      <span style={{ fontWeight: 500 }}>{v.size}</span>
                      <span className="mono" style={{ fontSize: 10, opacity: 0.65 }}>{v.dims}</span>
                    </button>
                  );
                })}
              </div>
            </div>
          )}

          <div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 8 }}>
              <span className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--muted)' }}>
                Quantity · MOQ {product.moq.toLocaleString('en-GB')}
              </span>
              <span className="mono" style={{ fontSize: 11 }}>
                {qty.toLocaleString('en-GB')} units
              </span>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: `repeat(${tiers.length}, 1fr)`, gap: 4, marginBottom: 8 }}>
              {tiers.map(t => {
                const active = qty === t.qty;
                const reached = qty >= t.qty;
                return (
                  <button
                    key={t.qty}
                    onClick={() => updateQty(product.id, t.qty)}
                    style={{
                      padding: '10px 8px', borderRadius: 8,
                      background: active ? 'var(--ink)' : reached ? 'rgba(21,19,14,.08)' : 'var(--paper)',
                      color: active ? 'var(--paper)' : 'var(--ink)',
                      display: 'flex', flexDirection: 'column', gap: 2,
                      border: active ? 'none' : '.5px solid var(--line-2)',
                      cursor: 'pointer',
                    }}
                  >
                    <span className="mono" style={{ fontSize: 11, fontWeight: 500 }}>
                      {t.qty >= 1000 ? `${t.qty/1000}k` : t.qty}
                    </span>
                    <span className="mono" style={{ fontSize: 9.5, opacity: 0.7 }}>£{t.unit.toFixed(3)}</span>
                  </button>
                );
              })}
            </div>
          </div>

          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', paddingTop: 8, borderTop: '.5px solid var(--line)' }}>
            <button
              onClick={() => removeProduct(product.id)}
              style={{ background: 'transparent', border: 0, fontSize: 12, color: 'var(--muted)', textDecoration: 'underline', textUnderlineOffset: 3, cursor: 'pointer' }}
            >
              Remove
            </button>
            <div style={{ display: 'flex', gap: 16, alignItems: 'baseline' }}>
              <span className="mono" style={{ fontSize: 11, color: 'var(--muted)' }}>Subtotal</span>
              <span style={{ fontSize: 16, fontWeight: 500, fontFamily: 'var(--font-mono)' }}>
                £{subtotal.toLocaleString('en-GB', { maximumFractionDigits: 0 })}
              </span>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { Builder });
