Three optimizations for EPUBs with many chapters (e.g. 2768 chapters):
1. OPF idref→href lookup: Build sorted hash index during manifest parsing,
use binary search during spine resolution. Reduces ~4min to ~30-60s.
2. TOC href→spineIndex lookup: Build sorted hash index in beginTocPass(),
use binary search in createTocEntry(). Reduces ~4min to ~30-60s.
3. ZIP central-dir cursor: Resume scanning from last position instead of
restarting from beginning. Reduces ~8min to ~1-3min.
All optimizations only activate for large EPUBs (≥400 spine items).
Small books use unchanged code paths.
Memory impact: ~33KB + ~39KB temporary during indexing, freed after.
Expected total: ~17min → ~3-5min for Shadow Slave (2768 chapters).
Also adds phase timing logs for performance measurement.
## Summary
* Swap to updated SDCardManager which uses SdFat
* Add exFAT support
* Swap to using FsFile everywhere
* Use newly exposed `SdMan` macro to get to static instance of
SDCardManager
* Move a bunch of FsHelpers up to SDCardManager
Still a bit raw, but gets the time required to determine the size of
each chapter (for reading progress) down from ~25ms to 0-1ms.
This is done by keeping the zipArchive open (so simple ;)).
Probably we don't need to cache the spine sizes anymore then...
---------
Co-authored-by: Dave Allie <dave@daveallie.com>