// Onboarding — short first-run setup for goals, monthly money structure,
// and customizable daily routines. Mounted full-screen by App.

const ONB_GOALS = [
  { key: 'tasks', label: 'کارها و وظایف', icon: 'CheckCircle' },
  { key: 'finance', label: 'دخل و خرج', icon: 'Wallet' },
  { key: 'knowledge', label: 'یادداشت و دانش', icon: 'Book' },
  { key: 'habits', label: 'عادت‌های روزانه', icon: 'Flame' },
];

const ONB_FINANCE_ITEMS = [
  { key: 'salary', title: 'حقوق ماهانه', label: 'حقوق یا درآمد ثابت', type: 'income', cat: 'salary', hint: 'مثلاً ۳۵ میلیون', icon: 'Briefcase' },
  { key: 'freelance', title: 'درآمد جانبی', label: 'فریلنس یا درآمد دوم', type: 'income', cat: 'freelance', hint: 'اختیاری', icon: 'TrendUp' },
  { key: 'rent', title: 'اجاره خانه', label: 'اجاره / خانه', type: 'expense', cat: 'rent', hint: 'مثلاً ۱۵ میلیون', icon: 'Home' },
  { key: 'loan', title: 'قسط‌های ماهانه', label: 'جمع قسط‌ها', type: 'expense', cat: 'loan', hint: 'مثلاً ۸ میلیون', icon: 'Calendar' },
  { key: 'utilities', title: 'قبض‌های ماهانه', label: 'قبض، اینترنت، شارژ', type: 'expense', cat: 'utilities', hint: 'مثلاً ۲ میلیون', icon: 'Bolt' },
  { key: 'food', title: 'خوراک و سوپرمارکت', label: 'خوراک ماهانه', type: 'expense', cat: 'food', hint: 'مثلاً ۱۲ میلیون', icon: 'Wallet' },
  { key: 'other', title: 'هزینه‌های ثابت دیگر', label: 'سایر ثابت‌ها', type: 'expense', cat: 'other', hint: 'اختیاری', icon: 'Plus' },
];

const ONB_ROUTINES = {
  morning: {
    title: 'صبح را خودت تنظیم کن',
    sub: 'هر عادتی را می‌خواهی انتخاب کن؛ ساعت پیش‌فرض را با دکمه‌های + و − تنظیم کن.',
    accent: 'var(--saffron)',
    soft: 'var(--saffron-soft)',
    items: [
      { t: 'بیدار شدن',       icon: 'Clock',       defaultTime: '06:30' },
      { t: 'نوشیدن آب',       icon: 'Wave',        defaultTime: '06:45' },
      { t: 'مدیتیشن یا نماز', icon: 'Heart',       defaultTime: '07:00' },
      { t: 'مسواک زدن',       icon: 'CheckCircle', defaultTime: '07:15' },
      { t: 'مصرف دارو',       icon: 'Bell',        defaultTime: '07:30' },
      { t: 'دوش گرفتن',       icon: 'Sparkle',     defaultTime: '07:00' },
      { t: 'صبحانه',          icon: 'Star',        defaultTime: '07:30' },
      { t: 'قهوه',            icon: 'Bolt',        defaultTime: '08:00' },
      { t: 'مرور برنامه روز', icon: 'Calendar',    defaultTime: '08:30' },
    ],
  },
  day: {
    title: 'وسط روز را قابل انجام کن',
    sub: 'کار عمیق، پیگیری‌ها و کارهای تکراری روزانه را اینجا بچین.',
    accent: 'var(--firoozeh)',
    soft: 'var(--firoozeh-soft)',
    items: [
      { t: 'شروع کار',       icon: 'Briefcase', defaultTime: '09:00' },
      { t: 'کار عمیق',       icon: 'Bolt',      defaultTime: '10:00' },
      { t: 'بررسی پیام‌ها',  icon: 'Chat',      defaultTime: '11:00' },
      { t: 'درس خواندن',     icon: 'Book',      defaultTime: '10:30' },
      { t: 'ناهار',          icon: 'Calendar',  defaultTime: '13:00' },
      { t: 'ورزش',           icon: 'Flame',     defaultTime: '17:00' },
      { t: 'خرید مایحتاج',  icon: 'Wallet',    defaultTime: '15:00' },
    ],
  },
  evening: {
    title: 'شب را آرام ببند',
    sub: 'چند عادت کوچک برای جمع‌بندی روز و آماده شدن برای فردا.',
    accent: 'var(--moss)',
    soft: 'var(--moss-soft)',
    items: [
      { t: 'شام',                    icon: 'Calendar',    defaultTime: '20:00' },
      { t: 'مرتب‌سازی سریع',         icon: 'CheckCircle', defaultTime: '21:00' },
      { t: 'یادداشت روزانه',         icon: 'Edit',        defaultTime: '21:30' },
      { t: 'مطالعه',                 icon: 'Book',        defaultTime: '22:00' },
      { t: 'کشش یا یوگا',            icon: 'Heart',       defaultTime: '21:00' },
      { t: 'آماده‌شدن برای خواب',    icon: 'Clock',       defaultTime: '22:30' },
    ],
  },
};

function OnbTimePicker({ value, onChange, accent }) {
  const faN = s => String(s).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d]);
  const [h, setH] = React.useState(() => value ? parseInt(value.split(':')[0], 10) : 7);
  const [m, setM] = React.useState(() => {
    if (!value) return 0;
    return Math.round(parseInt(value.split(':')[1], 10) / 15) * 15 % 60;
  });
  const emit = (hour, min) => onChange(`${String(hour).padStart(2, '0')}:${String(min).padStart(2, '0')}`);
  const adjH = d => { const nh = (h + d + 24) % 24; setH(nh); emit(nh, m); };
  const adjM = d => { const nm = (m + d + 60) % 60; setM(nm); emit(h, nm); };
  const period = h < 5 ? 'بامداد' : h < 12 ? 'صبح' : h === 12 ? 'ظهر' : h < 17 ? 'بعدازظهر' : 'شب';
  return (
    <div className="onb-tp" style={{ '--tp-accent': accent }}>
      <div className="onb-tp-row">
        <button type="button" className="onb-tp-btn" onClick={() => adjH(1)}>+</button>
        <span className="onb-tp-gap" />
        <button type="button" className="onb-tp-btn" onClick={() => adjM(15)}>+</button>
      </div>
      <div className="onb-tp-row">
        <span className="onb-tp-val">{faN(String(h).padStart(2, '0'))}</span>
        <span className="onb-tp-sep">:</span>
        <span className="onb-tp-val">{faN(String(m).padStart(2, '0'))}</span>
        <span className="onb-tp-period">{period}</span>
      </div>
      <div className="onb-tp-row">
        <button type="button" className="onb-tp-btn" onClick={() => adjH(-1)}>−</button>
        <span className="onb-tp-gap" />
        <button type="button" className="onb-tp-btn" onClick={() => adjM(-15)}>−</button>
      </div>
    </div>
  );
}

function Onboarding({ onFinish, onTryVoice, finishMode = 'voice' }) {
  const Icons = window.Icons || {};
  const asset = window.assetPath || ((name) => `assets/${name}`);
  const [step, setStep] = React.useState(0);
  const [name, setName] = React.useState('');
  const [goals, setGoals] = React.useState([]);
  const [financeDraft, setFinanceDraft] = React.useState({});
  const [picks, setPicks] = React.useState({ morning: {}, day: {}, evening: {} });
  const [routineTimes, setRoutineTimes] = React.useState({ morning: {}, day: {}, evening: {} });
  const [customItems, setCustomItems] = React.useState({ morning: [], day: [], evening: [] });
  const [newItemDraft, setNewItemDraft] = React.useState({ morning: '', day: '', evening: '' });

  const STEPS = ['identity', 'goals', 'finance', 'morning', 'day', 'evening', 'review', 'launch'];
  const cur = STEPS[step];
  const routine = ONB_ROUTINES[cur];
  const accent = routine?.accent || (cur === 'finance' ? 'var(--saffron)' : 'var(--firoozeh)');
  const bgSoft = routine?.soft || (cur === 'finance' ? 'var(--saffron-soft)' : 'var(--paper)');
  const canBack = step > 0;

  const faN = n => String(n).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d]);
  const cleanName = name.trim();
  const toggleGoal = key => setGoals(prev => prev.includes(key) ? prev.filter(x => x !== key) : [...prev, key]);
  const setFinanceValue = (key, value) => setFinanceDraft(prev => ({ ...prev, [key]: value }));

  const toAsciiDigits = value => String(value || '')
    .replace(/[۰-۹]/g, d => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d))
    .replace(/[٠-٩]/g, d => '٠١٢٣٤٥٦٧٨٩'.indexOf(d));

  const normalizeTime = value => {
    const v = String(value || '').trim();
    return /^([01]\d|2[0-3]):[0-5]\d$/.test(v) ? v : '';
  };

  const togglePick = (key, idx) => {
    const wasOn = !!picks[key]?.[idx];
    setPicks(prev => {
      const next = { ...prev[key] };
      if (next[idx]) delete next[idx]; else next[idx] = true;
      return { ...prev, [key]: next };
    });
    setRoutineTimes(prev => {
      const next = { ...prev[key] };
      if (wasOn) {
        delete next[idx];
      } else if (!next[idx]) {
        next[idx] = ONB_ROUTINES[key]?.items?.[idx]?.defaultTime || '08:00';
      }
      return { ...prev, [key]: next };
    });
  };

  const addCustomItem = key => {
    const title = (newItemDraft[key] || '').trim();
    if (!title) return;
    const id = `ci-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
    const defTime = key === 'morning' ? '08:00' : key === 'day' ? '12:00' : '21:00';
    setCustomItems(prev => ({ ...prev, [key]: [...prev[key], { id, t: title, selected: true, time: defTime }] }));
    setNewItemDraft(prev => ({ ...prev, [key]: '' }));
  };

  const deleteCustomItem = (key, id) => {
    setCustomItems(prev => ({ ...prev, [key]: prev[key].filter(ci => ci.id !== id) }));
  };

  const toggleCustomItem = (key, id) => {
    setCustomItems(prev => ({
      ...prev,
      [key]: prev[key].map(ci => ci.id === id ? { ...ci, selected: !ci.selected } : ci),
    }));
  };

  const setCustomItemTime = (key, id, time) => {
    setCustomItems(prev => ({
      ...prev,
      [key]: prev[key].map(ci => ci.id === id ? { ...ci, time } : ci),
    }));
  };

  const parseMoney = value => {
    const raw = String(value || '').trim();
    if (!raw) return 0;
    const ascii = toAsciiDigits(raw)
      .replace(/[,،٬]/g, '')
      .replace(/\s+/g, ' ');
    const match = ascii.match(/\d+(?:[.٫]\d+)?/);
    if (!match) return 0;
    let n = parseFloat(match[0].replace('٫', '.'));
    if (!Number.isFinite(n) || n <= 0) return 0;
    if (/میلیون|m\b/i.test(ascii)) n *= 1000000;
    else if (/هزار|k\b/i.test(ascii)) n *= 1000;
    else if (n > 0 && n < 1000) n *= 1000000;
    return Math.round(n);
  };

  const faMoney = n => n > 0 ? `${n.toLocaleString('fa-IR')} تومان` : 'ثبت نشده';

  const selectedRoutineCount = ['morning', 'day', 'evening']
    .reduce((sum, key) =>
      sum + Object.keys(picks[key]).length + customItems[key].filter(ci => ci.selected).length, 0);

  const buildSeed = () => {
    const now = new Date();
    const todayKey = [now.getFullYear(), String(now.getMonth() + 1).padStart(2, '0'), String(now.getDate()).padStart(2, '0')].join('-');
    const out = [];
    let i = 0;
    ['morning', 'day', 'evening'].forEach(key => {
      const def = ONB_ROUTINES[key];
      Object.keys(picks[key]).forEach(idx => {
        const item = def.items[Number(idx)];
        if (!item) return;
        out.push({
          id: `t-onb-${Date.now()}-${i++}`,
          title: item.t,
          sub: 'روتین',
          cat: 'یادآوری',
          dueDate: todayKey,
          dueTime: normalizeTime(routineTimes[key]?.[idx]),
          section: 'today',
          done: false,
          status: 'pending',
          priority: 'normal',
          recurrence: { type: 'daily' },
          createdAt: Date.now() + i,
        });
      });
      customItems[key].forEach(ci => {
        if (!ci.selected) return;
        out.push({
          id: `t-onb-${Date.now()}-${i++}`,
          title: ci.t,
          sub: 'روتین',
          cat: 'یادآوری',
          dueDate: todayKey,
          dueTime: normalizeTime(ci.time),
          section: 'today',
          done: false,
          status: 'pending',
          priority: 'normal',
          recurrence: { type: 'daily' },
          createdAt: Date.now() + i,
        });
      });
    });
    return out;
  };

  const buildFinanceSeed = () => {
    const now = new Date();
    const todayKey = [now.getFullYear(), String(now.getMonth() + 1).padStart(2, '0'), String(now.getDate()).padStart(2, '0')].join('-');
    let i = 0;
    return ONB_FINANCE_ITEMS.map(item => {
      const amount = parseMoney(financeDraft[item.key]);
      if (amount <= 0) return null;
      return {
        id: `fin-onb-${Date.now()}-${i++}`,
        type: item.type,
        cat: item.cat,
        title: item.title,
        amount,
        date: todayKey,
        recurrence: 'monthly',
      };
    }).filter(Boolean);
  };

  const financeSeed = buildFinanceSeed();
  const financeIncome = financeSeed.filter(f => f.type === 'income').reduce((s, f) => s + f.amount, 0);
  const financeExpense = financeSeed.filter(f => f.type === 'expense').reduce((s, f) => s + f.amount, 0);
  const financeNet = financeIncome - financeExpense;

  const finish = tryVoice => {
    onFinish({
      tasks: buildSeed(),
      finances: buildFinanceSeed(),
      profile: {
        name: cleanName || 'کاربر',
        avatar: (cleanName || 'کاربر')[0],
        goals,
      },
    });
    if (tryVoice && onTryVoice) onTryVoice();
  };

  const next = () => setStep(s => Math.min(s + 1, STEPS.length - 1));
  const prev = () => setStep(s => Math.max(s - 1, 0));
  const goStep = idx => setStep(Math.max(0, Math.min(idx, STEPS.length - 1)));

  const IconBox = ({ icon, tone = 'teal' }) => {
    const Icon = Icons[icon] || Icons.Star;
    return <span className={`onb-iconbox onb-iconbox-${tone}`}>{Icon ? <Icon size={19} /> : null}</span>;
  };

  const RoutineStep = ({ name: routineName }) => {
    const def = ONB_ROUTINES[routineName];
    return (
      <section className="onb-panel onb-panel-wide">
        <div className="onb-step-head">
          <span className="onb-kicker">روتین قابل ویرایش</span>
          <h1>{def.title}</h1>
          <p>{def.sub}</p>
        </div>

        <div className="onb-routine-grid">
          {def.items.map((item, idx) => {
            const on = !!picks[routineName][idx];
            const timeValue = routineTimes[routineName]?.[idx] || '';
            return (
              <article key={idx} className={`onb-routine-card ${on ? 'is-on' : ''}`} style={{ '--routine-accent': def.accent, '--routine-soft': def.soft }}>
                <button type="button" className="onb-routine-pick" onClick={() => togglePick(routineName, idx)}>
                  <IconBox icon={item.icon} tone={on ? 'accent' : 'quiet'} />
                  <span>{item.t}</span>
                  {on ? <span className="onb-check">✓</span> : null}
                </button>
                {on ? (
                  <OnbTimePicker
                    value={timeValue}
                    onChange={v => setRoutineTimes(prev => ({ ...prev, [routineName]: { ...prev[routineName], [idx]: v } }))}
                    accent={def.accent}
                  />
                ) : null}
              </article>
            );
          })}
          {customItems[routineName].map(ci => {
            const on = ci.selected;
            return (
              <article key={ci.id} className={`onb-routine-card onb-routine-custom ${on ? 'is-on' : ''}`} style={{ '--routine-accent': def.accent, '--routine-soft': def.soft }}>
                <div style={{ position: 'relative' }}>
                  <button type="button" className="onb-routine-pick" onClick={() => toggleCustomItem(routineName, ci.id)}>
                    <IconBox icon="Star" tone={on ? 'accent' : 'quiet'} />
                    <span>{ci.t}</span>
                    {on ? <span className="onb-check">✓</span> : null}
                  </button>
                  <button type="button" className="onb-custom-del" onClick={() => deleteCustomItem(routineName, ci.id)} aria-label="حذف">×</button>
                </div>
                {on ? (
                  <OnbTimePicker
                    value={ci.time}
                    onChange={v => setCustomItemTime(routineName, ci.id, v)}
                    accent={def.accent}
                  />
                ) : null}
              </article>
            );
          })}
        </div>

        <div className="onb-add-row">
          <input
            type="text"
            className="onb-add-input"
            placeholder="عادت دیگری داری؟ اینجا بنویس..."
            value={newItemDraft[routineName]}
            onChange={e => setNewItemDraft(prev => ({ ...prev, [routineName]: e.target.value }))}
            onKeyDown={e => e.key === 'Enter' && addCustomItem(routineName)}
            maxLength={40}
          />
          <button
            type="button"
            className="onb-add-btn"
            style={{ '--add-accent': def.accent }}
            onClick={() => addCustomItem(routineName)}
            disabled={!newItemDraft[routineName]?.trim()}
            aria-label="اضافه کردن عادت"
          >+</button>
        </div>
      </section>
    );
  };

  let content;
  let primaryLabel = 'ادامه';
  let primaryAction = next;
  let secondary = null;

  if (cur === 'identity') {
    content = (
      <section className="onb-panel onb-identity">
        <div className="onb-seal">
          <img src={asset('mark.svg?v=logi-functional-v2-20260604')} alt="" />
        </div>
        <div className="onb-step-head center">
          <span className="onb-kicker">شروع شخصی‌سازی</span>
          <h1>لاگی را با نام خودت روشن کن</h1>
          <p>این مسیر کوتاه، برنامه اولیه کارها، پول ماهانه و چند عادت روزانه را برای تو می‌سازد.</p>
        </div>
        <label className="onb-input-label">
          <span>نام تو</span>
          <input value={name} onChange={e => setName(e.target.value)} placeholder="مثلاً نوید" autoFocus />
        </label>
      </section>
    );
  } else if (cur === 'goals') {
    content = (
      <section className="onb-panel">
        <div className="onb-step-head">
          <span className="onb-kicker">تمرکز اصلی</span>
          <h1>می‌خواهی کدام بخش زندگی مرتب‌تر شود؟</h1>
          <p>هر چند مورد را که می‌خواهی انتخاب کن؛ بعداً هم از داخل برنامه قابل تغییر است.</p>
        </div>
        <div className="onb-choice-grid">
          {ONB_GOALS.map(goal => {
            const on = goals.includes(goal.key);
            return (
              <button key={goal.key} type="button" className={`onb-choice ${on ? 'is-on' : ''}`} onClick={() => toggleGoal(goal.key)}>
                <IconBox icon={goal.icon} tone={on ? 'accent' : 'quiet'} />
                <span>{goal.label}</span>
                {on ? <b>✓</b> : null}
              </button>
            );
          })}
        </div>
      </section>
    );
  } else if (cur === 'finance') {
    content = (
      <section className="onb-panel onb-panel-wide">
        <div className="onb-step-head">
          <span className="onb-kicker">چرتکه ماهانه</span>
          <h1>ساختار مالی ماهت را کوتاه وارد کن</h1>
          <p>فقط مبلغ‌های ثابت را تقریبی بنویس. هر ردیف خالی بماند ثبت نمی‌شود.</p>
        </div>
        <div className="onb-finance-layout">
          <div className="onb-finance-list">
            {ONB_FINANCE_ITEMS.map(item => {
              const value = financeDraft[item.key] || '';
              const amount = parseMoney(value);
              const Icon = Icons[item.icon] || Icons.Wallet;
              return (
                <label key={item.key} className={`onb-money-row ${item.type === 'income' ? 'income' : 'expense'}`}>
                  <span className="onb-money-icon">{Icon ? <Icon size={18} /> : null}</span>
                  <span className="onb-money-copy">
                    <b>{item.label}</b>
                    <small>{amount ? faMoney(amount) : item.hint}</small>
                  </span>
                  <input
                    value={value}
                    onChange={e => setFinanceValue(item.key, e.target.value)}
                    inputMode="numeric"
                    dir="rtl"
                    placeholder="مبلغ"
                  />
                </label>
              );
            })}
          </div>
          <aside className="onb-money-summary">
            <span className="onb-summary-label">نمای ماهانه</span>
            <div><small>درآمد ثابت</small><b>{faMoney(financeIncome)}</b></div>
            <div><small>هزینه ثابت</small><b>{faMoney(financeExpense)}</b></div>
            <strong className={financeNet >= 0 ? 'positive' : 'negative'}>
              <small>مانده تقریبی</small>
              <span>{financeSeed.length ? `${financeNet < 0 ? '−' : '+'}${faMoney(Math.abs(financeNet))}` : 'بعد از ورود مبالغ حساب می‌شود'}</span>
            </strong>
          </aside>
        </div>
      </section>
    );
  } else if (cur === 'morning') content = RoutineStep({ name: 'morning' });
  else if (cur === 'day') content = RoutineStep({ name: 'day' });
  else if (cur === 'evening') content = RoutineStep({ name: 'evening' });
  else if (cur === 'review') {
    content = (
      <section className="onb-panel onb-review">
        <div className="onb-step-head center">
          <span className="onb-kicker">مرور قبل از ورود</span>
          <h1>برنامه اولیه‌ات آماده است</h1>
          <p>هر بخشی نیاز به تغییر دارد، از همینجا برگرد و ویرایش کن.</p>
        </div>
        <div className="onb-review-grid">
          <button type="button" onClick={() => goStep(0)}><IconBox icon="User" /><span><b>{cleanName || 'نام وارد نشده'}</b><small>نام کاربر</small></span></button>
          <button type="button" onClick={() => goStep(1)}><IconBox icon="Star" /><span><b>{goals.length ? `${faN(goals.length)} هدف` : 'بدون هدف انتخابی'}</b><small>تمرکز برنامه</small></span></button>
          <button type="button" onClick={() => goStep(2)}><IconBox icon="Wallet" /><span><b>{financeSeed.length ? `${faN(financeSeed.length)} ردیف مالی` : 'بدون ردیف مالی'}</b><small>ساختار ماهانه</small></span></button>
          <button type="button" onClick={() => goStep(3)}><IconBox icon="Flame" /><span><b>{selectedRoutineCount ? `${faN(selectedRoutineCount)} عادت` : 'بدون عادت'}</b><small>روتین‌های روزانه</small></span></button>
        </div>
        <div className="onb-xp-card">
          <span>+۳۰ XP</span>
          <small>پاداش تکمیل مسیر شروع</small>
        </div>
      </section>
    );
  } else if (cur === 'launch') {
    const authMode = finishMode === 'auth';
    content = (
      <section className="onb-panel onb-launch">
        <div className="onb-launch-mark">
          {authMode ? (Icons.Bell ? <Icons.Bell size={34} /> : null) : (Icons.Mic ? <Icons.Mic size={34} /> : null)}
        </div>
        <div className="onb-step-head center">
          <span className="onb-kicker">{authMode ? 'تایید امن' : 'اولین ثبت سریع'}</span>
          <h1>{authMode ? 'یک کد پیامکی تا ورود' : 'از اینجا به بعد فقط بگو یا بنویس'}</h1>
          <p>
            {authMode
              ? 'در مرحله بعد نام و شماره موبایل را تایید می‌کنی و لاگی همین برنامه اولیه را وارد حساب تو می‌کند.'
              : 'مثلاً بگو «فردا ساعت ۶ جلسه دارم» یا «۵۰ هزار تومان قهوه خریدم»؛ لاگی خودش آن را به کار یا خرج تبدیل می‌کند.'}
          </p>
        </div>
      </section>
    );
    primaryLabel = authMode ? 'تایید شماره و ورود' : 'شروع با صدا';
    primaryAction = () => finish(!authMode);
    secondary = authMode ? null : { label: 'بعداً خودم شروع می‌کنم', action: () => finish(false) };
  }

  return (
    <div className="onb-root" dir="rtl" style={{ '--onb-accent': accent, '--onb-soft': bgSoft }}>
      <style>{`
        .onb-root{
          position:fixed; inset:0; z-index:4000; overflow:hidden; direction:rtl;
          display:grid; grid-template-rows:auto minmax(0,1fr) auto;
          font-family:var(--font-sans); color:var(--ink);
          background:
            radial-gradient(circle at 84% 10%, color-mix(in srgb, var(--onb-soft) 92%, transparent), transparent 30%),
            radial-gradient(circle at 10% 86%, rgba(42,157,143,0.14), transparent 26%),
            linear-gradient(135deg, var(--paper), color-mix(in srgb, var(--onb-soft) 46%, var(--paper)));
        }
        .onb-root:before{
          content:""; position:absolute; inset:0; pointer-events:none; opacity:0.54;
          background:
            linear-gradient(90deg, rgba(25,28,29,0.028) 1px, transparent 1px),
            linear-gradient(0deg, rgba(25,28,29,0.022) 1px, transparent 1px),
            url(${asset('paper-grain.svg')});
          background-size:42px 42px, 42px 42px, 180px 180px;
        }
        .onb-root *{ box-sizing:border-box; letter-spacing:0; }
        .onb-chrome,.onb-body,.onb-footer{ position:relative; z-index:1; width:min(840px, 100%); margin:0 auto; }
        .onb-chrome{ padding:16px 22px 6px; }
        .onb-meta{ display:flex; justify-content:space-between; align-items:center; gap:10px; margin-bottom:10px; }
        .onb-badge{
          min-height:30px; display:inline-flex; align-items:center; gap:7px; padding:0 10px;
          border-radius:999px; background:rgba(255,255,255,0.66); border:1px solid var(--c-border-xs);
          box-shadow:var(--shadow-press); color:var(--ink-2); font:850 11.5px/1 var(--font-sans);
        }
        .onb-progress{ display:grid; grid-template-columns:repeat(8,1fr); gap:6px; }
        .onb-dot{ height:4px; border-radius:999px; background:var(--c-border-md); overflow:hidden; }
        .onb-dot.is-on{ background:var(--onb-accent); box-shadow:0 0 0 3px color-mix(in srgb, var(--onb-accent) 16%, transparent); }
        .onb-body{ min-height:0; overflow:auto; padding:14px 22px 18px; display:grid; align-items:center; }
        .onb-panel{
          width:100%; max-width:680px; margin:0 auto; animation:onbEnter 460ms var(--ease-out) both;
        }
        .onb-panel-wide{ max-width:820px; }
        .onb-step-head{ margin-bottom:20px; }
        .onb-step-head.center{ text-align:center; display:grid; justify-items:center; }
        .onb-kicker{
          display:inline-flex; align-items:center; min-height:30px; padding:0 10px; border-radius:999px;
          background:rgba(255,255,255,0.70); border:1px solid var(--c-border-xs);
          color:var(--onb-accent); font:950 12px/1 var(--font-sans); box-shadow:var(--shadow-press);
        }
        .onb-step-head h1{ margin:13px 0 8px; font:950 28px/1.45 var(--font-sans); color:var(--ink); }
        .onb-step-head p{ max-width:520px; margin:0; font:600 15px/1.9 var(--font-sans); color:var(--ink-2); }
        .onb-seal{
          width:104px; height:104px; margin:0 auto 20px; display:grid; place-items:center; border-radius:32px;
          background:rgba(255,255,255,0.75); border:1px solid var(--c-border-xs);
          box-shadow:var(--shadow-float), var(--shadow-press); animation:onbLogoSettle 720ms var(--ease-out) both;
        }
        .onb-seal img{ width:82px; height:82px; display:block; }
        .onb-input-label{ display:grid; gap:8px; max-width:390px; margin:0 auto; }
        .onb-input-label span{ font:850 12px/1 var(--font-sans); color:var(--ink-2); }
        .onb-input-label input,.onb-money-row input{
          width:100%; border:1px solid var(--c-border-sm); background:rgba(255,255,255,0.78);
          color:var(--ink); border-radius:14px; outline:none; box-shadow:var(--shadow-press);
          transition:border-color 160ms var(--ease-out), box-shadow 160ms var(--ease-out), background 160ms var(--ease-out);
        }
        .onb-input-label input{ min-height:54px; padding:0 14px; font:850 16px/1 var(--font-sans); }
        .onb-input-label input:focus,.onb-money-row input:focus{ border-color:var(--onb-accent); box-shadow:var(--focus-ring); background:#fff; }
        .onb-choice-grid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; }
        .onb-choice,.onb-review-grid button{
          appearance:none; border:1px solid var(--c-border-xs); background:rgba(255,255,255,0.68);
          color:var(--ink); border-radius:18px; box-shadow:var(--shadow-lift), var(--shadow-press);
          cursor:pointer; transition:transform 170ms var(--ease-out), border-color 170ms var(--ease-out), background 170ms var(--ease-out);
        }
        .onb-choice{
          min-height:112px; padding:16px; display:grid; align-content:center; justify-items:center; gap:10px;
          font:900 14px/1.45 var(--font-sans); position:relative;
        }
        .onb-choice.is-on{ background:color-mix(in srgb, var(--firoozeh-soft) 78%, #fff); border-color:rgba(42,157,143,0.34); color:var(--firoozeh-deep); }
        .onb-choice b{ position:absolute; top:10px; left:10px; color:#fff; background:var(--firoozeh); width:24px; height:24px; display:grid; place-items:center; border-radius:999px; }
        .onb-iconbox{
          width:40px; height:40px; border-radius:14px; display:grid; place-items:center;
          background:var(--firoozeh-soft); color:var(--firoozeh-deep);
        }
        .onb-iconbox-quiet{ background:var(--paper-2); color:var(--ink-3); }
        .onb-iconbox-accent{ background:color-mix(in srgb, var(--onb-accent) 18%, #fff); color:var(--onb-accent); }
        .onb-finance-layout{ display:grid; grid-template-columns:minmax(0,1fr) 250px; gap:14px; align-items:start; }
        .onb-finance-list{ display:grid; gap:10px; }
        .onb-money-row{
          display:grid; grid-template-columns:auto minmax(0,1fr) minmax(118px,0.35fr); gap:10px; align-items:center;
          padding:11px; border-radius:17px; background:rgba(255,255,255,0.68);
          border:1px solid var(--c-border-xs); box-shadow:var(--shadow-press);
        }
        .onb-money-icon{ width:38px; height:38px; border-radius:14px; display:grid; place-items:center; background:var(--saffron-soft); color:#9a6200; }
        .onb-money-row.income .onb-money-icon{ background:var(--firoozeh-soft); color:var(--firoozeh-deep); }
        .onb-money-copy{ min-width:0; }
        .onb-money-copy b{ display:block; font:850 13px/1.45 var(--font-sans); color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
        .onb-money-copy small{ display:block; margin-top:2px; font:650 11px/1.4 var(--font-sans); color:var(--ink-3); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
        .onb-money-row input{ min-height:42px; padding:0 11px; font:800 13px/1 var(--font-sans); }
        .onb-money-summary{
          position:sticky; top:10px; display:grid; gap:10px; padding:15px; border-radius:22px;
          background:linear-gradient(180deg, rgba(25,28,29,0.96), rgba(28,43,41,0.96));
          color:var(--fg-on-invert); box-shadow:var(--shadow-ink), var(--shadow-press);
        }
        .onb-summary-label{ color:var(--saffron); font:950 12px/1 var(--font-sans); }
        .onb-money-summary div,.onb-money-summary strong{ display:grid; gap:4px; padding:10px 0; border-top:1px solid rgba(255,255,255,0.10); }
        .onb-money-summary small{ color:rgba(248,249,250,0.62); font:750 11px/1 var(--font-sans); }
        .onb-money-summary b,.onb-money-summary span{ font:950 15px/1.5 var(--font-sans); }
        .onb-money-summary .positive span{ color:var(--firoozeh); }
        .onb-money-summary .negative span{ color:var(--saffron); }
        .onb-routine-grid{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:10px; }
        .onb-routine-card{
          min-width:0; overflow:hidden; border-radius:17px; background:rgba(255,255,255,0.70);
          border:1px solid var(--c-border-xs); box-shadow:var(--shadow-press);
          transition:transform 170ms var(--ease-out), background 170ms var(--ease-out), border-color 170ms var(--ease-out);
        }
        .onb-routine-card.is-on{ background:color-mix(in srgb, var(--routine-soft) 82%, #fff); border-color:color-mix(in srgb, var(--routine-accent) 38%, transparent); box-shadow:var(--shadow-lift), var(--shadow-press); }
        .onb-routine-pick{
          width:100%; min-height:64px; display:grid; grid-template-columns:auto minmax(0,1fr) auto; align-items:center; gap:9px;
          padding:10px 11px; border:0; background:transparent; cursor:pointer; color:var(--ink); text-align:right;
          font:850 13px/1.55 var(--font-sans);
        }
        .onb-routine-pick span:nth-child(2){ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
        .onb-check{ color:var(--routine-accent); font:950 16px/1 var(--font-sans); }
        .onb-routine-custom{ position:relative; }
        .onb-custom-del{
          position:absolute; top:6px; left:6px;
          width:20px; height:20px; border-radius:50%; border:none;
          background:rgba(0,0,0,0.09); color:var(--ink-3);
          font:900 13px/1 var(--font-sans); cursor:pointer;
          display:grid; place-items:center; padding:0;
          transition:background 120ms;
        }
        .onb-custom-del:active{ background:rgba(0,0,0,0.20); color:var(--ink); }
        .onb-add-row{
          display:grid; grid-template-columns:minmax(0,1fr) 46px;
          gap:8px; margin-top:12px; align-items:center;
        }
        .onb-add-input{
          width:100%; min-height:46px; padding:0 14px;
          border:1.5px dashed var(--c-border-sm);
          background:rgba(255,255,255,0.70); border-radius:14px; outline:none;
          font:700 14px/1 var(--font-sans); color:var(--ink);
          transition:border-color 160ms, border-style 160ms, background 160ms;
        }
        .onb-add-input::placeholder{ color:var(--ink-4); }
        .onb-add-input:focus{ border-color:var(--onb-accent); border-style:solid; background:#fff; }
        .onb-add-btn{
          width:46px; height:46px; border-radius:14px; border:none;
          background:var(--add-accent, var(--firoozeh)); color:#fff;
          font:900 24px/1 var(--font-sans); cursor:pointer;
          display:grid; place-items:center; flex-shrink:0;
          transition:opacity 160ms;
        }
        .onb-add-btn:disabled{ opacity:0.30; cursor:default; }
        .onb-add-btn:not(:disabled):active{ opacity:0.75; }
        .onb-tp{ padding:2px 8px 10px; direction:ltr; }
        .onb-tp-row{ display:flex; align-items:center; justify-content:center; }
        .onb-tp-btn{
          width:26px; height:22px; border:none; border-radius:7px; cursor:pointer;
          background:color-mix(in srgb, var(--tp-accent) 14%, #fff);
          color:var(--tp-accent); font:900 14px/1 var(--font-sans);
          display:grid; place-items:center; flex-shrink:0;
          transition:background 120ms;
        }
        .onb-tp-btn:active{ background:color-mix(in srgb, var(--tp-accent) 30%, #fff); }
        .onb-tp-val{ width:26px; text-align:center; font:900 16px/1.6 var(--font-sans); color:var(--ink); }
        .onb-tp-sep{ width:10px; text-align:center; font:900 15px/1.6 var(--font-sans); color:var(--ink-2); }
        .onb-tp-gap{ width:10px; flex-shrink:0; }
        .onb-tp-period{ font:650 10px/1.6 var(--font-sans); color:var(--ink-3); padding-right:5px; direction:rtl; }
        .onb-review-grid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; }
        .onb-review-grid button{
          min-height:76px; padding:12px; display:grid; grid-template-columns:auto minmax(0,1fr); align-items:center; gap:10px; text-align:right;
        }
        .onb-review-grid b{ display:block; font:950 14px/1.5 var(--font-sans); color:var(--ink); }
        .onb-review-grid small{ display:block; font:650 11px/1.5 var(--font-sans); color:var(--ink-3); }
        .onb-xp-card{
          margin:14px auto 0; width:min(100%, 360px); min-height:58px; border-radius:18px;
          display:grid; place-items:center; gap:3px; background:linear-gradient(135deg, var(--firoozeh), var(--saffron));
          color:#fff; box-shadow:var(--shadow-float), var(--shadow-press); animation:onbPulse 1900ms var(--ease-io) infinite;
        }
        .onb-xp-card span{ font:950 18px/1 var(--font-sans); }
        .onb-xp-card small{ font:750 11px/1 var(--font-sans); opacity:0.82; }
        .onb-launch-mark{
          width:104px; height:104px; border-radius:34px; display:grid; place-items:center; margin:0 auto 20px;
          color:#fff; background:linear-gradient(135deg, var(--firoozeh), var(--saffron)); box-shadow:var(--shadow-float), var(--shadow-press);
          animation:onbPop 620ms var(--ease-out) both;
        }
        .onb-footer{ padding:12px 22px calc(18px + env(safe-area-inset-bottom)); }
        .onb-actions{ display:grid; grid-template-columns:var(--back-col, 0) minmax(0,1fr); gap:10px; }
        .onb-actions.no-back{ grid-template-columns:1fr; }
        .onb-btn{
          min-height:54px; border-radius:16px; border:0; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; gap:8px;
          font:950 15px/1 var(--font-sans); transition:transform 160ms var(--ease-out), box-shadow 160ms var(--ease-out), background 160ms var(--ease-out);
        }
        .onb-btn-primary{ background:var(--onb-accent); color:#fff; box-shadow:0 16px 32px color-mix(in srgb, var(--onb-accent) 22%, transparent), var(--shadow-press); }
        .onb-btn-back{ background:rgba(255,255,255,0.68); color:var(--ink-2); border:1px solid var(--c-border-sm); box-shadow:var(--shadow-press); }
        .onb-skip{ width:100%; margin-top:10px; border:0; background:transparent; color:var(--ink-3); cursor:pointer; font:800 13px/1 var(--font-sans); }
        .onb-root button:hover{ transform:translateY(-1px); }
        .onb-root button:active{ transform:translateY(0) scale(0.99); }
        .onb-root button:focus-visible,.onb-root input:focus-visible{ outline:none; box-shadow:var(--focus-ring), var(--shadow-lift); }
        @keyframes onbEnter{ from{ opacity:0; transform:translateY(14px) scale(0.99); } to{ opacity:1; transform:translateY(0) scale(1); } }
        @keyframes onbLogoSettle{ from{ opacity:0; transform:translateY(8px) scale(.9); } to{ opacity:1; transform:translateY(0) scale(1); } }
        @keyframes onbPulse{ 0%,100%{ filter:saturate(1); transform:translateY(0); } 50%{ filter:saturate(1.14); transform:translateY(-1px); } }
        @keyframes onbPop{ 0%{ opacity:0; transform:scale(0.72); } 70%{ opacity:1; transform:scale(1.05); } 100%{ opacity:1; transform:scale(1); } }
        @media (max-width: 760px){
          .onb-chrome{ padding:14px 18px 4px; }
          .onb-body{ padding:12px 18px 16px; align-items:start; }
          .onb-step-head h1{ font-size:24px; line-height:1.52; }
          .onb-step-head p{ font-size:14px; line-height:1.9; }
          .onb-choice-grid,.onb-review-grid{ grid-template-columns:1fr; }
          .onb-finance-layout{ grid-template-columns:1fr; }
          .onb-money-summary{ position:relative; top:auto; }
          .onb-money-row{ grid-template-columns:auto minmax(0,1fr); }
          .onb-money-row input{ grid-column:1 / -1; }
          .onb-routine-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
          .onb-footer{ padding:10px 18px calc(16px + env(safe-area-inset-bottom)); }
          .onb-meta{ align-items:flex-start; }
          .onb-badge{ max-width:50%; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
        }
        @media (max-width: 430px){
          .onb-routine-grid{ grid-template-columns:1fr; }
          .onb-actions{ --back-col:minmax(86px,0.34fr); }
        }
        @media (prefers-reduced-motion: reduce){
          .onb-root *, .onb-root *:before, .onb-root *:after{ animation:none!important; transition:none!important; }
        }
      `}</style>

      <header className="onb-chrome">
        <div className="onb-meta">
          <span className="onb-badge">مرحله {faN(step + 1)} از {faN(STEPS.length)}</span>
          <span className="onb-badge">{selectedRoutineCount ? `${faN(selectedRoutineCount)} عادت انتخاب شد` : 'مسیر شخصی تو'}</span>
        </div>
        <div className="onb-progress" aria-label="پیشرفت آنبوردینگ">
          {STEPS.map((_, idx) => <span key={idx} className={`onb-dot ${idx <= step ? 'is-on' : ''}`} />)}
        </div>
      </header>

      <main key={cur} className="onb-body">{content}</main>

      <footer className="onb-footer">
        <div className={`onb-actions ${canBack ? '' : 'no-back'}`} style={{ '--back-col': canBack ? 'minmax(96px, 0.32fr)' : '0' }}>
          {canBack ? <button type="button" className="onb-btn onb-btn-back" onClick={prev}>قبلی</button> : null}
          <button type="button" className="onb-btn onb-btn-primary" onClick={primaryAction}>
            {primaryLabel}
          </button>
        </div>
        {secondary
          ? <button type="button" className="onb-skip" onClick={secondary.action}>{secondary.label}</button>
          : (['morning', 'day', 'evening'].includes(cur)
              ? <button type="button" className="onb-skip" onClick={next}>فعلاً رد کن</button>
              : null)}
      </footer>
    </div>
  );
}

window.Onboarding = Onboarding;
