Upper edge — always finite, always > start. On a closed band this is
the real edge. The open-ended band has none, so end is a drawable
stand-in, never Infinity: wide enough to cover the highest value
observed, and at least as wide as the band below. Treat it as a drawing
bound, not as data — it can exceed anything actually recorded (and a
device's out-of-range sentinel sample will stretch it).
Share of total in-zone time, [0, 1].
true on the open-ended top band, whose real upper edge is unbounded —
end is a drawable stand-in. Label it "{start}+" rather than as a range.
Lower edge, in the value axis (watts / bpm / m·s⁻¹). Bands are
inclusive-upper ((start, end]), so this edge belongs to the band
below — except on Z1, whose floor is inclusive.
1-based zone number (Z1 = the lowest band).
One zone's time + share.
Carries pond's canonical bin edges (
start/end) so the array feeds@pond-ts/charts(<BarChart bins>/stacksFromBins) with no mapping step — the same{ start, end, …aggregates }shape core'sbyColumnreturns, and the same guarantee core enforces: finite, withend > start. (An infinite edge blows up a chart's axis domain; a zero-width bin is whatbyColumnitself rejects as unrepresentable.)