@dataimago/css 0.1.0-alpha.21 → 0.1.0-alpha.23

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 (123) hide show
  1. package/README.md +241 -0
  2. package/dist/bin/dataimago-figures.mjs +703 -0
  3. package/dist/bin/dataimago-sync.mjs +299 -19
  4. package/dist/dataimago.css +9 -3
  5. package/dist/dataimago.min.css +1 -1
  6. package/dist/dataviz/dataimago-dataviz.css +1 -1
  7. package/dist/dataviz/dataimago-dataviz.json +2 -2
  8. package/dist/dataviz/dataimago-dataviz.tex +1 -1
  9. package/dist/dataviz/dataimago_dataviz.R +1 -1
  10. package/dist/figures/NotoSans-Bold.otf +0 -0
  11. package/dist/figures/NotoSans-BoldItalic.otf +0 -0
  12. package/dist/figures/NotoSans-Italic.otf +0 -0
  13. package/dist/figures/NotoSans-Regular.otf +0 -0
  14. package/dist/figures/NotoSansMath-Regular.ttf +0 -0
  15. package/dist/figures/OFL-NotoSans.txt +93 -0
  16. package/dist/figures/OFL-NotoSansMath.txt +93 -0
  17. package/dist/figures/dataimago-figure.sty +105 -0
  18. package/dist/figures/dataimago-tokens.sty +134 -0
  19. package/dist/fonts/cyrillic/OFL-NotoSans.txt +93 -0
  20. package/dist/fonts/cyrillic/OFL-NotoSansMono.txt +93 -0
  21. package/dist/fonts/cyrillic/fonts.css +27 -0
  22. package/dist/fonts/cyrillic/noto-sans-italic.woff2 +0 -0
  23. package/dist/fonts/cyrillic/noto-sans-mono.woff2 +0 -0
  24. package/dist/fonts/cyrillic/noto-sans.woff2 +0 -0
  25. package/dist/fonts/cyrillic-ext/OFL-NotoSans.txt +93 -0
  26. package/dist/fonts/cyrillic-ext/OFL-NotoSansMono.txt +93 -0
  27. package/dist/fonts/cyrillic-ext/fonts.css +27 -0
  28. package/dist/fonts/cyrillic-ext/noto-sans-italic.woff2 +0 -0
  29. package/dist/fonts/cyrillic-ext/noto-sans-mono.woff2 +0 -0
  30. package/dist/fonts/cyrillic-ext/noto-sans.woff2 +0 -0
  31. package/dist/fonts/greek/OFL-NotoSans.txt +93 -0
  32. package/dist/fonts/greek/OFL-NotoSansMono.txt +93 -0
  33. package/dist/fonts/greek/fonts.css +27 -0
  34. package/dist/fonts/greek/noto-sans-italic.woff2 +0 -0
  35. package/dist/fonts/greek/noto-sans-mono.woff2 +0 -0
  36. package/dist/fonts/greek/noto-sans.woff2 +0 -0
  37. package/dist/fonts/greek-ext/OFL-NotoSans.txt +93 -0
  38. package/dist/fonts/greek-ext/OFL-NotoSansMono.txt +93 -0
  39. package/dist/fonts/greek-ext/fonts.css +27 -0
  40. package/dist/fonts/greek-ext/noto-sans-italic.woff2 +0 -0
  41. package/dist/fonts/greek-ext/noto-sans-mono.woff2 +0 -0
  42. package/dist/fonts/greek-ext/noto-sans.woff2 +0 -0
  43. package/dist/fonts/josefin/OFL-JosefinSans.txt +93 -0
  44. package/dist/fonts/josefin/fonts.css +8 -0
  45. package/dist/fonts/josefin/josefin-sans.woff2 +0 -0
  46. package/dist/fonts/lang.css +181 -0
  47. package/dist/fonts/latin/OFL-NotoSans.txt +93 -0
  48. package/dist/fonts/latin/OFL-NotoSansMono.txt +93 -0
  49. package/dist/fonts/latin/fonts.css +27 -0
  50. package/dist/fonts/latin/noto-sans-italic.woff2 +0 -0
  51. package/dist/fonts/latin/noto-sans-mono.woff2 +0 -0
  52. package/dist/fonts/latin/noto-sans.woff2 +0 -0
  53. package/dist/fonts/latin-ext/OFL-NotoSans.txt +93 -0
  54. package/dist/fonts/latin-ext/OFL-NotoSansMono.txt +93 -0
  55. package/dist/fonts/latin-ext/fonts.css +27 -0
  56. package/dist/fonts/latin-ext/noto-sans-italic.woff2 +0 -0
  57. package/dist/fonts/latin-ext/noto-sans-mono.woff2 +0 -0
  58. package/dist/fonts/latin-ext/noto-sans.woff2 +0 -0
  59. package/dist/fonts/math/OFL-NotoSansMath.txt +93 -0
  60. package/dist/fonts/math/fonts.css +8 -0
  61. package/dist/fonts/math/noto-sans-math.woff2 +0 -0
  62. package/dist/fonts/pkg/GFL.txt +29 -0
  63. package/dist/fonts/pkg/README-lm.txt +27 -0
  64. package/dist/fonts/pkg/fonts.css +8 -0
  65. package/dist/fonts/pkg/lmsans10-regular.woff2 +0 -0
  66. package/dist/fonts/vietnamese/OFL-NotoSans.txt +93 -0
  67. package/dist/fonts/vietnamese/OFL-NotoSansMono.txt +93 -0
  68. package/dist/fonts/vietnamese/fonts.css +27 -0
  69. package/dist/fonts/vietnamese/noto-sans-italic.woff2 +0 -0
  70. package/dist/fonts/vietnamese/noto-sans-mono.woff2 +0 -0
  71. package/dist/fonts/vietnamese/noto-sans.woff2 +0 -0
  72. package/dist/latex/dataimago-tokens.sty +14 -2
  73. package/dist/latex/dataimago.sty +6 -1
  74. package/dist/outputs.json +114 -21
  75. package/dist/quarto/_extensions/dataimago/monograph/_extension.yml +35 -0
  76. package/dist/quarto/_extensions/dataimago/monograph/dataimago-base.sty +275 -0
  77. package/dist/quarto/_extensions/dataimago/monograph/dataimago-monograph.sty +270 -0
  78. package/dist/quarto/_extensions/dataimago/monograph/dataimago-tokens.sty +134 -0
  79. package/dist/quarto/_extensions/dataimago/monograph/filters/figure-plate.lua +52 -0
  80. package/dist/quarto/_extensions/dataimago/monograph/filters/matter.lua +170 -0
  81. package/dist/quarto/_extensions/dataimago/monograph/filters/pkg-name.lua +17 -0
  82. package/dist/quarto/_extensions/dataimago/monograph/fonts/GFL.txt +29 -0
  83. package/dist/quarto/_extensions/dataimago/monograph/fonts/JosefinSans-VF.ttf +0 -0
  84. package/dist/quarto/_extensions/dataimago/monograph/fonts/NotoSans-Italic-VF.ttf +0 -0
  85. package/dist/quarto/_extensions/dataimago/monograph/fonts/NotoSans-VF.ttf +0 -0
  86. package/dist/quarto/_extensions/dataimago/monograph/fonts/NotoSansMath-Regular.ttf +0 -0
  87. package/dist/quarto/_extensions/dataimago/monograph/fonts/NotoSansMono-VF.ttf +0 -0
  88. package/dist/quarto/_extensions/dataimago/monograph/fonts/OFL-JosefinSans.txt +93 -0
  89. package/dist/quarto/_extensions/dataimago/monograph/fonts/OFL-NotoSans.txt +93 -0
  90. package/dist/quarto/_extensions/dataimago/monograph/fonts/OFL-NotoSansMath.txt +93 -0
  91. package/dist/quarto/_extensions/dataimago/monograph/fonts/OFL-NotoSansMono.txt +93 -0
  92. package/dist/quarto/_extensions/dataimago/monograph/fonts/README-lm.txt +27 -0
  93. package/dist/quarto/_extensions/dataimago/monograph/fonts/lmsans10-regular.otf +0 -0
  94. package/dist/quarto/_extensions/dataimago/monograph/partials/before-body.tex +16 -0
  95. package/dist/quarto/_extensions/dataimago/monograph/partials/title.tex +27 -0
  96. package/dist/quarto/_extensions/dataimago/pkgsite/_extension.yml +28 -0
  97. package/dist/quarto/_extensions/dataimago/pkgsite/components.scss +243 -0
  98. package/dist/quarto/_extensions/dataimago/pkgsite/dataimago-dark.scss +344 -0
  99. package/dist/quarto/_extensions/dataimago/pkgsite/dataimago-light.scss +338 -0
  100. package/dist/quarto/_extensions/dataimago/pkgsite/filters/landing.lua +233 -0
  101. package/dist/quarto/_extensions/dataimago/pkgsite/filters/provenance.lua +212 -0
  102. package/dist/quarto/_extensions/dataimago/pkgsite/hero-fallback.svg +53 -0
  103. package/dist/quarto/_extensions/dataimago/pkgsite/pkgsite-hero.js +99 -0
  104. package/dist/quarto/_extensions/dataimago/pkgsite/pkgsite.scss +281 -0
  105. package/dist/quarto/components.scss +14 -1
  106. package/dist/quarto/dataimago-dark.scss +22 -6
  107. package/dist/quarto/dataimago-light.scss +16 -6
  108. package/dist/tailwind-preset.js +4 -4
  109. package/dist/templates/KNOWLEDGE-explorer.md +1 -1
  110. package/dist/templates/KNOWLEDGE-framework.md +1 -1
  111. package/dist/templates/KNOWLEDGE-research.md +1 -1
  112. package/dist/templates/quarto_website/README.md +4 -2
  113. package/dist/templates/quarto_website/_quarto.yml.template +4 -2
  114. package/dist/templates/quarto_website/about.qmd.template +1 -1
  115. package/dist/templates/quarto_website/assets/css/lang.css +181 -0
  116. package/dist/templates/quarto_website/assets/js/custom-anchors.js +1 -1
  117. package/dist/templates/quarto_website/assets/js/logo-switch.js +1 -1
  118. package/dist/templates/quarto_website/assets/js/scroll.js +1 -1
  119. package/dist/templates/quarto_website/ethics.qmd.template +1 -1
  120. package/dist/templates/quarto_website/index.qmd.template +1 -1
  121. package/dist/tokens.css +3 -3
  122. package/dist/tokens.scss +3 -3
  123. package/package.json +6 -3
@@ -0,0 +1,338 @@
1
+ // @dataimago/css@0.1.0-alpha.23 dist/quarto/_extensions/dataimago/pkgsite/dataimago-light.scss · sha256:e456b3e8cfaa03df7fe5ac29bb6e8288454ee5daab29ff6470c45a12ff8d3f32 · generated from tokens; do not edit · restore: npx -p @dataimago/css@0.1.0-alpha.23 dataimago-sync
2
+ // dataimago light theme for Quarto 1.8 — generated from the design tokens (tools/formats/quarto.mjs).
3
+ // Bootstrap Sass variables are compile-time sRGB; runtime colours come from the custom properties below.
4
+
5
+ /*-- scss:defaults --*/
6
+ $body-bg: #ededeb !default;
7
+ $body-color: #14140f !default;
8
+ $headings-color: #14140f !default;
9
+ $navbar-bg: #ededeb !default;
10
+ $link-color: #434739 !default;
11
+ $link-hover-color: #363a2e !default;
12
+ $code-color: #1f618d !default;
13
+ $code-bg: #faf2e3 !default;
14
+ $border-color: #888785 !default;
15
+ $font-family-sans-serif: Noto Sans, Fira Sans, system-ui, sans-serif !default;
16
+ $font-family-monospace: Noto Sans Mono, SF Mono, Monaco, Inconsolata, monospace !default;
17
+ $headings-font-family: Josefin Sans, Noto Sans, system-ui, sans-serif !default;
18
+ $headings-font-weight: 500 !default;
19
+ $h2-font-size: 1.875rem !default;
20
+ $web-font-path: false !default;
21
+
22
+ /*-- scss:rules --*/
23
+ // ── Design tokens (contract custom properties) ───────────────────────
24
+ :root {
25
+ --color-palette-ink-50: #f5f5f4;
26
+ --color-palette-ink-100: #e7e5e4;
27
+ --color-palette-ink-200: #d6d3d1;
28
+ --color-palette-ink-300: #a8a29e;
29
+ --color-palette-ink-400: #78716c;
30
+ --color-palette-ink-500: #57534e;
31
+ --color-palette-ink-600: #44403c;
32
+ --color-palette-ink-700: #292524;
33
+ --color-palette-ink-800: #1c1917;
34
+ --color-palette-ink-900: #0c0a09;
35
+ --color-palette-stone-50: #f7f7f6;
36
+ --color-palette-stone-100: #ededeb;
37
+ --color-palette-stone-200: #dcdcda;
38
+ --color-palette-stone-300: #c1c1bf;
39
+ --color-palette-stone-400: #a0a0a0;
40
+ --color-palette-stone-500: #7c7c7c;
41
+ --color-palette-stone-600: #5e5e5c;
42
+ --color-palette-stone-700: #424240;
43
+ --color-palette-stone-800: #292927;
44
+ --color-palette-stone-900: #14140f;
45
+ --color-palette-forest-50: #f0f1ed;
46
+ --color-palette-forest-100: #dde0d4;
47
+ --color-palette-forest-200: #bdc4ad;
48
+ --color-palette-forest-300: #98a384;
49
+ --color-palette-forest-400: #7e8a6b;
50
+ --color-palette-forest-500: #5e6749;
51
+ --color-palette-forest-600: #4d5640;
52
+ --color-palette-forest-700: #434739;
53
+ --color-palette-forest-800: #363a2e;
54
+ --color-palette-forest-900: #1f2218;
55
+ --color-palette-paper-50: #fefdfb;
56
+ --color-palette-paper-100: #fdf9f2;
57
+ --color-palette-paper-200: #faf2e3;
58
+ --color-palette-paper-300: #f5e8cf;
59
+ --color-palette-paper-400: #edd9b3;
60
+ --color-palette-paper-500: #e0c088;
61
+ --color-palette-copper-50: #fdf4ee;
62
+ --color-palette-copper-100: #fbe5d1;
63
+ --color-palette-copper-200: #f6c79c;
64
+ --color-palette-copper-300: #f0a467;
65
+ --color-palette-copper-400: #ea8441;
66
+ --color-palette-copper-500: #d46820;
67
+ --color-palette-copper-600: #b55017;
68
+ --color-palette-copper-700: #913d15;
69
+ --color-palette-copper-800: #753318;
70
+ --color-palette-copper-900: #612b16;
71
+ --color-palette-accent-50: #f0f8fc;
72
+ --color-palette-accent-300: #3498DB;
73
+ --color-palette-accent-400: #2980B9;
74
+ --color-palette-accent-500: #1f618d;
75
+ --color-palette-accent-600: #154d6f;
76
+ --color-palette-accent-700: #0f3a52;
77
+ --color-palette-presentation-blue-50: #f0f8fc;
78
+ --color-palette-presentation-blue-500: #3498DB;
79
+ --color-palette-presentation-blue-600: #2980B9;
80
+ --color-palette-presentation-blue-700: #1f618d;
81
+ --color-functional-success: #27AE60;
82
+ --color-functional-warning: #F39C12;
83
+ --color-functional-error: #E74C3C;
84
+ --color-functional-info: #3498DB;
85
+ --transition-quick: 0.15s ease;
86
+ --transition-standard: 0.25s ease-in-out;
87
+ --transition-smooth: 0.35s ease;
88
+ --transition-logo: 0.3s;
89
+ --font-family-sans: Noto Sans, Fira Sans, system-ui, sans-serif;
90
+ --font-family-mono: Noto Sans Mono, SF Mono, Monaco, Inconsolata, monospace;
91
+ --font-family-display: var(--font-family-display-editorial);
92
+ --font-family-display-editorial: Josefin Sans, Noto Sans, system-ui, sans-serif;
93
+ --font-family-display-documentation: Noto Sans, system-ui, sans-serif;
94
+ --font-family-brand: Futura, system-ui, sans-serif;
95
+ --font-family-math: Noto Sans Math, math;
96
+ --font-size-micro: 0.75rem;
97
+ --font-size-small: 0.875rem;
98
+ --font-size-base: 1rem;
99
+ --font-size-readable: 1.125rem;
100
+ --font-size-emphasis: 1.25rem;
101
+ --font-size-heading-small: 1.5rem;
102
+ --font-size-heading-medium: 1.875rem;
103
+ --font-size-heading-large: 2.25rem;
104
+ --font-size-heading-xl: 3rem;
105
+ --font-weight-extralight: 200;
106
+ --font-weight-light: 300;
107
+ --font-weight-normal: 400;
108
+ --font-weight-medium: 500;
109
+ --font-weight-semibold: 600;
110
+ --font-weight-bold: 700;
111
+ --font-weight-heading-h1: var(--font-weight-medium);
112
+ --font-weight-heading-h2: var(--font-weight-medium);
113
+ --font-weight-heading-h3: var(--font-weight-normal);
114
+ --font-weight-heading-h4: var(--font-weight-light);
115
+ --font-weight-heading-h5: var(--font-weight-light);
116
+ --font-weight-heading-h6: var(--font-weight-light);
117
+ --font-weight-heading-subtitle: var(--font-weight-semibold);
118
+ --font-style-normal: normal;
119
+ --font-style-italic: italic;
120
+ --font-style-oblique: oblique;
121
+ --font-lineHeight-tight: 1.25;
122
+ --font-lineHeight-normal: 1.5;
123
+ --font-lineHeight-relaxed: 1.625;
124
+ --font-feature-settings-display: "lnum";
125
+ --font-feature-settings-body: "normal";
126
+ --spacing-xs: 0.25rem;
127
+ --spacing-sm: 0.5rem;
128
+ --spacing-md: 1rem;
129
+ --spacing-lg: 1.5rem;
130
+ --spacing-xl: 2rem;
131
+ --spacing-2xl: 3rem;
132
+ --spacing-3xl: 4rem;
133
+ --radius-sm: 0.25rem;
134
+ --radius-md: 0.5rem;
135
+ --radius-lg: 0.75rem;
136
+ --radius-xl: 1rem;
137
+ --radius-full: 9999px;
138
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
139
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
140
+ --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
141
+ --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
142
+ --color-dataviz-okabe-ito-orange: #E69F00;
143
+ --color-dataviz-okabe-ito-sky-blue: #56B4E9;
144
+ --color-dataviz-okabe-ito-bluish-green: #009E73;
145
+ --color-dataviz-okabe-ito-yellow: #F0E442;
146
+ --color-dataviz-okabe-ito-blue: #0072B2;
147
+ --color-dataviz-okabe-ito-vermillion: #D55E00;
148
+ --color-dataviz-okabe-ito-reddish-purple: #CC79A7;
149
+ --color-dataviz-categorical-1: #E69F00;
150
+ --color-dataviz-categorical-2: #56B4E9;
151
+ --color-dataviz-categorical-3: #009E73;
152
+ --color-dataviz-categorical-4: #F0E442;
153
+ --color-dataviz-categorical-5: #0072B2;
154
+ --color-dataviz-categorical-6: #D55E00;
155
+ --color-dataviz-categorical-7: #CC79A7;
156
+ }
157
+
158
+ :root, [data-bs-theme="light"] {
159
+ --color-surface-page: #ededeb;
160
+ --color-surface-page: color(display-p3 0.9294 0.9294 0.9223);
161
+ --color-surface-page-scrolled: #ededeb;
162
+ --color-surface-page-scrolled: color(display-p3 0.9294 0.9294 0.9223);
163
+ --color-surface-elevated: #f7f7f6;
164
+ --color-surface-elevated: color(display-p3 0.9686 0.9686 0.9651);
165
+ --color-surface-sunken: #faf2e3;
166
+ --color-surface-sunken: color(display-p3 0.9749 0.9501 0.8963);
167
+ --color-surface-navbar: #ededeb;
168
+ --color-surface-navbar: color(display-p3 0.9294 0.9294 0.9223);
169
+ --color-surface-navbar-scrolled: #ededeb;
170
+ --color-surface-navbar-scrolled: color(display-p3 0.9294 0.9294 0.9223);
171
+ --color-surface-code: #faf2e3;
172
+ --color-surface-code: color(display-p3 0.9749 0.9501 0.8963);
173
+ --color-border-subtle: rgba(12, 10, 9, 0.45);
174
+ --color-border-subtle: color(display-p3 0.0457 0.0395 0.0358 / 0.45);
175
+ --color-border-moderate: rgba(12, 10, 9, 0.60);
176
+ --color-border-moderate: color(display-p3 0.0457 0.0395 0.0358 / 0.60);
177
+ --color-border-strong: rgba(12, 10, 9, 0.75);
178
+ --color-border-strong: color(display-p3 0.0457 0.0395 0.0358 / 0.75);
179
+ --color-border-card: rgba(12, 10, 9, 0.60);
180
+ --color-border-card: color(display-p3 0.0457 0.0395 0.0358 / 0.60);
181
+ --color-border-code: #d6d3d1;
182
+ --color-border-code: color(display-p3 0.8371 0.8278 0.8205);
183
+ --color-content-primary: #14140f;
184
+ --color-content-primary: color(display-p3 0.0784 0.0784 0.0608);
185
+ --color-content-secondary: #6a6a6a;
186
+ --color-content-secondary: color(display-p3 0.4157 0.4157 0.4157);
187
+ --color-content-muted: #706964;
188
+ --color-content-muted: color(display-p3 0.4345 0.4127 0.3945);
189
+ --color-content-inverse: #fdf9f2;
190
+ --color-content-inverse: color(display-p3 0.9894 0.977 0.9518);
191
+ --color-interactive-primary: #434739;
192
+ --color-interactive-primary: color(display-p3 0.2656 0.2779 0.2287);
193
+ --color-interactive-hover: #363a2e;
194
+ --color-interactive-hover: color(display-p3 0.2146 0.2269 0.1848);
195
+ --color-interactive-accent: #1f618d;
196
+ --color-interactive-accent: color(display-p3 0.198 0.375 0.5385);
197
+ --color-interactive-focus: #434739;
198
+ --color-interactive-focus: color(display-p3 0.2656 0.2779 0.2287);
199
+ --color-presentation-accent: #3498db;
200
+ --color-presentation-accent: color(display-p3 0.3208 0.588 0.8369);
201
+ --color-presentation-accent-hover: #2980b9;
202
+ --color-presentation-accent-hover: color(display-p3 0.2638 0.495 0.7068);
203
+ --color-vertical-accent-dissertation: #b87333;
204
+ --color-vertical-accent-dissertation: color(display-p3 0.7242 0.4389 0.1259);
205
+ --color-vertical-accent-rpkg: #3b82f6;
206
+ --color-vertical-accent-rpkg: color(display-p3 0.3047 0.5035 0.9338);
207
+ --color-vertical-accent-SGPc: #5a6310;
208
+ --color-vertical-accent-SGPc: color(display-p3 0.3595 0.3871 0.1309);
209
+ --color-brand-mark-red: #cc0000;
210
+ --color-brand-mark-red: color(display-p3 0.7331 0.1519 0.1019);
211
+ --contrast-high: rgb(20, 20, 16);
212
+ --contrast-readable: rgb(20, 20, 16);
213
+ --contrast-medium: #7c7c7c;
214
+ --contrast-subtle: #7c7c7c;
215
+ --shadow-subtle: 0 1px 2px 0 rgb(20 20 16 / 0.05);
216
+ --shadow-moderate: 0 4px 6px -1px rgb(20 20 16 / 0.1);
217
+ --shadow-prominent: 0 10px 15px -3px rgb(20 20 16 / 0.1);
218
+ --border-subtle: rgba(20, 20, 16, 0.47);
219
+ --border-moderate: rgba(20, 20, 16, 0.63);
220
+ --border-focus: #3498DB;
221
+ --navigation-hover-background: rgba(20, 20, 16, 0.05);
222
+ --navigation-active-background: rgba(20, 20, 16, 0.1);
223
+ --color-dataviz-okabe-ito-black: #000000;
224
+ --color-dataviz-categorical-8: #000000;
225
+ --color-dataviz-uncertainty-outer: #D6D6D6;
226
+ --color-dataviz-uncertainty-union: #9E9E9E;
227
+ --color-dataviz-uncertainty-inner: #333333;
228
+ }
229
+
230
+ // ── Quarto chrome → tokens ──────────────────────────────────────────────
231
+ body {
232
+ background-color: var(--color-surface-page);
233
+ color: var(--color-content-primary);
234
+ }
235
+
236
+ h1, h2, h3, h4, h5, h6, .title {
237
+ color: var(--color-content-primary);
238
+ font-feature-settings: var(--font-feature-settings-display);
239
+ }
240
+
241
+ // Navbar chrome is brand voice: Josefin through the editorial variable (never the
242
+ // Futura brand token). Tagged-language rules in lang.css still switch links to Noto;
243
+ // the brand is never translated (display-family-split).
244
+ .navbar-brand, .navbar-title, .navbar-nav .nav-link, .navbar-nav .dropdown-item {
245
+ font-family: var(--font-family-display-editorial);
246
+ }
247
+
248
+ math { font-family: var(--font-family-math); }
249
+
250
+ // Links in running text are underlined: interactive.primary is about 1.9:1
251
+ // against body text in light mode, so colour cannot be the only cue (WCAG 1.4.1).
252
+ main.content :is(p, li, dd, td, blockquote, figcaption, .callout-body) a {
253
+ color: var(--color-interactive-primary);
254
+ text-decoration: underline;
255
+ text-underline-offset: 0.15em;
256
+ }
257
+
258
+ main.content :is(p, li, dd, td, blockquote, figcaption, .callout-body) a:hover {
259
+ color: var(--color-interactive-hover);
260
+ }
261
+
262
+ // Navigation and the outline stay plain.
263
+ #TOC a, nav a, .sidebar a, .navbar a, a.footnote-ref, a.anchorjs-link {
264
+ text-decoration: none;
265
+ }
266
+
267
+ :not(pre) > code {
268
+ color: var(--color-interactive-accent);
269
+ background-color: var(--color-surface-code);
270
+ }
271
+
272
+ pre, div.sourceCode {
273
+ background-color: var(--color-surface-code);
274
+ border: 1px solid var(--color-border-code);
275
+ }
276
+
277
+ // Quarto themes its popups as [data-theme~="quarto"] at compile time ($body-bg);
278
+ // match that specificity so the runtime token wins.
279
+ .tippy-box, .tippy-box[data-theme~="quarto"] {
280
+ background-color: var(--color-surface-elevated);
281
+ color: var(--color-content-primary);
282
+ border: 1px solid var(--color-border-subtle);
283
+ }
284
+
285
+ .tippy-box[data-theme~="quarto"] > .tippy-backdrop {
286
+ background-color: var(--color-surface-elevated);
287
+ }
288
+
289
+ .callout {
290
+ background-color: var(--color-surface-elevated);
291
+ border-color: var(--color-border-subtle);
292
+ }
293
+
294
+ .column-margin, .margin-aside, figcaption {
295
+ color: var(--color-content-secondary);
296
+ }
297
+
298
+ // Elevated cards carry an edge: in dark mode surface.elevated is about 1.06:1
299
+ // against surface.page, so a card without one disappears.
300
+ .di-elevated, div.abstract {
301
+ background-color: var(--color-surface-elevated);
302
+ border: 1px solid var(--color-border-subtle);
303
+ border-radius: var(--radius-md);
304
+ padding: var(--spacing-md);
305
+ }
306
+
307
+ // ===== THEME TOGGLE STYLING =====
308
+ // Light theme - show moon icon (switch to dark)
309
+
310
+ .quarto-color-scheme-toggle .bi::before {
311
+ display: inline-block !important;
312
+ height: 1rem !important;
313
+ width: 1rem !important;
314
+ content: "" !important;
315
+ vertical-align: -0.125em !important;
316
+ background-repeat: no-repeat !important;
317
+ background-size: 1rem 1rem !important;
318
+ background-color: transparent !important;
319
+ background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="%2383838F" class="bi bi-moon" viewBox="0 0 16 16"><path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/></svg>') !important;
320
+ transition: background-image 0.25s ease;
321
+ }
322
+
323
+ .quarto-color-scheme-toggle:hover .bi::before {
324
+ background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="%23000000" class="bi bi-moon" viewBox="0 0 16 16"><path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/></svg>') !important;
325
+ transition: background-image 0.25s ease;
326
+ }
327
+
328
+ @media (prefers-reduced-motion: no-preference) {
329
+ html {
330
+ scroll-behavior: smooth;
331
+ }
332
+ }
333
+
334
+ @media (prefers-reduced-motion: reduce) {
335
+ .quarto-color-scheme-toggle .bi::before {
336
+ transition: none !important;
337
+ }
338
+ }
@@ -0,0 +1,233 @@
1
+ -- @dataimago/css@0.1.0-alpha.23 dist/quarto/_extensions/dataimago/pkgsite/filters/landing.lua · sha256:84cdab2c95ff44271f4c3cf044d3a5d4886312d26c97417f276ab45ffa1e20ec · generated from tokens; do not edit · restore: npx -p @dataimago/css@0.1.0-alpha.23 dataimago-sync
2
+ -- landing.lua: replaces the author's `.di-landing` div with the package-site landing stage.
3
+ -- Pandoc 3 Lua filter for Quarto >= 1.8. Metadata comes from `pkgsite` (index.qmd's `metadata-files`
4
+ -- merges the generator's _landing.yml into it). A page with no `.di-landing` div is returned unchanged.
5
+ --
6
+ -- DOM order: pause control, then div.di-landing holding div.di-landing-intro, div.di-landing-overview (the
7
+ -- author's content, still Pandoc blocks), div.di-landing-hero[aria-hidden], nav.di-landing-cards.
8
+ -- The stage, the intro and the overview are real Pandoc Div nodes, never raw open/close tags around Pandoc
9
+ -- content: Quarto's section-divs wraps every heading in <section>, and a section swallows a raw closing tag
10
+ -- that follows it (a README's `##` headings put the hero and the cards inside the overview).
11
+ -- A page that holds a `.di-landing` stage gets `toc: false`: the stage is the page, a TOC beside it is noise.
12
+ -- Layout is pkgsite.scss's job; this file only produces markup.
13
+ --
14
+ -- Only the FIRST `.di-landing` div on a page is the stage; any later one is unwrapped (its content stays in
15
+ -- place, without the class). The name falls back to `pagetitle`, then `title`; with none of them the intro
16
+ -- (and its h1) is omitted. With no cards, nav.di-landing-cards is omitted. The visible pause label lives at the
17
+ -- end of the intro (reachable and in reading order); the checkbox it toggles comes first in the stage.
18
+
19
+ local stringify = pandoc.utils.stringify
20
+
21
+ local function esc(s)
22
+ s = tostring(s or '')
23
+ s = s:gsub('&', '&amp;')
24
+ s = s:gsub('<', '&lt;')
25
+ s = s:gsub('>', '&gt;')
26
+ s = s:gsub('"', '&quot;')
27
+ return s
28
+ end
29
+
30
+ -- Metadata strings arrive as Inlines, parsed as markdown: `<it>` becomes a RawInline and would vanish
31
+ -- under stringify. Rebuild the author's literal text from the inlines instead.
32
+ local function text(v)
33
+ if v == nil then return '' end
34
+ local t = pandoc.utils.type(v)
35
+ if t == 'string' then return v end
36
+ if t == 'boolean' or t == 'number' then return tostring(v) end
37
+ if t == 'Inlines' then
38
+ local out = {}
39
+ for _, el in ipairs(v) do
40
+ if el.t == 'Str' then out[#out + 1] = el.text
41
+ elseif el.t == 'Space' or el.t == 'SoftBreak' then out[#out + 1] = ' '
42
+ elseif el.t == 'RawInline' or el.t == 'Code' then out[#out + 1] = el.text
43
+ else out[#out + 1] = stringify(el) end
44
+ end
45
+ return table.concat(out)
46
+ end
47
+ return stringify(v)
48
+ end
49
+
50
+ local function list(v)
51
+ if v == nil then return {} end
52
+ if pandoc.utils.type(v) == 'List' or pandoc.utils.type(v) == 'table' then return v end
53
+ return { v }
54
+ end
55
+
56
+ local function dirname(p)
57
+ return (p:match('^(.*)/[^/]*$')) or '.'
58
+ end
59
+
60
+ local function read_file(p)
61
+ local f = io.open(p, 'r')
62
+ if not f then return nil end
63
+ local s = f:read('a')
64
+ f:close()
65
+ return s
66
+ end
67
+
68
+ -- An inlined SVG must start at `<svg`: drop a provenance comment and an xml declaration.
69
+ local function clean_svg(s)
70
+ s = s:gsub('^%s*<%?xml.-%?>%s*', '')
71
+ while s:match('^%s*<!%-%-') do s = s:gsub('^%s*<!%-%-.-%-%->%s*', '', 1) end
72
+ return (s:gsub('%s+$', ''))
73
+ end
74
+
75
+ local function project_dir()
76
+ if quarto and quarto.project and quarto.project.directory then return quarto.project.directory end
77
+ if quarto and quarto.doc and quarto.doc.input_file then return dirname(quarto.doc.input_file) end
78
+ local inputs = PANDOC_STATE and PANDOC_STATE.input_files
79
+ if inputs and inputs[1] then return dirname(inputs[1]) end
80
+ return '.'
81
+ end
82
+
83
+ local function extension_dir()
84
+ local script = PANDOC_SCRIPT_FILE or ''
85
+ return dirname(dirname(script)) -- <ext>/filters/landing.lua -> <ext>
86
+ end
87
+
88
+
89
+ local function fail(msg)
90
+ io.stderr:write('ERROR: landing.lua: ' .. msg .. '\n')
91
+ os.exit(1)
92
+ end
93
+
94
+ -- hero.src / hero.poster are project-relative: refuse an absolute path or any `..` segment.
95
+ local function check_rel(key, v)
96
+ if v == '' then return end
97
+ if v:sub(1, 1) == '/' or v:sub(1, 1) == '\\' or v:match('^%a[%w+.-]*:') or v:find('\\', 1, true) then
98
+ fail('hero.' .. key .. ' must be a relative path inside the project, got: ' .. v)
99
+ end
100
+ for seg in (v .. '/'):gmatch('([^/]*)/') do
101
+ if seg == '..' then fail('hero.' .. key .. ' must not contain a ".." segment, got: ' .. v) end
102
+ end
103
+ end
104
+
105
+ -- Re-validate an SVG before it is inlined into the page: the leaf does not trust the generator's check.
106
+ -- Returns nil when clean, else the reason. Comments are stripped first.
107
+ local function svg_problem(raw)
108
+ local s = raw:gsub('<!%-%-.-%-%->', '')
109
+ local l = s:lower()
110
+ for _, t in ipairs({ 'script', 'foreignobject', 'iframe', 'object', 'embed' }) do
111
+ if l:find('<' .. t .. '[%s/>]') or l:find('<%w+:' .. t .. '[%s/>]') then return 'contains <' .. t .. '>' end
112
+ end
113
+ if l:find('<animate') or l:find('<%w+:animate') then return 'contains a SMIL animate element' end
114
+ if l:find('<set[%s/>]') or l:find('<%w+:set[%s/>]') then return 'contains a SMIL set element' end
115
+ if l:find('javascript:', 1, true) then return 'contains "javascript:"' end
116
+ if l:find('[%s"\'/]on%a+%s*=') then return 'contains an on* event-handler attribute' end
117
+ for body in l:gmatch('<style[^>]*>(.-)</style>') do
118
+ if body:find('<', 1, true) then return 'has "<" inside a <style> element' end
119
+ end
120
+ if l:find('<style[^>]*>[^<]*$') then return 'has an unterminated <style> element' end
121
+ for q, c in l:gmatch('url%s*%(%s*(["\']?)%s*(.?)') do
122
+ if c ~= '#' then return 'has a url() that does not point at a #fragment' end
123
+ end
124
+ for pos in l:gmatch('()href%s*=') do
125
+ local rest = s:sub(pos):match('^href%s*=%s*(.*)$') or ''
126
+ local q = rest:sub(1, 1)
127
+ local v
128
+ if q == '"' or q == "'" then v = rest:match('^' .. q .. '(.-)' .. q) or ''
129
+ else v = rest:match('^([^%s>]*)') end
130
+ if v:gsub('^%s+', ''):sub(1, 1) ~= '#' then return 'has an href that is not a #fragment: ' .. v:sub(1, 60) end
131
+ end
132
+ return nil
133
+ end
134
+
135
+ local function hero_html(hero)
136
+ local kind = text(hero and hero.kind)
137
+ if kind == '' then kind = 'fallback' end
138
+ if hero then
139
+ check_rel('src', text(hero.src))
140
+ check_rel('poster', text(hero.poster))
141
+ end
142
+ local open = '<div class="di-landing-hero" aria-hidden="true">'
143
+ if kind == 'svg' then
144
+ local src = text(hero.src)
145
+ local body = read_file(project_dir() .. '/' .. src)
146
+ if body then
147
+ local why = svg_problem(body)
148
+ if why then fail('hero.src ' .. src .. ' is not safe to inline: ' .. why) end
149
+ return open .. clean_svg(body) .. '</div>'
150
+ end
151
+ io.stderr:write('landing.lua: hero.src not found: ' .. src .. '; using the brand fallback\n')
152
+ elseif kind == 'js' then
153
+ local src, poster, alt = text(hero.src), text(hero.poster), text(hero.alt)
154
+ local img = poster ~= '' and ('<img src="' .. esc(poster) .. '" alt="' .. esc(alt) .. '">') or ''
155
+ return open .. '<div class="di-hero-mount" data-hero-src="' .. esc(src) .. '" data-hero-poster="'
156
+ .. esc(poster) .. '">' .. img .. '</div><script type="module" src="pkgsite-hero.js"></script></div>'
157
+ end
158
+ local body = read_file(extension_dir() .. '/hero-fallback.svg')
159
+ return open .. (body and clean_svg(body) or '') .. '</div>'
160
+ end
161
+
162
+ local function build(div, meta)
163
+ local p = meta.pkgsite or {}
164
+ local out = pandoc.List()
165
+ local stage = pandoc.List()
166
+ local function raw(s) stage:insert(pandoc.RawBlock('html', s)) end
167
+
168
+ local label = '<label class="di-hero-pause-label" for="di-hero-pause">'
169
+ .. '<span class="di-pause-on">Pause animation</span><span class="di-pause-off">Play animation</span></label>'
170
+ out:insert(pandoc.RawBlock('html', '<input type="checkbox" id="di-hero-pause" class="di-hero-pause-input">'))
171
+
172
+ local name = text(p.name)
173
+ if name == '' then name = text(meta.pagetitle) end
174
+ if name == '' then name = text(meta.title) end
175
+ if name ~= '' then
176
+ local intro = pandoc.List()
177
+ local function iraw(s) intro:insert(pandoc.RawBlock('html', s)) end
178
+ iraw('<h1 class="di-landing-name">' .. esc(name) .. '</h1>')
179
+ if text(p.title) ~= '' then iraw('<p class="di-landing-title">' .. esc(text(p.title)) .. '</p>') end
180
+ if text(p.version) ~= '' then iraw('<p class="di-landing-version">Version ' .. esc(text(p.version)) .. '</p>') end
181
+ local links = list(p.links)
182
+ if #links > 0 then
183
+ iraw('<ul class="pill-links">')
184
+ for _, l in ipairs(links) do
185
+ local a = pandoc.Link({ pandoc.Str(text(l.text)) }, text(l.href))
186
+ intro:insert(pandoc.Plain({ pandoc.RawInline('html', '<li>'), a, pandoc.RawInline('html', '</li>') }))
187
+ end
188
+ iraw('</ul>')
189
+ end
190
+ iraw('<p class="di-hero-pause">' .. label .. '</p>')
191
+ stage:insert(pandoc.Div(intro, pandoc.Attr('', { 'di-landing-intro' })))
192
+ else
193
+ raw('<div class="di-landing-controls"><p class="di-hero-pause">' .. label .. '</p></div>')
194
+ end
195
+
196
+ local content = nil
197
+ for _, b in ipairs(div.content) do
198
+ if b.t == 'Div' and b.classes:includes('di-landing-overview') then content = b.content end
199
+ end
200
+ stage:insert(pandoc.Div(content or div.content, pandoc.Attr('', { 'di-landing-overview' })))
201
+
202
+ raw(hero_html(p.hero))
203
+
204
+ local cards = list(p.cards)
205
+ if #cards > 0 then raw('<nav class="di-landing-cards" aria-label="Sections">') end
206
+ for _, c in ipairs(cards) do
207
+ local inl = {
208
+ pandoc.Span({ pandoc.Str(text(c.title)) }, pandoc.Attr('', { 'di-card-title' })),
209
+ pandoc.Span({ pandoc.Str(text(c.desc)) }, pandoc.Attr('', { 'di-card-desc' })),
210
+ }
211
+ local a = pandoc.Link(inl, text(c.href), '', pandoc.Attr('', { 'di-card' }, { { 'data-card', text(c.key) } }))
212
+ stage:insert(pandoc.Plain({ a }))
213
+ end
214
+ if #cards > 0 then raw('</nav>') end
215
+ out:insert(pandoc.Div(stage, pandoc.Attr('', { 'di-landing' })))
216
+ return out
217
+ end
218
+
219
+ function Pandoc(doc)
220
+ local found = false
221
+ local result = doc:walk({
222
+ Div = function(div)
223
+ if div.classes:includes('di-landing') then
224
+ if found then return div.content end -- a later one: unwrapped, content stays in place
225
+ found = true
226
+ return build(div, doc.meta)
227
+ end
228
+ end,
229
+ })
230
+ if not found then return nil end
231
+ result.meta.toc = false
232
+ return result
233
+ end