# BaoLife Cozy Game UI Redesign Plan

**Version**: 1.0
**Date**: 2025-11-12
**Status**: Ready for Implementation
**Estimated Timeline**: 6 weeks

---

## Executive Summary

This document provides a complete, actionable plan to transform BaoLife from a functional iOS app into a warm, inviting cozy game experience. The redesign targets every visual element—colors, typography, components, animations, and layouts—to create an aesthetic inspired by Animal Crossing, Stardew Valley, and Cozy Grove.

**Key Goals:**
- Replace harsh, corporate colors with soft pastels and warm tones
- Add personality through playful animations and microinteractions
- Increase visual breathing room and comfort
- Make social features (dating, messaging) feel warm and inviting
- Maintain accessibility while enhancing aesthetics

---

## Current State Analysis

### Existing Cozy Elements ✅
- Rounded corners throughout (12pt standard)
- Seasonal background system with gradients
- Warm beige background color (#EDE0D4)
- Rounded font design (.rounded)
- Well-organized design system (AppColors, AppTypography, AppSpacing)

### Critical Issues to Fix ❌
- **Harsh iOS system blue (#007AFF)** - too corporate, dominates interface
- **Bright neon stat colors** - jarring (energy #00D084, happiness #FFCC00)
- **High contrast creates tension** - not relaxing
- **Sterile, utilitarian feel** - lacks warmth and personality
- **Generic iOS styling** - doesn't feel like a cozy game
- **Minimal warmth in social features** - dating/messaging should be inviting

---

## Phase 1: Foundation - Color & Typography System

### Timeline: Week 1
### Priority: CRITICAL - All subsequent work depends on this

### 1.1 Color System Overhaul

**File**: `lichunWebsocket/Shared/DesignSystem/AppColors.swift`

Replace all color definitions with the following cozy palette:

```swift
import SwiftUI

struct AppColors {

    // MARK: - Primary Colors (Warm & Inviting)

    /// Soft rose pink - Primary brand color (replaces harsh #007AFF blue)
    static let primary = Color(hex: 0xF4A5B5)
    static let primaryDark = Color(hex: 0xE88CA0)

    /// Soft periwinkle blue - Secondary accent
    static let secondary = Color(hex: 0xB5C9F4)
    static let secondaryDark = Color(hex: 0x8FA5D6)

    /// Warm peachy-yellow - Accent color
    static let accent = Color(hex: 0xFFD89B)
    static let accentDark = Color(hex: 0xFFCA6D)

    // MARK: - Background Hierarchy

    /// Warm cream - Main background (warmer than original beige)
    static let background = Color(hex: 0xFFF8F3)

    /// Peachy cream - Elevated surfaces (cards, modals)
    static let surfaceElevated = Color(hex: 0xFFF0E6)

    /// Subtle layering color
    static let surfaceSubtle = Color(hex: 0xFDF5EE)

    /// Modal overlay - softer than before
    static let modalOverlay = Color.black.opacity(0.4)

    // MARK: - Text Colors (Warm Browns)

    /// Primary text - warm brown (replaces white)
    static let primaryText = Color(hex: 0x5A4A3A)

    /// Secondary text - lighter warm brown
    static let secondaryText = Color(hex: 0x8B7A6A)

    /// Disabled text - warm gray
    static let disabledText = Color(hex: 0xC4B5A7)

    /// Accent text - primary for emphasis
    static let accentText = Color(hex: 0xE88CA0)

    // MARK: - Stat Colors (Soft Pastels)

    /// Energy - soft sage green (was #00D084 neon teal)
    static let energy = Color(hex: 0x9DDFAA)

    /// Money - warm butter yellow (was #4CD964 bright green)
    static let money = Color(hex: 0xFFE07A)

    /// Diamonds - soft sky blue (was #5AC8FA)
    static let diamond = Color(hex: 0xA8D5EA)

    /// Health - soft coral pink (was #FF3B30 harsh red)
    static let health = Color(hex: 0xFFB3BA)

    /// Happiness - warm sunflower (was #FFCC00 bright yellow)
    static let happiness = Color(hex: 0xFFFEA7)

    /// Intelligence - soft lavender (was #5856D6 harsh purple)
    static let intelligence = Color(hex: 0xC9B8F4)

    /// Looks - soft blush pink (was #FF2D55)
    static let looks = Color(hex: 0xFFB6C8)

    /// Prestige - warm apricot (was #FF9500)
    static let prestige = Color(hex: 0xF9D5A7)

    // MARK: - Relationship & Social Colors

    static let loveInterest = Color(hex: 0xFFB6C8)
    static let friend = Color(hex: 0xA8D5EA)
    static let family = Color(hex: 0xFFFEA7)
    static let acquaintance = Color(hex: 0xD4C5E8)

    // MARK: - Semantic Colors

    static let success = Color(hex: 0x9DDFAA)
    static let warning = Color(hex: 0xFFD89B)
    static let error = Color(hex: 0xFFB3BA)
    static let info = Color(hex: 0xA8D5EA)

    // MARK: - Dark Mode (Warm Evening Lighting)

    /// Dark mode background - warm dark brown (not pure black)
    static let backgroundDark = Color(hex: 0x2A2420)

    /// Dark mode elevated surfaces
    static let surfaceElevatedDark = Color(hex: 0x3A3230)

    /// Dark mode primary text - warm white
    static let primaryTextDark = Color(hex: 0xF5EDE6)

    /// Dark mode secondary text
    static let secondaryTextDark = Color(hex: 0xC4B5A7)

    // MARK: - Seasonal Gradients

    static func cozySeasonGradient(_ season: String) -> LinearGradient {
        switch season.lowercased() {
        case "spring":
            return LinearGradient(
                colors: [Color(hex: 0xE8F5E9), Color(hex: 0xFFE0F0)],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
        case "summer":
            return LinearGradient(
                colors: [Color(hex: 0xFFF9E6), Color(hex: 0xFFEDD4)],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
        case "autumn", "fall":
            return LinearGradient(
                colors: [Color(hex: 0xFFE5CC), Color(hex: 0xFFD4B8)],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
        case "winter":
            return LinearGradient(
                colors: [Color(hex: 0xE3F2FD), Color(hex: 0xF0F4FA)],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
        default:
            return LinearGradient(
                colors: [Color(hex: 0xFFF8F3), Color(hex: 0xFFF0E6)],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
        }
    }
}

// MARK: - Color Helper Extensions

extension Color {
    /// Initialize Color from hex integer
    init(hex: Int, opacity: Double = 1.0) {
        let red = Double((hex >> 16) & 0xFF) / 255.0
        let green = Double((hex >> 8) & 0xFF) / 255.0
        let blue = Double(hex & 0xFF) / 255.0
        self.init(.sRGB, red: red, green: green, blue: blue, opacity: opacity)
    }

    /// Lighten a color by a percentage (0.0 to 1.0)
    func lighter(by percentage: CGFloat = 0.2) -> Color {
        return self.adjust(by: abs(percentage))
    }

    /// Darken a color by a percentage (0.0 to 1.0)
    func darker(by percentage: CGFloat = 0.2) -> Color {
        return self.adjust(by: -abs(percentage))
    }

    /// Adjust color brightness
    private func adjust(by percentage: CGFloat) -> Color {
        var red: CGFloat = 0
        var green: CGFloat = 0
        var blue: CGFloat = 0
        var alpha: CGFloat = 0

        #if os(iOS)
        UIColor(self).getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        #else
        NSColor(self).getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        #endif

        return Color(
            .sRGB,
            red: min(max(red + percentage, 0), 1),
            green: min(max(green + percentage, 0), 1),
            blue: min(max(blue + percentage, 0), 1),
            opacity: alpha
        )
    }
}
```

### 1.2 Typography System Enhancement

**File**: `lichunWebsocket/Shared/DesignSystem/AppTypography.swift`

Update typography with increased sizes, tracking, and line height:

```swift
import SwiftUI

struct AppTypography {

    // MARK: - Font Styles

    /// Display title - 34pt, bold (new, for special moments)
    static let appDisplayTitle: Font = .system(size: 34, weight: .bold, design: .rounded)

    /// App title - 28pt, bold
    static let appTitle: Font = .system(size: 28, weight: .bold, design: .rounded)

    /// Title 2 - 26pt, semibold (was missing, now defined)
    static let appTitle2: Font = .system(size: 26, weight: .semibold, design: .rounded)

    /// Large title - 24pt, semibold
    static let appLargeTitle: Font = .system(size: 24, weight: .semibold, design: .rounded)

    /// Headline - 18pt, semibold (increased from 17pt)
    static let appHeadline: Font = .system(size: 18, weight: .semibold, design: .rounded)

    /// Body - 16pt, regular
    static let appBody: Font = .system(size: 16, weight: .regular, design: .rounded)

    /// Body bold - 16pt, semibold
    static let appBodyBold: Font = .system(size: 16, weight: .semibold, design: .rounded)

    /// Caption - 13pt, regular (increased from 12pt)
    static let appCaption: Font = .system(size: 13, weight: .regular, design: .rounded)

    /// Caption bold - 13pt, semibold (increased from 12pt)
    static let appCaptionBold: Font = .system(size: 13, weight: .semibold, design: .rounded)

    /// Small - 11pt, regular (increased from 10pt)
    static let appSmall: Font = .system(size: 11, weight: .regular, design: .rounded)
}

// MARK: - Text Style Extensions

extension Text {
    /// Cozy title with soft shadow
    func cozyTitle() -> some View {
        self.font(.appTitle)
            .foregroundColor(AppColors.primaryText)
            .shadow(color: AppColors.accent.opacity(0.2), radius: 8, x: 0, y: 4)
    }

    /// Stat number style with color and glow
    func statNumberStyle(color: Color) -> some View {
        self.font(.system(size: 20, weight: .bold, design: .rounded))
            .foregroundColor(color)
            .shadow(color: color.opacity(0.3), radius: 4, x: 0, y: 2)
    }

    /// Warm body text with comfortable line spacing
    func cozyBody() -> some View {
        self.font(.appBody)
            .foregroundColor(AppColors.primaryText)
            .lineSpacing(4)
    }

    /// Secondary description text
    func cozyCaption() -> some View {
        self.font(.appCaption)
            .foregroundColor(AppColors.secondaryText)
            .lineSpacing(2)
    }
}

extension View {
    /// Apply tracking (letter spacing) to text
    func tracking(_ value: CGFloat) -> some View {
        self.kerning(value)
    }

    /// Apply leading (line height multiplier)
    func leading(_ value: CGFloat) -> some View {
        self.lineSpacing(value * 4) // Approximate conversion
    }
}
```

### 1.3 Spacing System Update

**File**: `lichunWebsocket/Shared/DesignSystem/AppSpacing.swift`

Increase all spacing by ~25% for more breathing room:

```swift
import SwiftUI

struct AppSpacing {

    // MARK: - Base Spacing (Increased by ~25%)

    static let xxs: CGFloat = 2
    static let xs: CGFloat = 6      // was 4
    static let sm: CGFloat = 10     // was 8
    static let md: CGFloat = 20     // was 16
    static let lg: CGFloat = 30     // was 24
    static let xl: CGFloat = 40     // was 32
    static let xxl: CGFloat = 60    // was 48
    static let xxxl: CGFloat = 80   // new!

    // MARK: - Component Dimensions (More Generous)

    /// Standard button height
    static let buttonHeight: CGFloat = 54           // was 50

    /// Small button height
    static let smallButtonHeight: CGFloat = 40      // was 36

    /// Standard corner radius
    static let cornerRadius: CGFloat = 16           // was 12

    /// Small corner radius
    static let smallCornerRadius: CGFloat = 10      // was 8

    /// Large corner radius (new for cards)
    static let largeCornerRadius: CGFloat = 24      // was undefined (cornerRadiusLg)

    /// Pill corner radius (fully rounded)
    static let pillCornerRadius: CGFloat = 27       // new!

    // MARK: - Avatar Sizes (Slightly Larger)

    static let avatarSizeSmall: CGFloat = 44        // was 40
    static let avatarSizeMedium: CGFloat = 70       // was 60
    static let avatarSizeLarge: CGFloat = 120       // was 100
    static let avatarSizeXLarge: CGFloat = 180      // was 150

    // MARK: - Card Spacing

    /// Padding inside cards
    static let cardPadding: CGFloat = 20            // was 16

    /// Spacing between cards in lists
    static let cardSpacing: CGFloat = 16            // was 12

    /// Spacing within card content
    static let cardInnerSpacing: CGFloat = 12       // new!

    // MARK: - Icon Sizes

    static let iconSizeSmall: CGFloat = 16
    static let iconSizeMedium: CGFloat = 24
    static let iconSizeLarge: CGFloat = 32
    static let iconSizeXLarge: CGFloat = 44         // new!

    // MARK: - Shadow Constants

    struct Shadow {
        static let radiusSoft: CGFloat = 8
        static let radiusMedium: CGFloat = 12
        static let radiusLarge: CGFloat = 20
        static let offsetY: CGFloat = 4
        static let offsetYLarge: CGFloat = 10
    }
}
```

---

## Phase 2: Core Components

### Timeline: Week 2
### Priority: HIGH - Most visible changes

### 2.1 Button Components

**File**: `lichunWebsocket/Shared/Components/Buttons/PrimaryButton.swift`

Replace the existing button with a cozy, pillowy style:

```swift
import SwiftUI

struct PrimaryButton: View {
    let title: String
    let action: () -> Void
    var backgroundColor: Color = AppColors.primary
    var isDisabled: Bool = false
    var isLoading: Bool = false

    var body: some View {
        Button(action: {
            if !isDisabled && !isLoading {
                hapticFeedback(style: .medium)
                action()
            }
        }) {
            HStack(spacing: AppSpacing.sm) {
                if isLoading {
                    ProgressView()
                        .progressViewStyle(CircularProgressViewStyle(tint: .white))
                } else {
                    Text(title)
                        .font(.appHeadline)
                        .foregroundColor(.white)
                }
            }
            .frame(maxWidth: .infinity)
            .frame(height: AppSpacing.buttonHeight)
            .background(
                Group {
                    if isDisabled {
                        AppColors.disabledText
                    } else {
                        LinearGradient(
                            colors: [backgroundColor, backgroundColor.darker(by: 0.1)],
                            startPoint: .top,
                            endPoint: .bottom
                        )
                    }
                }
            )
            .cornerRadius(AppSpacing.pillCornerRadius)
            .shadow(
                color: isDisabled ? .clear : backgroundColor.opacity(0.4),
                radius: AppSpacing.Shadow.radiusSoft,
                x: 0,
                y: AppSpacing.Shadow.offsetY
            )
        }
        .buttonStyle(SquishButtonStyle())
        .disabled(isDisabled || isLoading)
    }
}

// Squish animation on press
struct SquishButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .scaleEffect(configuration.isPressed ? 0.96 : 1.0)
            .animation(.spring(response: 0.3, dampingFraction: 0.6), value: configuration.isPressed)
    }
}

#Preview {
    VStack(spacing: 20) {
        PrimaryButton(title: "Continue") {
            print("Tapped!")
        }

        PrimaryButton(
            title: "Send Message",
            backgroundColor: AppColors.accent
        ) {}

        PrimaryButton(
            title: "Disabled",
            isDisabled: true
        ) {}

        PrimaryButton(
            title: "Loading",
            isLoading: true
        ) {}
    }
    .padding()
    .background(AppColors.background)
}
```

**File**: `lichunWebsocket/Shared/Components/Buttons/SecondaryButton.swift`

Update secondary button:

```swift
import SwiftUI

struct SecondaryButton: View {
    let title: String
    let action: () -> Void
    var color: Color = AppColors.primary
    var isDisabled: Bool = false

    var body: some View {
        Button(action: {
            if !isDisabled {
                hapticFeedback(style: .light)
                action()
            }
        }) {
            Text(title)
                .font(.appHeadline)
                .foregroundColor(isDisabled ? AppColors.disabledText : color)
                .frame(maxWidth: .infinity)
                .frame(height: AppSpacing.buttonHeight - 4)
                .background(color.opacity(0.08))
                .overlay(
                    RoundedRectangle(cornerRadius: AppSpacing.pillCornerRadius - 2)
                        .strokeBorder(
                            isDisabled ? AppColors.disabledText.opacity(0.3) : color.opacity(0.4),
                            lineWidth: 2
                        )
                )
                .cornerRadius(AppSpacing.pillCornerRadius - 2)
        }
        .buttonStyle(SquishButtonStyle())
        .disabled(isDisabled)
    }
}
```

**New File**: `lichunWebsocket/Shared/Components/Buttons/CozyIconButton.swift`

Create icon button with soft background:

```swift
import SwiftUI

struct CozyIconButton: View {
    let icon: String
    var color: Color = AppColors.primary
    var size: CGFloat = 44
    let action: () -> Void

    var body: some View {
        Button(action: {
            hapticFeedback(style: .light)
            action()
        }) {
            Image(systemName: icon)
                .font(.system(size: size * 0.45, weight: .semibold))
                .foregroundColor(.white)
                .frame(width: size, height: size)
                .background(
                    Circle()
                        .fill(
                            LinearGradient(
                                colors: [color, color.darker(by: 0.1)],
                                startPoint: .topLeading,
                                endPoint: .bottomTrailing
                            )
                        )
                )
                .shadow(color: color.opacity(0.4), radius: 6, x: 0, y: 3)
        }
        .buttonStyle(SquishButtonStyle())
    }
}

#Preview {
    HStack(spacing: 20) {
        CozyIconButton(icon: "heart.fill", color: AppColors.primary) {}
        CozyIconButton(icon: "xmark", color: AppColors.error, size: 60) {}
        CozyIconButton(icon: "message.fill", color: AppColors.accent) {}
    }
    .padding()
    .background(AppColors.background)
}
```

### 2.2 Card Components

**File**: `lichunWebsocket/Shared/Components/Cards/BaseCard.swift`

Replace with layered, warm card design:

```swift
import SwiftUI

struct BaseCard<Content: View>: View {
    let content: Content
    var backgroundColor: Color = AppColors.surfaceElevated
    var borderColor: Color? = nil
    var cornerRadius: CGFloat = AppSpacing.largeCornerRadius
    var showShadow: Bool = true

    init(
        backgroundColor: Color = AppColors.surfaceElevated,
        borderColor: Color? = nil,
        cornerRadius: CGFloat = AppSpacing.largeCornerRadius,
        showShadow: Bool = true,
        @ViewBuilder content: () -> Content
    ) {
        self.backgroundColor = backgroundColor
        self.borderColor = borderColor
        self.cornerRadius = cornerRadius
        self.showShadow = showShadow
        self.content = content()
    }

    var body: some View {
        content
            .padding(AppSpacing.cardPadding)
            .background(backgroundColor)
            .cornerRadius(cornerRadius)
            .overlay(
                RoundedRectangle(cornerRadius: cornerRadius)
                    .strokeBorder(
                        borderColor ?? backgroundColor.lighter(by: 0.2),
                        lineWidth: 2
                    )
            )
            .if(showShadow) { view in
                view
                    .shadow(
                        color: Color.black.opacity(0.06),
                        radius: AppSpacing.Shadow.radiusMedium,
                        x: 0,
                        y: 6
                    )
                    .shadow(
                        color: Color.black.opacity(0.03),
                        radius: 4,
                        x: 0,
                        y: 2
                    )
            }
    }
}

// Helper extension for conditional modifiers
extension View {
    @ViewBuilder func `if`<Content: View>(_ condition: Bool, transform: (Self) -> Content) -> some View {
        if condition {
            transform(self)
        } else {
            self
        }
    }
}

#Preview {
    VStack(spacing: 20) {
        BaseCard {
            VStack(alignment: .leading, spacing: 12) {
                Text("Card Title")
                    .font(.appHeadline)
                    .foregroundColor(AppColors.primaryText)

                Text("This is a cozy card with soft shadows and warm colors.")
                    .font(.appBody)
                    .foregroundColor(AppColors.secondaryText)
            }
        }

        BaseCard(borderColor: AppColors.primary) {
            Text("Card with colored border")
                .font(.appBody)
        }
    }
    .padding()
    .background(AppColors.background)
}
```

### 2.3 Stat Display Components

**File**: `lichunWebsocket/Shared/Components/Stats/StatBar.swift`

Replace with gradient-filled progress bar:

```swift
import SwiftUI

struct CozyStatBar: View {
    let label: String?
    let value: Int
    let maxValue: Int = 100
    let color: Color
    var showPercentage: Bool = true
    var height: CGFloat = 12

    var body: some View {
        VStack(alignment: .leading, spacing: AppSpacing.sm) {
            if let label = label {
                HStack {
                    Text(label)
                        .font(.appCaption)
                        .foregroundColor(AppColors.secondaryText)
                    Spacer()
                    if showPercentage {
                        Text("\(value)")
                            .font(.system(size: 14, weight: .bold, design: .rounded))
                            .foregroundColor(color)
                    }
                }
            }

            GeometryReader { geometry in
                ZStack(alignment: .leading) {
                    // Background
                    RoundedRectangle(cornerRadius: height / 2)
                        .fill(color.opacity(0.15))
                        .frame(height: height)

                    // Foreground gradient
                    RoundedRectangle(cornerRadius: height / 2)
                        .fill(
                            LinearGradient(
                                colors: [color.lighter(by: 0.2), color],
                                startPoint: .leading,
                                endPoint: .trailing
                            )
                        )
                        .frame(
                            width: geometry.size.width * CGFloat(min(max(value, 0), maxValue)) / CGFloat(maxValue),
                            height: height
                        )
                        .shadow(color: color.opacity(0.4), radius: 4, x: 0, y: 2)

                    // Shine overlay on top half
                    RoundedRectangle(cornerRadius: height / 2)
                        .fill(
                            LinearGradient(
                                colors: [.white.opacity(0.3), .clear],
                                startPoint: .top,
                                endPoint: .bottom
                            )
                        )
                        .frame(
                            width: geometry.size.width * CGFloat(min(max(value, 0), maxValue)) / CGFloat(maxValue),
                            height: height / 2
                        )
                        .offset(y: -height / 4)
                }
            }
            .frame(height: height)
        }
    }
}

#Preview {
    VStack(spacing: 30) {
        CozyStatBar(label: "Health", value: 85, color: AppColors.health)
        CozyStatBar(label: "Happiness", value: 60, color: AppColors.happiness)
        CozyStatBar(label: "Energy", value: 30, color: AppColors.energy)
        CozyStatBar(label: nil, value: 95, color: AppColors.intelligence)
    }
    .padding()
    .background(AppColors.background)
}
```

**File**: `lichunWebsocket/Shared/Components/Stats/StatBadge.swift`

Create cozy stat badge:

```swift
import SwiftUI

struct CozyStatBadge: View {
    let icon: String
    let label: String
    let value: Int
    let color: Color

    var body: some View {
        VStack(spacing: AppSpacing.xs) {
            // Icon circle with soft background
            ZStack {
                Circle()
                    .fill(color.opacity(0.15))
                    .frame(width: 50, height: 50)

                Image(systemName: icon)
                    .font(.system(size: 20))
                    .foregroundColor(color)
            }

            // Value
            Text("\(value)")
                .font(.system(size: 16, weight: .bold, design: .rounded))
                .foregroundColor(AppColors.primaryText)

            // Label
            Text(label)
                .font(.system(size: 10, weight: .medium, design: .rounded))
                .foregroundColor(AppColors.secondaryText)
                .lineLimit(1)
        }
        .frame(maxWidth: .infinity)
    }
}

#Preview {
    HStack(spacing: 20) {
        CozyStatBadge(icon: "heart.fill", label: "Health", value: 85, color: AppColors.health)
        CozyStatBadge(icon: "brain.head.profile", label: "Intelligence", value: 72, color: AppColors.intelligence)
        CozyStatBadge(icon: "face.smiling", label: "Looks", value: 90, color: AppColors.looks)
    }
    .padding()
    .background(AppColors.background)
}
```

### 2.4 Interest Tags

**New File**: `lichunWebsocket/Shared/Components/Tags/CozyInterestTag.swift`

```swift
import SwiftUI

struct CozyInterestTag: View {
    let interest: String
    var isShared: Bool = false
    var icon: String? = nil

    var body: some View {
        HStack(spacing: 6) {
            if let icon = icon {
                Image(systemName: icon)
                    .font(.system(size: 11, weight: .semibold))
            }

            Text(interest.capitalized)
                .font(.system(size: 13, weight: .semibold, design: .rounded))
        }
        .padding(.horizontal, 12)
        .padding(.vertical, 7)
        .background(
            Group {
                if isShared {
                    LinearGradient(
                        colors: [
                            AppColors.primary.opacity(0.2),
                            AppColors.primary.opacity(0.15)
                        ],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                } else {
                    AppColors.surfaceElevated
                }
            }
        )
        .foregroundColor(isShared ? AppColors.primary : AppColors.primaryText)
        .cornerRadius(16)
        .overlay(
            RoundedRectangle(cornerRadius: 16)
                .strokeBorder(
                    isShared ? AppColors.primary.opacity(0.3) : Color.clear,
                    lineWidth: 1.5
                )
        )
        .shadow(
            color: isShared ? AppColors.primary.opacity(0.2) : Color.black.opacity(0.04),
            radius: 4,
            x: 0,
            y: 2
        )
    }
}

#Preview {
    VStack(spacing: 20) {
        HStack {
            CozyInterestTag(interest: "Reading", icon: "book.fill")
            CozyInterestTag(interest: "Gaming", icon: "gamecontroller.fill", isShared: true)
            CozyInterestTag(interest: "Cooking", icon: "fork.knife")
        }
    }
    .padding()
    .background(AppColors.background)
}
```

---

## Phase 3: Feature-Specific Redesigns

### Timeline: Week 3
### Priority: HIGH - Key user flows

### 3.1 Dating Interface

**File**: `lichunWebsocket/Views/DatingView/Components/EnhancedProfileCard.swift`

Update the profile card with cozy styling:

```swift
import SwiftUI

struct CozyDatingCard: View {
    @ObservedObject var person: Person

    var body: some View {
        VStack(spacing: 0) {
            // Avatar with gradient border and glow
            ZStack {
                // Gradient border circle
                Circle()
                    .fill(
                        LinearGradient(
                            colors: [AppColors.primary, AppColors.accent],
                            startPoint: .topLeading,
                            endPoint: .bottomTrailing
                        )
                    )
                    .frame(width: 204, height: 204)
                    .shadow(color: AppColors.primary.opacity(0.3), radius: 12, x: 0, y: 6)

                // Avatar image
                if let url = URL(string: person.image) {
                    SVGImageView(url: url, desiredSize: CGSize(width: 190, height: 190))
                        .frame(width: 190, height: 190)
                        .clipShape(Circle())
                        .overlay(
                            Circle()
                                .strokeBorder(Color.white, lineWidth: 4)
                        )
                }
            }
            .padding(.top, AppSpacing.xl)

            // Card content
            VStack(spacing: AppSpacing.md) {
                // Name and age
                VStack(spacing: AppSpacing.xs) {
                    Text("\(person.firstname), \(person.ageYears)")
                        .font(.system(size: 26, weight: .bold, design: .rounded))
                        .foregroundColor(AppColors.primaryText)

                    if !person.occupation.isEmpty {
                        Text(person.occupation)
                            .font(.appBody)
                            .foregroundColor(AppColors.accent)
                    }
                }

                // Compatibility badge with glow
                HStack(spacing: AppSpacing.sm) {
                    Image(systemName: "heart.fill")
                        .foregroundColor(AppColors.primary)
                    Text("\(person.compatibilityScore ?? 50)% Match")
                        .font(.system(size: 18, weight: .semibold, design: .rounded))
                        .foregroundColor(AppColors.primary)
                }
                .padding(.horizontal, AppSpacing.lg)
                .padding(.vertical, AppSpacing.sm)
                .background(AppColors.primary.opacity(0.12))
                .cornerRadius(20)

                // Bio
                if !person.bio.isEmpty {
                    Text(person.bio)
                        .font(.appBody)
                        .foregroundColor(AppColors.secondaryText)
                        .multilineTextAlignment(.center)
                        .lineLimit(3)
                        .lineSpacing(4)
                        .padding(.horizontal, AppSpacing.lg)
                }

                // Interest tags (max 5)
                if !person.interests.isEmpty {
                    FlowLayout(spacing: AppSpacing.sm) {
                        ForEach(Array(person.interests.prefix(5)), id: \.self) { interest in
                            CozyInterestTag(
                                interest: interest,
                                isShared: false // Check against player interests in actual implementation
                            )
                        }
                    }
                    .padding(.horizontal, AppSpacing.lg)
                }
            }
            .padding(.vertical, AppSpacing.lg)
        }
        .frame(maxWidth: .infinity)
        .background(AppColors.surfaceElevated)
        .cornerRadius(AppSpacing.largeCornerRadius)
        .overlay(
            RoundedRectangle(cornerRadius: AppSpacing.largeCornerRadius)
                .strokeBorder(
                    LinearGradient(
                        colors: [
                            Color.white.opacity(0.8),
                            Color.white.opacity(0.3)
                        ],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    ),
                    lineWidth: 2
                )
        )
        .shadow(color: Color.black.opacity(0.08), radius: 20, x: 0, y: 10)
        .shadow(color: Color.black.opacity(0.04), radius: 8, x: 0, y: 4)
    }
}

// FlowLayout helper for wrapping tags
struct FlowLayout<Content: View>: View {
    let spacing: CGFloat
    let content: () -> Content

    init(spacing: CGFloat = 8, @ViewBuilder content: @escaping () -> Content) {
        self.spacing = spacing
        self.content = content
    }

    var body: some View {
        // Simplified flow layout - use existing implementation or library
        // For now, use HStack with wrapping
        content()
    }
}
```

**File**: `lichunWebsocket/Views/DatingView/Components/SwipeButtons.swift` (create new)

Large, colorful action buttons:

```swift
import SwiftUI

struct CozySwipeButtons: View {
    let onReject: () -> Void
    let onAccept: () -> Void
    var isDisabled: Bool = false

    var body: some View {
        HStack(spacing: AppSpacing.xl) {
            // Reject button (X)
            Button(action: {
                if !isDisabled {
                    hapticFeedback(style: .medium)
                    onReject()
                }
            }) {
                Image(systemName: "xmark")
                    .font(.system(size: 28, weight: .bold))
                    .foregroundColor(.white)
                    .frame(width: 70, height: 70)
                    .background(
                        Circle()
                            .fill(
                                LinearGradient(
                                    colors: [
                                        AppColors.error,
                                        AppColors.error.darker(by: 0.1)
                                    ],
                                    startPoint: .topLeading,
                                    endPoint: .bottomTrailing
                                )
                            )
                    )
                    .shadow(color: AppColors.error.opacity(0.5), radius: 12, x: 0, y: 6)
            }
            .buttonStyle(SquishButtonStyle())
            .scaleEffect(1.1)
            .disabled(isDisabled)

            Spacer()

            // Accept button (Heart)
            Button(action: {
                if !isDisabled {
                    hapticFeedback(style: .medium)
                    onAccept()
                }
            }) {
                Image(systemName: "heart.fill")
                    .font(.system(size: 28, weight: .bold))
                    .foregroundColor(.white)
                    .frame(width: 70, height: 70)
                    .background(
                        Circle()
                            .fill(
                                LinearGradient(
                                    colors: [
                                        AppColors.primary,
                                        AppColors.primaryDark
                                    ],
                                    startPoint: .topLeading,
                                    endPoint: .bottomTrailing
                                )
                            )
                    )
                    .shadow(color: AppColors.primary.opacity(0.5), radius: 12, x: 0, y: 6)
            }
            .buttonStyle(SquishButtonStyle())
            .scaleEffect(1.1)
            .disabled(isDisabled)
        }
        .padding(.horizontal, AppSpacing.xl)
        .opacity(isDisabled ? 0.5 : 1.0)
    }
}
```

### 3.2 Messaging Interface

**File**: `lichunWebsocket/Views/MessagesView/Components/ChatBubble.swift` (create new)

Cozy chat bubbles:

```swift
import SwiftUI

struct CozyChatBubble: View {
    let message: Message
    let isPlayer: Bool

    var body: some View {
        HStack(alignment: .bottom, spacing: AppSpacing.sm) {
            if isPlayer {
                Spacer(minLength: 60)
            }

            VStack(alignment: isPlayer ? .trailing : .leading, spacing: AppSpacing.xs) {
                // Message bubble
                Text(message.text)
                    .font(.appBody)
                    .foregroundColor(isPlayer ? .white : AppColors.primaryText)
                    .padding(.horizontal, 16)
                    .padding(.vertical, 12)
                    .background(
                        Group {
                            if isPlayer {
                                LinearGradient(
                                    colors: [
                                        AppColors.primary,
                                        AppColors.primary.darker(by: 0.08)
                                    ],
                                    startPoint: .topLeading,
                                    endPoint: .bottomTrailing
                                )
                            } else {
                                Color(hex: 0xF5EDE6)
                            }
                        }
                    )
                    .cornerRadius(20)
                    .shadow(
                        color: isPlayer
                            ? AppColors.primary.opacity(0.3)
                            : Color.black.opacity(0.05),
                        radius: 6,
                        x: 0,
                        y: 3
                    )

                // Timestamp
                Text(formatTimestamp(message.timestamp))
                    .font(.system(size: 10, weight: .medium, design: .rounded))
                    .foregroundColor(AppColors.secondaryText)
                    .padding(.horizontal, AppSpacing.xs)
            }

            if !isPlayer {
                Spacer(minLength: 60)
            }
        }
    }

    private func formatTimestamp(_ timestamp: String) -> String {
        // Format timestamp logic here
        return timestamp
    }
}
```

**File**: `lichunWebsocket/Views/MessagesView/Components/MessageInput.swift` (create new)

Cozy message input:

```swift
import SwiftUI

struct CozyMessageInput: View {
    @Binding var text: String
    let onSend: () -> Void
    @FocusState private var isFocused: Bool

    var body: some View {
        HStack(spacing: AppSpacing.sm) {
            // Text input field
            TextField("Type a message...", text: $text)
                .font(.appBody)
                .padding(.horizontal, AppSpacing.md)
                .padding(.vertical, AppSpacing.sm)
                .background(Color(hex: 0xF5EDE6))
                .cornerRadius(24)
                .focused($isFocused)

            // Send button
            Button(action: {
                if !text.isEmpty {
                    hapticFeedback(style: .light)
                    onSend()
                }
            }) {
                Image(systemName: text.isEmpty ? "arrow.up.circle" : "arrow.up.circle.fill")
                    .font(.system(size: 36))
                    .foregroundColor(
                        text.isEmpty ? AppColors.disabledText : AppColors.primary
                    )
                    .shadow(
                        color: text.isEmpty ? .clear : AppColors.primary.opacity(0.3),
                        radius: 6,
                        x: 0,
                        y: 3
                    )
            }
            .disabled(text.isEmpty)
            .animation(.spring(response: 0.3, dampingFraction: 0.7), value: text.isEmpty)
        }
        .padding(.horizontal, AppSpacing.md)
        .padding(.vertical, AppSpacing.sm)
    }
}
```

### 3.3 Activity Interface

**File**: `lichunWebsocket/Views/ActivityView/Components/ActivityButton.swift`

Card-style activity buttons:

```swift
import SwiftUI

struct CozyActivityButton: View {
    let title: String
    let icon: String
    let color: Color
    let energyCost: Int
    let hasEnergy: Bool
    let action: () -> Void

    var body: some View {
        Button(action: {
            if hasEnergy {
                hapticFeedback(style: .medium)
                action()
            }
        }) {
            VStack(spacing: AppSpacing.sm) {
                // Icon circle
                ZStack {
                    Circle()
                        .fill(
                            LinearGradient(
                                colors: [
                                    color.opacity(0.2),
                                    color.opacity(0.15)
                                ],
                                startPoint: .topLeading,
                                endPoint: .bottomTrailing
                            )
                        )
                        .frame(width: 70, height: 70)

                    Image(systemName: icon)
                        .font(.system(size: 32, weight: .semibold))
                        .foregroundColor(color)
                }

                // Title
                Text(title)
                    .font(.system(size: 15, weight: .semibold, design: .rounded))
                    .foregroundColor(AppColors.primaryText)
                    .multilineTextAlignment(.center)
                    .lineLimit(2)

                // Energy cost badge
                HStack(spacing: 4) {
                    Image(systemName: "bolt.fill")
                        .font(.system(size: 10))
                    Text("\(energyCost)")
                        .font(.system(size: 12, weight: .bold, design: .rounded))
                }
                .foregroundColor(hasEnergy ? AppColors.energy : AppColors.error)
                .padding(.horizontal, 10)
                .padding(.vertical, 4)
                .background(
                    (hasEnergy ? AppColors.energy : AppColors.error).opacity(0.15)
                )
                .cornerRadius(12)
            }
            .padding(AppSpacing.md)
            .frame(maxWidth: .infinity)
            .background(AppColors.surfaceElevated)
            .cornerRadius(AppSpacing.cornerRadius)
            .overlay(
                RoundedRectangle(cornerRadius: AppSpacing.cornerRadius)
                    .strokeBorder(color.opacity(0.3), lineWidth: 2)
            )
            .shadow(
                color: Color.black.opacity(0.05),
                radius: AppSpacing.Shadow.radiusSoft,
                x: 0,
                y: 4
            )
            .opacity(hasEnergy ? 1.0 : 0.6)
        }
        .buttonStyle(SquishButtonStyle())
        .disabled(!hasEnergy)
    }
}
```

---

## Phase 4: Header & Navigation

### Timeline: Week 3
### Priority: HIGH - Always visible

### 4.1 Header Redesign

**File**: `lichunWebsocket/Shared/Components/HeaderView.swift`

Create warm, seasonal header:

```swift
import SwiftUI

struct CozyHeaderView: View {
    @EnvironmentObject var webSocketService: WebSocketService

    var seasonIcon: String {
        switch webSocketService.player.season.lowercased() {
        case "spring": return "leaf.fill"
        case "summer": return "sun.max.fill"
        case "autumn", "fall": return "leaf.fill"
        case "winter": return "snowflake"
        default: return "calendar"
        }
    }

    var body: some View {
        ZStack {
            // Seasonal gradient background with blur
            AppColors.cozySeasonGradient(webSocketService.player.season)
                .blur(radius: 20)
                .overlay(
                    // Subtle pattern overlay
                    Image(systemName: "circle.grid.cross.fill")
                        .resizable(resizingMode: .tile)
                        .foregroundColor(.white)
                        .opacity(0.05)
                )

            // Content
            HStack(alignment: .top, spacing: AppSpacing.md) {
                // Left: Date & Season
                VStack(alignment: .leading, spacing: 4) {
                    HStack(spacing: 6) {
                        Image(systemName: seasonIcon)
                            .font(.system(size: 14))
                            .foregroundColor(AppColors.primaryText)
                        Text(monthEmojiAndAbbreviation())
                            .font(.system(size: 13, weight: .semibold, design: .rounded))
                            .foregroundColor(AppColors.primaryText)
                    }

                    Text(formattedDateTime())
                        .font(.system(size: 11, weight: .medium, design: .rounded))
                        .foregroundColor(AppColors.secondaryText)
                }
                .padding(.horizontal, 12)
                .padding(.vertical, 8)
                .background(Color.white.opacity(0.3))
                .cornerRadius(12)
                .shadow(color: Color.black.opacity(0.05), radius: 4, x: 0, y: 2)

                Spacer()

                // Center: Status message
                if !webSocketService.person.intraDayMessage.isEmpty {
                    HStack(spacing: 6) {
                        Image(systemName: "sparkles")
                            .font(.system(size: 12))
                        Text(webSocketService.person.intraDayMessage)
                            .font(.system(size: 12, weight: .medium, design: .rounded))
                            .lineLimit(1)
                    }
                    .foregroundColor(AppColors.accent)
                    .padding(.horizontal, 12)
                    .padding(.vertical, 8)
                    .background(AppColors.accent.opacity(0.15))
                    .cornerRadius(12)
                }

                Spacer()

                // Right: Resources
                VStack(alignment: .trailing, spacing: 6) {
                    // Energy
                    ResourceBadge(
                        icon: "bolt.fill",
                        value: "\(webSocketService.person.calcEnergy)",
                        color: AppColors.energy
                    )

                    // Money
                    ResourceBadge(
                        icon: "dollarsign.circle.fill",
                        value: "\(webSocketService.person.money)",
                        color: AppColors.money
                    )

                    // Diamonds
                    ResourceBadge(
                        icon: "gem.fill",
                        value: "\(webSocketService.person.diamonds)",
                        color: AppColors.diamond
                    )
                }
            }
            .padding(.horizontal, AppSpacing.md)
        }
        .frame(height: 100)
    }

    private func monthEmojiAndAbbreviation() -> String {
        // Implementation from existing HeaderView
        return "Jan"
    }

    private func formattedDateTime() -> String {
        // Implementation from existing HeaderView
        return "Monday, 9:00 AM"
    }
}

struct ResourceBadge: View {
    let icon: String
    let value: String
    let color: Color

    var body: some View {
        HStack(spacing: 4) {
            Image(systemName: icon)
                .font(.system(size: 12))
                .foregroundColor(color)
            Text(value)
                .font(.system(size: 14, weight: .bold, design: .rounded))
                .foregroundColor(AppColors.primaryText)
        }
        .padding(.horizontal, 10)
        .padding(.vertical, 5)
        .background(color.opacity(0.15))
        .cornerRadius(10)
    }
}
```

---

## Phase 5: Animations & Microinteractions

### Timeline: Week 4
### Priority: MEDIUM - Adds delight

### 5.1 Animation Library

**New File**: `lichunWebsocket/Shared/Utilities/CozyAnimations.swift`

```swift
import SwiftUI

struct CozyAnimations {
    // Extra bouncy for primary interactions
    static let bounce = Animation.spring(response: 0.5, dampingFraction: 0.55)

    // Gentle float for idle states
    static let float = Animation.easeInOut(duration: 2.0).repeatForever(autoreverses: true)

    // Quick pop for feedback
    static let pop = Animation.spring(response: 0.25, dampingFraction: 0.5)

    // Smooth slide for transitions
    static let slide = Animation.spring(response: 0.6, dampingFraction: 0.75)

    // Soft fade
    static let fade = Animation.easeInOut(duration: 0.3)
}

// View extension for transition effects
extension View {
    /// Float in transition - scale + opacity
    func floatInTransition(delay: Double = 0) -> some View {
        self.transition(
            .asymmetric(
                insertion: .scale(scale: 0.8).combined(with: .opacity)
                    .animation(
                        .spring(response: 0.6, dampingFraction: 0.7).delay(delay)
                    ),
                removal: .scale(scale: 0.9).combined(with: .opacity)
                    .animation(.easeIn(duration: 0.2))
            )
        )
    }

    /// Number pop animation when value changes
    func popOnChange<V: Equatable>(of value: V) -> some View {
        self.modifier(PopOnChangeModifier(value: value))
    }
}

struct PopOnChangeModifier<V: Equatable>: ViewModifier {
    let value: V
    @State private var scale: CGFloat = 1.0

    func body(content: Content) -> some View {
        content
            .scaleEffect(scale)
            .onChange(of: value) { _, _ in
                withAnimation(.spring(response: 0.3, dampingFraction: 0.4)) {
                    scale = 1.2
                }
                withAnimation(.spring(response: 0.4, dampingFraction: 0.6).delay(0.1)) {
                    scale = 1.0
                }
            }
    }
}
```

### 5.2 Loading View

**File**: `lichunWebsocket/Shared/Components/LoadingView.swift`

Replace with cozy loading animation:

```swift
import SwiftUI

struct CozyLoadingView: View {
    @State private var isPulsing = false
    @State private var rotation: Double = 0
    var message: String = "Loading..."

    var body: some View {
        ZStack {
            // Warm background instead of black
            AppColors.background
                .ignoresSafeArea()

            VStack(spacing: AppSpacing.lg) {
                // Pulsing circle with gradient
                ZStack {
                    Circle()
                        .fill(
                            LinearGradient(
                                colors: [AppColors.primary, AppColors.accent],
                                startPoint: .topLeading,
                                endPoint: .bottomTrailing
                            )
                        )
                        .frame(width: 60, height: 60)
                        .scaleEffect(isPulsing ? 1.1 : 0.9)
                        .opacity(isPulsing ? 1.0 : 0.6)

                    // Rotating ring
                    Circle()
                        .stroke(
                            LinearGradient(
                                colors: [AppColors.secondary, .clear],
                                startPoint: .top,
                                endPoint: .bottom
                            ),
                            lineWidth: 3
                        )
                        .frame(width: 80, height: 80)
                        .rotationEffect(.degrees(rotation))
                }

                // Message
                Text(message)
                    .font(.appHeadline)
                    .foregroundColor(AppColors.secondaryText)
            }
        }
        .onAppear {
            withAnimation(.easeInOut(duration: 1.2).repeatForever(autoreverses: true)) {
                isPulsing = true
            }
            withAnimation(.linear(duration: 2.0).repeatForever(autoreverses: false)) {
                rotation = 360
            }
        }
    }
}
```

### 5.3 Enhanced Haptic Feedback

**File**: `lichunWebsocket/Shared/Utilities/HapticFeedback.swift`

Add cozy haptic patterns:

```swift
import SwiftUI
import UIKit

enum CozyHapticStyle {
    case cozyTap        // Ultra-light, gentle
    case successGlow    // Light tap + success notification
    case celebration    // Multiple quick taps
}

func performCozyHaptic(_ style: CozyHapticStyle) {
    switch style {
    case .cozyTap:
        let generator = UIImpactFeedbackGenerator(style: .soft)
        generator.impactOccurred()

    case .successGlow:
        let impact = UIImpactFeedbackGenerator(style: .light)
        impact.impactOccurred()

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            let notification = UINotificationFeedbackGenerator()
            notification.notificationOccurred(.success)
        }

    case .celebration:
        let generator = UIImpactFeedbackGenerator(style: .light)
        for i in 0..<3 {
            DispatchQueue.main.asyncAfter(deadline: .now() + Double(i) * 0.1) {
                generator.impactOccurred()
            }
        }
    }
}
```

---

## Phase 6: Modals & Special Views

### Timeline: Week 4
### Priority: MEDIUM

### 6.1 Event Modal

**File**: `lichunWebsocket/Views/ContentView/Components/EventModalView.swift`

Update with cozy styling:

```swift
import SwiftUI

struct CozyEventModal: View {
    let question: Question
    let onAnswer: (String) -> Void

    var body: some View {
        ZStack {
            // Softer backdrop
            Color.black.opacity(0.5)
                .ignoresSafeArea()
                .onTapGesture { } // Prevent dismissal

            // Card
            VStack(spacing: AppSpacing.lg) {
                // Decorative top accent bar
                RoundedRectangle(cornerRadius: 4)
                    .fill(
                        LinearGradient(
                            colors: [AppColors.accent, AppColors.primary],
                            startPoint: .leading,
                            endPoint: .trailing
                        )
                    )
                    .frame(width: 60, height: 6)

                // Question content
                VStack(spacing: AppSpacing.md) {
                    // Pre-text (if exists)
                    if !question.questionPretext.isEmpty {
                        Text(question.questionPretext)
                            .font(.appBody)
                            .foregroundColor(AppColors.secondaryText)
                            .multilineTextAlignment(.center)
                            .lineSpacing(4)
                    }

                    // Main question
                    Text(question.questionText)
                        .font(.system(size: 22, weight: .bold, design: .rounded))
                        .foregroundColor(AppColors.primaryText)
                        .multilineTextAlignment(.center)
                        .lineSpacing(6)
                }
                .padding(.horizontal, AppSpacing.lg)

                // Answer options
                VStack(spacing: AppSpacing.md) {
                    ForEach(Array(question.answerTexts.enumerated()), id: \.offset) { index, answer in
                        Button(action: {
                            performCozyHaptic(.cozyTap)
                            onAnswer(question.answers[index])
                        }) {
                            Text(answer)
                                .font(.appHeadline)
                                .foregroundColor(.white)
                                .frame(maxWidth: .infinity)
                                .padding(.vertical, 16)
                                .background(
                                    LinearGradient(
                                        colors: [
                                            AppColors.primary,
                                            AppColors.primary.darker(by: 0.1)
                                        ],
                                        startPoint: .topLeading,
                                        endPoint: .bottomTrailing
                                    )
                                )
                                .cornerRadius(16)
                                .shadow(
                                    color: AppColors.primary.opacity(0.4),
                                    radius: 8,
                                    x: 0,
                                    y: 4
                                )
                        }
                        .buttonStyle(SquishButtonStyle())
                    }
                }
                .padding(.horizontal, AppSpacing.lg)
            }
            .padding(.vertical, AppSpacing.xl)
            .frame(maxWidth: 400)
            .background(AppColors.surfaceElevated)
            .cornerRadius(AppSpacing.largeCornerRadius)
            .shadow(color: Color.black.opacity(0.2), radius: 30, x: 0, y: 15)
            .padding(AppSpacing.lg)
        }
    }
}
```

---

## Implementation Checklist

Use this checklist to track your progress:

### Week 1: Foundation
- [ ] Update AppColors.swift with new cozy palette
- [ ] Add Color helper extensions (lighter, darker)
- [ ] Update AppTypography.swift with increased sizes
- [ ] Add text style extensions
- [ ] Update AppSpacing.swift with larger values
- [ ] Test color changes throughout app
- [ ] Verify accessibility (contrast ratios)

### Week 2: Core Components
- [ ] Update PrimaryButton with gradient + shadows
- [ ] Create SquishButtonStyle
- [ ] Update SecondaryButton
- [ ] Create CozyIconButton
- [ ] Update BaseCard with layered shadows
- [ ] Replace StatBar with CozyStatBar (gradient fills)
- [ ] Create CozyStatBadge
- [ ] Create CozyInterestTag
- [ ] Test all components in light/dark mode

### Week 3: Feature Redesigns
- [ ] Update EnhancedProfileCard → CozyDatingCard
- [ ] Create CozySwipeButtons for dating
- [ ] Create CozyChatBubble for messaging
- [ ] Create CozyMessageInput
- [ ] Update ConversationListItem styling
- [ ] Create CozyActivityButton
- [ ] Update activity list layouts
- [ ] Update HeaderView → CozyHeaderView
- [ ] Create ResourceBadge component

### Week 4: Polish & Animation
- [ ] Create CozyAnimations.swift library
- [ ] Add floatInTransition view extension
- [ ] Add popOnChange modifier
- [ ] Update LoadingView → CozyLoadingView
- [ ] Add CozyHapticStyle patterns
- [ ] Update EventModalView → CozyEventModal
- [ ] Add celebration effects (confetti)
- [ ] Test all animations on device

### Week 5: Testing & Refinement
- [ ] Visual regression testing (before/after screenshots)
- [ ] Test on iPhone SE (smallest)
- [ ] Test on iPhone 15 Pro Max (largest)
- [ ] Test with VoiceOver enabled
- [ ] Test with largest Dynamic Type size
- [ ] Verify color contrast (WCAG AA)
- [ ] Performance profiling (animations, gradients)
- [ ] Address any performance issues

### Week 6: Final Polish
- [ ] User feedback gathering
- [ ] Fix any reported issues
- [ ] Dark mode final tweaks
- [ ] Create design documentation
- [ ] Update app screenshots
- [ ] Prepare for release

---

## Technical Notes

### Performance Considerations

1. **Gradient Rendering**: Use sparingly on scrolling lists
2. **Shadow Optimization**: Combine multiple shadows carefully
3. **Animation Performance**: Profile on older devices
4. **Memory Usage**: Monitor with many cards on screen

### Accessibility Requirements

1. **Color Contrast**: All text must meet WCAG AA (4.5:1 for body, 3:1 for large text)
2. **Dynamic Type**: Test with largest system font sizes
3. **VoiceOver**: Ensure all interactive elements have labels
4. **Motion**: Respect `UIAccessibility.isReduceMotionEnabled`

### Testing Strategy

1. **Visual Regression**: Take screenshots before changes
2. **Unit Tests**: Test color utility functions
3. **UI Tests**: Verify button interactions work
4. **Manual Testing**: Check feel and polish on device

---

## Color Reference Quick Guide

### Before → After

| Element | Old Color | New Color | Hex |
|---------|-----------|-----------|-----|
| Primary Button | System Blue | Soft Rose Pink | #F4A5B5 |
| Energy | Neon Teal | Soft Sage | #9DDFAA |
| Money | Bright Green | Butter Yellow | #FFE07A |
| Health | Harsh Red | Coral Pink | #FFB3BA |
| Happiness | Bright Yellow | Sunflower | #FFEAA7 |
| Background | Light Beige | Warm Cream | #FFF8F3 |
| Text | White | Warm Brown | #5A4A3A |

---

## Success Metrics

### User Experience Goals
- Session length increase: +20%
- Dating profile views: +30%
- Message reply rate: +15%
- App Store rating: +0.5 stars

### Qualitative Indicators
- "Cozy" mentioned in reviews
- Positive aesthetic feedback
- Increased social media sharing
- Reduced UI-related support tickets

---

## Support & Resources

### Design Inspiration
- **Animal Crossing: New Horizons** - UI warmth, rounded elements
- **Stardew Valley** - Cozy color palette
- **Cozy Grove** - Soft shadows, warm lighting
- **Coffee Talk** - Inviting atmosphere

### Color Tools
- [Coolors.co](https://coolors.co) - Palette generation
- [Lospec.com](https://lospec.com) - Cozy game palettes
- [Adobe Color](https://color.adobe.com) - Color harmony

### Accessibility
- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
- [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/)

---

## Final Notes

This redesign transforms BaoLife into a warm digital space where players want to spend time. Every color, shadow, animation, and spacing decision works together to create that cozy game feeling.

**Remember: Cozy isn't just pastel colors—it's warmth, personality, and making users feel at home.** 🏡✨

---

**Document Version**: 1.0
**Last Updated**: 2025-11-12
**Status**: Ready for Implementation
**Contact**: See project maintainers for questions
