• Home page component for the Kenmei to AniList sync tool.

    Displays dashboard statistics, feature carousel, quick actions, and sync status for the user.

    Returns Element

    export function HomePage() {
    // Get auth state to check authentication status
    const { authState } = useAuth();

    // State for dashboard data
    const [stats, setStats] = useState<StatsState>({
    total: 0,
    reading: 0,
    completed: 0,
    onHold: 0,
    dropped: 0,
    planToRead: 0,
    lastSync: null,
    syncStatus: "none",
    });
    const [matchStatus, setMatchStatus] = useState<{
    pendingMatches: number;
    skippedMatches: number;
    totalMatches: number;
    status: "none" | "pending" | "complete";
    }>({
    pendingMatches: 0,
    skippedMatches: 0,
    totalMatches: 0,
    status: "none",
    });

    // Version status state
    const [versionStatus, setVersionStatus] = useState<AppVersionStatus | null>(
    null,
    );
    const [syncStats, setSyncStats] = useState<SyncStats>({
    lastSyncTime: null,
    entriesSynced: 0,
    failedSyncs: 0,
    totalSyncs: 0,
    });

    useEffect(() => {
    let mounted = true;
    getAppVersionStatus().then((status) => {
    if (mounted) setVersionStatus(status);
    });
    return () => {
    mounted = false;
    };
    }, []);

    // Define interface for match result objects
    interface MatchResult {
    status?: string;
    selectedMatch?: {
    id: number;
    title: string;
    [key: string]: unknown;
    } | null;
    needsReview?: boolean;
    [key: string]: unknown;
    }

    // Load import stats & related data on mount
    useEffect(() => {
    const loadImportStats = () => {
    const importStats = getImportStats();
    if (!importStats) return;

    const statusCounts = importStats.statusCounts || {};
    setStats((prev) => ({
    ...prev,
    total: importStats.total || 0,
    reading: statusCounts.reading || 0,
    completed: statusCounts.completed || 0,
    dropped: statusCounts.dropped || 0,
    onHold: statusCounts.on_hold || 0,
    planToRead: statusCounts.plan_to_read || 0,
    lastSync: importStats.timestamp || null,
    }));
    };

    const parseMatchResults = () => {
    try {
    const matchResultsStr = localStorage.getItem("match_results");
    if (!matchResultsStr) {
    setMatchStatus({
    pendingMatches: 0,
    skippedMatches: 0,
    totalMatches: 0,
    status: "none",
    });
    return;
    }

    const matchResults = JSON.parse(matchResultsStr) || {};
    const entries = Object.values(matchResults);
    const totalCount = entries.length;

    if (totalCount === 0) {
    setMatchStatus({
    pendingMatches: 0,
    skippedMatches: 0,
    totalMatches: 0,
    status: "none",
    });
    return;
    }

    let pendingCount = 0;
    let skippedCount = 0;

    for (const result of entries) {
    const matchResult = result as MatchResult;

    if (matchResult.status === "skipped") {
    skippedCount++;
    continue;
    }

    const needsReview =
    matchResult.status === "pending" ||
    (matchResult.needsReview === true && !matchResult.selectedMatch) ||
    (matchResult.status !== "skipped" && !matchResult.selectedMatch);

    if (needsReview) pendingCount++;
    }

    setMatchStatus({
    pendingMatches: pendingCount,
    skippedMatches: skippedCount,
    totalMatches: totalCount,
    status: pendingCount === 0 ? "complete" : "pending",
    });
    } catch (error) {
    console.error("Error retrieving match status:", error);
    }
    };

    const loadSyncStats = () => {
    try {
    const raw = storage.getItem(STORAGE_KEYS.SYNC_STATS) || "{}";
    const parsed = JSON.parse(raw);
    setSyncStats({
    lastSyncTime: parsed.lastSyncTime || null,
    entriesSynced: parsed.entriesSynced || 0,
    failedSyncs: parsed.failedSyncs || 0,
    totalSyncs: parsed.totalSyncs || 0,
    });
    } catch {
    setSyncStats({
    lastSyncTime: null,
    entriesSynced: 0,
    failedSyncs: 0,
    totalSyncs: 0,
    });
    }
    };

    loadImportStats();
    parseMatchResults();
    loadSyncStats();
    }, []);

    const formatNumber = (value: number) => value.toLocaleString();

    // Format date for display
    const formatDate = (dateString: string | null) => {
    if (!dateString) return "Never";

    try {
    const date = new Date(dateString);
    return (
    date.toLocaleDateString() +
    " " +
    date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
    );
    } catch {
    return "Invalid date";
    }
    };

    const heroAction = useMemo(() => {
    if (!authState.isAuthenticated) {
    return {
    label: "Connect AniList",
    href: "/settings",
    tone: "from-blue-500 via-indigo-500 to-purple-500",
    };
    }

    if (stats.total === 0) {
    return {
    label: "Start Import",
    href: "/import",
    tone: "from-green-500 via-emerald-500 to-teal-500",
    };
    }

    if (matchStatus.pendingMatches > 0) {
    return {
    label: "Review Matches",
    href: "/review",
    tone: "from-amber-500 via-orange-500 to-rose-500",
    };
    }

    if (syncStats.totalSyncs === 0) {
    return {
    label: "Configure Sync",
    href: "/settings",
    tone: "from-purple-500 via-blue-500 to-indigo-500",
    };
    }

    return {
    label: "Run Sync",
    href: "/sync",
    tone: "from-fuchsia-500 via-purple-500 to-blue-500",
    };
    }, [
    authState.isAuthenticated,
    stats.total,
    matchStatus.pendingMatches,
    syncStats.totalSyncs,
    ]);

    const heroHighlights = useMemo(
    () => [
    {
    label: "Imported Entries",
    value: stats.total,
    icon: Library,
    accent: "text-blue-500 dark:text-blue-400",
    },
    {
    label: "Pending Review",
    value: matchStatus.pendingMatches,
    icon: ClipboardCheck,
    accent: "text-amber-500 dark:text-amber-400",
    },
    {
    label: "Entries Synced",
    value: syncStats.entriesSynced,
    icon: CheckCheck,
    accent: "text-emerald-500 dark:text-emerald-400",
    },
    ],
    [stats.total, matchStatus.pendingMatches, syncStats.entriesSynced],
    );

    const statusBreakdown = useMemo(
    () => [
    {
    label: "Reading",
    value: stats.reading,
    gradient: "from-sky-500 to-blue-500",
    },
    {
    label: "Completed",
    value: stats.completed,
    gradient: "from-green-500 to-emerald-500",
    },
    {
    label: "On Hold",
    value: stats.onHold,
    gradient: "from-amber-500 to-orange-500",
    },
    {
    label: "Plan to Read",
    value: stats.planToRead,
    gradient: "from-purple-500 to-indigo-500",
    },
    {
    label: "Dropped",
    value: stats.dropped,
    gradient: "from-rose-500 to-red-500",
    },
    ],
    [
    stats.reading,
    stats.completed,
    stats.onHold,
    stats.planToRead,
    stats.dropped,
    ],
    );

    let matchStatusText: string;
    if (matchStatus.status === "none") {
    matchStatusText = "Waiting";
    } else if (matchStatus.status === "pending") {
    matchStatusText = "Needs Review";
    } else {
    matchStatusText = "Complete";
    }

    const syncSuccessRate =
    syncStats.entriesSynced + syncStats.failedSyncs > 0
    ? Math.round(
    (syncStats.entriesSynced /
    Math.max(syncStats.entriesSynced + syncStats.failedSyncs, 1)) *
    100,
    )
    : null;

    let reviewFootnote: string;
    if (matchStatus.pendingMatches > 0) {
    reviewFootnote = `${formatNumber(matchStatus.pendingMatches)} pending`;
    } else if (matchStatus.status === "complete") {
    reviewFootnote = "All clear";
    } else {
    reviewFootnote = "Auto-matched";
    }

    const reviewAction =
    stats.total > 0
    ? {
    key: "review",
    label: "Review matches",
    description: "Verify smart matches before syncing",
    to: "/review",
    icon: ClipboardCheck,
    tone: "from-emerald-500/20 via-green-500/20 to-transparent",
    iconClass: "text-emerald-600 dark:text-emerald-300",
    badgeClass:
    "bg-emerald-500/20 text-emerald-700 dark:text-emerald-300",
    footnote: reviewFootnote,
    }
    : {
    key: "connect",
    label: authState.isAuthenticated
    ? "AniList connected"
    : "Connect AniList",
    description: authState.isAuthenticated
    ? authState.username || "Authenticated user"
    : "Authorize AniList to unlock syncing",
    to: "/settings",
    icon: authState.isAuthenticated ? UserCheck : AlertCircle,
    tone: "from-purple-500/20 via-blue-500/20 to-transparent",
    iconClass: authState.isAuthenticated
    ? "text-emerald-600 dark:text-emerald-300"
    : "text-blue-600 dark:text-blue-300",
    badgeClass: authState.isAuthenticated
    ? "bg-emerald-500/20 text-emerald-700 dark:text-emerald-300"
    : "bg-blue-500/20 text-blue-700 dark:text-blue-300",
    footnote: authState.isAuthenticated
    ? "Ready to review"
    : "Authentication required",
    };

    const quickActionConfigs = [
    {
    key: "import",
    label: "Import data",
    description: "Upload your Kenmei CSV export",
    to: "/import",
    icon: Download,
    tone: "from-blue-500/20 via-indigo-500/20 to-transparent",
    iconClass: "text-blue-600 dark:text-blue-300",
    badgeClass: "bg-blue-500/20 text-blue-700 dark:text-blue-300",
    footnote:
    stats.total > 0
    ? `${formatNumber(stats.total)} imported`
    : "New import",
    },
    reviewAction,
    {
    key: "sync",
    label: "Synchronize",
    description: "Push your curated list to AniList",
    to: "/sync",
    icon: RefreshCw,
    tone: "from-fuchsia-500/20 via-purple-500/20 to-transparent",
    iconClass: "text-purple-600 dark:text-purple-300",
    badgeClass: "bg-fuchsia-500/20 text-purple-700 dark:text-purple-300",
    footnote:
    syncStats.entriesSynced > 0
    ? `${formatNumber(syncStats.entriesSynced)} synced`
    : "Ready when reviewed",
    },
    {
    key: "settings",
    label: "Settings",
    description: "Tune sync priorities and privacy rules",
    to: "/settings",
    icon: Settings,
    tone: "from-amber-500/20 via-orange-500/20 to-transparent",
    iconClass: "text-amber-600 dark:text-amber-300",
    badgeClass: "bg-amber-500/20 text-amber-700 dark:text-amber-300",
    footnote: "Customize automation",
    },
    ];

    return (
    <div className="relative min-h-screen overflow-hidden">
    <div className="pointer-events-none absolute inset-0">
    <div className="absolute top-[8%] -left-1/3 h-[420px] w-[420px] rounded-full bg-gradient-to-br from-blue-500/25 via-purple-500/20 to-transparent blur-3xl" />
    <div className="absolute top-[35%] right-[-10%] h-[320px] w-[320px] rounded-full bg-gradient-to-br from-emerald-400/20 via-teal-400/20 to-transparent blur-[140px]" />
    <div className="absolute bottom-[-20%] left-1/2 h-[280px] w-[480px] -translate-x-1/2 rounded-full bg-gradient-to-br from-amber-300/20 via-pink-300/20 to-transparent blur-[200px]" />
    </div>

    <motion.div
    className="relative z-[1] container mx-auto px-4 py-10 md:px-6"
    initial={{ opacity: 0 }}
    animate={{ opacity: 1 }}
    transition={{ duration: 0.3 }}
    >
    <motion.section
    className="mb-12"
    variants={itemVariants}
    initial="hidden"
    animate="show"
    >
    <div className="relative overflow-hidden rounded-3xl border border-white/30 bg-gradient-to-br from-white/85 via-white/60 to-white/30 p-8 shadow-2xl backdrop-blur-lg dark:border-white/10 dark:from-slate-950/70 dark:via-slate-950/60 dark:to-slate-950/40">
    <div className="pointer-events-none absolute top-[-140px] -left-32 h-64 w-64 rounded-full bg-gradient-to-br from-blue-500/25 via-purple-500/20 to-transparent blur-3xl" />
    <div className="pointer-events-none absolute right-[-40px] bottom-[-140px] h-64 w-64 rounded-full bg-gradient-to-br from-fuchsia-500/25 via-purple-500/15 to-transparent blur-3xl" />
    <div className="relative z-[1] flex flex-col gap-10 lg:flex-row lg:items-center">
    <div className="space-y-6 lg:flex-1">
    <Badge
    variant="outline"
    className="text-foreground/70 w-fit rounded-full border-white/40 bg-white/80 px-3 py-1 text-xs font-semibold tracking-[0.2em] uppercase shadow-sm backdrop-blur dark:border-white/10 dark:bg-white/10"
    >
    KenmeiAniList
    </Badge>
    <div className="space-y-4">
    <h1 className="text-foreground text-4xl font-semibold tracking-tight md:text-5xl lg:text-6xl">
    Move your Kenmei library to AniList with confidence
    </h1>
    <p className="text-muted-foreground text-lg md:max-w-2xl">
    A simple, safe tool to import, match, and synchronize your
    manga collection from Kenmei to AniListwith smart
    matching and flexible sync options.
    </p>
    </div>
    <div className="flex flex-col gap-3 sm:flex-row sm:items-center">
    <Button
    asChild
    size="lg"
    className={`group h-auto rounded-full bg-gradient-to-r ${heroAction.tone} px-6 py-3 text-base font-semibold text-white shadow-lg transition hover:shadow-xl focus-visible:ring-2 focus-visible:ring-white/70 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-slate-950`}
    >
    <Link
    to={heroAction.href}
    className="flex items-center gap-2"
    >
    <span>{heroAction.label}</span>
    <ArrowUpRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
    </Link>
    </Button>
    <Button
    asChild
    variant="outline"
    size="lg"
    className="text-foreground hover:border-primary/50 hover:text-primary focus-visible:ring-primary/30 dark:hover:border-primary/50 dark:hover:text-primary h-auto rounded-full border-white/60 bg-white/75 px-6 py-3 text-base font-semibold shadow-sm transition focus-visible:ring-2 focus-visible:ring-offset-2 dark:border-white/20 dark:bg-slate-950/60 dark:focus-visible:ring-offset-slate-950"
    >
    <a
    href="https://github.com/RLAlpha49/KenmeiToAnilist/blob/master/docs/guides/USER_GUIDE.md"
    target="_blank"
    rel="noreferrer"
    className="inline-flex items-center gap-2"
    >
    Quickstart guide
    <ExternalLink className="h-4 w-4" />
    </a>
    </Button>
    </div>
    </div>
    <div className="grid gap-4 sm:grid-cols-3 lg:w-80 lg:grid-cols-1">
    {heroHighlights.map((metric) => {
    const Icon = metric.icon;
    return (
    <div
    key={metric.label}
    className="group rounded-2xl border border-white/40 bg-white/80 p-4 shadow-sm backdrop-blur-sm transition hover:-translate-y-1 hover:shadow-xl dark:border-white/10 dark:bg-slate-950/70"
    >
    <div className="flex h-10 w-10 items-center justify-center rounded-full bg-white/70 shadow-sm dark:bg-slate-900/80">
    <Icon className={`h-5 w-5 ${metric.accent}`} />
    </div>
    <p className="mt-3 text-2xl font-semibold">
    {formatNumber(metric.value)}
    </p>
    <p className="text-muted-foreground text-sm">
    {metric.label}
    </p>
    </div>
    );
    })}
    </div>
    </div>
    </div>
    </motion.section>

    <motion.section
    className="mb-12 space-y-6"
    variants={itemVariants}
    initial="hidden"
    animate="show"
    >
    <Carousel
    opts={{
    align: "start",
    loop: true,
    }}
    plugins={[
    Autoplay({
    delay: 4000,
    stopOnInteraction: false,
    stopOnMouseEnter: true,
    }),
    ]}
    className="w-full"
    >
    <CarouselContent className="-ml-4">
    {featureCards.map((feature) => (
    <CarouselItem
    key={feature.title}
    className="pl-4 md:basis-1/2 lg:basis-1/3"
    >
    <div className="p-1">
    <Card className="relative h-full overflow-hidden border border-white/20 bg-white/70 shadow-lg backdrop-blur dark:border-white/10 dark:bg-slate-950/70">
    <div
    className={`absolute inset-x-0 top-0 h-1.5 bg-gradient-to-r ${feature.color}`}
    />
    <CardContent className="flex h-full flex-col justify-between p-6">
    <div>
    <div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-full bg-gradient-to-br from-blue-100 to-indigo-100 text-blue-700 shadow-sm dark:from-blue-900/20 dark:to-indigo-900/20 dark:text-blue-300">
    {feature.icon}
    </div>
    <h3 className="text-foreground mb-2 text-xl font-semibold">
    {feature.title}
    </h3>
    <p className="text-muted-foreground text-sm">
    {feature.description}
    </p>
    </div>
    </CardContent>
    </Card>
    </div>
    </CarouselItem>
    ))}
    </CarouselContent>
    <div className="mt-4 flex justify-end gap-2">
    <CarouselPrevious className="static translate-y-0" />
    <CarouselNext className="static translate-y-0" />
    </div>
    </Carousel>
    </motion.section>

    <motion.section
    className="mb-12 grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3"
    variants={containerVariants}
    initial="hidden"
    animate="show"
    >
    <motion.div variants={itemVariants}>
    <Card className="relative overflow-hidden border border-blue-500/20 bg-gradient-to-br from-blue-500/15 via-indigo-500/10 to-blue-500/5 p-6 shadow-xl backdrop-blur-sm dark:border-blue-500/20 dark:from-blue-500/20 dark:via-indigo-500/20 dark:to-blue-500/10">
    <div className="absolute top-[-40px] right-[-40px] h-40 w-40 rounded-full bg-blue-500/20 blur-3xl" />
    <CardHeader className="flex flex-col gap-2 p-0 pb-4">
    <CardTitle className="flex items-center gap-2 text-lg font-semibold text-blue-700 dark:text-blue-200">
    <div className="flex h-10 w-10 items-center justify-center rounded-full bg-white/40 text-blue-600 shadow-sm dark:bg-slate-900/60">
    <Library className="h-5 w-5" />
    </div>
    Imported Library
    </CardTitle>
    <CardDescription className="text-sm text-blue-900/70 dark:text-blue-100/70">
    {stats.total > 0
    ? "Current snapshot from your Kenmei export."
    : "Import your Kenmei CSV to populate the dashboard."}
    </CardDescription>
    </CardHeader>
    <CardContent className="space-y-4 p-0">
    <p className="text-4xl font-bold text-blue-700 dark:text-blue-200">
    {formatNumber(stats.total)}
    </p>
    <div className="flex items-center gap-2 text-sm text-blue-900/70 dark:text-blue-100/70">
    <Clock className="h-4 w-4 text-blue-500" />
    <span>
    {stats.total > 0
    ? `Last import ${formatDate(stats.lastSync)}`
    : "Awaiting first import"}
    </span>
    </div>
    </CardContent>
    </Card>
    </motion.div>

    <motion.div variants={itemVariants}>
    <Card className="relative overflow-hidden border border-emerald-500/20 bg-gradient-to-br from-emerald-500/15 via-green-500/10 to-emerald-500/5 p-6 shadow-xl backdrop-blur-sm dark:border-emerald-500/20 dark:from-emerald-500/20 dark:via-green-500/20 dark:to-emerald-500/10">
    <div className="absolute top-[60px] left-[-60px] h-40 w-40 rounded-full bg-emerald-500/20 blur-3xl" />
    <CardHeader className="flex flex-col gap-2 p-0 pb-4">
    <CardTitle className="flex items-center gap-2 text-lg font-semibold text-emerald-700 dark:text-emerald-200">
    <div className="flex h-10 w-10 items-center justify-center rounded-full bg-white/40 text-emerald-600 shadow-sm dark:bg-slate-900/60">
    <ClipboardCheck className="h-5 w-5" />
    </div>
    Match Review
    </CardTitle>
    <CardDescription className="text-sm text-emerald-900/70 dark:text-emerald-100/70">
    Resolve matches before syncing to ensure accuracy.
    </CardDescription>
    </CardHeader>
    <CardContent className="space-y-4 p-0">
    <div className="flex items-center gap-3">
    <p className="text-4xl font-bold text-emerald-700 dark:text-emerald-200">
    {matchStatusText}
    </p>
    {(() => {
    let badgeClass = "";
    if (matchStatus.status === "complete") {
    badgeClass =
    "bg-emerald-500/20 text-emerald-900 dark:text-emerald-200";
    } else if (matchStatus.status === "pending") {
    badgeClass =
    "bg-amber-400/20 text-amber-900 dark:text-amber-300";
    } else {
    badgeClass = "bg-muted text-muted-foreground";
    }
    let badgeText = "";
    if (matchStatus.status === "pending") {
    badgeText = `${formatNumber(matchStatus.pendingMatches)} waiting`;
    } else if (matchStatus.status === "complete") {
    badgeText = "Review complete";
    } else {
    badgeText = "Import first";
    }
    return (
    <Badge
    variant="outline"
    className={`rounded-full border-transparent px-3 py-1 text-xs font-semibold ${badgeClass}`}
    >
    {badgeText}
    </Badge>
    );
    })()}
    </div>
    <div className="flex flex-wrap gap-2 text-xs text-emerald-900/70 dark:text-emerald-100/70">
    {matchStatus.totalMatches > 0 && (
    <span className="inline-flex items-center gap-1 rounded-full bg-white/60 px-3 py-1 shadow-sm dark:bg-slate-900/70">
    <BarChart2 className="h-3.5 w-3.5 text-emerald-500" />
    {formatNumber(matchStatus.totalMatches)} total matches
    </span>
    )}
    {matchStatus.skippedMatches > 0 && (
    <span className="inline-flex items-center gap-1 rounded-full bg-white/60 px-3 py-1 shadow-sm dark:bg-slate-900/70">
    <AlertCircle className="h-3.5 w-3.5 text-blue-500" />
    {formatNumber(matchStatus.skippedMatches)} skipped
    </span>
    )}
    </div>
    </CardContent>
    </Card>
    </motion.div>

    <motion.div variants={itemVariants}>
    <Card className="relative overflow-hidden border border-purple-500/20 bg-gradient-to-br from-purple-500/15 via-fuchsia-500/10 to-purple-500/5 p-6 shadow-xl backdrop-blur-sm dark:border-purple-500/20 dark:from-purple-500/20 dark:via-fuchsia-500/20 dark:to-purple-500/10">
    <div className="absolute top-[40px] right-[-70px] h-48 w-48 rounded-full bg-purple-500/25 blur-3xl" />
    <CardHeader className="flex flex-col gap-2 p-0 pb-4">
    <CardTitle className="flex items-center gap-2 text-lg font-semibold text-purple-700 dark:text-purple-200">
    <div className="flex h-10 w-10 items-center justify-center rounded-full bg-white/40 text-purple-600 shadow-sm dark:bg-slate-900/60">
    <Sparkles className="h-5 w-5" />
    </div>
    Sync Pulse
    </CardTitle>
    <CardDescription className="text-sm text-purple-900/70 dark:text-purple-100/70">
    Track how your latest syncs are performing.
    </CardDescription>
    </CardHeader>
    <CardContent className="space-y-3 p-0 text-sm text-purple-900/80 dark:text-purple-100/80">
    <div className="flex items-center justify-between">
    <span className="text-foreground font-medium">Last sync</span>
    <span>
    {syncStats.lastSyncTime
    ? formatDate(syncStats.lastSyncTime)
    : "Not yet"}
    </span>
    </div>
    <div className="flex items-center justify-between">
    <span className="text-foreground font-medium">
    Entries synced
    </span>
    <span>{formatNumber(syncStats.entriesSynced)}</span>
    </div>
    <div className="flex items-center justify-between">
    <span className="text-foreground font-medium">
    Failed syncs
    </span>
    <span>{formatNumber(syncStats.failedSyncs)}</span>
    </div>
    <div className="flex items-center justify-between">
    <span className="text-foreground font-medium">
    Total sync runs
    </span>
    <span>{formatNumber(syncStats.totalSyncs)}</span>
    </div>
    {syncSuccessRate !== null && (
    <div className="flex items-center justify-between rounded-xl bg-white/60 px-3 py-2 text-xs font-semibold tracking-wide text-purple-700 uppercase shadow-sm dark:bg-slate-900/60 dark:text-purple-200">
    <span>Reliability</span>
    <span>{syncSuccessRate}% success</span>
    </div>
    )}
    </CardContent>
    </Card>
    </motion.div>
    </motion.section>

    <motion.section
    className="mb-12"
    variants={itemVariants}
    initial="hidden"
    animate="show"
    >
    <Card className="relative overflow-hidden border border-white/30 bg-white/80 p-6 shadow-xl backdrop-blur dark:border-white/10 dark:bg-slate-950/70">
    <CardHeader className="space-y-2 p-0 pb-4">
    <CardTitle className="text-xl font-semibold">
    Status distribution
    </CardTitle>
    <CardDescription>
    See how your library breaks down by reading state.
    </CardDescription>
    </CardHeader>
    <CardContent className="space-y-4 p-0">
    {statusBreakdown.map((status) => {
    const percent =
    stats.total > 0
    ? Math.round((status.value / stats.total) * 100)
    : 0;
    return (
    <div key={status.label} className="space-y-2">
    <div className="flex items-center justify-between text-sm">
    <span className="text-foreground font-medium">
    {status.label}
    </span>
    <span className="text-muted-foreground">
    {formatNumber(status.value)}{" "}
    {status.value === 1 ? "entry" : "entries"} • {percent}%
    </span>
    </div>
    <div className="bg-muted relative h-2.5 overflow-hidden rounded-full">
    <div
    className={`absolute inset-y-0 left-0 rounded-full bg-gradient-to-r ${status.gradient}`}
    style={{ width: `${percent}%` }}
    />
    </div>
    </div>
    );
    })}
    {stats.total === 0 && (
    <p className="text-muted-foreground text-sm">
    Import your Kenmei CSV to unlock detailed visualizations.
    </p>
    )}
    </CardContent>
    </Card>
    </motion.section>

    <motion.section
    className="mb-12"
    variants={itemVariants}
    initial="hidden"
    animate="show"
    >
    <Card className="border border-white/30 bg-white/80 shadow-xl backdrop-blur dark:border-white/10 dark:bg-slate-950/70">
    <CardHeader className="space-y-2">
    <CardTitle className="flex items-center gap-2 text-xl">
    <Sparkles className="h-5 w-5 text-blue-500" />
    Quick actions
    </CardTitle>
    <CardDescription>
    Jump straight into the next best move for your migration.
    </CardDescription>
    </CardHeader>
    <CardContent className="space-y-6">
    <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
    {quickActionConfigs.map((action) => {
    const ActionIcon = action.icon;
    return (
    <Button
    key={action.key}
    asChild
    variant="outline"
    className={`group h-full w-full justify-start gap-4 rounded-2xl border border-transparent bg-gradient-to-br ${action.tone} dark:hover:border-primary/40 p-4 text-left transition hover:-translate-y-1 hover:border-white/40 hover:shadow-xl`}
    >
    <Link
    to={action.to}
    className="flex w-full items-center gap-4"
    >
    <div className="flex h-12 w-12 items-center justify-center rounded-xl bg-white/70 shadow-sm dark:bg-slate-900/70">
    <ActionIcon
    className={`h-5 w-5 ${action.iconClass}`}
    />
    </div>
    <div className="flex-1 space-y-1">
    <p className="text-foreground text-sm font-semibold">
    {action.label}
    </p>
    <p className="text-muted-foreground text-xs">
    {action.description}
    </p>
    </div>
    <div className="flex flex-col items-end gap-2">
    {action.footnote && (
    <Badge
    variant="outline"
    className={`rounded-full border-transparent px-2 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase ${action.badgeClass}`}
    >
    {action.footnote}
    </Badge>
    )}
    <ChevronRight className="text-muted-foreground h-4 w-4 transition group-hover:translate-x-1" />
    </div>
    </Link>
    </Button>
    );
    })}
    </div>
    </CardContent>
    </Card>
    </motion.section>

    <motion.section variants={itemVariants} initial="hidden" animate="show">
    <Card className="border border-white/30 bg-gradient-to-r from-white/70 via-white/50 to-white/30 text-center shadow-lg backdrop-blur dark:border-white/10 dark:from-slate-950/70 dark:via-slate-950/60 dark:to-slate-950/40">
    <CardContent className="flex flex-col items-center gap-2 py-6">
    <p className="text-muted-foreground text-sm">
    Kenmei to AniList Sync ToolVersion {getAppVersion()}
    </p>
    <div className="flex items-center gap-3">
    {(() => {
    if (versionStatus === null) {
    return (
    <Badge
    variant="outline"
    className="text-muted-foreground rounded-full border-transparent bg-white/60 px-3 py-1 text-xs font-normal dark:bg-white/10"
    >
    Checking...
    </Badge>
    );
    }
    if (versionStatus.status === "stable") {
    return (
    <Badge
    variant="outline"
    className="rounded-full border-transparent bg-emerald-500/20 px-3 py-1 text-xs font-normal text-emerald-800 dark:text-emerald-200"
    >
    Stable release
    </Badge>
    );
    }
    if (versionStatus.status === "beta") {
    return (
    <Badge
    variant="outline"
    className="rounded-full border-transparent bg-amber-400/20 px-3 py-1 text-xs font-normal text-amber-900 dark:text-amber-200"
    >
    Beta build
    </Badge>
    );
    }
    return (
    <Badge
    variant="outline"
    className="rounded-full border-transparent bg-blue-500/20 px-3 py-1 text-xs font-normal text-blue-800 dark:text-blue-200"
    >
    Development build
    </Badge>
    );
    })()}
    <a
    href="https://github.com/RLAlpha49/KenmeiToAnilist"
    target="_blank"
    rel="noopener noreferrer"
    className="text-muted-foreground hover:text-foreground inline-flex items-center gap-1 text-xs font-medium transition-colors"
    >
    <ExternalLink className="h-3 w-3" />
    GitHub
    </a>
    </div>
    <p className="text-muted-foreground/70 text-xs">
    Made with ❤️ for manga readers
    </p>
    </CardContent>
    </Card>
    </motion.section>
    </motion.div>
    </div>
    );
    }