/* ui.jsx — Persom 2.1 原型：设计令牌 + 通用小组件
   视觉基准：参考稿「Persom 2.1 UI」墨色版（暖灰侧边栏 / Newsreader 衬线 / 墨色按钮 / 墨绿状态点）
   所有导出挂在 window.P21 命名空间下，避免和仓库其他项目的全局组件重名 */
/* global React */
window.P21 = window.P21 || {};
(() => {
  /* ---------- 字体与悬停样式（只注入一次） ---------- */
  if (!document.getElementById('p21-assets')) {
    const link = document.createElement('link');
    link.id = 'p21-assets';
    link.rel = 'stylesheet';
    link.href = 'https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;1,6..72,400&family=JetBrains+Mono:wght@400;500&display=swap';
    document.head.appendChild(link);
    const st = document.createElement('style');
    st.textContent = `
      .p21 { font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", sans-serif; color: #37352F; font-size: 14px; line-height: 1.5; -webkit-font-smoothing: antialiased; }
      .p21 *, .p21 *::before, .p21 *::after { box-sizing: border-box; }
      .p21 input::placeholder, .p21 textarea::placeholder { color: #9AA19D; }
      .p21-h-side:hover { background: #EFEFED !important; }
      .p21-h-soft:hover { background: #F7F7F5 !important; }
      .p21-h-card:hover { background: #FAFAF9 !important; }
      .p21-h-chip:hover { background: #E9E9E6 !important; }
      .p21-h-link:hover { color: #2F5D45 !important; }
      .p21-h-danger:hover { background: #F7EEEB !important; }
      .p21-h-dark:hover { background: #2A2925 !important; }
      .p21-scroll::-webkit-scrollbar { width: 10px; }
      .p21-noscroll { scrollbar-width: none; } .p21-noscroll::-webkit-scrollbar { display: none; }
      .p21-scroll::-webkit-scrollbar-thumb { background: #E3E2E0; border-radius: 10px; border: 3px solid #fff; }
      @keyframes p21blink { 0%,100% { opacity: 1 } 50% { opacity: .25 } }
      @keyframes p21pop { from { opacity: 0; transform: translateY(6px) scale(.98) } to { opacity: 1; transform: none } }
      @keyframes p21fade { from { opacity: 0 } to { opacity: 1 } }
    `;
    document.head.appendChild(st);
  }

  /* ---------- 设计令牌 ---------- */
  const C = {
    ink: '#37352F', ink2: '#5F5E5A', muted: '#787774', faint: '#9B9A97',
    line: '#E9E9E7', line2: '#EDEDEB', border: '#E3E2E0',
    side: '#F7F7F5', active: '#EBEBE9', soft: '#F1F1EF',
    green: '#2F5D45', greenDot: '#3F7357', avatarBg: '#DDE8DB', leaf: '#7FA77E',
    red: '#8A3B2E', redBg: '#F7EEEB', amber: '#7A5A2A', rec: '#E0654A',
  };
  const SERIF = 'Newsreader, Georgia, serif';
  const MONO = "ui-monospace, 'JetBrains Mono', Menlo, monospace";

  /* ---------- 全局状态上下文：{ s, set, go, openModal } ---------- */
  const Ctx = React.createContext(null);
  const useP = () => React.useContext(Ctx);

  /* 小节标签：灰色 12px 半粗 */
  function Label({ children, style }) {
    return <div style={{ fontSize: 12, fontWeight: 600, color: C.faint, ...style }}>{children}</div>;
  }

  /* 统一的跳转入口「More ›」 */
  function More({ onClick, children = 'More ›', style }) {
    return (
      <span onClick={onClick} className="p21-h-link"
        style={{ fontSize: 13, color: C.muted, cursor: 'pointer', whiteSpace: 'nowrap', ...style }}>{children}</span>
    );
  }

  /* 按钮：primary 墨色实心 / ghost 描边 / danger 红字 */
  function Btn({ kind = 'ghost', onClick, disabled, children, style, small }) {
    const pad = small ? '5px 12px' : '7px 14px';
    const base = { display: 'inline-flex', alignItems: 'center', gap: 8, padding: pad, borderRadius: 6, fontSize: 13, fontWeight: 500, cursor: disabled ? 'default' : 'pointer', whiteSpace: 'nowrap', userSelect: 'none', transition: 'background .15s' };
    const kinds = {
      primary: { background: disabled ? '#D3D1CB' : C.ink, color: '#fff', border: '1px solid transparent' },
      ghost: { background: '#fff', color: C.ink, border: `1px solid ${C.border}` },
      danger: { background: 'transparent', color: C.red, border: '1px solid transparent' },
      dangerSolid: { background: C.red, color: '#fff', border: '1px solid transparent' },
      green: { background: disabled ? '#D3D1CB' : C.green, color: '#fff', border: '1px solid transparent' },
    };
    const hov = disabled ? '' : kind === 'primary' ? 'p21-h-dark' : kind === 'danger' ? 'p21-h-danger' : kind === 'ghost' ? 'p21-h-soft' : '';
    return <span className={hov} onClick={disabled ? undefined : onClick} style={{ ...base, ...kinds[kind], ...style }}>{children}</span>;
  }

  /* 头像：已上传用图片，没上传用首字母圆形占位 */
  function Av({ size = 26, uploaded }) {
    if (uploaded) {
      return <img src="assets/apple-touch-icon.png" alt="" style={{ width: size, height: size, borderRadius: '50%', objectFit: 'cover', flexShrink: 0, display: 'block' }} />;
    }
    return (
      <span style={{ width: size, height: size, borderRadius: '50%', background: C.avatarBg, color: C.green, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontFamily: SERIF, fontSize: Math.round(size * 0.5), flexShrink: 0, lineHeight: 1 }}>J</span>
    );
  }

  /* 分类 / 筛选标签（胶囊） */
  function Pill({ on, onClick, children, style }) {
    return (
      <span onClick={onClick} className={on ? '' : 'p21-h-soft'}
        style={{ display: 'inline-flex', alignItems: 'center', gap: 7, padding: '5px 12px', borderRadius: 999, fontSize: 13, cursor: 'pointer', border: `1px solid ${on ? C.active : C.border}`, background: on ? C.active : 'transparent', color: C.ink, whiteSpace: 'nowrap', ...style }}>{children}</span>
    );
  }

  /* 开关 */
  function Toggle({ on, onClick }) {
    return (
      <span onClick={onClick} style={{ width: 34, height: 20, borderRadius: 999, background: on ? C.green : C.border, position: 'relative', cursor: 'pointer', transition: 'background .2s', flexShrink: 0, display: 'inline-block' }}>
        <span style={{ position: 'absolute', top: 2, left: on ? 16 : 2, width: 16, height: 16, borderRadius: '50%', background: '#fff', boxShadow: '0 1px 2px rgba(0,0,0,.2)', transition: 'left .2s' }} />
      </span>
    );
  }

  /* 勾选框 */
  function Check({ on, disabled, onClick, children }) {
    return (
      <span onClick={disabled ? undefined : onClick} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, cursor: disabled ? 'default' : 'pointer', color: disabled ? '#AEAEB2' : C.ink }}>
        <span style={{ width: 18, height: 18, borderRadius: 5, border: `1px solid ${disabled ? C.line : on ? C.ink : '#C9C8C5'}`, background: on && !disabled ? C.ink : '#fff', color: '#fff', fontSize: 12, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>{on && !disabled ? '✓' : ''}</span>
        {children}
      </span>
    );
  }

  /* 弹窗：屏幕正中、背景变暗；点背景或 ✕ 关闭（定位在 App 窗口内部） */
  function Modal({ width = 520, onClose, children, pad = '22px 26px 24px' }) {
    return (
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, zIndex: 40, background: 'rgba(15,15,15,.28)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24, animation: 'p21fade .15s' }}>
        <div onClick={(e) => e.stopPropagation()} className="p21-scroll"
          style={{ width: '100%', maxWidth: width, maxHeight: 'calc(100% - 48px)', overflowY: 'auto', background: '#fff', borderRadius: 12, padding: pad, boxShadow: '0 24px 64px rgba(15,15,15,.2)', animation: 'p21pop .18s ease-out' }}>
          {children}
        </div>
      </div>
    );
  }

  /* 弹窗标题行：左标题，右 ✕ */
  function ModalHead({ title, onClose, sub }) {
    return (
      <div>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 16 }}>
          <span style={{ fontSize: 20, fontWeight: 600, letterSpacing: '-.01em' }}>{title}</span>
          <X onClick={onClose} />
        </div>
        {sub && <div style={{ marginTop: 4, fontSize: 13.5, color: C.muted }}>{sub}</div>}
      </div>
    );
  }
  function X({ onClick, size = 20 }) {
    return <span onClick={onClick} style={{ cursor: 'pointer', fontSize: size, lineHeight: 1, color: C.muted }}>×</span>;
  }

  /* 分段切换（Day / Week / Month、All / Done by AI 等） */
  function Seg({ items, value, onChange, small }) {
    return (
      <span style={{ display: 'inline-flex', padding: 2, background: C.soft, borderRadius: 6, fontSize: small ? 12.5 : 13 }}>
        {items.map(([k, label]) => {
          const on = k === value;
          return (
            <span key={k} onClick={() => onChange && onChange(k)}
              style={{ padding: small ? '3px 11px' : '5px 14px', borderRadius: 5, cursor: 'pointer', background: on ? '#fff' : 'transparent', color: on ? C.ink : C.muted, boxShadow: on ? '0 1px 2px rgba(15,15,15,.08)' : 'none', whiteSpace: 'nowrap' }}>{label}</span>
          );
        })}
      </span>
    );
  }

  /* 深色悬浮提示 */
  function Tip({ children, style }) {
    return (
      <div style={{ position: 'absolute', zIndex: 20, background: C.ink, color: '#F3F4F1', borderRadius: 6, padding: '10px 12px', fontSize: 12.5, whiteSpace: 'nowrap', boxShadow: '0 10px 28px rgba(15,15,15,.22)', animation: 'p21fade .12s', ...style }}>{children}</div>
    );
  }

  /* 线性图标（lucide 风格） */
  const ICON = {
    Home: 'M3 11l9-7 9 7v9a1 1 0 0 1-1 1h-5v-6h-6v6H4a1 1 0 0 1-1-1z',
    You: 'M12 12a4 4 0 1 0 0-8a4 4 0 1 0 0 8zM4 20a8 8 0 0 1 16 0',
    Timeline: 'M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18M12 7v5l3 2',
    Playbook: 'M4 6h.01M4 12h.01M4 18h.01M8 6h12M8 12h12M8 18h12',
    'Check-ins': 'M6 16v-5a6 6 0 0 1 12 0v5l2 2H4zM10 20a2 2 0 0 0 4 0',
    connections: 'M8 7h11l-3-3M16 17H5l3 3',
    settings: 'M12 15a3 3 0 1 0 0-6a3 3 0 1 0 0 6zM19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3a1.7 1.7 0 0 0-1 1.5V21a2 2 0 0 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5a1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8a1.7 1.7 0 0 0-1.5-1H3a2 2 0 0 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1a1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 0 1 4 0v.1a1.7 1.7 0 0 0 1 1.5a1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 0 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z',
    account: 'M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18M12 13a3 3 0 1 0 0-6a3 3 0 1 0 0 6M6.7 18.4a6 6 0 0 1 10.6 0',
    logout: 'M15 4h3a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-3M10 17l5-5-5-5M15 12H3',
    back: 'M15 18l-6-6 6-6',
    mail: 'M4 6h16a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zM3.5 7l8.5 6 8.5-6',
    expand: 'M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7',
    collapse: 'M4 14h6v6M20 10h-6V4M14 10l7-7M3 21l7-7',
    restart: 'M21 12a9 9 0 1 1-2.64-6.36L21 8M21 3v5h-5',
    pause: 'M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18M10 9v6M14 9v6',
    play: 'M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18M10 8.5l5 3.5-5 3.5z',
    ask: 'M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z',
  };
  function Ico({ name, size = 16, sw = 1.7, style }) {
    return (
      <svg width={size} height={size} viewBox="0 0 24 24" style={{ fill: 'none', stroke: 'currentColor', strokeWidth: sw, strokeLinecap: 'round', strokeLinejoin: 'round', flexShrink: 0, ...style }}>
        <path d={ICON[name]} />
      </svg>
    );
  }

  Object.assign(window.P21, { C, SERIF, MONO, Ctx, useP, Label, More, Btn, Av, Pill, Toggle, Check, Modal, ModalHead, X, Seg, Tip, Ico });
})();
