Layout code (line-break DP arrays, CSS lookups, glyph buffers) allocates
via std::vector/std::string and abort()s on OOM under -fno-exceptions --
it cannot fail cleanly mid-build. Field crashes (X4, BLE resident):
builds entered at ~11 KB free and aborted in ParsedText::
computeLineBreaks; an inline BLE restart after recovery re-starved the
render and abort()ed in FontCacheManager's scanText_.reserve at ~8 KB.
- BUILD_MIN_FREE_HEAP (40 KB): pre-flight before the build; below the
floor go straight to recovery instead of attempting a doomed build
- Recovery no longer restarts NimBLE inline; the lifecycle stays paused
until the render completes (scoped unpause guard), then the main-loop
lifecycle restarts BLE behind its own heap gate
- EpubReaderActivity: when a section build fails even after the BLE
teardown/retry, silentRestartToReader() as last-resort heap defrag,
guarded by bootWasSilentRestart() to prevent reboot loops
- main/SilentRestart.h: expose bootWasSilentRestart()
- platformio.ini: enable FREEINK_BLE_HID_REPORT_DEBUG in env:default