/* global React */
/* AIGC COMMERCIAL SYSTEM — stamp-archive case file (project detail layout).
   Cream "digital stamp album": 8 perforated stamps scatter on the right,
   the left rail is a sticky case-file panel. Click a stamp → it enlarges to
   centre, the others fade/blur, and the rail fills with that case. Mobile
   collapses the scatter into a vertical accordion. */
const { useState, useRef, useLayoutEffect, useEffect } = React;

const AIGC_STAMPS = [
{
  id: 1, no: "01", img: "assets/aigc/stamp-02.png", orient: "portrait",
  capEN: "OUTPAINTING", capZH: "反诈视频", val: "¥1",
  tag: "OUTPAINTING / ANTI-FRAUD",
  title: "新浪钱包：反诈创意视频全案",
  titleZH: "",
  method: "AI Outpainting Narrative",
  lead: "利用 AI Outpainting 技术的无限延展性，将男女大学生主观视角中的「甜蜜梦想」，与客观视角中的「诈骗流水线」同屏呈现。",
  slogan: "别让你的梦想，成为他的业绩。",
  blocks: [
  { k: "Role / 角色", v: "创意策略制定 · 核心脚本撰写" },
  { k: "Concept / 核心表达", v: "这个案例不是单纯使用 AI 扩图，而是让 AI Outpainting 本身成为创意隐喻。画面不断被延展，象征被骗者的幻想不断被放大、拉长，最终成为诈骗链条中的一个注脚。" },
  { k: "Why AI Works", v: "AI Outpainting 的「无限延展」正好对应反诈传播中「幻想被不断放大」的心理陷阱，让技术能力和传播概念形成一致。" }],
  links: [
  { label: "男大学生篇", url: "https://weibo.com/6685357186/4949574050383834" },
  { label: "女大学生篇", url: "https://weibo.com/5174400490/4949571219231926" }],
  pos: { left: 5, top: 3, rot: -6, w: 23 },
  hover: -1, active: { left: 50, top: 44, rot: 0, scale: 1.6 }
},
{
  id: 2, no: "02", img: "assets/aigc/stamp-03.png", orient: "portrait",
  capEN: "COMIC", capZH: "校园反诈", val: "¥2",
  tag: "COMIC / VISUAL ANCHOR",
  title: "新浪钱包：校园反诈漫画",
  titleZH: "",
  method: "AI Comic / Visual Anchoring",
  lead: "反诈科普「游戏化」实验。建立「受害者档案」，借鉴 AVG 文字冒险游戏的视觉语言，将枯燥案例转化为沉浸式的「剧本杀」体验。",
  slogan: "Visual Anchoring · 视觉锚点",
  blocks: [
  { k: "Role / 角色", v: "创意策略 · 脚本 · AIGC 视觉指导" },
  { k: "Method / 核心方法", v: "这个案例把校园反诈内容从普通科普，转化为更适合年轻人阅读和传播的漫画式内容。通过固定角色特征、固定视觉锚点和脚本结构，减少 AI 生成中的随机性，让 AIGC 漫画具备连续叙事能力。" },
  { k: "Why AI Works", v: "AIGC 降低了漫画内容生产成本，而 Visual Anchoring 保证了角色与风格的一致性，让漫画不只是单张图，而是一套可持续的内容生产方式。" }],
  links: [{ label: "查看漫画", url: "https://mp.weixin.qq.com/s/1fFRNekTv4BxbjiCrxpycg" }],
  pos: { left: 29, top: 9, rot: 5, w: 22 },
  hover: 1, active: { left: 50, top: 44, rot: 1, scale: 1.6 }
},
{
  id: 3, no: "03", img: "assets/aigc/stamp-04.png", orient: "landscape",
  capEN: "STORYBOARD", capZH: "科技基金", val: "¥3",
  tag: "FINANCE VIDEO / STORYBOARD",
  title: "易方达：科技指数基金宣传视频",
  titleZH: "",
  method: "AI Storyboard / Finance Video",
  lead: "借势《灌篮高手》热点，利用「定投」和「投篮」的中文关联，将枯燥的基金科普转化为更易理解的视频表达。",
  slogan: "科技指数算法 · VR 战术眼镜 · 篮球投篮隐喻",
  blocks: [
  { k: "Role / 角色", v: "创意策略 · 脚本 · AIGC 视觉指导" },
  { k: "Concept / 重新编辑", v: "这个案例的重点是将抽象的科技指数基金转译成可观看的视频方案。通过「定投 / 投篮」的语言关联，把金融产品逻辑包装成篮球场上的压哨球博弈，再用 AI 分镜和科技场景，让复杂产品变得更直观。" },
  { k: "Why AI Works", v: "AIGC 可以快速生成科技场景、运动分镜和视觉隐喻，帮助金融产品从说明性内容转化为更具画面感的视频叙事。" }],
  links: [{ label: "观看视频", url: "https://weixin.qq.com/sph/Axe5mxI1yi" }],
  pos: { left: 57, top: 5, rot: -3, w: 35 },
  hover: 0, active: { left: 50, top: 45, rot: -1, scale: 1.32 }
},
{
  id: 4, no: "04", img: "assets/aigc/stamp-05.png", orient: "landscape",
  capEN: "AVATAR", capZH: "虚拟演播", val: "¥4",
  tag: "DIGITAL ANCHOR / VIRTUAL STUDIO",
  title: "虚拟演播：AI 数字人街采",
  titleZH: "",
  method: "AI Avatar",
  lead: "突破实拍限制，利用 AI 生成多国籍、多身份的「虚拟路人」与新闻主播，低成本构建高公信力的财经新闻场景。",
  slogan: "",
  blocks: [
  { k: "Concept / 重新编辑", v: "这个应用展示了 AIGC 在虚拟演播与财经内容中的使用方式。通过生成不同身份、不同国籍的虚拟人物和新闻主播，可以在不进行真实拍摄的情况下，快速搭建具有新闻感和公信力的内容场景。" },
  { k: "Why AI Works", v: "AI Avatar 适合解决实拍成本高、人物素材难获取、新闻场景搭建复杂的问题，让财经内容具备更灵活的表现形式。" }],
  links: [{ label: "观看视频", url: "https://weixin.qq.com/sph/AEeUPLLdJX" }],
  pos: { left: 5, top: 39, rot: 4, w: 33 },
  hover: -1, active: { left: 50, top: 45, rot: -1, scale: 1.32 }
},
{
  id: 5, no: "05", img: "assets/aigc/stamp-06.png", orient: "landscape",
  capEN: "WUXIA", capZH: "金融武侠", val: "¥5",
  tag: "FINANCE WUXIA / CHARACTER",
  title: "金融武侠：红利低波「双侠」叙事",
  titleZH: "",
  method: "Wuxia Style",
  lead: "将枯燥的基金策略拟人化为「江湖侠客」，用 AI 国漫改风格，生动演绎「攻守兼备」的投资理念。",
  slogan: "",
  blocks: [
  { k: "Concept / 重新编辑", v: "这个应用将金融产品策略人格化，把红利与低波动等抽象基金概念转译成「江湖双侠」的角色叙事。通过 AI 国漫与武侠风格，让金融内容从参数说明变成更易记忆的故事表达。" },
  { k: "Why AI Works", v: "武侠风格可以把复杂的投资逻辑转化为角色关系与能力设定，适合让枯燥金融内容拥有更强的叙事性和传播记忆点。" }],
  links: [{ label: "观看视频", url: "https://weixin.qq.com/sph/Az6Ld3Q9zH" }],
  pos: { left: 42, top: 37, rot: -3, w: 34 },
  hover: 1, active: { left: 50, top: 45, rot: 1, scale: 1.3 }
},
{
  id: 6, no: "06", img: "assets/aigc/stamp-07.png", orient: "landscape",
  capEN: "METAPHOR", capZH: "安和航班", val: "¥6",
  tag: "FUND PRODUCT / EMOTION",
  title: "通感隐喻：安和航班",
  titleZH: "",
  method: "Visual Metaphor",
  lead: "将抽象的「安和基金」体验具象化为一次舒适的「头等舱飞行」。通过机场、服务、风景的 AI 视觉描绘，传递「安心持有」的情绪价值。",
  slogan: "",
  blocks: [
  { k: "Concept / 重新编辑", v: "这个应用把看不见的「稳健」和「安心」，转译成看得见的航班体验。通过机舱、服务、风景与飞行过程的视觉隐喻，让基金产品从抽象收益逻辑，变成更容易感知的情绪价值。" },
  { k: "Why AI Works", v: "AIGC 擅长把抽象概念具象化。对于金融产品这类难以直接视觉呈现的内容，视觉隐喻可以帮助用户更快理解产品感受。" }],
  links: [{ label: "观看视频", url: "https://weixin.qq.com/sph/A3Z3bgdMSz" }],
  pos: { left: 8, top: 67, rot: -5, w: 33 },
  hover: -2, active: { left: 50, top: 45, rot: -1, scale: 1.32 }
},
{
  id: 7, no: "07", img: "assets/aigc/stamp-08.png", orient: "landscape",
  capEN: "SURREALISM", capZH: "梦醒时刻", val: "¥7",
  tag: "DREAM LOGIC / CONTRAST",
  title: "反视觉实验：梦醒时刻",
  titleZH: "",
  method: "Surrealism",
  lead: "梦境与现实的瞬间切换策略。对比蒙太奇：闭眼是 AI 编织的「暴富美梦」，睁眼是现实的「家徒四壁」。用强烈的视觉反差，警示投资者切勿在贪念中沉睡。",
  slogan: "",
  blocks: [
  { k: "Concept / 重新编辑", v: "这个应用利用梦境与现实的强烈对比，制造一种荒诞、反讽和警醒的视觉体验。它不是直接说教，而是通过「暴富美梦」与「现实破败」的瞬间切换，让风险意识变得更具情绪冲击力。" },
  { k: "Why AI Works", v: "AI 可以快速生成梦境、现实、荒诞场景之间的强对比画面，适合表达金融风险、心理落差和欲望陷阱这类复杂情绪。" }],
  links: [{ label: "观看视频", url: "https://weixin.qq.com/sph/ATxKNMVhjh" }],
  pos: { left: 47, top: 65, rot: 5, w: 34 },
  hover: 1, active: { left: 50, top: 45, rot: 1, scale: 1.32 }
}];


const AIGC_RATIO = { portrait: 1.32, landscape: 0.62 };
const AIGC_TAGS = [
"AI Creative Direction", "Commercial Storytelling", "Visual Metaphor",
"Script & Storyboard", "Scenario Thinking", "Content Production System"];


function StampPic({ s }) {
  const pad = AIGC_RATIO[s.orient] * 100 + "%";
  if (s.sys) {
    return (
      <div className="aigc-pic sys" style={{ paddingBottom: pad }}>
        <div className="sys-in">
          <div className="sys-ico">AI</div>
          <div className="sys-flow"><span>BRIEF</span><b /><span>CONCEPT</span><b /><span>SCRIPT</span></div>
          <div className="sys-flow"><span>VISUAL</span><b /><span>AIGC</span><b /><span>BOARD</span></div>
        </div>
      </div>);

  }
  return (
    <div className="aigc-pic" style={{ paddingBottom: pad }}>
      <img src={s.img} alt="" loading="lazy" />
    </div>);

}

function CaseBody({ s }) {
  return (
    <React.Fragment>
      <div className="dc-top">
        <div className="dc-no">{s.no}</div>
        <div className="dc-tag">{s.tag}</div>
      </div>
      <div className="dc-title">{s.title}</div>
      <div className="dc-method">{s.method}</div>
      <div className="dc-lead">{s.lead}</div>
      {s.slogan && <div className="dc-slogan">「{s.slogan}」</div>}
      <div className="dc-divider" />
      {s.blocks.map((b) =>
      <div className="dc-block" key={b.k}>
          <div className="dc-k">{b.k}</div>
          <div className="dc-v">{b.v}</div>
        </div>
      )}
      {(s.links || []).map((lk) =>
      <a className="dc-video" key={lk.url} href={lk.url} target="_blank" rel="noopener noreferrer">
        <span className="vl"><span className="en">{lk.label || "Video Link"}</span><span className="zh">{lk.url}</span></span>
        <span className="arr">→</span>
      </a>
      )}
    </React.Fragment>);}

function AIGCStamps() {
  const [activeId, setActiveId] = useState(null);
  const [openM, setOpenM] = useState(null);
  const scatterRef = useRef(null);
  const stampEls = useRef({});

  const active = AIGC_STAMPS.find((x) => x.id === activeId) || null;

  function applyActive(s) {
    const el = stampEls.current[s.id];
    const frame = scatterRef.current;
    if (!el || !frame) return;
    const fr = frame.getBoundingClientRect();
    const a = s.active;
    const curLeft = s.pos.left + s.pos.w / 2;
    const dx = (a.left - curLeft) / 100 * fr.width;
    const dy = (a.top - (s.pos.top + s.pos.w * AIGC_RATIO[s.orient] / 2 * (fr.width / fr.height))) / 100 * fr.height;
    el.style.setProperty("--tf-active", `translate(${dx}px,${dy}px) rotate(${a.rot}deg) scale(${a.scale})`);
  }

  useLayoutEffect(() => {
    if (active) applyActive(active);
  }, [activeId]);

  useEffect(() => {
    if (!active) return;
    function onResize() {applyActive(active);}
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, [activeId]);

  const sel = (id) => {try {window.playSelect && window.playSelect();} catch (e) {}setActiveId(id);};

  return (
    <div className="aigc-archive">
      {/* archival top strip */}
      <div className="aigc-arctop">
        <span className="seal">N</span>
        <span className="t-id">NINI · CREATIVE OS</span>
        <span>FILE 04 / AIGC</span>
        <span className="sp" />
        <span>STAMP ARCHIVE · 邮票档案</span>
        <span className="barcode" />
      </div>

      {/* masthead */}
      <header className="aigc-mast">
        <div className="kick">04 — Commercial AI Method Library</div>
        <h1>AIGC Commercial<br />System</h1>
        <div className="cn">商业 AIGC 创意系统</div>
        <div className="sub">
          <div className="en">A collection of AI-driven commercial storytelling methods.</div>
          <div className="zh">一组面向商业 brief 的 AIGC 创意方法邮票 — 点击任意一枚，展开它的案例档案。</div>
        </div>
      </header>

      {/* split deck */}
      <div className="aigc-deck" style={{ padding: "0px 38px" }}>
        {/* LEFT — case file rail */}
        <div className="aigc-detail-col">
          <div className={"aigc-detail" + (active ? " has-case" : "")} style={{ padding: "21px 21px 60px", margin: "0px 0px 2px", borderWidth: "2px 2px 20px", borderColor: "rgb(227, 217, 194)", borderRadius: "3px", borderStyle: "solid" }}>
            <span className="d-corner tl" />
            <span className="d-corner br" />
            {active ?
            <div className="d-case" key={active.id}>
                <CaseBody s={active} />
                <button className="dc-reset" onClick={() => setActiveId(null)}>↺ Close case · 返回档案</button>
              </div> :

            <div className="d-default">
                <div className="d-no">CASE FILE — 00 / 07</div>
                <h2>AIGC Commercial<br />System</h2>
                <div className="h-cn">商业 AIGC 创意系统</div>
                <div className="d-intro">AIGC商业brief应用：反诈传播、漫画内容、金融视频、虚拟演播、武侠叙事、视觉隐喻与超现实表达。</div>
                <div className="prompt">
                  <div className="ar" style={{ padding: "0px" }}><span className="h" style={{ padding: "0px", margin: "1px" }}>→</span> Select a stamp to open the case</div>
                  <div className="zh">右侧 7 枚邮票，每一枚代表一个真正的商业 AIGC 作品。悬停查看，点击展开对应案例。</div>
                </div>
              </div>
            }
          </div>
        </div>

        {/* RIGHT — album sheet */}
        <div className="aigc-album-col">
          <div className="aigc-album"
          onClick={(e) => {if (!e.target.closest(".aigc-stamp") && activeId !== null) setActiveId(null);}}>
            <span className="album-label">SHEET A · 7 STAMPS · MINT CONDITION</span>
            <span className="album-grade">GRADE · AIGC</span>
            <div className={"aigc-scatter" + (activeId !== null ? " has-active" : "")} ref={scatterRef}>
              {AIGC_STAMPS.map((s) =>
              <button key={s.id}
              ref={(el) => {if (el) stampEls.current[s.id] = el;}}
              className={"aigc-stamp" + (activeId === s.id ? " active" : "")}
              aria-label={s.no + " " + s.capEN}
              style={{
                width: s.pos.w + "%", left: s.pos.left + "%", top: s.pos.top + "%",
                transform: `rotate(${s.pos.rot}deg)`,
                "--tf-hover": `rotate(${s.hover}deg) scale(1.08) translateY(-6px)`
              }}
              onClick={(e) => {e.stopPropagation();sel(s.id);}}>
                  <div className="aigc-frame">
                    <StampPic s={s} />
                    <div className="cap">
                      <span className="no">{s.no}</span>
                      <span className="mid"><span className="en">{s.capEN}</span><span className="zh">{s.capZH}</span></span>
                      <span className="val">{s.val}</span>
                    </div>
                  </div>
                  <div className="perf" />
                  <div className="postmark"><span className="pm-t">AIGC · 04</span><span className="pm-d">{s.no} / 07</span></div>
                  <div className="hint">View Case · 查看案例</div>
                </button>
              )}
            </div>
          </div>
        </div>
      </div>

      {/* MOBILE — accordion list */}
      <div className="aigc-mobile">
        {AIGC_STAMPS.map((s) =>
        <div className={"m-stamp" + (openM === s.id ? " open" : "")} key={s.id}>
            <button className="m-head" onClick={() => {try {window.playSelect && window.playSelect();} catch (e) {}setOpenM(openM === s.id ? null : s.id);}}>
              {s.sys ?
            <div className="m-thumb sys">AI</div> :

            <div className="m-thumb"><img src={s.img} alt="" loading="lazy" /></div>
            }
              <div className="m-meta">
                <div className="m-no">STAMP {s.no} · {s.tag}</div>
                <div className="m-en">{s.capEN}</div>
                <div className="m-zh">{s.titleZH || s.title}</div>
              </div>
              <span className="m-plus">+</span>
            </button>
            <div className="m-body"><div className="m-body-in"><CaseBody s={s} /></div></div>
          </div>
        )}
      </div>

      {/* bottom — what this proves */}
      <section className="aigc-proves">
        <div className="p-l">
          <div className="p-kick">What this project proves</div>
          <h3>What this<br />archive proves</h3>
          <div className="p-cn">这个项目证明了什么</div>
        </div>
        <div className="p-r">
          <p className="p-body">这组 AIGC 邮票展示了我如何将 AI 应用于不同商业 brief：反诈传播、漫画内容、金融视频、虚拟演播、武侠叙事、视觉隐喻与超现实表达。它证明我不是单纯使用 AI 生成画面，而是能够根据商业问题选择合适的 AI 表达方式，并将其转化为可展示、可传播、可执行的创意内容系统。</p>
          <div className="p-tags">{AIGC_TAGS.map((t) => <span key={t}>{t}</span>)}</div>
          <div className="p-foot">
            <span className="seal2">AIGC<br />04</span>
            <span>End of file · 商业 AIGC 创意系统 · 2024–2025</span>
          </div>
        </div>
      </section>
    </div>);

}

Object.assign(window, { AIGCStamps });