Navya-Sree commited on
Commit
2283865
·
verified ·
1 Parent(s): 943db96

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -105
app.py CHANGED
@@ -1,4 +1,3 @@
1
- # app.py
2
  import streamlit as st
3
  from datetime import date
4
  import math
@@ -7,33 +6,34 @@ import random
7
  from llm_utils import explain_savings_plan
8
 
9
 
10
- # ---------- Streamlit Page Config ----------
11
  st.set_page_config(
12
  page_title="Pistol Pete SmartAgent",
13
  page_icon="🏠",
14
- layout="centered"
15
  )
16
 
17
 
18
- # ---------- Helpers ----------
19
  def init_state():
20
  if "step" not in st.session_state:
21
  st.session_state.step = 1
22
 
23
- # User profile fields
24
- st.session_state.setdefault("home_type", "I'm not sure yet")
25
  st.session_state.setdefault("location", "")
26
- st.session_state.setdefault("timeline_bucket", 3) # screen 3 slider (1–5)
27
- st.session_state.setdefault("budget", 350000) # used by sliders
28
- st.session_state.setdefault("home_budget_raw", "") # raw text from screen 3
29
 
30
  st.session_state.setdefault("annual_income", "75000")
31
  st.session_state.setdefault("monthly_debt", "350")
32
  st.session_state.setdefault("current_savings", "12000")
33
 
34
- # Plan controls (screen 5)
35
- st.session_state.setdefault("timeline_years_plan", 4) # 2–7 yrs in original UI
36
- st.session_state.setdefault("down_pct", 20) # 10–20
 
 
37
  st.session_state.setdefault("llm_explanation", None)
38
 
39
 
@@ -51,15 +51,30 @@ def to_int(value, default):
51
  return default
52
 
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  def compute_savings_plan(budget, down_pct, current_savings, timeline_years):
55
  """
56
- Port of your JS logic from updatePlanCalculations():
57
- - 20% (or slider %) down payment
58
- - Remaining need
59
- - Months = years * 12
60
- - Closing costs = 5000 / months
61
- - Interest earnings via simple yearly compounding at 1.5% APY
62
- - Recommended monthly = base + closing - interestEarnings
63
  """
64
  down_payment_amount = round(budget * (down_pct / 100))
65
  remaining_need = max(0, down_payment_amount - current_savings)
@@ -68,7 +83,7 @@ def compute_savings_plan(budget, down_pct, current_savings, timeline_years):
68
  monthly_base = remaining_need / months
69
  closing_costs = 5000 / months
70
 
71
- # interest earnings (same style as JS)
72
  annual_rate = 0.015
73
  balance = current_savings
74
  total_interest = 0.0
@@ -81,9 +96,9 @@ def compute_savings_plan(budget, down_pct, current_savings, timeline_years):
81
 
82
  monthly_savings = monthly_base + closing_costs - interest_earnings
83
 
84
- # target date (approx – same idea as JS)
85
  today = date.today()
86
  target_year = today.year + timeline_years
 
87
  target_date = date(target_year, today.month, today.day)
88
 
89
  return {
@@ -101,16 +116,16 @@ def compute_savings_plan(budget, down_pct, current_savings, timeline_years):
101
  def compute_estimated_home_value(budget, timeline_years, location, down_pct):
102
  """
103
  Port of estimateValue() from your JS:
104
- - Start with budget
105
- - timelineAdjPct = ((years - 4) * 0.02)
106
- - random adjustment between -15000 and +15000
107
- - Pittsburgh/Lawrenceville: slight discount (0.98)
108
- - Confidence from size of random adjustment + timeline
109
  """
110
  base_budget = budget
111
  est = base_budget
112
 
113
- rand_adj = random.randint(-15000, 15000) # same range
114
  timeline_adj_pct = (timeline_years - 4) * 0.02
115
  est = round(est * (1 + timeline_adj_pct) + rand_adj)
116
 
@@ -118,7 +133,6 @@ def compute_estimated_home_value(budget, timeline_years, location, down_pct):
118
  if "pittsburgh" in loc or "lawrenceville" in loc:
119
  est = round(est * 0.98)
120
 
121
- # Confidence heuristic
122
  if abs(rand_adj) < 6000 and timeline_years <= 5:
123
  confidence = "High"
124
  elif abs(rand_adj) < 12000:
@@ -137,26 +151,19 @@ def prev_step():
137
  st.session_state.step = max(1, st.session_state.step - 1)
138
 
139
 
140
- # ---------- App Layout ----------
141
- init_state()
142
-
143
  st.markdown(
144
  "<h2 style='text-align:center;'>🏠 Pistol Pete SmartAgent</h2>",
145
  unsafe_allow_html=True,
146
  )
147
- st.caption(
148
- "Trusted, explainable AI coach for first-home savings — adapted from your prototype UI."
149
- )
150
-
151
- # Progress bar (7 screens)
152
  st.progress(st.session_state.step / 7.0)
153
-
154
  st.divider()
155
 
156
  step = st.session_state.step
157
 
158
 
159
- # ---------- Screen 1: Welcome ----------
160
  if step == 1:
161
  st.header("Ready to Plan for Your Home?")
162
  st.write(
@@ -167,15 +174,15 @@ if step == 1:
167
  with st.expander("How it works", expanded=True):
168
  st.markdown(
169
  "- We ask about your **home goals** and **finances**.\n"
170
- "- We compute a **down payment plan** and **monthly savings**.\n"
171
- "- An **LLM layer** explains the math in plain English (Screen 5).\n"
172
- "- You can always **adjust timeline and budget**, and see changes instantly."
173
  )
174
 
175
  st.button("Start Your Personalized Plan ➜", on_click=next_step)
176
 
177
 
178
- # ---------- Screen 2: Home Goals ----------
179
  elif step == 2:
180
  st.header("Let's Build Your Home Plan Together")
181
  st.write("Tell us about your dream home — this helps us create a plan that's right for you.")
@@ -183,7 +190,8 @@ elif step == 2:
183
  st.session_state.home_type = st.radio(
184
  "What type of home are you dreaming of?",
185
  ["Single-Family Home", "Townhouse", "Condominium", "I'm not sure yet"],
186
- index=["Single-Family Home", "Townhouse", "Condominium", "I'm not sure yet"].index(
 
187
  st.session_state.home_type
188
  ),
189
  )
@@ -201,7 +209,7 @@ elif step == 2:
201
  st.button("Continue ➜", on_click=next_step, key="next_2")
202
 
203
 
204
- # ---------- Screen 3: Timeline & Budget ----------
205
  elif step == 3:
206
  st.header("Your Timeline & Budget")
207
  st.write("Now let's talk about when you'd like to buy and your comfortable budget range.")
@@ -211,7 +219,6 @@ elif step == 3:
211
  min_value=1,
212
  max_value=5,
213
  value=st.session_state.timeline_bucket,
214
- help="This is your rough comfort range. We'll use a more precise timeline later.",
215
  )
216
 
217
  def bucket_label(b):
@@ -225,20 +232,24 @@ elif step == 3:
225
 
226
  st.caption(f"Selected range: **{bucket_label(st.session_state.timeline_bucket)}**")
227
 
228
- st.session_state.home_budget_raw = st.text_input(
 
229
  "What is your comfortable estimated home budget?",
230
- value=st.session_state.home_budget_raw,
231
  placeholder="e.g., 350000",
232
  )
 
233
 
234
  if st.session_state.location and any(
235
  k in st.session_state.location.lower() for k in ["pittsburgh", "lawrenceville"]
236
  ):
237
- st.info("We see average prices in Lawrenceville are around ~$350,000 (illustrative).")
238
 
239
- # If user typed a budget, pre-seed numeric slider state for later screens
240
- parsed_budget = to_int(st.session_state.home_budget_raw, st.session_state.budget)
241
- st.session_state.budget = parsed_budget
 
 
242
 
243
  col1, col2 = st.columns(2)
244
  with col1:
@@ -247,7 +258,7 @@ elif step == 3:
247
  st.button("Continue ➜", on_click=next_step, key="next_3")
248
 
249
 
250
- # ---------- Screen 4: Financial Picture ----------
251
  elif step == 4:
252
  st.header("Your Financial Snapshot")
253
  st.write(
@@ -255,7 +266,7 @@ elif step == 4:
255
  "Verify or update any of the details below."
256
  )
257
 
258
- st.info("We value your privacy. This information is used only to create your plan.")
259
 
260
  st.session_state.annual_income = st.text_input(
261
  "Annual Gross Income",
@@ -266,13 +277,13 @@ elif step == 4:
266
  st.session_state.monthly_debt = st.text_input(
267
  "Monthly Debt Payments",
268
  value=st.session_state.monthly_debt,
269
- help="Credit cards, loans, etc.",
270
  )
271
 
272
  st.session_state.current_savings = st.text_input(
273
  "Current Down Payment Savings",
274
  value=st.session_state.current_savings,
275
- help="Savings accounts earmarked for housing.",
276
  )
277
 
278
  col1, col2 = st.columns(2)
@@ -282,7 +293,7 @@ elif step == 4:
282
  st.button("Generate My Home Plan ➜", on_click=next_step, key="next_4")
283
 
284
 
285
- # ---------- Screen 5: AI Recommendation Dashboard ----------
286
  elif step == 5:
287
  st.header("Your Personalized Home Plan")
288
 
@@ -292,13 +303,13 @@ elif step == 5:
292
  "here's your tailored savings roadmap."
293
  )
294
 
295
- # Numeric values from state
296
  budget = st.session_state.budget
297
  income = to_int(st.session_state.annual_income, 75000)
298
  debt = to_int(st.session_state.monthly_debt, 350)
299
  savings = to_int(st.session_state.current_savings, 12000)
300
 
301
- # --- Adjust Your Plan (sliders) ---
302
  st.subheader("Adjust Your Plan")
303
 
304
  colA, colB = st.columns(2)
@@ -324,29 +335,27 @@ elif step == 5:
324
  max_value=20,
325
  step=5,
326
  value=st.session_state.down_pct,
327
- help="Below 20% may require Private Mortgage Insurance (PMI).",
328
  )
329
 
330
  if st.session_state.down_pct < 20:
331
  st.warning("A down payment below 20% may require Private Mortgage Insurance (PMI).")
332
 
333
- # --- Core plan calculations ---
 
334
  plan = compute_savings_plan(
335
- budget=st.session_state.budget,
336
  down_pct=st.session_state.down_pct,
337
  current_savings=savings,
338
  timeline_years=st.session_state.timeline_years_plan,
339
  )
340
 
341
- # ---------- Savings Timeline Card ----------
342
  st.subheader("Savings Timeline")
343
- today_col, _, goal_col = st.columns([1, 2, 1])
344
-
345
- with today_col:
346
  st.caption("Today")
347
  st.markdown(f"**${savings:,.0f}**")
348
-
349
- with goal_col:
350
  st.caption("Goal")
351
  st.markdown(f"**${plan['down_payment_amount']:,.0f}**")
352
 
@@ -357,29 +366,29 @@ elif step == 5:
357
 
358
  st.divider()
359
 
360
- # ---------- AI Recommendation ----------
361
  st.subheader("AI Recommendation")
362
  st.write(
363
  f"To reach your goal in **{st.session_state.timeline_years_plan} years**, "
364
  "we recommend saving:"
365
  )
366
-
367
  st.markdown(
368
- f"<div style='font-size:32px;font-weight:800;text-align:center;'>"
369
- f"${plan['monthly_savings']:,.0f} / month</div>",
370
  unsafe_allow_html=True,
371
  )
 
372
 
373
- st.caption(
374
- "Confidence: **High** (demo). In production, this can reflect stability of income, "
375
- "DTI, and housing market predictability."
376
  )
377
 
378
- # ---------- LLM Explanation Layer ----------
379
- st.markdown("#### Explanation (LLM)")
380
 
381
  payload = {
382
- "home_budget": st.session_state.budget,
383
  "down_payment_percent": st.session_state.down_pct,
384
  "down_payment_amount": plan["down_payment_amount"],
385
  "current_savings": savings,
@@ -392,16 +401,16 @@ elif step == 5:
392
  }
393
 
394
  if st.button("Explain this plan with AI"):
395
- with st.spinner("Calling trusted AI explainer..."):
396
  explanation = explain_savings_plan(payload)
397
  st.session_state.llm_explanation = explanation
398
 
399
  if st.session_state.llm_explanation:
400
  st.info(st.session_state.llm_explanation)
401
  else:
402
- st.caption("Click **'Explain this plan with AI'** to see a plain-English summary.")
403
 
404
- # ---------- See the AIs Math ----------
405
  with st.expander("See the AI's Math"):
406
  st.write(
407
  f"**Target Down Payment ({st.session_state.down_pct}%):** "
@@ -409,12 +418,18 @@ elif step == 5:
409
  )
410
  st.write(f"**− Current Savings:** ${savings:,.0f}")
411
  st.write(f"**= Remaining Need:** ${plan['remaining_need']:,.0f}")
412
- st.write(f"**÷ Months in Timeline ({plan['months']})** = "
413
- f"${plan['monthly_base']:,.0f} base / month")
414
- st.write(f"**+ Estimated Closing Costs (≈ $5,000 / {plan['months']}):** "
415
- f"+ ${plan['closing_costs']:,.0f}")
416
- st.write(f"**− Projected Interest on Savings (@1.5% APY):** "
417
- f" ${plan['interest_earnings']:,.0f}")
 
 
 
 
 
 
418
  st.write(
419
  f"**= Recommended Monthly Savings:** "
420
  f"${plan['monthly_savings']:,.0f} / month"
@@ -429,7 +444,7 @@ elif step == 5:
429
  st.button("Next Steps ➜", on_click=next_step, key="next_5")
430
 
431
 
432
- # ---------- Screen 6: Next Steps & Product Recommendations ----------
433
  elif step == 6:
434
  st.header("Tools to Help You Succeed")
435
  st.write("Based on your plan, here are products and support options to accelerate progress.")
@@ -437,26 +452,26 @@ elif step == 6:
437
  savings = to_int(st.session_state.current_savings, 12000)
438
 
439
  # Product 1
440
- st.subheader("PNC-style Product: High-Yield “Home Fund” Savings Account (Concept)")
441
  st.write(
442
- f"Based on your current savings of **${savings:,.0f}**, "
443
- "you could earn **more interest** in a high-yield account compared to a basic savings account."
444
  )
445
  st.caption("Why we suggest this: to maximize your savings growth with minimal risk.")
446
 
447
  st.divider()
448
 
449
  # Product 2
450
- st.subheader("Service: Consider a Home Loan Pre-approval (Concept)")
451
  st.write(
452
- "A pre-approval helps clarify your budget and shows sellers you're serious. "
453
- "Many successful buyers get pre-approved early in the process."
454
  )
455
  st.caption("Why we suggest this: to reduce uncertainty and strengthen your offers.")
456
 
457
  st.divider()
458
 
459
- # Human Agent contact form
460
  st.subheader("Prefer to Speak with a Human Agent?")
461
  with st.form("contact_form"):
462
  name = st.text_input("Full name")
@@ -479,9 +494,9 @@ elif step == 6:
479
  st.button("Save & Estimate Value ➜", on_click=next_step, key="next_6")
480
 
481
 
482
- # ---------- Screen 7: Estimated Home Value ----------
483
  elif step == 7:
484
- st.header("Your Estimated Home Value (Illustrative)")
485
 
486
  budget = st.session_state.budget
487
  down_pct = st.session_state.down_pct
@@ -496,10 +511,10 @@ elif step == 7:
496
  )
497
 
498
  st.markdown(
499
- f"<div style='background:#fff7eb;padding:18px;border-radius:12px;"
500
- f"text-align:center;border:1px solid #f0d2a3;'>"
501
- f"<h2 style='color:#D96932;font-size:34px;'>${est_value:,.0f}</h2>"
502
- f"<p>Estimated probable home value given your inputs (for demo only).</p>"
503
  f"<p>Confidence: <strong>{confidence}</strong></p>"
504
  f"</div>",
505
  unsafe_allow_html=True,
@@ -507,8 +522,9 @@ elif step == 7:
507
 
508
  st.subheader("How we estimate")
509
  st.write(
510
- "This demo estimate combines your input budget, timeline, and a simple heuristic. "
511
- "In a production system, we would integrate MLS or public-record APIs for more accurate values."
 
512
  )
513
 
514
  colA, colB = st.columns(2)
@@ -516,7 +532,7 @@ elif step == 7:
516
  st.markdown("**Input Budget**")
517
  st.markdown(f"${budget:,.0f}")
518
  with colB:
519
- st.markdown("**Down Payment**")
520
  st.markdown(f"${round(budget * down_pct / 100):,.0f}")
521
 
522
  st.divider()
@@ -526,5 +542,4 @@ elif step == 7:
526
  st.button("⬅ Back", on_click=prev_step, key="back_7")
527
  with col2:
528
  if st.button("Finish & Save"):
529
- st.success("Your plan summary has been saved (demo).")
530
- st.info("On Hugging Face, you can reset the app by refreshing the page.")
 
 
1
  import streamlit as st
2
  from datetime import date
3
  import math
 
6
  from llm_utils import explain_savings_plan
7
 
8
 
9
+ # ---------------------- PAGE CONFIG ----------------------
10
  st.set_page_config(
11
  page_title="Pistol Pete SmartAgent",
12
  page_icon="🏠",
13
+ layout="centered",
14
  )
15
 
16
 
17
+ # ---------------------- STATE INIT -----------------------
18
  def init_state():
19
  if "step" not in st.session_state:
20
  st.session_state.step = 1
21
 
22
+ # From your original JS userData object
23
+ st.session_state.setdefault("home_type", "")
24
  st.session_state.setdefault("location", "")
25
+ st.session_state.setdefault("timeline_bucket", 3) # 1–5 slider
26
+ st.session_state.setdefault("budget", 350000)
 
27
 
28
  st.session_state.setdefault("annual_income", "75000")
29
  st.session_state.setdefault("monthly_debt", "350")
30
  st.session_state.setdefault("current_savings", "12000")
31
 
32
+ # Controls on Screen 5
33
+ st.session_state.setdefault("timeline_years_plan", 4) # 2–7 years
34
+ st.session_state.setdefault("down_pct", 20) # 10–20
35
+
36
+ # LLM output
37
  st.session_state.setdefault("llm_explanation", None)
38
 
39
 
 
51
  return default
52
 
53
 
54
+ init_state()
55
+
56
+
57
+ # ---------------------- GOVERNANCE SIDEBAR ----------------------
58
+ with st.sidebar:
59
+ st.markdown("### 🔐 Governance & Fairness")
60
+ st.caption(
61
+ "- No protected attributes (race, gender, etc.) are used in calculations.\n"
62
+ "- The LLM **only** explains numbers already computed.\n"
63
+ "- Users can adjust timeline & budget and keep full control.\n"
64
+ "- This is a prototype; no real accounts or PII are stored."
65
+ )
66
+
67
+
68
+ # ---------------------- HELPERS ----------------------
69
  def compute_savings_plan(budget, down_pct, current_savings, timeline_years):
70
  """
71
+ Port of your JS updatePlanCalculations() logic:
72
+ - Down payment = budget * %
73
+ - Remaining need
74
+ - Months = years * 12
75
+ - Closing costs = 5000 / months
76
+ - Interest earnings via 1.5% APY on (savings + contributions)
77
+ - Recommended monthly = base + closing - interestEarnings
78
  """
79
  down_payment_amount = round(budget * (down_pct / 100))
80
  remaining_need = max(0, down_payment_amount - current_savings)
 
83
  monthly_base = remaining_need / months
84
  closing_costs = 5000 / months
85
 
86
+ # interestEarnings (same idea as your JS)
87
  annual_rate = 0.015
88
  balance = current_savings
89
  total_interest = 0.0
 
96
 
97
  monthly_savings = monthly_base + closing_costs - interest_earnings
98
 
 
99
  today = date.today()
100
  target_year = today.year + timeline_years
101
+ # Same month/day as today
102
  target_date = date(target_year, today.month, today.day)
103
 
104
  return {
 
116
  def compute_estimated_home_value(budget, timeline_years, location, down_pct):
117
  """
118
  Port of estimateValue() from your JS:
119
+ - Start with budget
120
+ - timelineAdjPct = ((years - 4) * 0.02)
121
+ - random adjustment ± 15k
122
+ - Location tweak for Pittsburgh / Lawrenceville
123
+ - Confidence from randAdj + timeline
124
  """
125
  base_budget = budget
126
  est = base_budget
127
 
128
+ rand_adj = random.randint(-15000, 15000)
129
  timeline_adj_pct = (timeline_years - 4) * 0.02
130
  est = round(est * (1 + timeline_adj_pct) + rand_adj)
131
 
 
133
  if "pittsburgh" in loc or "lawrenceville" in loc:
134
  est = round(est * 0.98)
135
 
 
136
  if abs(rand_adj) < 6000 and timeline_years <= 5:
137
  confidence = "High"
138
  elif abs(rand_adj) < 12000:
 
151
  st.session_state.step = max(1, st.session_state.step - 1)
152
 
153
 
154
+ # ---------------------- PROGRESS BAR ----------------------
 
 
155
  st.markdown(
156
  "<h2 style='text-align:center;'>🏠 Pistol Pete SmartAgent</h2>",
157
  unsafe_allow_html=True,
158
  )
159
+ st.caption("Prototype 2025 – Trusted, explainable first-home savings coach.")
 
 
 
 
160
  st.progress(st.session_state.step / 7.0)
 
161
  st.divider()
162
 
163
  step = st.session_state.step
164
 
165
 
166
+ # ---------------------- SCREEN 1 ----------------------
167
  if step == 1:
168
  st.header("Ready to Plan for Your Home?")
169
  st.write(
 
174
  with st.expander("How it works", expanded=True):
175
  st.markdown(
176
  "- We ask about your **home goals** and **finances**.\n"
177
+ "- We create a **down-payment savings plan**.\n"
178
+ "- You can see the **exact math** and adjust your own timeline and budget.\n"
179
+ "- An **LLM explainer** turns the numbers into plain-English explanations."
180
  )
181
 
182
  st.button("Start Your Personalized Plan ➜", on_click=next_step)
183
 
184
 
185
+ # ---------------------- SCREEN 2 ----------------------
186
  elif step == 2:
187
  st.header("Let's Build Your Home Plan Together")
188
  st.write("Tell us about your dream home — this helps us create a plan that's right for you.")
 
190
  st.session_state.home_type = st.radio(
191
  "What type of home are you dreaming of?",
192
  ["Single-Family Home", "Townhouse", "Condominium", "I'm not sure yet"],
193
+ index=3 if st.session_state.home_type == "" else
194
+ ["Single-Family Home", "Townhouse", "Condominium", "I'm not sure yet"].index(
195
  st.session_state.home_type
196
  ),
197
  )
 
209
  st.button("Continue ➜", on_click=next_step, key="next_2")
210
 
211
 
212
+ # ---------------------- SCREEN 3 ----------------------
213
  elif step == 3:
214
  st.header("Your Timeline & Budget")
215
  st.write("Now let's talk about when you'd like to buy and your comfortable budget range.")
 
219
  min_value=1,
220
  max_value=5,
221
  value=st.session_state.timeline_bucket,
 
222
  )
223
 
224
  def bucket_label(b):
 
232
 
233
  st.caption(f"Selected range: **{bucket_label(st.session_state.timeline_bucket)}**")
234
 
235
+ # Raw budget input
236
+ home_budget_raw = st.text_input(
237
  "What is your comfortable estimated home budget?",
238
+ value=str(st.session_state.budget),
239
  placeholder="e.g., 350000",
240
  )
241
+ st.session_state.budget = to_int(home_budget_raw, st.session_state.budget)
242
 
243
  if st.session_state.location and any(
244
  k in st.session_state.location.lower() for k in ["pittsburgh", "lawrenceville"]
245
  ):
246
+ st.info("We see average prices in Lawrenceville are ~ $350,000 (illustrative).")
247
 
248
+ st.checkbox(
249
+ "Let our AI calculate a budget for me based on my finances (concept only)",
250
+ value=False,
251
+ help="For this prototype, the slider/budget is still user-controlled.",
252
+ )
253
 
254
  col1, col2 = st.columns(2)
255
  with col1:
 
258
  st.button("Continue ➜", on_click=next_step, key="next_3")
259
 
260
 
261
+ # ---------------------- SCREEN 4 ----------------------
262
  elif step == 4:
263
  st.header("Your Financial Snapshot")
264
  st.write(
 
266
  "Verify or update any of the details below."
267
  )
268
 
269
+ st.info("We value your privacy. This information is used only to create your plan and is not sold.")
270
 
271
  st.session_state.annual_income = st.text_input(
272
  "Annual Gross Income",
 
277
  st.session_state.monthly_debt = st.text_input(
278
  "Monthly Debt Payments",
279
  value=st.session_state.monthly_debt,
280
+ help="Example: credit cards, loans",
281
  )
282
 
283
  st.session_state.current_savings = st.text_input(
284
  "Current Down Payment Savings",
285
  value=st.session_state.current_savings,
286
+ help="Example: savings accounts",
287
  )
288
 
289
  col1, col2 = st.columns(2)
 
293
  st.button("Generate My Home Plan ➜", on_click=next_step, key="next_4")
294
 
295
 
296
+ # ---------------------- SCREEN 5 ----------------------
297
  elif step == 5:
298
  st.header("Your Personalized Home Plan")
299
 
 
303
  "here's your tailored savings roadmap."
304
  )
305
 
306
+ # Collect numeric values
307
  budget = st.session_state.budget
308
  income = to_int(st.session_state.annual_income, 75000)
309
  debt = to_int(st.session_state.monthly_debt, 350)
310
  savings = to_int(st.session_state.current_savings, 12000)
311
 
312
+ # -------- Adjust Your Plan (Control Panel) --------
313
  st.subheader("Adjust Your Plan")
314
 
315
  colA, colB = st.columns(2)
 
335
  max_value=20,
336
  step=5,
337
  value=st.session_state.down_pct,
 
338
  )
339
 
340
  if st.session_state.down_pct < 20:
341
  st.warning("A down payment below 20% may require Private Mortgage Insurance (PMI).")
342
 
343
+ # Recompute plan with updated values
344
+ budget = st.session_state.budget
345
  plan = compute_savings_plan(
346
+ budget=budget,
347
  down_pct=st.session_state.down_pct,
348
  current_savings=savings,
349
  timeline_years=st.session_state.timeline_years_plan,
350
  )
351
 
352
+ # -------- Savings Timeline Card --------
353
  st.subheader("Savings Timeline")
354
+ col_today, _, col_goal = st.columns([1, 2, 1])
355
+ with col_today:
 
356
  st.caption("Today")
357
  st.markdown(f"**${savings:,.0f}**")
358
+ with col_goal:
 
359
  st.caption("Goal")
360
  st.markdown(f"**${plan['down_payment_amount']:,.0f}**")
361
 
 
366
 
367
  st.divider()
368
 
369
+ # -------- AI Recommendation Card --------
370
  st.subheader("AI Recommendation")
371
  st.write(
372
  f"To reach your goal in **{st.session_state.timeline_years_plan} years**, "
373
  "we recommend saving:"
374
  )
 
375
  st.markdown(
376
+ f"<div style='font-size:32px;font-weight:800;color:#D96932;text-align:center;'>"
377
+ f"${plan['monthly_savings']:,.0f}/month</div>",
378
  unsafe_allow_html=True,
379
  )
380
+ st.caption("Confidence: **High** (demo).")
381
 
382
+ st.write(
383
+ "💡 **Why this level?** Your income and debts produce a debt-to-income profile that "
384
+ "supports this plan, plus predictable regional assumptions for this demo."
385
  )
386
 
387
+ # -------- LLM Explanation Layer --------
388
+ st.markdown("#### Explanation (AI Coach)")
389
 
390
  payload = {
391
+ "home_budget": budget,
392
  "down_payment_percent": st.session_state.down_pct,
393
  "down_payment_amount": plan["down_payment_amount"],
394
  "current_savings": savings,
 
401
  }
402
 
403
  if st.button("Explain this plan with AI"):
404
+ with st.spinner("Generating a plain-English explanation..."):
405
  explanation = explain_savings_plan(payload)
406
  st.session_state.llm_explanation = explanation
407
 
408
  if st.session_state.llm_explanation:
409
  st.info(st.session_state.llm_explanation)
410
  else:
411
+ st.caption("Click the button above to see the AI Coach explain your plan in simple terms.")
412
 
413
+ # -------- See the AI's Math (Accordion-like) --------
414
  with st.expander("See the AI's Math"):
415
  st.write(
416
  f"**Target Down Payment ({st.session_state.down_pct}%):** "
 
418
  )
419
  st.write(f"**− Current Savings:** ${savings:,.0f}")
420
  st.write(f"**= Remaining Need:** ${plan['remaining_need']:,.0f}")
421
+ st.write(
422
+ f"**÷ Months in Timeline ({plan['months']}):** "
423
+ f"${plan['monthly_base']:,.0f} base / month"
424
+ )
425
+ st.write(
426
+ f"**+ Estimated Closing Costs (≈ $5,000 / {plan['months']}):** "
427
+ f"+ ${plan['closing_costs']:,.0f}"
428
+ )
429
+ st.write(
430
+ f"**− Projected Interest on Savings (@1.5% APY):** "
431
+ f"− ${plan['interest_earnings']:,.0f}"
432
+ )
433
  st.write(
434
  f"**= Recommended Monthly Savings:** "
435
  f"${plan['monthly_savings']:,.0f} / month"
 
444
  st.button("Next Steps ➜", on_click=next_step, key="next_5")
445
 
446
 
447
+ # ---------------------- SCREEN 6 ----------------------
448
  elif step == 6:
449
  st.header("Tools to Help You Succeed")
450
  st.write("Based on your plan, here are products and support options to accelerate progress.")
 
452
  savings = to_int(st.session_state.current_savings, 12000)
453
 
454
  # Product 1
455
+ st.subheader("PRODUCT High-Yield “Home Fund” Savings Account (Concept)")
456
  st.write(
457
+ f"Based on your current savings of **${savings:,.0f}**, you could earn "
458
+ f"**more interest** per year in a high-yield account compared to a basic account."
459
  )
460
  st.caption("Why we suggest this: to maximize your savings growth with minimal risk.")
461
 
462
  st.divider()
463
 
464
  # Product 2
465
+ st.subheader("SERVICE Consider a Home Loan Pre-approval (Concept)")
466
  st.write(
467
+ "A pre-approval helps clarify your budget. Many buyers who succeed "
468
+ "get pre-approved early in the process."
469
  )
470
  st.caption("Why we suggest this: to reduce uncertainty and strengthen your offers.")
471
 
472
  st.divider()
473
 
474
+ # Human contact form (replaces modal)
475
  st.subheader("Prefer to Speak with a Human Agent?")
476
  with st.form("contact_form"):
477
  name = st.text_input("Full name")
 
494
  st.button("Save & Estimate Value ➜", on_click=next_step, key="next_6")
495
 
496
 
497
+ # ---------------------- SCREEN 7 ----------------------
498
  elif step == 7:
499
+ st.header("Your Estimated Home Value")
500
 
501
  budget = st.session_state.budget
502
  down_pct = st.session_state.down_pct
 
511
  )
512
 
513
  st.markdown(
514
+ f"<div style='background:#FFF8EC;border-radius:12px;padding:18px;"
515
+ f"box-shadow:0 6px 18px rgba(217,105,50,0.08);text-align:center;'>"
516
+ f"<h2 style='font-size:34px;color:#D96932;'>${est_value:,.0f}</h2>"
517
+ f"<p>Estimated probable home value given your inputs (illustrative only).</p>"
518
  f"<p>Confidence: <strong>{confidence}</strong></p>"
519
  f"</div>",
520
  unsafe_allow_html=True,
 
522
 
523
  st.subheader("How we estimate")
524
  st.write(
525
+ "We combine your desired budget, regional assumptions (if you supplied a location), "
526
+ "and timeline to produce a probable value. In production, MLS or public-record APIs "
527
+ "would provide more accurate estimates."
528
  )
529
 
530
  colA, colB = st.columns(2)
 
532
  st.markdown("**Input Budget**")
533
  st.markdown(f"${budget:,.0f}")
534
  with colB:
535
+ st.markdown("**Down Payment (approx)**")
536
  st.markdown(f"${round(budget * down_pct / 100):,.0f}")
537
 
538
  st.divider()
 
542
  st.button("⬅ Back", on_click=prev_step, key="back_7")
543
  with col2:
544
  if st.button("Finish & Save"):
545
+ st.success("Your plan summary has been saved (demo only). Refresh to start over.")