/* Prioritisation - NeuroAI-driven "who to fund next" engine.
   Transparent 9-dimension composite you can defend, live weighting +
   scenario presets, NL query, a generated recommendation, and expandable
   rows with the full actor profile + radar. Exports: Prioritisation.     */

function scoreBand(s) {
  if (s >= 78) return { label: "Critical", c: "var(--rose)", bg: "var(--rose-bg)" };
  if (s >= 64) return { label: "High", c: "var(--accent)", bg: "var(--accent-soft)" };
  if (s >= 50) return { label: "Medium", c: "var(--warn)", bg: "var(--warn-bg)" };
  return { label: "Watch", c: "var(--text-muted)", bg: "var(--surface-2)" };
}

/* weighting scenarios - each is a full 9-dim profile (relative weights) */
const PRIO_SCENARIOS = {
  balanced:  { label: "Balanced", icon: "sliders", w: null }, // null = use SCORE_WEIGHTS
  impact:    { label: "Maximise impact", icon: "trendingUp", w: { impact: 30, alignment: 18, readiness: 12, leadership: 12, urgency: 8, neglect: 8, maturity: 6, tractability: 4, risk: 2 } },
  neglect:   { label: "Address neglect", icon: "signal", w: { neglect: 32, urgency: 20, impact: 16, alignment: 12, readiness: 8, leadership: 6, tractability: 3, maturity: 2, risk: 1 } },
  derisk:    { label: "De-risk", icon: "shield", w: { risk: 28, maturity: 20, tractability: 16, leadership: 14, alignment: 10, impact: 6, readiness: 4, urgency: 1, neglect: 1 } },
  quickwins: { label: "Quick wins", icon: "bolt", w: { tractability: 26, readiness: 24, maturity: 16, leadership: 12, impact: 10, alignment: 6, urgency: 3, neglect: 2, risk: 1 } },
  urgent:    { label: "Urgent need", icon: "target", w: { urgency: 34, neglect: 18, impact: 14, readiness: 12, alignment: 8, leadership: 6, tractability: 4, maturity: 2, risk: 2 } },
};

function WeightSlider({ label, value, onChange, dimMax }) {
  return (
    <div style={{ marginBottom: 12 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 5 }}>
        <span style={{ fontSize: 12.5, color: "var(--text-muted)" }}>{label}</span>
        <span className="mono" style={{ fontSize: 11.5, fontWeight: 600, color: value === 0 ? "var(--text-faint)" : "var(--accent)" }}>{value}%</span>
      </div>
      <input type="range" min="0" max="100" value={value} onChange={(e) => onChange(Number(e.target.value))} className="prio-range" style={{ width: "100%", accentColor: "var(--accent)" }} />
    </div>
  );
}

/* 9-axis radar of an org's raw dimension scores (0-10) */
function Radar({ scores, dims, size = 180, color = "var(--accent)" }) {
  const cx = size / 2, cy = size / 2, r = size / 2 - 22;
  const n = dims.length;
  const pt = (i, val) => {
    const a = -Math.PI / 2 + (i / n) * Math.PI * 2;
    const rr = (val / 10) * r;
    return [cx + Math.cos(a) * rr, cy + Math.sin(a) * rr];
  };
  const rings = [0.25, 0.5, 0.75, 1];
  const poly = dims.map(([k], i) => pt(i, scores[k] || 0).join(",")).join(" ");
  return (
    <svg width={size} height={size} style={{ display: "block" }}>
      {rings.map((rg, i) => (
        <polygon key={i} points={dims.map((_, j) => { const a = -Math.PI / 2 + (j / n) * Math.PI * 2; return [cx + Math.cos(a) * r * rg, cy + Math.sin(a) * r * rg].join(","); }).join(" ")}
          fill="none" stroke="var(--border)" strokeWidth="1" />
      ))}
      {dims.map((_, i) => { const [x, y] = pt(i, 10); return <line key={i} x1={cx} y1={cy} x2={x} y2={y} stroke="var(--border)" strokeWidth="1" />; })}
      <polygon points={poly} fill={`color-mix(in srgb, ${color} 22%, transparent)`} stroke={color} strokeWidth="2" />
      {dims.map(([k], i) => { const [x, y] = pt(i, scores[k] || 0); return <circle key={i} cx={x} cy={y} r="2.6" fill={color} />; })}
    </svg>
  );
}

function Prioritisation({ onOpen, onOpenIntel }) {
  const D = window.DATA;
  const dims = D.SCORE_DIMS;
  const defaultW = () => { const w = {}; dims.forEach(([k]) => { w[k] = Math.round((D.SCORE_WEIGHTS[k] || 0.1) * 100); }); return w; };
  const [weights, setWeights] = React.useState(defaultW);
  const [scenario, setScenario] = React.useState("balanced");
  const [query, setQuery] = React.useState("");
  const [expanded, setExpanded] = React.useState(null);
  const [showWeights, setShowWeights] = React.useState(false);

  const applyScenario = (key) => {
    setScenario(key);
    const sc = PRIO_SCENARIOS[key];
    setWeights(sc.w ? { ...sc.w } : defaultW());
  };

  const wsum = dims.reduce((s, [k]) => s + weights[k], 0) || 1;
  const contrib = (o, k) => (o.scores[k] || 0) * weights[k];
  const scoreOf = React.useCallback((o) => {
    let sum = 0; dims.forEach(([k]) => { sum += (o.scores[k] || 0) * weights[k]; });
    return Math.round((sum / wsum) * 10);
  }, [weights, wsum]);

  // NL query → predicate (+ readout of what was understood)
  const ql = query.toLowerCase();
  const parsed = [];
  const matchQuery = (o) => {
    if (!ql.trim()) return true;
    let ok = true;
    if (ql.includes("unfunded") || ql.includes("not funded")) { ok = ok && !o.funded; }
    else if (ql.includes("funded")) { ok = ok && o.funded; }
    if (ql.includes("prospect")) ok = ok && o.relationship === "Prospect";
    if (ql.includes("global")) ok = ok && o.reach === "Global";
    else if (ql.includes("local")) ok = ok && o.reach === "Local";
    else if (ql.includes("uk") || ql.includes("national")) ok = ok && (o.reach === "National" || o.reach === "Global");
    if (ql.includes("ready") || ql.includes("absorb")) ok = ok && o.scores.readiness >= 7;
    if (ql.includes("neglect")) ok = ok && o.scores.neglect >= 7;
    if (ql.includes("impact")) ok = ok && o.scores.impact >= 7;
    if (ql.includes("risk")) ok = ok && o.scores.risk <= 5;
    D.domains.forEach((d) => { if (ql.includes(d.label.toLowerCase().split(" ")[0])) ok = ok && o.domain === d.id; });
    return ok;
  };
  if (ql.trim()) {
    if (ql.includes("unfunded") || ql.includes("not funded")) parsed.push("unfunded only");
    else if (ql.includes("funded")) parsed.push("funded only");
    if (ql.includes("ready") || ql.includes("absorb")) parsed.push("readiness ≥ 7");
    if (ql.includes("neglect")) parsed.push("neglect ≥ 7");
    if (ql.includes("impact")) parsed.push("impact ≥ 7");
    if (ql.includes("risk")) parsed.push("low risk");
    if (ql.includes("global")) parsed.push("global reach");
    else if (ql.includes("local")) parsed.push("local reach");
    else if (ql.includes("uk") || ql.includes("national")) parsed.push("national/global");
    D.domains.forEach((d) => { if (ql.includes(d.label.toLowerCase().split(" ")[0])) parsed.push(d.label); });
  }

  const ranked = React.useMemo(() => D.orgs.map((o) => ({ o, s: scoreOf(o) })).filter((x) => matchQuery(x.o)).sort((a, b) => b.s - a.s), [weights, wsum, ql]);

  // NeuroAI top recommendation under current weighting (prefer fundable: unfunded or prospect)
  const rec = React.useMemo(() => {
    const pool = ranked.length ? ranked : D.orgs.map((o) => ({ o, s: scoreOf(o) }));
    const fundable = pool.filter((x) => !x.o.funded);
    const pick = (fundable[0] || pool[0]);
    if (!pick) return null;
    const top2 = [...dims].map(([k, l]) => ({ k, l, c: contrib(pick.o, k) })).sort((a, b) => b.c - a.c).slice(0, 2);
    return { o: pick.o, s: pick.s, drivers: top2 };
  }, [ranked, weights]);

  const examples = ["unfunded orgs ready to absorb funding", "neglected high-impact prospects", "funded orgs with risk"];

  // AI insight tiles
  const tiles = React.useMemo(() => {
    const pool = D.orgs.map((o) => ({ o, s: scoreOf(o) }));
    const unf = pool.filter((x) => !x.o.funded);
    const topNext = [...unf].sort((a, b) => b.s - a.s)[0] || pool[0];
    const byNeglect = [...unf].sort((a, b) => b.o.scores.neglect - a.o.scores.neglect)[0];
    const byImpact = [...pool].sort((a, b) => b.o.scores.impact - a.o.scores.impact)[0];
    const byRisk = [...pool].filter((x) => x.o.funded).sort((a, b) => a.o.scores.risk - b.o.scores.risk)[0];
    return [
      { icon: "target", tone: "var(--accent)", label: "Fund next", o: topNext && topNext.o, metric: topNext ? topNext.s + "/100" : "" },
      { icon: "signal", tone: "var(--info)", label: "Most neglected", o: byNeglect && byNeglect.o, metric: byNeglect ? "neglect " + byNeglect.o.scores.neglect + "/10" : "" },
      { icon: "trendingUp", tone: "var(--good)", label: "Highest impact", o: byImpact && byImpact.o, metric: byImpact ? "impact " + byImpact.o.scores.impact + "/10" : "" },
      { icon: "shield", tone: "var(--warn)", label: "De-risk first", o: byRisk && byRisk.o, metric: byRisk ? "risk index " + (10 - byRisk.o.scores.risk) + "/10" : "" },
    ].filter((t) => t.o);
  }, [weights]);

  return (
    <div style={{ position: "absolute", inset: 0, overflow: "auto", background: "var(--bg)" }}>
      <div style={{ width: "100%", maxWidth: 1340, margin: "0 auto", padding: "30px 36px 64px" }}>
        {/* header */}
        <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", gap: 16, flexWrap: "wrap", marginBottom: 18 }}>
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 11, marginBottom: 8 }}>
              <span style={{ width: 34, height: 34, borderRadius: 10, display: "grid", placeItems: "center", background: "var(--accent-soft)", color: "var(--accent)" }}><Icon name="target" size={19} /></span>
              <span className="t-eyebrow">Intelligence · NeuroAI</span>
            </div>
            <div className="display" style={{ fontSize: 34 }}>Prioritisation</div>
            <div style={{ fontSize: 15, color: "var(--text-muted)", marginTop: 8, maxWidth: 680 }}>A transparent 9-dimension composite you can defend - tune the weighting or let NeuroAI pick the lens, and ask in plain English.</div>
          </div>
        </div>

        {/* NL query */}
        <div style={{ position: "relative", marginBottom: 10 }}>
          <Icon name="spark" size={17} style={{ position: "absolute", left: 14, top: 15, color: "var(--accent)", pointerEvents: "none" }} />
          <input className="input focusable" placeholder="Ask the ecosystem…  e.g. unfunded orgs ready to absorb funding" value={query}
            onChange={(e) => setQuery(e.target.value)} style={{ paddingLeft: 42, height: 48, fontSize: 14.5, background: "var(--surface)" }} />
          {query && <button className="btn btn-icon btn-ghost" onClick={() => setQuery("")} style={{ position: "absolute", right: 8, top: 9 }}><Icon name="x" size={16} /></button>}
        </div>
        <div style={{ display: "flex", gap: 7, marginBottom: 18, flexWrap: "wrap", alignItems: "center" }}>
          {parsed.length > 0
            ? <React.Fragment><span style={{ fontSize: 12, color: "var(--accent)", fontWeight: 600 }}><Icon name="spark" size={12} style={{ verticalAlign: "-2px" }} /> Understood as:</span>{parsed.map((p) => <span key={p} className="badge" style={{ background: "var(--accent-soft)", color: "var(--accent)", borderColor: "transparent" }}>{p}</span>)}</React.Fragment>
            : <React.Fragment><span style={{ fontSize: 12, color: "var(--text-faint)" }}>Try:</span>{examples.map((ex) => <button key={ex} className="chip focusable" style={{ fontSize: 12 }} onClick={() => setQuery(ex)}>{ex}</button>)}</React.Fragment>}
        </div>

        {/* NeuroAI recommendation */}
        {rec && (
          <div style={{ marginBottom: 16 }}>
            <AINote title="Recommended to fund next" onAction={() => onOpen(rec.o.id)} actionLabel={`Open ${rec.o.name}`}>
              Under the <strong>{PRIO_SCENARIOS[scenario].label.toLowerCase()}</strong> lens, <strong>{rec.o.name}</strong> ranks highest at <strong>{rec.s}/100</strong> - driven mainly by {rec.drivers.map((d, i) => <span key={d.k}>{i > 0 ? " and " : ""}<strong>{d.l.toLowerCase()}</strong></span>)}. {rec.o.funded ? "Already funded - consider a top-up or renewal." : `Currently unfunded${D.orgGap(rec.o) > 0 ? ` with a ${D.fmtMoney(D.orgGap(rec.o))} open ask` : ""}. ${rec.o.nextStep}`}
            </AINote>
          </div>
        )}

        {/* AI insight tiles */}
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14, marginBottom: 16 }}>
          {tiles.map((t) => (
            <button key={t.label} className="card focusable" onClick={() => onOpen(t.o.id)} style={{ padding: 16, textAlign: "left", cursor: "pointer", display: "block" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 11 }}>
                <span style={{ width: 30, height: 30, flex: "none", borderRadius: 8, display: "grid", placeItems: "center", background: "var(--surface-3)", color: t.tone }}><Icon name={t.icon} size={16} /></span>
                <span className="t-eyebrow">{t.label}</span>
              </div>
              <div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 4 }}>
                <span style={{ width: 7, height: 7, borderRadius: 999, background: domainColor(t.o.domain), flex: "none" }} />
                <span style={{ fontSize: 14, fontWeight: 650, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{t.o.name}</span>
              </div>
              <div style={{ fontSize: 11.5, color: "var(--text-muted)" }}>{t.metric} · {(D.domains.find((d) => d.id === t.o.domain) || {}).label}</div>
            </button>
          ))}
        </div>

        {/* scoring lens + advanced weighting toggle */}
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 14, flexWrap: "wrap" }}>
          <span style={{ fontSize: 12.5, color: "var(--text-muted)", fontWeight: 600, marginRight: 2 }}>Scoring lens:</span>
          {Object.entries(PRIO_SCENARIOS).map(([key, sc]) => {
            const on = scenario === key;
            return (
              <button key={key} className="focusable" onClick={() => applyScenario(key)}
                style={{ display: "inline-flex", alignItems: "center", gap: 7, font: "inherit", fontSize: 12.5, fontWeight: 550, cursor: "pointer", padding: "7px 13px", borderRadius: 999, border: "1px solid " + (on ? "transparent" : "var(--border)"), background: on ? "var(--accent)" : "var(--surface)", color: on ? "var(--accent-contrast)" : "var(--text-muted)" }}>
                <Icon name={sc.icon} size={14} /> {sc.label}
              </button>
            );
          })}
          {scenario === "custom" && <span className="badge" style={{ background: "var(--accent-soft)", color: "var(--accent)", borderColor: "transparent" }}>Custom</span>}
          <button className="btn btn-sm" style={{ marginLeft: "auto" }} onClick={() => setShowWeights((v) => !v)}>
            <Icon name="sliders" size={14} /> {showWeights ? "Hide weighting" : "Advanced weighting"}
          </button>
        </div>

        {/* collapsible weighting grid */}
        {showWeights && (
          <div className="card" style={{ padding: 18, marginBottom: 16 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 14 }}>
              <Icon name="sliders" size={16} style={{ color: "var(--text-muted)" }} />
              <div style={{ fontWeight: 650, fontSize: 14.5 }}>Dimension weighting</div>
              <span style={{ fontSize: 12, color: "var(--text-faint)" }}>- the leaderboard re-ranks live</span>
              <button className="btn btn-sm btn-ghost" style={{ marginLeft: "auto", color: "var(--accent)" }} onClick={() => applyScenario("balanced")}>Reset</button>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: "4px 28px" }}>
              {dims.map(([k, l]) => <WeightSlider key={k} label={l} value={weights[k]} onChange={(v) => { setScenario("custom"); setWeights((w) => ({ ...w, [k]: v })); }} />)}
            </div>
          </div>
        )}

        {/* full-width leaderboard */}
        <div className="card" style={{ overflow: "hidden", padding: 0 }}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "14px 18px", borderBottom: "1px solid var(--border)" }}>
            <span style={{ fontSize: 14.5, fontWeight: 650 }}>Leaderboard</span>
            <span style={{ fontSize: 12.5, color: "var(--text-muted)" }}><span className="mono">{ranked.length}</span> actors{query ? " · filtered" : ""} · tap a row to expand</span>
          </div>
          <div>
            {ranked.map(({ o, s }, idx) => {
              const b = scoreBand(s);
              const isOpen = expanded === o.id;
              return (
                <div key={o.id} style={{ borderBottom: "1px solid var(--border)" }}>
                  <button className="focusable" onClick={() => setExpanded(isOpen ? null : o.id)}
                    style={{ display: "flex", alignItems: "center", gap: 13, width: "100%", textAlign: "left", padding: "13px 18px", background: isOpen ? "var(--surface-2)" : "none", border: "none", cursor: "pointer", font: "inherit" }}>
                    <span className="mono" style={{ width: 26, color: "var(--text-faint)", fontWeight: 600, flex: "none" }}>{idx + 1}</span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 9, fontWeight: 600, fontSize: 14 }}>
                        <span style={{ width: 8, height: 8, borderRadius: 999, background: domainColor(o.domain), flex: "none" }} />
                        <span style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{o.name}</span>
                        {!o.funded && <span className="badge" style={{ background: "var(--warn-bg)", color: "var(--warn)", borderColor: "transparent", fontSize: 10 }}>Unfunded</span>}
                      </div>
                      <div style={{ fontSize: 11.5, color: "var(--text-muted)", marginTop: 3 }}>{(D.domains.find((d) => d.id === o.domain) || {}).label} · {o.geography} · {o.relationship}</div>
                    </div>
                    <div style={{ width: 160, flex: "none", display: "flex", alignItems: "center", gap: 9 }}>
                      <div style={{ flex: 1, height: 7, borderRadius: 5, background: "var(--surface-3)", overflow: "hidden" }}><div style={{ width: s + "%", height: "100%", background: b.c, borderRadius: 5, transition: "width .35s cubic-bezier(.2,.7,.3,1)" }} /></div>
                      <span className="mono" style={{ fontSize: 14, fontWeight: 700, color: b.c, width: 26, textAlign: "right" }}>{s}</span>
                    </div>
                    <span className="badge" style={{ flex: "none", width: 70, justifyContent: "center", background: b.bg, color: b.c, borderColor: "transparent", fontWeight: 600 }}>{b.label}</span>
                    <Icon name="chevronDown" size={16} style={{ color: "var(--text-faint)", flex: "none", transform: isOpen ? "none" : "rotate(-90deg)", transition: ".15s" }} />
                  </button>
                  {isOpen && <ActorProfile o={o} s={s} dims={dims} weights={weights} wsum={wsum} onOpen={onOpen} onOpenIntel={onOpenIntel} />}
                </div>
              );
            })}
            {ranked.length === 0 && <div style={{ padding: 40, textAlign: "center", fontSize: 13.5, color: "var(--text-faint)" }}>No actors match "{query}".</div>}
          </div>
        </div>
      </div>
    </div>
  );
}

/* expanded full actor profile - every prioritisation field + radar + contribution */
function ActorProfile({ o, s, dims, weights, wsum, onOpen, onOpenIntel }) {
  const D = window.DATA, fmt = D.fmtMoney;
  const keyPeople = [...new Set([o.account, o.contact, ...(o.teamMembers || [])].filter(Boolean))];
  const rels = (o.linked || []).map((id) => D.byId[id]).filter(Boolean);
  const contribs = dims.map(([k, l]) => ({ k, l, raw: o.scores[k] || 0, share: ((o.scores[k] || 0) * weights[k]) / (wsum * 10) * 100 })).sort((a, b) => b.share - a.share);
  const Field = ({ label, children }) => (
    <div style={{ padding: "8px 0", borderBottom: "1px solid var(--border)" }}>
      <div style={{ fontSize: 11, fontWeight: 600, color: "var(--text-faint)", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: 3 }}>{label}</div>
      <div style={{ fontSize: 13, color: "var(--text)", lineHeight: 1.5 }}>{children}</div>
    </div>
  );
  const conf = { High: "var(--good)", Medium: "var(--warn)", Low: "var(--rose)" }[o.confidence] || "var(--text-muted)";

  return (
    <div style={{ padding: "4px 18px 20px", background: "var(--surface-2)" }}>
      <div style={{ display: "grid", gridTemplateColumns: "1.1fr 1fr 0.9fr", gap: 18, alignItems: "start" }}>
        {/* fields */}
        <div>
          <Field label="Domain"><span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}><span style={{ width: 7, height: 7, borderRadius: 999, background: domainColor(o.domain) }} />{(D.domains.find((d) => d.id === o.domain) || {}).label} · {o.category}</span></Field>
          <Field label="Geography · legal · maturity">{o.geography} · {o.legalEntity} · {o.maturityStage}</Field>
          <Field label="Key people">
            <span style={{ display: "inline-flex", flexWrap: "wrap", gap: 5 }}>{keyPeople.length ? keyPeople.map((id) => <button key={id} className="chip focusable" style={{ fontSize: 11.5 }} onClick={(e) => { e.stopPropagation(); onOpen(id); }}>{D.byId[id] ? D.byId[id].name : id}</button>) : "-"}</span>
          </Field>
          <Field label="Aims & activities">{o.aims}</Field>
          <Field label="Relationships / affiliations">
            <span style={{ display: "inline-flex", flexWrap: "wrap", gap: 5 }}>{rels.length ? rels.map((r) => <button key={r.id} className="chip focusable" style={{ fontSize: 11.5 }} onClick={(e) => { e.stopPropagation(); onOpen(r.id); }}><span className="dot" style={{ background: domainColor(r.domain) }} />{r.name}</button>) : "-"}</span>
          </Field>
        </div>

        {/* funding picture + scores */}
        <div>
          <Field label="Current funding picture">{o.fundingPicture}</Field>
          <Field label="Funding need">{o.fundingNeed}{D.orgGap(o) > 0 && <span style={{ color: "var(--rose)", fontWeight: 600 }}> · gap {fmt(D.orgGap(o))}</span>}</Field>
          <Field label="What funding would enable">{o.fundingEnable}</Field>
          <Field label="Non-funding support needs"><span style={{ display: "inline-flex", flexWrap: "wrap", gap: 5 }}>{(o.nonFundingNeeds || []).map((n) => <span key={n} className="badge" style={{ background: "var(--surface)" }}>{n}</span>)}</span></Field>
          <Field label="Risk notes">{o.riskNotes || "None recorded."}</Field>
          <div style={{ display: "flex", gap: 16, marginTop: 10 }}>
            <div><div style={{ fontSize: 10.5, color: "var(--text-faint)", textTransform: "uppercase" }}>Neglect</div><div className="mono" style={{ fontSize: 17, fontWeight: 700, color: "var(--accent)" }}>{o.scores.neglect}/10</div></div>
            <div><div style={{ fontSize: 10.5, color: "var(--text-faint)", textTransform: "uppercase" }}>Impact</div><div className="mono" style={{ fontSize: 17, fontWeight: 700, color: "var(--good)" }}>{o.scores.impact}/10</div></div>
            <div><div style={{ fontSize: 10.5, color: "var(--text-faint)", textTransform: "uppercase" }}>Confidence</div><div style={{ fontSize: 14, fontWeight: 700, color: conf }}>{o.confidence}</div></div>
          </div>
        </div>

        {/* radar + contribution */}
        <div>
          <div style={{ display: "flex", justifyContent: "center", marginBottom: 6 }}><Radar scores={o.scores} dims={dims} size={172} /></div>
          <div className="t-eyebrow" style={{ marginBottom: 8 }}>What's driving the score</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
            {contribs.slice(0, 5).map((c) => (
              <div key={c.k} style={{ display: "flex", alignItems: "center", gap: 8 }}>
                <span style={{ flex: 1, fontSize: 11.5, color: "var(--text-muted)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{c.l}</span>
                <div style={{ width: 70, height: 5, borderRadius: 3, background: "var(--surface-3)", overflow: "hidden" }}><div style={{ width: Math.min(100, c.share * 2.4) + "%", height: "100%", background: "var(--accent)", borderRadius: 3 }} /></div>
                <span className="mono" style={{ fontSize: 10.5, color: "var(--text-faint)", width: 28, textAlign: "right" }}>{Math.round(c.share)}%</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* recommended next step + actions */}
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 16, padding: "13px 15px", borderRadius: 12, background: "var(--accent-soft)", border: "1px solid color-mix(in srgb, var(--accent) 26%, transparent)" }}>
        <Icon name="spark" size={17} style={{ color: "var(--accent)", flex: "none" }} />
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 11, fontWeight: 700, color: "var(--accent)", letterSpacing: "0.02em", marginBottom: 2 }}>RECOMMENDED NEXT STEP</div>
          <div style={{ fontSize: 13.5, color: "var(--text)", lineHeight: 1.5 }}>{o.nextStep}</div>
        </div>
        <button className="btn btn-sm" onClick={(e) => { e.stopPropagation(); onOpenIntel && onOpenIntel(o.id); }}><Icon name="target" size={14} /> Intel</button>
        <button className="btn btn-sm btn-primary" onClick={(e) => { e.stopPropagation(); onOpen(o.id); }}>Open record <Icon name="arrowRight" size={14} /></button>
      </div>
    </div>
  );
}

window.Prioritisation = Prioritisation;
window.scoreBand = scoreBand;
