datalog-theme 0.10.1 → 0.11.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.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +127 -0
  3. data/CITATION.cff +2 -2
  4. data/README.md +4 -2
  5. data/_data/i18n/en.yml +55 -3
  6. data/_data/i18n/es.yml +55 -3
  7. data/_data/i18n/pt.yml +55 -3
  8. data/_includes/analytics/dashboard.html +24 -9
  9. data/_includes/components/academic-dashboard.html +168 -133
  10. data/_includes/components/author-bio.html +7 -5
  11. data/_includes/components/author-list.html +6 -5
  12. data/_includes/components/citation-tools.html +2 -1
  13. data/_includes/components/content-provenance.html +19 -1
  14. data/_includes/components/correction-report.html +15 -8
  15. data/_includes/components/hero.html +22 -15
  16. data/_includes/components/package-index.html +121 -0
  17. data/_includes/components/package-install.html +27 -50
  18. data/_includes/components/post-list.html +14 -0
  19. data/_includes/components/responsive-image.html +15 -21
  20. data/_includes/footer.html +1 -1
  21. data/_includes/head.html +70 -11
  22. data/_includes/layouts/default/article.html +76 -46
  23. data/_includes/meta/dataset-json.html +171 -0
  24. data/_includes/meta/math-config.html +15 -1
  25. data/_includes/meta/package-json.html +69 -0
  26. data/_includes/meta/person-json.html +36 -13
  27. data/_includes/meta/publisher.html +15 -0
  28. data/_includes/meta/schema.html +108 -23
  29. data/_includes/meta/scholarly.html +10 -5
  30. data/_includes/post/related-posts.html +17 -43
  31. data/_includes/scripts.html +2 -2
  32. data/_includes/search/index-data.json +10 -1
  33. data/_includes/search/page.html +11 -6
  34. data/_layouts/archive.html +67 -0
  35. data/_layouts/dataset.html +2 -1
  36. data/_layouts/default.html +13 -11
  37. data/_layouts/docs.html +53 -0
  38. data/_layouts/home.html +30 -1
  39. data/_layouts/notebook.html +5 -1
  40. data/_layouts/package.html +38 -21
  41. data/_layouts/portfolio.html +1 -0
  42. data/_layouts/post.html +21 -62
  43. data/_layouts/project.html +2 -1
  44. data/_layouts/research.html +14 -2
  45. data/_plugins/analytics_dashboard.rb +4 -1
  46. data/_plugins/archive.rb +114 -0
  47. data/_plugins/authors.rb +50 -1
  48. data/_plugins/citation_exports.rb +12 -1
  49. data/_plugins/config_validator.rb +77 -2
  50. data/_plugins/correction_fallback.rb +110 -0
  51. data/_plugins/image_optimizer.rb +129 -22
  52. data/_plugins/math_preprocessor.rb +7 -48
  53. data/_plugins/notebook_converter.rb +44 -5
  54. data/_plugins/packages.rb +84 -0
  55. data/_plugins/page_dates.rb +37 -0
  56. data/_plugins/references.rb +16 -2
  57. data/_plugins/related_posts.rb +149 -0
  58. data/_plugins/search_sections.rb +110 -0
  59. data/_plugins/site_identity.rb +42 -0
  60. data/_plugins/social_cards.rb +17 -0
  61. data/_sass/_academic-dashboard.scss +18 -30
  62. data/_sass/_base.scss +2 -0
  63. data/_sass/_components.scss +21 -23
  64. data/_sass/_docs.scss +143 -0
  65. data/_sass/_features.scss +6 -0
  66. data/_sass/_layout.scss +65 -6
  67. data/_sass/_mathematical.scss +61 -19
  68. data/_sass/_notebooks.scss +1 -32
  69. data/_sass/_package-docs.scss +6 -9
  70. data/_sass/_post-components.scss +23 -23
  71. data/_sass/_print.scss +1 -1
  72. data/_sass/_search-page.scss +75 -0
  73. data/_sass/_search.scss +17 -26
  74. data/_sass/_syntax-highlighting.scss +23 -1
  75. data/_sass/_theme.scss +1 -0
  76. data/_sass/_utilities.scss +87 -40
  77. data/_sass/_variables.scss +31 -29
  78. data/assets/css/main.scss +2 -1
  79. data/assets/js/dist/academic.js +1 -1
  80. data/assets/js/dist/analytics-dashboard.js +1 -1
  81. data/assets/js/dist/chunks/chunk-TNVD6UAM.js +1 -0
  82. data/assets/js/dist/comments.js +1 -1
  83. data/assets/js/dist/contact.js +1 -1
  84. data/assets/js/dist/core.js +1 -1
  85. data/assets/js/dist/corrections.js +5 -1
  86. data/assets/js/dist/loader.js +1 -1
  87. data/assets/js/dist/math.js +2 -1
  88. data/assets/js/dist/moderation.js +1 -1
  89. data/assets/js/dist/reactions.js +1 -1
  90. data/assets/js/dist/search.js +1 -1
  91. data/assets/js/dist/sources.json +20 -16
  92. data/assets/js/dist/subscriptions.js +1 -1
  93. data/assets/js/loader.js +6 -2
  94. data/lib/datalog/audit/checks.rb +269 -0
  95. data/lib/datalog/audit/known_keys.rb +61 -0
  96. data/lib/datalog/audit/site_reader.rb +118 -0
  97. data/lib/datalog/audit/source_file.rb +85 -0
  98. data/lib/datalog/audit.rb +145 -0
  99. data/lib/datalog/citations/bibtex.rb +200 -0
  100. data/lib/datalog/citations/entry.rb +333 -0
  101. data/lib/datalog/citations/markup.rb +79 -0
  102. data/lib/datalog/cli.rb +164 -89
  103. data/lib/datalog/critical_css.rb +126 -21
  104. data/lib/datalog/latex_speech/words.json +88 -0
  105. data/lib/datalog/latex_speech.rb +355 -0
  106. data/lib/datalog/packages/command.rb +51 -0
  107. data/lib/datalog/packages/refresh.rb +187 -0
  108. data/lib/datalog/packages.rb +177 -0
  109. data/lib/datalog/plugin_system.rb +5 -0
  110. data/lib/datalog/plugins/citations.rb +325 -109
  111. data/lib/datalog/site_config.rb +26 -0
  112. data/lib/datalog/social_cards/font.rb +286 -0
  113. data/lib/datalog/social_cards/fonts/IBMPlexSans-Regular.ttf +0 -0
  114. data/lib/datalog/social_cards/fonts/IBMPlexSerif-SemiBold.ttf +0 -0
  115. data/lib/datalog/social_cards/fonts/OFL.txt +92 -0
  116. data/lib/datalog/social_cards/geometry.rb +51 -0
  117. data/lib/datalog/social_cards/outline.rb +54 -0
  118. data/lib/datalog/social_cards/plain_text.rb +258 -0
  119. data/lib/datalog/social_cards/template.rb +322 -0
  120. data/lib/datalog/social_cards/template.svg +17 -0
  121. data/lib/datalog/social_cards/typesetter.rb +178 -0
  122. data/lib/datalog/social_cards.rb +369 -0
  123. data/lib/datalog/theme/updater.rb +307 -0
  124. data/lib/datalog/theme/version.rb +1 -1
  125. metadata +44 -7
  126. data/_includes/components/enhanced-code-block.html +0 -212
  127. data/_includes/components/performance-monitor.html +0 -170
  128. data/_includes/components/viz-table-fallback.html +0 -19
  129. data/_plugins/datalog_bibliography.rb +0 -21
  130. data/assets/js/dist/chunks/chunk-WIRUK3OZ.js +0 -1
@@ -397,6 +397,59 @@
397
397
  }
398
398
  }
399
399
 
400
+ // The passages of the page that matched, under its result: a reader who
401
+ // searched for a term buried in a long article can go straight to it.
402
+ .search-result__sections {
403
+ margin-top: map.get($spacing, 2);
404
+ padding-left: map.get($spacing, 3);
405
+ border-left: 2px solid rgba($color-accent-primary, 0.25);
406
+ }
407
+
408
+ .search-result__sections-label {
409
+ margin: 0 0 map.get($spacing, 1);
410
+ font-size: map.get($font-size-scale, xs);
411
+ text-transform: uppercase;
412
+ letter-spacing: 0.06em;
413
+ color: $color-ink-500;
414
+ }
415
+
416
+ .search-result__sections-list {
417
+ margin: 0;
418
+ padding: 0;
419
+ list-style: none;
420
+ display: flex;
421
+ flex-direction: column;
422
+ gap: map.get($spacing, 1);
423
+ }
424
+
425
+ .search-result__section {
426
+ font-size: map.get($font-size-scale, sm);
427
+ line-height: 1.5;
428
+ }
429
+
430
+ // A subsection is one step in, so the shape of the article shows in the result.
431
+ .search-result__section--h3 {
432
+ padding-left: map.get($spacing, 3);
433
+ }
434
+
435
+ .search-result__section-link {
436
+ font-weight: 600;
437
+
438
+ &::after {
439
+ content: " · ";
440
+ color: $color-ink-500;
441
+ font-weight: 400;
442
+ }
443
+
444
+ &:last-child::after {
445
+ content: none;
446
+ }
447
+ }
448
+
449
+ .search-result__section-snippet {
450
+ color: $color-ink-600;
451
+ }
452
+
400
453
  .search-result__footer {
401
454
  display: flex;
402
455
  flex-wrap: wrap;
@@ -494,6 +547,22 @@ body.dark-mode {
494
547
  }
495
548
  }
496
549
 
550
+ .search-result__sections {
551
+ border-left-color: rgba($dark-accent-primary, 0.4);
552
+ }
553
+
554
+ .search-result__sections-label {
555
+ color: rgba($dark-ink-500, 0.85);
556
+ }
557
+
558
+ .search-result__section-link::after {
559
+ color: rgba($dark-ink-500, 0.85);
560
+ }
561
+
562
+ .search-result__section-snippet {
563
+ color: $dark-ink-700;
564
+ }
565
+
497
566
  .search-result__math {
498
567
  background: rgba($dark-surface-300, 0.85);
499
568
  border-color: rgba($dark-ink-500, 0.3);
@@ -528,3 +597,9 @@ body.dark-mode {
528
597
  border-color: rgba($dark-accent-primary, 0.55);
529
598
  }
530
599
  }
600
+
601
+ // Nothing set this in dark mode, so it kept the light theme's mid grey on the
602
+ // dark surface: 3.27:1.
603
+ body.dark-mode .search-app__loading-text {
604
+ color: $dark-ink-500;
605
+ }
data/_sass/_search.scss CHANGED
@@ -481,7 +481,7 @@ body.dark-mode .search-result__type {
481
481
 
482
482
  body.dark-mode .search-result__difficulty {
483
483
  background: rgba($dark-accent-tertiary, 0.12);
484
- color: $dark-accent-tertiary;
484
+ color: $dark-accent-tertiary-ink;
485
485
  }
486
486
 
487
487
  .search-result__language {
@@ -513,21 +513,10 @@ body.dark-mode .search-result__title a {
513
513
  font-size: map.get($font-size-scale, sm);
514
514
  margin: 0;
515
515
  line-height: $line-height-base;
516
-
517
- mark {
518
- background: rgba($color-warning, 0.25);
519
- color: inherit;
520
- border-radius: 2px;
521
- padding: 0 0.125rem;
522
- }
523
516
  }
524
517
 
525
518
  body.dark-mode .search-result__summary {
526
519
  color: $dark-ink-500;
527
-
528
- mark {
529
- background: rgba($color-warning, 0.3);
530
- }
531
520
  }
532
521
 
533
522
  // Code and math previews
@@ -580,13 +569,6 @@ body.dark-mode .search-result__math {
580
569
  margin: 0;
581
570
 
582
571
  &[hidden] { display: none; }
583
-
584
- mark {
585
- background: rgba($color-warning, 0.25);
586
- color: inherit;
587
- border-radius: 2px;
588
- padding: 0 0.125rem;
589
- }
590
572
  }
591
573
 
592
574
  body.dark-mode .search-result__excerpt {
@@ -622,7 +604,7 @@ body.dark-mode .search-result__excerpt {
622
604
 
623
605
  body.dark-mode .search-result__tags li {
624
606
  background: rgba($dark-accent-tertiary, 0.12);
625
- color: $dark-accent-tertiary;
607
+ color: $dark-accent-tertiary-ink;
626
608
  }
627
609
 
628
610
  .search-result__date {
@@ -671,12 +653,6 @@ body.dark-mode .search-result:focus-within .search-result__title a {
671
653
  &__excerpt {
672
654
  margin: 0.75rem 0;
673
655
  color: var(--color-text-secondary, #4a5568);
674
-
675
- mark {
676
- background: #fef3c7;
677
- padding: 0.125rem 0.25rem;
678
- border-radius: 2px;
679
- }
680
656
  }
681
657
 
682
658
  &__meta {
@@ -698,3 +674,18 @@ body.dark-mode .search-result:focus-within .search-result__title a {
698
674
  @keyframes search-spinner {
699
675
  to { transform: rotate(360deg); }
700
676
  }
677
+
678
+ // The query highlight, in one place. Three rules gave it three backgrounds and
679
+ // none of them a colour, so it inherited the card's: light grey on a light
680
+ // amber wash in dark mode, 2.26:1. The wash decides the text colour (#365).
681
+ .search-result mark {
682
+ background: rgba($color-warning, 0.25);
683
+ color: $color-ink-900;
684
+ border-radius: 2px;
685
+ padding: 0 0.125rem;
686
+ }
687
+
688
+ body.dark-mode .search-result mark {
689
+ background: rgba($color-warning, 0.3);
690
+ color: $dark-ink-900;
691
+ }
@@ -177,6 +177,8 @@ body.dark-mode pre.highlight {
177
177
  background: rgba($dark-surface-300, 0.8);
178
178
  }
179
179
 
180
+ // Every token the light theme colours has a colour here too: one left out
181
+ // keeps its light colour, about 2:1 on the dark code background.
180
182
  body.dark-mode .highlight {
181
183
  .c,
182
184
  .ch,
@@ -185,6 +187,7 @@ body.dark-mode .highlight {
185
187
  .cpf,
186
188
  .c1,
187
189
  .cs,
190
+ .p,
188
191
  .rouge-gutter {
189
192
  color: $dark-ink-500;
190
193
  }
@@ -229,7 +232,13 @@ body.dark-mode .highlight {
229
232
  .kv,
230
233
  .ow,
231
234
  .cp,
232
- .o {
235
+ .o,
236
+ .ni,
237
+ .nv,
238
+ .vc,
239
+ .vg,
240
+ .vi,
241
+ .vm {
233
242
  color: $dark-accent-primary;
234
243
  }
235
244
 
@@ -240,4 +249,17 @@ body.dark-mode .highlight {
240
249
  .ne {
241
250
  color: #9fb6ff;
242
251
  }
252
+
253
+ .nt,
254
+ .no,
255
+ .ss,
256
+ .gd {
257
+ color: $dark-accent-tertiary;
258
+ }
259
+
260
+ .sr,
261
+ .gr,
262
+ .gt {
263
+ color: $dark-warning;
264
+ }
243
265
  }
data/_sass/_theme.scss CHANGED
@@ -16,6 +16,7 @@
16
16
  @include meta.load-css('base');
17
17
  @include meta.load-css('typography');
18
18
  @include meta.load-css('layout');
19
+ @include meta.load-css('docs');
19
20
  @include meta.load-css('header');
20
21
  @include meta.load-css('components');
21
22
  @include meta.load-css('utilities');
@@ -145,32 +145,48 @@ html[dir='rtl'] .site-search input {
145
145
  }
146
146
 
147
147
  .analytics-dashboard {
148
+ --analytics-series-1: #2155a6;
149
+ --analytics-series-2: #0c756b;
150
+ --analytics-series-3: #6b48a5;
151
+ --analytics-series-4: #9c4d13;
148
152
  display: flex;
149
153
  flex-direction: column;
150
154
  gap: map.get($spacing, 6);
151
155
  margin-top: map.get($spacing, 4);
152
156
  }
153
157
 
158
+ body.dark-mode .analytics-dashboard {
159
+ --analytics-series-1: #88adff;
160
+ --analytics-series-2: #63daca;
161
+ --analytics-series-3: #c5a7ff;
162
+ --analytics-series-4: #ffb876;
163
+ }
164
+
165
+ .page-admin-analytics .site-main.container {
166
+ width: min(100% - 2rem, 80rem);
167
+ min-width: 0;
168
+ }
169
+
154
170
  .analytics-header {
155
171
  display: flex;
156
172
  flex-wrap: wrap;
157
173
  justify-content: space-between;
158
174
  gap: map.get($spacing, 4);
159
175
  align-items: flex-start;
176
+ padding: clamp(1rem, 3vw, 2rem);
177
+ border: 1px solid var(--color-border);
178
+ border-radius: map.get($radius, lg);
179
+ background: var(--color-background-secondary);
160
180
  }
161
181
 
162
182
  .analytics-title {
163
183
  margin: 0;
164
- font-size: map.get($font-size-scale, xl);
184
+ font-size: clamp(1.6rem, 3vw, 2.3rem);
165
185
  }
166
186
 
167
187
  .analytics-subtitle {
168
188
  margin: map.get($spacing, 2) 0 0;
169
- color: rgba($color-neutral-700, 0.85);
170
- }
171
-
172
- body.dark-mode .analytics-subtitle {
173
- color: rgba($dark-surface-50, 0.85);
189
+ color: var(--color-text-secondary);
174
190
  }
175
191
 
176
192
  .analytics-meta {
@@ -178,75 +194,85 @@ body.dark-mode .analytics-subtitle {
178
194
  flex-direction: column;
179
195
  gap: map.get($spacing, 2);
180
196
  font-size: map.get($font-size-scale, sm);
181
- color: rgba($color-neutral-600, 0.9);
197
+ color: var(--color-text-secondary);
182
198
  }
183
199
 
184
- body.dark-mode .analytics-meta {
185
- color: rgba($dark-surface-50, 0.75);
200
+ .analytics-state {
201
+ align-self: flex-start;
202
+ padding: 0.3rem 0.65rem;
203
+ border: 1px solid var(--color-accent-text);
204
+ border-radius: 999px;
205
+ color: var(--color-accent-text);
206
+ font-weight: 600;
207
+ }
208
+
209
+ .analytics-dashboard[data-stale='true'] .analytics-state,
210
+ .analytics-dashboard:not([data-status='ok']) .analytics-state {
211
+ border-color: var(--color-border);
212
+ color: var(--color-text-primary);
186
213
  }
187
214
 
188
215
  .analytics-grid {
189
216
  display: grid;
190
217
  gap: map.get($spacing, 4);
191
- grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
218
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
192
219
  }
193
220
 
194
221
  .analytics-card {
195
- background: rgba($color-neutral-50, 0.6);
222
+ min-width: 0;
223
+ background: var(--color-background-secondary);
224
+ border: 1px solid var(--color-border);
196
225
  border-radius: map.get($radius, lg);
197
226
  padding: map.get($spacing, 4);
198
- box-shadow: $shadow-soft;
199
227
  display: flex;
200
228
  flex-direction: column;
201
229
  gap: map.get($spacing, 3);
202
230
  }
203
231
 
204
- body.dark-mode .analytics-card {
205
- background: rgba($dark-surface-200, 0.8);
206
- box-shadow: none;
207
- }
208
-
209
232
  .analytics-card header h3 {
210
233
  margin: 0;
211
234
  font-size: map.get($font-size-scale, lg);
212
235
  }
213
236
 
214
237
  .analytics-card--wide {
215
- grid-column: span 2;
238
+ grid-column: 1 / -1;
216
239
  }
217
240
 
218
- @media (max-width: 56rem) {
219
- .analytics-card--wide {
220
- grid-column: span 1;
221
- }
241
+ .analytics-table-scroll {
242
+ max-width: 100%;
243
+ overflow-x: auto;
244
+
245
+ &:focus-visible { outline: 2px solid var(--color-accent-text); outline-offset: -2px; }
222
246
  }
223
247
 
224
248
  .analytics-table {
225
249
  width: 100%;
250
+ min-width: 25rem;
226
251
  border-collapse: collapse;
227
252
  font-size: map.get($font-size-scale, sm);
228
253
  }
229
254
 
230
255
  .analytics-table th,
231
256
  .analytics-table td {
232
- padding: map.get($spacing, 2) map.get($spacing, 1);
233
- border-bottom: 1px solid rgba($color-neutral-200, 0.7);
257
+ padding: map.get($spacing, 2) map.get($spacing, 3);
258
+ border-bottom: 1px solid var(--color-border);
234
259
  vertical-align: top;
260
+ white-space: nowrap;
235
261
  }
236
262
 
237
- body.dark-mode .analytics-table th,
238
- body.dark-mode .analytics-table td {
239
- border-bottom: 1px solid rgba($dark-surface-100, 0.4);
263
+ .analytics-table th {
264
+ color: var(--color-text-primary);
265
+ background: var(--color-background);
240
266
  }
241
267
 
242
- .analytics-table tbody tr:last-child td {
243
- border-bottom: none;
268
+ .analytics-table th:first-child,
269
+ .analytics-table td:first-child {
270
+ white-space: normal;
271
+ overflow-wrap: anywhere;
272
+ min-width: 9rem;
244
273
  }
245
274
 
246
- .analytics-table td:nth-child(2),
247
- .analytics-table td:nth-child(3),
248
- .analytics-table th:nth-child(2),
249
- .analytics-table th:nth-child(3) {
275
+ .analytics-table :is(th, td):not(:first-child) {
250
276
  text-align: right;
251
277
  }
252
278
 
@@ -258,29 +284,50 @@ body.dark-mode .analytics-table td {
258
284
  flex-direction: column;
259
285
  gap: map.get($spacing, 2);
260
286
  font-size: map.get($font-size-scale, sm);
287
+
261
288
  }
262
289
 
263
290
  .analytics-definition-list {
264
291
  display: grid;
292
+ grid-template-columns: repeat(3, minmax(0, 1fr));
265
293
  gap: map.get($spacing, 2);
266
294
  font-size: map.get($font-size-scale, sm);
295
+
296
+ dd { margin: 0.4rem 0 0; color: var(--color-accent-text); font-size: 1.35rem; font-weight: 600; }
267
297
  }
268
298
 
269
299
  .analytics-definition-list dt {
270
300
  font-weight: 600;
271
301
  }
272
302
 
303
+ .analytics-chart {
304
+ min-width: 0;
305
+ height: 15rem;
306
+
307
+ canvas { display: block; width: 100% !important; height: 100% !important; }
308
+ &:has(canvas[hidden]) { height: auto; }
309
+ canvas[hidden] { display: none; }
310
+ }
311
+
312
+ .analytics-chart-status {
313
+ color: var(--color-text-secondary);
314
+ margin: 0;
315
+ }
316
+
317
+ .analytics-chart-data {
318
+ summary { color: var(--color-accent-text); font-weight: 600; cursor: pointer; }
319
+ .analytics-table-scroll { margin-top: map.get($spacing, 3); }
320
+ }
321
+
273
322
  .analytics-alert {
274
323
  padding: map.get($spacing, 3);
275
324
  border-radius: map.get($radius, md);
276
- background: rgba($color-warning, 0.12);
277
- color: color.adjust($color-warning, $lightness: -20%);
278
- font-size: map.get($font-size-scale, sm);
279
- }
325
+ background: var(--color-background-secondary);
326
+ border: 1px solid var(--color-border);
327
+ border-left: 4px solid var(--color-accent-text);
328
+ color: var(--color-text-primary);
280
329
 
281
- body.dark-mode .analytics-alert {
282
- background: rgba($color-warning, 0.18);
283
- color: color.adjust($color-warning, $lightness: 10%);
330
+ p { margin: 0; }
284
331
  }
285
332
 
286
333
  .analytics-dashboard [data-field],
@@ -28,27 +28,25 @@ $line-height-tight: 1.3;
28
28
  $line-height-base: 1.6;
29
29
  $line-height-loose: 1.75;
30
30
 
31
- // Color palette — balanced warm/cool tones for readability and visual variety
32
- $color-surface-50: #fafaf9; // warm white
33
- $color-surface-100: #f3f2ef; // warm light gray
34
- $color-surface-900: #1a1a2e; // deep navy (kept for hero/footer contrast)
35
- $color-ink-900: #1c1917; // warm near-black
36
- $color-ink-700: #44403c; // warm dark gray
37
- $color-ink-500: #6f6862; // warm mid gray (>=4.5:1 on surface-100)
38
- $color-ink-300: #a8a29e; // warm light gray
31
+ // Indigo/cyan palette: the dark scheme is the default, with a readable light
32
+ // alternative. The neutral tokens below still support legacy content surfaces.
33
+ $color-surface-50: #f8fafc;
34
+ $color-surface-100: #eef2f7;
35
+ $color-surface-900: #111b31; // deep navy for the hero and footer
36
+ $color-ink-900: #172033;
37
+ $color-ink-700: #334155;
38
+ $color-ink-500: #526173;
39
+ $color-ink-300: #506079; // tertiary text on light surfaces
39
40
  $color-ink-100: #e7e5e4 !default;
40
41
  $color-ink-400: #a1a1aa !default;
41
42
  $color-ink-600: #57534e !default;
42
43
  $color-ink-800: #292524 !default;
43
- $color-accent-primary: #2563eb; // vivid blue — links, primary actions
44
- $color-accent-secondary: #0d9488; // teal — fills, borders and other non-text accents
45
- // #0d9488 reaches only 3.1:1 to 3.7:1 against white and against its own
46
- // tinted backgrounds, so it fails WCAG AA wherever it is used as text.
47
- $color-accent-secondary-text: #115e59; // teal — the same accent as readable text
48
- // #2563eb reaches only 4.4:1 against its own 8% tint on the page background,
49
- // where a theorem's links sit.
50
- $color-accent-primary-text: #1d4ed8; // blue — links on a tinted background
44
+ $color-accent-primary: #4338ca; // indigo — links and primary actions
45
+ $color-accent-secondary: #0e7490; // cyan — fills, borders and accents
46
+ $color-accent-secondary-text: #155e75; // cyan on light-tinted surfaces
47
+ $color-accent-primary-text: #3730a3; // indigo on light-tinted surfaces
51
48
  $color-accent-tertiary: #7c3aed; // purple — charts, visual accents
49
+ $color-accent-tertiary-text: #6d28d9 !default; // purple on its own tint, 4.9:1
52
50
  $color-success: #16a34a;
53
51
  $color-success-text: #166534; // green — the success colour as readable text
54
52
  $color-warning: #d97706;
@@ -83,22 +81,26 @@ $color-danger-600: #c53929 !default; // ← NEW (used in components)
83
81
  $color-danger-700: #a52714 !default;
84
82
  $color-danger-900: #7f1d1d !default;
85
83
 
86
- // Dark mode adjustments
87
- $dark-surface-50: #262626 !default;
88
- $dark-surface-100: #171717; // near-black, neutral
89
- $dark-surface-200: #1e1e1e; // slightly lighter
90
- $dark-surface-300: #2a2a2a; // card backgrounds
91
- $dark-ink-900: #f5f5f4; // warm white text
92
- $dark-ink-700: #d6d3d1;
93
- $dark-ink-500: #a8a29e;
94
- $dark-ink-300: #78716c !default;
95
- $dark-ink-200: #57534e !default;
96
- $dark-ink-100: #44403c !default;
84
+ // Dark mode surfaces and text, tuned for long technical articles.
85
+ $dark-surface-50: #263651 !default;
86
+ $dark-surface-100: #0f172a;
87
+ $dark-surface-200: #162036;
88
+ $dark-surface-300: #1e2c46;
89
+ $dark-ink-900: #e7edf9;
90
+ $dark-ink-700: #cbd5e1;
91
+ $dark-ink-500: #a8b8d0;
92
+ $dark-ink-300: #98a9c4 !default; // tertiary text on dark surfaces
93
+ // The two dimmest inks were left from the old warm greys, at 2.3:1 and 1.7:1
94
+ // on the page. Every ink reads at 4.5:1 or more on every dark surface.
95
+ $dark-ink-200: #94a5c1 !default;
96
+ $dark-ink-100: #8fa1be !default;
97
97
  $dark-ink-050: #fafaf9 !default;
98
98
  $dark-ink-000: #fafaf9 !default;
99
- $dark-accent-primary: #60a5fa; // lighter blue for dark bg
100
- $dark-accent-secondary: #2dd4bf; // lighter teal
99
+ $dark-accent-primary: #a5b4fc; // lighter indigo for dark backgrounds
100
+ $dark-accent-secondary: #67e8f9; // lighter cyan for dark backgrounds
101
101
  $dark-accent-tertiary: #a78bfa !default; // lighter purple
102
+ // The same purple as text on its own 12% tint is 4.33:1, just under AA.
103
+ $dark-accent-tertiary-ink: #c4b5fd !default; // 6.4:1 on that tint
102
104
 
103
105
  // Border colors
104
106
  $color-border: $color-neutral-200 !default;
data/assets/css/main.scss CHANGED
@@ -13,6 +13,7 @@ that copies this file to add its own rules keeps these lines.
13
13
  $notebooks: {% if notebook_pages.size > 0 %}true{% else %}false{% endif %},
14
14
  $packages: {% if site.packages.size > 0 %}true{% else %}false{% endif %},
15
15
  $academic-dashboard: {% if site.features.academic_dashboard %}true{% else %}false{% endif %},
16
- $open-science-badges: {% if site.data.academic.badges.size > 0 %}true{% else %}false{% endif %}
16
+ $open-science-badges: {% if site.data.academic.badges.size > 0 %}true{% else %}false{% endif %},
17
+ $math-card: {% if site.theme_options.math.display_style == 'card' %}true{% else %}false{% endif %}
17
18
  );
18
19
  @use "theme";
@@ -1 +1 @@
1
- import"./chunks/chunk-PATLC23F.js";function d(){let a=window.DatalogAcademic||{},c=window.DatalogPublications||{},t=c.metrics||(a.citations?a.citations.metrics:{})||{},o=c.yearly_totals||(a.citations?a.citations.yearly_totals:{})||{};document.querySelectorAll("[data-citation-metric]").forEach(e=>{let n=e.getAttribute("data-citation-metric");if(!n)return;let i;switch(n){case"total":i=t.total;break;case"h_index":case"h-index":i=t.h_index;break;case"i10_index":case"i10-index":i=t.i10_index;break;case"since_total":i=t.since_2019?t.since_2019.total:void 0;break;case"since_h_index":i=t.since_2019?t.since_2019.h_index:void 0;break;case"since_i10":i=t.since_2019?t.since_2019.i10_index:void 0;break;default:if(n.startsWith("year_")){let s=n.replace("year_","");i=o[s]}break}typeof i=="number"?e.textContent=i.toLocaleString():i&&(e.textContent=i)})}function u(){let a=window.DatalogAcademic||{},t=(window.DatalogPublications||{}).citation_totals||(a.citations?a.citations.per_publication:{})||{};document.querySelectorAll("[data-publication-citations]").forEach(o=>{let e=o.getAttribute("data-publication-citations");if(!e)return;let n=e.toLowerCase(),i;t[e]?i=t[e].total||t[e]:t[n]&&(i=t[n].total||t[n]),typeof i=="number"&&(o.textContent=i.toLocaleString())})}function f(){let a=window.DatalogAcademic||{},t=(window.DatalogPublications||{}).yearly_totals||(a.citations?a.citations.yearly_totals:{})||{},o=document.querySelector("[data-citation-timeline]");o&&t&&o.querySelectorAll("li[data-year]").forEach(n=>{let i=n.getAttribute("data-year");if(!i)return;let s=n.querySelector("[data-year-total]"),r=t[i];s&&typeof r!="undefined"&&(s.textContent=Number(r).toLocaleString(),n.style.setProperty("--timeline-value",Math.min(Number(r)/5,100)))})}function y(){let a=document.querySelector("[data-submission-filter]");if(a){let c=document.querySelectorAll(".submission-card"),t=()=>{let o=a.value;c.forEach(e=>{if(!o){e.hidden=!1;return}let n=e.getAttribute("data-submission-status");e.hidden=n!==o})};a.addEventListener("change",t),t()}}function p(){let a=document.querySelector("[data-calendar-filter]"),c=document.querySelector("[data-academic-calendar]");if(a&&c){let t=c.querySelectorAll("li[data-event-type]"),o=()=>{let e=a.value;t.forEach(n=>{if(!e){n.hidden=!1;return}let i=n.getAttribute("data-event-type");n.hidden=i!==e})};a.addEventListener("change",o),o()}}function b(){document.querySelectorAll(".open-science-badge").forEach(c=>{let t=c.querySelector(".open-science-badge__description"),o=c.querySelector(".open-science-badge__criteria"),e=[];t&&e.push(t.textContent.trim()),o&&e.push(o.textContent.trim()),e.length&&c.setAttribute("title",e.join(" \u2022 "))})}function l(){d(),u(),f(),y(),p(),b()}typeof window!="undefined"&&document.readyState!=="loading"?l():typeof window!="undefined"&&document.addEventListener("DOMContentLoaded",l);export{l as initAcademicFeatures,p as initCalendarFilter,b as initOpenScienceBadges,y as initSubmissionFilter,d as populateCitationMetrics,f as populateCitationTimeline,u as populatePublicationCitations};
1
+ import"./chunks/chunk-PATLC23F.js";function u(){let a=window.DatalogAcademic||{},o=window.DatalogPublications||{},t=o.metrics||(a.citations?a.citations.metrics:{})||{},c=o.yearly_totals||(a.citations?a.citations.yearly_totals:{})||{};document.querySelectorAll("[data-citation-metric]").forEach(e=>{let n=e.getAttribute("data-citation-metric");if(!n)return;let i;switch(n){case"total":i=t.total;break;case"h_index":case"h-index":i=t.h_index;break;case"i10_index":case"i10-index":i=t.i10_index;break;case"since_total":i=t.since_2019?t.since_2019.total:void 0;break;case"since_h_index":i=t.since_2019?t.since_2019.h_index:void 0;break;case"since_i10":i=t.since_2019?t.since_2019.i10_index:void 0;break;default:if(n.startsWith("year_")){let r=n.replace("year_","");i=c[r]}break}typeof i=="number"?e.textContent=i.toLocaleString():i&&(e.textContent=i)})}function f(){let a=window.DatalogAcademic||{},t=(window.DatalogPublications||{}).citation_totals||(a.citations?a.citations.per_publication:{})||{};document.querySelectorAll("[data-publication-citations]").forEach(c=>{let e=c.getAttribute("data-publication-citations");if(!e)return;let n=e.toLowerCase(),i;t[e]?i=t[e].total||t[e]:t[n]&&(i=t[n].total||t[n]),typeof i=="number"&&(c.textContent=i.toLocaleString())})}function y(){let a=document.querySelector("[data-citation-timeline]");if(!a)return;let o=window.DatalogAcademic||{},t=window.DatalogPublications||{},c=o.citations&&o.citations.yearly_totals||t.yearly_totals||{},e=Array.from(a.querySelectorAll("li[data-year]")).filter(r=>r.getAttribute("data-year")),n=e.map(r=>{let s=r.querySelector("[data-year-total]"),l=c[r.getAttribute("data-year")];return typeof l!="undefined"?(s&&(s.textContent=Number(l).toLocaleString()),Number(l)||0):Number((s&&s.textContent||"").replace(/[^\d.]/g,""))||0}),i=Math.max(0,...n);e.forEach((r,s)=>{let l=i>0?Math.round(n[s]/i*100):0;r.style.setProperty("--timeline-value",`${l}%`)})}function p(){let a=document.querySelector("[data-submission-filter]");if(a){let o=document.querySelectorAll(".submission-card"),t=()=>{let c=a.value;o.forEach(e=>{if(!c){e.hidden=!1;return}let n=e.getAttribute("data-submission-status");e.hidden=n!==c})};a.addEventListener("change",t),t()}}function b(){let a=document.querySelector("[data-calendar-filter]"),o=document.querySelector("[data-academic-calendar]");if(a&&o){let t=o.querySelectorAll("li[data-event-type]"),c=()=>{let e=a.value;t.forEach(n=>{if(!e){n.hidden=!1;return}let i=n.getAttribute("data-event-type");n.hidden=i!==e})};a.addEventListener("change",c),c()}}function m(){document.querySelectorAll(".open-science-badge").forEach(o=>{let t=o.querySelector(".open-science-badge__description"),c=o.querySelector(".open-science-badge__criteria"),e=[];t&&e.push(t.textContent.trim()),c&&e.push(c.textContent.trim()),e.length&&o.setAttribute("title",e.join(" \u2022 "))})}function d(){u(),f(),y(),p(),b(),m()}typeof window!="undefined"&&document.readyState!=="loading"?d():typeof window!="undefined"&&document.addEventListener("DOMContentLoaded",d);export{d as initAcademicFeatures,b as initCalendarFilter,m as initOpenScienceBadges,p as initSubmissionFilter,u as populateCitationMetrics,y as populateCitationTimeline,f as populatePublicationCitations};
@@ -1 +1 @@
1
- import"./chunks/chunk-PATLC23F.js";function m(){return window.__DATALOG_ANALYTICS__||{}}function E(e){document.readyState==="loading"?document.addEventListener("DOMContentLoaded",e,{once:!0}):e()}function f(e){return!e||!Array.isArray(e.rows)?[]:e.rows}function d(e,a){return new Intl.NumberFormat(void 0,a||{maximumFractionDigits:0}).format(e||0)}function h(e,a,n){var r;if(!e)return;let c=n||((r=e.closest("table"))==null?void 0:r.querySelectorAll("th").length)||1,i=document.createElement("tr");i.className="placeholder";let s=document.createElement("td");s.setAttribute("colspan",c),s.textContent=a,i.appendChild(s),e.replaceChildren(i)}function v(){let e=document.getElementById("analytics-top-posts"),a=f(m().top_posts);if(e){if(!a.length){h(e,e.dataset.emptyMessage||"No data available",3);return}e.replaceChildren(),a.forEach(n=>{var b,y,C;let c=n.dimensionValues||[],i=n.metricValues||[],s=((b=c[0])==null?void 0:b.value)||"",r=Number(((y=i[0])==null?void 0:y.value)||0),t=Number(((C=i[1])==null?void 0:C.value)||0),o=document.createElement("tr"),l=document.createElement("a");l.href=s.startsWith("/")?s:`/${s}`,l.textContent=s||"\u2014",l.rel="noopener",l.className="analytics-link";let u=document.createElement("td");u.appendChild(l);let p=document.createElement("td");p.textContent=d(r);let g=document.createElement("td");g.textContent=d(t,{maximumFractionDigits:0}),o.append(u,p,g),e.appendChild(o)})}}function w(){let e=document.getElementById("analytics-search-terms");if(!e)return;let a=f(m().search_terms);if(!a.length){h(e,e.dataset.emptyMessage||"No search queries recorded",2);return}e.replaceChildren(),a.forEach(n=>{var u,p;let c=n.dimensionValues||[],i=n.metricValues||[],s=((u=c[0])==null?void 0:u.value)||"(not provided)",r=Number(((p=i[0])==null?void 0:p.value)||0),t=document.createElement("tr"),o=document.createElement("td");o.textContent=s;let l=document.createElement("td");l.textContent=d(r),t.append(o,l),e.appendChild(t)})}function N(e){return!e||e.includes("-")?e:e.length===8?`${e.slice(0,4)}-${e.slice(4,6)}-${e.slice(6,8)}`:e}function _(){let e=document.getElementById("analytics-visitors-chart");if(!e||typeof Chart=="undefined")return;let a=f(m().visitor_trends);if(!a.length)return;let n=a.map(t=>{var o,l;return N((l=(o=t.dimensionValues)==null?void 0:o[0])==null?void 0:l.value)}),c=a.map(t=>{var o,l;return Number(((l=(o=t.metricValues)==null?void 0:o[0])==null?void 0:l.value)||0)}),i=a.map(t=>{var o,l;return Number(((l=(o=t.metricValues)==null?void 0:o[1])==null?void 0:l.value)||0)}),s=a.map(t=>{var o,l;return Number(((l=(o=t.metricValues)==null?void 0:o[2])==null?void 0:l.value)||0)}),r=a.map(t=>{var o,l;return Number(((l=(o=t.metricValues)==null?void 0:o[3])==null?void 0:l.value)||0)});new Chart(e,{type:"line",data:{labels:n,datasets:[{label:"Total users",data:c,borderColor:"#2563eb",backgroundColor:"rgba(37, 99, 235, 0.15)",tension:.35,fill:!0},{label:"New users",data:i,borderColor:"#10b981",backgroundColor:"rgba(16, 185, 129, 0.12)",tension:.35,fill:!1},{label:"Sessions",data:s,borderColor:"#9333ea",backgroundColor:"rgba(147, 51, 234, 0.1)",tension:.35,fill:!1},{label:"Page views",data:r,borderColor:"#f97316",backgroundColor:"rgba(249, 115, 22, 0.1)",borderDash:[6,6],tension:.35,fill:!1}]},options:{responsive:!0,maintainAspectRatio:!1,interaction:{mode:"index",intersect:!1},scales:{y:{beginAtZero:!0,ticks:{callback:t=>d(t)}}},plugins:{legend:{position:"top"}}}})}function A(){let e=document.getElementById("analytics-engagement-chart");if(!e||typeof Chart=="undefined")return;let a=f(m().engagement_by_page).slice(0,10);if(!a.length)return;let n=a.map(s=>{var r,t;return((t=(r=s.dimensionValues)==null?void 0:r[0])==null?void 0:t.value)||"\u2014"}),c=a.map(s=>{var r,t;return Number(((t=(r=s.metricValues)==null?void 0:r[2])==null?void 0:t.value)||0)}),i=a.map(s=>{var r,t;return Number(((t=(r=s.metricValues)==null?void 0:r[0])==null?void 0:t.value)||0)});new Chart(e,{type:"bar",data:{labels:n,datasets:[{label:"Engaged sessions",data:c,backgroundColor:"rgba(59, 130, 246, 0.7)"},{label:"Page views",data:i,backgroundColor:"rgba(14, 165, 233, 0.5)"}]},options:{responsive:!0,maintainAspectRatio:!1,indexAxis:"y",scales:{x:{beginAtZero:!0,ticks:{callback:s=>d(s)}}},plugins:{legend:{position:"top"}}}})}function k(){let e=document.getElementById("analytics-key-events");if(!e)return;let a=f(m().key_events);if(!a.length){let n=document.createElement("li");n.className="placeholder",n.textContent="No tracked events in the selected window.",e.replaceChildren(n);return}e.replaceChildren(),a.forEach(n=>{var t,o,l,u;let c=((o=(t=n.dimensionValues)==null?void 0:t[0])==null?void 0:o.value)||"event",i=Number(((u=(l=n.metricValues)==null?void 0:l[0])==null?void 0:u.value)||0),s=document.createElement("li"),r=document.createElement("strong");r.textContent=d(i),s.appendChild(r),s.appendChild(document.createTextNode(` ${c.replace(/_/g," ")}`)),e.appendChild(s)})}function x(){let e=m().scholar||{},a=document.querySelector('[data-field="scholar-total"]'),n=document.querySelector('[data-field="scholar-h-index"]'),c=document.querySelector('[data-field="scholar-i10-index"]');a&&(a.textContent=e.total?d(Number(e.total)):"\u2014"),n&&(n.textContent=e.h_index?d(Number(e.h_index)):"\u2014"),c&&(c.textContent=e.i10_index?d(Number(e.i10_index)):"\u2014");let i=document.getElementById("analytics-scholar-chart");if(!i||typeof Chart=="undefined")return;let s=e.yearly_totals||{},r=Object.entries(s).map(([t,o])=>[Number(t),Number(o)]).sort((t,o)=>t[0]-o[0]);r.length&&new Chart(i,{type:"bar",data:{labels:r.map(t=>t[0]),datasets:[{label:"Citations",data:r.map(t=>t[1]),backgroundColor:"rgba(99, 102, 241, 0.8)"}]},options:{responsive:!0,maintainAspectRatio:!1,scales:{y:{beginAtZero:!0,ticks:{callback:t=>d(t)}}}}})}function V(){let e=document.getElementById("analytics-monthly-reports");if(!e)return;let a=Array.isArray(m().monthly_reports)?m().monthly_reports:[];if(!a.length){h(e,e.dataset.emptyMessage||"No monthly reports available",5);return}e.replaceChildren(),a.forEach(n=>{let c=document.createElement("tr"),i=document.createElement("td");i.textContent=n.month||"\u2014";let s=document.createElement("td");s.textContent=d(n.total_users||0);let r=document.createElement("td");r.textContent=d(n.new_users||0);let t=document.createElement("td");t.textContent=d(n.sessions||0);let o=document.createElement("td");o.textContent=d(n.page_views||0),c.append(i,s,r,t,o),e.appendChild(c)})}function I(){if(m().status!=="ok"){["analytics-top-posts","analytics-search-terms","analytics-monthly-reports"].forEach(n=>{let c=document.getElementById(n);c&&h(c,m().message||"Analytics data unavailable.")});let a=document.getElementById("analytics-key-events");if(a){let n=document.createElement("li");n.className="placeholder",n.textContent=m().message||"Analytics data unavailable.",a.replaceChildren(n)}x();return}v(),w(),_(),A(),k(),x(),V()}typeof window!="undefined"&&!window.__VITEST__&&E(I);export{h as ensurePlaceholder,N as formatDateLabel,d as formatNumber,E as onReady,f as parseRows,I as render,A as renderEngagementChart,k as renderKeyEvents,V as renderMonthlyReports,x as renderScholar,w as renderSearchTerms,v as renderTopPosts,_ as renderVisitorChart};
1
+ import"./chunks/chunk-PATLC23F.js";function p(){return window.__DATALOG_ANALYTICS__||{}}function q(e){document.readyState==="loading"?document.addEventListener("DOMContentLoaded",e,{once:!0}):e()}function g(e){return!e||!Array.isArray(e.rows)?[]:e.rows}function m(e,o){return new Intl.NumberFormat(void 0,o||{maximumFractionDigits:0}).format(e||0)}function x(e,o,t){var i;if(!e)return;let l=t||((i=e.closest("table"))==null?void 0:i.querySelectorAll("th").length)||1,r=document.createElement("tr");r.className="placeholder";let a=document.createElement("td");a.setAttribute("colspan",l),a.textContent=o,r.appendChild(a),e.replaceChildren(r)}function I(){let e=document.getElementById("analytics-top-posts"),o=g(p().top_posts);if(e){if(!o.length){x(e,e.dataset.emptyMessage||"No data available",3);return}e.replaceChildren(),o.forEach(t=>{var C,h,y;let l=t.dimensionValues||[],r=t.metricValues||[],a=((C=l[0])==null?void 0:C.value)||"",i=Number(((h=r[0])==null?void 0:h.value)||0),n=Number(((y=r[1])==null?void 0:y.value)||0),d=document.createElement("tr"),s=document.createElement("a");s.href=a.startsWith("/")?a:`/${a}`,s.textContent=a||"\u2014",s.rel="noopener",s.className="analytics-link";let c=document.createElement("td");c.appendChild(s);let u=document.createElement("td");u.textContent=m(i);let b=document.createElement("td");b.textContent=m(n,{maximumFractionDigits:0}),d.append(c,u,b),e.appendChild(d)})}}function D(){let e=document.getElementById("analytics-search-terms");if(!e)return;let o=g(p().search_terms);if(!o.length){x(e,e.dataset.emptyMessage||"No search queries recorded",2);return}e.replaceChildren(),o.forEach(t=>{var c,u;let l=t.dimensionValues||[],r=t.metricValues||[],a=((c=l[0])==null?void 0:c.value)||"(not provided)",i=Number(((u=r[0])==null?void 0:u.value)||0),n=document.createElement("tr"),d=document.createElement("td");d.textContent=a;let s=document.createElement("td");s.textContent=m(i),n.append(d,s),e.appendChild(n)})}function B(e){return!e||e.includes("-")?e:e.length===8?`${e.slice(0,4)}-${e.slice(4,6)}-${e.slice(6,8)}`:e}function A(){let e=document.querySelector(".analytics-dashboard")||document.body,o=window.getComputedStyle(e),t=(l,r)=>o.getPropertyValue(l).trim()||r;return{text:t("--color-text-secondary","#64748b"),grid:t("--color-border","#cbd5e1"),series:[t("--analytics-series-1","#2155a6"),t("--analytics-series-2","#0c756b"),t("--analytics-series-3","#6b48a5"),t("--analytics-series-4","#9c4d13")]}}function f(e,o,t,l){var b,C;let r=e.closest(".analytics-dashboard"),a=(b=e.parentElement)==null?void 0:b.querySelector(".analytics-chart-status"),i=(C=e.closest(".analytics-card"))==null?void 0:C.querySelector(".analytics-chart-data"),n=t.length>0,d=typeof Chart!="undefined";if(e.hidden=!n||!d,a&&(a.hidden=n&&d,a.textContent=n?(r==null?void 0:r.dataset.chartUnavailable)||"Chart unavailable; use the data table below.":(r==null?void 0:r.dataset.noChartData)||"No chart data available."),!i||(i.hidden=!n,!n))return;let s=i.querySelector("thead"),c=i.querySelector("tbody");if(!s||!c)return;let u=document.createElement("tr");[o,...l.map(h=>h.label)].forEach(h=>{let y=document.createElement("th");y.scope="col",y.textContent=h,u.appendChild(y)}),s.replaceChildren(u),c.replaceChildren(),t.forEach((h,y)=>{let E=document.createElement("tr"),v=document.createElement("th");v.scope="row",v.textContent=String(h),E.appendChild(v),l.forEach(V=>{let k=document.createElement("td");k.textContent=m(V.data[y]),E.appendChild(k)}),c.appendChild(E)})}function S(e,o){var t,l;(l=(t=Chart.getChart)==null?void 0:t.call(Chart,e))==null||l.destroy(),new Chart(e,o)}function _(){let e=document.getElementById("analytics-visitors-chart");if(!e)return;let o=g(p().visitor_trends);if(!o.length){f(e,"Date",[],[]);return}let t=o.map(s=>{var c,u;return B((u=(c=s.dimensionValues)==null?void 0:c[0])==null?void 0:u.value)}),l=o.map(s=>{var c,u;return Number(((u=(c=s.metricValues)==null?void 0:c[0])==null?void 0:u.value)||0)}),r=o.map(s=>{var c,u;return Number(((u=(c=s.metricValues)==null?void 0:c[1])==null?void 0:u.value)||0)}),a=o.map(s=>{var c,u;return Number(((u=(c=s.metricValues)==null?void 0:c[2])==null?void 0:u.value)||0)}),i=o.map(s=>{var c,u;return Number(((u=(c=s.metricValues)==null?void 0:c[3])==null?void 0:u.value)||0)}),n=A(),d=[{label:"Total users",data:l,borderColor:n.series[0],tension:.35,fill:!1},{label:"New users",data:r,borderColor:n.series[1],tension:.35,fill:!1},{label:"Sessions",data:a,borderColor:n.series[2],tension:.35,fill:!1},{label:"Page views",data:i,borderColor:n.series[3],borderDash:[6,6],tension:.35,fill:!1}];f(e,"Date",t,d),typeof Chart!="undefined"&&S(e,{type:"line",data:{labels:t,datasets:d},options:{responsive:!0,maintainAspectRatio:!1,interaction:{mode:"index",intersect:!1},scales:{y:{beginAtZero:!0,ticks:{color:n.text,callback:s=>m(s)},grid:{color:n.grid}},x:{ticks:{color:n.text},grid:{color:n.grid}}},plugins:{legend:{position:"top",labels:{color:n.text}}}}})}function w(){let e=document.getElementById("analytics-engagement-chart");if(!e)return;let o=g(p().engagement_by_page).slice(0,10);if(!o.length){f(e,"Post",[],[]);return}let t=o.map(n=>{var d,s;return((s=(d=n.dimensionValues)==null?void 0:d[0])==null?void 0:s.value)||"\u2014"}),l=o.map(n=>{var d,s;return Number(((s=(d=n.metricValues)==null?void 0:d[2])==null?void 0:s.value)||0)}),r=o.map(n=>{var d,s;return Number(((s=(d=n.metricValues)==null?void 0:d[0])==null?void 0:s.value)||0)}),a=A(),i=[{label:"Engaged sessions",data:l,backgroundColor:a.series[0]},{label:"Page views",data:r,backgroundColor:a.series[1]}];f(e,"Post",t,i),typeof Chart!="undefined"&&S(e,{type:"bar",data:{labels:t,datasets:i},options:{responsive:!0,maintainAspectRatio:!1,indexAxis:"y",scales:{x:{beginAtZero:!0,ticks:{color:a.text,callback:n=>m(n)},grid:{color:a.grid}},y:{ticks:{color:a.text},grid:{color:a.grid}}},plugins:{legend:{position:"top",labels:{color:a.text}}}}})}function T(){let e=document.getElementById("analytics-key-events");if(!e)return;let o=g(p().key_events);if(!o.length){let t=document.createElement("li");t.className="placeholder",t.textContent="No tracked events in the selected window.",e.replaceChildren(t);return}e.replaceChildren(),o.forEach(t=>{var n,d,s,c;let l=((d=(n=t.dimensionValues)==null?void 0:n[0])==null?void 0:d.value)||"event",r=Number(((c=(s=t.metricValues)==null?void 0:s[0])==null?void 0:c.value)||0),a=document.createElement("li"),i=document.createElement("strong");i.textContent=m(r),a.appendChild(i),a.appendChild(document.createTextNode(` ${l.replace(/_/g," ")}`)),e.appendChild(a)})}function N(){let e=p().scholar||{},o=document.querySelector('[data-field="scholar-total"]'),t=document.querySelector('[data-field="scholar-h-index"]'),l=document.querySelector('[data-field="scholar-i10-index"]');o&&(o.textContent=e.total?m(Number(e.total)):"\u2014"),t&&(t.textContent=e.h_index?m(Number(e.h_index)):"\u2014"),l&&(l.textContent=e.i10_index?m(Number(e.i10_index)):"\u2014");let r=document.getElementById("analytics-scholar-chart");if(!r)return;let a=e.yearly_totals||{},i=Object.entries(a).map(([c,u])=>[Number(c),Number(u)]).sort((c,u)=>c[0]-u[0]);if(!i.length){f(r,"Year",[],[]);return}let n=A(),d=i.map(c=>c[0]),s=[{label:"Citations",data:i.map(c=>c[1]),backgroundColor:n.series[2]}];f(r,"Year",d,s),typeof Chart!="undefined"&&S(r,{type:"bar",data:{labels:d,datasets:s},options:{responsive:!0,maintainAspectRatio:!1,scales:{y:{beginAtZero:!0,ticks:{color:n.text,callback:c=>m(c)},grid:{color:n.grid}},x:{ticks:{color:n.text},grid:{color:n.grid}}},plugins:{legend:{labels:{color:n.text}}}}})}function F(){let e=document.getElementById("analytics-monthly-reports");if(!e)return;let o=Array.isArray(p().monthly_reports)?p().monthly_reports:[];if(!o.length){x(e,e.dataset.emptyMessage||"No monthly reports available",5);return}e.replaceChildren(),o.forEach(t=>{let l=document.createElement("tr"),r=document.createElement("td");r.textContent=t.month||"\u2014";let a=document.createElement("td");a.textContent=m(t.total_users||0);let i=document.createElement("td");i.textContent=m(t.new_users||0);let n=document.createElement("td");n.textContent=m(t.sessions||0);let d=document.createElement("td");d.textContent=m(t.page_views||0),l.append(r,a,i,n,d),e.appendChild(l)})}function P(){if(p().status!=="ok"){["analytics-top-posts","analytics-search-terms","analytics-monthly-reports"].forEach(a=>{let i=document.getElementById(a);i&&x(i,p().message||"Analytics data unavailable.")});let r=document.getElementById("analytics-key-events");if(r){let a=document.createElement("li");a.className="placeholder",a.textContent=p().message||"Analytics data unavailable.",r.replaceChildren(a)}_(),w(),N();return}let o=p(),t=["top_posts","search_terms","visitor_trends","engagement_by_page","key_events"].some(r=>g(o[r]).length>0)||Array.isArray(o.monthly_reports)&&o.monthly_reports.length>0,l=document.querySelector(".analytics-dashboard");if(l){l.dataset.state=t?"populated":"empty";let r=l.querySelector(".analytics-state");!t&&l.dataset.stale!=="true"&&r&&(r.textContent=r.dataset.emptyLabel||"No results yet")}I(),D(),_(),w(),T(),N(),F()}typeof window!="undefined"&&!window.__VITEST__&&q(()=>{P(),document.querySelector(".analytics-dashboard")&&new MutationObserver(()=>{_(),w(),N()}).observe(document.body,{attributes:!0,attributeFilter:["class"]})});export{x as ensurePlaceholder,B as formatDateLabel,m as formatNumber,q as onReady,g as parseRows,P as render,w as renderEngagementChart,T as renderKeyEvents,F as renderMonthlyReports,N as renderScholar,D as renderSearchTerms,I as renderTopPosts,_ as renderVisitorChart};
@@ -0,0 +1 @@
1
+ import{a as l}from"./chunk-VZ5WKQVA.js";var b=["idle","pending","success","invalid","error","disabled"];function g(i=null){let t=new Map,e=()=>t.clear();return i&&["input","change","reset"].forEach(r=>i.addEventListener(r,e)),{key(r,n=""){var a,o,d;let s=JSON.stringify(r);if(((a=t.get(n))==null?void 0:a.fingerprint)!==s){let u=((d=(o=globalThis.crypto)==null?void 0:o.randomUUID)==null?void 0:d.call(o))||`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;t.set(n,{fingerprint:s,key:u})}return t.get(n).key},clear(r=""){t.delete(r)},reset:e}}function v(i,t,e,r={}){let n=null;return()=>(n||(n=i.feature(t).then(s=>(e.dataset.state==="error"&&c(e,"idle"),s)).catch(s=>{throw n=null,["disabled","unsupported","version"].includes(s.kind)?c(e,"disabled",l(s,r)):h(e,s,r),s})),n)}function E(i,t){let e=i.ownerDocument;if(e&&e.activeElement&&i.contains(e.activeElement)){t();return}i.addEventListener("focusin",()=>t(),{once:!0})}function f(i,t){let e=i.elements.namedItem(t);return e?typeof e.setAttribute=="function"?[e]:Array.from(e):[]}function y(i){i.querySelectorAll("[aria-invalid]").forEach(t=>{t.removeAttribute("aria-invalid");let e=(t.getAttribute("aria-describedby")||"").split(/\s+/).filter(r=>r&&!r.endsWith("-error")).join(" ");e?t.setAttribute("aria-describedby",e):t.removeAttribute("aria-describedby")}),i.querySelectorAll("[data-error-for]").forEach(t=>{t.textContent="",t.hidden=!0})}function p(i,t){let e=0,r=null;return Object.keys(t||{}).forEach(n=>{let s=Array.isArray(t[n])?t[n].join(" "):String(t[n]),a=i.querySelector(`[data-error-for="${n}"]`);a&&(a.textContent=s,a.hidden=!1,a.id||(a.id=`${i.id||"form"}-${n}-error`)),f(i,n).forEach(o=>{if(o.setAttribute("aria-invalid","true"),a){let d=(o.getAttribute("aria-describedby")||"").split(/\s+/).filter(Boolean);d.includes(a.id)||d.push(a.id),o.setAttribute("aria-describedby",d.join(" "))}r=r||o,e+=1})}),r&&typeof r.focus=="function"&&r.focus(),e}function c(i,t,e="",r=null){i.dataset.state=b.includes(t)?t:"idle";let n=t==="pending";i.setAttribute("aria-busy",n?"true":"false"),i.querySelectorAll("button[type=submit], [data-form-submit]").forEach(a=>{a.disabled=n||t==="disabled"}),i.querySelectorAll("fieldset").forEach(a=>{a.disabled=t==="disabled"});let s=i.querySelector("[data-form-status]");s&&(s.setAttribute("role",t==="error"||t==="invalid"?"alert":"status"),s.textContent=e,s.hidden=e===""),y(i),t==="invalid"&&r&&p(i,r)}function S(i){let t={};return new FormData(i).forEach((e,r)=>{let n=typeof e=="string"?e.trim():e;r in t?t[r]=[].concat(t[r],n):t[r]=n}),t}function h(i,t,e={}){let r=l(t,e);t&&t.kind==="invalid"?c(i,"invalid",r,t.errors||null):c(i,"error",r)}export{g as a,v as b,E as c,c as d,S as e,h as f};