// Shared primitives: Avatar, Button, Chip, Field, Modal, etc.
const { useState, useEffect, useRef, useMemo, useLayoutEffect } = React;

// ---- Avatar ----------------------------------------------------------------
function Avatar({ person, size = 40, ring = false }) {
  const initials = person.name.split(" ").map((s) => s[0]).slice(0, 2).join("");
  const style = {
    width: size, height: size, borderRadius: "50%",
    background: `linear-gradient(135deg, ${person.accent}, ${shade(person.accent, -20)})`,
    color: "white",
    display: "inline-flex", alignItems: "center", justifyContent: "center",
    fontFamily: "var(--serif)", fontWeight: 400,
    fontSize: size * 0.38,
    letterSpacing: "-0.02em",
    flexShrink: 0,
    boxShadow: ring ? `0 0 0 4px var(--bg), 0 0 0 5px var(--line)` : "none",
    userSelect: "none",
  };
  return <span style={style}>{initials}</span>;
}

function shade(hex, percent) {
  const num = parseInt(hex.replace("#", ""), 16);
  const r = Math.max(0, Math.min(255, (num >> 16) + percent));
  const g = Math.max(0, Math.min(255, ((num >> 8) & 0xff) + percent));
  const b = Math.max(0, Math.min(255, (num & 0xff) + percent));
  return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, "0")}`;
}

// ---- Button ----------------------------------------------------------------
function Button({ children, variant = "primary", size = "md", onClick, icon, type, full, disabled }) {
  const cls = `btn btn-${variant} btn-${size}${full ? " btn-full" : ""}`;
  return (
    <button className={cls} onClick={onClick} type={type || "button"} disabled={disabled}>
      {icon && <span className="btn-icon">{icon}</span>}
      <span>{children}</span>
    </button>
  );
}

// ---- Chip / Pill -----------------------------------------------------------
function Chip({ children, active, onClick }) {
  return (
    <button className={`chip${active ? " chip-active" : ""}`} onClick={onClick}>
      {children}
    </button>
  );
}

// ---- Icons (line) ----------------------------------------------------------
const I = {
  search: <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><circle cx="7" cy="7" r="4.5"/><path d="m10.5 10.5 3 3"/></svg>,
  bell:   <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M4 11V7a4 4 0 1 1 8 0v4l1 1.5H3L4 11Z"/><path d="M6.5 13.5a1.5 1.5 0 0 0 3 0"/></svg>,
  message:<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M2.5 4.5h11v7H6l-3 2.5v-2.5H2.5z"/></svg>,
  edit:   <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M11 2.5 13.5 5 5.5 13H3v-2.5z"/></svg>,
  plus:   <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M8 3v10M3 8h10"/></svg>,
  check:  <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="m3 8 3.5 3.5L13 5"/></svg>,
  arrow:  <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M3 8h10m-3.5-3.5L13 8l-3.5 3.5"/></svg>,
  ext:    <svg viewBox="0 0 16 16" width="11" height="11" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M6 3H3v10h10V10M9.5 2.5H13.5V6.5M13 3 7.5 8.5"/></svg>,
  back:   <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M13 8H3m3.5-3.5L3 8l3.5 3.5"/></svg>,
  more:   <svg viewBox="0 0 16 16" width="14" height="14" fill="currentColor"><circle cx="3.5" cy="8" r="1.1"/><circle cx="8" cy="8" r="1.1"/><circle cx="12.5" cy="8" r="1.1"/></svg>,
  heart:  <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M8 13s-5-3.2-5-7a2.7 2.7 0 0 1 5-1.4A2.7 2.7 0 0 1 13 6c0 3.8-5 7-5 7z"/></svg>,
  dot:    <svg viewBox="0 0 8 8" width="8" height="8"><circle cx="4" cy="4" r="3" fill="currentColor"/></svg>,
  globe:  <svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.3"><circle cx="8" cy="8" r="5.5"/><path d="M2.5 8h11M8 2.5c1.8 2 2.7 4 2.7 5.5S9.8 12 8 13.5C6.2 11.5 5.3 9.5 5.3 8S6.2 4.5 8 2.5z"/></svg>,
  pin:    <svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.3"><path d="M8 14s-4-4.2-4-7a4 4 0 1 1 8 0c0 2.8-4 7-4 7z"/><circle cx="8" cy="7" r="1.4"/></svg>,
  user:   <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><circle cx="8" cy="6" r="2.5"/><path d="M3 13.5c.7-2 2.6-3 5-3s4.3 1 5 3"/></svg>,
  home:   <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M2.5 7.5 8 3l5.5 4.5V13H10V9.5H6V13H2.5z"/></svg>,
  compass:<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><circle cx="8" cy="8" r="5.5"/><path d="m6 10 1.2-3.2L10.5 5.5 9.3 8.7z"/></svg>,
  grid:   <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><rect x="2.5" y="2.5" width="4.5" height="4.5"/><rect x="9" y="2.5" width="4.5" height="4.5"/><rect x="2.5" y="9" width="4.5" height="4.5"/><rect x="9" y="9" width="4.5" height="4.5"/></svg>,
  list:   <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M5 4h9M5 8h9M5 12h9M2.5 4h.01M2.5 8h.01M2.5 12h.01"/></svg>,
  settings:<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.3"><circle cx="8" cy="8" r="2"/><path d="M8 1.5v2M8 12.5v2M1.5 8h2M12.5 8h2M3.3 3.3l1.4 1.4M11.3 11.3l1.4 1.4M3.3 12.7l1.4-1.4M11.3 4.7l1.4-1.4"/></svg>,
  close:  <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="m4 4 8 8M12 4l-8 8"/></svg>,
  drag:   <svg viewBox="0 0 16 16" width="12" height="12" fill="currentColor"><circle cx="6" cy="4" r="1"/><circle cx="10" cy="4" r="1"/><circle cx="6" cy="8" r="1"/><circle cx="10" cy="8" r="1"/><circle cx="6" cy="12" r="1"/><circle cx="10" cy="12" r="1"/></svg>,
  slash:  <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M11 3 5 13"/></svg>,
};

// ---- Field (input wrapper) -------------------------------------------------
function Field({ label, hint, children, suffix }) {
  return (
    <label className="field">
      {label && <span className="field-label">{label}</span>}
      <span className="field-input-wrap">
        {children}
        {suffix && <span className="field-suffix">{suffix}</span>}
      </span>
      {hint && <span className="field-hint">{hint}</span>}
    </label>
  );
}

// ---- Cover swatch (placeholder for project art) ----------------------------
function Cover({ background, ratio = "4/3", label, year }) {
  return (
    <div className="cover" style={{ background, aspectRatio: ratio }}>
      {label && (
        <div className="cover-meta">
          <span>{label}</span>
          {year && <span>{year}</span>}
        </div>
      )}
    </div>
  );
}

// ---- Section header --------------------------------------------------------
function SectionH({ children, action, count }) {
  return (
    <div className="section-h">
      <h3>
        {children}
        {count != null && <span className="section-count">{count}</span>}
      </h3>
      {action}
    </div>
  );
}

// ---- Person row ------------------------------------------------------------
function PersonRow({ person, onOpen, dense }) {
  return (
    <div className={`person-row${dense ? " person-row-dense" : ""}`} onClick={() => onOpen?.(person)}>
      <Avatar person={person} size={dense ? 36 : 44} />
      <div className="person-row-text">
        <div className="person-row-name">
          {person.name}
          <span className="person-row-handle">@{person.handle}</span>
        </div>
        <div className="person-row-role">{person.role} · {person.location}</div>
      </div>
      <Button variant="ghost" size="sm">Follow</Button>
    </div>
  );
}

// ---- Stat ------------------------------------------------------------------
function Stat({ value, label }) {
  return (
    <div className="stat">
      <div className="stat-value">{value}</div>
      <div className="stat-label">{label}</div>
    </div>
  );
}

Object.assign(window, { Avatar, Button, Chip, Field, Cover, SectionH, PersonRow, Stat, I, shade });
