[nu-demo] hero_books library cards have poor light-mode text contrast — titles invisible on dark gradient backgrounds #184

Closed
opened 2026-04-25 03:24:30 +00:00 by mik-tf · 1 comment
Owner

Symptom

Hero Books "Knowledge World" homepage rendered under hero_os light mode has poor text contrast on the library cards:

  • Card titles ("Hero", "GeoMind", "Mycelium", "OurWorld") render in colors that are nearly invisible against their dark gradient backgrounds (deep blue, dark green, dark red, slate)
  • Subtitles like "1 books", "12 books", "6 books" are extremely faint
  • Selecting the text (Ctrl+A) reveals the actual content is there, just very low contrast

Affects only hero_os in light mode; in dark mode the cards' dark backgrounds are appropriate.

Root cause hypothesis

Hero Books's library card CSS likely uses fixed light-color text variables that look correct on the card's dark gradient when hero_os is in dark mode (overall light text on dark backgrounds is the design), but doesn't contrast-flip when hero_os is in light mode. The library cards keep their dark gradient backgrounds (intentional brand color) but the title text doesn't adjust.

Fix direction

The card body should always use light text since the card backgrounds are deliberately dark gradients regardless of overall theme. Two options:

  1. Hardcode card text color: in hero_books/templates/... (Askama) or hero_books_ui Dioxus, set library card titles to color: white or color: rgba(255,255,255,0.95) directly, not via theme tokens.

  2. Theme-aware: use a card-text token that's identical in light and dark modes (e.g., --hero-books-card-text: rgba(255,255,255,0.95) defined in both themes).

Option 1 is simpler and matches the design intent: the cards are always dark, so text is always light.

Where to look

  • hero_books_ui/templates/index.html (Knowledge World homepage)
  • hero_books_ui/static/css/*.css — library card classes
  • hero_archipelagos/archipelagos/embed/books/... — if the homepage is rendered by the WASM island

Demo state

Visible on herodemo.gent01.grid.tf in light mode. Functional (cards clickable, navigation works) — purely cosmetic contrast issue.

  • home#147 — Collab island has its own dark theme (similar pattern; theme tokens aren't propagating)
  • home#176 — hero_books library navbar disappears on click (different scope but same archipelago)
  • home#160 — consolidated demo state

Signed-off-by: mik-tf

## Symptom Hero Books "Knowledge World" homepage rendered under hero_os **light mode** has poor text contrast on the library cards: - Card titles ("Hero", "GeoMind", "Mycelium", "OurWorld") render in colors that are nearly invisible against their dark gradient backgrounds (deep blue, dark green, dark red, slate) - Subtitles like "1 books", "12 books", "6 books" are extremely faint - Selecting the text (Ctrl+A) reveals the actual content is there, just very low contrast Affects only hero_os in light mode; in dark mode the cards' dark backgrounds are appropriate. ## Root cause hypothesis Hero Books's library card CSS likely uses fixed light-color text variables that look correct on the card's dark gradient when hero_os is in dark mode (overall light text on dark backgrounds is the design), but doesn't contrast-flip when hero_os is in light mode. The library cards keep their dark gradient backgrounds (intentional brand color) but the title text doesn't adjust. ## Fix direction The card body should always use light text since the card backgrounds are deliberately dark gradients regardless of overall theme. Two options: 1. **Hardcode card text color**: in `hero_books/templates/...` (Askama) or `hero_books_ui` Dioxus, set library card titles to `color: white` or `color: rgba(255,255,255,0.95)` directly, not via theme tokens. 2. **Theme-aware**: use a card-text token that's identical in light and dark modes (e.g., `--hero-books-card-text: rgba(255,255,255,0.95)` defined in both themes). Option 1 is simpler and matches the design intent: the cards are always dark, so text is always light. ## Where to look - `hero_books_ui/templates/index.html` (Knowledge World homepage) - `hero_books_ui/static/css/*.css` — library card classes - `hero_archipelagos/archipelagos/embed/books/...` — if the homepage is rendered by the WASM island ## Demo state Visible on herodemo.gent01.grid.tf in light mode. Functional (cards clickable, navigation works) — purely cosmetic contrast issue. ## Related - [home#147](https://forge.ourworld.tf/lhumina_code/home/issues/147) — Collab island has its own dark theme (similar pattern; theme tokens aren't propagating) - [home#176](https://forge.ourworld.tf/lhumina_code/home/issues/176) — hero_books library navbar disappears on click (different scope but same archipelago) - [home#160](https://forge.ourworld.tf/lhumina_code/home/issues/160) — consolidated demo state Signed-off-by: mik-tf
Author
Owner

Fixed in hero_books commit 10493f5 on development.

Root cause — pinned via Hero Browser MCP CSS inspection on the live herodemo:

Bootstrap 5.3 cascades light-theme body color via [data-bs-theme="light"] .card (specificity (0,2,0)). The library cards' theme rule .lib-theme-N { color: #e8e8e8 } is only specificity (0,1,0), so Bootstrap's rule wins regardless of source order. Result: in light mode the dark body color (rgb(33, 37, 41)) cascades into all .library-card content, rendering titles invisible against the always-dark navy/red/purple gradients.

Fix — chain the selector to .library-card.lib-theme-N (now (0,2,0)) so it ties Bootstrap's specificity and wins via source order (the inline <style> loads after bootstrap.min.css):

-.lib-theme-0 {
+.library-card.lib-theme-0 {
     background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);
     color: #e8e8e8;
 }

Applied to all 6 lib-theme-N variants. Inner content (.card-body, .library-name, .library-stats) is pinned to color: inherit so children pick up the parent's gradient-aware light color regardless of theme.

Verification — live test on herodemo via Hero Browser MCP js_evaluate:

  1. Confirmed the bug visually in light mode (/tmp/books_light.png).
  2. Inspected with getComputedStyle().library-name color was rgb(33, 37, 41).
  3. Identified the overriding rule via Array.from(document.styleSheets) rule walk — [data-bs-theme="light"] .card → var(--bs-body-color).
  4. Injected the fixed CSS into the running page; computed color flipped to rgb(232, 232, 232).
  5. Re-screenshotted: titles now readable in light mode (/tmp/books_light_fixed.png).
  6. Toggled to dark mode: no regression (/tmp/books_dark_fixed.png).

Deploy: the fix lands automatically on next hero_books_ui binary rebuild — the template is embedded into the binary at build time. No infra changes needed. Will reach herodemo on the next combined deploy.

Meta-tracker: home#193.

Signed-off-by: mik-tf

Fixed in hero_books commit `10493f5` on `development`. **Root cause** — pinned via Hero Browser MCP CSS inspection on the live herodemo: Bootstrap 5.3 cascades light-theme body color via `[data-bs-theme="light"] .card` (specificity `(0,2,0)`). The library cards' theme rule `.lib-theme-N { color: #e8e8e8 }` is only specificity `(0,1,0)`, so Bootstrap's rule wins regardless of source order. Result: in light mode the dark body color (`rgb(33, 37, 41)`) cascades into all `.library-card` content, rendering titles invisible against the always-dark navy/red/purple gradients. **Fix** — chain the selector to `.library-card.lib-theme-N` (now `(0,2,0)`) so it ties Bootstrap's specificity and wins via source order (the inline `<style>` loads after `bootstrap.min.css`): ```diff -.lib-theme-0 { +.library-card.lib-theme-0 { background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460); color: #e8e8e8; } ``` Applied to all 6 lib-theme-N variants. Inner content (`.card-body`, `.library-name`, `.library-stats`) is pinned to `color: inherit` so children pick up the parent's gradient-aware light color regardless of theme. **Verification** — live test on herodemo via Hero Browser MCP `js_evaluate`: 1. Confirmed the bug visually in light mode (`/tmp/books_light.png`). 2. Inspected with `getComputedStyle()` — `.library-name` color was `rgb(33, 37, 41)`. 3. Identified the overriding rule via `Array.from(document.styleSheets)` rule walk — `[data-bs-theme="light"] .card → var(--bs-body-color)`. 4. Injected the fixed CSS into the running page; computed color flipped to `rgb(232, 232, 232)`. 5. Re-screenshotted: titles now readable in light mode (`/tmp/books_light_fixed.png`). 6. Toggled to dark mode: no regression (`/tmp/books_dark_fixed.png`). **Deploy:** the fix lands automatically on next hero_books_ui binary rebuild — the template is embedded into the binary at build time. No infra changes needed. Will reach herodemo on the next combined deploy. Meta-tracker: home#193. Signed-off-by: mik-tf
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/home#184
No description provided.