Mark · Foundations

Tokens

The contract every layer above reads. Components never name a colour or a radius directly — they name a token, which is why a theme can rebind the whole system without touching markup, and why a palette can flip at runtime.


Brand

--mk-primary · --mk-secondary · --mk-primary-soft · --mk-on-primary · --ring

Two hues, ordered: --mk-primary is the one the interface is built out of, --mk-secondary the one gradients and highlights reach for. Both are held on :root as a light/dark seed pair, so a nested dark region — an overlay header, a black footer — resolves the dark half even on a light page. --mk-on-primary is derived per seed rather than assumed white, which is what stops a pale hue rendering white-on-white.

Mark ships no colour utilities. These tokens are wired to Bootstrap's own --bs-primary-rgb and --bs-secondary-rgb, so .text-primary, .bg-primary and .border-primary already follow the palette and the mode — one name per role. -light and -dark modify a named hue; they never name one.

--mk-primary

The live half of the pair

--mk-primary-soft

A wash — .08 light, .16 dark

--mk-on-primary

Readable text ON the primary

--mk-secondary

The second hue — gradients, highlights

--ring — the focus ring every control shares:


The fixed pair

.text-off-white · .bg-off-black · .link-off-white

Two colours that do not flip with the mode, for the places where nothing is flipping: a control over a photograph has no ground to read, because its ground is a picture. Bootstrap keys these light and dark; here those two words are already taken — they name the color mode — so .text-light would read as “text for light mode” and mean the opposite. They are off-white and off-black, which is also what they are: $gray-100 and $gray-900, a step off each.

The rename is a re-key of $theme-colors, so every family Bootstrap generates from it follows — .btn-off-white, .text-bg-off-white, .table-off-black, --bs-off-white-rgb. The values did not move; only the keys.

Which leaves -light and -dark free for the only job they should have: modifying a named hue (primary-light). They never name one.


Ink and ground

--bs-body-color · --bs-body-bg · --bs-border-color

The pair the base button is drawn in. Both flip with the mode, which is the whole reason .mk-btn needs no variant to survive a dark band — ink already knows where it is.

--bs-body-color

Ink

--bs-body-bg

Ground

--bs-border-color

The quiet line


Shape

--bs-border-radius-*

Five steps. Controls take the base, cards take lg; the larger two are for full-bleed media and feature panels.

sm .375rem
base .625rem
lg 1rem
xl 1.25rem
xxl 1.75rem

Type

$font-family-sans-serif · $display-letter-spacing · $eyebrow-letter-spacing

Inter over a system stack — no external request unless a theme adds a webfont. Tracking is two tokens pulling opposite ways, and the tension between them is a theme decision rather than a constant.

Display pulls tight

$display-letter-spacing: -.02em · weight 800 · line-height 1.15

Eyebrows push wide

$eyebrow-letter-spacing: .08em

Body sits at 1rem with a 1.65 line-height — long-form measure, not UI density.

$font-size-base: 1rem · $line-height-base: 1.65


Space

$spacers → .p-*, .m-*, .gap-*

Bootstrap's scale with marketing-scale steps added — 5 and 6 are the band rhythm, which is why a section reads as a section without hand-tuned padding.

0 0
1 .25rem
2 .5rem
3 1rem
4 1.5rem
5 3rem
6 4.5rem