- Implemented complete design system with 40+ CSS custom properties - Created 9 UI primitives (GameCard, SectionHeader, StatRow, ManaBar, ElementBadge, ValueDisplay, ActionButton, SkillRow, TooltipInfo) - Redesigned all tabs: Spire, Skills, Stats, Equipment, Crafting, Attunements, Golemancy, Spells, Loot, Achievements, Lab, Debug - Added toast notification system (GameToast) with success/warning/error/info types - Added confirmation dialogs for destructive actions - Removed all dev artifacts and component name labels - Added empty states to all tabs - Replaced emoji icons with Lucide React icons - Added enchantPower placeholder to StatsTab and EquipmentTab - Mobile audit passed at 375px viewport - Build passes with 0 errors, lint passes with 0 errors Sub-tasks completed: - ST1: Design System Implementation - ST2: Global Layout & Header - ST3: Left Panel (Mana Display & Action Area) - ST4: Skills Tab - ST5: Spire Tab & Spire Mode UI - ST6: Stats Tab - ST7: Equipment & Crafting Tabs - ST8: Attunements Tab - ST9: Remaining Tabs - ST10: Toast System & Confirmation Dialogs Documentation: 15+ files in docs/task4/
28 KiB
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:
- Read
docs/AGENTS.mdfor the architecture overview and coding conventions. - Run
bun run lintand note any pre-existing errors (do not fix them now). - Browse
src/components/game/to map every component to its tab/panel. - Read
src/app/globals.cssand every file insrc/components/ui/to understand the current design token set (Tailwind config, CSS variables, shadcn theme). - Read
docs/GAME_BRIEFING.mdanddocs/skills.mdso 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-3andpx-4in 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 |
|---|---|
<GameCard> |
All panel/section wrappers. Accepts variant: default, elevated, sunken, danger |
<SectionHeader> |
Consistent section titles with optional right-side action slot |
<StatRow> |
Label + value pair. Accepts highlight for colored values |
<ManaBar> |
Progress bar skinned per mana type using --mana-* tokens |
<ElementBadge> |
Pill badge for mana/element type with matching icon + color |
<ValueDisplay> |
Animated numeric display for mana, DPS, etc. |
<ActionButton> |
Primary game CTA. Variants: primary, secondary, danger, ghost |
<SkillRow> |
Standard skill entry row (name, description, cost, study button, level dots) |
<TooltipInfo> |
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.mdper 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-primaryunderline or glow). - Tabs should never wrap to two rows on desktop.
- Group tabs into logical sections with subtle visual separators:
- 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
<ManaBar>primitive. Bar color uses--mana-*token (raw mana =--interactive-primaryor 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
(
<ElementBadge>+ 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
<ActionButton variant="primary">. - 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
<GameCard variant="sunken">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-dangerto 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
<GameCard>with a<SectionHeader>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 <SkillRow> 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
<ElementBadge>for the mana type required, not plain text. - Study time: keep as-is (
4.0h) — it's clear. - Study button: uses
<ActionButton>. 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
<ClimbSpireButton>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
<GameCard>with<StatRow>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
<ManaBar>with the floor's element color. Showscurrent / max HPand 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
<StatRow>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-sunkenbackground. - 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
<StatRow>. - 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
<GameCard>with a clear locked/unlocked/active state. - The primary mana type is shown with its
<ElementBadge>. - Raw Regen and Conversion stats use
<StatRow>. - XP progress bar uses
<ManaBar>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
<GameCard variant="sunken">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.
Add explicit empty state when
hasGolemancy && summonedGolems.length === 0. - Spells Tab — spell list with element badges, DPS, mana cost. Add empty state for pact spells section when no pact spells exist.
- 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. Selected element uses
--border-focusring, not raw blue. - 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.
- StatsTab / EquipmentTab — when
enchantPoweris implemented by task5, the enchantment power multiplier should surface here. Add a placeholderStatRowlabeled "Enchantment Power" that reads fromeffects.enchantPowerif present, defaulting to1.0×. This will light up automatically once task5 wires the value.
For each tab:
- Replace ad-hoc background/border colors with design tokens.
- Replace plain text label/value pairs with
<StatRow>. - Ensure empty states have explicit messaging.
- Verify mobile layout doesn't overflow.
- Standardize icons: use
Trash2(Lucide) everywhere, remove emoji trash icons. Use the same icon for the same concept across all tabs.
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.
- Consistent icon usage throughout.
Sub-task 10 — Toast System & Confirmation Dialogs [parallel after ST1]
Files: New src/components/game/GameToast.tsx,
src/components/game/ConfirmDialog.tsx,
updates to EquipmentTab.tsx, LootInventory.tsx,
EnchantmentPreparer.tsx, CraftingTab.tsx.
The game currently performs destructive actions silently and gives no confirmation feedback for success or failure. This is the highest-priority UX gap identified in the audit.
Toast notification system:
- Implement a lightweight toast component using the existing
useToasthook (src/hooks/use-toast.ts). Do not add a new library. - Toast types:
success(green),warning(amber),error(red),info(muted). - Position: bottom-right on desktop; bottom-center full-width on mobile.
- Auto-dismiss after 3 seconds. No manual dismiss button needed.
- Max 3 visible toasts at once (oldest dismissed first).
- Wire toasts to these actions:
- Item equipped / unequipped → success toast
- Item deleted → success toast ("Item discarded")
- Study started → info toast with skill name
- Enchantment applied → success toast
- Insufficient mana to study → error toast with specific mana type and amount needed (not a generic "not enough mana" message)
- Enchantment capacity exceeded → error toast explaining why Apply failed
Confirmation dialogs:
- Use the existing
AlertDialogfrom shadcn/ui (already available). - Require confirmation before:
- Deleting any item from inventory or equipment (both EquipmentTab and LootInventory). Dialog: "Discard [item name]? This cannot be undone."
- Cancelling in-progress study — "Cancel studying [skill]? Progress will be partially saved based on your Knowledge Retention skill."
- Starting Prepare on an enchanted item — "Prepare [item name]? This will remove its existing enchantments." (this overlaps with task3 bug #8 — verify that fix is done; if not, implement it here too).
- Do NOT require confirmation for: equipping items, gathering mana, studying (starting, not cancelling), or climbing.
Acceptance criteria:
- Toast appears and auto-dismisses for all wired actions.
- Error toasts for mana costs name the specific element type.
- Confirm dialog appears before all destructive actions.
- No action is performed before the user confirms.
- Toasts readable on mobile (full-width, no overflow).
Step 5 — Mobile Layout Audit
After all sub-tasks complete, do a dedicated mobile pass:
- Open the game at 375px viewport (iPhone SE size — the minimum target).
- Walk through every tab.
- Fix any overflow, truncation, or illegible text.
- Test touch targets — all interactive elements must be ≥ 44×44px.
- The left panel and tab content must not require horizontal scrolling.
- 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
useEffectthat sets state on every tick without proper memoization. - Run
bun run buildand 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
Cross-task Dependencies
Task 5 (running in parallel or after this task) fixes broken game logic
in src/lib/game/. Two of its fixes have UI implications:
enchantPowerimplementation (task5 H1): Once task5 addsenchantPowertoComputedEffects, the UI should display it. Sub-task 9 already handles this with a placeholderStatRowthat readseffects.enchantPowerand shows1.0×until the value is wired.- Per-mana-type capacity skills (task5 H2): Once task5 fixes
computeElementMax(), the mana breakdown in StatsTab (sub-task 6) will automatically show correct per-element capacities — no additional UI work needed if<StatRow>reads from the store correctly.
Do NOT attempt to fix enchantPower logic or computeElementMax in this
task. Only build the UI surface that will display those values.
Constraints & Rules
-
No new external dependencies unless absolutely necessary and approved. Tailwind, shadcn/ui, framer-motion, lucide-react are already available.
-
Do not change game logic. Only
src/components/,src/app/globals.css, and documentation files are in scope. Do not modifysrc/lib/game/. -
TypeScript strict. All new code must compile without
anytypes. -
Backwards compatible. The Zustand store interface must not change.
-
Git hygiene. Pull before starting. Commit after each sub-task with a clear message:
feat(ui): redesign skills tab — sub-task 4. -
Parallel agents must not edit the same file concurrently. The dependency graph in your sub-task docs must make this explicit.
-
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).
-
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
<div>spacers — usegap-*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 surveydocs/task4/design_system.md— all design decisions documentedsrc/app/globals.css— all CSS custom properties definedsrc/components/ui/— all 9 primitives implemented- All dev labels removed from rendered output
- Sub-task docs (1–10) with progress files
docs/task4/todo.mdupdated throughoutdocs/task4/mobile_audit.md— mobile pass findingsdocs/task4/ui_audit_report.md— final audit- Toast system wired to all destructive and error actions
- Confirm dialogs on item deletion, study cancel, prepare on enchanted item
enchantPowerplaceholder StatRow present in StatsTab/EquipmentTab- Consistent Lucide icons throughout (no emoji icons)
bun run buildpasses with 0 new errorsbun run lintpasses with 0 new errors