import React, { useEffect, useState } from "react";
import { createRoot } from "react-dom/client";
import {
  ArrowRight,
  BarChart3,
  BookOpen,
  BellRing,
  CheckCircle2,
  Cloud,
  Code2,
  Command,
  Database,
  Download,
  Github,
  GitCompare,
  History,
  Heart,
  Layers,
  Play,
  Search,
  ShieldCheck,
  Shuffle,
  Terminal,
  Users,
  Zap,
} from "lucide-react";
import "./styles.css";

const repoUrl = "https://github.com/dark-hxx/CLI-Manager";
const releaseUrl = "https://github.com/dark-hxx/CLI-Manager/releases";
const version = "V1.3.8";
const asset = (path) => `${import.meta.env.BASE_URL}${path}`;

const signalIcons = [BellRing, GitCompare, BarChart3, Terminal];
const featureIcons = [BellRing, History, BarChart3, Terminal, Shuffle, Cloud, ShieldCheck, Users, Heart];
const workflowIcons = [Play, Code2, Search];
const showcaseImages = [
  "screenshots/main.png",
  "screenshots/notifications.gif",
  "screenshots/realtime-stats.png",
  "screenshots/history.png",
  "screenshots/usage-dashboard.png",
  "screenshots/providers.png",
];

const i18n = {
  zh: {
    htmlLang: "zh-CN",
    title: "CLI-Manager | AI CLI 工作台",
    description:
      "CLI-Manager V1.3.8 是面向 Claude Code 与 Codex CLI 的多项目 AI CLI 工作台，覆盖终端、11 类历史来源、Hook 通知、Diff 回看、用量统计、SSH 与手机协作。",
    aria: {
      home: "CLI-Manager 首页",
      nav: "主导航",
      signals: "产品能力概览",
      heroActions: "主要操作",
      quickCommand: "快速开始命令",
      workflow: "CLI-Manager 工作流",
      language: "Switch language to English",
      openPreview: "放大查看截图",
      closePreview: "关闭截图预览",
      communityQrAlt: "CLI-Manager 微信交流群二维码",
    },
    nav: {
      features: "能力",
      showcase: "预览",
      workflow: "工作流",
      sponsors: "赞助商",
      manual: "使用手册",
      get: "获取",
      github: "GitHub",
      language: "EN",
    },
    hero: {
      eyebrow: "Cross-platform AI CLI Workspace",
      title: "CLI-Manager",
      lead:
        "面向 Claude Code 与 Codex CLI 的多项目终端工作台。Hook 通知、11 类来源历史、Diff 回看、Token 统计、SSH 远程与供应商路由都在一个桌面应用里完成。",
      primary: "下载 Release",
      secondary: "查看源码",
      command: "launch --project AI-workspace --with-hooks",
      screenAlt: "CLI-Manager 主界面截图",
    },
    signals: [
      { label: "Hook 桥接", value: "Claude / Codex" },
      { label: "历史来源", value: "11 类 CLI" },
      { label: "用量雷达", value: "Token / 成本" },
      { label: "远程协作", value: "SSH / 手机" },
    ],
    featuresSection: {
      eyebrow: "Core System",
      title: "让 AI CLI 任务状态清晰可控",
      text:
        "从审批提醒到执行结果，从会话历史到成本统计，CLI-Manager 把分散在终端、配置和历史文件里的上下文集中起来。",
    },
    features: [
      {
        title: "AI CLI Hook 通知",
        text:
          "Claude Code 或 Codex CLI 等待审批、完成或失败时，桌面通知和 Tab 状态同步出现，任务不会静默卡住。",
      },
      {
        title: "会话历史与 Diff 回看",
        text:
          "把 Claude / Codex 历史会话集中管理，按项目、来源和时间检索，并从代码变更跳回触发消息。",
      },
      {
        title: "实时 Token 与费用统计",
        text:
          "在每个终端会话里查看 input、output、cache token、模型上下文和工具调用明细。",
      },
      {
        title: "多项目终端工作台",
        text: "项目树、内置 PTY 终端、Tab、分屏和拖拽布局集中在一个桌面窗口里。",
      },
      {
        title: "供应商目录与故障转移",
        text:
          "维护 Claude、Codex、Grok Build 供应商与密钥，按项目切换，并通过本地路由配置健康检查和自动故障转移。",
      },
      {
        title: "命令模板与云同步",
        text:
          "常用命令、项目配置、快捷键和设置可以沉淀复用，并通过 WebDAV 在多设备之间同步。",
      },
      {
        title: "SSH 远程开发",
        text: "管理 SSH Config、代理、跳板机和远端 Agent，在同一工作区启动远程 AI CLI。",
      },
      {
        title: "cc-connect 手机对话",
        text: "通过 Telegram 或飞书继续 Claude Code / Codex 会话，项目授权和凭据由桌面主机托管。",
      },
      {
        title: "Worktree 与桌面宠物",
        text: "用 Git Worktree 隔离并行任务，以桌面宠物展示运行状态，支持 .clipet 宠物包。",
      },
    ],
    sponsorsSection: {
      eyebrow: "Community Sponsors",
      title: "感谢支持独立开发",
      text: "赞助商帮助我们持续维护跨平台终端、历史索引与远程协作能力。",
      visit: "访问赞助商",
      sponsor: {
        name: "Fluxion AI",
        tagline: "一个入口，接入并管理全球主流 AI 模型",
        text: "Fluxion AI 面向个人开发者、技术团队与企业，通过统一 API 接入全球主流 AI 模型，以多线路调度提升可用性，并集中管理模型质量、使用情况与费用。",
        href: "https://fluxionai.space/register?source=github&campaign=climanager",
      },
    },
    showcaseSection: {
      eyebrow: "Product Preview",
      title: "产品界面预览",
      text:
        "核心工作区、Hook 通知、实时统计、历史回看和供应商管理都来自实际产品界面，方便快速理解 CLI-Manager 的工作方式。",
    },
    showcases: [
      {
        title: "终端工作区",
        desc: "项目树、Tab、分屏和内置终端在同一工作流里协同。",
        alt: "CLI-Manager 主界面",
      },
      {
        title: "Hook 通知跳转",
        desc: "收到审批提醒后，点击通知直接回到对应会话。",
        alt: "CLI-Manager Hook 通知跳转动画",
      },
      {
        title: "会话实时统计",
        desc: "当前 AI CLI 会话的 token、费用、分支和工具调用实时可见。",
        alt: "CLI-Manager 实时统计面板",
      },
      {
        title: "历史 Diff 回看",
        desc: "从历史会话中定位代码变更、搜索上下文并复用 Prompt。",
        alt: "CLI-Manager 会话历史",
      },
      {
        title: "用量分析看板",
        desc: "热力图、趋势图、效率散点和项目排行帮助你看清长期成本。",
        alt: "CLI-Manager 用量分析看板",
      },
      {
        title: "供应商管理",
        desc: "集中管理 Claude、Codex、Grok Build 供应商，并按项目切换后端。",
        alt: "CLI-Manager 供应商列表",
      },
    ],
    workflowSection: {
      eyebrow: "Operator Flow",
      title: "一个窗口完成启动、执行和复盘",
      text:
        "多项目开发中，真正消耗注意力的是不断切换终端、历史记录、统计脚本和供应商配置。CLI-Manager 把这些环节收拢到同一个可扫读的工作区。",
      action: "阅读项目 README",
    },
    workflow: [
      {
        eyebrow: "01",
        title: "启动项目",
        text: "从项目树或命令面板启动终端，自动带上路径、Shell、启动命令和环境变量。",
      },
      {
        eyebrow: "02",
        title: "运行 AI CLI",
        text: "Claude Code / Codex CLI 会话被 Hook 绑定，Tab 状态、通知和统计面板跟随更新。",
      },
      {
        eyebrow: "03",
        title: "回看结果",
        text: "完成后从历史工作区检索会话、查看 Diff、定位消息并沉淀可复用 Prompt。",
      },
    ],
    trust: {
      eyebrow: "Built for Local Workflows",
      title: "Tauri + React + Rust，面向真实桌面工作流",
      items: [
        "Windows / macOS 完整测试，Linux 实验支持",
        "Hook 服务仅监听 127.0.0.1 并使用 bearer token",
        "AGPL-3.0-or-later，支持商业授权模式",
      ],
    },
    finalCta: {
      eyebrow: "Power up your AI terminal workflow",
      title: "把 AI CLI 会话变成可观察、可追踪、可复用的工作资产",
      primary: "获取 CLI-Manager",
      secondary: "Star on GitHub",
      communityTitle: "加入交流群",
      communityText: "扫码加入微信群，获取更新动态、使用反馈和技术交流。",
      communityAction: "放大二维码",
    },
    footer: {
      label: "CLI-Manager Website",
    },
  },
  en: {
    htmlLang: "en",
    title: "CLI-Manager | AI CLI Workspace",
    description:
      "CLI-Manager V1.3.8 is a multi-project AI CLI workspace for Claude Code and Codex CLI, bringing terminals, 11 history sources, hooks, diff review, analytics, SSH, and mobile chat together.",
    aria: {
      home: "CLI-Manager home",
      nav: "Primary navigation",
      signals: "Product capability overview",
      heroActions: "Primary actions",
      quickCommand: "Quick start command",
      workflow: "CLI-Manager workflow",
      language: "切换到中文",
      openPreview: "Open screenshot preview",
      closePreview: "Close screenshot preview",
      communityQrAlt: "CLI-Manager WeChat community group QR code",
    },
    nav: {
      features: "Features",
      showcase: "Preview",
      workflow: "Workflow",
      sponsors: "Sponsors",
      manual: "Manual",
      get: "Get",
      github: "GitHub",
      language: "中文",
    },
    hero: {
      eyebrow: "Cross-platform AI CLI Workspace",
      title: "CLI-Manager",
      lead:
        "A multi-project terminal workspace for Claude Code and Codex CLI. Hook notifications, 11 history sources, diff review, token analytics, SSH, and provider routing live in one desktop app.",
      primary: "Download Release",
      secondary: "View Source",
      command: "launch --project AI-workspace --with-hooks",
      screenAlt: "CLI-Manager main interface screenshot",
    },
    signals: [
      { label: "Hook Bridge", value: "Claude / Codex" },
      { label: "History Sources", value: "11 CLI tools" },
      { label: "Usage Radar", value: "Token / Cost" },
      { label: "Remote Access", value: "SSH / Mobile" },
    ],
    featuresSection: {
      eyebrow: "Core System",
      title: "Keep AI CLI tasks visible and controlled",
      text:
        "From approval alerts to execution results, from session history to cost analytics, CLI-Manager brings scattered terminal context into one place.",
    },
    features: [
      {
        title: "AI CLI Hook Notifications",
        text:
          "When Claude Code or Codex CLI waits for approval, completes, or fails, desktop notifications and tab states update together.",
      },
      {
        title: "Session History and Diff Review",
        text:
          "Browse Claude and Codex history in one place, filter by project/source/time, and jump from code changes back to the triggering message.",
      },
      {
        title: "Live Token and Cost Analytics",
        text:
          "Inspect input, output, cache tokens, model context, cost estimates, and tool calls for each terminal session.",
      },
      {
        title: "Multi-project Terminal Workspace",
        text:
          "Project tree, built-in PTY terminal, tabs, splits, and drag layout are organized in a single desktop window.",
      },
      {
        title: "Provider Directory and Failover",
        text:
          "Manage Claude, Codex, and Grok providers, switch per project, and configure health checks with local failover routing.",
      },
      {
        title: "Command Templates and Cloud Sync",
        text:
          "Reuse commands, project settings, shortcuts, and app preferences, then sync them across devices with WebDAV.",
      },
      {
        title: "SSH Remote Development",
        text: "Manage SSH Config, proxies, jump hosts, and the remote Agent while launching AI CLI sessions in the same workspace.",
      },
      {
        title: "cc-connect Mobile Chat",
        text: "Continue Claude Code or Codex sessions through Telegram or Feishu with project authorization managed on the desktop host.",
      },
      {
        title: "Worktrees and Desktop Pets",
        text: "Isolate parallel tasks with Git Worktrees and keep status visible with desktop pets and .clipet packages.",
      },
    ],
    sponsorsSection: {
      eyebrow: "Community Sponsors",
      title: "Built with independent support",
      text: "Sponsors help us keep the cross-platform terminal, history index, and remote workflows maintained.",
      visit: "Visit sponsor",
      sponsor: {
        name: "Fluxion AI",
        tagline: "One entry point for mainstream AI models",
        text: "Fluxion AI gives developers and teams one API for mainstream AI models, with multi-route scheduling and transparent usage and cost management.",
        href: "https://fluxionai.space/register?source=github&campaign=climanager",
      },
    },
    showcaseSection: {
      eyebrow: "Product Preview",
      title: "Product Interface Preview",
      text:
        "Explore the real workspace, hook notifications, live stats, session history, and provider management views from CLI-Manager.",
    },
    showcases: [
      {
        title: "Terminal Workspace",
        desc: "Project tree, tabs, splits, and the built-in terminal work together in one flow.",
        alt: "CLI-Manager main interface",
      },
      {
        title: "Hook Notification Jump",
        desc: "Click an approval notification and return directly to the related session.",
        alt: "CLI-Manager hook notification jump animation",
      },
      {
        title: "Live Session Stats",
        desc: "Token usage, cost, Git branch, and tool calls stay visible while the AI CLI runs.",
        alt: "CLI-Manager live statistics panel",
      },
      {
        title: "Historical Diff Review",
        desc: "Locate code changes, search context, and reuse prompts from previous sessions.",
        alt: "CLI-Manager session history",
      },
      {
        title: "Usage Analytics Dashboard",
        desc: "Heatmaps, trends, efficiency scatter charts, and project ranking expose long-term cost.",
        alt: "CLI-Manager usage analytics dashboard",
      },
      {
        title: "Provider Management",
        desc: "Manage Claude, Codex, and Grok providers, then switch backends per project.",
        alt: "CLI-Manager provider list",
      },
    ],
    workflowSection: {
      eyebrow: "Operator Flow",
      title: "Launch, run, and review in one window",
      text:
        "The expensive part of multi-project development is constant context switching across terminals, history files, analytics scripts, and provider configs. CLI-Manager pulls those steps into one scannable workspace.",
      action: "Read the project README",
    },
    workflow: [
      {
        eyebrow: "01",
        title: "Launch a Project",
        text:
          "Start a terminal from the project tree or command palette with path, shell, startup command, and environment variables applied.",
      },
      {
        eyebrow: "02",
        title: "Run the AI CLI",
        text:
          "Claude Code and Codex CLI sessions are bound through hooks, while tab states, notifications, and stats update in sync.",
      },
      {
        eyebrow: "03",
        title: "Review the Result",
        text:
          "After completion, search the history workspace, inspect diffs, jump to messages, and save reusable prompts.",
      },
    ],
    trust: {
      eyebrow: "Built for Local Workflows",
      title: "Tauri + React + Rust for real desktop work",
      items: [
        "Windows and macOS fully tested, with experimental Linux support",
        "Hook service listens only on 127.0.0.1 and uses bearer token validation",
        "AGPL-3.0-or-later with a commercial licensing path",
      ],
    },
    finalCta: {
      eyebrow: "Power up your AI terminal workflow",
      title: "Turn AI CLI sessions into observable, traceable, reusable work assets",
      primary: "Get CLI-Manager",
      secondary: "Star on GitHub",
      communityTitle: "Join the Community",
      communityText: "Scan the WeChat group QR code for updates, feedback, and technical discussion.",
      communityAction: "Open QR Code",
    },
    footer: {
      label: "CLI-Manager Website",
    },
  },
};

function getInitialLocale() {
  if (typeof window === "undefined") {
    return "zh";
  }

  const saved = window.localStorage.getItem("clim-locale");
  if (saved === "zh" || saved === "en") {
    return saved;
  }

  return window.navigator.language.toLowerCase().startsWith("zh") ? "zh" : "en";
}

function Header({ activeSection, isCommunityOpen, onToggleCommunity, onOpenImage, onToggleLocale, t }) {
  const navItems = [
    { id: "features", label: t.nav.features },
    { id: "showcase", label: t.nav.showcase },
    { id: "workflow", label: t.nav.workflow },
    { id: "sponsors", label: t.nav.sponsors },
    { id: "get", label: t.nav.get },
  ];

  return (
    <header className="site-header">
      <a className="brand" href="#top" aria-label={t.aria.home}>
        <img src={asset("app-icon-32.png")} alt="" />
        <span>CLI-Manager</span>
      </a>
      <nav className="nav-links" aria-label={t.aria.nav}>
        {navItems.map((item) => (
          <a
            className={activeSection === item.id ? "is-active" : undefined}
            href={`#${item.id}`}
            key={item.id}
          >
            {item.label}
          </a>
        ))}
        <a href={asset("manual.html")} target="_blank" rel="noreferrer">
          <BookOpen size={15} aria-hidden="true" />
          {t.nav.manual}
        </a>
      </nav>
      <div className="nav-actions">
        <button className="lang-toggle" type="button" onClick={onToggleLocale} aria-label={t.aria.language}>
          {t.nav.language}
        </button>
        <button
          className={`community-nav-button${isCommunityOpen ? " is-open" : ""}`}
          type="button"
          onClick={onToggleCommunity}
          aria-label={`${t.aria.openPreview}: ${t.finalCta.communityTitle}`}
          aria-expanded={isCommunityOpen}
        >
          <Users size={20} aria-hidden="true" />
        </button>
        {isCommunityOpen ? (
          <button
            className="community-qr-drop"
            type="button"
            onClick={() => {
              onToggleCommunity(false);
              onOpenImage({
                src: asset("wechat-group-qr.png"),
                alt: t.aria.communityQrAlt,
                title: t.finalCta.communityTitle,
              });
            }}
            aria-label={`${t.aria.openPreview}: ${t.finalCta.communityTitle}`}
          >
            <img src={asset("wechat-group-qr.png")} alt="" />
          </button>
        ) : null}
        <a className="icon-link" href={repoUrl} target="_blank" rel="noreferrer">
          <Github size={18} aria-hidden="true" />
          {t.nav.github}
        </a>
      </div>
    </header>
  );
}

function SignalStrip({ t }) {
  return (
    <div className="signal-strip" aria-label={t.aria.signals}>
      {t.signals.map((item, index) => {
        const Icon = signalIcons[index];
        return (
          <div className="signal-item" key={item.label}>
            <Icon size={18} aria-hidden="true" />
            <span>{item.label}</span>
            <strong>{item.value}</strong>
          </div>
        );
      })}
    </div>
  );
}

function Hero({ t }) {
  return (
    <section className="hero section-band" id="top">
      <div className="light-grid" aria-hidden="true" />
      <div className="container hero-content">
        <p className="eyebrow">
          <Zap size={18} aria-hidden="true" />
          {t.hero.eyebrow}
        </p>
        <h1>{t.hero.title}</h1>
        <a className="version-pill" href={releaseUrl} target="_blank" rel="noreferrer">
          {version}
        </a>
        <p className="hero-lead">{t.hero.lead}</p>
        <div className="hero-actions" aria-label={t.aria.heroActions}>
          <a className="primary-action" href={releaseUrl} target="_blank" rel="noreferrer">
            <Download size={19} aria-hidden="true" />
            {t.hero.primary}
          </a>
          <a className="secondary-action" href={repoUrl} target="_blank" rel="noreferrer">
            <Github size={19} aria-hidden="true" />
            {t.hero.secondary}
          </a>
        </div>
        <div className="terminal-line" aria-label={t.aria.quickCommand}>
          <span className="prompt">cli-manager</span>
          <span className="cursor-text">{t.hero.command}</span>
        </div>
      </div>
      <figure className="hero-screen">
        <img src={asset("screenshots/main.png")} alt={t.hero.screenAlt} />
      </figure>
      <div className="container">
        <SignalStrip t={t} />
      </div>
    </section>
  );
}

function Features({ t }) {
  return (
    <section className="section-band features" id="features">
      <div className="container section-heading">
        <p className="eyebrow">
          <Layers size={18} aria-hidden="true" />
          {t.featuresSection.eyebrow}
        </p>
        <h2>{t.featuresSection.title}</h2>
        <p>{t.featuresSection.text}</p>
      </div>
      <div className="container feature-grid">
        {t.features.map((feature, index) => {
          const Icon = featureIcons[index];
          return (
            <article className="feature-card" key={feature.title}>
              <div className="feature-icon">
                <Icon size={24} aria-hidden="true" />
              </div>
              <h3>{feature.title}</h3>
              <p>{feature.text}</p>
            </article>
          );
        })}
      </div>
    </section>
  );
}

function Sponsors({ t }) {
  const { sponsor } = t.sponsorsSection;

  return (
    <section className="section-band sponsors" id="sponsors">
      <div className="container section-heading">
        <p className="eyebrow">
          <Heart size={18} aria-hidden="true" />
          {t.sponsorsSection.eyebrow}
        </p>
        <h2>{t.sponsorsSection.title}</h2>
        <p>{t.sponsorsSection.text}</p>
      </div>
      <div className="container sponsor-card">
        <a className="sponsor-banner" href={sponsor.href} target="_blank" rel="noreferrer">
          <img src={asset("sponsors/fluxion-ai-banner.png")} alt={`${sponsor.name} banner`} loading="lazy" />
        </a>
        <div className="sponsor-body">
          <img className="sponsor-logo" src={asset("sponsors/fluxion-ai-logo.jpg")} alt={`${sponsor.name} logo`} loading="lazy" />
          <div>
            <p className="sponsor-kicker">Community sponsor</p>
            <h3>{sponsor.name}</h3>
            <p className="sponsor-tagline">{sponsor.tagline}</p>
            <p>{sponsor.text}</p>
            <a className="text-action" href={sponsor.href} target="_blank" rel="noreferrer">
              {t.sponsorsSection.visit}
              <ArrowRight size={18} aria-hidden="true" />
            </a>
          </div>
        </div>
      </div>
    </section>
  );
}

function Showcase({ t, onOpenImage }) {
  return (
    <section className="section-band showcase" id="showcase">
      <div className="container section-heading">
        <p className="eyebrow">
          <Database size={18} aria-hidden="true" />
          {t.showcaseSection.eyebrow}
        </p>
        <h2>{t.showcaseSection.title}</h2>
        <p>{t.showcaseSection.text}</p>
      </div>
      <div className="container showcase-grid">
        {t.showcases.map((item, index) => (
          <article className="screenshot-card" key={item.title}>
            <button
              className="screenshot-frame"
              type="button"
              onClick={() =>
                onOpenImage({
                  src: asset(showcaseImages[index]),
                  alt: item.alt,
                  title: item.title,
                })
              }
              aria-label={`${t.aria.openPreview}: ${item.title}`}
            >
              <img src={asset(showcaseImages[index])} alt={item.alt} loading="lazy" />
            </button>
            <h3>{item.title}</h3>
            <p>{item.desc}</p>
          </article>
        ))}
      </div>
    </section>
  );
}

function ImageLightbox({ image, onClose, t }) {
  useEffect(() => {
    if (!image) {
      return undefined;
    }

    const onKeyDown = (event) => {
      if (event.key === "Escape") {
        onClose();
      }
    };

    document.body.classList.add("lightbox-open");
    window.addEventListener("keydown", onKeyDown);

    return () => {
      document.body.classList.remove("lightbox-open");
      window.removeEventListener("keydown", onKeyDown);
    };
  }, [image, onClose]);

  if (!image) {
    return null;
  }

  return (
    <div className="image-lightbox" role="dialog" aria-modal="true" aria-label={image.title}>
      <button className="lightbox-backdrop" type="button" onClick={onClose} aria-label={t.aria.closePreview} />
      <div className="lightbox-panel">
        <div className="lightbox-header">
          <h2>{image.title}</h2>
          <button className="lightbox-close" type="button" onClick={onClose} aria-label={t.aria.closePreview}>
            ×
          </button>
        </div>
        <div className="lightbox-image-frame">
          <img src={image.src} alt={image.alt} />
        </div>
      </div>
    </div>
  );
}

function Workflow({ t }) {
  return (
    <section className="section-band workflow" id="workflow">
      <div className="container workflow-layout">
        <div className="workflow-copy">
          <p className="eyebrow">
            <Command size={18} aria-hidden="true" />
            {t.workflowSection.eyebrow}
          </p>
          <h2>{t.workflowSection.title}</h2>
          <p>{t.workflowSection.text}</p>
          <a className="text-action" href={repoUrl} target="_blank" rel="noreferrer">
            {t.workflowSection.action}
            <ArrowRight size={18} aria-hidden="true" />
          </a>
        </div>
        <div className="workflow-steps" aria-label={t.aria.workflow}>
          {t.workflow.map((step, index) => {
            const Icon = workflowIcons[index];
            return (
              <article className="workflow-step" key={step.title}>
                <span className="step-index">{step.eyebrow}</span>
                <div className="step-icon">
                  <Icon size={22} aria-hidden="true" />
                </div>
                <div>
                  <h3>{step.title}</h3>
                  <p>{step.text}</p>
                </div>
              </article>
            );
          })}
        </div>
      </div>
    </section>
  );
}

function TrustBand({ t }) {
  return (
    <section className="section-band trust-band">
      <div className="container trust-layout">
        <div>
          <p className="eyebrow">
            <ShieldCheck size={18} aria-hidden="true" />
            {t.trust.eyebrow}
          </p>
          <h2>{t.trust.title}</h2>
        </div>
        <ul className="trust-list">
          {t.trust.items.map((item) => (
            <li key={item}>
              <CheckCircle2 size={18} aria-hidden="true" />
              {item}
            </li>
          ))}
        </ul>
      </div>
    </section>
  );
}

function FinalCta({ t, onOpenImage }) {
  return (
    <section className="section-band final-cta" id="get">
      <div className="container final-layout">
        <div>
          <p className="eyebrow">
            <Terminal size={18} aria-hidden="true" />
            {t.finalCta.eyebrow}
          </p>
          <h2>{t.finalCta.title}</h2>
        </div>
        <div className="final-actions">
          <a className="primary-action" href={releaseUrl} target="_blank" rel="noreferrer">
            <Download size={19} aria-hidden="true" />
            {t.finalCta.primary}
          </a>
          <a className="secondary-action" href={repoUrl} target="_blank" rel="noreferrer">
            <Github size={19} aria-hidden="true" />
            {t.finalCta.secondary}
          </a>
        </div>
      </div>
    </section>
  );
}

function App() {
  const [locale, setLocale] = useState(getInitialLocale);
  const [activeSection, setActiveSection] = useState("");
  const [previewImage, setPreviewImage] = useState(null);
  const [isCommunityOpen, setIsCommunityOpen] = useState(false);
  const t = i18n[locale];

  useEffect(() => {
    const sectionIds = ["features", "sponsors", "showcase", "workflow", "get"];
    let frame = 0;

    const updateActiveSection = () => {
      const activationLine = window.scrollY + Math.min(window.innerHeight * 0.36, 320);
      let current = "";

      for (const id of sectionIds) {
        const section = document.getElementById(id);
        if (section && activationLine >= section.offsetTop) {
          current = id;
        }
      }

      setActiveSection((previous) => (previous === current ? previous : current));
    };

    const onScroll = () => {
      if (frame) {
        return;
      }

      frame = window.requestAnimationFrame(() => {
        frame = 0;
        updateActiveSection();
      });
    };

    updateActiveSection();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);

    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      if (frame) {
        window.cancelAnimationFrame(frame);
      }
    };
  }, []);

  useEffect(() => {
    window.localStorage.setItem("clim-locale", locale);
    document.documentElement.lang = t.htmlLang;
    document.title = t.title;
    const description = document.querySelector('meta[name="description"]');
    if (description) {
      description.setAttribute("content", t.description);
    }
  }, [locale, t]);

  const toggleLocale = () => {
    setLocale((current) => (current === "zh" ? "en" : "zh"));
  };

  return (
    <>
      <Header
        activeSection={activeSection}
        isCommunityOpen={isCommunityOpen}
        onToggleCommunity={(value) => setIsCommunityOpen((current) => (typeof value === "boolean" ? value : !current))}
        onOpenImage={setPreviewImage}
        onToggleLocale={toggleLocale}
        t={t}
      />
      <main>
        <Hero t={t} />
        <Features t={t} />
        <Sponsors t={t} />
        <Showcase t={t} onOpenImage={setPreviewImage} />
        <Workflow t={t} />
        <TrustBand t={t} />
        <FinalCta t={t} onOpenImage={setPreviewImage} />
      </main>
      <footer className="site-footer">
        <div className="container footer-layout">
          <span>{t.footer.label} · {version}</span>
          <div>
            <a href={asset("manual.html")} target="_blank" rel="noreferrer">
              {t.nav.manual}
            </a>
            <a href={repoUrl} target="_blank" rel="noreferrer">
              GitHub
            </a>
            <a href={`${repoUrl}/issues`} target="_blank" rel="noreferrer">
              Issues
            </a>
            <a href={`${repoUrl}/blob/main/LICENSE`} target="_blank" rel="noreferrer">
              License
            </a>
          </div>
        </div>
      </footer>
      <ImageLightbox image={previewImage} onClose={() => setPreviewImage(null)} t={t} />
    </>
  );
}

createRoot(document.getElementById("root")).render(<App />);
