// variant-b.jsx — POLISHED "Tabbed second brain" (sage)
// Bottom tabs (Vandaag/Geld/Lijsten/Mij), FAB + quick-add sheet, toast feedback,
// day selector strip, sub-tabs inside Lists, refined typography.

const TB = SAGE;

const VariantB = () => {
  const [state, set] = useDashboard();
  const [tab, setTab] = React.useState('today');
  const [showAdd, setShowAdd] = React.useState(false);
  const [toast, setToast] = React.useState(null);
  const [celebration, setCelebration] = React.useState(null); // { title, subtitle, emoji }
  const showToast = (msg, tint) => { setToast({ msg, tint }); setTimeout(() => setToast(null), 1800); };
  const money = calcMoney(state);
  const cal = (typeof useGoogleCalendar === 'function') ? useGoogleCalendar() : { events: [], sync: () => {}, syncing: false, error: null, lastSync: null };
  const notif = (typeof useNotifications === 'function') ? useNotifications() : null;

  // ── Cycle auto-reset ──
  React.useEffect(() => {
    if (typeof maybeAutoReset !== 'function') return;
    const next = maybeAutoReset(state, new Date());
    if (next !== state) {
      set(next);
      showToast('Nieuwe maand begint — fris starten ✨');
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // ── Celebration when a savings goal hits its target ──
  React.useEffect(() => {
    const celebrated = new Set(state.celebrated || []);
    const justHit = state.savings.find(g => g.current >= g.target && !celebrated.has(g.id));
    if (justHit) {
      setCelebration({
        emoji: '🎉',
        title: `${justHit.name} gehaald!`,
        subtitle: `Je hebt €${justHit.target} bij elkaar gespaard — trots op je.`,
      });
      set(s => ({ ...s, celebrated: [...(s.celebrated || []), justHit.id] }));
    }
  }, [state.savings, state.celebrated, set]);

  return (
    <div style={{
      fontFamily: '"Söhne", "Geist", -apple-system, "Helvetica Neue", system-ui, sans-serif',
      color: TB.ink,
      background: TB.bg,
      minHeight: '100%',
      position: 'relative',
      paddingBottom: 110,
      WebkitFontSmoothing: 'antialiased',
    }}>
      <style>{`
        .vb-cap   { text-transform: uppercase; letter-spacing: 0.13em; font-size: 11px; font-weight: 600; }
        .vb-card  { background: ${TB.card}; border-radius: 20px; padding: 16px; }
        .vb-num   { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1, 'cv11' 1; }
        .vb-display { letter-spacing: -0.02em; font-weight: 600; }
        button:focus, input:focus, select:focus { outline: 2px solid ${TB.accent}; outline-offset: 2px; }
        @keyframes vb-toast-in { from { transform: translate(-50%, 18px); opacity: 0 } to { transform: translate(-50%, 0); opacity: 1 } }
        .vb-toast { animation: vb-toast-in .25s cubic-bezier(.3,.7,.3,1) forwards }
        @keyframes vb-sheet-in { from { transform: translateY(100%) } to { transform: translateY(0) } }
        .vb-sheet { animation: vb-sheet-in .28s cubic-bezier(.2,.8,.2,1) forwards }
        @keyframes vb-fade { from { opacity: 0 } to { opacity: 1 } }
        .vb-fade { animation: vb-fade .2s forwards }
      `}</style>

      <div className="vb-fade" key={tab}>
        {tab === 'today'  && <ScreenToday   state={state} set={set} money={money} cal={cal} toast={showToast} openAdd={() => setShowAdd(true)} />}
        {tab === 'money'  && <ScreenMoney   state={state} set={set} money={money} toast={showToast} />}
        {tab === 'lists'  && <ScreenLists   state={state} set={set} toast={showToast} />}
        {tab === 'me'     && <ScreenMe      state={state} set={set} money={money} cal={cal} toast={showToast} notif={notif} />}
      </div>

      {/* Floating add button */}
      <button
        onClick={() => setShowAdd(true)}
        aria-label="Snel toevoegen"
        style={{
          position: 'absolute', right: 18, bottom: 100, zIndex: 20,
          width: 56, height: 56, borderRadius: '50%', border: 'none',
          background: TB.ink, color: '#fff', cursor: 'pointer',
          boxShadow: '0 12px 28px rgba(28,42,36,0.28), 0 4px 8px rgba(28,42,36,0.18)',
          fontSize: 28, fontWeight: 300, display: 'flex', alignItems: 'center', justifyContent: 'center',
          transform: showAdd ? 'rotate(45deg) scale(.95)' : 'none',
          transition: 'transform .25s cubic-bezier(.3,1.6,.3,1)',
        }}
      >+</button>

      {/* Add sheet */}
      {showAdd && (
        <AddSheet
          state={state} set={set}
          onClose={() => setShowAdd(false)}
          toast={(m, t) => { showToast(m, t); setShowAdd(false); }}
        />
      )}

      {/* Toast */}
      {toast && (
        <div className="vb-toast" style={{
          position: 'absolute', bottom: 168, left: '50%', transform: 'translateX(-50%)',
          padding: '10px 18px', borderRadius: 99,
          background: toast.tint === 'warn' ? '#C44A3A' : TB.ink, color: '#fff',
          fontSize: 13, fontWeight: 500, zIndex: 30, whiteSpace: 'nowrap',
          boxShadow: '0 8px 24px rgba(0,0,0,0.18)',
        }}>{toast.msg}</div>
      )}

      {/* Celebration */}
      {celebration && (typeof CelebrationOverlay === 'function') && (
        <CelebrationOverlay
          title={celebration.title}
          subtitle={celebration.subtitle}
          emoji={celebration.emoji}
          onClose={() => setCelebration(null)}
        />
      )}

      <BottomTabs tab={tab} setTab={setTab} />
    </div>
  );
};

// ═══ TODAY SCREEN ════════════════════════════════════════════════
function ScreenToday({ state, set, money, cal, toast, openAdd }) {
  // Selected day in the week strip. 0 = today, negative = past, positive = future.
  const [selectedOffset, setSelectedOffset] = React.useState(0);
  const moodMeta = MOODS.find(m => m.id === state.mood) || MOODS[0];

  // Per-day money math
  const cycleStart = (typeof cycleStartFor === 'function') ? cycleStartFor(TODAY, state.cycleResetDay || 23) : null;
  const cycleEnd   = (typeof cycleEndFor === 'function')   ? cycleEndFor(TODAY, state.cycleResetDay || 23) : null;
  const cycleLen   = cycleStart && cycleEnd
    ? Math.max(1, Math.round((cycleEnd - cycleStart) / 86400000))
    : 30;
  const dailyBudget = Math.max(0, Math.round((state.income - money.fixedTotal) / cycleLen));

  const daySpend = React.useCallback((dayOffset) => {
    if (dayOffset > 0) return null;
    const daysAgo = -dayOffset;
    const manual = (state.expenses || [])
      .filter(e => e.daysAgo === daysAgo)
      .reduce((s, e) => s + e.amount, 0);
    const bank = (state.bank?.transactions || [])
      .filter(t => t.amount < 0 && t.cat !== 'ignored' && t.daysAgo === daysAgo)
      .reduce((s, t) => s + Math.abs(t.amount), 0);
    return manual + bank;
  }, [state.expenses, state.bank]);

  // Selected day's appointments (manual + Google)
  const googleSelected = (typeof googleEventsForDay === 'function')
    ? googleEventsForDay(cal.events, selectedOffset).map(e => ({
        id: 'gc:' + (e.uid || e.start),
        time: e.allDay ? '—' : formatGoogleTime(e),
        title: e.summary,
        kind: 'gcal',
        day: selectedOffset,
        google: true,
      })) : [];
  const selectedAppts = [
    ...state.appointments.filter(a => a.day === selectedOffset),
    ...googleSelected,
  ].sort((a, b) => (a.time || '').localeCompare(b.time || ''));

  const completedTop3 = state.top3.filter(t => t.done).length;
  const completedReminders = state.reminders.filter(r => r.doneToday).length;

  const dayLabelShort = (offset) => {
    if (offset === 0) return 'vandaag';
    if (offset === -1) return 'gisteren';
    if (offset === 1) return 'morgen';
    const d = new Date(TODAY); d.setDate(d.getDate() + offset);
    return `${DAY_NAMES_NL[d.getDay()]} ${d.getDate()} ${MONTH_NAMES_NL[d.getMonth()].slice(0,3)}`;
  };

  const greeting = (() => {
    const h = 9;
    if (h < 12) return 'Goedemorgen';
    if (h < 18) return 'Hoi';
    return 'Goedeavond';
  })();

  return (
    <div>
      {/* ── Greeting ── */}
      <div style={{ padding: '54px 18px 12px' }}>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>
          <div>
            <div className="vb-cap" style={{ color: TB.accent }}>woensdag 13 mei</div>
            <div className="vb-display" style={{ fontSize: 30, marginTop: 2 }}>{greeting}, Maud</div>
          </div>
          <button onClick={openAdd} style={{
            width: 38, height: 38, borderRadius: 12, border: 'none',
            background: TB.card, color: TB.ink, cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
          }} aria-label="Toevoegen">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M12 5v14M5 12h14"/></svg>
          </button>
        </div>
      </div>

      {/* ── Day strip ── */}
      <DayStrip
        state={state}
        cal={cal}
        selectedOffset={selectedOffset}
        onSelect={setSelectedOffset}
        daySpend={daySpend}
        dailyBudget={dailyBudget}
      />

      <div style={{ padding: '14px 18px 0' }}>
        {/* ── Mood ── */}
        <div style={{ marginBottom: 14 }}>
          <div className="vb-cap" style={{ color: TB.inkFaint, marginBottom: 8 }}>hoe voel je je?</div>
          <div style={{ display: 'flex', gap: 6 }}>
            {MOODS.map(m => {
              const a = state.mood === m.id;
              return (
                <button key={m.id} onClick={() => { set(s => ({ ...s, mood: m.id })); toast(`${m.emoji} ${m.label}`); }} style={{
                  flex: 1, height: 42, borderRadius: 12, border: 'none', cursor: 'pointer',
                  background: a ? TB.ink : TB.card, color: a ? '#fff' : TB.ink,
                  fontSize: 19, transition: 'all .18s',
                  boxShadow: a ? '0 4px 12px rgba(28,42,36,0.18)' : '0 1px 0 rgba(0,0,0,0.02)',
                  transform: a ? 'translateY(-2px)' : 'none',
                }}>{m.emoji}</button>
              );
            })}
          </div>
        </div>

        {/* ── Money hero — morphs based on selectedOffset ── */}
        <DayMoneyHero
          state={state}
          money={money}
          selectedOffset={selectedOffset}
          dailyBudget={dailyBudget}
          daySpend={daySpend}
          dayLabelShort={dayLabelShort}
          onResetToToday={() => setSelectedOffset(0)}
        />

        {/* ── Top 3 ── */}
        <SectionHeader eyebrow="prioriteiten" title="Top 3" right={`${completedTop3}/3`} />
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 18 }}>
          {state.top3.map((t, i) => (
            <div key={t.id} className="vb-card" style={{
              padding: '14px 16px', display: 'flex', alignItems: 'center', gap: 12,
              opacity: t.done ? 0.55 : 1, transition: 'opacity .2s',
            }}>
              <button onClick={() => {
                const wasDone = t.done;
                set(s => ({ ...s, top3: s.top3.map(x => x.id===t.id ? {...x, done: !x.done} : x) }));
                if (!wasDone) toast('Lekker bezig 💚');
              }} style={{
                width: 30, height: 30, borderRadius: 10, flexShrink: 0,
                background: t.done ? TB.accent : TB.accentSoft,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                color: t.done ? '#fff' : TB.accent, fontWeight: 600, fontSize: 14,
                border: 'none', cursor: 'pointer', fontFamily: 'inherit',
              }}>{t.done ? '✓' : i+1}</button>
              <input
                value={t.text}
                onChange={(e) => set(s => ({ ...s, top3: s.top3.map(x => x.id===t.id ? {...x, text: e.target.value} : x) }))}
                style={{
                  flex: 1, fontSize: 15, border: 'none', background: 'transparent', outline: 'none',
                  color: t.done ? TB.inkFaint : TB.ink,
                  textDecoration: t.done ? 'line-through' : 'none',
                  fontFamily: 'inherit', padding: 0,
                }}
              />
            </div>
          ))}
        </div>

        {/* ── Agenda (selected day) ── */}
        <SectionHeader
          eyebrow="agenda"
          title={selectedOffset === 0 ? 'Vandaag' : dayLabelShort(selectedOffset).replace(/^./, c => c.toUpperCase())}
          right={selectedAppts.length ? `${selectedAppts.length} afspra${selectedAppts.length===1?'ak':'ken'}` : 'leeg'}
        />
        {selectedAppts.length === 0 ? (
          <div className="vb-card" style={{ marginBottom: 18, padding: 20, textAlign: 'center', color: TB.inkFaint, fontSize: 13 }}>
            {selectedOffset === 0 ? 'Geen afspraken vandaag — heerlijk' : 'Geen afspraken'}
          </div>
        ) : (
          <div className="vb-card" style={{ padding: 0, marginBottom: 18 }}>
            {selectedAppts.map((a, i) => (
              <div key={a.id} style={{
                display: 'flex', gap: 14, padding: '14px 16px',
                borderTop: i === 0 ? 'none' : `1px solid ${TB.hairline}`,
                alignItems: 'center',
              }}>
                <div className="vb-num" style={{ fontSize: 14, fontWeight: 600, color: TB.accent, minWidth: 48 }}>{a.time}</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 15 }}>{a.title}</div>
                  <div style={{ fontSize: 11, color: TB.inkFaint, marginTop: 2 }}>{kindLabel(a.kind)}</div>
                </div>
                {!a.google ? (
                  <button onClick={() => {
                    set(s => ({ ...s, appointments: s.appointments.filter(x => x.id !== a.id) }));
                    toast('Afspraak verwijderd');
                  }} style={{
                    width: 26, height: 26, borderRadius: 7, border: 'none',
                    background: 'transparent', color: TB.inkFaint, cursor: 'pointer', fontSize: 16,
                    fontFamily: 'inherit',
                  }} aria-label="Verwijderen">×</button>
                ) : (
                  <span title="Uit Google Agenda" style={{
                    fontSize: 9, padding: '2px 6px', borderRadius: 99,
                    background: TB.accentSoft, color: TB.accent, fontWeight: 700, letterSpacing: 0.1,
                  }}>GCAL</span>
                )}
                <div style={{ width: 3, height: 36, borderRadius: 2, background: kindColor(a.kind) }} />
              </div>
            ))}
          </div>
        )}

        {/* ── Niet vergeten ── */}
        <SectionHeader eyebrow="niet vergeten" title="Vandaag nog" right={`${completedReminders}/${state.reminders.length}`} />
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 6, marginBottom: 18 }}>
          {state.reminders.map(r => {
            const done = r.doneToday;
            const label = r.label.split(/[—-]/)[0].trim().split(' ').slice(0, 2).join(' ');
            return (
              <button key={r.id} onClick={() => {
                const wasDone = r.doneToday;
                set(s => ({ ...s, reminders: s.reminders.map(x => x.id===r.id ? {...x, doneToday: !x.doneToday, streak: !wasDone ? x.streak + 1 : Math.max(0, x.streak - 1)} : x) }));
                if (!wasDone) toast(`🔥 ${r.streak + 1} dagen!`);
              }} style={{
                padding: '12px 8px', borderRadius: 14, border: 'none', cursor: 'pointer',
                background: done ? TB.accent : TB.card, color: done ? '#fff' : TB.ink,
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
                fontFamily: 'inherit', transition: 'all .18s',
                transform: done ? 'scale(0.97)' : 'none',
              }}>
                <span style={{ fontSize: 16 }}>{done ? '✓' : '○'}</span>
                <span style={{ fontSize: 10, lineHeight: 1.2, textAlign: 'center', fontWeight: 500 }}>{label}</span>
              </button>
            );
          })}
        </div>

        {/* ── Slimme nudges ── */}
        {(typeof generateNudges === 'function') && (() => {
          const nudges = generateNudges(state, money);
          if (nudges.length === 0) return null;
          return (
            <div style={{ marginBottom: 8 }}>
              {nudges.map(n => <NudgeCard key={n.id} nudge={n} />)}
            </div>
          );
        })()}
      </div>
    </div>
  );
}

// ═══ MONEY SCREEN ════════════════════════════════════════════════
function ScreenMoney({ state, set, money, toast }) {
  const [sub, setSub] = React.useState('overzicht');
  return (
    <div>
      <Header eyebrow="mei 2026" title="Geld" />
      <SubTabs tabs={[
        { id: 'overzicht', label: 'Overzicht' },
        { id: 'inbox',     label: 'Inbox', count: money.inboxCount },
        { id: 'sparen',    label: 'Sparen' },
        { id: 'rekening',  label: 'Rekeningen' },
      ]} value={sub} onChange={setSub} />

      <div style={{ padding: '14px 18px 0' }}>
        {sub === 'overzicht' && <MoneyOverzicht state={state} set={set} money={money} toast={toast} />}
        {sub === 'inbox'     && (typeof ScreenInbox === 'function') && <ScreenInbox state={state} set={set} toast={toast} />}
        {sub === 'sparen'    && <MoneySparen    state={state} set={set} toast={toast} />}
        {sub === 'rekening'  && <MoneyRekening  state={state} set={set} toast={toast} />}
      </div>
    </div>
  );
}

function MoneyOverzicht({ state, set, money, toast }) {
  const accounts = state.bank?.accounts || [];
  const hasAccounts = accounts.length > 0;
  return (
    <React.Fragment>
      {/* Hero */}
      <div className="vb-card" style={{
        marginBottom: 14,
        background: money.safeToSpend < 0
          ? 'linear-gradient(135deg, #F8D8CE, #F2C0AF)'
          : `linear-gradient(135deg, ${TB.accent}, #4A6859)`,
        color: money.safeToSpend < 0 ? TB.ink : '#fff',
        padding: '20px 22px',
      }}>
        <div className="vb-cap" style={{ opacity: 0.78 }}>veilig uit te geven</div>
        <div className="vb-num vb-display" style={{ fontSize: 44, marginTop: 4, letterSpacing: -1.2 }}>
          {fmtEurShort(money.safeToSpend)}
        </div>
        <div style={{ fontSize: 12, opacity: 0.85, marginTop: 4 }}>
          ≈ {fmtEurShort(money.dailyAllow)}/dag voor {money.cycleDays} dagen
        </div>
      </div>

      {/* Accounts breakdown */}
      {hasAccounts && (
        <AccountsBreakdown state={state} set={set} toast={toast} />
      )}

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8, marginBottom: 18 }}>
        <KPI label="inkomen" value={fmtEurShort(state.income)} />
        <KPI label="vast" value={fmtEurShort(money.fixedTotal)} />
        <KPI label="uit" value={fmtEurShort(money.spent)} />
      </div>

      {/* Potjes */}
      <SectionHeader eyebrow="potjes" title="Budget per categorie" />
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 18 }}>
        {money.perCategory.map(b => {
          const pct = Math.min(1.2, b.spent / b.limit);
          const over = b.spent > b.limit;
          return (
            <div key={b.cat} className="vb-card" style={{ padding: '14px 16px' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                <span style={{ fontSize: 22 }}>{b.icon}</span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 14, fontWeight: 500 }}>{b.label}</div>
                  <div style={{ fontSize: 11, color: TB.inkFaint }}>{Math.round(pct*100)}% gebruikt</div>
                </div>
                <div className="vb-num" style={{ fontSize: 14, color: over ? '#C44A3A' : TB.ink, fontWeight: 500 }}>
                  {fmtEurShort(b.spent)} <span style={{ color: TB.inkFaint, fontWeight: 400 }}>/ {fmtEurShort(b.limit)}</span>
                </div>
              </div>
              <div style={{ marginTop: 10, height: 6, borderRadius: 3, background: TB.bg, overflow: 'hidden' }}>
                <div style={{
                  height: '100%', width: `${Math.min(100, pct*100)}%`,
                  background: over ? '#C44A3A' : TB.accent, borderRadius: 3, transition: 'width .3s',
                }} />
              </div>
            </div>
          );
        })}
      </div>

      {/* Recent */}
      {(() => {
        const merged = (typeof allExpenses === 'function') ? allExpenses(state) : state.expenses;
        return (
          <React.Fragment>
            <SectionHeader eyebrow="recent" title="" right={`${merged.length} uitgaven`} />
            <div className="vb-card" style={{ padding: 0, marginBottom: 18 }}>
              {merged.slice(0, 10).map((e, i) => {
                const cat = state.budgets.find(b => b.cat === e.cat);
                return (
                  <div key={e.id} style={{
                    display: 'flex', alignItems: 'center', gap: 12, padding: '12px 16px',
                    borderTop: i === 0 ? 'none' : `1px solid ${TB.hairline}`,
                  }}>
                    <span style={{ fontSize: 18 }}>{cat?.icon || '💸'}</span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 14, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.label}</div>
                      <div style={{ fontSize: 11, color: TB.inkFaint, display: 'flex', gap: 6, alignItems: 'center' }}>
                        <span>{e.daysAgo === 0 ? 'vandaag' : e.daysAgo === 1 ? 'gisteren' : `${e.daysAgo}d geleden`}</span>
                        {e.source === 'bank' && (
                          typeof AccountChip === 'function' && e.bankRaw?.accountUid
                            ? <AccountChip state={state} accountUid={e.bankRaw.accountUid} />
                            : <span style={{
                                fontSize: 9, padding: '1px 6px', borderRadius: 99,
                                background: TB.accentSoft, color: TB.accent, fontWeight: 700, letterSpacing: 0.1,
                              }}>BANK</span>
                        )}
                      </div>
                    </div>
                    <div className="vb-num" style={{ fontSize: 14, fontWeight: 500 }}>{fmtEur(e.amount)}</div>
                  </div>
                );
              })}
            </div>
          </React.Fragment>
        );
      })()}
    </React.Fragment>
  );
}

function MoneySparen({ state, set, toast }) {
  const totalSaved = state.savings.reduce((s, g) => s + g.current, 0);
  const totalTarget = state.savings.reduce((s, g) => s + g.target, 0);
  return (
    <React.Fragment>
      <div className="vb-card" style={{ padding: '20px 22px', marginBottom: 14, background: `linear-gradient(135deg, ${TB.accentSoft}, #F0EDDF)` }}>
        <div className="vb-cap" style={{ color: TB.inkSoft }}>al gespaard</div>
        <div className="vb-num vb-display" style={{ fontSize: 42, marginTop: 4, letterSpacing: -1.2 }}>
          {fmtEurShort(totalSaved)}
        </div>
        <div style={{ fontSize: 12, color: TB.inkSoft, marginTop: 4 }}>
          {Math.round((totalSaved/totalTarget)*100)}% van {fmtEurShort(totalTarget)} doelen
        </div>
        <div style={{ marginTop: 12, height: 8, borderRadius: 4, background: 'rgba(28,42,36,0.08)', overflow: 'hidden' }}>
          <div style={{ height: '100%', width: `${(totalSaved/totalTarget)*100}%`, background: TB.accent, borderRadius: 4 }} />
        </div>
      </div>

      <SectionHeader eyebrow="potjes" title="" right={`${state.savings.length} doelen`} />
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 18 }}>
        {state.savings.map(g => {
          const pct = Math.min(1, g.current / g.target);
          return (
            <div key={g.id} className="vb-card" style={{ padding: '16px 18px' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 8 }}>
                <span style={{ fontSize: 15, fontWeight: 500 }}>{g.name}</span>
                <span className="vb-num" style={{ fontSize: 12, color: TB.inkSoft }}>
                  {fmtEurShort(g.current)} / {fmtEurShort(g.target)}
                </span>
              </div>
              <div style={{ marginTop: 10, height: 8, borderRadius: 4, background: TB.bg, overflow: 'hidden' }}>
                <div style={{ height: '100%', width: `${pct*100}%`, background: TB.accent, borderRadius: 4, transition: 'width .3s' }} />
              </div>
              <div style={{ marginTop: 8, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span style={{ fontSize: 11, color: TB.inkFaint }}>
                  nog {fmtEurShort(g.target - g.current)} · {Math.round(pct*100)}%
                </span>
                <div style={{ display: 'flex', gap: 4 }}>
                  {[5, 10, 25].map(a => (
                    <button key={a} onClick={() => {
                      set(s => ({ ...s, savings: s.savings.map(x => x.id===g.id ? {...x, current: Math.min(x.target, x.current + a)} : x) }));
                      toast(`+${fmtEurShort(a)} → ${g.name}`);
                    }} style={{
                      padding: '5px 10px', borderRadius: 8, border: `1px solid ${TB.hairline}`,
                      background: 'transparent', cursor: 'pointer', fontSize: 11, color: TB.ink,
                      fontFamily: 'inherit', fontWeight: 500,
                    }}>+€{a}</button>
                  ))}
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </React.Fragment>
  );
}

function MoneyRekening({ state, set, toast }) {
  const open = state.bills.filter(b => !b.paid);
  const paid = state.bills.filter(b => b.paid);
  return (
    <React.Fragment>
      <SectionHeader eyebrow="open" title="" right={`${open.length} rekening${open.length===1?'':'en'}`} />
      {open.length === 0 ? (
        <div className="vb-card" style={{ marginBottom: 18, padding: 20, textAlign: 'center', color: TB.inkFaint, fontSize: 13 }}>
          Niks open. Lekker bezig 💚
        </div>
      ) : (
        <div className="vb-card" style={{ padding: 0, marginBottom: 18 }}>
          {open.map((b, i) => (
            <div key={b.id} style={{
              display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px',
              borderTop: i === 0 ? 'none' : `1px solid ${TB.hairline}`,
            }}>
              <div style={{ width: 10, height: 10, borderRadius: 5, background: '#D97757' }} />
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 14 }}>{b.name}</div>
                <div style={{ fontSize: 11, color: TB.inkFaint }}>dag {b.day} · maandelijks</div>
              </div>
              <div className="vb-num" style={{ fontSize: 14, fontWeight: 500 }}>{fmtEur(b.amount)}</div>
              <button onClick={() => {
                set(s => ({ ...s, bills: s.bills.map(x => x.id===b.id ? {...x, paid: true} : x) }));
                toast(`Betaald ✓ ${b.name}`);
              }} style={{
                padding: '6px 12px', borderRadius: 99, border: 'none', background: TB.accent, color: '#fff',
                fontSize: 11, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
              }}>betaal</button>
            </div>
          ))}
        </div>
      )}

      <SectionHeader eyebrow="betaald" title="" right={`${paid.length} deze maand`} />
      <div className="vb-card" style={{ padding: 0, marginBottom: 18 }}>
        {paid.map((b, i) => (
          <div key={b.id} style={{
            display: 'flex', alignItems: 'center', gap: 12, padding: '12px 16px',
            borderTop: i === 0 ? 'none' : `1px solid ${TB.hairline}`,
            opacity: 0.55,
          }}>
            <div style={{ width: 10, height: 10, borderRadius: 5, background: TB.accent }} />
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 14, textDecoration: 'line-through' }}>{b.name}</div>
              <div style={{ fontSize: 11, color: TB.inkFaint }}>dag {b.day}</div>
            </div>
            <div className="vb-num" style={{ fontSize: 14 }}>{fmtEur(b.amount)}</div>
          </div>
        ))}
      </div>
    </React.Fragment>
  );
}

// ═══ LISTS SCREEN ════════════════════════════════════════════════
function ScreenLists({ state, set, toast }) {
  const [sub, setSub] = React.useState('brain');
  // Count meals planned this week
  const monday = (typeof mondayOf === 'function') ? mondayOf(TODAY) : new Date(TODAY);
  let plannedCount = 0;
  for (let i = 0; i < 7; i++) {
    const d = new Date(monday); d.setDate(monday.getDate() + i);
    const iso = d.toISOString().slice(0, 10);
    if (state.mealPlan?.[iso]?.name?.trim()) plannedCount++;
  }
  return (
    <div>
      <Header eyebrow="onthouden" title="Lijsten" />
      <SubTabs tabs={[
        { id: 'brain',     label: 'Brein',     count: state.brainDump.length },
        { id: 'eten',      label: 'Eten',      count: plannedCount },
        { id: 'groceries', label: 'Boodschap', count: state.groceries.filter(g=>!g.done).length },
        { id: 'routines',  label: 'Routines',  count: state.reminders.length },
      ]} value={sub} onChange={setSub} />
      <div style={{ padding: '14px 18px 0' }}>
        {sub === 'brain'     && <ListBrain     state={state} set={set} toast={toast} />}
        {sub === 'eten'      && (typeof ScreenEetplan === 'function') && <ScreenEetplan state={state} set={set} toast={toast} />}
        {sub === 'groceries' && <ListGroceries state={state} set={set} toast={toast} />}
        {sub === 'routines'  && <ListRoutines  state={state} set={set} toast={toast} />}
      </div>
    </div>
  );
}

function ListBrain({ state, set, toast }) {
  return (
    <React.Fragment>
      <BrainInputB onAdd={(text) => { set(s => ({ ...s, brainDump: [{ id: 'bd'+Date.now(), text, tag: null }, ...s.brainDump] })); toast('Opgeslagen'); }} />
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 8 }}>
        {state.brainDump.length === 0 ? (
          <div className="vb-card" style={{ padding: 20, textAlign: 'center', color: TB.inkFaint, fontSize: 13 }}>
            Hoofd is leeg. Mooi.
          </div>
        ) : state.brainDump.map(b => (
          <div key={b.id} className="vb-card" style={{
            padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 10,
          }}>
            <span style={{ fontSize: 14, flex: 1 }}>{b.text}</span>
            {b.tag && <span style={{ fontSize: 10, padding: '3px 8px', borderRadius: 99, background: TB.accentSoft, color: TB.accent, textTransform: 'uppercase', letterSpacing: 0.1, fontWeight: 600 }}>{b.tag}</span>}
            <button onClick={() => set(s => ({ ...s, brainDump: s.brainDump.filter(x => x.id !== b.id) }))} style={{
              background: 'transparent', border: 'none', color: TB.inkFaint, cursor: 'pointer', fontSize: 18, padding: 0, fontFamily: 'inherit',
            }}>×</button>
          </div>
        ))}
      </div>
    </React.Fragment>
  );
}

function ListGroceries({ state, set, toast }) {
  return (
    <React.Fragment>
      <GroceryInputB onAdd={(label) => { set(s => ({ ...s, groceries: [...s.groceries, { id: 'g'+Date.now(), label, done: false }] })); toast('Toegevoegd'); }} />
      <div className="vb-card" style={{ padding: 0, marginTop: 8 }}>
        {state.groceries.length === 0 ? (
          <div style={{ padding: 20, textAlign: 'center', color: TB.inkFaint, fontSize: 13 }}>Nog niks op de lijst.</div>
        ) : state.groceries.map((g, i) => (
          <div key={g.id} style={{
            display: 'flex', alignItems: 'center', gap: 12, padding: '12px 16px',
            borderTop: i === 0 ? 'none' : `1px solid ${TB.hairline}`,
          }}>
            <button onClick={() => set(s => ({ ...s, groceries: s.groceries.map(x => x.id===g.id ? {...x, done: !x.done} : x) }))} style={{
              width: 22, height: 22, borderRadius: 6, border: `1.5px solid ${g.done ? TB.accent : TB.hairline}`,
              background: g.done ? TB.accent : 'transparent', color: '#fff', fontSize: 12, cursor: 'pointer', fontFamily: 'inherit',
            }}>{g.done ? '✓' : ''}</button>
            <span style={{ flex: 1, fontSize: 14, textDecoration: g.done ? 'line-through' : 'none', color: g.done ? TB.inkFaint : TB.ink }}>{g.label}</span>
            <button onClick={() => set(s => ({ ...s, groceries: s.groceries.filter(x => x.id !== g.id) }))} style={{
              background: 'transparent', border: 'none', color: TB.inkFaint, cursor: 'pointer', fontSize: 16, fontFamily: 'inherit',
            }}>×</button>
          </div>
        ))}
      </div>
    </React.Fragment>
  );
}

function ListRoutines({ state, set, toast }) {
  return (
    <div className="vb-card" style={{ padding: 0 }}>
      {state.reminders.map((r, i) => (
        <div key={r.id} style={{
          display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px',
          borderTop: i === 0 ? 'none' : `1px solid ${TB.hairline}`,
        }}>
          <button onClick={() => {
            const wasDone = r.doneToday;
            set(s => ({ ...s, reminders: s.reminders.map(x => x.id===r.id ? {...x, doneToday: !x.doneToday, streak: !wasDone ? x.streak + 1 : Math.max(0, x.streak - 1)} : x) }));
            if (!wasDone) toast(`🔥 ${r.streak + 1} dagen!`);
          }} style={{
            width: 26, height: 26, borderRadius: 7, border: `1.5px solid ${r.doneToday ? TB.accent : TB.hairline}`,
            background: r.doneToday ? TB.accent : 'transparent', color: '#fff', fontSize: 13, cursor: 'pointer', fontFamily: 'inherit',
          }}>{r.doneToday ? '✓' : ''}</button>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 14, color: r.doneToday ? TB.inkFaint : TB.ink, textDecoration: r.doneToday ? 'line-through' : 'none' }}>{r.label}</div>
            <div style={{ fontSize: 11, color: TB.inkFaint }}>{r.recur}</div>
          </div>
          <div style={{
            fontSize: 11, padding: '4px 10px', borderRadius: 99,
            background: TB.accentSoft, color: TB.accent, fontWeight: 600,
          }}>🔥 {r.streak}</div>
        </div>
      ))}
    </div>
  );
}

// ═══ ME SCREEN ═══════════════════════════════════════════════════
function ScreenMe({ state, set, money, cal, toast, notif }) {
  const completedTop3 = state.top3.filter(t => t.done).length;
  const completedReminders = state.reminders.filter(r => r.doneToday).length;
  const moodWeek = [...state.moodLog, { date: '2026-05-13', mood: state.mood }];
  return (
    <div>
      <Header eyebrow="overzicht" title="Mij" />
      <div style={{ padding: '0 18px' }}>
        <div className="vb-card" style={{
          marginBottom: 14, padding: '20px',
          background: `linear-gradient(135deg, ${TB.accentSoft} 0%, #F2EFE3 100%)`,
        }}>
          <div style={{ display: 'flex', gap: 14, alignItems: 'center' }}>
            <div style={{
              width: 52, height: 52, borderRadius: '50%', background: TB.accent,
              display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff',
              fontSize: 20, fontWeight: 600,
            }}>M</div>
            <div>
              <div className="vb-display" style={{ fontSize: 20 }}>Maud</div>
              <div style={{ fontSize: 12, color: TB.inkSoft }}>{completedTop3}/3 vandaag · {completedReminders}/{state.reminders.length} routines</div>
            </div>
          </div>
        </div>

        <SectionHeader eyebrow="deze week" title="Stemming" />
        <div className="vb-card" style={{ padding: '16px 14px', marginBottom: 18 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between' }}>
            {moodWeek.map((m, i) => {
              const meta = MOODS.find(x => x.id === m.mood);
              const d = new Date(m.date);
              const isToday = i === moodWeek.length - 1;
              return (
                <div key={i} style={{
                  display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6,
                  padding: 6, borderRadius: 12, background: isToday ? TB.accentSoft : 'transparent',
                  minWidth: 36,
                }}>
                  <div style={{ fontSize: 22 }}>{meta?.emoji || '·'}</div>
                  <div style={{ fontSize: 10, color: isToday ? TB.accent : TB.inkFaint, textTransform: 'uppercase', fontWeight: 600 }}>{DAY_SHORT_NL[d.getDay()]}</div>
                </div>
              );
            })}
          </div>
        </div>

        <SectionHeader eyebrow="streaks" title="Niet breken" />
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 18 }}>
          {state.reminders.map(r => (
            <div key={r.id} className="vb-card" style={{ padding: 14, textAlign: 'center' }}>
              <div style={{ fontSize: 11, color: TB.inkFaint, textTransform: 'uppercase', letterSpacing: 0.1, fontWeight: 600, minHeight: 26 }}>{r.label}</div>
              <div className="vb-num vb-display" style={{ fontSize: 32, color: TB.accent, marginTop: 6 }}>🔥{r.streak}</div>
              <div style={{ fontSize: 11, color: TB.inkFaint, marginTop: 2 }}>{r.recur}</div>
            </div>
          ))}
        </div>

        {/* Bank settings */}
        <BankSettings state={state} set={set} toast={toast} />

        {/* Google Calendar settings */}
        <GoogleCalendarSettings state={state} set={set} cal={cal} toast={toast} />

        {/* Notifications */}
        <NotificationSettings state={state} set={set} notif={notif} toast={toast} />

        {/* Cycle reset day is now derived automatically from bank salary transactions
            in bank.jsx — see IncomeSettings for the displayed salary date.
            <CycleSettings /> is still defined in this file for fallback/debug. */}

        {/* Backup */}
        <BackupSettings state={state} set={set} toast={toast} />

        <SectionHeader eyebrow="instellingen" title="Inkomen" />
        <IncomeSettings state={state} set={set} toast={toast} />

        {(typeof CategoryManager === 'function')
          ? <CategoryManager state={state} set={set} toast={toast} />
          : null}
      </div>
    </div>
  );
}

// ═══ INCOME SETTINGS ════════════════════════════════
function IncomeSettings({ state, set, toast }) {
  const bankConnected = !!state.bank?.connected;
  const autoFromBank  = state.incomeAutoFromBank !== false;
  const lastSalary = (state.bank?.transactions || [])
    .filter(t => t.cat === 'income' && t.amount > 0)
    .sort((a, b) => a.daysAgo - b.daysAgo)[0];

  if (bankConnected && autoFromBank) {
    const nextSalaryRange = (typeof fmtCycleRange === 'function') ? fmtCycleRange(state) : '';
    return (
      <div className="vb-card" style={{ padding: '14px 16px', marginBottom: 14 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <div style={{
            width: 38, height: 38, borderRadius: 11, background: TB.accentSoft,
            display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 18,
          }}>🏦</div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 13, color: TB.ink, fontWeight: 500 }}>Automatisch uit bank</div>
            <div style={{ fontSize: 11, color: TB.inkFaint }}>
              {lastSalary
                ? `Laatste salaris: ${fmtEur(lastSalary.amount)} · ${lastSalary.daysAgo}d geleden`
                : `Wacht op eerste salaris-transactie…`}
            </div>
          </div>
          <div className="vb-num" style={{ fontSize: 18, fontWeight: 600 }}>{fmtEurShort(state.income)}</div>
        </div>
        {nextSalaryRange && (
          <div style={{
            marginTop: 10, padding: '8px 10px', borderRadius: 8, background: TB.bg,
            fontSize: 11, color: TB.inkSoft, display: 'flex', justifyContent: 'space-between',
          }}>
            <span>maand-cyclus</span>
            <span className="vb-num" style={{ fontWeight: 500 }}>{nextSalaryRange}</span>
          </div>
        )}
        <button onClick={() => {
          set(s => ({ ...s, incomeAutoFromBank: false }));
          toast('Inkomen op handmatig');
        }} style={{
          marginTop: 10, padding: '6px 12px', borderRadius: 8, border: 'none',
          background: 'transparent', color: TB.inkSoft, fontSize: 11, fontWeight: 500,
          cursor: 'pointer', fontFamily: 'inherit',
        }}>Zet handmatig</button>
      </div>
    );
  }

  return (
    <div className="vb-card" style={{ padding: '14px 16px', marginBottom: 14 }}>
      <label style={{ fontSize: 12, color: TB.inkSoft, display: 'block', marginBottom: 6 }}>Maandinkomen</label>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <span style={{ fontSize: 18, color: TB.inkFaint }}>€</span>
        <input
          type="number" value={state.income}
          onChange={e => set(s => ({ ...s, income: Number(e.target.value) || 0 }))}
          style={{
            flex: 1, padding: '10px 12px', fontSize: 16, border: `1px solid ${TB.hairline}`,
            borderRadius: 10, background: TB.bg, outline: 'none', boxSizing: 'border-box',
            fontFamily: 'inherit', color: TB.ink,
          }}
        />
      </div>
      {bankConnected && (
        <button onClick={() => {
          set(s => ({ ...s, incomeAutoFromBank: true }));
          toast('Inkomen automatisch uit bank');
        }} style={{
          marginTop: 10, padding: '6px 12px', borderRadius: 8, border: 'none',
          background: TB.accentSoft, color: TB.accent, fontSize: 11, fontWeight: 600,
          cursor: 'pointer', fontFamily: 'inherit',
        }}>→ Uit bank halen</button>
      )}
    </div>
  );
}

// ═══ GOOGLE CALENDAR SETTINGS ═══════════════════════════════════
function GoogleCalendarSettings({ state, set, cal, toast }) {
  const [url, setUrl] = React.useState(state.googleICSUrl || '');
  const [showHelp, setShowHelp] = React.useState(false);
  const lastSync = state.googleLastSync ? new Date(state.googleLastSync) : null;
  const isConnected = !!state.googleICSUrl;

  const save = () => {
    const clean = url.trim();
    set(s => ({ ...s, googleICSUrl: clean }));
    if (clean && cal?.sync) {
      // give state a tick to settle, then sync
      setTimeout(() => cal.sync(), 50);
    }
    toast?.('Agenda gekoppeld 📅');
  };
  const disconnect = () => {
    setUrl('');
    set(s => ({ ...s, googleICSUrl: '', googleEvents: [], googleLastSync: null }));
    toast?.('Agenda ontkoppeld');
  };

  const fmtRelative = (d) => {
    const diff = Math.round((Date.now() - d.getTime()) / 60000);
    if (diff < 1)  return 'net nu';
    if (diff < 60) return `${diff} min geleden`;
    if (diff < 1440) return `${Math.round(diff/60)} uur geleden`;
    return d.toLocaleDateString('nl-NL');
  };

  return (
    <React.Fragment>
      <SectionHeader
        eyebrow="agenda"
        title="Google Agenda"
        right={isConnected
          ? <span style={{ color: TB.accent, fontWeight: 600 }}>● gekoppeld</span>
          : <span style={{ color: TB.inkFaint }}>niet gekoppeld</span>}
      />
      <div className="vb-card" style={{ padding: '14px 16px', marginBottom: 14 }}>
        <label style={{ fontSize: 12, color: TB.inkSoft, display: 'block', marginBottom: 6 }}>
          Geheime iCal-URL (van Google Agenda instellingen)
        </label>
        <input
          type="url" value={url} onChange={e => setUrl(e.target.value)}
          placeholder="https://calendar.google.com/calendar/ical/…/basic.ics"
          spellCheck={false}
          style={{
            width: '100%', padding: '10px 12px', fontSize: 13, border: `1px solid ${TB.hairline}`,
            borderRadius: 10, background: TB.bg, outline: 'none', boxSizing: 'border-box',
            fontFamily: 'ui-monospace, "SF Mono", Menlo, monospace', color: TB.ink,
          }}
        />
        <div style={{ marginTop: 10, display: 'flex', gap: 6, alignItems: 'center', flexWrap: 'wrap' }}>
          <button onClick={save} disabled={!url.trim() || url.trim() === state.googleICSUrl} style={{
            padding: '8px 14px', borderRadius: 10, border: 'none', cursor: 'pointer',
            background: (!url.trim() || url.trim() === state.googleICSUrl) ? TB.hairline : TB.accent,
            color: '#fff', fontSize: 12, fontWeight: 600, fontFamily: 'inherit',
          }}>{isConnected && url.trim() === state.googleICSUrl ? 'Opgeslagen' : 'Koppelen'}</button>
          {isConnected && (
            <button onClick={() => cal?.sync?.()} disabled={cal?.syncing} style={{
              padding: '8px 14px', borderRadius: 10, border: `1px solid ${TB.hairline}`, cursor: 'pointer',
              background: 'transparent', color: TB.ink, fontSize: 12, fontWeight: 600, fontFamily: 'inherit',
            }}>{cal?.syncing ? 'Bezig…' : 'Sync nu'}</button>
          )}
          {isConnected && (
            <button onClick={disconnect} style={{
              padding: '8px 14px', borderRadius: 10, border: 'none', cursor: 'pointer',
              background: 'transparent', color: '#C44A3A', fontSize: 12, fontWeight: 600, fontFamily: 'inherit',
            }}>Ontkoppel</button>
          )}
          <button onClick={() => setShowHelp(v => !v)} style={{
            marginLeft: 'auto', padding: '6px 8px', borderRadius: 8, border: 'none', cursor: 'pointer',
            background: 'transparent', color: TB.inkSoft, fontSize: 12, fontFamily: 'inherit',
          }}>{showHelp ? '× sluit' : '? hoe'}</button>
        </div>

        {/* Status */}
        <div style={{ marginTop: 10, fontSize: 11, color: TB.inkFaint, display: 'flex', justifyContent: 'space-between' }}>
          <span>
            {cal?.error
              ? <span style={{ color: '#C44A3A' }}>⚠ {cal.error}</span>
              : isConnected
                ? `${cal?.events?.length || 0} afspraken geladen`
                : 'Plak hierboven de URL'}
          </span>
          {lastSync && <span>laatst: {fmtRelative(lastSync)}</span>}
        </div>

        {/* Help */}
        {showHelp && (
          <div style={{
            marginTop: 12, padding: '12px 14px', background: TB.accentSoft, borderRadius: 12,
            fontSize: 12, color: TB.ink, lineHeight: 1.55,
          }}>
            <div style={{ fontWeight: 600, marginBottom: 6 }}>Zo vind je de URL:</div>
            <ol style={{ margin: 0, paddingLeft: 18, display: 'flex', flexDirection: 'column', gap: 4 }}>
              <li>Open Google Agenda in een browser (computer)</li>
              <li>Klik links naast je agenda op de drie puntjes → <i>Instellingen en delen</i></li>
              <li>Scroll naar <i>Privésleutel in iCal-formaat</i></li>
              <li>Kopieer het hele <code>https://calendar.google.com/…basic.ics</code> adres</li>
              <li>Plak het hier en tik <b>Koppelen</b></li>
            </ol>
            <div style={{ marginTop: 8, opacity: 0.7 }}>
              Deze URL is alleen voor jou — niet delen. Afspraken laden lokaal en blijven ook offline zichtbaar.
            </div>
          </div>
        )}
      </div>
    </React.Fragment>
  );
}

// ═══ BANK SETTINGS ══════════════════════════════════════════════
function BankSettings({ state, set, toast }) {
  const useBankFn = (typeof useBank === 'function') ? useBank : null;
  if (!useBankFn) return null;
  const b = useBankFn();
  const [showPicker, setShowPicker] = React.useState(false);
  const [showAdvanced, setShowAdvanced] = React.useState(false);
  const [backendUrl, setBackendUrl] = React.useState(state.bank?.config?.backendUrl || '');

  const onPickBank = async (institution) => {
    setShowPicker(false);
    const r = await b.connect(institution.id, institution.label);
    if (b.error) toast?.(b.error, 'warn'); else toast?.(`${institution.label} gekoppeld 🏦`);
  };

  const saveBackendUrl = () => {
    set(s => ({ ...s, bank: { ...(s.bank || {}), config: { backendUrl: backendUrl.trim() } } }));
    toast?.(backendUrl.trim() ? 'Backend opgeslagen' : 'Demo-modus actief');
  };

  const isConnected = b.isConnected;
  const isDemo = b.isDemoMode;
  const last = b.bank.lastSync ? new Date(b.bank.lastSync) : null;
  const txCount = (b.bank.transactions || []).length;

  // Auto-handle ?bank=connected redirect from Worker
  React.useEffect(() => {
    const url = new URL(window.location.href);
    if (url.searchParams.get('bank') === 'connected') {
      url.searchParams.delete('bank');
      url.searchParams.delete('account');
      window.history.replaceState({}, '', url.toString());
      toast?.('Bank gekoppeld 🏦');
      b.sync();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <React.Fragment>
      <SectionHeader
        eyebrow="bankrekening"
        title="Automatische sync"
        right={isConnected
          ? <span style={{ color: TB.accent, fontWeight: 600 }}>● {b.bank.institutionLabel}</span>
          : <span style={{ color: TB.inkFaint }}>niet gekoppeld</span>}
      />
      <div className="vb-card" style={{ padding: '14px 16px', marginBottom: 14 }}>
        {!isConnected ? (
          <React.Fragment>
            <div style={{ fontSize: 13, color: TB.inkSoft, lineHeight: 1.5, marginBottom: 12 }}>
              Koppel je bankrekening via PSD2. Transacties verschijnen automatisch in je uitgaven met de juiste categorie.
              {isDemo && (
                <span style={{ display: 'block', marginTop: 6, padding: '8px 10px', borderRadius: 8, background: '#FFF3D9', color: '#5A3F0F', fontSize: 11 }}>
                  ⚠ Demo-modus actief — kies een bank om met simulatie-data te starten. Zet de backend-URL onder "Geavanceerd" voor echte data.
                </span>
              )}
            </div>
            <button onClick={() => setShowPicker(true)} disabled={b.working === 'connecting'} style={{
              width: '100%', padding: '12px', borderRadius: 12, border: 'none',
              background: b.working === 'connecting' ? TB.hairline : TB.accent, color: '#fff',
              fontSize: 14, fontWeight: 600, cursor: b.working ? 'wait' : 'pointer', fontFamily: 'inherit',
            }}>
              {b.working === 'connecting' ? 'Doorsturen naar je bank…' : '🏦 Koppel je bank'}
            </button>
          </React.Fragment>
        ) : (
          <React.Fragment>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 12 }}>
              <BankMark institution={b.bank.institution} label={b.bank.institutionLabel} />
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 14, fontWeight: 600 }}>{b.bank.institutionLabel}</div>
                <div style={{ fontSize: 11, color: TB.inkFaint }}>
                  {(b.bank.accounts || []).length} rekening{(b.bank.accounts || []).length === 1 ? '' : 'en'} gekoppeld
                </div>
              </div>
              {(b.bank.accounts || []).length > 0 && (
                <div style={{ textAlign: 'right' }}>
                  <div style={{ fontSize: 10, color: TB.inkFaint, textTransform: 'uppercase', fontWeight: 600 }}>totaal</div>
                  <div className="vb-num" style={{ fontSize: 16, fontWeight: 600 }}>
                    {fmtEurShort((b.bank.accounts || []).reduce((s, a) => s + (typeof a.balance === 'number' ? a.balance : 0), 0))}
                  </div>
                </div>
              )}
            </div>

            <div style={{
              padding: '8px 10px', borderRadius: 8, background: TB.bg,
              fontSize: 11, color: TB.inkSoft, marginBottom: 10, lineHeight: 1.4,
            }}>
              💡 Klik op een rekening in <b>Geld → Overzicht</b> om de naam, type en hoeveel '% telt mee' in te stellen.
            </div>

            <div style={{ display: 'flex', gap: 6 }}>
              <button onClick={() => b.sync()} disabled={b.working === 'syncing'} style={{
                flex: 1, padding: '10px', borderRadius: 10, border: 'none',
                background: TB.accent, color: '#fff', fontSize: 12, fontWeight: 600,
                cursor: b.working ? 'wait' : 'pointer', fontFamily: 'inherit',
              }}>{b.working === 'syncing' ? 'Synct…' : `Sync nu${txCount ? ` · ${txCount} tx` : ''}`}</button>
              <button onClick={() => { if (confirm('Bank ontkoppelen? Transacties worden gewist.')) { b.disconnect(); toast?.('Ontkoppeld'); }}} style={{
                padding: '10px 14px', borderRadius: 10, border: 'none',
                background: 'transparent', color: '#C44A3A', fontSize: 12, fontWeight: 600,
                cursor: 'pointer', fontFamily: 'inherit',
              }}>Ontkoppel</button>
            </div>

            <div style={{ marginTop: 10, fontSize: 11, color: TB.inkFaint, display: 'flex', justifyContent: 'space-between' }}>
              <span>{last ? `Laatst: ${fmtRelative(last)}` : 'Nog niet gesynchroniseerd'}</span>
              {b.bank.consentExpiresAt && (
                <span>SCA tot {new Date(b.bank.consentExpiresAt).toLocaleDateString('nl-NL', { day:'numeric', month:'short' })}</span>
              )}
            </div>

            {b.error && (
              <div style={{ marginTop: 8, padding: '8px 10px', borderRadius: 8, background: '#FCE7E1', color: '#7A2A1A', fontSize: 12 }}>
                ⚠ {b.error}
              </div>
            )}
          </React.Fragment>
        )}

        {/* Advanced — backend URL */}
        <div style={{ marginTop: 12, paddingTop: 10, borderTop: `1px solid ${TB.hairline}` }}>
          <button onClick={() => setShowAdvanced(v => !v)} style={{
            width: '100%', textAlign: 'left', padding: 0, border: 'none', background: 'transparent',
            color: TB.inkSoft, fontSize: 12, cursor: 'pointer', fontFamily: 'inherit',
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          }}>
            <span>{showAdvanced ? '× Geavanceerd verbergen' : 'Geavanceerd · backend-URL'}</span>
            <span>{isDemo ? '(demo)' : '(live)'}</span>
          </button>
          {showAdvanced && (
            <div style={{ marginTop: 10 }}>
              <label style={{ fontSize: 11, color: TB.inkSoft, display: 'block', marginBottom: 4 }}>
                Cloudflare Worker URL
              </label>
              <input
                type="url" value={backendUrl} onChange={e => setBackendUrl(e.target.value)}
                placeholder="https://maud-bank.<jouw>.workers.dev"
                style={{
                  width: '100%', padding: '8px 10px', fontSize: 12, border: `1px solid ${TB.hairline}`,
                  borderRadius: 8, background: TB.bg, outline: 'none', boxSizing: 'border-box',
                  fontFamily: 'ui-monospace, monospace', color: TB.ink,
                }}
              />
              <button onClick={saveBackendUrl} style={{
                marginTop: 6, padding: '6px 12px', borderRadius: 8, border: 'none', cursor: 'pointer',
                background: TB.ink, color: '#fff', fontSize: 11, fontWeight: 600, fontFamily: 'inherit',
              }}>Opslaan</button>
              <div style={{ marginTop: 8, fontSize: 11, color: TB.inkFaint, lineHeight: 1.5 }}>
                Leeg laten = demo-modus met simulatiedata. Vul je eigen Worker-URL in voor echte ING-koppeling (zie <code>cloudflare-worker.js</code>).
              </div>
            </div>
          )}
        </div>
      </div>

      {/* Bank picker */}
      {showPicker && (
        <BankPickerSheet banks={b.banks} onPick={onPickBank} onClose={() => setShowPicker(false)} />
      )}
    </React.Fragment>
  );
}

function BankMark({ institution, label }) {
  const banks = (typeof BANKS !== 'undefined') ? BANKS : [];
  const meta = banks.find(b => b.id === institution) || { color: '#5E7C6B', mark: (label || '?')[0] };
  return (
    <div style={{
      width: 40, height: 40, borderRadius: 12, background: meta.color, color: '#fff',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontSize: 18, fontWeight: 700,
    }}>{meta.mark}</div>
  );
}

function BankPickerSheet({ banks, onPick, onClose }) {
  return (
    <div onClick={onClose} style={{
      position: 'absolute', inset: 0, zIndex: 100,
      background: 'rgba(28,42,36,0.32)', backdropFilter: 'blur(4px)',
      display: 'flex', alignItems: 'flex-end', justifyContent: 'center',
    }}>
      <div onClick={e => e.stopPropagation()} className="vb-sheet" style={{
        width: '100%', background: TB.bg, borderTopLeftRadius: 28, borderTopRightRadius: 28,
        padding: '14px 18px 28px', maxHeight: '85%', overflow: 'auto',
        boxShadow: '0 -20px 60px rgba(0,0,0,0.18)',
      }}>
        <div style={{ width: 40, height: 4, borderRadius: 2, background: TB.hairline, margin: '0 auto 16px' }} />
        <div className="vb-cap" style={{ color: TB.accent }}>kies je bank</div>
        <div className="vb-display" style={{ fontSize: 22, marginTop: 2, marginBottom: 12 }}>Bij welke bank zit je?</div>
        <div style={{ fontSize: 12, color: TB.inkSoft, marginBottom: 14, lineHeight: 1.5 }}>
          Je wordt doorgestuurd naar je bank om in te loggen. Maud's Dashboard krijgt alleen leesrechten via PSD2 — geen betalingen mogelijk.
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
          {banks.map(bank => (
            <button key={bank.id} onClick={() => onPick(bank)} style={{
              padding: '16px 12px', borderRadius: 14, border: 'none', cursor: 'pointer',
              background: TB.card, display: 'flex', alignItems: 'center', gap: 10,
              fontFamily: 'inherit', textAlign: 'left',
            }}>
              <BankMark institution={bank.id} label={bank.label} />
              <span style={{ fontSize: 14, fontWeight: 500, color: TB.ink }}>{bank.label}</span>
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

function fmtRelative(d) {
  const diff = Math.round((Date.now() - d.getTime()) / 60000);
  if (diff < 1)  return 'net nu';
  if (diff < 60) return `${diff} min geleden`;
  if (diff < 1440) return `${Math.round(diff/60)} uur geleden`;
  return d.toLocaleDateString('nl-NL');
}

// ═══ NOTIFICATIONS SETTINGS ═════════════════════════════════════
function NotificationSettings({ state, set, notif, toast }) {
  if (!notif) return null;
  const enabled = state.notifications?.enabled && notif.permission === 'granted';
  const settings = state.notifications || { medicationTime: '08:00', top3Time: '09:00', billsLeadDays: 2 };
  const updateSettings = (patch) => set(s => ({ ...s, notifications: { ...(s.notifications || {}), ...patch } }));

  return (
    <React.Fragment>
      <SectionHeader
        eyebrow="herinneringen"
        title="Notificaties"
        right={
          enabled
            ? <span style={{ color: TB.accent, fontWeight: 600 }}>● aan</span>
            : <span style={{ color: TB.inkFaint }}>uit</span>
        }
      />
      <div className="vb-card" style={{ padding: '14px 16px', marginBottom: 14 }}>
        {notif.permission === 'unavailable' && (
          <div style={{ fontSize: 12, color: TB.inkFaint, padding: '8px 0' }}>
            Notificaties worden niet ondersteund door deze browser.
          </div>
        )}

        {notif.permission !== 'unavailable' && (
          <React.Fragment>
            {!enabled ? (
              <React.Fragment>
                <div style={{ fontSize: 13, color: TB.inkSoft, marginBottom: 10, lineHeight: 1.5 }}>
                  Krijg een tikje op je telefoon voor medicatie, top-3 en rekeningen.
                  {notif.isIOS && !notif.isStandalone && (
                    <span style={{ display: 'block', marginTop: 6, padding: '8px 10px', borderRadius: 8, background: TB.accentSoft, color: TB.accent, fontSize: 12 }}>
                      💡 Op iPhone: tik <b>Deel → Zet op beginscherm</b> eerst, daarna open je 'm vanaf het beginscherm voor notificaties.
                    </span>
                  )}
                </div>
                <button onClick={async () => {
                  const r = await notif.enable();
                  if (r.granted) toast('Notificaties aan 💚');
                  else toast(r.reason || 'Kon niet aanzetten', 'warn');
                }} style={{
                  width: '100%', padding: '12px', borderRadius: 12, border: 'none',
                  background: TB.accent, color: '#fff', fontSize: 14, fontWeight: 600,
                  cursor: 'pointer', fontFamily: 'inherit',
                }}>
                  {notif.permission === 'denied' ? 'Permissie geweigerd — open browserinstellingen' : 'Zet notificaties aan'}
                </button>
              </React.Fragment>
            ) : (
              <React.Fragment>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                  <div>
                    <label style={{ fontSize: 12, color: TB.inkSoft, display: 'block', marginBottom: 4 }}>💊 Medicatie herinnering</label>
                    <input type="time" value={settings.medicationTime} onChange={e => updateSettings({ medicationTime: e.target.value })}
                      style={notifInputStyle} />
                  </div>
                  <div>
                    <label style={{ fontSize: 12, color: TB.inkSoft, display: 'block', marginBottom: 4 }}>✦ Top-3 ochtend</label>
                    <input type="time" value={settings.top3Time} onChange={e => updateSettings({ top3Time: e.target.value })}
                      style={notifInputStyle} />
                  </div>
                  <div>
                    <label style={{ fontSize: 12, color: TB.inkSoft, display: 'block', marginBottom: 4 }}>🪙 Rekeningen — dagen vooraf</label>
                    <select value={settings.billsLeadDays} onChange={e => updateSettings({ billsLeadDays: Number(e.target.value) })}
                      style={notifInputStyle}>
                      <option value={1}>1 dag</option>
                      <option value={2}>2 dagen</option>
                      <option value={3}>3 dagen</option>
                      <option value={5}>5 dagen</option>
                    </select>
                  </div>
                </div>

                <div style={{ marginTop: 12, padding: '10px 12px', background: TB.bg, borderRadius: 10, fontSize: 11, color: TB.inkSoft }}>
                  {notif.pending.length > 0
                    ? <span>📬 Vandaag staan er {notif.pending.length} geplanned</span>
                    : <span>Geen herinneringen meer vandaag</span>}
                </div>

                <div style={{ marginTop: 10, display: 'flex', gap: 6 }}>
                  <button onClick={() => { notif.testNotify(); toast('Test verstuurd'); }} style={{
                    flex: 1, padding: '10px', borderRadius: 10, border: `1px solid ${TB.hairline}`,
                    background: 'transparent', color: TB.ink, fontSize: 12, fontWeight: 600,
                    cursor: 'pointer', fontFamily: 'inherit',
                  }}>Test</button>
                  <button onClick={() => { notif.disable(); toast('Notificaties uit'); }} style={{
                    flex: 1, padding: '10px', borderRadius: 10, border: 'none',
                    background: 'transparent', color: '#C44A3A', fontSize: 12, fontWeight: 600,
                    cursor: 'pointer', fontFamily: 'inherit',
                  }}>Uitzetten</button>
                </div>
              </React.Fragment>
            )}
          </React.Fragment>
        )}
      </div>
    </React.Fragment>
  );
}

const notifInputStyle = {
  width: '100%', padding: '10px 12px', fontSize: 15, border: `1px solid ${TB.hairline}`,
  borderRadius: 10, background: TB.bg, outline: 'none', boxSizing: 'border-box',
  fontFamily: 'inherit', color: TB.ink,
};

// ═══ CYCLE SETTINGS ═════════════════════════════════════════════
function CycleSettings({ state, set, toast }) {
  const cycleRange = (typeof fmtCycleRange === 'function') ? fmtCycleRange(state) : '';
  return (
    <React.Fragment>
      <SectionHeader eyebrow="maandcyclus" title="Salaris-dag" right={cycleRange} />
      <div className="vb-card" style={{ padding: '14px 16px', marginBottom: 14 }}>
        <label style={{ fontSize: 12, color: TB.inkSoft, display: 'block', marginBottom: 6 }}>
          Op welke dag van de maand krijg je salaris?
        </label>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <input type="number" min="1" max="28" value={state.cycleResetDay || 23}
            onChange={e => set(s => ({ ...s, cycleResetDay: Math.min(28, Math.max(1, Number(e.target.value) || 23)) }))}
            style={{ ...notifInputStyle, width: 90 }} />
          <span style={{ fontSize: 13, color: TB.inkFaint }}>van elke maand</span>
        </div>
        <div style={{ marginTop: 10, fontSize: 11, color: TB.inkFaint, lineHeight: 1.5 }}>
          Op deze dag worden uitgaven gearchiveerd en rekeningen weer op "te betalen" gezet. Je krijgt dan een fris overzicht voor de nieuwe maand.
        </div>
        <button onClick={() => {
          if (!confirm('Nu handmatig resetten? Uitgaven en betaalde rekeningen worden naar de geschiedenis verplaatst.')) return;
          set(s => performCycleReset(s, new Date()));
          toast('Nieuwe maand begonnen ✨');
        }} style={{
          marginTop: 10, padding: '8px 14px', borderRadius: 10, border: `1px solid ${TB.hairline}`,
          background: 'transparent', color: TB.ink, fontSize: 12, fontWeight: 600,
          cursor: 'pointer', fontFamily: 'inherit',
        }}>Reset nu handmatig</button>
      </div>
    </React.Fragment>
  );
}

// ═══ BACKUP SETTINGS ════════════════════════════════════════════
function BackupSettings({ state, set, toast }) {
  const fileRef = React.useRef(null);

  const download = () => {
    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 = `maud-backup-${new Date().toISOString().slice(0,10)}.json`;
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(url);
    set(s => ({ ...s, lastBackupAt: new Date().toISOString() }));
    toast('Backup gedownload 💾');
  };

  const upload = (e) => {
    const f = e.target.files?.[0];
    if (!f) return;
    const reader = new FileReader();
    reader.onload = (ev) => {
      try {
        const data = JSON.parse(ev.target.result);
        if (!data || typeof data !== 'object' || !data.budgets) throw new Error('Geen geldige backup');
        if (!confirm('Backup laden — alle huidige data wordt vervangen. Doorgaan?')) return;
        set(() => ({ ...DEFAULTS, ...data }));
        toast('Backup geladen 💚');
      } catch (err) {
        toast(err.message || 'Bestand niet geldig', 'warn');
      }
    };
    reader.readAsText(f);
    e.target.value = '';
  };

  const last = state.lastBackupAt ? new Date(state.lastBackupAt) : null;

  return (
    <React.Fragment>
      <SectionHeader eyebrow="data" title="Backup & herstel" />
      <div className="vb-card" style={{ padding: '14px 16px', marginBottom: 14 }}>
        <div style={{ fontSize: 12, color: TB.inkSoft, marginBottom: 10, lineHeight: 1.5 }}>
          Sla alles op in een bestand — handig bij telefoon-wissel of als backup.
        </div>
        <div style={{ display: 'flex', gap: 6 }}>
          <button onClick={download} style={{
            flex: 1, padding: '10px', borderRadius: 10, border: 'none',
            background: TB.accent, color: '#fff', fontSize: 13, fontWeight: 600,
            cursor: 'pointer', fontFamily: 'inherit',
          }}>↓ Download</button>
          <button onClick={() => fileRef.current?.click()} style={{
            flex: 1, padding: '10px', borderRadius: 10, border: `1px solid ${TB.hairline}`,
            background: 'transparent', color: TB.ink, fontSize: 13, fontWeight: 600,
            cursor: 'pointer', fontFamily: 'inherit',
          }}>↑ Laad backup</button>
          <input ref={fileRef} type="file" accept="application/json,.json" onChange={upload} style={{ display: 'none' }} />
        </div>
        {last && (
          <div style={{ marginTop: 8, fontSize: 11, color: TB.inkFaint }}>
            Laatste backup: {last.toLocaleDateString('nl-NL')} {last.toLocaleTimeString('nl-NL', { hour: '2-digit', minute: '2-digit' })}
          </div>
        )}
      </div>
    </React.Fragment>
  );
}

// ═══ ADD SHEET ═══════════════════════════════════════════════════
function AddSheet({ state, set, onClose, toast }) {
  const [mode, setMode] = React.useState('menu');
  return (
    <div onClick={onClose} style={{
      position: 'absolute', inset: 0, zIndex: 100,
      background: 'rgba(28,42,36,0.32)', backdropFilter: 'blur(4px)',
      display: 'flex', alignItems: 'flex-end', justifyContent: 'center',
    }}>
      <div onClick={e => e.stopPropagation()} className="vb-sheet" style={{
        width: '100%', background: TB.bg, borderTopLeftRadius: 28, borderTopRightRadius: 28,
        padding: '14px 18px 32px', maxHeight: '80%', overflow: 'auto',
        boxShadow: '0 -20px 60px rgba(0,0,0,0.18)',
      }}>
        {/* handle */}
        <div style={{ width: 40, height: 4, borderRadius: 2, background: TB.hairline, margin: '0 auto 16px' }} />

        {mode === 'menu' && (
          <React.Fragment>
            <div className="vb-display" style={{ fontSize: 20, marginBottom: 14 }}>Wat voeg je toe?</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
              {[
                { id: 'appt',     label: 'Afspraak',    icon: '📅', sub: 'vandaag/komend' },
                { id: 'grocery',  label: 'Boodschap',   icon: '🛒', sub: 'op de lijst' },
                { id: 'brain',    label: 'Brain dump',  icon: '💭', sub: 'hoofd legen' },
                { id: 'bill',     label: 'Rekening',    icon: '🪙', sub: 'eenmalig/vast' },
                { id: 'goal',     label: 'Spaardoel',   icon: '🎯', sub: 'nieuw potje' },
              ].map(o => (
                <button key={o.id} onClick={() => setMode(o.id)} style={{
                  padding: 16, borderRadius: 16, border: 'none', cursor: 'pointer',
                  background: TB.card, textAlign: 'left', fontFamily: 'inherit',
                  display: 'flex', flexDirection: 'column', gap: 4,
                }}>
                  <div style={{ fontSize: 26 }}>{o.icon}</div>
                  <div style={{ fontSize: 14, fontWeight: 600, color: TB.ink, marginTop: 4 }}>{o.label}</div>
                  <div style={{ fontSize: 11, color: TB.inkFaint }}>{o.sub}</div>
                </button>
              ))}
            </div>
          </React.Fragment>
        )}

        {mode === 'expense' && <AddExpense state={state} set={set} onDone={() => toast('Genoteerd 💸')} onBack={() => setMode('menu')} />}
        {mode === 'appt'    && <AddAppt    state={state} set={set} onDone={() => toast('Afspraak erbij 📅')} onBack={() => setMode('menu')} />}
        {mode === 'grocery' && <AddGrocery state={state} set={set} onDone={() => toast('Op de lijst 🛒')} onBack={() => setMode('menu')} />}
        {mode === 'brain'   && <AddBrain   state={state} set={set} onDone={() => toast('Hoofd geleegd 💭')} onBack={() => setMode('menu')} />}
        {mode === 'bill'    && <AddBill    state={state} set={set} onDone={() => toast('Rekening genoteerd')} onBack={() => setMode('menu')} />}
        {mode === 'goal'    && <AddGoal    state={state} set={set} onDone={() => toast('Nieuw potje 🎯')} onBack={() => setMode('menu')} />}
      </div>
    </div>
  );
}

function SheetForm({ title, onBack, children, onSubmit, canSubmit }) {
  return (
    <React.Fragment>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14 }}>
        <button onClick={onBack} style={{
          width: 32, height: 32, borderRadius: 10, border: 'none', cursor: 'pointer',
          background: TB.card, color: TB.inkSoft, fontSize: 18, fontFamily: 'inherit',
        }}>←</button>
        <div className="vb-display" style={{ fontSize: 20 }}>{title}</div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>{children}</div>
      <button onClick={onSubmit} disabled={!canSubmit} style={{
        width: '100%', marginTop: 16, padding: '14px', borderRadius: 14, border: 'none',
        background: canSubmit ? TB.accent : TB.hairline, color: '#fff', fontSize: 15, fontWeight: 600,
        cursor: canSubmit ? 'pointer' : 'not-allowed', fontFamily: 'inherit',
      }}>Toevoegen</button>
    </React.Fragment>
  );
}

const sheetInput = {
  width: '100%', padding: '14px 16px', fontSize: 16, border: `1px solid ${TB.hairline}`,
  borderRadius: 12, background: TB.card, outline: 'none', boxSizing: 'border-box',
  fontFamily: 'inherit', color: TB.ink,
};

function AddExpense({ state, set, onDone, onBack }) {
  const [amt, setAmt] = React.useState('');
  const [label, setLabel] = React.useState('');
  const [cat, setCat] = React.useState('food');
  const submit = () => {
    const a = parseFloat(String(amt).replace(',', '.'));
    if (!a || !label.trim()) return;
    set(s => ({ ...s, expenses: [{ id: 'e'+Date.now(), amount: a, label: label.trim(), cat, daysAgo: 0 }, ...s.expenses] }));
    onDone();
  };
  return (
    <SheetForm title="Uitgave loggen" onBack={onBack} onSubmit={submit} canSubmit={!!amt && !!label.trim()}>
      <input value={amt} onChange={e=>setAmt(e.target.value)} placeholder="bedrag, bv. 4,50" inputMode="decimal" style={sheetInput} autoFocus />
      <input value={label} onChange={e=>setLabel(e.target.value)} placeholder="omschrijving, bv. koffie" style={sheetInput} />
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
        {state.budgets.map(c => (
          <button key={c.cat} onClick={() => setCat(c.cat)} style={{
            padding: '12px 10px', borderRadius: 12, cursor: 'pointer',
            border: 'none', background: cat === c.cat ? TB.ink : TB.card,
            color: cat === c.cat ? '#fff' : TB.ink, fontSize: 13, fontFamily: 'inherit',
            display: 'flex', alignItems: 'center', gap: 8,
          }}><span style={{ fontSize: 18 }}>{c.icon}</span> {c.label}</button>
        ))}
      </div>
    </SheetForm>
  );
}

function AddAppt({ state, set, onDone, onBack }) {
  const [time, setTime] = React.useState('14:00');
  const [title, setTitle] = React.useState('');
  const [kind, setKind] = React.useState('social');
  const [day, setDay] = React.useState(0);
  const submit = () => {
    if (!title.trim()) return;
    set(s => ({ ...s, appointments: [...s.appointments, { id: 'a'+Date.now(), time, title: title.trim(), kind, day }] }));
    onDone();
  };
  return (
    <SheetForm title="Afspraak toevoegen" onBack={onBack} onSubmit={submit} canSubmit={!!title.trim()}>
      <input value={title} onChange={e=>setTitle(e.target.value)} placeholder="wat?" style={sheetInput} autoFocus />
      <div style={{ display: 'flex', gap: 8 }}>
        <input type="time" value={time} onChange={e=>setTime(e.target.value)} style={{ ...sheetInput, flex: 1 }} />
        <select value={day} onChange={e=>setDay(Number(e.target.value))} style={{ ...sheetInput, flex: 1 }}>
          <option value={0}>vandaag</option>
          <option value={1}>morgen</option>
          <option value={2}>overmorgen</option>
          <option value={3}>over 3 dagen</option>
        </select>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 6 }}>
        {[
          { id: 'work',   label: 'werk' },
          { id: 'social', label: 'sociaal' },
          { id: 'health', label: 'gezond' },
          { id: 'other',  label: 'overig' },
        ].map(k => (
          <button key={k.id} onClick={() => setKind(k.id)} style={{
            padding: '10px 6px', borderRadius: 10, border: 'none', cursor: 'pointer',
            background: kind === k.id ? kindColor(k.id) : TB.card,
            color: kind === k.id ? '#fff' : TB.ink, fontSize: 12, fontFamily: 'inherit',
          }}>{k.label}</button>
        ))}
      </div>
    </SheetForm>
  );
}

function AddGrocery({ state, set, onDone, onBack }) {
  const [v, setV] = React.useState('');
  const submit = () => {
    if (!v.trim()) return;
    set(s => ({ ...s, groceries: [...s.groceries, { id: 'g'+Date.now(), label: v.trim(), done: false }] }));
    onDone();
  };
  return (
    <SheetForm title="Boodschap" onBack={onBack} onSubmit={submit} canSubmit={!!v.trim()}>
      <input value={v} onChange={e=>setV(e.target.value)} onKeyDown={e=>e.key==='Enter'&&submit()} placeholder="bv. melk" style={sheetInput} autoFocus />
    </SheetForm>
  );
}

function AddBrain({ state, set, onDone, onBack }) {
  const [v, setV] = React.useState('');
  const [tag, setTag] = React.useState(null);
  const submit = () => {
    if (!v.trim()) return;
    set(s => ({ ...s, brainDump: [{ id: 'bd'+Date.now(), text: v.trim(), tag }, ...s.brainDump] }));
    onDone();
  };
  return (
    <SheetForm title="Brain dump" onBack={onBack} onSubmit={submit} canSubmit={!!v.trim()}>
      <textarea value={v} onChange={e=>setV(e.target.value)} placeholder="wat zit er in je hoofd?" rows={3} style={{ ...sheetInput, resize: 'none', fontFamily: 'inherit' }} autoFocus />
      <div style={{ display: 'flex', gap: 6 }}>
        {[null, 'idee', 'todo', 'buy'].map(t => (
          <button key={t || 'none'} onClick={() => setTag(t)} style={{
            flex: 1, padding: '10px', borderRadius: 10, border: 'none', cursor: 'pointer',
            background: tag === t ? TB.accent : TB.card, color: tag === t ? '#fff' : TB.ink,
            fontSize: 12, fontFamily: 'inherit', textTransform: 'uppercase', letterSpacing: 0.1, fontWeight: 600,
          }}>{t || 'geen'}</button>
        ))}
      </div>
    </SheetForm>
  );
}

function AddBill({ state, set, onDone, onBack }) {
  const [name, setName] = React.useState('');
  const [amount, setAmount] = React.useState('');
  const [day, setDay] = React.useState('15');
  const submit = () => {
    const a = parseFloat(String(amount).replace(',', '.'));
    if (!name.trim() || !a) return;
    set(s => ({ ...s, bills: [...s.bills, { id: 'b'+Date.now(), name: name.trim(), amount: a, day: Number(day), kind: 'fixed', paid: false }] }));
    onDone();
  };
  return (
    <SheetForm title="Rekening" onBack={onBack} onSubmit={submit} canSubmit={!!name.trim() && !!amount}>
      <input value={name} onChange={e=>setName(e.target.value)} placeholder="bv. Netflix" style={sheetInput} autoFocus />
      <div style={{ display: 'flex', gap: 8 }}>
        <input value={amount} onChange={e=>setAmount(e.target.value)} placeholder="bedrag €" inputMode="decimal" style={{ ...sheetInput, flex: 2 }} />
        <input value={day} onChange={e=>setDay(e.target.value)} placeholder="dag" inputMode="numeric" style={{ ...sheetInput, flex: 1 }} />
      </div>
    </SheetForm>
  );
}

function AddGoal({ state, set, onDone, onBack }) {
  const [name, setName] = React.useState('');
  const [target, setTarget] = React.useState('');
  const submit = () => {
    const t = parseFloat(String(target).replace(',', '.'));
    if (!name.trim() || !t) return;
    set(s => ({ ...s, savings: [...s.savings, { id: 's'+Date.now(), name: name.trim(), target: t, current: 0, color: 'sage' }] }));
    onDone();
  };
  return (
    <SheetForm title="Nieuw spaardoel" onBack={onBack} onSubmit={submit} canSubmit={!!name.trim() && !!target}>
      <input value={name} onChange={e=>setName(e.target.value)} placeholder="bv. Vakantie Berlijn" style={sheetInput} autoFocus />
      <input value={target} onChange={e=>setTarget(e.target.value)} placeholder="doel €" inputMode="decimal" style={sheetInput} />
    </SheetForm>
  );
}

// ═══ SHARED CHUNKS ═══════════════════════════════════════════════
function Header({ eyebrow, title }) {
  return (
    <div style={{ padding: '54px 18px 16px' }}>
      <div className="vb-cap" style={{ color: TB.accent }}>{eyebrow}</div>
      <div className="vb-display" style={{ marginTop: 4, fontSize: 30 }}>{title}</div>
    </div>
  );
}

function SectionHeader({ eyebrow, title, right }) {
  return (
    <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 8, marginTop: 4 }}>
      <div>
        <div className="vb-cap" style={{ color: TB.inkFaint }}>{eyebrow}</div>
        {title && <div style={{ fontSize: 16, fontWeight: 500, marginTop: 2 }}>{title}</div>}
      </div>
      {right && <div style={{ fontSize: 12, color: TB.inkFaint }}>{right}</div>}
    </div>
  );
}

function KPI({ label, value }) {
  return (
    <div className="vb-card" style={{ padding: '10px 10px', textAlign: 'center' }}>
      <div style={{ fontSize: 10, color: TB.inkFaint, textTransform: 'uppercase', letterSpacing: 0.1, fontWeight: 600 }}>{label}</div>
      <div className="vb-num" style={{ fontSize: 14, fontWeight: 600, marginTop: 2 }}>{value}</div>
    </div>
  );
}

function SubTabs({ tabs, value, onChange }) {
  return (
    <div style={{ padding: '0 18px', display: 'flex', gap: 6 }}>
      {tabs.map(t => {
        const a = value === t.id;
        return (
          <button key={t.id} onClick={() => onChange(t.id)} style={{
            flex: 1, padding: '10px 8px', border: 'none', borderRadius: 12, cursor: 'pointer',
            background: a ? TB.card : 'transparent', color: a ? TB.ink : TB.inkSoft,
            fontSize: 13, fontWeight: a ? 600 : 500, fontFamily: 'inherit',
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
            boxShadow: a ? '0 1px 0 rgba(0,0,0,0.04)' : 'none',
            transition: 'all .15s',
          }}>
            {t.label}
            {t.count != null && t.count > 0 && (
              <span className="vb-num" style={{
                fontSize: 10, padding: '1px 6px', borderRadius: 99,
                background: a ? TB.accentSoft : TB.hairline, color: a ? TB.accent : TB.inkSoft, fontWeight: 600,
              }}>{t.count}</span>
            )}
          </button>
        );
      })}
    </div>
  );
}

// (NudgeCard component lives in nudges.jsx)

function DayStrip({ state, cal, selectedOffset = 0, onSelect, daySpend, dailyBudget }) {
  const baseDayIdx = TODAY.getDay() === 0 ? 6 : TODAY.getDay() - 1;
  const googleEvents = cal && cal.events ? cal.events : [];
  return (
    <div style={{ padding: '4px 14px', display: 'flex', gap: 4 }}>
      {['ma','di','wo','do','vr','za','zo'].map((label, idx0) => {
        const dayOffset = idx0 - baseDayIdx;
        const d = new Date(TODAY);
        d.setDate(TODAY.getDate() + dayOffset);
        const isToday = dayOffset === 0;
        const isSelected = dayOffset === selectedOffset;
        const manualCount = state.appointments.filter(a => a.day === dayOffset).length;
        const googleCount = (typeof googleEventsForDay === 'function')
          ? googleEventsForDay(googleEvents, dayOffset).length : 0;
        const apptCount = manualCount + googleCount;

        // Past days: over/under dot based on daily budget
        let moneyDot = null;
        if (daySpend && dailyBudget && dayOffset < 0) {
          const s = daySpend(dayOffset);
          if (s !== null) {
            moneyDot = (dailyBudget - s) >= 0 ? 'under' : 'over';
          }
        }

        const bg = isSelected ? (isToday ? TB.accent : TB.ink) : 'transparent';
        const fg = isSelected ? '#fff' : TB.ink;

        return (
          <button
            key={idx0}
            onClick={() => onSelect && onSelect(dayOffset)}
            style={{
              flex: 1, padding: '8px 4px', borderRadius: 12, textAlign: 'center',
              background: bg, color: fg, border: 'none', cursor: 'pointer',
              fontFamily: 'inherit', transition: 'all .15s',
              position: 'relative',
            }}
          >
            <div style={{ fontSize: 9, opacity: isSelected ? 0.85 : 0.5, textTransform: 'uppercase', fontWeight: 600, letterSpacing: 0.1 }}>{label}</div>
            <div className="vb-num" style={{ fontSize: 16, fontWeight: 600, marginTop: 2 }}>{d.getDate()}</div>
            <div style={{ marginTop: 4, display: 'flex', gap: 2, justifyContent: 'center', alignItems: 'center', height: 5 }}>
              {Array.from({ length: Math.min(3, apptCount) }).map((_, k) => (
                <div key={k} style={{ width: 4, height: 4, borderRadius: 2, background: isSelected ? 'rgba(255,255,255,0.85)' : TB.accent }} />
              ))}
              {moneyDot && (
                <div style={{
                  width: 4, height: 4, borderRadius: 2, marginLeft: apptCount ? 2 : 0,
                  background: moneyDot === 'under'
                    ? (isSelected ? 'rgba(255,255,255,0.85)' : '#5E7C6B')
                    : (isSelected ? '#FFD8A8' : '#C44A3A'),
                }} />
              )}
            </div>
            {isToday && !isSelected && (
              <div style={{
                position: 'absolute', inset: 0, borderRadius: 12,
                border: `1.5px solid ${TB.accent}`, pointerEvents: 'none',
              }} />
            )}
          </button>
        );
      })}
    </div>
  );
}

// ─── Money hero card: morphs based on selectedOffset ────────────
function DayMoneyHero({ state, money, selectedOffset, dailyBudget, daySpend, dayLabelShort, onResetToToday }) {
  const isToday = selectedOffset === 0;
  const isPast = selectedOffset < 0;

  let bg, eyebrow, big, subRow;

  if (isToday) {
    bg = money.dailyAllow > 0
      ? `linear-gradient(135deg, ${TB.accent} 0%, #4A6859 100%)`
      : 'linear-gradient(135deg, #C44A3A 0%, #A03A2D 100%)';
    eyebrow = 'vandaag mag je nog';
    big = '€' + money.dailyAllow;
    subRow = (
      <React.Fragment>
        <div>
          <div style={{ opacity: 0.75 }}>maand</div>
          <div className="vb-num" style={{ fontWeight: 600, fontSize: 14, marginTop: 2 }}>{fmtEurShort(money.safeToSpend)}</div>
        </div>
        <div style={{ textAlign: 'center' }}>
          <div style={{ opacity: 0.75 }}>uit deze maand</div>
          <div className="vb-num" style={{ fontWeight: 600, fontSize: 14, marginTop: 2 }}>{fmtEurShort(money.spent)}</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div style={{ opacity: 0.75 }}>nog</div>
          <div className="vb-num" style={{ fontWeight: 600, fontSize: 14, marginTop: 2 }}>{money.cycleDays}d</div>
        </div>
      </React.Fragment>
    );
  } else if (isPast) {
    const s = daySpend(selectedOffset) || 0;
    const diff = dailyBudget - s;
    const overspent = diff < 0;
    bg = overspent
      ? 'linear-gradient(135deg, #C44A3A 0%, #A03A2D 100%)'
      : `linear-gradient(135deg, ${TB.accent} 0%, #4A6859 100%)`;
    eyebrow = overspent
      ? dayLabelShort(selectedOffset) + ' — te veel uitgegeven'
      : dayLabelShort(selectedOffset) + ' — hield je over';
    big = (overspent ? '−€' : '+€') + Math.abs(Math.round(diff));
    subRow = (
      <React.Fragment>
        <div>
          <div style={{ opacity: 0.75 }}>uitgegeven</div>
          <div className="vb-num" style={{ fontWeight: 600, fontSize: 14, marginTop: 2 }}>{fmtEurShort(s)}</div>
        </div>
        <div style={{ textAlign: 'center' }}>
          <div style={{ opacity: 0.75 }}>budget</div>
          <div className="vb-num" style={{ fontWeight: 600, fontSize: 14, marginTop: 2 }}>€{dailyBudget}/dag</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <button onClick={onResetToToday} style={{
            background: 'rgba(255,255,255,0.18)', border: 'none', color: '#fff',
            padding: '6px 12px', borderRadius: 99, fontSize: 11, fontWeight: 600,
            cursor: 'pointer', fontFamily: 'inherit',
          }}>vandaag →</button>
        </div>
      </React.Fragment>
    );
  } else {
    bg = `linear-gradient(135deg, ${TB.accent} 0%, #4A6859 100%)`;
    eyebrow = dayLabelShort(selectedOffset) + ' mag je';
    big = '€' + dailyBudget;
    subRow = (
      <React.Fragment>
        <div>
          <div style={{ opacity: 0.75 }}>fair budget</div>
          <div className="vb-num" style={{ fontWeight: 600, fontSize: 14, marginTop: 2 }}>€{dailyBudget}/dag</div>
        </div>
        <div style={{ textAlign: 'center' }}>
          <div style={{ opacity: 0.75 }}>maand-totaal</div>
          <div className="vb-num" style={{ fontWeight: 600, fontSize: 14, marginTop: 2 }}>{fmtEurShort(money.safeToSpend)}</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <button onClick={onResetToToday} style={{
            background: 'rgba(255,255,255,0.18)', border: 'none', color: '#fff',
            padding: '6px 12px', borderRadius: 99, fontSize: 11, fontWeight: 600,
            cursor: 'pointer', fontFamily: 'inherit',
          }}>vandaag →</button>
        </div>
      </React.Fragment>
    );
  }

  return (
    <div style={{
      width: '100%', padding: '18px 20px', marginBottom: 14, borderRadius: 22,
      background: bg, color: '#fff', transition: 'background .3s',
    }}>
      <div className="vb-cap" style={{ opacity: 0.78 }}>{eyebrow}</div>
      <div className="vb-num vb-display" style={{ fontSize: 44, marginTop: 4, letterSpacing: -1.2 }}>{big}</div>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end',
        marginTop: 14, fontSize: 12, opacity: 0.9,
      }}>
        {subRow}
      </div>
    </div>
  );
}

function BottomTabs({ tab, setTab }) {
  const tabs = [
    { id: 'today', label: 'Vandaag', icon: <Icon name="sun" /> },
    { id: 'money', label: 'Geld',    icon: <Icon name="coin" /> },
    { id: 'lists', label: 'Lijsten', icon: <Icon name="list" /> },
    { id: 'me',    label: 'Mij',     icon: <Icon name="me" /> },
  ];
  return (
    <div style={{
      position: 'absolute', bottom: 0, left: 0, right: 0,
      padding: '10px 12px 26px',
      background: 'rgba(244,242,236,0.94)',
      backdropFilter: 'blur(20px)',
      WebkitBackdropFilter: 'blur(20px)',
      borderTop: `1px solid ${TB.hairline}`,
      display: 'flex', justifyContent: 'space-around',
      zIndex: 10,
    }}>
      {tabs.map(t => {
        const a = tab === t.id;
        return (
          <button key={t.id} onClick={() => setTab(t.id)} style={{
            flex: 1, padding: '6px 4px', border: 'none', background: 'transparent',
            cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
            color: a ? TB.accent : TB.inkFaint, fontFamily: 'inherit',
          }}>
            <span style={{ width: 24, height: 24, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{t.icon}</span>
            <span style={{ fontSize: 10, fontWeight: a ? 600 : 500, letterSpacing: 0.1 }}>{t.label}</span>
          </button>
        );
      })}
    </div>
  );
}

function Icon({ name }) {
  const s = 'currentColor';
  if (name === 'sun')  return <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={s} strokeWidth="1.8" strokeLinecap="round"><circle cx="12" cy="12" r="4.5"/><path d="M12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6l1.4 1.4M17 17l1.4 1.4M5.6 18.4l1.4-1.4M17 7l1.4-1.4"/></svg>;
  if (name === 'coin') return <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={s} strokeWidth="1.8" strokeLinecap="round"><ellipse cx="12" cy="6" rx="8" ry="3"/><path d="M4 6v6c0 1.7 3.6 3 8 3s8-1.3 8-3V6"/><path d="M4 12v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/></svg>;
  if (name === 'list') return <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={s} strokeWidth="1.8" strokeLinecap="round"><path d="M8 6h12M8 12h12M8 18h12"/><circle cx="4" cy="6" r="1" fill={s}/><circle cx="4" cy="12" r="1" fill={s}/><circle cx="4" cy="18" r="1" fill={s}/></svg>;
  if (name === 'me')   return <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={s} strokeWidth="1.8" strokeLinecap="round"><circle cx="12" cy="8" r="3.5"/><path d="M4 21c1.5-4.5 5-6.5 8-6.5s6.5 2 8 6.5"/></svg>;
  return null;
}

function kindLabel(k) { return ({ work: 'werk', social: 'sociaal', health: 'gezond', other: 'overig', gcal: 'Google agenda' })[k] || k; }
function kindColor(k) { return ({ work: '#7A5AF8', social: '#D97757', health: '#5E7C6B', other: '#A8998A', gcal: '#4285F4' })[k] || '#A8998A'; }

function QuickLogB({ onLog, cats }) {
  const [amt, setAmt] = React.useState('');
  const [label, setLabel] = React.useState('');
  const [cat, setCat] = React.useState('food');
  const submit = () => {
    const a = parseFloat(String(amt).replace(',', '.'));
    if (!a || !label.trim()) return;
    onLog(a, label.trim(), cat);
    setAmt(''); setLabel('');
  };
  return (
    <div className="vb-card" style={{ padding: 12, marginBottom: 18 }}>
      <div style={{ display: 'flex', gap: 6, marginBottom: 8 }}>
        <input value={amt} onChange={e=>setAmt(e.target.value)} placeholder="€" inputMode="decimal" style={{
          width: 80, padding: '10px 12px', fontSize: 15, border: `1px solid ${TB.hairline}`,
          borderRadius: 10, background: TB.bg, outline: 'none', boxSizing: 'border-box',
          fontFamily: 'inherit', color: TB.ink,
        }} />
        <input value={label} onChange={e=>setLabel(e.target.value)} placeholder="bv. koffie" onKeyDown={e=>e.key==='Enter'&&submit()} style={{
          flex: 1, padding: '10px 12px', fontSize: 15, border: `1px solid ${TB.hairline}`,
          borderRadius: 10, background: TB.bg, outline: 'none', boxSizing: 'border-box',
          fontFamily: 'inherit', color: TB.ink,
        }} />
      </div>
      <div style={{ display: 'flex', gap: 4 }}>
        {cats.map(c => (
          <button key={c.cat} onClick={() => setCat(c.cat)} style={{
            flex: 1, padding: '8px 4px', borderRadius: 10, cursor: 'pointer',
            border: 'none', background: cat === c.cat ? TB.ink : 'transparent',
            color: cat === c.cat ? '#fff' : TB.inkSoft, fontSize: 11, fontFamily: 'inherit',
          }}>{c.icon} {c.label}</button>
        ))}
      </div>
      <button onClick={submit} style={{
        marginTop: 8, width: '100%', padding: '12px', borderRadius: 12, border: 'none',
        background: TB.accent, color: '#fff', fontSize: 14, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
      }}>+ loggen</button>
    </div>
  );
}

function BrainInputB({ onAdd }) {
  const [v, setV] = React.useState('');
  return (
    <input value={v} onChange={e=>setV(e.target.value)} onKeyDown={e => { if (e.key==='Enter' && v.trim()) { onAdd(v.trim()); setV(''); }}}
      placeholder="schrijf, druk enter."
      style={{
        width: '100%', padding: '14px 16px', borderRadius: 14,
        border: `1px dashed ${TB.hairline}`, background: 'transparent',
        fontSize: 15, color: TB.ink, outline: 'none', boxSizing: 'border-box', fontFamily: 'inherit',
      }}
    />
  );
}

function GroceryInputB({ onAdd }) {
  const [v, setV] = React.useState('');
  return (
    <input value={v} onChange={e=>setV(e.target.value)} onKeyDown={e => { if (e.key==='Enter' && v.trim()) { onAdd(v.trim()); setV(''); }}}
      placeholder="bv. melk"
      style={{
        width: '100%', padding: '12px 14px', borderRadius: 12,
        border: `1px dashed ${TB.hairline}`, background: 'transparent',
        fontSize: 14, color: TB.ink, outline: 'none', boxSizing: 'border-box', fontFamily: 'inherit',
      }}
    />
  );
}

Object.assign(window, { VariantB });
