// ==========================================================
// VoAIs Call — shared UI: icons, primitives, sample data
// Exposes everything on window so other Babel scripts can use.
// ==========================================================

// ---------- Icon set (stroke-style, 1.6 weight) ----------
const Ic = ({ d, size = 16, fill = "none", stroke = "currentColor", w = 1.6, children, ...rest }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={fill} stroke={stroke}
       strokeWidth={w} strokeLinecap="round" strokeLinejoin="round" {...rest}>
    {d ? <path d={d} /> : children}
  </svg>
);

const I = {
  dashboard: (p) => <Ic {...p}><rect x="3" y="3" width="7" height="9" rx="1.5"/><rect x="14" y="3" width="7" height="5" rx="1.5"/><rect x="14" y="12" width="7" height="9" rx="1.5"/><rect x="3" y="16" width="7" height="5" rx="1.5"/></Ic>,
  campaigns: (p) => <Ic {...p}><path d="M3 7v10M21 7v10M7 5h10M7 19h10"/><rect x="6" y="8" width="12" height="8" rx="1.5"/></Ic>,
  agents: (p) => <Ic {...p}><circle cx="12" cy="9" r="3.5"/><path d="M5 20c0-3.5 3-6 7-6s7 2.5 7 6"/><circle cx="18" cy="6" r="1.4" fill="currentColor" stroke="none"/></Ic>,
  flow: (p) => <Ic {...p}><circle cx="5" cy="6" r="2.2"/><circle cx="19" cy="6" r="2.2"/><circle cx="12" cy="18" r="2.2"/><path d="M7 6h10M6.5 8l4 8M17.5 8l-4 8"/></Ic>,
  monitor: (p) => <Ic {...p}><path d="M2 12h3l2-7 4 14 2-9 3 5h6"/></Ic>,
  history: (p) => <Ic {...p}><path d="M3 12a9 9 0 1 0 3-6.7M3 4v4h4"/><path d="M12 7v5l3.5 2"/></Ic>,
  contacts: (p) => <Ic {...p}><rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="12" cy="11" r="2.5"/><path d="M8 17c.5-1.6 2-2.5 4-2.5s3.5.9 4 2.5"/><path d="M3 8h2M3 12h2M3 16h2"/></Ic>,
  analytics: (p) => <Ic {...p}><path d="M3 21h18"/><path d="M7 17V9M12 17V5M17 17v-6"/></Ic>,
  kb: (p) => <Ic {...p}><path d="M4 5a2 2 0 0 1 2-2h10l4 4v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z"/><path d="M16 3v4h4M8 11h8M8 15h6"/></Ic>,
  integrations: (p) => <Ic {...p}><path d="M3 12h6M15 12h6M9 9v6h6V9z"/><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/></Ic>,
  settings: (p) => <Ic {...p}><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></Ic>,
  billing: (p) => <Ic {...p}><rect x="2.5" y="6" width="19" height="13" rx="2"/><path d="M2.5 10h19M6 15h3"/></Ic>,
  search: (p) => <Ic {...p}><circle cx="11" cy="11" r="6"/><path d="m20 20-3.5-3.5"/></Ic>,
  bell: (p) => <Ic {...p}><path d="M6 8a6 6 0 1 1 12 0c0 7 3 7 3 9H3c0-2 3-2 3-9zM10 21a2 2 0 0 0 4 0"/></Ic>,
  chevD: (p) => <Ic {...p}><polyline points="6 9 12 15 18 9"/></Ic>,
  chevR: (p) => <Ic {...p}><polyline points="9 6 15 12 9 18"/></Ic>,
  chevL: (p) => <Ic {...p}><polyline points="15 6 9 12 15 18"/></Ic>,
  chevU: (p) => <Ic {...p}><polyline points="18 15 12 9 6 15"/></Ic>,
  plus: (p) => <Ic {...p}><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></Ic>,
  filter: (p) => <Ic {...p}><path d="M4 5h16M7 12h10M10 19h4"/></Ic>,
  more: (p) => <Ic {...p}><circle cx="12" cy="6" r="1.4" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="12" cy="18" r="1.4" fill="currentColor" stroke="none"/></Ic>,
  phone: (p) => <Ic {...p}><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3 19.5 19.5 0 0 1-6-6 19.8 19.8 0 0 1-3-8.6A2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7 12.8 12.8 0 0 0 .7 2.8 2 2 0 0 1-.5 2.1L8.1 9.7a16 16 0 0 0 6 6l1.1-1.1a2 2 0 0 1 2-.5c.9.3 1.9.5 2.9.6a2 2 0 0 1 1.7 2z"/></Ic>,
  phoneIn: (p) => <Ic {...p}><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3 19.5 19.5 0 0 1-6-6 19.8 19.8 0 0 1-3-8.6A2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .3 1.9.6 2.8a2 2 0 0 1-.5 2.1L8.1 9.7a16 16 0 0 0 6 6l1.1-1.1a2 2 0 0 1 2-.5c.9.3 1.9.5 2.9.6a2 2 0 0 1 1.7 2zM15 3l6 6M21 3l-6 6"/></Ic>,
  phoneOut: (p) => <Ic {...p}><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3 19.5 19.5 0 0 1-6-6 19.8 19.8 0 0 1-3-8.6A2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .3 1.9.6 2.8a2 2 0 0 1-.5 2.1L8.1 9.7a16 16 0 0 0 6 6l1.1-1.1a2 2 0 0 1 2-.5c.9.3 1.9.5 2.9.6a2 2 0 0 1 1.7 2zM21 3l-7 7M14 3h7v7"/></Ic>,
  mic: (p) => <Ic {...p}><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5 11a7 7 0 0 0 14 0M12 18v3M9 21h6"/></Ic>,
  micOff: (p) => <Ic {...p}><path d="M3 3l18 18M9 9v2a3 3 0 0 0 5 2.1M15 9.4V6a3 3 0 0 0-5.7-1.3M5 11a7 7 0 0 0 .3 2M19 11a7 7 0 0 1-10 6.3M12 19v2M9 21h6"/></Ic>,
  play: (p) => <Ic {...p}><polygon points="6 4 20 12 6 20 6 4" fill="currentColor"/></Ic>,
  pause: (p) => <Ic {...p}><rect x="6" y="4" width="4" height="16" rx="1" fill="currentColor"/><rect x="14" y="4" width="4" height="16" rx="1" fill="currentColor"/></Ic>,
  upload: (p) => <Ic {...p}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12"/></Ic>,
  download: (p) => <Ic {...p}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></Ic>,
  edit: (p) => <Ic {...p}><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7M18.5 2.5a2.12 2.12 0 1 1 3 3L12 15l-4 1 1-4z"/></Ic>,
  trash: (p) => <Ic {...p}><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M10 11v6M14 11v6"/></Ic>,
  copy: (p) => <Ic {...p}><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></Ic>,
  pin: (p) => <Ic {...p}><path d="M12 22V13M5 11l7-9 7 9M5 11h14M8.5 11l.5 5M15.5 11l-.5 5"/></Ic>,
  check: (p) => <Ic {...p}><polyline points="20 6 9 17 4 12"/></Ic>,
  x: (p) => <Ic {...p}><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></Ic>,
  star: (p) => <Ic {...p}><polygon points="12 2 15 8.5 22 9.3 17 14 18.3 21 12 17.8 5.7 21 7 14 2 9.3 9 8.5 12 2"/></Ic>,
  fire: (p) => <Ic {...p}><path d="M12 2c0 4-3 5-3 9a3 3 0 1 0 6 0c0-1-.5-2-1.5-2.5"/><path d="M5 14a7 7 0 0 0 14 0c0-4-3-5-3-9-2 1-4 3-4 6-2 0-3-2-3-3 0 2-2 4-2 5-1 0-2 1-2 1z"/></Ic>,
  bot: (p) => <Ic {...p}><rect x="4" y="7" width="16" height="12" rx="3"/><circle cx="9" cy="13" r="1.2" fill="currentColor"/><circle cx="15" cy="13" r="1.2" fill="currentColor"/><path d="M12 7V3M9 3h6"/></Ic>,
  spark: (p) => <Ic {...p}><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.5 5.5l2.8 2.8M15.7 15.7l2.8 2.8M5.5 18.5l2.8-2.8M15.7 8.3l2.8-2.8"/></Ic>,
  globe: (p) => <Ic {...p}><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18"/></Ic>,
  shield: (p) => <Ic {...p}><path d="M12 2l8 4v6c0 5-3.5 9-8 10-4.5-1-8-5-8-10V6z"/></Ic>,
  zap: (p) => <Ic {...p}><polygon points="13 2 4 14 12 14 11 22 20 10 12 10 13 2"/></Ic>,
  logout: (p) => <Ic {...p}><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></Ic>,
  sun: (p) => <Ic {...p}><circle cx="12" cy="12" r="4"/><path d="M12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6l1.4 1.4M17 17l1.4 1.4M5.6 18.4l1.4-1.4M17 7l1.4-1.4"/></Ic>,
  moon: (p) => <Ic {...p}><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></Ic>,
  collapse: (p) => <Ic {...p}><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M9 4v16M14 9l-3 3 3 3"/></Ic>,
  expand: (p) => <Ic {...p}><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M9 4v16M11 9l3 3-3 3"/></Ic>,
  user: (p) => <Ic {...p}><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></Ic>,
  users: (p) => <Ic {...p}><circle cx="9" cy="8" r="3.5"/><path d="M2 20a7 7 0 0 1 14 0"/><circle cx="17" cy="7" r="2.5"/><path d="M17 12c3 0 5 2 5 5"/></Ic>,
  server: (p) => <Ic {...p}><rect x="2" y="3" width="20" height="6" rx="1.5"/><rect x="2" y="13" width="20" height="6" rx="1.5"/><circle cx="6" cy="6" r="1" fill="currentColor"/><circle cx="6" cy="16" r="1" fill="currentColor"/></Ic>,
  tag: (p) => <Ic {...p}><path d="M20 12 12 20l-9-9V3h8l9 9z"/><circle cx="7" cy="7" r="1.5"/></Ic>,
  arrow_up_right: (p) => <Ic {...p}><path d="M7 17 17 7M7 7h10v10"/></Ic>,
  arrow_right: (p) => <Ic {...p}><path d="M5 12h14M13 5l7 7-7 7"/></Ic>,
  arrow_left: (p) => <Ic {...p}><path d="M19 12H5M11 5 4 12l7 7"/></Ic>,
  drag: (p) => <Ic {...p}><circle cx="9" cy="6" r="1.2" fill="currentColor"/><circle cx="15" cy="6" r="1.2" fill="currentColor"/><circle cx="9" cy="12" r="1.2" fill="currentColor"/><circle cx="15" cy="12" r="1.2" fill="currentColor"/><circle cx="9" cy="18" r="1.2" fill="currentColor"/><circle cx="15" cy="18" r="1.2" fill="currentColor"/></Ic>,
  link: (p) => <Ic {...p}><path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1"/></Ic>,
  brain: (p) => <Ic {...p}><path d="M9 4a3 3 0 0 0-3 3v1a2.5 2.5 0 0 0-2 4 2.5 2.5 0 0 0 0 4 2.5 2.5 0 0 0 3 4 3 3 0 0 0 5 0V4z"/><path d="M15 4a3 3 0 0 1 3 3v1a2.5 2.5 0 0 1 2 4 2.5 2.5 0 0 1 0 4 2.5 2.5 0 0 1-3 4 3 3 0 0 1-5 0"/></Ic>,
  message: (p) => <Ic {...p}><path d="M21 11a8 8 0 0 1-8 8 8 8 0 0 1-3.5-.8L3 20l1.8-6.5A8 8 0 1 1 21 11z"/></Ic>,
  alert: (p) => <Ic {...p}><circle cx="12" cy="12" r="9"/><line x1="12" y1="8" x2="12" y2="13"/><circle cx="12" cy="16.5" r="1" fill="currentColor"/></Ic>,
  calendar: (p) => <Ic {...p}><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 9h18M8 3v4M16 3v4"/></Ic>,
  network: (p) => <Ic {...p}><circle cx="12" cy="5" r="2"/><circle cx="5" cy="19" r="2"/><circle cx="19" cy="19" r="2"/><path d="M12 7v6M12 13l-5 4M12 13l5 4"/></Ic>,
  whatsapp: (p) => <Ic {...p}><path d="M3 21l1.5-5A8.5 8.5 0 1 1 8 19.5L3 21z"/><path d="M9 9c0 4 3 7 7 7l-1-2-2 .5c-2-.5-3-2-3.5-3.5L10 9z"/></Ic>,
  inbox: (p) => <Ic {...p}><path d="M22 12h-6l-2 3h-4l-2-3H2"/><path d="M5.5 5h13l3.5 7v7a2 2 0 0 1-2 2h-16a2 2 0 0 1-2-2v-7z"/></Ic>,
  send: (p) => <Ic {...p}><path d="M22 2L11 13M22 2l-7 20-4-9-9-4z"/></Ic>,
  paperclip: (p) => <Ic {...p}><path d="M21 11l-9 9a5.5 5.5 0 0 1-7.8-7.8l9.5-9.5a3.5 3.5 0 0 1 5 5l-9.6 9.5a1.5 1.5 0 0 1-2.1-2.1l8.5-8.5"/></Ic>,
  smile: (p) => <Ic {...p}><circle cx="12" cy="12" r="9"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><circle cx="9" cy="10" r="1" fill="currentColor"/><circle cx="15" cy="10" r="1" fill="currentColor"/></Ic>,
  template: (p) => <Ic {...p}><rect x="3" y="3" width="18" height="6" rx="1.5"/><rect x="3" y="13" width="11" height="8" rx="1.5"/><rect x="17" y="13" width="4" height="8" rx="1.5"/></Ic>,
  reply: (p) => <Ic {...p}><polyline points="9 14 4 9 9 4"/><path d="M4 9h11a5 5 0 0 1 5 5v6"/></Ic>,
  email: (p) => <Ic {...p}><rect x="2" y="5" width="20" height="14" rx="2"/><path d="m2 7 10 6 10-6"/></Ic>,
  archive: (p) => <Ic {...p}><rect x="2" y="3" width="20" height="5" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8M9 12h6"/></Ic>,
  branch: (p) => <Ic {...p}><circle cx="6" cy="5" r="2"/><circle cx="18" cy="5" r="2"/><circle cx="12" cy="19" r="2"/><path d="M6 7v3a3 3 0 0 0 3 3h6a3 3 0 0 0 3-3V7M12 13v4"/></Ic>,
  square: (p) => <Ic {...p}><rect x="4" y="4" width="16" height="16" rx="2"/></Ic>,
  keypad: (p) => <Ic {...p}><circle cx="6" cy="6" r="1.6"/><circle cx="12" cy="6" r="1.6"/><circle cx="18" cy="6" r="1.6"/><circle cx="6" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="18" cy="12" r="1.6"/><circle cx="6" cy="18" r="1.6"/><circle cx="12" cy="18" r="1.6"/><circle cx="18" cy="18" r="1.6"/></Ic>,
  clock: (p) => <Ic {...p}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></Ic>,
  code: (p) => <Ic {...p}><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/><line x1="14" y1="4" x2="10" y2="20"/></Ic>,
  database: (p) => <Ic {...p}><ellipse cx="12" cy="5" rx="8" ry="3"/><path d="M4 5v6c0 1.7 3.6 3 8 3s8-1.3 8-3V5M4 11v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/></Ic>,
  math: (p) => <Ic {...p}><path d="M4 6h7l-5 6 5 6H4M14 8l6 8M20 8l-6 8"/></Ic>,
  repeat: (p) => <Ic {...p}><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></Ic>,
  bolt: (p) => <Ic {...p}><polygon points="13 2 4 14 12 14 11 22 20 10 12 10 13 2"/></Ic>,
  grid: (p) => <Ic {...p}><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></Ic>,
};

// ---------- Primitives ----------
function Badge({ tone = "gray", children, dot }) {
  return <span className={`badge ${tone}`}>{dot && <span className="dot"/>}{children}</span>;
}

function Btn({ kind = "primary", size, icon, children, onClick, className = "", ...rest }) {
  const sizeCls = size === "sm" ? "sm" : size === "lg" ? "lg" : "";
  const iconOnly = icon && !children ? "icon-only" : "";
  return (
    <button className={`btn btn-${kind} ${sizeCls} ${iconOnly} ${className}`} onClick={onClick} {...rest}>
      {icon}{children}
    </button>
  );
}

function Card({ children, className = "", padded = true, ...rest }) {
  return <div className={`card ${padded ? "" : "flat"} ${className}`} {...rest}>{children}</div>;
}

function CardHead({ title, subtitle, right, icon }) {
  return (
    <div className="card-head">
      {icon}
      <div>
        <h3>{title}</h3>
        {subtitle && <div style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 2 }}>{subtitle}</div>}
      </div>
      <div className="head-spacer"/>
      {right}
    </div>
  );
}

function Segmented({ value, options, onChange }) {
  return (
    <div className="segmented">
      {options.map(o => {
        const v = typeof o === "string" ? o : o.value;
        const label = typeof o === "string" ? o : o.label;
        return (
          <button key={v} className={value === v ? "active" : ""} onClick={() => onChange?.(v)}>{label}</button>
        );
      })}
    </div>
  );
}

function Tabs({ value, options, onChange }) {
  return (
    <div className="tabs">
      {options.map(o => {
        const v = typeof o === "string" ? o : o.value;
        const label = typeof o === "string" ? o : o.label;
        const count = typeof o === "object" ? o.count : null;
        return (
          <div key={v} className={`tab ${value === v ? "active" : ""}`} onClick={() => onChange?.(v)}>
            {label}{count != null && <span style={{ marginLeft: 6, opacity: 0.6 }}>{count}</span>}
          </div>
        );
      })}
    </div>
  );
}

function Avatar({ name = "?", src, size = 32, color }) {
  const initials = name.split(/\s+/).slice(0, 2).map(s => s[0]).join("").toUpperCase();
  const palette = ["linear-gradient(135deg,#FFB199,#C46AFF)","linear-gradient(135deg,#5B8FFF,#00D49F)","linear-gradient(135deg,#FFD27D,#FF6F91)","linear-gradient(135deg,#A78BFA,#3B7BFF)","linear-gradient(135deg,#00D49F,#4DD0E1)","linear-gradient(135deg,#FF8A3D,#F4C53D)"];
  const bg = color || palette[(name.charCodeAt(0) || 0) % palette.length];
  return (
    <span className="avatar" style={{ width: size, height: size, background: bg, fontSize: size * 0.38 }}>
      {initials || "?"}
    </span>
  );
}

function Toggle({ value, onChange }) {
  return <span className={`toggle ${value ? "on" : ""}`} onClick={() => onChange?.(!value)} role="switch" aria-checked={!!value}/>;
}

function Field({ label, hint, children }) {
  return (
    <div>
      {label && <label className="field-label">{label}</label>}
      {children}
      {hint && <div className="field-hint">{hint}</div>}
    </div>
  );
}

// Sparkline (mini chart for KPI cards)
function Sparkline({ data, color = "var(--accent)", width = 80, height = 28 }) {
  if (!data?.length) return null;
  const max = Math.max(...data), min = Math.min(...data);
  const rng = max - min || 1;
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * width;
    const y = height - ((v - min) / rng) * (height - 4) - 2;
    return `${x},${y}`;
  });
  const area = `M0,${height} L${pts.join(" L")} L${width},${height} Z`;
  return (
    <svg width={width} height={height} style={{ display: "block" }}>
      <defs>
        <linearGradient id={`spark-${color.replace(/[^\w]/g,"")}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor={color} stopOpacity="0.25"/>
          <stop offset="1" stopColor={color} stopOpacity="0"/>
        </linearGradient>
      </defs>
      <path d={area} fill={`url(#spark-${color.replace(/[^\w]/g,"")})`}/>
      <polyline points={pts.join(" ")} fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

// Donut chart
function Donut({ data, size = 160, thickness = 22, center }) {
  const total = data.reduce((a, b) => a + b.value, 0) || 1;
  const radius = (size - thickness) / 2;
  const circ = 2 * Math.PI * radius;
  let offset = 0;
  return (
    <svg width={size} height={size} style={{ display: "block" }}>
      <circle cx={size/2} cy={size/2} r={radius} fill="none" stroke="var(--surface-3)" strokeWidth={thickness}/>
      {data.map((d, i) => {
        const len = (d.value / total) * circ;
        const seg = (
          <circle key={i} cx={size/2} cy={size/2} r={radius} fill="none"
                  stroke={d.color} strokeWidth={thickness}
                  strokeDasharray={`${len} ${circ - len}`}
                  strokeDashoffset={-offset}
                  strokeLinecap="butt"
                  transform={`rotate(-90 ${size/2} ${size/2})`}/>
        );
        offset += len;
        return seg;
      })}
      {center && (
        <foreignObject x="0" y="0" width={size} height={size}>
          <div style={{ width: size, height: size, display: "grid", placeItems: "center", textAlign: "center" }}>
            {center}
          </div>
        </foreignObject>
      )}
    </svg>
  );
}

// Bar chart for revenue/calls
function BarChart({ data, height = 220, accentIndex = null, format = (v) => v.toLocaleString() }) {
  const max = Math.max(...data.map(d => d.value));
  const yLines = [0, 0.25, 0.5, 0.75, 1].map(p => Math.round(max * p));
  return (
    <div style={{ display: "grid", gridTemplateColumns: "44px 1fr", gap: 8, height }}>
      <div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", textAlign: "right", fontSize: 10.5, color: "var(--ink-3)", paddingRight: 4 }}>
        {[...yLines].reverse().map((v, i) => <div key={i}>{v >= 1000 ? (v/1000).toFixed(1)+"k" : v}</div>)}
      </div>
      <div style={{ position: "relative", display: "flex", alignItems: "flex-end", gap: 10 }}>
        {[0, 0.25, 0.5, 0.75, 1].map((p, i) => (
          <div key={i} style={{ position: "absolute", left: 0, right: 0, bottom: `${p * 100}%`, borderTop: "1px dashed var(--line)" }}/>
        ))}
        {data.map((d, i) => {
          const isAcc = i === accentIndex;
          return (
            <div key={i} style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 6, position: "relative", zIndex: 1 }}>
              {isAcc && (
                <div className="badge" style={{ position: "absolute", top: -22, background: "var(--accent-soft)", color: "var(--accent)", fontSize: 10 }}>
                  ▲ {d.delta}
                </div>
              )}
              <div style={{
                width: "100%",
                maxWidth: 40,
                height: `${(d.value / max) * 100}%`,
                minHeight: 10,
                background: isAcc ? "var(--accent)" : "var(--surface-3)",
                borderRadius: 8,
                position: "relative",
                overflow: "hidden",
                boxShadow: isAcc ? "0 8px 18px -8px rgba(59,123,255,0.5)" : "none"
              }}>
                {!isAcc && (
                  <div style={{ position: "absolute", inset: 0, backgroundImage: "repeating-linear-gradient(135deg, transparent 0 4px, rgba(255,255,255,0.04) 4px 5px)" }}/>
                )}
                {isAcc && (
                  <div style={{ position: "absolute", top: 10, left: "50%", transform: "translateX(-50%)", fontSize: 11, fontWeight: 600, color: "white" }}>{format(d.value)}</div>
                )}
              </div>
              <div style={{ fontSize: 11, color: "var(--ink-3)", fontWeight: 500 }}>{d.label}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// Live waveform (animated)
function Waveform({ count = 36, color = "var(--accent)", height = 36, running = true }) {
  return (
    <div className="waveform" style={{ height }}>
      {Array.from({ length: count }).map((_, i) => {
        const seed = Math.sin(i * 1.3) * 0.5 + 0.5;
        const h = 25 + seed * 75;
        const delay = (i % 8) * 0.08;
        return (
          <span
            key={i}
            className="bar"
            style={{
              height: `${h}%`,
              background: color,
              animationDelay: `${delay}s`,
              animationPlayState: running ? "running" : "paused",
              opacity: 0.55 + seed * 0.45
            }}
          />
        );
      })}
    </div>
  );
}

// Empty state
function Empty({ title, sub, action, icon }) {
  return (
    <div style={{ padding: 48, textAlign: "center", color: "var(--ink-3)" }}>
      {icon && <div style={{ marginBottom: 12, opacity: 0.5 }}>{icon}</div>}
      <div style={{ fontSize: 15, color: "var(--ink-2)", fontWeight: 600 }}>{title}</div>
      {sub && <div style={{ marginTop: 6 }}>{sub}</div>}
      {action && <div style={{ marginTop: 14 }}>{action}</div>}
    </div>
  );
}

// ── Modal ────────────────────────────────────────────────────────────────
// Generic centered dialog: Escape closes, body scroll locked while open,
// click-outside closes. Shared primitive consumed by agents, campaigns,
// contacts, kb, whatsapp, call-history, flow-builder, integrations, admin and
// agent-editor — defined here in the UI kit so it loads before every screen.
function Modal({ title, onClose, children, width = 520 }) {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { document.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [onClose]);
  return (
    <div className="modal-backdrop" onClick={(e) => { if (e.target.classList.contains("modal-backdrop")) onClose(); }}>
      <div className="modal-card" style={{ maxWidth: width }}>
        <div className="modal-head">
          <h2 style={{ margin: 0, fontSize: 17, fontWeight: 600 }}>{title}</h2>
          <button className="topbar-icon-btn" onClick={onClose} title="Close"><I.x size={14}/></button>
        </div>
        <div className="modal-body">{children}</div>
      </div>
    </div>
  );
}

// ── Dashboard loading / error states ──────────────────────────────────────
// Originally defined in dashboard.jsx but reused as the generic page skeleton
// and error card across ~14 screens via shared global scope. Hoisted into the
// UI kit so the dependency is explicit and load-order-safe.
function DashboardSkeleton() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap-grid)" }}>
      <div className="kpi-grid">
        {[0,1,2,3].map((i) => <div key={i} className="card kpi-card skel-block" style={{ minHeight: 110 }}/>)}
      </div>
      <div className="mobile-stack" style={{ display: "grid", gridTemplateColumns: "1.55fr 1fr", gap: "var(--gap-grid)" }}>
        <div className="card skel-block" style={{ minHeight: 320 }}/>
        <div className="card skel-block" style={{ minHeight: 320 }}/>
      </div>
      <div className="card skel-block" style={{ minHeight: 240 }}/>
    </div>
  );
}

function DashboardError({ msg }) {
  return (
    <Card>
      <div style={{ padding: 20, textAlign: "center" }}>
        <div style={{ color: "var(--err)", marginBottom: 8 }}><I.alert size={24}/></div>
        <div style={{ fontWeight: 600, marginBottom: 6 }}>Couldn't load dashboard</div>
        <div style={{ fontSize: 13, color: "var(--ink-3)" }}>{msg}</div>
        <Btn kind="primary" size="sm" onClick={() => location.reload()} style={{ marginTop: 16 }}>Retry</Btn>
      </div>
    </Card>
  );
}

// expose globally
Object.assign(window, {
  I, Ic, Badge, Btn, Card, CardHead, Segmented, Tabs, Avatar, Toggle, Field,
  Sparkline, Donut, BarChart, Waveform, Empty,
  Modal, DashboardSkeleton, DashboardError
});
