File size: 3,784 Bytes
b2ad034 aff4140 1049372 aff4140 1049372 b2ad034 01f6914 aff4140 01f6914 aff4140 1049372 aff4140 b2ad034 01f6914 aff4140 01f6914 aff4140 1049372 aff4140 b2ad034 01f6914 aff4140 b2ad034 aff4140 1049372 aff4140 b2ad034 01f6914 aff4140 01f6914 aff4140 1049372 aff4140 1049372 aff4140 1049372 aff4140 01f6914 aff4140 1049372 01f6914 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | import streamlit as st
# Inline-style helpers — all colors use either Streamlit CSS vars or
# semi-transparent rgba so they render correctly in both light and dark mode.
_BADGE = (
'display:inline-flex;align-items:center;gap:4px;padding:3px 10px;'
'border-radius:20px;font-size:0.78rem;font-weight:600;'
'white-space:nowrap;line-height:1.4;'
)
def verdict_pill(verdict: str) -> str:
cfg = {
"eligible": ("rgba(34,197,94,0.15)", "#22C55E", "✅ Eligible"),
"not_eligible": ("rgba(239,68,68,0.15)", "#EF4444", "❌ Not Eligible"),
"needs_review": ("rgba(245,158,11,0.15)", "#F59E0B", "⚠️ Needs Review"),
}
bg, fg, label = cfg.get(verdict, ("rgba(128,128,128,0.1)", "var(--text-color)", verdict))
return (f'<span style="{_BADGE}background:{bg};color:{fg};'
f'border:1px solid {fg}33;">{label}</span>')
def category_badge(category: str) -> str:
cfg = {
"financial": ("rgba(37,99,235,0.12)", "#3B82F6", "💰 Financial"),
"technical": ("rgba(34,197,94,0.12)", "#22C55E", "🔧 Technical"),
"compliance": ("rgba(245,158,11,0.12)", "#F59E0B", "📋 Compliance"),
}
bg, fg, label = cfg.get(category, ("rgba(128,128,128,0.1)", "var(--text-color)", category))
return (f'<span style="{_BADGE}background:{bg};color:{fg};'
f'border:1px solid {fg}33;">{label}</span>')
def ocr_tier_badge(source_type: str) -> str:
cfg = {
"text_pdf": ("rgba(100,116,139,0.12)", "#94A3B8", "📄 Typed PDF"),
"tesseract": ("rgba(124,58,237,0.12)", "#8B5CF6", "🔍 Tesseract"),
"vision_llm": ("rgba(234,88,12,0.12)", "#F97316", "👁 Vision LLM"),
}
bg, fg, label = cfg.get(source_type, ("rgba(128,128,128,0.1)", "var(--text-color)", source_type))
return (f'<span style="{_BADGE}background:{bg};color:{fg};'
f'border:1px solid {fg}33;">{label}</span>')
def mandatory_badge(mandatory: bool) -> str:
if mandatory:
return (f'<span style="{_BADGE}background:rgba(239,68,68,0.12);color:#EF4444;'
f'border:1px solid #EF444433;">🔴 Mandatory</span>')
return (f'<span style="{_BADGE}background:rgba(245,158,11,0.12);color:#F59E0B;'
f'border:1px solid #F59E0B33;">🟡 Optional</span>')
def confidence_bar(value: float, label: str = "Confidence") -> None:
pct = min(max(value, 0.0), 1.0)
color = "#22C55E" if pct >= 0.80 else "#F59E0B" if pct >= 0.55 else "#EF4444"
st.markdown(
f"""<div style="margin:6px 0 10px;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:4px;">
<span style="font-size:0.72rem;font-weight:600;color:var(--text-color);
opacity:0.5;text-transform:uppercase;letter-spacing:0.05em;">{label}</span>
<span style="font-size:0.8rem;font-weight:700;color:{color};">{pct:.0%}</span>
</div>
<div style="background:rgba(128,128,128,0.15);border-radius:6px;height:6px;overflow:hidden;">
<div style="width:{pct*100:.1f}%;background:{color};height:100%;border-radius:6px;"></div>
</div>
</div>""",
unsafe_allow_html=True,
)
def stat_card(value: str | int, label: str, color: str = "#3B82F6") -> None:
st.markdown(
f"""<div style="background:var(--secondary-background-color);
border:1px solid rgba(128,128,128,0.2);border-radius:12px;
padding:20px 18px;text-align:center;">
<div style="font-size:2rem;font-weight:800;color:{color};line-height:1.1;">{value}</div>
<div style="font-size:0.7rem;font-weight:700;color:var(--text-color);opacity:0.45;
margin-top:5px;text-transform:uppercase;letter-spacing:0.08em;">{label}</div>
</div>""",
unsafe_allow_html=True,
)
|