// variant-minimal.jsx — App shell + screens (AddScreen, Settings, ExpenseDetail, etc.)

(function () {
  const { useState, useMemo, useEffect, createContext, useContext } = React;
  const AuthContext = createContext(null);
  const {
    fmtEUR, fmtEURshort, fmtDate, fmtDateLong, fmtWeekday,
    dayTotal, tripDays, tripDayNum, tripLength,
    tripSpent, tripRemaining, daysPassed, daysLeft,
    avgPerDay, recommendedPerDay,
    expDate, expTime, expCat, expDesc, expLoc, expAmt,
    tripStart, tripEnd, tripBudget, tripFlag, todayISO,
    Icon, IOSDevice,
    MinPalette: p, MinF: F, MinMono: MONO,
    CatProvider, useCats, NavContext, useNav,
    SyncProvider, useSync, fmtSyncAge,
    MinEyebrow: Eyebrow, MinHRule: HRule, MinCatMark: CatMark,
    MinMetric: Metric, MinPchip: Pchip, MinListRow: ListRow,
    MinFAB: FAB, MinOverlay: Overlay, MinOverlayHead: OverlayHead,
    MinReceiptSlot: ReceiptSlot, MinReceiptCapture: ReceiptCapture,
    MinConfirmModal: ConfirmModal, MinEmptyState: EmptyState,
    MinHeute, MinWoche, MinReise, MinListe, MinRubrik,
    useTweaks, TweaksPanel, TweakSection, TweakColor, TweakSelect, TweakButton,
  } = window;
  const { useAuth, useData, AuthProvider, DataAndSyncProvider } = window.UKProviders;

  // ── Color mixing helper for derived theme values ───────────
  const hexToRgb = (h) => {
    const v = parseInt(h.slice(1), 16);
    return [(v >> 16) & 255, (v >> 8) & 255, v & 255];
  };
  const mix = (c1, c2, t) => {
    const a = hexToRgb(c1), b = hexToRgb(c2);
    const r = Math.round(a[0] * (1 - t) + b[0] * t);
    const g = Math.round(a[1] * (1 - t) + b[1] * t);
    const v = Math.round(a[2] * (1 - t) + b[2] * t);
    return '#' + [r, g, v].map(x => x.toString(16).padStart(2, '0')).join('');
  };
  const withAlpha = (hex, a) => {
    const [r, g, b] = hexToRgb(hex);
    return `rgba(${r},${g},${b},${a})`;
  };

  // Mutate the shared MinPalette in place — components read these
  // properties live every render, so updating them refreshes the look.
  function applyTheme([accent, paper, ink]) {
    p.accent  = accent;
    p.accent2 = mix(accent, '#ffffff', 0.18);
    p.paper   = paper;
    p.paper2  = mix(paper, '#ffffff', 0.32);
    p.paper3  = mix(paper, ink, 0.07);
    p.ink     = ink;
    p.ink2    = mix(ink, paper, 0.10);
    p.muted   = mix(paper, ink, 0.55);
    p.line    = mix(paper, ink, 0.18);
    p.line2   = mix(paper, ink, 0.28);
    p.rule    = withAlpha(ink, 0.10);
    p.seaBg   = mix(paper, ink, 0.10);
    p.landBg  = mix(paper, ink, 0.04);
  }

  // ── Phone shell — prototype uses an iPhone frame, production fills viewport ──
  // window.RT_BARE === true (set by the production index.html) flips into the
  // full-bleed wrapper so the app sits on a real phone without a fake bezel.
  function PhoneShell({ children }) {
    if (typeof window !== 'undefined' && window.RT_BARE) {
      return (
        <div style={{
          width: '100vw', minHeight: '100vh', minHeight: '100dvh',
          background: p.paper, color: p.ink, position: 'relative', overflow: 'hidden',
          paddingTop: 'env(safe-area-inset-top, 0px)',
          paddingBottom: 'env(safe-area-inset-bottom, 0px)',
          boxSizing: 'border-box',
        }}>{children}</div>
      );
    }
    return <IOSDevice width={402} height={874}>{children}</IOSDevice>;
  }

  // ── Sync badge ─────────────────────────────────────────────
  function SyncBadge({ onClick }) {
    const s = useSync();
    const state = !s.online ? 'offline' : s.syncing ? 'syncing' : s.pending > 0 ? 'pending' : 'synced';
    const cfg = {
      synced:  { color: p.accent,  Icon: Icon.cloud,    label: 'synchron' },
      pending: { color: '#c79a30', Icon: Icon.sync,     label: `${s.pending} wartet` },
      syncing: { color: p.accent,  Icon: Icon.sync,     label: 'sendet …' },
      offline: { color: p.rust,    Icon: Icon.cloudOff, label: 'offline' },
    }[state];
    const IconC = cfg.Icon;
    return (
      <button onClick={onClick} style={{
        border: 0, background: cfg.color + '14', color: cfg.color, cursor: 'pointer',
        display: 'flex', alignItems: 'center', gap: 4,
        padding: '4px 8px', borderRadius: 999,
        fontFamily: F, fontSize: 10, fontWeight: 600, letterSpacing: 0.3,
      }}>
        <IconC style={{
          width: 12, height: 12,
          animation: state === 'syncing' ? 'rtSpin 1s linear infinite' : 'none',
        }}/>
        <style>{`@keyframes rtSpin { from { transform: rotate(0); } to { transform: rotate(360deg); } }`}</style>
        {cfg.label}
      </button>
    );
  }

  // ── Nameplate + tab strip ──────────────────────────────────
  function Nameplate({ tab, setTab, onSettings, onSwitchTrip }) {
    const { activeTrip } = useData();
    const today = todayISO();
    const tabs = [
      ['heute',  'Heute'],
      ['woche',  'Woche'],
      ['reise',  'Reise'],
      ['liste',  'Liste'],
      ['rubrik', 'Rubrik'],
    ];
    return (
      <div style={{ paddingTop: 4 }}>
        <div style={{ padding: '0 24px 4px', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
          <div style={{ minWidth: 0 }}>
            <Eyebrow style={{ fontSize: 9 }}>Reisetagebuch · Nr. 14</Eyebrow>
            <button onClick={onSwitchTrip} style={{
              display: 'flex', alignItems: 'center', gap: 8, border: 0, background: 'transparent',
              padding: 0, cursor: 'pointer', marginTop: 2, textAlign: 'left', maxWidth: '100%',
            }}>
              <span style={{ fontFamily: F, fontSize: 24, color: p.ink, fontWeight: 600, lineHeight: 1.05, letterSpacing: -0.6,
                whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: 220 }}>
                {activeTrip ? activeTrip.name : 'Noch keine Reise'}
              </span>
              {activeTrip && <span style={{ fontFamily: F, fontSize: 16, color: p.muted }}>{tripFlag(activeTrip)}</span>}
              <Icon.chev style={{ color: p.muted, width: 11, height: 11 }}/>
            </button>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 6, marginTop: 2 }}>
            <button onClick={onSettings} style={{
              border: 0, background: 'transparent', color: p.muted, cursor: 'pointer',
              padding: 4, display: 'flex',
            }}><Icon.gear/></button>
            <SyncBadge onClick={onSettings}/>
          </div>
        </div>
        <div style={{ padding: '4px 24px 10px', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', fontFamily: F, fontSize: 11, color: p.muted }}>
          {activeTrip ? (
            <>
              <span>{fmtDate(tripStart(activeTrip))} — {fmtDate(tripEnd(activeTrip))}</span>
              <span>Tag {daysPassed(activeTrip, today)} / {tripLength(activeTrip)}</span>
            </>
          ) : <span>Lege in den Einstellungen deine erste Reise an</span>}
        </div>
        <div style={{ borderTop: `1px solid ${p.line}`, borderBottom: `1px solid ${p.line}`, padding: '0 8px' }}>
          <div style={{ display: 'flex', overflowX: 'auto', scrollbarWidth: 'none' }}>
            {tabs.map(([k, l]) => (
              <button key={k} onClick={() => setTab(k)} style={{
                flexShrink: 0, border: 0, background: 'transparent',
                padding: '10px 14px', cursor: 'pointer',
                fontFamily: F, fontSize: 14, fontWeight: tab === k ? 600 : 400,
                color: tab === k ? p.ink : p.muted, position: 'relative',
              }}>
                {l}
                {tab === k && (
                  <div style={{ position: 'absolute', left: 14, right: 14, bottom: -1, height: 2, background: p.accent }}/>
                )}
              </button>
            ))}
          </div>
        </div>
      </div>
    );
  }

  // ── Add screen (with photo slot) ────────────────────────────
  function AddScreen({ onClose, prefill, expense }) {
    const { cats } = useCats();
    const { activeTrip, addExpense, updateExpense, uploadReceipt } = useData();
    const pf = prefill || {};
    const editing = !!expense;
    const nowHHMM = () => {
      const n = new Date();
      return String(n.getHours()).padStart(2, '0') + ':' + String(n.getMinutes()).padStart(2, '0');
    };
    const [amount, setAmount] = useState(editing ? expAmt(expense).toFixed(2).replace('.', ',') : '0');
    const [cat, setCat] = useState(editing ? (expCat(expense) || '') : (cats[0] ? cats[0].id : ''));
    const [desc, setDesc] = useState(editing ? (expDesc(expense) || '') : '');
    const [loc, setLoc] = useState(editing ? (expLoc(expense) || '') : (pf.location || ''));
    const [date, setDate] = useState(editing ? expDate(expense) : (pf.date || todayISO()));
    const [time, setTime] = useState(editing ? (expTime(expense) || nowHHMM()) : nowHHMM());
    const [photoBlob, setPhotoBlob] = useState(null);
    const [photoMime, setPhotoMime] = useState(null);
    const [saving, setSaving] = useState(false);

    useEffect(() => {
      if (!editing && !cat && cats[0]) setCat(cats[0].id);
    }, [cats, cat]);

    const press = (k) => {
      setAmount(a => {
        if (k === '⌫') return a.length <= 1 ? '0' : a.slice(0,-1);
        if (k === ',') return a.includes(',') ? a : a + ',';
        if (a === '0' && k !== ',') return k;
        if (a.includes(',') && a.split(',')[1].length >= 2) return a;
        return a + k;
      });
    };

    const save = async () => {
      const amt = parseFloat(amount.replace(',', '.')) || 0;
      if (amt <= 0) return;
      if (!editing && !activeTrip) return;
      setSaving(true);
      try {
        const fields = {
          category_id: cat || null,
          date: date,
          time: time || null,
          amount_eur: amt,
          description: desc.trim() || null,
          location: loc.trim() || null,
        };
        let targetId;
        if (editing) {
          await updateExpense(expense.id, fields);
          targetId = expense.id;
        } else {
          const e = await addExpense({ trip_id: activeTrip.id, ...fields });
          targetId = e.id;
        }
        if (photoBlob) {
          try { await uploadReceipt(targetId, photoBlob, photoMime); } catch (_) { /* gequeued */ }
        }
        onClose();
      } finally {
        setSaving(false);
      }
    };

    const canSave = (editing || !!activeTrip) && parseFloat(amount.replace(',', '.')) > 0 && !saving;

    return (
      <div style={{ height: '100%', background: p.paper, display: 'flex', flexDirection: 'column', fontFamily: F }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '14px 24px' }}>
          <button onClick={onClose} style={{ border: 0, background: 'transparent', color: p.muted, fontFamily: F, fontSize: 14, fontWeight: 500, cursor: 'pointer' }}>
            Verwerfen
          </button>
          <Eyebrow>{editing ? 'Eintrag bearbeiten' : 'Neuer Eintrag'}</Eyebrow>
          <button onClick={save} disabled={!canSave} style={{
            border: 0,
            background: canSave ? p.accent : p.line2, color: p.paper,
            fontFamily: F, fontSize: 13, fontWeight: 600,
            cursor: canSave ? 'pointer' : 'not-allowed',
            padding: '6px 12px', borderRadius: 4,
          }}>
            {saving ? 'Speichert …' : 'Sichern'}
          </button>
        </div>

        <div style={{ textAlign: 'center', padding: '20px 0 6px' }}>
          <Eyebrow>Betrag</Eyebrow>
          <div style={{ fontFamily: F, fontSize: 60, color: p.ink, fontWeight: 600, lineHeight: 1, marginTop: 10, letterSpacing: -2 }}>
            {amount}<span style={{ color: p.muted, fontSize: 30, fontWeight: 400 }}> €</span>
          </div>
        </div>

        <div style={{ padding: '10px 24px 0' }}>
          <Eyebrow style={{ marginBottom: 6 }}>Rubrik</Eyebrow>
          <div style={{ display: 'flex', gap: 5, overflowX: 'auto', scrollbarWidth: 'none', padding: '2px 0' }}>
            {cats.slice(0, 12).map(c => (
              <button key={c.id} onClick={() => setCat(c.id)} style={{
                flexShrink: 0,
                border: cat === c.id ? `1.5px solid ${c.color}` : `1px solid ${p.line}`,
                background: cat === c.id ? c.color + '14' : p.paper2,
                padding: '8px 10px', borderRadius: 6, cursor: 'pointer',
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
                minWidth: 64,
              }}>
                <div style={{ fontSize: 18 }}>{c.emoji}</div>
                <div style={{ fontFamily: F, fontSize: 10, color: p.ink, fontWeight: 500, textAlign: 'center', lineHeight: 1.1, whiteSpace: 'nowrap' }}>{c.label}</div>
              </button>
            ))}
          </div>
        </div>

        <div style={{ padding: '12px 24px 0' }}>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', borderBottom: `1px solid ${p.line2}`, padding: '8px 0' }}>
            <Icon.pin style={{ color: p.accent }}/>
            <input value={desc} onChange={e => setDesc(e.target.value)} placeholder="Was war's? (z.B. Tankstelle Esso)"
              style={{ border: 0, background: 'transparent', flex: 1, color: p.ink, fontFamily: F, fontSize: 15, outline: 'none' }}/>
          </div>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', borderBottom: `1px solid ${p.line2}`, padding: '8px 0' }}>
            <Icon.loc style={{ color: p.accent, width: 16, height: 16 }}/>
            <input value={loc} onChange={e => setLoc(e.target.value)} placeholder="Ort"
              style={{ border: 0, background: 'transparent', flex: 1, color: p.ink, fontFamily: F, fontSize: 15, outline: 'none' }}/>
          </div>
        </div>

        {/* Datum & Zeit */}
        <div style={{ padding: '12px 24px 0' }}>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', borderBottom: `1px solid ${p.line2}`, padding: '8px 0' }}>
            <Icon.cal style={{ color: p.accent, width: 16, height: 16 }}/>
            <input type="date" value={date} max="2100-12-31" onChange={e => setDate(e.target.value || todayISO())}
              style={{ border: 0, background: 'transparent', flex: 1, color: p.ink, fontFamily: F, fontSize: 15, outline: 'none', WebkitAppearance: 'none' }}/>
            <input type="time" value={time} onChange={e => setTime(e.target.value)}
              style={{ border: 0, background: 'transparent', width: 86, color: p.ink, fontFamily: F, fontSize: 15, outline: 'none', textAlign: 'right', WebkitAppearance: 'none' }}/>
          </div>
        </div>

        {/* Receipt slot */}
        <div style={{ padding: '12px 24px 0' }}>
          <Eyebrow style={{ marginBottom: 6 }}>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
              <Icon.cam style={{ width: 12, height: 12 }}/> Beleg
            </span>
          </Eyebrow>
          <ReceiptCapture
            height={120}
            onPick={(blob, mime) => { setPhotoBlob(blob); setPhotoMime(mime); }}
          />
        </div>

        <div style={{ flex: 1 }}/>

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 1, padding: '12px 24px 24px' }}>
          {['1','2','3','4','5','6','7','8','9',',','0','⌫'].map(k => (
            <button key={k} onClick={() => press(k)} style={{
              border: `1px solid ${p.line}`, background: p.paper2,
              fontFamily: F, fontSize: 20, fontWeight: 500, color: p.ink,
              cursor: 'pointer', padding: '12px 0',
            }}>{k}</button>
          ))}
        </div>
      </div>
    );
  }

  // ── Sync section (in Settings) ─────────────────────────────
  function SyncSection() {
    const s = useSync();
    const status = !s.online ? 'offline' : s.syncing ? 'syncing' : s.pending > 0 ? 'pending' : 'synced';
    const cfg = {
      synced:  { color: p.accent,  label: 'Synchronisiert',   desc: 'Letzter Abgleich ' + fmtSyncAge(s.lastSync) },
      pending: { color: '#c79a30', label: s.pending + ' Einträge warten', desc: 'Werden beim nächsten Abgleich gesendet' },
      syncing: { color: p.accent,  label: 'Synchronisiere …', desc: 'Daten werden mit dem Server abgeglichen' },
      offline: { color: p.rust,    label: 'Offline',           desc: 'Einträge werden lokal gespeichert und später synchronisiert' },
    }[status];

    return (
      <>
        <HRule label="Synchronisation"/>
        <div style={{ padding: '0 24px' }}>
          {/* status card */}
          <div style={{
            background: cfg.color + '0c', border: `1px solid ${cfg.color}33`,
            borderRadius: 6, padding: '12px 14px', marginBottom: 8,
            display: 'flex', alignItems: 'center', gap: 12,
          }}>
            <div style={{
              width: 10, height: 10, borderRadius: 5, background: cfg.color,
              animation: status === 'syncing' ? 'rtPulse 1s ease-in-out infinite' : 'none',
              flexShrink: 0,
            }}/>
            <style>{`@keyframes rtPulse { 0%,100% { opacity: 1 } 50% { opacity: 0.3 } }`}</style>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontFamily: F, fontSize: 14, color: p.ink, fontWeight: 600 }}>{cfg.label}</div>
              <div style={{ fontFamily: F, fontSize: 11, color: p.muted, marginTop: 1 }}>{cfg.desc}</div>
            </div>
            <button onClick={s.syncNow} disabled={!s.online || s.syncing} style={{
              border: `1px solid ${cfg.color}66`,
              background: s.online && !s.syncing ? cfg.color : 'transparent',
              color: s.online && !s.syncing ? p.paper : cfg.color,
              padding: '6px 12px', borderRadius: 4, cursor: s.online && !s.syncing ? 'pointer' : 'default',
              fontFamily: F, fontSize: 11, fontWeight: 600, opacity: s.online && !s.syncing ? 1 : 0.5,
            }}>Jetzt synchronisieren</button>
          </div>

          <SettingRow label="Datenbank" value="SQLite" />
          <SettingRow label="Letzter Abgleich" value={fmtSyncAge(s.lastSync)} />
          {s.error && <SettingRow label="Letzter Fehler" value={s.error} />}

          <div style={{ marginTop: 4 }}>
            <SettingToggle
              label="Offline-Modus erzwingen"
              sub="Nur lokal speichern, später synchronisieren (zum Testen)"
              value={!s.online}
              onChange={v => s.setOnline(!v)}
            />
          </div>
        </div>
      </>
    );
  }

  // ── New-trip inline form ───────────────────────────────────
  function NewTripForm({ onCancel, onSave }) {
    const { addTrip } = useData();
    const today = new Date();
    const in2w  = new Date(Date.now() + 14 * 86400000);
    const [name, setName]   = useState('');
    const [flag, setFlag]   = useState('🌍');
    const [start, setStart] = useState(today.toISOString().slice(0, 10));
    const [end, setEnd]     = useState(in2w.toISOString().slice(0, 10));
    const [budget, setBudget] = useState(2000);
    const [active, setActive] = useState(true);
    const [saving, setSaving] = useState(false);

    const flags = ['🌍', '🇳🇴', '🇸🇪', '🇩🇰', '🇫🇮', '🇮🇸', '🇩🇪', '🇨🇭', '🇦🇹', '🇮🇹', '🇫🇷', '🇪🇸', '🇵🇹', '🇬🇷', '🇭🇷', '🏴', '🇳🇱', '🇧🇪', '🇮🇪', '🏝️'];

    const save = async () => {
      if (!name.trim() || saving) return;
      setSaving(true);
      try {
        const trip = await addTrip({
          name: name.trim(),
          flag: flag || '🌍',
          start_date: start,
          end_date: end,
          budget_eur: +budget || 0,
          active: !!active,
        });
        onSave(trip);
      } finally {
        setSaving(false);
      }
    };

    return (
      <div style={{
        marginTop: 12, padding: 14, background: p.paper2,
        border: `1px solid ${p.line}`, borderRadius: 6,
      }}>
        <Eyebrow style={{ marginBottom: 8 }}>Neue Reise</Eyebrow>

        <input value={name} onChange={e => setName(e.target.value)} autoFocus
          placeholder='Name (z.B. „Schweden Sommer 2026“)'
          style={{
            width: '100%', boxSizing: 'border-box', border: `1px solid ${p.line2}`,
            background: p.paper, borderRadius: 4, padding: '8px 10px',
            fontFamily: F, fontSize: 14, color: p.ink, outline: 'none',
          }}/>

        <Eyebrow style={{ marginTop: 12, marginBottom: 6 }}>Flagge</Eyebrow>
        <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
          {flags.map(f => (
            <button key={f} onClick={() => setFlag(f)} style={{
              width: 32, height: 32, fontSize: 16,
              border: flag === f ? `1.5px solid ${p.ink}` : `1px solid ${p.line}`,
              background: flag === f ? p.paper3 : p.paper, borderRadius: 4,
              cursor: 'pointer',
            }}>{f}</button>
          ))}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginTop: 12 }}>
          <label>
            <Eyebrow>Von</Eyebrow>
            <input type="date" value={start} onChange={e => setStart(e.target.value)}
              style={{
                width: '100%', boxSizing: 'border-box', border: `1px solid ${p.line2}`,
                background: p.paper, borderRadius: 4, padding: '6px 8px', marginTop: 4,
                fontFamily: F, fontSize: 13, color: p.ink, outline: 'none',
              }}/>
          </label>
          <label>
            <Eyebrow>Bis</Eyebrow>
            <input type="date" value={end} onChange={e => setEnd(e.target.value)}
              style={{
                width: '100%', boxSizing: 'border-box', border: `1px solid ${p.line2}`,
                background: p.paper, borderRadius: 4, padding: '6px 8px', marginTop: 4,
                fontFamily: F, fontSize: 13, color: p.ink, outline: 'none',
              }}/>
          </label>
        </div>

        <label style={{ display: 'block', marginTop: 12 }}>
          <Eyebrow>Budget (€)</Eyebrow>
          <input type="number" value={budget} onChange={e => setBudget(e.target.value)}
            style={{
              width: '100%', boxSizing: 'border-box', border: `1px solid ${p.line2}`,
              background: p.paper, borderRadius: 4, padding: '8px 10px', marginTop: 4,
              fontFamily: F, fontSize: 14, color: p.ink, outline: 'none',
            }}/>
        </label>

        <label style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 12, cursor: 'pointer' }}>
          <input type="checkbox" checked={active} onChange={e => setActive(e.target.checked)}
            style={{ width: 16, height: 16, accentColor: p.accent }}/>
          <span style={{ fontFamily: F, fontSize: 13, color: p.ink }}>Als aktuelle Reise setzen</span>
        </label>

        <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
          <button onClick={onCancel} style={{
            flex: 1, border: `1px solid ${p.line2}`, background: 'transparent', color: p.ink,
            fontFamily: F, fontSize: 13, fontWeight: 500, padding: '8px 0', borderRadius: 4, cursor: 'pointer',
          }}>Abbrechen</button>
          <button onClick={save} disabled={!name.trim()} style={{
            flex: 1, border: 0, background: name.trim() ? p.accent : p.line2, color: p.paper,
            fontFamily: F, fontSize: 13, fontWeight: 600, padding: '8px 0', borderRadius: 4,
            cursor: name.trim() ? 'pointer' : 'not-allowed',
          }}>Speichern</button>
        </div>
      </div>
    );
  }

  // ── Settings (with category management) ─────────────────────
  function SettingsScreen({ onClose }) {
    const { cats, addCat, removeCat } = useCats();
    const data = useData();
    const [showAddCat, setShowAddCat] = useState(false);
    const [showNewTrip, setShowNewTrip] = useState(false);
    const [confirmTrip, setConfirmTrip] = useState(null);
    const [confirmCat, setConfirmCat]   = useState(null);
    const [newLabel, setNewLabel] = useState('');
    const [newEmoji, setNewEmoji] = useState('🎯');
    const emojiSuggestions = ['🎯','🏔️','⚓','🍷','🚲','📚','🎨','🌊','🎵','💊','🏊','🎪','🧭','🚁'];
    const trips = data.trips;
    const exps  = data.expenses;
    const activeTrip = data.activeTrip;
    const [budget, setBudget] = useState(activeTrip ? tripBudget(activeTrip) : 0);
    useEffect(() => { if (activeTrip) setBudget(tripBudget(activeTrip)); }, [activeTrip && activeTrip.id]);

    const saveBudget = async () => {
      if (!activeTrip) return;
      if (Math.round(budget * 100) === activeTrip.budget_cents) return;
      await data.updateTrip(activeTrip.id, { budget_cents: Math.round(budget * 100) });
    };

    const askRemoveTrip = (t) => {
      const count = exps.filter(e => e.trip_id === t.id).length;
      setConfirmTrip({ id: t.id, name: t.name, count });
    };
    const doRemoveTrip = async () => {
      await data.removeTrip(confirmTrip.id);
      setConfirmTrip(null);
    };
    const askRemoveCat = (c) => {
      const count = exps.filter(e => e.category_id === c.id).length;
      setConfirmCat({ id: c.id, label: c.label, count });
    };
    const doRemoveCat = async () => {
      await data.removeCategory(confirmCat.id);
      setConfirmCat(null);
    };

    return (
      <div style={{ minHeight: '100%', background: p.paper, paddingTop: 56, paddingBottom: 80, fontFamily: F }}>
        <OverlayHead onBack={onClose} label="Einstellungen"/>
        <div style={{ padding: '8px 24px 0' }}>
          <div style={{ fontFamily: F, fontSize: 28, color: p.ink, fontWeight: 600, letterSpacing: -0.8 }}>
            Einstellungen
          </div>
          <div style={{ fontFamily: F, fontSize: 13, color: p.muted, marginTop: 4 }}>
            Reise, Rubriken und Voreinstellungen
          </div>
        </div>

        <SyncSection/>

        <HRule label="Aktuelle Reise"/>
        <div style={{ padding: '0 24px' }}>
          {activeTrip ? (
            <>
              <SettingRow label="Reise" value={tripFlag(activeTrip) + ' ' + activeTrip.name} />
              <SettingRow label="Zeitraum" value={fmtDate(tripStart(activeTrip)) + ' – ' + fmtDate(tripEnd(activeTrip))} />
              <SettingRow label="Budget" value={
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                  <input type="number" value={budget} onChange={e => setBudget(+e.target.value || 0)}
                    onBlur={saveBudget}
                    style={{ border: 0, background: 'transparent', width: 70, textAlign: 'right',
                      fontFamily: F, fontSize: 15, color: p.ink, fontWeight: 600, outline: 'none' }}/>
                  <span style={{ color: p.muted }}>€</span>
                </span>
              } />
              <SettingRow label="Währung" value="Euro · €" />
            </>
          ) : (
            <div style={{ padding: '8px 0', fontFamily: F, fontSize: 13, color: p.muted }}>
              Noch keine Reise. Lege weiter unten unter „Reisearchiv" eine an.
            </div>
          )}
        </div>

        <HRule label="Rubriken verwalten"/>
        <div style={{ padding: '0 24px' }}>
          <div style={{ fontFamily: F, fontSize: 12, color: p.muted, lineHeight: 1.5, marginBottom: 12 }}>
            Eigene Rubriken erscheinen sofort in der Auswahl beim Erfassen und in den Auswertungen.
          </div>
          {cats.map((c) => {
            const isUser = !!c.is_user;
            const count = exps.filter(e => e.category_id === c.id).length;
            return (
              <div key={c.id} style={{
                display: 'flex', alignItems: 'center', gap: 12,
                padding: '10px 0', borderBottom: '1px solid ' + p.rule,
              }}>
                <CatMark cat={c} size={28}/>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontFamily: F, fontSize: 14, color: p.ink, fontWeight: 500 }}>{c.label}</div>
                  <div style={{ fontFamily: F, fontSize: 10, color: p.muted, marginTop: 1 }}>
                    {isUser ? 'Eigene Rubrik' : 'Standard'} · {count} Einträge
                  </div>
                </div>
                <button onClick={() => askRemoveCat(c)} style={{
                  border: 0, background: 'transparent', color: p.rust,
                  fontFamily: F, fontSize: 11, fontWeight: 500, cursor: 'pointer',
                }}>Entfernen</button>
              </div>
            );
          })}
          {showAddCat ? (
            <div style={{
              marginTop: 14, padding: 14, background: p.paper2, border: `1px solid ${p.line}`, borderRadius: 6,
            }}>
              <Eyebrow style={{ marginBottom: 8 }}>Neue Rubrik anlegen</Eyebrow>
              <input value={newLabel} onChange={e => setNewLabel(e.target.value)} autoFocus
                placeholder="Bezeichnung (z.B. Camping-Zubehör)"
                style={{ width: '100%', boxSizing: 'border-box', border: `1px solid ${p.line2}`,
                  background: p.paper, borderRadius: 4, padding: '8px 10px',
                  fontFamily: F, fontSize: 14, color: p.ink, outline: 'none' }}/>
              <Eyebrow style={{ marginTop: 12, marginBottom: 6 }}>Symbol</Eyebrow>
              <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                {emojiSuggestions.map(e => (
                  <button key={e} onClick={() => setNewEmoji(e)} style={{
                    width: 36, height: 36, fontSize: 18,
                    border: newEmoji === e ? `1.5px solid ${p.ink}` : `1px solid ${p.line}`,
                    background: newEmoji === e ? p.paper3 : p.paper, borderRadius: 4,
                    cursor: 'pointer',
                  }}>{e}</button>
                ))}
              </div>
              <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
                <button onClick={() => { setShowAddCat(false); setNewLabel(''); }} style={{
                  flex: 1, border: `1px solid ${p.line2}`, background: 'transparent', color: p.ink,
                  fontFamily: F, fontSize: 13, fontWeight: 500, padding: '8px 0', borderRadius: 4, cursor: 'pointer',
                }}>Abbrechen</button>
                <button onClick={() => { if (newLabel.trim()) { addCat(newLabel.trim(), newEmoji); setShowAddCat(false); setNewLabel(''); } }} style={{
                  flex: 1, border: 0, background: p.accent, color: p.paper,
                  fontFamily: F, fontSize: 13, fontWeight: 600, padding: '8px 0', borderRadius: 4, cursor: 'pointer',
                }}>Hinzufügen</button>
              </div>
            </div>
          ) : (
            <button onClick={() => setShowAddCat(true)} style={{
              width: '100%', marginTop: 14, padding: '12px',
              border: `1px dashed ${p.line2}`, background: 'transparent',
              color: p.accent, fontFamily: F, fontSize: 13, fontWeight: 600,
              cursor: 'pointer', borderRadius: 4,
            }}>+ Rubrik hinzufügen</button>
          )}
        </div>

        <HRule label="Voreinstellungen"/>
        <div style={{ padding: '0 24px' }}>
          <SettingToggle label="Beleg-Foto pflicht" sub="Bei Einträgen über 50 € erinnern" />
          <SettingToggle label="Tagesbudget-Warnung" sub="Push, wenn 80 % erreicht" defaultOn/>
          <SettingRow label="Export" value="CSV · PDF" action="öffnen" isLast/>
        </div>

        <HRule label="Reisearchiv"/>
        <div style={{ padding: '0 24px' }}>
          {trips.map((t, i) => (
            <div key={t.id} style={{
              display: 'flex', alignItems: 'baseline', gap: 8,
              padding: '12px 0', borderBottom: i === trips.length - 1 ? 0 : '1px solid ' + p.rule,
            }}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                  <span style={{ fontFamily: F, fontSize: 15, color: p.ink, fontWeight: 500 }}>{tripFlag(t)} {t.name}</span>
                  {t.active && <span style={{ fontFamily: F, fontSize: 9, fontWeight: 700, color: p.accent, background: p.accent + '18', padding: '2px 6px', borderRadius: 99, letterSpacing: 1, textTransform: 'uppercase' }}>aktiv</span>}
                </div>
                <div style={{ fontFamily: F, fontSize: 11, color: p.muted, marginTop: 2 }}>
                  {fmtDate(tripStart(t))} – {fmtDate(tripEnd(t))} · {fmtEURshort(tripBudget(t))}
                </div>
              </div>
              {!t.active && (
                <button onClick={() => data.setActiveTrip(t.id)} style={{
                  border: 0, background: 'transparent', color: p.accent, cursor: 'pointer',
                  fontFamily: F, fontSize: 11, fontWeight: 500, padding: 6,
                }}>aktiv setzen</button>
              )}
              <button onClick={() => askRemoveTrip(t)} style={{
                border: 0, background: 'transparent', color: p.rust, cursor: 'pointer',
                fontFamily: F, fontSize: 11, fontWeight: 500, padding: 6,
              }}>Löschen</button>
            </div>
          ))}
          {showNewTrip ? (
            <NewTripForm
              onCancel={() => setShowNewTrip(false)}
              onSave={() => setShowNewTrip(false)}
            />
          ) : (
            <button onClick={() => setShowNewTrip(true)} style={{
              width: '100%', marginTop: 6, padding: '12px',
              border: '1px dashed ' + p.line2, background: 'transparent',
              color: p.accent, fontFamily: F, fontSize: 13, fontWeight: 600,
              cursor: 'pointer', borderRadius: 4,
            }}>+ Neue Reise anlegen</button>
          )}
        </div>

        <LogoutSection/>

        {confirmTrip && (
          <ConfirmModal
            title="Reise löschen?"
            message={'„' + confirmTrip.name + '" mit ' + confirmTrip.count + ' Eintr' + (confirmTrip.count === 1 ? 'ag' : 'ägen') + ' löschen. Das kann nicht rückgängig gemacht werden.'}
            confirmLabel="Löschen"
            onCancel={() => setConfirmTrip(null)}
            onConfirm={doRemoveTrip}
          />
        )}
        {confirmCat && (
          <ConfirmModal
            title="Rubrik löschen?"
            message={confirmCat.count
              ? '„' + confirmCat.label + '" wird entfernt. ' + confirmCat.count + ' Eintr' + (confirmCat.count === 1 ? 'ag bleibt' : 'äge bleiben') + ' mit verwaister Kategorie.'
              : '„' + confirmCat.label + '" wird entfernt.'}
            confirmLabel="Löschen"
            onCancel={() => setConfirmCat(null)}
            onConfirm={doRemoveCat}
          />
        )}
      </div>
    );
  }

  function LogoutSection() {
    const auth = useAuth();
    if (!auth) return null;
    return (
      <>
        <HRule label="Konto"/>
        <div style={{ padding: '0 24px' }}>
          <div style={{ fontFamily: F, fontSize: 13, color: p.muted, marginBottom: 8 }}>
            Angemeldet als <span style={{ color: p.ink, fontWeight: 600 }}>{auth.email || '—'}</span>
          </div>
          <button onClick={auth.logout} style={{
            width: '100%', padding: '10px',
            border: '1px solid ' + p.rust + '55', background: 'transparent',
            color: p.rust, fontFamily: F, fontSize: 13, fontWeight: 600,
            cursor: 'pointer', borderRadius: 4,
          }}>Abmelden</button>
          <div style={{ fontFamily: F, fontSize: 10, color: p.muted, marginTop: 12, textAlign: 'center' }}>
            Urlaubskasse v1.4.0
          </div>
        </div>
      </>
    );
  }

  const SettingRow = ({ label, value, action, isLast }) => (
    <button style={{
      width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      padding: '12px 0', borderBottom: isLast ? 0 : `1px solid ${p.rule}`,
      border: 0, background: 'transparent', cursor: action ? 'pointer' : 'default', textAlign: 'left',
    }}>
      <div style={{ fontFamily: F, fontSize: 14, color: p.ink, fontWeight: 500 }}>{label}</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
        <div style={{ fontFamily: F, fontSize: 13, color: action ? p.muted : p.ink, fontWeight: action ? 400 : 600 }}>{value}</div>
        {action && <Icon.chev style={{ color: p.muted, width: 11, height: 11 }}/>}
      </div>
    </button>
  );

  const SettingToggle = ({ label, sub, defaultOn, value, onChange }) => {
    const [internalOn, setInternalOn] = useState(!!defaultOn);
    const controlled = value !== undefined;
    const on = controlled ? value : internalOn;
    const toggle = () => {
      if (controlled) onChange && onChange(!on);
      else setInternalOn(!on);
    };
    return (
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '12px 0', borderBottom: `1px solid ${p.rule}`,
      }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontFamily: F, fontSize: 14, color: p.ink, fontWeight: 500 }}>{label}</div>
          {sub && <div style={{ fontFamily: F, fontSize: 11, color: p.muted, marginTop: 1 }}>{sub}</div>}
        </div>
        <button onClick={toggle} style={{
          width: 44, height: 24, borderRadius: 12, border: 0,
          background: on ? p.accent : p.line2, position: 'relative', cursor: 'pointer',
          transition: 'background 0.18s',
        }}>
          <div style={{
            position: 'absolute', top: 2, left: on ? 22 : 2, width: 20, height: 20, borderRadius: 10,
            background: p.paper, boxShadow: '0 1px 3px rgba(0,0,0,0.2)', transition: 'left 0.18s',
          }}/>
        </button>
      </div>
    );
  };

  // ── Expense detail (tap a list row) ─────────────────────────
  function ExpenseDetail({ expense, onClose }) {
    const { catById } = useCats();
    const { uploadReceipt, removeExpense } = useData();
    const nav = useNav();
    const [confirm, setConfirm] = useState(false);
    const e = expense;
    const c = catById[expCat(e)];
    const loc = expLoc(e);
    return (
      <div style={{ minHeight: '100%', background: p.paper, paddingTop: 56, paddingBottom: 60 }}>
        <OverlayHead onBack={onClose} label="Eintrag"/>
        <div style={{ padding: '8px 24px 0' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <CatMark cat={c} size={26}/>
            <Eyebrow>{c ? c.label : '—'}</Eyebrow>
          </div>
          <div style={{ fontFamily: F, fontSize: 24, color: p.ink, fontWeight: 600, marginTop: 8, lineHeight: 1.2 }}>
            {expDesc(e) || '—'}
          </div>
          <div style={{ fontFamily: F, fontSize: 50, color: p.ink, fontWeight: 600, marginTop: 14, lineHeight: 1, letterSpacing: -1.5 }}>
            {expAmt(e).toLocaleString('de-DE', { minimumFractionDigits: 2 })}<span style={{ color: p.muted, fontWeight: 400 }}> €</span>
          </div>
          <div style={{ fontFamily: F, fontSize: 13, color: p.muted, marginTop: 6 }}>
            {fmtDateLong(expDate(e))} · {expTime(e) || ''}
          </div>
        </div>

        {loc && (
          <>
            <HRule label="Ort"/>
            <div style={{ padding: '0 24px' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <Icon.pin style={{ color: p.accent }}/>
                <span style={{ fontFamily: F, fontSize: 15, color: p.ink, fontWeight: 500 }}>{loc}</span>
              </div>
            </div>
          </>
        )}

        <HRule label="Beleg"/>
        <div style={{ padding: '0 24px' }}>
          <ReceiptCapture
            height={e.receipt_url ? 200 : 140}
            existingUrl={e.receipt_url || null}
            onPick={async (blob, mime) => {
              try { await uploadReceipt(e.id, blob, mime); }
              catch (err) { alert('Upload fehlgeschlagen: ' + err.message); }
            }}
          />
        </div>

        <HRule/>
        <div style={{ padding: '0 24px', display: 'flex', gap: 10 }}>
          <button onClick={() => nav.openEdit(e.id)} style={{
            flex: 1, border: '1px solid ' + p.accent, background: p.accent,
            color: p.paper, fontFamily: F, fontSize: 13, fontWeight: 600, padding: '10px 0', borderRadius: 4, cursor: 'pointer',
          }}>Bearbeiten</button>
          <button onClick={() => setConfirm(true)} style={{
            flex: 1, border: '1px solid ' + p.rust + '55', background: 'transparent',
            color: p.rust, fontFamily: F, fontSize: 13, fontWeight: 500, padding: '10px 0', borderRadius: 4, cursor: 'pointer',
          }}>Eintrag löschen</button>
        </div>

        {confirm && (
          <ConfirmModal
            title="Eintrag löschen?"
            message={'„' + (expDesc(e) || 'Eintrag') + '" ('  + expAmt(e).toLocaleString('de-DE', { minimumFractionDigits: 2 }) + ' €) wird entfernt.'}
            confirmLabel="Löschen"
            onCancel={() => setConfirm(false)}
            onConfirm={async () => { await removeExpense(e.id); setConfirm(false); onClose(); }}
          />
        )}
      </div>
    );
  }

  // ── Category detail ─────────────────────────────────────────
  function CatDetail({ catId, onClose, openExpense }) {
    const { catById } = useCats();
    const { activeTrip, expenses } = useData();
    const c = catById[catId];
    if (!c) return null;
    const tripExps = activeTrip ? expenses.filter(e => e.trip_id === activeTrip.id) : expenses;
    const exps = tripExps.filter(e => expCat(e) === catId)
      .sort((a, b) => ((expDate(b) || '') + (expTime(b) || '')).localeCompare((expDate(a) || '') + (expTime(a) || '')));
    const total = exps.reduce((s, e) => s + expAmt(e), 0);
    const tripTotal = tripExps.reduce((s, e) => s + expAmt(e), 0);
    return (
      <div style={{ minHeight: '100%', background: p.paper, paddingTop: 56, paddingBottom: 60 }}>
        <OverlayHead onBack={onClose} label="Rubrik"/>
        <div style={{ padding: '8px 24px 0' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <CatMark cat={c} size={36}/>
            <div>
              <Eyebrow>Rubrik</Eyebrow>
              <div style={{ fontFamily: F, fontSize: 26, color: p.ink, fontWeight: 600, lineHeight: 1.1, letterSpacing: -0.5 }}>
                {c.label}
              </div>
            </div>
          </div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginTop: 14 }}>
            <div style={{ fontFamily: F, fontSize: 42, color: p.ink, fontWeight: 600, lineHeight: 1, letterSpacing: -1.5 }}>
              {total.toLocaleString('de-DE', { minimumFractionDigits: 2 })}<span style={{ color: p.muted, fontWeight: 400 }}> €</span>
            </div>
          </div>
          <div style={{ fontFamily: F, fontSize: 12, color: p.muted, marginTop: 6 }}>
            {exps.length} Einträge {exps.length > 0 && '· Ø ' + fmtEUR(total / exps.length)}
            {tripTotal > 0 && ' · ' + Math.round(total / tripTotal * 100) + '% der Reise'}
          </div>
        </div>
        <HRule label="Alle Einträge" />
        <div style={{ padding: '0 24px' }}>
          {exps.map(e => <ListRow key={e.id} e={e} onClick={() => openExpense(e.id)}/>)}
          {!exps.length && <EmptyState title="Keine Einträge" hint="In dieser Rubrik wurde noch nichts erfasst."/>}
        </div>
      </div>
    );
  }

  // ── Day detail ──────────────────────────────────────────────
  function DayDetail({ date, onClose, openExpense }) {
    const { activeTrip, expenses } = useData();
    const tripExps = activeTrip ? expenses.filter(e => e.trip_id === activeTrip.id) : expenses;
    const exps = tripExps.filter(e => expDate(e) === date)
      .sort((a, b) => (expTime(a) || '').localeCompare(expTime(b) || ''));
    const total = exps.reduce((s, e) => s + expAmt(e), 0);
    return (
      <div style={{ minHeight: '100%', background: p.paper, paddingTop: 56, paddingBottom: 60 }}>
        <OverlayHead onBack={onClose} label="Tag"/>
        <div style={{ padding: '8px 24px 0' }}>
          <Eyebrow>{fmtDateLong(date)}</Eyebrow>
          <div style={{ fontFamily: F, fontSize: 26, color: p.ink, fontWeight: 600, marginTop: 4, letterSpacing: -0.5 }}>
            Tag {tripDayNum(date)}
          </div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginTop: 14 }}>
            <div style={{ fontFamily: F, fontSize: 42, color: p.ink, fontWeight: 600, lineHeight: 1, letterSpacing: -1.5 }}>
              {total.toLocaleString('de-DE', { minimumFractionDigits: 2 })}<span style={{ color: p.muted, fontWeight: 400 }}> €</span>
            </div>
            <div style={{ fontFamily: F, fontSize: 13, color: p.muted }}>{exps.length} Einträge</div>
          </div>
        </div>
        <HRule label="Tagesablauf"/>
        <div style={{ padding: '0 24px' }}>
          {exps.map(e => <ListRow key={e.id} e={e} onClick={() => openExpense(e.id)}/>)}
          {!exps.length && <EmptyState title="Nichts an diesem Tag" hint="Über das + unten neuen Eintrag erfassen."/>}
        </div>
      </div>
    );
  }

  // ── Trip switcher ───────────────────────────────────────────
  function TripsView({ onClose }) {
    const data = useData();
    const trips = data.trips;
    const [showNewTrip, setShowNewTrip] = useState(false);
    const pick = (id) => { data.setActiveTrip(id); onClose(); };
    return (
      <div style={{ minHeight: '100%', background: p.paper, paddingTop: 56, paddingBottom: 80, fontFamily: F }}>
        <OverlayHead onBack={onClose} label="Reisen"/>
        <div style={{ padding: '8px 24px 0' }}>
          <Eyebrow>Reisearchiv</Eyebrow>
          <div style={{ fontFamily: F, fontSize: 26, color: p.ink, fontWeight: 600, marginTop: 4, letterSpacing: -0.5 }}>
            Meine Reisen
          </div>
        </div>
        <HRule/>
        <div style={{ padding: '0 24px' }}>
          {trips.map(t => (
            <button key={t.id} onClick={() => pick(t.id)} style={{
              width: '100%', border: 0, background: 'transparent', textAlign: 'left',
              padding: '18px 0', borderBottom: '1px solid ' + p.line, cursor: 'pointer',
            }}>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                <Eyebrow>{t.active ? 'Aktiv' : 'Archiv'}</Eyebrow>
                <span style={{ fontFamily: F, fontSize: 11, color: p.muted }}>{fmtDate(tripStart(t))} – {fmtDate(tripEnd(t))}</span>
              </div>
              <div style={{ fontFamily: F, fontSize: 22, color: p.ink, fontWeight: 600, marginTop: 4, letterSpacing: -0.3 }}>
                {tripFlag(t)} {t.name}
              </div>
              <div style={{ fontFamily: F, fontSize: 11, color: p.muted, marginTop: 4 }}>
                Budget {fmtEURshort(tripBudget(t))}
              </div>
            </button>
          ))}
          {!trips.length && <EmptyState title="Noch keine Reise" hint="Lege deine erste Reise mit dem Button unten an."/>}
          {showNewTrip ? (
            <NewTripForm
              onCancel={() => setShowNewTrip(false)}
              onSave={() => setShowNewTrip(false)}
            />
          ) : (
            <button onClick={() => setShowNewTrip(true)} style={{
              width: '100%', border: 0, background: 'transparent', padding: '18px 0',
              color: p.accent, fontFamily: F, fontSize: 15, fontWeight: 600, cursor: 'pointer', textAlign: 'left',
            }}>+ Neue Reise hinzufügen</button>
          )}
        </div>
      </div>
    );
  }

  // ── Trip switcher pill (bottom-left) ───────────────────────
  const TripPill = ({ onClick }) => {
    const { activeTrip } = useData();
    if (!activeTrip) return null;
    return (
      <button onClick={onClick} style={{
        position: 'absolute', bottom: 56, left: 22, zIndex: 30,
        background: p.paper, border: '1px solid ' + p.line2, borderRadius: 999,
        padding: '8px 14px', display: 'flex', alignItems: 'center', gap: 6,
        fontFamily: F, fontSize: 11, color: p.ink, fontWeight: 600, cursor: 'pointer',
        boxShadow: '0 4px 12px rgba(28,26,22,0.10)',
      }}>
        {tripFlag(activeTrip)} Reisen
      </button>
    );
  };

  // ── Login screen (initial gate) ────────────────────────────
  function LoginScreen() {
    const auth = useAuth();
    const [email, setEmail] = useState(auth.email || '');
    const [pw, setPw] = useState('');
    const submit = async () => {
      if (!email.trim() || !pw) return;
      await auth.login(email, pw);
    };

    return (
      <div style={{
        position: 'absolute', inset: 0, zIndex: 99,
        background: p.paper, color: p.ink, fontFamily: F,
        display: 'flex', flexDirection: 'column',
        paddingTop: 80, paddingBottom: 60,
      }}>
        <div style={{ padding: '0 32px', flex: 1, display: 'flex', flexDirection: 'column' }}>
          {/* Logo block */}
          <div style={{ textAlign: 'center', marginBottom: 36 }}>
            <div style={{
              width: 72, height: 72, borderRadius: 36, margin: '0 auto 14px',
              background: p.accent, color: p.paper,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              boxShadow: `0 8px 24px ${withAlpha(p.accent, 0.35)}`,
              fontFamily: 'Georgia, serif', fontSize: 38, fontStyle: 'italic', fontWeight: 600,
            }}>U</div>
            <Eyebrow style={{ fontSize: 9 }}>Reisetagebuch · Nr. 14</Eyebrow>
            <div style={{ fontFamily: F, fontSize: 28, fontWeight: 600, marginTop: 4, letterSpacing: -0.8, color: p.ink }}>
              Urlaubskasse
            </div>
            <div style={{ fontFamily: F, fontSize: 13, color: p.muted, marginTop: 6, lineHeight: 1.5, maxWidth: 280, margin: '6px auto 0' }}>
              Anmelden, um deine Reisedaten zu sichern und auf anderen Geräten weiterzumachen.
            </div>
          </div>

          {/* Form */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14, maxWidth: 320, margin: '0 auto', width: '100%' }}>
            <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
              <Eyebrow>E-Mail</Eyebrow>
              <input
                type="email" value={email} onChange={e => setEmail(e.target.value)}
                autoComplete="email"
                style={{
                  border: '1px solid ' + p.line2, background: p.paper2,
                  padding: '10px 12px', borderRadius: 6,
                  fontFamily: F, fontSize: 15, color: p.ink, outline: 'none',
                }}
              />
            </label>
            <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
              <Eyebrow>Passwort</Eyebrow>
              <input
                type="password" value={pw} onChange={e => setPw(e.target.value)}
                autoComplete="current-password"
                onKeyDown={e => { if (e.key === 'Enter') submit(); }}
                style={{
                  border: '1px solid ' + p.line2, background: p.paper2,
                  padding: '10px 12px', borderRadius: 6,
                  fontFamily: F, fontSize: 15, color: p.ink, outline: 'none',
                }}
              />
            </label>
            {auth.error && (
              <div style={{ color: p.rust, fontSize: 12, fontFamily: F, marginTop: -4 }}>
                {auth.error}
              </div>
            )}
            <div style={{
              fontFamily: F, fontSize: 11, color: p.muted, padding: '4px 0',
              display: 'flex', alignItems: 'center', gap: 6,
            }}>
              <Icon.cloud style={{ width: 12, height: 12, color: p.accent }}/>
              Verschlüsselt auf deinem Webspace
            </div>
            <button onClick={submit} disabled={auth.loading || !pw || !email.trim()} style={{
              border: 0, background: p.accent, color: p.paper,
              padding: '12px 0', borderRadius: 6, marginTop: 8,
              fontFamily: F, fontSize: 14, fontWeight: 600, cursor: 'pointer',
              opacity: (auth.loading || !pw || !email.trim()) ? 0.6 : 1,
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            }}>
              {auth.loading ? (
                <>
                  <Icon.sync style={{ animation: 'rtSpin 1s linear infinite' }}/>
                  Verbinde …
                </>
              ) : 'Anmelden'}
            </button>
          </div>
        </div>

        <div style={{ padding: '0 32px', textAlign: 'center', fontFamily: F, fontSize: 10, color: p.muted }}>
          v1.4.0
        </div>
      </div>
    );
  }
  // ── App root ────────────────────────────────────────────────
  function MinimalAppInner() {
    const { expenses } = useData();
    const [tab, setTab] = useState('heute');
    const [overlay, setOverlay] = useState(null);

    const nav = {
      openCat:     (catId) => setOverlay({ type: 'cat', catId }),
      openDay:     (date)  => setOverlay({ type: 'day', date }),
      openExpense: (id)    => setOverlay({ type: 'expense', id }),
      openAdd:     (prefill) => setOverlay({ type: 'add', prefill: prefill || null }),
      openEdit:    (id)    => setOverlay({ type: 'add', editId: id }),
    };

    const closeOverlay = () => setOverlay(null);
    const currentExpense = overlay && overlay.type === 'expense' && expenses.find(e => e.id === overlay.id);

    return (
      <NavContext.Provider value={nav}>
        <PhoneShell>
          <div style={{ background: p.paper, minHeight: '100%', paddingTop: 56, color: p.ink, fontFamily: F }}>
            <Nameplate tab={tab} setTab={setTab}
              onSettings={() => setOverlay({ type: 'settings' })}
              onSwitchTrip={() => setOverlay({ type: 'trips' })}/>
            {tab === 'heute'  && <MinHeute/>}
            {tab === 'woche'  && <MinWoche/>}
            {tab === 'reise'  && <MinReise/>}
            {tab === 'liste'  && <MinListe/>}
            {tab === 'rubrik' && <MinRubrik/>}
          </div>

          <FAB onClick={() => setOverlay({ type: 'add' })}/>
          <TripPill onClick={() => setOverlay({ type: 'trips' })}/>

          {overlay && overlay.type === 'add'      && <Overlay><AddScreen onClose={closeOverlay} prefill={overlay.prefill} expense={overlay.editId ? expenses.find(e => e.id === overlay.editId) : null}/></Overlay>}
          {overlay && overlay.type === 'settings' && <Overlay><SettingsScreen onClose={closeOverlay}/></Overlay>}
          {overlay && overlay.type === 'trips'    && <Overlay><TripsView onClose={closeOverlay}/></Overlay>}
          {overlay && overlay.type === 'cat'      && <Overlay><CatDetail catId={overlay.catId} onClose={closeOverlay} openExpense={nav.openExpense}/></Overlay>}
          {overlay && overlay.type === 'day'      && <Overlay><DayDetail date={overlay.date} onClose={closeOverlay} openExpense={nav.openExpense}/></Overlay>}
          {overlay && overlay.type === 'expense' && currentExpense && (
            <Overlay><ExpenseDetail expense={currentExpense} onClose={closeOverlay}/></Overlay>
          )}
        </PhoneShell>
      </NavContext.Provider>
    );
  }

  // ── Tweakable app shell (theme + login gate + tweaks panel) ──
  function TweakedApp() {
    const DEFAULTS = window.TWEAK_DEFAULTS || { palette: ['#2e5a3d', '#f7f3eb', '#1c1a16'], font: 'Poppins' };
    const [t, setTweak] = useTweaks(DEFAULTS);
    applyTheme(t.palette);
    const fontStack = t.font + ', -apple-system, system-ui, sans-serif';

    return (
      <AuthProvider>
        <AppShell t={t} setTweak={setTweak} fontStack={fontStack}/>
      </AuthProvider>
    );
  }

  function AppShell({ t, setTweak, fontStack }) {
    const auth = useAuth();
    const fontStyle = '.rt-app, .rt-app * { font-family: ' + fontStack + ' !important; }';

    return (
      <div className="rt-app" style={{ position: 'relative', display: 'inline-block' }}>
        <style>{fontStyle}</style>
        {auth.isAuthed
          ? <DataAndSyncProvider><MinimalAppInner/></DataAndSyncProvider>
          : (
            <PhoneShell>
              <LoginScreen/>
            </PhoneShell>
          )
        }

        <TweaksPanel>
          <TweakSection label="Farbpalette"/>
          <TweakColor
            label="Palette" value={t.palette}
            options={[
              ['#2e5a3d', '#f7f3eb', '#1c1a16'],
              ['#1f4068', '#f4f1e8', '#1a1a1a'],
              ['#8b3a3a', '#f5f0e8', '#1f1815'],
              ['#6b8e6f', '#f7f4ec', '#2c2a24'],
              ['#4a3520', '#f0ebe0', '#1c1612'],
              ['#3d5a80', '#eef2f5', '#0d1b2a'],
            ]}
            onChange={(v) => setTweak('palette', v)}
          />
          <TweakSection label="Schriftart"/>
          <TweakSelect
            label="Familie" value={t.font}
            options={['Poppins', 'Inter', 'IBM Plex Sans', 'Work Sans']}
            onChange={(v) => setTweak('font', v)}
          />
          <TweakSection label="Werkzeuge"/>
          {auth.isAuthed && (
            <TweakButton label="Logout (Token verwerfen)" onClick={auth.logout} secondary/>
          )}
        </TweaksPanel>
      </div>
    );
  }

  function MinimalApp() {
    return <TweakedApp/>;
  }

  window.MinimalApp = MinimalApp;
})();
