// ==========================================
// gym-program-bundle.js
// ترکیب تمام فایل‌های JS پروژه در یک فایل
// بدون قابلیت افزودن کلاینت و برنامه جدید
// ==========================================

// ============================
// 1. CONSTANTS & GLOBALS
// ============================
const STORAGE_KEY = "gym-data";
const THEME_STORAGE_KEY = "gym-theme-v2";
const ACTIVE_PROGRAM_KEY = "gym-active-program-v2";
const PROGRAM_META_PREFIX = "gym-program-meta::";
const PROGRAM_DAYS_PREFIX = "gym-program-days::";
const STUDENTS_KEY = "gym-students-v2";
const CLIPBOARD_MOVE_KEY = "gym-clipboard-move-v2";
const CLIPBOARD_DAY_KEY = "gym-clipboard-day-v2";

// ============================
// 2. THEME
// ============================
const themes = {
  "neo-gym": {
    name: "نئو جیم",
    bodyClass: "theme-neo-gym",
    vars: {
      "--text": "#f2f7f4", "--muted": "#9aa8a0", "--panel": "#0f1513", "--panel-2": "#151d1a",
      "--card": "#141b18", "--card-2": "#1b2520", "--line": "rgba(214,255,228,.09)",
      "--line-2": "rgba(214,255,228,.16)", "--accent": "#7cff9b", "--accent-2": "#22c55e",
      "--accent-3": "rgba(124,255,155,.15)", "--danger": "#fb7185", "--warning": "#fbbf24",
      "--input-bg": "rgba(255,255,255,.035)", "--btn-text": "#04130a",
      "--page-grad": "radial-gradient(circle at 12% 12%, rgba(124,255,155,.14), transparent 24%), radial-gradient(circle at 88% 18%, rgba(34,197,94,.08), transparent 22%), radial-gradient(circle at 72% 84%, rgba(255,255,255,.045), transparent 20%), linear-gradient(145deg, #050806 0%, #0b1110 48%, #060908 100%)",
      "--texture": "linear-gradient(135deg, rgba(255,255,255,.018) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.018) 50%, rgba(255,255,255,.018) 75%, transparent 75%, transparent)",
      "--radius-shell": "28px", "--radius-panel": "26px", "--radius-card": "22px",
      "--radius-input": "16px", "--radius-chip": "999px",
      "--panel-border": "1px solid rgba(214,255,228,.10)",
      "--card-border": "1px solid rgba(214,255,228,.08)",
      "--shadow-shell": "0 24px 70px rgba(0,0,0,.42)",
      "--shadow-panel": "0 16px 42px rgba(0,0,0,.28)",
      "--shadow-card": "0 12px 28px rgba(0,0,0,.22)",
      "--panel-blur": "blur(18px)", "--card-blur": "none",
      "--header-bg": "linear-gradient(180deg, rgba(124,255,155,.07), rgba(255,255,255,.02)), rgba(12,18,16,.82)",
      "--button-style-bg": "rgba(255,255,255,.04)",
      "--button-style-border": "1px solid rgba(214,255,228,.10)",
      "--input-border": "1px solid rgba(214,255,228,.11)",
      "--input-shadow": "0 0 0 1px rgba(255,255,255,.01) inset",
      "--card-highlight": "linear-gradient(180deg, rgba(255,255,255,.055), rgba(255,255,255,.018))",
      "--panel-highlight": "linear-gradient(180deg, rgba(255,255,255,.045), rgba(255,255,255,.015))",
      "--grid-overlay-opacity": ".28", "--title-spacing": "0"
    }
  },
  "clean-sand": {
    name: "شن تمیز", bodyClass: "theme-clean-sand",
    vars: { "--text": "#2f332d", "--muted": "#747a70", "--panel": "#fffdf8", "--panel-2": "#f7f2e8", "--card": "#ffffff", "--card-2": "#fbf6ed", "--line": "rgba(47,51,45,.09)", "--line-2": "rgba(47,51,45,.16)", "--accent": "#b7791f", "--accent-2": "#975a16", "--accent-3": "rgba(183,121,31,.13)", "--danger": "#dc2626", "--warning": "#d97706", "--input-bg": "#f5efe4", "--btn-text": "#ffffff", "--page-grad": "radial-gradient(circle at 12% 8%, rgba(183,121,31,.08), transparent 22%), linear-gradient(180deg, #fbf7ef 0%, #f1eadf 100%)", "--texture": "none", "--radius-shell": "24px", "--radius-panel": "22px", "--radius-card": "18px", "--radius-input": "14px", "--radius-chip": "999px", "--panel-border": "1px solid rgba(47,51,45,.07)", "--card-border": "1px solid rgba(47,51,45,.075)", "--shadow-shell": "0 18px 38px rgba(64,54,38,.08)", "--shadow-panel": "0 12px 26px rgba(64,54,38,.065)", "--shadow-card": "0 8px 18px rgba(64,54,38,.055)", "--panel-blur": "none", "--card-blur": "none", "--header-bg": "rgba(255,253,248,.92)", "--button-style-bg": "#f6efe4", "--button-style-border": "1px solid rgba(47,51,45,.09)", "--input-border": "1px solid rgba(47,51,45,.10)", "--input-shadow": "none", "--card-highlight": "linear-gradient(180deg, rgba(255,255,255,1), rgba(255,255,255,.92))", "--panel-highlight": "linear-gradient(180deg, rgba(255,255,255,.96), rgba(255,255,255,.88))", "--grid-overlay-opacity": "0", "--title-spacing": "0" }
  },
  "clean-light": {
    name: "روشن تمیز", bodyClass: "theme-clean-light",
    vars: { "--text": "#111827", "--muted": "#667085", "--panel": "#ffffff", "--panel-2": "#f6f8fb", "--card": "#ffffff", "--card-2": "#fbfcfe", "--line": "rgba(17,24,39,.08)", "--line-2": "rgba(17,24,39,.15)", "--accent": "#2563eb", "--accent-2": "#1d4ed8", "--accent-3": "rgba(37,99,235,.12)", "--danger": "#dc2626", "--warning": "#d97706", "--input-bg": "#f8fafc", "--btn-text": "#ffffff", "--page-grad": "radial-gradient(circle at 10% 6%, rgba(37,99,235,.07), transparent 22%), linear-gradient(180deg, #f8fafc 0%, #eef2f7 100%)", "--texture": "none", "--radius-shell": "24px", "--radius-panel": "22px", "--radius-card": "18px", "--radius-input": "14px", "--radius-chip": "999px", "--panel-border": "1px solid rgba(17,24,39,.065)", "--card-border": "1px solid rgba(17,24,39,.07)", "--shadow-shell": "0 18px 42px rgba(15,23,42,.08)", "--shadow-panel": "0 12px 28px rgba(15,23,42,.065)", "--shadow-card": "0 8px 20px rgba(15,23,42,.055)", "--panel-blur": "none", "--card-blur": "none", "--header-bg": "rgba(255,255,255,.92)", "--button-style-bg": "#f8fafc", "--button-style-border": "1px solid rgba(17,24,39,.09)", "--input-border": "1px solid rgba(17,24,39,.10)", "--input-shadow": "0 1px 2px rgba(15,23,42,.04)", "--card-highlight": "linear-gradient(180deg, rgba(255,255,255,1), rgba(255,255,255,.94))", "--panel-highlight": "linear-gradient(180deg, rgba(255,255,255,1), rgba(255,255,255,.92))", "--grid-overlay-opacity": "0", "--title-spacing": "0" }
  },
  "midnight-blue": {
    name: "آبی نیمه‌شب", bodyClass: "theme-midnight-blue",
    vars: { "--text": "#eef6ff", "--muted": "#9fb3cc", "--panel": "#0b1424", "--panel-2": "#101b2e", "--card": "#121f35", "--card-2": "#172742", "--line": "rgba(191,219,254,.09)", "--line-2": "rgba(191,219,254,.17)", "--accent": "#60a5fa", "--accent-2": "#3b82f6", "--accent-3": "rgba(96,165,250,.15)", "--danger": "#fb7185", "--warning": "#fbbf24", "--input-bg": "rgba(6,16,31,.82)", "--btn-text": "#06111f", "--page-grad": "radial-gradient(circle at 18% 10%, rgba(96,165,250,.15), transparent 24%), radial-gradient(circle at 80% 18%, rgba(37,99,235,.10), transparent 22%), linear-gradient(145deg, #060c18 0%, #0b1730 52%, #060b15 100%)", "--texture": "radial-gradient(circle at 20% 20%, rgba(255,255,255,.025) 1px, transparent 1px)", "--radius-shell": "26px", "--radius-panel": "24px", "--radius-card": "20px", "--radius-input": "14px", "--radius-chip": "999px", "--panel-border": "1px solid rgba(147,197,253,.13)", "--card-border": "1px solid rgba(147,197,253,.11)", "--shadow-shell": "0 22px 64px rgba(0,0,0,.40)", "--shadow-panel": "0 14px 34px rgba(0,0,0,.28)", "--shadow-card": "0 10px 24px rgba(0,0,0,.21)", "--panel-blur": "blur(10px)", "--card-blur": "none", "--header-bg": "linear-gradient(180deg, rgba(96,165,250,.07), rgba(255,255,255,.02)), rgba(7,17,33,.84)", "--button-style-bg": "rgba(255,255,255,.04)", "--button-style-border": "1px solid rgba(147,197,253,.13)", "--input-border": "1px solid rgba(147,197,253,.14)", "--input-shadow": "0 0 0 1px rgba(255,255,255,.01) inset", "--card-highlight": "linear-gradient(180deg, rgba(147,197,253,.055), rgba(255,255,255,.012))", "--panel-highlight": "linear-gradient(180deg, rgba(147,197,253,.045), rgba(255,255,255,.012))", "--grid-overlay-opacity": ".18", "--title-spacing": "0.2px" }
  },
  "nord-frost": {
    name: "یخبندان نورد", bodyClass: "theme-nord-frost",
    vars: { "--text": "#263445", "--muted": "#66788c", "--panel": "rgba(248,251,255,.82)", "--panel-2": "rgba(239,246,252,.78)", "--card": "rgba(255,255,255,.88)", "--card-2": "rgba(244,248,252,.84)", "--line": "rgba(38,52,69,.10)", "--line-2": "rgba(38,52,69,.18)", "--accent": "#5e81ac", "--accent-2": "#4c6f98", "--accent-3": "rgba(94,129,172,.14)", "--danger": "#bf616a", "--warning": "#d08770", "--input-bg": "rgba(236,242,248,.72)", "--btn-text": "#ffffff", "--page-grad": "radial-gradient(circle at 12% 10%, rgba(94,129,172,.13), transparent 22%), radial-gradient(circle at 82% 15%, rgba(136,192,208,.14), transparent 24%), linear-gradient(145deg, #eef4f8 0%, #e5edf4 46%, #d8e3ec 100%)", "--texture": "linear-gradient(135deg, rgba(255,255,255,.24) 0%, transparent 42%)", "--radius-shell": "30px", "--radius-panel": "28px", "--radius-card": "24px", "--radius-input": "18px", "--radius-chip": "999px", "--panel-border": "1px solid rgba(255,255,255,.64)", "--card-border": "1px solid rgba(255,255,255,.82)", "--shadow-shell": "0 20px 46px rgba(86,110,132,.18)", "--shadow-panel": "0 14px 32px rgba(86,110,132,.15)", "--shadow-card": "0 9px 22px rgba(86,110,132,.12)", "--panel-blur": "blur(14px)", "--card-blur": "blur(8px)", "--header-bg": "rgba(255,255,255,.76)", "--button-style-bg": "rgba(255,255,255,.68)", "--button-style-border": "1px solid rgba(255,255,255,.78)", "--input-border": "1px solid rgba(255,255,255,.80)", "--input-shadow": "0 6px 18px rgba(86,110,132,.08)", "--card-highlight": "linear-gradient(180deg, rgba(255,255,255,.84), rgba(255,255,255,.58))", "--panel-highlight": "linear-gradient(180deg, rgba(255,255,255,.72), rgba(255,255,255,.46))", "--grid-overlay-opacity": "0", "--title-spacing": "0" }
  },
  "tokyo-night": {
    name: "شب توکیو", bodyClass: "theme-tokyo-night",
    vars: { "--text": "#e6edff", "--muted": "#9aa7d9", "--panel": "#171c2c", "--panel-2": "#1d2336", "--card": "#202740", "--card-2": "#26304c", "--line": "rgba(202,211,255,.09)", "--line-2": "rgba(202,211,255,.16)", "--accent": "#7aa2f7", "--accent-2": "#bb9af7", "--accent-3": "rgba(122,162,247,.15)", "--danger": "#f7768e", "--warning": "#e0af68", "--input-bg": "rgba(15,20,36,.92)", "--btn-text": "#0b1020", "--page-grad": "radial-gradient(circle at 16% 12%, rgba(122,162,247,.16), transparent 24%), radial-gradient(circle at 82% 16%, rgba(187,154,247,.13), transparent 22%), linear-gradient(145deg, #0f1322 0%, #181d31 50%, #0d1120 100%)", "--texture": "linear-gradient(transparent 96%, rgba(122,162,247,.055) 96%), linear-gradient(90deg, transparent 96%, rgba(187,154,247,.045) 96%)", "--radius-shell": "22px", "--radius-panel": "20px", "--radius-card": "18px", "--radius-input": "12px", "--radius-chip": "10px", "--panel-border": "1px solid rgba(122,162,247,.15)", "--card-border": "1px solid rgba(122,162,247,.12)", "--shadow-shell": "0 22px 56px rgba(0,0,0,.38)", "--shadow-panel": "0 14px 30px rgba(0,0,0,.27)", "--shadow-card": "0 9px 20px rgba(0,0,0,.20)", "--panel-blur": "none", "--card-blur": "none", "--header-bg": "linear-gradient(180deg, rgba(122,162,247,.06), rgba(187,154,247,.025)), #151a2a", "--button-style-bg": "linear-gradient(180deg, rgba(122,162,247,.055), rgba(255,255,255,.012))", "--button-style-border": "1px solid rgba(122,162,247,.15)", "--input-border": "1px solid rgba(122,162,247,.15)", "--input-shadow": "none", "--card-highlight": "linear-gradient(180deg, rgba(122,162,247,.045), rgba(187,154,247,.02))", "--panel-highlight": "linear-gradient(180deg, rgba(122,162,247,.035), rgba(187,154,247,.015))", "--grid-overlay-opacity": "0", "--title-spacing": "0.35px" }
  },
  "soft-peach": {
    name: "هلویی ملایم", bodyClass: "theme-soft-peach",
    vars: { "--text": "#3b302d", "--muted": "#806f68", "--panel": "#fffaf7", "--panel-2": "#fceee8", "--card": "#ffffff", "--card-2": "#fff5ef", "--line": "rgba(59,48,45,.085)", "--line-2": "rgba(59,48,45,.16)", "--accent": "#e76f51", "--accent-2": "#c9553d", "--accent-3": "rgba(231,111,81,.13)", "--danger": "#dc3f5f", "--warning": "#d08a24", "--input-bg": "#fff1eb", "--btn-text": "#ffffff", "--page-grad": "radial-gradient(circle at 14% 9%, rgba(231,111,81,.10), transparent 24%), radial-gradient(circle at 88% 14%, rgba(244,162,97,.10), transparent 22%), linear-gradient(180deg, #fff8f4 0%, #f8ebe4 100%)", "--texture": "none", "--radius-shell": "26px", "--radius-panel": "24px", "--radius-card": "20px", "--radius-input": "15px", "--radius-chip": "999px", "--panel-border": "1px solid rgba(59,48,45,.065)", "--card-border": "1px solid rgba(59,48,45,.07)", "--shadow-shell": "0 18px 38px rgba(88,55,44,.08)", "--shadow-panel": "0 12px 26px rgba(88,55,44,.06)", "--shadow-card": "0 8px 18px rgba(88,55,44,.055)", "--panel-blur": "none", "--card-blur": "none", "--header-bg": "rgba(255,250,247,.92)", "--button-style-bg": "#fff1eb", "--button-style-border": "1px solid rgba(59,48,45,.085)", "--input-border": "1px solid rgba(59,48,45,.095)", "--input-shadow": "none", "--card-highlight": "linear-gradient(180deg, rgba(255,255,255,1), rgba(255,255,255,.94))", "--panel-highlight": "linear-gradient(180deg, rgba(255,255,255,.98), rgba(255,255,255,.90))", "--grid-overlay-opacity": "0", "--title-spacing": "0" }
  },
  "emerald-glass": {
    name: "زمرد شیشه‌ای", bodyClass: "theme-emerald-glass",
    vars: { "--text": "#ecfff8", "--muted": "#9cc8bb", "--panel": "rgba(8,26,22,.72)", "--panel-2": "rgba(12,34,29,.76)", "--card": "rgba(15,42,36,.64)", "--card-2": "rgba(18,50,43,.72)", "--line": "rgba(187,255,232,.11)", "--line-2": "rgba(187,255,232,.19)", "--accent": "#34d399", "--accent-2": "#10b981", "--accent-3": "rgba(52,211,153,.16)", "--danger": "#fb7185", "--warning": "#fcd34d", "--input-bg": "rgba(255,255,255,.045)", "--btn-text": "#04130d", "--page-grad": "radial-gradient(circle at 14% 10%, rgba(52,211,153,.16), transparent 24%), radial-gradient(circle at 88% 18%, rgba(110,231,183,.09), transparent 20%), radial-gradient(circle at 50% 92%, rgba(20,184,166,.08), transparent 22%), linear-gradient(145deg, #04110e 0%, #09231d 48%, #040f0c 100%)", "--texture": "linear-gradient(120deg, rgba(255,255,255,.035) 0%, transparent 46%, rgba(255,255,255,.026) 100%)", "--radius-shell": "30px", "--radius-panel": "28px", "--radius-card": "24px", "--radius-input": "16px", "--radius-chip": "999px", "--panel-border": "1px solid rgba(187,255,232,.15)", "--card-border": "1px solid rgba(187,255,232,.13)", "--shadow-shell": "0 24px 62px rgba(0,0,0,.36)", "--shadow-panel": "0 15px 36px rgba(0,0,0,.26)", "--shadow-card": "0 10px 22px rgba(0,0,0,.18)", "--panel-blur": "blur(20px)", "--card-blur": "blur(14px)", "--header-bg": "linear-gradient(180deg, rgba(187,255,232,.06), rgba(255,255,255,.02)), rgba(7,22,18,.58)", "--button-style-bg": "rgba(255,255,255,.045)", "--button-style-border": "1px solid rgba(187,255,232,.15)", "--input-border": "1px solid rgba(187,255,232,.15)", "--input-shadow": "0 8px 24px rgba(0,0,0,.12)", "--card-highlight": "linear-gradient(180deg, rgba(255,255,255,.085), rgba(255,255,255,.022))", "--panel-highlight": "linear-gradient(180deg, rgba(255,255,255,.075), rgba(255,255,255,.02))", "--grid-overlay-opacity": "0", "--title-spacing": "0" }
  },
  "monochrome-pro": {
    name: "تک‌رنگ حرفه‌ای", bodyClass: "theme-monochrome-pro",
    vars: { "--text": "#f5f5f5", "--muted": "#a3a3a3", "--panel": "#171717", "--panel-2": "#1f1f1f", "--card": "#202020", "--card-2": "#292929", "--line": "rgba(255,255,255,.09)", "--line-2": "rgba(255,255,255,.16)", "--accent": "#ffffff", "--accent-2": "#d4d4d4", "--accent-3": "rgba(255,255,255,.12)", "--danger": "#f87171", "--warning": "#facc15", "--input-bg": "#121212", "--btn-text": "#111111", "--page-grad": "radial-gradient(circle at 12% 8%, rgba(255,255,255,.045), transparent 22%), linear-gradient(180deg, #0a0a0a 0%, #141414 100%)", "--texture": "none", "--radius-shell": "12px", "--radius-panel": "10px", "--radius-card": "8px", "--radius-input": "6px", "--radius-chip": "6px", "--panel-border": "1px solid rgba(255,255,255,.09)", "--card-border": "1px solid rgba(255,255,255,.085)", "--shadow-shell": "0 22px 56px rgba(0,0,0,.34)", "--shadow-panel": "0 12px 28px rgba(0,0,0,.24)", "--shadow-card": "0 8px 18px rgba(0,0,0,.18)", "--panel-blur": "none", "--card-blur": "none", "--header-bg": "#151515", "--button-style-bg": "#111111", "--button-style-border": "1px solid rgba(255,255,255,.12)", "--input-border": "1px solid rgba(255,255,255,.12)", "--input-shadow": "none", "--card-highlight": "linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,.008))", "--panel-highlight": "linear-gradient(180deg, rgba(255,255,255,.03), rgba(255,255,255,.006))", "--grid-overlay-opacity": "0", "--title-spacing": "0.5px" }
  },
  "royal-purple": {
    name: "بنفش سلطنتی", bodyClass: "theme-royal-purple",
    vars: { "--text": "#f7efff", "--muted": "#b8a6d5", "--panel": "#1a102b", "--panel-2": "#23163a", "--card": "#281a45", "--card-2": "#302052", "--line": "rgba(233,213,255,.09)", "--line-2": "rgba(233,213,255,.17)", "--accent": "#a78bfa", "--accent-2": "#7c3aed", "--accent-3": "rgba(167,139,250,.16)", "--danger": "#fb7185", "--warning": "#fbbf24", "--input-bg": "rgba(255,255,255,.035)", "--btn-text": "#12081d", "--page-grad": "radial-gradient(circle at 14% 12%, rgba(167,139,250,.18), transparent 24%), radial-gradient(circle at 82% 18%, rgba(124,58,237,.14), transparent 20%), radial-gradient(circle at 60% 90%, rgba(216,180,254,.08), transparent 22%), linear-gradient(145deg, #10071a 0%, #211038 50%, #0c0614 100%)", "--texture": "linear-gradient(135deg, rgba(255,255,255,.018) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.018) 50%, rgba(255,255,255,.018) 75%, transparent 75%, transparent)", "--radius-shell": "32px", "--radius-panel": "30px", "--radius-card": "26px", "--radius-input": "18px", "--radius-chip": "999px", "--panel-border": "1px solid rgba(216,180,254,.15)", "--card-border": "1px solid rgba(216,180,254,.13)", "--shadow-shell": "0 26px 70px rgba(16,6,28,.44)", "--shadow-panel": "0 16px 38px rgba(16,6,28,.30)", "--shadow-card": "0 11px 24px rgba(16,6,28,.22)", "--panel-blur": "blur(12px)", "--card-blur": "none", "--header-bg": "linear-gradient(180deg, rgba(167,139,250,.07), rgba(255,255,255,.02)), rgba(26,16,43,.80)", "--button-style-bg": "rgba(255,255,255,.04)", "--button-style-border": "1px solid rgba(216,180,254,.15)", "--input-border": "1px solid rgba(216,180,254,.15)", "--input-shadow": "none", "--card-highlight": "linear-gradient(180deg, rgba(255,255,255,.055), rgba(167,139,250,.02))", "--panel-highlight": "linear-gradient(180deg, rgba(255,255,255,.045), rgba(167,139,250,.018))", "--grid-overlay-opacity": "0.14", "--title-spacing": "0.2px" }
  }
};

function loadGlobalTheme() {
  try {
    const savedTheme = localStorage.getItem(THEME_STORAGE_KEY);
    return savedTheme && themes[savedTheme] ? savedTheme : "neo-gym";
  } catch (err) {
    console.error("خطا در خواندن تم سراسری", err);
    return "neo-gym";
  }
}

function saveGlobalTheme(themeName) {
  try {
    localStorage.setItem(THEME_STORAGE_KEY, themeName);
  } catch (err) {
    console.error("خطا در ذخیره تم سراسری", err);
  }
}

function applyTheme(themeKey, options = {}) {
  const { save = true } = options;
  const safeThemeKey = themes[themeKey] ? themeKey : "neo-gym";
  const theme = themes[safeThemeKey];

  document.documentElement.setAttribute("data-theme", safeThemeKey);

  // Apply theme to both themes object vars AND our new CSS variables
  Object.entries(theme.vars).forEach(([key, val]) => {
    document.documentElement.style.setProperty(key, val);
  });

  // Map theme vars to our new CSS variable system
  const mapping = {
    '--panel': '--app-bg',
    '--card': '--card-bg',
    '--text': '--text',
    '--muted': '--text-muted',
    '--accent': '--accent',
    '--accent-2': '--accent-hover',
    '--accent-3': '--accent-light',
    '--danger': '--danger',
    '--input-bg': '--input-bg',
    '--input-border': '--input-border',
    '--line': '--border',
    '--panel-2': '--card-bg'
  };

  Object.entries(mapping).forEach(([themeVar, cssVar]) => {
    const val = theme.vars[themeVar];
    if (val) {
      document.documentElement.style.setProperty(cssVar, val);
    }
  });

  // Handle derived variables
  const panelColor = theme.vars['--panel'] || '#ffffff';
  const lineColor = theme.vars['--line'] || 'rgba(0,0,0,0.08)';
  const headerBg = theme.vars['--header-bg'] || '#f8f9fa';

  document.documentElement.style.setProperty('--sidebar-bg', panelColor);
  document.documentElement.style.setProperty('--sidebar-border', lineColor);
  document.documentElement.style.setProperty('--titlebar-bg', headerBg);
  document.documentElement.style.setProperty('--titlebar-border', lineColor);
  document.documentElement.style.setProperty('--accent-glow', theme.vars['--accent-3'] || 'rgba(37,99,235,0.1)');

  const themeClasses = Object.values(themes).map((t) => t.bodyClass);
  document.body.classList.remove(...themeClasses);
  document.body.classList.add(theme.bodyClass);
  document.body.style.background = theme.vars["--page-grad"];

  const themeSelect = document.getElementById("themeSelect");
  if (themeSelect) {
    themeSelect.value = safeThemeKey;
  }

  state.theme = safeThemeKey;
  if (save) saveGlobalTheme(safeThemeKey);
}

// ============================
// Shared Clipboard (Local Storage)
// ============================
function saveMoveToClipboard(item) {
  try {
    localStorage.setItem(CLIPBOARD_MOVE_KEY, JSON.stringify(item));
    state.clipboard = item;
    updatePasteButtons();
    showSuccessToast('کپی موفق', 'حرکت در کلیپبورد ذخیره شد', 2000);
  } catch (e) {
    console.error("خطا در ذخیره کلیپبورد حرکت", e);
    showErrorToast('خطا', 'مشکلی در کپی حرکت پیش آمد', 2000);
  }
}

function loadMoveFromClipboard() {
  try {
    const raw = localStorage.getItem(CLIPBOARD_MOVE_KEY);
    if (!raw) return null;
    return JSON.parse(raw);
  } catch (e) {
    localStorage.removeItem(CLIPBOARD_MOVE_KEY);
    return null;
  }
}

function clearMoveClipboard() {
  localStorage.removeItem(CLIPBOARD_MOVE_KEY);
  state.clipboard = null;
  updatePasteButtons();
}

function saveDayToClipboard(dayData) {
  try {
    localStorage.setItem(CLIPBOARD_DAY_KEY, JSON.stringify(dayData));
    state.dayClipboard = dayData;
    updatePasteButtons();
    showSuccessToast('کپی موفق', `جلسه "${dayData.name}" در کلیپبورد ذخیره شد`, 2000);
  } catch (e) {
    console.error("خطا در ذخیره کلیپبورد جلسه", e);
    showErrorToast('خطا', 'مشکلی در کپی جلسه پیش آمد', 2000);
  }
}

function loadDayFromClipboard() {
  try {
    const raw = localStorage.getItem(CLIPBOARD_DAY_KEY);
    if (!raw) return null;
    return JSON.parse(raw);
  } catch (e) {
    localStorage.removeItem(CLIPBOARD_DAY_KEY);
    return null;
  }
}

function clearDayClipboard() {
  localStorage.removeItem(CLIPBOARD_DAY_KEY);
  state.dayClipboard = null;
  updatePasteButtons();
}

function clearAllClipboards() {
  clearMoveClipboard();
  clearDayClipboard();
  showInfoToast('پاکسازی شد', 'کلیپبورد حرکت و جلسه پاک شد', 2000);
}

// ============================
// 3. STORAGE
// ============================
function getProgramStorageKey(studentId, programId, type = 'days') {
  const prefix = type === 'meta' ? PROGRAM_META_PREFIX : PROGRAM_DAYS_PREFIX;
  return `${prefix}${studentId}::${programId}`;
}

function loadActiveProgramRef() {
  try {
    const raw = localStorage.getItem(ACTIVE_PROGRAM_KEY);
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== "object") return null;
    if (!parsed.studentId || !parsed.programId) return null;
    return { studentId: parsed.studentId, programId: parsed.programId };
  } catch (error) { return null; }
}

function saveActiveProgramRef(studentId, programId) {
  localStorage.setItem(ACTIVE_PROGRAM_KEY, JSON.stringify({ studentId, programId }));
}

function clearActiveProgramRef() {
  localStorage.removeItem(ACTIVE_PROGRAM_KEY);
}

function createDefaultDays() {
  return [
    { name: "جلسه ۱", items: [] },
    { name: "جلسه ۲", items: [] },
    { name: "جلسه ۳", items: [] }
  ];
}

function normalizeWorkoutItem(item) {
  if (!item || typeof item !== "object") return null;
  return { ...item, uid: item.uid || uid() };
}

function normalizeDay(day, index) {
  if (!day || typeof day !== "object") return { name: `جلسه ${index + 1}`, items: [] };
  return {
    name: typeof day.name === "string" && day.name.trim() ? day.name : `جلسه ${index + 1}`,
    items: Array.isArray(day.items) ? day.items.map(normalizeWorkoutItem).filter(Boolean) : []
  };
}

function loadProgramDataByRef(studentId, programId) {
  try {
    const key = PROGRAM_DAYS_PREFIX + studentId + "::" + programId;
    const raw = localStorage.getItem(key);
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== "object") return null;

    let studentName = "";
    if (studentId) {
      try {
        const students = JSON.parse(localStorage.getItem(STUDENTS_KEY) || '[]');
        const student = students.find(s => s.id === studentId);
        if (student && student.name) {
          studentName = student.name;
        }
      } catch(e) {
        console.error("خطا در خواندن نام کلاینت", e);
      }
    }

    return {
      days: Array.isArray(parsed.days) ? parsed.days.map(normalizeDay) : createDefaultDays(),
      theme: loadGlobalTheme(),
      studentName: studentName || (typeof parsed.studentName === "string" ? parsed.studentName : ""),
      clipboard: parsed.clipboard ? normalizeWorkoutItem(parsed.clipboard) : null,
      dayClipboard: parsed.dayClipboard || null
    };
  } catch (error) {
    console.error("خطا در خواندن دیتای برنامه", error);
    return null;
  }
}

function saveProgramDataByRef(studentId, programId, data) {
  try {
    localStorage.setItem(getProgramStorageKey(studentId, programId), JSON.stringify(data));
  } catch (error) {
    console.error("خطا در ذخیره دیتای برنامه", error);
  }
}

function deleteProgramDataByRef(studentId, programId) {
  try {
    localStorage.removeItem(getProgramStorageKey(studentId, programId));
  } catch (error) {
    console.error("خطا در حذف دیتای برنامه", error);
  }
}

function loadAppData() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== "object") return null;
    return {
      days: Array.isArray(parsed.days) ? parsed.days.map(normalizeDay) : createDefaultDays(),
      theme: typeof parsed.theme === "string" && parsed.theme.trim() ? parsed.theme : "neo-gym",
      studentName: typeof parsed.studentName === "string" ? parsed.studentName : "",
      clipboard: parsed.clipboard ? normalizeWorkoutItem(parsed.clipboard) : null,
      dayClipboard: parsed.dayClipboard || null
    };
  } catch (err) {
    console.error("خطا در خواندن اطلاعات از localStorage", err);
    return null;
  }
}

let saveTimeout = null;
function saveAppData() {
  if (saveTimeout) clearTimeout(saveTimeout);

  saveTimeout = setTimeout(() => {
    try {
      saveGlobalTheme(state.theme || "neo-gym");
      const data = {
        days: Array.isArray(state.days) ? state.days : createDefaultDays(),
        studentName: state.studentName || ""
      };
      if (state.activeStudentId && state.activeProgramId) {
        saveProgramDataByRef(state.activeStudentId, state.activeProgramId, data);
      } else {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
      }
    } catch (err) {
      console.error("خطا در ذخیره اطلاعات در localStorage", err);
    }
  }, 300);
}

function loadDrawerStudents() {
  try {
    const raw = localStorage.getItem(STUDENTS_KEY);
    if (!raw) return [];
    const parsed = JSON.parse(raw);
    if (!Array.isArray(parsed)) return [];
    return parsed.map(s => ({ ...s, isOpen: false }));
  } catch (error) { return []; }
}

function saveDrawerStudents() {
  const clean = drawerStudents.map(({ isOpen, ...rest }) => rest);
  localStorage.setItem(STUDENTS_KEY, JSON.stringify(clean));
}

// ============================
// 4. UTILS
// ============================
function uid() {
  return Math.random().toString(36).slice(2, 9) + Date.now().toString(36).slice(-4);
}

function deepCloneWorkoutItem(item) {
  return {
    ...item,
    uid: uid(),
    subsets: (item.subsets || []).map((sub) => ({ ...sub, uid: uid() }))
  };
}

function toNumber(value) {
  const n = parseInt(value, 10);
  return isNaN(n) ? 0 : n;
}

function toPersianDigits(value) {
  return String(value).replace(/\d/g, (d) => "۰۱۲۳۴۵۶۷۸۹"[d]);
}

function escapeHtml(str = "") {
  return String(str)
      .replaceAll("&", "&amp;")
      .replaceAll("<", "&lt;")
      .replaceAll(">", "&gt;")
      .replaceAll('"', "&quot;")
      .replaceAll("'", "&#039;");
}

function sanitizeFileName(text = "") {
  return String(text).replace(/[\\/:*?"<>|]/g, "-").trim();
}

function normalizeCell(value, suffix = "") {
  if (value === null || value === undefined || value === "") return "—";
  return `${escapeHtml(String(value))}${suffix}`;
}

function waitForBrowserPaint() {
  return new Promise((resolve) => {
    requestAnimationFrame(() => requestAnimationFrame(resolve));
  });
}

function canvasToBlob(canvas, type = "image/jpeg", quality = 0.95) {
  return new Promise((resolve) => canvas.toBlob(resolve, type, quality));
}

async function downloadBlob(blob, fileName) {
  if (!blob) throw new Error("ساخت فایل تصویر ناموفق بود.");
  const link = document.createElement("a");
  const url = URL.createObjectURL(blob);
  link.href = url;
  link.download = fileName;
  document.body.appendChild(link);
  link.click();
  link.remove();
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}

function numberToPersianWord(num) {
  const map = {
    1: "اول", 2: "دوم", 3: "سوم", 4: "چهارم", 5: "پنجم",
    6: "ششم", 7: "هفتم", 8: "هشتم", 9: "نهم", 10: "دهم",
    11: "یازدهم", 12: "دوازدهم", 13: "سیزدهم", 14: "چهاردهم", 15: "پانزدهم"
  };
  return map[num] || num;
}

function getExportThemeColors() {
  const styles = getComputedStyle(document.documentElement);
  return {
    text: styles.getPropertyValue("--text").trim() || "#1f2937",
    muted: styles.getPropertyValue("--muted").trim() || "#6b7280",
    accent: styles.getPropertyValue("--accent").trim() || "#22c55e",
    accent2: styles.getPropertyValue("--accent-2").trim() || "#16a34a",
    line: styles.getPropertyValue("--line-2").trim() || "rgba(0,0,0,.12)",
    font: styles.getPropertyValue("--font-main").trim() || "Tahoma, Arial, sans-serif"
  };
}

function getActiveProgramName() {
  if (!state.activeStudentId || !state.activeProgramId) return "";
  const student = drawerStudents.find(item => item.id === state.activeStudentId);
  if (!student) return "";
  const program = Array.isArray(student.programs)
      ? student.programs.find(item => item.id === state.activeProgramId)
      : null;
  return program?.name || "";
}

function updateHeaderTitle() {
  const headerTitleEl = document.getElementById("headerTitle");
  const headerStudentName = document.getElementById("headerStudentName");

  const pName = getActiveProgramName().trim();
  const sName = (state.studentName || "").trim();

  if (headerTitleEl) {
    headerTitleEl.textContent = pName || "سیستم طراحی برنامه تمرینی";
  }

  if (headerStudentName) {
    headerStudentName.textContent = sName || "تعریف نشده";
  }
}

async function safeHtml2Canvas(element) {
  const changed = [];
  const all = [element, ...element.querySelectorAll("*")];

  for (const node of all) {
    const style = getComputedStyle(node);
    const props = [
      "color", "backgroundColor", "borderTopColor", "borderRightColor",
      "borderBottomColor", "borderLeftColor", "outlineColor", "textDecorationColor"
    ];

    for (const prop of props) {
      const value = style[prop];
      if (value && value.includes("color(")) {
        const oldInline = node.style[prop];
        node.style[prop] = "#000000";
        changed.push({ node, prop, oldInline });
      }
    }
  }

  try {
    return await html2canvas(element, {
      useCORS: true,
      backgroundColor: "#ffffff",
      scale: 2
    });
  } finally {
    for (const item of changed) {
      item.node.style[item.prop] = item.oldInline;
    }
  }
}

// ============================
// 5. STATE
// ============================
const initialActiveProgramRef = loadActiveProgramRef();
const persistedData = initialActiveProgramRef
    ? (loadProgramDataByRef(initialActiveProgramRef.studentId, initialActiveProgramRef.programId) || loadAppData())
    : loadAppData();

const state = {
  activeCategory: "همه",
  pendingInsertIndex: null,
  search: "",
  currentDay: 0,
  days: persistedData?.days || createDefaultDays(),
  dragSource: null,
  theme: persistedData?.theme || "neo-gym",
  clipboard: loadMoveFromClipboard() || null,
  dayClipboard: loadDayFromClipboard() || null,
  studentName: persistedData?.studentName || "",
  activeStudentId: initialActiveProgramRef?.studentId || null,
  activeProgramId: initialActiveProgramRef?.programId || null
};

// ============================
// 6. UI - ادامه توابع رندر
// ============================
const categoryOrder = [
  "همه",
  "سینه",
  "زیربغل و پشت",
  "سرشانه",
  "کول",
  "چهارسر ران",
  "پشت ران و همسترینگ",
  "باسن - سرینی",
  "داخل ران",
  "خارج ران",
  "ساق",
  "جلو بازو",
  "پشت بازو",
  "ساعد",
  "شکم و فیله",
];

function getFilteredExercises() {
  return exercises.filter((ex) => {
    const byCategory = state.activeCategory === "همه" || ex.category === state.activeCategory;
    const bySearch =
        ex.name.includes(state.search) ||
        ex.category.includes(state.search) ||
        ex.meta.includes(state.search);
    return byCategory && bySearch;
  });
}

function createWorkoutItem(ex) {
  return {
    uid: uid(),
    exerciseId: ex.id,
    name: ex.name,
    category: ex.category,
    image: ex.image || null,
    sets: "",
    reps: "",
    rest: "",
    note: "",
    subsets: []
  };
}

function createSubset() {
  return {
    uid: uid(),
    note: "",
    sets: "",
    reps: "",
    rest: ""
  };
}

function updatePasteButtons() {
  const moveClipboard = loadMoveFromClipboard();
  const dayClipboard = loadDayFromClipboard();

  state.clipboard = moveClipboard;
  state.dayClipboard = dayClipboard;

  const pasteBtn = document.getElementById("pasteBtn");
  if (pasteBtn) {
    pasteBtn.disabled = !moveClipboard;
    pasteBtn.textContent = "جایگذاری حرکت";
  }

  const pasteDayBtn = document.getElementById("pasteDayBtn");
  if (pasteDayBtn) {
    pasteDayBtn.disabled = !dayClipboard;
    pasteDayBtn.textContent = "جایگذاری جلسه";
  }
}

function renderCategories() {
  const categoryButtons = document.getElementById("categoryButtons");
  if (!categoryButtons) return;
  categoryButtons.innerHTML = "";
  categoryOrder.forEach((cat) => {
    const btn = document.createElement("button");
    btn.className = "category-btn" + (state.activeCategory === cat ? " active" : "");
    btn.textContent = cat;
    btn.addEventListener("click", () => {
      state.activeCategory = cat;
      renderCategories();
      renderExerciseList();
    });
    categoryButtons.appendChild(btn);
  });
}

function renderExerciseList() {
  const exerciseList = document.getElementById("exerciseList");
  if (!exerciseList) return;
  const filtered = getFilteredExercises();
  const exerciseCount = document.getElementById("exerciseCount");
  exerciseList.innerHTML = "";
  if (exerciseCount) exerciseCount.textContent = `${filtered.length} حرکت`;

  filtered.forEach((ex) => {
    const card = document.createElement("div");
    card.className = "exercise-card";
    card.draggable = true;
    card.dataset.exerciseId = ex.id;
    card.innerHTML = `
      <div class="exercise-top">
        <div class="exercise-name">${ex.name}</div>
      </div>
      <div class="exercise-meta">
        <span class="exercise-tag">${ex.category}</span>
        ${ex.meta ? `<span class="exercise-meta-separator">•</span> ${ex.meta}` : ''}
      </div>
    `;
    card.addEventListener("dragstart", (e) => {
      state.dragSource = { type: "bank", exerciseId: ex.id };
      e.dataTransfer.setData("text/plain", JSON.stringify(state.dragSource));
      if (ex.image) {
        const dragIcon = document.createElement('img');
        dragIcon.src = ex.image;
        dragIcon.width = 60; dragIcon.height = 60;
        dragIcon.style.cssText = 'position:fixed;top:-1000px;border-radius:8px;';
        document.body.appendChild(dragIcon);
        e.dataTransfer.setDragImage(dragIcon, 30, 30);
        setTimeout(() => document.body.removeChild(dragIcon), 0);
      }
    });
    exerciseList.appendChild(card);
  });

  if (!filtered.length) {
    exerciseList.innerHTML = `<div class="empty-state"><div><strong>حرکتی پیدا نشد</strong><div>جستجو یا دسته‌بندی را تغییر بده</div></div></div>`;
  }
}

function renderDays() {
  const daysBar = document.getElementById("daysBar");
  if (!daysBar) return;
  daysBar.innerHTML = "";

  state.days.forEach((day, index) => {
    const wrapper = document.createElement("div");
    wrapper.className = "day-btn-wrapper";

    const btn = document.createElement("button");
    btn.className = "day-btn" + (state.currentDay === index ? " active" : "");
    btn.textContent = day.name;

    btn.addEventListener("dblclick", (e) => {
      e.preventDefault();
      const newName = prompt("نام جدید جلسه:", day.name);
      if (newName && newName.trim()) {
        day.name = newName.trim();
        renderDays();
        renderWorkoutList();
        saveAppData();
      }
    });

    btn.addEventListener("contextmenu", (e) => {
      e.preventDefault();
      showDayContextMenu(e, index);
    });

    btn.addEventListener("click", () => {
      state.currentDay = index;
      renderDays();
      renderWorkoutList();
      saveAppData();
    });

    wrapper.appendChild(btn);

    if (state.days.length > 1) {
      const deleteBtn = document.createElement("button");
      deleteBtn.className = "day-delete-btn";
      deleteBtn.innerHTML = "✕";
      deleteBtn.title = "حذف جلسه";
      deleteBtn.addEventListener("click", (e) => {
        e.stopPropagation();
        if (confirm(`جلسه "${day.name}" حذف شود؟ تمام حرکات این جلسه نیز حذف خواهند شد.`)) {
          state.days.splice(index, 1);
          if (state.currentDay >= state.days.length) {
            state.currentDay = state.days.length - 1;
          }
          renderDays();
          renderWorkoutList();
          saveAppData();
        }
      });
      wrapper.appendChild(deleteBtn);
    }

    daysBar.appendChild(wrapper);
  });

  const addBtn = document.createElement("button");
  addBtn.className = "add-day-btn";
  addBtn.textContent = "＋ افزودن جلسه";
  addBtn.addEventListener("click", () => {
    const next = state.days.length + 1;
    state.days.push({ name: `جلسه ${numberToPersianWord(next) || next}`, items: [] });
    state.currentDay = state.days.length - 1;
    renderDays();
    renderWorkoutList();
    saveAppData();
  });
  daysBar.appendChild(addBtn);
}

function renderWorkoutList() {
  const workoutList = document.getElementById("workoutList");
  if (!workoutList) return;
  const day = state.days[state.currentDay];
  updatePasteButtons();
  workoutList.innerHTML = "";

  if (day.items.length === 0) {
    workoutList.innerHTML = `<div class="empty-state"><div><strong>هنوز حرکتی اضافه نشده</strong><div>حرکات را از بانک حرکات بکشید و اینجا رها کنید</div></div></div>`;
    return;
  }

  day.items.forEach((item, index) => {
    const hasValidImage = item.image &&
        item.image !== "asset/exercise-images/undefined" &&
        !item.image.includes("undefined") &&
        item.image.trim() !== "";

    const dragHandleHtml = hasValidImage
        ? `<img src="${item.image}" alt="${item.name}" class="drag-handle-img" onerror="this.style.display='none';this.parentElement.querySelector('.drag-handle-icon').style.display='flex'">`
        : `<span class="drag-handle-icon">⋮⋮</span>`;

    const el = document.createElement("div");
    el.className = "workout-item";
    el.draggable = true;
    el.dataset.uid = item.uid;
    el.dataset.index = index;

    el.innerHTML = `
      <div class="workout-main">
        <div class="workout-title-row">
          <div class="drag-handle">${dragHandleHtml}</div>
          <div class="workout-name">${escapeHtml(item.name)}</div>
          <div class="item-actions">
            <button class="action-btn subset-btn" title="افزودن زیرست">+</button>
            <button class="action-btn copy" title="کپی">⧉</button>
            <button class="action-btn delete" title="حذف">✕</button>
          </div>
        </div>
        <div class="workout-fields">
          <div class="field"><label>توضیح / حالت</label><input type="text" value="${escapeHtml(item.note || "")}" data-field="note" placeholder="مثلاً سنگین" /></div>
          <div class="field"><label>تعداد ست</label><div class="field-control"><button class="mini-step" data-step-field="sets" data-step="-1">−</button><input type="text" value="${item.sets}" data-field="sets" placeholder="3" /><button class="mini-step" data-step-field="sets" data-step="1">+</button></div></div>
          <div class="field"><label>تکرار</label><div class="field-control"><button class="mini-step" data-step-field="reps" data-step="-1">−</button><input type="text" value="${item.reps}" data-field="reps" placeholder="12" /><button class="mini-step" data-step-field="reps" data-step="1">+</button></div></div>
          <div class="field"><label>استراحت (دقیقه)</label><div class="field-control"><button class="mini-step" data-step-field="rest" data-step="-1">−</button><input type="text" value="${item.rest}" data-field="rest" placeholder="60" /><button class="mini-step" data-step-field="rest" data-step="1">+</button></div></div>
        </div>
        <div class="subsets-wrap">${(item.subsets || []).map((sub, subIndex) => `
          <div class="subset-item" data-subuid="${sub.uid}">
            <div class="field"><label>توضیح</label><input type="text" value="${escapeHtml(sub.note)}" data-subfield="note" data-subindex="${subIndex}" placeholder="زیرست" /></div>
            <div class="field"><label>ست</label><div class="field-control"><button class="mini-step" data-substep-field="sets" data-subindex="${subIndex}" data-step="-1">−</button><input type="text" value="${sub.sets}" data-subfield="sets" data-subindex="${subIndex}" placeholder="3" /><button class="mini-step" data-substep-field="sets" data-subindex="${subIndex}" data-step="1">+</button></div></div>
            <div class="field"><label>تکرار</label><div class="field-control"><button class="mini-step" data-substep-field="reps" data-subindex="${subIndex}" data-step="-1">−</button><input type="text" value="${sub.reps}" data-subfield="reps" data-subindex="${subIndex}" placeholder="12" /><button class="mini-step" data-substep-field="reps" data-subindex="${subIndex}" data-step="1">+</button></div></div>
            <div class="field"><label>استراحت</label><div class="field-control"><button class="mini-step" data-substep-field="rest" data-subindex="${subIndex}" data-step="-1">−</button><input type="text" value="${sub.rest}" data-subfield="rest" data-subindex="${subIndex}" placeholder="60" /><button class="mini-step" data-substep-field="rest" data-subindex="${subIndex}" data-step="1">+</button></div></div>
            <button class="subset-remove" data-remove-sub="${subIndex}" title="حذف زیرست">✕</button>
          </div>
        `).join("")}</div>
      </div>
    `;

    // Event listeners for fields
    el.querySelectorAll("input[data-field]").forEach((input) => {
      const saveField = () => {
        const field = input.dataset.field;
        const newValue = input.value;
        if (item[field] !== newValue) {
          item[field] = newValue;
          saveAppData();
        }
      };
      input.addEventListener("input", saveField);
      input.addEventListener("change", saveField);
      input.addEventListener("blur", saveField);
    });

    el.querySelectorAll("[data-step-field]").forEach((btn) => {
      btn.addEventListener("click", () => {
        const field = btn.dataset.stepField;
        const delta = +btn.dataset.step;
        const next = Math.max(0, toNumber(item[field]) + delta);
        item[field] = String(next);
        const input = el.querySelector(`input[data-field="${field}"]`);
        if (input) input.value = next;
        saveAppData();
      });
    });

    el.querySelectorAll("[data-substep-field]").forEach((btn) => {
      btn.addEventListener("click", () => {
        const subIndex = +btn.dataset.subindex;
        const subField = btn.dataset.substepField;
        const delta = +btn.dataset.step;
        const next = Math.max(0, toNumber(item.subsets[subIndex][subField]) + delta);
        item.subsets[subIndex][subField] = String(next);
        const subsetItem = el.querySelector(`[data-subuid="${item.subsets[subIndex].uid}"]`);
        if (subsetItem) {
          const input = subsetItem.querySelector(`input[data-subfield="${subField}"][data-subindex="${subIndex}"]`);
          if (input) input.value = next;
        }
        saveAppData();
      });
    });

    el.querySelectorAll("input[data-subfield]").forEach((input) => {
      const saveSubField = () => {
        const subIndex = +input.dataset.subindex;
        const subField = input.dataset.subfield;
        const newValue = input.value;
        if (item.subsets[subIndex] && item.subsets[subIndex][subField] !== newValue) {
          item.subsets[subIndex][subField] = newValue;
          saveAppData();
        }
      };
      input.addEventListener("input", saveSubField);
      input.addEventListener("change", saveSubField);
      input.addEventListener("blur", saveSubField);
    });

    el.querySelectorAll("[data-remove-sub]").forEach((btn) => {
      btn.addEventListener("click", () => {
        const subIndex = +btn.dataset.removeSub;
        item.subsets.splice(subIndex, 1);
        renderWorkoutList();
        saveAppData();
      });
    });

    el.querySelector(".subset-btn").addEventListener("click", () => {
      if (!item.subsets) item.subsets = [];
      item.subsets.push(createSubset());
      renderWorkoutList();
      saveAppData();
    });

    el.querySelector(".copy").addEventListener("click", () => {
      const clonedItem = deepCloneWorkoutItem(item);
      saveMoveToClipboard(clonedItem);
    });

    el.querySelector(".delete").addEventListener("click", () => {
      day.items.splice(index, 1);
      renderWorkoutList();
      saveAppData();
    });

    // Drag events
    el.addEventListener("dragstart", (e) => {
      state.dragSource = {
        type: "workout",
        dayIndex: state.currentDay,
        itemIndex: index,
        uid: item.uid
      };
      el.classList.add("dragging");
      e.dataTransfer.setData("text/plain", JSON.stringify(state.dragSource));
      if (hasValidImage && item.image) {
        const dragIcon = document.createElement('img');
        dragIcon.src = item.image;
        dragIcon.width = 50; dragIcon.height = 50;
        dragIcon.style.cssText = 'position:fixed;top:-1000px;border-radius:6px;';
        document.body.appendChild(dragIcon);
        e.dataTransfer.setDragImage(dragIcon, 25, 25);
        setTimeout(() => document.body.removeChild(dragIcon), 0);
      }
    });

    el.addEventListener("dragend", () => {
      el.classList.remove("dragging");
      removeGhosts();
      state.dragSource = null;
      state.pendingInsertIndex = null;
    });

    el.addEventListener("dragover", (e) => {
      e.preventDefault();
      e.stopPropagation();
      if (!state.dragSource) return;
      removeGhosts();
      const ghost = document.createElement("div");
      ghost.className = "ghost-line";
      const rect = el.getBoundingClientRect();
      const before = e.clientY < rect.top + rect.height / 2;
      const currentIndex = Number(el.dataset.index);
      state.pendingInsertIndex = before ? currentIndex : currentIndex + 1;
      if (before) {
        el.parentNode.insertBefore(ghost, el);
      } else {
        el.parentNode.insertBefore(ghost, el.nextSibling);
      }
    });

    el.addEventListener("drop", (e) => {
      e.preventDefault();
      e.stopPropagation();
      const insertIndex = state.pendingInsertIndex;
      if (insertIndex === null || insertIndex === undefined) return;
      handleDropAtIndex(e, insertIndex);
    });

    workoutList.appendChild(el);
  });
}

function removeGhosts() {
  document.querySelectorAll(".ghost-line").forEach((el) => el.remove());
}

function handleDropAtIndex(e, insertIndex) {
  e.preventDefault();
  e.stopPropagation();

  const raw = e.dataTransfer.getData("text/plain");
  const data = raw ? JSON.parse(raw) : state.dragSource;
  if (!data) return;

  const targetDay = state.days[state.currentDay];
  insertIndex = Math.max(0, Math.min(insertIndex, targetDay.items.length));

  if (data.type === "bank") {
    const ex = exercises.find((x) => x.id === data.exerciseId);
    if (!ex) return;
    targetDay.items.splice(insertIndex, 0, createWorkoutItem(ex));
  } else if (data.type === "workout") {
    const sourceDay = state.days[data.dayIndex];
    const sourceIndex = sourceDay.items.findIndex((x) => x.uid === data.uid);
    if (sourceIndex === -1) return;
    if (sourceDay === targetDay && sourceIndex < insertIndex) {
      insertIndex--;
    }
    const [moved] = sourceDay.items.splice(sourceIndex, 1);
    targetDay.items.splice(Math.max(0, Math.min(insertIndex, targetDay.items.length)), 0, moved);
  }

  state.dragSource = null;
  state.pendingInsertIndex = null;
  removeGhosts();
  renderWorkoutList();
  renderDays();
  saveAppData();
}

function showDayContextMenu(event, dayIndex) {
  const oldMenu = document.getElementById("dayContextMenu");
  if (oldMenu) oldMenu.remove();

  const menu = document.createElement("div");
  menu.id = "dayContextMenu";
  menu.className = "day-context-menu";

  let top = event.clientY;
  let left = event.clientX;

  if (left + 200 > window.innerWidth) {
    left = window.innerWidth - 210;
  }
  if (top + 200 > window.innerHeight) {
    top = window.innerHeight - 210;
  }

  menu.style.cssText = `position:fixed;top:${top}px;left:${left}px;`;

  const day = state.days[dayIndex];

  const menuItems = [
    { label: "تغییر نام", icon: "✏️", action: () => {
        const newName = prompt("نام جدید جلسه:", day.name);
        if (newName && newName.trim()) {
          day.name = newName.trim();
          renderDays();
          renderWorkoutList();
          saveAppData();
          showSuccessToast('تغییر نام موفق', `نام جلسه به "${day.name}" تغییر کرد`, 2000);
        }
      }
    }
  ];

  if (dayIndex > 0) {
    menuItems.push({ label: "انتقال به راست", icon: "➡️", action: () => {
        const [moved] = state.days.splice(dayIndex, 1);
        state.days.splice(dayIndex - 1, 0, moved);
        if (state.currentDay === dayIndex) state.currentDay = dayIndex - 1;
        else if (state.currentDay === dayIndex - 1) state.currentDay = dayIndex;
        renderDays(); renderWorkoutList(); saveAppData();
      }
    });
  }

  if (dayIndex < state.days.length - 1) {
    menuItems.push({ label: "انتقال به چپ", icon: "⬅️", action: () => {
        const [moved] = state.days.splice(dayIndex, 1);
        state.days.splice(dayIndex + 1, 0, moved);
        if (state.currentDay === dayIndex) state.currentDay = dayIndex + 1;
        else if (state.currentDay === dayIndex + 1) state.currentDay = dayIndex;
        renderDays(); renderWorkoutList(); saveAppData();
      }
    });
  }

  menuItems.push({ label: "کپی جلسه", icon: "📋", action: () => {
      const dayData = { name: day.name, items: day.items.map(item => deepCloneWorkoutItem(item)) };
      saveDayToClipboard(dayData);
    }
  });

  menuItems.forEach(item => {
    const menuItem = document.createElement("button");
    menuItem.className = "day-context-menu-item";
    menuItem.innerHTML = `<span style="display:flex;align-items:center;gap:8px;"><span>${item.icon}</span><span>${item.label}</span></span>`;
    menuItem.addEventListener("click", () => { item.action(); menu.remove(); });
    menu.appendChild(menuItem);
  });

  document.body.appendChild(menu);

  const closeMenu = (e) => {
    if (!menu.contains(e.target)) {
      menu.remove();
      document.removeEventListener("click", closeMenu);
      document.removeEventListener("contextmenu", closeMenu);
    }
  };

  setTimeout(() => {
    document.addEventListener("click", closeMenu);
    document.addEventListener("contextmenu", closeMenu);
  }, 0);
}

// ==========================================
// IndexedDB - Logo Storage
// ==========================================
const PHOTO_DB_NAME = "gym-photo-db";
const LOGO_STORE = "logo";
const PHOTO_DB_VERSION = 2;
let logoDb = null;

async function openLogoDB() {
  if (logoDb) return logoDb;

  return new Promise((resolve, reject) => {
    const request = indexedDB.open(PHOTO_DB_NAME, PHOTO_DB_VERSION);

    request.onupgradeneeded = event => {
      const db = event.target.result;
      if (!db.objectStoreNames.contains(LOGO_STORE)) {
        db.createObjectStore(LOGO_STORE, { keyPath: "id" });
      }
    };

    request.onsuccess = () => {
      logoDb = request.result;
      resolve(logoDb);
    };

    request.onerror = () => reject(request.error);
  });
}

async function loadLogo() {
  const db = await openLogoDB();

  return new Promise((resolve, reject) => {
    const tx = db.transaction(LOGO_STORE, "readonly");
    const request = tx.objectStore(LOGO_STORE).get("gym-logo");

    request.onsuccess = () => {
      if (!request.result) { resolve(null); return; }
      resolve(request.result.blob);
    };

    request.onerror = () => reject(request.error);
  });
}

async function getLogoUrlForExport() {
  try {
    const blob = await loadLogo();
    if (!blob) return null;
    return URL.createObjectURL(blob);
  } catch (e) { return null; }
}

async function injectLogoIntoExport() {
  try {
    const logoUrl = await getLogoUrlForExport();
    const logoImg = document.getElementById('export-logo-img');
    const logoPlaceholder = document.getElementById('export-logo-placeholder');
    if (!logoImg || !logoPlaceholder) return;
    if (!logoUrl) {
      logoImg.style.display = 'none';
      logoPlaceholder.style.display = 'flex';
      return;
    }
    await new Promise((resolve) => {
      logoImg.onload = () => { logoImg.style.display = 'block'; logoPlaceholder.style.display = 'none'; resolve(); };
      logoImg.onerror = () => { logoImg.style.display = 'none'; logoPlaceholder.style.display = 'flex'; resolve(); };
      logoImg.src = logoUrl;
      setTimeout(() => resolve(), 5000);
    });
  } catch (e) { console.error('خطا در injectLogoIntoExport:', e); }
}

// ============================
// 7. EXPORT: IMAGE
// ============================
function buildExportHtml_Image(daysOverride) {
  const colors = getExportThemeColors();
  const studentName = state.studentName?.trim() || "بدون نام";
  const days = Array.isArray(daysOverride) && daysOverride.length ? daysOverride : state.days || [];
  const nonEmptyDays = days.filter(day => day.items && day.items.length > 0);

  let programGoal = '';
  let programRestDays = '';
  if (state.activeStudentId && state.activeProgramId) {
    try {
      const metaKey = PROGRAM_META_PREFIX + state.activeStudentId + '::' + state.activeProgramId;
      const metaRaw = localStorage.getItem(metaKey);
      if (metaRaw) { const meta = JSON.parse(metaRaw); programGoal = meta.goal || ''; programRestDays = meta.restDays || ''; }
    } catch (e) {}
  }

  const styles = getComputedStyle(document.documentElement);
  const bgColor = styles.getPropertyValue('--panel').trim() || '#ffffff';
  const textColor = styles.getPropertyValue('--text').trim() || '#1a1a1a';
  const mutedColor = styles.getPropertyValue('--muted').trim() || '#999999';
  const lineColor = styles.getPropertyValue('--line').trim() || 'rgba(0,0,0,0.08)';

  const isDark = (() => {
    const bg = bgColor;
    if (!bg || bg === '#ffffff' || bg === '#fff') return false;
    const hex = bg.replace('#', '');
    if (hex.length < 6) return false;
    const r = parseInt(hex.substring(0, 2), 16);
    const g = parseInt(hex.substring(2, 4), 16);
    const b = parseInt(hex.substring(4, 6), 16);
    return (0.299 * r + 0.587 * g + 0.114 * b) / 255 < 0.5;
  })();

  if (!nonEmptyDays.length) {
    return `<div id="program-export-root" style="width:100%;height:100%;direction:rtl;font-family:'IRANSansWeb','IRANSans',Tahoma;background:${bgColor};color:${textColor};display:flex;align-items:center;justify-content:center;min-height:400px;"><div style="text-align:center;font-size:15px;color:${mutedColor};">هنوز برنامه‌ای ثبت نشده</div></div>`;
  }

  let gymName = '';
  let gymPhone = '';
  try { const settings = JSON.parse(localStorage.getItem('gym-settings-v2') || '{}'); gymName = settings.gymName || ''; gymPhone = settings.phone || ''; } catch (e) {}

  const today = new Date().toLocaleDateString('fa-IR');
  const FONT = "'IRANSansWeb', 'IRANSans', Tahoma";
  const pageBg = bgColor;
  const surfaceBg = isDark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.02)';
  const borderColor = isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.08)';
  const borderColorStrong = isDark ? 'rgba(255,255,255,0.13)' : 'rgba(0,0,0,0.13)';
  const labelColor = mutedColor;
  const valueColor = textColor;

  function buildDayRows(day) {
    if (!day.items || day.items.length === 0) {
      return `<tr><td colspan="5" style="padding:24px 16px;text-align:center;color:${mutedColor};font-size:14px;">بدون حرکت</td></tr>`;
    }
    return day.items.map((item, idx) => {
      const subsets = item.subsets || [];
      const totalRows = 1 + subsets.length;
      const hasValidImage = item.image && !item.image.includes("undefined") && item.image.trim() !== "";
      const isLast = idx === day.items.length - 1;
      const rowBorder = isLast ? '' : `border-bottom:1px solid ${borderColor};`;
      const imageHtml = hasValidImage
          ? `<img src="${item.image}" style="width:65px;height:65px;object-fit:cover;border-radius:8px;display:block;" onerror="this.style.display='none'">`
          : `<div style="width:65px;height:65px;border-radius:8px;background:${surfaceBg};display:flex;align-items:center;justify-content:center;font-size:18px;color:${mutedColor};">—</div>`;
      const noteText = item.note && item.note.trim() ? ` <span style="font-size:12px;color:${mutedColor};">: ${escapeHtml(item.note.trim())}</span>` : '';

      if (!subsets.length) {
        return `<tr style="${rowBorder}">
          <td style="padding:12px 10px;vertical-align:middle;width:85px;text-align:center;">${imageHtml}</td>
          <td style="padding:12px 16px;vertical-align:middle;text-align:right;"><span style="font-size:15px;font-weight:700;color:${valueColor};">${escapeHtml(item.name)}${noteText}</span></td>
          <td style="padding:12px 4px;vertical-align:middle;text-align:center;"><span style="font-size:14px;color:${valueColor};">${normalizeCell(item.sets)}</span></td>
          <td style="padding:12px 4px;vertical-align:middle;text-align:center;"><span style="font-size:14px;color:${valueColor};">${normalizeCell(item.reps)}</span></td>
          <td style="padding:12px 4px 12px 14px;vertical-align:middle;text-align:center;"><span style="font-size:14px;color:${valueColor};">${normalizeCell(item.rest)}</span></td>
        </tr>`;
      }

      const mainRow = `<tr>
        <td rowspan="${totalRows}" style="padding:12px 10px;vertical-align:top;width:85px;text-align:center;border-bottom:1px solid ${borderColor};">${imageHtml}</td>
        <td style="padding:12px 16px 6px 16px;vertical-align:middle;text-align:right;border-bottom:1px solid ${borderColor};"><span style="font-size:15px;font-weight:700;color:${valueColor};">${escapeHtml(item.name)}${noteText}</span></td>
        <td style="padding:12px 4px 6px 4px;vertical-align:middle;text-align:center;border-bottom:1px solid ${borderColor};"><span style="font-size:14px;color:${valueColor};">${normalizeCell(item.sets)}</span></td>
        <td style="padding:12px 4px 6px 4px;vertical-align:middle;text-align:center;border-bottom:1px solid ${borderColor};"><span style="font-size:14px;color:${valueColor};">${normalizeCell(item.reps)}</span></td>
        <td style="padding:12px 4px 6px 14px;vertical-align:middle;text-align:center;border-bottom:1px solid ${borderColor};"><span style="font-size:14px;color:${valueColor};">${normalizeCell(item.rest)}</span></td>
      </tr>`;

      const subsetRows = subsets.map((sub, si) => {
        const isSubLast = si === subsets.length - 1;
        const subBorder = isSubLast ? `border-bottom:1px solid ${borderColor};` : `border-bottom:1px solid ${borderColor};`;
        return `<tr>
          <td style="padding:6px 16px 10px 16px;vertical-align:middle;text-align:right;${subBorder}"><span style="font-size:12px;color:${mutedColor};display:block;padding-right:12px;">↳ ${escapeHtml(sub.note || 'زیرست')}</span></td>
          <td style="padding:6px 4px 10px 4px;vertical-align:middle;text-align:center;${subBorder}"><span style="font-size:14px;color:${mutedColor};">${normalizeCell(sub.sets)}</span></td>
          <td style="padding:6px 4px 10px 4px;vertical-align:middle;text-align:center;${subBorder}"><span style="font-size:14px;color:${mutedColor};">${normalizeCell(sub.reps)}</span></td>
          <td style="padding:6px 4px 10px 14px;vertical-align:middle;text-align:center;${subBorder}"><span style="font-size:14px;color:${mutedColor};">${normalizeCell(sub.rest)}</span></td>
        </tr>`;
      }).join('');

      return mainRow + subsetRows;
    }).join('');
  }

  function buildDayTable(day) {
    return `<table style="width:100%;border-collapse:collapse;table-layout:fixed;">
      <colgroup><col style="width:85px;"><col><col style="width:55px;"><col style="width:50px;"><col style="width:85px;"></colgroup>
      <thead><tr><td colspan="5" style="padding:14px 12px;background:${surfaceBg};border-bottom:1px solid ${borderColorStrong};"><div style="display:flex;align-items:center;justify-content:space-between;"><span style="font-size:16px;font-weight:700;color:${valueColor};">${escapeHtml(day.name)}</span><div style="display:flex;gap:0;font-size:10px;font-weight:700;color:${labelColor};"><span style="width:50px;text-align:center;">ست</span><span style="width:50px;text-align:center;">تکرار</span><span style="width:78px;text-align:center;">استراحت</span></div></div></td></tr></thead>
      <tbody>${buildDayRows(day)}</tbody></table>`;
  }

  const infoCardsHtml = (programGoal || programRestDays) ? `<div style="display:flex;gap:16px;padding:0 32px;margin-bottom:24px;flex-wrap:wrap;">
    ${programGoal ? `<div style="flex:1;min-width:200px;background:${surfaceBg};border:1px solid ${borderColor};border-radius:10px;padding:14px 18px;"><div style="font-size:11px;font-weight:700;color:${labelColor};margin-bottom:6px;">هدف برنامه</div><div style="font-size:15px;font-weight:700;color:${valueColor};">${escapeHtml(programGoal)}</div></div>` : ''}
    ${programRestDays ? `<div style="flex:1;min-width:200px;background:${surfaceBg};border:1px solid ${borderColor};border-radius:10px;padding:14px 18px;"><div style="font-size:11px;font-weight:700;color:${labelColor};margin-bottom:6px;">روزهای استراحت</div><div style="font-size:15px;font-weight:700;color:${valueColor};">${escapeHtml(programRestDays)}</div></div>` : ''}
  </div>` : '';

  return `<div id="program-export-root" style="width:794px;min-height:1123px;direction:rtl;font-family:${FONT};background:${pageBg};color:${valueColor};box-sizing:border-box;position:relative;overflow:hidden;">
    <div style="height:4px;background:linear-gradient(90deg, ${colors.accent} 0%, ${colors.accent2} 100%);width:100%;"></div>
    <div style="padding:24px 32px 18px 32px;display:flex;align-items:center;justify-content:space-between;gap:20px;">
      <div style="display:flex;align-items:center;gap:16px;">
        <div id="export-logo-container" style="flex-shrink:0;width:56px;height:56px;border-radius:10px;overflow:hidden;background:${surfaceBg};display:flex;align-items:center;justify-content:center;">
          <img id="export-logo-img" src="" style="width:100%;height:100%;object-fit:cover;display:none;" onerror="this.style.display='none'">
          <span id="export-logo-placeholder" style="font-size:24px;display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:${mutedColor};">—</span>
        </div>
        <div><div style="font-size:23px;font-weight:800;color:${valueColor};line-height:1.2;">${escapeHtml(gymName || 'باشگاه')}</div>${gymPhone ? `<div style="font-size:12px;color:${mutedColor};margin-top:3px;direction:ltr;text-align:right;">${escapeHtml(gymPhone)}</div>` : ''}</div>
      </div>
      <div style="text-align:left;direction:ltr;"><div style="font-size:11px;font-weight:700;color:${labelColor};margin-bottom:3px;">CLIENT</div><div style="font-size:17px;font-weight:700;color:${valueColor};">${escapeHtml(studentName)}</div></div>
    </div>
    <div style="margin:0 32px;height:1px;background:${borderColor};"></div>
    <div style="padding-top:18px;">${infoCardsHtml}</div>
    <div style="padding:0 32px 50px 32px;">
      ${nonEmptyDays.map((day, index) => `<div style="margin-bottom:${index === nonEmptyDays.length - 1 ? '0' : '20px'};border:1px solid ${borderColorStrong};border-radius:10px;overflow:hidden;">${buildDayTable(day)}</div>`).join('')}
    </div>
    <div style="position:absolute;bottom:0;left:0;right:0;padding:14px 32px;display:flex;align-items:center;justify-content:space-between;border-top:1px solid ${borderColor};"><span style="font-size:11px;color:${mutedColor};">Inline Dev</span><span style="font-size:11px;color:${mutedColor};">${today}</span></div>
  </div>`;
}

function buildA4PageHtml_Image(daysForThisPage) {
  const nonEmptyDays = daysForThisPage.filter(day => day.items && day.items.length > 0);
  if (nonEmptyDays.length === 0) return `<div class="program-export-a4-page" style="width:794px;height:1123px;box-sizing:border-box;background:#ffffff;padding:0;margin:0;overflow:hidden;position:relative;"><div style="display:flex;align-items:center;justify-content:center;height:100%;color:#ccc;font-size:14px;">صفحه خالی</div></div>`;
  return `<div class="program-export-a4-page" style="width:794px;min-height:1123px;height:auto;box-sizing:border-box;background:#ffffff;padding:0;margin:0;position:relative;">${buildExportHtml_Image(nonEmptyDays)}</div>`;
}

async function paginateDaysForA4_Image(days) {
  const pages = []; let currentPageDays = [];
  const measureWrap = document.createElement("div"); measureWrap.id = "program-export-measure-wrap"; measureWrap.style.cssText = "position:fixed;left:-20000px;top:0;z-index:-1;pointer-events:none;width:794px;background:#ffffff;opacity:0;"; document.body.appendChild(measureWrap);
  try {
    for (const originalDay of days) {
      if (!originalDay.items || originalDay.items.length === 0) continue;
      const testFullDay = [...currentPageDays, originalDay]; measureWrap.innerHTML = buildA4PageHtml_Image(testFullDay); await waitForBrowserPaint();
      const rootElement = measureWrap.querySelector("#program-export-root"); if (!rootElement) continue;
      if (rootElement.scrollHeight <= 1143) { currentPageDays.push(originalDay); continue; }
      if (currentPageDays.length > 0) { pages.push([...currentPageDays]); currentPageDays = []; }
      const splitParts = await splitDayIntoParts_Image(originalDay, measureWrap);
      for (let partIndex = 0; partIndex < splitParts.length; partIndex++) {
        const part = splitParts[partIndex];
        if (partIndex > 0) { if (currentPageDays.length > 0) { pages.push([...currentPageDays]); currentPageDays = []; } currentPageDays = [part]; continue; }
        if (currentPageDays.length > 0) {
          const testWithPart = [...currentPageDays, part]; measureWrap.innerHTML = buildA4PageHtml_Image(testWithPart); await waitForBrowserPaint();
          const testRoot = measureWrap.querySelector("#program-export-root");
          if (testRoot && testRoot.scrollHeight <= 1143) currentPageDays.push(part); else { pages.push([...currentPageDays]); currentPageDays = [part]; }
        } else currentPageDays = [part];
      }
    }
    if (currentPageDays.length > 0) pages.push([...currentPageDays]);
    return pages.filter(page => page.some(day => day.items && day.items.length > 0));
  } finally { measureWrap.remove(); }
}

async function splitDayIntoParts_Image(originalDay, measureWrap) {
  const items = originalDay.items || []; if (items.length === 0) return [originalDay];
  let maxItemsPerPage = 1;
  for (let testCount = 1; testCount <= items.length; testCount++) {
    measureWrap.innerHTML = buildA4PageHtml_Image([{ ...originalDay, name: originalDay.name, items: items.slice(0, testCount) }]); await waitForBrowserPaint();
    const rootEl = measureWrap.querySelector("#program-export-root");
    if (rootEl && rootEl.scrollHeight <= 1143) maxItemsPerPage = testCount; else break;
  }
  const parts = []; let remainingItems = [...items]; let partNumber = 1;
  while (remainingItems.length > 0) {
    const chunkItems = remainingItems.slice(0, maxItemsPerPage);
    parts.push({ ...originalDay, name: partNumber === 1 ? originalDay.name : `${originalDay.name} (ادامه ${partNumber - 1})`, items: chunkItems });
    remainingItems = remainingItems.slice(maxItemsPerPage); partNumber++;
  }
  return parts;
}

async function exportProgramAsImage() {
  if (!window.html2canvas) { showErrorToast('کتابخانه موجود نیست', 'html2canvas لود نشده.'); return; }
  const days = Array.isArray(state.days) ? state.days : [];
  if (!days.length) { showWarningToast('برنامه خالی است', 'برنامه تمرینی برای خروجی گرفتن وجود ندارد.'); return; }
  const oldNode = document.getElementById("program-export-capture-wrap");
  if (oldNode) oldNode.remove();
  const wrap = document.createElement("div");
  wrap.id = "program-export-capture-wrap";
  wrap.style.cssText = "position:fixed;left:-20000px;top:0;z-index:-1;pointer-events:none;width:794px;background:#ffffff;";
  document.body.appendChild(wrap);
  try {
    const pagesOfDays = await paginateDaysForA4_Image(days);
    const stuName = sanitizeFileName(state.studentName || "کاربر");
    if (pagesOfDays.length === 0) { showWarningToast('برنامه خالی است', 'هیچ صفحه‌ای برای خروجی گرفتن وجود ندارد.'); return; }
    const loadingToast = showInfoToast('در حال آماده‌سازی', `در حال ساخت ${pagesOfDays.length} عکس...`, 0);
    for (let i = 0; i < pagesOfDays.length; i++) {
      wrap.innerHTML = buildA4PageHtml_Image(pagesOfDays[i]);
      await waitForBrowserPaint();
      await injectLogoIntoExport();
      await waitForBrowserPaint();
      await new Promise(r => setTimeout(r, 300));
      const pageElement = wrap.querySelector(".program-export-a4-page");
      if (!pageElement) throw new Error("صفحه A4 پیدا نشد.");
      const canvas = await safeHtml2Canvas(pageElement, { useCORS: true, allowTaint: true, scale: 2 });
      if (!canvas) throw new Error("ساخت canvas ناموفق بود.");
      const blob = await canvasToBlob(canvas, "image/jpeg", 0.95);
      await downloadBlob(blob, `${stuName} - صفحه ${toPersianDigits(i + 1)} از ${toPersianDigits(pagesOfDays.length)}.jpg`);
      await new Promise(r => setTimeout(r, 250));
    }
    if (loadingToast) removeToast(loadingToast);
    if (pagesOfDays.length > 0) showSuccessToast('دانلود با موفقیت انجام شد', `${toPersianDigits(pagesOfDays.length)} عکس ایجاد و دانلود شد`, 5000);
  } catch (err) { console.error(err); showErrorToast('خطا در خروجی', 'مشکلی در ساخت یا ذخیره تصویر برنامه پیش آمد.'); } finally { wrap.remove(); }
}

// ============================
// 8. EXPORT: PDF
// ============================
async function exportProgramAsPdf() {
  if (!window.html2canvas) { showErrorToast('کتابخانه موجود نیست', 'html2canvas لود نشده.'); return; }
  if (!window.jspdf || !window.jspdf.jsPDF) { showErrorToast('کتابخانه موجود نیست', 'jsPDF لود نشده.'); return; }
  const days = Array.isArray(state.days) ? state.days : [];
  if (!days.length) { showWarningToast('برنامه خالی است', 'برنامه تمرینی برای خروجی گرفتن وجود ندارد.'); return; }
  const oldNode = document.getElementById("program-export-capture-wrap");
  if (oldNode) oldNode.remove();
  const wrap = document.createElement("div");
  wrap.id = "program-export-capture-wrap";
  wrap.style.cssText = "position:fixed;left:-20000px;top:0;z-index:-1;pointer-events:none;width:794px;background:#f8fafc;";
  document.body.appendChild(wrap);
  try {
    const pagesOfDays = await paginateDaysForA4_Image(days);
    const stuName = sanitizeFileName(state.studentName || "کاربر");
    if (pagesOfDays.length === 0) { showWarningToast('برنامه خالی است', 'هیچ صفحه‌ای برای خروجی گرفتن وجود ندارد.'); return; }
    const loadingToast = showInfoToast('در حال آماده‌سازی', `در حال ساخت فایل PDF...`, 0);
    const { jsPDF } = window.jspdf;
    const pdf = new jsPDF({ orientation: "portrait", unit: "mm", format: "a4" });
    for (let i = 0; i < pagesOfDays.length; i++) {
      wrap.innerHTML = buildA4PageHtml_Image(pagesOfDays[i]);
      await waitForBrowserPaint();
      await injectLogoIntoExport();
      await waitForBrowserPaint();
      await new Promise(r => setTimeout(r, 300));
      const pageElement = wrap.querySelector(".program-export-a4-page");
      if (!pageElement) throw new Error("صفحه A4 پیدا نشد.");
      const canvas = await safeHtml2Canvas(pageElement, { useCORS: true, allowTaint: true, scale: 2 });
      if (!canvas) throw new Error("ساخت canvas ناموفق بود.");
      const imgData = canvas.toDataURL("image/jpeg", 0.95);
      if (i > 0) pdf.addPage("a4", "portrait");
      pdf.addImage(imgData, "JPEG", 0, 0, 210, 297, undefined, "FAST");
      await new Promise(r => setTimeout(r, 150));
    }
    if (loadingToast) removeToast(loadingToast);
    pdf.save(`${stuName}.pdf`);
    showSuccessToast('دانلود با موفقیت انجام شد', `فایل PDF با ${toPersianDigits(pagesOfDays.length)} صفحه ایجاد و دانلود شد`, 5000);
  } catch (err) { console.error(err); showErrorToast('خطا در خروجی', 'مشکلی در ساخت یا ذخیره فایل PDF پیش آمد.'); } finally { wrap.remove(); }
}

// ============================
// 9. EXPORT: WORD
// ============================
async function exportProgramAsWord() {
  if (!window.docx || !window.docx.Document || !window.docx.Packer) { showErrorToast('کتابخانه موجود نیست', 'docx.js لود نشده.'); return; }
  const days = Array.isArray(state.days) ? state.days : [];
  if (!days.length) { showWarningToast('برنامه خالی است', 'برنامه تمرینی برای خروجی گرفتن وجود ندارد.'); return; }

  try {
    const loadingToast = showInfoToast('در حال آماده‌سازی', 'در حال ساخت فایل Word...', 0);
    const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun, PageBreak, WidthType, AlignmentType, BorderStyle, ShadingType } = docx;

    function parseColorToHex(c) {
      if (!c || c === "transparent" || c === "none") return null;
      c = c.trim();
      if (c.startsWith("#")) { const h = c.replace("#", ""); if (h.length === 6) return h; if (h.length === 3) return h.split("").map(x => x + x).join(""); return null; }
      const m = c.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
      if (m) return m.slice(1).map(x => Math.min(255, Math.max(0, parseInt(x))).toString(16).padStart(2, "0")).join("");
      return null;
    }
    function hexToRgb(hex) { if (!hex) return { r: 255, g: 255, b: 255 }; const h = hex.replace("#", ""); return { r: parseInt(h.substring(0, 2), 16), g: parseInt(h.substring(2, 4), 16), b: parseInt(h.substring(4, 6), 16) }; }

    const styles = getComputedStyle(document.documentElement);
    const bgHex = parseColorToHex(styles.getPropertyValue("--panel").trim()) || "ffffff";
    const textHex = parseColorToHex(styles.getPropertyValue("--text").trim()) || "1a1a1a";
    const mutedHex = parseColorToHex(styles.getPropertyValue("--muted").trim()) || "888888";
    const panel2Hex = parseColorToHex(styles.getPropertyValue("--panel-2").trim()) || "f5f5f5";
    const bgRgb = hexToRgb(bgHex);
    const isDark = (0.299 * bgRgb.r + 0.587 * bgRgb.g + 0.114 * bgRgb.b) / 255 < 0.5;

    const textColor = "#" + textHex;
    const mutedColor = "#" + mutedHex;
    const pageBg = "#" + bgHex;
    const surfaceColor = "#" + panel2Hex;
    const borderColor = isDark ? "#3a3a3a" : "#e0e0e0";
    const borderLight = isDark ? "#2a2a2a" : "#f0f0f0";
    const labelColor = isDark ? "#888888" : "#999999";

    async function loadFontBuffer(url) { try { const r = await fetch(url); if (!r.ok) return null; return await r.arrayBuffer(); } catch (e) { return null; } }
    const [iranSansMedium, iranSansBold] = await Promise.all([loadFontBuffer("asset/fonts/IRANSansWeb_Medium.ttf"), loadFontBuffer("asset/fonts/IRANSansWeb_Bold.ttf")]);

    const studentName = state.studentName?.trim() || "بدون نام";
    const nonEmptyDays = days.filter(d => d.items && d.items.length > 0);
    if (!nonEmptyDays.length) { if (loadingToast) removeToast(loadingToast); showWarningToast('برنامه خالی است', 'هیچ حرکتی برای خروجی وجود ندارد.'); return; }

    let programGoal = ''; let programRestDays = '';
    if (state.activeStudentId && state.activeProgramId) { try { const metaKey = PROGRAM_META_PREFIX + state.activeStudentId + '::' + state.activeProgramId; const metaRaw = localStorage.getItem(metaKey); if (metaRaw) { const meta = JSON.parse(metaRaw); programGoal = meta.goal || ''; programRestDays = meta.restDays || ''; } } catch (e) {} }

    let gymName = ''; let gymPhone = '';
    try { const settings = JSON.parse(localStorage.getItem('gym-settings-v2') || '{}'); gymName = settings.gymName || ''; gymPhone = settings.phone || ''; } catch (e) {}

    const today = new Date().toLocaleDateString('fa-IR');
    const FONT = "IRANSansWeb";
    const imageCache = {};
    async function getImageBuffer(url) { if (!url || url.includes("undefined") || !url.trim()) return null; if (imageCache[url]) return imageCache[url]; try { const r = await fetch(url); if (!r.ok) return null; const b = await r.arrayBuffer(); imageCache[url] = b; return b; } catch (e) { return null; } }

    let logoBuffer = null;
    try { const logoUrl = await getLogoUrlForExport(); if (logoUrl) { const logoResponse = await fetch(logoUrl); if (logoResponse.ok) logoBuffer = await logoResponse.arrayBuffer(); } } catch (e) {}

    const ZERO_BORDER = { top: { style: BorderStyle.NONE, size: 0 }, bottom: { style: BorderStyle.NONE, size: 0 }, left: { style: BorderStyle.NONE, size: 0 }, right: { style: BorderStyle.NONE, size: 0 } };
    const TABLE_ZERO_BORDERS = { top: { style: BorderStyle.NONE, size: 0 }, bottom: { style: BorderStyle.NONE, size: 0 }, left: { style: BorderStyle.NONE, size: 0 }, right: { style: BorderStyle.NONE, size: 0 }, insideHorizontal: { style: BorderStyle.NONE, size: 0 }, insideVertical: { style: BorderStyle.NONE, size: 0 } };
    const BOTTOM_BORDER = { top: { style: BorderStyle.NONE, size: 0 }, bottom: { style: BorderStyle.SINGLE, size: 0.5, color: borderLight }, left: { style: BorderStyle.NONE, size: 0 }, right: { style: BorderStyle.NONE, size: 0 } };
    const FULL_BORDER = { top: { style: BorderStyle.SINGLE, size: 0.5, color: borderColor }, bottom: { style: BorderStyle.SINGLE, size: 0.5, color: borderColor }, left: { style: BorderStyle.SINGLE, size: 0.5, color: borderColor }, right: { style: BorderStyle.SINGLE, size: 0.5, color: borderColor } };

    const children = [];

    // Header
    const headerCells = [];
    headerCells.push(new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "CLIENT", bold: true, size: 15, font: FONT, rightToLeft: false, color: labelColor })], alignment: AlignmentType.LEFT, spacing: { after: 20 } }), new Paragraph({ children: [new TextRun({ text: studentName, bold: true, size: 24, font: FONT, rightToLeft: true, color: textColor })], alignment: AlignmentType.LEFT, spacing: { after: 0 } })], width: { size: 32, type: WidthType.PERCENTAGE }, borders: ZERO_BORDER, margins: { top: 0, bottom: 0, left: 0, right: 0 } }));
    headerCells.push(new TableCell({ children: [new Paragraph({ children: [], spacing: { after: 0 } })], width: { size: 20, type: WidthType.PERCENTAGE }, borders: ZERO_BORDER, margins: { top: 0, bottom: 0, left: 0, right: 0 } }));
    headerCells.push(new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: gymName || "باشگاه ورزشی", bold: true, size: 27, font: FONT, rightToLeft: true, color: textColor })], alignment: AlignmentType.RIGHT, spacing: { after: 0 } })], width: { size: 32, type: WidthType.PERCENTAGE }, borders: ZERO_BORDER, margins: { top: 100, bottom: 0, left: 0, right: 0 } }));
    if (logoBuffer) { headerCells.push(new TableCell({ children: [new Paragraph({ children: [new ImageRun({ data: logoBuffer, transformation: { width: 58, height: 58 } })], alignment: AlignmentType.CENTER, spacing: { after: 0 } })], width: { size: 58, type: WidthType.PERCENTAGE }, borders: ZERO_BORDER, margins: { top: 0, bottom: 0, left: 0, right: 0 } })); }
    children.push(new Table({ width: { size: 100, type: WidthType.PERCENTAGE }, rows: [new TableRow({ children: headerCells })], borders: TABLE_ZERO_BORDERS }));
    children.push(new Paragraph({ spacing: { before: 0, after: 160 }, children: [new TextRun({ text: "", size: 1, font: FONT })] }));

    // Info cards
    if (programGoal || programRestDays) {
      const infoCells = [];
      if (programGoal) infoCells.push(new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "هدف برنامه", bold: true, size: 16, font: FONT, rightToLeft: true, color: labelColor })], alignment: AlignmentType.RIGHT, spacing: { after: 40 } }), new Paragraph({ children: [new TextRun({ text: programGoal, bold: true, size: 22, font: FONT, rightToLeft: true, color: textColor })], alignment: AlignmentType.RIGHT, spacing: { after: 0 } })], width: programRestDays ? { size: 50, type: WidthType.PERCENTAGE } : { size: 100, type: WidthType.PERCENTAGE }, borders: FULL_BORDER, margins: { top: 100, bottom: 100, left: 120, right: 120 } }));
      if (programRestDays) infoCells.push(new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "روزهای استراحت", bold: true, size: 16, font: FONT, rightToLeft: true, color: labelColor })], alignment: AlignmentType.RIGHT, spacing: { after: 40 } }), new Paragraph({ children: [new TextRun({ text: programRestDays, bold: true, size: 22, font: FONT, rightToLeft: true, color: textColor })], alignment: AlignmentType.RIGHT, spacing: { after: 0 } })], width: { size: 50, type: WidthType.PERCENTAGE }, borders: FULL_BORDER, margins: { top: 100, bottom: 100, left: 120, right: 120 } }));
      children.push(new Table({ width: { size: 100, type: WidthType.PERCENTAGE }, rows: [new TableRow({ children: infoCells })] }));
      children.push(new Paragraph({ spacing: { before: 0, after: 200 }, children: [new TextRun({ text: "", size: 1, font: FONT })] }));
    }

    // Days
    for (let d = 0; d < nonEmptyDays.length; d++) {
      const day = nonEmptyDays[d];
      const items = day.items || [];
      if (!items.length) continue;
      const dayRows = [];
      dayRows.push(new TableRow({ children: [new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "استراحت (دقیقه)", bold: true, size: 15, font: FONT, rightToLeft: true, color: labelColor }), new TextRun({ text: "       ", size: 15, font: FONT }), new TextRun({ text: "تکرار", bold: true, size: 15, font: FONT, rightToLeft: true, color: labelColor }), new TextRun({ text: "             ", size: 15, font: FONT }), new TextRun({ text: "ست", bold: true, size: 15, font: FONT, rightToLeft: true, color: labelColor }), new TextRun({ text: "\t\t\t\t\t\t\t\t\t\t        ", size: 14, font: FONT }), new TextRun({ text: day.name, bold: true, size: 24, font: FONT, rightToLeft: true, color: textColor })], alignment: AlignmentType.LEFT, spacing: { after: 0 } })], columnSpan: 5, borders: ZERO_BORDER, shading: { type: ShadingType.SOLID, color: surfaceColor, fill: surfaceColor }, margins: { top: 100, bottom: 100, left: 100, right: 100 } }) ] }));
      for (const item of items) {
        const subsets = item.subsets || [];
        const restCell = new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: normalizeCell(item.rest), size: 20, font: FONT, rightToLeft: true, color: textColor })], alignment: AlignmentType.CENTER, spacing: { after: 0 } })], width: { size: 10, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 60, bottom: 60, left: 30, right: 30 } });
        const repsCell = new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: normalizeCell(item.reps), size: 20, font: FONT, rightToLeft: true, color: textColor })], alignment: AlignmentType.CENTER, spacing: { after: 0 } })], width: { size: 8, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 60, bottom: 60, left: 30, right: 30 } });
        const setsCell = new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: normalizeCell(item.sets), size: 20, font: FONT, rightToLeft: true, color: textColor })], alignment: AlignmentType.CENTER, spacing: { after: 0 } })], width: { size: 8, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 60, bottom: 60, left: 30, right: 30 } });
        const nameRuns = [new TextRun({ text: item.name || "—", bold: true, size: 22, font: FONT, rightToLeft: true, color: textColor })];
        if (item.note && item.note.trim()) nameRuns.push(new TextRun({ text: `: ${item.note.trim()}`, size: 18, font: FONT, rightToLeft: true, color: mutedColor }));
        const nameCell = new TableCell({ children: [new Paragraph({ children: nameRuns, alignment: AlignmentType.RIGHT, spacing: { after: 0 } })], width: { size: 64, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 60, bottom: 60, left: 80, right: 80 } });
        let imageCell;
        const hasValidImage = item.image && !item.image.includes("undefined") && item.image.trim();
        if (hasValidImage) { const imgBuffer = await getImageBuffer(item.image); if (imgBuffer) imageCell = new TableCell({ children: [new Paragraph({ children: [new ImageRun({ data: imgBuffer, transformation: { width: 60, height: 60 } })], alignment: AlignmentType.CENTER, spacing: { after: 0 } })], width: { size: 10, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 40, bottom: 40, left: 40, right: 40 } }); }
        if (!imageCell) imageCell = new TableCell({ children: [new Paragraph({ children: [], spacing: { after: 0 } })], width: { size: 10, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 40, bottom: 40, left: 40, right: 40 } });
        dayRows.push(new TableRow({ children: [restCell, repsCell, setsCell, nameCell, imageCell] }));
        for (const sub of subsets) {
          dayRows.push(new TableRow({ children: [
              new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: normalizeCell(sub.rest), size: 18, font: FONT, rightToLeft: true, color: mutedColor })], alignment: AlignmentType.CENTER, spacing: { after: 0 } })], width: { size: 10, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 40, bottom: 40, left: 30, right: 30 } }),
              new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: normalizeCell(sub.reps), size: 18, font: FONT, rightToLeft: true, color: mutedColor })], alignment: AlignmentType.CENTER, spacing: { after: 0 } })], width: { size: 8, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 40, bottom: 40, left: 30, right: 30 } }),
              new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: normalizeCell(sub.sets), size: 18, font: FONT, rightToLeft: true, color: mutedColor })], alignment: AlignmentType.CENTER, spacing: { after: 0 } })], width: { size: 8, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 40, bottom: 40, left: 30, right: 30 } }),
              new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: `↳ ${sub.note || 'زیرست'}`, size: 18, font: FONT, rightToLeft: true, color: mutedColor })], alignment: AlignmentType.RIGHT, indent: { right: 300 }, spacing: { after: 0 } })], width: { size: 64, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 40, bottom: 40, left: 80, right: 80 } }),
              new TableCell({ children: [new Paragraph({ children: [], spacing: { after: 0 } })], width: { size: 10, type: WidthType.PERCENTAGE }, borders: BOTTOM_BORDER, margins: { top: 40, bottom: 40, left: 40, right: 40 } })
            ] }));
        }
      }
      children.push(new Table({ width: { size: 100, type: WidthType.PERCENTAGE }, rows: dayRows }));
      children.push(new Paragraph({ spacing: { before: 0, after: 240 }, children: [new TextRun({ text: "", size: 1, font: FONT })] }));
      if ((d + 1) % 2 === 0 && d < nonEmptyDays.length - 1) children.push(new Paragraph({ children: [new PageBreak()] }));
    }

    // Footer
    children.push(new Paragraph({ children: [new TextRun({ text: "Inline Dev", size: 16, font: FONT, rightToLeft: true, color: mutedColor }), new TextRun({ text: "\t\t\t\t\t\t\t\t\t\t\t", size: 16, font: FONT }), new TextRun({ text: today, size: 16, font: FONT, rightToLeft: true, color: mutedColor })], alignment: AlignmentType.RIGHT, border: { top: { style: BorderStyle.SINGLE, size: 0.5, color: borderColor } }, spacing: { before: 200, after: 0 } }));

    const fonts = [];
    if (iranSansMedium) fonts.push({ name: "IRANSansWeb", data: iranSansMedium, characterSet: "ARABIC", weight: 500 });
    if (iranSansBold) fonts.push({ name: "IRANSansWeb", data: iranSansBold, characterSet: "ARABIC", weight: 700 });

    const doc = new Document({ fonts: fonts.length > 0 ? fonts : undefined, background: { color: bgHex }, sections: [{ properties: { page: { margin: { top: 600, bottom: 600, left: 600, right: 600 }, rightToLeft: true } }, children }] });
    const blob = await Packer.toBlob(doc);
    if (loadingToast) removeToast(loadingToast);
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a"); a.href = url; a.download = `${sanitizeFileName(studentName)} - برنامه تمرینی.docx`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
    showSuccessToast('دانلود با موفقیت انجام شد', `فایل Word با ${toPersianDigits(nonEmptyDays.length)} جلسه ایجاد و دانلود شد`, 5000);
  } catch (err) { console.error(err); showErrorToast('خطا در خروجی', 'مشکلی در ساخت یا ذخیره فایل Word پیش آمد.'); }
}

// ============================
// Toast System
// ============================
function createToastContainer() {
  let container = document.getElementById('toast-container');
  if (!container) { container = document.createElement('div'); container.id = 'toast-container'; container.className = 'toast-container'; document.body.appendChild(container); }
  return container;
}

function showToast({ title, message, type = 'success', duration = 4000 }) {
  const container = createToastContainer();
  const icons = { success: '✅', info: 'ℹ️', warning: '⚠️', error: '❌' };
  const toast = document.createElement('div');
  toast.className = 'toast';
  toast.innerHTML = `<div class="toast-icon ${type}">${icons[type] || icons.success}</div><div class="toast-content"><div class="toast-title">${title}</div>${message ? `<div class="toast-message">${message}</div>` : ''}</div><button class="toast-close">✕</button><div class="toast-progress"></div>`;
  container.appendChild(toast);
  requestAnimationFrame(() => toast.classList.add('show'));
  const progressBar = toast.querySelector('.toast-progress');
  let startTime = Date.now();
  let remainingTime = duration;
  let progressInterval;
  function updateProgress() { const elapsed = Date.now() - startTime; remainingTime = Math.max(0, duration - elapsed); progressBar.style.width = (remainingTime / duration) * 100 + '%'; if (remainingTime <= 0) clearInterval(progressInterval); }
  progressInterval = setInterval(updateProgress, 50);
  toast.querySelector('.toast-close').addEventListener('click', () => removeToast(toast, progressInterval));
  toast.addEventListener('mouseenter', () => clearInterval(progressInterval));
  toast.addEventListener('mouseleave', () => { startTime = Date.now(); duration = remainingTime; progressInterval = setInterval(updateProgress, 50); });
  const timeoutId = setTimeout(() => removeToast(toast, progressInterval), duration);
  toast._timeoutId = timeoutId; toast._progressInterval = progressInterval;
  return toast;
}

function removeToast(toast, progressInterval) {
  if (toast._removing) return; toast._removing = true;
  clearTimeout(toast._timeoutId); clearInterval(progressInterval || toast._progressInterval);
  toast.classList.add('hide'); toast.classList.remove('show');
  setTimeout(() => { if (toast.parentNode) toast.remove(); }, 400);
}

function showSuccessToast(title, message, duration) { return showToast({ title, message, type: 'success', duration }); }
function showInfoToast(title, message, duration) { return showToast({ title, message, type: 'info', duration }); }
function showWarningToast(title, message, duration) { return showToast({ title, message, type: 'warning', duration }); }
function showErrorToast(title, message, duration) { return showToast({ title, message, type: 'error', duration }); }

// ============================
// 10. DRAWER - بدون افزودن کلاینت و برنامه جدید
// ============================
let drawerStudents = loadDrawerStudents();

function createId(prefix = "id") { return `${prefix}_${Date.now()}_${Math.random().toString(16).slice(2)}`; }

function renameProgram(studentId, programId) {
  const student = drawerStudents.find(item => item.id === studentId);
  if (!student) return;
  const program = student.programs.find(item => item.id === programId);
  if (!program) return;
  const newName = prompt("نام جدید برنامه را وارد کنید:", program.name);
  if (!newName || !newName.trim()) return;
  program.name = newName.trim();
  saveDrawerStudents();
  renderDrawerStudents();
}

function deleteProgram(studentId, programId) {
  const student = drawerStudents.find(item => item.id === studentId);
  if (!student) return;
  const program = student.programs.find(item => item.id === programId);
  if (!program) return;
  if (!confirm(`برنامه «${program.name}» حذف شود؟`)) return;
  const wasActiveProgram = state.activeStudentId === studentId && state.activeProgramId === programId;
  student.programs = student.programs.filter(item => item.id !== programId);
  deleteProgramDataByRef(studentId, programId);
  saveDrawerStudents();
  if (wasActiveProgram) {
    state.activeStudentId = null; state.activeProgramId = null;
    clearActiveProgramRef();
    const fallbackData = { days: createDefaultDays(), clipboard: null, studentName: "" };
    localStorage.setItem(STORAGE_KEY, JSON.stringify(fallbackData));
    loadStateFromProgramData(fallbackData);
  }
  renderDrawerStudents();
}

function toggleStudent(studentId) {
  const student = drawerStudents.find(item => item.id === studentId);
  if (!student) return;
  student.isOpen = !student.isOpen;
  const studentItem = document.querySelector(`[data-student-toggle="${studentId}"]`)?.closest(".drawer-student-item");
  if (studentItem) studentItem.classList.toggle("is-open");
}

function toggleProgramMenu(programItemEl) {
  document.querySelectorAll(".drawer-program-item.menu-open").forEach(item => { if (item !== programItemEl) item.classList.remove("menu-open"); });
  programItemEl.classList.toggle("menu-open");
}

function toggleStudentMenu(studentItemEl) {
  document.querySelectorAll(".drawer-student-item.menu-open").forEach(item => { if (item !== studentItemEl) item.classList.remove("menu-open"); });
  studentItemEl.classList.toggle("menu-open");
}

function selectProgram(studentId, programId) {
  const student = drawerStudents.find(item => item.id === studentId);
  if (!student) return;
  const program = student.programs.find(item => item.id === programId);
  if (!program) return;
  const data = ensureProgramDataExists(studentId, programId, student.name);
  state.activeStudentId = studentId;
  state.activeProgramId = programId;
  saveActiveProgramRef(studentId, programId);
  loadStateFromProgramData(data);
  renderDrawerStudents();
}

function renameStudent(studentId) {
  const student = drawerStudents.find(item => item.id === studentId);
  if (!student) return;
  const newName = prompt("نام جدید کلاینت را وارد کنید:", student.name);
  if (!newName || !newName.trim()) return;
  const trimmedName = newName.trim();
  student.name = trimmedName;
  if (state.activeStudentId === studentId) {
    state.studentName = trimmedName;
    if (state.activeProgramId) { const ad = loadProgramDataByRef(studentId, state.activeProgramId) || createEmptyProgramData(trimmedName); ad.studentName = trimmedName; saveProgramDataByRef(studentId, state.activeProgramId, ad); }
    saveAppData(); updateHeaderTitle();
  }
  saveDrawerStudents(); renderDrawerStudents();
}

function deleteStudent(studentId) {
  const student = drawerStudents.find(item => item.id === studentId);
  if (!student) return;
  if (!confirm(`کلاینت «${student.name}» و تمام برنامه‌هایش حذف شود؟`)) return;
  if (Array.isArray(student.programs)) student.programs.forEach(program => deleteProgramDataByRef(studentId, program.id));
  const wasActiveStudent = state.activeStudentId === studentId;
  drawerStudents = drawerStudents.filter(item => item.id !== studentId);
  saveDrawerStudents();
  if (wasActiveStudent) { state.activeStudentId = null; state.activeProgramId = null; clearActiveProgramRef(); const fallbackData = { days: createDefaultDays(), clipboard: null, studentName: "" }; localStorage.setItem(STORAGE_KEY, JSON.stringify(fallbackData)); loadStateFromProgramData(fallbackData); }
  renderDrawerStudents(); updateHeaderTitle();
}

function renderDrawerStudents() {
  const drawerStudentsList = document.getElementById("drawerStudentsList");
  if (!drawerStudentsList) return;
  drawerStudentsList.innerHTML = "";
  if (!drawerStudents.length) { drawerStudentsList.innerHTML = `<div class="drawer-empty-text">هنوز کلاینتی اضافه نشده است.</div>`; return; }
  drawerStudents.forEach(student => {
    const studentItem = document.createElement("div");
    studentItem.className = "drawer-student-item";
    const isActiveStudent = state.activeStudentId === student.id;
    if (student.isOpen || isActiveStudent) studentItem.classList.add("is-open");
    studentItem.innerHTML = `
      <div class="drawer-student-head-wrap">
        <button class="drawer-student-head" type="button" data-student-toggle="${student.id}">
          <span class="drawer-student-name">${escapeHtml(student.name)}</span>
          <span class="drawer-student-arrow" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"><path d="M6 9L12 15L18 9" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
        </button>
        <button class="program-more-btn student-more-btn icon-more-btn" type="button" data-student-menu-btn aria-label="گزینه‌های کلاینت">
          <svg class="more-dots-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="5" r="1.8"></circle><circle cx="12" cy="12" r="1.8"></circle><circle cx="12" cy="19" r="1.8"></circle></svg>
        </button>
        <div class="program-menu student-menu">
          <button type="button" data-rename-student="${student.id}">تغییر نام کلاینت</button>
          <button type="button" class="delete-program-action" data-delete-student="${student.id}">حذف کلاینت</button>
        </div>
      </div>
      <div class="drawer-student-body">
        <div class="drawer-programs-list">
          ${student.programs.length ? student.programs.map(program => {
      const isActive = state.activeStudentId === student.id && state.activeProgramId === program.id;
      return `<div class="drawer-program-item${isActive ? " is-active" : ""}" data-program-item>
              <div class="drawer-program-name" data-select-program="${student.id}|${program.id}" title="${escapeHtml(program.name)}">${escapeHtml(program.name)}</div>
              <button class="program-more-btn" type="button" data-program-menu-btn aria-label="گزینه‌های برنامه"><svg class="more-dots-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="5" r="1.8"></circle><circle cx="12" cy="12" r="1.8"></circle><circle cx="12" cy="19" r="1.8"></circle></svg></button>
              <div class="program-menu"><button type="button" data-rename-program="${student.id}|${program.id}">تغییر اسم برنامه</button><button type="button" class="delete-program-action" data-delete-program="${student.id}|${program.id}">حذف برنامه</button></div>
            </div>`;
    }).join("") : `<div class="drawer-empty-text">برای این کلاینت برنامه‌ای وجود ندارد.</div>`}
        </div>
      </div>`;
    drawerStudentsList.appendChild(studentItem);
  });
}

// ============================
// 11. HELPERS
// ============================
function loadStateFromProgramData(data) {
  const safeData = data || {};
  state.days = Array.isArray(safeData.days) ? safeData.days.map(normalizeDay) : createDefaultDays();
  state.theme = loadGlobalTheme();
  state.clipboard = safeData.clipboard ? normalizeWorkoutItem(safeData.clipboard) : null;
  state.dayClipboard = safeData.dayClipboard || null;
  let studentName = typeof safeData.studentName === "string" ? safeData.studentName : "";
  if (state.activeStudentId) { try { const students = JSON.parse(localStorage.getItem(STUDENTS_KEY) || '[]'); const student = students.find(s => s.id === state.activeStudentId); if (student && student.name) studentName = student.name; } catch(e) {} }
  state.studentName = studentName;
  state.currentDay = 0;
  applyTheme(state.theme, { save: false });
  renderDays(); renderWorkoutList(); renderExerciseList(); updatePasteButtons(); updateHeaderTitle();
}

function createEmptyProgramData(studentName = "") { return { days: createDefaultDays(), clipboard: null, studentName: studentName || "" }; }

function ensureProgramDataExists(studentId, programId, studentName = "") { const existing = loadProgramDataByRef(studentId, programId); if (existing) return existing; const freshData = createEmptyProgramData(studentName); saveProgramDataByRef(studentId, programId, freshData); return freshData; }

// ============================
// 12. DRAWER EVENT DELEGATION
// ============================
document.addEventListener("DOMContentLoaded", () => {
  const drawerSearchInput = document.getElementById("drawerSearchInput");
  if (drawerSearchInput) { drawerSearchInput.addEventListener("input", function() { const query = this.value.trim().toLowerCase(); document.querySelectorAll(".drawer-student-item").forEach(item => { const nameEl = item.querySelector(".drawer-student-name"); if (nameEl) item.style.display = (query === "" || nameEl.textContent.toLowerCase().includes(query)) ? "" : "none"; }); }); }

  document.getElementById("drawerStudentsList")?.addEventListener("click", function (event) {
    const target = event.target;
    const btn = target.closest("[data-student-toggle]"); if (btn) { toggleStudent(btn.dataset.studentToggle); return; }
    const moreBtn = target.closest("[data-program-menu-btn]"); if (moreBtn) { event.stopPropagation(); const pi = moreBtn.closest("[data-program-item]"); if (pi) toggleProgramMenu(pi); return; }
    const renameBtn = target.closest("[data-rename-program]"); if (renameBtn) { event.stopPropagation(); const [s, p] = renameBtn.dataset.renameProgram.split("|"); renameProgram(s, p); return; }
    const deleteBtn = target.closest("[data-delete-program]"); if (deleteBtn) { event.stopPropagation(); const [s, p] = deleteBtn.dataset.deleteProgram.split("|"); deleteProgram(s, p); return; }
    const selBtn = target.closest("[data-select-program]"); if (selBtn) { const [s, p] = selBtn.dataset.selectProgram.split("|"); selectProgram(s, p); return; }
    const stuMoreBtn = target.closest("[data-student-menu-btn]"); if (stuMoreBtn) { event.stopPropagation(); const si = stuMoreBtn.closest(".drawer-student-item"); if (si) toggleStudentMenu(si); return; }
    const renStuBtn = target.closest("[data-rename-student]"); if (renStuBtn) { event.stopPropagation(); renameStudent(renStuBtn.dataset.renameStudent); return; }
    const delStuBtn = target.closest("[data-delete-student]"); if (delStuBtn) { event.stopPropagation(); deleteStudent(delStuBtn.dataset.deleteStudent); return; }
  });
  document.addEventListener("click", function (event) {
    if (!event.target.closest(".drawer-program-item")) document.querySelectorAll(".drawer-program-item.menu-open").forEach(item => item.classList.remove("menu-open"));
    if (!event.target.closest(".drawer-student-item")) document.querySelectorAll(".drawer-student-item.menu-open").forEach(item => item.classList.remove("menu-open"));
  });
  renderDrawerStudents();
});

// ============================
// 13. APP INITIALIZATION
// ============================
document.body.classList.add("app-loading");

function init() {
  state.theme = loadGlobalTheme();
  applyTheme(state.theme, { save: false });
  renderCategories();
  renderExerciseList();
  renderDays();
  renderWorkoutList();
  renderDrawerStudents();
  updatePasteButtons();
  updateHeaderTitle();
  document.body.classList.remove("app-loading");
  document.body.classList.add("app-ready");
}

// Event Listeners
const pasteDayBtn = document.getElementById("pasteDayBtn");
if (pasteDayBtn) { pasteDayBtn.addEventListener("click", () => { const dayClipboard = loadDayFromClipboard(); if (!dayClipboard) { showWarningToast('کلیپبورد خالی', 'ابتدا یک جلسه را کپی کنید', 2000); return; } const clonedDay = { name: dayClipboard.name || "جلسه کپی شده", items: (dayClipboard.items || []).map(item => deepCloneWorkoutItem(item)) }; state.days.push(clonedDay); state.currentDay = state.days.length - 1; renderDays(); renderWorkoutList(); saveAppData(); showSuccessToast('جایگذاری موفق', `جلسه "${clonedDay.name}" به انتها اضافه شد`, 3000); }); }

const dropzone = document.getElementById("dropzone");
if (dropzone) { dropzone.addEventListener("dragover", (e) => { e.preventDefault(); dropzone.classList.add("drag-over"); }); dropzone.addEventListener("dragleave", () => { dropzone.classList.remove("drag-over"); }); dropzone.addEventListener("drop", (e) => { e.preventDefault(); dropzone.classList.remove("drag-over"); if (state.pendingInsertIndex !== null && state.pendingInsertIndex !== undefined) { handleDropAtIndex(e, state.pendingInsertIndex); return; } removeGhosts(); const raw = e.dataTransfer.getData("text/plain"); if (!raw) return; const data = JSON.parse(raw); const day = state.days[state.currentDay]; if (data.type === "bank") { const ex = exercises.find((x) => x.id === data.exerciseId); if (!ex) return; day.items.push(createWorkoutItem(ex)); } else if (data.type === "workout") { const sourceDay = state.days[data.dayIndex]; const sourceIndex = sourceDay.items.findIndex((x) => x.uid === data.uid); if (sourceIndex === -1) return; const [moved] = sourceDay.items.splice(sourceIndex, 1); day.items.push(moved); } state.dragSource = null; state.pendingInsertIndex = null; renderWorkoutList(); renderDays(); saveAppData(); }); }

const pasteBtn = document.getElementById("pasteBtn");
if (pasteBtn) { pasteBtn.addEventListener("click", () => { const clipboard = loadMoveFromClipboard(); if (!clipboard) { showWarningToast('کلیپبورد خالی', 'ابتدا یک حرکت را کپی کنید', 2000); return; } state.days[state.currentDay].items.push(deepCloneWorkoutItem(clipboard)); renderWorkoutList(); renderDays(); saveAppData(); showSuccessToast('جایگذاری موفق', 'حرکت با موفقیت اضافه شد', 2000); }); }

const searchInput = document.getElementById("searchInput");
if (searchInput) { searchInput.addEventListener("input", (e) => { state.search = e.target.value.trim(); renderExerciseList(); }); }

const themeSelect = document.getElementById("themeSelect");
if (themeSelect) { themeSelect.addEventListener("change", (e) => applyTheme(e.target.value)); }

const exportOutputBtn = document.getElementById("exportOutputBtn");
const exportMenu = document.getElementById("exportMenu");
const closeExportMenuBtn = document.getElementById("closeExportMenu");
if (exportOutputBtn && exportMenu) { exportOutputBtn.addEventListener("click", (e) => { e.stopPropagation(); if (!exportMenu.classList.contains("hidden")) { exportMenu.classList.add("hidden"); return; } const rect = exportOutputBtn.getBoundingClientRect(); exportMenu.style.top = `${rect.bottom + window.scrollY}px`; exportMenu.style.left = `${rect.left + window.scrollX}px`; exportMenu.classList.remove("hidden"); }); }
if (closeExportMenuBtn && exportMenu) { closeExportMenuBtn.addEventListener("click", (e) => { e.stopPropagation(); exportMenu.classList.add("hidden"); }); }
document.addEventListener("click", (e) => { if (exportMenu && !exportMenu.contains(e.target) && e.target !== exportOutputBtn) exportMenu.classList.add("hidden"); });

document.getElementById("exportAsImage")?.addEventListener("click", () => { exportProgramAsImage(); if (exportMenu) exportMenu.classList.add("hidden"); });
document.getElementById("exportAsPdf")?.addEventListener("click", exportProgramAsPdf);
document.getElementById("exportAsWord")?.addEventListener("click", exportProgramAsWord);

const openAppDrawerBtn = document.getElementById("openAppDrawer");
const closeAppDrawerBtn = document.getElementById("closeAppDrawer");
const appDrawer = document.getElementById("appDrawer");
const drawerBackdrop = document.getElementById("drawerBackdrop");

function openAppDrawer() { if (!appDrawer || !drawerBackdrop) return; appDrawer.classList.add("is-open"); drawerBackdrop.classList.add("is-open"); document.body.classList.add("drawer-open"); appDrawer.setAttribute("aria-hidden", "false"); renderDrawerStudents(); }
function closeAppDrawer() { if (!appDrawer || !drawerBackdrop) return; appDrawer.classList.remove("is-open"); drawerBackdrop.classList.remove("is-open"); document.body.classList.remove("drawer-open"); appDrawer.setAttribute("aria-hidden", "true"); }

openAppDrawerBtn?.addEventListener("click", openAppDrawer);
closeAppDrawerBtn?.addEventListener("click", closeAppDrawer);
drawerBackdrop?.addEventListener("click", closeAppDrawer);
document.addEventListener("keydown", (event) => { if (event.key === "Escape") { closeAppDrawer(); const dayMenu = document.getElementById("dayContextMenu"); if (dayMenu) dayMenu.remove(); } });

// ============================
// 14. START
// ============================
init();