setOpen((v) => !v)}>
{title}
{!c.included && Excluded}
{c.alreadyEntitled && (
Already entitled
)}
{mapped.length ? `→ ${mapped.map((p) => p!.name).join(", ")}` : "No replacement mapped yet"}
Net / yr
{money(m.annualSavings, true)}
Payback
{monthsLabel(m.paybackMonths)}
{m.score.toFixed(0)}
{open ? "▴" : "▾"}
{/* ---- Incumbent ---- */}
Incumbent tool
{ setApplied(null); set(field, value); }}
onPick={applyEntry}
/>
{applied && (
Filled from the knowledge base. Adjust anything — your values are learned back.
)}
set("renewalDate", e.target.value)} />
{/* ---- Replacement ---- */}
Our replacement
set("productIds", ids)} />
{suggestions.length > 0 && (
Suggested
{suggestions.map((p) => (
))}
)}
{/* ---- Total cost and pricing ---- */}
Total cost of ownership
{money(m.licence)} licence + {money(m.infra)} infra + {money(m.admin)} admin + {money(m.other)} other = {money(m.tco)}/yr
{conf && (
Defaults: {conf.level} confidence · {conf.source}{conf.stale ? " · needs review" : ""}
)}
setTco("infra", v)} />
0 ? d.adminFte : 0}
hint={`${money(m.admin, true)} at the assessment FTE cost`} step={0.05} onChange={(v) => setTco("adminFte", v)} />
setTco("other", v)} />
Our price / yr >} value={c.investment?.annual ?? null} fallback={Math.round(m.subscription)}
hint={c.alreadyEntitled ? "Already entitled — none by default" : "Blank = share of the deal-level price"} step={1000} onChange={(v) => setInv("annual", v)} />
Our services >} value={c.investment?.services ?? null} fallback={Math.round(m.services)}
hint="Blank = share of deal-level services" step={1000} onChange={(v) => setInv("services", v)} />
{/* ---- Scoring ---- */}
set("capability", n)} />
set("switchEase", n)} />
= 36 ? "Beyond the scoring horizon" : "Within the scoring horizon"}
onChange={(n) => set("timeToRoiMonths", n)} />
set("strategicValue", n)} />