/* CRM Record detail - Person / Organisation / Project / Event.
   Read + edit. Editing mutates window.DATA and calls onMutate() so the
   change is reflected everywhere (single dataset). Exports: RecordDetail. */

function EditText({ label, value, onChange, area }) {
  return (
    <div style={{ marginBottom: 12 }}>
      <label className="field-label">{label}</label>
      {area
        ? <textarea className="input focusable" rows={3} value={value || ""} onChange={(e) => onChange(e.target.value)} style={{ resize: "vertical", lineHeight: 1.5 }} />
        : <input className="input focusable" value={value || ""} onChange={(e) => onChange(e.target.value)} />}
    </div>
  );
}
function EditSelect({ label, value, onChange, options }) {
  return (
    <div style={{ marginBottom: 12 }}>
      <label className="field-label">{label}</label>
      <select className="input focusable" value={value} onChange={(e) => onChange(e.target.value)}>
        {options.map((o) => <option key={o} value={o}>{o}</option>)}
      </select>
    </div>
  );
}
function ChipWrap({ children }) {
  return <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>{children}</div>;
}

/* a 1-5 meter (pips + word). invert=true means low number is "best". */
function Meter({ value, invert, words, color = "var(--accent)" }) {
  const filled = invert ? (6 - value) : value;
  const word = words ? words[Math.max(0, Math.min(words.length - 1, value - 1))] : null;
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 9 }}>
      <span style={{ display: "inline-flex", gap: 3 }}>
        {[1, 2, 3, 4, 5].map((n) => (
          <span key={n} style={{ width: 16, height: 6, borderRadius: 3, background: n <= filled ? color : "var(--surface-3)" }} />
        ))}
      </span>
      <span className="mono" style={{ fontSize: 12, color: "var(--text-muted)" }}>{value}/5</span>
      {word && <span style={{ fontSize: 12.5, color: "var(--text-muted)" }}>· {word}</span>}
    </span>
  );
}

/* clickable person with photo */
function PersonPill({ id, onOpen, sub }) {
  const p = window.DATA.byId[id];
  if (!p) return null;
  return (
    <button className="chip focusable" onClick={() => onOpen && onOpen(id)} style={{ paddingLeft: 4 }}>
      {p.photo ? <Portrait p={p} w={20} h={20} radius={999} /> : <Avatar name={p.name} size={20} />}
      <span>{p.name}{sub && p.title ? <span style={{ color: "var(--text-faint)" }}> · {p.title}</span> : ""}</span>
    </button>
  );
}

/* AI-draft affordance - visual sparkle button beside soft text fields */
function AIDraft({ onClick, loading }) {
  return (
    <button className="focusable" onClick={onClick} disabled={loading} title="AI draft"
      style={{ display: "inline-flex", alignItems: "center", gap: 4, padding: "2px 7px", borderRadius: 999, border: "1px solid color-mix(in srgb, var(--accent) 30%, transparent)", background: "var(--accent-soft)", color: "var(--accent)", cursor: loading ? "default" : "pointer", font: "inherit", fontSize: 10.5, fontWeight: 600, flex: "none", opacity: loading ? 0.6 : 1 }}>
      <Icon name="spark" size={11} /> {loading ? "Drafting…" : "AI draft"}
    </button>
  );
}

/* AI-draftable soft field - sparkle button generates real text (live AI
   with a deterministic fallback) and replaces the value inline. */
function AIField({ label, value, prompt, fallback, accent }) {
  const [text, setText] = React.useState(value);
  const [loading, setLoading] = React.useState(false);
  const [drafted, setDrafted] = React.useState(false);
  React.useEffect(() => { setText(value); setDrafted(false); }, [value]);
  const draft = async () => {
    setLoading(true);
    let out = "";
    try {
      if (window.__ai && window.__ai.complete) out = await window.__ai.complete({ messages: [{ role: "user", content: prompt }] });
    } catch (e) { out = ""; }
    if (!out || !out.trim()) out = fallback;
    setText((out || "").trim()); setDrafted(true); setLoading(false);
  };
  return (
    <div style={{ marginTop: 12 }} className={accent ? "card" : ""}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: accent ? 7 : 5, padding: accent ? "13px 15px 0" : 0 }}>
        {accent && <span style={{ width: 22, height: 22, flex: "none", borderRadius: 7, display: "grid", placeItems: "center", background: "var(--accent)", color: "var(--accent-contrast)" }}><Icon name="spark" size={12} /></span>}
        <span className="t-eyebrow" style={accent ? { color: "var(--accent)" } : {}}>{label}</span>
        {drafted && <span className="badge" style={{ background: "var(--accent-soft)", color: "var(--accent)", borderColor: "transparent", fontSize: 9.5, padding: "1px 6px" }}>AI drafted</span>}
        <span style={{ marginLeft: "auto" }}><AIDraft onClick={draft} loading={loading} /></span>
      </div>
      {loading
        ? <div style={{ display: "flex", gap: 5, alignItems: "center", padding: accent ? "4px 15px 14px" : "4px 0" }}>{[0, 1, 2].map((d) => <span key={d} style={{ width: 6, height: 6, borderRadius: 999, background: "var(--text-faint)", animation: "intel-blink 1s infinite", animationDelay: d * 0.15 + "s" }} />)}</div>
        : <div className={drafted ? "fade-up" : ""} style={{ fontSize: 13.5, lineHeight: 1.55, color: accent ? "var(--text)" : "var(--text-muted)", padding: accent ? "0 15px 14px" : 0 }}>{text || "-"}</div>}
    </div>
  );
}

/* confidence dots (1-3) */
function ConfidenceDots({ level }) {
  const n = level === "High" ? 3 : level === "Medium" ? 2 : 1;
  return (
    <span style={{ display: "inline-flex", gap: 3, alignItems: "center" }} title={`${level} confidence`}>
      {[1, 2, 3].map((i) => <span key={i} style={{ width: 6, height: 6, borderRadius: 999, background: i <= n ? "var(--accent)" : "var(--surface-3)" }} />)}
    </span>
  );
}

/* explainable scorecard - all dims, weighted contribution, confidence */
function ScoreCard({ e }) {
  const D = window.DATA;
  const dims = D.SCORE_DIMS, W = D.SCORE_WEIGHTS;
  const wsum = dims.reduce((s, [k]) => s + (W[k] || 0), 0) || 1;
  return (
    <div className="card" style={{ padding: 14, marginBottom: 12 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
        <Icon name="spark" size={13} style={{ color: "var(--accent)" }} />
        <span style={{ fontSize: 11.5, color: "var(--text-muted)" }}>AI suggested these scores - review</span>
        <span className="badge mono" style={{ marginLeft: "auto", background: "var(--accent-soft)", color: "var(--accent)", borderColor: "transparent", fontWeight: 700 }}>{e.priorityScore}/100</span>
      </div>
      <div style={{ fontSize: 10.5, color: "var(--text-faint)", marginBottom: 12 }}>Composite = Σ (score × weight). Drag weights on the Prioritisation page.</div>
      {dims.map(([k, l]) => {
        const v = e.scores[k], contrib = Math.round((v * (W[k] || 0) / wsum) * 10);
        const col = v >= 8 ? "var(--good)" : v >= 5 ? "var(--accent)" : "var(--warn)";
        return (
          <div key={k} style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 8 }}>
            <span style={{ width: 150, flex: "none", fontSize: 12, color: "var(--text-muted)" }}>{l}</span>
            <div style={{ flex: 1, height: 7, borderRadius: 5, background: "var(--surface-3)", overflow: "hidden", minWidth: 50 }}>
              <div style={{ width: (v * 10) + "%", height: "100%", background: col, borderRadius: 5 }} />
            </div>
            <span className="mono" style={{ width: 18, textAlign: "right", fontSize: 11.5, fontWeight: 600 }}>{v}</span>
            <span className="mono" style={{ width: 52, textAlign: "right", fontSize: 10.5, color: "var(--text-faint)" }}>×{Math.round((W[k] || 0) * 100)}% </span>
          </div>
        );
      })}
    </div>
  );
}

/* RACI row */
function RaciRow({ label, ids, onOpen, color }) {
  return (
    <div style={{ display: "flex", gap: 12, padding: "9px 0", borderBottom: "1px solid var(--border)" }}>
      <div style={{ width: 96, flex: "none", display: "flex", alignItems: "center", gap: 7 }}>
        <span style={{ width: 18, height: 18, borderRadius: 5, display: "grid", placeItems: "center", background: color, color: "#fff", fontSize: 10, fontWeight: 700, flex: "none" }}>{label[0]}</span>
        <span style={{ fontSize: 12.5, color: "var(--text-muted)" }}>{label}</span>
      </div>
      <div style={{ flex: 1, display: "flex", flexWrap: "wrap", gap: 6 }}>
        {ids.length ? ids.map((id) => <PersonPill key={id} id={id} onOpen={onOpen} />) : <span style={{ fontSize: 13, color: "var(--text-faint)" }}>-</span>}
      </div>
    </div>
  );
}


function RecordHeader({ e, kind, onClose, onEdit, editing, onSave, onCancel, onViewConnections, onOpenIntel, onExpand }) {
  const dc = kind === "org" ? domainColor(e.domain) : "var(--accent)";
  return (
    <div style={{ padding: "24px 26px 18px", borderBottom: "1px solid var(--border)", background: "var(--surface)" }}>
      <div style={{ display: "flex", alignItems: "flex-start", gap: 15 }}>
        <div style={{ width: 54, height: 54, borderRadius: 16, flex: "none", display: "grid", placeItems: "center", background: kind === "org" ? domainColor(e.domain, true) : "var(--accent-soft)", color: dc, border: "1px solid var(--border)" }}>
          {kind === "person" ? <Avatar name={e.name} size={52} accent /> : <Icon name={KIND_META[kind].icon} size={26} />}
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 5, flexWrap: "wrap" }}>
            <KindBadge kind={kind} />
            {kind === "org" && <FundingBadge funded={e.funded} />}
            {kind === "org" && <PriorityPill priority={e.priority} />}
            {kind === "org" && e.dataStatus && <span className="badge" style={e.dataStatus === "Complete" ? { background: "var(--good-bg)", color: "var(--good)", borderColor: "transparent" } : { background: "var(--warn-bg)", color: "var(--warn)", borderColor: "transparent" }}>{e.dataStatus === "Complete" ? "✓ Complete" : "◴ " + e.dataStatus}</span>}
          </div>
          <div className="display" style={{ fontSize: 28, lineHeight: 1.1 }}>{e.name}</div>
          {kind === "org" && <div style={{ fontSize: 14, color: "var(--text-muted)", marginTop: 4 }}>{(window.DATA.domains.find((d) => d.id === e.domain) || {}).label} · {e.reach} reach</div>}
          {kind === "person" && <div style={{ fontSize: 14, color: "var(--text-muted)", marginTop: 4 }}>{e.title}{e.org ? ` · ${window.DATA.byId[e.org].name}` : e.team ? " · The Wellspring Fund" : ""}</div>}
          {kind === "project" && <div style={{ fontSize: 14, color: "var(--text-muted)", marginTop: 4 }}>{e.type} · {e.year} · {window.DATA.byId[e.org].name}</div>}
          {kind === "event" && <div style={{ fontSize: 14, color: "var(--text-muted)", marginTop: 4 }}>{new Date(e.date).toLocaleDateString("en-GB", { day: "numeric", month: "long", year: "numeric" })}</div>}
        </div>
        {onClose && <button className="btn btn-icon btn-ghost" onClick={onClose} title="Close"><Icon name="x" size={19} /></button>}
      </div>
      <div style={{ display: "flex", gap: 8, marginTop: 18, flexWrap: "wrap" }}>
        {editing ? (
          <React.Fragment>
            <button className="btn btn-primary btn-sm" onClick={onSave}><Icon name="check" size={15} /> Save changes</button>
            <button className="btn btn-sm" onClick={onCancel}>Cancel</button>
          </React.Fragment>
        ) : (
          <React.Fragment>
            <button className="btn btn-sm" onClick={onEdit}><Icon name="edit" size={14} /> Edit</button>
            {onExpand && kind === "project" && <button className="btn btn-sm" onClick={onExpand}><Icon name="external" size={14} /> Open in CRM</button>}
            {kind !== "funder" && <button className="btn btn-sm" onClick={onViewConnections}><Icon name="link" size={15} /> View connections</button>}
            {kind !== "funder" && <button className="btn btn-sm" onClick={onOpenIntel}><Icon name="target" size={15} /> Intel</button>}
          </React.Fragment>
        )}
      </div>
    </div>
  );
}

/* ---------- bodies (read + edit), driven by shared editState ---------- */
function OrgBody({ id, e, ed, onOpen, onMutate }) {
  const D = window.DATA;
  const [linkPicker, setLinkPicker] = React.useState(false);
  const [linkQuery, setLinkQuery] = React.useState("");
  const projects = D.projectsByOrg(id);
  const ppl = D.peopleByOrg(id);
  const evs = D.eventsByOrg(id);
  const linked = e.linked || [];
  const account = e.account ? D.byId[e.account] : null;
  const candidateLinks = D.orgs.filter((o) => {
    if (o.id === id || linked.includes(o.id)) return false;
    if (!linkQuery.trim()) return true;
    const q = linkQuery.toLowerCase();
    const dom = (D.domains.find((d) => d.id === o.domain) || {}).label || "";
    return o.name.toLowerCase().includes(q) || dom.toLowerCase().includes(q);
  });
  const openLinkPicker = () => { setLinkPicker((v) => !v); setLinkQuery(""); };
  const addLink = (oid) => { e.linked = [...(e.linked || []), oid]; setLinkPicker(false); setLinkQuery(""); onMutate && onMutate(); };
  const removeLink = (oid) => { e.linked = (e.linked || []).filter((x) => x !== oid); onMutate && onMutate(); };

  if (ed.editing) return (
    <div style={{ padding: "16px 22px 28px" }}>
      <EditText label="Name" value={ed.draft.name} onChange={(v) => ed.set("name", v)} />
      <EditSelect label="Funding status" value={ed.draft.funded ? "Funded" : "Not funded"} onChange={(v) => ed.set("funded", v === "Funded")} options={["Funded", "Not funded"]} />
      <EditSelect label="Relationship" value={ed.draft.relationship} onChange={(v) => ed.set("relationship", v)} options={["Grantee", "Active supporter", "Prospect"]} />
      <EditSelect label="Reach" value={ed.draft.reach} onChange={(v) => ed.set("reach", v)} options={["Local", "National", "Global"]} />
      <EditSelect label="Priority" value={ed.draft.priority || "None"} onChange={(v) => ed.set("priority", v === "None" ? null : v)} options={["None", "key", "need"]} />
      <EditText label="Notes" value={ed.draft.notes} onChange={(v) => ed.set("notes", v)} area />
    </div>
  );
  return (
    <div style={{ padding: "4px 22px 28px" }}>
      <SectionLabel>Details</SectionLabel>
      <FieldRow label="Relationship" icon="link"><RelBadge value={e.relationship} /></FieldRow>
      <FieldRow label="Reach" icon="map">{e.reach}</FieldRow>
      <FieldRow label="Account holder" icon="user">{account ? <EntityChip id={account.id} onOpen={onOpen} /> : null}</FieldRow>
      <FieldRow label="Domain" icon="grid">
        <span style={{ display: "inline-flex", alignItems: "center", gap: 7 }}>
          <span style={{ width: 8, height: 8, borderRadius: 999, background: domainColor(e.domain) }} />
          {(D.domains.find((d) => d.id === e.domain) || {}).label}
        </span>
      </FieldRow>

      <SectionLabel right={<span className="badge mono">{projects.length}</span>}>Projects</SectionLabel>
      {projects.length ? (
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {projects.map((pr) => (
            <button key={pr.id} className="card focusable" onClick={() => onOpen(pr.id)}
              style={{ display: "flex", alignItems: "center", gap: 11, padding: "11px 13px", cursor: "pointer", textAlign: "left", background: "var(--surface)" }}>
              <Icon name="folder" size={16} style={{ color: "var(--text-muted)" }} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13.5, fontWeight: 550 }}>{pr.name}</div>
                <div style={{ fontSize: 12, color: "var(--text-muted)" }}><span className="mono">{pr.year}</span> · {pr.type} · {pr.status}</div>
              </div>
              <Icon name="chevronRight" size={16} style={{ color: "var(--text-faint)" }} />
            </button>
          ))}
        </div>
      ) : <EmptyState icon="folder" title="No projects yet" body="Projects under this organisation will appear here." />}

      {ppl.length > 0 && <React.Fragment>
        <SectionLabel>People</SectionLabel>
        <ChipWrap>{ppl.map((p) => <EntityChip key={p.id} id={p.id} onOpen={onOpen} />)}</ChipWrap>
      </React.Fragment>}

      <SectionLabel right={<button className="btn btn-sm btn-ghost" style={{ color: "var(--accent)" }} onClick={openLinkPicker}><Icon name={linkPicker ? "x" : "plus"} size={14} /> {linkPicker ? "Done" : "Add link"}</button>}>Linked organisations</SectionLabel>
      {linkPicker && (
        <div className="card fade-up" style={{ padding: 10, marginBottom: 10 }}>
          <div style={{ position: "relative", marginBottom: 9 }}>
            <Icon name="search" size={15} style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--text-faint)", pointerEvents: "none" }} />
            <input autoFocus className="input focusable" placeholder="Search organisations to link…" value={linkQuery}
              onChange={(ev) => setLinkQuery(ev.target.value)}
              style={{ paddingLeft: 32, fontSize: 13, height: 36 }} />
          </div>
          <div style={{ fontSize: 11.5, color: "var(--text-muted)", marginBottom: 8 }}>
            {linkQuery.trim()
              ? <span><span className="mono">{candidateLinks.length}</span> {candidateLinks.length === 1 ? "match" : "matches"} - picking one redraws the map instantly.</span>
              : "Pick an organisation to link - it redraws on the map instantly."}
          </div>
          {candidateLinks.length ? (
            <div style={{ display: "flex", flexWrap: "wrap", gap: 6, maxHeight: 168, overflow: "auto" }}>
              {candidateLinks.map((o) => (
                <button key={o.id} className="chip focusable" onClick={() => addLink(o.id)}>
                  <span className="dot" style={{ background: domainColor(o.domain) }} />{o.name}
                </button>
              ))}
            </div>
          ) : (
            <div style={{ fontSize: 12.5, color: "var(--text-faint)", padding: "6px 2px" }}>No organisations match “{linkQuery}”.</div>
          )}
        </div>
      )}
      {linked.length ? (
        <ChipWrap>
          {linked.map((l) => (
            <span key={l} className="chip" style={{ paddingRight: 4 }}>
              <span className="dot" style={{ background: domainColor(D.byId[l].domain) }} />
              <span onClick={() => onOpen(l)} style={{ cursor: "pointer" }}>{D.byId[l].name}</span>
              <button className="focusable" onClick={() => removeLink(l)} style={{ padding: 2, border: "none", background: "none", cursor: "pointer", color: "var(--text-faint)", marginLeft: 2, display: "inline-flex" }}><Icon name="x" size={13} /></button>
            </span>
          ))}
        </ChipWrap>
      ) : <div style={{ fontSize: 13, color: "var(--text-faint)" }}>No linked organisations.</div>}

      {evs.length > 0 && <React.Fragment>
        <SectionLabel>Related events</SectionLabel>
        <ChipWrap>{evs.map((ev) => <EntityChip key={ev.id} id={ev.id} onOpen={onOpen} />)}</ChipWrap>
      </React.Fragment>}

      {/* ---- Characteristics ---- */}
      <SectionLabel>Characteristics</SectionLabel>
      <FieldRow label="Category" icon="search"><span className="badge" style={{ background: "var(--surface-2)" }}>{e.category}</span></FieldRow>
      <FieldRow label="Subcategory" icon="grid">
        <span style={{ display: "inline-flex", flexWrap: "wrap", gap: 6 }}>{(e.subcategories || []).map((s) => <span key={s} className="badge">{s}</span>)}</span>
      </FieldRow>
      <FieldRow label="Importance" icon="target"><Meter value={e.importance} invert words={["Critical", "High", "Medium", "Low", "Minimal"]} color="var(--accent)" /></FieldRow>
      <FieldRow label="Intensity" icon="bolt"><Meter value={e.intensity} words={["Dormant", "Light", "Steady", "Active", "Intensive"]} color="var(--info)" /></FieldRow>

      {/* ---- Team & RACI ---- */}
      <SectionLabel right={<span className="badge mono">{(e.accountHolders || []).length}</span>}>Account holders</SectionLabel>
      <ChipWrap>{(e.accountHolders || []).map((pid) => <PersonPill key={pid} id={pid} onOpen={onOpen} />)}</ChipWrap>
      {(e.teamMembers || []).length > 0 && <React.Fragment>
        <div style={{ height: 10 }} />
        <div style={{ fontSize: 12, fontWeight: 600, color: "var(--text-muted)", marginBottom: 7 }}>Team members</div>
        <ChipWrap>{e.teamMembers.map((pid) => <PersonPill key={pid} id={pid} onOpen={onOpen} sub />)}</ChipWrap>
      </React.Fragment>}

      <SectionLabel>RACI</SectionLabel>
      <div style={{ borderTop: "1px solid var(--border)" }}>
        <RaciRow label="Responsible" ids={e.raci ? e.raci.responsible : []} onOpen={onOpen} color="var(--good)" />
        <RaciRow label="Accountable" ids={e.raci ? e.raci.accountable : []} onOpen={onOpen} color="var(--accent)" />
        <RaciRow label="Consulted" ids={e.raci ? e.raci.consulted : []} onOpen={onOpen} color="var(--info)" />
        <RaciRow label="Informed" ids={e.raci ? e.raci.informed : []} onOpen={onOpen} color="var(--warn)" />
      </div>

      {/* ---- Benefits in Kind ---- */}
      <SectionLabel>Benefits in kind</SectionLabel>
      {(e.bik || []).length ? (
        <ChipWrap>{e.bik.map((b) => (
          <span key={b} className="badge" style={{ background: "var(--surface-2)", padding: "6px 10px" }}>
            <Icon name={({ "Office Space": "building", "Network Connections": "link", "Strategy Advice": "spark", "Introductions": "users", "Events Access": "calendar" })[b] || "check"} size={13} style={{ color: "var(--accent)" }} /> {b}
          </span>
        ))}</ChipWrap>
      ) : <div style={{ fontSize: 13, color: "var(--text-faint)" }}>No in-kind support recorded.</div>}

      {/* ---- Prioritisation assessment (explainable scorecard) ---- */}
      <SectionLabel>Prioritisation</SectionLabel>
      <FieldRow label="Maturity" icon="trendingUp">{e.maturityStage}</FieldRow>
      <FieldRow label="Legal entity" icon="building">{e.legalEntity}</FieldRow>
      <FieldRow label="Funding need" icon="funding">{e.fundingNeed}</FieldRow>
      <FieldRow label="Confidence" icon="check"><span style={{ display: "inline-flex", alignItems: "center", gap: 8 }}><ConfidenceDots level={e.confidence} /> {e.confidence}</span></FieldRow>
      <div style={{ height: 12 }} />
      <ScoreCard e={e} />
      <AIField accent label="Recommended next step" value={e.nextStep}
        prompt={`You advise grant funder The Wellspring Fund. In ONE decisive sentence, recommend the next step for ${e.name} (${e.relationship}, ${e.funded ? "funded" : "not funded"}, priority score ${e.priorityScore}/100, funding need ${e.fundingNeed}, risk ${e.risk ? e.risk.level : "?"}).`}
        fallback={e.nextStep} />
      <SectionLabel>Assessment notes</SectionLabel>
      <AIField label="What funding would enable" value={e.fundingEnable}
        prompt={`In 1-2 sentences, describe what new funding would enable ${e.name} to do. Domain: ${(D.domains.find((d) => d.id === e.domain) || {}).label}. Aims: ${e.aims}`}
        fallback={e.fundingEnable} />
      <AIField label="Risk notes" value={e.riskNotes || "None recorded."}
        prompt={`In 1-2 sentences, summarise the funding risk for ${e.name}. Risk level: ${e.risk ? e.risk.level : "?"}. Context: ${e.riskNotes || "none"}. ${e.funded ? "Currently funded." : "Not currently funded."}`}
        fallback={e.riskNotes || "No material risks recorded; standard diligence applies."} />

      {/* ---- Funding & recognition ---- */}
      <SectionLabel>Funding &amp; recognition</SectionLabel>
      <FieldRow label="Funding type" icon="funding">
        <span style={{ display: "inline-flex", flexWrap: "wrap", gap: 6 }}>{(e.fundingTypes || []).map((ft) => <span key={ft} className="badge" style={ft === "None" ? {} : { background: "var(--good-bg)", color: "var(--good)", borderColor: "transparent" }}>{ft}</span>)}</span>
      </FieldRow>
      <FieldRow label="Engagement" icon="signal"><span className="badge" style={{ background: "var(--accent-soft)", color: "var(--accent)", borderColor: "transparent" }}>{e.engagementTier}</span></FieldRow>
      {(e.donorCredit || []).length > 0 && <FieldRow label="Donor credit" icon="receipt">
        <span style={{ display: "inline-flex", flexWrap: "wrap", gap: 6 }}>{e.donorCredit.map((d) => <span key={d} className="badge" style={d === "Star Grantee" ? { background: "var(--rose-bg)", color: "var(--rose)", borderColor: "transparent" } : { background: "var(--surface-2)" }}>{d}</span>)}</span>
      </FieldRow>}
      {(e.badges || []).length > 0 && <FieldRow label="Badges" icon="spark">
        <span style={{ display: "inline-flex", flexWrap: "wrap", gap: 6 }}>{e.badges.map((b) => <span key={b} className="badge" style={{ background: "var(--warn-bg)", color: "var(--warn)", borderColor: "transparent" }}>★ {b}</span>)}</span>
      </FieldRow>}

      <SectionLabel>Notes</SectionLabel>
      <div style={{ fontSize: 13.5, lineHeight: 1.6, color: "var(--text-muted)" }}>{e.notes}</div>
    </div>
  );
}

function PersonBody({ id, e, ed, onOpen }) {
  const D = window.DATA;
  const org = e.org ? D.byId[e.org] : null;
  const evs = (e.events || []).map((x) => D.byId[x]).filter(Boolean);
  const ownedOrgs = D.orgs.filter((o) => o.account === id);
  const contactOrgs = D.orgs.filter((o) => o.contact === id);
  if (ed.editing) return (
    <div style={{ padding: "16px 22px 28px" }}>
      <EditText label="Name" value={ed.draft.name} onChange={(v) => ed.set("name", v)} />
      <EditText label="Title" value={ed.draft.title} onChange={(v) => ed.set("title", v)} />
      <EditText label="Email" value={ed.draft.email} onChange={(v) => ed.set("email", v)} />
      <EditText label="Phone" value={ed.draft.phone} onChange={(v) => ed.set("phone", v)} />
      <EditText label="Notes" value={ed.draft.notes} onChange={(v) => ed.set("notes", v)} area />
    </div>
  );
  return (
    <div style={{ padding: "4px 22px 28px" }}>
      <SectionLabel>Contact</SectionLabel>
      <FieldRow label="Email" icon="mail"><span className="mono" style={{ color: "var(--accent)" }}>{e.email}</span></FieldRow>
      <FieldRow label="Phone" icon="phone"><span className="mono">{e.phone}</span></FieldRow>
      <FieldRow label="Role" icon="user">{e.title}{e.team ? " · The Wellspring Fund" : ""}</FieldRow>
      {org && <FieldRow label="Works at" icon="building"><EntityChip id={org.id} onOpen={onOpen} /></FieldRow>}
      <FieldRow label="Reach out" icon="clock">
        {e.lastContact
          ? <span style={{ display: "inline-flex", alignItems: "center", gap: 7 }}><span className="statdot" style={{ background: "var(--good)" }} />Last interaction <strong style={{ fontWeight: 600 }}>{e.lastContact}</strong></span>
          : <span style={{ display: "inline-flex", alignItems: "center", gap: 7, color: "var(--text-muted)" }}><span className="statdot" style={{ background: "var(--text-faint)" }} />No last interaction recorded</span>}
      </FieldRow>

      {ownedOrgs.length > 0 && <React.Fragment>
        <SectionLabel right={<span className="badge mono">{ownedOrgs.length}</span>}>Account holder for</SectionLabel>
        <ChipWrap>{ownedOrgs.map((o) => <EntityChip key={o.id} id={o.id} onOpen={onOpen} />)}</ChipWrap>
      </React.Fragment>}
      {contactOrgs.length > 0 && <React.Fragment>
        <SectionLabel>Main contact at</SectionLabel>
        <ChipWrap>{contactOrgs.map((o) => <EntityChip key={o.id} id={o.id} onOpen={onOpen} />)}</ChipWrap>
      </React.Fragment>}

      <SectionLabel right={<span className="badge mono">{evs.length}</span>}>Invited to</SectionLabel>
      {evs.length ? (
        <div style={{ display: "flex", flexDirection: "column", gap: 7 }}>
          {evs.map((ev) => {
            const status = (e.rsvp && e.rsvp[ev.id]) || "Invited";
            const sm = {
              Attended: { c: "var(--good)", bg: "var(--good-bg)", icon: "check" },
              Yes: { c: "var(--info)", bg: "var(--info-bg)", icon: "check" },
              Regrets: { c: "var(--text-muted)", bg: "var(--surface-2)", icon: "x" },
              Invited: { c: "var(--warn)", bg: "var(--warn-bg)", icon: "clock" },
            }[status];
            return (
              <button key={ev.id} className="card focusable" onClick={() => onOpen(ev.id)}
                style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", cursor: "pointer", textAlign: "left", background: "var(--surface)" }}>
                <span style={{ width: 22, height: 22, flex: "none", borderRadius: 6, display: "grid", placeItems: "center", background: sm.bg, color: sm.c }}><Icon name={sm.icon} size={13} /></span>
                <span style={{ flex: 1, fontSize: 13, fontWeight: 550, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{ev.name}</span>
                <span className="badge" style={{ background: sm.bg, color: sm.c, borderColor: "transparent" }}>{status}</span>
              </button>
            );
          })}
        </div>
      ) : <div style={{ fontSize: 13, color: "var(--text-faint)" }}>No events recorded.</div>}

      <SectionLabel>Notes</SectionLabel>
      <div style={{ fontSize: 13.5, lineHeight: 1.6, color: "var(--text-muted)" }}>{e.notes}</div>
    </div>
  );
}

function ProjectBody({ id, e, ed, onOpen }) {
  const D = window.DATA;
  const org = D.byId[e.org];
  const contact = e.contact ? D.byId[e.contact] : null;
  const ev = e.event ? D.byId[e.event] : null;
  if (ed.editing) return (
    <div style={{ padding: "16px 22px 28px" }}>
      <EditText label="Name" value={ed.draft.name} onChange={(v) => ed.set("name", v)} />
      <EditSelect label="Type" value={ed.draft.type} onChange={(v) => ed.set("type", v)} options={["Proposal", "Grant", "Beneficiary", "Sponsorship", "Conference"]} />
      <EditSelect label="Status" value={ed.draft.status} onChange={(v) => ed.set("status", v)} options={["In review", "Approved", "Active", "Planned", "Closed"]} />
      <EditText label="Year" value={String(ed.draft.year)} onChange={(v) => ed.set("year", v)} />
      <EditText label="Notes" value={ed.draft.notes} onChange={(v) => ed.set("notes", v)} area />
    </div>
  );
  return (
    <div style={{ padding: "4px 22px 28px" }}>
      <SectionLabel>Details</SectionLabel>
      <FieldRow label="Parent org" icon="building"><EntityChip id={org.id} onOpen={onOpen} /></FieldRow>
      <FieldRow label="Type" icon="folder">{e.type}</FieldRow>
      <FieldRow label="Status" icon="bolt"><span className="badge" style={{ background: "var(--info-bg)", color: "var(--info)", borderColor: "transparent" }}>{e.status}</span></FieldRow>
      <FieldRow label="Dates" icon="calendar">
        <span className="mono">{new Date(e.startDate).toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" })}</span>
        <span style={{ color: "var(--text-faint)" }}> → </span>
        <span className="mono">{new Date(e.endDate).toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" })}</span>
      </FieldRow>
      <FieldRow label="Importance" icon="target"><Meter value={e.importance} invert words={["High: would miss out", "Significant", "Useful", "Nice to have", "Marginal"]} color="var(--accent)" /></FieldRow>
      <FieldRow label="Main contact" icon="user">{contact ? <EntityChip id={contact.id} onOpen={onOpen} /> : null}</FieldRow>
      {ev && <FieldRow label="Related event" icon="calendar"><EntityChip id={ev.id} onOpen={onOpen} /></FieldRow>}

      <SectionLabel>RACI</SectionLabel>
      <div style={{ borderTop: "1px solid var(--border)" }}>
        <RaciRow label="Responsible" ids={e.raci ? e.raci.responsible : []} onOpen={onOpen} color="var(--good)" />
        <RaciRow label="Accountable" ids={e.raci ? e.raci.accountable : []} onOpen={onOpen} color="var(--accent)" />
        <RaciRow label="Consulted" ids={e.raci ? e.raci.consulted : []} onOpen={onOpen} color="var(--info)" />
        <RaciRow label="Informed" ids={e.raci ? e.raci.informed : []} onOpen={onOpen} color="var(--warn)" />
      </div>

      <SectionLabel>Project details</SectionLabel>
      <FieldRow label="Year" icon="calendar"><span className="mono">{e.year}</span></FieldRow>
      <FieldRow label="Geographical reach" icon="map">{e.geoReach}</FieldRow>
      <FieldRow label="Intensity" icon="bolt"><Meter value={e.intensity} words={["Dormant", "Light", "Steady", "Active", "Intensive"]} color="var(--info)" /></FieldRow>
      <FieldRow label="Pillar" icon="search"><span className="badge" style={{ background: "var(--surface-2)" }}>{e.pillar}</span></FieldRow>
      <FieldRow label="Subcategory" icon="grid"><span className="badge">{e.subcategory}</span></FieldRow>
      <FieldRow label="Credit" icon="receipt"><span className="badge" style={{ background: "var(--accent-soft)", color: "var(--accent)", borderColor: "transparent" }}>{e.credit}</span></FieldRow>

      <SectionLabel>Grant application</SectionLabel>
      <FieldRow label="Cycle stage" icon="pipeline"><span className="badge" style={{ background: "var(--good-bg)", color: "var(--good)", borderColor: "transparent" }}>{e.cycleStage}</span></FieldRow>
      <FieldRow label="Applied" icon="calendar"><span className="mono">{new Date(e.applicationDate).toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" })}</span></FieldRow>
      {e.granteeBadge && <FieldRow label="Grantee badge" icon="spark"><span className="badge" style={{ background: "var(--warn-bg)", color: "var(--warn)", borderColor: "transparent" }}>★ {e.granteeBadge}</span></FieldRow>}
      <FieldRow label="Co-funders" icon="users">
        <span style={{ display: "inline-flex", alignItems: "center", gap: 7 }}>
          <span style={{ width: 16, height: 16, borderRadius: 4, display: "grid", placeItems: "center", background: e.coFunders ? "var(--accent)" : "var(--surface-3)", color: "#fff" }}>{e.coFunders ? <Icon name="check" size={11} /> : null}</span>
          {e.coFunders ? "Yes - shared funding" : "None"}
        </span>
      </FieldRow>

      <SectionLabel>Support provided</SectionLabel>
      {(e.support || []).length ? (
        <div style={{ display: "flex", flexDirection: "column", gap: 7 }}>
          {e.support.map((s) => (
            <div key={s} style={{ display: "flex", alignItems: "center", gap: 10, padding: "9px 11px", background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: 9 }}>
              <span style={{ width: 18, height: 18, flex: "none", borderRadius: 5, display: "grid", placeItems: "center", background: "var(--good)", color: "#fff" }}><Icon name="check" size={12} /></span>
              <Icon name={({ "Office Space": "building", "Network Connections": "link", "Strategy Advice": "spark", "Introductions": "users", "Events Access": "calendar", "Sponsored": "receipt" })[s] || "check"} size={14} style={{ color: "var(--text-muted)" }} />
              <span style={{ fontSize: 13, fontWeight: 550 }}>{s}</span>
            </div>
          ))}
        </div>
      ) : <div style={{ fontSize: 13, color: "var(--text-faint)" }}>No in-kind support recorded for this project.</div>}

      <SectionLabel>Notes</SectionLabel>
      <div style={{ fontSize: 13.5, lineHeight: 1.6, color: "var(--text-muted)" }}>{e.notes}</div>
    </div>
  );
}

function EventBody({ id, e, ed, onOpen }) {
  const D = window.DATA;
  const orgs = (e.orgs || []).map((x) => D.byId[x]).filter(Boolean);
  const att = (e.attendees || []).map((x) => D.byId[x]).filter(Boolean);
  if (ed.editing) return (
    <div style={{ padding: "16px 22px 28px" }}>
      <EditText label="Name" value={ed.draft.name} onChange={(v) => ed.set("name", v)} />
      <EditText label="Date" value={ed.draft.date} onChange={(v) => ed.set("date", v)} />
      <EditText label="Notes" value={ed.draft.notes} onChange={(v) => ed.set("notes", v)} area />
    </div>
  );
  return (
    <div style={{ padding: "4px 22px 28px" }}>
      <SectionLabel>Details</SectionLabel>
      <FieldRow label="Date" icon="calendar"><span className="mono">{new Date(e.date).toLocaleDateString("en-GB", { day: "numeric", month: "long", year: "numeric" })}</span></FieldRow>
      <SectionLabel right={<span className="badge mono">{orgs.length}</span>}>Related organisations</SectionLabel>
      <ChipWrap>{orgs.map((o) => <EntityChip key={o.id} id={o.id} onOpen={onOpen} />)}</ChipWrap>
      <SectionLabel right={<span className="badge mono">{att.length}</span>}>Attendees</SectionLabel>
      <ChipWrap>{att.map((p) => <EntityChip key={p.id} id={p.id} onOpen={onOpen} />)}</ChipWrap>
      <SectionLabel>Notes</SectionLabel>
      <div style={{ fontSize: 13.5, lineHeight: 1.6, color: "var(--text-muted)" }}>{e.notes}</div>
    </div>
  );
}

function FunderBody({ onOpen }) {
  const D = window.DATA;
  return (
    <div style={{ padding: "4px 22px 28px" }}>
      <SectionLabel>About</SectionLabel>
      <div style={{ fontSize: 13.5, lineHeight: 1.6, color: "var(--text-muted)" }}>
        The Wellspring Fund is the centre of this ecosystem - every organisation connects here by a funding relationship.
        Solid links are funded; dashed links are tracked but not yet funded.
      </div>
      <SectionLabel right={<span className="badge mono">{D.counts.funded}</span>}>Funded organisations</SectionLabel>
      <ChipWrap>{D.orgs.filter((o) => o.funded).map((o) => <EntityChip key={o.id} id={o.id} onOpen={onOpen} />)}</ChipWrap>
    </div>
  );
}

/* ---------- RecordDetail: owns edit state, renders header + body ---------- */
function RecordDetail({ id, onOpen, onClose, onMutate, onViewConnections, onOpenIntel, onExpand }) {
  const D = window.DATA;
  const kind = D.kindOf(id);
  const e = D.byId[id];
  const [editing, setEditing] = React.useState(false);
  const [draft, setDraft] = React.useState({});
  React.useEffect(() => { setEditing(false); }, [id]);
  const ed = {
    editing, draft,
    begin: () => { setDraft({ ...e }); setEditing(true); },
    cancel: () => setEditing(false),
    save: () => { Object.assign(D.byId[id], draft); setEditing(false); onMutate && onMutate(); },
    set: (k, v) => setDraft((d) => ({ ...d, [k]: v })),
  };
  if (!e) return null;
  const display = editing ? { ...e, ...draft } : e;
  const bodyProps = { id, e, ed, onOpen, onMutate };
  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", background: "var(--surface)" }}>
      <RecordHeader e={display} kind={kind} onClose={onClose}
        editing={editing} onEdit={ed.begin} onSave={ed.save} onCancel={ed.cancel}
        onViewConnections={() => onViewConnections && onViewConnections(id)}
        onOpenIntel={() => onOpenIntel && onOpenIntel(id)}
        onExpand={onExpand ? () => onExpand(id) : null} />
      <div style={{ flex: 1, overflow: "auto" }}>
        {kind === "org" && <OrgBody {...bodyProps} />}
        {kind === "person" && <PersonBody {...bodyProps} />}
        {kind === "project" && <ProjectBody {...bodyProps} />}
        {kind === "event" && <EventBody {...bodyProps} />}
        {kind === "funder" && <FunderBody onOpen={onOpen} />}
      </div>
    </div>
  );
}

window.RecordDetail = RecordDetail;
Object.assign(window, { Meter, PersonPill, RaciRow, ScoreCard, ConfidenceDots, AIDraft, AIField });
