The wordmark is the identity. The substrate is cream paper. The mark holds its terminals. The platform serves the operator's commercial agency, and beauty is part of the contract.
The B is the mark. An adinkra-style geometric crest in bark, derived from Canva design DAHJfCx22YE. It carries Baobab the way Sakura’s blossom carries Curator. “That B means Baobab.”
Baobab and the adinkra B mark are trademarks of Lacuna Labs, pending USPTO registration. The mark, the wordmark, and the B+wordmark lockup are reserved use; their appearance outside Baobab’s own surfaces or operator-authorized contexts is not permitted. The favicon set ships as a transparent SVG (vector, infinite scale) plus PNG raster fallbacks (16, 32, 180, 192, 512). Co-marketing surfaces require explicit Lacuna Labs sign-off.
The B leads. The wordmark follows. At the top of every Baobab surface this is the lockup — B as the trademark on the left, "Baobab" on the right.
The B also stands alone where the word doesn’t fit — favicons, app icons, social avatars, in-product chrome where the wordmark is too wide.
The wordmark also stands alone where the trademark is implicit — running mast on internal-only surfaces, footer attributions, in-prose mentions.
| Property | Value |
|---|---|
| Family | Fraunces (variable) |
| Style / weight | Italic 600 |
opsz axis | Bound to render size: 9 / 24 / 72 / 96 / 144 (see 1.3) |
SOFT axis | 0. Terminals stay firm. Never softened. |
| Tracking | -0.018em display, -0.01em masthead, 0 below 24px |
| Default color | --forest #2D5016 on cream |
| Identity-warm color | --bark #6B4423 on masthead and warm contexts |
| Photographic substrate | --ink #1A1A1A |
| Inverted (dark substrate) | --ink-on-dark #F1ECDE |
| Minimum width | 88px |
| Clear space | Equal to the cap-height of the lowercase “b” on all four sides |
| Minimum contrast | 4.5:1 against the mean luminance of any substrate |
| Baseline | Optical baseline of the italic “b”-stem foot — never bounding-box bottom |
favicon-16.png, favicon-32.png, favicon.ico.apple-touch-icon-180.png, icon-192.png, icon-512.png.--bark #6B4423 (B on cream) or --ink-on-dark (B on bark). Never both. Forest variant only on the wordmark, never on the B.| Render size | opsz | Tracking |
|---|---|---|
| 14–18px (inline) | 9 | 0 |
| 19–28px (in-flow) | 24 | -0.005em |
| 29–56px (masthead) | 72 | -0.01em |
| ≥ 57px (hero / share) | 96 | -0.018em |
| ≥ 96px (canvas / billboard) | 144 | -0.02em |
text-shadow.Three families plus one transitional fallback. All OFL-licensed. Self-hostable. Loaded with the variable axes the canon uses, no more.
| Family | Role | Axes |
|---|---|---|
| Fraunces | Display, headlines, wordmark, emphasis, drop caps. | opsz (9–144), wght (100–900), ital. SOFT always 0. |
| Crimson Pro | Long-form body, reading surfaces, captions, pull-quotes, LLM voice on dark substrate (see 2.5). | wght (200–900), ital. |
| JetBrains Mono | Data, ticker, code, metadata, attribution, eyebrows, operator-typed input. | wght (100–800). Italic loaded but never used in product. |
| Inter | UI-chrome fallback only where serif is too soft below 14px (compact form fields, lang-picker dropdown options). Transitional concession. | wght (100–900). |
display=swap + preconnect. Acceptable for v0./fonts/, Latin + Latin-Extended subsets, preload the Fraunces variable file (masthead is above-the-fold). CDN dependency removed.fraunces-2026-05.woff2); served with Cache-Control: public, max-age=31536000, immutable.Mobile baseline (≤ 639px). Two breakpoint bumps. Body and metadata sizes do not grow on larger viewports — legibility doesn’t get bigger because the screen does.
| Token | Family | Weight | Mobile | Tablet | Desktop | Italic |
|---|---|---|---|---|---|---|
--type-masthead | Fraunces opsz 96 | 600 ital | 30/32 | 40/42 | 56/56 | locked |
--type-display-xl | Fraunces opsz 72 | 600 | 34/38 | 48/52 | 64/64 | lead story |
--type-display | Fraunces opsz 48 | 600 | 26/30 | 36/40 | 44/46 | roman default |
--type-headline | Fraunces opsz 36 | 600 | 22/26 | 26/30 | 30/34 | lead only |
--type-subhead | Fraunces opsz 24 | 500 | 18/24 | 20/26 | 22/28 | optional |
--type-body | Crimson Pro | 400 | 17/28 | 17/28 | 18/30 | inline em |
--type-body-emphasis | Crimson Pro | 500 | 19/30 | 19/30 | 21/32 | pull-quote |
--type-metadata | JetBrains Mono | 500 | 11/16 | 11/16 | 11/16 | never |
--type-caption | Crimson Pro | 400 | 13/18 | 13/18 | 13/18 | italic default |
--type-code | JetBrains Mono | 400 | 13/20 | 13/20 | 13.5/20 | never |
--type-data-tabular | JetBrains Mono | 500 | 13/18 | 13/18 | 14/20 | never |
--type-ticker | JetBrains Mono | 600 | 12/18 | 12/18 | 12/18 | never |
--type-attribution | JetBrains Mono | 500 | 9.5/12 ALL-CAPS | 9.5/12 | 9.5/12 | never |
Italic is allowed in five places only:
<em> emphasis inside body text (Crimson Pro italic).Italic is forbidden in: UI chrome (buttons, tabs, nav, breadcrumbs, form labels, inputs, dropdowns, toasts, tooltips); metadata, byline, timestamp, attribution, eyebrow; all data surfaces (ticker, tables, prices, counters, wallet balances); code blocks; the mono family in any product context; all-caps anything.
Tabular figures with slashed zero on data surfaces. Proportional figures everywhere else.
/* Data surfaces only */
.ticker, .market-tile, .wallet, .tabular, .data {
font-variant-numeric: tabular-nums slashed-zero;
font-feature-settings: "tnum" 1, "zero" 1;
}
/* Body, headlines, captions: proportional (default) */
Lining numerals in flowing prose break the reading rhythm. font-variant-numeric is set on the data token, not inherited globally.
When the Baobab LLM renders its own speech, the type is serif. Crimson Pro italic 400 on the dark --ink substrate, color --ink-on-dark #F1ECDE.
The conversational overlay is the one dark surface in the system. Inside it: the operator’s typed input renders in JetBrains Mono (operator voice = typing, characters in a fixed pitch); system metadata (timestamps, handles, tool calls) renders in JetBrains Mono uppercase letter-spaced; the LLM’s own utterances render in Crimson Pro italic — the literary register, the broker’s memo, the considered reply.
| Element | Family | Style | Color |
|---|---|---|---|
| LLM utterance | Crimson Pro | italic 400, 16/24 | --ink-on-dark |
| Operator input | JetBrains Mono | regular 400, 14/22 | --ink-on-dark |
| System metadata | JetBrains Mono | 500, 10/14 letter-spaced 0.08em ALL-CAPS | --ink-on-dark-mute |
| Tool call / inline citation | JetBrains Mono | 500, 11/14 | --ink-on-dark-mute |
system-ui as the primary face in chrome.background-clip: text).text-shadow).SOFT > 0.The substrate is warm cream paper. Six surfaces, seven inks, fifteen accents, eight state tokens, four rules. Each accent has one job; if you cannot decide between two accents, the job decides.
| Token | Hex | Role |
|---|---|---|
--surface-paper | #FDFCF7 | Default page substrate. The cream. The brand. |
--surface-soft | #FAF6EC | Card body, table-row hover, sidebar fill. |
--surface-warm | #F6F1E6 | Section bands. Eyebrow strips. |
--surface-elevated | #FFFFFF | Reserved: modal interior, popover body, image-card mat. Never page background. |
--surface-overlay | rgba(253,252,247,0.78) | Frost scrim. Translucent paper, never translucent ink. |
--surface-ink | #1A1A1A | Dark inverted. LLM overlay only. One dark moment. |
| Token | Hex | Role |
|---|---|---|
--ink | #1A1A1A | Headlines, body emphasis. Not #000. |
--ink-soft | #3A3A3A | Body text default. |
--ink-mute | #6E6A60 | Metadata, byline, timestamp. |
--ink-faint | #9A9588 | Disabled state. Affordance for disabled only — fails AA on every surface. |
--ink-on-dark | #F1ECDE | Body on the Baobab LLM overlay. Cream-tinted, not pure white. |
--ink-on-dark-mute | #C9C2B0 | Metadata on the Baobab LLM overlay. |
--ink-inverse | #FDFCF7 | Type on saturated accent fills. |
| Token | Hex | Job |
|---|---|---|
--forest | #2D5016 | Action. CTAs, links, active-tab, focus rings. |
--forest-deep | #1F3A0F | Hover/pressed forest. |
--bark | #6B4423 | Identity. Wordmark, masthead, the color that says “this is Baobab.” |
--bark-deep | #4A2E16 | Deep bark headings; the hex behind every warm-tinted shadow alpha. |
--bark-soft | #C9A87C | Adinkra glyph in empty states. |
--terracotta | #B5503E | Down / alert. Deliberately not red. Red is alarm; terracotta is signal. |
--gold | #C9A24F | Up / earned / winning. Price up, audit-tick, adinkra on dark. |
--sage | #8FA68E | Ambient. Neutral metadata pills, peace-state indicators, selection background. |
rgba(74, 46, 22, α) — bark at low alpha. Pure-black shadows on cream produce muddy gray halos.--ink #1A1A1A.--surface-elevated #FFFFFF is for modal interiors only.| Foreground | Background | Ratio | Level |
|---|---|---|---|
--ink | --surface-paper | ~16.1 | AAA |
--ink-soft | --surface-paper | ~11.3 | AAA |
--ink-mute | --surface-paper | ~5.0 | AA |
--forest | --surface-paper | ~9.0 | AAA |
--bark | --surface-paper | ~6.4 | AA |
--terracotta | --surface-paper | ~4.5 | AA ≥14px |
--ink-faint | --surface-paper | ~2.6 | Below AA — disabled affordance only |
--gold | --surface-paper | ~2.2 | Below AA — never on type |
--shadow-1: 0 1px 2px rgba(74,46,22,.04), 0 2px 8px rgba(74,46,22,.04); --shadow-2: 0 4px 14px rgba(74,46,22,.10), 0 2px 4px rgba(74,46,22,.05); --shadow-3: 0 18px 48px rgba(74,46,22,.16), 0 6px 12px rgba(74,46,22,.08); --shadow-3-dark: 0 18px 48px rgba(0,0,0,.55), 0 6px 12px rgba(0,0,0,.30);
The canon’s banking move: 1px --rule hairline preferred to shadow at rest in 80% of cases. Shadow wins only when an element is literally lifting off the page (hover, focus, drawer-in-transit), floating over cream (popovers), or seating itself on white (modal interiors).
| Breakpoint | Range | Columns | Gutter | Gap |
|---|---|---|---|---|
| mobile | ≤639px | 1 | 16px | --space-5 (20px) |
| tablet | 640–1023px | 2 | 24px | --space-7 (32px) |
| desktop | ≥1024px | 3 | 24px | --space-7 (32px) |
Container max-width: 1080px. Centered. Three surfaces and three only break the container for full-bleed: the kente masthead, the hero block on landing, the ticker frame.
| Token | px | Canonical use |
|---|---|---|
--space-0 | 0 | reset |
--space-1 | 4 | tight inline; chip flex-gap |
--space-2 | 8 | pill internal padding |
--space-3 | 12 | button vertical; desktop tab padding |
--space-4 | 16 | card internal padding mobile; mobile gutter |
--space-5 | 20 | sibling stack default; mobile grid gap |
--space-6 | 24 | section internal padding; desktop gutter |
--space-7 | 32 | desktop grid gap; distinct content blocks |
--space-8 | 40 | section margin only. Never sibling stack. |
--space-9 | 56 | generous section break |
--space-10 | 80 | hero / page-top breathing |
Read · Trade · Talk · Wallet. Locked. Atlas is a substrate, not a tab — appears inside Read (story-clusters), inside Trade (dealer-flow, corridors), inside Wallet (Sankey).
--type-attribution.--space-3 vertical padding, --space-6 inter-tab gap, 2px --forest-deep bottom border on the active tab.| Row | Component | Desktop | Mobile |
|---|---|---|---|
| 1 | Kente hairline gradient (4–6px) | full-bleed | full-bleed |
| 2 | Wordmark left + meta + lang + sign-in + B monogram upper-right | 56px | 48px |
| 3 | Ticker frame | 40px | 36px |
| 4 | Tabs (Read · Trade · Talk · Wallet) | 48px | hidden (bottom-nav serves) |
| 5 | Main content | — | — |
Every actionable element has a minimum 44×44px tap target. Hard rule. touch-action: manipulation on every tap surface (cards, chips, tabs, pills, menu rows, buttons, links). This removes the 300ms tap delay and disables double-tap-to-zoom.
--ease-in: cubic-bezier(0.32, 0.72, 0.2, 1); /* every enter */ --ease-out: cubic-bezier(0.4, 0, 0.6, 1); /* every exit */ --dur-in: 240ms; /* overlay enter, drawer enter */ --dur-out: 180ms; /* overlay exit, drawer exit */ --dur-cross: 160ms; /* content swap inside same surface */
Two easings, three durations. No custom cubic-beziers outside this pair. No ease-in-out. No springs, no bouncing, no overshoot. Baobab is paper, not gummy. Hover transitions are 120ms; press states are 60ms scale(0.97).
| Window | Direction | Desktop width | Mobile |
|---|---|---|---|
| Article reader | right | 720px | bottom-sheet |
| Room overlay | bottom | 720px | bottom-sheet |
| Account drawer | top-right | 360px | bottom-sheet |
| Ask palette | center fade-up | 640px | bottom-sheet |
| Atlas focus | right | 1080px | full-screen |
| Audio mini-player | bottom-pinned, persistent | 1080px | full-width 64px |
Backdrop: cream-paper frost (rgba(253,252,247,0.78) + blur(8px) saturate(140%)). Never a black scrim. Mobile uses solid cream at 0.92 instead of blur.
Stacking rule: replace, not stack. Three-deep is rejected. The audio mini-player is the one exception — it survives navigation across destinations.
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Surfaces remain functional. The audio mini-player still pins; it just does not slide. Color flashes on price ticks remain (200ms is not motion in the sense reduced-motion targets — the operator still needs to see the price moved).
Single SVG sprite. 16px in compact rows; 20px in default chrome; 24px in section openers. Regular weight only — not Thin, not Bold, not Light. Single-color always: --ink-soft at rest, --forest on hover and active, --ink-on-dark on dark substrates, --ink-faint for disabled. Never multi-color. Never gradient.
Phosphor lives at: search, close, settings, menu, expand, collapse, chevrons, sort arrows, kebab, hamburger, share, bookmark, upload, download, eye, copy, edit, trash, plus, minus, check, x, alert-triangle, info-circle, calendar, clock, link, paperclip.
12px (ticker provenance), 14px (eyebrow co-marks), 24–32px (avatar discs, station glyphs in Tune, ticker tile marks), 64px (empty states). Single-color, 1px stroke on cream. Default --bark; --forest on nav active; --gold on dark substrates. Single SVG sprite, 25–30 glyphs maximum.
Adinkra are named, sourced, and used as identity-bearing marks — never as decorative African pattern.
Every adinkra used in the system appears in the canon appendix table with: Twi name, one-line meaning, source citation (museum / archive / scholarly), and the Baobab surface it lives on. No mock adinkra. No flattening to pattern. No religious / funerary glyphs in commercial-transaction surfaces. The kente hairline carries any decorative-band role; adinkra carry meaning roles.
| Surface | Before (off-canon) | After (canon) |
|---|---|---|
| Splash CTA | Get Early Access! | Sign in |
| Empty wallet | No transactions yet 😢 Make your first move! | No transactions yet. Your first deposit lands here. |
| Markets provenance | Trusted Source ✓ | Source: COCOBOD daily · attribution audit ok |
| News empty | Discover the latest from across Africa! | Pan-African channel. Today’s wires below. |
| Upload toast | Awesome! Your file is uploading! | Uploading. You can keep working. |
| Send confirm | You’re all set! Funds on their way! | Sent. Settling in two to three minutes. |
| Fill row | Congrats on your fill! 🎉 | Filled. 0.5 MT sesame · Abuja · settled. |
| Property | Value |
|---|---|
| Max widths | 760px article reader; 380px grid cell; 220px compact row. |
| Aspect ratios | 4:5 portrait; 16:9 landscape; 1:1 square in three-up grids only. |
| Border-radius | 4px. Never circular. |
| Ground | 1px --rule border on every photo. No drop shadow. |
| Color treatment | None. No filter, no vignette, no duotone, no preset. |
| Caption type | JetBrains Mono 12/16, --ink-mute, letter-spaced 0.04em. |
| Attribution | Required. PHOTO · {source} in mono ALL-CAPS 0.06em, --space-2 below image. |
Treatment 1 — warm-tinted paper grain at 3% opacity over --surface-paper. SVG noise, biased toward bark, fixed-attachment. Sensed-not-seen at all zoom levels. Disabled under prefers-contrast: more.
Treatment 2 — kente hairline at the masthead top. Exactly one 4–6px band, full-bleed, gradient gold→forest→gold→bark→gold. The only kente in the system. Never repeated. Never on cards. Never on borders elsewhere.
What marks a bad Baobab implementation. Each item is a canon decision, not a preference. Reviewers reject on hit.
box-shadow on a flat at-rest card with no hover state.--surface-soft).The canon’s enforcement layer. Every item is mechanizable in CI.
font-family with Inter as the primary face for body / article / reader surfaces.Arial, Helvetica, Helvetica Neue in any font stack.var(--font-head) + italic + 600.font-variant-numeric: tabular-nums slashed-zero.text-shadow declaration anywhere.background-clip: text.favicon-16.png (B alone) and favicon-32.png (full or B).background: #fff on body / html / page-section selectors.rgba(0, 0, 0, in box-shadow on cream substrates.color: red, #ff0000, crimson, firebrick anywhere.color: #000 or background: #000 on operator-facing surfaces.#6b46c1 / #8b5cf6 values.outline: none always paired with a forest box-shadow focus ring.#2D5016 → var(--forest)).linear-gradient outside three permitted sites (kente band, hero overlay, chart axis).rgba(0, *0, *0 in overlay backdrop selectors.cubic-bezier is (0.32, 0.72, 0.2, 1) or (0.4, 0, 0.6, 1).transition-duration or animation-duration > 320ms (annotated exceptions only).prefers-reduced-motion block.touch-action: manipulation.max-width: 1080px appears in the page wrapper, not duplicated inside cards.backdrop-filter uses blur(8px) saturate(140%) (or removes the filter inside a mobile media block).scale(1.x) hover on cards (only graph nodes 1.15; treemap uses inset border).bounce, spring, or elastic in any transform or animation.! in operator copy strings (outside legal, code, UGC).U+1F300–U+1FAFF) in operator chrome.[data-photo-source] attribute or .photo-attribution sibling.h1–h3 (>50% words uppercase first letter and not all proper names).lucide-react, @heroicons/*, @material-ui/icons, react-icons/*. Only Phosphor + local adinkra sprite.aria-label, alt, or button text.text-shadow in stylesheets (also in 10.1, mirrored here).!.we / our / us capped at 2 per page in marketing directories (colophon, legal, about exempt).research/canon-appendix-adinkra.json.This v1.0 entry does not supersede any prior Baobab canon (none existed). It supersedes the design memos at research/2026-05-12-redesign-*.md, which become informational. Future revisions register here.
| Version | Date | Change | Authored by |
|---|---|---|---|
| v1.0 | 2026-05-12 | Initial canon. Wordmark + B monogram, three font families, cream substrate, four destinations, motion + window pattern, voice register, photo + texture, anti-patterns, 42-point compliance checklist. | Claude session (PM) synthesizing four parallel section leads. |