"""AiCippy Mascot - Animated ZooZoo-style character.

Provides cute animated ASCII art mascot with various poses and animations:
- Idle animation (breathing/bobbing)
- Thinking animation (head scratch)
- Working animation (typing)
- Happy animation (jumping)
- Waving animation
"""

from __future__ import annotations

import asyncio
import itertools
import time
from dataclasses import dataclass
from enum import Enum, auto
from typing import TYPE_CHECKING, Final

from rich.align import Align
from rich.box import ROUNDED
from rich.console import Console, Group
from rich.live import Live
from rich.panel import Panel
from rich.text import Text

from aicippy.cli.terminal_caps import supports_utf8
from aicippy.config import is_founder

if TYPE_CHECKING:
    from collections.abc import Iterator


def _normalize_frames(frames: tuple[str, ...]) -> tuple[str, ...]:
    """Normalize frame widths within a frame set by right-padding all lines.

    For each frame set, finds the maximum line width across all frames and pads
    every line to that width with spaces. This prevents visual jitter during
    animation.

    Args:
        frames: Tuple of multi-line ASCII art frame strings.

    Returns:
        New tuple with all frames padded to uniform width.

    """
    # First pass: find the maximum line width across all frames
    max_width = 0
    for frame in frames:
        for line in frame.strip("\n").split("\n"):
            max_width = max(max_width, len(line))

    # Second pass: pad all lines to max_width
    normalized: list[str] = []
    for frame in frames:
        lines = frame.strip("\n").split("\n")
        padded_lines = [line.ljust(max_width) for line in lines]
        normalized.append("\n" + "\n".join(padded_lines) + "\n")

    return tuple(normalized)


# Brand colors
MASCOT_PRIMARY: Final[str] = "#667eea"
MASCOT_SECONDARY: Final[str] = "#764ba2"
MASCOT_ACCENT: Final[str] = "#f093fb"
MASCOT_GLOW: Final[str] = "#a78bfa"
MASCOT_WHITE: Final[str] = "#ffffff"
MASCOT_HIGHLIGHT: Final[str] = "#c4b5fd"


class MascotMood(Enum):
    """Mascot mood/animation state."""

    IDLE = auto()
    THINKING = auto()
    WORKING = auto()
    HAPPY = auto()
    WAVING = auto()
    SLEEPING = auto()
    EXCITED = auto()


# ============================================================================
# Mascot Frames - ZooZoo Style Character
# ============================================================================

# Idle animation frames (gentle bobbing)
IDLE_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
       .~~~~~.
      /       \\
     |  o   o  |
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
       .~~~~~.
      /       \\
     |  o   o  |
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
         '--'
    """,
        """
       .~~~~~.
      /       \\
     |  o   o  |
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
         |  |
         '--'
    """,
    ),
)

# Thinking animation frames (scratching head)
THINKING_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
       .~~~~~.  ?
      /       \\
     |  o   o  |
     |    __   |
      \\  \\__/ /
       '-----'
        \\|  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
       .~~~~~.  ?
      /   __   \\
     |  o   o  |
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
     ? .~~~~~.
      /       \\
     |  o   o  |
     |    __   |
      \\  \\__/ /
       '-----'
         |  |/
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
       .~~~~~.
      /   ??   \\
     |  o   o  |
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
    ),
)

# Working animation frames (typing)
WORKING_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
       .~~~~~.
      /       \\
     |  *   *  |
     |    __   |
      \\  \\__/ /
       '-----'
        \\|  |/
       __|  |__
      |  |  |  |
      '  '--'  '
    """,
        """
       .~~~~~.
      /       \\
     |  *   *  |
     |    __   |
      \\  \\__/ /
       '-----'
        \\|  |/
      ___|  |___
     |   |  |   |
      '  '--'  '
    """,
        """
       .~~~~~.
      /       \\
     |  o   o  |
     |    __   |
      \\  \\__/ /
       '-----'
        \\|  |/
       __|  |__
      |  '--'  |
      '        '
    """,
        """
       .~~~~~.
      /       \\
     |  *   *  |
     |    __   |
      \\  \\__/ /
       '-----'
        \\|  |/
      ___|  |___
      |  '--'  |
      '        '
    """,
    ),
)

# Happy/jumping animation frames
HAPPY_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
       .~~~~~.    *
      /       \\
     |  ^   ^  |
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
    *  .~~~~~.  *
      /       \\
     |  ^   ^  |
     |   \\__/  |
      \\        /
       '-----'
       \\ |  | /
        \\|  |/
         |  |
         '--'
    """,
        """
       .~~~~~.
      /   *    \\
     |  ^   ^  |
     |   \\__/  |
      \\        /
       '-----'
         \\  /
          ||
         /  \\
        /    \\
    """,
        """
   *   .~~~~~.   *
      /       \\
     |  ^   ^  |
     |   \\__/  |
      \\        /
       '-----'
        \\|  |/
         |  |
        /    \\
       '      '
    """,
    ),
)

# Waving animation frames
WAVING_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
       .~~~~~.
      /       \\
     |  o   o  | /
     |    __   |/
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
       .~~~~~.   \\
      /       \\  |
     |  o   o  | |
     |    __   |/
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
       .~~~~~.  __/
      /       \\
     |  o   o  |
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
       .~~~~~.   \\
      /       \\  \\
     |  o   o  |  |
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
    ),
)

# Sleeping animation frames
SLEEPING_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
       .~~~~~.   z
      /       \\  z
     |  -   -  |  z
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
       .~~~~~.    z
      /       \\   z
     |  -   -  |   z
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
        """
       .~~~~~.     z
      /       \\    z
     |  -   -  |    z
     |    __   |
      \\  \\__/ /
       '-----'
         |  |
        /|  |\\
       / |  | \\
      '  '--'  '
    """,
    ),
)

# Excited animation frames (bouncing with sparkles)
EXCITED_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
    ** .~~~~~. **
      /       \\
     |  *   *  |
     |   \\__/  |
      \\        /
       '-----'
       \\ |  | /
        \\|  |/
        /|  |\\
       ' '--' '
    """,
        """
   **  .~~~~~.  **
      /   **   \\
     |  *   *  |
     |   \\__/  |
      \\        /
       '-----'
         |  |
        /|  |\\
         |  |
         '--'
    """,
        """
  **   .~~~~~.   **
      /       \\
     |  *   *  |
     |   \\__/  |
      \\        /
       '-----'
      \\ |    | /
       \\|    |/
        '----'
    """,
        """
    ** .~~~~~. **
      /       \\
     |  *   *  |
     |   \\__/  |
      \\        /
       '-----'
        \\    /
         \\  /
         /  \\
        /    \\
    """,
    ),
)

# Mini mascot for header (smaller version)
MINI_IDLE_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
  .---.
 / o o \\
 \\  ^  /
  '---'
   | |
  /   \\
    """,
        """
  .---.
 / o o \\
 \\  ^  /
  '---'
   | |
   | |
    """,
        """
  .---.
 / o o \\
 \\  ^  /
  '---'
   ||
  /  \\
    """,
    ),
)

MINI_THINKING_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
  .---. ?
 / o o \\
 \\  ^  /
  '---'
   | |
  /   \\
    """,
        """
  .---.  ?
 / o o \\
 \\  ^  /
  '---'
   | |
  /   \\
    """,
        """
? .---.
 / o o \\
 \\  ^  /
  '---'
   | |
  /   \\
    """,
    ),
)

MINI_HAPPY_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
  .---. *
 / ^ ^ \\
 \\ \\_/ /
  '---'
   \\|/
    |
    """,
        """
* .---.
 / ^ ^ \\
 \\ \\_/ /
  '---'
   |||
   \\_/
    """,
        """
  .---. *
 / ^ ^ \\
 \\ \\_/ /
  '---'
  \\   /
   \\_/
    """,
    ),
)

MINI_WORKING_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
  .---.
 / * * \\
 \\  ^  /
  '---'
  \\| |/
  _| |_
    """,
        """
  .---.
 / * * \\
 \\  ^  /
  '---'
  \\| |/
 __| |__
    """,
        """
  .---.
 / o o \\
 \\  ^  /
  '---'
  \\| |/
  _| |_
    """,
    ),
)

MINI_WAVING_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
  .---. /
 / o o \\/
 \\  ^  /
  '---'
   | |
  /   \\
    """,
        """
  .---.  \\
 / o o \\ |
 \\  ^  /
  '---'
   | |
  /   \\
    """,
        """
  .---._/
 / o o \\
 \\  ^  /
  '---'
   | |
  /   \\
    """,
    ),
)


# ============================================================================
# Mascot Animation Controller
# ============================================================================


@dataclass
class MascotAnimator:
    """Animated mascot controller.

    Provides frame-by-frame animation with mood transitions.
    """

    mood: MascotMood = MascotMood.IDLE
    frame_delay: float = 0.3
    use_mini: bool = False

    def get_frames(self) -> tuple[str, ...]:
        """Get animation frames for current mood."""
        if self.use_mini:
            frames_map = {
                MascotMood.IDLE: MINI_IDLE_FRAMES,
                MascotMood.THINKING: MINI_THINKING_FRAMES,
                MascotMood.WORKING: MINI_WORKING_FRAMES,
                MascotMood.HAPPY: MINI_HAPPY_FRAMES,
                MascotMood.WAVING: MINI_WAVING_FRAMES,
                MascotMood.SLEEPING: MINI_IDLE_FRAMES,  # Reuse idle for mini
                MascotMood.EXCITED: MINI_HAPPY_FRAMES,
            }
        else:
            frames_map = {
                MascotMood.IDLE: IDLE_FRAMES,
                MascotMood.THINKING: THINKING_FRAMES,
                MascotMood.WORKING: WORKING_FRAMES,
                MascotMood.HAPPY: HAPPY_FRAMES,
                MascotMood.WAVING: WAVING_FRAMES,
                MascotMood.SLEEPING: SLEEPING_FRAMES,
                MascotMood.EXCITED: EXCITED_FRAMES,
            }
        return frames_map.get(self.mood, IDLE_FRAMES if not self.use_mini else MINI_IDLE_FRAMES)

    def get_frame_iterator(self) -> Iterator[str]:
        """Get infinite frame iterator."""
        return itertools.cycle(self.get_frames())

    def render_frame(self, frame: str, with_color: bool = True) -> Text:
        """Render a single frame with gradient coloring.

        Args:
            frame: ASCII art frame string.
            with_color: Whether to apply gradient colors.

        Returns:
            Rich Text with colored frame.

        """
        if not with_color:
            return Text(frame)

        lines = frame.strip("\n").split("\n")
        result = Text()

        for i, line in enumerate(lines):
            # Apply gradient based on line position
            if i < len(lines) // 3:
                color = MASCOT_GLOW
            elif i < 2 * len(lines) // 3:
                color = MASCOT_PRIMARY
            else:
                color = MASCOT_SECONDARY

            # Highlight special characters
            colored_line = Text()
            for char in line:
                if char in "o*^":
                    colored_line.append(char, style=MASCOT_ACCENT)
                elif char in "?z":
                    colored_line.append(char, style=f"bold {MASCOT_HIGHLIGHT}")
                elif char in "/-\\|_":
                    colored_line.append(char, style=color)
                elif char in "'.~":
                    colored_line.append(char, style="dim " + color)
                else:
                    colored_line.append(char, style=color)

            result.append(colored_line)
            if i < len(lines) - 1:
                result.append("\n")

        return result


def create_mascot_panel(
    mood: MascotMood = MascotMood.IDLE,
    frame_idx: int = 0,
    mini: bool = False,
    title: str | None = None,
) -> Panel:
    """Create a panel with the mascot in specified mood.

    Args:
        mood: Mascot mood/animation state.
        frame_idx: Which frame to show.
        mini: Use mini version.
        title: Optional panel title.

    Returns:
        Rich Panel with mascot.

    """
    animator = MascotAnimator(mood=mood, use_mini=mini)
    frames = animator.get_frames()
    frame = frames[frame_idx % len(frames)]
    colored = animator.render_frame(frame)

    return Panel(
        Align.center(colored),
        border_style=MASCOT_PRIMARY,
        title=title,
        title_align="center",
        padding=(0, 1),
    )


def create_animated_header(
    version: str = "1.0.0",
    mood: MascotMood = MascotMood.IDLE,
    frame_idx: int = 0,
) -> Group:
    """Create animated header with mini mascot.

    Args:
        version: App version string.
        mood: Mascot mood.
        frame_idx: Animation frame index.

    Returns:
        Rich Group with header and mascot.

    """
    animator = MascotAnimator(mood=mood, use_mini=True)
    frames = animator.get_frames()
    frame = frames[frame_idx % len(frames)]
    mascot_text = animator.render_frame(frame)

    # Logo text
    logo = Text()
    logo.append(
        "+=======================================================+\n",
        style=MASCOT_PRIMARY,
    )
    logo.append("|", style=MASCOT_PRIMARY)
    logo.append("          ", style=MASCOT_PRIMARY)
    logo.append("A", style=f"bold {MASCOT_GLOW}")
    logo.append("i", style=f"bold {MASCOT_PRIMARY}")
    logo.append("C", style=f"bold {MASCOT_SECONDARY}")
    logo.append("i", style=f"bold {MASCOT_ACCENT}")
    logo.append("p", style=f"bold {MASCOT_PRIMARY}")
    logo.append("p", style=f"bold {MASCOT_GLOW}")
    logo.append("y", style=f"bold {MASCOT_SECONDARY}")
    logo.append(f"  v{version}", style="dim")
    logo.append("                            ", style=MASCOT_PRIMARY)
    logo.append("|\n", style=MASCOT_PRIMARY)
    logo.append("|", style=MASCOT_PRIMARY)
    logo.append("    Enterprise Multi-Agent CLI System    ", style=f"italic {MASCOT_HIGHLIGHT}")
    logo.append("              |\n", style=MASCOT_PRIMARY)
    logo.append(
        "+=======================================================+",
        style=MASCOT_PRIMARY,
    )

    return Group(mascot_text, logo)


async def run_mascot_animation(
    console: Console,
    mood: MascotMood = MascotMood.IDLE,
    duration: float = 3.0,
    mini: bool = False,
) -> None:
    """Run mascot animation for specified duration.

    Args:
        console: Rich console.
        mood: Mascot mood.
        duration: Animation duration in seconds.
        mini: Use mini version.

    """
    animator = MascotAnimator(mood=mood, use_mini=mini)
    frames = animator.get_frames()

    start_time = time.monotonic()
    frame_idx = 0

    with Live(console=console, refresh_per_second=4) as live:
        while time.monotonic() - start_time < duration:
            frame = frames[frame_idx % len(frames)]
            colored = animator.render_frame(frame)
            live.update(Align.center(colored))
            frame_idx += 1
            await asyncio.sleep(animator.frame_delay)


def get_mood_message(mood: MascotMood) -> str:
    """Get a message for the mascot's mood."""
    messages = {
        MascotMood.IDLE: "Ready to help!",
        MascotMood.THINKING: "Hmm, let me think...",
        MascotMood.WORKING: "Working on it...",
        MascotMood.HAPPY: "Yay! All done!",
        MascotMood.WAVING: "Hello there!",
        MascotMood.SLEEPING: "Zzz...",
        MascotMood.EXCITED: "This is exciting!",
    }
    return messages.get(mood, "")


# ============================================================================
# Welcome Screen with Animated Mascot
# ============================================================================


def create_welcome_with_mascot(  # noqa: PLR0915 — Welcome screen assembly requires many Rich layout statements
    version: str = "1.0.0",
    frame_idx: int = 0,
    user_email: str | None = None,
) -> Group:
    """Create welcome screen with animated mascot.

    Args:
        version: App version.
        frame_idx: Animation frame.
        user_email: Optional user email for personalized greeting.

    Returns:
        Rich Group with welcome content.

    """
    animator = MascotAnimator(mood=MascotMood.WAVING, use_mini=False)
    frames = animator.get_frames()
    frame = frames[frame_idx % len(frames)]
    mascot = animator.render_frame(frame)

    # Title with gradient
    title = Text()
    title.append("\n")
    _p = MASCOT_PRIMARY
    _h = MASCOT_HIGHLIGHT
    _bar = "  +===============================================================+\n"
    _sp = "                                                               "
    _pipe = "              |\n"
    title.append(_bar, style=_p)
    title.append("  |", style=_p)
    title.append(_sp, style=_p)
    title.append("|\n", style=_p)
    title.append("  |", style=_p)
    title.append(
        "      _    _  ____  _                           ",
        style=MASCOT_GLOW,
    )
    title.append(_pipe, style=_p)
    title.append("  |", style=_p)
    title.append(
        "     / \\  (_)/ ___||_|_ __  _ __  _   _          ",
        style=_p,
    )
    title.append(_pipe, style=_p)
    title.append("  |", style=_p)
    title.append(
        "    / _ \\ | | |    | | '_ \\| '_ \\| | | |         ",
        style=MASCOT_SECONDARY,
    )
    title.append(_pipe, style=_p)
    title.append("  |", style=_p)
    title.append(
        "   / ___ \\| | |___ | | |_) | |_) | |_| |         ",
        style=MASCOT_ACCENT,
    )
    title.append(_pipe, style=_p)
    title.append("  |", style=_p)
    title.append(
        "  /_/   \\_\\_|\\____||_| .__/| .__/ \\__, |         ",
        style=_h,
    )
    title.append(_pipe, style=_p)
    title.append("  |", style=_p)
    title.append(
        "                     |_|   |_|    |___/          ",
        style=_h,
    )
    title.append(_pipe, style=_p)
    title.append("  |", style=_p)
    title.append(_sp, style=_p)
    title.append("|\n", style=_p)
    title.append("  |", style=_p)
    ver_line = f"         Enterprise Multi-Agent CLI System  v{version}         "
    title.append(ver_line, style=f"italic {_h}")
    title.append("    |\n", style=_p)
    title.append("  |", style=_p)
    title.append(_sp, style=_p)
    title.append("|\n", style=_p)
    title.append(_bar, style=_p)

    # Mascot says hi - speech bubble using Rich Panel for dynamic sizing
    bubble_content = Text()
    if is_founder(user_email):
        bubble_content.append("Welcome back, Lord AJ!", style=f"bold {MASCOT_ACCENT}")
        bubble_content.append("\n")
        bubble_content.append("Your Cippy awaits your command!", style=MASCOT_GLOW)
    else:
        bubble_content.append("Hi! I'm Cippy!", style=f"bold {MASCOT_ACCENT}")
        bubble_content.append("\n")
        bubble_content.append("Let's build magic!", style=MASCOT_GLOW)

    speech_panel = Panel(
        bubble_content,
        box=ROUNDED,
        border_style=_h,
        padding=(0, 1),
        expand=False,
    )

    # Speech bubble tail
    tail = Text()
    tail.append("  \\", style=MASCOT_HIGHLIGHT)
    tail.append("\n")
    tail.append("   \\", style=MASCOT_HIGHLIGHT)

    return Group(title, Align.center(speech_panel), Align.center(tail), Align.center(mascot))


async def animate_welcome(
    console: Console,
    version: str = "1.0.0",
    duration: float = 2.5,
) -> None:
    """Show animated welcome screen.

    Args:
        console: Rich console.
        version: App version.
        duration: Animation duration.

    """
    animator = MascotAnimator(mood=MascotMood.WAVING, use_mini=False)
    animator.get_frames()

    start_time = time.monotonic()
    frame_idx = 0

    with Live(console=console, refresh_per_second=4, transient=True) as live:
        while time.monotonic() - start_time < duration:
            content = create_welcome_with_mascot(version, frame_idx)
            live.update(content)
            frame_idx += 1
            await asyncio.sleep(0.25)

    # End with final pose
    console.print(create_welcome_with_mascot(version, 0))


# ============================================================================
# Compact Colored Zozoo Welcome Animation (for login success)
# ============================================================================

# Compact oval-bodied Zozoo frames (filled with color) - UTF-8 version
COMPACT_ZOZOO_WELCOME_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
      ╭─────╮
     /  ◕ ◕  ╲
    │    ▽    │
    │  ╲___/  │
     ╲       /
      ╰─────╯
       │ │ /
      /│ │/
     / │ │
    """,
        """
      ╭─────╮
     /  ◕ ◕  ╲
    │    ▽    │
    │  ╲___/  │
     ╲       /
      ╰─────╯
       │ │  \\
      /│ │  │
     / │ │
    """,
        """
      ╭─────╮
     /  ◕ ◕  ╲
    │    ▽    │
    │  ╲___/  │
     ╲       /
      ╰─────╯
       │ │__/
      /│ │
     / │ │
    """,
        """
      ╭─────╮
     /  ◕ ◕  ╲
    │    ▽    │
    │  ╲___/  │
     ╲       /
      ╰─────╯
       │ │ \\
      /│ │ \\
     / │ │  │
    """,
    ),
)

# Compact oval-bodied Zozoo frames - ASCII fallback for non-UTF-8 terminals
COMPACT_ZOZOO_ASCII_FRAMES: Final[tuple[str, ...]] = _normalize_frames(
    (
        """
      +-----+
     /  o o  \\
    |    v    |
    |  \\___/  |
     \\       /
      +-----+
       | | /
      /| |/
     / | |
    """,
        """
      +-----+
     /  o o  \\
    |    v    |
    |  \\___/  |
     \\       /
      +-----+
       | |  \\
      /| |  |
     / | |
    """,
        """
      +-----+
     /  o o  \\
    |    v    |
    |  \\___/  |
     \\       /
      +-----+
       | |__/
      /| |
     / | |
    """,
        """
      +-----+
     /  o o  \\
    |    v    |
    |  \\___/  |
     \\       /
      +-----+
       | | \\
      /| | \\
     / | |  |
    """,
    ),
)


def render_compact_zozoo(frame: str, fill_color: str = MASCOT_PRIMARY) -> Text:  # noqa: PLR0912
    """Render compact Zozoo with colored fill.

    Automatically detects whether the frame uses UTF-8 box-drawing characters
    or plain ASCII, and applies appropriate character-level styling.

    Args:
        frame: ASCII art frame string (UTF-8 or ASCII).
        fill_color: Main fill color for the body.

    Returns:
        Rich Text with colored frame.

    """
    lines = frame.strip("\n").split("\n")
    result = Text()
    # Detect if this is an ASCII frame (uses '+' corners instead of box-drawing)
    is_ascii = "+" in frame and "\u256d" not in frame

    eye_row_limit = 3
    nose_row_limit = 4
    glow_limit = 3
    fill_limit = 6
    limb_limit = 4

    for i, line in enumerate(lines):
        colored_line = Text()
        for char in line:
            if not is_ascii and char in "\u25d5":
                # Eyes - bright accent (UTF-8 ◕)
                colored_line.append(char, style=f"bold {MASCOT_ACCENT}")
            elif is_ascii and char == "o" and i < eye_row_limit:
                # Eyes - bright accent (ASCII fallback)
                colored_line.append(char, style=f"bold {MASCOT_ACCENT}")
            elif not is_ascii and char in "\u25bd":
                # Nose - highlight (UTF-8 ▽)
                colored_line.append(char, style=MASCOT_HIGHLIGHT)
            elif is_ascii and char == "v" and i < nose_row_limit:
                # Nose - highlight (ASCII fallback)
                colored_line.append(char, style=MASCOT_HIGHLIGHT)
            elif not is_ascii and char in "\u256d\u256e\u2570\u256f\u2500\u2502":
                # Body outline - gradient based on position (UTF-8)
                if i < glow_limit:
                    colored_line.append(char, style=f"bold {MASCOT_GLOW}")
                elif i < fill_limit:
                    colored_line.append(char, style=f"bold {fill_color}")
                else:
                    colored_line.append(char, style=f"bold {MASCOT_SECONDARY}")
            elif is_ascii and char in "+-|" and (char != "|" or i < fill_limit):
                # Body outline - gradient based on position (ASCII)
                if i < glow_limit:
                    colored_line.append(char, style=f"bold {MASCOT_GLOW}")
                elif i < fill_limit:
                    colored_line.append(char, style=f"bold {fill_color}")
                else:
                    colored_line.append(char, style=f"bold {MASCOT_SECONDARY}")
            elif char in "/\u2572\\/_":
                # Body curves and limbs
                if i < limb_limit:
                    colored_line.append(char, style=fill_color)
                else:
                    colored_line.append(char, style=MASCOT_SECONDARY)
            elif char == " ":
                colored_line.append(char)
            else:
                colored_line.append(char, style=fill_color)

        result.append(colored_line)
        if i < len(lines) - 1:
            result.append("\n")

    return result


def create_compact_welcome_panel(
    username: str,
    frame_idx: int = 0,
    user_email: str | None = None,
) -> Panel:
    """Create compact welcome panel with Zozoo animation.

    Args:
        username: User's name to greet.
        frame_idx: Animation frame index.
        user_email: Optional user email for personalized greeting.

    Returns:
        Rich Panel with welcome content.

    """
    frames = COMPACT_ZOZOO_WELCOME_FRAMES if supports_utf8() else COMPACT_ZOZOO_ASCII_FRAMES
    frame = frames[frame_idx % len(frames)]
    zozoo = render_compact_zozoo(frame)

    # Welcome message
    welcome = Text()
    welcome.append("\n")
    welcome.append("  ✨ ", style=MASCOT_ACCENT)
    welcome.append("Welcome, ", style=f"bold {MASCOT_HIGHLIGHT}")
    welcome.append(username, style=f"bold {MASCOT_GLOW}")
    welcome.append("!", style=f"bold {MASCOT_HIGHLIGHT}")
    welcome.append(" ✨\n\n", style=MASCOT_ACCENT)
    if is_founder(user_email):
        welcome.append("     Welcome back, Lord AJ!", style=f"bold {MASCOT_ACCENT}")
        welcome.append("\n")
        welcome.append("     Your Cippy awaits your command!\n", style=f"italic {MASCOT_GLOW}")
    else:
        welcome.append("     Hi! I'm ", style=MASCOT_WHITE)
        welcome.append("Cippy", style=f"bold {MASCOT_PRIMARY}")
        welcome.append("!\n", style=MASCOT_WHITE)
        welcome.append("     Let's build something amazing!\n", style=f"italic {MASCOT_HIGHLIGHT}")

    return Panel(
        Group(
            Align.center(zozoo),
            welcome,
        ),
        border_style=MASCOT_PRIMARY,
        title=f"[bold {MASCOT_GLOW}]AiCippy[/bold {MASCOT_GLOW}]",
        title_align="center",
        padding=(0, 2),
    )


async def animate_welcome_compact(
    console: Console,
    username: str,
    duration: float = 1.5,
    user_email: str | None = None,
) -> None:
    """Show compact colored Zozoo welcome animation after login.

    Args:
        console: Rich console.
        username: User's name to greet.
        duration: Animation duration.
        user_email: Optional user email for personalized greeting.

    """
    console.clear()

    start_time = time.monotonic()
    frame_idx = 0

    with Live(console=console, refresh_per_second=6, transient=True) as live:
        while time.monotonic() - start_time < duration:
            panel = create_compact_welcome_panel(username, frame_idx, user_email=user_email)
            live.update(panel)
            frame_idx += 1
            await asyncio.sleep(0.15)

    # End with final frame
    console.print(create_compact_welcome_panel(username, 0, user_email=user_email))
    console.print()  # Add spacing before prompt area
