diff --git a/tradingagents/ui/theme.py b/tradingagents/ui/theme.py
index 5b19674a..414a4eb5 100644
--- a/tradingagents/ui/theme.py
+++ b/tradingagents/ui/theme.py
@@ -629,46 +629,58 @@ def signal_card(
safe_risk_title = safe_risk.title() if safe_risk else "—"
- return f"""
-
HTML block at the FIRST blank line, so any
+ # empty interpolation (name_html, desc_html, risk_badge_html = "") would leave
+ # a whitespace-only line that makes Streamlit's markdown parser stop treating
+ # subsequent content as HTML and render it as literal text instead.
+ parts = [
+ f'
',
+ '"]
+ if desc_html:
+ parts.append(desc_html)
+ parts += [
+ '
',
+ f'{safe_strategy}',
+ f'Score {score}',
+ f'Conf {confidence}/10',
+ ]
+ if risk_badge_html:
+ parts.append(risk_badge_html)
+ parts += [
+ "
",
+ '
',
+ '
',
+ '
Entry
',
+ f'
{entry_str}
',
+ "
",
+ '
',
+ '
Score
',
+ f'
{score}/100
',
+ "
",
+ '
',
+ '
Confidence
',
+ f'
{confidence}/10
',
+ "
",
+ '
',
+ '
Risk
',
+ f'
{safe_risk_title}
',
+ "
",
+ "
",
+ f'
{safe_reason}
',
+ '
",
+ "
",
+ ]
+ return "\n".join(parts)
def pnl_color(value: float) -> str: