import { useState, useEffect, useRef, useCallback } from "react";

/* ============================================================
   Chelsea-Labs バーチャル市民開発ラボ
   SHEET 8 のエージェント編成(P1〜P5)+ 主役のメカ設計者(人間)が
   「課題 → 3点セット → 壁打ち → プロトタイプ → 自走」を回す
   市民開発の一日シミュレーター
   ============================================================ */

const AGENTS = [
  { id: "member", name: "設計 学",   role: "メカ設計者(市民開発者)", kind: "人間", color: "#E0563C", desk: { x: 20, y: 40, z: 0.9 } },
  { id: "pm",     name: "仕切 舞",   role: "P1 進行管理・人格",       kind: "AI",   color: "#D94F1E", desk: { x: 50, y: 30, z: 0.8 } },
  { id: "kabe",   name: "壁打 直人", role: "P2 壁打ち・一次対応",     kind: "AI",   color: "#C9962B", desk: { x: 32, y: 62, z: 1.0 } },
  { id: "yoken",  name: "要件 定子", role: "P3 要件定義(3点セット)",  kind: "AI",   color: "#2B8A78", desk: { x: 58, y: 64, z: 1.0 } },
  { id: "review", name: "目利 厳",   role: "P4 品質レビュー",         kind: "AI",   color: "#6B4A9E", desk: { x: 78, y: 52, z: 0.93 } },
  { id: "watch",  name: "巡回 守",   role: "P5 進捗ウォッチ",         kind: "AI",   color: "#3D6EA8", desk: { x: 85, y: 32, z: 0.82 } },
];

const DOOR = { x: -8, y: 78 };

const IDLE_QUIPS = {
  member: ["この作業、絶対アプリにできる", "Gitって図面の版管理と同じか", "次は自分で直してみたい"],
  pm:     ["ゴールは納品じゃなく自走", "定時とは、守るための概念", "今日の采配、冴えてる"],
  kabe:   ["エラーは成長の入口", "比喩は治具。伝わるまで調整", "質問、歓迎です"],
  yoken:  ["スコープは削るほど輝く", "『あれもこれも』は敵", "要確認事項が3つ…"],
  review: ["良い点から言うのが流儀", "指摘は3件まで。それが優しさ", "安全第一、学び第二"],
  watch:  ["停滞は責めない。拾うだけ", "needs-human 見逃しません", "今週も巡回日和"],
};

const buildScenario = (request) => [
  { d: 600,  phase: "commute", log: { who: "受付", icon: "🚪", text: "おはようございます。市民開発ラボ、開所します" } },
  { d: 2800, log: { who: "設計者", icon: "💬", text: `設計さんが Issue を投稿:「${request}」` },
    focus: "member",
    fly: { from: "member", to: "pm", icon: "💬" },
    agent: { member: { status: "課題を投稿", bubble: "この困りごと、何とかしたい!", working: true } } },
  { d: 2400, log: { who: "P1", icon: "🗂", text: "課題を受領。市民開発フローに沿ってタスク分解" },
    focus: "pm",
    board: [
      { label: "ヒアリング整理・要件定義", owner: "P3", state: "着手待ち" },
      { label: "3点セットHTML作成", owner: "P3", state: "着手待ち" },
      { label: "本人の壁打ち・修正", owner: "設計さん", state: "待機" },
      { label: "品質レビュー", owner: "P4", state: "待機" },
      { label: "プロトタイプ実装", owner: "伴走担当", state: "待機" },
    ],
    fly: { from: "pm", to: "yoken", icon: "📋" },
    agent: {
      pm:     { status: "進行管理中", bubble: "定子さん、3点セットを!", working: false },
      member: { status: "壁打ち準備中", bubble: null, working: false },
    } },
  { d: 2200, log: { who: "P3", icon: "✍️", text: "ヒアリングメモを構造化し、執筆開始" },
    focus: "yoken",
    agent: { yoken: { status: "執筆中", bubble: "考え中…", working: true } },
    boardState: { 0: "作業中" } },
  { d: 2600, log: { who: "成果物", icon: "📦", text: "requirements.html / architecture.html / mockup.html 生成" },
    deliver: "requirements.html", flyDoc: "yoken",
    boardState: { 0: "完了", 1: "完了", 2: "壁打ち中" },
    agent: { yoken: { status: "壁打ち待ち", bubble: "3点セット、できました!", working: false } } },
  { d: 1200, deliver: "architecture.html", flyDoc: "yoken" },
  { d: 1200, deliver: "mockup.html", flyDoc: "yoken" },
  { d: 2200, log: { who: "設計者", icon: "🗣", text: "設計さんが壁打ち開始:「この画面、現場の流れと違うかも」" },
    focus: "member",
    fly: { from: "member", to: "kabe", icon: "❓" },
    agent: {
      member: { status: "壁打ち中", bubble: "工程の順番、現場と違うかも", working: true },
      kabe:   { status: "一次対応中", bubble: "考え中…", working: true },
    } },
  { d: 2800, log: { who: "P2", icon: "💡", text: "意図を言語化して修正案を提示(治具の比喩で説明)" },
    fly: { from: "kabe", to: "yoken", icon: "📝" },
    agent: {
      kabe:  { status: "修正案を提示", bubble: "検査工程は最後に回しましょう", working: true },
      yoken: { status: "修正対応中", bubble: "考え中…", working: true },
    } },
  { d: 2400, log: { who: "設計者", icon: "✅", text: "設計さん「これなら現場で使える!」— 方向性決定" },
    focus: "member",
    boardState: { 2: "完了", 3: "レビュー中" },
    fly: { from: "yoken", to: "review", icon: "📄" },
    agent: {
      member: { status: "方向性を承認", bubble: "これなら現場で使える!", working: false },
      review: { status: "レビュー中", bubble: "考え中…", working: true },
    } },
  { d: 2600, log: { who: "P4", icon: "🔍", text: "安全・要件一致・学びの観点でレビュー → 承認" },
    boardState: { 3: "完了", 4: "実装中" },
    agent: {
      review: { status: "承認済み", bubble: "安全性クリア。良い要件です", working: false },
      yoken:  { status: "業務完了", bubble: "達成感…!", working: false },
    } },
  { d: 2600, log: { who: "伴走", icon: "🚀", text: "プロトタイプを社内ドメインへ自動デプロイ" },
    deliver: "prototype v0.1(社内URL)", flyDoc: "pm",
    boardState: { 4: "完了" },
    focus: "pm",
    agent: { pm: { status: "デプロイ確認中", bubble: "社内URL、公開しました", working: true } } },
  { d: 2600, log: { who: "設計者", icon: "🎓", text: "設計さんが自分で軽微修正をPR → マージ成功(自走の一歩!)" },
    focus: "member",
    agent: {
      member: { status: "自走スタート!", bubble: "自分で直せた…!", working: false },
      kabe:   { status: "見守り中", bubble: "その調子です!", working: false },
    } },
  { d: 2200, log: { who: "P5", icon: "📋", text: "週次レポート起票: 自走事例1件・needs-human 0件" },
    focus: "watch",
    agent: { watch: { status: "レポート起票中", bubble: "考え中…", working: true } } },
  { d: 2200, log: { who: "P1", icon: "🎉", text: "市民開発、1案件完走。全員定時で退勤!" },
    confetti: true, focus: null,
    agent: {
      pm:     { status: "完走!", bubble: "みんな、おつかれさま!", working: false },
      member: { status: "本日の主役", bubble: "次の改善アイデアもある!", working: false },
      watch:  { status: "業務完了", bubble: "また来週", working: false },
    } },
  { d: 3200, phase: "leave", log: { who: "受付", icon: "🌙", text: "本日のラボは閉所しました" }, night: true },
];

const initialAgents = () =>
  AGENTS.reduce((acc, a) => {
    acc[a.id] = { status: "未出勤", bubble: null, working: false };
    return acc;
  }, {});

let uid = 0;

export default function VirtualCitizenDevLab() {
  const [agentState, setAgentState] = useState(initialAgents);
  const [phase, setPhase] = useState("off");
  const [logs, setLogs] = useState([]);
  const [board, setBoard] = useState([]);
  const [deliverables, setDeliverables] = useState([]);
  const [running, setRunning] = useState(false);
  const [done, setDone] = useState(false);
  const [night, setNight] = useState(false);
  const [focus, setFocus] = useState(null);
  const [flights, setFlights] = useState([]);
  const [confetti, setConfetti] = useState([]);
  const [request, setRequest] = useState("検査記録の転記作業をアプリ化したい");
  const [quipTick, setQuipTick] = useState(0);
  const timers = useRef([]);

  const clearTimers = () => { timers.current.forEach(clearTimeout); timers.current = []; };
  useEffect(() => () => clearTimers(), []);
  useEffect(() => {
    const iv = setInterval(() => setQuipTick((t) => t + 1), 4200);
    return () => clearInterval(iv);
  }, []);

  const pushLog = (e) => setLogs((p) => [...p.slice(-6), { ...e, id: ++uid }]);

  const spawnFlight = (fromId, toMonitor, icon) => {
    const from = AGENTS.find((a) => a.id === fromId).desk;
    const to = toMonitor === true ? { x: 90, y: 22 } : AGENTS.find((a) => a.id === toMonitor).desk;
    const id = ++uid;
    setFlights((p) => [...p, { id, from, to, icon }]);
    const t = setTimeout(() => setFlights((p) => p.filter((f) => f.id !== id)), 1400);
    timers.current.push(t);
  };

  const fireConfetti = () => {
    const pieces = Array.from({ length: 46 }, (_, i) => ({
      id: ++uid,
      x: 20 + Math.random() * 60,
      delay: Math.random() * 0.8,
      dur: 2.2 + Math.random() * 1.4,
      color: ["#D94F1E", "#2B8A78", "#C9962B", "#6B4A9E", "#3D6EA8"][i % 5],
      rot: Math.random() * 360,
      drift: (Math.random() - 0.5) * 120,
    }));
    setConfetti(pieces);
    const t = setTimeout(() => setConfetti([]), 4600);
    timers.current.push(t);
  };

  const start = useCallback(() => {
    clearTimers();
    setAgentState(initialAgents());
    setLogs([]); setBoard([]); setDeliverables([]);
    setDone(false); setNight(false); setFocus(null);
    setFlights([]); setConfetti([]);
    setRunning(true); setPhase("off");

    const steps = buildScenario(request.trim() || "現場の困りごとをアプリ化したい");
    let acc = 0;
    steps.forEach((step) => {
      acc += step.d;
      const t = setTimeout(() => {
        if (step.phase === "commute") {
          setPhase("commute");
          AGENTS.forEach((a, i) => {
            const tt = setTimeout(() => {
              setAgentState((prev) => ({
                ...prev,
                [a.id]: { ...prev[a.id], status: "着席", bubble: a.kind === "人間" ? "今日こそ形にするぞ" : "おはようございます" },
              }));
            }, 400 + i * 300);
            timers.current.push(tt);
          });
          const tw = setTimeout(() => setPhase("work"), 400 + AGENTS.length * 300 + 900);
          timers.current.push(tw);
        }
        if (step.phase === "leave") setPhase("leave");
        if (step.night) setNight(true);
        if (step.log) pushLog(step.log);
        if (step.board) setBoard(step.board);
        if (step.boardState)
          setBoard((prev) => prev.map((b, i) =>
            step.boardState[i] !== undefined ? { ...b, state: step.boardState[i] } : b));
        if (step.deliver) {
          const tt = setTimeout(() => setDeliverables((p) => [...p, step.deliver]), 900);
          timers.current.push(tt);
        }
        if (step.flyDoc) spawnFlight(step.flyDoc, true, "📄");
        if (step.fly) spawnFlight(step.fly.from, step.fly.to, step.fly.icon);
        if (step.focus !== undefined) setFocus(step.focus);
        if (step.confetti) fireConfetti();
        if (step.agent)
          setAgentState((prev) => {
            const next = { ...prev };
            Object.entries(step.agent).forEach(([id, patch]) => {
              next[id] = { ...next[id], ...patch };
            });
            return next;
          });
        if (step.phase === "leave") { setDone(true); setRunning(false); }
      }, acc);
      timers.current.push(t);
    });
  }, [request]);

  const reset = () => {
    clearTimers();
    setAgentState(initialAgents());
    setPhase("off"); setLogs([]); setBoard([]); setDeliverables([]);
    setRunning(false); setDone(false); setNight(false); setFocus(null);
    setFlights([]); setConfetti([]);
  };

  const bubbleFor = (a) => {
    const st = agentState[a.id];
    if (st.bubble) return st.bubble;
    const quips = IDLE_QUIPS[a.id];
    return quips[(quipTick + AGENTS.findIndex((x) => x.id === a.id)) % quips.length];
  };

  const atDesk = phase === "work" || phase === "commute";
  const leaving = phase === "leave";
  const stateColor = (s) =>
    s.includes("完了") || s.includes("完走") || s === "着席" || s.includes("自走") || s.includes("主役") || s.includes("承認") ? "#2E7D4F"
    : s === "未出勤" || s === "待機" || s === "着手待ち" || s.includes("見守り") ? "#8FA0AE"
    : "#D94F1E";

  return (
    <div className={`vc-root${night ? " night" : ""}`}>
      <style>{`
        @import url('https://fonts.googleapis.com/css2?family=Zen+Kaku+Gothic+New:wght@500;700;900&family=IBM+Plex+Mono:wght@400;500&display=swap');

        .vc-root{
          font-family:'Zen Kaku Gothic New',sans-serif;
          width:100%;min-height:100vh;position:relative;overflow:hidden;
          color:#2B2620;display:flex;flex-direction:column;
          background:linear-gradient(180deg,#E4CE8F 0%,#E9D8A5 34%,#EFE6CE 34%,#EDE4CA 100%);
          transition:filter 2.4s ease;
        }
        .vc-root.night{filter:brightness(0.72) saturate(0.85) hue-rotate(-8deg);}
        .vc-mono{font-family:'IBM Plex Mono',monospace;}

        .vc-header{
          display:flex;align-items:center;gap:14px;
          padding:14px 22px;background:#2B2620;color:#F5EFE2;
          border-bottom:3px solid #1B1712;z-index:40;
        }
        .vc-logo{
          width:34px;height:34px;border-radius:8px;flex-shrink:0;
          background:linear-gradient(135deg,#D94F1E,#2B8A78);
          display:flex;align-items:center;justify-content:center;font-size:17px;
        }
        .vc-header h1{font-size:17px;font-weight:900;letter-spacing:0.04em;}
        .vc-header .sub{font-size:10.5px;color:#B9AE99;letter-spacing:0.14em;}
        .vc-live{
          margin-left:auto;display:flex;align-items:center;gap:7px;
          font-family:'IBM Plex Mono',monospace;font-size:11px;
          border:1.5px solid #D94F1E;color:#FF8A5C;
          padding:4px 12px;border-radius:99px;
        }
        .vc-live .dot{width:8px;height:8px;border-radius:50%;background:#FF5C33;animation:vcBlink 1.2s infinite;}
        @keyframes vcBlink{0%,100%{opacity:1}50%{opacity:.25}}

        .vc-stage{position:relative;flex:1;min-height:540px;}
        .vc-camera{
          position:absolute;inset:0;
          animation:vcCam 26s ease-in-out infinite alternate;
          transform-origin:50% 55%;
        }
        @keyframes vcCam{
          0%{transform:scale(1) translateX(0)}
          50%{transform:scale(1.035) translateX(-0.7%)}
          100%{transform:scale(1.02) translateX(0.7%)}
        }
        .vc-floor{
          position:absolute;left:50%;top:56%;width:88%;max-width:980px;height:64%;
          transform:translate(-50%,-42%);
          background:radial-gradient(ellipse at 50% 42%, #F2ECDD 0%, #E8E0CB 68%, transparent 72%);
          border-radius:50%;
        }
        .vc-sign{
          position:absolute;left:50%;top:8%;transform:translateX(-50%);
          background:#8A6238;color:#F5EFE2;font-weight:900;font-size:13px;
          letter-spacing:0.22em;padding:7px 24px;border-radius:4px;
          box-shadow:0 3px 0 #6E4C2A;z-index:5;
          animation:vcSway 5.5s ease-in-out infinite;
          transform-origin:top center;
        }
        @keyframes vcSway{0%,100%{transform:translateX(-50%) rotate(-0.7deg)}50%{transform:translateX(-50%) rotate(0.7deg)}}
        .vc-scroll{
          position:absolute;width:60px;padding:12px 8px 16px;
          background:#F7F1E2;border:1.5px solid #C7B896;border-top:8px solid #8A6238;
          writing-mode:vertical-rl;font-size:11px;font-weight:700;color:#6E5A3A;
          letter-spacing:0.24em;border-radius:2px;z-index:4;
          animation:vcSway 7s ease-in-out infinite;transform-origin:top center;
        }
        .vc-plant{
          position:absolute;font-size:34px;z-index:4;
          animation:vcSway 4.5s ease-in-out infinite;transform-origin:bottom center;
        }
        .vc-clock{
          position:absolute;right:26%;top:9%;width:44px;height:44px;z-index:5;
          background:#FFFDF7;border:3px solid #2B2620;border-radius:50%;
        }
        .vc-clock .hand{position:absolute;left:50%;bottom:50%;transform-origin:bottom center;background:#2B2620;border-radius:2px;}
        .vc-clock .h{width:3px;height:11px;}
        .vc-clock .m{width:2px;height:15px;}
        .vc-clock.run .h{animation:vcSpin 24s linear infinite;}
        .vc-clock.run .m{animation:vcSpin 2s linear infinite;}
        @keyframes vcSpin{to{transform:rotate(360deg)}}

        .vc-board{
          position:absolute;left:50%;top:14%;transform:translateX(-50%);
          width:min(440px,46%);
          background:#23282E;color:#E4E8ED;
          border:3px solid #171B1F;border-radius:6px;
          padding:10px 14px 12px;z-index:20;
          box-shadow:0 8px 20px rgba(30,25,18,0.28);
          animation:vcSway 8s ease-in-out infinite;transform-origin:top center;
        }
        .vc-board::before,.vc-board::after{content:'';position:absolute;top:-42px;width:2px;height:42px;background:#5A5248;}
        .vc-board::before{left:18%}
        .vc-board::after{right:18%}
        .vc-board h2{
          font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:0.2em;
          color:#8FB8E8;border-bottom:1px solid #3A424B;padding-bottom:6px;margin-bottom:7px;
        }
        .vc-board .row{display:flex;align-items:baseline;gap:8px;font-size:10.5px;padding:3px 0;animation:vcSlide .4s ease;}
        .vc-board .row .lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
        .vc-board .row .own{color:#9AA6B2;font-size:9.5px;flex-shrink:0;}
        .vc-board .row .st{
          font-family:'IBM Plex Mono',monospace;font-size:9px;
          padding:1px 8px;border-radius:99px;border:1px solid;flex-shrink:0;
          transition:color .4s,border-color .4s;
        }
        .vc-board .empty{font-size:11px;color:#7A868F;padding:8px 0;}

        .vc-spot{
          position:absolute;z-index:10;
          transition:left 1.6s cubic-bezier(.45,.05,.35,1), top 1.6s cubic-bezier(.45,.05,.35,1), opacity .8s;
        }
        .vc-spot.walking .vc-char{animation:vcWalk .5s ease-in-out infinite;}
        @keyframes vcWalk{
          0%,100%{transform:translateX(-50%) translateY(0) rotate(-2.5deg)}
          50%{transform:translateX(-50%) translateY(-4px) rotate(2.5deg)}
        }
        .vc-desk{position:relative;width:126px;height:64px;transition:transform .6s ease;}
        .vc-spot.focused .vc-desk{transform:scale(1.1);}
        .vc-spot.focused .vc-halo{opacity:1;}
        .vc-halo{
          position:absolute;left:50%;top:58%;width:165px;height:78px;
          transform:translate(-50%,-50%);border-radius:50%;
          background:radial-gradient(ellipse, rgba(217,79,30,0.22), transparent 68%);
          opacity:0;transition:opacity .6s;pointer-events:none;
        }
        .vc-desk .top{
          position:absolute;left:0;right:0;top:26px;height:15px;
          background:linear-gradient(180deg,#C99A64,#B98A5A);
          border-radius:4px;box-shadow:0 2px 0 #9A7146;
        }
        .vc-desk .leg{position:absolute;top:41px;width:7px;height:24px;background:#9A7146;border-radius:0 0 2px 2px;}
        .vc-desk .laptop{
          position:absolute;left:50%;top:9px;transform:translateX(-50%);
          width:30px;height:19px;background:#3A4150;border-radius:2.5px 2.5px 0 0;
          border-bottom:3px solid #262C38;
        }
        .vc-desk .laptop::after{
          content:'';position:absolute;inset:2.5px;
          background:linear-gradient(135deg,#8FD0C2,#5C89B8);border-radius:1.5px;opacity:.9;
        }
        .vc-desk.busy .laptop::after{animation:vcScreen 0.9s steps(2) infinite;}
        @keyframes vcScreen{0%{opacity:.9}50%{opacity:.65}100%{opacity:.9}}
        .vc-desk .mug{position:absolute;right:14px;top:15px;width:9px;height:9px;border-radius:2px;}
        .vc-steam{
          position:absolute;right:16px;top:-2px;width:4px;height:12px;
          border-radius:99px;background:rgba(255,255,255,0.75);
          animation:vcSteam 2.6s ease-in-out infinite;
        }
        .vc-steam.s2{right:11px;animation-delay:1.1s;}
        @keyframes vcSteam{
          0%{transform:translateY(6px) scaleY(.4);opacity:0}
          35%{opacity:.85}
          100%{transform:translateY(-10px) scaleY(1.1);opacity:0}
        }

        .vc-char{
          position:absolute;left:50%;top:-24px;transform:translateX(-50%);
          width:40px;display:flex;flex-direction:column;align-items:center;z-index:-1;
        }
        .vc-char .head{
          width:24px;height:24px;border-radius:50%;
          background:#F3D3AC;border:1.5px solid rgba(0,0,0,0.08);position:relative;
        }
        .vc-char.human .head::marker{content:none;}
        .vc-char .helmet{
          position:absolute;left:50%;top:-7px;transform:translateX(-50%);
          width:26px;height:13px;border-radius:13px 13px 0 0;
          background:#F2C230;border:1.5px solid rgba(0,0,0,0.12);
        }
        .vc-char .head::before,.vc-char .head::after{
          content:'';position:absolute;top:10px;width:3px;height:4.5px;
          border-radius:2px;background:#2B2620;
          animation:vcEyes 4.4s infinite;
        }
        .vc-char .head::before{left:6px}
        .vc-char .head::after{right:6px}
        @keyframes vcEyes{0%,93%,100%{transform:scaleY(1)}95.5%{transform:scaleY(.12)}}
        .vc-char .body{width:36px;height:30px;margin-top:-3px;border-radius:12px 12px 6px 6px;}
        .vc-char.working .body{animation:vcType .8s infinite;}
        .vc-char.working .arm{
          position:absolute;bottom:2px;width:9px;height:5px;border-radius:3px;
          background:#F3D3AC;animation:vcHands .4s infinite alternate;
        }
        .vc-char.working .arm.l{left:-3px}
        .vc-char.working .arm.r{right:-3px;animation-delay:.2s}
        @keyframes vcHands{from{transform:translateY(0)}to{transform:translateY(-3px)}}
        @keyframes vcType{0%,100%{transform:translateY(0)}50%{transform:translateY(1.5px)}}
        .vc-char.happy{animation:vcJump .7s ease-in-out 2;}
        @keyframes vcJump{
          0%,100%{transform:translateX(-50%) translateY(0)}
          40%{transform:translateX(-50%) translateY(-13px)}
        }

        .vc-bubble{
          position:absolute;left:50%;bottom:100%;
          transform:translate(-50%,-52px) scale(1);
          background:#FFFDF7;border:1.5px solid #2B2620;border-radius:12px;
          padding:5px 12px;font-size:11px;font-weight:700;white-space:nowrap;
          max-width:215px;overflow:hidden;text-overflow:ellipsis;
          box-shadow:0 2px 0 rgba(43,38,32,0.18);z-index:14;
          animation:vcBubbleIn .45s cubic-bezier(.34,1.56,.64,1);
        }
        @keyframes vcBubbleIn{
          from{transform:translate(-50%,-42px) scale(.4);opacity:0}
          to{transform:translate(-50%,-52px) scale(1);opacity:1}
        }
        .vc-bubble::after{
          content:'';position:absolute;left:50%;top:100%;transform:translateX(-50%);
          border:6px solid transparent;border-top-color:#2B2620;
        }
        .vc-bubble.think{color:#8A6238;}
        .vc-bubble.think .pulse{animation:vcBlink 1.1s infinite;display:inline-block;}
        .vc-nametag{
          position:absolute;left:50%;top:62px;transform:translateX(-50%);
          font-size:9.5px;color:#6E5A3A;white-space:nowrap;text-align:center;line-height:1.5;
        }
        .vc-nametag b{font-size:11px;color:#2B2620;}
        .vc-kind{
          display:inline-block;font-family:'IBM Plex Mono',monospace;
          font-size:8px;padding:0 5px;border-radius:99px;border:1px solid;
          margin-left:4px;vertical-align:1px;
        }
        .vc-kind.ai{color:#6B4A9E;border-color:#6B4A9E;background:#F0EBF8;}
        .vc-kind.human{color:#D94F1E;border-color:#D94F1E;background:#FBEDE6;}

        .vc-flight{
          position:absolute;font-size:22px;z-index:26;pointer-events:none;
          animation:vcFly 1.35s cubic-bezier(.4,.1,.4,1) forwards;
          filter:drop-shadow(0 3px 2px rgba(43,38,32,0.25));
        }
        @keyframes vcFly{
          0%{transform:translate(0,0) scale(.7) rotate(-8deg);opacity:0}
          12%{opacity:1}
          50%{transform:translate(calc(var(--dx)/2), calc(var(--dy)/2 - 70px)) scale(1.05) rotate(6deg)}
          88%{opacity:1}
          100%{transform:translate(var(--dx), var(--dy)) scale(.6) rotate(-4deg);opacity:0}
        }

        .vc-confetti{
          position:absolute;top:-4%;width:9px;height:14px;z-index:38;
          border-radius:2px;pointer-events:none;
          animation:vcFall var(--dur) ease-in var(--delay) forwards;
        }
        @keyframes vcFall{
          0%{transform:translateY(0) translateX(0) rotate(var(--rot));opacity:1}
          80%{opacity:1}
          100%{transform:translateY(105vh) translateX(var(--drift)) rotate(calc(var(--rot) + 540deg));opacity:0}
        }

        .vc-staff{
          position:absolute;left:18px;top:15%;z-index:22;
          display:flex;flex-direction:column;gap:7px;width:216px;
        }
        .vc-staff .card{
          background:rgba(255,253,247,0.94);
          border:1.5px solid #2B2620;border-radius:8px;
          padding:6px 12px;display:flex;align-items:center;gap:9px;
          box-shadow:0 2px 0 rgba(43,38,32,0.14);
          transition:transform .3s ease;
        }
        .vc-staff .card.hot{transform:translateX(5px);border-color:#D94F1E;}
        .vc-staff .card.human-card{border-left:4px solid #D94F1E;}
        .vc-staff .swatch{width:11px;height:11px;border-radius:50%;flex-shrink:0;}
        .vc-staff .nm{font-size:12px;font-weight:700;line-height:1.3;}
        .vc-staff .rl{font-size:9px;color:#8A7E68;}
        .vc-staff .st{margin-left:auto;font-size:9.5px;font-weight:700;text-align:right;line-height:1.3;flex-shrink:0;transition:color .4s;}

        .vc-monitor{
          position:absolute;right:18px;top:15%;z-index:22;width:218px;
          background:rgba(255,253,247,0.96);
          border:1.5px solid #2B2620;border-radius:10px;
          padding:12px 14px 14px;box-shadow:0 2px 0 rgba(43,38,32,0.14);
        }
        .vc-monitor.receiving{animation:vcRecv .5s ease;}
        @keyframes vcRecv{0%{transform:scale(1)}40%{transform:scale(1.05)}100%{transform:scale(1)}}
        .vc-monitor h3{font-size:12px;font-weight:900;margin-bottom:8px;display:flex;align-items:center;gap:7px;}
        .vc-monitor .empty{
          font-size:11px;color:#9A8F7A;border:1.5px dashed #C7B896;
          border-radius:8px;padding:20px 10px;text-align:center;
        }
        .vc-chip{
          display:inline-block;font-family:'IBM Plex Mono',monospace;font-size:10px;
          background:#F0EBE0;border:1.5px solid #8A6238;color:#5C4326;
          border-radius:6px;padding:3px 9px;margin:0 6px 6px 0;
          animation:vcPop .5s cubic-bezier(.34,1.56,.64,1);
        }
        @keyframes vcPop{from{transform:scale(.4);opacity:0}to{transform:scale(1);opacity:1}}
        .vc-done{
          margin-top:8px;font-size:11.5px;font-weight:900;color:#2E7D4F;
          background:#E9F4EC;border:1.5px solid #2E7D4F;border-radius:8px;
          padding:7px 10px;text-align:center;animation:vcPop .5s cubic-bezier(.34,1.56,.64,1);
        }

        .vc-log{
          position:absolute;left:18px;bottom:96px;z-index:22;
          width:min(340px,46%);display:flex;flex-direction:column;gap:4px;
        }
        .vc-log .line{
          background:rgba(255,253,247,0.92);border-left:3px solid #8A6238;
          font-size:11px;padding:4px 10px;border-radius:0 6px 6px 0;
          display:flex;gap:8px;align-items:baseline;
          animation:vcSlide .4s cubic-bezier(.34,1.4,.64,1);
          overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
        }
        .vc-log .line .who{font-weight:900;font-size:10px;color:#8A6238;flex-shrink:0;}
        @keyframes vcSlide{from{transform:translateX(-14px);opacity:0}to{transform:none;opacity:1}}

        .vc-controls{
          position:relative;z-index:40;display:flex;gap:10px;align-items:center;
          padding:16px 22px 20px;
          background:linear-gradient(180deg,transparent,rgba(43,38,32,0.06));
        }
        .vc-input{
          flex:1;max-width:520px;font-family:'Zen Kaku Gothic New',sans-serif;
          font-size:13px;padding:11px 16px;border:2px solid #2B2620;border-radius:10px;
          background:#FFFDF7;color:#2B2620;outline:none;
        }
        .vc-input:focus{border-color:#D94F1E;box-shadow:0 0 0 3px rgba(217,79,30,0.18);}
        .vc-btn{
          font-family:'Zen Kaku Gothic New',sans-serif;font-size:13.5px;font-weight:900;
          letter-spacing:0.06em;padding:11px 26px;border-radius:10px;cursor:pointer;
          border:2px solid #2B2620;transition:transform .12s ease;
        }
        .vc-btn:focus-visible{outline:3px solid #D94F1E;outline-offset:2px;}
        .vc-btn.primary{background:#D94F1E;color:#FFF6EE;box-shadow:0 3px 0 #A83A12;}
        .vc-btn.primary:hover{transform:translateY(-1px);}
        .vc-btn.primary:disabled{opacity:.45;cursor:not-allowed;transform:none;}
        .vc-btn.ghost{background:#FFFDF7;color:#2B2620;box-shadow:0 3px 0 rgba(43,38,32,0.25);}
        .vc-hint{font-size:11px;color:#8A7E68;margin-left:4px;}

        @media (prefers-reduced-motion: reduce){
          .vc-camera,.vc-sign,.vc-scroll,.vc-plant,.vc-board,
          .vc-char.working .body,.vc-char.working .arm,
          .vc-live .dot,.vc-bubble.think .pulse,.vc-steam,
          .vc-clock.run .h,.vc-clock.run .m,.vc-desk.busy .laptop::after,
          .vc-spot.walking .vc-char,.vc-char .head::before,.vc-char .head::after{animation:none;}
          .vc-spot{transition:none;}
        }
        @media (max-width: 900px){
          .vc-staff{width:170px}
          .vc-staff .rl{display:none}
          .vc-monitor{width:170px}
          .vc-log{width:52%}
        }
      `}</style>

      {/* ===== ヘッダー ===== */}
      <header className="vc-header">
        <div className="vc-logo">🛠</div>
        <div>
          <h1>Chelsea-Labs バーチャル市民開発ラボ</h1>
          <div className="sub vc-mono">CITIZEN DEV × P1–P5 AGENTS — LIVE SIMULATION</div>
        </div>
        <div className="vc-live">
          <span className="dot" />
          {running ? "稼働中" : done ? "本日のラボ終了" : "待機中"}
        </div>
      </header>

      {/* ===== オフィス ===== */}
      <div className="vc-stage">
        <div className="vc-camera">
          <div className="vc-floor" />
          <div className="vc-sign">市民開発ラボ — CHELSEA-LABS</div>
          <div className="vc-scroll" style={{ left: "8%", top: "32%" }}>現場が主役 AIは伴走</div>
          <div className="vc-scroll" style={{ right: "8%", top: "34%" }}>目指すは自走</div>
          <div className="vc-plant" style={{ left: "13%", bottom: "10%" }}>🪴</div>
          <div className="vc-plant" style={{ right: "12%", bottom: "12%", animationDelay: "1.4s" }}>🌿</div>
          <div className={`vc-clock${running ? " run" : ""}`}>
            <div className="hand h" style={{ transform: running ? undefined : "rotate(300deg)" }} />
            <div className="hand m" style={{ transform: running ? undefined : "rotate(90deg)" }} />
          </div>

          {/* 業務ボード */}
          <div className="vc-board">
            <h2>CITIZEN DEV — 案件ボード</h2>
            {board.length === 0 ? (
              <div className="empty">案件はまだありません。下の欄から現場の困りごとを投稿してください。</div>
            ) : (
              board.map((b, i) => (
                <div className="row" key={i}>
                  <span className="lbl">▸ {b.label}</span>
                  <span className="own">{b.owner}</span>
                  <span className="st" style={{ color: stateColor(b.state), borderColor: stateColor(b.state) }}>
                    {b.state}
                  </span>
                </div>
              ))
            )}
          </div>

          {/* メンバーとエージェント */}
          {AGENTS.map((a, idx) => {
            const st = agentState[a.id];
            const seated = atDesk || done;
            const px = leaving ? DOOR.x : seated ? a.desk.x : DOOR.x;
            const py = leaving ? DOOR.y : seated ? a.desk.y : DOOR.y;
            const walking = phase === "commute" || leaving;
            const isThink = st.bubble === "考え中…";
            const happy = (st.bubble || "").includes("自分で直せた") || (st.bubble || "").includes("おつかれ") || (st.bubble || "").includes("達成感");
            return (
              <div
                className={`vc-spot${walking ? " walking" : ""}${focus === a.id ? " focused" : ""}`}
                key={a.id}
                style={{
                  left: `${px}%`,
                  top: `${py}%`,
                  transform: `translate(-50%,-50%) scale(${a.desk.z})`,
                  zIndex: Math.round(a.desk.z * 12),
                  transitionDelay: walking ? `${idx * 0.26}s` : "0s",
                  opacity: phase === "off" && !done ? 0.28 : 1,
                }}
              >
                <div className="vc-halo" />
                <div className={`vc-desk${st.working ? " busy" : ""}`}>
                  {(seated || leaving) && st.bubble !== null && (
                    <div className={`vc-bubble${isThink ? " think" : ""}`} key={st.bubble}>
                      {isThink ? <span className="pulse">🤔 考え中…</span> : st.bubble}
                    </div>
                  )}
                  {seated && st.bubble === null && phase === "work" && (
                    <div className="vc-bubble" key={`q${quipTick}`}>{bubbleFor(a)}</div>
                  )}
                  <div className={`vc-char${st.working ? " working" : ""}${happy ? " happy" : ""}${a.kind === "人間" ? " human" : ""}`}>
                    <div className="head">
                      {a.kind === "人間" && <span className="helmet" />}
                    </div>
                    <div className="body" style={{ background: a.color }}>
                      {st.working && (<><span className="arm l" /><span className="arm r" /></>)}
                    </div>
                  </div>
                  <div className="top" />
                  <div className="leg" style={{ left: 10 }} />
                  <div className="leg" style={{ right: 10 }} />
                  <div className="laptop" />
                  <div className="mug" style={{ background: a.color }} />
                  {seated && !leaving && (<><span className="vc-steam" /><span className="vc-steam s2" /></>)}
                  <div className="vc-nametag">
                    <b>{a.name}</b>
                    <span className={`vc-kind ${a.kind === "人間" ? "human" : "ai"}`}>{a.kind}</span>
                    <br />{a.role}
                  </div>
                </div>
              </div>
            );
          })}

          {/* 飛ぶ書類 */}
          {flights.map((f) => (
            <div
              className="vc-flight"
              key={f.id}
              style={{
                left: `${f.from.x}%`,
                top: `${f.from.y}%`,
                "--dx": `${(f.to.x - f.from.x) * 9.6}px`,
                "--dy": `${(f.to.y - f.from.y) * 5.4}px`,
              }}
            >
              {f.icon}
            </div>
          ))}
        </div>

        {/* メンバー・エージェント一覧 */}
        <aside className="vc-staff" aria-label="ラボメンバー">
          {AGENTS.map((a) => (
            <div className={`card${agentState[a.id].working ? " hot" : ""}${a.kind === "人間" ? " human-card" : ""}`} key={a.id}>
              <span className="swatch" style={{ background: a.color }} />
              <div>
                <div className="nm">{a.name}</div>
                <div className="rl">{a.role}</div>
              </div>
              <div className="st" style={{ color: stateColor(agentState[a.id].status) }}>
                {agentState[a.id].status}
              </div>
            </div>
          ))}
        </aside>

        {/* 成果物モニター */}
        <aside className={`vc-monitor${flights.some((f) => f.to.x === 90) ? " receiving" : ""}`} aria-label="成果物モニター">
          <h3>🗄 成果物モニター</h3>
          {deliverables.length === 0 ? (
            <div className="empty">納品物はまだありません</div>
          ) : (
            <div>
              {deliverables.map((d) => (<span className="vc-chip" key={d}>{d}</span>))}
              {done && <div className="vc-done">✅ 3点セット+プロトタイプ 納品/自走達成</div>}
            </div>
          )}
        </aside>

        {/* 活動ログ */}
        <div className="vc-log" aria-live="polite">
          {logs.map((l) => (
            <div className="line" key={l.id}>
              <span>{l.icon}</span>
              <span className="who">{l.who}</span>
              <span>{l.text}</span>
            </div>
          ))}
        </div>

        {/* 紙吹雪 */}
        {confetti.map((c) => (
          <span
            className="vc-confetti"
            key={c.id}
            style={{
              left: `${c.x}%`,
              background: c.color,
              "--dur": `${c.dur}s`,
              "--delay": `${c.delay}s`,
              "--rot": `${c.rot}deg`,
              "--drift": `${c.drift}px`,
            }}
          />
        ))}
      </div>

      {/* ===== 操作パネル ===== */}
      <div className="vc-controls">
        <input
          className="vc-input"
          value={request}
          onChange={(e) => setRequest(e.target.value)}
          placeholder="現場の困りごとを入力(例: 点検記録の転記をなくしたい)"
          disabled={running}
        />
        <button className="vc-btn primary" onClick={start} disabled={running}>
          {done ? "次の案件を開始" : "ラボ稼働開始"}
        </button>
        <button className="vc-btn ghost" onClick={reset}>リセット</button>
        <span className="vc-hint">課題 → 3点セット → 壁打ち → プロトタイプ → 自走 の一日を再生します</span>
      </div>
    </div>
  );
}
