// Meta screens: Analytics, Calendar, Notifications, Settings.

// ═══ ANALYTICS ═══════════════════════════════════
function AnalyticsScreen({ dark, onNav, txs }) {
  const t = T(dark);
  const [period, setPeriod] = React.useState('month');
  const [showAddPlan, setShowAddPlan] = React.useState(false);
  const [planForm, setPlanForm] = React.useState(null);

  // Recompute current-month aggregates from store.
  const now = new Date();
  const ymStart = new Date(now.getFullYear(), now.getMonth(), 1).toISOString();
  const dayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()).toISOString();
  const wkStart = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 6).toISOString();
  const yrStart = new Date(now.getFullYear(), 0, 1).toISOString();

  const periodStart = period === 'day' ? dayStart : period === 'week' ? wkStart : period === 'year' ? yrStart : ymStart;
  const filtered = (txs || []).filter(t => t.date >= periodStart && (period !== 'all' || true));
  const income = filtered.filter(t => t.type === 'income').reduce((s,t) => s + t.amount, 0);
  const expense = filtered.filter(t => t.type === 'expense').reduce((s,t) => s + t.amount, 0);
  const net = income - expense;

  // Category breakdown for the period.
  const catSums = {};
  for (const tx of filtered.filter(t => t.type === 'expense')) {
    catSums[tx.categoryId] = (catSums[tx.categoryId] || 0) + tx.amount;
  }
  const catBreakdown = DATA.categories
    .filter(c => !c.archived && (catSums[c.id] || c.spent || 0) > 0)
    .map(c => ({ ...c, spent: catSums[c.id] || c.spent || 0 }))
    .sort((a,b) => b.spent - a.spent);
  const totalExpense = catBreakdown.reduce((s,c) => s + c.spent, 0) || expense || 1;

  const maxBar = Math.max(...DATA.monthsHistory.map(m => Math.max(m.inc, m.plannedExp)), expense/1000, income/1000);

  const incomeShare = DATA.income.planned > 0 ? Math.round(income / DATA.income.planned * 100) : 0;
  const expenseShare = DATA.expense.planned > 0 ? Math.round(expense / DATA.expense.planned * 100) : 0;

  const savePlanChange = (kind, delta, catId) => {
    if (kind === 'income') DATA.income.planned += delta;
    else if (kind === 'expense') DATA.expense.planned += delta;
    else if (kind === 'cat' && catId) {
      const c = DATA.categories.find(c => c.id === catId);
      if (c) { updateCategory(catId, { planned: (c.planned || 0) + delta }); }
    }
    setPlanForm(null); setShowAddPlan(false);
  };

  return (
    <Screen dark={dark}>
      <PageHeader dark={dark} title="Аналитика" subtitle={`${period === 'day' ? 'Сегодня' : period === 'week' ? 'Неделя' : period === 'year' ? 'Год' : DATA.month.name + ' ' + DATA.month.year}`} large />

      <div style={{ padding: '0 20px' }}>
        <Segmented dark={dark} value={period} onChange={setPeriod} options={[
          { value: 'day', label: 'День' },
          { value: 'week', label: 'Неделя' },
          { value: 'month', label: 'Месяц' },
          { value: 'year', label: 'Год' },
          { value: 'all', label: 'Всё' },
        ]} />
      </div>

      <div style={{ padding: '14px 20px 0' }}>
        <Card dark={dark} pad={22} radius={24}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
            <div>
              <div style={{ fontSize: 12, color: t.muted, fontWeight: 700, letterSpacing: 0.3 }}>ЧИСТЫЙ ПОТОК</div>
              <div style={{ fontFamily: TOK.fontDisplay, fontSize: 36, fontWeight: 800, color: net >= 0 ? t.positive : t.danger, letterSpacing: -1.2, lineHeight: 1, marginTop: 4, fontVariantNumeric: 'tabular-nums' }}>
                {net >= 0 ? '+' : '−'}{fmtR(Math.abs(net))} ₽
              </div>
            </div>
          </div>

          <div style={{ marginTop: 22 }}>
            <div style={{ display: 'flex', alignItems: 'flex-end', gap: 6, height: 100, position: 'relative' }}>
              {DATA.monthsHistory.map(m => {
                const incH = (m.inc / maxBar) * 100;
                const expH = (m.exp / maxBar) * 100;
                return (
                  <div key={m.m} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100%' }}>
                    <div style={{ flex: 1, width: '100%', display: 'flex', alignItems: 'flex-end', gap: 3, position: 'relative' }}>
                      <div style={{ flex: 1, height: `${incH}%`, background: t.positive, borderRadius: '4px 4px 0 0', opacity: m.m === 'Окт' ? 1 : 0.55 }} />
                      <div style={{ flex: 1, position: 'relative', height: `${expH}%` }}>
                        <div style={{ position: 'absolute', inset: 0, background: t.danger, borderRadius: '4px 4px 0 0', opacity: m.m === 'Окт' ? 1 : 0.55 }} />
                        <div style={{ position: 'absolute', left: -2, right: -2, bottom: `${(m.plannedExp/m.exp - 1) * 100}%`, height: 2, background: t.ink, opacity: 0.4 }} />
                      </div>
                    </div>
                  </div>
                );
              })}
            </div>
            <div style={{ display: 'flex', gap: 6, marginTop: 8 }}>
              {DATA.monthsHistory.map(m => (
                <div key={m.m} style={{ flex: 1, textAlign: 'center', fontSize: 11, color: m.m === 'Окт' ? t.ink : t.muted, fontWeight: 600 }}>{m.m}</div>
              ))}
            </div>
            <div style={{ display: 'flex', gap: 14, marginTop: 8, fontSize: 11, color: t.muted, fontWeight: 600 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}><div style={{ width: 10, height: 10, borderRadius: 3, background: t.positive }} /> доход</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}><div style={{ width: 10, height: 10, borderRadius: 3, background: t.danger }} /> расход</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}><div style={{ width: 12, height: 2, background: t.ink, opacity: 0.4 }} /> план</div>
            </div>
          </div>
        </Card>
      </div>

      {/* prev month comparison */}
      <div style={{ padding: '12px 20px 0' }}>
        <Card dark={dark} pad={18} radius={20} style={{ display: 'flex', alignItems: 'center', gap: 14, background: t.accentSoft, color: t.accent }}>
          <div style={{ width: 44, height: 44, borderRadius: 14, background: t.accent, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <Icon d={ICONS.arrowDownRight} size={22} stroke="#fff" sw={2.2} />
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 13, color: dark ? t.accent : '#0B6B47', fontWeight: 600 }}>В {DATA.prevMonth.name.toLowerCase()}е сэкономил</div>
            <div style={{ fontFamily: TOK.fontDisplay, fontSize: 22, fontWeight: 800, color: dark ? t.accent : '#0B6B47', letterSpacing: -0.5, fontVariantNumeric: 'tabular-nums', marginTop: 2 }}>
              {fmtR(DATA.prevMonth.saved)} ₽ · {Math.abs(DATA.prevMonth.percent)}%
            </div>
          </div>
        </Card>
      </div>

      <div style={{ padding: '12px 20px 0' }}>
        <Card dark={dark} pad={20} radius={22}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>
            <div style={{ fontFamily: TOK.fontDisplay, fontSize: 16, fontWeight: 700, color: t.ink }}>План & факт</div>
            <button onClick={() => setShowAddPlan(true)} style={{
              padding: '6px 12px', borderRadius: 14, border: 'none', cursor: 'pointer',
              background: t.accentSoft, color: t.accent,
              fontFamily: 'inherit', fontSize: 12, fontWeight: 700,
              display: 'flex', alignItems: 'center', gap: 4,
            }}>
              <Icon d={ICONS.plus} size={12} stroke={t.accent} sw={2.5} />
              План
            </button>
          </div>

          {[
            { label: 'Доходы', plan: DATA.income.planned, fact: income, color: t.positive, pct: incomeShare },
            { label: 'Расходы', plan: DATA.expense.planned, fact: expense, color: t.danger, pct: expenseShare },
          ].map((r,i) => {
            const pct = r.pct;
            return (
              <div key={i} style={{ marginBottom: i === 0 ? 16 : 0 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 6 }}>
                  <div style={{ fontSize: 13, fontWeight: 700, color: t.ink }}>{r.label}</div>
                  <div style={{ fontSize: 13, fontWeight: 800, color: r.color, fontVariantNumeric: 'tabular-nums' }}>{pct}%</div>
                </div>
                <div style={{ height: 10, background: t.surfaceAlt, borderRadius: 5, position: 'relative', overflow: 'hidden' }}>
                  <div style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: `${Math.min(100, pct)}%`, background: `linear-gradient(90deg, ${r.color}, ${r.color}cc)`, borderRadius: 5 }} />
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 4, fontSize: 11, color: t.muted, fontVariantNumeric: 'tabular-nums' }}>
                  <span>{fmtR(r.fact)} ₽</span>
                  <span>/ {fmtR(r.plan)} ₽</span>
                </div>
              </div>
            );
          })}
        </Card>
      </div>

      {/* donut */}
      {catBreakdown.length > 0 && (
        <>
          <SectionLabel dark={dark}>Структура трат</SectionLabel>
          <div style={{ padding: '0 20px' }}>
            <Card dark={dark} pad={20} radius={22}>
              <div style={{ display: 'flex', gap: 18, alignItems: 'center' }}>
                <svg width="120" height="120" viewBox="0 0 42 42" style={{ flexShrink: 0 }}>
                  {(() => {
                    let off = 25;
                    const r = 15.9155, C = 2 * Math.PI * r;
                    return catBreakdown.map(c => {
                      const pct = (c.spent / totalExpense) * 100;
                      const dash = `${(pct/100)*C} ${C}`;
                      const el = <circle key={c.id} cx="21" cy="21" r={r} fill="none" stroke={c.color} strokeWidth="6.5" strokeDasharray={dash} strokeDashoffset={-(off/100)*C} />;
                      off += pct;
                      return el;
                    });
                  })()}
                  <text x="21" y="21" textAnchor="middle" fontSize="5" fontWeight="800" fill={t.ink}>{fmtCompact(totalExpense)}</text>
                  <text x="21" y="25" textAnchor="middle" fontSize="2.6" fill={t.muted} fontWeight="600">потрачено</text>
                </svg>
                <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 7 }}>
                  {catBreakdown.slice(0, 5).map(c => {
                    const pct = Math.round((c.spent / totalExpense) * 100);
                    return (
                      <div key={c.id} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                        <div style={{ width: 8, height: 8, borderRadius: 2, background: c.color }} />
                        <div style={{ flex: 1, fontSize: 13, color: t.ink, fontWeight: 600 }}>{c.title}</div>
                        <div style={{ fontSize: 12, color: t.muted, fontWeight: 700, fontVariantNumeric: 'tabular-nums' }}>{pct}%</div>
                      </div>
                    );
                  })}
                </div>
              </div>
            </Card>
          </div>

          <SectionLabel dark={dark} action="Все →" onAction={() => onNav('categories')}>По категориям</SectionLabel>
          <div style={{ padding: '0 20px' }}>
            <Card dark={dark} pad={0} radius={20}>
              {catBreakdown.slice(0, 8).map((c, i, arr) => {
                const diff = (c.planned || 0) - c.spent;
                const over = diff < 0;
                return (
                  <div key={c.id} style={{ padding: '12px 16px', borderBottom: i === arr.length-1 ? 'none' : `1px solid ${t.line}`, display: 'flex', alignItems: 'center', gap: 12, background: over ? t.dangerSoft : 'transparent' }}>
                    <IconCircle icon={c.icon} color={c.color} size={36} dark={dark} />
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 14, fontWeight: 600, color: t.ink }}>{c.title}</div>
                      <div style={{ fontSize: 11, color: t.muted, marginTop: 2, fontWeight: 500, fontVariantNumeric: 'tabular-nums' }}>
                        {fmtR(c.spent)} / {fmtR(c.planned || 0)} ₽
                      </div>
                    </div>
                    <div style={{ textAlign: 'right' }}>
                      <div style={{ fontFamily: TOK.fontDisplay, fontSize: 14, fontWeight: 800, color: over ? t.danger : t.positive, fontVariantNumeric: 'tabular-nums' }}>
                        {over ? '+' : '−'}{fmtR(Math.abs(diff))}
                      </div>
                    </div>
                  </div>
                );
              })}
            </Card>
          </div>
        </>
      )}

      <Sheet open={showAddPlan} onClose={() => { setShowAddPlan(false); setPlanForm(null); }} dark={dark} title={planForm ? 'Добавить план' : 'Что увеличить?'}>
        {!planForm && (
          <>
            <div style={{ color: t.muted, fontSize: 13, marginBottom: 14 }}>Можно увеличить план по доходам, расходам или конкретной категории.</div>
            {[
              { kind: 'income', ic: 'arrowDownRight', t: 'Доход', color: t.positive, sub: 'Премия, разовая выплата' },
              { kind: 'expense', ic: 'arrowUpRight', t: 'Расход', color: t.danger, sub: 'Крупная покупка' },
              { kind: 'cat', ic: 'cart', t: 'Категория', color: t.accent2, sub: 'Увеличить бюджет' },
            ].map((o, i, arr) => (
              <button key={i} onClick={() => setPlanForm({ kind: o.kind, delta: 5000, catId: o.kind === 'cat' ? DATA.categories[0].id : null })} style={{
                width: '100%', border: 'none', background: 'transparent', cursor: 'pointer', padding: 0, textAlign: 'left',
              }}>
                <ListRow dark={dark} icon={o.ic} color={o.color} title={o.t} sub={o.sub}
                  right={<Icon d={ICONS.chevronR} size={14} stroke={t.faint} />}
                  last={i === arr.length - 1} />
              </button>
            ))}
          </>
        )}
        {planForm && (
          <div style={{ padding: '8px 0' }}>
            <div style={{ fontSize: 13, color: t.muted, marginBottom: 12 }}>
              Сколько добавить к плану «{planForm.kind === 'income' ? 'Доходы' : planForm.kind === 'expense' ? 'Расходы' : (DATA.categories.find(c => c.id === planForm.catId) || {}).title}»?
            </div>
            {planForm.kind === 'cat' && (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 12 }}>
                {DATA.categories.filter(c => !c.archived).map(c => (
                  <Pill key={c.id} dark={dark} active={planForm.catId === c.id} color={c.color}
                    onClick={() => setPlanForm({ ...planForm, catId: c.id })}>{c.title}</Pill>
                ))}
              </div>
            )}
            <div style={{ display: 'flex', gap: 8, marginBottom: 14, flexWrap: 'wrap' }}>
              {[1000, 5000, 10000, 25000, 50000].map(n => (
                <Pill key={n} dark={dark} active={planForm.delta === n} onClick={() => setPlanForm({ ...planForm, delta: n })}>+{fmtR(n)}</Pill>
              ))}
            </div>
            <Btn dark={dark} primary full icon="check" onClick={() => savePlanChange(planForm.kind, planForm.delta, planForm.catId)}>
              Добавить +{fmtR(planForm.delta)} ₽
            </Btn>
          </div>
        )}
      </Sheet>
    </Screen>
  );
}

// ═══ CALENDAR ════════════════════════════════════
function CalendarScreen({ dark, onBack, onPlan, txs }) {
  const t = T(dark);
  const MONTHS = ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'];
  const now = new Date();
  const baseMonth = now.getMonth(), baseYear = now.getFullYear();
  const [offset, setOffset] = React.useState(0);
  const currentMonth = ((baseMonth + offset) % 12 + 12) % 12;
  const currentYear = baseYear + Math.floor((baseMonth + offset) / 12);
  const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
  const firstDow = (new Date(currentYear, currentMonth, 1).getDay() + 6) % 7;
  const todayDay = (offset === 0) ? now.getDate() : null;

  const [selectedDay, setSelectedDay] = React.useState(null);

  // Combine subs/credits/incomes (recurring) + stored txs + planned future txs.
  const eventMap = React.useMemo(() => {
    const m = {};
    // Recurring obligations
    DATA.subs.filter(s => s.active !== false).forEach(s => {
      if (s.day > daysInMonth) return;
      (m[s.day] = m[s.day] || []).push({ id: 'sub-' + s.id + '-' + currentMonth, title: s.title, amount: s.amount, day: s.day, tag: 'Подписка', isSub: true });
    });
    DATA.credits.forEach(c => {
      const d = creditPaymentDayForMonth(c, currentYear, currentMonth + 1);
      if (!d || d > daysInMonth) return;
      const amount = creditPaymentForMonth(c, currentYear, currentMonth + 1);
      (m[d] = m[d] || []).push({ id: 'cr-' + c.id + '-' + currentMonth, title: c.title, amount, day: d, tag: 'Кредит', isCredit: true });
    });
    DATA.incomeSources.forEach(s => {
      if (s.day > daysInMonth) return;
      (m[s.day] = m[s.day] || []).push({ id: 'inc-' + s.id + '-' + currentMonth, title: s.title, amount: s.amount, day: s.day, tag: 'Доход', income: true });
    });

    // Actual transactions from store in this month
    const ym = `${currentYear}-${String(currentMonth + 1).padStart(2,'0')}`;
    (txs || []).filter(tx => (tx.date || '').slice(0, 7) === ym).forEach(tx => {
      const d = new Date(tx.date).getDate();
      const c = DATA.categories.find(c => c.id === tx.categoryId) || { title: 'Прочее' };
      (m[d] = m[d] || []).push({
        id: tx.id, title: tx.note || c.title, amount: tx.amount, day: d,
        tag: c.title, income: tx.type === 'income', isTx: true, tx,
      });
    });
    return m;
  }, [offset, daysInMonth, currentMonth, currentYear, txs]);

  const monthTotal = (filter) => Object.values(eventMap).flat()
    .filter(e => filter === 'income' ? e.income : !e.income)
    .reduce((s, e) => s + e.amount, 0);

  const days = Array.from({ length: daysInMonth }, (_, i) => i + 1);
  const blankBefore = Array.from({ length: firstDow }, (_, i) => i);

  const selectedEvents = selectedDay ? (eventMap[selectedDay] || []) : [];

  const NavBtn = ({ icon, onClick }) => (
    <button onClick={onClick} style={{
      width: 36, height: 36, borderRadius: 18, border: `1px solid ${t.line}`,
      background: t.surface, display: 'flex', alignItems: 'center', justifyContent: 'center',
      cursor: 'pointer',
    }}>
      <Icon d={ICONS[icon]} size={16} stroke={t.ink} sw={2} />
    </button>
  );

  return (
    <Screen dark={dark}>
      <PageHeader dark={dark} title="Календарь" large
        leading={<BackBtn dark={dark} onClick={onBack} />} />

      <div style={{ padding: '0 20px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <NavBtn icon="chevronL" onClick={() => setOffset(o => o - 1)} />
        <div style={{ textAlign: 'center' }}>
          <div style={{ fontFamily: TOK.fontDisplay, fontSize: 20, fontWeight: 700, color: t.ink, letterSpacing: -0.3 }}>
            {MONTHS[currentMonth]} {currentYear}
          </div>
          {offset !== 0 && (
            <button onClick={() => { setOffset(0); setSelectedDay(null); }} style={{
              background: 'transparent', border: 'none', cursor: 'pointer', color: t.accent,
              fontSize: 11, fontWeight: 700, marginTop: 2, fontFamily: 'inherit',
            }}>Сегодня</button>
          )}
        </div>
        <NavBtn icon="chevronR" onClick={() => setOffset(o => o + 1)} />
      </div>

      <div style={{ padding: '0 20px 12px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <div style={{ padding: '10px 14px', borderRadius: 14, background: t.accentSoft, color: t.positive }}>
          <div style={{ fontSize: 11, fontWeight: 700, opacity: 0.8 }}>ДОХОДЫ</div>
          <div style={{ fontFamily: TOK.fontDisplay, fontSize: 18, fontWeight: 800, marginTop: 2, fontVariantNumeric: 'tabular-nums' }}>
            +{fmtR(monthTotal('income'))} ₽
          </div>
        </div>
        <div style={{ padding: '10px 14px', borderRadius: 14, background: t.dangerSoft, color: t.danger }}>
          <div style={{ fontSize: 11, fontWeight: 700, opacity: 0.8 }}>РАСХОДЫ</div>
          <div style={{ fontFamily: TOK.fontDisplay, fontSize: 18, fontWeight: 800, marginTop: 2, fontVariantNumeric: 'tabular-nums' }}>
            −{fmtR(monthTotal('out'))} ₽
          </div>
        </div>
      </div>

      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={16} radius={24}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 4, marginBottom: 8 }}>
            {['П','В','С','Ч','П','С','В'].map((d, i) => (
              <div key={i} style={{ textAlign: 'center', fontSize: 11, color: i >= 5 ? t.danger : t.muted, fontWeight: 700 }}>{d}</div>
            ))}
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 4 }}>
            {blankBefore.map(i => <div key={'b'+i} />)}
            {days.map(d => {
              const ev = eventMap[d] || [];
              const today = d === todayDay;
              const isSelected = d === selectedDay;
              const hasInc = ev.some(e => e.income);
              const hasOut = ev.some(e => !e.income);
              return (
                <button key={d} onClick={() => setSelectedDay(d)} style={{
                  aspectRatio: '1', borderRadius: 14, border: 'none', cursor: 'pointer',
                  background: isSelected ? t.accent : (today ? t.accentSoft : (ev.length ? t.surfaceAlt : 'transparent')),
                  color: isSelected ? '#fff' : (today ? t.accent : t.ink),
                  position: 'relative', display: 'flex', flexDirection: 'column',
                  alignItems: 'center', justifyContent: 'center', padding: 4, fontFamily: 'inherit',
                  transition: 'background .15s',
                  outline: today && !isSelected ? `1.5px solid ${t.accent}` : 'none',
                  outlineOffset: -1,
                }}>
                  <div style={{ fontFamily: TOK.fontDisplay, fontSize: 14, fontWeight: (today || isSelected) ? 800 : 600 }}>{d}</div>
                  {ev.length > 0 && (
                    <div style={{ position: 'absolute', bottom: 5, display: 'flex', gap: 2 }}>
                      {hasInc && <div style={{ width: 5, height: 5, borderRadius: 3, background: isSelected ? '#fff' : t.positive }} />}
                      {hasOut && <div style={{ width: 5, height: 5, borderRadius: 3, background: isSelected ? '#fff' : t.danger }} />}
                    </div>
                  )}
                </button>
              );
            })}
          </div>
          <div style={{ display: 'flex', gap: 14, marginTop: 14, paddingTop: 12, borderTop: `1px solid ${t.line}`, fontSize: 11, color: t.muted, fontWeight: 600 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}><div style={{ width: 8, height: 8, borderRadius: 4, background: t.positive }} /> доход</div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}><div style={{ width: 8, height: 8, borderRadius: 4, background: t.danger }} /> расход</div>
            <div style={{ flex: 1 }} />
            <div>Нажмите на дату</div>
          </div>
        </Card>
      </div>

      {selectedDay && (
        <>
          <SectionLabel dark={dark}>
            {selectedDay} {MONTHS[currentMonth].toLowerCase()} {currentYear}
          </SectionLabel>
          <div style={{ padding: '0 20px', display: 'flex', flexDirection: 'column', gap: 10 }}>
            {selectedEvents.length > 0 ? selectedEvents.map(u => (
              <Card key={u.id} dark={dark} pad={0} radius={16}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 14 }}>
                  <div style={{
                    width: 40, height: 40, borderRadius: 12,
                    background: u.income ? t.accentSoft : (u.isCredit ? t.warnSoft : t.dangerSoft),
                    color: u.income ? t.accent : (u.isCredit ? t.warn : t.danger),
                    display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
                  }}>
                    <Icon d={ICONS[u.income ? 'arrowDownRight' : u.isCredit ? 'bank' : u.isSub ? 'music' : 'arrowUpRight']} size={18} stroke={u.income ? t.accent : (u.isCredit ? t.warn : t.danger)} />
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 14.5, fontWeight: 700, color: t.ink }}>{u.title}</div>
                    <div style={{ fontSize: 12, color: t.muted, marginTop: 2, fontWeight: 500 }}>{u.tag}{u.isSub && ' · подписка'}</div>
                  </div>
                  <div style={{ fontFamily: TOK.fontDisplay, fontSize: 15, fontWeight: 800, color: u.income ? t.positive : t.ink, fontVariantNumeric: 'tabular-nums' }}>
                    {u.income ? '+' : '−'}{fmtR(u.amount)}
                  </div>
                </div>
              </Card>
            )) : (
              <Card dark={dark} pad={20} radius={16} style={{ textAlign: 'center', color: t.muted, fontSize: 13 }}>
                В этот день событий нет. Можно запланировать.
              </Card>
            )}
            {selectedEvents.length > 0 && (
              <div style={{ display: 'flex', gap: 8, marginTop: 4 }}>
                <div style={{ flex: 1, padding: '10px 12px', borderRadius: 12, background: t.accentSoft, color: t.positive, fontSize: 12, fontWeight: 700, display: 'flex', justifyContent: 'space-between' }}>
                  <span>За день</span>
                  <span style={{ fontVariantNumeric: 'tabular-nums' }}>
                    +{fmtR(selectedEvents.filter(e => e.income).reduce((s,e) => s + e.amount, 0))} −{fmtR(selectedEvents.filter(e => !e.income).reduce((s,e) => s + e.amount, 0))}
                  </span>
                </div>
              </div>
            )}
            <button onClick={() => onPlan && onPlan(new Date(currentYear, currentMonth, selectedDay))} style={{
              padding: '14px 16px', borderRadius: 16, border: `2px dashed ${t.lineStrong}`,
              background: 'transparent', color: t.accent, cursor: 'pointer',
              fontFamily: 'inherit', fontSize: 13, fontWeight: 700,
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            }}>
              <Icon d={ICONS.plus} size={14} stroke={t.accent} sw={2.4} />
              Запланировать на этот день
            </button>
          </div>
        </>
      )}

      {!selectedDay && (
        <>
          <SectionLabel dark={dark}>События {MONTHS[currentMonth].toLowerCase()}а</SectionLabel>
          <div style={{ padding: '0 20px', display: 'flex', flexDirection: 'column', gap: 10 }}>
            {Object.values(eventMap).flat().sort((a,b) => a.day - b.day).slice(0, 20).map(u => (
              <Card key={u.id} dark={dark} pad={0} radius={16}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 14 }}>
                  <div style={{ width: 46, padding: '6px 0', borderRadius: 12,
                    background: u.income ? t.accentSoft : (u.isCredit ? t.warnSoft : t.dangerSoft),
                    color: u.income ? t.accent : (u.isCredit ? t.warn : t.danger),
                    textAlign: 'center', flexShrink: 0,
                  }}>
                    <div style={{ fontFamily: TOK.fontDisplay, fontSize: 15, fontWeight: 800, lineHeight: 1 }}>{String(u.day).padStart(2,'0')}</div>
                    <div style={{ fontSize: 9, marginTop: 2, fontWeight: 700, textTransform: 'uppercase', opacity: 0.8 }}>{MONTHS[currentMonth].slice(0,3).toLowerCase()}</div>
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 14.5, fontWeight: 700, color: t.ink }}>{u.title}</div>
                    <div style={{ fontSize: 12, color: t.muted, marginTop: 2, fontWeight: 500 }}>{u.tag}{u.isSub && ' · подписка'}</div>
                  </div>
                  <div style={{ fontFamily: TOK.fontDisplay, fontSize: 15, fontWeight: 800, color: u.income ? t.positive : t.ink, fontVariantNumeric: 'tabular-nums' }}>
                    {u.income ? '+' : '−'}{fmtR(u.amount)}
                  </div>
                </div>
              </Card>
            ))}
          </div>
        </>
      )}

      <div style={{ padding: '14px 20px 0' }}>
        <div style={{ padding: '14px 16px', borderRadius: 16, background: t.accentSoft, color: t.accent, fontSize: 13, fontWeight: 600, display: 'flex', alignItems: 'center', gap: 10 }}>
          <Icon d={ICONS.check} size={18} stroke={t.accent} sw={2.4} />
          Будущие траты учитываются в плане месяца автоматически
        </div>
      </div>
    </Screen>
  );
}

// ═══ NOTIFICATIONS ═══════════════════════════════
function NotificationsScreen({ dark, onBack, onNav, settings, setSetting }) {
  const t = T(dark);
  const feed = (settings && settings.notifFeed) || [];
  const [, force] = React.useReducer(x => x + 1, 0);

  const markAllRead = () => {
    setSetting('notifFeed', feed.map(n => ({ ...n, read: true })));
  };
  const removeOne = (id) => {
    setSetting('notifFeed', feed.filter(n => n.id !== id));
  };

  return (
    <Screen dark={dark}>
      <PageHeader dark={dark} title="Уведомления" subtitle={`${feed.filter(n => !n.read).length} новых`} large
        leading={<BackBtn dark={dark} onClick={onBack} />}
        trailing={
          <div style={{ display: 'flex', gap: 6 }}>
            {feed.length > 0 && (
              <button onClick={markAllRead} style={{ width: 36, height: 36, borderRadius: 18, border: `1px solid ${t.line}`, background: t.surface, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }} title="Отметить прочитанными">
                <Icon d={ICONS.check} size={16} stroke={t.ink} />
              </button>
            )}
            <button onClick={() => onNav('me')} style={{ width: 36, height: 36, borderRadius: 18, border: `1px solid ${t.line}`, background: t.surface, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }} title="Настройки">
              <Icon d={ICONS.cog} size={16} stroke={t.ink} />
            </button>
          </div>
        }
      />

      <div style={{ padding: '0 20px', display: 'flex', flexDirection: 'column', gap: 10 }}>
        {feed.length === 0 && (
          <Card dark={dark} pad={28} radius={20} style={{ textAlign: 'center' }}>
            <div style={{ fontSize: 32, marginBottom: 8 }}>🔕</div>
            <div style={{ fontSize: 14, fontWeight: 700, color: t.ink }}>Уведомлений пока нет</div>
            <div style={{ fontSize: 12, color: t.muted, marginTop: 6 }}>
              Напоминания о подписках и кредитах появятся здесь.
            </div>
          </Card>
        )}
        {feed.slice().reverse().map(n => (
          <Card key={n.id} dark={dark} pad={0} radius={18} style={{
            background: n.read ? t.surface : t.accentSoft,
            border: n.read ? undefined : `1px solid ${t.accent}33`,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 14 }}>
              <IconCircle icon={n.icon || 'bell'} color={t.accent} size={40} dark={dark} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 14.5, fontWeight: 700, color: t.ink }}>{n.title}</div>
                <div style={{ fontSize: 12, color: t.muted, marginTop: 2, fontWeight: 500 }}>{n.sub || n.body}</div>
              </div>
              <div style={{ fontSize: 11, color: t.muted, fontWeight: 600, flexShrink: 0 }}>{n.time}</div>
              {!n.read && <div style={{ width: 8, height: 8, borderRadius: 4, background: t.accent, flexShrink: 0 }} />}
              <button onClick={() => removeOne(n.id)} style={{ border: 'none', background: 'transparent', cursor: 'pointer', padding: 4 }}>
                <Icon d={ICONS.x} size={14} stroke={t.faint} />
              </button>
            </div>
          </Card>
        ))}
      </div>
    </Screen>
  );
}

// ═══ SETTINGS ════════════════════════════════════
function SettingsScreen({ dark, setDark, onNav, settings, setSetting, onLogout, onExport, onImport, onRequestPush, syncStatus, onPullNow, onPushNow, onResetSync }) {
  const t = T(dark);
  const [showAcctPicker, setShowAcctPicker] = React.useState(false);
  const [ratesBusy, setRatesBusy] = React.useState(false);
  const [pushStatus, setPushStatus] = React.useState(typeof Notification !== 'undefined' ? Notification.permission : 'unsupported');
  const [, force] = React.useReducer(x => x + 1, 0);
  const importRef = React.useRef(null);

  const homeAcctId = (settings && settings.homeAccountId) || ((DATA.accounts.find(a => a.main) || DATA.accounts[0]) || {}).id;
  const homeAcct = DATA.accounts.find(a => a.id === homeAcctId) || DATA.accounts[0];
  const displayName = (settings && settings.displayName) || 'Саша';

  const refreshRates = async () => {
    setRatesBusy(true);
    try {
      const r = await fetch('https://www.cbr-xml-daily.ru/daily_json.js');
      const j = await r.json();
      const usd = j.Valute && j.Valute.USD ? Math.round(j.Valute.USD.Value * 100) / 100 : DATA.rates.usd;
      const eur = j.Valute && j.Valute.EUR ? Math.round(j.Valute.EUR.Value * 100) / 100 : DATA.rates.eur;
      DATA.rates = { usd, eur, manual: false, updated: new Date().toISOString() };
      saveLS('money:rates', DATA.rates);
      force();
    } catch (e) {
      alert('Не удалось обновить курсы: ' + e.message);
    }
    setRatesBusy(false);
  };

  const setManualRate = (cur, val) => {
    DATA.rates = { ...DATA.rates, [cur]: val, manual: true, updated: new Date().toISOString() };
    saveLS('money:rates', DATA.rates);
    force();
  };

  const askPush = async () => {
    if (typeof Notification === 'undefined') return alert('Браузер не поддерживает уведомления.');
    if (!('serviceWorker' in navigator)) return alert('SW не поддерживается.');
    let perm = Notification.permission;
    if (perm === 'default') perm = await Notification.requestPermission();
    setPushStatus(perm);
    if (perm === 'granted') {
      // Show a confirmation push.
      const reg = await navigator.serviceWorker.ready;
      reg.showNotification('Money', { body: 'Уведомления включены', icon: './icons/icon-192.png' });
      onRequestPush && onRequestPush();
    }
  };

  const Row = ({ ic, color, l, v, last, onClick, danger }) => (
    <button onClick={onClick} style={{
      width: '100%', border: 'none', background: 'transparent', cursor: onClick ? 'pointer' : 'default',
      padding: 0, textAlign: 'left', fontFamily: 'inherit',
    }}>
      <ListRow dark={dark} icon={ic} color={color} title={l} value={v} last={last}
        valueColor={danger ? t.danger : undefined}
        right={onClick ? <Icon d={ICONS.chevronR} size={14} stroke={t.faint} /> : null} />
    </button>
  );

  return (
    <Screen dark={dark}>
      <PageHeader dark={dark} title="Настройки" large />

      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={18} radius={22}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
            <div style={{ width: 56, height: 56, borderRadius: 28, background: `linear-gradient(135deg, ${t.accent}, ${t.accent2})`, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: TOK.fontDisplay, fontWeight: 800, fontSize: 22, flexShrink: 0 }}>{displayName.slice(0,1).toUpperCase()}</div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 17, fontWeight: 700, color: t.ink }}>{displayName}</div>
              <div style={{ fontSize: 13, color: t.muted, marginTop: 2 }}>{(() => { try { return localStorage.getItem('money:email') || ''; } catch { return ''; } })()}</div>
            </div>
            <div style={{ padding: '5px 11px', background: t.accentSoft, color: t.accent, borderRadius: 12, fontSize: 11, fontWeight: 800, letterSpacing: 0.3 }}>PWA</div>
          </div>
        </Card>
      </div>

      <SectionLabel dark={dark}>Профиль</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={0} radius={20}>
          <div style={{ padding: '13px 16px', display: 'flex', alignItems: 'center', gap: 12, borderBottom: `1px solid ${t.line}` }}>
            <IconCircle icon="user" color={t.accent} size={38} dark={dark} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4 }}>Имя в приложении</div>
              <input value={displayName}
                onChange={e => setSetting('displayName', e.target.value)}
                placeholder="Как к вам обращаться"
                style={{ width: '100%', marginTop: 2, padding: 0, border: 'none', outline: 'none', background: 'transparent',
                  fontFamily: 'inherit', fontSize: 15, fontWeight: 600, color: t.ink }} />
            </div>
          </div>
          <button onClick={() => setShowAcctPicker(true)} style={{
            width: '100%', border: 'none', background: 'transparent', cursor: 'pointer',
            padding: 0, textAlign: 'left', fontFamily: 'inherit',
          }}>
            <ListRow dark={dark} icon="card" color={homeAcct ? homeAcct.color : t.accent}
              title="Главный счёт"
              sub="Показывать на главной"
              value={homeAcct ? `${homeAcct.bank} · ${homeAcct.title}` : '—'}
              right={<Icon d={ICONS.chevronR} size={14} stroke={t.faint} />} last />
          </button>
        </Card>
      </div>

      <SectionLabel dark={dark}>Внешний вид</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={16} radius={20}>
          <div style={{ fontSize: 13, color: t.muted, marginBottom: 10, fontWeight: 600 }}>Тема</div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8 }}>
            {[
              { id: 'light', label: 'Светлая', val: false },
              { id: 'dark',  label: 'Тёмная',  val: true  },
              { id: 'auto',  label: 'Авто',    val: null  },
            ].map(m => {
              const sel = m.val === dark;
              return (
                <button key={m.id} onClick={() => m.val !== null && setDark(m.val)} style={{
                  padding: 10, borderRadius: 14, border: 'none', cursor: 'pointer',
                  background: sel ? t.accent : t.surfaceAlt, color: sel ? '#fff' : t.ink,
                  fontFamily: 'inherit', fontSize: 13, fontWeight: 700,
                }}>
                  <div style={{
                    width: 36, height: 48, borderRadius: 8, margin: '0 auto 6px',
                    background: m.id === 'light' ? '#F5F1EA' : m.id === 'dark' ? '#15130F' : 'linear-gradient(90deg, #F5F1EA 50%, #15130F 50%)',
                    boxShadow: 'inset 0 0 0 1px rgba(0,0,0,0.08)',
                  }} />
                  {m.label}
                </button>
              );
            })}
          </div>
        </Card>
      </div>

      <SectionLabel dark={dark}>Валюта</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={0} radius={20}>
          <Row ic="card" color={t.accent} l="Основная" v="₽ рубль" />
          <Row ic="card" color={t.accent2} l="Вторая (в скобках)" v="$ доллар" />
          <div style={{ padding: '13px 16px', borderBottom: `1px solid ${t.line}` }}>
            <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 6 }}>Курсы (ЦБ или вручную)</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 8 }}>
              <div style={{ background: t.surface, borderRadius: 10, padding: '8px 12px', display: 'flex', alignItems: 'center', gap: 6 }}>
                <div style={{ fontSize: 12, color: t.muted, fontWeight: 700 }}>₽/$</div>
                <input value={DATA.rates.usd} type="number" step="0.01" onChange={e => setManualRate('usd', parseFloat(e.target.value) || 0)}
                  style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent', textAlign: 'right', fontFamily: 'inherit', fontSize: 14, fontWeight: 700, color: t.ink, fontVariantNumeric: 'tabular-nums' }} />
              </div>
              <div style={{ background: t.surface, borderRadius: 10, padding: '8px 12px', display: 'flex', alignItems: 'center', gap: 6 }}>
                <div style={{ fontSize: 12, color: t.muted, fontWeight: 700 }}>₽/€</div>
                <input value={DATA.rates.eur} type="number" step="0.01" onChange={e => setManualRate('eur', parseFloat(e.target.value) || 0)}
                  style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent', textAlign: 'right', fontFamily: 'inherit', fontSize: 14, fontWeight: 700, color: t.ink, fontVariantNumeric: 'tabular-nums' }} />
              </div>
            </div>
            <div style={{ display: 'flex', gap: 8 }}>
              <Btn dark={dark} secondary onClick={refreshRates} style={{ flex: 1 }} icon="repeat">
                {ratesBusy ? 'Обновляю…' : 'Обновить с ЦБ'}
              </Btn>
            </div>
            {DATA.rates.updated && (
              <div style={{ fontSize: 11, color: t.faint, marginTop: 6 }}>
                Обновлено: {new Date(DATA.rates.updated).toLocaleString('ru-RU')} · {DATA.rates.manual ? 'вручную' : 'ЦБ РФ'}
              </div>
            )}
          </div>
        </Card>
      </div>

      <SectionLabel dark={dark}>Регулярные доходы</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={0} radius={20}>
          {DATA.incomeSources.map((s, i, a) => (
            <ListRow key={s.id} dark={dark} icon={s.icon} color={s.color}
              title={s.title} sub={`Каждого ${s.day}-го`}
              value={`+${fmtR(s.amount)} ₽`} valueColor={t.positive}
              last={i === a.length - 1} />
          ))}
        </Card>
      </div>

      <SectionLabel dark={dark} action="Управлять" onAction={() => onNav('accounts')}>Счета и карты</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={0} radius={20}>
          {DATA.accounts.map((a, i) => (
            <ListRow key={a.id} dark={dark} icon="card" color={a.color}
              title={`${a.bank} · ${a.title}`}
              sub={`•• ${a.last4}${a.main ? ' · основной' : ''}`}
              value={`${fmtR(a.balance)} ₽`} last={i === DATA.accounts.length - 1} />
          ))}
        </Card>
      </div>

      <SectionLabel dark={dark} action="CRUD" onAction={() => onNav('categories')}>Категории</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={14} radius={20} onClick={() => onNav('categories')} style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 12 }}>
          <IconCircle icon="cart" color={t.accent} size={36} dark={dark} />
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 14, fontWeight: 700, color: t.ink }}>Управлять категориями</div>
            <div style={{ fontSize: 11, color: t.muted, marginTop: 2 }}>{DATA.categories.filter(c => !c.archived).length} активных · {DATA.categories.filter(c => c.archived).length} в архиве</div>
          </div>
          <Icon d={ICONS.chevronR} size={14} stroke={t.faint} />
        </Card>
      </div>

      <SectionLabel dark={dark}>Уведомления о списаниях</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={0} radius={20}>
          <NotifToggle dark={dark} settings={settings} setSetting={setSetting} k="dayBeforeSub"  label="За день до подписки" sub="Spotify, iCloud и др." />
          <NotifToggle dark={dark} settings={settings} setSetting={setSetting} k="threeBefCr"   label="За 3 дня до кредита" sub="Ипотека, авто" />
          <NotifToggle dark={dark} settings={settings} setSetting={setSetting} k="dayOf"        label="В день списания" sub="Push-уведомление" />
          <NotifToggle dark={dark} settings={settings} setSetting={setSetting} k="afterCharge"  label="После списания" sub="Карточка операции" last />
        </Card>
        <Btn dark={dark} secondary full icon="bell" onClick={askPush} style={{ marginTop: 10 }}>
          {pushStatus === 'granted' ? 'Уведомления разрешены' : pushStatus === 'denied' ? 'Разрешите в настройках браузера' : 'Разрешить уведомления'}
        </Btn>
        <Card dark={dark} pad={0} radius={16} style={{ marginTop: 10 }}>
          <div style={{ padding: '13px 16px', borderBottom: `1px solid ${t.line}` }}>
            <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 4 }}>URL push-сервера (опционально)</div>
            <input value={settings.pushServerUrl || ''}
              onChange={e => setSetting('pushServerUrl', e.target.value)}
              placeholder="https://money-push.YOUR.workers.dev"
              style={{ width: '100%', padding: 0, border: 'none', outline: 'none', background: 'transparent',
                fontFamily: TOK.fontMono, fontSize: 12, fontWeight: 500, color: t.ink }} />
            <div style={{ fontSize: 11, color: t.faint, marginTop: 6, lineHeight: 1.4 }}>
              Если оставить пустым — push работает только в foreground (пока приложение открыто). Для фоновых напоминаний задеплойте <code>server/worker.js</code> на Cloudflare Workers (бесплатно) и вставьте URL сюда.
            </div>
          </div>
          {settings.pushSubscription && (
            <div style={{ padding: '13px 16px', display: 'flex', alignItems: 'center', gap: 8 }}>
              <Icon d={ICONS.check} size={16} stroke={t.positive} sw={2.4} />
              <div style={{ flex: 1, fontSize: 12, color: t.muted, fontFamily: TOK.fontMono, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                {(settings.pushSubscription.endpoint || '').slice(0, 60)}…
              </div>
            </div>
          )}
        </Card>
      </div>

      <SectionLabel dark={dark}>Данные</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 12 }}>
          <button onClick={onExport} style={{
            padding: 18, borderRadius: 18, border: 'none', cursor: 'pointer',
            background: t.surface, color: t.ink, textAlign: 'left',
            boxShadow: dark ? `1px solid ${t.line}` : '0 6px 20px rgba(40,30,15,0.06)',
            fontFamily: 'inherit',
          }}>
            <IconCircle icon="download" color={t.accent} size={36} dark={dark} />
            <div style={{ fontSize: 14, fontWeight: 700, marginTop: 12 }}>Экспорт</div>
            <div style={{ fontSize: 11, color: t.muted, marginTop: 2 }}>JSON-бэкап</div>
          </button>
          <button onClick={() => importRef.current && importRef.current.click()} style={{
            padding: 18, borderRadius: 18, border: 'none', cursor: 'pointer',
            background: t.surface, color: t.ink, textAlign: 'left', fontFamily: 'inherit',
            boxShadow: dark ? `1px solid ${t.line}` : '0 6px 20px rgba(40,30,15,0.06)',
          }}>
            <IconCircle icon="upload" color={t.accent2} size={36} dark={dark} />
            <div style={{ fontSize: 14, fontWeight: 700, marginTop: 12 }}>Импорт</div>
            <div style={{ fontSize: 11, color: t.muted, marginTop: 2 }}>JSON-бэкап</div>
          </button>
          <input ref={importRef} type="file" accept=".json,application/json" style={{ display: 'none' }}
            onChange={e => { const f = e.target.files && e.target.files[0]; e.target.value = ''; if (f) onImport && onImport(f); }} />
        </div>
        <Card dark={dark} pad={0} radius={20}>
          <Row ic="trash" color={t.danger} l="Удалить все данные" danger onClick={() => {
            if (confirm('Точно стереть все данные? Бэкап лучше сделать заранее.')) {
              localStorage.clear();
              if (typeof TxStore !== 'undefined') TxStore.clear();
              location.reload();
            }
          }} last />
        </Card>
      </div>

      <SectionLabel dark={dark}>AI для распознавания трат</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={0} radius={20}>
          <div style={{ padding: '13px 16px', borderBottom: `1px solid ${t.line}`, display: 'flex', alignItems: 'center', gap: 12 }}>
            <IconCircle icon="invest" color={t.accent} size={34} dark={dark} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 14, fontWeight: 700, color: t.ink }}>Включить AI-распознавание</div>
              <div style={{ fontSize: 11, color: t.muted, marginTop: 2, fontWeight: 500 }}>Голос и текст обрабатываются нейросетью</div>
            </div>
            <button onClick={() => setSetting('aiEnabled', !settings.aiEnabled)} style={{
              width: 42, height: 24, borderRadius: 12, border: 'none', cursor: 'pointer', position: 'relative',
              background: settings.aiEnabled ? t.accent : t.lineStrong, transition: 'background .15s',
            }}>
              <div style={{ position: 'absolute', top: 2, left: settings.aiEnabled ? 20 : 2, width: 20, height: 20, borderRadius: 10, background: '#fff', boxShadow: '0 1px 3px rgba(0,0,0,0.25)', transition: 'left .15s' }} />
            </button>
          </div>

          <div style={{ padding: '13px 16px', borderBottom: `1px solid ${t.line}` }}>
            <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 4 }}>API ключ</div>
            <input type="password" value={settings.aiKey || ''}
              onChange={e => setSetting('aiKey', e.target.value)}
              placeholder="sk-…"
              style={{ width: '100%', padding: 0, border: 'none', outline: 'none', background: 'transparent',
                fontFamily: TOK.fontMono, fontSize: 13, fontWeight: 500, color: t.ink }} />
            {settings.aiKey && (
              <div style={{ fontSize: 11, color: t.muted, marginTop: 4, fontFamily: TOK.fontMono }}>
                •••• {settings.aiKey.slice(-6)}
              </div>
            )}
          </div>

          <div style={{ padding: '13px 16px', borderBottom: `1px solid ${t.line}` }}>
            <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 4 }}>Базовый URL</div>
            <input value={settings.aiBaseUrl || ''}
              onChange={e => setSetting('aiBaseUrl', e.target.value)}
              placeholder="https://api.apiyi.com/v1"
              style={{ width: '100%', padding: 0, border: 'none', outline: 'none', background: 'transparent',
                fontFamily: TOK.fontMono, fontSize: 13, fontWeight: 500, color: t.ink }} />
          </div>

          <div style={{ padding: '13px 16px', borderBottom: `1px solid ${t.line}` }}>
            <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 4 }}>Модель для трат и голоса</div>
            <input value={settings.aiModel || ''}
              onChange={e => setSetting('aiModel', e.target.value)}
              placeholder="claude-haiku-4-5"
              style={{ width: '100%', padding: 0, border: 'none', outline: 'none', background: 'transparent',
                fontFamily: TOK.fontMono, fontSize: 13, fontWeight: 500, color: t.ink }} />
            <div style={{ display: 'flex', gap: 6, marginTop: 8, flexWrap: 'wrap' }}>
              {['claude-haiku-4-5','gpt-4o-mini','gemini-2.5-flash','deepseek-chat'].map(m => (
                <Pill key={m} dark={dark} active={settings.aiModel === m}
                  onClick={() => setSetting('aiModel', m)}
                  style={{ padding: '5px 10px', fontSize: 11 }}>{m}</Pill>
              ))}
            </div>
            <div style={{ fontSize: 11, color: t.faint, marginTop: 6, lineHeight: 1.4 }}>
              Короткие запросы → дешёвая быстрая модель. На трату ~$0.0001.
            </div>
          </div>

          <div style={{ padding: '13px 16px' }}>
            <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 4 }}>Модель для PDF / изображений</div>
            <input value={settings.aiModelMultimodal || ''}
              onChange={e => setSetting('aiModelMultimodal', e.target.value)}
              placeholder="claude-sonnet-4-5"
              style={{ width: '100%', padding: 0, border: 'none', outline: 'none', background: 'transparent',
                fontFamily: TOK.fontMono, fontSize: 13, fontWeight: 500, color: t.ink }} />
            <div style={{ display: 'flex', gap: 6, marginTop: 8, flexWrap: 'wrap' }}>
              {['claude-sonnet-4-5','claude-opus-4-7','gpt-4o','gemini-2.5-pro'].map(m => (
                <Pill key={m} dark={dark} active={settings.aiModelMultimodal === m}
                  onClick={() => setSetting('aiModelMultimodal', m)}
                  style={{ padding: '5px 10px', fontSize: 11 }}>{m}</Pill>
              ))}
            </div>
            <div style={{ fontSize: 11, color: t.faint, marginTop: 6, lineHeight: 1.4 }}>
              Для разбора кредитного договора (текст + сканы). Нужна multimodal модель — Sonnet или GPT-4o рекомендуются.
            </div>
          </div>
        </Card>
        <div style={{
          marginTop: 10, padding: '10px 14px', borderRadius: 12,
          background: t.warnSoft, color: dark ? t.warn : '#7A5E1B',
          fontSize: 11, fontWeight: 500, lineHeight: 1.4,
        }}>
          ⚠ Ключ хранится только в этом устройстве. На публичных страницах используйте Cloudflare-прокси (шаблон в server/worker.js).
        </div>
      </div>

      <SectionLabel dark={dark}>Синхронизация</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={0} radius={20}>
          <div style={{ padding: '13px 16px', display: 'flex', alignItems: 'center', gap: 12, borderBottom: `1px solid ${t.line}` }}>
            <div style={{ width: 38, height: 38, borderRadius: 12,
              background: !syncStatus || !syncStatus.enabled ? t.surfaceAlt : (syncStatus.status === 'error' || syncStatus.status === 'conflict' ? t.dangerSoft : t.accentSoft),
              color: !syncStatus || !syncStatus.enabled ? t.muted : (syncStatus.status === 'error' || syncStatus.status === 'conflict' ? t.danger : t.accent),
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <Icon d={ICONS.repeat} size={18} stroke="currentColor" sw={2} />
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 14, fontWeight: 700, color: t.ink }}>
                {!syncStatus || !syncStatus.enabled
                  ? 'Облачная синхронизация выключена'
                  : syncStatus.status === 'syncing' ? 'Синхронизация…'
                  : syncStatus.status === 'ok' ? 'Синхронизировано'
                  : syncStatus.status === 'error' ? 'Ошибка синхронизации'
                  : syncStatus.status === 'conflict' ? 'Был конфликт — применили сервер'
                  : 'Готово к синхронизации'}
              </div>
              <div style={{ fontSize: 11, color: t.muted, marginTop: 2 }}>
                {!syncStatus || !syncStatus.enabled
                  ? 'Заполните URL push-сервера выше — он же используется для sync'
                  : (syncStatus.text || 'Готово')}
                {syncStatus && syncStatus.lastSyncedAt > 0 && ' · ' + new Date(syncStatus.lastSyncedAt).toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' })}
              </div>
            </div>
          </div>
          <div style={{ padding: 14, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
            <Btn dark={dark} secondary icon="download" onClick={onPullNow} style={{ fontSize: 13 }}>Загрузить</Btn>
            <Btn dark={dark} secondary icon="upload" onClick={onPushNow} style={{ fontSize: 13 }}>Выгрузить</Btn>
          </div>
          {syncStatus && syncStatus.enabled && (
            <div style={{ padding: '0 16px 14px', fontSize: 11, color: t.faint, lineHeight: 1.5 }}>
              ID устройства: <span style={{ fontFamily: TOK.fontMono }}>{(syncStatus.userId || '').slice(0, 12)}…</span>
              <br/>На других устройствах войдите по тому же email — данные подтянутся автоматически.
              <button onClick={onResetSync} style={{ border: 'none', background: 'transparent', color: t.danger, fontWeight: 700, cursor: 'pointer', padding: '6px 0 0', fontFamily: 'inherit', fontSize: 11 }}>
                Стереть копию с сервера →
              </button>
            </div>
          )}
        </Card>
        {(!syncStatus || !syncStatus.enabled) && (
          <div style={{ marginTop: 10, padding: '10px 14px', borderRadius: 12, background: t.surfaceAlt, color: t.muted, fontSize: 11, lineHeight: 1.4 }}>
            💡 Синхронизация работает через тот же Cloudflare Worker, что и push. Один деплой — и push, и облачный бэкап включены. AI-ключ <b>не</b> уходит на сервер.
          </div>
        )}
      </div>

      <SectionLabel dark={dark}>Аккаунт</SectionLabel>
      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={0} radius={20}>
          <Row ic="mail" color={t.muted} l="Email" v={(() => { try { return localStorage.getItem('money:email') || ''; } catch { return ''; } })()} />
          <Row ic="arrowRight" color={t.danger} l="Выйти" danger onClick={() => {
            if (confirm('Выйти из аккаунта? Данные останутся.')) onLogout && onLogout();
          }} last />
        </Card>
      </div>

      <div style={{ padding: '24px 20px 0', textAlign: 'center', fontSize: 11, color: t.faint, fontWeight: 600 }}>
        Money · v1.0 · PWA · Сделано с любовью
      </div>

      <Sheet open={showAcctPicker} onClose={() => setShowAcctPicker(false)} dark={dark} title="Какой счёт показывать на главной">
        <div style={{ color: t.muted, fontSize: 13, marginBottom: 12 }}>Выберите счёт, баланс которого будет на главном экране.</div>
        {DATA.accounts.map((a, i) => {
          const sel = a.id === homeAcctId;
          return (
            <button key={a.id} onClick={() => { setSetting('homeAccountId', a.id); setShowAcctPicker(false); }} style={{
              width: '100%', padding: '12px 14px', marginBottom: 6, borderRadius: 14,
              border: `1.5px solid ${sel ? t.accent : t.line}`,
              background: sel ? t.accentSoft : t.surface, cursor: 'pointer',
              display: 'flex', alignItems: 'center', gap: 12, fontFamily: 'inherit',
            }}>
              <div style={{ width: 28, height: 28, borderRadius: 8, background: a.color }} />
              <div style={{ flex: 1, textAlign: 'left' }}>
                <div style={{ fontSize: 15, fontWeight: 700, color: t.ink }}>{a.bank} · {a.title}</div>
                <div style={{ fontSize: 11, color: t.muted, marginTop: 2 }}>•• {a.last4} · {fmtR(a.balance)} ₽</div>
              </div>
              {sel && <Icon d={ICONS.check} size={18} stroke={t.accent} sw={2.4} />}
            </button>
          );
        })}
      </Sheet>
    </Screen>
  );
}

function NotifToggle({ dark, settings, setSetting, k, label, sub, last }) {
  const t = T(dark);
  const flags = (settings && settings.notifFlags) || { dayBeforeSub: true, threeBefCr: true, dayOf: true, afterCharge: false };
  const on = !!flags[k];
  const toggle = () => setSetting('notifFlags', { ...flags, [k]: !on });
  return (
    <div style={{ padding: '13px 16px', borderBottom: last ? 'none' : `1px solid ${t.line}`, display: 'flex', alignItems: 'center', gap: 12 }}>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 15, fontWeight: 600, color: t.ink }}>{label}</div>
        {sub && <div style={{ fontSize: 12, color: t.muted, marginTop: 2, fontWeight: 500 }}>{sub}</div>}
      </div>
      <button onClick={toggle} style={{
        width: 42, height: 24, borderRadius: 12, border: 'none', cursor: 'pointer', position: 'relative',
        background: on ? t.accent : t.lineStrong, transition: 'background .15s',
      }}>
        <div style={{ position: 'absolute', top: 2, left: on ? 20 : 2, width: 20, height: 20, borderRadius: 10, background: '#fff', boxShadow: '0 1px 3px rgba(0,0,0,0.25)', transition: 'left .15s' }} />
      </button>
    </div>
  );
}

Object.assign(window, { AnalyticsScreen, CalendarScreen, NotificationsScreen, SettingsScreen, NotifToggle });
