"""Render an AnalysisResult into the three HTML result cards. All model-derived text is HTML-escaped here — the model can never inject markup into the page. Styling hooks (classes) are defined in app.py's CSS. """ from __future__ import annotations import html from . import ui_text from .pipeline import AnalysisResult def _card(css_class: str, heading: str, body_html: str, prefix: str = "") -> str: return ( f'
{prefix}' f"

{html.escape(heading)}

{body_html}
" ) # Postage-stamp verdict icons — inline SVG, hand-drawn feel, no external assets. _STAMP_ICONS = { "low": ( # check inside a postmark ring '' ), "caution": ( # gently tilted warning triangle '' ), "warning": ( # exclamation octagon '' ), } def _stamp(level: str) -> str: icon = _STAMP_ICONS.get(level, _STAMP_ICONS["low"]) return f'' def _bullets(items: list[str]) -> str: if not items: return "" lis = "".join(f"
  • {html.escape(i)}
  • " for i in items) return f"" def render_result(result: AnalysisResult) -> tuple[str, str, str]: """-> (what_html, worry_html, todo_html).""" lang = result.lang if not result.ok: message = f"

    {html.escape(result.error)}

    " return ( _card("card-neutral", ui_text.get(lang, "section_what"), message), "", "", ) what_html = _card( "card-neutral", ui_text.get(lang, "section_what"), f"

    {html.escape(result.what_this_is)}

    {_bullets(result.key_facts)}", ) worry_class = { "low": "card-low", "caution": "card-caution", "warning": "card-warning", }.get(result.worry_level, "card-caution") worry_html = _card( worry_class, ui_text.get(lang, "section_worry"), f"

    {html.escape(result.worry_headline)}

    " + _bullets(result.worry_reasons), prefix=_stamp(result.worry_level), ) todo_html = _card( "card-todo", ui_text.get(lang, "section_todo"), _bullets(result.actions), ) return what_html, worry_html, todo_html def render_placeholder(lang: str) -> tuple[str, str, str]: return ( _card("card-neutral", ui_text.get(lang, "section_what"), f"

    {html.escape(ui_text.get(lang, 'waiting'))}

    "), "", "", )