/* global React */
/* 03 · SKILL MAP — 职业能力图谱.
   An orbit / capability-system diagram: a glowing CREATIVE-OS core with 6
   elliptical orbits, each carrying one capability node. Hover brightens the
   orbit + node + label; clicking opens ONE detail card (说明 / 代表项目 / 使用场景).
   Self-contained: injects its own CSS and exposes window.SkillMap. Sits inside
   the existing .do-screen section, so it inherits the dark matrix background. */
(function () {
  const { useState } = React;

  const CORE = [550, 360]; // stage coordinate space is 1100 x 680

  const NODES = [
    {
      key: "logic", no: "01", name: "Logic", cn: "产品逻辑", color: "#37cfe6",
      kw: "功能架构 / 用户路径 / 原型拆解",
      desc: "把模糊需求拆成用户路径、功能模块和可体验原型。",
      scene: "把一个想法快速变成可点击、可验证的原型时。",
      projects: ["OC MART", "My Room", "Tarot Cat", "小账"],
      pos: [716, 250], k: 0.42, side: "right",
    },
    {
      key: "planning", no: "02", name: "Planning", cn: "策划思维", color: "#f0913f",
      kw: "叙事逻辑 / 体验流程 / 方案结构",
      desc: "把复杂 brief 转化为清晰的传播主轴、内容结构和执行路径。",
      scene: "面对复杂 brief，需要理出传播主轴与执行结构时。",
      projects: ["Global Brand Content", "Live & Sports Concepts", "Complex Briefs"],
      pos: [652, 436], k: 0.62, side: "right",
    },
    {
      key: "visual", no: "03", name: "Visual", cn: "视觉执行", color: "#ef5a48",
      kw: "AIGC 画面 / 分镜表现 / 风格控制",
      desc: "使用 AIGC 和视觉判断，把抽象概念转化为可展示的画面和分镜。",
      scene: "概念需要被「看见」，转化为画面、分镜与风格时。",
      projects: ["AIGC Commercial System", "LoRA Style Test", "Visual Inspiration Radar"],
      pos: [430, 168], k: 0.40, side: "left",
    },
    {
      key: "creativity", no: "04", name: "Creativity", cn: "创意表达", color: "#f0c23f",
      kw: "概念发想 / 品牌表达 / 内容钩子",
      desc: "从用户语境和品牌命题中找到有传播力的创意表达。",
      scene: "需要一个有传播力的创意切入点或品牌表达时。",
      projects: ["Silicon Angel", "VERO MODA", "Heineken", "FIFA Concept"],
      pos: [706, 566], k: 0.40, side: "right",
    },
    {
      key: "implementation", no: "05", name: "Implementation", cn: "落地执行", color: "#a861e8",
      kw: "版本优化 / 资源统筹 / 交付推进",
      desc: "把创意方案推进到可执行、可展示、可交付的版本。",
      scene: "方案要从 PPT 走向可交付、可上线的成品时。",
      projects: ["Proposal Decks", "Portfolio Website", "Client Campaigns"],
      pos: [352, 474], k: 0.36, side: "left",
    },
    {
      key: "synergy", no: "06", name: "Synergy", cn: "协同沟通", color: "#4d7bf0",
      kw: "多方沟通 / 需求转译 / 交付节奏",
      desc: "在客户、团队、平台和工具之间进行需求翻译与协作推进。",
      scene: "客户、团队与平台之间需要有人翻译需求、对齐节奏时。",
      projects: ["Agency Projects", "Social Content", "Event Planning"],
      pos: [410, 328], k: 0.52, side: "left",
    },
  ];

  // derive each orbit ellipse from core → node (node sits on the major-axis tip)
  const GEO = NODES.map((n) => {
    const dx = n.pos[0] - CORE[0];
    const dy = n.pos[1] - CORE[1];
    const rx = Math.hypot(dx, dy);
    const rot = Math.atan2(dy, dx) * 180 / Math.PI;
    const ry = rx * n.k;
    return { rx, ry, rot, left: n.pos[0] / 1100 * 100, top: n.pos[1] / 680 * 100 };
  });

  function SkillMap() {
    const [active, setActive] = useState(0);
    const [hover, setHover] = useState(-1);
    const [mOpen, setMOpen] = useState(0); // mobile accordion (independent)
    const cur = NODES[active] || NODES[0];
    const lit = hover >= 0 ? hover : active;

    return (
      <React.Fragment>
      <div className="skillmap">
        {/* ---- orbit stage ---- */}
        <div className="sm-stage">
          <svg className="sm-svg" viewBox="0 0 1100 680" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
            <defs>
              <radialGradient id="sm-core-g" cx="50%" cy="50%" r="50%">
                <stop offset="0%" stopColor="#bfeaff" stopOpacity="0.95" />
                <stop offset="34%" stopColor="#4aa6ff" stopOpacity="0.7" />
                <stop offset="70%" stopColor="#2b6fe0" stopOpacity="0.28" />
                <stop offset="100%" stopColor="#2b6fe0" stopOpacity="0" />
              </radialGradient>
            </defs>
            {GEO.map((g, i) => (
              <ellipse key={NODES[i].key} cx={CORE[0]} cy={CORE[1]} rx={g.rx} ry={g.ry}
                transform={`rotate(${g.rot} ${CORE[0]} ${CORE[1]})`}
                fill="none" stroke={NODES[i].color}
                className={"sm-orbit" + (lit === i ? " is-on" : "")} />
            ))}
            {/* core glow */}
            <circle cx={CORE[0]} cy={CORE[1]} r="160" fill="url(#sm-core-g)" className="sm-core-glow" />
            <circle cx={CORE[0]} cy={CORE[1]} r="92" fill="none" stroke="#7cc4ff" strokeOpacity="0.5" strokeWidth="1.3" className="sm-core-ring" />
            <circle cx={CORE[0]} cy={CORE[1]} r="64" fill="none" stroke="#bfeaff" strokeOpacity="0.4" strokeWidth="1" className="sm-core-ring2" />
          </svg>

          {/* core label */}
          <div className="sm-core-label">
            <span className="sm-core-k">CREATIVE OS</span>
            <span className="sm-core-cn">产品型创意系统</span>
          </div>

          {/* nodes */}
          {NODES.map((n, i) => (
            <button
              key={n.key}
              className={"sm-node sm-node--" + n.side + (active === i ? " is-active" : "") + (hover === i ? " is-hover" : "")}
              style={{ left: GEO[i].left + "%", top: GEO[i].top + "%", "--ac": n.color }}
              onMouseEnter={() => setHover(i)}
              onMouseLeave={() => setHover(-1)}
              onClick={() => { try { window.playSelect && window.playSelect(); } catch (e) {} setActive(i); }}
              aria-label={n.name + " · " + n.cn}
            >
              <span className="sm-dot" />
              <span className="sm-label">
                <span className="sm-l-name">{n.name}</span>
                <span className="sm-l-kw">{n.cn} — {n.kw}</span>
              </span>
            </button>
          ))}
        </div>

        {/* ---- detail card ---- */}
        <aside className="sm-detail" style={{ "--ac": cur.color }} key={cur.key}>
          <div className="sm-d-top">
            <span className="sm-d-no">{cur.no}</span>
            <span className="sm-d-dot" />
          </div>
          <h3 className="sm-d-name">{cur.name}</h3>
          <div className="sm-d-cn">{cur.cn} <span>{cur.kw}</span></div>

          <div className="sm-d-block">
            <div className="sm-d-k">能力说明 · What</div>
            <p className="sm-d-v">{cur.desc}</p>
          </div>
          <div className="sm-d-block">
            <div className="sm-d-k">使用场景 · When</div>
            <p className="sm-d-v">{cur.scene}</p>
          </div>
          <div className="sm-d-block">
            <div className="sm-d-k">代表项目 · Projects</div>
            <div className="sm-d-proj">{cur.projects.map((p) => <span key={p}>{p}</span>)}</div>
          </div>
        </aside>
      </div>

      {/* ---- MOBILE: compact orbit core + accordion node rows (Option A) ---- */}
      <div className="sm-mobile">
        <div className="sm-m-core">
          <span className="sm-m-orb" aria-hidden="true">
            <span className="sm-m-orb-ring r1" />
            <span className="sm-m-orb-ring r2" />
            <span className="sm-m-orb-core" />
          </span>
          <span className="sm-m-core-txt">
            <b>CREATIVE OS</b>
            <i>SKILL MAP · 职业能力图谱</i>
          </span>
        </div>

        <div className="sm-m-list">
          {NODES.map((n, i) => (
            <div className={"sm-m-row" + (mOpen === i ? " open" : "")} key={n.key} style={{ "--ac": n.color }}>
              <button className="sm-m-head"
                aria-expanded={mOpen === i}
                onClick={() => { try { window.playSelect && window.playSelect(); } catch (e) {} setMOpen(mOpen === i ? -1 : i); }}>
                <span className="sm-m-node" />
                <span className="sm-m-tt">
                  <b>{n.no} · {n.name}</b>
                  <i>{n.cn} — {n.kw}</i>
                </span>
                <span className="sm-m-chev">{mOpen === i ? "–" : "+"}</span>
              </button>
              <div className="sm-m-panel">
                <div className="sm-m-panel-in">
                  <div className="sm-m-block">
                    <span className="sm-m-k">能力说明 · What</span>
                    <p>{n.desc}</p>
                  </div>
                  <div className="sm-m-block">
                    <span className="sm-m-k">使用场景 · When</span>
                    <p>{n.scene}</p>
                  </div>
                  <div className="sm-m-block">
                    <span className="sm-m-k">代表项目 · Projects</span>
                    <div className="sm-m-proj">{n.projects.map((p) => <span key={p}>{p}</span>)}</div>
                  </div>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
      </React.Fragment>
    );
  }

  const CSS = `
  .skillmap-mount{ width:100%; max-width:1280px; margin:0 auto; z-index:2; }
  .skillmap{ display:grid; grid-template-columns:minmax(0,1fr) 380px; gap:clamp(18px,2.6vw,44px); align-items:center; }

  .sm-stage{ position:relative; width:100%; aspect-ratio:1100/680; }
  .sm-svg{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; }

  .sm-orbit{ stroke-width:1.2; stroke-opacity:.24; transition:stroke-opacity .35s, stroke-width .35s, filter .35s; }
  .sm-orbit.is-on{ stroke-opacity:.92; stroke-width:1.8; filter:drop-shadow(0 0 7px currentColor); }
  @media (prefers-reduced-motion: no-preference){
    .sm-core-glow{ animation:smBreath 5.5s ease-in-out infinite; transform-origin:550px 360px; }
    .sm-core-ring{ animation:smSpin 26s linear infinite; transform-origin:550px 360px; }
    .sm-core-ring2{ animation:smSpin 18s linear infinite reverse; transform-origin:550px 360px; }
  }
  @keyframes smBreath{ 0%,100%{ opacity:.82; transform:scale(1);} 50%{ opacity:1; transform:scale(1.05);} }
  @keyframes smSpin{ to{ transform:rotate(360deg);} }

  .sm-core-label{ position:absolute; left:50%; top:52.9%; transform:translate(-50%,-50%); text-align:center;
    pointer-events:none; z-index:3; }
  .sm-core-k{ display:block; font-family:"Oswald",sans-serif; font-style:italic; font-weight:700;
    font-size:clamp(15px,1.55vw,23px); letter-spacing:.16em; color:#eaf6ff; text-shadow:0 0 18px rgba(120,196,255,.8); }
  .sm-core-cn{ display:block; font-family:"Noto Sans SC",sans-serif; font-weight:700; font-size:clamp(11px,1.05vw,14px);
    letter-spacing:.22em; color:#a9d6ff; margin-top:5px; text-shadow:0 0 12px rgba(80,150,240,.7); }

  .sm-node{ position:absolute; width:0; height:0; padding:0; border:0; background:none; cursor:pointer;
    color:var(--ac); font:inherit; z-index:5; }
  .sm-dot{ position:absolute; left:0; top:0; width:14px; height:14px; margin:-7px 0 0 -7px; border-radius:50%;
    background:var(--ac); box-shadow:0 0 0 4px rgba(255,255,255,.06), 0 0 14px 1px var(--ac);
    transition:transform .3s, box-shadow .3s; }
  .sm-dot::after{ content:""; position:absolute; inset:-9px; border-radius:50%; border:1px solid var(--ac); opacity:.4;
    transition:opacity .3s, transform .3s; }
  .sm-node:hover .sm-dot, .sm-node.is-active .sm-dot{ transform:scale(1.25); box-shadow:0 0 0 5px rgba(255,255,255,.08), 0 0 22px 3px var(--ac); }
  .sm-node.is-active .sm-dot::after{ opacity:.9; transform:scale(1.15); }

  .sm-label{ position:absolute; top:50%; transform:translateY(-50%); white-space:nowrap; pointer-events:none;
    display:flex; flex-direction:column; gap:2px; transition:transform .3s; }
  .sm-node--right .sm-label{ left:20px; text-align:left; align-items:flex-start; }
  .sm-node--left .sm-label{ right:20px; text-align:right; align-items:flex-end; }
  .sm-l-name{ font-family:"Oswald",sans-serif; font-style:italic; font-weight:600; font-size:clamp(16px,1.5vw,21px);
    letter-spacing:.04em; color:#d8d3e6; transition:color .3s, text-shadow .3s; }
  .sm-l-kw{ font-family:"Noto Sans SC",sans-serif; font-weight:500; font-size:clamp(11.5px,1.05vw,13.5px);
    letter-spacing:.01em; color:#7d7790; transition:color .3s; }
  .sm-node:hover .sm-l-name, .sm-node.is-active .sm-l-name{ color:#fff; text-shadow:0 0 14px var(--ac); }
  .sm-node:hover .sm-l-kw, .sm-node.is-active .sm-l-kw{ color:#c3bdd2; }
  .sm-node:hover .sm-label{ transform:translateY(-50%) translateX(0); }
  .sm-node--right:hover .sm-label{ transform:translate(3px,-50%); }
  .sm-node--left:hover .sm-label{ transform:translate(-3px,-50%); }

  /* ---- detail card ---- */
  .sm-detail{ position:relative; align-self:center; border:1px solid rgba(255,255,255,.1);
    border-top:2px solid var(--ac); border-radius:14px; padding:26px 26px 28px;
    background:linear-gradient(180deg, rgba(22,20,32,.92), rgba(14,13,20,.92));
    box-shadow:0 30px 70px -34px rgba(0,0,0,.8), 0 0 40px -20px var(--ac);
    animation:smCard .5s cubic-bezier(.2,.7,.3,1) both; }
  @keyframes smCard{ from{ opacity:0; transform:translateY(12px);} to{ opacity:1; transform:none;} }
  .sm-d-top{ display:flex; align-items:center; justify-content:space-between; }
  .sm-d-no{ font-family:"Oswald",sans-serif; font-style:italic; font-weight:700; font-size:38px; line-height:1;
    color:transparent; -webkit-text-stroke:1.3px var(--ac); opacity:.85; }
  .sm-d-dot{ width:11px; height:11px; border-radius:50%; background:var(--ac); box-shadow:0 0 14px 1px var(--ac); }
  .sm-d-name{ font-family:"Oswald",sans-serif; font-style:italic; font-weight:600; font-size:clamp(26px,2.3vw,33px);
    letter-spacing:.02em; color:#fff; margin:12px 0 3px; }
  .sm-d-cn{ font-family:"Noto Sans SC",sans-serif; font-weight:700; font-size:15px; color:var(--ac); letter-spacing:.02em; }
  .sm-d-cn span{ display:block; font-weight:500; font-size:12.5px; color:#8b8599; margin-top:4px; letter-spacing:.04em; }
  .sm-d-block{ margin-top:18px; padding-top:16px; border-top:1px solid rgba(255,255,255,.08); }
  .sm-d-block:first-of-type{ margin-top:20px; }
  .sm-d-k{ font-family:"Oswald",sans-serif; font-style:italic; font-weight:600; font-size:12px; letter-spacing:.14em;
    text-transform:uppercase; color:var(--ac); opacity:.9; margin-bottom:8px; }
  .sm-d-v{ font-family:"Noto Sans SC",sans-serif; font-weight:500; font-size:14.5px; line-height:1.75; color:#c9c4d6; margin:0; text-wrap:pretty; }
  .sm-d-proj{ display:flex; flex-wrap:wrap; gap:7px; }
  .sm-d-proj span{ font-family:"Noto Sans SC",sans-serif; font-weight:500; font-size:12.5px; color:#d6d1e2;
    padding:5px 11px; border-radius:999px; border:1px solid rgba(255,255,255,.16); background:rgba(255,255,255,.04); }

  /* ---- mobile accordion (Option A) — hidden on desktop ---- */
  .sm-mobile{ display:none; }

  /* ---- responsive ---- */
  @media (max-width:1000px){
    .skillmap{ grid-template-columns:1fr; gap:24px; }
    .sm-detail{ max-width:560px; margin:0 auto; width:100%; }
  }
  @media (max-width:768px){
    .skillmap{ display:none !important; }
    .sm-mobile{ display:block; width:100%; }

    .sm-m-core{ display:flex; align-items:center; gap:16px; padding:6px 4px 22px; margin-bottom:8px;
      border-bottom:1px solid rgba(255,255,255,.08); }
    .sm-m-orb{ position:relative; width:62px; height:62px; flex:none; display:grid; place-items:center; }
    .sm-m-orb-core{ width:24px; height:24px; border-radius:50%;
      background:radial-gradient(circle at 38% 32%, #cdeeff, #4aa6ff 55%, #2b6fe0); box-shadow:0 0 18px 2px rgba(74,166,255,.8); }
    .sm-m-orb-ring{ position:absolute; border-radius:50%; border:1px solid rgba(124,196,255,.5); }
    .sm-m-orb-ring.r1{ inset:6px; }
    .sm-m-orb-ring.r2{ inset:0; border-color:rgba(124,196,255,.28); }
    @media (prefers-reduced-motion: no-preference){
      .sm-m-orb-ring.r1{ animation:smSpin 14s linear infinite; }
      .sm-m-orb-core{ animation:smBreath 4.5s ease-in-out infinite; }
    }
    .sm-m-core-txt{ display:flex; flex-direction:column; gap:4px; }
    .sm-m-core-txt b{ font-family:"Oswald",sans-serif; font-style:italic; font-weight:700; font-size:19px;
      letter-spacing:.1em; color:#eaf6ff; text-shadow:0 0 14px rgba(120,196,255,.7); }
    .sm-m-core-txt i{ font-family:"Noto Sans SC",sans-serif; font-style:normal; font-size:11.5px; letter-spacing:.06em; color:#9da7c4; }

    .sm-m-list{ display:flex; flex-direction:column; gap:10px; }
    .sm-m-row{ border:1px solid rgba(255,255,255,.1); border-radius:13px; overflow:hidden;
      background:linear-gradient(180deg, rgba(22,20,32,.7), rgba(14,13,20,.7)); transition:border-color .3s, box-shadow .3s; }
    .sm-m-row.open{ border-color:var(--ac); box-shadow:0 0 0 1px var(--ac), 0 18px 40px -24px var(--ac); }
    .sm-m-head{ display:flex; align-items:center; gap:13px; width:100%; min-height:64px; padding:12px 15px;
      background:none; border:0; cursor:pointer; text-align:left; color:inherit; }
    .sm-m-node{ width:13px; height:13px; flex:none; border-radius:50%; background:var(--ac);
      box-shadow:0 0 12px 1px var(--ac); position:relative; }
    .sm-m-row.open .sm-m-node::after{ content:""; position:absolute; inset:-5px; border-radius:50%; border:1px solid var(--ac); opacity:.6; }
    .sm-m-tt{ flex:1; min-width:0; display:flex; flex-direction:column; gap:3px; }
    .sm-m-tt b{ font-family:"Oswald",sans-serif; font-style:italic; font-weight:600; font-size:17px; letter-spacing:.02em; color:#ece9f4; }
    .sm-m-tt i{ font-family:"Noto Sans SC",sans-serif; font-style:normal; font-size:12.5px; line-height:1.4; color:#8b8599; }
    .sm-m-row.open .sm-m-tt b{ color:#fff; }
    .sm-m-chev{ flex:none; width:30px; height:30px; display:grid; place-items:center; border-radius:50%;
      border:1px solid rgba(255,255,255,.18); color:var(--ac); font-size:18px; font-weight:300; line-height:1; }
    .sm-m-panel{ display:grid; grid-template-rows:0fr; transition:grid-template-rows .34s cubic-bezier(.2,.8,.2,1); }
    .sm-m-row.open .sm-m-panel{ grid-template-rows:1fr; }
    .sm-m-panel-in{ overflow:hidden; }
    .sm-m-block{ padding:14px 16px 0; }
    .sm-m-block:last-child{ padding-bottom:18px; }
    .sm-m-k{ display:block; font-family:"Oswald",sans-serif; font-style:italic; font-weight:600; font-size:11px;
      letter-spacing:.14em; text-transform:uppercase; color:var(--ac); margin-bottom:6px; }
    .sm-m-block p{ font-family:"Noto Sans SC",sans-serif; font-size:14px; line-height:1.7; color:#c9c4d6; margin:0; text-wrap:pretty; }
    .sm-m-proj{ display:flex; flex-wrap:wrap; gap:7px; }
    .sm-m-proj span{ font-family:"Noto Sans SC",sans-serif; font-size:12.5px; color:#d6d1e2;
      padding:5px 11px; border-radius:999px; border:1px solid rgba(255,255,255,.16); background:rgba(255,255,255,.04); }
  }
  @media (max-width:430px){
    .sm-m-core-txt b{ font-size:17px; }
    .sm-m-tt b{ font-size:16px; }
    .sm-m-tt i{ font-size:12px; }
  }
  `;

  if (!document.getElementById("skillmap-style")) {
    const s = document.createElement("style");
    s.id = "skillmap-style";
    s.textContent = CSS;
    document.head.appendChild(s);
  }

  window.SkillMap = SkillMap;
})();
