Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .streamlit/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Native Streamlit widgets share the mark.dev after-dark palette with ui_theme.py
# (MODE = "dark"). Night accent for this project: Crimson.
[theme]
base = "dark"
primaryColor = "#F0655A"
backgroundColor = "#14110f"
secondaryBackgroundColor = "#1f1a17"
textColor = "#f4ede4"
font = "sans serif"
203 changes: 14 additions & 189 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,208 +7,33 @@
from pathlib import Path
import json

from ui_theme import apply_theme

st.set_page_config(
page_title="SENTINEL Fraud Detection",
layout="wide",
initial_sidebar_state="expanded",
page_icon="S",
)

# Shared CSS theme
st.markdown("""
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap');

[data-testid="stAppViewContainer"] {
background: linear-gradient(160deg, #0b0f19 0%, #111827 40%, #1e293b 100%);
font-family: 'Inter', sans-serif;
}

[data-testid="stHeader"] {
background: rgba(11, 15, 25, 0.95);
backdrop-filter: blur(10px);
border-bottom: 1px solid rgba(147, 197, 253, 0.15);
}

[data-testid="stSidebar"] {
background: linear-gradient(180deg, #0b0f19 0%, #111827 100%);
border-right: 1px solid rgba(147, 197, 253, 0.1);
}

.main-header {
text-align: center;
margin-bottom: 2.5rem;
padding: 2rem 0;
}

.main-header h1 {
color: #e2e8f0;
font-weight: 900;
font-size: 2.8rem;
letter-spacing: -0.02em;
background: linear-gradient(135deg, #93c5fd 0%, #60a5fa 50%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 0.5rem;
}

.main-header p {
color: #94a3b8 !important;
font-size: 1.1rem;
font-weight: 400;
}

.kpi-card {
background: linear-gradient(135deg, rgba(147, 197, 253, 0.08) 0%, rgba(59, 130, 246, 0.05) 100%);
border: 1px solid rgba(147, 197, 253, 0.15);
border-radius: 12px;
padding: 1.5rem;
text-align: center;
transition: all 0.3s ease;
}

.kpi-card:hover {
border-color: rgba(147, 197, 253, 0.35);
box-shadow: 0 8px 32px rgba(59, 130, 246, 0.15);
transform: translateY(-2px);
}

.kpi-card .kpi-value {
font-size: 2rem;
font-weight: 800;
color: #93c5fd;
line-height: 1.2;
}

.kpi-card .kpi-label {
font-size: 0.85rem;
color: #94a3b8;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-top: 0.5rem;
}

.kpi-card .kpi-delta {
font-size: 0.75rem;
color: #34d399;
margin-top: 0.25rem;
}

.feature-card {
background: rgba(147, 197, 253, 0.05);
border: 1px solid rgba(147, 197, 253, 0.1);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1rem;
transition: border-color 0.3s ease;
}

.feature-card:hover {
border-color: rgba(147, 197, 253, 0.3);
}

.feature-card h4 {
color: #93c5fd !important;
font-size: 1rem;
font-weight: 700;
margin-bottom: 0.5rem;
}

.feature-card p {
color: #94a3b8 !important;
font-size: 0.9rem;
line-height: 1.5;
}

h1, h2, h3 {
color: #e2e8f0 !important;
}

p, label, .stMarkdown {
color: #cbd5e1 !important;
}

.stTabs [role="tablist"] {
background: rgba(147, 197, 253, 0.05);
border-radius: 8px;
padding: 4px;
gap: 4px;
}

.stTabs [role="tablist"] button {
color: #94a3b8 !important;
border-radius: 6px;
font-weight: 500;
}

.stTabs [role="tablist"] button[aria-selected="true"] {
background: rgba(59, 130, 246, 0.2) !important;
color: #93c5fd !important;
border-bottom: 2px solid #3b82f6 !important;
}

.stMetric {
background: linear-gradient(135deg, rgba(147, 197, 253, 0.08) 0%, rgba(59, 130, 246, 0.05) 100%);
border: 1px solid rgba(147, 197, 253, 0.15);
border-radius: 12px;
padding: 1rem;
}

.stMetric label {
color: #94a3b8 !important;
}

.stMetric [data-testid="stMetricValue"] {
color: #e2e8f0 !important;
}

.section-divider {
height: 1px;
background: linear-gradient(90deg, transparent, rgba(147, 197, 253, 0.2), transparent);
margin: 2rem 0;
}

.footer-text {
text-align: center;
color: #475569 !important;
font-size: 0.8rem;
padding: 1.5rem 0;
border-top: 1px solid rgba(147, 197, 253, 0.08);
}

.status-badge {
display: inline-block;
padding: 4px 12px;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
letter-spacing: 0.03em;
}

.status-active {
background: rgba(52, 211, 153, 0.15);
color: #34d399;
border: 1px solid rgba(52, 211, 153, 0.3);
}
</style>
""", unsafe_allow_html=True)
# Shared mark.dev theme — MODE and accent live in ui_theme.py (tokens, type, widgets, SENTINEL components)
apply_theme()

# Sidebar
with st.sidebar:
st.markdown("""
<div style="text-align: center; padding: 1.5rem; margin-bottom: 1rem;">
<div style="font-size: 2.5rem; margin-bottom: 0.5rem; color: #93c5fd;">S</div>
<h2 style="color: #e2e8f0; margin: 0; font-weight: 900; font-size: 1.3rem; letter-spacing: 0.1em;">SENTINEL</h2>
<p style="color: #64748b; margin: 0.25rem 0 0 0; font-size: 0.8rem; letter-spacing: 0.05em;">FRAUD DETECTION SYSTEM</p>
<div class="brand-block">
<div class="brand-mark">S</div>
<h2>SENTINEL</h2>
<p>FRAUD DETECTION SYSTEM</p>
</div>
""", unsafe_allow_html=True)

st.markdown("---")
st.markdown("""
<div style="padding: 0 0.5rem;">
<p style="color: #94a3b8; font-size: 0.85rem; font-weight: 600; margin-bottom: 0.75rem;">NAVIGATION</p>
<p style="color: #64748b; font-size: 0.8rem; line-height: 2;">
<div class="side-block">
<div class="side-label">NAVIGATION</div>
<p class="side-list">
Home Dashboard<br>
Predict Fraud<br>
Performance Metrics<br>
Expand All @@ -219,9 +44,9 @@

st.markdown("---")
st.markdown("""
<div style="padding: 0 0.5rem;">
<p style="color: #94a3b8; font-size: 0.85rem; font-weight: 600; margin-bottom: 0.75rem;">POWERED BY</p>
<p style="color: #64748b; font-size: 0.8rem; line-height: 1.8;">
<div class="side-block">
<div class="side-label">POWERED BY</div>
<p class="side-list">
XGBoost Classifier<br>
Pandas + scikit-learn<br>
DVC Pipeline
Expand Down
129 changes: 4 additions & 125 deletions pages/1_Predict.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,132 +8,12 @@
import sys
sys.path.insert(0, str(Path(__file__).parent.parent))
from src.predict import predict_dataframe
from ui_theme import apply_theme

st.set_page_config(page_title="Predict Fraud - SENTINEL", layout="wide", page_icon="S")

# Dark theme CSS
st.markdown("""
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap');

[data-testid="stAppViewContainer"] {
background: linear-gradient(160deg, #0b0f19 0%, #111827 40%, #1e293b 100%);
font-family: 'Inter', sans-serif;
}

[data-testid="stHeader"] {
background: rgba(11, 15, 25, 0.95);
backdrop-filter: blur(10px);
border-bottom: 1px solid rgba(147, 197, 253, 0.15);
}

[data-testid="stSidebar"] {
background: linear-gradient(180deg, #0b0f19 0%, #111827 100%);
border-right: 1px solid rgba(147, 197, 253, 0.1);
}

h1, h2, h3 {
color: #e2e8f0 !important;
}

p, label, .stMarkdown {
color: #cbd5e1 !important;
}

.page-header {
padding: 1rem 0 2rem 0;
}

.page-header h1 {
background: linear-gradient(135deg, #93c5fd 0%, #60a5fa 50%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: 900;
font-size: 2.2rem;
}

.page-header p {
color: #94a3b8 !important;
}

.stTabs [role="tablist"] {
background: rgba(147, 197, 253, 0.05);
border-radius: 8px;
padding: 4px;
}

.stTabs [role="tablist"] button {
color: #94a3b8 !important;
border-radius: 6px;
font-weight: 500;
}

.stTabs [role="tablist"] button[aria-selected="true"] {
background: rgba(59, 130, 246, 0.2) !important;
color: #93c5fd !important;
border-bottom: 2px solid #3b82f6 !important;
}

.stButton > button {
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
color: #ffffff !important;
border: 1px solid rgba(147, 197, 253, 0.3);
font-weight: 600;
border-radius: 8px;
padding: 0.6rem 1.5rem;
transition: all 0.3s ease;
}

.stButton > button:hover {
background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);
box-shadow: 0 4px 20px rgba(59, 130, 246, 0.4);
transform: translateY(-1px);
}

.stMetric {
background: linear-gradient(135deg, rgba(147, 197, 253, 0.08) 0%, rgba(59, 130, 246, 0.05) 100%);
border: 1px solid rgba(147, 197, 253, 0.15);
border-radius: 12px;
padding: 1rem;
}

.stMetric label { color: #94a3b8 !important; }
.stMetric [data-testid="stMetricValue"] { color: #e2e8f0 !important; }

.result-fraud {
background: linear-gradient(135deg, rgba(239, 68, 68, 0.1) 0%, rgba(185, 28, 28, 0.05) 100%);
border: 1px solid rgba(239, 68, 68, 0.3);
border-left: 4px solid #ef4444;
padding: 1.5rem;
border-radius: 12px;
margin: 1rem 0;
}

.result-fraud h3 { color: #fca5a5 !important; margin: 0 0 0.5rem 0; }
.result-fraud p { color: #fecaca !important; margin: 0; font-weight: 500; }

.result-safe {
background: linear-gradient(135deg, rgba(52, 211, 153, 0.1) 0%, rgba(16, 185, 129, 0.05) 100%);
border: 1px solid rgba(52, 211, 153, 0.3);
border-left: 4px solid #34d399;
padding: 1.5rem;
border-radius: 12px;
margin: 1rem 0;
}

.result-safe h3 { color: #6ee7b7 !important; margin: 0 0 0.5rem 0; }
.result-safe p { color: #a7f3d0 !important; margin: 0; font-weight: 500; }

.section-divider {
height: 1px;
background: linear-gradient(90deg, transparent, rgba(147, 197, 253, 0.2), transparent);
margin: 2rem 0;
}

.stNumberInput label, .stSelectbox label { color: #94a3b8 !important; }
</style>
""", unsafe_allow_html=True)
# Shared mark.dev theme (MODE and accent live in ui_theme.py)
apply_theme()

st.markdown("""
<div class="page-header">
Expand Down Expand Up @@ -413,8 +293,7 @@
)

st.markdown("""
<div style="text-align: center; color: #475569; font-size: 0.8rem; padding: 1.5rem 0;
border-top: 1px solid rgba(147, 197, 253, 0.08);">
<div class="footer-text">
Predictions powered by XGBoost trained on PaySim and Sparkov datasets
</div>
""", unsafe_allow_html=True)
Loading
Loading