Skip to content

Monorepo Design + Brand Review — 2026-06-25

Section titled “Monorepo Design + Brand Review — 2026-06-25”

Strong forward progress. The single highest-leverage finding from the prior review — mBR bypassing the OKLCH token pipeline (Critical #1) — is fully resolved: mBR now has src/brand/mbr/colors.oklch.json, tokens.css, generated themes/{base,light,dark}.css, a complete Tailwind theme config, and zero hardcoded hex values in global.css (was 30+). The rates dashboard (Phase C) is almost entirely token-driven. Several prior minor items are also fixed (Card #ececec default removed, Button stale ring: block removed).

The just-landed brand-animation SSOT refactor (342db93) is a genuine SSOT — verified below. The new Tooltip component is clean and accessible.

The remaining issues cluster around one theme: the two SvelteKit-style PWA focus pages (sites/mbr/src/pages/focus.astro, sites/sdc/src/pages/focus.astro) live outside the design system — they hardcode brand hex, and they carry a third tooltip implementation (.ft) that duplicates the canonical Tooltip.astro (.tt). One concrete latent bug: SDC injects .ft tooltip spans with no matching CSS, so the first Glossary() term added to SDC focus content will dump its definition inline, unstyled. Dark-mode tokens for mBR fail WCAG badly, but dark mode is currently unreachable (no toggle), so that is latent, not shipping.

Severity counts: Critical 0 · High 1 · Medium 5 · Low 4


[HIGH] [effort: 1h] SDC focus page injects .ft tooltip spans with no matching CSS — latent inline-text leak

Section titled “[HIGH] [effort: 1h] SDC focus page injects .ft tooltip spans with no matching CSS — latent inline-text leak”

sites/sdc/src/utils/load-focus-content.ts:68-72 runs injectGlossaryTooltips() and emits <span class="ft" tabindex="0">{term}<span class="ft-tip" role="tooltip">{def}</span></span>. But sites/sdc/src/pages/focus.astro contains no .ft / .ft-tip CSS and no positioning JS (grep for .ft-tip / positionTooltip / initTooltips returns nothing — confirmed). The mBR focus page has all of it (sites/mbr/src/pages/focus.astro:212-281 CSS, :297-334 JS); SDC does not.

Consequence: an unstyled .ft-tip span has no visibility:hidden, so the definition text renders permanently inline inside the body copy. SDC focus content currently has no Glossary() terms (confirmed via 2026-06-23_Glossary-Tooltip-Syntax.md and SDC/_WorkingOn/Focus.md:31), so this is latent — but the commit message for a741aa2 claims “Same infrastructure added to SDC” and the author docs explicitly invite SDC authors to use Glossary(Term). The day someone does, the page breaks silently.

Recommendation: This is the SSOT smell behind the symptom. Don’t copy the .ft CSS into SDC. Instead, extract the .ft tooltip CSS + positioning JS into a shared partial (or better — render through the canonical Tooltip.astro .tt component, see Medium #1) so any page that imports the focus-content pipeline gets working tooltips automatically. Minimum fix: extract .ft CSS/JS to a shared focus-tooltip.css + script imported by both focus pages.


[MEDIUM] [effort: 3h] Three parallel tooltip implementations — .tt (canonical) vs .ft (duplicated in two focus pages)

Section titled “[MEDIUM] [effort: 3h] Three parallel tooltip implementations — .tt (canonical) vs .ft (duplicated in two focus pages)”

A canonical Tooltip.astro was just added (packages/components/src/ui/Tooltip.astro) with a .tt class, token-driven colors (hsl(var(--foreground)) / hsl(var(--background))), 4-way smart repositioning, and proper role="tooltip". Good component.

But the focus pages do not use it. The build-time glossary injector (sites/mbr/src/utils/load-focus-content.ts:77,226,230 and the SDC twin) emits a different .ft markup, styled by a hand-rolled .ft/.ft-tip block duplicated inline in sites/mbr/src/pages/focus.astro:212-281 (and missing entirely in SDC, see High #1). The .ft version hardcodes --brand-primary: #004425 for the bubble background and only does vertical-flip

  • horizontal-clamp, where .tt does full 4-way fit. So the repo now maintains two tooltip behaviours, two CSS blocks, and two positioning algorithms for the same UX.

Recommendation: Make Tooltip.astro (.tt) the single tooltip. Have the glossary injector emit .tt markup (or a class the component’s CSS already covers), delete the per-page .ft CSS. One tooltip, one positioning algorithm, token-driven colors that also work if focus pages ever adopt tokens.

[MEDIUM] [effort: 4h] Both focus PWA pages live entirely outside the OKLCH token system — hardcoded brand hex

Section titled “[MEDIUM] [effort: 4h] Both focus PWA pages live entirely outside the OKLCH token system — hardcoded brand hex”

sites/mbr/src/pages/focus.astro:29-30 and sites/sdc/src/pages/focus.astro:28-29 both define --brand-primary: #004425; --brand-gold: #D5B038; as raw hex, then drive the entire page off them (focus.astro:38 color:#222, :54 background:#ececec, :90 rgba(0,69,38,.7) h2 banner, :139 #fffbe6, :156 #e0a200, :233 #fff). These are standalone Astro pages that do not import @brand/mbr/tokens.css or the generated themes. This is the same opt-out problem the prior review flagged for the main mBR site (Critical #1) — now resolved for the site, but the PWA focus pages were never brought onto the pipeline.

Note #004425 is correct for both brands (SDC primary is also Treasury Emerald, per src/brand/sd/index.ts:20), so this is not a wrong-color bug — it’s a token-adherence / maintainability bug. A brand color change now requires editing these two pages by hand.

Recommendation: Import the generated theme CSS (or at least @brand/{mbr,sd}/tokens.css) into the focus pages and replace --brand-primary / --brand-gold / the ad-hoc hexes with hsl(var(--primary)), hsl(var(--muted)), etc. This also unlocks dark mode and fixes Medium #1 (tokenized tooltips) in one move.

[MEDIUM] [effort: 2h] mBR dark-mode tokens fail WCAG AA — but dark mode is unreachable (latent)

Section titled “[MEDIUM] [effort: 2h] mBR dark-mode tokens fail WCAG AA — but dark mode is unreachable (latent)”

sites/mbr/src/styles/themes/dark.css defines (measured against --background: 24 15% 13%):

  • --muted-foreground: 28 7% 36%2.42:1 (needs 4.5:1) — secondary text, captions, table notes, chip labels all use this (rates.astro:461,475,479,516,518,533,534,549,564).
  • --primary: 146 45% 24%1.95:1 against the dark bg — any color: hsl(var(--primary)) text (rate values, links, headings) would be nearly invisible.

These are generated by the OKLCH pipeline, so the anchor parameters / dark semantic mappings in src/brand/mbr/colors.oklch.json need adjusting (lift dark primary lightness, lift muted-foreground to ~55-60% L).

Why only Medium: dark mode is currently unreachabledark.css activates on [data-theme='dark'] (themes/dark.css:12) but there is no theme toggle and no prefers-color-scheme handler that sets the attribute anywhere in sites/mbr/src/ (only a favicon swaps on prefers-color-scheme, BaseLayout.astro:22). So the broken contrast does not ship today. The day a toggle is added, it ships broken. Either (a) fix the dark anchors now, or (b) explicitly remove the dark theme from mBR (as was done for TS in ce6d9dd) until it’s needed — don’t keep a broken-contrast theme one toggle away from production.

[MEDIUM] [effort: 1h] Rates dashboard debt/invest accent colors are hardcoded HSL, not tokens

Section titled “[MEDIUM] [effort: 1h] Rates dashboard debt/invest accent colors are hardcoded HSL, not tokens”

sites/mbr/src/pages/rates.astro is otherwise a model citizen (token-driven), but the debt (amber) and invest (blue) accent families are raw HSL literals, not token scale positions:

  • :473,477 amber chip hsl(46 65% 53%) / hsl(45 51% 45%)
  • :497 debt banner hsl(38 55% 38%), :501 invest banner hsl(220 60% 38%)
  • :537 debt rate hsl(38 55% 38%), :538,555,559 invest blue hsl(220 60% 42%)

These repeat across ~10 sites; a tweak to “debt amber” means editing every line. They also have no relationship to the OKLCH palette, so they won’t shift correctly in dark mode (compounding Medium #3).

Contrast (measured, on white): debt amber hsl(38 55% 38%) = 4.55:1 (passes AA normal, thin margin); invest blue hsl(220 60% 42%) = 6.97:1 (good); amber chip value hsl(45 51% 45%) = 3.07:1 — passes only as large/bold text (it is 1.4rem/700 at :476-477, so it qualifies, but it’s right at the line).

Recommendation: Add accent-debt / accent-invest (or a tertiary/quaternary) to the OKLCH palette in colors.oklch.json and reference hsl(var(--accent-debt)) etc. Single source for the two non-primary semantic accent families.

[MEDIUM] [effort: 1h] Rates banner white text on amber is at the WCAG floor (4.55:1)

Section titled “[MEDIUM] [effort: 1h] Rates banner white text on amber is at the WCAG floor (4.55:1)”

sites/mbr/src/pages/rates.astro:497-498 — debt banner background: hsl(38 55% 38%); color:#fff. Measured 4.55:1, just clearing AA for normal text but with no margin; banner text at :493-510 looks to be normal-weight section headers. Any future darkening of the amber, or use at smaller sizes, drops it below AA. The blue banner (:501-502, 7.97:1) and emerald are fine.

Recommendation: Darken the amber banner ~5-8% L (e.g. hsl(38 55% 32%)) for headroom, or bump banner text to 600 weight. Fold into the tokenization in Medium #4.


[LOW] [effort: 0.5h] Tooltip.astro uses role="group" on the trigger — non-standard; prefer aria-describedby

Section titled “[LOW] [effort: 0.5h] Tooltip.astro uses role="group" on the trigger — non-standard; prefer aria-describedby”

packages/components/src/ui/Tooltip.astro:12-17 puts role="group" + tabindex="0" on the trigger and role="tooltip" on the bubble, but the two are not linked via aria-describedby. Screen readers won’t reliably announce the tooltip as the description of the trigger. The build-time .ft injector has the same gap (load-focus-content.ts:77).

Recommendation: Give the bubble an id and the trigger aria-describedby="{id}"; drop the role="group" (a tooltip trigger is not a group). Low because the visible text is still readable and tabindex="0" makes it focusable; this is a refinement, not a blocker.

[LOW] [effort: 0.5h] Tooltip is hover/focus only — no touch/tap dismissal path

Section titled “[LOW] [effort: 0.5h] Tooltip is hover/focus only — no touch/tap dismissal path”

Both .tt (Tooltip.astro:114-119) and .ft rely on :hover / :focus-within. On touch devices a tap focuses the element (so it can open) but there is no documented tap-again-to-dismiss or tap-outside-to-close behaviour, and cursor:help is meaningless on touch. For glossary terms this is mostly acceptable (tap shows it, tap elsewhere blurs it), but worth a deliberate decision + a test on a real touch viewport.

Recommendation: Confirm tap-to-open / tap-outside-to-dismiss works on iOS Safari and Android Chrome (Playwright touch emulation), and note the supported interaction in the component docstring.

[LOW] [effort: 0.5h] Card.astro docstring still advertises #ececec as an example background

Section titled “[LOW] [effort: 0.5h] Card.astro docstring still advertises #ececec as an example background”

The hardcoded #ececec default from prior review #7 is correctly removed (component now uses hsl(var(--card)), :54). But the docstring example still reads custom color (e.g., "#ececec") (packages/components/src/ui/Card.astro:9), inviting callers to pass raw hex and re-introduce the anti-pattern.

Recommendation: Change the example to a token, e.g. hsl(var(--muted)).

[LOW] [effort: 0.5h] Button retains default + primary variant aliases (prior #9, unresolved)

Section titled “[LOW] [effort: 0.5h] Button retains default + primary variant aliases (prior #9, unresolved)”

packages/components/src/ui/Button.astro:27 still lists both 'default' | 'primary' mapping to identical styles. The stale ring: <style> block (prior #10) is fixed — only this alias remains.

Recommendation: Pick default (shadcn convention), drop primary, or document primary as a deliberate alias. Minor drift risk.


  • Brand-animation SSOT (342db93) is real. sites/mbr/src/pages/focus.astro:3 imports @monorepo/components/brand/MyBetterRates.css; the page has zero inline @keyframes / animation: for the brand text (confirmed by grep). The previously-frozen inline copy is gone. MyBetterRates.astro imports the same CSS (:69) and adds only theme-aware color overrides. One source for mbr-wm-bar, one for --mbr-wm-cycle. The intentional logo/text timing divergence (logos brief-flash at 93.75%, text 50/50) is documented in the CSS and the commit.
  • Reduced-motion is handled everywhere it matters: MyBetterRates.css:70-75, BrandLogo.astro (sd-dot-pulse guard added in 342db93), Tooltip.astro:121-125, focus.astro:279-281, global.css:442-446. Consistent prefers-reduced-motion: reduce.
  • mBR token pipeline (prior Critical #1) fully resolved: colors.oklch.json + tokens.css + generated themes + full Tailwind config; global.css hardcoded-hex count = 0.
  • Tooltip.astro repositioning (:138-159) is well-built: preferred → opposite → remaining, uses getBoundingClientRect() on the hidden bubble (correctly relies on layout being forced), GAP=6 viewport clamping. The horizontal-clamp + caret-tracking on .ft (focus.astro:323-334) is also a nice touch.
  • mbr-reverse variant (MyBetterRates.astro:88-94) cleanly handles white-on-dark-banner brand text for the inverted h2 banners — good brand consistency call.