readwhitepaper-embed 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1206 @@
1
+ /* readwhitepaper-embed v1.0.0 | MIT | https://widget.readwhitepaper.com */
2
+
3
+ // src/styles/modern.ts
4
+ function getModernCSS() {
5
+ return `
6
+ /* Modern: gradient accent header */
7
+ .readwhitepaper-header {
8
+ background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 70%, #000));
9
+ border-radius: 12px 12px 0 0;
10
+ padding: 16px 20px;
11
+ display: flex;
12
+ align-items: flex-start;
13
+ gap: 14px;
14
+ }
15
+
16
+ .readwhitepaper-header-title {
17
+ font-size: 15px;
18
+ font-weight: 700;
19
+ color: #fff;
20
+ margin: 0 0 4px 0;
21
+ line-height: 1.3;
22
+ }
23
+
24
+ .readwhitepaper-header-subtitle {
25
+ font-size: 12px;
26
+ color: rgba(255, 255, 255, 0.8);
27
+ margin: 0;
28
+ }
29
+
30
+ /* Image/preview area \u2014 for document icons, logos */
31
+ .readwhitepaper-img {
32
+ width: 56px;
33
+ height: 56px;
34
+ border-radius: 8px;
35
+ object-fit: cover;
36
+ background: rgba(255, 255, 255, 0.15);
37
+ flex-shrink: 0;
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ overflow: hidden;
42
+ }
43
+
44
+ .readwhitepaper-img svg {
45
+ width: 28px;
46
+ height: 28px;
47
+ color: rgba(255, 255, 255, 0.9);
48
+ }
49
+
50
+ /* Body area */
51
+ .readwhitepaper-body {
52
+ padding: 16px 20px;
53
+ }
54
+
55
+ /* Key-value rows \u2014 spacious */
56
+ .readwhitepaper-row {
57
+ display: flex;
58
+ justify-content: space-between;
59
+ align-items: flex-start;
60
+ gap: 12px;
61
+ padding: 8px 0;
62
+ border-bottom: 1px solid var(--border);
63
+ }
64
+
65
+ .readwhitepaper-row:last-child {
66
+ border-bottom: none;
67
+ }
68
+
69
+ .readwhitepaper-label {
70
+ font-size: 12px;
71
+ font-weight: 500;
72
+ color: var(--muted);
73
+ white-space: nowrap;
74
+ flex-shrink: 0;
75
+ min-width: 30%;
76
+ }
77
+
78
+ .readwhitepaper-value {
79
+ font-size: 13px;
80
+ color: var(--text);
81
+ text-align: right;
82
+ word-break: break-word;
83
+ }
84
+
85
+ /* Section title */
86
+ .readwhitepaper-section-title {
87
+ font-size: 11px;
88
+ font-weight: 600;
89
+ color: var(--muted);
90
+ text-transform: uppercase;
91
+ letter-spacing: 0.06em;
92
+ margin: 0 0 10px 0;
93
+ }
94
+
95
+ /* Tags \u2014 colored rounded badges */
96
+ .readwhitepaper-tag {
97
+ display: inline-block;
98
+ font-size: 11px;
99
+ font-weight: 600;
100
+ padding: 3px 10px;
101
+ border-radius: 12px;
102
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
103
+ color: var(--accent);
104
+ margin: 2px 3px 2px 0;
105
+ letter-spacing: 0.02em;
106
+ }
107
+
108
+ /* Link */
109
+ .readwhitepaper-link {
110
+ font-size: 13px;
111
+ font-weight: 500;
112
+ color: var(--link);
113
+ text-decoration: none;
114
+ display: inline-flex;
115
+ align-items: center;
116
+ gap: 4px;
117
+ }
118
+
119
+ .readwhitepaper-link:hover {
120
+ opacity: 0.8;
121
+ text-decoration: underline;
122
+ }
123
+
124
+ .readwhitepaper-link svg {
125
+ width: 12px;
126
+ height: 12px;
127
+ flex-shrink: 0;
128
+ }
129
+
130
+ /* Footer link row */
131
+ .readwhitepaper-footer-link {
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: space-between;
135
+ padding: 12px 20px;
136
+ border-top: 1px solid var(--border);
137
+ gap: 8px;
138
+ }
139
+
140
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
141
+ Card shared: key-value dotted rows
142
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
143
+ .readwhitepaper-kv-rows { padding:10px 18px; border-bottom:1px solid var(--border); }
144
+ .readwhitepaper-kv-row { display:flex; justify-content:space-between; align-items:baseline; padding:4px 0; border-bottom:1px dotted var(--border); }
145
+ .readwhitepaper-kv-row:last-child { border-bottom:none; }
146
+ .readwhitepaper-kv-label { font-size:11px; color:var(--muted); }
147
+ .readwhitepaper-kv-value { font-size:11px; font-weight:600; color:var(--text); }
148
+
149
+ /* Card shared: pill tags */
150
+ .readwhitepaper-pills { display:flex; flex-wrap:wrap; gap:4px; padding:10px 18px; border-bottom:1px solid var(--border); }
151
+ .readwhitepaper-pill { padding:2px 8px; border-radius:10px; font-size:11px; font-weight:500; background:color-mix(in srgb, var(--accent) 10%, var(--bg)); color:var(--accent); text-decoration:none; }
152
+ .readwhitepaper-pill:hover { opacity:0.8; }
153
+
154
+ /* Card shared: section label */
155
+ .readwhitepaper-section-label { font-size:10px; text-transform:uppercase; letter-spacing:0.05em; color:var(--accent); font-weight:600; margin-bottom:3px; }
156
+
157
+ /* Card shared: description */
158
+ .readwhitepaper-desc { padding:10px 18px; font-size:11px; color:var(--muted); line-height:1.5; border-bottom:1px solid var(--border); }
159
+
160
+ /* Card shared: view link */
161
+ .readwhitepaper-view-link { display:block; text-align:center; padding:10px 18px; border-bottom:1px solid var(--border); }
162
+ .readwhitepaper-view-link a { color:var(--link); text-decoration:none; font-size:12px; font-weight:500; display:inline-flex; align-items:center; gap:4px; }
163
+ .readwhitepaper-view-link a:hover { text-decoration:underline; }
164
+ .readwhitepaper-view-link svg { width:12px; height:12px; }
165
+
166
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
167
+ Card domain: whitepaper abstract
168
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
169
+ .readwhitepaper-abstract {
170
+ padding: 10px 18px;
171
+ font-size: 12px;
172
+ color: var(--text);
173
+ line-height: 1.55;
174
+ border-bottom: 1px solid var(--border);
175
+ }
176
+
177
+ /* Card domain: authors row */
178
+ .readwhitepaper-authors {
179
+ padding: 8px 18px;
180
+ font-size: 11px;
181
+ color: var(--muted);
182
+ border-bottom: 1px solid var(--border);
183
+ }
184
+
185
+ .readwhitepaper-authors strong {
186
+ color: var(--text);
187
+ font-weight: 600;
188
+ }
189
+
190
+ /* Card domain: glossary summary block */
191
+ .readwhitepaper-summary {
192
+ padding: 12px 18px;
193
+ font-size: 12px;
194
+ color: var(--text);
195
+ line-height: 1.55;
196
+ border-bottom: 1px solid var(--border);
197
+ }
198
+
199
+ /* Card domain: related terms in pills row */
200
+ .readwhitepaper-pills-row {
201
+ display: flex;
202
+ flex-wrap: wrap;
203
+ gap: 4px;
204
+ padding: 8px 18px;
205
+ border-bottom: 1px solid var(--border);
206
+ }
207
+
208
+ /* Card domain: actions links */
209
+ .readwhitepaper-actions {
210
+ padding: 10px 18px;
211
+ display: flex;
212
+ flex-direction: column;
213
+ gap: 6px;
214
+ border-bottom: 1px solid var(--border);
215
+ }
216
+ `;
217
+ }
218
+
219
+ // src/styles/minimal.ts
220
+ function getMinimalCSS() {
221
+ return `
222
+ /* Minimal: thin accent border, no gradient */
223
+ .readwhitepaper-widget {
224
+ font-family: 'Fira Code', 'Cascadia Code', 'JetBrains Mono', ui-monospace, 'SFMono-Regular', Consolas, monospace;
225
+ font-size: 12px;
226
+ }
227
+
228
+ /* Header \u2014 surface bg with thin accent top border */
229
+ .readwhitepaper-header {
230
+ background: var(--surface);
231
+ border-top: 2px solid var(--accent);
232
+ padding: 8px 10px;
233
+ display: flex;
234
+ align-items: flex-start;
235
+ gap: 10px;
236
+ }
237
+
238
+ .readwhitepaper-header-title {
239
+ font-size: 13px;
240
+ font-weight: 600;
241
+ color: var(--text);
242
+ margin: 0 0 2px 0;
243
+ line-height: 1.3;
244
+ font-family: inherit;
245
+ }
246
+
247
+ .readwhitepaper-header-subtitle {
248
+ font-size: 11px;
249
+ color: var(--muted);
250
+ margin: 0;
251
+ }
252
+
253
+ /* Image/preview area \u2014 compact */
254
+ .readwhitepaper-img {
255
+ width: 36px;
256
+ height: 36px;
257
+ border-radius: 4px;
258
+ background: var(--badge-bg);
259
+ flex-shrink: 0;
260
+ display: flex;
261
+ align-items: center;
262
+ justify-content: center;
263
+ overflow: hidden;
264
+ border: 1px solid var(--border);
265
+ }
266
+
267
+ .readwhitepaper-img svg {
268
+ width: 18px;
269
+ height: 18px;
270
+ color: var(--muted);
271
+ }
272
+
273
+ /* Body area */
274
+ .readwhitepaper-body {
275
+ padding: 8px 10px;
276
+ }
277
+
278
+ /* Key-value rows \u2014 compact */
279
+ .readwhitepaper-row {
280
+ display: flex;
281
+ justify-content: space-between;
282
+ align-items: baseline;
283
+ gap: 8px;
284
+ padding: 4px 0;
285
+ border-bottom: 1px solid var(--border);
286
+ }
287
+
288
+ .readwhitepaper-row:last-child {
289
+ border-bottom: none;
290
+ }
291
+
292
+ .readwhitepaper-label {
293
+ font-size: 10px;
294
+ font-weight: 500;
295
+ color: var(--muted);
296
+ white-space: nowrap;
297
+ flex-shrink: 0;
298
+ min-width: 30%;
299
+ text-transform: uppercase;
300
+ letter-spacing: 0.05em;
301
+ }
302
+
303
+ .readwhitepaper-value {
304
+ font-size: 11px;
305
+ color: var(--text);
306
+ text-align: right;
307
+ word-break: break-word;
308
+ font-family: inherit;
309
+ }
310
+
311
+ /* Section title */
312
+ .readwhitepaper-section-title {
313
+ font-size: 9px;
314
+ font-weight: 600;
315
+ color: var(--muted);
316
+ text-transform: uppercase;
317
+ letter-spacing: 0.08em;
318
+ margin: 0 0 6px 0;
319
+ }
320
+
321
+ /* Tags \u2014 muted, minimal */
322
+ .readwhitepaper-tag {
323
+ display: inline-block;
324
+ font-size: 10px;
325
+ font-weight: 500;
326
+ padding: 1px 6px;
327
+ border-radius: 3px;
328
+ background: var(--badge-bg);
329
+ color: var(--badge-text);
330
+ border: 1px solid var(--border);
331
+ margin: 1px 2px 1px 0;
332
+ }
333
+
334
+ /* Link */
335
+ .readwhitepaper-link {
336
+ font-size: 11px;
337
+ font-weight: 500;
338
+ color: var(--link);
339
+ text-decoration: none;
340
+ display: inline-flex;
341
+ align-items: center;
342
+ gap: 3px;
343
+ }
344
+
345
+ .readwhitepaper-link:hover {
346
+ text-decoration: underline;
347
+ }
348
+
349
+ .readwhitepaper-link svg {
350
+ width: 10px;
351
+ height: 10px;
352
+ flex-shrink: 0;
353
+ }
354
+
355
+ /* Footer link row */
356
+ .readwhitepaper-footer-link {
357
+ display: flex;
358
+ align-items: center;
359
+ justify-content: space-between;
360
+ padding: 6px 10px;
361
+ border-top: 1px solid var(--border);
362
+ gap: 6px;
363
+ }
364
+
365
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
366
+ Minimal overrides for card shared components
367
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
368
+
369
+ /* KV rows: all monospace */
370
+ .readwhitepaper-kv-rows { padding:6px 10px; border-bottom:1px solid var(--border); }
371
+ .readwhitepaper-kv-row { display:flex; justify-content:space-between; align-items:baseline; padding:3px 0; border-bottom:1px dotted var(--border); }
372
+ .readwhitepaper-kv-row:last-child { border-bottom:none; }
373
+ .readwhitepaper-kv-label { font-size:9px; color:var(--muted); text-transform:uppercase; letter-spacing:0.04em; }
374
+ .readwhitepaper-kv-value { font-size:10px; font-weight:600; color:var(--text); font-family:inherit; }
375
+
376
+ /* Pills: border outline only */
377
+ .readwhitepaper-pills { display:flex; flex-wrap:wrap; gap:3px; padding:6px 10px; border-bottom:1px solid var(--border); }
378
+ .readwhitepaper-pill { padding:1px 6px; border-radius:3px; font-size:10px; font-weight:500; background:transparent; border:1px solid var(--border); color:var(--muted); text-decoration:none; }
379
+ .readwhitepaper-pill:hover { color:var(--text); border-color:var(--accent); }
380
+
381
+ /* Section label */
382
+ .readwhitepaper-section-label { font-size:9px; text-transform:uppercase; letter-spacing:0.06em; color:var(--muted); font-weight:600; margin-bottom:3px; }
383
+
384
+ /* Description: compact */
385
+ .readwhitepaper-desc { padding:6px 10px; font-size:10px; color:var(--muted); line-height:1.4; border-bottom:1px solid var(--border); }
386
+
387
+ /* View link */
388
+ .readwhitepaper-view-link { display:block; text-align:left; padding:6px 10px; border-bottom:1px solid var(--border); }
389
+ .readwhitepaper-view-link a { color:var(--link); text-decoration:none; font-size:11px; font-weight:500; display:inline-flex; align-items:center; gap:3px; }
390
+ .readwhitepaper-view-link a:hover { text-decoration:underline; }
391
+ .readwhitepaper-view-link svg { width:10px; height:10px; }
392
+
393
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
394
+ Minimal: domain-specific overrides
395
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
396
+
397
+ /* Abstract */
398
+ .readwhitepaper-abstract {
399
+ padding: 6px 10px;
400
+ font-size: 10px;
401
+ color: var(--text);
402
+ line-height: 1.4;
403
+ border-bottom: 1px solid var(--border);
404
+ }
405
+
406
+ /* Authors row */
407
+ .readwhitepaper-authors {
408
+ padding: 4px 10px;
409
+ font-size: 10px;
410
+ color: var(--muted);
411
+ border-bottom: 1px solid var(--border);
412
+ }
413
+
414
+ .readwhitepaper-authors strong {
415
+ color: var(--text);
416
+ font-weight: 600;
417
+ font-family: inherit;
418
+ }
419
+
420
+ /* Glossary summary */
421
+ .readwhitepaper-summary {
422
+ padding: 6px 10px;
423
+ font-size: 10px;
424
+ color: var(--text);
425
+ line-height: 1.4;
426
+ border-bottom: 1px solid var(--border);
427
+ }
428
+
429
+ /* Related pills row */
430
+ .readwhitepaper-pills-row {
431
+ display: flex;
432
+ flex-wrap: wrap;
433
+ gap: 3px;
434
+ padding: 4px 10px;
435
+ border-bottom: 1px solid var(--border);
436
+ }
437
+
438
+ /* Actions links */
439
+ .readwhitepaper-actions {
440
+ padding: 6px 10px;
441
+ display: flex;
442
+ flex-direction: column;
443
+ gap: 4px;
444
+ border-bottom: 1px solid var(--border);
445
+ }
446
+
447
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
448
+ Minimal: copy button \u2014 inline symbol style
449
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
450
+ .readwhitepaper-copy-btn {
451
+ background: transparent;
452
+ color: var(--muted);
453
+ border: 1px solid var(--border);
454
+ border-radius: 3px;
455
+ padding: 2px 6px;
456
+ font-size: 10px;
457
+ cursor: pointer;
458
+ display: inline-flex;
459
+ align-items: center;
460
+ gap: 2px;
461
+ transition: color 0.1s, border-color 0.1s;
462
+ font-family: inherit;
463
+ }
464
+
465
+ .readwhitepaper-copy-btn:hover {
466
+ color: var(--text);
467
+ border-color: var(--accent);
468
+ }
469
+
470
+ .readwhitepaper-copy-btn svg {
471
+ width: 10px;
472
+ height: 10px;
473
+ }
474
+ `;
475
+ }
476
+
477
+ // src/themes.ts
478
+ function getStyleCSS(style) {
479
+ switch (style) {
480
+ case "minimal":
481
+ return getMinimalCSS();
482
+ case "modern":
483
+ default:
484
+ return getModernCSS();
485
+ }
486
+ }
487
+ function getThemeCSS(accent, style = "modern") {
488
+ return `
489
+ :host {
490
+ display: block;
491
+ --site-accent: ${accent};
492
+ }
493
+
494
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
495
+ Size variants
496
+ compact=280px, default=420px, large=720px
497
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
498
+ .readwhitepaper-widget {
499
+ box-sizing: border-box;
500
+ min-width: 240px;
501
+ max-width: 420px;
502
+ border-radius: 8px;
503
+ overflow: hidden;
504
+ border: 1px solid var(--border);
505
+ background: var(--bg);
506
+ color: var(--text);
507
+ font-size: 14px;
508
+ line-height: 1.6;
509
+ transition: border-color 0.2s;
510
+ font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
511
+ }
512
+
513
+ .readwhitepaper-widget[data-size="compact"] {
514
+ max-width: 280px;
515
+ font-size: 13px;
516
+ }
517
+
518
+ .readwhitepaper-widget[data-size="default"] {
519
+ max-width: 420px;
520
+ }
521
+
522
+ .readwhitepaper-widget[data-size="large"] {
523
+ max-width: 720px;
524
+ }
525
+
526
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
527
+ Light theme (default)
528
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
529
+ .readwhitepaper-widget[data-theme="light"] {
530
+ --bg: #fff;
531
+ --text: #1e293b;
532
+ --border: #e2e8f0;
533
+ --accent: var(--site-accent);
534
+ --muted: #64748b;
535
+ --surface: #f8fafc;
536
+ --badge-bg: #f1f5f9;
537
+ --badge-text: #374151;
538
+ --link: var(--site-accent);
539
+ --copy-bg: #f3f4f6;
540
+ --copy-hover: #e5e7eb;
541
+ --input-bg: #ffffff;
542
+ --input-border: #d1d5db;
543
+ --input-focus: var(--site-accent);
544
+ --shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
545
+ }
546
+
547
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
548
+ Dark theme
549
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
550
+ .readwhitepaper-widget[data-theme="dark"] {
551
+ --bg: #1a1a1a;
552
+ --text: #f3f4f6;
553
+ --border: #374151;
554
+ --accent: var(--site-accent);
555
+ --muted: #9ca3af;
556
+ --surface: #111827;
557
+ --badge-bg: #374151;
558
+ --badge-text: #d1d5db;
559
+ --link: color-mix(in srgb, var(--site-accent) 80%, #fff);
560
+ --copy-bg: #374151;
561
+ --copy-hover: #4b5563;
562
+ --input-bg: #111111;
563
+ --input-border: #4b5563;
564
+ --input-focus: var(--site-accent);
565
+ --shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
566
+ }
567
+
568
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
569
+ Sepia theme
570
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
571
+ .readwhitepaper-widget[data-theme="sepia"] {
572
+ --bg: #f5f0e8;
573
+ --text: #3d3529;
574
+ --border: #d4c5a9;
575
+ --accent: var(--site-accent);
576
+ --muted: #8b7d6b;
577
+ --surface: #ede8df;
578
+ --badge-bg: #e8e0d0;
579
+ --badge-text: #5c4f3d;
580
+ --link: color-mix(in srgb, var(--site-accent) 70%, #3d3529);
581
+ --copy-bg: #e8e0d0;
582
+ --copy-hover: #ddd4c0;
583
+ --input-bg: #f5f0e8;
584
+ --input-border: #c4b49a;
585
+ --input-focus: var(--site-accent);
586
+ --shadow: 0 1px 3px rgba(61, 53, 41, 0.12);
587
+ }
588
+
589
+ .readwhitepaper-widget *, .readwhitepaper-widget *::before, .readwhitepaper-widget *::after {
590
+ box-sizing: border-box;
591
+ }
592
+
593
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
594
+ Loading state
595
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
596
+ .readwhitepaper-loading {
597
+ padding: 20px 16px;
598
+ text-align: center;
599
+ color: var(--muted);
600
+ font-size: 13px;
601
+ display: flex;
602
+ align-items: center;
603
+ justify-content: center;
604
+ gap: 8px;
605
+ }
606
+
607
+ .readwhitepaper-spinner {
608
+ width: 16px;
609
+ height: 16px;
610
+ border: 2px solid var(--border);
611
+ border-top-color: var(--accent);
612
+ border-radius: 50%;
613
+ animation: readwhitepaper-spin 0.7s linear infinite;
614
+ display: inline-block;
615
+ flex-shrink: 0;
616
+ }
617
+
618
+ @keyframes readwhitepaper-spin {
619
+ to { transform: rotate(360deg); }
620
+ }
621
+
622
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
623
+ Error state
624
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
625
+ .readwhitepaper-error {
626
+ padding: 16px;
627
+ color: var(--muted);
628
+ font-size: 13px;
629
+ text-align: center;
630
+ }
631
+
632
+ .readwhitepaper-error p {
633
+ margin: 0 0 8px 0;
634
+ }
635
+
636
+ .readwhitepaper-error a {
637
+ color: var(--link);
638
+ text-decoration: none;
639
+ }
640
+
641
+ .readwhitepaper-error a:hover {
642
+ text-decoration: underline;
643
+ }
644
+
645
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
646
+ Badge (generic)
647
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
648
+ .readwhitepaper-badge {
649
+ display: inline-block;
650
+ font-size: 10px;
651
+ font-weight: 600;
652
+ padding: 2px 7px;
653
+ border-radius: 4px;
654
+ background: var(--badge-bg);
655
+ color: var(--badge-text);
656
+ text-transform: uppercase;
657
+ letter-spacing: 0.04em;
658
+ }
659
+
660
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
661
+ Search inputs
662
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
663
+ .readwhitepaper-search-wrap {
664
+ padding: 12px 16px;
665
+ }
666
+
667
+ .readwhitepaper-search-form {
668
+ display: flex;
669
+ gap: 8px;
670
+ }
671
+
672
+ .readwhitepaper-search-input {
673
+ flex: 1;
674
+ padding: 8px 12px;
675
+ border: 1px solid var(--input-border);
676
+ border-radius: 6px;
677
+ background: var(--input-bg);
678
+ color: var(--text);
679
+ font-size: 13px;
680
+ font-family: inherit;
681
+ outline: none;
682
+ transition: border-color 0.15s;
683
+ }
684
+
685
+ .readwhitepaper-search-input:focus {
686
+ border-color: var(--input-focus);
687
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--input-focus) 20%, transparent);
688
+ }
689
+
690
+ .readwhitepaper-search-input::placeholder {
691
+ color: var(--muted);
692
+ }
693
+
694
+ .readwhitepaper-search-btn {
695
+ background: var(--accent);
696
+ color: #fff;
697
+ border: none;
698
+ border-radius: 6px;
699
+ padding: 8px 14px;
700
+ font-size: 13px;
701
+ font-weight: 500;
702
+ cursor: pointer;
703
+ font-family: inherit;
704
+ transition: opacity 0.15s;
705
+ white-space: nowrap;
706
+ }
707
+
708
+ .readwhitepaper-search-btn:hover {
709
+ opacity: 0.9;
710
+ }
711
+
712
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
713
+ Powered by footer
714
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
715
+ .readwhitepaper-powered {
716
+ display: block;
717
+ text-align: center;
718
+ padding: 8px 16px;
719
+ font-size: 11px;
720
+ color: var(--muted);
721
+ border-top: 1px solid var(--border);
722
+ }
723
+
724
+ .readwhitepaper-powered a {
725
+ color: var(--link);
726
+ text-decoration: none;
727
+ font-weight: 500;
728
+ }
729
+
730
+ .readwhitepaper-powered a:hover {
731
+ text-decoration: underline;
732
+ }
733
+
734
+ /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
735
+ Copy button (base)
736
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
737
+ .readwhitepaper-copy-btn {
738
+ background: var(--copy-bg);
739
+ color: var(--text);
740
+ border: none;
741
+ border-radius: 5px;
742
+ padding: 4px 9px;
743
+ font-size: 11px;
744
+ cursor: pointer;
745
+ display: inline-flex;
746
+ align-items: center;
747
+ gap: 4px;
748
+ transition: background 0.15s;
749
+ font-family: inherit;
750
+ }
751
+
752
+ .readwhitepaper-copy-btn:hover {
753
+ background: var(--copy-hover);
754
+ }
755
+
756
+ .readwhitepaper-copy-btn svg {
757
+ width: 11px;
758
+ height: 11px;
759
+ }
760
+
761
+ ${getStyleCSS(style)}
762
+ `;
763
+ }
764
+
765
+ // src/shadow.ts
766
+ function createShadow(el, config) {
767
+ const widgetStyle = el.dataset.styleVariant || "modern";
768
+ const shadow = el.attachShadow({ mode: "open" });
769
+ const style = document.createElement("style");
770
+ style.textContent = getThemeCSS(config.accent, widgetStyle);
771
+ shadow.appendChild(style);
772
+ return shadow;
773
+ }
774
+ function resolveTheme(el) {
775
+ const raw = el.dataset.theme || "light";
776
+ if (raw === "auto") {
777
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
778
+ }
779
+ return raw;
780
+ }
781
+ function createWidgetRoot(shadow, el, extraClass) {
782
+ const theme = resolveTheme(el);
783
+ const size = el.dataset.size || "default";
784
+ const div = document.createElement("div");
785
+ div.className = ["readwhitepaper-widget", extraClass].filter(Boolean).join(" ");
786
+ div.setAttribute("data-theme", theme);
787
+ div.setAttribute("data-size", size);
788
+ shadow.appendChild(div);
789
+ if (el.dataset.theme === "auto") {
790
+ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
791
+ div.setAttribute("data-theme", e.matches ? "dark" : "light");
792
+ });
793
+ }
794
+ return div;
795
+ }
796
+ function renderLoading(container) {
797
+ container.innerHTML = `
798
+ <div class="readwhitepaper-loading">
799
+ <span class="readwhitepaper-spinner"></span>
800
+ Loading\u2026
801
+ </div>
802
+ `;
803
+ }
804
+ function renderError(container, message, config) {
805
+ container.innerHTML = `
806
+ <div class="readwhitepaper-error">
807
+ <p>${message}</p>
808
+ <a href="https://${config.domain}" target="_blank" rel="noopener">
809
+ Visit ${config.name}
810
+ </a>
811
+ </div>
812
+ `;
813
+ }
814
+ var externalLinkIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>`;
815
+ var documentIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>`;
816
+ function poweredByHTML(config) {
817
+ return `<span class="readwhitepaper-powered">Powered by <a href="https://${config.domain}" target="_blank" rel="noopener">${config.name}</a></span>`;
818
+ }
819
+ function escapeHTML(str) {
820
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
821
+ }
822
+
823
+ // src/api.ts
824
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
825
+ function cacheKey(url) {
826
+ return `readwhitepaper_embed_${url}`;
827
+ }
828
+ function getFromCache(url) {
829
+ try {
830
+ const raw = sessionStorage.getItem(cacheKey(url));
831
+ if (!raw) return null;
832
+ const entry = JSON.parse(raw);
833
+ if (Date.now() - entry.ts > CACHE_TTL_MS) {
834
+ sessionStorage.removeItem(cacheKey(url));
835
+ return null;
836
+ }
837
+ return entry.data;
838
+ } catch (e) {
839
+ return null;
840
+ }
841
+ }
842
+ function setInCache(url, data) {
843
+ try {
844
+ const entry = { data, ts: Date.now() };
845
+ sessionStorage.setItem(cacheKey(url), JSON.stringify(entry));
846
+ } catch (e) {
847
+ }
848
+ }
849
+ async function fetchAPI(baseUrl, path, params) {
850
+ const base = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
851
+ const relativePath = path.startsWith("/") ? path.slice(1) : path;
852
+ const url = new URL(relativePath, base);
853
+ if (params) {
854
+ Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
855
+ }
856
+ const urlStr = url.toString();
857
+ const cached = getFromCache(urlStr);
858
+ if (cached !== null) return cached;
859
+ const response = await fetch(urlStr, {
860
+ headers: { Accept: "application/json" }
861
+ });
862
+ if (!response.ok) {
863
+ throw new Error(`API error ${response.status}: ${urlStr}`);
864
+ }
865
+ const data = await response.json();
866
+ setInCache(urlStr, data);
867
+ return data;
868
+ }
869
+
870
+ // src/widgets/entity.ts
871
+ function initEntityWidget(el, config) {
872
+ var _a;
873
+ const dataset = el.dataset;
874
+ const slug = (_a = dataset.slug) != null ? _a : "";
875
+ if (!slug) {
876
+ const shadow2 = createShadow(el, config);
877
+ const container2 = createWidgetRoot(shadow2, el, "readwhitepaper-entity-widget");
878
+ renderError(container2, "Missing data-slug attribute.", config);
879
+ return;
880
+ }
881
+ const shadow = createShadow(el, config);
882
+ const container = createWidgetRoot(shadow, el, "readwhitepaper-entity-widget");
883
+ renderLoading(container);
884
+ fetchAPI(config.apiBase, `whitepapers/${slug}/`).then((data) => {
885
+ renderEntity(container, data, config);
886
+ }).catch(() => {
887
+ renderError(
888
+ container,
889
+ `Unable to load whitepaper "${escapeHTML(slug)}". Please try again later.`,
890
+ config
891
+ );
892
+ });
893
+ }
894
+ function renderEntity(container, data, config) {
895
+ const paperUrl = data.url || `https://${config.domain}/whitepapers/${escapeHTML(data.slug)}/`;
896
+ const category = data.category ? escapeHTML(data.category) : "";
897
+ const authors = data.authors ? escapeHTML(data.authors) : "";
898
+ const year = data.year ? String(data.year) : "";
899
+ const subtitle = [category, year].filter(Boolean).join(" \xB7 ");
900
+ let abstractExcerpt = "";
901
+ if (data.abstract) {
902
+ const raw = data.abstract;
903
+ abstractExcerpt = raw.length > 150 ? escapeHTML(raw.slice(0, 147)) + "..." : escapeHTML(raw);
904
+ }
905
+ container.innerHTML = `
906
+ <div class="readwhitepaper-header">
907
+ <div class="readwhitepaper-img">${documentIcon}</div>
908
+ <div>
909
+ <p class="readwhitepaper-header-title">${escapeHTML(data.title)}</p>
910
+ <p class="readwhitepaper-header-subtitle">${subtitle || "Whitepaper"}</p>
911
+ </div>
912
+ </div>
913
+
914
+ ${authors ? `<div class="readwhitepaper-authors"><strong>Authors:</strong> ${authors}</div>` : ""}
915
+
916
+ ${abstractExcerpt ? `<div class="readwhitepaper-abstract">${abstractExcerpt}</div>` : ""}
917
+
918
+ ${category ? `<div class="readwhitepaper-pills"><span class="readwhitepaper-tag">${category}</span></div>` : ""}
919
+
920
+ <div class="readwhitepaper-view-link">
921
+ <a href="${escapeHTML(paperUrl)}" target="_blank" rel="noopener">
922
+ Read full whitepaper on ${escapeHTML(config.name)} ${externalLinkIcon}
923
+ </a>
924
+ </div>
925
+
926
+ ${poweredByHTML(config)}
927
+ `;
928
+ }
929
+
930
+ // src/rich-snippets.ts
931
+ function injectDefinedTerm(data, domain, siteName) {
932
+ if (document.querySelector('script[data-readwhitepaper-snippet="term"]')) return;
933
+ const jsonLd = {
934
+ "@context": "https://schema.org",
935
+ "@type": "DefinedTerm",
936
+ name: data.name,
937
+ description: data.definition,
938
+ inDefinedTermSet: {
939
+ "@type": "DefinedTermSet",
940
+ name: `${siteName} Glossary`,
941
+ url: `https://${domain}/glossary/`
942
+ }
943
+ };
944
+ const script = document.createElement("script");
945
+ script.type = "application/ld+json";
946
+ script.setAttribute("data-readwhitepaper-snippet", "term");
947
+ script.textContent = JSON.stringify(jsonLd);
948
+ document.head.appendChild(script);
949
+ }
950
+
951
+ // src/widgets/glossary.ts
952
+ function initGlossaryWidget(el, config) {
953
+ var _a, _b;
954
+ const dataset = el.dataset;
955
+ const slug = (_a = dataset.slug) != null ? _a : "";
956
+ if (!slug) {
957
+ const shadow2 = createShadow(el, config);
958
+ const container2 = createWidgetRoot(shadow2, el, "readwhitepaper-glossary-widget");
959
+ renderError(container2, "Missing data-slug attribute.", config);
960
+ return;
961
+ }
962
+ const shadow = createShadow(el, config);
963
+ const container = createWidgetRoot(shadow, el, "readwhitepaper-glossary-widget");
964
+ renderLoading(container);
965
+ const params = {};
966
+ const lang = (_b = dataset.lang) != null ? _b : "";
967
+ if (lang) params.lang = lang;
968
+ fetchAPI(config.apiBase, `glossary/${slug}/`, params).then((data) => {
969
+ renderGlossary(container, data, config);
970
+ if (el.dataset.noSnippet !== "true") {
971
+ injectDefinedTerm(
972
+ { name: data.name, definition: data.definition },
973
+ config.domain,
974
+ config.name
975
+ );
976
+ }
977
+ }).catch(() => {
978
+ renderError(
979
+ container,
980
+ `Unable to load glossary term "${escapeHTML(slug)}". Please try again later.`,
981
+ config
982
+ );
983
+ });
984
+ }
985
+ function renderGlossary(container, data, config) {
986
+ const termUrl = `https://${config.domain}/glossary/${escapeHTML(data.slug)}/`;
987
+ const glossaryUrl = `https://${config.domain}/glossary/`;
988
+ const category = data.category ? escapeHTML(data.category) : "";
989
+ const relatedPills = data.related_terms && data.related_terms.length > 0 ? data.related_terms.map(
990
+ (rt) => `<a class="readwhitepaper-pill" href="https://${config.domain}/glossary/${escapeHTML(rt.slug)}/" target="_blank" rel="noopener">${escapeHTML(rt.name)}</a>`
991
+ ).join("") : "";
992
+ container.innerHTML = `
993
+ <div class="readwhitepaper-header">
994
+ <div>
995
+ <p class="readwhitepaper-header-title">${escapeHTML(data.name)}</p>
996
+ <p class="readwhitepaper-header-subtitle">Glossary term${category ? ` \xB7 ${category}` : ""}</p>
997
+ </div>
998
+ ${category ? `<span class="readwhitepaper-badge">${category}</span>` : ""}
999
+ </div>
1000
+
1001
+ <div class="readwhitepaper-summary">
1002
+ ${escapeHTML(data.definition)}
1003
+ </div>
1004
+
1005
+ ${relatedPills ? `<div class="readwhitepaper-pills-row">${relatedPills}</div>` : ""}
1006
+
1007
+ <div class="readwhitepaper-actions">
1008
+ <a class="readwhitepaper-link" href="${termUrl}" target="_blank" rel="noopener">
1009
+ ${escapeHTML(data.name)} ${externalLinkIcon}
1010
+ </a>
1011
+ <a class="readwhitepaper-link" href="${glossaryUrl}" target="_blank" rel="noopener">
1012
+ Full glossary on ${escapeHTML(config.name)} ${externalLinkIcon}
1013
+ </a>
1014
+ </div>
1015
+
1016
+ ${poweredByHTML(config)}
1017
+ `;
1018
+ }
1019
+
1020
+ // src/widgets/guide.ts
1021
+ function initGuideWidget(el, config) {
1022
+ var _a;
1023
+ const dataset = el.dataset;
1024
+ const slug = (_a = dataset.slug) != null ? _a : "";
1025
+ if (!slug) {
1026
+ const shadow2 = createShadow(el, config);
1027
+ const container2 = createWidgetRoot(shadow2, el, "readwhitepaper-guide-widget");
1028
+ renderError(container2, "Missing data-slug attribute.", config);
1029
+ return;
1030
+ }
1031
+ const shadow = createShadow(el, config);
1032
+ const container = createWidgetRoot(shadow, el, "readwhitepaper-guide-widget");
1033
+ renderLoading(container);
1034
+ fetchAPI(config.apiBase, `guides/${slug}/`).then((data) => {
1035
+ renderGuide(container, data, config);
1036
+ }).catch(() => {
1037
+ renderError(
1038
+ container,
1039
+ `Unable to load guide "${escapeHTML(slug)}". Please try again later.`,
1040
+ config
1041
+ );
1042
+ });
1043
+ }
1044
+ function renderGuide(container, data, config) {
1045
+ const guideUrl = data.url || `https://${config.domain}/guides/${escapeHTML(data.slug)}/`;
1046
+ const guidesUrl = `https://${config.domain}/guides/`;
1047
+ const description = data.description ? escapeHTML(data.description) : "";
1048
+ container.innerHTML = `
1049
+ <div class="readwhitepaper-header">
1050
+ <div>
1051
+ <p class="readwhitepaper-header-title">${escapeHTML(data.title)}</p>
1052
+ <p class="readwhitepaper-header-subtitle">Guide</p>
1053
+ </div>
1054
+ </div>
1055
+
1056
+ ${description ? `<div class="readwhitepaper-desc">${description}</div>` : ""}
1057
+
1058
+ <div class="readwhitepaper-actions">
1059
+ <a class="readwhitepaper-link" href="${escapeHTML(guideUrl)}" target="_blank" rel="noopener">
1060
+ Read guide ${externalLinkIcon}
1061
+ </a>
1062
+ <a class="readwhitepaper-link" href="${escapeHTML(guidesUrl)}" target="_blank" rel="noopener">
1063
+ All guides on ${escapeHTML(config.name)} ${externalLinkIcon}
1064
+ </a>
1065
+ </div>
1066
+
1067
+ ${poweredByHTML(config)}
1068
+ `;
1069
+ }
1070
+
1071
+ // src/widgets/search.ts
1072
+ function initSearchWidget(el, config) {
1073
+ const shadow = createShadow(el, config);
1074
+ const container = createWidgetRoot(shadow, el, "readwhitepaper-search-widget");
1075
+ const placeholder = el.dataset.placeholder || `Search ${config.entityName}...`;
1076
+ container.innerHTML = `
1077
+ <div class="readwhitepaper-search-wrap">
1078
+ <form class="readwhitepaper-search-form" action="https://${escapeHTML(config.domain)}${escapeHTML(config.searchPath)}" method="get" target="_blank" rel="noopener">
1079
+ <input
1080
+ class="readwhitepaper-search-input"
1081
+ type="text"
1082
+ name="q"
1083
+ placeholder="${escapeHTML(placeholder)}"
1084
+ autocomplete="off"
1085
+ aria-label="Search ${escapeHTML(config.entityName)}"
1086
+ />
1087
+ <button class="readwhitepaper-search-btn" type="submit">Search</button>
1088
+ </form>
1089
+ </div>
1090
+ ${poweredByHTML(config)}
1091
+ `;
1092
+ }
1093
+
1094
+ // src/_entry_readwhitepaper.ts
1095
+ function initWidget(el, type, config) {
1096
+ switch (type) {
1097
+ case "entity":
1098
+ initEntityWidget(el, config);
1099
+ break;
1100
+ case "glossary":
1101
+ initGlossaryWidget(el, config);
1102
+ break;
1103
+ case "guide":
1104
+ initGuideWidget(el, config);
1105
+ break;
1106
+ case "search":
1107
+ initSearchWidget(el, config);
1108
+ break;
1109
+ default:
1110
+ break;
1111
+ }
1112
+ }
1113
+ function lazyInit(el, callback) {
1114
+ if ("IntersectionObserver" in window) {
1115
+ const observer = new IntersectionObserver((entries) => {
1116
+ entries.forEach((entry) => {
1117
+ if (entry.isIntersecting) {
1118
+ observer.unobserve(el);
1119
+ callback();
1120
+ }
1121
+ });
1122
+ }, { rootMargin: "200px" });
1123
+ observer.observe(el);
1124
+ } else {
1125
+ callback();
1126
+ }
1127
+ }
1128
+ function processElement(el, config) {
1129
+ if (el.shadowRoot) return;
1130
+ const widgetType = el.dataset["readwhitepaper"];
1131
+ if (!widgetType) return;
1132
+ lazyInit(el, () => {
1133
+ if (!el.shadowRoot) initWidget(el, widgetType, config);
1134
+ });
1135
+ }
1136
+ function initAll(config) {
1137
+ document.querySelectorAll(`[${config.attribute}]`).forEach((el) => processElement(el, config));
1138
+ }
1139
+ (function bootstrap() {
1140
+ const config = '{"site":"readwhitepaper","name":"ReadWhitepaper","domain":"readwhitepaper.com","accent":"#6366F1","attribute":"data-readwhitepaper","apiBase":"https://readwhitepaper.com/api/v1/","searchPath":"/search/","entityName":"Whitepapers","entitySlug":"whitepapers"}';
1141
+ if (document.readyState === "loading") {
1142
+ document.addEventListener("DOMContentLoaded", () => initAll(config));
1143
+ } else {
1144
+ initAll(config);
1145
+ }
1146
+ const observer = new MutationObserver((mutations) => {
1147
+ mutations.forEach((mutation) => {
1148
+ mutation.addedNodes.forEach((node) => {
1149
+ var _a;
1150
+ if (node.nodeType !== Node.ELEMENT_NODE) return;
1151
+ const el = node;
1152
+ if (el.hasAttribute(config.attribute)) processElement(el, config);
1153
+ (_a = el.querySelectorAll) == null ? void 0 : _a.call(el, `[${config.attribute}]`).forEach((child) => processElement(child, config));
1154
+ });
1155
+ });
1156
+ });
1157
+ observer.observe(document.body || document.documentElement, { childList: true, subtree: true });
1158
+ })();
1159
+ function makeWidgetElement(widgetType, initFn, domainAttrs) {
1160
+ const observed = [...domainAttrs, "theme", "style-variant", "size"];
1161
+ return class extends HTMLElement {
1162
+ static get observedAttributes() {
1163
+ return observed;
1164
+ }
1165
+ connectedCallback() {
1166
+ if (this.shadowRoot) return;
1167
+ this._syncDataAttrs();
1168
+ initFn(this, '{"site":"readwhitepaper","name":"ReadWhitepaper","domain":"readwhitepaper.com","accent":"#6366F1","attribute":"data-readwhitepaper","apiBase":"https://readwhitepaper.com/api/v1/","searchPath":"/search/","entityName":"Whitepapers","entitySlug":"whitepapers"}');
1169
+ }
1170
+ attributeChangedCallback(_name, oldVal, newVal) {
1171
+ if (oldVal === newVal || !this.shadowRoot) return;
1172
+ const shadow = this.shadowRoot;
1173
+ while (shadow.firstChild) shadow.firstChild.remove();
1174
+ this._syncDataAttrs();
1175
+ initFn(this, '{"site":"readwhitepaper","name":"ReadWhitepaper","domain":"readwhitepaper.com","accent":"#6366F1","attribute":"data-readwhitepaper","apiBase":"https://readwhitepaper.com/api/v1/","searchPath":"/search/","entityName":"Whitepapers","entitySlug":"whitepapers"}');
1176
+ }
1177
+ _syncDataAttrs() {
1178
+ this.dataset["readwhitepaper"] = widgetType;
1179
+ for (const a of domainAttrs) {
1180
+ const val = this.getAttribute(a);
1181
+ if (val !== null) this.dataset[a] = val;
1182
+ }
1183
+ const theme = this.getAttribute("theme");
1184
+ if (theme !== null) this.dataset.theme = theme;
1185
+ const styleVariant = this.getAttribute("style-variant");
1186
+ if (styleVariant !== null) this.dataset.styleVariant = styleVariant;
1187
+ const size = this.getAttribute("size");
1188
+ if (size !== null) this.dataset.size = size;
1189
+ }
1190
+ };
1191
+ }
1192
+ (function registerElements() {
1193
+ if (typeof customElements === "undefined") return;
1194
+ const defs = [
1195
+ ["readwhitepaper-entity", initEntityWidget, ["slug"]],
1196
+ ["readwhitepaper-glossary", initGlossaryWidget, ["slug"]],
1197
+ ["readwhitepaper-guide", initGuideWidget, ["slug"]],
1198
+ ["readwhitepaper-search", initSearchWidget, ["placeholder"]]
1199
+ ];
1200
+ for (const [tagName, initFn, attrs] of defs) {
1201
+ if (!customElements.get(tagName)) {
1202
+ const widgetType = tagName.replace("readwhitepaper-", "");
1203
+ customElements.define(tagName, makeWidgetElement(widgetType, initFn, attrs));
1204
+ }
1205
+ }
1206
+ })();