drawBoxes = (sheet, crate) => {
const container = sheet.append("svg")
.attr("name", "crate")
.attr("viewBox", `0 0 ${crate.max.w} ${crate.total.h}`)
.attr("preserveAspectRatio", "xMidYMin meet")
.attr("fill", "white")
.style("font-family", "monospace")
.style("font-size", ".09em")
.style("text-anchor", "middle")
.style("alignment-baseline", "central")
const box = container.selectAll("_")
.data(crate.boxes)
.enter()
.append("svg")
.attr("name", (d, i) => `box-${i}`)
.attr("y", d => d.framed.total.h)
.attr("x", d => (crate.max.w - d.framed.w) / 2)
box
.append("rect")
.attr("width", d => d.framed.w)
.attr("height", d => d.framed.h)
.attr("fill", "dimgrey")
box
.append("rect")
.attr("x", d => d.framed.x)
.attr("y", d => d.framed.y)
.attr("width", d => d.normalized.w)
.attr("height", d => d.normalized.h)
.attr("fill", "red")
const text = box
.append("text")
.attr("x", d => d.framed.w / 2)
.attr("y", d => d.framed.y + d.normalized.h / 2)
text.append("tspan")
.text(d => `${fix(d.original.w)}:${fix(d.original.h)} = ${fix(d.normalized.a)}`)
text.append("tspan")
.attr("x", d => d.framed.w / 2)
.attr("dy", 1.5)
.text(d => `×${fix(d.normalized.scale)} = ${fix(d.normalized.w)}:${fix(d.normalized.h)}`)
}