tfrere HF Staff commited on
Commit
f07c960
·
1 Parent(s): 3f44950

update table, banner text, footer wording

Browse files
app/src/components/Footer.astro CHANGED
@@ -47,7 +47,7 @@ const { citationText, bibtex, licence, doi } = Astro.props as Props;
47
  </section>
48
  <div class="template-credit">
49
  <p>
50
- made with love with <a
51
  href="https://huggingface.co/spaces/tfrere/research-article-template"
52
  target="_blank"
53
  rel="noopener noreferrer">research article template</a
 
47
  </section>
48
  <div class="template-credit">
49
  <p>
50
+ made with ❤️ with <a
51
  href="https://huggingface.co/spaces/tfrere/research-article-template"
52
  target="_blank"
53
  rel="noopener noreferrer">research article template</a
app/src/components/HtmlEmbed.astro CHANGED
@@ -1,15 +1,42 @@
1
  ---
2
- interface Props { src: string; title?: string; desc?: string; frameless?: boolean; align?: 'left' | 'center' | 'right'; id?: string, data?: string | string[], config?: any }
3
- const { src, title, desc, frameless = false, align = 'left', id, data, config } = Astro.props as Props;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  // Load all .html embeds under src/content/embeds/** as strings (dev & build)
6
- const embeds = (import.meta as any).glob('../content/embeds/**/*.html', { query: '?raw', import: 'default', eager: true }) as Record<string, string>;
 
 
 
 
7
 
8
  function resolveFragment(requested: string): string | null {
9
  // Allow both "banner.html" and "embeds/banner.html"
10
- const needle = requested.replace(/^\/*/, '');
11
  for (const [key, html] of Object.entries(embeds)) {
12
- if (key.endsWith('/' + needle) || key.endsWith('/' + needle.replace(/^embeds\//, ''))) {
 
 
 
13
  return html;
14
  }
15
  }
@@ -18,25 +45,62 @@ function resolveFragment(requested: string): string | null {
18
 
19
  const html = resolveFragment(src);
20
  const mountId = `frag-${Math.random().toString(36).slice(2)}`;
21
- const dataAttr = Array.isArray(data) ? JSON.stringify(data) : (typeof data === 'string' ? data : undefined);
22
- const configAttr = typeof config === 'string' ? config : (config != null ? JSON.stringify(config) : undefined);
 
 
 
 
 
 
 
 
 
23
 
24
  // Apply the ID to the HTML content if provided
25
- const htmlWithId = id && html ? html.replace(/<div class="([^"]*)"[^>]*>/, `<div class="$1" id="${id}">`) : html;
 
 
 
26
  ---
27
- { html ? (
28
- <figure class="html-embed" id={id}>
29
- {title && <figcaption class="html-embed__title" style={`text-align:${align}`}>{title}</figcaption>}
30
- <div class={`html-embed__card${frameless ? ' is-frameless' : ''}`}>
31
- <div id={mountId} data-datafiles={dataAttr} data-config={configAttr} set:html={htmlWithId} />
32
- </div>
33
- {desc && <figcaption class="html-embed__desc" style={`text-align:${align}`} set:html={desc}></figcaption>}
34
- </figure>
35
- ) : (
36
- <div><!-- Fragment not found: {src} --></div>
37
- ) }
38
-
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
  <script>
42
  // Re-execute <script> tags inside the injected fragment (innerHTML doesn't run scripts)
@@ -44,40 +108,50 @@ const htmlWithId = id && html ? html.replace(/<div class="([^"]*)"[^>]*>/, `<div
44
  const mount = scriptEl ? scriptEl.previousElementSibling : null;
45
  const execute = () => {
46
  if (!mount) return;
47
- const scripts = mount.querySelectorAll('script');
48
- scripts.forEach(old => {
49
  // ignore non-executable types (e.g., application/json)
50
- if (old.type && old.type !== 'text/javascript' && old.type !== 'module' && old.type !== '') return;
51
- if (old.dataset.executed === 'true') return;
52
- old.dataset.executed = 'true';
 
 
 
 
 
 
53
  if (old.src) {
54
- const s = document.createElement('script');
55
- Array.from(old.attributes).forEach(attr => s.setAttribute(attr.name, attr.value));
 
 
56
  document.body.appendChild(s);
57
  } else {
58
  try {
59
  // run inline
60
- (0, eval)(old.text || '');
61
  } catch (e) {
62
- console.error('HtmlEmbed inline script error:', e);
63
  }
64
  }
65
  });
66
  };
67
  // Execute after DOM is parsed (ensures deferred module scripts are executed first)
68
- if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', execute, { once: true });
 
69
  else execute();
70
- </script>
71
 
72
  <style is:global>
73
- .html-embed { margin: 0 0 var(--block-spacing-y);
 
74
  z-index: var(--z-elevated);
75
  position: relative;
76
  }
77
- .html-embed__title {
78
- text-align: left;
79
- font-weight: 600;
80
- font-size: 0.95rem;
81
  color: var(--text-color);
82
  margin: 0;
83
  padding: 0;
@@ -89,7 +163,7 @@ const htmlWithId = id && html ? html.replace(/<div class="([^"]*)"[^>]*>/, `<div
89
  z-index: var(--z-elevated);
90
  }
91
  .html-embed__card {
92
- background: var(--code-bg);
93
  border: 1px solid var(--border-color);
94
  border-radius: 10px;
95
  padding: 24px;
@@ -98,14 +172,14 @@ const htmlWithId = id && html ? html.replace(/<div class="([^"]*)"[^>]*>/, `<div
98
  }
99
  .html-embed__card.is-frameless {
100
  background: transparent;
101
- border-color: transparent;
102
  padding: 0;
103
  }
104
- .html-embed__desc {
105
- text-align: left;
106
- font-size: 0.9rem;
107
- color: var(--muted-color);
108
- margin: 0;
109
  padding: 0;
110
  padding-top: var(--spacing-1);
111
  position: relative;
@@ -114,63 +188,220 @@ const htmlWithId = id && html ? html.replace(/<div class="([^"]*)"[^>]*>/, `<div
114
  width: 100%;
115
  background: var(--page-bg);
116
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  /* Plotly – fragments & controls */
118
- .html-embed__card svg text { fill: var(--text-color); }
119
- .html-embed__card label { color: var(--text-color); }
120
- .plotly-graph-div { width: 100%; min-height: 320px; }
121
- @media (max-width: 768px) { .plotly-graph-div { min-height: 260px; } }
122
- [id^="plot-"] { display: flex; flex-direction: column; align-items: center; gap: 15px; }
123
- .plotly_caption { font-style: italic; margin-top: 10px; }
124
- .plotly_controls { display: flex; flex-wrap: wrap; justify-content: center; gap: 30px; }
125
- .plotly_input_container { display: flex; align-items: center; flex-direction: column; gap: 10px; }
126
- .plotly_input_container > select { padding: 2px 4px; line-height: 1.5em; text-align: center; border-radius: 4px; font-size: 12px; background-color: var(--neutral-200); outline: none; border: 1px solid var(--neutral-300); }
127
- .plotly_slider { display: flex; align-items: center; gap: 10px; }
128
- .plotly_slider > input[type="range"] { -webkit-appearance: none; appearance: none; height: 2px; background: var(--neutral-400); border-radius: 5px; outline: none; }
129
- .plotly_slider > input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; border-radius: 50%; background: var(--primary-color); cursor: pointer; }
130
- .plotly_slider > input[type="range"]::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: var(--primary-color); cursor: pointer; }
131
- .plotly_slider > span { font-size: 14px; line-height: 1.6em; min-width: 16px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  /* Dark mode overrides for Plotly readability */
133
- [data-theme="dark"] .html-embed__card:not(.is-frameless) { background: #12151b; border-color: rgba(255,255,255,.15); }
134
  [data-theme="dark"] .html-embed__card .xaxislayer-above text,
135
  [data-theme="dark"] .html-embed__card .yaxislayer-above text,
136
  [data-theme="dark"] .html-embed__card .infolayer text,
137
  [data-theme="dark"] .html-embed__card .legend text,
138
  [data-theme="dark"] .html-embed__card .annotation text,
139
  [data-theme="dark"] .html-embed__card .colorbar text,
140
- [data-theme="dark"] .html-embed__card .hoverlayer text { fill: #fff !important; }
 
 
141
  [data-theme="dark"] .html-embed__card .xaxislayer-above path,
142
  [data-theme="dark"] .html-embed__card .yaxislayer-above path,
143
  [data-theme="dark"] .html-embed__card .xlines-above,
144
- [data-theme="dark"] .html-embed__card .ylines-above { stroke: rgba(255,255,255,.35) !important; }
145
- [data-theme="dark"] .html-embed__card .gridlayer path { stroke: rgba(255,255,255,.15) !important; }
146
- [data-theme="dark"] .html-embed__card .legend rect.bg { fill: rgba(0,0,0,.25) !important; stroke: rgba(255,255,255,.2) !important; }
147
- [data-theme="dark"] .html-embed__card .hoverlayer .bg { fill: rgba(0,0,0,.8) !important; stroke: rgba(255,255,255,.2) !important; }
148
- [data-theme="dark"] .html-embed__card .colorbar .cbbg { fill: rgba(0,0,0,.25) !important; stroke: rgba(255,255,255,.2) !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  @media print {
150
- .html-embed, .html-embed__card { max-width: 100% !important; width: 100% !important; margin-left: 0 !important; margin-right: 0 !important; }
151
- .html-embed__card { padding: 6px; }
152
- .html-embed__card.is-frameless { padding: 0; }
 
 
 
 
 
 
 
 
 
 
153
  .html-embed__card svg,
154
  .html-embed__card canvas,
155
- .html-embed__card img { max-width: 100% !important; height: auto !important; }
156
- .html-embed__card > div[id^="frag-"] { width: 100% !important; }
 
 
 
 
 
157
  }
158
  @media print {
159
  /* Avoid breaks inside embeds */
160
- .html-embed, .html-embed__card { break-inside: avoid; page-break-inside: avoid; }
 
 
 
 
161
  /* Constrain width and scale inner content */
162
- .html-embed, .html-embed__card { max-width: 100% !important; width: 100% !important; }
163
- .html-embed__card { padding: 6px; }
164
- .html-embed__card.is-frameless { padding: 0; }
 
 
 
 
 
 
 
 
165
  .html-embed__card svg,
166
  .html-embed__card canvas,
167
  .html-embed__card img,
168
  .html-embed__card video,
169
- .html-embed__card iframe { max-width: 100% !important; height: auto !important; }
170
- .html-embed__card > div[id^="frag-"] { width: 100% !important; max-width: 100% !important; }
 
 
 
 
 
 
171
  /* Center and constrain the banner (galaxy) when printing */
172
- .html-embed .d3-galaxy { width: 100% !important; max-width: 980px !important; margin-left: auto !important; margin-right: auto !important; }
 
 
 
 
 
173
  }
174
  </style>
175
-
176
-
 
1
  ---
2
+ interface Props {
3
+ src: string;
4
+ title?: string;
5
+ desc?: string;
6
+ caption?: string;
7
+ frameless?: boolean;
8
+ align?: "left" | "center" | "right";
9
+ id?: string;
10
+ data?: string | string[];
11
+ config?: any;
12
+ }
13
+ const {
14
+ src,
15
+ title,
16
+ desc,
17
+ caption,
18
+ frameless = false,
19
+ align = "left",
20
+ id,
21
+ data,
22
+ config,
23
+ } = Astro.props as Props;
24
 
25
  // Load all .html embeds under src/content/embeds/** as strings (dev & build)
26
+ const embeds = (import.meta as any).glob("../content/embeds/**/*.html", {
27
+ query: "?raw",
28
+ import: "default",
29
+ eager: true,
30
+ }) as Record<string, string>;
31
 
32
  function resolveFragment(requested: string): string | null {
33
  // Allow both "banner.html" and "embeds/banner.html"
34
+ const needle = requested.replace(/^\/*/, "");
35
  for (const [key, html] of Object.entries(embeds)) {
36
+ if (
37
+ key.endsWith("/" + needle) ||
38
+ key.endsWith("/" + needle.replace(/^embeds\//, ""))
39
+ ) {
40
  return html;
41
  }
42
  }
 
45
 
46
  const html = resolveFragment(src);
47
  const mountId = `frag-${Math.random().toString(36).slice(2)}`;
48
+ const dataAttr = Array.isArray(data)
49
+ ? JSON.stringify(data)
50
+ : typeof data === "string"
51
+ ? data
52
+ : undefined;
53
+ const configAttr =
54
+ typeof config === "string"
55
+ ? config
56
+ : config != null
57
+ ? JSON.stringify(config)
58
+ : undefined;
59
 
60
  // Apply the ID to the HTML content if provided
61
+ const htmlWithId =
62
+ id && html
63
+ ? html.replace(/<div class="([^"]*)"[^>]*>/, `<div class="$1" id="${id}">`)
64
+ : html;
65
  ---
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
+ {
68
+ html ? (
69
+ <figure class="html-embed" id={id}>
70
+ {title && (
71
+ <figcaption class="html-embed__title" style={`text-align:${align}`}>
72
+ {title}
73
+ </figcaption>
74
+ )}
75
+ <div class={`html-embed__card${frameless ? " is-frameless" : ""}`}>
76
+ <div
77
+ id={mountId}
78
+ data-datafiles={dataAttr}
79
+ data-config={configAttr}
80
+ set:html={htmlWithId}
81
+ />
82
+ </div>
83
+ {(desc || caption) && (
84
+ <figcaption
85
+ class="html-embed__desc"
86
+ style={`text-align:${align}`}
87
+ set:html={caption || desc}
88
+ />
89
+ )}
90
+ </figure>
91
+ ) : (
92
+ <figure class="html-embed html-embed--error" id={id}>
93
+ <div class="html-embed__card html-embed__card--error">
94
+ <div class="html-embed__error">
95
+ <strong>Embed not found</strong>
96
+ <p>
97
+ The requested embed could not be loaded: <code>{src}</code>
98
+ </p>
99
+ </div>
100
+ </div>
101
+ </figure>
102
+ )
103
+ }
104
 
105
  <script>
106
  // Re-execute <script> tags inside the injected fragment (innerHTML doesn't run scripts)
 
108
  const mount = scriptEl ? scriptEl.previousElementSibling : null;
109
  const execute = () => {
110
  if (!mount) return;
111
+ const scripts = mount.querySelectorAll("script");
112
+ scripts.forEach((old) => {
113
  // ignore non-executable types (e.g., application/json)
114
+ if (
115
+ old.type &&
116
+ old.type !== "text/javascript" &&
117
+ old.type !== "module" &&
118
+ old.type !== ""
119
+ )
120
+ return;
121
+ if (old.dataset.executed === "true") return;
122
+ old.dataset.executed = "true";
123
  if (old.src) {
124
+ const s = document.createElement("script");
125
+ Array.from(old.attributes).forEach((attr) =>
126
+ s.setAttribute(attr.name, attr.value),
127
+ );
128
  document.body.appendChild(s);
129
  } else {
130
  try {
131
  // run inline
132
+ (0, eval)(old.text || "");
133
  } catch (e) {
134
+ console.error("HtmlEmbed inline script error:", e);
135
  }
136
  }
137
  });
138
  };
139
  // Execute after DOM is parsed (ensures deferred module scripts are executed first)
140
+ if (document.readyState === "loading")
141
+ document.addEventListener("DOMContentLoaded", execute, { once: true });
142
  else execute();
143
+ </script>
144
 
145
  <style is:global>
146
+ .html-embed {
147
+ margin: 0 0 var(--block-spacing-y);
148
  z-index: var(--z-elevated);
149
  position: relative;
150
  }
151
+ .html-embed__title {
152
+ text-align: left;
153
+ font-weight: 600;
154
+ font-size: 0.95rem;
155
  color: var(--text-color);
156
  margin: 0;
157
  padding: 0;
 
163
  z-index: var(--z-elevated);
164
  }
165
  .html-embed__card {
166
+ background-color: var(--surface-bg);
167
  border: 1px solid var(--border-color);
168
  border-radius: 10px;
169
  padding: 24px;
 
172
  }
173
  .html-embed__card.is-frameless {
174
  background: transparent;
175
+ border: none;
176
  padding: 0;
177
  }
178
+ .html-embed__desc {
179
+ text-align: left;
180
+ font-size: 0.9rem;
181
+ color: var(--muted-color);
182
+ margin: 0;
183
  padding: 0;
184
  padding-top: var(--spacing-1);
185
  position: relative;
 
188
  width: 100%;
189
  background: var(--page-bg);
190
  }
191
+ /* Error state for missing embeds */
192
+ .html-embed__card--error {
193
+ background: #fef2f2;
194
+ border: 2px solid #dc2626;
195
+ border-radius: 8px;
196
+ padding: 20px;
197
+ }
198
+ .html-embed__error {
199
+ text-align: center;
200
+ color: #dc2626;
201
+ }
202
+ .html-embed__error strong {
203
+ display: block;
204
+ font-size: 1.1rem;
205
+ font-weight: 600;
206
+ margin-bottom: 8px;
207
+ }
208
+ .html-embed__error p {
209
+ margin: 0;
210
+ font-size: 0.9rem;
211
+ line-height: 1.5;
212
+ }
213
+ .html-embed__error code {
214
+ background: rgba(220, 38, 38, 0.1);
215
+ padding: 2px 6px;
216
+ border-radius: 4px;
217
+ font-family: var(--font-mono);
218
+ font-size: 0.85rem;
219
+ word-break: break-all;
220
+ }
221
+ /* Dark mode for error state */
222
+ [data-theme="dark"] .html-embed__card--error {
223
+ background: #1f2937;
224
+ border-color: #ef4444;
225
+ }
226
+ [data-theme="dark"] .html-embed__error {
227
+ color: #ef4444;
228
+ }
229
+ [data-theme="dark"] .html-embed__error code {
230
+ background: rgba(239, 68, 68, 0.2);
231
+ }
232
  /* Plotly – fragments & controls */
233
+ .html-embed__card svg text {
234
+ fill: var(--text-color);
235
+ }
236
+ .html-embed__card label {
237
+ color: var(--text-color);
238
+ }
239
+ .plotly-graph-div {
240
+ width: 100%;
241
+ min-height: 320px;
242
+ }
243
+ @media (max-width: 768px) {
244
+ .plotly-graph-div {
245
+ min-height: 260px;
246
+ }
247
+ }
248
+ [id^="plot-"] {
249
+ display: flex;
250
+ flex-direction: column;
251
+ align-items: center;
252
+ gap: 15px;
253
+ }
254
+ .plotly_caption {
255
+ font-style: italic;
256
+ margin-top: 10px;
257
+ }
258
+ .plotly_controls {
259
+ display: flex;
260
+ flex-wrap: wrap;
261
+ justify-content: center;
262
+ gap: 30px;
263
+ }
264
+ .plotly_input_container {
265
+ display: flex;
266
+ align-items: center;
267
+ flex-direction: column;
268
+ gap: 10px;
269
+ }
270
+ .plotly_input_container > select {
271
+ padding: 2px 4px;
272
+ line-height: 1.5em;
273
+ text-align: center;
274
+ border-radius: 4px;
275
+ font-size: 12px;
276
+ background-color: var(--neutral-200);
277
+ outline: none;
278
+ border: 1px solid var(--neutral-300);
279
+ }
280
+ .plotly_slider {
281
+ display: flex;
282
+ align-items: center;
283
+ gap: 10px;
284
+ }
285
+ .plotly_slider > input[type="range"] {
286
+ -webkit-appearance: none;
287
+ appearance: none;
288
+ height: 2px;
289
+ background: var(--neutral-400);
290
+ border-radius: 5px;
291
+ outline: none;
292
+ }
293
+ .plotly_slider > input[type="range"]::-webkit-slider-thumb {
294
+ -webkit-appearance: none;
295
+ width: 18px;
296
+ height: 18px;
297
+ border-radius: 50%;
298
+ background: var(--primary-color);
299
+ cursor: pointer;
300
+ }
301
+ .plotly_slider > input[type="range"]::-moz-range-thumb {
302
+ width: 18px;
303
+ height: 18px;
304
+ border-radius: 50%;
305
+ background: var(--primary-color);
306
+ cursor: pointer;
307
+ }
308
+ .plotly_slider > span {
309
+ font-size: 14px;
310
+ line-height: 1.6em;
311
+ min-width: 16px;
312
+ }
313
  /* Dark mode overrides for Plotly readability */
 
314
  [data-theme="dark"] .html-embed__card .xaxislayer-above text,
315
  [data-theme="dark"] .html-embed__card .yaxislayer-above text,
316
  [data-theme="dark"] .html-embed__card .infolayer text,
317
  [data-theme="dark"] .html-embed__card .legend text,
318
  [data-theme="dark"] .html-embed__card .annotation text,
319
  [data-theme="dark"] .html-embed__card .colorbar text,
320
+ [data-theme="dark"] .html-embed__card .hoverlayer text {
321
+ fill: #fff !important;
322
+ }
323
  [data-theme="dark"] .html-embed__card .xaxislayer-above path,
324
  [data-theme="dark"] .html-embed__card .yaxislayer-above path,
325
  [data-theme="dark"] .html-embed__card .xlines-above,
326
+ [data-theme="dark"] .html-embed__card .ylines-above {
327
+ stroke: rgba(255, 255, 255, 0.35) !important;
328
+ }
329
+ [data-theme="dark"] .html-embed__card .gridlayer path {
330
+ stroke: rgba(255, 255, 255, 0.15) !important;
331
+ }
332
+ [data-theme="dark"] .html-embed__card .legend rect.bg {
333
+ fill: rgba(0, 0, 0, 0.25) !important;
334
+ stroke: rgba(255, 255, 255, 0.2) !important;
335
+ }
336
+ [data-theme="dark"] .html-embed__card .hoverlayer .bg {
337
+ fill: rgba(0, 0, 0, 0.8) !important;
338
+ stroke: rgba(255, 255, 255, 0.2) !important;
339
+ }
340
+ [data-theme="dark"] .html-embed__card .colorbar .cbbg {
341
+ fill: rgba(0, 0, 0, 0.25) !important;
342
+ stroke: rgba(255, 255, 255, 0.2) !important;
343
+ }
344
  @media print {
345
+ .html-embed,
346
+ .html-embed__card {
347
+ max-width: 100% !important;
348
+ width: 100% !important;
349
+ margin-left: 0 !important;
350
+ margin-right: 0 !important;
351
+ }
352
+ .html-embed__card {
353
+ padding: 6px;
354
+ }
355
+ .html-embed__card.is-frameless {
356
+ padding: 0;
357
+ }
358
  .html-embed__card svg,
359
  .html-embed__card canvas,
360
+ .html-embed__card img {
361
+ max-width: 100% !important;
362
+ height: auto !important;
363
+ }
364
+ .html-embed__card > div[id^="frag-"] {
365
+ width: 100% !important;
366
+ }
367
  }
368
  @media print {
369
  /* Avoid breaks inside embeds */
370
+ .html-embed,
371
+ .html-embed__card {
372
+ break-inside: avoid;
373
+ page-break-inside: avoid;
374
+ }
375
  /* Constrain width and scale inner content */
376
+ .html-embed,
377
+ .html-embed__card {
378
+ max-width: 100% !important;
379
+ width: 100% !important;
380
+ }
381
+ .html-embed__card {
382
+ padding: 6px;
383
+ }
384
+ .html-embed__card.is-frameless {
385
+ padding: 0;
386
+ }
387
  .html-embed__card svg,
388
  .html-embed__card canvas,
389
  .html-embed__card img,
390
  .html-embed__card video,
391
+ .html-embed__card iframe {
392
+ max-width: 100% !important;
393
+ height: auto !important;
394
+ }
395
+ .html-embed__card > div[id^="frag-"] {
396
+ width: 100% !important;
397
+ max-width: 100% !important;
398
+ }
399
  /* Center and constrain the banner (galaxy) when printing */
400
+ .html-embed .d3-galaxy {
401
+ width: 100% !important;
402
+ max-width: 980px !important;
403
+ margin-left: auto !important;
404
+ margin-right: auto !important;
405
+ }
406
  }
407
  </style>
 
 
app/src/content/article.mdx CHANGED
@@ -380,9 +380,7 @@ Note that we trained this model for 1k steps and stopped early. For a more compl
380
 
381
  Starting from the above checkpoint from SFT, we used the [`GKDTrainer`](https://huggingface.co/docs/trl/en/gkd_trainer) with the [`allenai/tulu-3-sft-mixture`](https://huggingface.co/datasets/allenai/tulu-3-sft-mixture) dataset which improved performance on IFEval ***79.5%*** to ***82.8%*** whilst maintaining an approximate livecodebench score of ***39.8%***.
382
 
383
- ---
384
- <HtmlEmbed id="domain-distillation" src="domain-distillation.html" desc="Results from first finetuning on Codeforces data to improve LCB and then recovering performance on IFEval by distilling the initial Qwen3-4B model." />
385
- ---
386
 
387
  ### Building it for yourself
388
 
 
380
 
381
  Starting from the above checkpoint from SFT, we used the [`GKDTrainer`](https://huggingface.co/docs/trl/en/gkd_trainer) with the [`allenai/tulu-3-sft-mixture`](https://huggingface.co/datasets/allenai/tulu-3-sft-mixture) dataset which improved performance on IFEval ***79.5%*** to ***82.8%*** whilst maintaining an approximate livecodebench score of ***39.8%***.
382
 
383
+ <HtmlEmbed frameless id="domain-distillation" src="domain-distillation.html" desc="Results from first finetuning on Codeforces data to improve LCB and then recovering performance on IFEval by distilling the initial Qwen3-4B model." />
 
 
384
 
385
  ### Building it for yourself
386
 
app/src/content/embeds/domain-distillation.html CHANGED
@@ -1,26 +1,26 @@
1
- <table style="border-collapse: separate; border-spacing: 0; font-family: Roboto, sans-serif; font-size: 14px; border: 1px solid #ddd; border-radius: 8px; overflow: hidden;">
2
  <thead>
3
  <tr>
4
- <th style="padding: 8px; text-align: left; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; background-color: #f5f5f5;">Model</th>
5
- <th style="padding: 8px; text-align: center; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; background-color: #f5f5f5;">IFEval</th>
6
- <th style="padding: 8px; text-align: center; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; background-color: #f5f5f5;">LCB</th>
7
  </tr>
8
  </thead>
9
  <tbody>
10
  <tr>
11
- <td style="padding: 8px; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd;">Qwen3-4B</td>
12
- <td style="width:50px; padding: 8px; text-align: center; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; background-color: #94e1a1; color: white; font-weight: bold;">83.4</td>
13
- <td style="width:50px; padding: 8px; text-align: center; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; background-color: lightgrey; color: white; font-weight: bold;">35.1</td>
14
  </tr>
15
  <tr>
16
- <td style="padding: 8px; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd;">Qwen3-4B + Codeforces SFT</td>
17
- <td style="width:50px; padding: 8px; text-align: center; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; background-color: lightgrey; color: white; font-weight: bold;">79.48</td>
18
- <td style="width:50px; padding: 8px; text-align: center; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; background-color: #94e1a1; color: white; font-weight: bold;">40.29</td>
19
  </tr>
20
  <tr>
21
- <td style="padding: 8px; border-right: 1px solid #ddd;">Qwen3-4B + Codeforces SFT + Tulu3 GKD</td>
22
- <td style="width:50px; padding: 8px; text-align: center; border-right: 1px solid #ddd; background-color: #94e1a1; color: white; font-weight: bold;">82.8</td>
23
- <td style="width:50px; padding: 8px; text-align: center; border-right: 1px solid #ddd; background-color: #94e1a1; color: white; font-weight: bold;">39.8</td>
24
  </tr>
25
  </tbody>
26
  </table>
 
1
+ <table class="table-scroll" style="width: 100%;">
2
  <thead>
3
  <tr>
4
+ <th>Model</th>
5
+ <th>IFEval</th>
6
+ <th>LCB</th>
7
  </tr>
8
  </thead>
9
  <tbody>
10
  <tr>
11
+ <td>Qwen3-4B</td>
12
+ <td style="background-color: var(--table-highlight-bg);">83.4</td>
13
+ <td>35.1</td>
14
  </tr>
15
  <tr>
16
+ <td>Qwen3-4B + Codeforces SFT</td>
17
+ <td>79.48</td>
18
+ <td style="background-color: var(--table-highlight-bg);">40.29</td>
19
  </tr>
20
  <tr>
21
+ <td>Qwen3-4B + Codeforces SFT + Tulu3 GKD</td>
22
+ <td style="background-color: var(--table-highlight-bg);">82.8</td>
23
+ <td style="background-color: var(--table-highlight-bg);">39.8</td>
24
  </tr>
25
  </tbody>
26
  </table>
app/src/styles/_variables.css CHANGED
@@ -76,6 +76,7 @@
76
  --table-border-radius: 8px;
77
  --table-header-bg: oklch(from var(--surface-bg) calc(l - 0.02) c h);
78
  --table-row-odd-bg: oklch(from var(--surface-bg) calc(l - 0.01) c h);
 
79
 
80
  /* Z-index */
81
  --z-base: 0;
@@ -113,6 +114,9 @@
113
  --primary-color-active: oklch(from var(--primary-color) calc(l - 0.10) c h);
114
  --on-primary: #0f1115;
115
 
 
 
 
116
  color-scheme: dark;
117
  background: var(--page-bg);
118
  }
 
76
  --table-border-radius: 8px;
77
  --table-header-bg: oklch(from var(--surface-bg) calc(l - 0.02) c h);
78
  --table-row-odd-bg: oklch(from var(--surface-bg) calc(l - 0.01) c h);
79
+ --table-highlight-bg: oklch(0.85 0.10 150);
80
 
81
  /* Z-index */
82
  --z-base: 0;
 
114
  --primary-color-active: oklch(from var(--primary-color) calc(l - 0.10) c h);
115
  --on-primary: #0f1115;
116
 
117
+ /* Table highlight (darker green for dark mode) */
118
+ --table-highlight-bg: oklch(0.45 0.12 150);
119
+
120
  color-scheme: dark;
121
  background: var(--page-bg);
122
  }
app/src/styles/components/_table.css CHANGED
@@ -2,6 +2,7 @@
2
  border-collapse: collapse;
3
  table-layout: auto;
4
  margin: 0;
 
5
  }
6
 
7
  .content-grid main th,
@@ -12,7 +13,7 @@
12
  white-space: nowrap;
13
  /* prevent squashing; allow horizontal scroll instead */
14
  word-break: auto-phrase;
15
- white-space: break-spaces;
16
  vertical-align: top;
17
  }
18
 
 
2
  border-collapse: collapse;
3
  table-layout: auto;
4
  margin: 0;
5
+ background-color: var(--surface-bg);
6
  }
7
 
8
  .content-grid main th,
 
13
  white-space: nowrap;
14
  /* prevent squashing; allow horizontal scroll instead */
15
  word-break: auto-phrase;
16
+ /* white-space: break-spaces; */
17
  vertical-align: top;
18
  }
19