{options.map((o) => {
const v = typeof o === 'string' ? o : o.value;
const lab = typeof o === 'string' ? o : o.label;
const active = v === value;
return (
);
})}
);
}
// ── Chip de metadata (mono) ────────────────────────────────────────────────
function Chip({ icon, children, tone = 'neutral', style }) {
const tones = {
neutral: { background: 'var(--surface-2)', color: 'var(--muted-2)', border: '1px solid var(--line)' },
line: { background: 'transparent', color: 'var(--muted-2)', border: '1px solid var(--line-strong)' },
signal: { background: 'var(--signal-soft)', color: 'var(--signal-ink-2)', border: '1px solid var(--signal-line)' },
alert: { background: 'var(--alert-soft)', color: 'var(--alert-ink)', border: '1px solid var(--alert-line)' },
};
return (
{icon && }
{children}
);
}
// ── Punto de estado con pulso ──────────────────────────────────────────────
function StatusDot({ active, size = 8 }) {
return (
{active && }
);
}
// ── Sparkline ──────────────────────────────────────────────────────────────
function Sparkline({ data, w = 96, h = 30, color = 'var(--signal-ink-2)', fill = true, strokeW = 1.75 }) {
const max = Math.max(1, ...data);
const n = data.length;
const stepX = w / (n - 1);
const pts = data.map((v, i) => [i * stepX, h - 3 - (v / max) * (h - 6)]);
const line = pts.map((p, i) => `${i === 0 ? 'M' : 'L'}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' ');
const area = `${line} L${w},${h} L0,${h} Z`;
const gid = 'sg' + Math.round(w + h + n + data[0]);
return (
);
}
// ── Placeholder de foto de producto ────────────────────────────────────────
function ProductThumb({ cat, size = 64, radius = 'var(--r-md)', tag = true }) {
const c = SAT_CATS[cat] || SAT_CATS.tech;
return (
{/* watermark grande */}
{tag && (
FOTO
)}
);
}
// ── Eyebrow mono ───────────────────────────────────────────────────────────
function Eyebrow({ children, color = 'var(--muted-2)', style }) {
return