{
const w = 420, h = 320;
const margin = {top: 25, right: 20, bottom: 42, left: 50};
const iw = w - margin.left - margin.right;
const ih = h - margin.top - margin.bottom;
const xMaxPlot = Math.max(200, Math.max(homeMaxC, homeIncomeW / pEq) * 1.1);
const yMaxPlot = Math.max(140, Math.max(homeMaxW, homeIncomeW) * 1.1);
const x = d3.scaleLinear().domain([0, xMaxPlot]).range([0, iw]);
const y = d3.scaleLinear().domain([0, yMaxPlot]).range([ih, 0]);
const svg = d3.create("svg").attr("viewBox", [0, 0, w, h]);
const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
g.append("g").attr("transform", `translate(0,${ih})`).call(d3.axisBottom(x).ticks(5)).selectAll("text").attr("font-size", 9);
g.append("g").call(d3.axisLeft(y).ticks(5)).selectAll("text").attr("font-size", 9);
g.append("text").attr("x", iw / 2).attr("y", ih + 35).attr("text-anchor", "middle").attr("font-size", 11).text("Q_C (cloth)");
g.append("text").attr("transform", "rotate(-90)").attr("x", -ih / 2).attr("y", -38).attr("text-anchor", "middle").attr("font-size", 11).text("Q_W (wine)");
// Title
g.append("text").attr("x", iw / 2).attr("y", -10).attr("text-anchor", "middle")
.attr("font-size", 13).attr("font-weight", "bold").attr("fill", "#005ab5").text("Home");
// PPF
g.append("line")
.attr("x1", x(homeMaxC)).attr("y1", y(0))
.attr("x2", x(0)).attr("y2", y(homeMaxW))
.attr("stroke", "#005ab5").attr("stroke-width", 2.2);
// Autarky IC (gray)
const uAut = Math.pow(homeAutC, alpha) * Math.pow(homeAutW, 1 - alpha);
const icAutData = d3.range(0.5, xMaxPlot, xMaxPlot / 300).map(c => {
const wV = Math.pow(uAut / Math.pow(c, alpha), 1 / (1 - alpha));
return [c, wV];
}).filter(d => d[1] <= yMaxPlot && d[1] >= 0);
g.append("path").datum(icAutData)
.attr("d", d3.line().x(d => x(d[0])).y(d => y(d[1])).curve(d3.curveMonotoneX))
.attr("fill", "none").attr("stroke", "#d6d6ce").attr("stroke-width", 1.2);
g.append("circle").attr("cx", x(homeAutC)).attr("cy", y(homeAutW)).attr("r", 4)
.attr("fill", "#d6d6ce").attr("stroke", "#3e3e3e").attr("stroke-width", 1);
g.append("text").attr("x", x(homeAutC) - 8).attr("y", y(homeAutW) - 8)
.attr("font-size", 9).attr("fill", "#3e3e3e").attr("text-anchor", "end").text("Autarky");
// Trade budget line
const blXint = homeIncomeW / pEq;
const blYint = Math.min(homeIncomeW, yMaxPlot);
g.append("line")
.attr("x1", x(blXint)).attr("y1", y(0))
.attr("x2", x(0)).attr("y2", y(blYint))
.attr("stroke", "#800000").attr("stroke-width", 1.5).attr("stroke-dasharray", "5,3");
// Production point
g.append("circle").attr("cx", x(homeTradeProdC)).attr("cy", y(homeTradeProdW)).attr("r", 5)
.attr("fill", "#005ab5").attr("stroke", "#800000").attr("stroke-width", 1);
g.append("text").attr("x", x(homeTradeProdC) - 6).attr("y", y(homeTradeProdW) + 15)
.attr("font-size", 9).attr("fill", "#005ab5").text("Prod");
// Trade IC (gold)
const uTrade = Math.pow(homeTradeC, alpha) * Math.pow(homeTradeW, 1 - alpha);
const icTradeData = d3.range(0.5, xMaxPlot, xMaxPlot / 300).map(c => {
const wV = Math.pow(uTrade / Math.pow(c, alpha), 1 / (1 - alpha));
return [c, wV];
}).filter(d => d[1] <= yMaxPlot && d[1] >= 0);
g.append("path").datum(icTradeData)
.attr("d", d3.line().x(d => x(d[0])).y(d => y(d[1])).curve(d3.curveMonotoneX))
.attr("fill", "none").attr("stroke", "#ffa319").attr("stroke-width", 1.6);
g.append("circle").attr("cx", x(homeTradeC)).attr("cy", y(homeTradeW)).attr("r", 5)
.attr("fill", "#ffa319").attr("stroke", "#800000").attr("stroke-width", 1.2);
g.append("text").attr("x", x(homeTradeC) + 8).attr("y", y(homeTradeW) - 8)
.attr("font-size", 10).attr("font-weight", "bold").attr("fill", "#800000").text("Trade");
// Drop lines
g.append("line").attr("x1", x(homeTradeC)).attr("y1", y(homeTradeW)).attr("x2", x(homeTradeC)).attr("y2", y(0))
.attr("stroke", "#3e3e3e").attr("stroke-width", 0.7).attr("stroke-dasharray", "2,2");
g.append("line").attr("x1", x(homeTradeC)).attr("y1", y(homeTradeW)).attr("x2", x(0)).attr("y2", y(homeTradeW))
.attr("stroke", "#3e3e3e").attr("stroke-width", 0.7).attr("stroke-dasharray", "2,2");
return svg.node();
}