// ── ورودی عدد با فرمت تومان ────────────────────────────────────
const MoneyInput = ({ value, onChange, placeholder, style, className }) => {
  const { fa } = window.SB_DATA;
  const [focused, setFocused] = React.useState(false);
  const [raw, setRaw] = React.useState(''); // همیشه رقمِ خامِ انگلیسی، بدونِ جداکننده
  const inputRef = React.useRef(null);
  const pendingCaret = React.useRef(null);

  const toWestern = s => s.replace(/[۰-۹]/g, d => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d));
  const isDigitOrDot = ch => /[0-9۰-۹.]/.test(ch);
  const fmtLive = s => {
    if (!s) return '';
    const [intPart, decPart] = s.split('.');
    const withSep = (intPart || '').replace(/\B(?=(\d{3})+(?!\d))/g, '،');
    return fa(withSep + (decPart !== undefined ? '.' + decPart : ''));
  };
  const fmt = v => !v ? '' : fmtLive(String(Math.round(v)));

  const onFocus = () => { setFocused(true); setRaw(value ? String(Math.round(value)) : ''); };
  const onBlur  = () => { setFocused(false); onChange(parseFloat(raw.replace(/[^0-9.]/g,'')) || 0); };
  const onKey   = e => {
    if (!/^[0-9.]$/.test(e.key) && !['Backspace','Delete','ArrowLeft','ArrowRight','Tab'].includes(e.key)) e.preventDefault();
  };
  // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): حینِ تایپ هم باید جداکننده‌یِ هزارگان نشون داده بشه (نه فقط
  // بعدِ خروج از فیلد). چالش: بعدِ هر رقم، اضافه/حذف‌شدنِ جداکننده طولِ رشته رو عوض می‌کنه —
  // اگه مکان‌نما رو دستی برنگردونیم، مرورگر می‌بره ته رشته (تایپِ وسطِ عدد غیرممکن می‌شه).
  // راه‌حل: تعدادِ کاراکترِ «رقم یا نقطه» قبلِ مکان‌نما رو قبل از فرمت نگه می‌داریم، بعد از
  // رندرِ رشته‌ی تازه‌فرمت‌شده همون تعداد رو پیدا می‌کنیم و مکان‌نما رو دقیقاً همون‌جا می‌ذاریم.
  const onChangeInput = e => {
    const el = e.target;
    const caretPos = el.selectionStart ?? el.value.length;
    let cnt = 0;
    for (let i = 0; i < caretPos; i++) if (isDigitOrDot(el.value[i])) cnt++;
    pendingCaret.current = cnt;
    setRaw(toWestern(el.value).replace(/[^0-9.]/g, ''));
  };
  React.useLayoutEffect(() => {
    if (!focused || pendingCaret.current == null || !inputRef.current) return;
    const target = pendingCaret.current;
    pendingCaret.current = null;
    if (target === 0) { inputRef.current.setSelectionRange(0, 0); return; }
    const val = inputRef.current.value;
    let cnt = 0, pos = val.length;
    for (let i = 0; i < val.length; i++) {
      if (isDigitOrDot(val[i])) { cnt++; if (cnt === target) { pos = i + 1; break; } }
    }
    inputRef.current.setSelectionRange(pos, pos);
  }, [raw, focused]);

  return (
    <input ref={inputRef} className={className || 'sw-inp'}
      style={{ direction:'ltr', textAlign:'left', ...style }}
      value={focused ? fmtLive(raw) : (value ? fmt(value) : '')}
      placeholder={placeholder || '۰'}
      onFocus={onFocus} onBlur={onBlur} onKeyDown={onKey}
      onChange={onChangeInput} />
  );
};

// ── تارگت‌گذاری فروش — ویزارد ۵ مرحله‌ای ─────────────────────
const SalesTargets = () => {
  const { fa } = window.SB_DATA;
  const toast = (window.SB_UI?.useToast?.()) || { show: () => {} };

  // ─── CSS ────────────────────────────────────────────────────────
  useEffect(() => {
    const SID = 'st-wiz2-css';
    if (document.getElementById(SID)) return;
    const el = document.createElement('style');
    el.id = SID; el.textContent = `
.sw{direction:rtl;font-family:inherit;max-width:1100px}
.sw-steps{display:flex;align-items:flex-start;margin-bottom:28px;position:relative;gap:0}
.sw-steps::before{content:'';position:absolute;top:18px;right:28px;left:28px;height:2px;background:rgba(255,255,255,0.06);z-index:0}
.sw-step{display:flex;flex-direction:column;align-items:center;gap:5px;flex:1;position:relative;z-index:1;cursor:default}
.sw-step.clickable{cursor:pointer}
.sw-dot{width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:800;border:2px solid rgba(255,255,255,0.08);background:#0d1219;transition:all .2s}
.sw-dot.done{background:#122a1d;border-color:#34d399;color:#34d399}
.sw-dot.active{background:#141830;border-color:#818cf8;color:#a5b4fc;box-shadow:0 0 0 4px rgba(129,140,248,0.12)}
.sw-dot.idle{color:#334155}
.sw-step-lbl{font-size:10px;font-weight:700;white-space:nowrap;text-align:center}
.sw-step.active .sw-step-lbl{color:#a5b4fc}
.sw-step.done  .sw-step-lbl{color:#34d399}
.sw-step.idle  .sw-step-lbl{color:#334155}
.sw-card{background:#121823;border:1px solid rgba(255,255,255,0.07);border-radius:16px;padding:22px 24px;margin-bottom:14px}
.sw-title{font-size:17px;font-weight:800;margin-bottom:3px}
.sw-sub{font-size:12px;color:#64748b;margin-bottom:18px;line-height:1.6}
.sw-field{margin-bottom:14px}
.sw-lbl{font-size:11px;color:#64748b;font-weight:700;margin-bottom:5px}
.sw-inp{background:#0d1219;border:1px solid rgba(255,255,255,0.09);border-radius:9px;padding:10px 14px;color:#e6eaf2;font-size:14px;font-weight:700;font-family:inherit;outline:none;width:100%;box-sizing:border-box;transition:border-color .15s}
.sw-inp:focus{border-color:rgba(129,140,248,0.45)}
.sw-inp-sm{font-size:12px;padding:7px 10px}
.sw-inp-xs{font-size:12px;padding:5px 8px}
.sw-grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.sw-grid3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px}
.sw-grid4{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:10px}
.sw-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
/* ── سبک‌کارت ── */
.sw-model-card{border-radius:14px;padding:18px 20px;border:2px solid rgba(255,255,255,0.07);background:#0a1017;cursor:pointer;transition:all .18s;position:relative;overflow:hidden}
.sw-model-card:hover{border-color:rgba(255,255,255,0.15)}
.sw-model-card.sel-webinar{border-color:#818cf8;background:rgba(129,140,248,0.07)}
.sw-model-card.sel-linear{border-color:#34d399;background:rgba(52,211,153,0.07)}
.sw-model-card.sel-campaign{border-color:#f472b6;background:rgba(244,114,182,0.07)}
.sw-model-card.sel-content{border-color:#fbbf24;background:rgba(251,191,36,0.07)}
.sw-model-icon{font-size:32px;margin-bottom:10px}
.sw-model-name{font-size:15px;font-weight:800;margin-bottom:4px}
.sw-model-desc{font-size:11px;color:#64748b;line-height:1.6}
.sw-model-check{position:absolute;top:12px;left:12px;width:20px;height:20px;border-radius:50%;border:2px solid rgba(255,255,255,0.15);display:flex;align-items:center;justify-content:center;font-size:10px;transition:all .15s}
.sel-webinar  .sw-model-check{background:#818cf8;border-color:#818cf8;color:#fff}
.sel-linear   .sw-model-check{background:#34d399;border-color:#34d399;color:#fff}
.sel-campaign .sw-model-check{background:#f472b6;border-color:#f472b6;color:#fff}
.sel-content  .sw-model-check{background:#fbbf24;border-color:#fbbf24;color:#fff}
/* ── نرخ‌باکس ── */
.sw-rate-box{background:#0a1017;border:1px solid rgba(255,255,255,0.07);border-radius:11px;padding:14px 16px}
.sw-rate-box-title{font-size:11px;font-weight:800;margin-bottom:10px;display:flex;align-items:center;gap:6px}
/* ── جدول ── */
.sw-tbl{width:100%;border-collapse:separate;border-spacing:0 5px}
.sw-tbl th{font-size:10px;color:#475569;font-weight:700;padding:5px 8px;text-align:center;white-space:nowrap}
.sw-tbl th:first-child{text-align:right}
.sw-tbl td{background:#0d1320;padding:9px 7px;text-align:center;vertical-align:middle;font-size:12px}
.sw-tbl tr td:first-child{border-radius:10px 0 0 10px;padding-right:12px;text-align:right}
.sw-tbl tr td:last-child{border-radius:0 10px 10px 0}
.sw-tbl tfoot td{background:#101c12;border-top:1px solid rgba(255,255,255,0.06)}
.sw-rate{background:#0a1017;border:1px solid rgba(255,255,255,0.07);border-radius:7px;padding:5px 7px;color:#e2e8f0;font-size:12px;font-weight:700;font-family:inherit;outline:none;width:68px;text-align:center;-moz-appearance:textfield}
.sw-rate::-webkit-inner-spin-button,.sw-rate::-webkit-outer-spin-button{-webkit-appearance:none}
.sw-rate:focus{border-color:rgba(129,140,248,0.4)}
/* ── nav ── */
.sw-nav{display:flex;justify-content:space-between;align-items:center;margin-top:20px;padding-top:16px;border-top:1px solid rgba(255,255,255,0.06)}
.sw-btn{display:inline-flex;align-items:center;gap:7px;border-radius:10px;padding:10px 20px;font-size:13px;font-weight:700;cursor:pointer;border:none;font-family:inherit;transition:opacity .15s;white-space:nowrap}
.sw-btn:hover{opacity:.85}.sw-btn:disabled{opacity:.4;cursor:not-allowed}
.sw-btn-p{background:rgba(129,140,248,0.18);color:#c7cdfa;border:1px solid rgba(129,140,248,0.3)}
.sw-btn-g{background:rgba(52,211,153,0.15);color:#5ee9b5;border:1px solid rgba(52,211,153,0.3)}
.sw-btn-ghost{background:transparent;color:#64748b;border:1px solid rgba(255,255,255,0.08)}
.sw-btn-sm{padding:6px 12px;font-size:11px;border-radius:8px}
/* ── kpi ── */
.sw-kpi{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:8px;margin-bottom:14px}
.sw-kpi-box{background:#0d1219;border:1px solid rgba(255,255,255,0.07);border-radius:11px;padding:12px 14px;text-align:center}
.sw-kpi-lbl{font-size:9px;color:#64748b;font-weight:700;margin-bottom:4px}
.sw-kpi-val{font-size:17px;font-weight:800}
.sw-bar-wrap{height:7px;border-radius:4px;background:rgba(255,255,255,0.06);overflow:hidden;margin-top:6px}
.sw-bar{height:100%;border-radius:4px;transition:width .5s}
.sw-av{width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;flex:none}
.sw-insight{display:flex;gap:8px;align-items:flex-start;background:rgba(129,140,248,0.07);border:1px solid rgba(129,140,248,0.16);border-radius:10px;padding:10px 13px;font-size:12px;line-height:1.7;color:#c4cbd8;margin-top:12px}
.sw-tag{display:inline-flex;align-items:center;font-size:10px;font-weight:700;border-radius:6px;padding:2px 8px}
.sw-g{color:#5ee9b5;background:rgba(52,211,153,0.12);border:1px solid rgba(52,211,153,0.22)}
.sw-b{color:#93c5fd;background:rgba(96,165,250,0.12);border:1px solid rgba(96,165,250,0.22)}
.sw-y{color:#fcd66b;background:rgba(251,191,36,0.12);border:1px solid rgba(251,191,36,0.22)}
.sw-pk{color:#f9a8d4;background:rgba(244,114,182,0.12);border:1px solid rgba(244,114,182,0.22)}
.sw-v{color:#c4b5fd;background:rgba(167,139,250,0.12);border:1px solid rgba(167,139,250,0.22)}
.sw-divider{height:1px;background:rgba(255,255,255,0.05);margin:14px 0}
.sw-prod-dot{width:8px;height:8px;border-radius:50%;display:inline-block;flex:none}
/* ── real-data badge ── */
.sw-real{display:inline-flex;align-items:center;gap:3px;font-size:9px;font-weight:700;color:#34d399;background:rgba(52,211,153,0.1);border:1px solid rgba(52,211,153,0.2);border-radius:4px;padding:1px 5px;white-space:nowrap}
.sw-nodata{font-size:9px;color:#475569;margin-top:2px}
.sw-rate-real{border-color:rgba(52,211,153,0.35)!important;color:#6ee7b7!important}
@media(max-width:700px){.sw-grid2,.sw-grid3,.sw-grid4{grid-template-columns:1fr}}
    `;
    document.head.appendChild(el);
  }, []);

  const COLORS = ['#818cf8','#34d399','#f472b6','#fb923c','#a78bfa','#38bdf8','#4ade80','#fbbf24','#f87171','#c084fc'];
  // قانونِ کاربر (۲۰۲۶-۰۷-۲۹): قبلاً curPeriod همیشه «همینِ ماه» بود — حالا با انتخاب‌گرِ
  // ماه (پیکان‌هایِ ماهِ قبل/بعد) قابلِ تغییره تا بشه از حالا برایِ ماه‌هایِ آینده هم تارگت چید.
  // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): «period» قبلاً ماهِ میلادی بود با یه برچسبِ تقریبیِ شمسی —
  // چون ماه‌هایِ شمسی و میلادی رويِ هم نمی‌افتن، همیشه گمراه‌کننده بود (مثلاً «ماهِ جاری» رو
  // مرداد نشون می‌داد درحالی‌که واقعاً شهریور بود). حالا period خودش مستقیماً یه ماهِ شمسیِ
  // کامله («۱۴۰۵-۰۶» = ۱ تا ۳۰/۳۱ شهریور) — نه فقط برچسب، خودِ بازه‌یِ ذخیره/فیلتر هم شمسیه.
  const [periodOffset, setPeriodOffset] = useState(0);
  const { start: periodDate, end: periodEndDate, jy, jm } = jalaliMonthRange(new Date(), periodOffset);
  const curPeriod = `${jy}-${String(jm).padStart(2, '0')}`;
  const periodLabelFa = `${JALALI_MONTHS[jm - 1]} ${fa(String(jy))}`;
  const hdrs = { 'Content-Type':'application/json', Authorization:`Bearer ${localStorage.getItem(window.TOKEN_KEY)}` };
  const api = (path, opts={}) => fetch('/api/market'+path, {headers:hdrs,...opts,body:opts.body?JSON.stringify(opts.body):undefined}).then(r=>r.json());

  const fnum  = v => (!v&&v!==0)?'—':fa(Math.round(v).toLocaleString('en').replace(/,/g,'،'));
  const fmoney= v => !v?'—':fnum(v)+' تومان';
  const fp    = v => fa(+(+v||0).toFixed(1))+'٪';

  // ─── State ─────────────────────────────────────────────────────
  const [step,    setStep]    = useState(1);
  const [loading, setLoading] = useState(true);
  const [saving,  setSaving]  = useState(false);
  // قانونِ کاربر (۲۰۲۶-۰۷-۲۹): تأییدِ قابلِ‌مشاهده‌یِ ذخیره‌شدن + قابلیتِ ویرایش/حذف/شروعِ دوباره
  const [savedThisPeriod, setSavedThisPeriod] = useState(false);
  const [deleting, setDeleting] = useState(false);
  const [prods,   setProds]   = useState([]);
  const [sellers, setSellers] = useState([]);

  // گام ۱: هدف
  const [target,  setTarget]  = useState(0);

  // گام ۲: سبک فروش — Set از 'webinar'|'linear'|'campaign'
  const [models,  setModels]  = useState(new Set(['linear']));

  // نرخ‌های پیش‌فرض هر مدل (قابل ویرایش در گام ۲)
  const [webinarRates, setWebinarRates] = useState({ attend_rate:18.8, stay_rate:46.7, conv_rate:17.8 });
  const [linearRates,  setLinearRates]  = useState({ sales_conv:25, sec_conv:80, work_days:22 });
  const [campaignCfg,  setCampaignCfg]  = useState({ budget:0, cpl:0, lead_conv:5 });
  const [contentCfg,   setContentCfg]   = useState({ target_count:0, lead_per_content:0, content_conv:5 });

  // گام ۳: محصولات
  const [pCfg, setPCfg] = useState({});

  // گام ۴: فروشندگان
  const [sCfg,     setSCfg]     = useState({});
  // آمار واقعی هر فروشنده از تاریخچه: sellerId → { conv_rate, sec_conv, avg_deal, sample }
  const [realStats, setRealStats] = useState({});
  // نرخِ کانورتِ پیش‌فرض برایِ فروشنده‌یِ بدونِ سابقه — قابلِ‌تنظیم از قوانین › محاسبه‌ی نرخ کانورت/پاسخ فروشنده‌ها
  const [defaultConvRate, setDefaultConvRate] = useState(25);
  // بافرِ لیدِ نیاز (٪) — قابلِ‌تنظیم از همون‌جا، پیش‌فرض ۲۰٪
  const [leadBufferPct, setLeadBufferPct] = useState(20);
  // آمار واقعیِ همین دوره (فروش/مشاوره/شماره دریافتی): sellerId → { sales_count, consultations_count, phones_count }
  const [periodActuals, setPeriodActuals] = useState({});
  // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): تفکیکِ نرخ‌ها/لیدِ نیاز به‌ازایِ هر محصول، به‌ازایِ هر فروشنده —
  // فقط وقتی کارتِ فروشنده باز می‌شه lazy لود می‌شه (نه رويِ همه‌ی فروشنده‌ها همزمان).
  const [prodBreakdown, setProdBreakdown] = useState({}); // sellerId → { loading, products }
  const [expandedSeller, setExpandedSeller] = useState(null);
  // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): نرخِ کانورتِ واقعی و نرخِ پاسخِ واقعی تويِ جدولِ تفکیکِ محصولات
  // قابلِ‌ویرایش باشن (دستی override رويِ عددِ واقعیِ تاریخی، به‌ازایِ هر فروشنده+محصول).
  const [prodRateOv, setProdRateOv] = useState({}); // `${sellerId}::${productId}` → { conv_rate?, sec_conv? }
  // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): این override قبلاً فقط تويِ حافظه بود و با رفرش پاک می‌شد —
  // حالا هم‌زمان با ست‌شدن، رويِ سرور هم ذخیره می‌شه (seller_product_plan).
  const updProdRateOv = (sellerId, productId, field, val) => {
    const key = `${sellerId}::${productId}`;
    setProdRateOv(m => ({...m, [key]: {...m[key], [field]: val}}));
    const body = { period: curPeriod, [field==='conv_rate'?'conv_rate_override':'sec_conv_override']: val };
    api(`/seller-product-plan/${sellerId}/${productId}`, {method:'PUT', body}).catch(()=>{});
  };
  const toggleProdBreakdown = (sellerId) => {
    if (expandedSeller === sellerId) { setExpandedSeller(null); return; }
    setExpandedSeller(sellerId);
    if (prodBreakdown[sellerId]) return;
    setProdBreakdown(m => ({...m, [sellerId]: { loading:true, products:[] }}));
    api(`/seller-product-stats?seller_id=${sellerId}`)
      .then(r => setProdBreakdown(m => ({...m, [sellerId]: { loading:false, products: r.data?.products || r.products || [] }})))
      .catch(() => setProdBreakdown(m => ({...m, [sellerId]: { loading:false, products: [] }})));
  };

  // قانونِ کاربر (۲۰۲۶-۰۸-۱۹): گزارشِ «کدوم ماه چه سبکِ فروشی داشتیم»
  const [history,     setHistory]     = useState([]);
  const [showHistory, setShowHistory] = useState(false);
  const loadHistory = () => api('/period-config/history?limit=12').then(r=>{
    setHistory((r.data||r)?.history || []);
  }).catch(()=>{});
  useEffect(() => { loadHistory(); }, []);

  // ─── Load ───────────────────────────────────────────────────────
  useEffect(()=>{
    setLoading(true);
    setSavedThisPeriod(false);
    setTarget(0);
    Promise.all([
      api('/products'),
      api('/sellers'),
      api(`/product-plan?period=${curPeriod}`),
      api(`/targets?period=${curPeriod}`),
      api(`/seller-real-stats?period=${curPeriod}`),
      api(`/period-actuals?period=${curPeriod}`),
      api(`/period-config?period=${curPeriod}`),
      fetch(`/api/crm/admin/seller-stats-params?period=${curPeriod}`, {headers:hdrs}).then(r=>r.json()).catch(()=>null),
      api(`/seller-product-plan?period=${curPeriod}`).catch(()=>null),
    ]).then(([pr,sr,planR,tgtR,realR,actR,pcR,sssR,sppR])=>{
      const sssParams = (sssR?.data||sssR)?.params || [];
      const dcrParam = sssParams.find(p=>p.key==='default_conv_rate');
      const dcrNum = Number(dcrParam?.value);
      const dcr = Number.isFinite(dcrNum) ? dcrNum : 25; // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): || باعث می‌شد مقدارِ صفر به پیش‌فرض برگرده
      setDefaultConvRate(dcr);
      const bufParam = sssParams.find(p=>p.key==='lead_buffer_pct');
      const bufNum = Number(bufParam?.value);
      setLeadBufferPct(Number.isFinite(bufNum) ? bufNum : 20); // همون باگ: بافرِ صفر با || به ۲۰٪ برمی‌گشت
      // قانونِ کاربر (۲۰۲۶-۰۸-۱۹): سبک‌فروشِ فعال و تنظیماتِ کمپین/محتوا مالِ همین دوره‌ست —
      // اگه برایِ این ماه ذخیره شده بازیابی کن، وگرنه به پیش‌فرض برگرد (نه چیزیِ باقی‌مونده از یه ماهِ دیگه)
      const pc = pcR.data || pcR;
      setModels(new Set(pc.active_models?.length ? pc.active_models : ['linear']));
      setWebinarRates(pc.webinar_rates || { attend_rate:18.8, stay_rate:46.7, conv_rate:17.8 });
      setLinearRates (pc.linear_rates  || { sales_conv:25, sec_conv:80, work_days:22 });
      setCampaignCfg (pc.campaign_cfg  || { budget:0, cpl:0, lead_conv:5 });
      setContentCfg  (pc.content_cfg   || { target_count:0, lead_per_content:0, content_conv:5 });
      const ap=(pr.data?.products||[]).filter(p=>!p.is_prize&&p.is_active);
      setProds(ap);
      // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): sec_conv هیچ‌وقت فیلدِ قابلِ‌ویرایشِ تک‌محصولی نداشته
      // (فقط sales_conv/work_days دارن) — پس مقدارِ ذخیره‌شده‌ش تویِ product_plan صرفاً یه
      // کپیِ یخ‌زده‌یِ همون لحظه‌یِ ذخیره‌ست، نه یه override‌یِ عمدی. اگه بعداً نرخِ پیش‌فرض
      // عوض بشه، این کپیِ قدیمی دیگه هیچ‌وقت به‌روز نمی‌شد. حالا همیشه از رويِ نرخِ فعلی
      // ساخته می‌شه (چه محصولِ تازه، چه محصولی که قبلاً پلن داشته).
      const _lr = pc.linear_rates || { sales_conv:25, sec_conv:80, work_days:22 };
      const pm={};
      ap.forEach(p=>{
        pm[p.id]={ webinar_price:p.list_price||p.avg_value||0, avg_deal:p.avg_value||0, target_units:0,
          attend_rate:18.8, stay_rate:46.7, conv_rate:17.8,
          sales_conv:_lr.sales_conv, sec_conv:_lr.sec_conv, work_days:_lr.work_days };
      });
      (planR.data?.plans||[]).forEach(pl=>{ if(pm[pl.product_id]) pm[pl.product_id]={...pm[pl.product_id],...pl, sec_conv:_lr.sec_conv}; });
      setPCfg(pm);

      const sl=(sr.data?.sellers||[]).filter(s=>s.is_active);
      setSellers(sl);

      // ساخت نقشه آمار واقعی
      const rm={};
      (realR.data?.stats||[]).forEach(r=>{ rm[r.seller_id]=r; });
      setRealStats(rm);

      const am={};
      (actR.data?.actuals||[]).forEach(a=>{ am[a.seller_id]=a; });
      setPeriodActuals(am);

      const sm={};
      sl.forEach(s=>{
        const r=rm[s.id]||{};
        // اولویت: داده‌ی ذخیره‌شده قبلی → آمار واقعی → پیش‌فرض
        sm[s.id]={
          amount:            0,
          conv_rate:         r.conv_rate  ?? dcr,
          sec_conv:          r.sec_conv   ?? 80,
          commission_rate:   10,
          avg_deal:          r.avg_deal   ?? 0,
          conv_rate_manual:  false,
          sec_conv_manual:   false,
          avg_deal_manual:   false,
        };
      });
      // اگه تارگت قبلی ذخیره شده، override کن
      // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): تشخیصِ «دستی‌بودن» با مقایسه‌ی مقدارِ ذخیره‌شده با آمارِ
      // واقعی باگ‌زا بود — چون آمارِ واقعی به‌مرور drift می‌کنه، عددِ قدیمیِ ذخیره‌شده (که
      // واقعی بود، نه دستی) به‌غلط manual تشخیص داده می‌شد و جایِ نرخِ تازه رو می‌گرفت. حالا
      // یه فلگِ صریحِ دستیِ ذخیره‌شده (conv_rate_manual/...) تصمیم می‌گیره، نه مقایسه‌یِ عدد.
      (tgtR.data?.targets||[]).forEach(t=>{
        if(sm[t.seller_id]) sm[t.seller_id]={
          ...sm[t.seller_id],
          amount:          t.amount||0,
          commission_rate: t.commission_rate||10,
          ...(t.conv_rate_manual ? {conv_rate: t.conv_rate, conv_rate_manual:true} : {}),
          ...(t.sec_conv_manual  ? {sec_conv:  t.sec_conv,  sec_conv_manual:true}  : {}),
          ...(t.avg_deal_manual  ? {avg_deal:  t.avg_deal,  avg_deal_manual:true}  : {}),
        };
      });
      setSCfg(sm);

      // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): override دستیِ نرخِ کانورت/پاسخِ واقعیِ جدولِ تفکیکِ
      // محصولات — قبلاً فقط تويِ حافظه بود و با رفرش پاک می‌شد، حالا از سرور بازیابی می‌شه.
      const ovm={};
      (sppR?.data?.matrix||[]).forEach(row=>{
        if (row.conv_rate_override==null && row.sec_conv_override==null) return;
        const key = `${row.seller_id}::${row.product_id}`;
        ovm[key] = {
          ...(row.conv_rate_override!=null ? {conv_rate: row.conv_rate_override} : {}),
          ...(row.sec_conv_override !=null ? {sec_conv:  row.sec_conv_override } : {}),
        };
      });
      setProdRateOv(ovm);
      const tot=Object.values(sm).reduce((a,v)=>a+(v.amount||0),0);
      if(tot>0) setTarget(tot);
      // قانونِ کاربر (۲۰۲۶-۰۷-۲۹): اگه از قبل برایِ این دوره تارگت ذخیره شده، نیازی به گذروندنِ
      // دوباره‌یِ ۵ قدمِ ویزارد نیست — مستقیم برو رویِ صفحه‌یِ «مرورِ نهایی» (فقط‌خواندنی-ایش).
      // فقط وقتی کاربر صریحاً «ویرایش» بزنه (setStep(1)) باید دوباره واردِ ویزارد بشه.
      if ((tgtR.data?.targets||[]).length > 0) { setSavedThisPeriod(true); setStep(5); }
      else setStep(1);
    }).finally(()=>setLoading(false));
  },[curPeriod]);

  // ─── Helpers ────────────────────────────────────────────────────
  const updP = (pid,k,v) => setPCfg(m=>({...m,[pid]:{...m[pid],[k]:v}}));
  // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): وقتی ادمین صراحتاً conv_rate/sec_conv/avg_deal رو ویرایش می‌کنه،
  // فلگِ دستیِ متناظرش هم true می‌شه — همینه که تصمیم می‌گیره بعدِ رفرش این عدد بمونه یا نه.
  // ۰/خالی یعنی «پاک‌کردنِ دستی، برگرد به آمارِ زنده» — نه یه مقدارِ دستیِ صفر.
  const MANUAL_FLAG = { conv_rate:'conv_rate_manual', sec_conv:'sec_conv_manual', avg_deal:'avg_deal_manual' };
  const updS = (sid,k,v) => setSCfg(m=>({...m,[sid]:{...m[sid],[k]:v, ...(MANUAL_FLAG[k]?{[MANUAL_FLAG[k]]:!!v}:{})}}));
  // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): کشفِ زنده — عوض‌کردنِ «نرخِ پیش‌فرض» تویِ این کارت‌ها هیچ اثری
  // رويِ چیزی که واقعاً ذخیره می‌شه نداشت! هر محصول از همون لحظه‌یِ بارگذاری یه مقدارِ
  // هاردکدِ خودش می‌گرفت (مثلاً sec_conv:80 — خطِ بالاتر)، پس فال‌بکِ pc.X??linearRates.X
  // تویِ فیلدهایِ تک‌محصولی هیچ‌وقت واقعاً اجرا نمی‌شد (pc.X همیشه از قبل مقدار داشت، نه
  // null/undefined) — یعنی «نرخِ پاسخ‌دهیِ پیش‌فرض» رو هرچی می‌ذاشتی (مثلاً ۷۰)، تویِ
  // گزارشِ نهایی بازم همون ۸۰ی اولیه ذخیره می‌شد. حالا عوض‌کردنِ نرخِ پیش‌فرض واقعاً رويِ
  // همه‌ی محصولات اعمال می‌شه (بعداً می‌شه تک‌تک override کرد، دقیقاً مثلِ معنیِ «پیش‌فرض»).
  const updWR= (k,v) => { setWebinarRates(r=>({...r,[k]:v})); setPCfg(m=>{ const n={...m}; prods.forEach(p=>{ n[p.id]={...n[p.id],[k]:v}; }); return n; }); };
  const updLR= (k,v) => { setLinearRates(r=>({...r,[k]:v}));  setPCfg(m=>{ const n={...m}; prods.forEach(p=>{ n[p.id]={...n[p.id],[k]:v}; }); return n; }); };
  const updCC= (k,v) => setCampaignCfg(r=>({...r,[k]:v}));
  const updCT= (k,v) => setContentCfg(r=>({...r,[k]:v}));

  const toggleModel = m => setModels(prev=>{
    const n=new Set(prev);
    n.has(m)?n.delete(m):n.add(m);
    return n;
  });

  // محاسبه لید از تارگت با استفاده از آمار واقعی فروشنده (+۲۰٪ بافر)
  const selLeads = sid => {
    const s  = sCfg[sid];     if (!s || !s.amount) return 0;
    const rs = realStats[sid] || {};
    // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): اولویتِ نرخِ کانورت/پاسخ — اول دستیِ ادمین، بعد واقعیِ
    // تاریخی، بعد پیش‌فرض.
    const cr  = s.conv_rate || rs.conv_rate || defaultConvRate;
    const sec = s.sec_conv  || rs.sec_conv  || 80;
    if (cr<=0 || sec<=0) return 0;

    // avg_deal برایِ بخشِ «پیکربندی‌نشده»: واقعی → ذخیره‌شده → میانگین محصولات گام ۳
    const prodAvgDeal = (() => {
      const vals = prods.map(p=>pCfg[p.id]?.avg_deal||0).filter(Boolean);
      return vals.length ? Math.round(vals.reduce((a,b)=>a+b,0)/vals.length) : 0;
    })();
    const blendedAd = s.avg_deal || rs.avg_deal || prodAvgDeal || 0;

    // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): وقتی محصولات جداگانه (با تارگتِ درآمد و میانگینِ معاملهٔ
    // خودشون) تويِ گامِ «محصولات» پیکربندی شدن، لیدِ نیاز باید جمعِ لیدِ نیازِ تک‌تکِ محصولات
    // باشه — نه یه میانگینِ معاملهٔ ترکیبی برایِ کلِ تارگت (ریاضیاتاً غلطه: وقتی ad_i ها فرق
    // دارن، sum(target_i/ad_i) با target_total/avg(ad_i) برابر نیست — قبلاً باعث می‌شد عددِ
    // بالایِ کارتِ فروشنده با جمعِ ردیف‌هایِ تفکیکِ محصولات هماهنگ نباشه).
    const configuredProds = prods.filter(p => (pCfg[p.id]?.target_revenue||0) > 0 && (pCfg[p.id]?.avg_deal||0) > 0);
    const configuredTargetSum = configuredProds.reduce((a,p)=>a+pCfg[p.id].target_revenue,0);

    // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): نرخِ کانورت/پاسخِ هر محصول باید دقیقاً همون چیزی باشه که
    // تويِ ردیفِ «تفکیکِ محصولات» نشون داده می‌شه (اول overrideِ دستیِ همون‌جا، بعد نرخِ
    // واقعیِ تاریخیِ همون فروشنده‌رويِ‌همون‌محصول، بعد نرخِ سطحِ فروشنده) — وگرنه عددِ بالایِ
    // کارت با جمعِ ردیف‌ها هماهنگ نمی‌مونه (قبلاً همه‌ی محصولات از یه نرخِ یکسانِ سطحِ
    // فروشنده استفاده می‌کردن، حتی وقتی ردیفِ محصول دستی/واقعیِ فرق‌داری داشت).
    const bd = prodBreakdown[sid]?.products || [];
    let totalRaw = 0;
    configuredProds.forEach(p => {
      const pc = pCfg[p.id];
      const ov = prodRateOv[`${sid}::${p.id}`] || {};
      const real = bd.find(x=>x.product_id===p.id) || {};
      const pCr  = ov.conv_rate ?? real.conv_rate ?? cr;
      const pSec = ov.sec_conv  ?? real.sec_conv  ?? sec;
      const pConsult = (pc.target_revenue/pc.avg_deal)/(pCr/100);
      totalRaw += Math.ceil(pConsult/(pSec/100));
    });

    const remainder = Math.max(0, (s.amount||0) - configuredTargetSum);
    if (remainder > 0 && blendedAd > 0) {
      const rConsult = (remainder/blendedAd)/(cr/100);
      totalRaw += Math.ceil(rConsult/(sec/100));
    }

    return totalRaw>0 ? Math.ceil(totalRaw * (1 + leadBufferPct/100)) : 0; // بافر برای لیدهای بی‌پاسخ — قابلِ‌تنظیم از قوانین
  };

  // قانونِ کاربر (۲۰۲۶-۰۸-۱۹): تا اینجا فقط «فروش خطی» توی محاسبه‌ی لید نیاز/توزیعِ
  // تارگتِ فروشنده‌ها اثر داشت — وبینار/کمپین/تولیدِ محتوا فقط تخمینِ محلی نشون
  // می‌دادن و ذخیره می‌شدن ولی به عددِ نهایی وصل نبودن. حالا: درآمدِ تخمینیِ هرکدوم
  // از این ۳ کانال از هدفِ کل کم می‌شه و فقط باقیمونده («هدفِ فروشِ خطی») بینِ
  // فروشنده‌ها توزیع می‌شه؛ لیدِ لازمِ هر کانال هم به «لید نیازِ ماه» اضافه می‌شه.
  const prodAvgDealAll = (() => {
    const vals = prods.map(p=>pCfg[p.id]?.avg_deal||0).filter(Boolean);
    return vals.length ? Math.round(vals.reduce((a,b)=>a+b,0)/vals.length) : 0;
  })();

  // وبینار: درآمد و لیدِ لازم از مجموعِ محصولاتِ وبیناری (ثبت‌نام → حضور → ماندگاری → خرید)
  const webinarStats = (() => {
    if (!models.has('webinar')) return { revenue:0, leads:0 };
    let revenue=0, leads=0;
    prods.forEach(p=>{
      const pc = pCfg[p.id]||{};
      const units = pc.target_units||0;
      if (!units) return;
      revenue += units * (pc.webinar_price||0);
      const funnel = ((pc.attend_rate??webinarRates.attend_rate)/100) * ((pc.stay_rate??webinarRates.stay_rate)/100) * ((pc.conv_rate??webinarRates.conv_rate)/100);
      if (funnel>0) leads += Math.ceil(units/funnel);
    });
    return { revenue, leads };
  })();

  // کمپین: بودجه÷CPL=لید، لید×نرخ‌تبدیل=فروش، فروش×میانگینِ معامله=درآمدِ تخمینی
  const campaignStats = (() => {
    if (!models.has('campaign') || !campaignCfg.budget || !campaignCfg.cpl) return { revenue:0, leads:0 };
    const leads = Math.round(campaignCfg.budget/campaignCfg.cpl);
    const sales = Math.round(leads*(campaignCfg.lead_conv/100));
    return { revenue: sales*prodAvgDealAll, leads };
  })();

  // تولیدِ محتوا: محتوا×لید‌به‌ازایِ‌محتوا=لید، لید×نرخ‌تبدیل=فروش، فروش×میانگینِ معامله=درآمدِ تخمینی
  const contentStats = (() => {
    if (!models.has('content') || !contentCfg.target_count || !contentCfg.lead_per_content) return { revenue:0, leads:0 };
    const leads = contentCfg.target_count*contentCfg.lead_per_content;
    const sales = Math.round(leads*(contentCfg.content_conv/100));
    return { revenue: sales*prodAvgDealAll, leads };
  })();

  const nonLinearRevenue = webinarStats.revenue + campaignStats.revenue + contentStats.revenue;
  const nonLinearLeads   = webinarStats.leads   + campaignStats.leads   + contentStats.leads;
  // هدفی که باید از طریقِ فروشِ خطی (تماسِ فروشنده) پوشش داده بشه = هدفِ کل منهایِ
  // چیزی که کانال‌هایِ دیگه تامین می‌کنن (اگه فروشِ خطی اصلاً فعال نباشه، سهمش صفره)
  const linearTarget = models.has('linear') ? Math.max(target - nonLinearRevenue, 0) : 0;

  // توزیع هوشمند بر اساس نرخ کانورت ماه گذشته (فصلی fallback)
  const smartDistribute = (tgt) => {
    const total = tgt ?? linearTarget;
    if (!total || !sellers.length) return;
    const weights = sellers.map(s => {
      const rs = realStats[s.id] || {};
      // ترجیح: ماه گذشته → فصلی → پیش‌فرض
      return rs.last_month?.conv_rate ?? rs.seasonal?.conv_rate ?? rs.conv_rate ?? 10;
    });
    const sum = weights.reduce((a,b)=>a+b,0);
    if (!sum) return;
    const nm = {...sCfg};
    sellers.forEach((s,i) => { nm[s.id] = {...nm[s.id], amount: Math.round(total * (weights[i] / sum))}; });
    setSCfg(nm);
  };

  // خلاصه
  const totalSel  = sellers.reduce((a,s)=>a+(sCfg[s.id]?.amount||0),0);
  const totalComm = sellers.reduce((a,s)=>a+(sCfg[s.id]?.amount||0)*((sCfg[s.id]?.commission_rate||10)/100),0);
  const totalPro  = totalSel-totalComm;
  const linearLeads = sellers.reduce((a,s)=>a+selLeads(s.id),0);
  // لیدِ نیازِ کلِ ماه = فروشِ خطی (سهمِ فروشنده‌ها) + وبینار + کمپین + تولیدِ محتوا
  const totalLeads = linearLeads + nonLinearLeads;

  // هر بار که وارد step 4 می‌شیم یا realStats لود می‌شه، خودکار توزیع کن
  useEffect(()=>{
    if (step===4 && linearTarget>0 && sellers.length>0 && Object.keys(realStats).length>0) {
      smartDistribute();
    }
  }, [step, Object.keys(realStats).length, linearTarget]);

  const save = async () => {
    setSaving(true);
    try {
      await Promise.all([
        ...prods.map(p=>api(`/product-plan/${p.id}`,{method:'PUT',body:{...pCfg[p.id],period:curPeriod}})),
        ...sellers.map(s=>api(`/sellers/${s.id}/target`,{method:'PUT',body:{...sCfg[s.id],period:curPeriod}})),
        api('/period-config',{method:'PUT',body:{
          period: curPeriod, active_models:[...models],
          webinar_rates: webinarRates, linear_rates: linearRates,
          campaign_cfg: campaignCfg, content_cfg: contentCfg,
        }}),
      ]);
      toast.show?.('تارگت‌ها با موفقیت ذخیره شد ✓','success');
      setSavedThisPeriod(true);
      loadHistory();
    } catch { toast.show?.('خطا در ذخیره‌سازی','error'); } finally { setSaving(false); }
  };

  // حذفِ کاملِ تارگتِ این دوره — برایِ شروعِ دوباره/تارگتِ جدید
  const deleteTargets = async () => {
    if (!confirm(`تارگتِ ثبت‌شده‌یِ ${curPeriod} کاملاً حذف بشه؟ این کار قابلِ بازگشت نیست.`)) return;
    setDeleting(true);
    try {
      await api(`/targets/${curPeriod}`, { method:'DELETE' });
      toast.show?.('تارگتِ این دوره حذف شد','success');
      setSavedThisPeriod(false);
      // ریست کردنِ کاملِ فرم به حالتِ اولیه تا کاربر بتونه از نو بسازه
      setTarget(0);
      const sm = {};
      sellers.forEach(s => { const r = realStats[s.id]||{}; sm[s.id] = { amount:0, conv_rate:r.conv_rate??defaultConvRate, sec_conv:r.sec_conv??80, commission_rate:10, avg_deal:r.avg_deal??0 }; });
      setSCfg(sm);
      setStep(1);
    } catch { toast.show?.('خطا در حذف','error'); } finally { setDeleting(false); }
  };

  const STEPS = [
    {n:1, icon:'🎯', label:'هدف ماه'},
    {n:2, icon:'🧭', label:'سبک فروش'},
    {n:3, icon:'📦', label:'محصولات'},
    {n:4, icon:'👥', label:'فروشندگان'},
    {n:5, icon:'✅', label:'تایید'},
  ];

  // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): این ورودی قبلاً کاملاً controlled بود (value مستقیم به عددِ
  // state وصل بود) — هر کیبورد یه re-render فوری با parseFloat می‌ساخت که مکان‌نمای تایپ رو
  // به‌هم می‌ریخت (تایپِ رقمِ دوم اغلب گم/جابه‌جا می‌شد). حالا مثلِ input‌هایِ مشابهِ همین پروژه
  // (مثلاً overdue_grace_minutes تویِ rules_ops.jsx) uncontrolled شد — فقط با onBlur ست می‌شه؛
  // key={val} باعث می‌شه اگه val از بیرون عوض شد (مثلاً با عوض‌کردنِ دوره/مدل)، فیلد ریست بشه.
  const RateInp = ({label, val, onChange, step=1, min=0, max=100, unit='٪'}) => (
    <div className="sw-field" style={{marginBottom:0}}>
      <div className="sw-lbl">{label}</div>
      <div style={{display:'flex',alignItems:'center',gap:5}}>
        <input key={val} className="sw-rate" type="number" defaultValue={val} step={step} min={min} max={max}
          onBlur={e=>onChange(parseFloat(e.target.value)||0)} style={{width:'100%'}}/>
        {unit && <span style={{fontSize:11,color:'#475569',whiteSpace:'nowrap'}}>{unit}</span>}
      </div>
    </div>
  );

  if(loading) return <div style={{padding:60,textAlign:'center',color:'#64748b'}}>در حال بارگذاری...</div>;

  const modelLabel = m => ({'webinar':'وبینار','linear':'خطی','campaign':'کمپین','content':'تولید محتوا'}[m]||m);
  const modelColor = m => ({'webinar':'#818cf8','linear':'#34d399','campaign':'#f472b6','content':'#fbbf24'}[m]||'#64748b');
  const modelIcon  = m => ({'webinar':'🎤','linear':'📞','campaign':'📢','content':'🎬'}[m]||'');

  // ══════════════════════════════════════════════════════════════════
  return (
    <div className="sw">
      {/* هدر */}
      <div style={{display:'flex',alignItems:'flex-start',justifyContent:'space-between',marginBottom:20,flexWrap:'wrap',gap:12}}>
        <div>
          <div style={{fontSize:21,fontWeight:800}}>تعیین تارگت ماهانه فروش</div>
          <div style={{fontSize:12,color:'#64748b',marginTop:3}}>{curPeriod} · {prods.length} محصول · {sellers.length} فروشنده</div>
        </div>
        <div style={{display:'flex',alignItems:'center',gap:8,flexWrap:'wrap'}}>
          {/* گزارشِ تاریخچه‌ی سبکِ فروش — قانونِ کاربر (۲۰۲۶-۰۸-۱۹) */}
          <button className="sw-btn sw-btn-ghost" style={{padding:'8px 12px'}} onClick={()=>setShowHistory(v=>!v)}>
            📜 تاریخچه‌ی سبک فروش {showHistory?'▲':'▼'}
          </button>
          {/* انتخاب‌گرِ ماه — قانونِ کاربر (۲۰۲۶-۰۷-۲۹): امکانِ چیدنِ تارگت برایِ ماه‌هایِ آینده هم */}
          <div style={{display:'flex',alignItems:'center',gap:8,background:'#0d1219',border:'1px solid rgba(255,255,255,0.09)',borderRadius:11,padding:'8px 10px'}}>
            <button className="sw-btn sw-btn-ghost" style={{padding:'5px 10px'}} onClick={()=>setPeriodOffset(o=>o-1)}>→ ماهِ قبل</button>
            <div style={{fontSize:13,fontWeight:800,minWidth:110,textAlign:'center'}}>{periodLabelFa}{periodOffset===0 && <span style={{fontSize:10,color:'#34d399',display:'block',fontWeight:700}}>(ماهِ جاری)</span>}</div>
            <button className="sw-btn sw-btn-ghost" style={{padding:'5px 10px'}} onClick={()=>setPeriodOffset(o=>o+1)}>ماهِ بعد ←</button>
            {periodOffset!==0 && <button className="sw-btn sw-btn-ghost" style={{padding:'5px 10px',fontSize:11}} onClick={()=>setPeriodOffset(0)}>بازگشت به ماهِ جاری</button>}
          </div>
        </div>
      </div>

      {/* پنلِ تاریخچه‌ی سبکِ فروش — هر ماه چه مدل(هایی) فروش فعال بوده */}
      {showHistory && (
        <div className="sw-card" style={{marginBottom:18,padding:'16px 18px'}}>
          <div style={{fontSize:13,fontWeight:800,marginBottom:12}}>📜 تاریخچه‌ی سبک فروش ماه‌های قبل</div>
          {history.length===0 ? (
            <div style={{fontSize:12,color:'#64748b'}}>هنوز هیچ ماهی سبک فروش/تارگت ذخیره‌شده‌ای نداره.</div>
          ) : (
            <div style={{display:'flex',flexDirection:'column',gap:6}}>
              {history.map(h=>{
                // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): h.period از وقتی period شمسی شد، دیگه یه YYYY-MM
                // میلادی نیست — ساختنِ Date میلادی از رويِ عددهایِ شمسی (مثلاً new Date(1405,...))
                // یه تاریخِ میلادیِ بی‌معنی می‌ساخت (سالِ ۱۴۰۵ میلادی!) که برچسب و آفستِ کاملاً
                // غلط تولید می‌کرد. حالا مستقیم از رويِ اعدادِ شمسیِ خودِ period ساخته می‌شه.
                const [hy,hm] = h.period.split('-').map(Number);
                const hLabel = `${JALALI_MONTHS[hm-1]} ${fa(String(hy))}`;
                const { jy: nowJy, jm: nowJm } = jalaliParts(new Date());
                const hOffset = (hy-nowJy)*12 + (hm-nowJm);
                return (
                  <div key={h.period} onClick={()=>setPeriodOffset(hOffset)}
                    style={{display:'flex',alignItems:'center',gap:10,padding:'8px 12px',borderRadius:9,
                      background: hOffset===periodOffset?'rgba(129,140,248,0.12)':'rgba(255,255,255,0.02)',
                      border: hOffset===periodOffset?'1px solid rgba(129,140,248,0.35)':'1px solid rgba(255,255,255,0.05)',
                      cursor:'pointer'}}>
                    <span style={{fontSize:12,fontWeight:700,minWidth:90}}>{hLabel}</span>
                    <div style={{display:'flex',gap:6,flexWrap:'wrap',flex:1}}>
                      {h.active_models.map(m=>(
                        <span key={m} className="sw-tag" style={{color:modelColor(m),background:modelColor(m)+'18',border:`1px solid ${modelColor(m)}33`}}>
                          {modelIcon(m)} {modelLabel(m)}
                        </span>
                      ))}
                    </div>
                    {!h.has_target && <span style={{fontSize:10,color:'#475569'}}>تارگت ذخیره نشده</span>}
                  </div>
                );
              })}
            </div>
          )}
        </div>
      )}

      {/* بنّرِ تأییدِ ذخیره‌شدن — قانونِ کاربر (۲۰۲۶-۰۷-۲۹): ذخیره‌شدن باید به‌طورِ قابلِ‌مشاهده
          نشون داده بشه (نه فقط یه toast که ناپدید می‌شه)، با قابلیتِ ویرایش/حذف/شروعِ دوباره */}
      {savedThisPeriod && (
        <div style={{display:'flex',alignItems:'center',gap:12,padding:'12px 16px',borderRadius:12,marginBottom:18,
          background:'rgba(52,211,153,0.08)',border:'1px solid rgba(52,211,153,0.3)'}}>
          <span style={{fontSize:20}}>✅</span>
          <div style={{flex:1}}>
            <div style={{fontSize:13,fontWeight:800,color:'#34d399'}}>تارگتِ {curPeriod} ذخیره شده</div>
            <div style={{fontSize:11,color:'#64748b',marginTop:2}}>می‌تونی ویرایش کنی یا کاملاً حذف/از نو بسازی</div>
          </div>
          <button className="sw-btn sw-btn-ghost" onClick={()=>setStep(1)}>✏️ ویرایش</button>
          <button onClick={deleteTargets} disabled={deleting}
            style={{padding:'8px 16px',borderRadius:9,fontSize:12,fontWeight:700,cursor:'pointer',border:'1px solid rgba(248,113,113,0.35)',background:'rgba(248,113,113,0.1)',color:'#F87171'}}>
            {deleting?'...':'🗑 حذف / تارگتِ جدید'}
          </button>
        </div>
      )}

      {/* استپر */}
      <div className="sw-steps">
        {STEPS.map(st=>{
          const cls=step>st.n?'done':step===st.n?'active':'idle';
          return (
            <div key={st.n} className={`sw-step ${step>st.n?'clickable':''} ${cls}`}
              onClick={()=>step>st.n&&setStep(st.n)}>
              <div className={`sw-dot ${cls}`}>{step>st.n?'✓':st.icon}</div>
              <div className="sw-step-lbl">{st.label}</div>
            </div>
          );
        })}
      </div>

      {/* ═══════ گام ۱: هدف ماه ══════════════════════════════════ */}
      {step===1 && (
        <div className="sw-card" style={{borderTop:'3px solid #818cf8'}}>
          <div className="sw-title">🎯 هدف درآمدی این ماه چقدر است؟</div>
          <div className="sw-sub">هدف کل شرکت را به تومان وارد کنید — در مراحل بعد بین فروشندگان تقسیم می‌شود</div>

          <div className="sw-field">
            <div className="sw-lbl">هدف کل درآمد (تومان)</div>
            <MoneyInput value={target} onChange={setTarget} placeholder="مثلاً ۹۰۰٬۰۰۰٬۰۰۰"
              style={{fontSize:26,fontWeight:900,padding:'13px 18px',maxWidth:340}}/>
            {target>0 && (
              <div style={{marginTop:8,display:'flex',gap:10,alignItems:'center',flexWrap:'wrap'}}>
                <span style={{fontSize:14,color:'#a5b4fc',fontWeight:800}}>{fmoney(target)}</span>
                <span style={{fontSize:11,color:'#475569'}}>≈ {fa(+(target/1e9).toFixed(2))} میلیارد</span>
              </div>
            )}
          </div>

          {target>0 && (
            <div className="sw-kpi" style={{marginTop:16}}>
              {[
                {l:'هدف ماه',v:fmoney(target),c:'#a5b4fc'},
                {l:'تعداد فروشنده',v:fa(sellers.length)+' نفر',c:'#e2e8f0'},
                {l:'میانگین هر فروشنده',v:fmoney(sellers.length?Math.round(target/sellers.length):0),c:'#fbbf24'},
              ].map((k,i)=>(
                <div key={i} className="sw-kpi-box">
                  <div className="sw-kpi-lbl">{k.l}</div>
                  <div className="sw-kpi-val" style={{color:k.c,fontSize:15}}>{k.v}</div>
                </div>
              ))}
            </div>
          )}

          <div className="sw-nav">
            <div/>
            <button className="sw-btn sw-btn-p" disabled={!target} onClick={()=>setStep(2)}>
              مرحله بعد: سبک فروش ←
            </button>
          </div>
        </div>
      )}

      {/* ═══════ گام ۲: سبک فروش ══════════════════════════════════ */}
      {step===2 && (
        <div>
          <div className="sw-card" style={{borderTop:'3px solid #f472b6'}}>
            <div className="sw-title">🧭 سبک فروش این ماه را انتخاب کنید</div>
            <div className="sw-sub">می‌توانید یک یا چند سبک را همزمان فعال کنید</div>

            <div className="sw-grid4" style={{marginBottom:16}}>
              {/* وبینار */}
              <div className={`sw-model-card ${models.has('webinar')?'sel-webinar':''}`}
                onClick={()=>toggleModel('webinar')}>
                <div className="sw-model-check">{models.has('webinar')&&'✓'}</div>
                <div className="sw-model-icon">🎤</div>
                <div className="sw-model-name" style={{color:models.has('webinar')?'#a5b4fc':'#e2e8f0'}}>وبینار</div>
                <div className="sw-model-desc">ثبت‌نام → حضور → ماندگاری → خرید<br/>مناسب دوره‌های آنلاین و آموزشی</div>
              </div>
              {/* خطی */}
              <div className={`sw-model-card ${models.has('linear')?'sel-linear':''}`}
                onClick={()=>toggleModel('linear')}>
                <div className="sw-model-check">{models.has('linear')&&'✓'}</div>
                <div className="sw-model-icon">📞</div>
                <div className="sw-model-name" style={{color:models.has('linear')?'#6ee7b7':'#e2e8f0'}}>فروش خطی</div>
                <div className="sw-model-desc">لید → منشی → مشاوره → فروش<br/>مناسب تیم‌های تماس‌محور</div>
              </div>
              {/* کمپین */}
              <div className={`sw-model-card ${models.has('campaign')?'sel-campaign':''}`}
                onClick={()=>toggleModel('campaign')}>
                <div className="sw-model-check">{models.has('campaign')&&'✓'}</div>
                <div className="sw-model-icon">📢</div>
                <div className="sw-model-name" style={{color:models.has('campaign')?'#f9a8d4':'#e2e8f0'}}>کمپین تبلیغاتی</div>
                <div className="sw-model-desc">بودجه تبلیغات → لید → فروش<br/>مناسب کمپین‌های فصلی و ویژه</div>
              </div>
              {/* تولید محتوا */}
              <div className={`sw-model-card ${models.has('content')?'sel-content':''}`}
                onClick={()=>toggleModel('content')}>
                <div className="sw-model-check">{models.has('content')&&'✓'}</div>
                <div className="sw-model-icon">🎬</div>
                <div className="sw-model-name" style={{color:models.has('content')?'#fcd66b':'#e2e8f0'}}>تولید محتوا</div>
                <div className="sw-model-desc">محتوا → لید → فروش<br/>مناسب رشد ارگانیک از شبکه‌های اجتماعی</div>
              </div>
            </div>

            {models.size===0 && (
              <div style={{textAlign:'center',color:'#f87171',fontSize:12,padding:'8px 0'}}>حداقل یک سبک فروش انتخاب کنید</div>
            )}
          </div>

          {/* نرخ‌های پیش‌فرض هر سبک */}
          {models.has('webinar') && (
            <div className="sw-card" style={{borderTop:'2px solid #818cf8'}}>
              <div style={{fontSize:13,fontWeight:800,color:'#a5b4fc',marginBottom:12}}>🎤 نرخ‌های پیش‌فرض وبینار</div>
              <div className="sw-grid3">
                <RateInp label="نرخ حضور"      val={webinarRates.attend_rate} step={0.5} onChange={v=>updWR('attend_rate',v)}/>
                <RateInp label="نرخ ماندگاری"  val={webinarRates.stay_rate}   step={0.5} onChange={v=>updWR('stay_rate',v)}/>
                <RateInp label="نرخ تبدیل"     val={webinarRates.conv_rate}   step={0.5} onChange={v=>updWR('conv_rate',v)}/>
              </div>
              <div className="sw-insight" style={{marginTop:10}}>
                <span>💡</span><div>این نرخ‌ها به عنوان پیش‌فرض برای همه محصولات وبینار اعمال می‌شود — در گام بعد می‌توانید به‌ازای هر محصول تغییر دهید.</div>
              </div>
            </div>
          )}

          {models.has('linear') && (
            <div className="sw-card" style={{borderTop:'2px solid #34d399'}}>
              <div style={{fontSize:13,fontWeight:800,color:'#6ee7b7',marginBottom:12}}>📞 نرخ‌های پیش‌فرض فروش خطی</div>
              <div className="sw-grid3">
                <RateInp label="نرخ کانورت فروش" val={linearRates.sales_conv} step={1} onChange={v=>updLR('sales_conv',v)}/>
                <RateInp label="نرخ پاسخ‌دهی"   val={linearRates.sec_conv}   step={1} onChange={v=>updLR('sec_conv',v)}/>
                <RateInp label="روزهای کاری ماه" val={linearRates.work_days}  step={1} max={31} unit='روز' onChange={v=>updLR('work_days',v)}/>
              </div>
            </div>
          )}

          {models.has('campaign') && (
            <div className="sw-card" style={{borderTop:'2px solid #f472b6'}}>
              <div style={{fontSize:13,fontWeight:800,color:'#f9a8d4',marginBottom:12}}>📢 بودجه و تخمین کمپین</div>
              <div className="sw-grid3">
                <div className="sw-field" style={{marginBottom:0}}>
                  <div className="sw-lbl">بودجه تبلیغات (تومان)</div>
                  <MoneyInput className="sw-inp sw-inp-sm" value={campaignCfg.budget} onChange={v=>updCC('budget',v)} placeholder="بودجه"/>
                </div>
                <div className="sw-field" style={{marginBottom:0}}>
                  <div className="sw-lbl">هزینه هر لید — CPL (تومان)</div>
                  <MoneyInput className="sw-inp sw-inp-sm" value={campaignCfg.cpl} onChange={v=>updCC('cpl',v)} placeholder="CPL"/>
                </div>
                <RateInp label="نرخ تبدیل لید به فروش" val={campaignCfg.lead_conv} step={0.5} onChange={v=>updCC('lead_conv',v)}/>
              </div>
              {campaignCfg.budget>0 && campaignCfg.cpl>0 && (
                <div style={{marginTop:12,display:'flex',gap:10,flexWrap:'wrap'}}>
                  <span className="sw-tag sw-pk">لید تخمینی: {fnum(Math.round(campaignCfg.budget/campaignCfg.cpl))} نفر</span>
                  <span className="sw-tag sw-g">فروش تخمینی: {fnum(Math.round(campaignCfg.budget/campaignCfg.cpl*campaignCfg.lead_conv/100))} نفر</span>
                </div>
              )}
            </div>
          )}

          {models.has('content') && (
            <div className="sw-card" style={{borderTop:'2px solid #fbbf24'}}>
              <div style={{fontSize:13,fontWeight:800,color:'#fcd66b',marginBottom:12}}>🎬 هدف تولید محتوا</div>
              <div className="sw-grid3">
                <div className="sw-field" style={{marginBottom:0}}>
                  <div className="sw-lbl">تعداد محتوای هدف در ماه</div>
                  <input className="sw-inp sw-inp-sm" type="number" step={1} value={contentCfg.target_count||0}
                    onChange={e=>updCT('target_count',parseInt(e.target.value)||0)} placeholder="مثلاً ۳۰"/>
                </div>
                <div className="sw-field" style={{marginBottom:0}}>
                  <div className="sw-lbl">لید به‌ازای هر محتوا</div>
                  <input className="sw-inp sw-inp-sm" type="number" step={1} value={contentCfg.lead_per_content||0}
                    onChange={e=>updCT('lead_per_content',parseInt(e.target.value)||0)} placeholder="مثلاً ۵"/>
                </div>
                <RateInp label="نرخ تبدیل لید به فروش" val={contentCfg.content_conv} step={0.5} onChange={v=>updCT('content_conv',v)}/>
              </div>
              {contentCfg.target_count>0 && contentCfg.lead_per_content>0 && (
                <div style={{marginTop:12,display:'flex',gap:10,flexWrap:'wrap'}}>
                  <span className="sw-tag sw-y">لید تخمینی: {fnum(contentCfg.target_count*contentCfg.lead_per_content)} نفر</span>
                  <span className="sw-tag sw-g">فروش تخمینی: {fnum(Math.round(contentCfg.target_count*contentCfg.lead_per_content*contentCfg.content_conv/100))} نفر</span>
                </div>
              )}
            </div>
          )}

          <div className="sw-nav">
            <button className="sw-btn sw-btn-ghost" onClick={()=>setStep(1)}>← برگشت</button>
            <button className="sw-btn sw-btn-p" disabled={models.size===0} onClick={()=>setStep(3)}>
              مرحله بعد: محصولات ←
            </button>
          </div>
        </div>
      )}

      {/* ═══════ گام ۳: محصولات ══════════════════════════════════ */}
      {step===3 && (
        <div className="sw-card" style={{borderTop:'3px solid #fb923c'}}>
          <div className="sw-title">📦 تنظیمات محصولات</div>
          <div style={{display:'flex',gap:8,marginBottom:14,flexWrap:'wrap'}}>
            {[...models].map(m=>(
              <span key={m} className="sw-tag" style={{fontSize:11,color:modelColor(m),background:modelColor(m)+'18',border:`1px solid ${modelColor(m)}33`}}>
                {modelIcon(m)} {modelLabel(m)} فعال
              </span>
            ))}
          </div>

          {prods.map((p,i)=>{
            const pc=pCfg[p.id]||{};
            return (
              <div key={p.id} style={{padding:'14px 0',borderBottom:'1px solid rgba(255,255,255,0.05)'}}>
                <div style={{display:'flex',alignItems:'center',gap:10,marginBottom:12}}>
                  <span className="sw-prod-dot" style={{background:p.color||COLORS[i%COLORS.length]}}/>
                  <span style={{fontWeight:800,fontSize:14}}>{p.name}</span>
                  <span className="sw-tag sw-b" style={{marginRight:'auto'}}>{p.category}</span>
                </div>

                {/* فیلدهای وبینار */}
                {models.has('webinar') && (
                  <div style={{marginBottom:10}}>
                    <div style={{fontSize:10,color:'#818cf8',fontWeight:700,marginBottom:8}}>🎤 وبینار</div>
                    <div className="sw-grid4">
                      <div className="sw-field" style={{marginBottom:0}}>
                        <div className="sw-lbl">قیمت وبینار (تومان)</div>
                        <MoneyInput className="sw-inp sw-inp-xs" value={pc.webinar_price||0}
                          onChange={v=>updP(p.id,'webinar_price',v)} placeholder="قیمت"/>
                      </div>
                      <div className="sw-field" style={{marginBottom:0}}>
                        <div className="sw-lbl">تارگت خریدار (نفر)</div>
                        <input className="sw-inp sw-inp-xs" type="number" step={1} value={pc.target_units||0}
                          onChange={e=>updP(p.id,'target_units',parseInt(e.target.value)||0)}/>
                      </div>
                      <RateInp label="نرخ حضور ٪"    val={pc.attend_rate??webinarRates.attend_rate} step={0.5} onChange={v=>updP(p.id,'attend_rate',v)}/>
                      <RateInp label="نرخ ماندگاری ٪" val={pc.stay_rate??webinarRates.stay_rate}   step={0.5} onChange={v=>updP(p.id,'stay_rate',v)}/>
                    </div>
                    {pc.target_units>0 && pc.webinar_price>0 && (
                      <div style={{marginTop:6}}>
                        <span className="sw-tag sw-v">درآمد تخمینی وبینار: {fmoney((pc.target_units||0)*(pc.webinar_price||0))}</span>
                      </div>
                    )}
                  </div>
                )}

                {/* خط جداکننده */}
                {models.has('webinar') && models.has('linear') && <div className="sw-divider"/>}

                {/* فیلدهای خطی */}
                {models.has('linear') && (
                  <div>
                    <div style={{fontSize:10,color:'#34d399',fontWeight:700,marginBottom:8}}>📞 فروش خطی</div>
                    <div className="sw-grid4">
                      <div className="sw-field" style={{marginBottom:0}}>
                        <div className="sw-lbl">میانگین معامله (تومان)</div>
                        <MoneyInput className="sw-inp sw-inp-xs" value={pc.avg_deal||0}
                          onChange={v=>updP(p.id,'avg_deal',v)} placeholder="میانگین"/>
                      </div>
                      <div className="sw-field" style={{marginBottom:0}}>
                        <div className="sw-lbl">تارگت درآمد خطی (تومان)</div>
                        <MoneyInput className="sw-inp sw-inp-xs" value={pc.target_revenue||0}
                          onChange={v=>updP(p.id,'target_revenue',v)} placeholder="درآمد"/>
                      </div>
                      <RateInp label="نرخ کانورت ٪"  val={pc.sales_conv??linearRates.sales_conv} step={1} onChange={v=>updP(p.id,'sales_conv',v)}/>
                      <RateInp label="روزهای کاری"   val={pc.work_days??linearRates.work_days}   step={1} max={31} unit='روز' onChange={v=>updP(p.id,'work_days',v)}/>
                    </div>
                    {pc.target_revenue>0 && pc.avg_deal>0 && (
                      <div style={{marginTop:6}}>
                        <span className="sw-tag sw-g">فروش تخمینی: {fnum(Math.ceil(pc.target_revenue/pc.avg_deal))} معامله</span>
                      </div>
                    )}
                  </div>
                )}
              </div>
            );
          })}

          <div className="sw-nav">
            <button className="sw-btn sw-btn-ghost" onClick={()=>setStep(2)}>← برگشت</button>
            <button className="sw-btn sw-btn-p" onClick={()=>setStep(4)}>مرحله بعد: فروشندگان ←</button>
          </div>
        </div>
      )}

      {/* ═══════ گام ۴: فروشندگان — توزیع خودکار ══════════════════ */}
      {step===4 && (()=>{
        return (
        <div>
          {/* هدر */}
          <div className="sw-card" style={{borderTop:'3px solid #34d399',marginBottom:12}}>
            <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:12}}>
              <div>
                <div className="sw-title">👥 توزیع تارگت بین فروشندگان</div>
                <div className="sw-sub" style={{marginBottom:0}}>سیستم بر اساس نرخ کانورت واقعی هر فروشنده تارگت تعیین کرده — فقط کمیسیون قابل تنظیم است</div>
              </div>
              <button className="sw-btn sw-btn-g sw-btn-sm" onClick={()=>smartDistribute()}>↺ توزیع مجدد</button>
            </div>

            {nonLinearRevenue>0 && (
              <div className="sw-insight" style={{marginBottom:10}}>
                <span>💡</span>
                <div>از هدفِ کل ({fmoney(target)})، {fmoney(nonLinearRevenue)} قراره از کانال‌هایِ غیرِخطی (وبینار/کمپین/محتوا) تامین بشه — پس فقط <b>{fmoney(linearTarget)}</b> بینِ فروشنده‌ها توزیع می‌شه.</div>
              </div>
            )}

            {/* نوار هدف */}
            <div style={{background:'rgba(255,255,255,0.02)',borderRadius:10,padding:'10px 14px',display:'flex',gap:14,alignItems:'center'}}>
              <div style={{flex:1}}>
                <div style={{display:'flex',justifyContent:'space-between',fontSize:11,color:'#64748b',marginBottom:4}}>
                  <span>توزیع‌شده: <b style={{color:'#e2e8f0'}}>{fmoney(totalSel)}</b></span>
                  <span>هدفِ فروشِ خطی: <b style={{color:'#a5b4fc'}}>{fmoney(linearTarget)}</b></span>
                </div>
                <div className="sw-bar-wrap">
                  <div className="sw-bar" style={{width:`${Math.min(totalSel/(linearTarget||1)*100,100)}%`,background:totalSel>=linearTarget?'#34d399':'#818cf8'}}/>
                </div>
              </div>
              <span style={{fontSize:14,fontWeight:800,color:totalSel>=linearTarget?'#34d399':'#fbbf24',whiteSpace:'nowrap'}}>{fp(Math.min(totalSel/(linearTarget||1)*100,999))}</span>
            </div>

            {/* legend */}
            <div style={{display:'flex',gap:12,marginTop:10,fontSize:10,color:'#475569',flexWrap:'wrap'}}>
              <span style={{display:'flex',alignItems:'center',gap:4}}><span style={{width:8,height:8,borderRadius:'50%',background:'#34d399',display:'inline-block'}}/> ماه گذشته</span>
              <span style={{display:'flex',alignItems:'center',gap:4}}><span style={{width:8,height:8,borderRadius:'50%',background:'#fbbf24',display:'inline-block'}}/> فصلی (۳ ماه)</span>
              <span style={{display:'flex',alignItems:'center',gap:4}}><span style={{width:8,height:8,borderRadius:'50%',background:'#60a5fa',display:'inline-block'}}/> کل تاریخچه</span>
              <span style={{display:'flex',alignItems:'center',gap:4}}><span style={{width:8,height:8,borderRadius:'50%',background:'#475569',display:'inline-block'}}/> پیش‌فرض</span>
            </div>
          </div>

          {/* کارت هر فروشنده */}
          {sellers.map((s,i)=>{
            const sc  = sCfg[s.id]||{};
            const rs  = realStats[s.id]||{};
            const pa  = periodActuals[s.id]||{};
            const col = COLORS[i%COLORS.length];
            const leads = selLeads(s.id);

            // منبع نرخ کانورت
            const convSrc = rs.last_month?.conv_rate != null ? 'last_month'
                          : rs.seasonal?.conv_rate   != null ? 'seasonal'
                          : rs.all_time?.conv_rate   != null ? 'all_time'
                          : 'default';
            const convVal = rs.conv_rate ?? defaultConvRate;
            const secVal  = rs.sec_conv  ?? 80;
            const dealVal = rs.avg_deal  ?? 0;

            const srcColor = convSrc==='last_month'?'#34d399':convSrc==='seasonal'?'#fbbf24':convSrc==='all_time'?'#60a5fa':'#475569';
            const srcLabel = convSrc==='last_month'?'ماه گذشته':convSrc==='seasonal'?'فصلی':convSrc==='all_time'?'کل تاریخچه':'پیش‌فرض';
            const srcLeads = convSrc==='last_month' ? rs.last_month?.leads : convSrc==='seasonal' ? rs.seasonal?.leads : rs.all_time?.leads;

            const selIncome = (sc.amount||0) * ((sc.commission_rate||10)/100);
            const coProfit  = (sc.amount||0) - selIncome;

            // میانگین معامله: قانونِ کاربر (۲۰۲۶-۰۸-۲۰): اولویتِ اول دستیِ ادمینه (sc.avg_deal) —
            // اگه ادمین صراحتاً یه عدد وارد کرده باشه (مثلاً «این ماه محصولِ ۱۵ میلیونی می‌فروشیم»)،
            // همون به‌جایِ میانگینِ واقعیِ تاریخی استفاده می‌شه. اگه دستی خالیه، میره سراغِ
            // واقعی → میانگینِ محصولاتِ گام ۳.
            const prodAvgDealVals = prods.map(p=>pCfg[p.id]?.avg_deal||0).filter(Boolean);
            const prodAvgDeal = prodAvgDealVals.length ? Math.round(prodAvgDealVals.reduce((a,b)=>a+b,0)/prodAvgDealVals.length) : 0;
            // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): «دستی‌بودن» دیگه با مقایسه‌ی عدد حدس زده نمی‌شه (باگ‌زا
            // بود، چون آمارِ واقعی drift می‌کنه) — یه فلگِ صریحِ ذخیره‌شده تصمیم می‌گیره.
            const isManualDeal = !!sc.avg_deal_manual;
            const effectiveDeal = sc.avg_deal || dealVal || prodAvgDeal;
            const isManualConv = !!sc.conv_rate_manual;
            const isManualSec  = !!sc.sec_conv_manual;

            return (
              <div key={s.id} className="sw-card" style={{marginBottom:8,padding:'14px 18px',borderRight:`3px solid ${col}55`}}>
                <div style={{display:'grid',gridTemplateColumns:'auto 1fr auto',gap:12,alignItems:'center'}}>
                  {/* نام */}
                  <div style={{display:'flex',alignItems:'center',gap:10}}>
                    <div className="sw-av" style={{background:col+'22',color:col,border:`1.5px solid ${col}55`,width:36,height:36,fontSize:14}}>{s.name?.[0]||'؟'}</div>
                    <div>
                      <div style={{fontWeight:800,fontSize:14}}>{s.name}</div>
                      <div style={{display:'flex',gap:5,marginTop:2}}>
                        <span style={{width:7,height:7,borderRadius:'50%',background:srcColor,display:'inline-block',marginTop:2}}/>
                        <span style={{fontSize:10,color:srcColor,fontWeight:700}}>{srcLabel}</span>
                        {srcLeads>0 && <span style={{fontSize:9,color:'#475569'}}>({fa(srcLeads)} لید)</span>}
                      </div>
                    </div>
                  </div>

                  {/* آمار */}
                  <div style={{display:'grid',gridTemplateColumns:'repeat(5,1fr)',gap:8}}>
                    {/* نرخِ کانورت — قانونِ کاربر (۲۰۲۶-۰۸-۲۴): اولویت با سیستمه، ادمین اگه بخواد
                        دستی override می‌کنه (مثلِ میانگینِ معامله). */}
                    <div style={{background:'rgba(255,255,255,0.025)',borderRadius:8,padding:'6px 8px',textAlign:'center'}}>
                      <div style={{fontSize:9,color:'#475569',fontWeight:700,marginBottom:3}}>نرخ کانورت</div>
                      <input type="number" step={0.5} min={0} max={100} dir="ltr"
                        value={sc.conv_rate ?? convVal}
                        onChange={e=>updS(s.id,'conv_rate', parseFloat(e.target.value)||0)}
                        style={{fontSize:12,fontWeight:800,padding:'4px 6px',textAlign:'center',width:'100%',
                          background:'transparent',border:'1px solid rgba(255,255,255,.08)',borderRadius:6,
                          color:isManualConv?'#fbbf24':srcColor}}/>
                      <div style={{fontSize:8,color:isManualConv?'#fbbf24':'#475569',marginTop:2}}>
                        {isManualConv ? 'دستی' : convSrc==='seasonal' ? 'فصلی' : convSrc==='all_time' ? 'کل تاریخچه' : convSrc==='last_month' ? 'ماه گذشته' : 'پیش‌فرض'}
                      </div>
                    </div>

                    {/* نرخِ پاسخ — قانونِ کاربر (۲۰۲۶-۰۸-۲۴): مثلِ نرخِ کانورت قابلِ‌ویرایش شد. */}
                    <div style={{background:'rgba(255,255,255,0.025)',borderRadius:8,padding:'6px 8px',textAlign:'center'}}>
                      <div style={{fontSize:9,color:'#475569',fontWeight:700,marginBottom:3}}>نرخ پاسخ</div>
                      <input type="number" step={0.5} min={0} max={100} dir="ltr"
                        value={sc.sec_conv ?? secVal}
                        onChange={e=>updS(s.id,'sec_conv', parseFloat(e.target.value)||0)}
                        style={{fontSize:12,fontWeight:800,padding:'4px 6px',textAlign:'center',width:'100%',
                          background:'transparent',border:'1px solid rgba(255,255,255,.08)',borderRadius:6,
                          color:isManualSec?'#fbbf24':'#94a3b8'}}/>
                      <div style={{fontSize:8,color:isManualSec?'#fbbf24':'#475569',marginTop:2}}>
                        {isManualSec ? 'دستی' : 'کل تاریخچه'}
                      </div>
                    </div>

                    {/* میانگین معامله — قانونِ کاربر (۲۰۲۶-۰۸-۲۰): دستی و قابلِ‌ویرایش، با اولویتِ اول */}
                    <div style={{background:'rgba(255,255,255,0.025)',borderRadius:8,padding:'6px 8px',textAlign:'center'}}>
                      <div style={{fontSize:9,color:'#475569',fontWeight:700,marginBottom:3}}>میانگین معامله</div>
                      <MoneyInput value={sc.avg_deal||0} onChange={v=>updS(s.id,'avg_deal',v)}
                        placeholder={dealVal>0?fmoney(dealVal):(prodAvgDeal>0?fmoney(prodAvgDeal):'دستی')}
                        style={{fontSize:12,fontWeight:800,padding:'4px 6px',textAlign:'center',color:isManualDeal?'#fbbf24':'#94a3b8'}}/>
                      <div style={{fontSize:8,color:isManualDeal?'#fbbf24':'#475569',marginTop:2}}>
                        {isManualDeal ? 'دستی' : dealVal>0 ? 'واقعی (قابلِ‌ویرایش)' : prodAvgDeal>0 ? 'از محصولات' : 'خالی بذار'}
                      </div>
                    </div>

                    {/* تارگتِ ماه — قانونِ کاربر (۲۰۲۶-۰۸-۲۴): دستی و قابلِ‌ویرایش، اولویت با سیستمه
                        (توزیعِ هوشمند) و ادمین بعدش می‌تونه override کنه؛ «توزیعِ مجدد» دوباره
                        از رویِ سیستم حساب می‌کنه و مقدارِ دستی رو پاک می‌کنه. */}
                    <div style={{background:'rgba(255,255,255,0.025)',borderRadius:8,padding:'6px 8px',textAlign:'center'}}>
                      <div style={{fontSize:9,color:'#475569',fontWeight:700,marginBottom:3}}>تارگت ماه</div>
                      <MoneyInput value={sc.amount||0} onChange={v=>updS(s.id,'amount',v)}
                        placeholder="۰"
                        style={{fontSize:12,fontWeight:800,padding:'4px 6px',textAlign:'center',color:'#a5b4fc'}}/>
                    </div>
                    <div style={{background:'rgba(255,255,255,0.025)',borderRadius:8,padding:'8px 10px',textAlign:'center'}}>
                      <div style={{fontSize:9,color:'#475569',fontWeight:700,marginBottom:3}}>لید نیاز (+{fa(leadBufferPct)}٪)</div>
                      <div style={{fontSize:13,fontWeight:800,color:'#fbbf24'}}>{leads>0?fnum(leads)+' لید':'—'}</div>
                      {(convSrc==='seasonal'||convSrc==='all_time')&&leads>0 && <div style={{fontSize:9,color:'#fbbf24',marginTop:2,lineHeight:1.3}}>{srcLabel}</div>}
                    </div>
                  </div>

                  {/* کمیسیون (تنها فیلد قابل ویرایش) */}
                  <div style={{display:'flex',flexDirection:'column',gap:6,alignItems:'center',minWidth:100}}>
                    <div style={{fontSize:10,color:'#64748b',fontWeight:700}}>کمیسیون ٪</div>
                    <div style={{display:'flex',alignItems:'center',gap:4}}>
                      <input className="sw-rate" type="number" step={0.5} min={0} max={50}
                        value={sc.commission_rate||10}
                        onChange={e=>updS(s.id,'commission_rate',parseFloat(e.target.value)||0)}/>
                      <span style={{fontSize:10,color:'#475569'}}>٪</span>
                    </div>
                    <div style={{fontSize:9,color:'#a5b4fc',textAlign:'center'}}>
                      <div>کمیسیون: {fmoney(selIncome)}</div>
                      <div style={{color:'#6ee7b7'}}>سود شرکت: {fmoney(coProfit)}</div>
                    </div>
                  </div>
                </div>

                {/* هشدار فصلی */}
                {convSrc==='seasonal' && leads>0 && (
                  <div style={{marginTop:10,padding:'6px 12px',background:'rgba(251,191,36,0.07)',border:'1px solid rgba(251,191,36,0.2)',borderRadius:8,fontSize:11,color:'#fbbf24',display:'flex',alignItems:'center',gap:6}}>
                    ⚠ با محاسبه فصلی — باید <b style={{margin:'0 4px'}}>{fnum(leads)} لید</b> دریافت کند (داده ماه گذشته کافی نبود)
                  </div>
                )}
                {convSrc==='default' && (
                  <div style={{marginTop:10,padding:'6px 12px',background:'rgba(100,116,139,0.07)',border:'1px solid rgba(100,116,139,0.15)',borderRadius:8,fontSize:11,color:'#64748b',display:'flex',alignItems:'center',gap:6}}>
                    ℹ داده تاریخی کافی نیست — از نرخ پیش‌فرض استفاده شده
                  </div>
                )}

                {/* عملکردِ واقعیِ همین دوره */}
                <div style={{marginTop:10,display:'flex',gap:8,flexWrap:'wrap',alignItems:'center'}}>
                  <span style={{fontSize:10,color:'#64748b',fontWeight:700}}>عملکردِ {periodLabelFa} تا الان:</span>
                  <span className="sw-tag sw-g">{fa(pa.sales_count||0)} فروش</span>
                  <span className="sw-tag sw-b">{fa(pa.consultations_count||0)} مشاوره</span>
                  <span className="sw-tag sw-v">{fa(pa.phones_count||0)} شماره دریافتی</span>
                  {/* قانونِ کاربر (۲۰۲۶-۰۸-۲۴): تفکیکِ نرخ‌ها/لیدِ نیاز به‌ازایِ هر محصول، بر
                      اساسِ سهمِ واقعیِ هر محصول از فروشِ تاریخیِ همین فروشنده. */}
                  <button onClick={()=>toggleProdBreakdown(s.id)} className="sw-btn sw-btn-ghost" style={{padding:'3px 10px',fontSize:10,marginRight:'auto'}}>
                    📦 تفکیکِ محصولات {expandedSeller===s.id?'▲':'▼'}
                  </button>
                </div>

                {expandedSeller===s.id && (()=>{
                  const bd = prodBreakdown[s.id];
                  if (!bd || bd.loading) return <div style={{marginTop:8,fontSize:11,color:'#64748b',textAlign:'center',padding:8}}>در حال بارگذاری...</div>;
                  // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): فقط محصولاتی که واقعاً برایِ همین ماه تارگتِ درآمد
                  // براشون تويِ مرحله‌ی «محصولات» ثبت شده — نه کلِ تاریخچه‌یِ فروش (بی‌ربط به گذشته).
                  const configured = bd.products.filter(p => (pCfg[p.product_id]?.target_revenue || 0) > 0);
                  if (!configured.length) return <div style={{marginTop:8,fontSize:11,color:'#64748b',textAlign:'center',padding:8}}>هنوز برایِ هیچ محصولی «تارگتِ درآمدِ خطی» تويِ مرحله‌ی «محصولات» ثبت نشده.</div>;
                  return (
                    <div style={{marginTop:10,overflowX:'auto'}}>
                      <table style={{width:'100%',borderCollapse:'collapse',fontSize:11}}>
                        <thead>
                          <tr style={{color:'#64748b',borderBottom:'1px solid rgba(255,255,255,.08)'}}>
                            <th style={{padding:'4px 6px',textAlign:'right'}}>محصول</th>
                            <th style={{padding:'4px 6px'}}>نرخِ کانورتِ واقعی</th>
                            <th style={{padding:'4px 6px'}}>نرخِ پاسخِ واقعی</th>
                            <th style={{padding:'4px 6px'}}>میانگینِ معامله</th>
                            <th style={{padding:'4px 6px'}}>تارگتِ این محصول</th>
                            <th style={{padding:'4px 6px'}}>لیدِ نیاز</th>
                          </tr>
                        </thead>
                        <tbody>
                          {configured.map(p=>{
                            // تارگتِ همین محصول = دقیقاً همون عددی که خودت تويِ مرحله‌ی «محصولات» زدی
                            // (نه یه حدسِ نسبتی از رويِ سهمِ تاریخی).
                            const productTarget = pCfg[p.product_id]?.target_revenue || 0;
                            // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): میانگینِ معامله هم اولویتش با همونی باشه که
                            // خودت تويِ مرحله‌ی «محصولات» برایِ این محصول زدی — نه میانگینِ تاریخی.
                            const manualProdDeal = pCfg[p.product_id]?.avg_deal || 0;
                            const ad  = manualProdDeal || p.avg_deal || dealVal || prodAvgDeal || 0;
                            const ovKey = `${s.id}::${p.product_id}`;
                            const ov = prodRateOv[ovKey] || {};
                            const isManualCr  = ov.conv_rate != null;
                            const isManualSec2= ov.sec_conv  != null;
                            // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): فال‌بکِ نهایی باید همون نرخِ مؤثرِ سطحِ
                            // فروشنده باشه (sc.conv_rate ?? convVal) — نه فقط نرخِ واقعیِ خام —
                            // وگرنه اگه محصولی نه override داره نه دیتایِ کافی، این ردیف با
                            // selLeads (که از sc.conv_rate استفاده می‌کنه) هماهنگ نمی‌مونه.
                            const cr  = (isManualCr  ? ov.conv_rate : p.conv_rate) || (sc.conv_rate ?? convVal);
                            const sec = (isManualSec2? ov.sec_conv  : p.sec_conv)  || (sc.sec_conv  ?? secVal);
                            let productLeads = 0;
                            if (ad>0 && cr>0 && sec>0 && productTarget>0) {
                              const salesN  = productTarget/ad;
                              const consult = salesN/(cr/100);
                              productLeads  = Math.ceil(Math.ceil(consult/(sec/100)) * (1+leadBufferPct/100));
                            }
                            return (
                              <tr key={p.product_id} style={{borderBottom:'1px solid rgba(255,255,255,.04)'}}>
                                <td style={{padding:'5px 6px',color:'#e2e8f0',fontWeight:600}}>{p.product_name}</td>
                                <td style={{padding:'5px 6px',textAlign:'center'}}>
                                  <input key={`${ovKey}_cr_${ov.conv_rate ?? 'x'}`} type="number" step={0.5} min={0} max={100} dir="ltr"
                                    defaultValue={isManualCr ? ov.conv_rate : (p.conv_rate ?? '')}
                                    placeholder={p.conv_rate!=null?fp(p.conv_rate):'کافی نیست'}
                                    onBlur={e=>{ const t=e.target.value; updProdRateOv(s.id,p.product_id,'conv_rate', t===''?null:(parseFloat(t)||0)); }}
                                    style={{width:52,fontSize:11,fontWeight:700,padding:'3px 4px',textAlign:'center',
                                      background:'transparent',border:'1px solid rgba(255,255,255,.12)',borderRadius:5,
                                      color:isManualCr?'#fbbf24':'#e2e8f0'}}/>
                                  {isManualCr && <div style={{fontSize:8,color:'#fbbf24'}}>دستی</div>}
                                </td>
                                <td style={{padding:'5px 6px',textAlign:'center'}}>
                                  <input key={`${ovKey}_sec_${ov.sec_conv ?? 'x'}`} type="number" step={0.5} min={0} max={100} dir="ltr"
                                    defaultValue={isManualSec2 ? ov.sec_conv : (p.sec_conv ?? '')}
                                    placeholder={p.sec_conv!=null?fp(p.sec_conv):'کافی نیست'}
                                    onBlur={e=>{ const t=e.target.value; updProdRateOv(s.id,p.product_id,'sec_conv', t===''?null:(parseFloat(t)||0)); }}
                                    style={{width:52,fontSize:11,fontWeight:700,padding:'3px 4px',textAlign:'center',
                                      background:'transparent',border:'1px solid rgba(255,255,255,.12)',borderRadius:5,
                                      color:isManualSec2?'#fbbf24':'#e2e8f0'}}/>
                                  {isManualSec2 && <div style={{fontSize:8,color:'#fbbf24'}}>دستی</div>}
                                </td>
                                <td style={{padding:'5px 6px',textAlign:'center',color:manualProdDeal?'#fbbf24':'#e2e8f0'}}>
                                  {ad>0?fmoney(ad):'—'}
                                  {manualProdDeal>0 && <div style={{fontSize:8,color:'#fbbf24'}}>دستی</div>}
                                </td>
                                <td style={{padding:'5px 6px',textAlign:'center',color:'#a5b4fc'}}>{productTarget>0?fmoney(Math.round(productTarget)):'—'}</td>
                                <td style={{padding:'5px 6px',textAlign:'center',color:'#fbbf24',fontWeight:700}}>{productLeads>0?fnum(productLeads)+' لید':'—'}</td>
                              </tr>
                            );
                          })}
                        </tbody>
                      </table>
                      <div style={{fontSize:9,color:'#475569',marginTop:6}}>
                        نرخِ کانورت/پاسخ از تاریخچه‌یِ واقعیِ همین فروشنده تويِ همین محصوله؛ میانگینِ معامله و تارگت دقیقاً همون عددهاییه که تويِ مرحله‌ی «محصولات» زدی (اگه دستی زده باشی).
                      </div>
                    </div>
                  );
                })()}
              </div>
            );
          })}

          <div className="sw-nav" style={{marginTop:16}}>
            <button className="sw-btn sw-btn-ghost" onClick={()=>setStep(3)}>← برگشت</button>
            <button className="sw-btn sw-btn-p" onClick={()=>setStep(5)}>مرحله بعد: تایید ←</button>
          </div>
        </div>
        );
      })()}

      {/* ═══════ گام ۵: تایید نهایی ══════════════════════════════ */}
      {step===5 && (
        <div>
          <div className="sw-card" style={{borderTop:'3px solid #34d399'}}>
            <div className="sw-title">✅ مرور نهایی</div>
            <div className="sw-sub">
              سبک‌های فعال:&nbsp;
              {[...models].map(m=>(
                <span key={m} className="sw-tag" style={{marginLeft:4,color:modelColor(m),background:modelColor(m)+'18',border:`1px solid ${modelColor(m)}33`}}>
                  {modelIcon(m)} {modelLabel(m)}
                </span>
              ))}
            </div>

            <div className="sw-kpi">
              {[
                {l:'هدف کل',           v:fmoney(target),       c:'#a5b4fc'},
                {l:'سهمِ فروشِ خطی (فروشنده‌ها)',v:fmoney(totalSel),     c:totalSel>=linearTarget?'#34d399':'#fbbf24'},
                {l:'جمع کمیسیون‌ها',   v:fmoney(totalComm),    c:'#f9a8d4'},
                {l:'سود خالص شرکت',    v:fmoney(totalPro),     c:'#34d399'},
                {l:'لید نیاز ماه (همه کانال‌ها)',v:fnum(totalLeads)+' لید',c:'#fbbf24'},
                ...(models.has('webinar')&&webinarStats.revenue>0?[{l:'درآمد تخمینی وبینار',v:fmoney(webinarStats.revenue),c:'#818cf8'},{l:'لید لازمِ وبینار',v:fnum(webinarStats.leads)+' لید',c:'#818cf8'}]:[]),
                ...(models.has('campaign')&&campaignStats.revenue>0?[{l:'درآمد تخمینی کمپین',v:fmoney(campaignStats.revenue),c:'#f9a8d4'},{l:'لید لازمِ کمپین',v:fnum(campaignStats.leads)+' لید',c:'#f9a8d4'}]:[]),
                ...(models.has('content')&&contentStats.revenue>0?[{l:'درآمد تخمینی تولید محتوا',v:fmoney(contentStats.revenue),c:'#fcd66b'},{l:'لید لازمِ تولید محتوا',v:fnum(contentStats.leads)+' لید',c:'#fcd66b'}]:[]),
              ].map((k,i)=>(
                <div key={i} className="sw-kpi-box">
                  <div className="sw-kpi-lbl">{k.l}</div>
                  <div className="sw-kpi-val" style={{color:k.c,fontSize:14}}>{k.v}</div>
                </div>
              ))}
            </div>

            {target>0 && (()=>{
              const covered = totalSel + nonLinearRevenue;
              return (
              <div style={{marginBottom:4}}>
                <div style={{display:'flex',justifyContent:'space-between',fontSize:11,color:'#64748b',marginBottom:4}}>
                  <span>پوشش هدف (همه کانال‌ها)</span>
                  <span style={{color:covered>=target?'#34d399':'#fbbf24',fontWeight:700}}>{fp(Math.min(covered/target*100,999))}</span>
                </div>
                <div className="sw-bar-wrap">
                  <div className="sw-bar" style={{width:`${Math.min(covered/target*100,100)}%`,background:covered>=target?'#34d399':'#818cf8'}}/>
                </div>
                {covered<target && <div style={{fontSize:11,color:'#f87171',marginTop:4}}>کسری: {fmoney(target-covered)}</div>}
              </div>
              );
            })()}
          </div>

          {/* جدول سودآوری */}
          <div className="sw-card">
            <div style={{fontSize:13,fontWeight:800,marginBottom:12}}>📊 سودآوری فروشندگان</div>
            <div style={{overflowX:'auto'}}>
              <table className="sw-tbl">
                <thead>
                  <tr>
                    <th style={{minWidth:130}}>فروشنده</th>
                    <th>تارگت درآمد</th>
                    <th style={{color:'#fbbf24'}}>لید نیاز</th>
                    <th>کمیسیون</th>
                    <th style={{color:'#a5b4fc'}}>درآمد فروشنده</th>
                    <th style={{color:'#6ee7b7'}}>سود شرکت</th>
                  </tr>
                </thead>
                <tbody>
                  {sellers.map((s,i)=>{
                    const sc=sCfg[s.id]||{};
                    const rs=realStats[s.id]||{};
                    const amt=sc.amount||0;
                    const com=(sc.commission_rate||10)/100;
                    const selInc=amt*com, co=amt-selInc;
                    const leads=selLeads(s.id);
                    const col=COLORS[i%COLORS.length];
                    return (
                      <tr key={s.id}>
                        <td>
                          <div style={{display:'flex',alignItems:'center',gap:8}}>
                            <div className="sw-av" style={{background:col+'22',color:col,border:`1.5px solid ${col}44`}}>{s.name?.[0]||'؟'}</div>
                            <div>
                              <div style={{fontWeight:700,fontSize:13}}>{s.name}</div>
                              <div style={{fontSize:9,color:'#475569'}}>کانورت {fp(rs.conv_rate??defaultConvRate)}</div>
                            </div>
                          </div>
                        </td>
                        <td style={{fontWeight:700}}>{amt?fmoney(amt):'—'}</td>
                        <td style={{color:'#fbbf24',fontWeight:700}}>{leads>0?fnum(leads):'—'}</td>
                        <td><span className="sw-tag sw-y">{fp(sc.commission_rate||10)}</span></td>
                        <td style={{color:'#a5b4fc',fontWeight:800}}>{selInc?fmoney(selInc):'—'}</td>
                        <td style={{color:'#6ee7b7',fontWeight:800}}>{co?fmoney(co):'—'}</td>
                      </tr>
                    );
                  })}
                </tbody>
                <tfoot>
                  <tr>
                    <td style={{fontWeight:800,fontSize:12}}>جمع</td>
                    <td style={{fontWeight:800}}>{fmoney(totalSel)}</td>
                    <td style={{color:'#fbbf24',fontWeight:700}}>{fnum(totalLeads)}</td>
                    <td/>
                    <td style={{color:'#a5b4fc',fontWeight:800}}>{fmoney(totalComm)}</td>
                    <td style={{color:'#6ee7b7',fontWeight:800}}>{fmoney(totalPro)}</td>
                  </tr>
                </tfoot>
              </table>
            </div>
          </div>

          {/* جدولِ گزارشِ محصولی — قانونِ کاربر (۲۰۲۶-۰۷-۲۹): دقیقاً مثلِ فرمِ کاغذیِ کارگاه‌ها
              (ردیف=معیار، ستون=هر محصول + یه ستونِ جمع)، همه‌ش از رویِ همون داده‌هایِ pCfg
              (که تویِ قدمِ «محصولات» ست شده) با ریاضیِ ساده محاسبه می‌شه. */}
          {prods.length > 0 && (
            <div className="sw-card">
              <div style={{fontSize:13,fontWeight:800,marginBottom:12}}>📋 گزارشِ تارگتِ محصولات</div>
              <div style={{overflowX:'auto'}}>
                {(() => {
                  const rowsDef = [
                    { key:'rev',     label:'مبلغِ فروش',      fmt:fmoney },
                    { key:'avg',     label:'میانگینِ فروش',    fmt:fmoney },
                    { key:'cnt',     label:'تعدادِ فروش',      fmt:fnum },
                    { key:'conv',    label:'نرخِ کانورتِ فروش', fmt:fp },
                    { key:'consult', label:'تعدادِ مشاوره انجام‌شده - فروشنده', fmt:fnum },
                    { key:'sec',     label:'نرخِ پاسخ‌دهی', fmt:fp },
                    { key:'numbers', label:'تعدادِ شماره دریافتی - تولید محتوا', fmt:fnum },
                    { key:'days',    label:'تعدادِ روزهایِ کاری در ماه', fmt:fnum },
                  ];
                  // قانونِ کاربر (۲۰۲۶-۰۷-۲۹): فقط محصولاتی که واقعاً براشون تارگت تعیین شده
                  // (مبلغ یا تعداد) نشون داده بشن — نه همه‌ی محصولاتِ فعال با «—» خالی.
                  const perProduct = prods
                    .map(p => {
                      const c = pCfg[p.id] || {};
                      const rev  = c.target_revenue || 0;
                      const avg  = c.avg_deal || 0;
                      // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): وقتی تارگت با «مبلغ» تعیین شده نه «تعدادِ
                      // واحد» (که حالتِ رایجه)، target_units صفر می‌مونه و کلِ ردیف‌هایِ زیرش
                      // (مشاوره/شماره دریافتی/نرخِ کلِ کانورت) به‌غلط صفر نشون داده می‌شدن —
                      // با اینکه مبلغ و نرخِ کانورتِ خودِ محصول درست بودن. حالا وقتی واحدِ صریح
                      // ثبت نشده، تعدادِ فروش از رويِ مبلغ/میانگینِ معامله حساب می‌شه (دقیقاً
                      // همون منطقی که تويِ لیدِ نیاز/تفکیکِ محصولات استفاده می‌شه).
                      const cnt  = c.target_units>0 ? c.target_units : (avg>0 ? Math.round(rev/avg) : 0);
                      const conv = c.sales_conv || 0;
                      const consult = conv > 0 ? Math.round(cnt / (conv/100)) : 0;
                      const sec  = c.sec_conv || 0;
                      const numbers = sec > 0 ? Math.round(consult / (sec/100)) : 0;
                      const days = c.work_days || 0;
                      return { product:p, rev, avg, cnt, conv, consult, sec, numbers, days };
                    })
                    .filter(r => r.rev > 0 || r.cnt > 0);
                  const totalRev = perProduct.reduce((a,r)=>a+r.rev,0);
                  const totalCnt = perProduct.reduce((a,r)=>a+r.cnt,0);
                  const totalConsult = perProduct.reduce((a,r)=>a+r.consult,0);
                  const totalNumbers = perProduct.reduce((a,r)=>a+r.numbers,0);
                  const totals = {
                    rev: totalRev, cnt: totalCnt,
                    avg: totalCnt>0 ? Math.round(totalRev/totalCnt) : 0,
                    // قانونِ کاربر (۲۰۲۶-۰۸-۲۴): گیت‌کردنِ رويِ totalCnt>0 باگ‌زا بود — وقتی
                    // totalConsult محاسبه‌شده بود ولی totalCnt به‌هردلیلی صفر می‌موند، کلِ
                    // درصد به‌غلط صفر می‌شد؛ الان گیت رويِ خودِ مخرج (totalConsult/totalNumbers)ه.
                    conv: totalConsult>0 ? Math.round(totalCnt/totalConsult*100*10)/10 : 0,
                    consult: totalConsult,
                    sec: totalNumbers>0 ? Math.round(totalConsult/totalNumbers*100*10)/10 : 0,
                    numbers: totalNumbers,
                    days: Math.max(...perProduct.map(r=>r.days), 0),
                  };
                  if (perProduct.length === 0) {
                    return <div style={{padding:20,textAlign:'center',color:'#64748b',fontSize:12}}>هنوز برایِ هیچ محصولی تارگت تعیین نشده — تویِ قدمِ «محصولات» تعدادِ فروش یا مبلغِ تارگت رو وارد کن.</div>;
                  }
                  return (
                    <table className="sw-tbl">
                      <thead>
                        <tr>
                          <th style={{textAlign:'right',minWidth:170}}>ردیف</th>
                          {perProduct.map(r => <th key={r.product.id}>{r.product.name}</th>)}
                          <th style={{color:'#a5b4fc'}}>تارگتِ کل</th>
                        </tr>
                      </thead>
                      <tbody>
                        {rowsDef.map(rd => (
                          <tr key={rd.key}>
                            <td style={{textAlign:'right',fontWeight:700}}>{rd.label}</td>
                            {perProduct.map(r => <td key={r.product.id}>{rd.fmt(r[rd.key])}</td>)}
                            <td style={{color:'#a5b4fc',fontWeight:800}}>{rd.fmt(totals[rd.key])}</td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  );
                })()}
              </div>
            </div>
          )}

          <div className="sw-insight">
            <span>📢</span>
            <div>پس از ذخیره، تارگت و نرخ‌ها در <b>داشبورد هر فروشنده</b> و <b>پنل مدیر فروش</b> نمایش داده می‌شود.</div>
          </div>

          <div className="sw-nav">
            <button className="sw-btn sw-btn-ghost" onClick={()=>setStep(4)}>← ویرایش فروشندگان</button>
            <button className="sw-btn sw-btn-g" style={{fontSize:14,padding:'12px 28px'}} onClick={save} disabled={saving}>
              {saving?'در حال ذخیره...':'✓ ذخیره و اعمال تارگت‌ها'}
            </button>
          </div>
        </div>
      )}
    </div>
  );
};
