|
3 | 3 | <html> |
4 | 4 |
|
5 | 5 | <head> |
| 6 | + <meta charset="utf-8"> |
6 | 7 | <meta name="color-scheme" content="light dark"> |
| 8 | + <!-- Import Adeu Brand Fonts --> |
| 9 | + <link rel="preconnect" href="https://fonts.googleapis.com"> |
| 10 | + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| 11 | + <link |
| 12 | + href="https://fonts.googleapis.com/css2?family=Jost:wght@400;500;600&family=Lora:ital,wght@0,600;1,600&display=swap" |
| 13 | + rel="stylesheet"> |
| 14 | + |
7 | 15 | <style> |
8 | | - body { |
9 | | - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; |
10 | | - padding: 20px; |
11 | | - line-height: 1.6; |
12 | | - color: #333; |
13 | | - margin: 0; |
14 | | - background: transparent; |
| 16 | + /* Adeu Design System Tokens */ |
| 17 | + :root { |
| 18 | + /* Primary Colors */ |
| 19 | + --brand-sand: #e8c0a1; |
| 20 | + --brand-sand-light: #f2d9c7; |
| 21 | + --brand-sand-dark: #d4a882; |
| 22 | + --brand-mint: #e6f3f0; |
| 23 | + --brand-mint-dark: #c9e4de; |
| 24 | + --brand-navy: #1a2a2c; |
| 25 | + --brand-navy-light: #2a3a3c; |
| 26 | + --brand-mauve: #dacad2; |
| 27 | + |
| 28 | + /* Neutral Palette */ |
| 29 | + --neutral-50: #fafafa; |
| 30 | + --neutral-100: #f5f5f5; |
| 31 | + --neutral-200: #e5e5e5; |
| 32 | + --neutral-300: #d9d9d9; |
| 33 | + --neutral-600: #555969; |
| 34 | + --neutral-800: #1e2028; |
| 35 | + --neutral-900: #171717; |
| 36 | + |
| 37 | + /* Typography */ |
| 38 | + --font-lora: 'Lora', Georgia, serif; |
| 39 | + --font-jost: 'Jost', system-ui, -apple-system, BlinkMacSystemFont, sans-serif; |
| 40 | + |
| 41 | + /* Semantic overrides for Light Mode */ |
| 42 | + --bg-body: var(--neutral-50); |
| 43 | + --bg-card: #ffffff; |
| 44 | + --border-card: var(--neutral-200); |
| 45 | + --text-main: var(--neutral-600); |
| 46 | + --text-heading: var(--brand-navy); |
| 47 | + --bg-blockquote: rgba(232, 192, 161, 0.15); |
| 48 | + /* Sand transparent */ |
15 | 49 | } |
16 | 50 |
|
| 51 | + /* Dark Mode Semantic Overrides */ |
17 | 52 | @media (prefers-color-scheme: dark) { |
18 | | - body { |
19 | | - color: #eee; |
| 53 | + :root { |
| 54 | + --bg-body: var(--neutral-900); |
| 55 | + --bg-card: var(--brand-navy); |
| 56 | + --border-card: var(--brand-navy-light); |
| 57 | + --text-main: rgba(255, 255, 255, 0.85); |
| 58 | + --text-heading: #ffffff; |
| 59 | + --bg-blockquote: rgba(232, 192, 161, 0.1); |
| 60 | + --neutral-100: var(--brand-navy-light); |
20 | 61 | } |
21 | 62 | } |
22 | 63 |
|
| 64 | + /* Base Setup */ |
| 65 | + body { |
| 66 | + font-family: var(--font-jost); |
| 67 | + background-color: transparent; |
| 68 | + color: var(--text-main); |
| 69 | + padding: 16px 0; |
| 70 | + /* Removed horizontal padding since shadow is gone */ |
| 71 | + margin: 0; |
| 72 | + line-height: 1.6; |
| 73 | + -webkit-font-smoothing: antialiased; |
| 74 | + } |
| 75 | + |
| 76 | + /* Main Card Container (Separates UI from Claude) */ |
| 77 | + .adeu-card { |
| 78 | + background-color: var(--bg-card); |
| 79 | + border: 1px solid var(--border-card); |
| 80 | + border-radius: 12px; |
| 81 | + /* rounded-xl */ |
| 82 | + padding: 32px; |
| 83 | + /* space-8 */ |
| 84 | + transition: all 0.2s ease; |
| 85 | + } |
| 86 | + |
| 87 | + /* Typography inside Card */ |
| 88 | + h1, |
| 89 | + h2, |
| 90 | + h3, |
| 91 | + h4 { |
| 92 | + font-family: var(--font-lora); |
| 93 | + color: var(--text-heading); |
| 94 | + font-weight: 600; |
| 95 | + letter-spacing: -0.02em; |
| 96 | + margin-top: 1.5em; |
| 97 | + margin-bottom: 0.5em; |
| 98 | + } |
| 99 | + |
23 | 100 | h1 { |
24 | | - border-bottom: 1px solid #ddd; |
25 | | - padding-bottom: 10px; |
26 | | - margin-bottom: 20px; |
| 101 | + font-size: 2.25rem; |
| 102 | + border-bottom: 1px solid var(--border-card); |
| 103 | + padding-bottom: 0.3em; |
| 104 | + margin-top: 0; |
27 | 105 | } |
28 | 106 |
|
29 | 107 | h2 { |
30 | | - margin-top: 30px; |
31 | | - color: #0056b3; |
| 108 | + font-size: 1.75rem; |
32 | 109 | } |
33 | 110 |
|
34 | | - @media (prefers-color-scheme: dark) { |
35 | | - h2 { |
36 | | - color: #4da3ff; |
37 | | - } |
| 111 | + h3 { |
| 112 | + font-size: 1.25rem; |
38 | 113 | } |
39 | 114 |
|
40 | | - h3 { |
41 | | - margin-top: 25px; |
| 115 | + a { |
| 116 | + color: var(--brand-sand-dark); |
| 117 | + text-decoration: none; |
| 118 | + border-bottom: 1px solid transparent; |
| 119 | + transition: border 0.2s ease; |
42 | 120 | } |
43 | 121 |
|
44 | | - h4 { |
45 | | - margin-top: 15px; |
46 | | - margin-bottom: 5px; |
| 122 | + a:hover { |
| 123 | + border-bottom-color: var(--brand-sand-dark); |
| 124 | + } |
| 125 | + |
| 126 | + strong { |
| 127 | + font-weight: 600; |
| 128 | + color: var(--text-heading); |
| 129 | + } |
| 130 | + |
| 131 | + ul, |
| 132 | + ol { |
| 133 | + padding-left: 1.5rem; |
| 134 | + margin-bottom: 1rem; |
47 | 135 | } |
48 | 136 |
|
| 137 | + li { |
| 138 | + margin-bottom: 0.5rem; |
| 139 | + } |
| 140 | + |
| 141 | + /* Blockquotes */ |
49 | 142 | blockquote { |
50 | | - border-left: 4px solid #ccc; |
51 | | - padding-left: 15px; |
52 | | - margin: 15px 0; |
53 | | - color: #555; |
54 | | - background: rgba(0, 0, 0, 0.03); |
55 | | - padding-top: 5px; |
56 | | - padding-bottom: 5px; |
| 143 | + border-left: 4px solid var(--brand-sand); |
| 144 | + padding: 12px 20px; |
| 145 | + margin: 24px 0; |
| 146 | + color: var(--text-main); |
| 147 | + background: var(--bg-blockquote); |
| 148 | + border-radius: 0 8px 8px 0; |
| 149 | + font-style: italic; |
57 | 150 | } |
58 | 151 |
|
59 | | - @media (prefers-color-scheme: dark) { |
60 | | - blockquote { |
61 | | - border-color: #666; |
62 | | - color: #bbb; |
63 | | - background: rgba(255, 255, 255, 0.05); |
64 | | - } |
| 152 | + /* Inline Code & Code Blocks */ |
| 153 | + code { |
| 154 | + font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; |
| 155 | + font-size: 0.85em; |
| 156 | + background: var(--neutral-100); |
| 157 | + color: var(--brand-sand-dark); |
| 158 | + padding: 0.2em 0.4em; |
| 159 | + border-radius: 4px; |
65 | 160 | } |
66 | 161 |
|
67 | | - strong { |
68 | | - font-weight: 600; |
| 162 | + pre code { |
| 163 | + display: block; |
| 164 | + padding: 16px; |
| 165 | + background: var(--neutral-900); |
| 166 | + color: #e5e5e5; |
| 167 | + border-radius: 8px; |
| 168 | + overflow-x: auto; |
| 169 | + } |
| 170 | + |
| 171 | + /* Loading Skeleton Animation */ |
| 172 | + .skeleton { |
| 173 | + background: linear-gradient(90deg, var(--neutral-100) 25%, var(--border-card) 50%, var(--neutral-100) 75%); |
| 174 | + background-size: 200% 100%; |
| 175 | + animation: skeleton 1.5s ease-in-out infinite; |
| 176 | + border-radius: 4px; |
| 177 | + } |
| 178 | + |
| 179 | + @keyframes skeleton { |
| 180 | + 0% { |
| 181 | + background-position: 200% 0; |
| 182 | + } |
| 183 | + |
| 184 | + 100% { |
| 185 | + background-position: -200% 0; |
| 186 | + } |
69 | 187 | } |
70 | 188 |
|
71 | 189 | /* Polished Error Component Styles */ |
72 | 190 | .alert { |
73 | 191 | padding: 16px; |
74 | | - border-radius: 6px; |
| 192 | + border-radius: 8px; |
75 | 193 | margin-bottom: 20px; |
76 | 194 | display: flex; |
77 | 195 | flex-direction: column; |
78 | 196 | gap: 8px; |
79 | | - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); |
80 | | - } |
81 | | - |
82 | | - .alert-danger { |
83 | | - background-color: #fef0f0; |
84 | | - border: 1px solid #f5c2c7; |
85 | | - color: #842029; |
| 197 | + background-color: #fef2f2; |
| 198 | + border: 1px solid #fecaca; |
| 199 | + color: #991b1b; |
86 | 200 | } |
87 | 201 |
|
88 | 202 | @media (prefers-color-scheme: dark) { |
89 | | - .alert-danger { |
90 | | - background-color: #2c0b0e; |
91 | | - border-color: #842029; |
92 | | - color: #ea868f; |
| 203 | + .alert { |
| 204 | + background-color: rgba(127, 29, 29, 0.2); |
| 205 | + border-color: rgba(248, 113, 113, 0.3); |
| 206 | + color: #fca5a5; |
93 | 207 | } |
94 | 208 | } |
95 | 209 |
|
|
100 | 214 | display: flex; |
101 | 215 | align-items: center; |
102 | 216 | gap: 8px; |
| 217 | + font-family: var(--font-lora); |
103 | 218 | } |
104 | 219 |
|
105 | 220 | .alert-body { |
|
109 | 224 |
|
110 | 225 | .alert-details { |
111 | 226 | background: rgba(0, 0, 0, 0.05); |
112 | | - padding: 10px; |
113 | | - border-radius: 4px; |
114 | | - font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; |
| 227 | + padding: 12px; |
| 228 | + border-radius: 6px; |
| 229 | + font-family: ui-monospace, Consolas, monospace; |
115 | 230 | font-size: 0.85em; |
116 | 231 | white-space: pre-wrap; |
117 | 232 | word-break: break-all; |
118 | 233 | margin-top: 8px; |
119 | 234 | border: 1px solid rgba(0, 0, 0, 0.1); |
120 | 235 | } |
121 | | - |
122 | | - @media (prefers-color-scheme: dark) { |
123 | | - .alert-details { |
124 | | - background: rgba(255, 255, 255, 0.05); |
125 | | - border-color: rgba(255, 255, 255, 0.1); |
126 | | - } |
127 | | - } |
128 | 236 | </style> |
129 | 237 | <script id="marked-script">[[marked_js_code | safe]]</script> |
130 | 238 | </head> |
131 | 239 |
|
132 | 240 | <body> |
133 | | - <div id="app">Loading report...</div> |
| 241 | + <div id="app" class="adeu-card"> |
| 242 | + <!-- Brand-aligned Loading State --> |
| 243 | + <div class="skeleton" style="height: 36px; width: 40%; margin-bottom: 24px;"></div> |
| 244 | + <div class="skeleton" style="height: 16px; width: 100%; margin-bottom: 12px;"></div> |
| 245 | + <div class="skeleton" style="height: 16px; width: 95%; margin-bottom: 12px;"></div> |
| 246 | + <div class="skeleton" style="height: 16px; width: 90%; margin-bottom: 24px;"></div> |
| 247 | + <div class="skeleton" style="height: 16px; width: 80%; margin-bottom: 12px;"></div> |
| 248 | + </div> |
134 | 249 | <script> |
135 | 250 | const appDiv = document.getElementById('app'); |
136 | 251 | const INIT_ID = 1; |
137 | 252 |
|
138 | | - // Helper to safely render text to prevent HTML injection in error details |
139 | 253 | function escapeHtml(unsafe) { |
140 | 254 | return (unsafe || "").toString() |
141 | 255 | .replace(/&/g, "&") |
|
145 | 259 | .replace(/'/g, "'"); |
146 | 260 | } |
147 | 261 |
|
148 | | - // Standardized UI Error Component |
149 | 262 | function showError(title, message, details = null) { |
150 | 263 | let html = ` |
151 | | - <div class="alert alert-danger"> |
| 264 | + <div class="alert"> |
152 | 265 | <div class="alert-title"> |
153 | 266 | <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg> |
154 | 267 | ${escapeHtml(title)} |
|
164 | 277 | } |
165 | 278 |
|
166 | 279 | function triggerResize() { |
| 280 | + // Removed height buffer since the drop shadow is gone |
| 281 | + const height = Math.min(Math.ceil(document.documentElement.getBoundingClientRect().height), 600); |
167 | 282 | window.parent.postMessage({ |
168 | 283 | jsonrpc: "2.0", |
169 | 284 | method: "ui/notifications/size-changed", |
170 | | - params: { height: Math.min(Math.ceil(document.documentElement.getBoundingClientRect().height), 600), width: 600 } |
| 285 | + params: { height: height, width: 600 } |
171 | 286 | }, "*"); |
172 | 287 | } |
173 | 288 |
|
|
176 | 291 | if (!event.data || event.data.jsonrpc !== "2.0") return; |
177 | 292 | const msg = event.data; |
178 | 293 |
|
179 | | - // 1. Host Initialization Handshake |
180 | 294 | if (msg.id === INIT_ID) { |
181 | 295 | window.parent.postMessage({ |
182 | 296 | jsonrpc: "2.0", |
|
186 | 300 | return; |
187 | 301 | } |
188 | 302 |
|
189 | | - // 2. Incoming Data Render |
190 | 303 | if (msg.method === "ui/notifications/tool-result") { |
191 | | - |
192 | | - // Check for critical missing dependencies first |
193 | 304 | if (window.__MARKED_ERROR || typeof marked === 'undefined') { |
194 | | - showError( |
195 | | - "Missing Dependency", |
196 | | - "The Markdown renderer (marked.min.js) failed to load. The report cannot be displayed.", |
197 | | - window.__MARKED_ERROR || "The 'marked' global variable is undefined." |
198 | | - ); |
| 305 | + showError("Missing Dependency", "The Markdown renderer failed to load.", window.__MARKED_ERROR || "marked is undefined."); |
199 | 306 | return; |
200 | 307 | } |
201 | 308 |
|
202 | 309 | const result = msg.params; |
203 | | - |
204 | 310 | if (!result) { |
205 | | - showError("Empty Response", "The server returned an empty tool result payload."); |
| 311 | + showError("Empty Response", "The server returned an empty payload."); |
206 | 312 | return; |
207 | 313 | } |
208 | 314 |
|
209 | 315 | if (result.structuredContent && result.structuredContent.markdown) { |
210 | | - // Render successfully |
211 | 316 | appDiv.innerHTML = marked.parse(result.structuredContent.markdown); |
212 | 317 | triggerResize(); |
213 | 318 | } else if (result.content) { |
214 | | - // Fallback content rendering |
215 | 319 | if (Array.isArray(result.content)) { |
216 | 320 | const txt = result.content.find(c => c.type === 'text'); |
217 | 321 | if (txt) { appDiv.textContent = txt.text; triggerResize(); } |
218 | 322 | } else if (typeof result.content === 'string') { |
219 | 323 | appDiv.textContent = result.content; |
220 | 324 | triggerResize(); |
221 | 325 | } else { |
222 | | - showError("Unsupported Format", "Received an unrecognizable content format.", JSON.stringify(result.content)); |
| 326 | + showError("Unsupported Format", "Unrecognizable content format.", JSON.stringify(result.content)); |
223 | 327 | } |
224 | 328 | } else { |
225 | | - showError("No Content", "The tool result payload contained no structured content or raw text.", JSON.stringify(result)); |
| 329 | + showError("No Content", "No structured content or raw text found.", JSON.stringify(result)); |
226 | 330 | } |
227 | 331 | } |
228 | 332 | } catch (error) { |
229 | | - showError("Rendering Engine Error", "An unexpected error occurred while parsing the document.", error.toString() + "\n" + error.stack); |
| 333 | + showError("Rendering Engine Error", "An unexpected error occurred.", error.toString() + "\n" + error.stack); |
230 | 334 | } |
231 | 335 | }); |
232 | 336 |
|
|
0 commit comments