/* global React */

// =============================================================================
// Knockit product mockups — recreated from the real Sales CRM design system.
// All screens render the actual product chrome (sidebar, topbar, cards, tables)
// with realistic Korean B2B dummy data.
//
// Scoped under a `.pm` wrapper so the indigo brand vars don't leak into
// the landing's warm palette.
// =============================================================================

const { useState, useEffect } = React;

// ---- one-time scoped style injection ---------------------------------------
if (typeof document !== "undefined" && !document.getElementById("pm-styles")) {
  const s = document.createElement("style");
  s.id = "pm-styles";
  s.textContent = `
.pm {
  /* product design tokens — scoped */
  --c-bg: #fafafa;
  --c-surface: #ffffff;
  --c-surface-2: #f7f7f8;
  --c-surface-3: #f3f3f5;
  --c-border: #e7e7ea;
  --c-border-strong: #d4d4d8;
  --c-divider: #efeff1;
  --c-text: #18181b;
  --c-text-2: #52525b;
  --c-text-3: #71717a;
  --c-text-4: #a1a1aa;
  --c-brand: #4f46e5;
  --c-brand-600: #4338ca;
  --c-brand-700: #3730a3;
  --c-brand-50: #eef2ff;
  --c-brand-100: #e0e7ff;
  --c-success: #16a34a; --c-success-bg: #ecfdf5;
  --c-warning: #d97706; --c-warning-bg: #fffbeb;
  --c-danger:  #dc2626; --c-danger-bg:  #fef2f2;
  --pm-font-sans: "Inter", "Pretendard", -apple-system, BlinkMacSystemFont, sans-serif;
  --pm-font-mono: "JetBrains Mono", "SF Mono", ui-monospace, Menlo, monospace;

  font-family: var(--pm-font-sans);
  font-size: 13px;
  line-height: 1.5;
  color: var(--c-text);
  background: var(--c-bg);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: "cv11", "ss01";
  font-variant-numeric: tabular-nums;
  width: 100%;
  display: block;
  position: relative;
  overflow: hidden;
}
.pm * { box-sizing: border-box; }
.pm .mono { font-family: var(--pm-font-mono); font-variant-numeric: tabular-nums; }

/* App shell */
.pm-shell { display: flex; height: 100%; min-height: 100%; background: var(--c-bg); overflow: hidden; }
.pm-side { width: 200px; flex: 0 0 200px; background: var(--c-surface); border-right: 1px solid var(--c-border); display: flex; flex-direction: column; }
.pm-side[data-icon-only="1"] { width: 52px; flex: 0 0 52px; }
.pm-side[data-icon-only="1"] .pm-side-brand { padding: 0; justify-content: center; gap: 0; }
.pm-side[data-icon-only="1"] .pm-nav-item { justify-content: center; padding: 8px 0; }
.pm-side[data-icon-only="1"] .pm-nav-item.active::before { left: 0; }
.pm-side[data-icon-only="1"] .pm-nav { padding: 8px 4px; }
.pm-side-brand { height: 48px; padding: 0 14px; display: flex; align-items: center; gap: 9px; border-bottom: 1px solid var(--c-divider); }
.pm-mark { width: 22px; height: 22px; border-radius: 5px; background: var(--c-text); color: #fff; display: grid; place-items: center; font-weight: 700; font-size: 10px; letter-spacing: -0.02em; }
.pm-brand-name { font-weight: 600; font-size: 12px; letter-spacing: -0.01em; }
.pm-side-user { padding: 8px 10px; border-bottom: 1px solid var(--c-divider); }
.pm-user-card { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: 6px; }
.pm-avatar { width: 24px; height: 24px; border-radius: 50%; background: var(--c-brand-100); color: var(--c-brand-700); display: grid; place-items: center; font-weight: 600; font-size: 10px; flex-shrink: 0; }
.pm-user-name { font-size: 11.5px; font-weight: 600; line-height: 1.2; }
.pm-user-role { font-size: 10px; color: var(--c-text-3); line-height: 1.3; margin-top: 1px; }
.pm-nav { flex: 1; padding: 8px 6px; }
.pm-nav-label { font-size: 9.5px; font-weight: 600; color: var(--c-text-4); text-transform: uppercase; letter-spacing: 0.06em; padding: 8px 8px 4px; }
.pm-nav-item { display: flex; align-items: center; gap: 9px; padding: 6px 8px; border-radius: 5px; font-size: 12px; color: var(--c-text-2); font-weight: 500; position: relative; margin-bottom: 1px; }
.pm-nav-item.active { background: var(--c-surface-3); color: var(--c-text); }
.pm-nav-item.active::before { content: ""; position: absolute; left: -6px; top: 6px; bottom: 6px; width: 2px; background: var(--c-brand); border-radius: 0 2px 2px 0; }
.pm-nav-item i { width: 14px; text-align: center; color: var(--c-text-3); font-size: 12px; }
.pm-nav-item.active i { color: var(--c-brand); }

/* Main + topbar */
.pm-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.pm-topbar { height: 48px; background: var(--c-surface); border-bottom: 1px solid var(--c-border); display: flex; align-items: center; padding: 0 16px; gap: 14px; flex-shrink: 0; }
.pm-topbar-title { font-size: 13.5px; font-weight: 600; letter-spacing: -0.01em; }
.pm-topbar-sub { font-size: 10.5px; color: var(--c-text-4); margin-top: 1px; }
.pm-topbar .actions { margin-left: auto; display: flex; gap: 6px; }
.pm-body { flex: 1; overflow: hidden; background: var(--c-bg); }

/* Buttons */
.pm-btn { display: inline-flex; align-items: center; justify-content: center; gap: 5px; height: 26px; padding: 0 10px; font-size: 11.5px; font-weight: 500; border-radius: 6px; border: 1px solid transparent; background: transparent; color: var(--c-text); white-space: nowrap; letter-spacing: -0.005em; cursor: default; }
.pm-btn i { font-size: 10.5px; }
.pm-btn.brand { background: var(--c-brand); color: #fff; border-color: var(--c-brand); }
.pm-btn.default { background: var(--c-surface); border-color: var(--c-border); color: var(--c-text); }
.pm-btn.ghost { color: var(--c-text-2); }
.pm-btn.sm { height: 22px; font-size: 11px; padding: 0 8px; }

/* Forms */
.pm-input, .pm-select { width: 100%; height: 28px; padding: 0 9px; font-size: 11.5px; color: var(--c-text); background: var(--c-surface); border: 1px solid var(--c-border); border-radius: 6px; font-family: inherit; }
.pm-input::placeholder { color: var(--c-text-4); }

/* Status */
.pm-status { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 500; white-space: nowrap; }
.pm-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pm-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }

/* Chips */
.pm-chip { display: inline-flex; align-items: center; height: 18px; padding: 0 7px; font-size: 10.5px; font-weight: 500; border-radius: 9px; }

/* Cards */
.pm-card { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: 9px; box-shadow: 0 1px 0 rgba(16,24,40,0.04); }
.pm-card-h { display: flex; align-items: center; gap: 10px; padding: 11px 13px; border-bottom: 1px solid var(--c-divider); }
.pm-card-t { font-size: 12px; font-weight: 600; }
.pm-card-b { padding: 13px; }

/* Metric */
.pm-metric { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: 9px; padding: 12px 14px; box-shadow: 0 1px 0 rgba(16,24,40,0.04); }
.pm-metric .lbl { font-size: 10.5px; color: var(--c-text-3); font-weight: 500; display: flex; align-items: center; gap: 5px; }
.pm-metric .lbl i { font-size: 10px; color: var(--c-text-4); }
.pm-metric .val { font-family: var(--pm-font-mono); font-variant-numeric: tabular-nums; font-size: 22px; font-weight: 600; letter-spacing: -0.02em; margin-top: 6px; line-height: 1.1; }
.pm-metric .val .u { font-size: 12px; color: var(--c-text-3); margin-left: 2px; }
.pm-metric .d { margin-top: 6px; display: inline-flex; align-items: center; gap: 3px; font-family: var(--pm-font-mono); font-size: 10.5px; font-weight: 500; }
.pm-metric .d.up { color: var(--c-success); }

/* Table */
.pm-table-wrap { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: 9px; overflow: hidden; }
.pm-table-tool { display: flex; align-items: center; gap: 7px; padding: 8px 11px; border-bottom: 1px solid var(--c-divider); }
.pm-table { width: 100%; border-collapse: collapse; font-size: 11.5px; table-layout: fixed; }
.pm-table thead th { background: var(--c-surface-2); padding: 7px 10px; text-align: left; font-size: 10.5px; font-weight: 500; color: var(--c-text-3); border-bottom: 1px solid var(--c-border); white-space: nowrap; letter-spacing: 0.01em; }
.pm-table thead th.num { text-align: right; }
.pm-table tbody tr { border-bottom: 1px solid var(--c-divider); }
.pm-table tbody tr:last-child { border-bottom: 0; }
.pm-table tbody td { padding: 9px 12px; color: var(--c-text); vertical-align: middle; overflow: hidden; text-overflow: ellipsis; }
.pm-table tbody td.muted { color: var(--c-text-3); }
.pm-table tbody td.num { text-align: right; font-family: var(--pm-font-mono); }
.pm-row-pri { font-weight: 500; }
.pm-row-sec { color: var(--c-text-3); font-size: 10.5px; margin-top: 1px; }

/* Mobile shell */
.pm-mobile {
  width: 290px; height: 600px; background: #0a0a0a;
  border-radius: 38px; padding: 8px; position: relative;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5), inset 0 0 0 1px #2a2a2a;
  flex-shrink: 0;
}
.pm-mobile-screen { background: var(--c-bg); width: 100%; height: 100%; border-radius: 30px; overflow: hidden; position: relative; display: flex; flex-direction: column; font-family: var(--pm-font-sans); }
.pm-mobile-notch { position: absolute; top: 8px; left: 50%; transform: translateX(-50%); width: 90px; height: 22px; background: #0a0a0a; border-radius: 14px; z-index: 5; }
.pm-mobile-topbar { height: 64px; padding: 32px 14px 8px; display: flex; align-items: flex-end; justify-content: space-between; background: var(--c-surface); border-bottom: 1px solid var(--c-border); flex-shrink: 0; }
.pm-mobile-content { flex: 1; position: relative; overflow: hidden; }
.pm-mobile-nav { height: 56px; background: var(--c-surface); border-top: 1px solid var(--c-border); display: flex; flex-shrink: 0; }
.pm-mobile-nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; color: var(--c-text-4); font-size: 9px; font-weight: 500; }
.pm-mobile-nav-item i { font-size: 16px; }
.pm-mobile-nav-item.active { color: var(--c-brand); }
.pm-fab {
  position: absolute; right: 14px; bottom: 16px; z-index: 4;
  display: flex; align-items: center; gap: 6px;
  padding: 10px 14px; border-radius: 999px;
  background: var(--c-brand); color: #fff;
  box-shadow: 0 6px 18px rgba(79,70,229,0.35);
  font-size: 12px; font-weight: 600;
}
.pm-fab i { font-size: 11px; }
`;
  document.head.appendChild(s);
}

// =============================================================================
// Shared dummy data
// =============================================================================
const STATUSES = {
  prospect: { name: "예상거래처", short: "예상", color: "#71717a", chipBg: "#f3f3f5", chipBd: "#e7e7ea" },
  visited: { name: "방문완료", short: "방문", color: "#4f46e5", chipBg: "#eef2ff", chipBd: "#dbe1ff" },
  existing: { name: "기존거래처", short: "기존", color: "#15803d", chipBg: "#ecfdf5", chipBd: "#bbf7d0" }
};

const CUSTOMERS = [
{ id: 1, name: "동성식품(주)", industry: "식자재 유통", region: "서울 강서구 화곡동", status: "existing", visits: 14, last: "어제", mapX: 24, mapY: 32 },
{ id: 2, name: "한일전자", industry: "전자부품", region: "인천 남동구 논현동", status: "visited", visits: 3, last: "2일 전", mapX: 44, mapY: 26 },
{ id: 3, name: "성진금속(주)", industry: "금속가공", region: "서울 강남구 봉은사로", status: "existing", visits: 22, last: "3일 전", mapX: 56, mapY: 48 },
{ id: 4, name: "유진산업", industry: "포장재", region: "경기 안산시 단원구", status: "visited", visits: 5, last: "오늘", mapX: 72, mapY: 38 },
{ id: 5, name: "두림케미칼", industry: "화학", region: "충북 청주시 흥덕구", status: "prospect", visits: 0, last: "-", mapX: 36, mapY: 62 },
{ id: 6, name: "현민산업", industry: "산업재", region: "대구 달서구 성서공단", status: "existing", visits: 9, last: "1주 전", mapX: 64, mapY: 70 },
{ id: 7, name: "태광정밀", industry: "정밀가공", region: "경남 창원시 의창구", status: "visited", visits: 2, last: "5일 전", mapX: 82, mapY: 56 },
{ id: 8, name: "선경상사", industry: "도매 유통", region: "광주 광산구 하남대로", region2: "광주", status: "prospect", visits: 0, last: "-", mapX: 19, mapY: 52 }];


// Knockit mini mark — confirmed brand (Ink tile + Cream k + Terra dots)
function PmKnockMark({ size = 22, radius = 5 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 100 100" style={{ borderRadius: radius, flexShrink: 0 }} aria-hidden="true">
      <rect width="100" height="100" fill="#1F2430" />
      <g stroke="#F7F1E8" strokeWidth="10.5" strokeLinecap="round" strokeLinejoin="round" fill="none">
        <path d="M36 22 L36 78" />
        <path d="M36 55 L55 39" />
        <path d="M36 54 Q45 62 57 78" />
      </g>
      <g fill="#C96F4A">
        <circle cx="64" cy="62" r="3.4" opacity="0.6" />
        <circle cx="76" cy="44" r="5.2" />
      </g>
    </svg>);

}

const ACTIVITY_TYPES = {
  call: { name: "전화", color: "#1d4ed8", bg: "#dbeafe", icon: "fa-phone" },
  visit: { name: "방문", color: "#15803d", bg: "#dcfce7", icon: "fa-map-marker-alt" },
  email: { name: "이메일", color: "#be185d", bg: "#fce7f3", icon: "fa-envelope" },
  meeting: { name: "미팅", color: "#7c3aed", bg: "#ede9fe", icon: "fa-users" },
  proposal: { name: "제안서 발송", color: "#a16207", bg: "#fef9c3", icon: "fa-file-alt" }
};

const RECENT_ACTIVITIES = [
{ type: "visit", customer: "성진금속(주)", note: "신규 거래 협의, 견적서 요청받음", who: "김민수", when: "오늘 14:20" },
{ type: "call", customer: "한일전자", note: "내년도 발주 일정 조율", who: "이지은", when: "오늘 11:05" },
{ type: "email", customer: "동성식품(주)", note: "월간 정기 단가표 송부", who: "박지훈", when: "어제 17:48" },
{ type: "proposal", customer: "유진산업", note: "프리미엄 라인 제안서 전달", who: "김민수", when: "어제 10:12" },
{ type: "meeting", customer: "현민산업", note: "분기 리뷰 미팅 — 다음 액션 등록", who: "이지은", when: "5월 14일" }];


// =============================================================================
// Reusable building blocks
// =============================================================================
function Sidebar({ active = "map", role = "admin", iconOnly = false }) {
  const items = [
  { key: "dashboard", icon: "fa-chart-pie", label: "대시보드" },
  { key: "map", icon: "fa-map", label: "지도" },
  { key: "customers", icon: "fa-building", label: "거래처 목록" },
  { key: "activities", icon: "fa-clipboard-list", label: "영업활동" }];

  const adminItems = [
  { key: "users", icon: "fa-users", label: "사용자 관리" },
  { key: "statuses", icon: "fa-tags", label: "거래처 상태" },
  { key: "custom-fields", icon: "fa-list-alt", label: "커스텀 필드" }];

  return (
    <aside className="pm-side" data-icon-only={iconOnly ? "1" : undefined}>
      <div className="pm-side-brand">
        <PmKnockMark size={22} radius={5} />
        {!iconOnly && <span className="pm-brand-name">노킷</span>}
      </div>
      {!iconOnly &&
      <div className="pm-side-user">
          <div className="pm-user-card">
            <div className="pm-avatar">{role === "admin" ? "관" : "김"}</div>
            <div style={{ minWidth: 0, flex: 1 }}>
              <div className="pm-user-name">{role === "admin" ? "관리자" : "김민수"}</div>
              <div className="pm-user-role">{role === "admin" ? "관리자" : "영업담당자"}</div>
            </div>
            <i className="fas fa-chevron-down" style={{ color: "var(--c-text-4)", fontSize: 9 }} />
          </div>
        </div>
      }
      <nav className="pm-nav">
        {!iconOnly && <div className="pm-nav-label">메뉴</div>}
        {items.map((it) =>
        <div className={`pm-nav-item ${active === it.key ? "active" : ""}`} key={it.key}>
            <i className={`fas ${it.icon}`} />
            {!iconOnly && <span>{it.label}</span>}
          </div>
        )}
        {role === "admin" && !iconOnly &&
        <>
            <div className="pm-nav-label" style={{ marginTop: 8 }}>관리자</div>
            {adminItems.map((it) =>
          <div className={`pm-nav-item ${active === it.key ? "active" : ""}`} key={it.key}>
                <i className={`fas ${it.icon}`} />
                <span>{it.label}</span>
              </div>
          )}
          </>
        }
      </nav>
    </aside>);

}

function Topbar({ title, subtitle, actions }) {
  return (
    <header className="pm-topbar">
      <div style={{ display: "flex", flexDirection: "column", flex: 1, minWidth: 0 }}>
        <span className="pm-topbar-title">{title}</span>
        {subtitle && <span className="pm-topbar-sub">{subtitle}</span>}
      </div>
      {actions && <div className="actions">{actions}</div>}
    </header>);

}

function StatusPill({ status }) {
  const s = STATUSES[status];
  return <span className="pm-status" style={{ color: s.color }}>{s.name}</span>;
}

// =============================================================================
// MapMockup — full product, map page with sidebar + side list + map area
// =============================================================================
function MapMockup({ animate = false, compact = false }) {
  const [activeId, setActiveId] = useState(3);
  useEffect(() => {
    if (!animate) return;
    const seq = [1, 3, 4, 6, 3];
    let i = 0;
    const t = setInterval(() => {i = (i + 1) % seq.length;setActiveId(seq[i]);}, 2400);
    return () => clearInterval(t);
  }, [animate]);
  const active = CUSTOMERS.find((c) => c.id === activeId);
  return (
    <div className="pm" style={{ aspectRatio: compact ? "16/10" : "16/9", height: compact ? undefined : "100%", minHeight: compact ? 0 : 480 }}>
      <div className="pm-shell">
        <Sidebar active="map" role="admin" iconOnly={compact} />
        <div className="pm-main">
          <Topbar
            title="지도"
            subtitle={compact ? undefined : "전체 거래처 178건 · 표시 중 38건"}
            actions={<button className="pm-btn brand"><i className="fas fa-plus" /> 거래처 등록</button>} />
          
          <div className="pm-body" style={{ display: "flex", overflow: "hidden" }}>
            {/* left list panel — only when not compact */}
            {!compact &&
            <aside style={{ width: 280, flex: "0 0 280px", background: "var(--c-surface)", borderRight: "1px solid var(--c-border)", display: "flex", flexDirection: "column" }}>
              <div style={{ padding: "10px 12px", borderBottom: "1px solid var(--c-divider)", display: "flex", flexDirection: "column", gap: 6 }}>
                <div style={{ position: "relative" }}>
                  <i className="fas fa-search" style={{ position: "absolute", left: 9, top: "50%", transform: "translateY(-50%)", color: "var(--c-text-4)", fontSize: 11 }} />
                  <input className="pm-input" style={{ paddingLeft: 28 }} placeholder="거래처명·주소 검색" readOnly />
                </div>
                <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
                  <select className="pm-select" defaultValue=""><option value="">전체 지역</option></select>
                  <select className="pm-select" defaultValue=""><option value="">전체 상태</option></select>
                </div>
              </div>
              <div style={{ padding: "8px 12px 4px", display: "flex", justifyContent: "space-between", fontSize: 10.5, color: "var(--c-text-3)" }}>
                <span>지도 영역 내</span>
                <span style={{ color: "var(--c-text-2)", fontWeight: 500 }}>{CUSTOMERS.length}건</span>
              </div>
              <ul style={{ listStyle: "none", margin: 0, padding: "2px 6px 6px", overflowY: "auto", flex: 1 }}>
                {CUSTOMERS.map((c) =>
                <li key={c.id}
                onClick={() => setActiveId(c.id)}
                style={{
                  padding: "9px 9px", borderRadius: 7, display: "flex", gap: 8,
                  background: activeId === c.id ? "var(--c-brand-50)" : "transparent",
                  cursor: "default", marginBottom: 1
                }}>
                    <span className="pm-dot" style={{ marginTop: 5, background: STATUSES[c.status].color }} />
                    <div style={{ minWidth: 0, flex: 1 }}>
                      <div style={{ fontSize: 12, fontWeight: 600, color: "var(--c-text)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{c.name}</div>
                      <div style={{ fontSize: 10.5, color: "var(--c-text-3)", marginTop: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{c.region}</div>
                      <div style={{ fontSize: 10, color: "var(--c-text-4)", marginTop: 3, fontFamily: "var(--pm-font-mono)" }}>{c.industry} · 방문 {c.visits}회 · {c.last}</div>
                    </div>
                  </li>
                )}
              </ul>
            </aside>
            }

            {/* map */}
            <div style={{ flex: 1, position: "relative", overflow: "hidden", background: "#eef1f4" }}>
              <MapBackground />
              {/* legend */}
              <div style={{ position: "absolute", top: 12, left: 12, background: "rgba(255,255,255,0.96)", border: "1px solid var(--c-border)", borderRadius: 7, padding: "6px 10px", display: "flex", gap: 12, fontSize: 10.5, color: "var(--c-text-2)", boxShadow: "0 1px 2px rgba(0,0,0,0.05)" }}>
                {Object.entries(STATUSES).map(([k, s]) =>
                <span key={k} style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
                    <span className="pm-dot" style={{ background: s.color }} />{s.name}
                  </span>
                )}
              </div>
              {/* pins */}
              {CUSTOMERS.map((c) => {
                const isActive = activeId === c.id;
                const s = STATUSES[c.status];
                return (
                  <div key={c.id}
                  style={{ position: "absolute", left: `${c.mapX}%`, top: `${c.mapY}%`, transform: `translate(-50%, -100%) scale(${isActive ? 1.15 : 1})`, transition: "transform .2s", zIndex: isActive ? 5 : 1 }}>
                    <svg width={isActive ? 32 : 26} height={isActive ? 40 : 32} viewBox="0 0 32 40" fill="none">
                      <path d="M16 0 C7 0 0 7 0 16 C0 26 16 40 16 40 C16 40 32 26 32 16 C32 7 25 0 16 0 Z"
                      fill={s.color} stroke="#fff" strokeWidth="2" />
                      <circle cx="16" cy="15" r="5" fill="#fff" />
                    </svg>
                  </div>);

              })}
              {/* info card for active pin */}
              {active &&
              <div style={{
                position: "absolute",
                left: `${active.mapX}%`, top: `${active.mapY}%`,
                transform: `translate(-50%, calc(-100% - 44px))`,
                background: "var(--c-surface)", border: "1px solid var(--c-border)",
                borderRadius: 9, padding: "10px 12px", minWidth: 200, maxWidth: 240,
                boxShadow: "0 8px 24px rgba(0,0,0,0.10), 0 1px 3px rgba(0,0,0,0.06)",
                zIndex: 10,
                fontSize: 11.5
              }}>
                  <div style={{ fontWeight: 600, fontSize: 12.5, marginBottom: 4, paddingBottom: 6, borderBottom: "1px solid var(--c-divider)", display: "flex", alignItems: "center", gap: 6 }}>
                    <span className="pm-dot" style={{ background: STATUSES[active.status].color }} />
                    {active.name}
                  </div>
                  <div style={{ color: "var(--c-text-2)", marginBottom: 3, display: "flex", gap: 5 }}>
                    <i className="fas fa-map-marker-alt" style={{ fontSize: 10, color: "var(--c-text-4)", marginTop: 2 }} />
                    <span>{active.region}</span>
                  </div>
                  <div style={{ color: "var(--c-text-2)", marginBottom: 8, display: "flex", gap: 5 }}>
                    <i className="fas fa-briefcase" style={{ fontSize: 10, color: "var(--c-text-4)", marginTop: 2 }} />
                    <span>{active.industry} · 방문 {active.visits}회</span>
                  </div>
                  <button className="pm-btn brand sm" style={{ width: "100%" }}>상세 보기</button>
                </div>
              }
              {/* zoom controls */}
              <div style={{ position: "absolute", right: 12, top: 12, display: "flex", flexDirection: "column", gap: 4 }}>
                {["fa-plus", "fa-minus", "fa-expand"].map((ic, i) =>
                <button key={i} className="pm-btn default" style={{ width: 30, height: 30, padding: 0 }}>
                    <i className={`fas ${ic}`} />
                  </button>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>);

}

function MapBackground() {
  return (
    <svg width="100%" height="100%" viewBox="0 0 800 500" preserveAspectRatio="xMidYMid slice" style={{ position: "absolute", inset: 0 }}>
      <rect width="800" height="500" fill="#eef1f4" />
      {/* park / green areas */}
      <path d="M120 60 Q200 30 290 80 T420 130 L380 240 Q280 280 180 240 Z" fill="#dfe8d6" opacity="0.7" />
      <path d="M560 280 Q640 250 720 290 L700 400 Q620 430 540 390 Z" fill="#dfe8d6" opacity="0.6" />
      {/* water */}
      <path d="M0 360 Q150 340 320 380 T620 410 L800 400 L800 500 L0 500 Z" fill="#cfdce6" opacity="0.7" />
      {/* roads */}
      <line x1="0" y1="180" x2="800" y2="170" stroke="#fff" strokeWidth="14" />
      <line x1="0" y1="180" x2="800" y2="170" stroke="#dfe2e6" strokeWidth="1" />
      <line x1="0" y1="320" x2="800" y2="310" stroke="#fff" strokeWidth="10" />
      <line x1="200" y1="0" x2="220" y2="500" stroke="#fff" strokeWidth="12" />
      <line x1="500" y1="0" x2="520" y2="500" stroke="#fff" strokeWidth="10" />
      <line x1="680" y1="0" x2="690" y2="500" stroke="#fff" strokeWidth="8" />
      {/* minor roads */}
      <line x1="0" y1="90" x2="800" y2="85" stroke="#fff" strokeWidth="5" />
      <line x1="0" y1="250" x2="800" y2="240" stroke="#fff" strokeWidth="5" />
      <line x1="0" y1="430" x2="800" y2="425" stroke="#fff" strokeWidth="5" />
      <line x1="100" y1="0" x2="110" y2="500" stroke="#fff" strokeWidth="5" />
      <line x1="350" y1="0" x2="360" y2="500" stroke="#fff" strokeWidth="5" />
      <line x1="600" y1="0" x2="610" y2="500" stroke="#fff" strokeWidth="5" />
      <line x1="760" y1="0" x2="770" y2="500" stroke="#fff" strokeWidth="5" />
      {/* labels */}
      <text x="62" y="38" fill="#9ba2ab" fontSize="11" fontFamily="Inter, sans-serif" fontWeight="500">강서구</text>
      <text x="280" y="125" fill="#9ba2ab" fontSize="11" fontFamily="Inter, sans-serif" fontWeight="500">강남구</text>
      <text x="540" y="180" fill="#9ba2ab" fontSize="11" fontFamily="Inter, sans-serif" fontWeight="500">송파구</text>
      <text x="320" y="350" fill="#9ba2ab" fontSize="11" fontFamily="Inter, sans-serif" fontWeight="500">한강</text>
    </svg>);

}

// =============================================================================
// DashboardMockup — KPI metrics + status distribution + recent activity
// =============================================================================
function DashboardMockup({ tone = "light" }) {
  const dark = tone === "dark";
  return (
    <div className="pm" style={{ aspectRatio: "16/9", height: "100%", minHeight: 460, background: dark ? "#0f0f12" : undefined }}>
      <div className="pm-shell" style={{ background: dark ? "#0f0f12" : undefined }}>
        <Sidebar active="dashboard" role="admin" />
        <div className="pm-main">
          <Topbar title="대시보드" subtitle="2026년 5월 18일 · 전사 보기" actions={<button className="pm-btn default"><i className="fas fa-download" /> 내보내기</button>} />
          <div className="pm-body" style={{ overflow: "auto", padding: "18px 22px" }}>
            {/* metrics */}
            <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 11 }}>
              {[
              { lbl: "전체 거래처", val: "178", u: "건", icon: "fa-building", delta: "+12 이번 주" },
              { lbl: "이번 주 방문", val: "42", u: "회", icon: "fa-map-marker-alt", delta: "+8.4% WoW" },
              { lbl: "활성 영업담당자", val: "7", u: "명", icon: "fa-user-tag", delta: "전체 8명" },
              { lbl: "오픈 다음 액션", val: "23", u: "건", icon: "fa-flag", delta: "오늘 마감 4건" }].
              map((m, i) =>
              <div className="pm-metric" key={i}>
                  <div className="lbl"><i className={`fas ${m.icon}`} /> {m.lbl}</div>
                  <div className="val">{m.val}<span className="u">{m.u}</span></div>
                  <div className="d up"><i className="fas fa-arrow-up" /> {m.delta}</div>
                </div>
              )}
            </div>

            {/* Two col */}
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 11, marginTop: 14 }}>
              {/* status distribution */}
              <div className="pm-card">
                <div className="pm-card-h">
                  <div>
                    <div className="pm-card-t">상태별 거래처 분포</div>
                    <div style={{ fontSize: 11, color: "var(--c-text-3)" }}>전체 178건 기준</div>
                  </div>
                </div>
                <div className="pm-card-b" style={{ display: "flex", flexDirection: "column", gap: 11 }}>
                  {[
                  { s: "existing", count: 92, pct: 52 },
                  { s: "visited", count: 48, pct: 27 },
                  { s: "prospect", count: 38, pct: 21 }].
                  map((row, i) => {
                    const st = STATUSES[row.s];
                    return (
                      <div key={i}>
                        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 5 }}>
                          <span className="pm-status" style={{ color: st.color }}>{st.name}</span>
                          <span className="mono" style={{ fontSize: 11.5, color: "var(--c-text-3)" }}>{row.count}건 · {row.pct}%</span>
                        </div>
                        <div style={{ height: 5, borderRadius: 2.5, background: "var(--c-surface-3)", overflow: "hidden" }}>
                          <div style={{ height: "100%", width: `${row.pct}%`, background: st.color }} />
                        </div>
                      </div>);

                  })}
                </div>
              </div>

              {/* user stats */}
              <div className="pm-card">
                <div className="pm-card-h">
                  <div>
                    <div className="pm-card-t">담당자별 거래처</div>
                    <div style={{ fontSize: 11, color: "var(--c-text-3)" }}>이번 달 기준</div>
                  </div>
                </div>
                <div className="pm-card-b" style={{ display: "flex", flexDirection: "column", gap: 9 }}>
                  {[
                  { name: "김민수", count: 38, pct: 78 },
                  { name: "이지은", count: 32, pct: 66 },
                  { name: "박지훈", count: 27, pct: 56 },
                  { name: "최서연", count: 24, pct: 50 },
                  { name: "정우진", count: 19, pct: 39 }].
                  map((u, i) =>
                  <div key={i} style={{ display: "flex", alignItems: "center", gap: 10 }}>
                      <div className="pm-avatar">{u.name[0]}</div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 3 }}>
                          <span style={{ fontSize: 11.5, fontWeight: 500 }}>{u.name}</span>
                          <span className="mono" style={{ fontSize: 11, color: "var(--c-text-3)" }}>{u.count}건</span>
                        </div>
                        <div style={{ height: 4, borderRadius: 2, background: "var(--c-surface-3)", overflow: "hidden" }}>
                          <div style={{ height: "100%", width: `${u.pct}%`, background: "var(--c-brand)" }} />
                        </div>
                      </div>
                    </div>
                  )}
                </div>
              </div>
            </div>

            {/* recent activities */}
            <div className="pm-card" style={{ marginTop: 14 }}>
              <div className="pm-card-h">
                <div className="pm-card-t">최근 영업 활동</div>
                <div style={{ marginLeft: "auto" }}><button className="pm-btn ghost sm">전체 보기 →</button></div>
              </div>
              <div style={{ padding: "4px 0" }}>
                {RECENT_ACTIVITIES.slice(0, 4).map((a, i) => {
                  const t = ACTIVITY_TYPES[a.type];
                  return (
                    <div key={i} style={{ display: "flex", gap: 11, padding: "9px 14px", borderBottom: i < 3 ? "1px solid var(--c-divider)" : "none", alignItems: "center" }}>
                      <div style={{ width: 28, height: 28, borderRadius: 6, background: t.bg, color: t.color, display: "grid", placeItems: "center", flexShrink: 0 }}>
                        <i className={`fas ${t.icon}`} style={{ fontSize: 11 }} />
                      </div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
                          <span style={{ fontSize: 12, fontWeight: 600 }}>{a.customer}</span>
                          <span className="pm-chip" style={{ background: t.bg + "", color: t.color, border: `1px solid ${t.color}33` }}>{t.name}</span>
                        </div>
                        <div style={{ fontSize: 11, color: "var(--c-text-2)", marginTop: 2, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{a.note}</div>
                      </div>
                      <div style={{ fontSize: 10.5, color: "var(--c-text-3)", textAlign: "right", flexShrink: 0 }}>
                        <div style={{ fontWeight: 500, color: "var(--c-text-2)" }}>{a.who}</div>
                        <div className="mono" style={{ marginTop: 1 }}>{a.when}</div>
                      </div>
                    </div>);

                })}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>);

}

// =============================================================================
// PermissionMockup — admin (dashboard / team-wide) vs sales (map / my-only)
// Two genuinely different pages to make the role split visually obvious.
// =============================================================================
function PermissionMockup() {
  function AdminMini() {
    return (
      <div className="pm" style={{ aspectRatio: "16/11", minHeight: 340, borderRadius: 9, border: "1px solid var(--c-border)", overflow: "hidden" }}>
        <div className="pm-shell">
          <Sidebar active="dashboard" role="admin" iconOnly />
          <div className="pm-main">
            <Topbar
              title="대시보드"
              subtitle="전사 보기 · 5월 18일"
              actions={
              <span className="pm-chip" style={{ background: "var(--c-brand-50)", color: "var(--c-brand-700)", border: "1px solid #dbe1ff" }}>
                  <i className="fas fa-shield-alt" style={{ fontSize: 9, marginRight: 4 }} />
                  관리자
                </span>
              } />
            
            <div className="pm-body" style={{ padding: 12, overflow: "hidden", display: "flex", flexDirection: "column", gap: 10 }}>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8 }}>
                {[
                { lbl: "전체 거래처", val: "178", u: "건" },
                { lbl: "팀 활동", val: "312", u: "건" },
                { lbl: "활성 담당자", val: "7", u: "명" }].
                map((m, i) =>
                <div className="pm-metric" key={i} style={{ padding: "9px 11px" }}>
                    <div className="lbl" style={{ fontSize: 9.5 }}>{m.lbl}</div>
                    <div className="val" style={{ fontSize: 17, marginTop: 3 }}>{m.val}<span className="u" style={{ fontSize: 10 }}>{m.u}</span></div>
                  </div>
                )}
              </div>
              <div className="pm-card" style={{ flex: 1, minHeight: 0, overflow: "hidden" }}>
                <div className="pm-card-h" style={{ padding: "8px 11px" }}>
                  <div className="pm-card-t" style={{ fontSize: 11 }}>팀원별 거래처</div>
                  <span style={{ marginLeft: "auto", fontSize: 10, color: "var(--c-text-4)" }}>전체 5명</span>
                </div>
                <div style={{ padding: "8px 11px", display: "flex", flexDirection: "column", gap: 7 }}>
                  {[
                  { name: "김민수", count: 38, pct: 78 },
                  { name: "이지은", count: 32, pct: 66 },
                  { name: "박지훈", count: 27, pct: 56 },
                  { name: "최서연", count: 24, pct: 50 }].
                  map((u, i) =>
                  <div key={i} style={{ display: "flex", alignItems: "center", gap: 8 }}>
                      <div className="pm-avatar" style={{ width: 20, height: 20, fontSize: 9 }}>{u.name[0]}</div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 2 }}>
                          <span style={{ fontSize: 10.5, fontWeight: 500 }}>{u.name}</span>
                          <span className="mono" style={{ fontSize: 10, color: "var(--c-text-3)" }}>{u.count}건</span>
                        </div>
                        <div style={{ height: 3, borderRadius: 2, background: "var(--c-surface-3)", overflow: "hidden" }}>
                          <div style={{ height: "100%", width: `${u.pct}%`, background: "var(--c-brand)" }} />
                        </div>
                      </div>
                    </div>
                  )}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>);

  }

  function SalesMini() {
    return (
      <div className="pm" style={{ aspectRatio: "16/11", minHeight: 340, borderRadius: 9, border: "1px solid var(--c-border)", overflow: "hidden" }}>
        <div className="pm-shell">
          <Sidebar active="map" role="sales" iconOnly />
          <div className="pm-main">
            <Topbar
              title="지도"
              subtitle="내 담당 38건"
              actions={
              <span className="pm-chip" style={{ background: "var(--c-success-bg)", color: "#166534", border: "1px solid #bbf7d0" }}>
                  <i className="fas fa-user-tag" style={{ fontSize: 9, marginRight: 4 }} />
                  영업담당자
                </span>
              } />
            
            <div className="pm-body" style={{ display: "flex", overflow: "hidden", position: "relative" }}>
              <div style={{ flex: 1, position: "relative", overflow: "hidden", background: "#eef1f4" }}>
                <MapBackground />
                {CUSTOMERS.slice(0, 5).map((c, i) =>
                <div key={c.id} style={{ position: "absolute", left: `${c.mapX}%`, top: `${c.mapY}%`, transform: "translate(-50%, -100%)" }}>
                    <svg width={i === 1 ? 26 : 20} height={i === 1 ? 32 : 26} viewBox="0 0 32 40" fill="none">
                      <path d="M16 0 C7 0 0 7 0 16 C0 26 16 40 16 40 C16 40 32 26 32 16 C32 7 25 0 16 0 Z" fill={STATUSES[c.status].color} stroke="#fff" strokeWidth="2" />
                      <circle cx="16" cy="15" r="5" fill="#fff" />
                    </svg>
                  </div>
                )}
                {/* mini info card */}
                <div style={{
                  position: "absolute", left: "44%", top: "26%",
                  transform: "translate(-50%, calc(-100% - 34px))",
                  background: "var(--c-surface)", border: "1px solid var(--c-border)",
                  borderRadius: 7, padding: "6px 9px", minWidth: 130,
                  boxShadow: "0 4px 12px rgba(0,0,0,0.10)",
                  fontSize: 10.5
                }}>
                  <div style={{ fontWeight: 600, fontSize: 11, display: "flex", alignItems: "center", gap: 5, marginBottom: 3 }}>
                    <span className="pm-dot" style={{ background: STATUSES.visited.color, width: 6, height: 6 }} />
                    한일전자
                  </div>
                  <div style={{ color: "var(--c-text-3)", fontSize: 9.5 }}>내 담당 · 방문 3회</div>
                </div>
                {/* legend */}
                <div style={{ position: "absolute", top: 8, left: 8, background: "rgba(255,255,255,0.96)", border: "1px solid var(--c-border)", borderRadius: 6, padding: "4px 8px", fontSize: 9.5, color: "var(--c-text-2)", display: "flex", gap: 8 }}>
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
                    <span className="pm-dot" style={{ width: 6, height: 6, background: STATUSES.existing.color }} />기존
                  </span>
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
                    <span className="pm-dot" style={{ width: 6, height: 6, background: STATUSES.visited.color }} />방문
                  </span>
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
                    <span className="pm-dot" style={{ width: 6, height: 6, background: STATUSES.prospect.color }} />예상
                  </span>
                </div>
                {/* FAB */}
                <button className="pm-fab" style={{ position: "absolute", right: 10, bottom: 10, padding: "8px 12px", fontSize: 11 }}>
                  <i className="fas fa-plus" /> 활동
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>);

  }

  return (
    <div style={{ width: "100%", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 18 }}>
      <div>
        <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 12 }}>
          <span style={{
            display: "inline-flex", alignItems: "center", gap: 6,
            fontFamily: "var(--font-text)", fontSize: 12, fontWeight: 600,
            color: "var(--ink)", padding: "5px 10px",
            background: "rgba(79,70,229,0.08)", border: "1px solid rgba(79,70,229,0.20)",
            borderRadius: 9999
          }}>
            <span style={{ width: 6, height: 6, borderRadius: 3, background: "#4f46e5" }} />
            관리자용 전사 대시보드
          </span>
        </div>
        <AdminMini />
      </div>
      <div>
        <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 12 }}>
          <span style={{
            display: "inline-flex", alignItems: "center", gap: 6,
            fontFamily: "var(--font-text)", fontSize: 12, fontWeight: 600,
            color: "var(--ink)", padding: "5px 10px",
            background: "rgba(22,163,74,0.08)", border: "1px solid rgba(22,163,74,0.22)",
            borderRadius: 9999
          }}>
            <span style={{ width: 6, height: 6, borderRadius: 3, background: "#16a34a" }} />
            영업담당자용 거래처 관리
          </span>
        </div>
        <SalesMini />
      </div>
    </div>);

}

// =============================================================================
// PhoneMockup — real mobile UI with bottom nav + FAB
// =============================================================================
function PhoneMockup() {
  return (
    <div className="pm-mobile">
      <div className="pm-mobile-notch" />
      <div className="pm pm-mobile-screen">
        <div className="pm-mobile-topbar">
          <div>
            <div style={{ fontSize: 13, fontWeight: 600 }}>지도</div>
            <div style={{ fontSize: 9.5, color: "var(--c-text-4)", marginTop: 1 }}>내 담당 38건</div>
          </div>
          <div style={{ width: 30, height: 30, borderRadius: "50%", background: "var(--c-brand-100)", color: "var(--c-brand-700)", display: "grid", placeItems: "center", fontWeight: 700, fontSize: 11 }}>김</div>
        </div>
        <div className="pm-mobile-content">
          <MapBackground />
          {/* pins (a few) */}
          {CUSTOMERS.slice(0, 5).map((c, i) =>
          <div key={c.id} style={{ position: "absolute", left: `${c.mapX}%`, top: `${c.mapY}%`, transform: "translate(-50%, -100%)", zIndex: 2 }}>
              <svg width={i === 2 ? 28 : 22} height={i === 2 ? 36 : 28} viewBox="0 0 32 40" fill="none">
                <path d="M16 0 C7 0 0 7 0 16 C0 26 16 40 16 40 C16 40 32 26 32 16 C32 7 25 0 16 0 Z" fill={STATUSES[c.status].color} stroke="#fff" strokeWidth="2" />
                <circle cx="16" cy="15" r="5" fill="#fff" />
              </svg>
            </div>
          )}
          {/* bottom sheet w/ active customer */}
          <div style={{
            position: "absolute", bottom: 0, left: 0, right: 0,
            background: "var(--c-surface)", borderTopLeftRadius: 16, borderTopRightRadius: 16,
            boxShadow: "0 -4px 20px rgba(0,0,0,0.08)", padding: "12px 14px 14px",
            zIndex: 3
          }}>
            <div style={{ width: 32, height: 3, background: "var(--c-border-strong)", borderRadius: 2, margin: "0 auto 10px" }} />
            <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }}>
              <span className="pm-dot" style={{ background: STATUSES.existing.color }} />
              <span style={{ fontSize: 13, fontWeight: 600 }}>성진금속(주)</span>
            </div>
            <div style={{ fontSize: 10.5, color: "var(--c-text-3)", marginBottom: 8 }}>서울 강남구 봉은사로 · 방문 22회</div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
              <button className="pm-btn brand sm" style={{ width: "100%", height: 30 }}><i className="fas fa-plus" /> 활동 등록</button>
              <button className="pm-btn default sm" style={{ width: "100%", height: 30 }}>상세 보기</button>
            </div>
          </div>
          <button className="pm-fab" style={{ bottom: 132 }}><i className="fas fa-plus" /> 영업활동</button>
        </div>
        <nav className="pm-mobile-nav">
          {[
          { icon: "fa-map", label: "지도", active: true },
          { icon: "fa-building", label: "거래처" },
          { icon: "fa-clipboard-list", label: "영업활동" },
          { icon: "fa-chart-pie", label: "대시보드" },
          { icon: "fa-bars", label: "더보기" }].
          map((n, i) =>
          <div className={`pm-mobile-nav-item ${n.active ? "active" : ""}`} key={i}>
              <i className={`fas ${n.icon}`} />
              <span>{n.label}</span>
            </div>
          )}
        </nav>
      </div>
    </div>);

}

// =============================================================================
// ExcelMockup — customer list table (the "기존 엑셀 그대로 옮겨오기" result)
// =============================================================================
function ExcelMockup() {
  return (
    <div className="pm" style={{ aspectRatio: "16/10", minHeight: 380 }}>
      <div className="pm-shell">
        <Sidebar active="customers" role="admin" iconOnly />
        <div className="pm-main">
          <Topbar
            title="거래처 목록"
            subtitle="전체 178건"
            actions={
            <>
                <button className="pm-btn default"><i className="fas fa-file-import" /> 엑셀</button>
                <button className="pm-btn brand"><i className="fas fa-plus" /> 등록</button>
              </>
            } />
          
          <div className="pm-body" style={{ padding: 14, overflow: "hidden" }}>
            <div className="pm-table-wrap">
              <div className="pm-table-tool">
                <div style={{ position: "relative", flex: 1, minWidth: 0 }}>
                  <i className="fas fa-search" style={{ position: "absolute", left: 9, top: "50%", transform: "translateY(-50%)", color: "var(--c-text-4)", fontSize: 11 }} />
                  <input className="pm-input" style={{ paddingLeft: 28 }} placeholder="거래처 검색" readOnly />
                </div>
                <select className="pm-select" style={{ width: 100, flexShrink: 0 }}><option>전체 상태</option></select>
                <span style={{ fontSize: 11, color: "var(--c-text-3)", whiteSpace: "nowrap", flexShrink: 0 }}>178건</span>
              </div>
              <table className="pm-table">
                <thead>
                  <tr>
                    <th style={{ width: "36%" }}>거래처</th>
                    <th style={{ width: "20%" }}>업종</th>
                    <th style={{ width: "22%" }}>상태</th>
                    <th style={{ width: "16%" }}>담당자</th>
                    <th className="num" style={{ width: "6%" }}>방문</th>
                  </tr>
                </thead>
                <tbody>
                  {CUSTOMERS.slice(0, 6).map((c, i) => {
                    const owners = ["김민수", "이지은", "박지훈", "최서연", "정우진", "김민수"];
                    return (
                      <tr key={c.id}>
                        <td>
                          <div className="pm-row-pri" style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{c.name}</div>
                          <div className="pm-row-sec" style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{c.region}</div>
                        </td>
                        <td className="muted" style={{ whiteSpace: "nowrap" }}>{c.industry}</td>
                        <td><StatusPill status={c.status} /></td>
                        <td style={{ whiteSpace: "nowrap" }}>
                          <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
                            <span className="pm-avatar" style={{ width: 20, height: 20, fontSize: 9 }}>{owners[i][0]}</span>
                            <span>{owners[i]}</span>
                          </span>
                        </td>
                        <td className="num">{c.visits}</td>
                      </tr>);

                  })}
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>
    </div>);

}

// =============================================================================
// CustomFieldMockup — admin custom field config table
// =============================================================================
function CustomFieldMockup() {
  const fields = [
  { name: "사업자번호", key: "biz_no", type: "텍스트", required: true, active: true },
  { name: "매출 규모", key: "revenue_band", type: "선택", required: false, active: true, options: "1억 이하 · 1~10억 · 10억 초과" },
  { name: "신용등급", key: "credit_grade", type: "선택", required: false, active: true, options: "AAA · AA · A · B · C" },
  { name: "계약 시작일", key: "contract_at", type: "날짜", required: false, active: true },
  { name: "VIP 여부", key: "is_vip", type: "체크박스", required: false, active: false },
  { name: "주거래은행", key: "bank_name", type: "텍스트", required: false, active: true }];

  const typeColors = {
    "텍스트": { bg: "#eef2ff", color: "#4338ca", bd: "#dbe1ff" },
    "선택": { bg: "#fce7f3", color: "#be185d", bd: "#fbcfe8" },
    "날짜": { bg: "#dcfce7", color: "#15803d", bd: "#bbf7d0" },
    "체크박스": { bg: "#fef9c3", color: "#a16207", bd: "#fde68a" }
  };
  return (
    <div className="pm" style={{ aspectRatio: "16/10", minHeight: 460 }}>
      <div className="pm-shell">
        <Sidebar active="custom-fields" role="admin" />
        <div className="pm-main">
          <Topbar
            title="커스텀 필드"
            subtitle="회사 고유의 항목을 직접 정의합니다"
            actions={<button className="pm-btn brand"><i className="fas fa-plus" /> 필드 추가</button>} />
          
          <div className="pm-body" style={{ padding: 16, overflow: "hidden" }}>
            <div className="pm-table-wrap">
              <table className="pm-table">
                <thead>
                  <tr>
                    <th style={{ width: 28 }} />
                    <th>필드명</th>
                    <th>키</th>
                    <th>유형</th>
                    <th>필수</th>
                    <th>옵션</th>
                    <th>상태</th>
                    <th style={{ width: 60 }} />
                  </tr>
                </thead>
                <tbody>
                  {fields.map((f, i) => {
                    const c = typeColors[f.type] || typeColors["텍스트"];
                    return (
                      <tr key={i}>
                        <td style={{ color: "var(--c-text-4)" }}><i className="fas fa-grip-vertical" style={{ fontSize: 11 }} /></td>
                        <td><div className="pm-row-pri">{f.name}</div></td>
                        <td className="muted mono" style={{ fontSize: 11 }}>{f.key}</td>
                        <td>
                          <span className="pm-chip" style={{ background: c.bg, color: c.color, border: `1px solid ${c.bd}` }}>{f.type}</span>
                        </td>
                        <td>
                          {f.required ?
                          <span style={{ color: "var(--c-danger)", fontSize: 11, fontWeight: 600 }}>필수</span> :
                          <span style={{ color: "var(--c-text-4)", fontSize: 11 }}>—</span>}
                        </td>
                        <td className="muted" style={{ fontSize: 10.5 }}>{f.options || "—"}</td>
                        <td>
                          <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: 11 }}>
                            <span style={{ width: 26, height: 14, borderRadius: 7, background: f.active ? "var(--c-brand)" : "var(--c-border-strong)", position: "relative" }}>
                              <span style={{ position: "absolute", top: 1, left: f.active ? 13 : 1, width: 12, height: 12, borderRadius: "50%", background: "#fff", transition: "left .15s" }} />
                            </span>
                            <span style={{ color: f.active ? "var(--c-text)" : "var(--c-text-4)" }}>{f.active ? "활성" : "비활성"}</span>
                          </span>
                        </td>
                        <td>
                          <button className="pm-btn ghost sm" style={{ padding: 0, width: 22, height: 22 }}><i className="fas fa-ellipsis-h" style={{ fontSize: 10 }} /></button>
                        </td>
                      </tr>);

                  })}
                </tbody>
              </table>
            </div>

            <div style={{ marginTop: 12, padding: "10px 12px", background: "var(--c-info-bg, #f0f9ff)", border: "1px solid #bae6fd", borderRadius: 8, display: "flex", gap: 10, alignItems: "flex-start" }}>
              <i className="fas fa-info-circle" style={{ color: "#0284c7", fontSize: 13, marginTop: 1 }} />
              <div style={{ fontSize: 11.5, color: "#0c4a6e", lineHeight: 1.55 }}>
                엑셀로 거래처를 일괄등록할 때 <span className="mono" style={{ background: "#fff", border: "1px solid #bae6fd", padding: "0 4px", borderRadius: 3, color: "#0284c7" }}>biz_no</span>·<span className="mono" style={{ background: "#fff", border: "1px solid #bae6fd", padding: "0 4px", borderRadius: 3, color: "#0284c7" }}>revenue_band</span>처럼 키가 동일한 컬럼이 있으면 자동으로 매핑됩니다.
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>);

}

// =============================================================================
// PhoneActivityMockup — mobile activity registration modal + follow-up section
// (used in the Mobile tile to avoid repeating the map screen)
// =============================================================================
function PhoneActivityMockup() {
  return (
    <div className="pm-mobile">
      <div className="pm-mobile-notch" />
      <div className="pm pm-mobile-screen" style={{ background: "rgba(24,24,27,0.55)" }}>
        {/* dimmed map underneath (for depth) */}
        <div style={{ position: "absolute", inset: 0, opacity: 0.35, filter: "blur(1px)" }}>
          <MapBackground />
        </div>

        {/* bottom sheet modal */}
        <div style={{
          position: "absolute", left: 0, right: 0, bottom: 0,
          background: "var(--c-surface)",
          borderTopLeftRadius: 18, borderTopRightRadius: 18,
          boxShadow: "0 -8px 24px rgba(0,0,0,0.18)",
          padding: "14px 14px 16px",
          maxHeight: "92%",
          display: "flex", flexDirection: "column",
          overflow: "hidden"
        }}>
          <div style={{ width: 32, height: 3, background: "var(--c-border-strong)", borderRadius: 2, margin: "0 auto 12px", flexShrink: 0 }} />

          {/* header */}
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 12 }}>
            <div style={{ width: 24, height: 24, borderRadius: 5, background: "var(--c-brand-50)", color: "var(--c-brand)", display: "grid", placeItems: "center", flexShrink: 0 }}>
              <i className="fas fa-clipboard-list" style={{ fontSize: 11 }} />
            </div>
            <div style={{ fontSize: 13, fontWeight: 600, flex: 1 }}>영업활동 등록</div>
            <i className="fas fa-times" style={{ color: "var(--c-text-4)", fontSize: 12 }} />
          </div>

          {/* form */}
          <div style={{ overflowY: "auto", flex: 1 }}>
            <div style={{ marginBottom: 10 }}>
              <div style={{ fontSize: 10, fontWeight: 500, color: "var(--c-text)", marginBottom: 4 }}>거래처 <span style={{ color: "var(--c-danger)" }}>*</span></div>
              <div className="pm-input" style={{ display: "flex", alignItems: "center", justifyContent: "space-between", height: 32, fontSize: 11.5 }}>
                <span style={{ fontWeight: 500 }}>성진금속(주)</span>
                <i className="fas fa-chevron-down" style={{ color: "var(--c-text-4)", fontSize: 10 }} />
              </div>
            </div>

            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 10 }}>
              <div>
                <div style={{ fontSize: 10, fontWeight: 500, color: "var(--c-text)", marginBottom: 4 }}>활동일시 <span style={{ color: "var(--c-danger)" }}>*</span></div>
                <div className="pm-input" style={{ display: "flex", alignItems: "center", gap: 5, height: 32, fontSize: 11 }}>
                  <i className="fas fa-calendar-alt" style={{ color: "var(--c-text-4)", fontSize: 10 }} />
                  <span>오늘 14:20</span>
                </div>
              </div>
              <div>
                <div style={{ fontSize: 10, fontWeight: 500, color: "var(--c-text)", marginBottom: 4 }}>활동유형 <span style={{ color: "var(--c-danger)" }}>*</span></div>
                <div className="pm-input" style={{ display: "flex", alignItems: "center", justifyContent: "space-between", height: 32, fontSize: 11.5 }}>
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
                    <span style={{ width: 14, height: 14, borderRadius: 3, background: ACTIVITY_TYPES.visit.bg, color: ACTIVITY_TYPES.visit.color, display: "grid", placeItems: "center" }}>
                      <i className="fas fa-map-marker-alt" style={{ fontSize: 8 }} />
                    </span>
                    방문
                  </span>
                  <i className="fas fa-chevron-down" style={{ color: "var(--c-text-4)", fontSize: 10 }} />
                </div>
              </div>
            </div>

            <div style={{ marginBottom: 10 }}>
              <div style={{ fontSize: 10, fontWeight: 500, color: "var(--c-text)", marginBottom: 4 }}>활동내용 <span style={{ color: "var(--c-danger)" }}>*</span></div>
              <div className="pm-input" style={{ height: 52, padding: "7px 9px", fontSize: 11, lineHeight: 1.45, color: "var(--c-text)", whiteSpace: "normal", display: "block" }}>
                신규 거래 협의, 견적서 요청받음. 다음 주 화요일까지 회신 필요.
              </div>
            </div>

            {/* follow-up section */}
            <div style={{
              padding: 10,
              border: "1px solid var(--c-brand-100)",
              borderRadius: 7,
              background: "var(--c-brand-50)"
            }}>
              <div style={{ display: "flex", alignItems: "center", gap: 7, fontSize: 11.5, color: "var(--c-text)", marginBottom: 9 }}>
                <span style={{ width: 13, height: 13, borderRadius: 3, background: "var(--c-brand)", display: "grid", placeItems: "center", flexShrink: 0 }}>
                  <i className="fas fa-check" style={{ color: "#fff", fontSize: 8 }} />
                </span>
                <span style={{ fontWeight: 600 }}>다음에 할 일도 등록</span>
              </div>

              <div style={{ marginBottom: 8 }}>
                <div style={{ fontSize: 9.5, fontWeight: 500, color: "var(--c-text-2)", marginBottom: 3 }}>다음 액션 제목</div>
                <div className="pm-input" style={{ height: 28, fontSize: 11, background: "#fff" }}>
                  <span style={{ display: "flex", alignItems: "center", height: "100%" }}>견적서 재전달 + 단가 협의</span>
                </div>
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 7 }}>
                <div>
                  <div style={{ fontSize: 9.5, fontWeight: 500, color: "var(--c-text-2)", marginBottom: 3 }}>예정일</div>
                  <div className="pm-input" style={{ display: "flex", alignItems: "center", gap: 5, height: 28, fontSize: 11, background: "#fff" }}>
                    <i className="fas fa-calendar" style={{ color: "var(--c-brand)", fontSize: 9 }} />
                    <span>5월 22일</span>
                  </div>
                </div>
                <div>
                  <div style={{ fontSize: 9.5, fontWeight: 500, color: "var(--c-text-2)", marginBottom: 3 }}>알림</div>
                  <div className="pm-input" style={{ display: "flex", alignItems: "center", gap: 5, height: 28, fontSize: 11, background: "#fff" }}>
                    <i className="fas fa-bell" style={{ color: "var(--c-warning)", fontSize: 9 }} />
                    <span>당일 09:00</span>
                  </div>
                </div>
              </div>
            </div>
          </div>

          {/* footer buttons */}
          <div style={{ display: "flex", gap: 7, paddingTop: 12, borderTop: "1px solid var(--c-divider)", marginTop: 10, flexShrink: 0 }}>
            <button className="pm-btn default" style={{ flex: "0 0 36%", height: 34 }}>취소</button>
            <button className="pm-btn brand" style={{ flex: 1, height: 34, fontSize: 12 }}>
              <i className="fas fa-check" /> 등록하기
            </button>
          </div>
        </div>
      </div>
    </div>);

}

// =============================================================================
// KakaoLoginMockup — mobile frame showing the actual login screen (kakao CTA)
// =============================================================================
function KakaoLoginMockup() {
  return (
    <div className="pm-mobile">
      <div className="pm-mobile-notch" />
      <div className="pm pm-mobile-screen" style={{ background: "var(--c-bg)" }}>
        {/* faux status bar spacing */}
        <div style={{ height: 36, flexShrink: 0 }} />

        {/* login card centered */}
        <div style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", padding: "0 18px" }}>
          <div style={{
            width: "100%",
            background: "var(--c-surface)",
            border: "1px solid var(--c-border)",
            borderRadius: 14,
            padding: "26px 22px",
            boxShadow: "0 6px 18px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)"
          }}>
            {/* logo lockup */}
            <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 22 }}>
              <PmKnockMark size={34} radius={8} />
              <div>
                <div style={{ fontSize: 15, fontWeight: 700, color: "var(--c-text)", letterSpacing: "-0.01em" }}>노킷</div>
                <div style={{ fontSize: 10, color: "var(--c-text-4)", marginTop: 1 }}>지도 기반 거래처·방문 관리</div>
              </div>
            </div>

            <div style={{ fontSize: 17, fontWeight: 700, color: "var(--c-text)", marginBottom: 6, letterSpacing: "-0.01em" }}>로그인</div>
            <div style={{ fontSize: 11, color: "var(--c-text-3)", lineHeight: 1.6, marginBottom: 18 }}>
              카카오 계정으로 로그인할 수 있습니다.<br />
              관리자에게 초대받은 계정만 접근할 수 있습니다.
            </div>

            {/* kakao button */}
            <div style={{
              display: "flex", alignItems: "center", justifyContent: "center", gap: 8,
              width: "100%", padding: "12px 16px",
              background: "#FEE500", color: "#191919",
              borderRadius: 8, fontSize: 13, fontWeight: 700,
              boxShadow: "0 2px 6px rgba(254,229,0,0.4)"
            }}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
                <path fillRule="evenodd" clipRule="evenodd" d="M12 3C7.03 3 3 6.14 3 10.01c0 2.51 1.66 4.72 4.17 5.98L6.1 19.5c-.08.32.33.57.6.37l4.13-2.74c.38.04.77.06 1.17.06 4.97 0 9-3.14 9-7.01C21 6.14 16.97 3 12 3z" fill="#191919" />
              </svg>
              카카오로 로그인
            </div>

            {/* footer */}
            <div style={{
              marginTop: 16, paddingTop: 14,
              borderTop: "1px solid var(--c-surface-3)",
              fontSize: 9.5, color: "var(--c-text-4)",
              textAlign: "center", lineHeight: 1.6
            }}>
              등록되지 않은 계정은 로그인할 수 없습니다.<br />
              계정 초대가 필요하면 관리자에게 문의하세요.
            </div>
          </div>
        </div>

        {/* faux home indicator */}
        <div style={{ height: 18, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
          <div style={{ width: 110, height: 4, borderRadius: 2, background: "rgba(0,0,0,0.18)" }} />
        </div>
      </div>
    </div>);

}

// =============================================================================
// Exports
// =============================================================================
Object.assign(window, {
  MapMockup, DashboardMockup, PermissionMockup, PhoneMockup, PhoneActivityMockup, KakaoLoginMockup, ExcelMockup, CustomFieldMockup
});