diff --git a/README.md b/README.md
index 75b64c4..603e294 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@ across sites.
| `weirsoe-theme.css` | Tokens (`--color-*`) + base (glow, selection, transitions) + `.wt-card/.wt-btn/.wt-input/.wt-tag` + `.prose` + theme-toggle styles |
| `weirsoe-theme.js` | Persisted dark⇄light toggle + a no-flash snippet |
| `adapters/bulma.css` | Maps Bulma classes → tokens (for Bulma sites) |
+| `adapters/bootstrap.css` | Maps Bootstrap 5 classes → tokens (for Bootstrap sites) |
| `examples/demo.html` | Standalone preview |
## Quick start (vanilla)
@@ -51,6 +52,21 @@ Load the adapter **after** Bulma and **after** `weirsoe-theme.css`:
Your existing `.box`, `.button`, `.input`, `.tag`, `.navbar`… are now dark and
card-styled. `wish.weircon.dk` (Christmas-Community fork) consumes it this way.
+## Theming an existing Bootstrap site
+
+Load the adapter **after** Bootstrap and **after** `weirsoe-theme.css`, and mirror
+`data-theme` onto Bootstrap’s `data-bs-theme` on `` so the two stay in sync:
+
+```html
+
+
+
+```
+
+Your existing `.card`, `.btn`, `.form-control`, `.alert`, `.table`, `.navbar`,
+`.badge`… become dark and card-styled. `email-manager.weircon.dk` consumes it
+this way.
+
## Tokens
`--color-bg --color-surface --color-surface-2 --color-surface-3 --color-border
diff --git a/adapters/bootstrap.css b/adapters/bootstrap.css
new file mode 100644
index 0000000..5bc2405
--- /dev/null
+++ b/adapters/bootstrap.css
@@ -0,0 +1,173 @@
+/* ============================================================================
+ weirsoe-theme — Bootstrap 5 adapter.
+ Maps Bootstrap's component classes onto the weirsoe-theme tokens so an
+ existing Bootstrap site gets the dark, card-based look without rewriting
+ markup. Load AFTER bootstrap(.min).css and AFTER weirsoe-theme.css (which
+ defines the --color-* tokens). Mirror of adapters/bulma.css.
+
+ Keep Bootstrap's own dark mode in sync by mirroring data-theme onto
+ data-bs-theme on (dark for "dark"/"terminal", light for "light").
+ ========================================================================== */
+
+/* ---------- page surfaces ---------- */
+body,
+body.bg-light { background-color: var(--color-bg) !important; color: var(--color-text); }
+.bg-white, .bg-body, .bg-body-tertiary, .bg-body-secondary { background-color: var(--color-surface) !important; }
+.bg-light { background-color: var(--color-surface-2) !important; }
+
+/* ---------- typography ---------- */
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6,
+strong, b, label, .form-label { color: var(--color-text); }
+.text-muted, .text-secondary { color: var(--color-muted) !important; }
+.text-body, .text-dark, .text-black { color: var(--color-text) !important; }
+.text-primary { color: var(--color-accent) !important; }
+.text-success { color: var(--color-good) !important; }
+.text-danger { color: var(--color-bad) !important; }
+.text-warning { color: #ffd479 !important; }
+a { color: var(--color-accent); }
+a:hover { color: var(--color-accent-2); }
+h1, .h1, h2, .h2, h3, .h3 { letter-spacing: -0.02em; }
+
+/* ---------- header / navbar (translucent dark, blurred) ---------- */
+.navbar,
+.navbar.navbar-gradient {
+ background: color-mix(in srgb, var(--color-bg) 70%, transparent) !important;
+ -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
+ border-bottom: 1px solid color-mix(in srgb, var(--color-border) 70%, transparent);
+ box-shadow: none !important;
+}
+.navbar .navbar-brand,
+.navbar .nav-link,
+.navbar .navbar-text { color: var(--color-text) !important; }
+.navbar .nav-link {
+ border-radius: 0.5rem; padding: 0.375rem 0.75rem;
+ transition: color .2s, background-color .2s;
+}
+.navbar .nav-link:hover,
+.navbar .nav-link.active,
+.navbar .nav-link[aria-current="page"] { background: var(--color-surface-2); color: var(--color-text) !important; }
+.navbar .navbar-brand { font-weight: 700; letter-spacing: -0.02em; }
+.navbar-toggler { border: 1px solid var(--color-border) !important; }
+.navbar-toggler:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent); }
+
+/* ---------- cards (the card-based look) ---------- */
+.card {
+ background: color-mix(in srgb, var(--color-surface) 75%, transparent);
+ border: 1px solid var(--color-border);
+ border-radius: var(--wt-radius);
+ box-shadow: var(--wt-shadow);
+ color: var(--color-text);
+ transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
+}
+.card:hover { border-color: color-mix(in srgb, var(--color-accent) 35%, var(--color-border)); }
+.card-header,
+.card-footer {
+ background: color-mix(in srgb, var(--color-surface-2) 60%, transparent);
+ border-color: var(--color-border);
+ color: var(--color-text);
+}
+.card .card { box-shadow: none; }
+.list-group-item {
+ background: color-mix(in srgb, var(--color-surface) 70%, transparent);
+ border-color: var(--color-border);
+ color: var(--color-text);
+}
+.list-group-item-action:hover { background: var(--color-surface-2); color: var(--color-text); }
+
+/* ---------- buttons ---------- */
+.btn { border-radius: var(--wt-radius-sm); transition: filter .15s ease, background-color .15s ease, border-color .15s ease; }
+.btn-primary,
+.btn-gradient {
+ background: var(--color-accent) !important; border-color: transparent !important;
+ color: var(--color-accent-ink) !important; font-weight: 650;
+}
+.btn-primary:hover,
+.btn-gradient:hover { filter: brightness(1.08); color: var(--color-accent-ink) !important; }
+.btn-secondary, .btn-light,
+.btn-outline-secondary, .btn-outline-light {
+ background: var(--color-surface-2) !important; border-color: var(--color-border) !important; color: var(--color-text) !important;
+}
+.btn-secondary:hover, .btn-light:hover,
+.btn-outline-secondary:hover { background: var(--color-surface-3) !important; color: var(--color-text) !important; }
+.btn-outline-primary { background: transparent !important; border-color: var(--color-accent) !important; color: var(--color-accent) !important; }
+.btn-outline-primary:hover { background: var(--color-accent) !important; color: var(--color-accent-ink) !important; }
+.btn-danger { background: #3a1620 !important; border-color: #5b2230 !important; color: var(--color-bad) !important; }
+.btn-danger:hover { filter: brightness(1.12); }
+.btn-success { background: #10341f !important; border-color: #1d5a32 !important; color: var(--color-good) !important; }
+.btn-warning { background: #3a2c10 !important; border-color: #5b471d !important; color: #ffd479 !important; }
+.btn-link { color: var(--color-accent) !important; text-decoration: none; }
+.btn-link:hover { color: var(--color-accent-2) !important; }
+.btn-close { filter: invert(1) grayscale(1) brightness(1.7); }
+
+/* ---------- form controls ---------- */
+.form-control, .form-select, .input-group-text {
+ background: var(--color-surface-2) !important; border-color: var(--color-border) !important;
+ color: var(--color-text) !important; border-radius: var(--wt-radius-sm);
+}
+.form-control::placeholder { color: color-mix(in srgb, var(--color-muted) 80%, transparent); }
+.form-control:focus, .form-select:focus {
+ border-color: var(--color-accent) !important;
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent) !important;
+}
+.form-check-input { background-color: var(--color-surface-2); border-color: var(--color-border); }
+.form-check-input:checked { background-color: var(--color-accent); border-color: var(--color-accent); }
+.form-check-input:focus { border-color: var(--color-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent); }
+.form-label { font-weight: 600; }
+.form-text { color: var(--color-muted); }
+
+/* ---------- alerts (notification style) ---------- */
+.alert { border-radius: var(--wt-radius); border: 1px solid var(--color-border); }
+.alert-success { background: #10341f; color: #c8f7d6; border-color: #1d5a32; }
+.alert-danger, .alert-error { background: #3a1620; color: #ffd0d9; border-color: #5b2230; }
+.alert-warning { background: #3a2c10; color: #ffe1a8; border-color: #5b471d; }
+.alert-info, .alert-primary { background: #10243a; color: #cfe6ff; border-color: #1d3a5a; }
+
+/* ---------- tables ---------- */
+.table {
+ color: var(--color-text);
+ --bs-table-bg: transparent; --bs-table-color: var(--color-text);
+ --bs-table-border-color: var(--color-border);
+ --bs-table-striped-bg: color-mix(in srgb, var(--color-surface-2) 35%, transparent);
+ --bs-table-striped-color: var(--color-text);
+ --bs-table-hover-bg: color-mix(in srgb, var(--color-accent) 8%, transparent);
+ --bs-table-hover-color: var(--color-text);
+}
+.table > :not(caption) > * > * { border-bottom-color: var(--color-border); }
+.table thead th, .em-table thead th {
+ background: var(--color-surface-2) !important; color: var(--color-text) !important;
+ border-bottom: 1px solid var(--color-border) !important;
+}
+
+/* ---------- badges ---------- */
+.badge.bg-primary, .badge.text-bg-primary { background: var(--color-accent) !important; color: var(--color-accent-ink) !important; }
+.badge.bg-secondary, .badge.text-bg-secondary { background: var(--color-surface-3) !important; color: var(--color-text) !important; }
+.badge.bg-success, .badge.text-bg-success { background: #10341f !important; color: var(--color-good) !important; }
+.badge.bg-danger, .badge.text-bg-danger { background: #3a1620 !important; color: var(--color-bad) !important; }
+.badge.bg-warning, .badge.text-bg-warning { background: #3a2c10 !important; color: #ffd479 !important; }
+.badge.bg-info, .badge.text-bg-info { background: #10243a !important; color: #cfe6ff !important; }
+
+/* ---------- dropdowns / modals / offcanvas ---------- */
+.dropdown-menu, .modal-content, .offcanvas {
+ background: var(--color-surface); border: 1px solid var(--color-border);
+ color: var(--color-text); border-radius: var(--wt-radius-sm); box-shadow: var(--wt-shadow);
+}
+.dropdown-item { color: var(--color-text); }
+.dropdown-item:hover, .dropdown-item:focus { background: var(--color-surface-2); color: var(--color-accent); }
+.dropdown-divider, .modal-header, .modal-footer { border-color: var(--color-border); }
+
+/* ---------- pagination ---------- */
+.page-link { background: var(--color-surface-2); border-color: var(--color-border); color: var(--color-text); }
+.page-link:hover { background: var(--color-surface-3); color: var(--color-accent); }
+.page-item.active .page-link { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-accent-ink); }
+.page-item.disabled .page-link { background: var(--color-surface); color: var(--color-muted); }
+
+/* ---------- borders / dividers / misc ---------- */
+.border, .border-top, .border-bottom, .border-start, .border-end { border-color: var(--color-border) !important; }
+hr { border-top-color: var(--color-border); color: var(--color-border); opacity: 1; }
+.shadow-sm, .shadow, .shadow-lg { box-shadow: var(--wt-shadow) !important; }
+.nav-tabs { border-bottom-color: var(--color-border); }
+.nav-tabs .nav-link.active { background: var(--color-surface); border-color: var(--color-border) var(--color-border) var(--color-surface); color: var(--color-text); }
+.progress { background: var(--color-surface-2); }
+.progress-bar { background: var(--color-accent); }
+code, kbd { color: var(--color-accent-2); }