// ledger-shell.jsx — App shell: AuthScreen, Sidebar, TopBar, Drawer, Modal

const { useState, useEffect, useRef, useMemo } = React;

// ─────────── ICONS (inline SVG, currentColor) ───────────
const Icon = ({ name, size = 16, strokeWidth = 1.6, ...rest }) => {
  const paths = {
    list:    <><path d="M3 5h14M3 10h14M3 15h14" strokeLinecap="round" /></>,
    stats:   <><path d="M3 16V8M9 16V4M15 16v-6" strokeLinecap="round" /></>,
    budget:  <><circle cx="10" cy="10" r="6.5" /><path d="M10 3.5v6.5l4.5 2.5" strokeLinecap="round" /></>,
    repeat:  <><path d="M3 8l2-2h10l2 2M17 12l-2 2H5l-2-2" strokeLinecap="round" strokeLinejoin="round" /></>,
    fuel:    <><path d="M4 16V5a1 1 0 011-1h6a1 1 0 011 1v11M4 16h8M4 10h8M12 8l3 1v6a1.5 1.5 0 003 0v-8l-2-2" strokeLinecap="round" strokeLinejoin="round" /></>,
    search:  <><circle cx="9" cy="9" r="5" /><path d="M13 13l3 3" strokeLinecap="round" /></>,
    plus:    <><path d="M10 4v12M4 10h12" strokeLinecap="round" /></>,
    export:  <><path d="M10 3v9M6 9l4 4 4-4M3 16h14" strokeLinecap="round" strokeLinejoin="round" /></>,
    settings:<><circle cx="10" cy="10" r="2.5" /><path d="M10 2v2M10 16v2M2 10h2M16 10h2M4.5 4.5l1.4 1.4M14.1 14.1l1.4 1.4M4.5 15.5l1.4-1.4M14.1 5.9l1.4-1.4" strokeLinecap="round" /></>,
    edit:    <><path d="M3 17h4l9-9-4-4-9 9v4z" strokeLinejoin="round" /></>,
    trash:   <><path d="M4 6h12M8 6V4h4v2M6 6l1 10h6l1-10" strokeLinejoin="round" strokeLinecap="round" /></>,
    chev:    <><path d="M7 5l5 5-5 5" strokeLinecap="round" strokeLinejoin="round" /></>,
    chevDown:<><path d="M5 7l5 5 5-5" strokeLinecap="round" strokeLinejoin="round" /></>,
    close:   <><path d="M5 5l10 10M15 5L5 15" strokeLinecap="round" /></>,
    check:   <><path d="M4 10l4 4 8-8" strokeLinecap="round" strokeLinejoin="round" /></>,
    filter:  <><path d="M3 5h14L12 11v5l-4-2v-3L3 5z" strokeLinejoin="round" /></>,
    menu:    <><path d="M3 6h14M3 10h14M3 14h14" strokeLinecap="round" /></>,
    arrowDown:<><path d="M10 4v12M5 11l5 5 5-5" strokeLinecap="round" strokeLinejoin="round" /></>,
    arrowUp: <><path d="M10 16V4M5 9l5-5 5 5" strokeLinecap="round" strokeLinejoin="round" /></>,
    tag:     <><path d="M3 9V3h6l8 8-6 6-8-8z" strokeLinejoin="round" /><circle cx="6" cy="6" r="1" /></>,
    calendar:<><rect x="3" y="4" width="14" height="13" rx="1.5" /><path d="M3 8h14M7 2v3M13 2v3" strokeLinecap="round" /></>,
  };
  return (
    <svg width={size} height={size} viewBox="0 0 20 20" fill="none"
         stroke="currentColor" strokeWidth={strokeWidth} {...rest}>
      {paths[name]}
    </svg>
  );
};

// ─────────── AUTH SCREEN ───────────
function AuthScreen({ onSignIn }) {
  const existing = AUTH.getAccount();
  const [mode, setMode] = useState(existing ? 'signin' : 'signup');
  const [u, setU] = useState(existing?.username || '');
  const [p, setP] = useState('');
  const [p2, setP2] = useState('');
  const [error, setError] = useState(null);
  const [busy, setBusy] = useState(false);
  const [shake, setShake] = useState(false);

  const fail = (msg) => {
    setError(msg); setShake(true);
    setTimeout(() => setShake(false), 350);
  };

  const submit = async (e) => {
    e?.preventDefault();
    setError(null);
    if (!u.trim() || !p) return fail('Fill in both fields');
    setBusy(true);
    try {
      if (mode === 'signup') {
        if (p.length < 4) return fail('Password must be 4+ chars');
        if (p !== p2)     return fail("Passwords don't match");
        await AUTH.createAccount(u, p);
        onSignIn({ username: u.trim() });
      } else {
        const ok = await AUTH.verify(u, p);
        if (!ok) return fail('Wrong username or password');
        onSignIn({ username: u.trim() });
      }
    } catch (err) {
      fail(err.message || 'Something went wrong');
    } finally {
      setBusy(false);
    }
  };

  return (
    <div style={{
      minHeight: '100vh',
      display: 'grid', placeItems: 'center',
      background: 'var(--bg)', padding: 24,
      backgroundImage: 'radial-gradient(circle at 20% 10%, oklch(0.95 0.04 38 / .35), transparent 40%), radial-gradient(circle at 80% 80%, oklch(0.95 0.04 150 / .25), transparent 50%)',
    }}>
      <form onSubmit={submit} style={{
        width: 'min(380px, 100%)',
        background: 'var(--surface)',
        border: '1px solid var(--line)',
        borderRadius: 'var(--r-xl)',
        padding: '32px 28px',
        boxShadow: 'var(--shadow-md)',
        animation: shake ? 'shake .3s' : undefined,
      }}>
        <div style={{ textAlign: 'center', marginBottom: 22 }}>
          <div className="display" style={{ fontSize: 48, lineHeight: 1, color: 'var(--accent)' }}>£</div>
          <div className="display" style={{ fontSize: 26, marginTop: 4 }}>
            {mode === 'signup' ? 'Create your books' : 'Welcome back'}
          </div>
          <div style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 4 }}>
            {mode === 'signup'
              ? 'Pick a username and a password.'
              : `Sign in to ${existing?.username ? `@${existing.username}` : 'your account'}.`}
          </div>
        </div>

        <label className="micro" style={{ display: 'block', marginBottom: 4 }}>Username</label>
        <div className="field field-lg" style={{ marginBottom: 14 }}>
          <input value={u} onChange={e => setU(e.target.value)} autoComplete="username"
                 placeholder="e.g. danny" autoFocus={!existing} disabled={busy} />
        </div>
        <label className="micro" style={{ display: 'block', marginBottom: 4 }}>Password</label>
        <div className="field field-lg" style={{ marginBottom: mode === 'signup' ? 14 : 18 }}>
          <input type="password" value={p} onChange={e => setP(e.target.value)}
                 autoComplete={mode === 'signup' ? 'new-password' : 'current-password'}
                 placeholder={mode === 'signup' ? 'at least 4 characters' : '••••••••'}
                 autoFocus={!!existing} disabled={busy} />
        </div>
        {mode === 'signup' && (
          <>
            <label className="micro" style={{ display: 'block', marginBottom: 4 }}>Confirm password</label>
            <div className="field field-lg" style={{ marginBottom: 18 }}>
              <input type="password" value={p2} onChange={e => setP2(e.target.value)}
                     autoComplete="new-password" placeholder="repeat password" disabled={busy} />
            </div>
          </>
        )}

        {error && (
          <div style={{
            padding: '8px 12px', marginBottom: 12,
            background: 'oklch(0.95 0.04 28)', color: 'var(--neg)',
            borderRadius: 'var(--r-sm)', fontSize: 12.5,
          }}>{error}</div>
        )}

        <button type="submit" disabled={busy} className="btn solid"
                style={{ width: '100%', padding: '10px', justifyContent: 'center', fontSize: 14 }}>
          {busy ? 'Working…' : (mode === 'signup' ? 'Create account' : 'Sign in')}
        </button>

        <div style={{ marginTop: 18, fontSize: 12.5, color: 'var(--ink-3)', textAlign: 'center' }}>
          {mode === 'signup' ? (
            existing ? (
              <>Already have an account? <button type="button" onClick={() => { setMode('signin'); setError(null); setU(existing.username); setP(''); setP2(''); }} style={{ color: 'var(--accent)', textDecoration: 'underline' }}>Sign in</button></>
            ) : (
              <>This creates a local account on this device.</>
            )
          ) : (
            <>Forgot password? <button type="button" onClick={() => {
              if (confirm('Reset your account? All saved data on this device will be deleted.')) {
                STORE.clearAll();
                setMode('signup'); setU(''); setP(''); setP2(''); setError(null);
              }
            }} style={{ color: 'var(--accent)', textDecoration: 'underline' }}>Reset account</button></>
          )}
        </div>

        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 16, fontSize: 11.5, color: 'var(--ink-3)', borderTop: '1px solid var(--line)', paddingTop: 14 }}>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
            <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--pos)' }}></span>
            saved locally
          </span>
          <span className="mono">v0.2</span>
        </div>
      </form>
      <style>{`@keyframes shake { 0%,100%{transform:none} 25%{transform:translateX(-6px)} 75%{transform:translateX(6px)} }`}</style>
    </div>
  );
}

// ─────────── SIDEBAR ───────────
function Sidebar({ activeView, setView, month, setMonth, categoryFilter, setCategoryFilter, txs, categories, user, onSignOut, onClearData, onResetDemo, onAccount, onExport, onAddCategory, onEditCategory, recurringCount, storageMode, cloudSync }) {
  const byCat = useMemo(() => {
    const m = {};
    txs.forEach(t => { if (monthOf(t.date) === month && t.type === 'out') m[t.category] = (m[t.category]||0) + 1; });
    return m;
  }, [txs, month]);

  const totalCount = txs.filter(t => monthOf(t.date) === month).length;
  const [menuOpen, setMenuOpen] = useState(false);
  const menuAnchor = useRef(null);

  const NavItem = ({ id, icon, label, count }) => (
    <button onClick={() => setView(id)} style={{
      display: 'flex', alignItems: 'center', gap: 10,
      width: '100%', padding: '6px 8px', borderRadius: 'var(--r-sm)',
      background: activeView === id ? 'var(--surface-3)' : 'transparent',
      color: activeView === id ? 'var(--ink)' : 'var(--ink-2)',
      fontSize: 13.5, fontWeight: activeView === id ? 500 : 400,
    }}>
      <Icon name={icon} size={15} />
      <span>{label}</span>
      {count != null && <span className="mono tnum" style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--ink-3)' }}>{count}</span>}
    </button>
  );

  const monthLabel = new Date(month + '-01').toLocaleDateString('en-GB', { month: 'long', year: 'numeric' });
  const stepMonth = (delta) => {
    const [y, m] = month.split('-').map(Number);
    const d = new Date(y, m - 1 + delta, 1);
    setMonth(`${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}`);
  };

  return (
    <aside style={{
      width: 240, flexShrink: 0,
      background: 'var(--surface)', borderRight: '1px solid var(--line)',
      display: 'flex', flexDirection: 'column',
      height: '100%',
    }}>
      {/* brand */}
      <div style={{ padding: '14px 16px 12px', display: 'flex', alignItems: 'center', gap: 10 }}>
        <div style={{
          width: 28, height: 28, borderRadius: 7,
          background: 'var(--accent)', color: 'white',
          display: 'grid', placeItems: 'center',
          fontFamily: 'var(--font-display)', fontSize: 20, lineHeight: 1,
        }}>£</div>
        <div style={{ display: 'flex', flexDirection: 'column', lineHeight: 1.1 }}>
          <span style={{ fontSize: 14, fontWeight: 600 }}>Ledger</span>
          <span style={{ fontSize: 11, color: 'var(--ink-3)' }}>{user?.username || 'demo'}'s books</span>
        </div>
      </div>

      {/* month switcher */}
      <div style={{ padding: '4px 12px 12px' }}>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 4,
          background: 'var(--surface-2)', borderRadius: 'var(--r-sm)',
          padding: '4px',
        }}>
          <button className="btn ghost" style={{ padding: 4 }} onClick={() => stepMonth(-1)}>
            <Icon name="chev" size={14} style={{ transform: 'rotate(180deg)' }} />
          </button>
          <div style={{ flex: 1, textAlign: 'center', fontSize: 13, fontWeight: 500 }}>{monthLabel}</div>
          <button className="btn ghost" style={{ padding: 4 }} onClick={() => stepMonth(1)}>
            <Icon name="chev" size={14} />
          </button>
        </div>
      </div>

      {/* nav */}
      <nav style={{ padding: '0 12px', display: 'flex', flexDirection: 'column', gap: 1 }}>
        <NavItem id="transactions" icon="list"   label="Transactions" count={totalCount} />
        <NavItem id="stats"        icon="stats"  label="Stats" />
        <NavItem id="budgets"      icon="budget" label="Budgets" />
        <NavItem id="recurring"    icon="repeat" label="Recurring" count={recurringCount} />
        <NavItem id="fuel"         icon="fuel"   label="Fuel log" />
      </nav>

      {/* categories */}
      <div style={{ flex: 1, overflow: 'auto', padding: '16px 12px 8px' }}>
        <div className="micro" style={{ padding: '0 8px 4px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span>Categories</span>
          <button className="btn ghost" style={{ padding: 2, color: 'var(--ink-3)' }}
                  onClick={onAddCategory} title="New category">
            <Icon name="plus" size={12} />
          </button>
        </div>
        <button onClick={() => setCategoryFilter(null)} style={catRowStyle(categoryFilter == null)}>
          <span className="cdot" style={{ background: 'var(--ink-3)' }}></span>
          <span>All categories</span>
          <span className="mono tnum" style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--ink-3)' }}>{totalCount}</span>
        </button>
        {categories.filter(c => c.kind === 'out').map(c => (
          <SidebarCatRow key={c.id} cat={c} active={categoryFilter === c.id} count={byCat[c.id]}
                         onClick={() => setCategoryFilter(c.id)} onEdit={() => onEditCategory(c)} />
        ))}
        <div className="micro" style={{ padding: '14px 8px 4px' }}>Income</div>
        {categories.filter(c => c.kind === 'in').map(c => (
          <SidebarCatRow key={c.id} cat={c} active={categoryFilter === c.id}
                         onClick={() => setCategoryFilter(c.id)} onEdit={() => onEditCategory(c)} />
        ))}
      </div>

      {/* footer */}
      <div ref={menuAnchor} style={{ position: 'relative', borderTop: '1px solid var(--line)', padding: '10px 12px', fontSize: 12, color: 'var(--ink-3)', display: 'flex', alignItems: 'center', gap: 8 }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '3px 8px', fontSize: 11 }} title="Data is stored on this device. Cloud sync coming when deployed to Cloudflare.">
          <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--pos)' }}></span>
          saved locally
        </span>
        <span style={{ marginLeft: 'auto' }} className="mono">v0.1</span>
        <button className="btn ghost" style={{ padding: 4 }} onClick={() => setMenuOpen(v => !v)} title="Settings">
          <Icon name="settings" size={13} />
        </button>
        {menuOpen && (
          <SettingsMenu
            anchorRef={menuAnchor}
            user={user}
            onAccount={() => { setMenuOpen(false); onAccount(); }}
            onExport={() => { onExport(); setMenuOpen(false); }}
            onClearData={() => { setMenuOpen(false); onClearData(); }}
            onResetDemo={() => { setMenuOpen(false); onResetDemo(); }}
            onSignOut={() => { setMenuOpen(false); onSignOut(); }}
            onClose={() => setMenuOpen(false)}
          />
        )}
      </div>
    </aside>
  );
}

function StorageIndicator({ mode, sync }) {
  const isCloud = mode === 'cloud';
  let dot = 'var(--pos)';
  let label = isCloud ? 'synced to cloud' : 'saved locally';
  let title = isCloud
    ? 'Signed in to the Cloudflare backend — changes are saved to the server.'
    : 'Data lives on this device only. Deploy the cloud/ folder to enable sync.';

  if (isCloud && sync === 'saving')  { dot = 'var(--warn)';   label = 'saving…';   }
  if (isCloud && sync === 'loading') { dot = 'var(--warn)';   label = 'loading…';  }
  if (isCloud && sync === 'error')   { dot = 'var(--neg)';    label = 'sync error';
    title = 'Could not reach the cloud — local copy is up to date.'; }

  return (
    <span title={title} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '3px 8px', fontSize: 11 }}>
      <span style={{
        width: 6, height: 6, borderRadius: '50%', background: dot,
        animation: (sync === 'saving' || sync === 'loading') ? 'pulse 1.2s ease-in-out infinite' : 'none',
      }}></span>
      {label}
    </span>
  );
}

function SidebarCatRow({ cat, active, count, onClick, onEdit }) {
  const [hover, setHover] = useState(false);
  return (
    <div
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{ position: 'relative' }}
    >
      <button onClick={onClick} style={catRowStyle(active)}>
        <span className="cdot" style={{ background: cat.color }}></span>
        <span style={{ flex: 1, textAlign: 'left', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{cat.name}</span>
        {count != null && !hover && (
          <span className="mono tnum" style={{ fontSize: 11, color: active ? 'var(--accent-ink)' : 'var(--ink-3)' }}>{count}</span>
        )}
      </button>
      {hover && (
        <button onClick={(e) => { e.stopPropagation(); onEdit(); }}
          style={{
            position: 'absolute', right: 6, top: '50%', transform: 'translateY(-50%)',
            width: 22, height: 22, borderRadius: 4,
            background: 'var(--surface)', border: '1px solid var(--line-2)',
            display: 'grid', placeItems: 'center',
            color: 'var(--ink-3)', cursor: 'pointer',
          }}
          title="Edit category"
        >
          <Icon name="edit" size={11} />
        </button>
      )}
    </div>
  );
}

function catRowStyle(active) {
  return {
    display: 'flex', alignItems: 'center', gap: 8,
    width: '100%', padding: '5px 8px', borderRadius: 'var(--r-sm)',
    background: active ? 'var(--accent-soft)' : 'transparent',
    color: active ? 'var(--accent-ink)' : 'var(--ink-2)',
    fontWeight: active ? 500 : 400,
    fontSize: 13,
    transition: 'background .08s, color .08s',
    textAlign: 'left',
  };
}

// ─────────── EDIT DRAWER ───────────
function EditDrawer({ tx, categories, onClose, onSave, onDelete }) {
  const [draft, setDraft] = useState(tx);
  useEffect(() => setDraft(tx), [tx?.id]);

  if (!tx) return null;
  const isFuel = draft?.category === 'fuel';
  const CAT_MAP = window.CAT_MAP;
  const cat = CAT_MAP[draft?.category];
  const cats = categories || window.CATEGORIES;

  const upd = (patch) => setDraft(d => ({ ...d, ...patch }));

  return (
    <>
      <div onClick={onClose} style={{
        position: 'fixed', inset: 0, background: 'rgba(40,30,20,.25)',
        backdropFilter: 'blur(2px)', zIndex: 50, animation: 'fadeIn .15s',
      }} />
      <div style={{
        position: 'fixed', top: 0, right: 0, bottom: 0,
        width: 'min(440px, 100vw)',
        background: 'var(--bg)', borderLeft: '1px solid var(--line)',
        boxShadow: 'var(--shadow-lg)', zIndex: 51,
        display: 'flex', flexDirection: 'column',
        animation: 'slideInRight .22s cubic-bezier(.2,.7,.3,1)',
      }}>
        <div style={{ padding: '16px 20px', borderBottom: '1px solid var(--line)', display: 'flex', alignItems: 'center', gap: 10 }}>
          <span className="cglyph cglyph-lg" style={{ background: cat?.color, color: 'white' }}>{cat?.icon}</span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="micro">{tx.id ? 'Edit transaction' : 'New transaction'}</div>
            <div style={{ fontSize: 16, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{draft.desc || 'Untitled'}</div>
          </div>
          <button className="btn ghost icon" onClick={onClose}><Icon name="close" size={16} /></button>
        </div>

        <div style={{ padding: '16px 20px', display: 'flex', flexDirection: 'column', gap: 14, overflow: 'auto', flex: 1 }}>
          {/* type segmented */}
          <div>
            <div className="micro" style={{ marginBottom: 6 }}>Type</div>
            <div style={{ display: 'flex', background: 'var(--surface-2)', borderRadius: 8, padding: 3, gap: 2 }}>
              {[['out','Expense'],['in','Income'],['xfer','Transfer']].map(([v,l]) => (
                <button key={v} onClick={() => upd({ type: v })} style={{
                  flex: 1, padding: '6px', borderRadius: 6,
                  background: draft.type === v ? 'var(--surface)' : 'transparent',
                  boxShadow: draft.type === v ? 'var(--shadow-sm)' : 'none',
                  fontSize: 13, fontWeight: 500,
                  color: draft.type === v ? 'var(--ink)' : 'var(--ink-2)',
                }}>{l}</button>
              ))}
            </div>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
            <div>
              <div className="micro" style={{ marginBottom: 6 }}>Amount</div>
              <div className="field field-lg">
                <span style={{ color: 'var(--ink-3)', marginRight: 4 }}>£</span>
                <input
                  type="number" step="0.01"
                  value={draft.amount ?? ''}
                  onChange={e => upd({ amount: parseFloat(e.target.value) || 0 })}
                  className="tnum"
                />
              </div>
            </div>
            <div>
              <div className="micro" style={{ marginBottom: 6 }}>Date</div>
              <div className="field field-lg">
                <input type="date" value={draft.date} onChange={e => upd({ date: e.target.value })} />
              </div>
            </div>
          </div>

          <div>
            <div className="micro" style={{ marginBottom: 6 }}>Category</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
              {cats.filter(c => c.kind === (draft.type === 'in' ? 'in' : 'out')).map(c => (
                <button key={c.id} onClick={() => upd({ category: c.id })} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 6,
                  padding: '5px 10px', borderRadius: 999,
                  border: draft.category === c.id ? `1px solid ${c.color}` : '1px solid var(--line-2)',
                  background: draft.category === c.id ? 'var(--surface)' : 'var(--surface)',
                  fontSize: 12.5,
                  boxShadow: draft.category === c.id ? `inset 0 0 0 1px ${c.color}` : 'none',
                }}>
                  <span style={{ fontSize: 14 }}>{c.icon}</span>
                  {c.name}
                </button>
              ))}
            </div>
          </div>

          <div>
            <div className="micro" style={{ marginBottom: 6 }}>Description</div>
            <div className="field field-lg">
              <input value={draft.desc || ''} onChange={e => upd({ desc: e.target.value })} placeholder="What was it?" />
            </div>
          </div>

          <div>
            <div className="micro" style={{ marginBottom: 6 }}>Tags</div>
            <div className="field" style={{ height: 'auto', minHeight: 38, padding: '6px 10px', flexWrap: 'wrap', gap: 4 }}>
              {(draft.tags || []).map((t, i) => (
                <span key={t} className="tag" style={{ background: 'var(--accent-soft)', color: 'var(--accent-ink)' }}>
                  {t}
                  <button onClick={() => upd({ tags: draft.tags.filter((_,j) => j !== i) })} style={{ marginLeft: 4, color: 'var(--accent-ink)', opacity: .7 }}>×</button>
                </span>
              ))}
              <input
                placeholder="add tag…"
                onKeyDown={e => {
                  if (e.key === 'Enter' && e.target.value.trim()) {
                    upd({ tags: [...(draft.tags || []), e.target.value.trim()] });
                    e.target.value = '';
                  }
                }}
                style={{ width: 80, fontSize: 12.5 }}
              />
            </div>
          </div>

          {isFuel && <FuelFieldset draft={draft} upd={upd} />}

          <div>
            <div className="micro" style={{ marginBottom: 6 }}>Recurring</div>
            <div style={{ display: 'flex', gap: 4 }}>
              {[['off','Off'],['weekly','Weekly'],['monthly','Monthly'],['yearly','Yearly']].map(([v,l]) => (
                <button key={v} onClick={() => upd({ recurring: v === 'off' ? false : v })}
                  className={`chip ${(draft.recurring ? (draft.recurring === v) : v === 'off') ? 'on' : ''}`}>
                  {l}
                </button>
              ))}
            </div>
          </div>
        </div>

        <div style={{
          padding: '12px 20px', borderTop: '1px solid var(--line)',
          display: 'flex', gap: 8, background: 'var(--surface)',
        }}>
          {tx.id && (
            <button className="btn ghost" onClick={() => onDelete(tx.id)} style={{ color: 'var(--neg)' }}>
              <Icon name="trash" size={14} /> Delete
            </button>
          )}
          <div style={{ flex: 1 }} />
          <button className="btn" onClick={onClose}>Cancel</button>
          <button className="btn accent" onClick={() => onSave(draft)}>Save changes</button>
        </div>
      </div>
    </>
  );
}

function FuelFieldset({ draft, upd }) {
  // Find previous fill-up for default odometer hint + trip↔odo conversion
  const prev = SAMPLE_TX
    .filter(t => t.category === 'fuel' && t.fuel?.odo && t.id !== draft.id && t.date < (draft.date || '9999'))
    .sort((a, b) => b.date.localeCompare(a.date))[0];
  const prevOdo = prev?.fuel?.odo;

  const [mode, setMode] = useState(draft.fuel?.odo ? 'odo' : 'trip');

  const litres = draft.fuel?.litres ?? '';
  const odo = draft.fuel?.odo ?? '';
  const trip = (odo && prevOdo) ? Math.max(0, odo - prevOdo) : (draft.fuel?.trip ?? '');

  const setLitres = (v) => upd({ fuel: { ...(draft.fuel || {}), litres: parseFloat(v) || 0 } });
  const setOdo = (v) => {
    const n = parseFloat(v) || 0;
    upd({ fuel: { ...(draft.fuel || {}), odo: n } });
  };
  const setTrip = (v) => {
    const n = parseFloat(v) || 0;
    // Derive odo from previous + trip when we know previous
    const newOdo = prevOdo ? prevOdo + n : undefined;
    upd({ fuel: { ...(draft.fuel || {}), trip: n, odo: newOdo } });
  };

  return (
    <div style={{
      padding: '14px 16px', background: 'var(--accent-soft)',
      borderRadius: 'var(--r-md)', border: '1px solid oklch(0.88 0.05 38)',
      display: 'flex', flexDirection: 'column', gap: 12,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div className="micro" style={{ color: 'var(--accent-ink)' }}>⛽ Fuel-up details</div>
        <div style={{ display: 'flex', background: 'var(--surface)', borderRadius: 6, padding: 2, gap: 2 }}>
          {[['odo', 'Odometer'], ['trip', 'Trip']].map(([v, l]) => (
            <button key={v} type="button" onClick={() => setMode(v)} style={{
              padding: '3px 10px', borderRadius: 4, fontSize: 11.5, fontWeight: 500,
              background: mode === v ? 'var(--accent)' : 'transparent',
              color: mode === v ? 'white' : 'var(--ink-3)',
              transition: 'background .12s, color .12s',
            }}>{l}</button>
          ))}
        </div>
      </div>

      {/* Litres — full width */}
      <FuelField label="Litres" unit="L" value={litres} step="0.1" type="number"
                 onChange={setLitres} placeholder="38.2" />

      {/* Odo or Trip */}
      {mode === 'odo' ? (
        <FuelField label="Odometer" unit="mi" value={odo} type="number"
                   onChange={setOdo}
                   placeholder={prevOdo ? String(prevOdo + 300) : 'e.g. 42318'}
                   hint={prevOdo ? `last fill-up: ${prevOdo.toLocaleString()} mi` : 'no previous fill-up yet'} />
      ) : (
        <FuelField label="Trip since last fill-up" unit="mi" value={trip} type="number"
                   onChange={setTrip}
                   placeholder="312"
                   hint={prevOdo ? `→ odometer will be ${(prevOdo + (parseFloat(trip) || 0)).toLocaleString()} mi` : 'first fill-up — enter odometer next time'} />
      )}

      <FuelCalc tx={draft} />
    </div>
  );
}

function FuelField({ label, unit, value, onChange, type = 'text', step, placeholder, hint }) {
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4, gap: 8 }}>
        <span style={{ fontSize: 11, color: 'var(--ink-3)', fontWeight: 500, flexShrink: 0 }}>{label}</span>
        {hint && <span style={{ fontSize: 10.5, color: 'var(--ink-3)', textAlign: 'right', minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{hint}</span>}
      </div>
      <div className="field" style={{ background: 'var(--surface)', height: 36 }}>
        <input
          type={type} step={step}
          value={value}
          placeholder={placeholder}
          onChange={e => onChange(e.target.value)}
          className="tnum"
          style={{ flex: 1, minWidth: 0, fontSize: 15 }}
        />
        <span style={{ color: 'var(--ink-3)', fontSize: 13, marginLeft: 6, flexShrink: 0 }}>{unit}</span>
      </div>
    </div>
  );
}

function FuelCalc({ tx }) {
  const prev = SAMPLE_TX
    .filter(t => t.category === 'fuel' && t.fuel?.odo && t.id !== tx.id && t.date < tx.date)
    .sort((a,b) => b.date.localeCompare(a.date))[0];
  if (!prev || !tx.fuel?.odo || !tx.fuel?.litres) {
    return <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>Enter litres and odometer (or trip) to see mi/L.</div>;
  }
  const miles = tx.fuel.odo - prev.fuel.odo;
  const mpl = miles / tx.fuel.litres;
  const mpg = mpl * 4.546; // UK gallon
  return (
    <div style={{ display: 'flex', gap: 16, alignItems: 'baseline', paddingTop: 4, borderTop: '1px dashed oklch(0.88 0.05 38)' }}>
      <div>
        <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>Trip</div>
        <div className="tnum" style={{ fontSize: 16 }}>{miles} mi</div>
      </div>
      <div>
        <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>Efficiency</div>
        <div className="display tnum" style={{ fontSize: 22, color: 'var(--accent-ink)' }}>{mpl.toFixed(2)} <span style={{ fontSize: 13, color: 'var(--ink-3)' }}>mi/L</span></div>
      </div>
      <div>
        <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>UK MPG</div>
        <div className="tnum" style={{ fontSize: 16 }}>{mpg.toFixed(1)}</div>
      </div>
    </div>
  );
}

Object.assign(window, { Icon, AuthScreen, Sidebar, EditDrawer, FuelCalc, StorageIndicator });
