fix(breaking): bordered elements should reserve layout space for border sides (#116) master
* fix: bordered boxes now reserve layout space for their border sides Clay doesn't account for border widths in layout — borders were drawn as visual overlays, so any element with border width > padding had its content collapsed behind the border glyphs (or, for fit-height boxes, collapsed to a single row with top and bottom glyphs overlapping and children invisible). Fix: at pack time, compute effective padding per side as max(userPadding, borderWidth). Border glyphs draw in the same cells as before; only the Clay layout values change so the engine reserves those cells. Semantics of the max rule: - No explicit padding: border width becomes the effective padding; content lands inside the border, not behind it. - padding == borderWidth (prior workaround): max evaluates to the same value, no double-reservation; these elements render identically. - padding > borderWidth: extra padding provides breathing room inside the border, measured from the border edge inward. Callers who set padding == borderWidth as a workaround are unaffected. Downstream compensators (e.g. lgtm.shop Panel) will render identically until they drop the manual compensation on their next pin bump. Resolves Open Decision #4 in specs/renderer-spec.md. * fix!: border padding is now additive, not max Border presence implies padding on that side equal to the border width. Callers who compensated by setting `padding == borderWidth` now receive double-reservation and must remove the workaround padding. `padding: 1` with `border: 1` → effective 2; `border: 1` alone → effective 1. * refactor: move border padding reservation into the wasm renderer The additive effective-padding rule (userPadding + borderWidth per side) was applied in pack() on the TypeScript side, so the packed layout word carried a pre-computed value. It now happens in clayterm.c when the PROP_BORDER block decodes border widths: decl is zero-initialized and PROP_LAYOUT decodes first, so border-without-layout and layout-without-border both fall out naturally. The wire format's padding field now carries raw user padding; the renderer owns the reservation. Behavior is unchanged — all existing border tests pass as-is.