// witness-app.jsx — App shell + design canvas + tweaks
const { useState: useAppState, useEffect: useAppEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "metal": "gold",
  "lang": "zh",
  "hairlineDensity": 1,
  "monoFont": "JetBrains Mono",
  "displayFont": "Inter Tight"
}/*EDITMODE-END*/;

// ─────────────────────────────────────────────────────────────
// Dynamic today date string — always reflects the real current date
const _d = new Date();
const TODAY_DATE_STR = `${_d.getMonth() + 1}月${_d.getDate()}日`;

// ─────────────────────────────────────────────────────────────
// Initial app state
// Categories the user creates in Goals mode. Each maps to a tag tasks carry.
// 'unsorted' is the default bucket.
const INIT_GOAL_SUBCATS = {
  holland: [
    { id: 'ielts', label: { en: 'IELTS', zh: '雅思' } },
  ],
  job: [
    { id: 'elec_backend', label: { en: 'Elec Backend', zh: '電控後台' } },
  ],
};

const INIT_CATEGORIES = [
  { id: 'holland',  label: { en: 'Netherlands',      zh: '荷蘭' } },
  { id: 'job',      label: { en: 'Day Job',          zh: '正職' } },
  { id: 'life',     label: { en: 'Life',             zh: '生活' } },
  { id: 'unsorted', label: { en: 'Unsorted',         zh: '無分類' } },
];

const INIT_TASKS = [
  // ───── Overdue ─────
  { id: 't11', type: 'A', title: 'Cue Card * 5', date: '5月11日', overdue: true, category: 'holland', subCategory: 'ielts', day: 'overdue', estMin: 30 },
  // B: container with simple subtasks
  { id: 't2', type: 'B', title: 'Listening Review', date: TODAY_DATE_STR, category: 'holland', subCategory: 'ielts', day: 'today', estMin: 90,
    subtasks: [
      { id: 's1', title: '陷阱選項分析 * 3',   done: false },
      { id: 's2', title: '拼字錯誤整理 * 10',  done: false },
      { id: 's3', title: 'Section 3 弱點整理', done: false },
    ]},

  { id: 't10', type: 'A', title: '雅思寫作練習', date: '5月16日', category: 'holland', subCategory: 'ielts', day: 'next7', estMin: 90 },

  // ───── Today ─────
  // C: many-items container with progress pie
  { id: 't5', type: 'C', title: '曼陀號', date: '5月20日', overdue: true, category: 'life', day: 'overdue', estMin: 120,
    subtasks: [
      { id: 's7', title: '開發分享',   done: false },
      { id: 's8', title: 'Coffee Chat', done: false },
    ]},

  // job category — type A
  { id: 't6', type: 'A', title: '薪水轉帳', date: '5月9日', overdue: true, category: 'life', done: false, day: 'overdue', estMin: 10 },
  { id: 't7', type: 'A', title: '回信給 PM', date: '5月26日', category: 'job', done: false, day: 'next7', estMin: 20 },
  { id: 't_elec1', type: 'C', title: '預警監控', date: TODAY_DATE_STR, category: 'job', subCategory: 'elec_backend', done: false, day: 'today', estMin: 60,
    subtasks: [
      { id: 't_elec1_s1', title: '建立異常預警 CRUD', done: false },
      { id: 't_elec1_s2', title: '即時警示通知',       done: false },
      { id: 't_elec1_s3', title: '預警篩選查詢',       done: false },
    ]},
  { id: 't_elec2', type: 'A', title: '權限管理 UI 修正', date: TODAY_DATE_STR, category: 'job', subCategory: 'elec_backend', done: false, day: 'today', estMin: 45 },

];

function useAppModel() {
  const [tasks, setTasks] = useAppState(INIT_TASKS);
  const [categories] = useAppState(INIT_CATEGORIES);

  const todayTasks = tasks.filter(x => x.day === 'today');
  const todayHours = todayTasks.filter(x => x.done).reduce((a, b) => a + b.estMin / 60, 0);
  const todayTarget = 8;

  const toggleTask = (id) => {
    if (id.includes('/')) {
      const [taskId, subId] = id.split('/');
      setTasks(p => p.map(x => {
        if (x.id !== taskId) return x;
        return { ...x, subtasks: x.subtasks.map(s => s.id === subId ? { ...s, done: !s.done } : s) };
      }));
    } else {
      setTasks(p => p.map(x => {
        if (x.id !== id) return x;
        const newDone = !x.done;
        // Also sync all subtasks when checking/unchecking main task
        const subtasks = x.subtasks
          ? x.subtasks.map(s => ({ ...s, done: newDone }))
          : x.subtasks;
        return { ...x, done: newDone, subtasks };
      }));
    }
  };

  const addTask = (task) => setTasks(prev => [task, ...prev]);

  return {
    tasks, categories, toggleTask, addTask,
    todayHours, todayTarget,
    date: 'WED · 13 MAY 2026', dayOfYear: 133,
    totalHours: categories.reduce((a, b) => a + b.hours, 0),
    lifetimeDays: 412, witnessIndex: 0.84,
    setTasks,
  };
}

// ─────────────────────────────────────────────────────────────
// One iOS-framed screen wrapper
function PhoneScreen({ children }) {
  return (
    <IOSDevice width={390} height={844} dark={true} title={undefined} statusBar={false}>
      {children}
    </IOSDevice>
  );
}

// ─────────────────────────────────────────────────────────────
// Interactive prototype — single phone, screen state machine
function Prototype({ t }) {
  const model = useAppModel();
  const [screen, setScreen] = useAppState('onboarding'); // onboarding | home | timer | applock
  const [mode, setMode] = useAppState('list');     // list | goals
  const [listCat, setListCat] = useAppState('today');
  const [goalAxis, setGoalAxis] = useAppState('holland');
  const [goalSubCats, setGoalSubCats] = useAppState(INIT_GOAL_SUBCATS);
  const [activeTaskId, setActiveTaskId] = useAppState('t2');
  // null when activeTaskId is unset (e.g. entering timer from tomato tab)
  const activeTask = activeTaskId ? (model.tasks.find(x => x.id === activeTaskId) || null) : null;
  const activeCategory = activeTask ? (model.categories.find(c => c.id === activeTask.category) || model.categories[0]) : null;

  const handleCheck = (id) => model.toggleTask(id);
  const handleStart = (id) => { setActiveTaskId(id); setScreen('timer'); };

  // Intercept "pomodoro" tab → navigate to existing ScreenTimer, with no pre-selected task
  const handleSetMode = (m) => {
    if (m === 'pomodoro') {
      setActiveTaskId(null); // clear so ScreenTimer defaults to "專注" (no task)
      setScreen('timer');
    } else {
      setMode(m);
    }
  };

  const baseState = {
    ...model,
    mode, setMode: handleSetMode, listCat, setListCat, goalAxis, setGoalAxis,
    goalSubCats, setGoalSubCats,
    activeTask, activeCategory, strict: true,
  };

  const screens = {
    onboarding: (
      <ScreenOnboarding onComplete={() => setScreen('home')} />
    ),
    home: (
      <ScreenHome state={baseState} onCheck={handleCheck} onStartTask={handleStart}
        onOpenSettings={() => setScreen('applock')} />
    ),
    timer: (
      <ScreenTimer state={baseState} onAbort={() => setScreen('home')}
        onComplete={() => { handleCheck(activeTaskId); setScreen('home'); }} />
    ),
    applock: (
      <ScreenAppLockNew onBack={() => setScreen('home')} />
    ),
  };

  const order = ['onboarding', 'home', 'timer', 'applock'];
  const idx = order.indexOf(screen);

  return (
    <PhoneScreen>
      <div style={{ width: '100%', height: '100%', position: 'relative', overflow: 'hidden' }}>
        {order.map((s, i) => (
          <div key={s} style={{
            position: 'absolute', inset: 0,
            transform: `translateX(${(i - idx) * 100}%)`,
            transition: 'transform .38s cubic-bezier(.4,0,.2,1)',
            willChange: 'transform',
          }}>
            {screens[s]}
          </div>
        ))}
      </div>
    </PhoneScreen>
  );
}

// ─────────────────────────────────────────────────────────────
// Static, fully-populated state for each "preview" artboard
function useStaticModel() {
  const [tasks, setTasks] = useAppState(INIT_TASKS);
  const addTask = (task) => setTasks(prev => [task, ...prev]);
  return {
    tasks,
    categories: INIT_CATEGORIES,
    addTask,
    todayHours: 4.8, todayTarget: 8,
    date: 'WED · 13 MAY 2026', dayOfYear: 133,
    totalHours: INIT_CATEGORIES.reduce((a, b) => a + b.hours, 0),
    lifetimeDays: 412, witnessIndex: 0.84,
  };
}

// ─────────────────────────────────────────────────────────────
// Desktop screenshot carousel
function DesktopCarousel() {
  const images = [
    'uploads/desktop1.png',
    'uploads/desktop2.png',
    'uploads/desktop4.png',
    'uploads/desktop3.png',
  ];
  const [idx, setIdx] = useAppState(0);
  useAppEffect(() => {
    const id = setInterval(() => setIdx(i => (i + 1) % images.length), 2500);
    return () => clearInterval(id);
  }, []);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12, alignItems: 'flex-start', width: '100%', height: '100%' }}>
      <div style={{
        position: 'relative', overflow: 'hidden', borderRadius: 6,
        border: `1px solid rgba(255,255,255,0.08)`,
        boxShadow: '0 4px 32px rgba(0,0,0,0.6)',
        flex: 1, width: '100%',
        background: '#050507',
      }}>
        {images.map((src, i) => (
          <img key={src} src={src} alt={`desktop ${i + 1}`} style={{
            position: 'absolute', inset: 0,
            width: '100%', height: '100%', objectFit: 'cover',
            opacity: i === idx ? 1 : 0,
            transition: 'opacity 0.5s ease',
          }} />
        ))}
        {/* dots */}
        <div style={{
          position: 'absolute', bottom: 10, left: '50%',
          transform: 'translateX(-50%)',
          display: 'flex', gap: 6,
        }}>
          {images.map((_, i) => (
            <div key={i} onClick={() => setIdx(i)} style={{
              width: i === idx ? 18 : 6, height: 6, borderRadius: 3,
              background: i === idx ? '#c9a84c' : 'rgba(255,255,255,0.25)',
              transition: 'all 0.3s ease', cursor: 'pointer',
            }} />
          ))}
        </div>
      </div>
      <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, letterSpacing: '0.18em', color: 'rgba(255,255,255,0.25)' }}>
        DESKTOP {idx + 1} / {images.length}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Monthly stats screen — identity drift + time distribution + time black hole
function ScreenAIStats({ onComplete }) {
  const [phase, setPhase] = useAppState(0);
  useAppEffect(() => {
    const ts = [[1,120],[2,360],[3,580],[4,800]];
    const timers = ts.map(([p, d]) => setTimeout(() => setPhase(p), d));
    return () => timers.forEach(clearTimeout);
  }, []);

  const a = (delay) => ({
    opacity: 0,
    animation: `ob-up 0.62s cubic-bezier(.16,1,.3,1) ${delay} forwards`,
  });

  // Pie chart helpers
  const polar = (cx, cy, r, deg) => ({
    x: cx + r * Math.cos((deg - 90) * Math.PI / 180),
    y: cy + r * Math.sin((deg - 90) * Math.PI / 180),
  });
  const arc = (cx, cy, R, r, s, e) => {
    const sp = polar(cx, cy, R, s), ep = polar(cx, cy, R, e);
    const si = polar(cx, cy, r, s), ei = polar(cx, cy, r, e);
    const lg = e - s > 180 ? 1 : 0;
    const f = (n) => n.toFixed(2);
    return `M${f(sp.x)} ${f(sp.y)} A${R} ${R} 0 ${lg} 1 ${f(ep.x)} ${f(ep.y)} L${f(ei.x)} ${f(ei.y)} A${r} ${r} 0 ${lg} 0 ${f(si.x)} ${f(si.y)}Z`;
  };

  const timeData = [
    { label: '正職', hours: 40, pct: 60, color: 'rgba(80,130,230,0.85)', sub: '電控後台 75%、未分類 25%' },
    { label: '荷蘭', hours: 18, pct: 27, color: W.accentHi,              sub: 'IELTS 100%' },
    { label: '生活', hours:  9, pct: 13, color: 'rgba(80,170,130,0.78)', sub: '未分類 100%' },
  ];
  let cum = 0;
  const slices = timeData.map(d => {
    const s = cum, e = cum + d.pct * 3.6;
    cum = e;
    return { ...d, s, e };
  });
  const PIE = { cx: 65, cy: 65, R: 58, r: 40 };

  // Identity drift: 0=荷蘭(top), 1=正職(mid), 2=生活(bot)
  const ids = [1,1,1,0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,0,1,2,1,0];
  const idLabels = ['荷蘭','正職','生活'];
  const idColors = [W.accentHi,'rgba(80,130,230,0.85)','rgba(80,170,130,0.78)'];
  const CW = 316, CH = 76;
  const xStep = CW / (ids.length - 1);
  const yMap = [6, CH / 2, CH - 6];
  const pts = ids.map((id, i) => ({ x: +(i * xStep).toFixed(1), y: yMap[id], id }));
  const pathD = pts.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`).join(' ');

  const blackHoles = [
    { task: '長文寫作任務',       tag: '高阻力任務',   count: '延遲 7次' },
    { task: 'Section 3 弱點整理', tag: '高認知負擔',   count: '延遲 4次' },
    { task: '系統設計文件',       tag: '缺乏立即回饋', count: '延遲 3次' },
  ];

  const [hover, setHover] = useAppState(false);

  return (
    <div style={{
      width: '100%', height: '100%',
      background: '#07070a', color: '#ede9e1',
      display: 'flex', flexDirection: 'column',
      fontFamily: W.mono, overflow: 'hidden',
    }}>
      <WStatusBar time="09:00" />

      <div style={{ flex: 1, overflowY: 'auto', padding: '18px 28px 44px' }}>

        {/* Header */}
        {phase >= 1 && (
          <div style={{ marginBottom: 24, ...a('0s') }}>
            <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: 34, fontWeight: 500, color: '#fff', lineHeight: 1.1, marginBottom: 4 }}>
              本月見證
            </div>
            <div style={{ fontSize: 9.5, letterSpacing: '0.22em', color: 'rgba(237,233,225,0.28)', textTransform: 'uppercase' }}>
              MAY 2026
            </div>
          </div>
        )}

        {/* Section 1: Time Distribution — Donut Pie */}
        {phase >= 1 && (
          <div style={{ marginBottom: 22, ...a('0.08s') }}>
            <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: 17, color: 'rgba(237,233,225,0.82)', marginBottom: 2 }}>時間分佈</div>
            <div style={{ fontSize: 9, letterSpacing: '0.1em', color: 'rgba(237,233,225,0.28)', marginBottom: 14 }}>本月累計 67 小時</div>

            <div style={{ display: 'flex', alignItems: 'center', gap: 18 }}>
              {/* Donut */}
              <svg width="130" height="130" viewBox="0 0 130 130" style={{ flexShrink: 0 }}>
                {slices.map((s, i) => (
                  <path key={i} d={arc(PIE.cx, PIE.cy, PIE.R, PIE.r, s.s, s.e)} fill={s.color} />
                ))}
                <text x={PIE.cx} y={PIE.cy - 5} textAnchor="middle"
                  fill="rgba(237,233,225,0.9)" fontSize="20"
                  fontFamily="Cormorant Garamond, serif" fontWeight="500">67</text>
                <text x={PIE.cx} y={PIE.cy + 11} textAnchor="middle"
                  fill="rgba(237,233,225,0.28)" fontSize="8"
                  fontFamily="JetBrains Mono, monospace" letterSpacing="1">小時</text>
              </svg>

              {/* Legend */}
              <div style={{ flex: 1 }}>
                {timeData.map((d, i) => (
                  <div key={i} style={{ marginBottom: 13 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 7, marginBottom: 3 }}>
                      <div style={{ width: 6, height: 6, borderRadius: 1, background: d.color, flexShrink: 0 }} />
                      <span style={{ fontSize: 12, color: 'rgba(237,233,225,0.7)', letterSpacing: '0.05em' }}>{d.label}</span>
                      <span style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: 17, color: d.color, marginLeft: 'auto', lineHeight: 1 }}>
                        {d.hours}<span style={{ fontSize: 10, opacity: 0.6 }}>h</span>
                      </span>
                    </div>
                    <div style={{ fontSize: 9, color: 'rgba(237,233,225,0.2)', letterSpacing: '0.07em', paddingLeft: 13 }}>{d.sub}</div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        )}

        {/* Divider */}
        {phase >= 1 && <div style={{ height: '0.3px', background: 'rgba(255,255,255,0.06)', marginBottom: 22 }} />}

        {/* Section 2: Identity Drift */}
        {phase >= 2 && (
          <div style={{ marginBottom: 22, ...a('0.12s') }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 10 }}>
              <div>
                <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: 17, color: 'rgba(237,233,225,0.82)', marginBottom: 2 }}>身份漂移</div>
                <div style={{ fontSize: 9, letterSpacing: '0.1em', color: 'rgba(237,233,225,0.28)' }}>你這個月在三個角色間的軌跡</div>
              </div>
              <div style={{ display: 'flex', gap: 8 }}>
                {idLabels.map((l, i) => (
                  <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 3 }}>
                    <div style={{ width: 5, height: 5, borderRadius: 9999, background: idColors[i] }} />
                    <span style={{ fontSize: 8.5, color: 'rgba(237,233,225,0.35)', letterSpacing: '0.06em' }}>{l}</span>
                  </div>
                ))}
              </div>
            </div>

            <div style={{ background: 'rgba(255,255,255,0.025)', borderRadius: 8, padding: '10px 8px 6px', border: '0.5px solid rgba(255,255,255,0.06)' }}>
              <svg width="100%" viewBox={`-2 0 ${CW + 4} ${CH + 18}`} style={{ overflow: 'visible', display: 'block' }}>
                {yMap.map((y, i) => (
                  <line key={i} x1={-2} y1={y} x2={CW + 2} y2={y} stroke="rgba(255,255,255,0.05)" strokeWidth="0.5" strokeDasharray="3,5" />
                ))}
                <path d={pathD} fill="none" stroke={W.accentHi} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.65" />
                {pts.map((p, i) => (
                  <circle key={i} cx={p.x} cy={p.y} r={i === pts.length - 1 ? 3.5 : 1.8}
                    fill={idColors[p.id]} opacity={i === pts.length - 1 ? 1 : 0.65} />
                ))}
                {[1, 8, 15, 23].map(day => (
                  <text key={day} x={(day - 1) * xStep} y={CH + 15}
                    textAnchor="middle" fill="rgba(237,233,225,0.28)" fontSize="8"
                    fontFamily="JetBrains Mono, monospace">{day}日</text>
                ))}
              </svg>
            </div>
          </div>
        )}

        {/* Divider */}
        {phase >= 2 && <div style={{ height: '0.3px', background: 'rgba(255,255,255,0.06)', marginBottom: 22 }} />}

        {/* Section 3: Time Black Hole */}
        {phase >= 3 && (
          <div style={{ marginBottom: 28, ...a('0.16s') }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
              <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: 17, color: 'rgba(237,233,225,0.82)' }}>時間黑洞</div>
              <div style={{ width: 5, height: 5, borderRadius: 9999, background: 'rgba(255,80,80,0.8)', boxShadow: '0 0 5px rgba(255,80,80,0.5)' }} />
            </div>

            <div style={{ background: 'rgba(255,255,255,0.025)', borderRadius: 10, border: '0.5px solid rgba(255,255,255,0.06)', overflow: 'hidden' }}>
              {blackHoles.map((bh, i) => (
                <div key={i} style={{
                  padding: '12px 16px',
                  borderBottom: i < blackHoles.length - 1 ? '0.5px solid rgba(255,255,255,0.05)' : 'none',
                  display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10,
                }}>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 13, color: 'rgba(237,233,225,0.78)', marginBottom: 5, fontFamily: W.display }}>{bh.task}</div>
                    <div style={{
                      display: 'inline-flex', padding: '2px 8px',
                      background: 'rgba(255,70,70,0.07)', border: '0.5px solid rgba(255,90,70,0.22)',
                      borderRadius: 3, fontSize: 9, color: 'rgba(255,120,100,0.75)', letterSpacing: '0.08em',
                    }}>{bh.tag}</div>
                  </div>
                  <div style={{ fontSize: 9.5, color: 'rgba(237,233,225,0.22)', letterSpacing: '0.1em', flexShrink: 0 }}>{bh.count}</div>
                </div>
              ))}
            </div>
          </div>
        )}

        {/* CTA */}
        {phase >= 4 && (
          <button
            onClick={onComplete}
            onMouseEnter={() => setHover(true)}
            onMouseLeave={() => setHover(false)}
            style={{
              width: '100%', padding: '15px 22px',
              border: `0.5px solid rgba(237,233,225,0.22)`,
              borderRadius: 3, background: 'transparent', cursor: 'pointer',
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              position: 'relative', overflow: 'hidden', ...a('0.2s'),
            }}
          >
            <div style={{ position: 'absolute', inset: 0, background: 'rgba(255,255,255,0.14)', transformOrigin: 'left center', transform: hover ? 'scaleX(1)' : 'scaleX(0)', transition: 'transform 0.38s cubic-bezier(.16,1,.3,1)', pointerEvents: 'none' }} />
            <div style={{ position: 'absolute', top: 0, bottom: 0, left: 0, width: hover ? '100%' : '0%', background: 'linear-gradient(90deg, transparent 80%, rgba(255,255,255,0.18))', transition: 'width 0.38s cubic-bezier(.16,1,.3,1)', pointerEvents: 'none' }} />
            <span style={{ fontFamily: W.mono, fontSize: 10.5, fontWeight: 500, letterSpacing: '0.26em', textTransform: 'uppercase', color: '#ede9e1', position: 'relative', zIndex: 1 }}>重新開始見證</span>
            <svg width="18" height="10" viewBox="0 0 18 10" fill="none" style={{ color: W.accentHi, filter: hover ? 'brightness(1.4)' : 'none', transition: 'filter .25s', position: 'relative', zIndex: 1 }}>
              <line x1="0" y1="5" x2="15" y2="5" stroke="currentColor" strokeWidth="1" strokeLinecap="round"/>
              <path d="M11 1.5l4 3.5-4 3.5" stroke="currentColor" strokeWidth="1" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </button>
        )}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// AI Insights demo tasks — specific done states (Section 3 弱點整理 is the one undone)
const AI_INSIGHTS_TASKS = [
  { id: 'ai_t1', type: 'B', title: 'Listening Review', date: '5月23日', category: 'holland', subCategory: 'ielts', day: 'today', estMin: 90, done: false,
    subtasks: [
      { id: 'ai_s1', title: '陷阱選項分析 * 3',   done: true },
      { id: 'ai_s2', title: '拼字錯誤整理 * 10',  done: true },
      { id: 'ai_s3', title: 'Section 3 弱點整理', done: false },
    ]},
  { id: 'ai_t2', type: 'C', title: '預警監控', date: '5月23日', category: 'job', subCategory: 'elec_backend', day: 'today', estMin: 60, done: true,
    subtasks: [
      { id: 'ai_s4', title: '建立異常預警 CRUD', done: true },
      { id: 'ai_s5', title: '即時警示通知',      done: true },
      { id: 'ai_s6', title: '預警篩選查詢',      done: true },
    ]},
  { id: 'ai_t3', type: 'A', title: '權限管理 UI 修正', date: '5月23日', category: 'job', subCategory: 'elec_backend', day: 'today', estMin: 45, done: true },
];

// ─────────────────────────────────────────────────────────────
// AI Insights prototype — onboarding → today home → AI summary
function AIInsightsPrototype() {
  const [screen, setScreen] = useAppState('onboarding');
  const [tasks, setTasks] = useAppState(AI_INSIGHTS_TASKS);
  const [mode, setMode] = useAppState('list');
  const [listCat, setListCat] = useAppState('today');
  const [goalAxis, setGoalAxis] = useAppState('holland');
  const [goalSubCats] = useAppState(INIT_GOAL_SUBCATS);

  const toggleTask = (id) => {
    if (id.includes('/')) {
      const [taskId, subId] = id.split('/');
      setTasks(p => p.map(t => {
        if (t.id !== taskId) return t;
        return { ...t, subtasks: t.subtasks.map(s => s.id === subId ? { ...s, done: !s.done } : s) };
      }));
    } else {
      setTasks(p => p.map(t => {
        if (t.id !== id) return t;
        const nd = !t.done;
        return { ...t, done: nd, subtasks: t.subtasks ? t.subtasks.map(s => ({ ...s, done: nd })) : t.subtasks };
      }));
    }
  };

  const baseState = {
    tasks, categories: INIT_CATEGORIES,
    addTask: () => {}, toggleTask,
    todayHours: 5.5, todayTarget: 8,
    date: 'FRI · 23 MAY 2026', dayOfYear: 143,
    totalHours: 0, lifetimeDays: 45, witnessIndex: 0.72,
    mode, setMode, listCat, setListCat,
    goalAxis, setGoalAxis,
    goalSubCats, setGoalSubCats: () => {},
    activeTask: null, activeCategory: null, strict: false,
  };

  const order = ['onboarding', 'home', 'summary', 'stats'];
  const idx = order.indexOf(screen);

  const screens = {
    onboarding: <ScreenOnboarding onComplete={() => setScreen('home')} />,
    home: (
      <div style={{ position: 'relative', width: '100%', height: '100%' }}>
        <ScreenHome state={baseState} onCheck={toggleTask} onStartTask={() => {}} onOpenSettings={() => {}} />
        {/* Full-screen dark scrim — dims "+" and everything behind */}
        <div style={{
          position: 'absolute', inset: 0, zIndex: 60,
          background: 'rgba(5,5,7,0.87)',
          display: 'flex', flexDirection: 'column',
          justifyContent: 'flex-end',
          padding: '0 28px 52px',
        }}>
          <button
            onClick={() => setScreen('summary')}
            style={{
              width: '100%', padding: '17px 24px',
              borderRadius: 99,
              background: W.accentHi,
              border: 'none', cursor: 'pointer',
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              boxShadow: `0 2px 8px rgba(0,0,0,0.5)`,
            }}
          >
            <span style={{
              fontFamily: W.mono, fontSize: 11.5, fontWeight: 500,
              letterSpacing: '0.22em', textTransform: 'uppercase',
              color: W.onAccent,
            }}>
              回頭看昨天的自己
            </span>
            <svg width="18" height="10" viewBox="0 0 18 10" fill="none" style={{ color: W.onAccent }}>
              <line x1="0" y1="5" x2="15" y2="5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
              <path d="M11 1.5l4 3.5-4 3.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </button>
        </div>
      </div>
    ),
    summary: <ScreenAISummary onComplete={() => setScreen('stats')} />,
    stats: <ScreenAIStats onComplete={() => setScreen('onboarding')} />,
  };

  return (
    <PhoneScreen>
      <div style={{ width: '100%', height: '100%', position: 'relative', overflow: 'hidden' }}>
        {order.map((s, i) => (
          <div key={s} style={{
            position: 'absolute', inset: 0,
            transform: `translateX(${(i - idx) * 100}%)`,
            transition: 'transform .38s cubic-bezier(.4,0,.2,1)',
            willChange: 'transform',
          }}>
            {screens[s]}
          </div>
        ))}
      </div>
    </PhoneScreen>
  );
}

// ─────────────────────────────────────────────────────────────
// App root — design canvas with all screens + interactive prototype + tweaks

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // Theme + language tweaks mutate global tokens; repaint triggers full rerender.
  const [paint, setPaint] = useAppState(0);
  useAppEffect(() => {
    setMetal(t.metal || 'silver');
    setLang(t.lang || 'en');
    setPaint(p => p + 1);
  }, [t.metal, t.lang]);

  return (
    <div key={paint} style={{ minHeight: '100vh', background: W.void }}>
      <DesignCanvas bg={W.void}>
        <DCSection id="overview" title="THE WITNESS · Identity Ledger" subtitle="Industrial witness · charcoal + brushed dark gold · monospaced precision">
          <DCArtboard id="proto" label="● INTERACTIVE PROTOTYPE" width={390} height={844}>
            <Prototype t={t} />
          </DCArtboard>
          <DCArtboard id="desktop-preview" label="● LACK APP" width={390} height={844}>
            <DesktopCarousel />
          </DCArtboard>
          <DCArtboard id="ai-insights" label="● AI INSIGHTS" width={390} height={844}>
            <AIInsightsPrototype />
          </DCArtboard>
        </DCSection>

        {/* Screen set and Visual System sections hidden */}
      </DesignCanvas>

      <TweaksPanel>
        <TweakSection label="Language" />
        <TweakRadio label="Language" value={t.lang}
          options={['en', 'zh']}
          onChange={(v) => setTweak('lang', v)} />
        <TweakSection label="Material" />
        <TweakRadio label="Accent metal" value={t.metal}
          options={['gold', 'silver']}
          onChange={(v) => setTweak('metal', v)} />
        <TweakSlider label="Hairline density" value={t.hairlineDensity}
          min={0.3} max={1.8} step={0.1}
          onChange={(v) => setTweak('hairlineDensity', v)} />
        <TweakSection label="Type" />
        <TweakSelect label="Mono font" value={t.monoFont}
          options={['JetBrains Mono', 'IBM Plex Mono', 'Space Mono', 'ui-monospace']}
          onChange={(v) => setTweak('monoFont', v)} />
        <TweakSelect label="Display font" value={t.displayFont}
          options={['Inter Tight', 'Cormorant Garamond', 'JetBrains Mono']}
          onChange={(v) => setTweak('displayFont', v)} />
      </TweaksPanel>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Static-state thin wrappers (so screens render fully populated in the canvas)
function ScreenHomeStatic({ mode = 'list', listCat = 'today', goalAxis = 'holland' }) {
  const m = useStaticModel();
  const [smode, setMode] = useAppState(mode);
  const [slc, setListCat] = useAppState(listCat);
  const [sga, setGoalAxis] = useAppState(goalAxis);
  const [sgsc, setGoalSubCats] = useAppState(INIT_GOAL_SUBCATS);
  return <ScreenHome state={{
    ...m,
    mode: smode, setMode,
    listCat: slc, setListCat,
    goalAxis: sga, setGoalAxis,
    goalSubCats: sgsc, setGoalSubCats,
  }}
    onCheck={() => {}} onStartTask={() => {}} onOpenSettings={() => {}} />;
}
function ScreenIdentityStatic() {
  return <ScreenHomeStatic mode="goals" />;
}

function ScreenHomeStaticSheetOpen() {
  const m = useStaticModel();
  const [smode] = useAppState('list');
  const [slc, setListCat] = useAppState('today');
  const [sga, setGoalAxis] = useAppState('all');
  return <ScreenHome state={{
    ...m, mode: smode, setMode: () => {},
    listCat: slc, setListCat,
    goalAxis: sga, setGoalAxis,
  }} defaultSheetOpen={true}
    onCheck={() => {}} onStartTask={() => {}} onOpenSettings={() => {}} />;
}
function ScreenTimerStatic() {
  const m = useStaticModel();
  const at = m.tasks.find(x => x.id === 't2');
  const ac = m.categories.find(c => c.id === at.category) || m.categories[0];
  return <ScreenTimer state={{ ...m, activeTask: at, activeCategory: ac, strict: true, elapsedSec: 22 * 60 + 14 }}
    onAbort={() => {}} onComplete={() => {}} />;
}
function ScreenAppLockStatic() {
  const m = useStaticModel();
  return <ScreenAppLock state={{ ...m, onNav: () => {} }} onDone={() => {}} />;
}
function ScreenSettlementStatic() {
  const m = useStaticModel();
  return <ScreenSettlement state={{
    ...m,
    todayDist: [
      { id: 'gmat',     name: 'GMAT EXPERT',       hours: 3.2, color: W.accentHi },
      { id: 'eng',      name: 'SOFTWARE ENGINEER', hours: 2.4, color: W.accent },
      { id: 'athlete',  name: 'ATHLETE',           hours: 1.0, color: W.accentLo },
      { id: 'reader',   name: 'READER',            hours: 0.6, color: W.accentDk },
    ],
    todayInvestedPct: 72, todayWasted: 1.4,
  }} onClose={() => {}} />;
}

// ─────────────────────────────────────────────────────────────
// System board — materials and identity-axis state ladder
function SystemBoard() {
  const stages = [0.04, 0.15, 0.35, 0.6, 0.85, 1.0];
  return (
    <div style={{
      width: '100%', height: '100%', boxSizing: 'border-box',
      background: W.ink, color: W.textHi, padding: 24,
      fontFamily: W.mono, position: 'relative', overflow: 'hidden',
    }}>
      <div style={{
        position: 'absolute', inset: 0,
        background: hairlineMetal({ base: 'transparent', intensity: 0.3, density: 0.5 }),
        opacity: 0.6, mixBlendMode: 'screen', pointerEvents: 'none',
      }} />
      <div style={{ position: 'relative', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 22 }}>
        {/* Materials */}
        <div>
          <SerialNum>MATERIALS · METALLURGY</SerialNum>
          <div style={{ marginTop: 12, display: 'flex', flexDirection: 'column', gap: 10 }}>
            <Swatch label="VOID" sub="#050507 · page bg"      bg={W.void} />
            <Swatch label="MATTE CHARCOAL" sub="#0a0a0b · ink" bg={W.ink} />
            <Swatch label="GUNMETAL · IRON" sub="#16171a hairline" bg={hairlineMetal({ base: W.iron, intensity: 0.7 })} dark />
            <Swatch label="GUNMETAL · STEEL" sub="#1f2025 hairline + sheen" bg={hairlineMetal({ base: W.steel, intensity: 0.9 })} dark />
            <Swatch label="BRUSHED DARK GOLD" sub="not amber · etched"     bg={brushedGold({ intensity: 1 })} darkText />
            <Swatch label="ENGRAVED WELL" sub="sunken value wells" bg="linear-gradient(180deg,#050608,#0d0e10)" inset />
          </div>
        </div>
        {/* Type */}
        <div>
          <SerialNum>TYPE · PRECISION + GRAVITY</SerialNum>
          <div style={{ marginTop: 14 }}>
            <SerialNum style={{ color: W.textXLo }}>MONO · DATA</SerialNum>
            <div style={{ fontFamily: W.mono, fontSize: 36, color: W.textHi, lineHeight: 1, marginTop: 6, ...etched() }}>
              0123 / 456.7
            </div>
            <div style={{ fontFamily: W.mono, fontSize: 12, color: W.text, marginTop: 4, letterSpacing: '0.18em' }}>
              JETBRAINS MONO · TABULAR
            </div>
            <WDivider style={{ margin: '14px 0' }} />
            <SerialNum style={{ color: W.textXLo }}>SERIF · CONFESSION</SerialNum>
            <div style={{ fontFamily: W.serif, fontStyle: 'italic', fontSize: 26, color: W.goldHi, lineHeight: 1.1, marginTop: 4 }}>
              becoming who he wants to be.
            </div>
            <WDivider style={{ margin: '14px 0' }} />
            <SerialNum style={{ color: W.textXLo }}>DISPLAY · STATEMENT</SerialNum>
            <div style={{ fontFamily: W.display, fontSize: 18, color: W.textHi, lineHeight: 1.2, marginTop: 4 }}>
              Today, you are someone who invested 72% of your time.
            </div>
          </div>
        </div>
      </div>

      {/* Identity Axis states */}
      <div style={{ position: 'relative', marginTop: 20 }}>
        <SerialNum>IDENTITY AXIS · ENGRAVING DEPTH BY HOURS INVESTED</SerialNum>
        <div style={{ marginTop: 14, display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 14 }}>
          {stages.map((p, i) => (
            <div key={i}>
              <IdentityAxis progress={p} hours={p * 1000} cap={1000} label={`STAGE ${i + 1} · ${Math.round(p * 100)}%`} height={16} />
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
function Swatch({ label, sub, bg, dark, darkText, inset }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'stretch',
      boxShadow: inset
        ? 'inset 0 1px 2px rgba(0,0,0,0.85), 0 0 0 1px rgba(0,0,0,0.6)'
        : 'inset 0 1px 0 rgba(255,255,255,0.05), inset 0 -1px 0 rgba(0,0,0,0.6), 0 0 0 1px rgba(0,0,0,0.5)',
    }}>
      <div style={{ width: 86, height: 56, background: bg, flexShrink: 0 }} />
      <div style={{ padding: '8px 14px', display: 'flex', flexDirection: 'column', justifyContent: 'center', background: W.iron, flex: 1 }}>
        <div style={{ fontFamily: W.mono, fontSize: 10.5, letterSpacing: '0.18em', color: darkText ? W.goldHi : W.textHi, fontWeight: 500 }}>{label}</div>
        <div style={{ fontFamily: W.mono, fontSize: 9, letterSpacing: '0.12em', color: W.textLo, marginTop: 2 }}>{sub.toUpperCase()}</div>
      </div>
    </div>
  );
}

// Mount
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
