Tarek Masryo
chore: update project files
6bef416
from __future__ import annotations
from collections.abc import Iterable
import streamlit as st
CSS = """
<style>
:root {
--app-bg: #0b1020;
--panel: #111827;
--border: rgba(148, 163, 184, 0.28);
--muted: #94a3b8;
}
.stApp {
background: linear-gradient(180deg, #08111f 0%, #0b1020 45%, #0f172a 100%);
}
.block-container {
max-width: 1480px;
padding-top: 1.25rem;
padding-bottom: 3rem;
}
[data-testid="stSidebar"] {
background: #0b1220;
border-right: 1px solid var(--border);
}
h1, h2, h3 {
letter-spacing: -0.02em;
}
[data-testid="stMetric"] {
background: rgba(15, 23, 42, 0.72);
border: 1px solid var(--border);
border-radius: 16px;
padding: 14px 14px 12px 14px;
}
[data-testid="stDataFrame"] {
border-radius: 12px;
}
.small-note {
color: var(--muted);
font-size: 0.92rem;
line-height: 1.5;
}
</style>
"""
def inject_css() -> None:
"""Inject static CSS only; do not interpolate user or dataset values into this markup."""
st.markdown(CSS, unsafe_allow_html=True)
def badge(text: str, kind: str = "info") -> str:
"""Return a plain-text badge label for native Streamlit rendering."""
prefix = {
"good": "✅",
"warn": "⚠️",
"bad": "🚨",
"info": "ℹ️",
}.get(kind, "•")
return f"{prefix} {text}"
def hero(title: str, subtitle: str, badges: Iterable[str] | None = None) -> None:
st.title(title)
st.markdown(subtitle)
if badges:
st.caption(" · ".join(str(item) for item in badges))
st.divider()
def decision_strip(items: list[tuple[str, str, str]]) -> None:
"""Render the decision brief with native Streamlit elements.
This keeps the decision brief stable across Streamlit versions.
"""
st.subheader("Decision brief")
cols = st.columns(len(items))
for col, (label, value, hint) in zip(cols, items, strict=False):
with col:
with st.container(border=True):
st.caption(label)
st.markdown(f"**{value}**")
st.caption(hint)
def metric_card(label: str, value: str, caption: str, status: str = "info") -> None:
st.metric(label=label, value=value)
st.caption(f"{status.title()} · {caption}")
def status_kind(status: str) -> str:
s = status.lower()
if any(x in s for x in ["stable", "good", "healthy", "pass"]):
return "good"
if any(x in s for x in ["risk", "high", "bad", "fail"]):
return "bad"
if any(x in s for x in ["watch", "review", "warn"]):
return "warn"
return "info"
def section_title(title: str, subtitle: str = "", chip: str = "") -> None:
label = f" — {chip}" if chip else ""
st.markdown(f"## {title}{label}")
if subtitle:
st.caption(subtitle)
def callout(kind: str, title: str, body: str) -> None:
text = f"**{title}**\n\n{body}"
if kind in {"good", "success", "pass"}:
st.success(text)
elif kind in {"warn", "warning", "review"}:
st.warning(text)
elif kind in {"bad", "error", "risk", "fail"}:
st.error(text)
else:
st.info(text)
def trace_box(title: str, body: str) -> None:
with st.container(border=True):
st.markdown(f"**{title}**")
st.write(body)