"""Shared visual style: page config, dark-mode CSS, palette."""
from __future__ import annotations
import streamlit as st
# Polished dark palette inspired by analyst-tool surfaces (Looker, Hex, Mode).
PALETTE = {
"primary": "#E15A63", # accent crimson
"secondary": "#5BA3DA", # accent steel-blue
"accent": "#E0B458", # mountain gold
"good": "#3FAE7B",
"warn": "#E0B458",
"bad": "#D9534F",
"muted": "#9CA3AF",
"bg": "#0B0E13",
"surface": "#141821",
"surface2": "#1A1F2A",
"border": "#262C38",
"text": "#E6E8EB",
"text_dim": "#9CA3AF",
"treated": "#5BA3DA",
"control": "#E15A63",
}
INITIATIVE_COLOR = {
1: "#E0B458", # workforce (gold)
2: "#5BA3DA", # facility (blue)
3: "#3FAE7B", # innovative (green)
4: "#D679A4", # prevention (rose)
5: "#A487E0", # technology (violet)
}
def page_setup(title: str, layout: str = "wide") -> None:
st.set_page_config(
page_title=f"RHTP Evaluation — {title}",
layout=layout,
initial_sidebar_state="expanded",
)
st.markdown(_CSS, unsafe_allow_html=True)
_CSS = """
"""
def header(title: str, subtitle: str | None = None,
pill: tuple[str, str] | None = None) -> None:
pill_html = ""
if pill:
text, kind = pill
pill_html = f' {text}'
st.markdown(f"# {title}{pill_html}", unsafe_allow_html=True)
if subtitle:
st.markdown(
f"
{subtitle}
",
unsafe_allow_html=True,
)
st.markdown("
", unsafe_allow_html=True)
def section(title: str, kicker: str | None = None) -> None:
st.markdown(f"## {title}")
if kicker:
st.markdown(
f""
f"{kicker}
",
unsafe_allow_html=True,
)
def callout(body: str, kind: str = "info", title: str | None = None) -> None:
cls = {"info": " info", "success": " success",
"warn": " warn", "bad": " bad"}.get(kind, "")
head = f"{title}
" if title else ""
st.markdown(
f"{head}{body}
",
unsafe_allow_html=True,
)
def formula(latex: str, caption: str | None = None) -> None:
st.latex(latex)
if caption:
st.caption(caption)
# Plain-text verdict labels (no emojis). Callers can pass these to a styler
# inside dataframes, or embed them in markdown via verdict_chip().
VERDICT_LABELS = {
"pass": "Effective",
"partial": "Right direction",
"weak": "Imprecise",
"fail": "Wrong direction",
"context": "Contextual",
}
def verdict_chip(kind: str, text: str | None = None) -> str:
"""Return an HTML chip with the right CSS class. Used inside markdown."""
cls = kind if kind in {"pass", "partial", "weak", "fail", "context"} else "context"
label = text or VERDICT_LABELS.get(kind, kind)
return f"{label}"
def section_divider(label: str | None = None) -> None:
"""Visible divider used between major page sections."""
st.markdown("
", unsafe_allow_html=True)
if label:
st.markdown(
f"{label}
",
unsafe_allow_html=True,
)
def initiative_scope(
*,
initiative_no: int,
title: str,
kpos: list[dict],
inputs: list[dict],
) -> None:
"""Render the KPO table and the treatment-input table side-by-side.
Each kpo dict: name, level, baseline, target.
Each input dict: name, level, notes.
"""
st.markdown(f"## Initiative scope")
st.markdown(
f""
f"What this initiative is trying to move and the levers it pulls. "
f"All baselines and FY2031 targets are derived from the synthetic "
f"data in /data/ and the RHTP plan structure.
",
unsafe_allow_html=True,
)
def _kpo_row(k: dict) -> str:
return (
""
f"| {k['name']} | "
f"{k['level']} | "
f"{k['baseline']} | "
f"{k['target']} | "
"
"
)
def _input_row(i: dict) -> str:
notes = i.get("notes", "")
return (
""
f"| {i['name']} | "
f"{i['level']} | "
f"{notes} | "
"
"
)
# Stacked vertically: KPOs first (full width), then inputs.
kpo_body = (
""
"
"
"Initiative " + f"{initiative_no:02d} · KPOs"
+ ""
"Key Program Outcomes monitored"
"
"
"
"
"| Outcome | Level | "
"Baseline | FY2031 target |
"
""
+ "".join(_kpo_row(k) for k in kpos)
+ "
"
)
st.markdown(kpo_body, unsafe_allow_html=True)
input_body = (
""
"
"
"Initiative " + f"{initiative_no:02d} · inputs"
+ ""
"Treatment / intervention levers"
"
"
"
"
"| Input | Level | Notes |
"
""
+ "".join(_input_row(i) for i in inputs)
+ "
"
)
st.markdown(input_body, unsafe_allow_html=True)
def equation_legend(rows: list[tuple[str, str]]) -> None:
"""Render an equation symbol -> definition legend."""
body = ""
for sym, defn in rows:
body += (
"
"
)
body += "
"
st.markdown(body, unsafe_allow_html=True)
def role_box(rows: list[tuple[str, str]], title: str | None = None) -> None:
"""Small box labeling the role each model component plays."""
body = ""
if title:
body += (
f"
{title}
"
)
for label, desc in rows:
body += (
"
"
)
body += "
"
st.markdown(body, unsafe_allow_html=True)
def glossary(title: str, rows: list[tuple[str, str]]) -> None:
"""Render a term/definition glossary card."""
body = (
""
f"
{title}
"
)
for term, defn in rows:
body += (
"
"
)
body += "
"
st.markdown(body, unsafe_allow_html=True)