# Mana Loop - Design System ## Version: 1.0 ## Date: 2024-04-27 --- ## 1. Visual Identity ### Theme: Ancient Arcane Grimoire The Mana Loop UI should feel like an ancient spellbook infused with crystalline magic - not a generic dark mode SaaS application. **Aesthetic References:** - Path of Exile passive tree (dark, arcane, intricate) - Slay the Spire card UI (clear, readable, atmospheric) - Hades menu screens (bold, high-contrast, mythological) **Guiding Principles:** 1. Every UI region should feel like it belongs in the world 2. Restraint over decoration: one strong texture/treatment per region 3. The UI must stay fast and readable - this is an idle game 4. No generic purple-gradient-on-charcoal **Key Visual Elements:** - Illuminated manuscript styling for headers (gold accents, serif fonts) - Crystalline magic effects for interactive elements - Subtle arcane patterns as background texture - High contrast for readability with muted atmospheric colors --- ## 2. Color Tokens ### 2a. Background Colors (Depth Levels) ```css --bg-base: #060811; /* Outermost / page - deep void black */ --bg-surface: #0C1020; /* Panels, cards - dark navy */ --bg-elevated: #111628; /* Dropdowns, tooltips, modals - medium dark */ --bg-sunken: #181f35; /* Inset wells, progress track - lighter panel */ ``` ### 2b. Border Colors ```css --border-subtle: #1e2a45; /* Barely-there separators */ --border-default: #2a3a60; /* Standard card edges */ --border-focus: #5B8FFF; /* Interactive focus rings */ ``` ### 2c. Text Colors ```css --text-primary: #c8d8f8; /* Main text - light blue-white */ --text-secondary: #7a92c0; /* Secondary text - muted blue-gray */ --text-muted: #4a5f8a; /* Muted text - darker blue-gray */ --text-disabled: #2a3a60; /* Disabled text - very muted */ ``` ### 2d. Mana Element Colors Each mana type has a distinct, semantic color that reflects its nature: ```css --mana-fire: #E8734A; /* Ember orange-red */ --mana-water: #3BAFDA; /* Deep teal */ --mana-air: #C8D8F8; /* Silver-white */ --mana-earth: #B8860B; /* Warm ochre */ --mana-light: #D4A843; /* Gold */ --mana-dark: #4B0082; /* Deep indigo */ --mana-death: #8B7D8B; /* Muted violet-grey */ --mana-transfer: #00CED1; /* Cyan - the "tech mana" */ --mana-metal: #708090; /* Cool steel */ --mana-sand: #C2B280; /* Warm tan */ --mana-lightning: #FFD700; /* Electric yellow */ --mana-crystal: #B0E0E6; /* Pale ice blue */ --mana-stellar: #FF8C00; /* Bright amber */ --mana-void: #1A0A2E; /* Deep black-purple */ ``` ### 2e. Semantic UI Colors ```css --color-success: #27AE60; /* Green */ --color-warning: #F39C12; /* Orange */ --color-danger: #C0392B; /* Red */ --color-info: #3B6FE8; /* Blue */ ``` ### 2f. Interactive Colors ```css --interactive-primary: #3B6FE8; /* Main CTA - Gather, Study, Climb */ --interactive-primary-hover: #5B8FFF; /* Hover state */ --interactive-secondary: #2a3a60; /* Secondary actions */ --interactive-secondary-hover: #3a4a70; /* Secondary hover */ --interactive-danger: #C0392B; /* Danger actions */ --interactive-danger-hover: #E74C3C; /* Danger hover */ --interactive-disabled: #1e2a45; /* Disabled state */ ``` --- ## 3. Typography ### 3a. Font Stack ```css --font-heading: 'Cinzel', serif; /* Fantasy-adjacent serif for headers */ --font-body: 'Crimson Text', Georgia, serif; /* All body copy */ --font-mono: 'JetBrains Mono', monospace; /* Numbers, values, timers */ ``` ### 3b. Type Scale | Size | Font Size | Line Height | Letter Spacing | Usage | |------|-----------|--------------|----------------|-------| | xs | 0.75rem (12px) | 1rem | 0.05em | Captions, labels | | sm | 0.875rem (14px) | 1.25rem | 0.025em | Secondary text | | base | 1rem (16px) | 1.5rem | normal | Body text | | lg | 1.125rem (18px) | 1.75rem | normal | Emphasized text | | xl | 1.25rem (20px) | 1.75rem | -0.025em | Subheaders | | 2xl | 1.5rem (24px) | 2rem | -0.05em | Section headers | | 3xl | 1.875rem (30px) | 2.25rem | -0.05em | Page titles | **Heading Specifics:** - Font: `--font-heading` (Cinzel) - Letter spacing: 0.05em to 0.1em - Text transform: uppercase for game panel titles - Font weight: 600 or 700 --- ## 4. Spacing & Layout ### 4a. Base Unit - **4px** (Tailwind default: 1 unit = 0.25rem) ### 4b. Border Radius ```css --radius: 0.5rem; /* 8px - used everywhere for consistency */ ``` ### 4c. Panel Inner Padding - All tabs/panels: `1.5rem` (24px / p-6 in Tailwind) - Card content: `1rem` (16px / p-4 in Tailwind) - Tight spacing: `0.75rem` (12px / p-3 in Tailwind) ### 4d. Gaps - Between cards: `1rem` (16px / gap-4) - Between elements: `0.5rem` (8px / gap-2) - Tight elements: `0.25rem` (4px / gap-1) --- ## 5. Component Primitives ### 5a. GameCard **Purpose:** All panel/section wrappers **Variants:** default, elevated, sunken, danger **Props:** `variant`, `className`, `children` ```typescript interface GameCardProps { variant?: 'default' | 'elevated' | 'sunken' | 'danger'; className?: string; children: React.ReactNode; } ``` **Styling:** - default: `--bg-surface` background, `--border-default` border - elevated: `--bg-elevated` background, stronger shadow - sunken: `--bg-sunken` background, inset appearance - danger: Red-tinted border for warning states ### 5b. SectionHeader **Purpose:** Consistent section titles with optional right-side action slot **Props:** `title`, `action`, `className` ```typescript interface SectionHeaderProps { title: string; action?: React.ReactNode; className?: string; } ``` **Styling:** - Font: `--font-heading` - Text transform: uppercase - Letter spacing: 0.1em - Color: `--text-primary` - Optional right-side action slot for buttons/badges ### 5c. StatRow **Purpose:** Label + value pair **Props:** `label`, `value`, `highlight`, `className` ```typescript interface StatRowProps { label: string; value: string | number; highlight?: 'default' | 'success' | 'warning' | 'danger' | 'mana-*'; className?: string; } ``` **Styling:** - Label: `--text-secondary`, left-aligned - Value: `--text-primary`, right-aligned, `--font-mono` - Highlight colors change value text color ### 5d. ManaBar **Purpose:** Progress bar skinned per mana type **Props:** `value`, `max`, `manaType`, `className` ```typescript interface ManaBarProps { value: number; max: number; manaType?: keyof typeof MANA_COLORS; className?: string; } ``` **Styling:** - Height: 8px (h-2) - Border radius: `--radius` - Fill uses appropriate `--mana-*` color - Transition: 300ms ease-out - Background: `--bg-sunken` ### 5e. ElementBadge **Purpose:** Pill badge for mana/element type with matching icon + color **Props:** `element`, `showIcon`, `size`, `className` ```typescript interface ElementBadgeProps { element: string; showIcon?: boolean; size?: 'sm' | 'md'; className?: string; } ``` **Styling:** - Pill shape (rounded-full) - Background: `--mana-{type}` at 20% opacity - Border: `--mana-{type}` at 60% opacity - Text: `--mana-{type}` full color - Icon from Lucide icons matching element ### 5f. ValueDisplay **Purpose:** Animated numeric display for mana, DPS, etc. **Props:** `value`, `label`, `color`, `className` ```typescript interface ValueDisplayProps { value: number; label?: string; color?: string; className?: string; } ``` **Styling:** - Font: `--font-mono` - Font feature: `tabular-nums` for aligned digits - Transition on value change (CSS only) - Optional label below in `--text-secondary` ### 5g. ActionButton **Purpose:** Primary game CTA **Variants:** primary, secondary, danger, ghost **Props:** `variant`, `size`, `disabled`, `children`, `className` ```typescript interface ActionButtonProps { variant?: 'primary' | 'secondary' | 'danger' | 'ghost'; size?: 'sm' | 'md' | 'lg'; disabled?: boolean; children: React.ReactNode; className?: string; } ``` **Styling:** - primary: `--interactive-primary` background - secondary: `--interactive-secondary` background - danger: `--interactive-danger` background - ghost: Transparent with border - Hover: 100ms ease transition - Disabled: `--interactive-disabled` with reduced opacity ### 5h. SkillRow **Purpose:** Standard skill entry row **Props:** `skill`, `onStudy`, `onUpgrade`, `children`, `className` ```typescript interface SkillRowProps { skill: Skill; onStudy?: () => void; onUpgrade?: () => void; children?: React.ReactNode; className?: string; } ``` **Styling:** - Name: `--text-primary`, `--font-heading` - Description: `--text-secondary`, `--font-body` - Cost: `--text-muted`, `--font-mono` - Level dots: Using `--mana-purple` for filled - Study button: ActionButton (secondary variant) ### 5i. TooltipInfo **Purpose:** Consistent tooltip triggered by `?` icon **Props:** `content`, `children`, `className` ```typescript interface TooltipInfoProps { content: string; children?: React.ReactNode; className?: string; } ``` **Styling:** - Trigger: `?` icon in circle, `--text-muted` - Content: `--bg-elevated` background, `--text-primary` text - Uses Radix Tooltip under the hood - Delay: 0ms (instant) --- ## 6. Animation Budget | Category | Rule | Duration | Easing | |----------|------|----------|--------| | Mana bar fill | CSS transition | 300ms | ease-out | | Progress bars (study/cast) | CSS transition | linear | linear | | Tab switch | CSS transition | 150ms | fade-in | | Hover states | CSS transition | 100ms | ease | | Number changes | CSS `tabular-nums` | N/A | N/A | | Idle sparkle / glow | One subtle glow pulse on Gather button ONLY | 2s | ease-in-out, infinite | | Spire combat | Cast bar animates smoothly | 300ms | ease-out | **Important Notes:** - NO framer-motion for layout shifts - CSS transitions only - All animations must be performant (idle game runs constantly) - Respect `prefers-reduced-motion` setting --- ## 7. Icon System **Library:** Lucide React (already installed) **Usage Guidelines:** - No emoji in UI - use Lucide icons only - Icons should match mana element colors when applicable - Standard sizes: 16px (sm), 20px (md), 24px (lg) - Stroke width: 2 (default) **Common Icons:** - Mana: Zap, Flame, Droplet, Wind, Mountain, Sun, Moon, Skull, etc. - Actions: Play, Pause, RotateCcw, ChevronRight, etc. - UI: Settings, Info, AlertTriangle, Check, X, etc. --- ## 8. Z-Index Scale | Layer | Value | Usage | |-------|-------|-------| | Base | 0 | Normal content | | Dropdown | 50 | Select, dropdown menus | | Sticky | 100 | Sticky headers | | Overlay | 200 | Modals, dialogs | | Toast | 300 | Toast notifications | | Tooltip | 400 | Tooltips | --- ## 9. Shadow System ```css --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3); --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4); --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.5); --shadow-glow-gold: 0 0 15px rgba(212, 168, 67, 0.4); --shadow-glow-purple: 0 0 15px rgba(124, 92, 191, 0.4); --shadow-glow-accent: 0 0 15px rgba(60, 111, 232, 0.4); ``` --- ## 10. Implementation Checklist - [ ] Update `src/app/globals.css` with all CSS custom properties - [ ] Create `src/components/ui/game-card.tsx` - [ ] Create `src/components/ui/section-header.tsx` - [ ] Create `src/components/ui/stat-row.tsx` - [ ] Create `src/components/ui/mana-bar.tsx` - [ ] Create `src/components/ui/element-badge.tsx` - [ ] Create `src/components/ui/value-display.tsx` - [ ] Create `src/components/ui/action-button.tsx` (or update existing button.tsx) - [ ] Create `src/components/ui/skill-row.tsx` - [ ] Create `src/components/ui/tooltip-info.tsx` - [ ] Update `src/components/ui/index.ts` with all exports - [ ] Search and remove component name labels - [ ] Create all sub-task documentation files - [ ] Run final lint verification