@wxxb789/anc 0.0.1

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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +295 -0
  3. package/astro.config.mjs +255 -0
  4. package/bin/anc.mjs +798 -0
  5. package/package.json +93 -0
  6. package/public/_headers +45 -0
  7. package/public/favicon.ico +0 -0
  8. package/public/favicon.svg +9 -0
  9. package/public/fonts/Temml.woff2 +0 -0
  10. package/scripts/build-snapshot.js +69 -0
  11. package/scripts/build-wasm.js +67 -0
  12. package/scripts/build-workspace.js +50 -0
  13. package/scripts/copy-snapshot.js +48 -0
  14. package/scripts/copy-wasm.js +57 -0
  15. package/scripts/emit-redirects.js +64 -0
  16. package/scripts/generate-corpus.js +421 -0
  17. package/scripts/init-repository.js +249 -0
  18. package/scripts/load-config.js +975 -0
  19. package/scripts/markdown-to-artifact.js +1286 -0
  20. package/scripts/preview-site.js +364 -0
  21. package/scripts/publish-set-review.js +157 -0
  22. package/scripts/resolve-links.js +640 -0
  23. package/scripts/run-pagefind.js +125 -0
  24. package/scripts/scan-residue.js +1016 -0
  25. package/scripts/scan-secrets.js +268 -0
  26. package/scripts/seed-gitignore.js +410 -0
  27. package/scripts/snapshot-rows.js +205 -0
  28. package/scripts/validate-content.js +95 -0
  29. package/scripts/vendor-provenance.js +307 -0
  30. package/scripts/verify-output-inventory.js +307 -0
  31. package/scripts/write-report.js +351 -0
  32. package/scripts/write-snapshot.js +136 -0
  33. package/src/components/CollectionExplorer.astro +149 -0
  34. package/src/components/FacetIndex.astro +45 -0
  35. package/src/components/LinkedNotes.astro +94 -0
  36. package/src/components/NoteGraph.astro +434 -0
  37. package/src/components/NoteList.astro +54 -0
  38. package/src/components/SiteMetadata.astro +143 -0
  39. package/src/components/TableOfContents.astro +69 -0
  40. package/src/components/TagBrowser.astro +70 -0
  41. package/src/layouts/Layout.astro +305 -0
  42. package/src/lib/artifact-source.js +72 -0
  43. package/src/lib/build-bindings.js +11 -0
  44. package/src/lib/collection-navigation.js +145 -0
  45. package/src/lib/content.js +92 -0
  46. package/src/lib/diagram-mode.js +18 -0
  47. package/src/lib/graph-layout.js +219 -0
  48. package/src/lib/graph-selection.js +84 -0
  49. package/src/lib/graph.js +42 -0
  50. package/src/lib/link-resolution.js +389 -0
  51. package/src/lib/markdown.js +1469 -0
  52. package/src/lib/math-mode.js +31 -0
  53. package/src/lib/math-output.js +131 -0
  54. package/src/lib/math.js +165 -0
  55. package/src/lib/mermaid-environment.js +475 -0
  56. package/src/lib/mermaid-render.js +769 -0
  57. package/src/lib/preview-model.js +96 -0
  58. package/src/lib/relations.js +242 -0
  59. package/src/lib/rendered-marker.js +55 -0
  60. package/src/lib/route-path.js +192 -0
  61. package/src/lib/routes.js +342 -0
  62. package/src/lib/schema.js +578 -0
  63. package/src/lib/site.js +578 -0
  64. package/src/lib/snapshot-contract.js +216 -0
  65. package/src/lib/snapshot-operations.js +147 -0
  66. package/src/lib/snapshot-queries.js +216 -0
  67. package/src/lib/snapshot-reader.js +210 -0
  68. package/src/lib/snapshot.js +233 -0
  69. package/src/lib/sqlite-warning.js +22 -0
  70. package/src/lib/sqlite.js +14 -0
  71. package/src/lib/tag-browser-model.js +18 -0
  72. package/src/lib/translations.js +533 -0
  73. package/src/lib/wasm-asset.js +47 -0
  74. package/src/lib/worker-protocol.js +93 -0
  75. package/src/pages/404.astro +35 -0
  76. package/src/pages/about.astro +100 -0
  77. package/src/pages/collections/[slug].astro +36 -0
  78. package/src/pages/collections/index.astro +33 -0
  79. package/src/pages/graph.astro +64 -0
  80. package/src/pages/index.astro +33 -0
  81. package/src/pages/notes/[slug].astro +509 -0
  82. package/src/pages/privacy.astro +121 -0
  83. package/src/pages/private.astro +59 -0
  84. package/src/pages/recent.astro +33 -0
  85. package/src/pages/robots.txt.js +15 -0
  86. package/src/pages/rss.xml.js +21 -0
  87. package/src/pages/sitemap.xml.js +20 -0
  88. package/src/pages/tags/[tag].astro +56 -0
  89. package/src/pages/tags/index.astro +37 -0
  90. package/src/scripts/code-copy.js +45 -0
  91. package/src/scripts/diagram-disabled.js +16 -0
  92. package/src/scripts/diagram.js +322 -0
  93. package/src/scripts/graph-client.js +222 -0
  94. package/src/scripts/graph-draw.js +166 -0
  95. package/src/scripts/link-preview.js +334 -0
  96. package/src/scripts/math-disabled.js +18 -0
  97. package/src/scripts/math.js +133 -0
  98. package/src/scripts/preferences.js +123 -0
  99. package/src/scripts/search-dialog.js +651 -0
  100. package/src/scripts/snapshot-client.js +157 -0
  101. package/src/scripts/snapshot-worker.js +341 -0
  102. package/src/scripts/tag-browser.js +153 -0
  103. package/src/scripts/theme-init.js +35 -0
  104. package/src/scripts/toc-active.js +38 -0
  105. package/src/styles/code.css +152 -0
  106. package/src/styles/diagram.css +149 -0
  107. package/src/styles/global.css +1739 -0
  108. package/src/styles/graph.css +317 -0
  109. package/src/styles/math.css +376 -0
  110. package/src/styles/tokens.css +171 -0
  111. package/tsconfig.json +25 -0
@@ -0,0 +1,317 @@
1
+ /*
2
+ * The graph.
3
+ *
4
+ * Loaded on every page that draws one, via a conditional `<link>` gated on the
5
+ * graph having edges — owner decision 7's pattern, the same way `code.css` and
6
+ * `diagram.css` reach only the pages that need them. A note with no
7
+ * neighbourhood requests nothing.
8
+ *
9
+ * **The region's own frame is in `global.css`, not here**, and that split is a
10
+ * fix rather than a preference: the region renders on every note page, with an
11
+ * empty state where there is no neighbourhood, so a frame in this conditional
12
+ * sheet left that empty state unstyled on every page of the published site.
13
+ * What lives here is only what a page that actually draws a figure needs.
14
+ *
15
+ * **Nothing here carries information by colour alone** (WCAG 1.4.1,
16
+ * requirements section 17). The three edge directions are three line *shapes*:
17
+ * an outgoing edge is solid with one arrowhead, an incoming one dashed, a
18
+ * mutual one solid with an arrowhead at each end. The subject node is larger
19
+ * and ringed. Every one of those distinctions survives a monochrome print and a
20
+ * reader who cannot see hue at all — and each node's accessible name states its
21
+ * relationship in words regardless.
22
+ *
23
+ * **No animation, so `prefers-reduced-motion` needs no rule.** The layout is
24
+ * computed at build time and never moves; there is no force simulation to
25
+ * settle and no transition to suppress. The global reduce block in `global.css`
26
+ * still covers the focus transitions this file inherits.
27
+ *
28
+ * Colour comes from the same tokens as everything else, so both themes follow
29
+ * `light-dark()` with no second palette and no script.
30
+ */
31
+
32
+ .graph {
33
+ margin-block: var(--space-6);
34
+ /* `figure` carries a user-agent `margin-inline: 40px` that would indent the
35
+ graph relative to the prose around it. */
36
+ margin-inline: 0;
37
+ }
38
+
39
+ .graph-canvas {
40
+ /* A graph wider than the measure scrolls rather than widening the page.
41
+ `tabindex="0"` is on the element in the markup: a scrollable region must be
42
+ reachable by keyboard, and the browser then scrolls it with the arrows.
43
+ The focus ring comes from `global.css`'s universal `:focus-visible`, which
44
+ already sets exactly this outline — restating it here was 87 bytes of a
45
+ conditional stylesheet that changed no computed value. */
46
+ overflow-x: auto;
47
+ text-align: center;
48
+ }
49
+
50
+ /*
51
+ * The figure scrolls rather than shrinking past legibility.
52
+ *
53
+ * `min-width` is what makes the scroll container real. With `max-width: 100%`
54
+ * alone the SVG always fits its parent, so `overflow-x: auto` could never
55
+ * trigger and the `tabindex="0"` beside it was a focus stop that did nothing —
56
+ * while a 60-node `/graph/` squeezed into 320 px rendered its labels at about
57
+ * five CSS pixels. Below this width the figure scrolls sideways instead, which
58
+ * is the same treatment a wide diagram and a wide code fence already get.
59
+ *
60
+ * `max-width: 100%` still caps it on a wide viewport, and without `height:
61
+ * auto` the browser keeps the attribute height and distorts the aspect ratio.
62
+ * The `width` and `height` attributes hold the intrinsic size, so the figure
63
+ * has a ratio before this stylesheet arrives and nothing shifts when it does.
64
+ */
65
+ .graph-svg {
66
+ display: block;
67
+ margin-inline: auto;
68
+ min-width: 22rem;
69
+ max-width: 100%;
70
+ height: auto;
71
+ }
72
+
73
+ .graph-edge {
74
+ stroke: var(--color-line-strong);
75
+ stroke-width: 1.5;
76
+ fill: none;
77
+ }
78
+
79
+ /*
80
+ * An edge the reader's note *receives* is dashed; one it *sends* is solid.
81
+ *
82
+ * Shape, not hue — this is the whole of requirements section 13.2's "incoming
83
+ * and outgoing edges visually distinguished" and section 17's "no information
84
+ * encoded by color alone". The dash pattern is coarse enough to read at the
85
+ * scale a 320 px viewport shrinks the figure to.
86
+ *
87
+ * Only the subject's own neighbourhood has a direction at all: `/graph/` has no
88
+ * subject, so its edges are all plain solid, which is honest — there is no
89
+ * "incoming" without a somewhere to come in to.
90
+ */
91
+ .graph-edge-incoming {
92
+ stroke-dasharray: 6 4;
93
+ }
94
+
95
+ /* A mutual edge carries an arrowhead at both ends, which is its distinction.
96
+ It is drawn slightly heavier so the pair reads as one relationship rather
97
+ than as a line somebody drew twice. */
98
+ .graph-edge-mutual {
99
+ stroke-width: 2;
100
+ }
101
+
102
+ .graph-arrow {
103
+ fill: var(--color-line-strong);
104
+ stroke: none;
105
+ }
106
+
107
+ .graph-dot {
108
+ fill: var(--color-surface);
109
+ stroke: var(--color-link);
110
+ stroke-width: 2;
111
+ }
112
+
113
+ /*
114
+ * The note the reader is on: larger, filled, and ringed.
115
+ *
116
+ * Three distinctions rather than one, because a reader who cannot see the fill
117
+ * colour still meets a bigger circle with a heavier edge. Requirements section
118
+ * 13.2 asks for the current page emphasized; the node's accessible name also
119
+ * says "this note" in words.
120
+ */
121
+ .graph-node-subject .graph-dot {
122
+ fill: var(--color-accent);
123
+ stroke: var(--color-accent);
124
+ stroke-width: 3;
125
+ }
126
+
127
+ .graph-label {
128
+ fill: var(--color-text);
129
+ /* `px` rather than `rem`: the label is positioned in the SVG's own user units
130
+ and the `viewBox` scales the whole figure with the reader's text size
131
+ already, so a `rem` here would scale it twice and push labels over their
132
+ neighbours. */
133
+ font-size: 13px;
134
+ font-family: var(--font-sans);
135
+ text-anchor: middle;
136
+ }
137
+
138
+ .graph-node-subject .graph-label {
139
+ font-weight: 650;
140
+ }
141
+
142
+ /*
143
+ * The focus ring, on the node rather than on the anchor's bounding box.
144
+ *
145
+ * An `<a>` wrapping SVG shapes has a bounding box that spans the circle and its
146
+ * label, so the default ring is a wide rectangle that overlaps its neighbours'.
147
+ * Ringing the circle itself puts the indicator on the thing the reader is
148
+ * actually on. `outline` on an SVG child is honoured by every current engine;
149
+ * the stroke change is what carries it where it is not, so the indicator can
150
+ * never be absent (WCAG 2.4.7).
151
+ */
152
+ .graph-node:focus-visible {
153
+ outline: none;
154
+ }
155
+
156
+ .graph-node:focus-visible .graph-dot {
157
+ stroke: var(--color-focus);
158
+ stroke-width: 4;
159
+ }
160
+
161
+ .graph-node:focus-visible .graph-label,
162
+ .graph-node:hover .graph-label {
163
+ fill: var(--color-link);
164
+ text-decoration: underline;
165
+ }
166
+
167
+ .graph-node:hover .graph-dot {
168
+ fill: var(--color-wash);
169
+ stroke: var(--color-link);
170
+ }
171
+
172
+ /* The figcaption carries the derivation — how the layout was built, which a
173
+ reader cannot see by looking at it. */
174
+ .graph figcaption {
175
+ max-width: var(--measure);
176
+ margin-top: var(--space-2);
177
+ color: var(--color-muted);
178
+ font-size: var(--text-sm);
179
+ }
180
+
181
+ /*
182
+ * The equivalent table, in a native disclosure.
183
+ *
184
+ * `<details>` rather than an always-open table: the same data twice in a row is
185
+ * a long page, and the native element is keyboard-operable, announced as one
186
+ * control, and costs no script. No `interpolate-size` transition here — the
187
+ * explorer's collapse animates because it is navigation a reader opens
188
+ * repeatedly; this one is opened once, and an animation would be motion with no
189
+ * purpose to justify it.
190
+ */
191
+ .graph-table {
192
+ margin-top: var(--space-6);
193
+ }
194
+
195
+ .graph-table summary {
196
+ padding: var(--space-2) 0;
197
+ color: var(--color-link);
198
+ cursor: pointer;
199
+ }
200
+
201
+ /*
202
+ * The table's own scroll container.
203
+ *
204
+ * Four columns do not fit 320 px — the narrowest supported viewport — and the
205
+ * article's Markdown tables have the same problem with no fix, because a
206
+ * wrapper is the pipeline's to emit and `display: block` on the `<table>`
207
+ * itself would strip its semantics (TK-02's deferral, still recorded in
208
+ * `global.css`). This table is rendered by a component, so the wrapper is
209
+ * simply written.
210
+ *
211
+ * Its `tabindex="0"` is unconditional even though the container only scrolls at
212
+ * narrow widths — measured: 350 px of content in 288 px at 320 px, and no
213
+ * overflow at 768 or 1280. That is the same shape `<pre>` and `.diagram-canvas`
214
+ * already have, and for the same reason: whether a region scrolls depends on
215
+ * the viewport and on the content, so the alternative is a keyboard stop that
216
+ * appears and disappears as a reader resizes. This is not the dead stop the
217
+ * figure's own `min-width` fixed — that one could *never* scroll at any width,
218
+ * which is a different fault.
219
+ */
220
+ .graph-table-scroll {
221
+ overflow-x: auto;
222
+ }
223
+
224
+ .graph-table table {
225
+ width: 100%;
226
+ margin-top: var(--space-2);
227
+ border-collapse: collapse;
228
+ font-size: var(--text-sm);
229
+ }
230
+
231
+ .graph-table th,
232
+ .graph-table td {
233
+ padding: var(--space-2);
234
+ border-bottom: 1px solid var(--color-line-strong);
235
+ text-align: left;
236
+ /* A title is the one cell that can be long, and a long one would otherwise
237
+ set the column's width from its longest unbroken word. Wrapping keeps the
238
+ table close to its container; the scroll wrapper above is what handles the
239
+ rest, since four columns do not fit 320 px however they wrap. */
240
+ overflow-wrap: break-word;
241
+ }
242
+
243
+ .graph-table thead th {
244
+ color: var(--color-muted);
245
+ font-weight: 650;
246
+ }
247
+
248
+ .graph-table tbody th {
249
+ font-weight: 400;
250
+ }
251
+
252
+ /* The degree column, which is the one cell holding a bare number. */
253
+ .graph-table td:nth-child(3) {
254
+ text-align: right;
255
+ font-variant-numeric: tabular-nums;
256
+ }
257
+
258
+ /* The notes at the other end of a row's lines: a list, not a sentence, so a
259
+ screen reader announces how many there are before reading them. */
260
+ .graph-joined {
261
+ margin: 0;
262
+ padding: 0;
263
+ list-style: none;
264
+ }
265
+
266
+ .graph-none {
267
+ color: var(--color-muted);
268
+ }
269
+
270
+ .graph-bound {
271
+ max-width: var(--measure);
272
+ margin-top: var(--space-4);
273
+ color: var(--color-muted);
274
+ font-size: var(--text-sm);
275
+ }
276
+
277
+ @media print {
278
+ /* A scroll container prints as its visible window, cutting the figure off at
279
+ the page edge. Letting it size itself prints the whole graph. */
280
+ .graph-canvas {
281
+ overflow-x: visible;
282
+ }
283
+
284
+ /*
285
+ * The table is the graph's equivalent representation (requirements section
286
+ * 17), so a printed page has to carry it — and a closed `<details>` prints
287
+ * closed, which drops it from paper entirely.
288
+ *
289
+ * `content-visibility: visible` on `::details-content` is what opens it:
290
+ * `details[open]` cannot be set from CSS, and Chromium hides a closed
291
+ * disclosure's content with `content-visibility: hidden` on that
292
+ * pseudo-element rather than with `display`. This repository already measured
293
+ * that once — `tests/rendered-page.test.ts` records it for the explorer rail's
294
+ * collapse — and two earlier versions of this rule ignored it: one set only
295
+ * `list-style: none`, the other overrode `display` on a `<div>` that was
296
+ * already block. Both left the table off the printed page while claiming in a
297
+ * comment to have fixed it. Verified by `checkVisibility()` on a body cell
298
+ * under `media: print`, not by reading a bounding box, which a hidden element
299
+ * still reports.
300
+ *
301
+ * The marker goes because a disclosure triangle on paper points at an
302
+ * interaction nobody can perform.
303
+ */
304
+ .graph-table > summary {
305
+ list-style: none;
306
+ }
307
+
308
+ .graph-table::details-content {
309
+ content-visibility: visible;
310
+ }
311
+
312
+ .graph-table-scroll {
313
+ /* A scroll container prints as its visible window, cutting the right-hand
314
+ columns off at the page edge. */
315
+ overflow-x: visible;
316
+ }
317
+ }
@@ -0,0 +1,376 @@
1
+ /*
2
+ * Math.
3
+ *
4
+ * Loaded only on pages whose body contains an expression, via the conditional
5
+ * `<link>` in `src/pages/notes/[slug].astro` gated on `RenderedNote.hasMath` —
6
+ * owner decision 7. A page with no math pays nothing, which is asserted by
7
+ * `tests/math-and-diagrams.test.ts` in both directions.
8
+ *
9
+ * Temml's own stylesheet is vendored below rather than imported from
10
+ * `node_modules`, for two reasons that are properties of this project rather
11
+ * than preferences. It must be **same-origin** — requirements §19.3 sets
12
+ * `style-src 'self'` and `font-src 'self'`, so the upstream advice to load it
13
+ * from a CDN is not available. And it must be **edited**: upstream declares
14
+ * `src: url('Temml.woff2')`, a relative reference that resolves against
15
+ * whatever path the sheet is served from, which is not where Astro puts the
16
+ * font. The `@font-face` below points at `/fonts/Temml.woff2`, copied verbatim
17
+ * from the package by `public/fonts/`.
18
+ *
19
+ * Sections marked "Temml 0.13.4" are upstream, trimmed to the rules this
20
+ * projection can reach: the Firefox and WebKit correction blocks are kept
21
+ * whole, because they are what makes an accent sit in the right place in those
22
+ * browsers, and dropping them would ship subtly wrong typesetting to half the
23
+ * readers. What is dropped is the `\cancelto` mask image — a `data:image/svg+xml`
24
+ * URL that the privacy residue scan rejects as a non-image `data:` URL, and
25
+ * whose command (`\cancelto`) reaches nothing in this corpus.
26
+ */
27
+
28
+ @font-face {
29
+ font-family: 'Temml';
30
+ src: url('/fonts/Temml.woff2') format('woff2');
31
+ font-weight: normal;
32
+ font-style: normal;
33
+ /* The font supplies exactly the script capitals in U+1D49C–U+1D4B5. Naming
34
+ the range means a browser fetches it only for an expression that uses
35
+ `\mathscr`, so most math pages never request the 9.4 KB at all. */
36
+ unicode-range: U+1D49C-1D4B5;
37
+ font-display: swap;
38
+ }
39
+
40
+ math {
41
+ font-family: 'Cambria Math', 'STIXTwoMath-Regular', 'NotoSansMath-Regular', math;
42
+ font-style: normal;
43
+ font-weight: normal;
44
+ line-height: normal;
45
+ font-size-adjust: none;
46
+ text-indent: 0;
47
+ text-transform: none;
48
+ letter-spacing: normal;
49
+ word-wrap: normal;
50
+ direction: ltr;
51
+ /* Prevent Firefox from omitting the dot on i or j. */
52
+ font-feature-settings: 'dtls' off;
53
+ }
54
+
55
+ math * {
56
+ border-color: currentColor;
57
+ }
58
+
59
+ /* `display: block` is needed in Firefox and Safari; Chromium honours the
60
+ `display: block math` that Temml writes inline — which the sanitizer strips,
61
+ so this rule is what makes display math a block in every browser. */
62
+ math.tml-display {
63
+ display: block;
64
+ width: 100%;
65
+ }
66
+
67
+ *.mathcal {
68
+ font-feature-settings: 'ss01';
69
+ }
70
+
71
+ math .mathscr {
72
+ font-family: 'Temml';
73
+ }
74
+
75
+ mo.tml-prime {
76
+ font-family: 'Temml';
77
+ }
78
+
79
+ /* Cramped superscripts in WebKit */
80
+ mfrac > :nth-child(2),
81
+ msqrt,
82
+ mover > :first-child {
83
+ math-shift: compact;
84
+ }
85
+
86
+ .menclose {
87
+ display: inline-block;
88
+ position: relative;
89
+ padding: 0.5ex 0;
90
+ }
91
+
92
+ @supports (-moz-appearance: none) {
93
+ /* \vec without italic correction for Firefox */
94
+ .tml-vec {
95
+ transform: scale(0.75);
96
+ }
97
+ .ff-narrow {
98
+ width: 0;
99
+ }
100
+ .ff-nudge-left {
101
+ margin-left: -0.2em;
102
+ }
103
+ /* Squash hidden mrows in \bordermatrix. */
104
+ .ff-squash mtd {
105
+ display: block;
106
+ height: 0;
107
+ }
108
+ }
109
+
110
+ @supports (not (-moz-appearance: none)) {
111
+ /* Chromium and WebKit */
112
+ mo.tml-prime {
113
+ font-family: 'Temml';
114
+ }
115
+ .tml-sml-pad {
116
+ padding-left: 0.05em;
117
+ }
118
+ .tml-med-pad {
119
+ padding-left: 0.1em;
120
+ }
121
+ .tml-lrg-pad {
122
+ padding-left: 0.15em;
123
+ }
124
+ }
125
+
126
+ @supports (-webkit-backdrop-filter: blur(1px)) {
127
+ /* WebKit vertical and italic correction on accents */
128
+ .wbk-acc { transform: translate(0, 0.431em); }
129
+ .wbk-sml { transform: translate(0.07em, 0); }
130
+ .wbk-sml-acc { transform: translate(0.07em, 0.431em); }
131
+ .wbk-sml-vec { transform: scale(0.75) translate(0.07em, 0); }
132
+ .wbk-med { transform: translate(0.14em, 0); }
133
+ .wbk-med-acc { transform: translate(0.14em, 0.431em); }
134
+ .wbk-med-vec { transform: scale(0.75) translate(0.14em, 0); }
135
+ .wbk-lrg { transform: translate(0.21em, 0); }
136
+ .wbk-lrg-acc { transform: translate(0.21em, 0.431em); }
137
+ .wbk-lrg-vec { transform: scale(0.75) translate(0.21em, 0); }
138
+ }
139
+
140
+ /* \cancel and \phase paint with a background; get them to print. */
141
+ menclose {
142
+ -webkit-print-color-adjust: exact;
143
+ print-color-adjust: exact;
144
+ }
145
+
146
+ /* Array cell justification in Firefox and WebKit */
147
+ .tml-right { text-align: right; }
148
+ .tml-left { text-align: left; }
149
+
150
+ /* CD labels that grow leftward in Firefox and WebKit */
151
+ .tml-shift-left { margin-left: -200%; }
152
+
153
+ /* Chromium only */
154
+ @supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
155
+ .chr-sml { transform: translate(0.07em, 0); }
156
+ .chr-sml-vec { transform: scale(0.75) translate(0.07em, 0); }
157
+ .chr-med { transform: translate(0.14em, 0); }
158
+ .chr-med-vec { transform: scale(0.75) translate(0.14em, 0); }
159
+ .chr-lrg { transform: translate(0.21em, 0); }
160
+ .chr-lrg-vec { transform: scale(0.75) translate(0.21em, 0); }
161
+
162
+ .tml-shift-left { margin-left: -100%; }
163
+
164
+ /* MathML Core and Chromium do not support the MathML 3 <menclose>
165
+ attributes, so these reproduce them. */
166
+ menclose {
167
+ position: relative;
168
+ padding: 0.5ex 0;
169
+ }
170
+ .tml-overline {
171
+ padding: 0.1em 0 0 0;
172
+ border-top: 0.065em solid;
173
+ }
174
+ .tml-underline {
175
+ padding: 0 0 0.1em 0;
176
+ border-bottom: 0.065em solid;
177
+ }
178
+ .tml-cancel {
179
+ display: inline-block;
180
+ position: absolute;
181
+ left: 0.5px;
182
+ bottom: 0;
183
+ width: 100%;
184
+ height: 100%;
185
+ background-color: currentColor;
186
+ }
187
+ .upstrike {
188
+ clip-path: polygon(0.05em 100%, 0 calc(100% - 0.05em), calc(100% - 0.05em) 0, 100% 0.05em);
189
+ }
190
+ .downstrike {
191
+ clip-path: polygon(0 0.05em, 0.05em 0, 100% calc(100% - 0.05em), calc(100% - 0.05em) 100%);
192
+ }
193
+ .sout {
194
+ clip-path: polygon(0 calc(55% + 0.0333em), 0 calc(55% - 0.0333em), 100% calc(55% - 0.0333em), 100% calc(55% + 0.0333em));
195
+ }
196
+ .tml-xcancel {
197
+ clip-path: polygon(0.05em 0, 0 0.05em, calc(50% - 0.05em) 50%, 0 calc(100% - 0.05em), 0.05em 100%, 50% calc(50% + 0.05em), calc(100% - 0.05em) 100%, 100% calc(100% - 0.05em), calc(50% + 0.05em) 50%, 100% 0.05em, calc(100% - 0.05em) 0, 50% calc(50% - 0.05em));
198
+ }
199
+ .longdiv-top {
200
+ border-top: 0.067em solid;
201
+ padding: 0.1em 0.2em 0.2em 0.433em;
202
+ }
203
+ .longdiv-arc {
204
+ position: absolute;
205
+ top: 0;
206
+ bottom: 0.1em;
207
+ left: -0.4em;
208
+ width: 0.7em;
209
+ border: 0.067em solid;
210
+ transform: translateY(-0.067em);
211
+ border-radius: 70%;
212
+ clip-path: inset(0 0 0 0.4em);
213
+ box-sizing: border-box;
214
+ }
215
+ .menclose {
216
+ display: inline-block;
217
+ text-align: left;
218
+ position: relative;
219
+ }
220
+ .phasor-bottom {
221
+ border-bottom: 0.067em solid;
222
+ padding: 0.2em 0.2em 0.1em 0.6em;
223
+ }
224
+ .phasor-angle {
225
+ display: inline-block;
226
+ position: absolute;
227
+ left: 0.5px;
228
+ bottom: -0.04em;
229
+ height: 100%;
230
+ aspect-ratio: 0.5;
231
+ background-color: currentColor;
232
+ clip-path: polygon(0.05em 100%, 0 calc(100% - 0.05em), calc(100% - 0.05em) 0, 100% 0.05em);
233
+ }
234
+ .tml-fbox {
235
+ padding: 3pt;
236
+ border: 1px solid;
237
+ }
238
+ .circle-pad { padding: 0.267em; }
239
+ .textcircle {
240
+ position: absolute;
241
+ inset: 0;
242
+ border: 0.067em solid;
243
+ border-radius: 50%;
244
+ }
245
+ .actuarial {
246
+ padding: 0.03889em 0.03889em 0 0.03889em;
247
+ border-width: 0.08em 0.08em 0 0;
248
+ border-style: solid;
249
+ margin-right: 0.03889em;
250
+ }
251
+ /* Stretch \widetilde */
252
+ .tml-tilde-2 { transform: scale(2, 1.1); }
253
+ .tml-tilde-3 { transform: scale(3, 1.1); }
254
+ .tml-tilde-4 { transform: scale(4, 1.1); }
255
+ /* Stretch \widehat */
256
+ .tml-hat-1 { transform: scale(1.9, 1); }
257
+ .tml-hat-2 { transform: scale(3.9, 1); }
258
+ .tml-hat-3 { transform: scale(5.8, 1); }
259
+ .tml-hat-4 { transform: scale(7.8, 1); }
260
+
261
+ .tml-right { text-align: -webkit-right; }
262
+ .tml-left { text-align: -webkit-left; }
263
+ }
264
+
265
+ .special-fraction {
266
+ font-family: 'STIX TWO', 'Times New Roman', Times, Tinos, serif;
267
+ }
268
+
269
+ /* Line-breaking in Chromium */
270
+ math {
271
+ display: inline-flex;
272
+ flex-wrap: wrap;
273
+ align-items: baseline;
274
+ }
275
+
276
+ math > mrow {
277
+ padding: 0.5ex 0;
278
+ }
279
+
280
+ /* Default mtd top padding is 0.5ex per MathML Core; adjust for jot and small. */
281
+ mtable.tml-jot mtd {
282
+ padding-top: 0.7ex;
283
+ padding-bottom: 0.7ex;
284
+ }
285
+
286
+ mtable.tml-small mtd {
287
+ padding-top: 0.35ex;
288
+ padding-bottom: 0.35ex;
289
+ }
290
+
291
+ @-moz-document url-prefix() {
292
+ /* Firefox: avoid flex-wrap and adjust array row spacing. */
293
+ math { display: inline; }
294
+ math > mrow { padding: 0; }
295
+ mtd,
296
+ mtable.tml-small mtd { padding-top: 0; padding-bottom: 0; }
297
+ mtable.tml-jot mtd { padding-top: 0.2ex; padding-bottom: 0; }
298
+ }
299
+
300
+ /* AMS environment auto-numbering. The counter is reset on the article rather
301
+ than on `body`, as upstream does: the article is the numbering scope a reader
302
+ expects, and resetting on `body` would number across the page chrome. */
303
+ .prose {
304
+ counter-reset: tmlEqnNo;
305
+ }
306
+
307
+ .tml-eqn::before {
308
+ counter-increment: tmlEqnNo;
309
+ content: '(' counter(tmlEqnNo) ')';
310
+ }
311
+
312
+ /*
313
+ * This projection's own rules.
314
+ *
315
+ * Six classes reproducing the inline declarations that measurably change
316
+ * layout. `src/lib/math.ts` documents which they are, how they were chosen —
317
+ * by dropping each property group in a real browser and re-measuring — and why
318
+ * the other 33 declarations Temml emits need no rule at all.
319
+ */
320
+
321
+ .math-boxed {
322
+ border: 1px solid currentColor;
323
+ }
324
+
325
+ .math-boxed-pad {
326
+ padding: 3pt;
327
+ }
328
+
329
+ .math-cell-rule-right {
330
+ border-right: 0.06em solid currentColor;
331
+ }
332
+
333
+ .math-cell-rule-bottom {
334
+ border-bottom: 0.06em solid currentColor;
335
+ }
336
+
337
+ .math-cell-tight {
338
+ padding: 0;
339
+ }
340
+
341
+ .math-cell-tight-top {
342
+ padding-top: 0;
343
+ }
344
+
345
+ .math-cell-tight-bottom {
346
+ padding-bottom: 0;
347
+ }
348
+
349
+ /*
350
+ * Placement in the article.
351
+ *
352
+ * Display math is a block that can be wider than the measure — a long
353
+ * derivation does not wrap — so it scrolls horizontally rather than pushing the
354
+ * page wide, and the scroll container is focusable so a keyboard reader can
355
+ * reach it (axe `scrollable-region-focusable`, WCAG 2.1.1).
356
+ */
357
+ .math-display {
358
+ display: block;
359
+ margin-block: var(--space-6);
360
+ overflow-x: auto;
361
+ overflow-y: hidden;
362
+ /* Room for the focus ring, which would otherwise be clipped by the scroll
363
+ container's own edge. */
364
+ padding: var(--space-1);
365
+ }
366
+
367
+ .math-display:focus-visible {
368
+ outline: 2px solid var(--color-focus);
369
+ outline-offset: 2px;
370
+ }
371
+
372
+ .math-inline {
373
+ /* Keeps an inline expression from setting the line height of its paragraph. */
374
+ display: inline-block;
375
+ vertical-align: baseline;
376
+ }