u_curve = (x_target) => d3.range(0, 10.1, 0.2).map(x => [x, 10 - Math.abs(x - x_target)])
Plot.plot({
height: 320,
x: { label: "一维政策空间(如公共支出规模) →", domain: [0, 10] },
y: { label: "↑ 选民单峰效用", domain: [0, 11] },
marks: [
// 水平参考基准线
Plot.ruleY([0], { stroke: "#cbd5e1" }),
// 三位选民的单峰效用折线 (绿、紫、橙)
Plot.line(u_curve(pts[0].x), { stroke: "#10b981", strokeWidth: 1.8 }),
Plot.line(u_curve(pts[1].x), { stroke: "#8b5cf6", strokeWidth: 2.5 }), // 中位选民加粗高亮
Plot.line(u_curve(pts[2].x), { stroke: "#f59e0b", strokeWidth: 1.8 }),
// 理想点峰顶散点
Plot.dot([[pts[0].x, 10], [pts[1].x, 10], [pts[2].x, 10]], { fill: ["#10b981", "#8b5cf6", "#f59e0b"], r: 6 }),
Plot.text([[pts[0].x, 10.5], [pts[1].x, 10.5], [pts[2].x, 10.5]], { text: [pts[0].id, `${pts[1].id} (中位)`, pts[2].id], fontSize: 12, fontWeight: "bold" }),
// 挑战方案 y 的竖直参考线 (红色虚线)
Plot.ruleX([y_alt], { stroke: "#ef4444", strokeWidth: 2, strokeDasharray: "4,4" }),
Plot.text([[y_alt, 2]], { text: [`挑战 y = ${y_alt}`], dx: 14, fill: "#ef4444", fontSize: 12, fontWeight: "bold" }),
// 中位方案 x_m 的竖直参考线 (紫色粗虚线)
Plot.ruleX([x_median], { stroke: "#8b5cf6", strokeWidth: 2, strokeDasharray: "2,2" })
],
title: "单峰效用分布与中位选民理想点(紫色粗线为中位选民,y 永远无法击败它)"
})