// screens-history-stats.jsx — History list, History detail, Stats screen, Settings, More menu

function HistoryScreen({ store, onOpenMonth }) {
  const { state, totalIncome, totalSubs, subsPct } = store;
  const months = Object.keys(state.history).sort().reverse();
  const curYm = ymKey(new Date());

  // Build descending list, with current month first
  const items = [
    {
      ym: curYm, current: true,
      income: totalIncome, subs: totalSubs, subsPct,
    },
    ...months.map(ym => {
      const h = state.history[ym];
      const inc = h.incomes.reduce((a,b)=>a+b.amount,0);
      const subs = h.subsCharged.reduce((a,b)=>a+b.amount,0);
      return { ym, income: inc, subs, subsPct: inc > 0 ? subs/inc*100 : 0 };
    }),
  ];

  return (
    <div className="page-in" style={{ paddingBottom: 110 }}>
      <ScreenHeader eyebrow="Past months" title="History"/>
      <div style={{ padding: '4px 18px 0' }}>
        {items.length === 1 && totalIncome === 0 ? (
          <Card style={{ textAlign: 'center', padding: '32px 22px' }} delay={60}>
            <div className="breathe" style={{ marginBottom: 14 }}>
              <svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
                <circle cx="22" cy="22" r="18" stroke={tokens.ink3} strokeOpacity="0.35" strokeWidth="1.2"/>
                <circle cx="22" cy="22" r="4" fill={tokens.ink3}/>
              </svg>
            </div>
            <div style={{ fontFamily: tokens.serif, fontSize: 22, color: tokens.ink, marginBottom: 6 }}>
              No history yet
            </div>
            <div style={{ fontFamily: tokens.sans, fontSize: 14, color: tokens.ink3, textWrap: 'pretty' }}>
              Months will appear here once you start logging income.
            </div>
          </Card>
        ) : (
          <Card padding={0} delay={60}>
            {items.map((it, i) => (
              <div key={it.ym} onClick={() => onOpenMonth(it.ym)}
                onPointerDown={e => e.currentTarget.style.background = tokens.inset}
                onPointerUp={e => e.currentTarget.style.background = 'transparent'}
                onPointerLeave={e => e.currentTarget.style.background = 'transparent'}
                className="rise-in"
                style={{
                display: 'flex', alignItems: 'center', gap: 14,
                padding: '16px 18px', cursor: 'pointer',
                borderBottom: i < items.length - 1 ? `1px solid ${tokens.hairline}` : 'none',
                animationDelay: (120 + i * 50) + 'ms',
                transition: 'background-color 200ms cubic-bezier(0.22,1,0.36,1)',
              }}>
                <div style={{ flex: 1 }}>
                  <div style={{
                    display: 'flex', alignItems: 'center', gap: 8,
                    fontFamily: tokens.sans, fontSize: 16, fontWeight: 500, color: tokens.ink,
                  }}>
                    {fmtMonth(it.ym)}
                    {it.current && (
                      <span style={{
                        fontSize: 10, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase',
                        color: tokens.sageDeep, background: tokens.sageSoft, padding: '2px 6px', borderRadius: 4,
                      }}>Current</span>
                    )}
                  </div>
                  <div style={{
                    display: 'flex', alignItems: 'center', gap: 8,
                    fontFamily: tokens.sans, fontSize: 12, color: tokens.ink3, marginTop: 3,
                  }}>
                    <BurdenDot pct={it.subsPct} thresholds={state.thresholds} size={6}/>
                    <span>Subs {fmtPct(it.subsPct, 1)} of income</span>
                  </div>
                </div>
                <div style={{ textAlign: 'right' }}>
                  <div style={{
                    fontFamily: tokens.serif, fontSize: 22, color: tokens.ink,
                    fontVariantNumeric: 'tabular-nums', letterSpacing: -0.3, lineHeight: 1,
                  }}>{fmtEUR(it.income, { decimals: 0 })}</div>
                  <div style={{
                    fontFamily: tokens.sans, fontSize: 11, color: tokens.ink3, marginTop: 4,
                  }}>−{fmtEUR(it.subs, { decimals: 0 })} subs</div>
                </div>
                {Ico.chev(16, tokens.ink3)}
              </div>
            ))}
          </Card>
        )}
      </div>
    </div>
  );
}

function HistoryDetailScreen({ store, ym, onBack }) {
  const { state, totalIncome, activeSubs, splitFor } = store;
  const isCurrent = ym === ymKey(new Date());
  let income, splits, entries, charged;
  if (isCurrent) {
    income = totalIncome;
    entries = state.incomes;
    charged = activeSubs.map(s => ({ name: s.name, amount: s.amount, date: nextBillingDate(s.billingDay).toISOString() }));
    // derive per-income for current month
    splits = entries.reduce((a, e) => {
      const sf = splitFor(e);
      a.investments += sf.investments;
      a.savings += sf.savings;
      a.free += sf.free;
      return a;
    }, { investments: 0, savings: 0, free: 0 });
  } else {
    const h = state.history[ym] || { incomes: [], subsCharged: [] };
    income = h.incomes.reduce((a,b)=>a+b.amount,0);
    entries = h.incomes;
    charged = h.subsCharged;
    splits = {
      investments: income * ((state.splits.investments || 0)/100),
      savings:     income * ((state.splits.savings     || 0)/100),
      free:        income * ((state.splits.free        || 0)/100),
    };
  }
  const subsTotal = charged.reduce((a,b)=>a+b.amount,0);
  const pct = income > 0 ? subsTotal/income*100 : 0;

  return (
    <div className="page-in" style={{ paddingBottom: 110 }}>
      <div style={{ padding: '8px 18px 0' }}>
        <button onClick={onBack} style={{
          display: 'flex', alignItems: 'center', gap: 4,
          background: 'none', border: 'none', cursor: 'pointer',
          color: tokens.ink2, fontFamily: tokens.sans, fontSize: 15, padding: '6px 0',
        }}>{Ico.back(18, tokens.ink2)} History</button>
      </div>
      <ScreenHeader eyebrow={isCurrent ? 'In progress' : 'Closed month'} title={fmtMonth(ym)}/>

      <div style={{ padding: '4px 18px 14px' }}>
        <Card delay={60}>
          <div style={{
            fontFamily: tokens.sans, fontSize: 12, fontWeight: 500, letterSpacing: 0.6,
            textTransform: 'uppercase', color: tokens.ink3, marginBottom: 4,
          }}>Total income</div>
          <div style={{
            fontFamily: tokens.serif, fontSize: 44, color: tokens.ink,
            letterSpacing: -0.7, lineHeight: 1, fontVariantNumeric: 'tabular-nums', marginBottom: 18,
          }}>{fmtEUR(income, { decimals: 0 })}</div>

          <SplitsBar splits={splits} total={income}/>
        </Card>
      </div>

      <Section label="Income entries">
        <Card padding={0}>
          {entries.length === 0 ? (
            <div style={{ padding: 24, textAlign: 'center', color: tokens.ink3, fontFamily: tokens.sans, fontSize: 14 }}>
              No entries
            </div>
          ) : entries.map((e, i) => (
            <div key={e.id || i} style={{
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              padding: '12px 18px',
              borderBottom: i < entries.length - 1 ? `1px solid ${tokens.hairline}` : 'none',
            }}>
              <div>
                <div style={{ fontFamily: tokens.sans, fontSize: 15, color: tokens.ink, fontWeight: 500 }}>{e.name}</div>
                <div style={{ fontFamily: tokens.sans, fontSize: 12, color: tokens.ink3, marginTop: 2 }}>{fmtDate(e.date)}</div>
              </div>
              <div style={{ fontFamily: tokens.serif, fontSize: 18, color: tokens.ink, fontVariantNumeric: 'tabular-nums' }}>
                +{fmtEUR(e.amount, { decimals: 0 })}
              </div>
            </div>
          ))}
        </Card>
      </Section>

      <Section label={`Subs charged · ${fmtPct(pct, 1)} of income`}>
        <Card padding={0}>
          {charged.length === 0 ? (
            <div style={{ padding: 24, textAlign: 'center', color: tokens.ink3, fontFamily: tokens.sans, fontSize: 14 }}>
              No charges
            </div>
          ) : charged.map((c, i) => (
            <div key={i} style={{
              display: 'flex', alignItems: 'center', gap: 12,
              padding: '12px 18px',
              borderBottom: i < charged.length - 1 ? `1px solid ${tokens.hairline}` : 'none',
            }}>
              <SubAvatar name={c.name} size={28}/>
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: tokens.sans, fontSize: 14, color: tokens.ink, fontWeight: 500 }}>{c.name}</div>
                <div style={{ fontFamily: tokens.sans, fontSize: 12, color: tokens.ink3, marginTop: 1 }}>{fmtDate(c.date)}</div>
              </div>
              <div style={{ fontFamily: tokens.serif, fontSize: 16, color: tokens.ink, fontVariantNumeric: 'tabular-nums' }}>
                {fmtEUR(c.amount, { decimals: 2 })}
              </div>
            </div>
          ))}
          <div style={{
            display: 'flex', justifyContent: 'space-between',
            padding: '12px 18px', borderTop: `1px solid ${tokens.divider}`,
            background: tokens.inset,
          }}>
            <span style={{ fontFamily: tokens.sans, fontSize: 13, color: tokens.ink2, fontWeight: 500 }}>Total subs</span>
            <span style={{ fontFamily: tokens.sans, fontSize: 14, color: tokens.ink, fontWeight: 600, fontVariantNumeric: 'tabular-nums' }}>
              {fmtEUR(subsTotal)}
            </span>
          </div>
        </Card>
      </Section>
    </div>
  );
}

function SplitsBar({ splits, total }) {
  const inv = splits.investments || 0;
  const sav = splits.savings || 0;
  const fre = splits.free || 0;
  const segs = [
    { label: 'Investments', amount: inv, pct: total > 0 ? (inv / total) * 100 : 0, color: tokens.sage },
    { label: 'Savings',     amount: sav, pct: total > 0 ? (sav / total) * 100 : 0, color: tokens.sageDeep },
    { label: 'Free',        amount: fre, pct: total > 0 ? (fre / total) * 100 : 0, color: tokens.ink3 },
  ];
  return (
    <>
      <div style={{ display: 'flex', height: 8, borderRadius: 4, overflow: 'hidden', background: tokens.inset }}>
        {segs.map((s, i) => (
          <div key={i} style={{
            width: `${s.pct}%`, background: s.color,
            transition: 'width 760ms cubic-bezier(0.22,1,0.36,1), background-color 320ms cubic-bezier(0.22,1,0.36,1)',
          }}/>
        ))}
      </div>
      <div style={{ marginTop: 14, display: 'flex', flexDirection: 'column', gap: 8 }}>
        {segs.map((s, i) => (
          <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ width: 8, height: 8, borderRadius: '50%', background: s.color, flexShrink: 0 }}/>
            <span style={{ flex: 1, fontFamily: tokens.sans, fontSize: 14, color: tokens.ink2 }}>
              {s.label} <span style={{ color: tokens.ink3, fontSize: 12 }}>· {Math.round(s.pct)}%</span>
            </span>
            <span style={{ fontFamily: tokens.sans, fontSize: 14, color: tokens.ink, fontWeight: 500, fontVariantNumeric: 'tabular-nums' }}>
              {fmtEUR(s.amount, { decimals: 0 })}
            </span>
          </div>
        ))}
      </div>
    </>
  );
}

function Section({ label, children }) {
  return (
    <div style={{ padding: '4px 18px 14px' }}>
      <div style={{
        padding: '4px 4px 10px',
        fontFamily: tokens.sans, fontSize: 12, fontWeight: 500, letterSpacing: 0.6,
        textTransform: 'uppercase', color: tokens.ink3,
      }}>{label}</div>
      {children}
    </div>
  );
}

// ── Stats ──────────────────────────────────────────────────────────────────
function StatsScreen({ store }) {
  const { state, totalIncome, totalSubs, subsPct } = store;
  const allTime = computeAllTime(state, { totalIncome, totalSubs, subsPct });
  const last6 = allTime.monthly.slice(-6);

  // Pad to always show 6 columns — empty months render as ghost placeholders so a single bar doesn't fill the chart.
  const padTo6 = (arr, mapper) => {
    const need = 6 - arr.length;
    if (need <= 0) return arr.map(mapper);
    const cur = new Date();
    const placeholders = [];
    for (let i = need; i > 0; i--) {
      const d = new Date(cur.getFullYear(), cur.getMonth() - (arr.length + i - 1), 1);
      const ym = d.toISOString().slice(0, 7);
      placeholders.push({ label: ym.slice(5), value: 0, ghost: true });
    }
    return [...placeholders, ...arr.map(mapper)];
  };
  const last6Income = padTo6(last6, m => ({ label: m.ym.slice(5), value: m.income }));
  const last6SubsPct = padTo6(last6, m => ({ label: m.ym.slice(5), value: m.subsPct }));

  return (
    <div className="page-in" style={{ paddingBottom: 110 }}>
      <ScreenHeader eyebrow="All-time totals" title="Stats"/>

      {/* Big totals */}
      <div style={{ padding: '4px 18px 14px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
        <BigStat label="Earned" value={allTime.totalEarned} accent={tokens.ink} delay={60}/>
        <BigStat label="Saved" value={allTime.totalSaved} accent={tokens.sage} delay={120}/>
        <BigStat label="Invested" value={allTime.totalInvested} accent={tokens.sageDeep} delay={180}/>
        <BigStat label="Spent on subs" value={allTime.totalSubsPaid} accent={tokens.bad} negative delay={240}/>
      </div>

      {/* Avg subs % */}
      <div style={{ padding: '4px 18px 14px' }}>
        <Card delay={300}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div>
              <div style={{
                fontFamily: tokens.sans, fontSize: 12, fontWeight: 500, letterSpacing: 0.6,
                textTransform: 'uppercase', color: tokens.ink3, marginBottom: 4,
              }}>Avg subs of income</div>
              <div style={{ fontFamily: tokens.serif, fontSize: 36, color: tokens.ink, letterSpacing: -0.5, lineHeight: 1, fontVariantNumeric: 'tabular-nums' }}>
                {fmtPct(allTime.avgSubsPct, 1)}
              </div>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <BurdenDot pct={allTime.avgSubsPct} thresholds={state.thresholds} size={10} pulse/>
              <span style={{ fontFamily: tokens.sans, fontSize: 12, color: tokens.ink3 }}>
                {burdenLabel(allTime.avgSubsPct, state.thresholds)}
              </span>
            </div>
          </div>
        </Card>
      </div>

      <Section label="Last 6 months income">
        <Card>
          <BarChart data={last6Income} accent={tokens.ink} format={(v) => fmtEUR(v, { decimals: 0 })}/>
        </Card>
      </Section>

      <Section label="Subs % per month">
        <Card>
          <BarChart data={last6SubsPct}
            accent={tokens.sage} format={(v) => fmtPct(v, 1)}
            colorByValue={v => burdenColor(v, state.thresholds)} maxOverride={Math.max(15, ...last6SubsPct.map(m=>m.value))}/>
        </Card>
      </Section>
    </div>
  );
}

function BigStat({ label, value, accent, negative, delay = 0 }) {
  return (
    <Card padding={0} delay={delay}>
      <div style={{ padding: '14px 14px 12px' }}>
        <div style={{
          fontFamily: tokens.sans, fontSize: 11, fontWeight: 500, letterSpacing: 0.5,
          textTransform: 'uppercase', color: tokens.ink3, marginBottom: 4,
        }}>{label}</div>
        <div style={{
          fontFamily: tokens.serif, fontSize: 24, color: value > 0 ? accent : tokens.ink, lineHeight: 1.05,
          fontVariantNumeric: 'tabular-nums', letterSpacing: -0.3,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>
          {negative && value > 0 && '−'}<CountNumber value={value} format={(v) => fmtEURShort(v)} />
        </div>
      </div>
    </Card>
  );
}

function BarChart({ data, accent, format, colorByValue, maxOverride }) {
  const max = maxOverride != null ? maxOverride : Math.max(1, ...data.map(d => d.value));
  const monthLabel = (ym) => {
    const m = parseInt(ym, 10);
    return MONTHS_SHORT[m - 1] || ym;
  };
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'flex-end', gap: 10, height: 130 }}>
        {data.map((d, i) => {
          const h = max > 0 ? Math.max(2, (d.value / max) * 110) : 2;
          const c = colorByValue ? colorByValue(d.value) : accent;
          if (d.ghost) {
            return (
              <div key={i} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
                <div style={{
                  fontFamily: tokens.sans, fontSize: 10, color: tokens.ink3, opacity: 0.45,
                  marginBottom: 2,
                }}>—</div>
                <div style={{
                  width: '100%', height: 4, borderRadius: 2,
                  background: tokens.hairline,
                }}/>
              </div>
            );
          }
          return (
            <div key={i} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
              <div style={{
                fontFamily: tokens.sans, fontSize: 10, color: tokens.ink3, fontVariantNumeric: 'tabular-nums',
                marginBottom: 2,
                animation: 'fade-in 480ms cubic-bezier(0.22,1,0.36,1) both',
                animationDelay: (200 + i * 70) + 'ms',
              }}>{format(d.value)}</div>
              <div style={{
                width: '100%', height: h, borderRadius: '6px 6px 2px 2px',
                background: `linear-gradient(180deg, ${c} 0%, ${c}D9 100%)`,
                boxShadow: `inset 0 1px 0 rgba(255,255,255,0.18)`,
                transformOrigin: 'bottom',
                animation: 'rise-in 720ms cubic-bezier(0.34, 1.20, 0.64, 1) both',
                animationDelay: (120 + i * 70) + 'ms',
                transition: 'height 720ms cubic-bezier(0.22, 1, 0.36, 1), background 320ms cubic-bezier(0.22,1,0.36,1)',
              }}/>
            </div>
          );
        })}
      </div>
      <div style={{ display: 'flex', gap: 10, marginTop: 8 }}>
        {data.map((d, i) => (
          <div key={i} style={{
            flex: 1, textAlign: 'center', fontFamily: tokens.sans, fontSize: 11, color: tokens.ink3,
          }}>{monthLabel(d.label)}</div>
        ))}
      </div>
    </div>
  );
}

// ── Settings ───────────────────────────────────────────────────────────────
function SettingsScreen({ store, onBack }) {
  const { state, setState, setSplits, setThresholds, resetAll } = store;
  const fileInputRef = React.useRef(null);
  const importJson = () => fileInputRef.current && fileInputRef.current.click();
  const onImportFile = (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => {
      try {
        const parsed = JSON.parse(String(reader.result || '{}'));
        if (!parsed || typeof parsed !== 'object') throw new Error('Bad JSON');
        if (!confirm('Replace current data with the imported file? This cannot be undone.')) return;
        setState(normalizeState(parsed, state));
      } catch (err) {
        alert('Could not import: ' + (err && err.message ? err.message : 'invalid file'));
      }
    };
    reader.readAsText(file);
    e.target.value = '';
  };
  const splits = state.splits;
  const sum = (splits.free || 0) + (splits.investments || 0) + (splits.savings || 0);
  const ok = sum === 100;

  // Adjust one slider; redistribute the delta proportionally across the other two
  // (so all three always sum to 100). If both other sliders are 0, split delta evenly.
  const updateSplit = (k, raw) => {
    const n = Math.max(0, Math.min(100, parseInt(raw, 10) || 0));
    const others = ['free', 'investments', 'savings'].filter(x => x !== k);
    const a = others[0], b = others[1];
    const remaining = 100 - n;
    const oldA = splits[a] || 0;
    const oldB = splits[b] || 0;
    const oldSum = oldA + oldB;
    let newA, newB;
    if (oldSum === 0) { newA = Math.round(remaining / 2); newB = remaining - newA; }
    else {
      newA = Math.round(remaining * (oldA / oldSum));
      newB = remaining - newA;
    }
    setSplits({ [k]: n, [a]: newA, [b]: newB });
  };

  return (
    <div className="page-in" style={{ paddingBottom: 110 }}>
      <div style={{ padding: '8px 18px 0' }}>
        <button onClick={onBack} style={{
          display: 'flex', alignItems: 'center', gap: 4,
          background: 'none', border: 'none', cursor: 'pointer',
          color: tokens.ink2, fontFamily: tokens.sans, fontSize: 15, padding: '6px 0',
        }}>{Ico.back(18, tokens.ink2)} More</button>
      </div>
      <ScreenHeader title="Settings"/>

      <Section label="Default income split">
        <Card>
          <div style={{ fontFamily: tokens.sans, fontSize: 12, color: tokens.ink3, marginBottom: 14 }}>
            How every euro of income is allocated. Adjust one — the others rebalance.
          </div>
          <SplitRow label="Invest" color={tokens.sage}     value={splits.investments || 0} onChange={v => updateSplit('investments', v)} />
          <SplitRow label="Save"   color={tokens.sageDeep} value={splits.savings || 0}     onChange={v => updateSplit('savings', v)} />
          <SplitRow label="Free"   color={tokens.ink3}     value={splits.free || 0}        onChange={v => updateSplit('free', v)} last />
          <div style={{
            marginTop: 14, paddingTop: 12, borderTop: `1px solid ${tokens.hairline}`,
            display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
            fontFamily: tokens.sans, fontSize: 12, color: tokens.ink3,
          }}>
            <span>Total</span>
            <span style={{ color: ok ? tokens.ink2 : '#B85450', fontWeight: 600 }}>{sum}%</span>
          </div>
        </Card>
      </Section>

      <Section label="Subscription burden thresholds">
        <Card>
          <div style={{ fontFamily: tokens.sans, fontSize: 12, color: tokens.ink3, marginBottom: 10 }}>
            Below {state.thresholds.low}% is light, between {state.thresholds.low}–{state.thresholds.high}% is moderate, above is heavy.
          </div>
          <ThresholdSlider value={state.thresholds} onChange={setThresholds}/>
        </Card>
      </Section>

      <Section label="Data">
        <Card padding={0}>
          <SettingsRow label="Export JSON" detail="Download all data" onClick={() => exportJson(state)}/>
          <SettingsRow label="Import JSON" detail="Replace current data" onClick={importJson}/>
          <SettingsRow label="Reset all data" danger isLast onClick={() => {
            if (confirm('Wipe all data? This cannot be undone.')) resetAll();
          }}/>
        </Card>
        <input ref={fileInputRef} type="file" accept="application/json,.json"
          onChange={onImportFile} style={{ display: 'none' }}/>
      </Section>
    </div>
  );
}

function SplitRow({ label, color, value, onChange, last }) {
  return (
    <div style={{ marginBottom: last ? 0 : 18 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
        <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ width: 10, height: 10, borderRadius: '50%', background: color }}/>
          <span style={{ fontFamily: tokens.sans, fontSize: 13, color: tokens.ink2, fontWeight: 500 }}>{label}</span>
        </span>
        <span style={{ fontFamily: tokens.serif, fontSize: 18, color: tokens.ink, letterSpacing: -0.2 }}>{value}%</span>
      </div>
      <input type="range" min={0} max={100} step={5} value={value}
        onChange={(e) => onChange(parseInt(e.target.value, 10))}
        style={{ width: '100%', accentColor: color, height: 22, cursor: 'pointer' }}/>
    </div>
  );
}

function SplitSlider({ value, onChange }) {
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 6 }}>
        <span style={{ fontFamily: tokens.sans, fontSize: 11, color: tokens.ink3, letterSpacing: 0.5, textTransform: 'uppercase' }}>Invest</span>
        <span style={{ fontFamily: tokens.sans, fontSize: 11, color: tokens.ink3, letterSpacing: 0.5, textTransform: 'uppercase' }}>Save</span>
      </div>
      <input type="range" min={0} max={100} step={5} value={value}
        onChange={(e) => onChange(parseInt(e.target.value, 10))}
        style={{ width: '100%', accentColor: tokens.sage, height: 22, cursor: 'pointer' }}/>
    </div>
  );
}

function SplitChip({ label, value, color }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
      <span style={{ width: 10, height: 10, borderRadius: '50%', background: color }}/>
      <span style={{ fontFamily: tokens.sans, fontSize: 13, color: tokens.ink2 }}>{label}</span>
      <span style={{
        fontFamily: tokens.serif, fontSize: 22, color: tokens.ink, letterSpacing: -0.4,
        fontVariantNumeric: 'tabular-nums', minWidth: 44, textAlign: 'right',
      }}>{value}%</span>
    </div>
  );
}

function SplitInput({ label, value, onChange, color }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '8px 0' }}>
      <span style={{ width: 8, height: 8, borderRadius: '50%', background: color }}/>
      <span style={{ flex: 1, fontFamily: tokens.sans, fontSize: 15, color: tokens.ink, fontWeight: 500 }}>
        {label}
      </span>
      <div style={{
        display: 'flex', alignItems: 'center',
        background: tokens.inset, borderRadius: 10, padding: '4px 8px', width: 84,
      }}>
        <input type="number" value={value} onChange={e => onChange(e.target.value)} min={0} max={100}
          style={{
            flex: 1, border: 'none', outline: 'none', background: 'transparent',
            fontFamily: tokens.sans, fontSize: 16, color: tokens.ink, fontWeight: 500,
            textAlign: 'right', fontVariantNumeric: 'tabular-nums', width: '100%',
          }}/>
        <span style={{ fontFamily: tokens.sans, fontSize: 14, color: tokens.ink3, marginLeft: 4 }}>%</span>
      </div>
    </div>
  );
}

function ThresholdSlider({ value, onChange }) {
  const { low, high } = value;
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '4px 0' }}>
        <span style={{ fontFamily: tokens.sans, fontSize: 13, color: tokens.ink2 }}>
          <span style={{ display: 'inline-block', width: 8, height: 8, borderRadius: '50%', background: tokens.ok, marginRight: 8, verticalAlign: 'middle' }}/>
          Light below
        </span>
        <input type="number" value={low} min={1} max={high - 1}
          onChange={e => onChange({ ...value, low: Math.max(1, Math.min(high - 1, parseInt(e.target.value, 10) || 1)) })}
          style={thresholdInput}/>
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '4px 0' }}>
        <span style={{ fontFamily: tokens.sans, fontSize: 13, color: tokens.ink2 }}>
          <span style={{ display: 'inline-block', width: 8, height: 8, borderRadius: '50%', background: tokens.warn, marginRight: 8, verticalAlign: 'middle' }}/>
          Heavy above
        </span>
        <input type="number" value={high} min={low + 1} max={50}
          onChange={e => onChange({ ...value, high: Math.max(low + 1, Math.min(50, parseInt(e.target.value, 10) || low+1)) })}
          style={thresholdInput}/>
      </div>
    </div>
  );
}
const thresholdInput = {
  width: 64, padding: '6px 10px', background: tokens.inset, border: 'none', borderRadius: 8,
  fontFamily: 'Inter, sans-serif', fontSize: 15, color: '#1F1B14', fontWeight: 500,
  textAlign: 'right', fontVariantNumeric: 'tabular-nums', outline: 'none',
};

function SettingsRow({ label, detail, onClick, danger = false, isLast = false }) {
  return (
    <div onClick={onClick}
      onPointerDown={e => e.currentTarget.style.background = tokens.inset}
      onPointerUp={e => e.currentTarget.style.background = 'transparent'}
      onPointerLeave={e => e.currentTarget.style.background = 'transparent'}
      style={{
      display: 'flex', alignItems: 'center', gap: 12,
      padding: '14px 18px', cursor: 'pointer',
      borderBottom: !isLast ? `1px solid ${tokens.hairline}` : 'none',
      transition: 'background-color 200ms cubic-bezier(0.22,1,0.36,1)',
    }}>
      <div style={{ flex: 1 }}>
        <div style={{
          fontFamily: tokens.sans, fontSize: 15, fontWeight: 500,
          color: danger ? tokens.bad : tokens.ink,
        }}>{label}</div>
        {detail && (
          <div style={{ fontFamily: tokens.sans, fontSize: 12, color: tokens.ink3, marginTop: 2 }}>{detail}</div>
        )}
      </div>
      {!danger && Ico.chev(16, tokens.ink3)}
    </div>
  );
}

function exportJson(state) {
  try {
    const blob = new Blob([JSON.stringify(state, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = 'monthly-plan.json'; a.click();
    URL.revokeObjectURL(url);
  } catch (e) { /* iframe may block */ }
}

// ── More menu ─────────────────────────────────────────────────────────────
function MoreScreen({ onNav }) {
  return (
    <div className="page-in" style={{ paddingBottom: 110 }}>
      <ScreenHeader title="Settings"/>
      <div style={{ padding: '4px 18px 0' }}>
        <Card padding={0} delay={60}>
          <SettingsRow label="Subscriptions" detail="Set & forget recurring bills" onClick={() => onNav('subs')}/>
          <SettingsRow label="Coffee machines" detail="Manage machines and pricing" onClick={() => onNav('machines')}/>
          <SettingsRow label="History" detail="Past months and breakdowns" onClick={() => onNav('history')}/>
          <SettingsRow label="Splits & data" detail="Income split, thresholds, export" onClick={() => onNav('settings')} isLast/>
        </Card>
      </div>
    </div>
  );
}

Object.assign(window, {
  HistoryScreen, HistoryDetailScreen, SplitsBar, Section,
  StatsScreen, BigStat, BarChart,
  SettingsScreen, SplitInput, ThresholdSlider, SettingsRow,
  MoreScreen, exportJson,
});
