Plot.plot({
height: 360, width: 520, marginLeft: 56, marginRight: 30, marginTop: 30, marginBottom: 46, grid: true,
x: {domain:[0.7,5.3], label:"Locals per park →", ticks:[1,2,3,4,5]},
y: {label:"↑ Retention % (still active at week 52)", domain:[26, 47]},
marks: [
Plot.areaY(dose, {x:"dose", y1:"retention_ci_low", y2:"retention_ci_high", fill:pal.steel, fillOpacity:0.15}),
Plot.line(dose, {x:"dose", y:"retention_mean", stroke:pal.steel, strokeWidth:2}),
Plot.dot(dose, {x:"dose", y:"retention_mean", fill:pal.steel, r:4.5, stroke:"#fff", strokeWidth:1, tip:true, channels:{scenario:"scenario"}}),
Plot.text(dose, {x:"dose", y:"retention_mean", text:d=>d3.format(".1f")(d.retention_mean)+"%", dy:-12, fontSize:9.5, fill:"#333"}),
// connect the endpoints to the named scenarios used elsewhere
Plot.text(dose.filter(d=>d.dose===1), {x:"dose", y:"retention_mean", text:["1 local = Suboptimal"], dy:17, dx:2, fontSize:8.5, fill:"#888", textAnchor:"start"}),
Plot.text(dose.filter(d=>d.dose===5), {x:"dose", y:"retention_mean", text:["5 locals = Baseline"], dy:17, dx:-2, fontSize:8.5, fill:"#888", textAnchor:"end"}),
// plain-language takeaway in the empty upper-left
Plot.text([{x:0.85, y:45}], {x:"x", y:"y", text:["Each extra local per park\n≈ +4.3 pp retention"], textAnchor:"start", fontSize:11, fontWeight:"bold", fill:pal.steel, lineHeight:1.25})
]
})