The app CSS in `karldns/web/styles.py` already owns the custom KarlDNS look. Bootstrap is mainly supplying reset, grid, forms, buttons, tables, navigation, pagination, and common utilities.
Use `scripts/build-bootstrap-subset.py` to compile a Bootstrap Sass subset from transient npm packages:
```sh
python3 scripts/build-bootstrap-subset.py
python3 scripts/build-bootstrap-subset.py --write
```
The script imports Bootstrap 5.3.8 Sass modules for the components above and filters `$utilities` before `utilities/api` so unused utility families are not emitted. It does not require a committed `package.json`, lockfile, or `node_modules`.
Dry-run result on this worktree:
- Subset: 113.8 KiB raw, 16.8 KiB gzip.
- Full local asset: 226.7 KiB raw, 30.1 KiB gzip.
- Reduction: 49.8% raw, 44.2% gzip.
## Rollout Recommendation
Keep the current app references unchanged until the subset is visually tested. The safe implementation sequence is:
2. Add an isolated asset route for `/bootstrap-karldns.min.css`.
3. Switch `_page()` from `/bootstrap-5.3.8.min.css?v=2` to `/bootstrap-karldns.min.css?v=1`.
4. Run UI tests and browser-check public, dashboard, locked dashboard, admin tables, pagination, dark mode, and copy fields.
Do not use a selector-purge pass against rendered HTML yet. The Python templates include dynamic branches and JavaScript-created pagination classes, so Sass module selection plus a curated utility allowlist is simpler and less likely to break rare pages.