mimi111222 commited on
Commit
acd7bea
Β·
verified Β·
1 Parent(s): b3b7658

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +496 -214
app.py CHANGED
@@ -24,17 +24,17 @@ st.set_page_config(
24
  initial_sidebar_state="collapsed"
25
  )
26
 
27
- # Premium Black & Gold CSS Styling - CLEAN VERSION (NO BOXES)
28
  st.markdown("""
29
  <style>
30
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700;800&display=swap');
31
 
32
  * {
33
  font-family: 'Inter', sans-serif;
34
  }
35
 
36
  .stApp {
37
- background: linear-gradient(135deg, #0f0f0f 0%, #1a1a1a 50%, #0f0f0f 100%);
38
  }
39
 
40
  .main {
@@ -51,16 +51,19 @@ section[data-testid="stSidebar"] {
51
  display: none;
52
  }
53
 
54
- /* Hero Section */
55
  .hero-container {
56
  background: linear-gradient(135deg, #1a1a1a 0%, #0f0f0f 100%);
57
- border-radius: 28px;
58
- padding: 3.5rem 3rem;
59
- margin-bottom: 2.5rem;
60
- box-shadow: 0 25px 70px rgba(0,0,0,0.5), 0 10px 30px rgba(218,165,32,0.2);
 
 
 
61
  position: relative;
62
  overflow: hidden;
63
- border: 2px solid rgba(218,165,32,0.3);
64
  }
65
 
66
  .hero-container::before {
@@ -68,10 +71,16 @@ section[data-testid="stSidebar"] {
68
  position: absolute;
69
  top: -50%;
70
  right: -20%;
71
- width: 500px;
72
- height: 500px;
73
- background: radial-gradient(circle, rgba(218,165,32,0.15) 0%, transparent 70%);
74
  border-radius: 50%;
 
 
 
 
 
 
75
  }
76
 
77
  .hero-container::after {
@@ -79,75 +88,115 @@ section[data-testid="stSidebar"] {
79
  position: absolute;
80
  bottom: -30%;
81
  left: -10%;
82
- width: 400px;
83
- height: 400px;
84
- background: radial-gradient(circle, rgba(255,215,0,0.1) 0%, transparent 70%);
85
  border-radius: 50%;
86
  }
87
 
88
  .hero-title {
89
- font-size: 4rem;
90
  font-weight: 900;
91
  background: linear-gradient(135deg, #FFD700 0%, #FFA500 50%, #FFD700 100%);
92
  -webkit-background-clip: text;
93
  -webkit-text-fill-color: transparent;
94
- margin-bottom: 0.75rem;
95
  position: relative;
96
  z-index: 1;
97
- letter-spacing: -0.02em;
98
- filter: drop-shadow(0 4px 20px rgba(255,215,0,0.3));
 
99
  }
100
 
101
  .hero-subtitle {
102
- font-size: 1.35rem;
103
  color: #e5e7eb;
104
  font-weight: 500;
105
  margin-bottom: 1.5rem;
106
  position: relative;
107
  z-index: 1;
108
  line-height: 1.6;
 
 
 
 
 
 
 
 
 
 
109
  }
110
 
111
  .hero-badge {
112
  display: inline-block;
113
  background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
114
  color: #0f0f0f;
115
- padding: 0.7rem 2rem;
116
  border-radius: 50px;
117
- font-size: 1rem;
118
  font-weight: 700;
119
- margin-top: 1.5rem;
120
- box-shadow: 0 8px 25px rgba(255,215,0,0.4);
 
 
121
  position: relative;
122
  z-index: 1;
 
 
 
 
 
 
 
 
123
  }
124
 
125
- /* Section Headers - CLEAN TEXT ONLY */
126
  .section-title {
127
- font-size: 2rem;
128
- font-weight: 700;
129
- color: #FFD700;
130
- margin: 3rem 0 1.5rem 0;
 
 
131
  text-align: center;
132
  letter-spacing: 0.5px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  }
134
 
135
- /* Stats Grid */
136
  .stats-grid {
137
  display: grid;
138
- grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
139
- gap: 1.5rem;
140
- margin: 2rem 0;
141
  }
142
 
143
  .stat-card {
144
  background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
145
- padding: 2rem 1.5rem;
146
- border-radius: 20px;
147
  text-align: center;
148
  color: #0f0f0f;
149
- box-shadow: 0 10px 30px rgba(255,215,0,0.3);
150
- transition: all 0.3s ease;
 
 
 
151
  position: relative;
152
  overflow: hidden;
153
  }
@@ -159,191 +208,344 @@ section[data-testid="stSidebar"] {
159
  right: -50%;
160
  width: 200%;
161
  height: 200%;
162
- background: radial-gradient(circle, rgba(255,255,255,0.2) 0%, transparent 70%);
163
- transition: all 0.5s ease;
 
 
 
 
 
 
164
  }
165
 
166
  .stat-card:hover {
167
- transform: translateY(-8px) scale(1.02);
168
- box-shadow: 0 15px 40px rgba(255,215,0,0.5);
 
 
 
169
  }
170
 
171
  .stat-value {
172
- font-size: 3rem;
173
  font-weight: 900;
174
  margin-bottom: 0.5rem;
175
  position: relative;
176
  z-index: 1;
177
  color: #0f0f0f;
 
178
  }
179
 
180
  .stat-label {
181
  font-size: 0.95rem;
182
- font-weight: 600;
183
  opacity: 0.9;
184
  text-transform: uppercase;
185
- letter-spacing: 1.5px;
186
  position: relative;
187
  z-index: 1;
188
  color: #0f0f0f;
189
  }
190
 
191
- /* Input Areas */
192
  .stTextArea textarea {
193
- border-radius: 16px;
194
- border: 2px solid rgba(218,165,32,0.3);
195
- font-size: 1rem;
196
  transition: all 0.3s ease;
197
- background: #1a1a1a;
198
- color: #e5e7eb;
 
 
199
  }
200
 
201
  .stTextArea textarea:focus {
202
  border-color: #FFD700;
203
- box-shadow: 0 0 0 3px rgba(255,215,0,0.2);
 
204
  }
205
 
206
- /* Buttons */
207
  .stButton > button {
208
  background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
209
  color: #0f0f0f;
210
  border: none;
211
- border-radius: 12px;
212
- padding: 0.75rem 2.5rem;
213
- font-size: 1.1rem;
214
- font-weight: 600;
215
- transition: all 0.3s ease;
216
- box-shadow: 0 4px 15px rgba(255,215,0,0.4);
 
 
217
  width: 100%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  }
219
 
220
  .stButton > button:hover {
221
- transform: translateY(-2px);
222
- box-shadow: 0 6px 20px rgba(255,215,0,0.6);
 
 
 
 
 
 
223
  }
224
 
225
- /* Alert Boxes */
226
  .alert-danger {
227
  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
228
  color: white;
229
- padding: 1.5rem;
230
- border-radius: 16px;
231
  font-size: 1.1rem;
232
  font-weight: 600;
233
- box-shadow: 0 8px 24px rgba(239,68,68,0.3);
234
- margin: 1rem 0;
 
 
 
235
  }
236
 
237
  .alert-success {
238
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
239
  color: white;
240
- padding: 1.5rem;
241
- border-radius: 16px;
242
  font-size: 1.1rem;
243
  font-weight: 600;
244
- box-shadow: 0 8px 24px rgba(16,185,129,0.3);
245
- margin: 1rem 0;
 
 
 
246
  }
247
 
248
  .confidence-bar {
249
- height: 12px;
250
- background: rgba(255,255,255,0.3);
251
- border-radius: 10px;
252
  overflow: hidden;
253
- margin-top: 0.75rem;
 
254
  }
255
 
256
  .confidence-fill {
257
  height: 100%;
258
- background: rgba(255,255,255,0.9);
259
- border-radius: 10px;
260
- transition: width 1s ease;
 
261
  }
262
 
263
- /* Hints Panel */
264
  .hints-panel {
265
- background: linear-gradient(135deg, #1a1a1a 0%, #0f0f0f 100%);
266
- border-radius: 16px;
267
- padding: 1.5rem;
268
- border-left: 4px solid #FFD700;
269
- box-shadow: 0 4px 15px rgba(0,0,0,0.3);
 
 
 
270
  }
271
 
272
  .hint-item {
273
  display: flex;
274
  align-items: start;
275
- gap: 0.75rem;
276
- margin-bottom: 1rem;
277
- font-size: 0.95rem;
278
  color: #d1d5db;
 
279
  }
280
 
281
  .hint-icon {
282
- min-width: 24px;
283
- height: 24px;
284
- background: #FFD700;
285
  color: #0f0f0f;
286
  border-radius: 50%;
287
  display: flex;
288
  align-items: center;
289
  justify-content: center;
290
- font-size: 0.75rem;
291
- font-weight: 700;
 
292
  }
293
 
294
- /* Footer */
295
- .footer {
296
- background: linear-gradient(135deg, #1a1a1a 0%, #0f0f0f 100%);
 
297
  border-radius: 16px;
298
- padding: 2rem;
299
- text-align: center;
300
- margin-top: 3rem;
301
- color: #9ca3af;
302
- box-shadow: 0 8px 24px rgba(0,0,0,0.3);
303
- border: 2px solid rgba(218,165,32,0.2);
304
  }
305
 
306
- .footer-name {
307
- font-weight: 700;
308
- background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
309
- -webkit-background-clip: text;
310
- -webkit-text-fill-color: transparent;
311
  }
312
 
313
- /* File Uploader */
314
  .stFileUploader {
315
- border: 2px dashed rgba(218,165,32,0.4);
316
- border-radius: 16px;
317
- padding: 1.5rem;
318
- background: rgba(26,26,26,0.5);
319
  transition: all 0.3s ease;
320
  }
321
 
322
  .stFileUploader:hover {
323
  border-color: #FFD700;
324
- background: rgba(218,165,32,0.1);
 
325
  }
326
 
327
- /* Metric Cards */
328
- .metric-container {
329
- background: linear-gradient(135deg, #1a1a1a 0%, #0f0f0f 100%);
330
- padding: 1.25rem;
331
- border-radius: 12px;
332
- border-left: 4px solid #FFD700;
333
- box-shadow: 0 2px 8px rgba(0,0,0,0.3);
 
 
334
  }
335
 
336
- /* Expanders */
337
- .streamlit-expanderHeader {
338
- background: rgba(218,165,32,0.15);
339
- border-radius: 12px;
340
- font-weight: 600;
341
- color: #f5f5f5;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  }
343
 
344
  /* Hide Streamlit Branding */
345
  #MainMenu {visibility: hidden;}
346
  footer {visibility: hidden;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
  </style>
348
  """, unsafe_allow_html=True)
349
 
@@ -372,8 +574,8 @@ def preprocess_text(text):
372
  st.markdown("""
373
  <div class="hero-container">
374
  <div class="hero-title">πŸ›‘οΈ AI Phishing Shield</div>
375
- <div class="hero-subtitle">Advanced machine learning protection against email threats</div>
376
- <div style="color: #d1d5db; font-size: 1rem; line-height: 1.6;">
377
  Powered by TF-IDF vectorization and Logistic Regression, trained on thousands of real-world phishing examples.
378
  Get instant threat analysis with confidence scoring and explainable AI insights.
379
  </div>
@@ -523,7 +725,7 @@ with col1:
523
  st.markdown(f"""
524
  <div class="metric-container">
525
  <div style="color: #9ca3af; font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 0.5rem;">Accuracy</div>
526
- <div style="font-size: 2rem; font-weight: 800; color: #FFD700;">{accuracy:.1%}</div>
527
  </div>
528
  """, unsafe_allow_html=True)
529
 
@@ -532,7 +734,7 @@ with col2:
532
  st.markdown(f"""
533
  <div class="metric-container">
534
  <div style="color: #9ca3af; font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 0.5rem;">Precision</div>
535
- <div style="font-size: 2rem; font-weight: 800; color: #FFD700;">{precision:.1%}</div>
536
  </div>
537
  """, unsafe_allow_html=True)
538
 
@@ -541,36 +743,59 @@ with col3:
541
  st.markdown(f"""
542
  <div class="metric-container">
543
  <div style="color: #9ca3af; font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 0.5rem;">Recall</div>
544
- <div style="font-size: 2rem; font-weight: 800; color: #FFD700;">{recall:.1%}</div>
545
  </div>
546
  """, unsafe_allow_html=True)
547
 
 
548
  with st.expander("πŸ“ˆ Detailed Metrics & Confusion Matrix"):
549
- col_matrix, col_spacer = st.columns([1, 1.5])
550
 
551
  with col_matrix:
552
- fig, ax = plt.subplots(figsize=(4,3.5))
553
- sns.heatmap(
554
- model_info["confusion_matrix"],
555
- annot=True,
556
- fmt="d",
557
- ax=ax,
558
- cmap="YlOrBr",
559
- cbar=False,
560
- square=True,
561
- annot_kws={"size": 14, "weight": "bold"}
562
- )
563
- ax.set_xlabel("Predicted", fontsize=10, fontweight='bold')
564
- ax.set_ylabel("Actual", fontsize=10, fontweight='bold')
565
- ax.set_xticklabels(["Safe", "Phishing"], fontsize=9)
566
- ax.set_yticklabels(["Safe", "Phishing"], fontsize=9, rotation=0)
567
- ax.set_title("Confusion Matrix", fontsize=11, fontweight='bold', pad=10)
568
- plt.tight_layout()
569
- st.pyplot(fig)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
570
 
571
- st.write("**Classification Report:**")
572
- report_df = pd.DataFrame(model_info["report"]).transpose().round(3)
573
- st.dataframe(report_df, use_container_width=True, height=200)
 
 
 
 
 
574
 
575
  # Inference UI
576
  st.markdown('<div class="section-title">βœ‰οΈ Email Threat Scanner</div>', unsafe_allow_html=True)
@@ -580,7 +805,7 @@ col_input, col_hints = st.columns([2, 1])
580
  with col_input:
581
  email_input = st.text_area(
582
  "Paste email content for analysis",
583
- height=250,
584
  placeholder="Example: Urgent! Your account has been compromised. Click here to verify your identity immediately...",
585
  help="Paste the full email content including subject and body"
586
  )
@@ -597,77 +822,82 @@ with col_input:
597
  if not email_input.strip():
598
  st.warning("⚠️ Please paste or upload email content to analyze")
599
  else:
600
- processed_input = preprocess_text(email_input)
601
- input_vec = vectorizer.transform([processed_input])
602
-
603
- try:
604
- proba = model.predict_proba(input_vec)[0][1]
605
- except Exception:
606
  try:
607
- score = model.decision_function(input_vec)[0]
608
- proba = 1/(1+np.exp(-score))
609
  except Exception:
610
- proba = None
611
-
612
- pred = model.predict(input_vec)[0]
613
-
614
- if pred == 1:
615
- conf_pct = f"{proba:.1%}" if proba is not None else "N/A"
616
- st.markdown(f"""
617
- <div class="alert-danger">
618
- <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 0.75rem;">
619
- <div style="font-size: 2.5rem;">⚠️</div>
620
- <div>
621
- <div style="font-size: 1.4rem; font-weight: 800;">PHISHING DETECTED</div>
622
- <div style="font-size: 1rem; opacity: 0.95;">Threat Confidence: {conf_pct}</div>
 
 
 
 
 
 
 
 
623
  </div>
624
  </div>
625
- <div class="confidence-bar">
626
- <div class="confidence-fill" style="width: {proba*100 if proba else 0}%;"></div>
627
- </div>
628
- </div>
629
- """, unsafe_allow_html=True)
630
-
631
- st.markdown("**πŸ” Threat Indicators Detected:**")
632
- indicators = []
633
- if "url" in processed_input:
634
- indicators.append("πŸ”— Suspicious URL tokens detected")
635
- if re.search(r'\b(urgent|immediately|verify|password|suspended|click|act now)\b', processed_input):
636
- indicators.append("⚑ Urgency manipulation tactics")
637
- if re.search(r'\b(bank|account|verify|login|password|security|credential)\b', processed_input):
638
- indicators.append("🏦 Financial/security keywords present")
639
- if re.search(r'\b(winner|prize|congratulations|claim|free)\b', processed_input):
640
- indicators.append("🎁 Reward/prize baiting language")
641
-
642
- for indicator in indicators:
643
- st.markdown(f"- {indicator}")
644
-
645
- if not indicators:
646
- st.markdown("- ⚠️ Content pattern matches known phishing templates")
647
 
648
- else:
649
- conf_pct = f"{(1-proba):.1%}" if proba is not None else "N/A"
650
- st.markdown(f"""
651
- <div class="alert-success">
652
- <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 0.75rem;">
653
- <div style="font-size: 2.5rem;">βœ…</div>
654
- <div>
655
- <div style="font-size: 1.4rem; font-weight: 800;">EMAIL APPEARS SAFE</div>
656
- <div style="font-size: 1rem; opacity: 0.95;">Safety Confidence: {conf_pct}</div>
 
 
 
 
 
 
 
 
 
 
 
 
657
  </div>
658
  </div>
659
- <div class="confidence-bar">
660
- <div class="confidence-fill" style="width: {(1-proba)*100 if proba else 100}%;"></div>
661
- </div>
662
- </div>
663
- """, unsafe_allow_html=True)
664
- st.markdown("**βœ“ No obvious threat indicators found in content analysis**")
665
- st.info("πŸ’‘ Remember: Always verify sender identity and be cautious with unexpected emails, even if they appear safe.")
666
 
667
  with col_hints:
668
  st.markdown("""
669
  <div class="hints-panel">
670
- <div style="font-weight: 700; font-size: 1.1rem; margin-bottom: 1rem; color: #f5f5f5;">🧠 AI Detection Insights</div>
671
 
672
  <div class="hint-item">
673
  <div class="hint-icon">1</div>
@@ -689,6 +919,11 @@ with col_hints:
689
  <div>Confidence <strong>>70%</strong> warrants immediate caution</div>
690
  </div>
691
 
 
 
 
 
 
692
  <div class="hint-item">
693
  <div class="hint-icon">⚠️</div>
694
  <div><strong>Limitations:</strong> This tool analyzes text content only. Always verify sender identity separately.</div>
@@ -696,18 +931,65 @@ with col_hints:
696
  </div>
697
  """, unsafe_allow_html=True)
698
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
699
  # Footer
700
  st.markdown("""
701
  <div class="footer">
702
- <div style="font-size: 1.1rem; margin-bottom: 0.5rem;">
703
  Developed and Deployed by <span class="footer-name">Umaima Qureshi</span>
704
  </div>
705
- <div style="font-size: 0.9rem; color: #94a3b8;">
706
  πŸŽ“ Educational demonstration of ML-powered email security<br>
707
  For production use: Implement additional verification layers, link scanning, attachment analysis, and human oversight
708
  </div>
709
- <div style="margin-top: 1rem; font-size: 0.85rem; color: #6b7280;">
710
  Powered by TF-IDF β€’ Logistic Regression β€’ Scikit-learn β€’ Streamlit
711
  </div>
 
 
 
712
  </div>
713
  """, unsafe_allow_html=True)
 
24
  initial_sidebar_state="collapsed"
25
  )
26
 
27
+ # Premium Black & Gold CSS Styling - ENHANCED VERSION
28
  st.markdown("""
29
  <style>
30
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700;800;900&display=swap');
31
 
32
  * {
33
  font-family: 'Inter', sans-serif;
34
  }
35
 
36
  .stApp {
37
+ background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0a0a0a 100%);
38
  }
39
 
40
  .main {
 
51
  display: none;
52
  }
53
 
54
+ /* Hero Section - Enhanced */
55
  .hero-container {
56
  background: linear-gradient(135deg, #1a1a1a 0%, #0f0f0f 100%);
57
+ border-radius: 32px;
58
+ padding: 4rem 3rem;
59
+ margin-bottom: 3rem;
60
+ box-shadow:
61
+ 0 25px 70px rgba(0,0,0,0.6),
62
+ 0 10px 30px rgba(218,165,32,0.25),
63
+ inset 0 1px 0 rgba(255,255,255,0.1);
64
  position: relative;
65
  overflow: hidden;
66
+ border: 2px solid rgba(218,165,32,0.4);
67
  }
68
 
69
  .hero-container::before {
 
71
  position: absolute;
72
  top: -50%;
73
  right: -20%;
74
+ width: 600px;
75
+ height: 600px;
76
+ background: radial-gradient(circle, rgba(218,165,32,0.2) 0%, transparent 70%);
77
  border-radius: 50%;
78
+ animation: pulse 8s ease-in-out infinite;
79
+ }
80
+
81
+ @keyframes pulse {
82
+ 0%, 100% { transform: scale(1); opacity: 0.3; }
83
+ 50% { transform: scale(1.1); opacity: 0.5; }
84
  }
85
 
86
  .hero-container::after {
 
88
  position: absolute;
89
  bottom: -30%;
90
  left: -10%;
91
+ width: 500px;
92
+ height: 500px;
93
+ background: radial-gradient(circle, rgba(255,215,0,0.15) 0%, transparent 70%);
94
  border-radius: 50%;
95
  }
96
 
97
  .hero-title {
98
+ font-size: 4.5rem;
99
  font-weight: 900;
100
  background: linear-gradient(135deg, #FFD700 0%, #FFA500 50%, #FFD700 100%);
101
  -webkit-background-clip: text;
102
  -webkit-text-fill-color: transparent;
103
+ margin-bottom: 1rem;
104
  position: relative;
105
  z-index: 1;
106
+ letter-spacing: -0.03em;
107
+ filter: drop-shadow(0 4px 20px rgba(255,215,0,0.4));
108
+ text-shadow: 0 0 80px rgba(255,215,0,0.3);
109
  }
110
 
111
  .hero-subtitle {
112
+ font-size: 1.45rem;
113
  color: #e5e7eb;
114
  font-weight: 500;
115
  margin-bottom: 1.5rem;
116
  position: relative;
117
  z-index: 1;
118
  line-height: 1.6;
119
+ letter-spacing: 0.3px;
120
+ }
121
+
122
+ .hero-description {
123
+ color: #d1d5db;
124
+ font-size: 1.05rem;
125
+ line-height: 1.7;
126
+ position: relative;
127
+ z-index: 1;
128
+ max-width: 900px;
129
  }
130
 
131
  .hero-badge {
132
  display: inline-block;
133
  background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
134
  color: #0f0f0f;
135
+ padding: 0.8rem 2.5rem;
136
  border-radius: 50px;
137
+ font-size: 1.05rem;
138
  font-weight: 700;
139
+ margin-top: 1.8rem;
140
+ box-shadow:
141
+ 0 8px 25px rgba(255,215,0,0.5),
142
+ 0 0 40px rgba(255,215,0,0.3);
143
  position: relative;
144
  z-index: 1;
145
+ transition: all 0.3s ease;
146
+ }
147
+
148
+ .hero-badge:hover {
149
+ transform: translateY(-2px);
150
+ box-shadow:
151
+ 0 12px 35px rgba(255,215,0,0.6),
152
+ 0 0 50px rgba(255,215,0,0.4);
153
  }
154
 
155
+ /* Section Headers */
156
  .section-title {
157
+ font-size: 2.2rem;
158
+ font-weight: 800;
159
+ background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
160
+ -webkit-background-clip: text;
161
+ -webkit-text-fill-color: transparent;
162
+ margin: 3.5rem 0 2rem 0;
163
  text-align: center;
164
  letter-spacing: 0.5px;
165
+ position: relative;
166
+ padding-bottom: 1rem;
167
+ }
168
+
169
+ .section-title::after {
170
+ content: '';
171
+ position: absolute;
172
+ bottom: 0;
173
+ left: 50%;
174
+ transform: translateX(-50%);
175
+ width: 100px;
176
+ height: 4px;
177
+ background: linear-gradient(90deg, transparent, #FFD700, transparent);
178
+ border-radius: 2px;
179
  }
180
 
181
+ /* Stats Grid - Enhanced */
182
  .stats-grid {
183
  display: grid;
184
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
185
+ gap: 1.8rem;
186
+ margin: 2.5rem 0;
187
  }
188
 
189
  .stat-card {
190
  background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
191
+ padding: 2.5rem 1.8rem;
192
+ border-radius: 24px;
193
  text-align: center;
194
  color: #0f0f0f;
195
+ box-shadow:
196
+ 0 10px 30px rgba(255,215,0,0.35),
197
+ 0 0 40px rgba(255,215,0,0.2),
198
+ inset 0 1px 0 rgba(255,255,255,0.3);
199
+ transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
200
  position: relative;
201
  overflow: hidden;
202
  }
 
208
  right: -50%;
209
  width: 200%;
210
  height: 200%;
211
+ background: radial-gradient(circle, rgba(255,255,255,0.25) 0%, transparent 70%);
212
+ transition: all 0.6s ease;
213
+ opacity: 0;
214
+ }
215
+
216
+ .stat-card:hover::before {
217
+ opacity: 1;
218
+ transform: translate(-25%, -25%);
219
  }
220
 
221
  .stat-card:hover {
222
+ transform: translateY(-10px) scale(1.03);
223
+ box-shadow:
224
+ 0 20px 50px rgba(255,215,0,0.5),
225
+ 0 0 60px rgba(255,215,0,0.3),
226
+ inset 0 1px 0 rgba(255,255,255,0.4);
227
  }
228
 
229
  .stat-value {
230
+ font-size: 3.5rem;
231
  font-weight: 900;
232
  margin-bottom: 0.5rem;
233
  position: relative;
234
  z-index: 1;
235
  color: #0f0f0f;
236
+ text-shadow: 0 2px 4px rgba(0,0,0,0.1);
237
  }
238
 
239
  .stat-label {
240
  font-size: 0.95rem;
241
+ font-weight: 700;
242
  opacity: 0.9;
243
  text-transform: uppercase;
244
+ letter-spacing: 1.8px;
245
  position: relative;
246
  z-index: 1;
247
  color: #0f0f0f;
248
  }
249
 
250
+ /* Input Areas - Enhanced */
251
  .stTextArea textarea {
252
+ border-radius: 18px;
253
+ border: 2px solid rgba(218,165,32,0.35);
254
+ font-size: 1.05rem;
255
  transition: all 0.3s ease;
256
+ background: rgba(26,26,26,0.8) !important;
257
+ color: #e5e7eb !important;
258
+ padding: 1rem !important;
259
+ line-height: 1.6 !important;
260
  }
261
 
262
  .stTextArea textarea:focus {
263
  border-color: #FFD700;
264
+ box-shadow: 0 0 0 4px rgba(255,215,0,0.15);
265
+ background: rgba(26,26,26,0.95) !important;
266
  }
267
 
268
+ /* Buttons - Enhanced */
269
  .stButton > button {
270
  background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
271
  color: #0f0f0f;
272
  border: none;
273
+ border-radius: 14px;
274
+ padding: 0.9rem 2.8rem;
275
+ font-size: 1.15rem;
276
+ font-weight: 700;
277
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
278
+ box-shadow:
279
+ 0 4px 15px rgba(255,215,0,0.4),
280
+ 0 0 30px rgba(255,215,0,0.2);
281
  width: 100%;
282
+ letter-spacing: 0.5px;
283
+ position: relative;
284
+ overflow: hidden;
285
+ }
286
+
287
+ .stButton > button::before {
288
+ content: '';
289
+ position: absolute;
290
+ top: 50%;
291
+ left: 50%;
292
+ width: 0;
293
+ height: 0;
294
+ border-radius: 50%;
295
+ background: rgba(255,255,255,0.3);
296
+ transform: translate(-50%, -50%);
297
+ transition: width 0.6s, height 0.6s;
298
+ }
299
+
300
+ .stButton > button:hover::before {
301
+ width: 300px;
302
+ height: 300px;
303
  }
304
 
305
  .stButton > button:hover {
306
+ transform: translateY(-3px);
307
+ box-shadow:
308
+ 0 8px 25px rgba(255,215,0,0.6),
309
+ 0 0 50px rgba(255,215,0,0.3);
310
+ }
311
+
312
+ .stButton > button:active {
313
+ transform: translateY(-1px);
314
  }
315
 
316
+ /* Alert Boxes - Enhanced */
317
  .alert-danger {
318
  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
319
  color: white;
320
+ padding: 2rem;
321
+ border-radius: 20px;
322
  font-size: 1.1rem;
323
  font-weight: 600;
324
+ box-shadow:
325
+ 0 10px 30px rgba(239,68,68,0.4),
326
+ 0 0 50px rgba(239,68,68,0.2);
327
+ margin: 1.5rem 0;
328
+ border: 2px solid rgba(255,255,255,0.1);
329
  }
330
 
331
  .alert-success {
332
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
333
  color: white;
334
+ padding: 2rem;
335
+ border-radius: 20px;
336
  font-size: 1.1rem;
337
  font-weight: 600;
338
+ box-shadow:
339
+ 0 10px 30px rgba(16,185,129,0.4),
340
+ 0 0 50px rgba(16,185,129,0.2);
341
+ margin: 1.5rem 0;
342
+ border: 2px solid rgba(255,255,255,0.1);
343
  }
344
 
345
  .confidence-bar {
346
+ height: 14px;
347
+ background: rgba(255,255,255,0.25);
348
+ border-radius: 12px;
349
  overflow: hidden;
350
+ margin-top: 1rem;
351
+ box-shadow: inset 0 2px 4px rgba(0,0,0,0.2);
352
  }
353
 
354
  .confidence-fill {
355
  height: 100%;
356
+ background: rgba(255,255,255,0.95);
357
+ border-radius: 12px;
358
+ transition: width 1.2s cubic-bezier(0.4, 0, 0.2, 1);
359
+ box-shadow: 0 0 10px rgba(255,255,255,0.5);
360
  }
361
 
362
+ /* Hints Panel - Enhanced */
363
  .hints-panel {
364
+ background: linear-gradient(135deg, rgba(26,26,26,0.95) 0%, rgba(15,15,15,0.95) 100%);
365
+ border-radius: 20px;
366
+ padding: 2rem;
367
+ border-left: 5px solid #FFD700;
368
+ box-shadow:
369
+ 0 4px 15px rgba(0,0,0,0.4),
370
+ inset 0 1px 0 rgba(255,255,255,0.05);
371
+ backdrop-filter: blur(10px);
372
  }
373
 
374
  .hint-item {
375
  display: flex;
376
  align-items: start;
377
+ gap: 1rem;
378
+ margin-bottom: 1.2rem;
379
+ font-size: 0.98rem;
380
  color: #d1d5db;
381
+ line-height: 1.6;
382
  }
383
 
384
  .hint-icon {
385
+ min-width: 28px;
386
+ height: 28px;
387
+ background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
388
  color: #0f0f0f;
389
  border-radius: 50%;
390
  display: flex;
391
  align-items: center;
392
  justify-content: center;
393
+ font-size: 0.8rem;
394
+ font-weight: 800;
395
+ box-shadow: 0 2px 8px rgba(255,215,0,0.4);
396
  }
397
 
398
+ /* Metric Cards - Enhanced */
399
+ .metric-container {
400
+ background: linear-gradient(135deg, rgba(26,26,26,0.95) 0%, rgba(15,15,15,0.95) 100%);
401
+ padding: 1.8rem;
402
  border-radius: 16px;
403
+ border-left: 5px solid #FFD700;
404
+ box-shadow:
405
+ 0 4px 12px rgba(0,0,0,0.4),
406
+ inset 0 1px 0 rgba(255,255,255,0.05);
407
+ transition: all 0.3s ease;
 
408
  }
409
 
410
+ .metric-container:hover {
411
+ transform: translateY(-2px);
412
+ box-shadow:
413
+ 0 6px 18px rgba(0,0,0,0.5),
414
+ inset 0 1px 0 rgba(255,255,255,0.08);
415
  }
416
 
417
+ /* File Uploader - Enhanced */
418
  .stFileUploader {
419
+ border: 2px dashed rgba(218,165,32,0.45);
420
+ border-radius: 18px;
421
+ padding: 2rem;
422
+ background: rgba(26,26,26,0.6);
423
  transition: all 0.3s ease;
424
  }
425
 
426
  .stFileUploader:hover {
427
  border-color: #FFD700;
428
+ background: rgba(218,165,32,0.12);
429
+ box-shadow: 0 0 20px rgba(255,215,0,0.15);
430
  }
431
 
432
+ /* Expanders - Enhanced */
433
+ .streamlit-expanderHeader {
434
+ background: linear-gradient(135deg, rgba(218,165,32,0.2) 0%, rgba(218,165,32,0.1) 100%) !important;
435
+ border-radius: 14px !important;
436
+ font-weight: 700 !important;
437
+ color: #f5f5f5 !important;
438
+ border: 1px solid rgba(218,165,32,0.3) !important;
439
+ padding: 1rem 1.5rem !important;
440
+ transition: all 0.3s ease !important;
441
  }
442
 
443
+ .streamlit-expanderHeader:hover {
444
+ background: linear-gradient(135deg, rgba(218,165,32,0.25) 0%, rgba(218,165,32,0.15) 100%) !important;
445
+ border-color: rgba(218,165,32,0.5) !important;
446
+ }
447
+
448
+ /* Dataframe Styling */
449
+ .stDataFrame {
450
+ background: rgba(26,26,26,0.95) !important;
451
+ border-radius: 12px !important;
452
+ overflow: hidden !important;
453
+ }
454
+
455
+ .stDataFrame [data-testid="stDataFrameResizable"] {
456
+ background: rgba(26,26,26,0.95) !important;
457
+ }
458
+
459
+ .stDataFrame table {
460
+ background: rgba(26,26,26,0.95) !important;
461
+ color: #e5e7eb !important;
462
+ }
463
+
464
+ .stDataFrame thead tr th {
465
+ background: rgba(218,165,32,0.2) !important;
466
+ color: #FFD700 !important;
467
+ font-weight: 700 !important;
468
+ border-bottom: 2px solid rgba(218,165,32,0.4) !important;
469
+ }
470
+
471
+ .stDataFrame tbody tr {
472
+ background: rgba(26,26,26,0.8) !important;
473
+ border-bottom: 1px solid rgba(255,255,255,0.05) !important;
474
+ }
475
+
476
+ .stDataFrame tbody tr:hover {
477
+ background: rgba(218,165,32,0.1) !important;
478
+ }
479
+
480
+ .stDataFrame tbody tr td {
481
+ color: #d1d5db !important;
482
+ }
483
+
484
+ /* Info/Warning boxes */
485
+ .stAlert {
486
+ background: rgba(26,26,26,0.9) !important;
487
+ border-radius: 12px !important;
488
+ border-left: 4px solid #FFD700 !important;
489
+ color: #e5e7eb !important;
490
+ }
491
+
492
+ /* Footer - Enhanced */
493
+ .footer {
494
+ background: linear-gradient(135deg, rgba(26,26,26,0.95) 0%, rgba(15,15,15,0.95) 100%);
495
+ border-radius: 20px;
496
+ padding: 2.5rem;
497
+ text-align: center;
498
+ margin-top: 4rem;
499
+ color: #9ca3af;
500
+ box-shadow:
501
+ 0 8px 24px rgba(0,0,0,0.4),
502
+ inset 0 1px 0 rgba(255,255,255,0.05);
503
+ border: 2px solid rgba(218,165,32,0.3);
504
+ }
505
+
506
+ .footer-name {
507
+ font-weight: 800;
508
+ background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
509
+ -webkit-background-clip: text;
510
+ -webkit-text-fill-color: transparent;
511
+ font-size: 1.1rem;
512
+ }
513
+
514
+ /* Matplotlib figure styling */
515
+ .stPlotlyChart, .stPyplot {
516
+ background: rgba(26,26,26,0.6) !important;
517
+ border-radius: 12px !important;
518
+ padding: 1rem !important;
519
  }
520
 
521
  /* Hide Streamlit Branding */
522
  #MainMenu {visibility: hidden;}
523
  footer {visibility: hidden;}
524
+ header {visibility: hidden;}
525
+
526
+ /* Smooth scrolling */
527
+ html {
528
+ scroll-behavior: smooth;
529
+ }
530
+
531
+ /* Custom scrollbar */
532
+ ::-webkit-scrollbar {
533
+ width: 10px;
534
+ height: 10px;
535
+ }
536
+
537
+ ::-webkit-scrollbar-track {
538
+ background: #1a1a1a;
539
+ }
540
+
541
+ ::-webkit-scrollbar-thumb {
542
+ background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
543
+ border-radius: 5px;
544
+ }
545
+
546
+ ::-webkit-scrollbar-thumb:hover {
547
+ background: linear-gradient(135deg, #FFA500 0%, #FFD700 100%);
548
+ }
549
  </style>
550
  """, unsafe_allow_html=True)
551
 
 
574
  st.markdown("""
575
  <div class="hero-container">
576
  <div class="hero-title">πŸ›‘οΈ AI Phishing Shield</div>
577
+ <div class="hero-subtitle">Advanced Machine Learning Protection Against Email Threats</div>
578
+ <div class="hero-description">
579
  Powered by TF-IDF vectorization and Logistic Regression, trained on thousands of real-world phishing examples.
580
  Get instant threat analysis with confidence scoring and explainable AI insights.
581
  </div>
 
725
  st.markdown(f"""
726
  <div class="metric-container">
727
  <div style="color: #9ca3af; font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 0.5rem;">Accuracy</div>
728
+ <div style="font-size: 2.5rem; font-weight: 900; color: #FFD700;">{accuracy:.1%}</div>
729
  </div>
730
  """, unsafe_allow_html=True)
731
 
 
734
  st.markdown(f"""
735
  <div class="metric-container">
736
  <div style="color: #9ca3af; font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 0.5rem;">Precision</div>
737
+ <div style="font-size: 2.5rem; font-weight: 900; color: #FFD700;">{precision:.1%}</div>
738
  </div>
739
  """, unsafe_allow_html=True)
740
 
 
743
  st.markdown(f"""
744
  <div class="metric-container">
745
  <div style="color: #9ca3af; font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 0.5rem;">Recall</div>
746
+ <div style="font-size: 2.5rem; font-weight: 900; color: #FFD700;">{recall:.1%}</div>
747
  </div>
748
  """, unsafe_allow_html=True)
749
 
750
+ # Fixed Confusion Matrix Section - No re-rendering
751
  with st.expander("πŸ“ˆ Detailed Metrics & Confusion Matrix"):
752
+ col_matrix, col_report = st.columns([1, 1.5])
753
 
754
  with col_matrix:
755
+ # Use container to prevent re-rendering
756
+ with st.container():
757
+ # Set dark theme for matplotlib
758
+ plt.style.use('dark_background')
759
+ fig, ax = plt.subplots(figsize=(5, 4), facecolor='#1a1a1a')
760
+ ax.set_facecolor('#1a1a1a')
761
+
762
+ sns.heatmap(
763
+ model_info["confusion_matrix"],
764
+ annot=True,
765
+ fmt="d",
766
+ ax=ax,
767
+ cmap="YlOrBr",
768
+ cbar=True,
769
+ square=True,
770
+ annot_kws={"size": 16, "weight": "bold", "color": "#0f0f0f"},
771
+ linewidths=2,
772
+ linecolor='#0f0f0f',
773
+ cbar_kws={'label': 'Count', 'shrink': 0.8}
774
+ )
775
+
776
+ ax.set_xlabel("Predicted", fontsize=11, fontweight='bold', color='#FFD700')
777
+ ax.set_ylabel("Actual", fontsize=11, fontweight='bold', color='#FFD700')
778
+ ax.set_xticklabels(["Safe", "Phishing"], fontsize=10, color='#e5e7eb')
779
+ ax.set_yticklabels(["Safe", "Phishing"], fontsize=10, rotation=0, color='#e5e7eb')
780
+ ax.set_title("Confusion Matrix", fontsize=13, fontweight='bold', pad=12, color='#FFD700')
781
+
782
+ # Style the colorbar
783
+ cbar = ax.collections[0].colorbar
784
+ cbar.ax.yaxis.set_tick_params(color='#e5e7eb')
785
+ plt.setp(plt.getp(cbar.ax.axes, 'yticklabels'), color='#e5e7eb')
786
+
787
+ plt.tight_layout()
788
+ st.pyplot(fig, use_container_width=True)
789
+ plt.close(fig) # Close figure to prevent memory leak
790
 
791
+ with col_report:
792
+ st.markdown("**πŸ“Š Classification Report:**")
793
+ report_df = pd.DataFrame(model_info["report"]).transpose().round(3)
794
+ st.dataframe(
795
+ report_df,
796
+ use_container_width=True,
797
+ height=250
798
+ )
799
 
800
  # Inference UI
801
  st.markdown('<div class="section-title">βœ‰οΈ Email Threat Scanner</div>', unsafe_allow_html=True)
 
805
  with col_input:
806
  email_input = st.text_area(
807
  "Paste email content for analysis",
808
+ height=280,
809
  placeholder="Example: Urgent! Your account has been compromised. Click here to verify your identity immediately...",
810
  help="Paste the full email content including subject and body"
811
  )
 
822
  if not email_input.strip():
823
  st.warning("⚠️ Please paste or upload email content to analyze")
824
  else:
825
+ with st.spinner("πŸ” Analyzing email threat..."):
826
+ processed_input = preprocess_text(email_input)
827
+ input_vec = vectorizer.transform([processed_input])
828
+
 
 
829
  try:
830
+ proba = model.predict_proba(input_vec)[0][1]
 
831
  except Exception:
832
+ try:
833
+ score = model.decision_function(input_vec)[0]
834
+ proba = 1/(1+np.exp(-score))
835
+ except Exception:
836
+ proba = None
837
+
838
+ pred = model.predict(input_vec)[0]
839
+
840
+ if pred == 1:
841
+ conf_pct = f"{proba:.1%}" if proba is not None else "N/A"
842
+ st.markdown(f"""
843
+ <div class="alert-danger">
844
+ <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 0.75rem;">
845
+ <div style="font-size: 2.5rem;">⚠️</div>
846
+ <div>
847
+ <div style="font-size: 1.5rem; font-weight: 800; letter-spacing: 0.5px;">PHISHING DETECTED</div>
848
+ <div style="font-size: 1.05rem; opacity: 0.95; margin-top: 0.25rem;">Threat Confidence: {conf_pct}</div>
849
+ </div>
850
+ </div>
851
+ <div class="confidence-bar">
852
+ <div class="confidence-fill" style="width: {proba*100 if proba else 0}%;"></div>
853
  </div>
854
  </div>
855
+ """, unsafe_allow_html=True)
856
+
857
+ st.markdown("**πŸ” Threat Indicators Detected:**")
858
+ indicators = []
859
+ if "url" in processed_input:
860
+ indicators.append("πŸ”— Suspicious URL tokens detected")
861
+ if re.search(r'\b(urgent|immediately|verify|password|suspended|click|act now|action required)\b', processed_input):
862
+ indicators.append("⚑ Urgency manipulation tactics")
863
+ if re.search(r'\b(bank|account|verify|login|password|security|credential|paypal)\b', processed_input):
864
+ indicators.append("🏦 Financial/security keywords present")
865
+ if re.search(r'\b(winner|prize|congratulations|claim|free|won)\b', processed_input):
866
+ indicators.append("🎁 Reward/prize baiting language")
867
+ if re.search(r'\b(confirm|update|validate|unlock|restore)\b', processed_input):
868
+ indicators.append("πŸ” Account action requests")
 
 
 
 
 
 
 
 
869
 
870
+ for indicator in indicators:
871
+ st.markdown(f"- {indicator}")
872
+
873
+ if not indicators:
874
+ st.markdown("- ⚠️ Content pattern matches known phishing templates")
875
+
876
+ st.error("🚨 **Recommendation:** Do NOT click any links. Delete this email immediately and report to your IT security team.")
877
+
878
+ else:
879
+ conf_pct = f"{(1-proba):.1%}" if proba is not None else "N/A"
880
+ st.markdown(f"""
881
+ <div class="alert-success">
882
+ <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 0.75rem;">
883
+ <div style="font-size: 2.5rem;">βœ…</div>
884
+ <div>
885
+ <div style="font-size: 1.5rem; font-weight: 800; letter-spacing: 0.5px;">EMAIL APPEARS SAFE</div>
886
+ <div style="font-size: 1.05rem; opacity: 0.95; margin-top: 0.25rem;">Safety Confidence: {conf_pct}</div>
887
+ </div>
888
+ </div>
889
+ <div class="confidence-bar">
890
+ <div class="confidence-fill" style="width: {(1-proba)*100 if proba else 100}%;"></div>
891
  </div>
892
  </div>
893
+ """, unsafe_allow_html=True)
894
+ st.markdown("**βœ“ No obvious threat indicators found in content analysis**")
895
+ st.info("πŸ’‘ **Best Practice:** Always verify sender identity through known contact methods and be cautious with unexpected emails, even if they appear safe.")
 
 
 
 
896
 
897
  with col_hints:
898
  st.markdown("""
899
  <div class="hints-panel">
900
+ <div style="font-weight: 700; font-size: 1.15rem; margin-bottom: 1.2rem; color: #f5f5f5;">🧠 AI Detection Insights</div>
901
 
902
  <div class="hint-item">
903
  <div class="hint-icon">1</div>
 
919
  <div>Confidence <strong>>70%</strong> warrants immediate caution</div>
920
  </div>
921
 
922
+ <div class="hint-item">
923
+ <div class="hint-icon">5</div>
924
+ <div><strong>Prize/reward</strong> language is a common phishing tactic</div>
925
+ </div>
926
+
927
  <div class="hint-item">
928
  <div class="hint-icon">⚠️</div>
929
  <div><strong>Limitations:</strong> This tool analyzes text content only. Always verify sender identity separately.</div>
 
931
  </div>
932
  """, unsafe_allow_html=True)
933
 
934
+ # Additional Tips Section
935
+ st.markdown('<div class="section-title">πŸ’‘ Phishing Protection Tips</div>', unsafe_allow_html=True)
936
+
937
+ col_tip1, col_tip2, col_tip3 = st.columns(3)
938
+
939
+ with col_tip1:
940
+ st.markdown("""
941
+ <div style="background: linear-gradient(135deg, rgba(26,26,26,0.95) 0%, rgba(15,15,15,0.95) 100%);
942
+ padding: 1.5rem; border-radius: 16px; border-left: 4px solid #FFD700;
943
+ box-shadow: 0 4px 15px rgba(0,0,0,0.3); height: 100%;">
944
+ <div style="font-size: 2rem; margin-bottom: 0.75rem;">πŸ”</div>
945
+ <div style="font-weight: 700; font-size: 1.1rem; color: #FFD700; margin-bottom: 0.75rem;">Verify Sender</div>
946
+ <div style="color: #d1d5db; font-size: 0.95rem; line-height: 1.6;">
947
+ Always check the sender's email address carefully. Phishers often use addresses that look similar to legitimate ones.
948
+ </div>
949
+ </div>
950
+ """, unsafe_allow_html=True)
951
+
952
+ with col_tip2:
953
+ st.markdown("""
954
+ <div style="background: linear-gradient(135deg, rgba(26,26,26,0.95) 0%, rgba(15,15,15,0.95) 100%);
955
+ padding: 1.5rem; border-radius: 16px; border-left: 4px solid #FFD700;
956
+ box-shadow: 0 4px 15px rgba(0,0,0,0.3); height: 100%;">
957
+ <div style="font-size: 2rem; margin-bottom: 0.75rem;">πŸ”—</div>
958
+ <div style="font-weight: 700; font-size: 1.1rem; color: #FFD700; margin-bottom: 0.75rem;">Hover Links</div>
959
+ <div style="color: #d1d5db; font-size: 0.95rem; line-height: 1.6;">
960
+ Hover over links (don't click!) to see the actual URL. Legitimate companies use their official domains.
961
+ </div>
962
+ </div>
963
+ """, unsafe_allow_html=True)
964
+
965
+ with col_tip3:
966
+ st.markdown("""
967
+ <div style="background: linear-gradient(135deg, rgba(26,26,26,0.95) 0%, rgba(15,15,15,0.95) 100%);
968
+ padding: 1.5rem; border-radius: 16px; border-left: 4px solid #FFD700;
969
+ box-shadow: 0 4px 15px rgba(0,0,0,0.3); height: 100%;">
970
+ <div style="font-size: 2rem; margin-bottom: 0.75rem;">πŸ“ž</div>
971
+ <div style="font-weight: 700; font-size: 1.1rem; color: #FFD700; margin-bottom: 0.75rem;">Contact Directly</div>
972
+ <div style="color: #d1d5db; font-size: 0.95rem; line-height: 1.6;">
973
+ When in doubt, contact the company directly using official contact information, not the email's links.
974
+ </div>
975
+ </div>
976
+ """, unsafe_allow_html=True)
977
+
978
  # Footer
979
  st.markdown("""
980
  <div class="footer">
981
+ <div style="font-size: 1.2rem; margin-bottom: 0.75rem; font-weight: 700;">
982
  Developed and Deployed by <span class="footer-name">Umaima Qureshi</span>
983
  </div>
984
+ <div style="font-size: 1rem; color: #94a3b8; margin-bottom: 1rem; line-height: 1.6;">
985
  πŸŽ“ Educational demonstration of ML-powered email security<br>
986
  For production use: Implement additional verification layers, link scanning, attachment analysis, and human oversight
987
  </div>
988
+ <div style="margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid rgba(218,165,32,0.2); font-size: 0.9rem; color: #6b7280;">
989
  Powered by TF-IDF β€’ Logistic Regression β€’ Scikit-learn β€’ Streamlit
990
  </div>
991
+ <div style="margin-top: 1rem; font-size: 0.85rem; color: #6b7280;">
992
+ Β© 2024 AI Phishing Shield | All Rights Reserved
993
+ </div>
994
  </div>
995
  """, unsafe_allow_html=True)