// Chichi Fu — landing page sections, restyled in the Liquid Glass UI Kit.

// Lucide-style inline icons
const ArrowRight = ({ className = "", size = 18, style }) => (
  <svg className={className} style={style} width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d="M5 12h14M13 5l7 7-7 7"/>
  </svg>
);
const Check = ({ className = "", size = 14 }) => (
  <svg className={className} width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
    <path d="M20 6 9 17l-5-5"/>
  </svg>
);

// ========== HERO ==========
// Scroll-scrubbed video, pinned only within the hero's tall track.
// The clip's playback position is driven by scroll progress (not looping),
// and the video lives only on the first screen — the sheet below has its
// own light background.
window.Hero = function Hero() {
  const sectionRef = React.useRef(null);
  const videoRef = React.useRef(null);
  const canvasRef = React.useRef(null);
  const fgRef = React.useRef(null);
  const nameRef = React.useRef(null);
  const [nameW, setNameW] = React.useState(null);

  // Pin the subtitle + bio to the rendered width of the name, so the
  // justified subtitle's edges line up exactly with the characters above.
  React.useLayoutEffect(() => {
    const measure = () => {
      if (nameRef.current) setNameW(Math.round(nameRef.current.getBoundingClientRect().width));
    };
    measure();
    window.addEventListener("resize", measure);
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(measure);
    const t = setTimeout(measure, 400);
    return () => { window.removeEventListener("resize", measure); clearTimeout(t); };
  }, []);

  React.useEffect(() => {
    const v = videoRef.current, sec = sectionRef.current, fg = fgRef.current, cv = canvasRef.current;
    if (!v || !sec || !cv) return;
    const ctx = cv.getContext("2d");
    let dur = 0, cur = 0, raf = 0;
    const readDur = () => { dur = isFinite(v.duration) ? v.duration : 0; };
    v.addEventListener("loadedmetadata", readDur);
    if (v.readyState >= 1) readDur();

    // Keep the canvas backing store matched to its displayed size (capped DPR).
    const resize = () => {
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      const r = cv.getBoundingClientRect();
      cv.width = Math.max(1, Math.round(r.width * dpr));
      cv.height = Math.max(1, Math.round(r.height * dpr));
    };
    resize();
    window.addEventListener("resize", resize);

    // Paint the current video frame onto the canvas with object-fit:cover math.
    // Drawing through a canvas sidesteps the browser quirk where a *paused*
    // <video> seeked via script doesn't repaint its on-screen layer.
    const drawFrame = () => {
      const vw = v.videoWidth, vh = v.videoHeight;
      if (!vw || !vh) return;
      const cw = cv.width, ch = cv.height;
      const scale = Math.max(cw / vw, ch / vh);
      const dw = vw * scale, dh = vh * scale;
      try { ctx.drawImage(v, (cw - dw) / 2, (ch - dh) / 2, dw, dh); } catch (e) {}
    };

    const progress = () => {
      const total = sec.offsetHeight - window.innerHeight;
      const top = sec.getBoundingClientRect().top;
      return total > 0 ? Math.min(1, Math.max(0, -top / total)) : 0;
    };
    const tick = () => {
      const p = progress();
      if (dur) {
        const target = p * (dur - 0.05);
        cur += (target - cur) * 0.14;                 // smooth follow
        if (Math.abs(target - cur) < 0.008) cur = target;
        try { v.currentTime = cur; } catch (e) {}
      }
      drawFrame();                                     // composite via canvas every frame
      if (fg) fg.style.opacity = p < 0.82 ? 1 : Math.max(0, 1 - (p - 0.82) / 0.18);
      raf = requestAnimationFrame(tick);
    };
    // prime playback so browsers decode/allow seeking, then paint first frame
    const prime = () => { v.play().then(() => { v.pause(); drawFrame(); }).catch(() => {}); };
    prime();
    // recover from a stalled / failed fetch (flaky networks): retry load once
    let retried = false;
    const recover = () => {
      if (retried) return;
      retried = true;
      try { v.load(); v.play().then(() => { v.pause(); drawFrame(); }).catch(() => {}); } catch (e) {}
    };
    v.addEventListener("error", recover);
    v.addEventListener("stalled", recover);
    // repaint as soon as a seeked frame is actually ready
    const onSeeked = () => drawFrame();
    v.addEventListener("seeked", onSeeked);
    if (typeof v.requestVideoFrameCallback === "function") {
      const rvfc = () => { drawFrame(); v.requestVideoFrameCallback(rvfc); };
      v.requestVideoFrameCallback(rvfc);
    }
    raf = requestAnimationFrame(tick);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", resize);
      v.removeEventListener("loadedmetadata", readDur);
      v.removeEventListener("seeked", onSeeked);
      v.removeEventListener("error", recover);
      v.removeEventListener("stalled", recover);
    };
  }, []);

  return (
    <section className="hero-scroll" ref={sectionRef}>
      <div className="hero-sticky">
        {/* scroll-driven video background, composited through a canvas */}
        <div className="hero-bg">
          <video ref={videoRef} className="hero-video" src="hero-bg.mp4" muted playsInline preload="auto" />
          <canvas ref={canvasRef} className="hero-canvas" />
          <div className="vignette" />
        </div>

        {/* foreground chrome (fades out as the hero hands off) */}
        <div className="hero-fg" ref={fgRef}>
          <nav className="glass-dark nav-glass r-pill absolute top-5 left-1/2 -translate-x-1/2 px-8 py-1 md:px-12 md:py-1.5 z-20 w-[min(760px,84vw)]">
            <ul className="flex items-center justify-between w-full">
              {[
                { label: "关于我", href: "#about" },
                { label: "经历", href: "#experience" },
                { label: "项目", href: "#projects" },
                { label: "合作", href: "#contact" }
              ].map(item => (
                <li key={item.href}>
                  <a
                    href={item.href}
                    className="text-[11px] sm:text-xs md:text-sm tracking-wide whitespace-nowrap transition-colors"
                    style={{ color: "rgba(243,244,246,0.78)" }}
                    onMouseOver={e => (e.currentTarget.style.color = "#fff")}
                    onMouseOut={e => (e.currentTarget.style.color = "rgba(243,244,246,0.78)")}
                  >
                    {item.label}
                  </a>
                </li>
              ))}
            </ul>
          </nav>

          {/* unified pure-text identity module — centered on the page's 7:3 vertical split line */}
          <div className="hero-identity absolute z-10 flex flex-col items-center px-5" style={{ left: "70%", top: "50%", transform: "translate(-50%, -50%)", textAlign: "center" }}>
            <span ref={nameRef} style={{ display: "inline-block" }}>
              <window.WordsPullUp
                text="傅筱湄"
                className="font-semibold leading-[0.92] tracking-[-0.04em] text-[13vw] sm:text-[12vw] md:text-[11vw] lg:text-[10vw] xl:text-[9.5vw] 2xl:text-[10vw]"
                style={{ color: "#f3f4f6", textShadow: "0 2px 30px rgba(0,0,0,0.35)" }}
              />
            </span>
            <window.FadeUp
              as="div"
              delay={0.45}
              className="mt-3 md:mt-4 font-mono"
              style={{
                fontSize: "clamp(21px,2.64vw,39px)",
                textTransform: "uppercase",
                color: "rgba(243,244,246,0.88)",
                textAlign: "justify",
                textAlignLast: "justify",
                marginInline: "auto",
                width: nameW ? `${nameW}px` : "100%"
              }}
            >
              Chichi Fu · AI PM
            </window.FadeUp>
            <window.FadeUp
              as="p"
              delay={0.6}
              className="mt-20 md:mt-24"
              style={{ marginInline: "auto", textAlign: "center", maxWidth: nameW ? `${nameW}px` : "clamp(280px,34vw,440px)", fontSize: "clamp(13px,1vw,16px)", lineHeight: 1.6, color: "rgba(243,244,246,0.74)" }}
            >
              3年AI探索 · 5年项目管理<br />
              企业级落地AI产品负责人<br />
              专注智能体和企业AI应用场景
            </window.FadeUp>
            <window.FadeUp
              as="div"
              delay={0.75}
              className="mt-7 md:mt-9 flex items-center justify-center gap-3"
            >
              <a href="resume.pdf" download="AI产品经理-傅筱湄-简历.pdf" className="glass-dark nav-glass r-pill px-6 py-2.5 md:px-7 md:py-3 font-medium"
                 style={{ color: "#f3f4f6", fontSize: "clamp(13px,1vw,16px)" }}>下载简历</a>
              <a href="#contact" className="glass-dark nav-glass r-pill px-6 py-2.5 md:px-7 md:py-3 font-medium"
                 style={{ color: "#f3f4f6", fontSize: "clamp(13px,1vw,16px)" }}>联系我</a>
            </window.FadeUp>
          </div>

          <div className="scroll-cue">
            <span>scroll</span>
            <span className="rail"></span>
          </div>
        </div>
      </div>
    </section>
  );
};

// ========== ABOUT ==========
window.About = function About() {
  const skills = ["RAG 产品化", "多 Agent 工作流编排", "合规风控评测"];
  return (
    <section id="about" className="px-4 md:px-6 py-16 md:py-28">
      <div className="glass r-xl max-w-4xl mx-auto py-14 md:py-20 px-6 md:px-14">
        {/* hero line */}
        <window.FadeUp
          delay={0.05}
          className="text-center font-semibold tracking-[-0.02em]"
          style={{
            fontSize: "clamp(28px, 5.2vw, 56px)",
            lineHeight: 1.15,
            color: "var(--ink-1)"
          }}
        >
          我是傅筱湄，一名&nbsp;AI&nbsp;产品经理
        </window.FadeUp>

        {/* skill row */}
        <window.FadeUp delay={0.15} className="mt-6 md:mt-8 flex flex-wrap items-center justify-center gap-x-3 gap-y-2">
          {skills.map((s, i) => (
            <React.Fragment key={s}>
              <span
                className="text-[13px] md:text-[14px] font-medium px-3 py-1 rounded-full"
                style={{
                  color: "var(--ink-2)",
                  background: "rgba(255,255,255,0.55)",
                  border: "1px solid rgba(0,0,0,0.06)",
                  boxShadow: "inset 0 1px 0 rgba(255,255,255,.7)"
                }}
              >
                {s}
              </span>
              {i < skills.length - 1 ? (
                <span aria-hidden="true" style={{ color: "var(--ink-5)" }}>·</span>
              ) : null}
            </React.Fragment>
          ))}
        </window.FadeUp>

        {/* divider */}
        <div className="mt-10 md:mt-12 mx-auto h-px max-w-md" style={{ background: "linear-gradient(90deg, transparent, color-mix(in srgb, var(--ink-5) 90%, transparent), transparent)" }}></div>

        {/* body */}
        <div
          className="mt-10 md:mt-12 max-w-[640px] mx-auto space-y-5 md:space-y-6"
          style={{
            color: "var(--ink-2)",
            fontSize: "clamp(15px, 1.15vw, 17px)",
            lineHeight: 1.85,
            textWrap: "pretty",
            textAlign: "center"
          }}
        >
          <window.FadeUp as="p" delay={0.3}>
            从&nbsp;0&nbsp;到&nbsp;1 主导一个知识密集型行业的&nbsp;<span className="font-semibold" style={{ color: "var(--ink-1)" }}>AI&nbsp;智能投标系统</span>，<br />
            完整走过产品设计、落地交付与功能迭代。
          </window.FadeUp>
          <window.FadeUp as="p" delay={0.4}>
            兼具<span className="font-semibold" style={{ color: "var(--ink-1)" }}>国企体系内</span>与<span className="font-semibold" style={{ color: "var(--ink-1)" }}>创业实操</span>推动创新的双重经历，<br />
            能在资源有限、规则复杂的环境下，<br />
            拆解目标、搭建体系并快速验证&nbsp;MVP。
          </window.FadeUp>
        </div>
      </div>
    </section>
  );
};

// ========== EXPERIENCE (经历) ==========
// Reverse-chronological career timeline. Each entry carries optional
// structured fields — focus (重点), highlights (亮点), metrics (指标) —
// rendered with mono eyebrow labels so the densest record stays scannable.
window.Experience = function Experience() {
  const items = [
    {
      year: "2024 — 2026",
      range: "",
      role: "AI 项目经理",
      org: "深水集团子公司（清源）",
      focus: "企业级 AI 系统从 0 到 1 — 需求调研、MVP、风控、版本推进、评测",
      highlights: [
        "主导 AI 智能投标系统：RAG + Prompt 体系 + 工作流 + 三层风控"
      ],
      metrics: [
        ["标书周期", "6 天 → 1.5 天"],
        ["合规覆盖", "半自动 · 零事故"]
      ]
    },
    {
      year: "2023 — 2024",
      range: "",
      role: "项目负责人",
      org: "美妆仓店",
      focus: "0 → 1 运营 + 在真实经营中验证应用层 AI",
      highlights: [
        "1500+ SKU 多渠道经营",
        "AI 经营复盘工作流（复盘耗时 −60%）",
        "AI 辅助复盘 / ROI / 扩店 / 止损四类决策"
      ],
      metrics: [
        ["损耗", "1.5% → 0.3%"],
        ["人效", "+18%"],
        ["坪效", "+13%"]
      ]
    },
    {
      year: "2021 — 2023",
      range: "",
      role: "项目经理",
      org: "深圳广电集团",
      focus: "政府类大型项目的复杂多方协同、强时效交付、风险管控",
      highlights: [
        "14 天交付罗湖首个户外移动直播间（含 8 小时夜间紧急迁移）",
        "统筹新春消费节 30+ 品牌、2 场直播"
      ]
    },
    {
      year: "2017 — 2021",
      range: "",
      role: "本科",
      org: "湖南财政经济学院",
      muted: true
    }
  ];
  return (
    <section id="experience" className="px-4 md:px-6 py-12 md:py-24">
      <div className="max-w-4xl mx-auto">
        <div className="text-center mb-12 md:mb-16">
          <window.WordsPullUpMultiStyle
            className="text-2xl sm:text-3xl md:text-4xl font-semibold leading-tight tracking-[-0.02em]"
            segments={[
              { text: "5年，从项目管理走向AI产品。", className: "text-ink" }
            ]}
          />
        </div>

        <div className="glass r-xl px-6 md:px-10 lg:px-14 py-10 md:py-14">
          <ol className="flex flex-col">
            {items.map((it, i) => (
              <li
                key={i}
                className="grid grid-cols-[72px_1fr] md:grid-cols-[140px_1fr] gap-x-5 md:gap-x-10 py-7 md:py-9"
                style={{ borderTop: i === 0 ? "none" : "1px solid rgba(20,24,32,0.10)" }}
              >
                {/* Left rail: year span + dot marker */}
                <div className="relative pt-1.5">
                  <div className="num-mono leading-tight" style={{ color: it.muted ? "var(--ink-4)" : "var(--ink-2)", fontSize: "11.5px" }}>
                    {it.year}
                  </div>
                  {it.current ? (
                    <span
                      className="inline-flex items-center gap-1.5 mt-2 num-mono"
                      style={{ color: "var(--accent)", fontSize: "10.5px" }}
                    >
                      <span
                        aria-hidden="true"
                        style={{
                          width: 6, height: 6, borderRadius: "50%",
                          background: "var(--accent)",
                          boxShadow: "0 0 0 3px rgba(30,58,138,0.18)"
                        }}
                      />
                      现任
                    </span>
                  ) : null}
                </div>

                {/* Right body */}
                <div>
                  <div className="flex flex-wrap items-baseline gap-x-3 gap-y-1">
                    <h3
                      className="text-lg md:text-xl font-semibold tracking-[-0.01em]"
                      style={{ color: "var(--ink-1)" }}
                    >
                      {it.org}
                    </h3>
                    <span
                      aria-hidden="true"
                      className="hidden sm:inline-block"
                      style={{ width: 4, height: 4, borderRadius: "50%", background: "var(--ink-5)", transform: "translateY(-3px)" }}
                    />
                    <span className="text-base md:text-[17px] font-medium" style={{ color: "var(--ink-2)" }}>
                      {it.role}
                    </span>
                  </div>
                  {it.range ? (
                    <div className="num-mono mt-1.5" style={{ color: "var(--ink-4)", fontSize: "11.5px" }}>
                      {it.range}
                    </div>
                  ) : null}

                  {it.focus ? (
                    <div className="mt-4 flex gap-3">
                      <span
                        className="num-mono shrink-0 pt-[3px]"
                        style={{ color: "var(--accent)", fontSize: "10.5px", letterSpacing: ".14em", textTransform: "uppercase" }}
                      >
                        重点
                      </span>
                      <p className="text-sm md:text-[15px] leading-relaxed" style={{ color: "var(--ink-2)", textWrap: "pretty" }}>
                        {it.focus}
                      </p>
                    </div>
                  ) : null}

                  {it.highlights && it.highlights.length ? (
                    <div className="mt-3 flex gap-3">
                      <span
                        className="num-mono shrink-0 pt-[3px]"
                        style={{ color: "var(--accent)", fontSize: "10.5px", letterSpacing: ".14em", textTransform: "uppercase" }}
                      >
                        亮点
                      </span>
                      <ul className="flex flex-col gap-1.5 text-sm md:text-[15px] leading-relaxed" style={{ color: "var(--ink-3)" }}>
                        {it.highlights.map((h, hi) => (
                          <li key={hi} className="flex gap-2" style={{ textWrap: "pretty" }}>
                            <span aria-hidden="true" className="shrink-0" style={{ color: "var(--ink-5)" }}>—</span>
                            <span>{h}</span>
                          </li>
                        ))}
                      </ul>
                    </div>
                  ) : null}

                  {it.metrics && it.metrics.length ? (
                    <div className="mt-4 flex flex-wrap items-stretch gap-2">
                      {it.metrics.map((m, mi) => (
                        <div
                          key={mi}
                          className="glass-plate r-md px-3.5 py-2 flex flex-col"
                          style={{ minWidth: 124 }}
                        >
                          <span className="num-mono" style={{ color: "var(--ink-4)", fontSize: "10.5px", letterSpacing: ".12em", textTransform: "uppercase" }}>
                            {m[0]}
                          </span>
                          <span
                            className="font-semibold mt-0.5 tracking-tight"
                            style={{ color: "var(--ink-1)", fontSize: "14.5px", fontFeatureSettings: '"tnum"' }}
                          >
                            {m[1]}
                          </span>
                        </div>
                      ))}
                    </div>
                  ) : null}
                </div>
              </li>
            ))}
          </ol>
        </div>
      </div>
    </section>
  );
};

// ========== FEATURES ==========
const LearnMore = () => (
  <a href="#" className="inline-flex items-center gap-2 text-sm font-medium mt-auto group" style={{ color: "var(--ink-1)" }}>
    <span>Learn more</span>
    <span className="flex items-center justify-center rounded-full transition-transform group-hover:translate-x-0.5"
          style={{ width: 26, height: 26, background: "rgba(59,109,240,0.12)", color: "var(--accent)" }}>
      <ArrowRight size={13}/>
    </span>
  </a>
);

const ChecklistItem = ({ children }) => (
  <li className="flex items-start gap-2.5 text-xs sm:text-[13px] leading-snug" style={{ color: "var(--ink-3)" }}>
    <span className="mt-[2px] flex-shrink-0" style={{ color: "var(--accent)" }}><Check size={13}/></span>
    <span>{children}</span>
  </li>
);

const FeatureNum = ({ n }) => <div className="num-mono mb-1">{n}</div>;

// Individual card bodies, rendered inside the coverflow track.
const featureCards = [
  // 01
  (
    <div className="absolute inset-0 p-5 md:p-6 flex flex-col gap-4 z-10">
      <div className="w-11 h-11 rounded-[12px] glass-plate flex items-center justify-center" style={{ color: "var(--ink-2)" }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>
      </div>
      <div>
        <FeatureNum n="01"/>
        <h3 className="text-base md:text-lg font-semibold" style={{ color: "var(--ink-1)" }}>OPC AI Agent 系统</h3>
        <p className="text-[11px] sm:text-xs leading-snug mt-1.5" style={{ color: "var(--ink-4)" }}>
          基于 Claude Code / Codex CLI 的本地多 Agent 协作框架——用自然语言指挥「CEO + 产品 + 编程 + 验证 + 客服」虚拟团队完成端到端任务。
        </p>
      </div>
      <ul className="flex flex-col gap-2 mb-2">
        <ChecklistItem>角色化多 Agent 架构 · CEO 单一入口自动分派</ChecklistItem>
        <ChecklistItem>结构化协作协议 · 任务卡→分派→交叉验证→汇总</ChecklistItem>
        <ChecklistItem>双 Runtime 隔离 + 三层文件共享记忆</ChecklistItem>
        <ChecklistItem>飞书 WebSocket Bot 实时被动触发闭环</ChecklistItem>
        <ChecklistItem>macOS 菜单栏控制台 · 状态/日志/自动重启</ChecklistItem>
      </ul>
      <a href="https://github.com/nils0000shiyong/claude-cyber-company" target="_blank" rel="noopener noreferrer"
         className="inline-flex items-center gap-2 text-sm font-medium mt-auto group" style={{ color: "var(--ink-1)" }}>
        <span>查看仓库</span>
        <span className="flex items-center justify-center rounded-full transition-transform group-hover:translate-x-0.5"
              style={{ width: 26, height: 26, background: "rgba(59,109,240,0.12)", color: "var(--accent)" }}>
          <ArrowRight size={13}/>
        </span>
      </a>
    </div>
  ),
  // 02
  (
    <div className="absolute inset-0 p-5 md:p-6 flex flex-col gap-4 z-10">
      <div className="w-11 h-11 rounded-[12px] glass-plate flex items-center justify-center" style={{ color: "var(--ink-2)" }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
      </div>
      <div>
        <FeatureNum n="02"/>
        <h3 className="text-base md:text-lg font-semibold" style={{ color: "var(--ink-1)" }}>快答 · 面试话术 AI</h3>
        <p className="text-[11px] sm:text-xs leading-snug mt-1.5" style={{ color: "var(--ink-4)" }}>
          Android 端面试话术提升助手——基于你的真实经历与项目（RAG）生成参考回答，多家国内外大模型 Provider 自由切换，端到端独立设计与开发。
        </p>
      </div>
      <ul className="flex flex-col gap-2 mb-2">
        <ChecklistItem>多模块架构 · 11 个 Gradle 模块 + MVVM + Hilt + Navigation · 零循环依赖</ChecklistItem>
        <ChecklistItem>全 Jetpack Compose + Material 3 · 自建主题与通用组件库</ChecklistItem>
        <ChecklistItem>多 Provider LLM（BYOK）· 一键切换 + 实时 token 用量与费用</ChecklistItem>
        <ChecklistItem>语音转写 → 结构化口语答案 &lt; 5 秒 · 一键「更简洁 / 加案例」重写</ChecklistItem>
        <ChecklistItem>本地 RAG · PdfBox 解析简历 / 项目，相似度匹配注入个人经历</ChecklistItem>
      </ul>
      <a href="https://github.com/nils0000shiyong/Kuaida-AI-assistant" target="_blank" rel="noopener noreferrer"
         className="inline-flex items-center gap-2 text-sm font-medium mt-auto group" style={{ color: "var(--ink-1)" }}>
        <span>查看仓库</span>
        <span className="flex items-center justify-center rounded-full transition-transform group-hover:translate-x-0.5"
              style={{ width: 26, height: 26, background: "rgba(59,109,240,0.12)", color: "var(--accent)" }}>
          <ArrowRight size={13}/>
        </span>
      </a>
    </div>
  ),
  // 03
  (
    <div className="absolute inset-0 p-5 md:p-6 flex flex-col gap-4 z-10">
      <div className="w-11 h-11 rounded-[12px] glass-plate flex items-center justify-center" style={{ color: "var(--ink-2)" }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M3 7l3-3h12l3 3-9 13L3 7z"/><path d="M3 7h18"/><path d="M9 7l3 5 3-5"/></svg>
      </div>
      <div>
        <FeatureNum n="03"/>
        <h3 className="text-base md:text-lg font-semibold" style={{ color: "var(--ink-1)" }}>AdWeave 炼图坊 · 服装 AIGC 内容工厂</h3>
        <p className="text-[11px] sm:text-xs leading-snug mt-1.5" style={{ color: "var(--ink-4)" }}>
          面向淘宝 / 抖音中小女装卖家的 AIGC 商品内容生成工厂——赛事完整商业方案，从技术选型到 GTM 策略端到端闭环。
        </p>
      </div>
      <ul className="flex flex-col gap-2 mb-2">
        <ChecklistItem>定义 AIGC 内容生产流水线 · 可灵 3.0 图生视频 / 模特合成 + 授权 BGM 批量出片</ChecklistItem>
        <ChecklistItem>主导技术选型权衡 · 基于成本与并发上限将 Seedance 2.0 降级，选定可灵 3.0 为主引擎</ChecklistItem>
        <ChecklistItem>输出 21 页完整商业计划 · 竞品分析 + 技术架构 + 分层定价模型</ChecklistItem>
        <ChecklistItem>依托深圳服装产业带资源的冷启动 GTM 策略</ChecklistItem>
        <ChecklistItem>端到端方案设计 · 成本 / 性能权衡 · 商业化与 GTM 闭环</ChecklistItem>
      </ul>
    </div>
  ),
  // 04 — NEW
  (
    <div className="absolute inset-0 p-5 md:p-6 flex flex-col gap-4 z-10">
      <div className="w-11 h-11 rounded-[12px] glass-plate flex items-center justify-center" style={{ color: "var(--ink-2)" }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
      </div>
      <div>
        <FeatureNum n="04"/>
        <h3 className="text-base md:text-lg font-semibold" style={{ color: "var(--ink-1)" }}>CareFamily · 银发健康监护</h3>
        <p className="text-[11px] sm:text-xs leading-snug mt-1.5" style={{ color: "var(--ink-4)" }}>
          银发健康远程监护产品——基于 Apple Watch 采集父母体征，LLM 生成子女看得懂的自然语言健康摘要，软硬一体演进路线的产品定义与架构设计。
        </p>
      </div>
      <ul className="flex flex-col gap-2 mb-2">
        <ChecklistItem>体征采集 · Apple Watch + HealthKit · 心率 / 活动 / 睡眠多维数据实时同步</ChecklistItem>
        <ChecklistItem>AI 健康摘要 · LLM 生成自然语言「今日状态」· 替代专业指标解读门槛</ChecklistItem>
        <ChecklistItem>异常感知 → 主动推送异地子女 · 把「被动监测」转为「主动安心」</ChecklistItem>
        <ChecklistItem>软硬一体 Roadmap · Phase 1 Apple Watch 轻量 MVP → Phase 2 自研硬件</ChecklistItem>
        <ChecklistItem>端到端产品定义 · 数据链路 + 分阶段商业化路径设计</ChecklistItem>
      </ul>
    </div>
  ),
  // 05 — NEW
  (
    <div className="absolute inset-0 p-5 md:p-6 flex flex-col gap-4 z-10">
      <div className="w-11 h-11 rounded-[12px] glass-plate flex items-center justify-center" style={{ color: "var(--ink-2)" }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/><path d="M8 11h6M11 8v6"/></svg>
      </div>
      <div>
        <FeatureNum n="05"/>
        <h3 className="text-base md:text-lg font-semibold" style={{ color: "var(--ink-1)" }}>筛到 · 求职信息工作台</h3>
        <p className="text-[11px] sm:text-xs leading-snug mt-1.5" style={{ color: "var(--ink-4)" }}>
          面向主动求职者的「公司筛选 × JD 面试管理」一体化系统——基于 Notion 搭建前端，把零散的招聘信息沉淀为可追踪、可复盘的求职数据库。开发中。
        </p>
      </div>
      <ul className="flex flex-col gap-2 mb-2">
        <ChecklistItem>公司画像筛选 · 行业 / 规模 / 文化 / 待遇多维度打分排序</ChecklistItem>
        <ChecklistItem>JD 结构化解析 · 关键词高亮 + 岗位与个人匹配度评估</ChecklistItem>
        <ChecklistItem>面试全流程管理 · 进度看板 + 复盘笔记 + Offer 对比</ChecklistItem>
        <ChecklistItem>Notion 前端 · 数据可视化 + 跨设备同步，零搭建成本</ChecklistItem>
        <ChecklistItem>求职数据资产化 · 从「海投碰运气」转为「系统化决策」</ChecklistItem>
      </ul>
      <span className="inline-flex items-center gap-2 text-sm font-medium mt-auto" style={{ color: "var(--ink-3)" }}>
        <span>coming soon······</span>
      </span>
    </div>
  )
];

window.Features = function Features() {
  const trackRef = React.useRef(null);

  // Coverflow: scale/rotate each card by its distance from the track centre,
  // so neighbours recede in 3D and only their outlines peek behind the focus.
  const update = React.useCallback(() => {
    const track = trackRef.current;
    if (!track) return;
    const tr = track.getBoundingClientRect();
    const mid = tr.left + tr.width / 2;
    track.querySelectorAll(".cf-item").forEach(item => {
      const r = item.getBoundingClientRect();
      const d = ((r.left + r.width / 2) - mid) / tr.width;   // normalised offset
      const c = Math.max(-1, Math.min(1, d * 1.7));
      const a = Math.abs(c);
      const scale = 1 - a * 0.20;
      const rot = -c * 32;
      const tx = -c * 26;
      item.style.transform = `translateX(${tx}px) rotateY(${rot}deg) scale(${scale})`;
      item.style.opacity = (1 - a * 0.42).toFixed(3);
      item.style.zIndex = String(100 - Math.round(a * 100));
    });
  }, []);

  React.useEffect(() => {
    const track = trackRef.current;
    if (!track) return;
    update();
    track.addEventListener("scroll", update, { passive: true });
    window.addEventListener("resize", update);
    const t1 = setTimeout(update, 120);
    const t2 = setTimeout(update, 600);
    return () => {
      track.removeEventListener("scroll", update);
      window.removeEventListener("resize", update);
      clearTimeout(t1); clearTimeout(t2);
    };
  }, [update]);

  const nudge = (dir) => {
    const track = trackRef.current;
    if (!track) return;
    const item = track.querySelector(".cf-item");
    const step = item ? item.getBoundingClientRect().width + 26 : 360;
    track.scrollBy({ left: dir * step, behavior: "smooth" });
  };

  return (
    <section id="projects" className="py-12 md:py-24">
      <div className="px-4 md:px-6">
        <div className="max-w-4xl mb-6 md:mb-10 text-center mx-auto">
          <window.FadeUp
            as="h2"
            delay={0.05}
            className="text-2xl sm:text-3xl md:text-4xl font-semibold leading-tight tracking-[-0.02em]"
            style={{ color: "var(--ink-1)" }}
          >
            AI worth shipping. Let's build the next one together.
          </window.FadeUp>
          <window.FadeUp
            delay={0.15}
            className="mt-2 md:mt-3 text-2xl sm:text-3xl md:text-4xl font-normal leading-tight tracking-[-0.02em]"
            style={{ color: "rgb(94, 123, 239)" }}
          >
            个人项目展示
          </window.FadeUp>
        </div>
      </div>

      <div className="cf-wrap">
        <div className="cf-track" ref={trackRef}>
          <div className="cf-spacer" aria-hidden="true"></div>
          {featureCards.map((body, i) => (
            <div className="cf-item" key={i}>
              <window.FeatureCard index={i} className="glass r-xl cf-card">
                {body}
              </window.FeatureCard>
            </div>
          ))}
          <div className="cf-spacer" aria-hidden="true"></div>
        </div>

        <button type="button" className="cf-nav prev" aria-label="上一张" onClick={() => nudge(-1)}>
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
        </button>
        <button type="button" className="cf-nav next" aria-label="下一张" onClick={() => nudge(1)}>
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round"><path d="M9 18l6-6-6-6"/></svg>
        </button>
      </div>
    </section>
  );
};

// ========== CONTACT (合作) ==========
window.Contact = function Contact() {
  const socials = [
    {
      label: "邮箱",
      href: "mailto:chichi77fu@gmail.com",
      icon: (
        <svg viewBox="0 0 24 24" width="22" height="22" fill="none"
             stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
          <rect x="3" y="5" width="18" height="14" rx="2.5" />
          <path d="M3.5 7l8.5 6 8.5-6" />
        </svg>
      )
    },
    {
      label: "公众号",
      href: "wechat-qr.html",
      icon: (
        <svg viewBox="0 0 24 24" width="23" height="23" fill="currentColor">
          <path d="M9.4 3.2C5.2 3.2 1.8 6 1.8 9.5c0 1.96 1.07 3.7 2.74 4.86a.46.46 0 0 1 .19.51l-.36 1.32c-.05.18.14.33.3.24l1.74-.99a.6.6 0 0 1 .47-.06c.66.18 1.36.28 2.08.29a4.93 4.93 0 0 1-.2-1.39c0-3.06 2.97-5.45 6.5-5.45.23 0 .45.01.67.03C15.86 5.5 13 3.2 9.4 3.2zM6.9 8.16a.97.97 0 1 1 0-1.94.97.97 0 0 1 0 1.94zm5 0a.97.97 0 1 1 0-1.94.97.97 0 0 1 0 1.94z" />
          <path d="M22.2 13.06c0-2.86-2.78-5.18-6.2-5.18-3.43 0-6.2 2.32-6.2 5.18 0 2.87 2.77 5.19 6.2 5.19.62 0 1.22-.08 1.79-.23a.52.52 0 0 1 .4.05l1.45.83c.14.08.3-.05.26-.21l-.3-1.1a.4.4 0 0 1 .16-.43c1.36-.96 2.19-2.39 2.19-3.9zm-8.21-.8a.8.8 0 1 1 0-1.6.8.8 0 0 1 0 1.6zm4.02 0a.8.8 0 1 1 0-1.6.8.8 0 0 1 0 1.6z" />
        </svg>
      )
    },
    {
      label: "GitHub",
      href: "https://github.com/nils0000shiyong",
      icon: (
        <svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor">
          <path d="M12 2C6.48 2 2 6.58 2 12.25c0 4.53 2.87 8.37 6.84 9.73.5.1.68-.22.68-.49 0-.24-.01-.88-.01-1.73-2.78.62-3.37-1.37-3.37-1.37-.46-1.18-1.11-1.49-1.11-1.49-.91-.64.07-.62.07-.62 1 .07 1.53 1.06 1.53 1.06.89 1.57 2.34 1.12 2.91.85.09-.66.35-1.12.63-1.38-2.22-.26-4.55-1.14-4.55-5.07 0-1.12.39-2.03 1.03-2.75-.1-.26-.45-1.3.1-2.72 0 0 .84-.27 2.75 1.05a9.36 9.36 0 0 1 5 0c1.91-1.32 2.75-1.05 2.75-1.05.55 1.42.2 2.46.1 2.72.64.72 1.03 1.63 1.03 2.75 0 3.94-2.34 4.81-4.57 5.06.36.32.68.94.68 1.9 0 1.37-.01 2.48-.01 2.82 0 .27.18.6.69.49A10.04 10.04 0 0 0 22 12.25C22 6.58 17.52 2 12 2z" />
        </svg>
      )
    },
    {
      label: "Instagram",
      href: "https://www.instagram.com/chichi77fu/",
      icon: (
        <svg viewBox="0 0 24 24" width="22" height="22" fill="none"
             stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
          <rect x="3" y="3" width="18" height="18" rx="5" />
          <circle cx="12" cy="12" r="4" />
          <circle cx="17.2" cy="6.8" r="1" fill="currentColor" stroke="none" />
        </svg>
      )
    },
    {
      label: "X",
      href: "https://x.com/chichi77fu",
      icon: (
        <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
          <path d="M17.53 3h3.07l-6.71 7.67L21.75 21h-6.18l-4.84-6.33L5.18 21H2.1l7.18-8.2L2.25 3h6.33l4.38 5.79L17.53 3zm-1.08 16.17h1.7L7.62 4.74H5.8l10.65 14.43z" />
        </svg>
      )
    }
  ];
  return (
    <section id="contact" className="px-4 md:px-6 py-20 md:py-32">
      <div className="glass r-xl max-w-4xl mx-auto px-6 md:px-16 py-16 md:py-24 text-center">

        <window.WordsPullUpMultiStyle
          className="text-3xl sm:text-4xl md:text-5xl max-w-2xl mx-auto leading-[1.02] tracking-[-0.02em]"
          segments={[
            { text: "一起把AI", className: "font-semibold text-ink" },
            { text: "真正落地。", className: "font-normal", style: { color: "var(--ink-3)" } }
          ]}
        />

        <window.FadeUp
          as="p"
          delay={0.4}
          className="mt-7 md:mt-9 max-w-xl mx-auto text-sm md:text-base leading-relaxed"
          style={{ color: "var(--ink-3)" }}
        >
          对企业级 AI 落地、智能体应用场景感兴趣，或想聊聊合作？欢迎随时联系。
        </window.FadeUp>

        <div className="mt-11 md:mt-14 flex items-center justify-center gap-4 md:gap-5">
          {socials.map(s => (
            <a key={s.label} href={s.href} aria-label={s.label} title={s.label}
               className="social-orb"
               style={{ color: "var(--ink-2)" }}>
              {s.icon}
            </a>
          ))}
        </div>
      </div>
    </section>
  );
};

// ========== FOOTER ==========
window.Footer = function Footer() {
  const toTop = () => window.scrollTo({ top: 0, behavior: "smooth" });
  return (
    <footer className="px-4 md:px-6 pb-12 md:pb-16">
      <div className="max-w-4xl mx-auto">
        <div className="footer-divider"></div>
        <div className="flex items-center justify-between gap-4 pt-8 md:pt-10">
          <p className="text-sm md:text-[15px] tracking-[-0.01em]" style={{ color: "var(--ink-3)" }}>
            <span className="font-semibold" style={{ color: "var(--ink-3)" }}>© 2026</span>
            {" ChichiFu.site"}
          </p>
          <a href="mailto:chichi77fu@gmail.com"
             className="hidden sm:inline-block text-sm md:text-[15px]"
             style={{
               color: "var(--ink-3)",
               fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
               letterSpacing: "0.18em",
               textDecoration: "none",
               borderBottom: "1px solid color-mix(in srgb, var(--ink-3) 35%, transparent)",
               paddingBottom: "2px",
             }}>
            chichi77fu@gmail.com
          </a>
          <button type="button" onClick={toTop} aria-label="回到顶部" title="回到顶部"
                  className="social-orb" style={{ color: "var(--ink-2)", cursor: "pointer", border: "none" }}>
            <svg viewBox="0 0 24 24" width="20" height="20" fill="none"
                 stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
              <path d="M12 19V6" />
              <path d="M6 11l6-6 6 6" />
            </svg>
          </button>
        </div>
      </div>
    </footer>
  );
};
