UI Design System — Umaguide

The source of truth for Umaguide's interface. Read this before changing shared styles, adding components, or building a new page.

One identity, stated once: Umaguide is a fast, readable reference tool with a single game-flavored showcase — the homepage. Utility comes first everywhere; the "game UI" is a deliberate accent, never the default.


1. Governing principle — usability first

Every decision answers one question before any other: does this help someone find an answer faster? Decoration is welcome only after that's true.

This resolves the tension the app was stuck in. The site briefly leaned into a "gamified" chrome everywhere (glossy panels, ribbon headers, beveled buttons on ordinary content). Feedback was clear: people came for a tool and the chrome got in the way. We are not reverting to a plain wiki, and we are not keeping chrome everywhere. We commit to a single rule that makes both camps right:

One system, two registers

RegisterWhereFeels likeBuilt from
A — Utility (default)Everything except the homepage: lists, detail pages, tools, guides, the nav shellA clean, fast document / control panelVitePress --vp-c-* surfaces, plain typography, page-local section markup
B — Showcase (exception)The homepage board, and only the homepageA tasteful game-UI "portal board"The ui/ game-kit: UPanel, USectionHeader, UNavTile, glossy --uma-* chrome

If you are unsure which register a surface belongs to, it is Register A. Register B is an allow-list of one page.


2. The 10% brand-color rule

This is the most important operational rule in the document. Brand color (green) should occupy roughly 10% of any given screen. It is a spotlight, not a wash.

Spend brand color on:

  • the active/current nav item indicator
  • primary CTA buttons (one per view, usually)
  • links and focus rings
  • small status badges and counts (e.g. "142 / 312")
  • the homepage showcase chrome (Register B is the budgeted exception)

Never spend brand color on:

  • full section-header bands on content pages
  • card borders, card backgrounds, or thumbnail placeholders
  • large fills behind text
  • hover backgrounds for ordinary rows (use a neutral tint)

When a page feels "heavy" or "loud," it is almost always over budget on brand color. The fix is to demote fills to neutral surfaces and let typography and spacing carry the hierarchy.


3. Foundations

Two CSS-variable namespaces, kept strictly separate. All tokens live in custom.css.

  • --vp-c-* — VitePress core: page surfaces, text, dividers. Neutral cool-white / dark. This is the substrate for Register A and the shell.
  • --uma-* — game-UI chrome: glossy gradients, panel headers, beveled buttons. Register B and a few accents only.

Keeping the substrate neutral is what makes the 10% rule achievable. Do not pipe --uma-* greens into page backgrounds or content surfaces.

3.1 Surfaces & text (the neutral substrate)

TokenLightDarkUse
--vp-c-bg#f2f3f7#1b1b1fPage background
--vp-c-bg-soft#eef0f6#202127Filter bars, soft rows, subtle fills
--vp-c-bg-elv#ffffff#202127Elevated cards, dropdown panels
--vp-c-text-1#2b2f38rgba(255,255,245,.86)Primary text
--vp-c-text-2#5b6472rgba(235,235,245,.6)Secondary text
--vp-c-text-3#8a93a3rgba(235,235,245,.38)Muted labels, placeholders
--vp-c-divider#d6dae3rgba(82,82,89,.32)Hairlines between sections/rows
--vp-c-border#c8cdd8rgba(82,82,89,.68)Stronger outlines
--shadow-color / --shadow-color-lggreen-cast softblack softCard / popover elevation

3.2 Brand & accent

TokenLightDarkRole
--vp-c-brand-1#3f8a00#6a9e3aLinks, active text, primary accent (AA on white)
--uma-green#65ba00#6a9e3aChrome fills, focus glow, active indicators
--uma-green-light#90d300#7aba40Hover borders, badges
--uma-green-deep#3f8a00#8dd050Brand text on white (e.g. wordmark)

Secondary accents — use sparingly, with meaning, mostly inside Register B and small badges:

  • Pink --uma-pink #ff3376 — events / community / "gold"-tier highlights.
  • Blue --uma-blue #6b79e9 — database / tools.

These three (green / pink / blue) propagate through game-kit components via a color prop. On content pages, prefer green-or-neutral and reserve pink/blue for genuine category meaning, not decoration.

3.3 Semantic, rarity, skill & training colors

Domain palettes are stable and theme-aware (each has a dark + colorblind variant). Do not hard-code these hex values in components — reference the tokens.

  • Status: --color-success, --color-danger, --color-warning, --color-info
  • Rarity: --color-rarity-{ssr,sr,r}-{bg,text}
  • Skill types: --skill-type-{name} + --skill-type-{name}-bg for debuff · overtake · style · distance · recovery · special · passive · vision
  • Training stats: --training-{speed,stamina,power,guts,wit} + -bg

3.4 Themes

Six themes, set by toggling classes on <html> (managed in UmaTopNav.vue). Legacy is the default identity; the gamified green is the opt-in "Uma" theme.

Stored value key (stable)Menu labelNotes
legacy-lightLegacy Light✅ default when system = light
legacy-darkLegacy Dark✅ default when system = dark
lightUma Lightopt-in green
darkUma Darkopt-in green
cb-lightColorblind LightOkabe-Ito
cb-darkColorblind DarkOkabe-Ito
  • Default: a first-time visitor with no stored uma-theme lands in Legacy, matching prefers-color-scheme (light → legacy-light, dark → legacy-dark). The menu is ordered default-first: Legacy → Uma → Colorblind.
  • Stored keys never change — only the labels did — so every previously saved preference (light / dark / legacy-* / cb-*) still loads.
  • .dark overrides surface/text/shadow + every --uma-* chrome token. Every new surface variable must have a dark value.
  • .legacy swaps the brand to the site's original reddish-brown (#c16a5f) without touching surfaces — it layers on top of light or dark. This is the default brand.
  • .colorblind swaps to an Okabe-Ito palette (brand → blue, red↔green pairs remapped). New status/category colors must stay legible here too.

Rule: never hard-code brand hex. Go through tokens so all six themes follow.

3.5 Typography

TokenStack
--uma-font-displayInter → Noto Sans JP → Hiragino Kaku Gothic ProN → system-ui
--uma-font-roundedsame stack — bold UI labels, badges, buttons
--uma-font-bodysame stack — prose, vp-doc
  • Hierarchy comes from size and weight, not color bands. Section titles on content pages are plain <h2>/<h3>, --vp-c-text-1, optionally with a bottom hairline — never a gradient header.
  • Display weight 700 for UI; reserve 800 for the homepage showcase and the wordmark. Nav categories sit at 600 (700 when active) — see §4.
  • Body prose: 17px / 1.75 line-height (vp-doc).
  • letter-spacing: 0.01–0.02em on headers; avoid wide tracking on small UI.

3.6 Spacing, radius & elevation scale

Keep these consistent so the two registers still feel like one app.

Utility (A)Showcase (B)
Corner radius6–8px controls, 12px cards/popovers9px headers, 11px rows, 18px panels
Border1px var(--vp-c-divider)1px var(--uma-panel-border) + inset gloss
Elevationflat or 0 4px 12px var(--shadow-color) on hover--uma-panel-shadow (layered)
Gap rhythm0.25 / 0.5 / 0.75 / 1rem8 / 12 / 16px

Register A leans flat: hairlines and soft hover shadows do the work. Register B is allowed real elevation and gloss.


Files: UmaTopNav.vue (two-tier bar + mobile drawer) and ui/UNavMenu.vue (each desktop category).

The shell is Register A — it must be quiet and functional. It frames every page, so any noise here is noise everywhere.

Structure

  • Tier 1 — utility row (52px): wordmark · search · region tabs · external icons · theme menu. Mobile collapses this to wordmark · search · hamburger.
  • Tier 2 — category strip (42px, desktop only): the UNavMenu items.
  • Mobile drawer: the categories + utilities stacked, scroll-locked.

Spec (implemented)

The category strip was once a glossy green ribbon, then half-flattened into a "limbo" — two muddy greys, a white-chiclet hover, 800-weight type, no active indicator, and dead ribbon scaffolding. It is now a quiet header:

  • One coherent header surface. Both tiers share --vp-c-bg; the util row's hairline separates the two, and the strip's bottom hairline divides the whole header from the page. No second competing grey block, no glossy ribbon.
  • Quiet categories: --uma-font-display at 600 (700 when active), ~0.9rem, --vp-c-text-2 resting, --vp-c-text-1 on hover. No background swap on hover — a low-contrast --vp-c-divider underline instead of the white chiclet.
  • Clear active state: a persistent 2px brand-color bottom indicator under the current category, plus slightly stronger (700) text weight. A budgeted brand use, kept to a thin line.
  • Dropdown panels (UNavMenu): neutral--vp-c-bg-elv card, 12px radius, 1px --vp-c-divider border, pointer notch. Item hover is a neutral --vp-c-bg-soft tint with brand text, never a brand fill. The optional desc line stays --vp-c-text-3.
  • Behavior: opens on hover for pointer devices, toggles on click/tap, closes on outside-click, Escape, and route change.

The search field (SearchDropdown) is canonical Register A and a good north star for the whole shell: pill input on --vp-c-bg-soft, 1px --vp-c-divider, and brand spent only on the focus ring (box-shadow: 0 0 0 3px rgba(101,186,0,.16)). Copy this restraint.


5. Register A — Utility (content & tools)

The default language for all non-homepage pages: lists/grids, character and support-card detail, skills, guides, and every tool. The canonical references are the original, well-liked grids:

Page anatomy

  1. Heading row — plain <h2> (+ optional count / filter metadata). No colored band, no panel header.
  2. Filter / toolbar — a --vp-c-bg-soft bar, 8px radius, 1px divider border. Search box, chip toggles, segmented buttons. Active filter = brand fill on that chip only (small, budgeted).
  3. Content gridrepeat(auto-fill, minmax(…)). Items are clean cards or tiles: neutral surface, hairline or shadow, hover = subtle translateY(-4 to -8px) lift + soft shadow. No brand border-color on hover.
  4. Sections within a detail page — semantic <section> with a plain heading and, at most, a bottom hairline. Inner repeated items may stay card-like where scanning/comparison benefits; the outer wrapper is borderless.

Hard rules for Register A

  • Do not import or use UPanel, USectionHeader, or other game-kit chrome. Replace any panel wrapper with page-local <section> + heading markup.
  • Headings carry hierarchy; colored bands do not.
  • Callouts (e.g. a unique effect) use a left-border accent, not a full saturated box.
  • Stay under the 10% brand budget. Counts, active filters, links, and focus rings are where brand lives.
  • Every surface and hover has a working dark + colorblind appearance.

6. Register B — Showcase (homepage only)

File: HomeLayout.vue.

The homepage is the one place the game-UI board lives. It earns the richer treatment because it's the front door, not a working surface — and a front door is meant to draw the eye and route people into the best content. Restraint still applies (a tidy portal board, not a carnival), but here a prominent focal point is correct, not a distraction.

What we learned

  • Lead with a featured hero — people liked it. A large featured hero (banner cards / video embed with thumbnail, title, tag, and CTA) is the page's deliberate focal point. It was once demoted to a compact side-panel list — a regression — and is now restored as a showcase "Featured Content" section sitting just below the Browse row, fed by HeroContent.ts (heroItems + sidebarItem) and built from HeroSlot + HeroBanner / HeroVideo, styled to match the board (--uma-panel-* chrome + a green accent strip).
  • A hero is both showcase and utility. It's eye-candy and the fastest path to the guides most people came for — so it does not violate usability-first.
  • The focal point belongs to the homepage only. This is exactly the attention-grabbing treatment that must not spread onto content pages (Register A). Concentrating it on the front door is what keeps the rest calm.
  • Hierarchy: hero → Banner Reviews → Current Events. The hero leads; Banner Reviews is the wide primary column (the one saturated green band); Current Events is demoted into the neutral reference rail.

Structure

home-layout
├── home-bg            (fixed atmospheric academy background; light/dark)
└── content-wrapper
    ├── div-sidebar    (rail ad, only > 1640px AND landscape)
    ├── board-shell    (max-width 1300px)
    │   ├── portal-section   USectionHeader "Browse" + UNavTile grid
    │   ├── feature-section  Featured hero — USectionHeader "Featured Content"
    │   │                      + HeroSlot (HeroBanner/HeroVideo, 3 equal cards)
    │   ├── board-cols        primary + rail (~3:2), stack < 920px
    │   │   ├── board-main   HomeBannerReviews (showcase green band)
    │   │   └── board-side   Current Events (neutral) · Timers · Promo · Esports
    │   │                      · Community · Birthdays
    │   └── bottom-ad
    └── div-sidebar    (right rail ad)

The hero sits below Browse (not above) and is the page's single focal point; board-cols is a weighted primary + reference rail, not two equal columns.

Portal (nav tile) grid

ViewportColumnsGap
> 1275pxrepeat(10, 1fr) — single row, tiles compress12px
721–1275pxrepeat(5, 1fr)12px
481–720pxrepeat(5, 1fr)8px
≤ 480pxrepeat(5, 1fr)5px

justify-items: center keeps tiles centered at every width.

Register B rules

  • Game-kit chrome (UPanel, USectionHeader, UNavTile, glossy buttons) is allowed here and only here, or in widgets rendered exclusively by HomeLayout (HomeBannerReviews, UCurrentEvents, UResetTimers, UBirthdays, and the hero HeroSlot / HeroBanner / HeroVideo).
  • Keep it calm: one accent per panel via the color prop, generous spacing, no competing animations.
  • Emphasis tiers via UPanel tone: tone="showcase" (default — glossy saturated band) marks the lead/primary surfaces; tone="neutral" (neutral --vp-c-bg-elv header + a thin colored accent rule, hue still set by color) is for the reference-rail widgets that should recede. Aim for only ~1–2 saturated bands on the whole board (here: the Browse header + Banner Reviews).
  • Brand budget still applies in spirit — the board is colorful because it's the showcase, but individual panels shouldn't all shout at once.

7. Component reference

Game-kit components live in components/ui/. Each is tagged with the register it belongs to. B = homepage showcase only; A/B = usable in both; A = utility-safe.

ComponentRegisterPurpose
UPanelBGlossy header card. Homepage board boxes. Do not wrap content-page sections.
USectionHeaderBRibbon header (pennant / banner). Homepage section titles.
UNavTileBIllustrated square portal tile. Homepage Browse grid.
UBannerItemBFramed event/scout banner with status footer. Current Events.
UPromoBannerBDark promo banner with logo + CTA. Homepage side column.
UPortraitCardA/BFramed character portrait + name plate.
UCardA/BGeneral content tile (row / tile). Prefer neutral framing on content pages.
UButtonA/BBeveled glossy button (green/pink/blue/ghost). On content pages, reserve for the primary CTA; use ghost for secondary.
UBadgeA/BPill badge with white outline (green/pink/blue/gold/gray, outline).
UGradeBadgeA/BRace-grade swallowtail flag (G1 blue · G2 pink · G3 green · OP/EX orange · Listed purple).
UTabsA/BPill tab selector (v-model). Glossy track; fine on tools.
USelectA/BThemed dropdown select (v-model).
UNavMenuATop-nav category / dropdown. See §4 for target spec.

When a content page needs "a box," reach for page-local <section> markup first, then UCard/UBadge with neutral framing — not UPanel.


8. Interaction patterns

PatternImplementation
Card / tile hover (A)translateY(-4 to -8px) + soft neutral shadow. No brand border.
Row hover (A)--vp-c-bg-soft background tint, optional translateY(-1px).
Panel hover (B)translateY(-1 to -2px) + stronger --shadow-color.
Button presstranslateY(3px), bevel shadow collapses to 1px.
Focus ringbox-shadow: 0 0 0 3px rgba(101,186,0,.16) (brand glow) — the one consistent brand touch on every focusable control.
Dropdown openopacity + translateY(-4px), ~130ms.
Tab switchInstant; no transition.
Active navPersistent 2px brand bottom-indicator (§4).

Keep transitions short (110–180ms) and purposeful. Animation should confirm an action, never decorate idle state.


9. Responsive breakpoints

pxChange
2048+Root font scales to 20px (proportional UI on 2K+)
1640Homepage rail ads appear (also requires landscape)
1275Homepage portal grid → repeat(5,1fr)
920Homepage board columns stack
820Shell collapses to mobile: category strip hides, hamburger drawer; --vp-nav-height → 52px
768Grid filter toolbars wrap; grids tighten
720board-shell padding reduces
640UPromoBanner hides description, shrinks logo
480Grids drop to smallest minmax; portal gap → 5px

The two-tier desktop nav exists only above 820px; below that everything is the drawer. Account for both nav heights (98px desktop / 52px mobile) when positioning sticky elements.


10. Do / Don't

Do

  • Default to Register A. Treat Register B as a one-page allow-list.
  • Spend brand color like money — ~10%, on active states, CTAs, links, focus.
  • Let size, weight, spacing, and hairlines build hierarchy.
  • Give every new color a dark + colorblind value, via tokens.
  • Make the primary action obvious; make everything else quiet.
  • Lead the homepage with a prominent featured hero — that focal-point energy belongs there, and only there.

Don't

  • Wrap content-page sections in UPanel or any glossy header band.
  • Tint page/card backgrounds or hover rows with brand color.
  • Use 800-weight or wide tracking on utility text.
  • Let a homepage-style hero or focal banner leak onto content / tool pages.
  • Solve a structural problem (panel chrome) with a global CSS override — fix it in the consuming component.

11. Migration status

This document describes the shipped state. The "chrome-everywhere" rework has been walked back to usability-first across all five plan phases; the execution log is UIUnificationAndOptimizationPlan.md (and the earlier structural tracker, UIFeedbackRework.md).

Closed seams:

  • Homepage featured hero — restored below the Browse row as a showcase "Featured Content" section (3 equal cards from heroItems/sidebarItem), with the hierarchy hero → Banner Reviews → demoted Current Events.
  • Nav strip — implemented the §4 spec: one unified header surface, quiet 600-weight categories, low-contrast hover underline + 2px brand active indicator, and the dead ::before gloss + --uma-nav-strip-* indirection removed.
  • UPanel on content pages — game chrome is now homepage-only; UPanel / USectionHeader no longer appear on detail/guide pages.
  • Vestigial reddish-brown shadows in CharacterGrid--shadow-color / --shadow-color-lg tokens (they now follow the active theme).
  • Theme default — Legacy is now the first-time default (matching system light/dark); menu reads Legacy → Uma → Colorblind; stored keys unchanged.
  • Component galleryui-preview.md labels each component with its register (§7).

Remaining (out of the plan's named scope, optional sweeps):

  • Hard-coded rgba(193,106,95,…) still in RosterViewer, SkillList, SearchPage / SearchDropdown, UnifiedTopBar (the plan tokenized only the reference grids).
  • Phase 3 refinements: featured guide-card = badge not accent border; unique- effect callouts → left-border accent.

Last updated: 2026-06-14.