BudgetBuddy / frontend /index.html
KrishnaGarg's picture
Deploy BudgetBuddy update
385ae59 verified
Raw
History Blame Contribute Delete
26.9 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<title>BudgetBuddy</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<style>
:root{
--bg:#0a0c11; --surface:#15181f; --surface2:#1c2029; --surface3:#242936; --line:#2a2f3b;
--ink:#f0f3f8; --muted:#8b94a6; --faint:#5e6678;
--lime:#d7f25a; --lime-ink:#161f08; --lav:#bca8f9; --lav-ink:#1c1430;
--good:#74dca6; --bad:#f08aa6; --warn:#f5cd76; --r:20px;
--sh:0 1px 0 rgba(255,255,255,.03), 0 6px 22px rgba(0,0,0,.30);
}
*{box-sizing:border-box} html,body{margin:0;height:100%}
body{background:var(--bg);color:var(--ink);font-family:Inter,system-ui,sans-serif;-webkit-font-smoothing:antialiased;font-size:14px;line-height:1.5}
button{font-family:inherit;cursor:pointer;border:0;color:inherit} input,select,textarea{font-family:inherit}
.hidden{display:none !important}
.vh{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
.muted{color:var(--muted)} .good{color:var(--good)} .bad{color:var(--bad)} .warn{color:var(--warn)}
.up{color:var(--good);font-weight:700} .down{color:var(--bad);font-weight:700}
::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:#2d3340;border-radius:6px}
svg{stroke-width:1.9;fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round}
input,select,textarea{width:100%;background:var(--surface2);border:1px solid var(--line);color:var(--ink);border-radius:12px;padding:11px 13px;font-size:.9rem;outline:none;transition:border-color .15s}
input:focus,select:focus,textarea:focus{border-color:var(--lav)}
select{-webkit-appearance:none;appearance:none;cursor:pointer;padding-right:34px;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a7a3c4' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");background-repeat:no-repeat;background-position:right 11px center;background-size:16px}
select:hover{border-color:var(--lav)}
select option{background:var(--surface);color:var(--ink)}
select option:disabled{color:var(--muted)}
input[type=date]{cursor:pointer}
input[type=date]::-webkit-calendar-picker-indicator{filter:invert(.65);cursor:pointer;opacity:.8}
input[type=date]::-webkit-calendar-picker-indicator:hover{opacity:1}
input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}
input[type=number]{-moz-appearance:textfield;appearance:textfield}
.empty-chart{height:230px;display:flex;align-items:center;justify-content:center;color:var(--faint);font-size:.86rem;border:1px dashed var(--line);border-radius:14px}
label{display:block;font-size:.76rem;color:var(--muted);margin-bottom:6px;font-weight:600}
.field{margin:13px 0} .row{display:flex;gap:11px}.row>*{flex:1} .msg{margin-top:11px;font-size:.84rem;min-height:1em}
.btn{background:var(--lime);color:var(--lime-ink);font-weight:800;border-radius:13px;padding:11px 17px;font-size:.88rem;transition:filter .12s,transform .05s}
.btn:hover{filter:brightness(1.05)} .btn:active{transform:translateY(1px)} .btn:disabled{opacity:.4;cursor:not-allowed}
.btn.alt{background:var(--surface3);color:var(--ink);border:1px solid var(--line)}
.btn.lav{background:var(--lav);color:var(--lav-ink)} .btn.sm{padding:8px 13px;font-size:.8rem;border-radius:11px}
.logo{display:flex;align-items:center;gap:11px;font-weight:850;font-size:1.3rem;letter-spacing:-.02em}
.logo .dot{width:32px;height:32px;border-radius:10px;background:var(--lime);display:grid;place-items:center;color:var(--lime-ink)}
/* login */
#login{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;background:radial-gradient(1000px 560px at 72% -12%,#1e2a12 0%,var(--bg) 58%)}
.login-card{width:100%;max-width:380px;background:var(--surface);border:1px solid var(--line);border-radius:26px;padding:32px;box-shadow:var(--sh)}
/* shell */
#app{display:flex;min-height:100vh}
.sidebar{width:236px;flex:0 0 236px;background:var(--surface);border-right:1px solid var(--line);padding:22px 16px;display:flex;flex-direction:column;gap:5px;position:sticky;top:0;height:100vh}
.side-logo{margin:2px 6px 20px}
.nav-item{display:flex;align-items:center;gap:13px;padding:12px 14px;border-radius:14px;color:var(--muted);font-weight:650;background:transparent;width:100%;text-align:left;font-size:.9rem;transition:.12s}
.nav-item svg{width:19px;height:19px;flex:0 0 19px}
.nav-item:hover{background:var(--surface2);color:var(--ink)}
.nav-item.active{background:var(--lime);color:var(--lime-ink);box-shadow:0 4px 16px rgba(215,242,90,.18)}
.side-foot{margin-top:auto;border-top:1px solid var(--line);padding-top:14px}
.side-user{display:flex;align-items:center;gap:11px;padding:6px}
.avatar{width:34px;height:34px;border-radius:50%;background:var(--lav);color:var(--lav-ink);display:grid;place-items:center;font-weight:800}
.main{flex:1;min-width:0;padding:26px 32px 70px}
.topbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:22px;gap:16px;flex-wrap:wrap}
.title{font-size:1.55rem;font-weight:850;letter-spacing:-.025em} .sub{color:var(--muted);font-size:.85rem;margin-top:2px}
.controls{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.controls select{width:auto;min-width:150px;padding:9px 34px 9px 14px;border-radius:12px;font-weight:600;background-color:var(--surface);font-size:.84rem}
.seg{display:flex;gap:4px;background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:4px}
.seg button{background:transparent;color:var(--muted);padding:7px 13px;border-radius:9px;font-weight:650;font-size:.8rem}
.seg button.active{background:var(--surface3);color:var(--ink)}
/* cards */
.cards{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:18px}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:18px 20px;box-shadow:var(--sh)}
.card .lbl{color:var(--muted);font-size:.8rem;font-weight:600;display:flex;align-items:center;gap:8px}
.card .ic{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;background:var(--surface3)}
.card .ic svg{width:16px;height:16px} .card .val{font-size:1.7rem;font-weight:850;margin-top:10px;letter-spacing:-.02em}
.card .delta{font-size:.8rem;margin-top:4px}
.grid2{display:grid;grid-template-columns:.95fr 1.4fr;gap:16px;margin-bottom:18px}
.grid2b{display:grid;grid-template-columns:1.4fr 1fr;gap:16px;margin-bottom:18px}
.panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:20px;box-shadow:var(--sh)}
.panel h3{margin:0;font-size:1rem;font-weight:750} .panel .ph-sub{color:var(--muted);font-size:.8rem;margin:2px 0 14px}
.chart-box{position:relative;height:230px}
.ring-wrap{display:flex;align-items:center;gap:20px}
.ring{position:relative;width:160px;height:160px;flex:0 0 160px}
.ring .rc{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:0 14px}
.rc .big{font-size:1.28rem;font-weight:850;letter-spacing:-.02em;line-height:1.1;max-width:100%} .rc .sm{color:var(--muted);font-size:.71rem;margin-top:2px}
/* pills + comparison */
.pill{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:999px;font-size:.73rem;font-weight:700}
.dotc{width:8px;height:8px;border-radius:50%;display:inline-block;flex:0 0 8px}
.cmp{display:flex;flex-direction:column;gap:13px}
.cmp-row{display:grid;grid-template-columns:108px 1fr 86px;gap:12px;align-items:center;font-size:.83rem}
.bars{display:flex;flex-direction:column;gap:5px}
.bar{height:9px;border-radius:6px;background:var(--surface3);overflow:hidden}.bar>i{display:block;height:100%;border-radius:6px}
.bar.t>i{background:var(--lime)} .bar.l>i{background:var(--lav)}
.legend{display:flex;gap:14px;font-size:.74rem;color:var(--muted);margin-top:13px}
.legend span{display:inline-flex;align-items:center;gap:6px}.legend i{width:9px;height:9px;border-radius:3px;display:inline-block}
/* tables */
table{width:100%;border-collapse:collapse;font-size:.86rem}
th{text-align:left;color:var(--muted);font-weight:600;padding:9px 10px;border-bottom:1px solid var(--line);font-size:.76rem}
td{padding:9px 10px;border-bottom:1px solid #1a1e27;vertical-align:middle} tr:last-child td{border-bottom:0}
td input,td select{padding:8px 9px;border-radius:9px}
.col-qty{width:64px} .col-amt{width:104px} .col-cat{width:140px} .col-x{width:38px}
.iconbtn{background:var(--surface3);color:var(--muted);width:30px;height:30px;border-radius:9px;display:grid;place-items:center}
.iconbtn:hover{color:var(--ink)} .iconbtn svg{width:15px;height:15px}
/* add */
.modes{display:flex;gap:9px;margin-bottom:18px;flex-wrap:wrap}
.mode{background:var(--surface);border:1px solid var(--line);color:var(--muted);padding:11px 17px;border-radius:14px;font-weight:650;font-size:.86rem;display:flex;gap:9px;align-items:center}
.mode svg{width:17px;height:17px} .mode.active{background:var(--lime);color:var(--lime-ink);border-color:var(--lime)}
.drop{border:1.5px dashed var(--line);border-radius:15px;padding:18px;text-align:center;color:var(--muted);font-size:.85rem;display:block;cursor:pointer}
.drop:hover{border-color:var(--lav);color:var(--ink)} .drop img{max-height:280px;max-width:100%;border-radius:12px;margin-top:10px}
.cap-row{display:flex;gap:9px;margin-top:10px}
.upload-row{display:flex;gap:14px;align-items:stretch}
.upload-actions{display:flex;flex-direction:column;gap:9px;justify-content:center;min-width:160px}
@media(max-width:720px){.upload-row{flex-direction:column}.upload-actions{min-width:0}}
.banner{border-radius:12px;padding:11px 14px;font-size:.84rem;margin:12px 0;border:1px solid transparent}
.banner.ok{background:#10271d;color:var(--good);border-color:#1d3a2c} .banner.warn{background:#2c2611;color:var(--warn);border-color:#3c331a}
.banner.lav{background:#211a37;color:var(--lav);border-color:#352c57}
/* chat */
.chat-wrap{display:flex;flex-direction:column;height:66vh}
.msgs{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:12px;padding:4px 2px}
.bubble{max-width:82%;padding:12px 15px;border-radius:18px;font-size:.9rem;line-height:1.5;white-space:pre-wrap}
.bubble.me{align-self:flex-end;background:var(--lime);color:var(--lime-ink);border-bottom-right-radius:6px;font-weight:600}
.bubble.bot{align-self:flex-start;background:var(--surface2);border:1px solid var(--line);border-bottom-left-radius:6px}
.bubble .tr{font-size:.69rem;color:var(--muted);margin-top:9px;border-top:1px solid #ffffff14;padding-top:7px;display:flex;flex-wrap:wrap;align-items:center;gap:5px}
.bubble .tr-h{color:var(--lime);font-weight:700;letter-spacing:.02em;margin-right:2px}
.bubble .tr-step{background:#ffffff10;border:1px solid var(--line);border-radius:7px;padding:2px 7px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:.66rem;color:var(--ink)}
.bubble .tr-arrow{color:var(--muted);opacity:.7}
.chips{display:flex;gap:8px;flex-wrap:wrap;margin:12px 0}
.chip{background:var(--surface2);border:1px solid var(--line);color:var(--muted);border-radius:999px;padding:8px 13px;font-size:.8rem}.chip:hover{color:var(--ink);border-color:var(--lav)}
/* calendar */
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:8px}
.cal-grid .head{color:var(--muted);font-size:.72rem;text-align:center;padding:4px;font-weight:600}
.cell{aspect-ratio:1;border-radius:13px;background:var(--surface2);border:1px solid var(--line);padding:8px;display:flex;flex-direction:column;justify-content:space-between;cursor:pointer;transition:.1s}
.cell.empty{background:transparent;border:0;cursor:default} .cell:not(.empty):hover{border-color:var(--lav)}
.cell.sel{outline:2px solid var(--lime)} .cell .d{font-size:.74rem;color:var(--muted)} .cell .a{font-size:.74rem;font-weight:750}
/* transactions */
.txn-filters{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:14px;align-items:end}
.txn-filters .field{margin:0;min-width:140px} .txn-filters .field.search{flex:1;min-width:200px}
.day-group{margin-bottom:18px} .day-head{color:var(--muted);font-size:.78rem;font-weight:700;margin:0 2px 8px;text-transform:uppercase;letter-spacing:.03em}
.txn{background:var(--surface2);border:1px solid var(--line);border-radius:14px;padding:13px 15px;margin-bottom:9px}
.txn-top{display:flex;align-items:center;gap:12px;cursor:pointer}
.txn-cat{width:38px;height:38px;border-radius:11px;display:grid;place-items:center;font-weight:800;flex:0 0 38px}
.txn-main{flex:1;min-width:0} .txn-v{font-weight:700} .txn-u{color:var(--muted);font-size:.78rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.txn-amt{font-weight:800;text-align:right} .txn-items{margin:11px 0 2px;border-top:1px solid var(--line);padding-top:10px;display:flex;flex-direction:column;gap:6px}
.txn-item{display:flex;justify-content:space-between;font-size:.82rem;gap:10px}
.txn-subh{color:var(--muted);font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin:10px 0 4px}
.txn-charge{color:var(--muted)}
.txn-tot{font-weight:800;border-top:1px solid var(--line);padding-top:8px;margin-top:7px}
.spin{display:inline-block;width:14px;height:14px;border:2px solid #00000033;border-top-color:currentColor;border-radius:50%;animation:sp .8s linear infinite;vertical-align:-2px}
@keyframes sp{to{transform:rotate(360deg)}}
/* responsive */
@media(max-width:1040px){.grid2,.grid2b{grid-template-columns:1fr}.cards{grid-template-columns:repeat(2,1fr)}}
@media(max-width:720px){
#app{flex-direction:column}
.sidebar{width:100%;flex-basis:auto;height:auto;position:sticky;top:0;z-index:9;flex-direction:row;flex-wrap:wrap;gap:4px;padding:10px;overflow-x:auto}
.side-logo{display:none}.side-foot{margin:0 0 0 auto;border:0;padding:0;display:flex;align-items:center}
.side-user .u{display:none}.nav-item span{display:none}.nav-item{padding:11px}
.main{padding:16px}.title{font-size:1.3rem}.cards{grid-template-columns:1fr 1fr;gap:11px}
.ring-wrap{flex-direction:column;align-items:stretch}.cmp-row{grid-template-columns:90px 1fr 72px}
}
</style>
</head>
<body>
<!-- LOGIN -->
<div id="login">
<div class="login-card">
<div class="logo"><span class="dot"><svg viewBox="0 0 24 24" width="18" height="18"><path d="M3 7h18v12H3z"/><path d="M3 10.5h18"/></svg></span> BudgetBuddy</div>
<p class="muted" style="margin:.6rem 0 1.1rem">Snap a bill, ask where your money went — private, on-device AI.</p>
<div class="field"><label>Username</label><input id="lg-user" placeholder="3–30 chars" autocomplete="username"></div>
<div class="field"><label>PIN</label><input id="lg-pin" type="password" placeholder="4–8 digits" autocomplete="current-password"></div>
<div class="row"><button class="btn" id="lg-login">Log in</button><button class="btn alt" id="lg-signup">Sign up</button></div>
<div class="msg" id="lg-msg"></div>
</div>
</div>
<!-- APP -->
<div id="app" class="hidden">
<aside class="sidebar">
<div class="side-logo logo"><span class="dot"><svg viewBox="0 0 24 24" width="18" height="18"><path d="M3 7h18v12H3z"/><path d="M3 10.5h18"/></svg></span> BudgetBuddy</div>
<button class="nav-item active" data-view="dashboard"><svg viewBox="0 0 24 24"><rect x="3" y="3" width="8" height="8" rx="2"/><rect x="13" y="3" width="8" height="5" rx="2"/><rect x="13" y="10" width="8" height="11" rx="2"/><rect x="3" y="13" width="8" height="8" rx="2"/></svg><span>Dashboard</span></button>
<button class="nav-item" data-view="add"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 8v8M8 12h8"/></svg><span>Add spend</span></button>
<button class="nav-item" data-view="calendar"><svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="17" rx="3"/><path d="M3 9h18M8 2v4M16 2v4"/></svg><span>Calendar</span></button>
<button class="nav-item" data-view="chat"><svg viewBox="0 0 24 24"><path d="M21 15a2 2 0 0 1-2 2H8l-5 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg><span>Assistant</span></button>
<button class="nav-item" data-view="txns"><svg viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h10"/></svg><span>Transactions</span></button>
<div class="side-foot">
<div class="side-user"><span class="avatar" id="av">?</span><span class="u" id="who"></span></div>
<button class="nav-item" id="logout" style="margin-top:4px"><svg viewBox="0 0 24 24"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg><span>Log out</span></button>
</div>
</aside>
<main class="main">
<!-- Dashboard -->
<section id="view-dashboard">
<div class="topbar">
<div><div class="title" id="greet">Welcome</div><div class="sub" id="todaystr"></div></div>
<div class="controls">
<select id="period"></select>
<div class="seg" id="gran"><button data-g="Daily">Daily</button><button data-g="Weekly">Weekly</button><button class="active" data-g="Monthly">Monthly</button></div>
</div>
</div>
<div class="cards" id="cards"></div>
<div class="grid2">
<div class="panel"><h3>Budget</h3><div class="ph-sub" id="budget-sub">Monthly budget</div>
<div class="ring-wrap"><div class="ring"><canvas id="ring-budget"></canvas><div class="rc" id="ring-budget-txt"></div></div>
<div style="flex:1"><div class="field" style="margin:0"><label>Set monthly budget</label><div class="row"><input id="budget-in" type="number" inputmode="decimal" placeholder="e.g. 20000"><button class="btn sm lav" id="budget-save" style="flex:0 0 auto">Set</button></div></div><div class="muted" id="budget-msg" style="font-size:.8rem;margin-top:9px"></div></div></div>
</div>
<div class="panel"><h3>Spend by category</h3><div class="ph-sub">Where your money goes</div><div class="chart-box"><canvas id="chart-cat"></canvas></div></div>
</div>
<div class="grid2b">
<div class="panel"><h3>Spend over time</h3><div class="ph-sub" id="ot-sub">Monthly</div><div class="chart-box"><canvas id="chart-time"></canvas></div></div>
<div class="panel"><h3>This month vs last</h3><div class="ph-sub">By category</div><div class="cmp" id="comparison"></div></div>
</div>
<div class="panel"><div style="display:flex;justify-content:space-between;align-items:center"><h3>Recent transactions</h3><button class="btn sm alt" id="see-all">See all</button></div><div class="ph-sub">Your latest spends</div><div id="recent"></div></div>
</section>
<!-- Add -->
<section id="view-add" class="hidden">
<div class="topbar"><div class="title">Add a spend</div></div>
<div class="modes">
<button class="mode active" data-mode="receipt"><svg viewBox="0 0 24 24"><path d="M5 2v20l2.5-1.6L10 22l2-1.6L14 22l2.5-1.6L19 22V2l-2.5 1.6L14 2l-2 1.6L10 2 7.5 3.6z"/><path d="M9 8h6M9 12h6"/></svg>Receipt</button>
<button class="mode" data-mode="payment"><svg viewBox="0 0 24 24"><rect x="2" y="5" width="20" height="14" rx="3"/><path d="M2 10h20"/></svg>Payment screenshot</button>
<button class="mode" data-mode="manual"><svg viewBox="0 0 24 24"><path d="M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z"/></svg>Manual</button>
</div>
<div id="mode-receipt">
<div class="panel" style="margin-bottom:16px">
<h3>Bill photo</h3><div class="ph-sub">Snap or upload — items, taxes, round-off and all</div>
<div class="upload-row">
<label class="drop" for="rc-file" style="flex:1;margin:0">Tap to choose a photo<div id="rc-prev"></div></label>
<div class="upload-actions">
<label class="btn alt sm" for="rc-file" style="text-align:center">Choose file</label>
<label class="btn alt sm" for="rc-cam" style="text-align:center">Take photo</label>
<button class="btn" id="rc-extract">Extract</button>
</div>
</div>
<input id="rc-file" type="file" accept="image/*" class="vh"><input id="rc-cam" type="file" accept="image/*" capture="environment" class="vh">
<div class="msg" id="rc-status"></div>
</div>
<div class="panel">
<h3>Review &amp; understand</h3><div class="ph-sub">Fix anything wrong, then let the AI categorize it</div>
<div class="row"><div class="field"><label>Vendor</label><input id="rc-vendor"></div><div class="field"><label>Date</label><input id="rc-date" type="date"></div><div class="field"><label>Currency</label><input id="rc-currency"></div></div>
<label>Line items</label>
<table id="rc-items"><thead><tr><th>Item</th><th class="col-qty">Qty</th><th class="col-amt">Amount</th><th class="col-cat">Category</th><th class="col-x"></th></tr></thead><tbody></tbody></table>
<button class="btn sm alt" id="rc-additem" style="margin-top:8px">+ Add item</button>
<div class="row" style="margin-top:16px;align-items:flex-start">
<div style="flex:1"><label>Charges &amp; taxes</label><table id="rc-charges"><thead><tr><th>Label</th><th class="col-amt">Amount</th><th class="col-x"></th></tr></thead><tbody></tbody></table><button class="btn sm alt" id="rc-addcharge" style="margin-top:8px">+ Add charge</button></div>
<div style="flex:1"><div class="field" style="margin:0 0 13px"><label>Total</label><input id="rc-total" type="number" inputmode="decimal"></div><div class="field" style="margin:0"><label>Overall category</label><select id="rc-cat"></select></div></div>
</div>
<div id="rc-recon" class="banner ok">Totals reconcile.</div>
<div id="rc-understand" class="banner lav hidden"></div>
<div class="row" style="margin-top:4px"><button class="btn lav" id="rc-confirm">Understand &amp; categorize</button><button class="btn" id="rc-save" disabled>Save</button></div>
<div class="msg" id="rc-savemsg"></div>
</div>
</div>
<div id="mode-payment" class="grid2b hidden">
<div class="panel"><h3>Payment screenshot</h3><div class="ph-sub">UPI / GPay / PhonePe / card</div>
<label class="drop" for="pm-file">Tap to choose a screenshot<div id="pm-prev"></div></label>
<input id="pm-file" type="file" accept="image/*" class="vh"><input id="pm-cam" type="file" accept="image/*" capture="environment" class="vh">
<div class="cap-row"><label class="btn alt sm" for="pm-file" style="flex:1;display:inline-flex;align-items:center;justify-content:center">Choose file</label><label class="btn alt sm" for="pm-cam" style="flex:1;display:inline-flex;align-items:center;justify-content:center">Take photo</label></div>
<button class="btn" id="pm-extract" style="margin-top:11px;width:100%">Read</button><div class="msg" id="pm-status"></div></div>
<div class="panel"><h3>Review &amp; save</h3>
<div class="field"><label>Paid to</label><input id="pm-vendor"></div>
<div class="row"><div class="field"><label>Amount</label><input id="pm-amount" type="number" inputmode="decimal"></div><div class="field"><label>Currency</label><input id="pm-currency"></div></div>
<div class="row"><div class="field"><label>Date</label><input id="pm-date" type="date"></div><div class="field"><label>Category</label><select id="pm-cat"></select></div></div>
<div class="field"><label>Note</label><input id="pm-note"></div>
<button class="btn" id="pm-save" style="width:100%" disabled>Save</button><div class="msg" id="pm-savemsg"></div></div>
</div>
<div id="mode-manual" class="panel hidden" style="max-width:680px">
<h3>Add a spend</h3><div class="ph-sub">A single amount, or add items one by one</div>
<div class="row"><div class="field"><label>What / where</label><input id="mn-vendor"></div><div class="field"><label>Date</label><input id="mn-date" type="date"></div></div>
<label>Items (optional)</label>
<table id="mn-items"><thead><tr><th>Item</th><th class="col-amt">Amount</th><th class="col-cat">Category</th><th class="col-x"></th></tr></thead><tbody></tbody></table>
<button class="btn sm alt" id="mn-additem" style="margin-top:8px">+ Add item</button>
<div class="row" style="margin-top:15px"><div class="field"><label>Total amount</label><input id="mn-amount" type="number" inputmode="decimal"></div><div class="field"><label>Category</label><select id="mn-cat"></select></div></div>
<div class="field"><label>Note</label><input id="mn-note"></div>
<button class="btn" id="mn-save" style="width:100%">Add spend</button><div class="msg" id="mn-savemsg"></div>
</div>
</section>
<!-- Calendar -->
<section id="view-calendar" class="hidden">
<div class="topbar"><div class="title">Calendar</div>
<div class="controls"><button class="btn sm alt" id="cal-prev">‹ Prev</button><div class="sub" id="cal-month" style="min-width:120px;text-align:center"></div><button class="btn sm alt" id="cal-next">Next ›</button></div>
</div>
<div class="grid2b">
<div class="panel"><div class="cal-grid" id="cal"></div></div>
<div class="panel"><h3 id="cal-day-title">Pick a day</h3><div class="ph-sub">Spending on the selected day</div><div id="cal-day"></div></div>
</div>
</section>
<!-- Chat -->
<section id="view-chat" class="hidden">
<div class="topbar"><div class="title">Assistant</div></div>
<div class="panel chat-wrap">
<div class="msgs" id="chat-msgs"><div class="bubble bot">Ask me about your spending — I only use your saved data. The first question after a while may take a moment to warm up.</div></div>
<div class="chips" id="chat-chips"></div>
<div class="row"><input id="chat-in" placeholder="e.g. How much did I spend on Dining this month?" style="flex:5"><button class="btn" id="chat-send" style="flex:0 0 auto;min-width:84px">Send</button></div>
</div>
</section>
<!-- Transactions -->
<section id="view-txns" class="hidden">
<div class="topbar"><div class="title">Transactions</div></div>
<div class="panel">
<div class="txn-filters">
<div class="field search"><label>Search</label><input id="tx-q" placeholder="vendor or item…"></div>
<div class="field"><label>Category</label><select id="tx-cat"></select></div>
<div class="field"><label>Period</label><select id="tx-period"></select></div>
</div>
<div id="txn-list"></div>
</div>
</section>
</main>
</div>
<script type="module" src="/assets/app.js"></script>
</body>
</html>