# Mana Loop — UI Redesign Task You are a senior Next.js/React developer and UI/UX designer working on the Mana Loop game at `/home/user/repos/Mana-Loop`. --- ## Step 1 — Orient yourself Before touching any file: 1. Read `docs/AGENTS.md` for the architecture overview and coding conventions. 2. Run `bun run lint` and note any pre-existing errors (do not fix them now). 3. Browse `src/components/game/` to map every component to its tab/panel. 4. Read `src/app/globals.css` and every file in `src/components/ui/` to understand the current design token set (Tailwind config, CSS variables, shadcn theme). 5. Read `docs/GAME_BRIEFING.md` and `docs/skills.md` so you understand the game's thematic world before making visual decisions. Document your findings in `docs/task4/orient.md` before proceeding. --- ## Step 2 — Design System First **Before touching any component**, establish a unified design system. All subsequent work MUST reference this system — no component should introduce ad-hoc colors, spacing, or typography. Create `docs/task4/design_system.md` containing every decision below. ### 2a. Visual Identity The game is about **ancient arcane magic**, a mysterious **100-floor spire**, mana weaving, and time loops. The visual language must reflect this world. **Target aesthetic:** Dark arcane grimoire — not generic "dark mode SaaS". Think illuminated manuscript meets crystalline magic UI. Reference aesthetics: Path of Exile passive tree, Slay the Spire card UI, Hades menu screens. Do NOT produce generic purple-gradient-on-charcoal. **Guiding principles:** - Every UI region should feel like it belongs in the world (mana pools should feel liquid, spire floors should feel dangerous, research should feel scholarly). - Restraint over decoration: one strong texture/treatment per region, not everywhere at once. - The UI must stay fast and readable — this is an idle game the player watches for minutes at a time. No motion sickness-inducing animations. ### 2b. Color Tokens Define a strict set of CSS custom properties in `src/app/globals.css`. Every shade must have a semantic name — never use raw hex in components. Required token groups (design the specific values yourself): ``` /* Backgrounds — at least 3 depth levels */ --bg-base /* outermost / page */ --bg-surface /* panels, cards */ --bg-elevated /* dropdowns, tooltips, modals */ --bg-sunken /* inset wells, progress track */ /* Borders */ --border-subtle /* barely-there separators */ --border-default /* standard card edges */ --border-focus /* interactive focus rings */ /* Text */ --text-primary --text-secondary --text-muted --text-disabled /* Mana element colors — one per mana type */ /* Must feel elemental, not random. Examples: */ --mana-fire /* ember orange-red */ --mana-water /* deep teal */ --mana-air /* silver-white */ --mana-earth /* warm ochre */ --mana-light /* gold */ --mana-dark /* deep indigo */ --mana-death /* muted violet-grey */ --mana-transfer /* cyan — the "tech mana" */ --mana-metal /* cool steel */ --mana-sand /* warm tan */ --mana-lightning/* electric yellow */ --mana-crystal /* pale ice blue */ --mana-stellar /* bright amber */ --mana-void /* deep black-purple */ /* Semantic UI colors */ --color-success --color-warning --color-danger --color-info /* Interactive */ --interactive-primary /* main CTA — Gather, Study, Climb */ --interactive-primary-hover --interactive-secondary --interactive-secondary-hover --interactive-danger --interactive-danger-hover --interactive-disabled ``` All mana element colors defined here must be used consistently everywhere that element appears (mana bars, skill icons, spell tags, floor element badges, etc.). ### 2c. Typography Define a clear typographic scale. Use a single font stack. Suggested: a fantasy-adjacent serif for headings (`Cinzel`, `IM Fell English`, or system `Georgia` as fallback) paired with a clean sans-serif for body/numbers. Both must be legible at small sizes on mobile. Required classes/variables: ``` --font-heading /* section headers */ --font-body /* all body copy */ --font-mono /* numbers, values, timers */ ``` Type scale: xs / sm / base / lg / xl / 2xl / 3xl Define line-height and letter-spacing for headings. ### 2d. Spacing & Layout - Base unit: 4px (Tailwind default — use `space-*` tokens, no magic numbers). - Card border radius: define one value and use it everywhere (`--radius`). - Panel inner padding: consistent across all tabs. - Never mix `px-3` and `px-4` in the same panel row. ### 2e. Component Primitives Design (and implement) these shared primitives in `src/components/ui/` before touching any game component. Each primitive must accept className overrides. | Primitive | Purpose | |-----------|---------| | `` | All panel/section wrappers. Accepts `variant`: default, elevated, sunken, danger | | `` | Consistent section titles with optional right-side action slot | | `` | Label + value pair. Accepts `highlight` for colored values | | `` | Progress bar skinned per mana type using `--mana-*` tokens | | `` | Pill badge for mana/element type with matching icon + color | | `` | Animated numeric display for mana, DPS, etc. | | `` | Primary game CTA. Variants: primary, secondary, danger, ghost | | `` | Standard skill entry row (name, description, cost, study button, level dots) | | `` | Consistent tooltip triggered by `?` icon | ### 2f. Animation Budget | Category | Rule | |----------|------| | Mana bar fill | CSS transition, 300ms ease-out. No spring physics. | | Progress bars (study/cast) | CSS transition, linear, match game tick rate | | Tab switch | Instant or 150ms fade-in only. No slide/bounce. | | Hover states | 100ms ease | | Number changes | Use CSS `tabular-nums`. No odometer effects. | | Idle sparkle / glow | One subtle glow pulse on the Gather button ONLY. Nowhere else. | | Spire combat | Cast bar animates smoothly with `requestAnimationFrame` or CSS only | No `framer-motion` animations for layout shifts. Framer Motion is available but should be used sparingly and only for intentional moments (e.g., floor cleared notification). --- ## Step 3 — Remove All Dev Artifacts The current UI has component name labels rendered in production (`ManaDisplay`, `SpireModeUI`, `ActionButtons`, `SkillsTab`, etc.). These must be completely removed from all rendered output before redesign begins. Search for and remove: - Any component that renders its own name as a visible label - The debug component name display toggle (or gate it strictly behind `process.env.NODE_ENV === 'development'`) - Any `[data-component]` labels visible to users --- ## Step 4 — Sub-task Breakdown Break the work into sub-tasks. Before writing any code, create: - `docs/task4/subtask_N.md` per sub-task (scope, acceptance criteria, dependencies) - `docs/task4/subtask_N_progress.md` (update as you go) - `docs/task4/todo.md` (overall tracker) The sub-tasks must follow this order of operations. Sub-tasks marked **parallel** may run simultaneously if they touch non-overlapping files. ### Sub-task 1 — Design System Implementation (MUST COMPLETE FIRST) **Sequential — all others depend on this.** - Implement all CSS custom properties in `globals.css`. - Implement all component primitives in `src/components/ui/`. - Verify primitives render correctly with a temporary test page or Storybook (if available); otherwise visually verify by inserting them into one tab. - Remove dev labels (Step 3 above). Acceptance criteria: - All `--bg-*`, `--border-*`, `--text-*`, `--mana-*`, `--color-*`, `--interactive-*` tokens defined and working. - All 9 primitives implemented and exported. - Zero component name labels visible in UI. --- ### Sub-task 2 — Global Layout & Header [parallel after Sub-task 1] **Files:** `src/app/page.tsx`, `src/app/layout.tsx`, Header component. Changes required: - **Remove the pause button** from the header. (Bug fix #5 from task3 — verify it has been done; if not, do it here.) - Header must contain: game title/logo, Day + time display, Insight counter. - On mobile (< 640px): header collapses to a compact single row. Day, time, and insight stack or abbreviate gracefully. - Tab bar redesign: - Group tabs into logical sections with subtle visual separators: - **World**: Spire, Attune - **Power**: Skills, Spells, Golems - **Gear**: Gear, Craft, Loot - **Meta**: Achieve, Lab, Stats, Grimoire, Debug - On mobile: tab bar becomes a horizontally scrollable strip with icon-only buttons (icons + tooltip on long-press). - Active tab uses a distinct indicator (not just background color change — use the `--interactive-primary` underline or glow). - Tabs should never wrap to two rows on desktop. - The two-row tab layout (main row + second row for Debug/Grimoire) is acceptable if necessary, but style them as a cohesive set, not as an afterthought. Acceptance criteria: - Header renders correctly at 375px, 768px, 1280px viewport widths. - No pause button visible. - Tab groups visually distinguishable. - Active tab clearly indicated. --- ### Sub-task 3 — Left Panel: Mana Display & Action Area [parallel after ST1] **Files:** `src/components/game/ManaDisplay.tsx`, `src/components/game/ActionButtons.tsx`, `src/components/game/CalendarDisplay.tsx`, and any related sidebar wrapper. The left panel is the player's heartbeat — they watch it constantly. It must be calm, clear, and beautiful. Changes required: **Mana Display:** - Raw mana: large, readable current / max with regen rate below. - Use `` primitive. Bar color uses `--mana-*` token (raw mana = `--interactive-primary` or a neutral "arcane" color). - Regen rate label: show current effective regen/hr including meditation multiplier. Format: `+4.1/hr (1.5× med)` — keep this, it's informative. - Elemental mana section: each unlocked element shows as a compact row (`` + mini bar + value). Locked elements are hidden entirely (not shown as greyed-out rows). - If only one element is unlocked (Transference early game), the section occupies minimal vertical space. - Collapsible elemental section is fine if space is tight on mobile. **Gather Button:** - This is the primary action — make it visually dominant and satisfying. - Full width, well-padded. Uses ``. - The single subtle glow/pulse animation lives here. - On click: brief scale press (CSS `active:scale-95`, no JS needed). **Current Activity:** - Show the active action name and a compact progress bar if applicable. - Do not show a list of all possible actions — only what's happening now. - When studying: show skill name + time remaining. - When meditating: show meditation bonus multiplier and time spent. - When climbing: hide this panel entirely (SpireModeUI takes over). - Use `` to make it feel like a status readout. **Calendar:** - Day grid must be compact and legible. Current day is highlighted. - Days past: muted. Days future: subtle. Day 20+ (incursion): tinted with `--color-danger` to signal urgency. - On mobile: show only current week row + day number badge, not full grid. **Climb the Spire button:** - Keep it prominent (orange/amber CTA as currently designed). - On mobile: ensure it doesn't overflow the panel. Acceptance criteria: - Panel fits within its container at 375px without horizontal scroll. - Elemental mana section doesn't show locked elements. - Calendar incursion days visually distinguished. - Activity display updates reactively. --- ### Sub-task 4 — Skills Tab [parallel after ST1] **Files:** `src/components/game/tabs/SkillsTab.tsx` and related. The skills tab is the most visually complex tab. Currently it looks like a generic settings page. It must feel like a research journal. Changes required: **Category sections:** - Each category (Mana, Study, Research, Enchanting, etc.) is a collapsible `` with a `` showing category name, icon, and skill count badge. - Categories collapsed by default if the player has no skills in them yet. - Smooth collapse animation (height transition). **Skill rows (use `` primitive):** - Layout: [Icon] [Name + tier badge] [short description] ... [level dots] [Study button] - Tier badge: small colored pill showing `T1`, `T2`, etc. - Level dots: current implementation is fine in concept but dots should use mana-type-colored fills, not plain purple. Match the skill's associated mana type. - Cost display: show mana cost with a `` for the mana type required, not plain text. - Study time: keep as-is (`4.0h`) — it's clear. - Study button: uses ``. Disabled state must look disabled (not just grey text — lower opacity + `cursor-not-allowed`). - If a skill has prerequisites not yet met: show a lock icon with a small tooltip explaining the requirement. Do not hide the skill entirely. **Milestone upgrade UI:** - When a milestone is available (level 5 or 10), the row gets a special indicator (glowing border or "!" badge) so the player notices. - Clicking opens a focused upgrade choice modal — not an inline expansion. Modal must show all choices clearly with their effects. **Tier-up UI:** - When a skill is at max level and tier-up is possible, the Study button changes to "Tier Up" with a distinct visual (gold outline or similar). **Mobile:** - Skills tab on mobile: category headers sticky. Level dots shrink. Study button full width below description. Acceptance criteria: - All skill categories render correctly. - Level dots match mana type colors. - Disabled state is visually obvious. - Milestone indicator visible at levels 5 and 10. - Tier-up path clearly communicated. --- ### Sub-task 5 — Spire Tab & Spire Mode UI [parallel after ST1] **Files:** `src/components/game/tabs/SpireTab.tsx`, `src/components/game/SpireModeUI.tsx` (or equivalent). The spire is the heart of the game's drama. The UI must feel tense. **SpireTab (the overview/stats view — per task3 bug #3):** - This should now be a "Spire Stats" view, not a floor-by-floor list. - Show: highest floor reached, total pacts signed, total guardians defeated, best run summary. - The `` lives here (moved from left panel if task3 did that — verify and adjust). - If task3 hasn't moved the climb button yet: leave it in the left panel and note the discrepancy in your progress file. - Style the stats as a `` with `` rows. - Guardian pacts section: list signed pacts with their element badge and multiplier value. **SpireModeUI (active combat view):** - Header: "Spire Mode" title + current floor number (large, bold) + floor element badge. - Floor HP bar: uses `` with the floor's element color. Shows `current / max HP` and DPS label. - The HP value MUST update reactively on every tick (this is bug #1 from task3 — verify the fix; if not done, it must be done here as part of layout). - "Best Floor" and pact count shown below HP bar in `` pairs. - Activity log (moved here per task3 bug #3): compact scrollable list of recent events (damage dealt, floor cleared, pact signed). Max 20 entries. Auto-scrolls to bottom. Uses `--bg-sunken` background. - Active Spells section: each spell card shows name, type badge, DPS, raw damage, cast rate, and a live cast progress bar. - The cast bar must animate smoothly from 0→100% between casts. - Spell cards use a left border colored by spell element. - Active Golems section: if empty, show a subtle empty state ("No golems summoned"), not a blank space. - Climb Down button: prominent but secondary styling (not the same as Gather). Per task3 bug #2 — must trigger floor-by-floor downward combat; verify the fix is in place. **Mobile combat view:** - Floor info, cast bar, and HP bar above the fold. - Spells and golems scrollable below. - No horizontal scroll anywhere. Acceptance criteria: - Floor HP updates every game tick visually. - Cast bar animates correctly. - Element colors match `--mana-*` tokens. - Activity log auto-scrolls. - Empty golem state shown gracefully. - No content clipped on 375px viewport. --- ### Sub-task 6 — Stats Tab [parallel after ST1] **Files:** `src/components/game/tabs/StatsTab.tsx` (or stats subdirectory). The stats tab should feel like opening a detailed character sheet. Changes required: - Group stats into sections: Mana Stats, Combat Stats, Skill Bonuses, Equipment Modifiers, Attunement Effects. - **Mana breakdown section** (new — per task3 bug #14): For each unlocked mana type, show a row with: `[ElementBadge] [Name] | Current: X | Cap: Y | Regen: +Z/hr | Modifiers: ...` Raw mana appears first, then elements in unlock order. Modifiers should list attunement conversions and any drain effects. - All label/value pairs use ``. - Multipliers highlighted in gold/amber. - Bonuses from skills listed in a "Active Skill Upgrades" sub-section as compact tags, not full rows. Acceptance criteria: - Mana breakdown section present with per-type rows. - All values reactive (update without page reload). - Clearly grouped sections. --- ### Sub-task 7 — Equipment & Crafting Tabs [parallel after ST1] **Files:** `src/components/game/tabs/EquipmentTab.tsx` (GearTab), `src/components/game/tabs/CraftingTab.tsx` and crafting subdirectory. **Equipment/Gear Tab:** - Equipment slots: visual slot layout (head, chest, hands, feet, weapon, offhand). Not a flat list. - Each slot shows: item name, enchantment count / capacity, rarity color. - 2-handed weapon rule (task3 bug #6): offhand slot overlaid with a "Occupied — 2H Weapon" badge when a 2-handed item is equipped. Slot interaction disabled. - Empty slots show a subtle dashed border with slot type label. - On mobile: slots stack vertically in two columns (weapon + offhand as a pair). **Crafting Tab:** - The three phases (Design, Prepare, Apply) are shown as a visual stepper at the top of the tab, not as separate unlabeled sections. - Design phase: filter enchantments by items the player owns (task3 bug #7). Show incompatible enchantments in a greyed-out "Unavailable" section below compatible ones, with a tooltip explaining why (e.g., "Requires a weapon"). - Prepare phase: if the target item has existing enchantments, the button reads "Prepare — removes existing enchantments". Confirm dialog before proceeding. (task3 bug #8) - Items tagged "Ready for Enchantment" get a distinct visual badge. - Apply phase: only shows items tagged "Ready for Enchantment". Acceptance criteria: - 2H weapon slot disable visible and clear. - Phase stepper renders correctly. - Prepare button label changes based on enchantment state. - "Ready for Enchantment" tag visible on item cards. --- ### Sub-task 8 — Attunements Tab [parallel after ST1] **Files:** `src/components/game/tabs/AttunementTab.tsx` (AttunmentsTab). Currently looks reasonable but needs design-system alignment. Changes required: - Each attunement card (Enchanter, Invoker, Fabricator) should be a `` with a clear locked/unlocked/active state. - The primary mana type is shown with its ``. - Raw Regen and Conversion stats use ``. - XP progress bar uses `` with the attunement's mana color. - Capabilities list: icon + label, not plain text. - Locked attunements: show unlock condition prominently — "Defeat your first guardian" should appear as an amber callout, not grey body text. - Summary row ("+0.5 raw mana/hr · 1 active attunement") styled as a `` header, not a row of green pills. - On mobile: attunement cards stack vertically. Each card is full width. Acceptance criteria: - All three cards render at all viewport sizes. - Locked state clearly communicated with unlock path. - Summary row consistent with design system. --- ### Sub-task 9 — Remaining Tabs [parallel after ST1] Apply design-system alignment to all remaining tabs without deep redesign. The goal is visual consistency, not a full rework. Tabs to align: - **Golems Tab** — golem cards with element badges, stat rows, slot count. - **Spells Tab** — spell list with element badges, DPS, mana cost. - **Loot Tab** — inventory with item rarity colors, category filter pills styled consistently. - **Achievements Tab** — achievement cards with progress bars. - **Lab Tab** — prestige/insight upgrades; upgrade cards consistent with skill rows. - **Grimoire Tab** — whatever this displays; ensure heading and content structure uses design system. - **Debug Tab** — fix crash (task3 bug #4 — verify it's done; if not, fix it here). Style minimally; this is a dev tool. For each tab: 1. Replace ad-hoc background/border colors with design tokens. 2. Replace plain text label/value pairs with ``. 3. Ensure empty states have explicit messaging. 4. Verify mobile layout doesn't overflow. Acceptance criteria: - All tabs render without crashes. - All tabs use `--bg-*`, `--border-*`, `--text-*` tokens (no raw hex). - All tabs have explicit empty states. - All tabs usable at 375px width. --- ## Step 5 — Mobile Layout Audit After all sub-tasks complete, do a dedicated mobile pass: 1. Open the game at 375px viewport (iPhone SE size — the minimum target). 2. Walk through every tab. 3. Fix any overflow, truncation, or illegible text. 4. Test touch targets — all interactive elements must be ≥ 44×44px. 5. The left panel and tab content must not require horizontal scrolling. 6. The tab bar must be reachable with one thumb (bottom placement on mobile is acceptable if it avoids stretching). Document findings in `docs/task4/mobile_audit.md`. --- ## Step 6 — Performance Check The game ticks every 200ms. UI updates must not cause jank. Rules: - Never read from the Zustand store inside a render loop without selectors. - All animated elements (mana bar, cast bar, calendar) must use CSS transitions rather than JS-driven style updates where possible. - No `useEffect` that sets state on every tick without proper memoization. - Run `bun run build` and confirm 0 TypeScript errors and 0 new ESLint errors. --- ## Step 7 — Final Audit Write `docs/task4/ui_audit_report.md` covering: - Visual inconsistencies found and resolved - UX friction points addressed - Remaining issues flagged with priority (high/medium/low) - Screenshots or descriptions of before/after for major changes --- ## Constraints & Rules 1. **No new external dependencies** unless absolutely necessary and approved. Tailwind, shadcn/ui, framer-motion, lucide-react are already available. 2. **Do not change game logic.** Only `src/components/`, `src/app/globals.css`, and documentation files are in scope. Do not modify `src/lib/game/`. 3. **TypeScript strict.** All new code must compile without `any` types. 4. **Backwards compatible.** The Zustand store interface must not change. 5. **Git hygiene.** Pull before starting. Commit after each sub-task with a clear message: `feat(ui): redesign skills tab — sub-task 4`. 6. **Parallel agents must not edit the same file concurrently.** The dependency graph in your sub-task docs must make this explicit. 7. **Accessibility baseline.** All interactive elements need proper ARIA labels. Color must not be the only differentiator for state (use icons or text labels alongside color). 8. **Banned patterns:** - Generic purple gradients as the only visual treatment - Inline `style={{}}` with hardcoded hex values - `className="bg-purple-900"` type raw Tailwind colors — use CSS vars - Visible component name debug labels - Empty `
` spacers — use `gap-*` on flex/grid parents - Multiple nested cards (card inside card inside card) - Tooltip-only affordances with no static label --- ## Deliverables Checklist - [ ] `docs/task4/orient.md` — initial codebase survey - [ ] `docs/task4/design_system.md` — all design decisions documented - [ ] `src/app/globals.css` — all CSS custom properties defined - [ ] `src/components/ui/` — all 9 primitives implemented - [ ] All dev labels removed from rendered output - [ ] Sub-task docs (1–9) with progress files - [ ] `docs/task4/todo.md` updated throughout - [ ] `docs/task4/mobile_audit.md` — mobile pass findings - [ ] `docs/task4/ui_audit_report.md` — final audit - [ ] `bun run build` passes with 0 new errors - [ ] `bun run lint` passes with 0 new errors