createCardCanvas(400, 220, (ctx, w, h) => {
// Define boundary line styling
ctx.strokeStyle = "#adb5bd";
ctx.lineWidth = 1.5;
let tracts = [
[[20, 60], [80, 45], [110, 80], [60, 110]],
[[80, 45], [150, 50], [140, 95], [110, 80]],
[[20, 60], [60, 110], [70, 170], [15, 130]],
[[60, 110], [160, 150], [110, 180], [70, 170]],
[[60, 110], [110, 80], [125, 87.5], [110, 130]],
[[110, 130], [125, 87.5], [140, 95], [160, 150]]
];
tracts.forEach((tract, i) => {
if (i === 5) {
ctx.fillStyle = "rgba(13, 110, 253, 0.15)";
ctx.strokeStyle = "#0d6efd";
ctx.lineWidth = 2;
} else {
ctx.fillStyle = "#ffffff";
ctx.strokeStyle = "#adb5bd";
ctx.lineWidth = 1;
}
ctx.beginPath();
tract.forEach((pt, idx) => {
if (idx === 0) ctx.moveTo(pt[0], pt[1]);
else ctx.lineTo(pt[0], pt[1]);
});
ctx.closePath();
ctx.fill();
ctx.stroke();
});
let tableX = 210;
let tableY = 25;
let colWidths = [45, 45, 45, 45];
let rowHeight = 22;
let totalWidth = colWidths.reduce((a, b) => a + b, 0);
ctx.fillStyle = "#e9ecef";
ctx.fillRect(tableX, tableY, totalWidth, rowHeight);
ctx.strokeStyle = "#ced4da";
ctx.lineWidth = 1;
ctx.strokeRect(tableX, tableY, totalWidth, rowHeight);
let headers = ["GEOID", "NAME", "VALUE", "MOE"];
let curX = tableX;
ctx.fillStyle = "#495057";
ctx.font = "bold 9px sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
headers.forEach((h, idx) => {
ctx.fillText(h, curX + colWidths[idx] / 2, tableY + rowHeight / 2);
if (idx < headers.length - 1) {
ctx.beginPath();
ctx.moveTo(curX + colWidths[idx], tableY);
ctx.lineTo(curX + colWidths[idx], tableY + rowHeight * 7);
ctx.stroke();
}
curX += colWidths[idx];
});
for (let r = 1; r <= 6; r++) {
let curY = tableY + (r * rowHeight);
if (r === 4) {
ctx.fillStyle = "rgba(13, 110, 253, 0.08)";
ctx.fillRect(tableX, curY, totalWidth, rowHeight);
ctx.strokeStyle = "#0d6efd";
} else {
ctx.strokeStyle = "#dee2e6";
}
ctx.strokeRect(tableX, curY, totalWidth, rowHeight);
// Mock text lines inside data table cells
let cellX = tableX;
colWidths.forEach((w) => {
ctx.fillStyle = (r === 4) ? "#0d6efd" : "#6c757d";
ctx.fillRect(cellX + 6, curY + 9, w - 12, 4);
cellX += w;
});
}
ctx.strokeStyle = "rgba(13, 110, 253, 0.4)";
ctx.lineWidth = 1.5;
ctx.setLineDash([4, 4]);
ctx.beginPath();
ctx.moveTo(140, 95);
ctx.lineTo(tableX, tableY + (4 * rowHeight));
ctx.moveTo(160, 150);
ctx.lineTo(tableX, tableY + (5 * rowHeight));
ctx.stroke();
ctx.setLineDash([]);
})