/* ========== 共用 UI 原子 ========== */
const { useState, useEffect, useRef, useMemo, useCallback, useLayoutEffect, createContext, useContext } = React;

/* ===== 圖示系統（線稿，IDE 風格） ===== */
const Icon = ({ name, size = 16, color = 'currentColor', strokeWidth = 1.5, ...rest }) => {
  const paths = {
    home: 'M3 11l9-8 9 8v9a2 2 0 0 1-2 2h-4v-7H10v7H6a2 2 0 0 1-2-2v-9z',
    flow: 'M3 5h6M3 12h12M3 19h18M11 5l3-2-3-2M17 12l3-2-3-2M21 19l3-2-3-2',
    sparkle: 'M12 3l1.8 4.6L18 9.4l-4.2 1.8L12 16l-1.8-4.8L6 9.4l4.2-1.8L12 3zM19 14l.9 2.3L22 17l-2.1.7L19 20l-.9-2.3L16 17l2.1-.7L19 14z',
    chart: 'M3 21V8M9 21V3M15 21v-9M21 21v-6M3 21h18',
    formula: 'M4 4h16v3l-5 5 5 5v3H4v-3l5-5-5-5V4z',
    todo: 'M9 11l3 3L22 4M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11',
    skill: 'M13 2L3 14h7l-1 8 10-12h-7l1-8z',
    search: 'M11 19a8 8 0 1 1 0-16 8 8 0 0 1 0 16zM21 21l-4.3-4.3',
    arrow_right: 'M5 12h14M13 5l7 7-7 7',
    arrow_left: 'M19 12H5M11 5l-7 7 7 7',
    chevron_right: 'M9 6l6 6-6 6',
    chevron_down: 'M6 9l6 6 6-6',
    close: 'M18 6L6 18M6 6l18 18',
    plus: 'M12 5v14M5 12h14',
    play: 'M5 3v18l15-9z',
    pause: 'M6 4h4v16H6zM14 4h4v16h-4z',
    eye: 'M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7zM12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z',
    clock: 'M12 8v4l3 2M12 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20z',
    fire: 'M12 23a7 7 0 0 0 7-7c0-3-2-5-3-6 0 2-1 3-3 3a4 4 0 0 1 0-8 5 5 0 0 0-3 5 7 7 0 0 0 2 13z',
    warn: 'M12 2L1 22h22L12 2zM12 9v5M12 17.5h.01',
    check: 'M5 13l4 4L19 7',
    git: 'M5 7v10M19 7v4M19 11a4 4 0 0 1-4 4H9M5 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM5 21a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM19 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4z',
    folder: 'M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z',
    file: 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6zM14 2v6h6',
    radar: 'M12 2a10 10 0 1 0 10 10M22 12L12 12 12 2',
    cpu: 'M9 3v3M15 3v3M9 18v3M15 18v3M3 9h3M3 15h3M18 9h3M18 15h3M5 5h14v14H5z M9 9h6v6H9z',
    layers: 'M12 2L2 8l10 6 10-6-10-6zM2 16l10 6 10-6M2 12l10 6 10-6',
    target: 'M12 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20zM12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zM12 14a2 2 0 1 1 0-4 2 2 0 0 1 0 4z',
    inbox: 'M22 12h-6l-2 3h-4l-2-3H2M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z',
    grid: 'M3 3h7v7H3V3zM14 3h7v7h-7V3zM14 14h7v7h-7v-7zM3 14h7v7H3v-7z',
    list: 'M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01',
    refresh: 'M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15',
    settings: 'M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h0a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v0a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z',
    keyboard: 'M2 4h20v16H2zM6 8h.01M10 8h.01M14 8h.01M18 8h.01M6 12h.01M10 12h.01M14 12h.01M18 12h.01M7 16h10',
    bolt: 'M13 2L3 14h7l-1 8 10-12h-7z',
    trending_up: 'M23 6l-9.5 9.5-5-5L1 18M17 6h6v6',
    trending_down: 'M23 18l-9.5-9.5-5 5L1 6M17 18h6v-6',
    tag: 'M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82zM7 7h.01',
    hash: 'M4 9h16M4 15h16M10 3L8 21M16 3l-2 18',
  };
  const d = paths[name] || paths.search;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" {...rest}>
      <path d={d} />
    </svg>
  );
};

/* ===== Pill 標籤 ===== */
const Pill = ({ children, color = 'var(--ink-2)', bg = 'var(--bg-3)', border, size = 'sm' }) => {
  const sizes = {
    xs: { padding: '1px 6px', fontSize: 9.5, h: 16 },
    sm: { padding: '2px 8px', fontSize: 10.5, h: 18 },
    md: { padding: '3px 10px', fontSize: 11.5, h: 22 },
  };
  const s = sizes[size];
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      padding: s.padding, height: s.h, borderRadius: 4,
      fontFamily: 'var(--mono)', fontSize: s.fontSize, fontWeight: 500, lineHeight: 1,
      color, background: bg,
      border: border ? `1px solid ${border}` : '1px solid transparent',
      whiteSpace: 'nowrap', flexShrink: 0,
    }}>{children}</span>
  );
};

/* ===== 狀態點 ===== */
const Dot = ({ color, pulse, size = 6 }) => (
  <span style={{
    display: 'inline-block', flexShrink: 0,
    width: size, height: size, borderRadius: '50%',
    background: color,
    animation: pulse ? 'pulse-soft 1.6s ease-in-out infinite' : 'none',
    boxShadow: pulse ? `0 0 0 3px ${color}33` : 'none',
  }} />
);

/* ===== 小型按鈕 ===== */
const IconBtn = ({ icon, label, onClick, active, size = 32, tip }) => {
  const [hover, setHover] = useState(false);
  return (
    <button
      onClick={onClick}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      data-tip={tip}
      style={{
        width: size, height: size, borderRadius: 6,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
        background: active ? 'var(--kai-tint)' : hover ? 'var(--bg-3)' : 'transparent',
        color: active ? 'var(--kai-bright)' : hover ? 'var(--ink-0)' : 'var(--ink-2)',
        border: active ? '1px solid var(--kai-glow)' : '1px solid transparent',
        transition: 'all 0.12s var(--ease-out)',
      }}
    >
      <Icon name={icon} size={15} />
      {label && <span style={{ fontSize: 11.5, fontWeight: 500 }}>{label}</span>}
    </button>
  );
};

/* ===== 數字格式 ===== */
const fmtNum = (n) => {
  if (n == null) return '—';
  if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M';
  if (n >= 1000) return (n / 1000).toFixed(n >= 10000 ? 0 : 1) + 'k';
  return String(n);
};
const fmtPct = (n, d = 1) => n == null ? '—' : (Number(n).toFixed(d) + '%');

/* ===== 進度條 ===== */
const Bar = ({ value, max = 100, color = 'var(--kai)', height = 4, bg = 'var(--bg-3)', label }) => (
  <div style={{ width: '100%' }}>
    <div style={{ height, background: bg, borderRadius: height, overflow: 'hidden', position: 'relative' }}>
      <div style={{
        position: 'absolute', inset: 0, right: 'auto',
        width: `${Math.min(100, (value / max) * 100)}%`,
        background: color,
        borderRadius: height,
        transition: 'width 0.6s var(--ease-out)',
      }} />
    </div>
    {label && <div style={{ marginTop: 3, fontSize: 10, color: 'var(--ink-3)', fontFamily: 'var(--mono)' }}>{label}</div>}
  </div>
);

/* ===== 關鍵框架（區塊容器） ===== */
const Card = ({ title, action, children, padding = 16, accent }) => (
  <div className="lift" style={{
    background: 'var(--bg-1)',
    border: '1px solid var(--line)',
    borderRadius: 10,
    overflow: 'hidden',
    position: 'relative',
  }}>
    {accent && <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 2, background: accent }} />}
    {title && (
      <div style={{
        padding: '12px 16px',
        borderBottom: '1px solid var(--line-faint)',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10,
      }}>
        <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink-1)', display: 'flex', alignItems: 'center', gap: 8 }}>
          {title}
        </div>
        {action}
      </div>
    )}
    <div style={{ padding }}>{children}</div>
  </div>
);

/* ===== Performance 顏色 ===== */
const perfColor = (p) => p === 'high' ? 'var(--high)' : p === 'low' ? 'var(--low)' : 'var(--normal)';
const perfLabel = (p) => p === 'high' ? '🏆 高表現' : p === 'low' ? '啞彈' : 'Normal';

/* ===== 階段顏色 ===== */
const stageColor = (s) => ({
  'inbox': 'var(--stage-inbox)',
  'selected': 'var(--stage-selected)',
  '待拍': 'var(--stage-shoot)',
  '剪輯中': 'var(--stage-edit)',
  '已上線': 'var(--stage-live)',
  'archived': 'var(--ink-4)',
}[s] || 'var(--ink-3)');

/* 暴露到 window */
Object.assign(window, { Icon, Pill, Dot, IconBtn, fmtNum, fmtPct, Bar, Card, perfColor, perfLabel, stageColor });
