rapier-markdown-kit 1.1.78 → 1.1.79

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.
@@ -24,19 +24,42 @@ const RAPIER_SANITIZE_OPTIONS = Object.freeze({
24
24
  }),
25
25
  });
26
26
 
27
- // Snapshot current math text before a Markdown writer collapses whitespace. The parsed copy
28
- // stays inert; the writer still admits raw source through its shared math grammar.
27
+ const DIAGRAM_LABEL_HTML = new Set('div span p br strong em b i s u del code sub sup'.split(' '));
28
+ const DIAGRAM_LABEL_MATH = new Set(('math mrow mi mn mo mtext mspace ms msub msup msubsup mfrac msqrt mroot mstyle merror '
29
+ + 'mpadded mphantom mfenced menclose munder mover munderover mtable mtr mtd mlabeledtr mmultiscripts mprescripts none semantics').split(' '));
30
+ const DIAGRAM_LABEL_MATH_ATTRIBUTES = new Set(('display mathvariant mathsize mathcolor mathbackground dir accent accentunder '
31
+ + 'columnalign columnlines columnspacing columnspan columnwidth depth displaystyle equalcolumns equalrows fence frame framespacing '
32
+ + 'height largeop linebreak linethickness lspace maxsize minsize movablelimits notation rowalign rowlines rowspacing rowspan rspace '
33
+ + 'scriptlevel scriptminsize scriptsizemultiplier separator stretchy subscriptshift superscriptshift valign voffset width').split(' '));
34
+ const DIAGRAM_LABEL_CLASSES = new Set('nodeLabel edgeLabel labelBkg markdown-node-label katex messageText'.split(' '));
35
+ const DIAGRAM_LABEL_CSS = new Set(('color fill stroke background-color font-family font-size font-style font-weight font-variant '
36
+ + 'font-variant-ligatures font-feature-settings line-height letter-spacing word-spacing text-align vertical-align white-space '
37
+ + 'word-break overflow-wrap text-wrap text-transform text-decoration text-decoration-line text-decoration-style text-decoration-color '
38
+ + 'text-decoration-thickness text-underline-offset align-items align-content justify-content justify-items flex-direction flex-wrap '
39
+ + 'width height min-width min-height max-width max-height margin margin-top margin-right margin-bottom margin-left '
40
+ + 'padding padding-top padding-right padding-bottom padding-left').split(' '));
41
+ const DIAGRAM_LABEL_SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
42
+ const DIAGRAM_LABEL_HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
43
+ const DIAGRAM_LABEL_MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
44
+
45
+ // Snapshot current math text before a Markdown writer collapses whitespace. Rendered SVG
46
+ // glyphs have no textContent: put their retained source in this inert copy so the writer's
47
+ // blank-node rule cannot discard an equation or its containing paragraph/list item.
29
48
  function prepareMathSource(input, DOMParser) {
30
49
  const html = typeof input === 'string';
31
- const MARK = 'span[data-rapier-math-source]';
32
- if (html ? !/data-rapier-math-source/i.test(input) : typeof input?.cloneNode !== 'function' ||
50
+ const MARK = 'span[data-rapier-math-source],span.math-rendered[data-math-src]';
51
+ if (html ? !/data-(?:rapier-math-source|math-src)/i.test(input) : typeof input?.cloneNode !== 'function' ||
33
52
  !(input.matches?.(MARK) || input.querySelector?.(MARK))) return input;
34
53
  const root = html ? new DOMParser().parseFromString(
35
54
  '<x-turndown id="turndown-root">' + input + '</x-turndown>', 'text/html').getElementById('turndown-root') : input.cloneNode(true);
36
55
  const nodes = Array.from(root.querySelectorAll(MARK));
37
- const sourceRoot = root.nodeName === 'SPAN' && root.hasAttribute('data-rapier-math-source');
56
+ const sourceRoot = root.nodeName === 'SPAN' && root.matches(MARK);
38
57
  if (sourceRoot) nodes.push(root);
39
58
  for (const node of nodes) {
59
+ if (node.classList.contains('math-rendered') && node.hasAttribute('data-math-src')) {
60
+ try { node.textContent = decodeURIComponent(node.getAttribute('data-math-src')); } catch (_) {}
61
+ continue;
62
+ }
40
63
  try { node.setAttribute('data-rapier-math-source', encodeURIComponent(node.textContent || '')); }
41
64
  catch (_) { node.removeAttribute('data-rapier-math-source'); }
42
65
  }
@@ -47,6 +70,89 @@ function prepareMathSource(input, DOMParser) {
47
70
  function createRenderSanitizer(runtime) {
48
71
  const {CSSStyleSheet, DOMPurify, RAPIER_RASTER_DATA_URL_RE, URL, _rapierCssDeclaration, _rapierDropRemoteDeclarations, _rapierRemoteContent, _rapierRuleDescriptorIsRemote, _rapierSanitizeRuntime, _rapierVerifyRasterBytes, document, globalThis, location} = runtime;
49
72
 
73
+ // Only the diagram reader and its styled export admit static foreignObject labels. The
74
+ // ordinary SVG reader still rejects HTML subdocuments. The export class selects scope;
75
+ // every descendant is checked again, so a copied class never confers authority.
76
+ function diagramLabelRoot(node) {
77
+ for (let current = node; current?.nodeType === 1; current = current.parentElement) {
78
+ if (current.localName?.toLowerCase() === 'foreignobject') return current;
79
+ }
80
+ return null;
81
+ }
82
+
83
+ function diagramLabelStyle(property, value) {
84
+ property = String(property).toLowerCase();
85
+ value = String(value).trim();
86
+ if (property === 'display') return /^(?:none|block|inline|inline-block|table|table-cell|flex|inline-flex)$/.test(value);
87
+ if (/^overflow(?:-[xy])?$/.test(property)) return /^(?:hidden|clip)$/.test(value);
88
+ if (property === 'contain') return value === 'content';
89
+ if (property === 'isolation') return value === 'isolate';
90
+ if (!DIAGRAM_LABEL_CSS.has(property)) return false;
91
+ const declaration = document.createElement('span').style;
92
+ declaration.setProperty(property, value);
93
+ const parsed = declaration.getPropertyValue(property);
94
+ if (!parsed || /(?:url|image-set|element|paint|attr)\s*\(/i.test(parsed)) return false;
95
+ // SVG paint accepts resource references; a custom property must not smuggle one in.
96
+ return !/^(?:fill|stroke)$/.test(property) || !/var\s*\(/i.test(parsed);
97
+ }
98
+
99
+ function diagramLabelElement(node) {
100
+ if (node.nodeType !== 1) return;
101
+ const label = diagramLabelRoot(node);
102
+ if (!label) return;
103
+ if (node === label) {
104
+ const svg = node.parentElement?.closest('svg');
105
+ if (node.namespaceURI !== DIAGRAM_LABEL_SVG_NAMESPACE || !svg || diagramLabelRoot(node.parentElement) ||
106
+ (_rapierSanitizeRuntime.context !== 'diagram' && !svg.classList.contains('rapier-diagram'))) node.remove();
107
+ return;
108
+ }
109
+ const name = node.localName?.toLowerCase();
110
+ if (!(node.namespaceURI === DIAGRAM_LABEL_HTML_NAMESPACE && DIAGRAM_LABEL_HTML.has(name)) &&
111
+ !(node.namespaceURI === DIAGRAM_LABEL_MATH_NAMESPACE && DIAGRAM_LABEL_MATH.has(name))) node.remove();
112
+ }
113
+
114
+ function diagramLabelAttribute(node, data) {
115
+ const label = diagramLabelRoot(node);
116
+ if (!label) return;
117
+ data.forceKeepAttr = false;
118
+ const name = String(data.attrName).toLowerCase();
119
+ const value = String(data.attrValue);
120
+ if (name === 'style') {
121
+ const declaration = document.createElement('span').style;
122
+ declaration.cssText = value;
123
+ for (const property of Array.from(declaration)) {
124
+ if (!diagramLabelStyle(property, declaration.getPropertyValue(property))) declaration.removeProperty(property);
125
+ }
126
+ data.attrValue = declaration.cssText;
127
+ data.keepAttr = !!data.attrValue;
128
+ return;
129
+ }
130
+ if (name === 'class') {
131
+ data.attrValue = value.split(/\s+/).filter(token => DIAGRAM_LABEL_CLASSES.has(token)).join(' ');
132
+ data.keepAttr = !!data.attrValue;
133
+ return;
134
+ }
135
+ if (name === 'xmlns') {
136
+ data.keepAttr = value === node.namespaceURI;
137
+ return;
138
+ }
139
+ if (node === label) {
140
+ data.keepAttr = name === 'transform' || /^(?:x|y|width|height)$/.test(name) &&
141
+ /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[-+]?\d+)?(?:px|%)?$/i.test(value) && Number.isFinite(parseFloat(value)) &&
142
+ (!/^(?:width|height)$/.test(name) || parseFloat(value) >= 0);
143
+ return;
144
+ }
145
+ data.keepAttr = node.namespaceURI === DIAGRAM_LABEL_MATH_NAMESPACE
146
+ ? DIAGRAM_LABEL_MATH_ATTRIBUTES.has(name)
147
+ : name === 'dir' && /^(?:ltr|rtl|auto)$/.test(value);
148
+ }
149
+
150
+ function diagramLabelContained(node) {
151
+ const label = diagramLabelRoot(node);
152
+ if (!label) return;
153
+ if (node === label) node.style.setProperty('overflow', 'hidden', 'important');
154
+ else if (node.parentElement === label) node.style.setProperty('contain', 'content', 'important');
155
+ }
50
156
 
51
157
  function _rapierInstallSanitizeHooks() {
52
158
  DOMPurify.addHook('uponSanitizeAttribute', (node, data) => {
@@ -148,11 +254,24 @@ function sanitizeRapierHtml(value, context = 'render') {
148
254
  // (the hook) without an id the chrome owns. 'source' is Markdown source HTML, written and never shown: the render
149
255
  // profile's admission, and the block on remote content stays the reader's (a remote picture's URL is the person's words).
150
256
  const selected = context === 'raw' || context === 'export' || context === 'source' || RAPIER_SANITIZE_OPTIONS[context] ? context : 'render';
151
- const options = selected === 'raw' ? { ...RAPIER_SANITIZE_OPTIONS.render, ALLOW_DATA_ATTR: false } : RAPIER_SANITIZE_OPTIONS[selected] || RAPIER_SANITIZE_OPTIONS.render;
257
+ let options = selected === 'raw' ? { ...RAPIER_SANITIZE_OPTIONS.render, ALLOW_DATA_ATTR: false } : RAPIER_SANITIZE_OPTIONS[selected] || RAPIER_SANITIZE_OPTIONS.render;
258
+ const labels = selected === 'diagram' || selected === 'export';
259
+ if (labels) {
260
+ options = {...options, USE_PROFILES: {...options.USE_PROFILES, mathMl: true}, ADD_TAGS: ['foreignobject'],
261
+ HTML_INTEGRATION_POINTS: {foreignobject: true}, FORBID_TAGS: options.FORBID_TAGS.filter(tag => tag !== 'foreignobject')};
262
+ DOMPurify.addHook('uponSanitizeElement', diagramLabelElement);
263
+ DOMPurify.addHook('uponSanitizeAttribute', diagramLabelAttribute);
264
+ DOMPurify.addHook('afterSanitizeAttributes', diagramLabelContained);
265
+ }
152
266
  _rapierSanitizeRuntime.context = selected;
153
267
  try {
154
268
  return DOMPurify.sanitize(value == null ? '' : String(value), options);
155
269
  } finally {
270
+ if (labels) {
271
+ DOMPurify.removeHook('uponSanitizeElement', diagramLabelElement);
272
+ DOMPurify.removeHook('uponSanitizeAttribute', diagramLabelAttribute);
273
+ DOMPurify.removeHook('afterSanitizeAttributes', diagramLabelContained);
274
+ }
156
275
  _rapierSanitizeRuntime.context = 'render';
157
276
  }
158
277
  }
@@ -237,6 +356,6 @@ function _rapierDropRemoteRules(rules, owner) {
237
356
  }
238
357
  }
239
358
 
240
- return {_rapierInstallSanitizeHooks, sanitizeRapierHtml, escapeRapierHtmlText, _rapierChromeOwnsId, _rapierSafeRasterDataUrl, _rapierCssPresentationIsRemote, _rapierRemoteSubresourceOrigin, _rapierStyleWithoutRemoteUrls, _rapierStylesheetWithoutRemoteUrls, _rapierDropRemoteRules};
359
+ return {_rapierInstallSanitizeHooks, sanitizeRapierHtml, diagramLabelStyle, escapeRapierHtmlText, _rapierChromeOwnsId, _rapierSafeRasterDataUrl, _rapierCssPresentationIsRemote, _rapierRemoteSubresourceOrigin, _rapierStyleWithoutRemoteUrls, _rapierStylesheetWithoutRemoteUrls, _rapierDropRemoteRules};
241
360
  }
242
361
  export {RAPIER_SANITIZE_FORBID_TAGS as forbidTags, RAPIER_SANITIZE_FORBID_ATTR as forbidAttributes, createRenderSanitizer, RAPIER_SANITIZE_OPTIONS as options, prepareMathSource};
@@ -157,7 +157,7 @@ function _rapierProjectStyledRoot(semanticRoot, options) {
157
157
  });
158
158
 
159
159
  root.querySelectorAll('math[display="block"]').forEach(math => {
160
- if (math.closest('.math-display-wrap')) return;
160
+ if (math.closest('svg') || math.closest('.math-display-wrap')) return;
161
161
  const wrap = document.createElement('span');
162
162
  wrap.className = 'math-display-wrap';
163
163
  math.parentNode.insertBefore(wrap, math);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rapier-markdown-kit",
3
- "version": "1.1.78",
3
+ "version": "1.1.79",
4
4
  "description": "Read, render, write and style Self-contained Markdown, and carry its optional edit ledger: the shared HTML writer, semantic renderer, stylesheet, layout, marks, pictures, Will/1, replay, authorship and offline merge. MIT, no npm dependencies.",
5
5
  "keywords": [
6
6
  "markdown",
package/style.css CHANGED
@@ -159,193 +159,78 @@
159
159
  :where(.md-render) .diagram-block .diagram-cache {
160
160
  max-width: 100%;
161
161
  }
162
- /* ---------------------------------------------------------------------------------------------
163
- What a diagram is drawn with. Mermaid packs its own light theme into a <style> inside every
164
- drawing it makes, scoped to that drawing's own id -- `#rapier-dN .node rect` -- so on dark
165
- paper a diagram arrived as a strip of white cards holding black type, and a state diagram's
166
- transitions were drawn in #000 on #000: a state machine with no visible transitions. Rapier
167
- repaints them from the theme's own tokens instead of configuring a second Mermaid theme
168
- beside it. The theme stays the one owner of colour, and a theme change carries every diagram
169
- already on the page, because nothing has to be drawn again.
170
-
171
- Materialization resolves the sanitized generator rules to inline presentation declarations.
172
- Generator defaults yield to this palette; authored style/classDef fills and strokes carry
173
- a light-dark pair above it, keeping their light colour and the shared dark derivation.
174
- The same class reaches rendered blocks and source previews: the owner
175
- marks each admitted drawing `rapier-diagram`, which remains stable when export namespaces
176
- local SVG IDs and references. */
162
+ /* Mermaid owns its geometry and typography. Only known paint roles are themed here;
163
+ other families keep their generator's matching fill and ink. Authored inline pairs win. */
177
164
  :where(.md-render) svg.rapier-native-flowchart{display:block;margin-inline:auto;height:auto}
178
- :where(.md-render) svg.rapier-diagram{
179
- display:block;margin-inline:auto;height:auto;
180
- font-family:var(--md-font-sans)!important;
181
- font-size:var(--md-text-sm)!important;
182
- fill:var(--md-color-text)!important;
183
- }
184
- :where(.md-render) svg.rapier-diagram text,:where(.md-render) svg.rapier-diagram tspan,:where(.md-render) svg.rapier-diagram .nodeLabel,:where(.md-render) svg.rapier-diagram .messageText,:where(.md-render) svg.rapier-diagram text.actor>tspan,:where(.md-render) svg.rapier-diagram .noteText>tspan,:where(.md-render) svg.rapier-diagram .loopText>tspan,:where(.md-render) svg.rapier-diagram .labelText>tspan{
185
- font-family:var(--md-font-sans)!important;fill:var(--md-color-text)!important;
186
- }
187
- /* Rapier's diagram look, one for a figure an agent lays out in Draw and for the drawing Mermaid makes from the
188
- author's source (Draw writes the same pairs into its SVG; _diagram-cells holds the two copies equal). Swiss
189
- editorial after the mid-century magazines: nearly monochrome, a box or a decision a flat field of one grey with no
190
- outline, the words the page's own type in its ink; the one accent is spent sparingly, on meaning only -- the outcome
191
- (a round node, where a flow ends) under black words. It keeps the corner the source asked for: a stadium, a diamond and
192
- a parallelogram are what the author wrote; the roundings Mermaid adds to a plain box, an actor, a note and a
193
- cluster are not, and Rapier's boxes are square. An author's own style or classDef fill and stroke stay above all
194
- of it (they are materialised inline, and an inline declaration outranks this sheet). */
195
- :where(.md-render) svg.rapier-diagram .node :is(rect,circle,ellipse,polygon,path){
196
- fill:var(--md-diagram-box)!important;stroke:none!important;
197
- }
198
- :where(.md-render) svg.rapier-diagram[aria-roledescription^="flowchart"] .node:has(>circle) :is(circle,path){fill:var(--md-diagram-accent)!important}
199
- :where(.md-render) svg.rapier-diagram[aria-roledescription^="flowchart"] .node:has(>circle) :is(text,tspan){fill:var(--md-diagram-on-accent)!important}
200
- :where(.md-render) svg.rapier-diagram g.classGroup rect,:where(.md-render) svg.rapier-diagram .actor,:where(.md-render) svg.rapier-diagram .labelBox,:where(.md-render) svg.rapier-diagram .activation0,:where(.md-render) svg.rapier-diagram .activation1,:where(.md-render) svg.rapier-diagram .activation2{
201
- fill:var(--md-diagram-node-fill)!important;stroke:var(--md-diagram-node-line)!important;stroke-width:var(--md-diagram-hairline)!important;
202
- }
203
- /* A group (a subgraph, a composite state) is a typographic band, not a frame: its title in the caption's spaced
204
- mono capitals above its members, the paper left open around them. */
205
- :where(.md-render) svg.rapier-diagram :is(.cluster,.statediagram-cluster) rect{fill:none!important;stroke:none!important}
206
- :where(.md-render) svg.rapier-diagram :is(.cluster-label,.cluster .label) :is(text,tspan){
207
- font-family:var(--md-font-mono)!important;font-size:var(--md-diagram-caption-size)!important;text-transform:uppercase;letter-spacing:var(--md-diagram-title-track)!important;
208
- }
209
- :where(.md-render) svg.rapier-diagram .classTitle,:where(.md-render) svg.rapier-diagram text.actor>tspan{font-weight:var(--md-fw-medium)!important}
210
- :where(.md-render) svg.rapier-diagram :is(.nodeLabel,.node text,.node tspan){font-weight:var(--md-fw-semibold)!important}
211
- :where(.md-render) svg.rapier-diagram rect.basic,:where(.md-render) svg.rapier-diagram rect.title-state,:where(.md-render) svg.rapier-diagram rect.outer,:where(.md-render) svg.rapier-diagram .actor,:where(.md-render) svg.rapier-diagram .note,:where(.md-render) svg.rapier-diagram .labelBox,:where(.md-render) svg.rapier-diagram .cluster rect,:where(.md-render) svg.rapier-diagram .statediagram-cluster rect{rx:0!important;ry:0!important}
212
- /* The line between two boxes is mid-ladder and one hairline weight everywhere: it is the road,
213
- not the destination. A lifeline and a divider are neither -- they are a box's own rule down
214
- or across the page -- and drop to the faintest step there is. */
215
- :where(.md-render) svg.rapier-diagram .edgePath .path,:where(.md-render) svg.rapier-diagram .flowchart-link,:where(.md-render) svg.rapier-diagram .relation,:where(.md-render) svg.rapier-diagram .transition,:where(.md-render) svg.rapier-diagram .messageLine0,:where(.md-render) svg.rapier-diagram .messageLine1,:where(.md-render) svg.rapier-diagram .er.relationshipLine,:where(.md-render) svg.rapier-diagram g.stateGroup line{
216
- stroke:var(--md-diagram-line)!important;stroke-width:var(--md-diagram-stroke)!important;fill:none!important;
217
- }
218
- /* `line[id^="actor"]` is the lifeline. It is not `.actor-line`: Mermaid writes the actor's own
219
- WIDTH into that element's class attribute (`class="200"`), so the class it documents matches
220
- nothing, and the lifeline fell through to Mermaid's bare `#rapier-dN line` rule and came out a
221
- 2px near-white rail down the page -- the brightest thing in a sequence diagram, for a line that
222
- only says "this actor is still here". The id is what the element actually carries. */
223
- :where(.md-render) svg.rapier-diagram .actor-line,:where(.md-render) svg.rapier-diagram .loopLine,:where(.md-render) svg.rapier-diagram .divider,:where(.md-render) svg.rapier-diagram g.classGroup line,:where(.md-render) svg.rapier-diagram .statediagram-state .divider{
224
- stroke:var(--md-diagram-inner-line)!important;stroke-width:1px!important;
225
- }
226
- /* One stroke weight for every connector, in the ink, and its head a solid closed triangle of the same ink with no
227
- outline of its own, so its point is the stroke's and not a rounded burr. Mermaid marks some of these `!important`
228
- under the drawing's id, which nothing here could outrank -- but the shape inside a marker declares no fill of its
229
- own, so a declaration on the shape itself wins over anything it would otherwise inherit. What is hollow stays
230
- hollow: a hollow triangle is inheritance and a filled one is not. */
231
- :where(.md-render) svg.rapier-diagram marker path,:where(.md-render) svg.rapier-diagram .marker{
232
- fill:var(--md-diagram-arrow)!important;stroke:none!important;
233
- }
234
- :where(.md-render) svg.rapier-diagram marker path[fill="none"],:where(.md-render) svg.rapier-diagram .marker.extension path,:where(.md-render) svg.rapier-diagram .marker.aggregation path,:where(.md-render) svg.rapier-diagram .marker.lollipop path{
235
- fill:var(--md-color-bg)!important;stroke:var(--md-diagram-arrow)!important;stroke-width:var(--md-diagram-hairline)!important;
236
- }
237
- :where(.md-render) svg.rapier-diagram marker circle{fill:var(--md-color-bg)!important;stroke:var(--md-diagram-arrow)!important}
238
- /* A label on a line sits in a gap it cuts in that line, on the page's own paper -- not in the
239
- translucent grey sticker Mermaid lays over the line and its arrow head. */
240
- :where(.md-render) svg.rapier-diagram .edgeLabel rect,:where(.md-render) svg.rapier-diagram .labelBkg,:where(.md-render) svg.rapier-diagram .er.relationshipLabelBox,:where(.md-render) svg.rapier-diagram .er.relationshipLabelBox rect,:where(.md-render) svg.rapier-diagram .stateLabel .box,:where(.md-render) svg.rapier-diagram .classLabel .box{
241
- fill:var(--md-color-bg)!important;stroke:none!important;opacity:1!important;
242
- }
243
- :where(.md-render) svg.rapier-diagram .edgeLabel text,:where(.md-render) svg.rapier-diagram .edgeLabel tspan,:where(.md-render) svg.rapier-diagram .er.relationshipLabel,:where(.md-render) svg.rapier-diagram .classLabel .label,:where(.md-render) svg.rapier-diagram .edgeTerminals{
244
- fill:var(--md-diagram-quiet)!important;font-size:var(--md-text-xs)!important;
245
- }
246
- /* A connector's caption is set as the magazines set one: small spaced mono capitals in the ink, in the gap it
247
- knocks out of its line. The label room measures it as it is drawn, capitals and tracking included. */
248
- :where(.md-render) svg.rapier-diagram .edgeLabel :is(text,tspan){
249
- fill:var(--md-diagram-ink)!important;font-family:var(--md-font-mono)!important;font-size:var(--md-diagram-caption-size)!important;
250
- text-transform:uppercase;letter-spacing:var(--md-diagram-caption-track)!important;
251
- }
252
- /* A note is an aside and takes the inset the rest of Rapier's asides take. ER reads as a table:
253
- a headed box over rows that alternate by one step of the same surface, ruled between rows by
254
- the faintest line so the rows read as one block rather than as a grid of little boxes. */
255
- :where(.md-render) svg.rapier-diagram .note,:where(.md-render) svg.rapier-diagram .statediagram-note rect{
256
- fill:var(--md-color-inset)!important;stroke:var(--md-diagram-node-line)!important;
257
- }
258
- :where(.md-render) svg.rapier-diagram .er.entityBox{fill:var(--md-color-surface)!important;stroke:var(--md-diagram-node-line)!important}
259
- :where(.md-render) svg.rapier-diagram .er.attributeBoxOdd{fill:var(--md-color-bg)!important;stroke:var(--md-diagram-inner-line)!important}
260
- :where(.md-render) svg.rapier-diagram .er.attributeBoxEven{fill:var(--md-diagram-node-fill)!important;stroke:var(--md-diagram-inner-line)!important}
261
- /* An entity's name and its rows wear the same class in Mermaid's output and are told apart only
262
- by the id it gives each cell (`...-attr-2-name`), so that is what tells them apart here: the
263
- name is type, the cells are data. */
264
- :where(.md-render) svg.rapier-diagram .er.entityLabel[id*="-attr-"]{fill:var(--md-diagram-quiet)!important}
265
- :where(.md-render) svg.rapier-diagram .er.entityLabel:not([id*="-attr-"]){font-weight:var(--md-fw-medium)!important}
266
- /* A state machine starts on a filled dot and ends on a ringed one; both are ink on paper. */
267
- :where(.md-render) svg.rapier-diagram circle.state-start,:where(.md-render) svg.rapier-diagram .node .fork-join,:where(.md-render) svg.rapier-diagram .end-state-inner{fill:var(--md-color-text)!important;stroke:var(--md-color-text)!important}
268
- :where(.md-render) svg.rapier-diagram circle.state-end{fill:var(--md-color-bg)!important;stroke:var(--md-color-text)!important}
269
- /* The kinds that are colour by nature -- a pie's slices, a mindmap's branches, a timeline's periods,
270
- a git graph's branches, a gantt chart's bars -- are drawn in the nine colours of the document
271
- (rapier-notes.css, "The nine note colours"), the mate the theme gives a note card: the pale under
272
- pure black ink on light paper, the deep under pure white ink on dark. Mermaid's own greys are a
273
- light-paper drawing: on dark paper a mindmap and a timeline would become white cards under the
274
- page's white type. The hex is copied here because a written page carries this sheet and not the
275
- Notes sheet; mermaid-sanitised holds the two copies equal, pair for pair. The order keeps
276
- neighbours apart: blue, orange, teal, pink, yellow, red, green, purple, brown. */
277
- :where(.md-render) svg.rapier-diagram{
278
- font-variant-numeric:tabular-nums;
165
+ :where(.md-render) svg.rapier-diagram{display:block;margin-inline:auto;height:auto}
166
+
167
+ /* Recolour connectors without changing widths, dashes, marker contours or hollow interiors. */
168
+ :where(.md-render) svg.rapier-diagram:is([aria-roledescription^="flowchart"],[aria-roledescription="classDiagram"],[aria-roledescription="stateDiagram"],[aria-roledescription="requirement"],[aria-roledescription="er"]) :is(path.flowchart-link,path.relation,path.relationshipLine,path.transition){stroke:var(--md-diagram-line)!important}
169
+ :where(.md-render) svg.rapier-diagram:is([aria-roledescription^="flowchart"],[aria-roledescription="classDiagram"],[aria-roledescription="stateDiagram"],[aria-roledescription="requirement"],[aria-roledescription="er"],[aria-roledescription="sequence"],[aria-roledescription="c4"],[aria-roledescription="journey"]) marker{fill:var(--md-diagram-arrow)!important}
170
+
171
+ /* Sequence surfaces and their labels move together between paper colours. */
172
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="sequence"] :is(rect.actor,rect.activation0,rect.activation1,rect.activation2,polygon.labelBox){fill:var(--md-diagram-node-fill)!important;stroke:var(--md-diagram-node-line)!important}
173
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="sequence"] :is(text.actor,text.labelText,text.loopText,text.messageText,text.sectionTitle),
174
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="sequence"] :is(text.actor,text.labelText,text.loopText,text.messageText,text.sectionTitle) tspan{fill:var(--md-color-text)!important}
175
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="sequence"] :is(text.sequenceNumber,text.sequenceNumber tspan){fill:var(--md-color-bg)!important}
176
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="sequence"] rect.note{fill:var(--md-color-inset)!important;stroke:var(--md-diagram-node-line)!important}
177
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="sequence"] :is(text.noteText,text.noteText tspan){fill:var(--md-color-text)!important}
178
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="sequence"] :is(line.messageLine0,line.messageLine1,path.messageLine0,path.messageLine1){stroke:var(--md-diagram-line)!important}
179
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="sequence"] :is(line.actor-line,line.loopLine){stroke:var(--md-diagram-inner-line)!important}
180
+
181
+ /* A state begins with a dot, ends with a ring, and forks through a bar. */
182
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="stateDiagram"] :is(circle.state-start,rect.fork-join,circle.end-state-inner){fill:var(--md-color-text)!important;stroke:var(--md-color-text)!important}
183
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="stateDiagram"] circle.state-end{fill:var(--md-color-bg)!important;stroke:var(--md-color-text)!important}
184
+ /* Compound-state frames follow the paper; their child states keep their own surfaces and ink. */
185
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="stateDiagram"] g.statediagram-cluster>rect.inner{fill:var(--md-color-bg)!important}
186
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="stateDiagram"] g.statediagram-cluster>g>rect.outer{fill:var(--md-diagram-node-fill)!important}
187
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="stateDiagram"] g.statediagram-cluster>.cluster-label :is(text,tspan){fill:var(--md-color-text)!important}
188
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="stateDiagram"] g.statediagram-cluster>.cluster-label :is(foreignObject,.nodeLabel){color:var(--md-color-text)!important}
189
+
190
+ /* C4 node colours include their own label ink. Outside captions and connections use the page. */
191
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="c4"] text:not(.c4-shape *){fill:var(--md-color-text)!important}
192
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="c4"] :is(line,path)[stroke]:not(.c4-shape *):not(marker *):not(symbol *){stroke:var(--md-diagram-line)!important}
193
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="c4"] rect[fill="none"][stroke]:not(.c4-shape *){stroke:var(--md-diagram-node-line)!important}
194
+
195
+ /* Journey cards pair their surface with both HTML and SVG label branches; faces keep their paints. */
196
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="journey"] rect:is(.journey-section,.task){fill:var(--md-diagram-node-fill)!important}
197
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="journey"] rect:is(.journey-section,.task)+switch :is(text,tspan){fill:var(--md-color-text)!important}
198
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="journey"] rect:is(.journey-section,.task)+switch foreignObject{color:var(--md-color-text)!important}
199
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="journey"]>text,
200
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="journey"] text.legend{fill:var(--md-color-text)!important}
201
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="journey"]>line{stroke:var(--md-diagram-line)!important}
202
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="journey"] line.task-line{stroke:var(--md-diagram-inner-line)!important}
203
+
204
+ /* Gantt paint selectors name their element type: journey also uses the class "task" on text. */
205
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] rect:is(.section0,.section2){fill:var(--md-diagram-node-fill)!important}
206
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] rect:is(.section1,.section3){fill:var(--md-color-bg)!important}
207
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] rect.task{fill:var(--md-diagram-c1)!important;stroke:var(--md-diagram-c1)!important}
208
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] rect:is(.active0,.active1,.active2,.active3){fill:var(--md-diagram-c3)!important;stroke:var(--md-diagram-c3)!important}
209
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] rect:is(.done0,.done1,.done2,.done3){fill:var(--md-diagram-node-line)!important;stroke:var(--md-diagram-node-line)!important}
210
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] rect:is(.crit0,.crit1,.crit2,.crit3,.activeCrit0,.activeCrit1,.activeCrit2,.activeCrit3,.doneCrit0,.doneCrit1,.doneCrit2,.doneCrit3){fill:var(--md-diagram-c6)!important;stroke:var(--md-diagram-c6)!important}
211
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] text.taskText{fill:var(--md-diagram-on-colour)!important}
212
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] text:is(.taskTextOutsideRight,.taskTextOutsideLeft,.sectionTitle,.titleText){fill:var(--md-color-text)!important}
213
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] .grid .tick line{stroke:var(--md-diagram-inner-line)!important}
214
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] .grid .tick text{fill:var(--md-diagram-quiet)!important}
215
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gantt"] line.today{stroke:var(--md-diagram-c6)!important}
216
+
217
+ /* Outside labels never acquire the ink intended for a coloured slice or branch. */
218
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="pie"] text.pieTitleText,
219
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="pie"] g.legend text,
220
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="timeline"]>text{fill:var(--md-color-text)!important}
221
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="timeline"] g.lineWrapper>line{stroke:var(--md-diagram-line)!important}
222
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gitGraph"] rect.commit-label-bkg{fill:var(--md-color-bg)!important}
223
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gitGraph"] text.commit-label{fill:var(--md-diagram-quiet)!important}
224
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gitGraph"] polygon.tag-label-bkg{fill:var(--md-diagram-node-fill)!important;stroke:var(--md-diagram-node-line)!important}
225
+ :where(.md-render) svg.rapier-diagram[aria-roledescription="gitGraph"] text.tag-label{fill:var(--md-color-text)!important}
226
+
227
+ /* Generator styles are removed at admission; these owned keyframes animate only dash offset. */
228
+ @keyframes rapier-mermaid-dash{from{stroke-dashoffset:900}to{stroke-dashoffset:0}}
229
+ :where(.md-render) svg.rapier-diagram[aria-roledescription^="flowchart"] :is(path,line,polyline).edge-animation-fast{animation:rapier-mermaid-dash 20s linear infinite!important}
230
+ :where(.md-render) svg.rapier-diagram[aria-roledescription^="flowchart"] :is(path,line,polyline).edge-animation-slow{animation:rapier-mermaid-dash 50s linear infinite!important}
231
+ @media (prefers-reduced-motion:reduce){
232
+ :where(.md-render) svg.rapier-diagram[aria-roledescription^="flowchart"] :is(path,line,polyline):is(.edge-animation-fast,.edge-animation-slow){animation:none!important;stroke-dashoffset:0!important}
279
233
  }
280
- /* One colour per branch, per section, per slice, in that order; the tenth wraps to the first. Mermaid's
281
- own first colour is `section--1` (a timeline's first period; a mindmap's root, which is ink here, so a
282
- mindmap's branches begin at the second), and a git graph counts its branches from 0. A shape takes the
283
- colour, its words the ink that colour is paired with, its edge the colour itself. */
284
- :where(.md-render) svg.rapier-diagram :is(.section--1,.section-8,.section-edge--1,.section-edge-8,.commit0,.branch0,.label0,.arrow0){--md-diagram-colour:var(--md-diagram-c1)}
285
- :where(.md-render) svg.rapier-diagram :is(.section-0,.section-9,.section-edge-0,.section-edge-9,.commit1,.branch1,.label1,.arrow1){--md-diagram-colour:var(--md-diagram-c2)}
286
- :where(.md-render) svg.rapier-diagram :is(.section-1,.section-10,.section-edge-1,.section-edge-10,.commit2,.branch2,.label2,.arrow2){--md-diagram-colour:var(--md-diagram-c3)}
287
- :where(.md-render) svg.rapier-diagram :is(.section-2,.section-edge-2,.commit3,.branch3,.label3,.arrow3){--md-diagram-colour:var(--md-diagram-c4)}
288
- :where(.md-render) svg.rapier-diagram :is(.section-3,.section-edge-3,.commit4,.branch4,.label4,.arrow4){--md-diagram-colour:var(--md-diagram-c5)}
289
- :where(.md-render) svg.rapier-diagram :is(.section-4,.section-edge-4,.commit5,.branch5,.label5,.arrow5){--md-diagram-colour:var(--md-diagram-c6)}
290
- :where(.md-render) svg.rapier-diagram :is(.section-5,.section-edge-5,.commit6,.branch6,.label6,.arrow6){--md-diagram-colour:var(--md-diagram-c7)}
291
- :where(.md-render) svg.rapier-diagram :is(.section-6,.section-edge-6,.commit7,.branch7,.label7,.arrow7){--md-diagram-colour:var(--md-diagram-c8)}
292
- :where(.md-render) svg.rapier-diagram :is(.section-7,.section-edge-7){--md-diagram-colour:var(--md-diagram-c9)}
293
- :where(.md-render) svg.rapier-diagram .pieCircle:nth-of-type(9n+1),:where(.md-render) svg.rapier-diagram .legend:nth-of-type(9n+1){--md-diagram-colour:var(--md-diagram-c1)}
294
- :where(.md-render) svg.rapier-diagram .pieCircle:nth-of-type(9n+2),:where(.md-render) svg.rapier-diagram .legend:nth-of-type(9n+2){--md-diagram-colour:var(--md-diagram-c2)}
295
- :where(.md-render) svg.rapier-diagram .pieCircle:nth-of-type(9n+3),:where(.md-render) svg.rapier-diagram .legend:nth-of-type(9n+3){--md-diagram-colour:var(--md-diagram-c3)}
296
- :where(.md-render) svg.rapier-diagram .pieCircle:nth-of-type(9n+4),:where(.md-render) svg.rapier-diagram .legend:nth-of-type(9n+4){--md-diagram-colour:var(--md-diagram-c4)}
297
- :where(.md-render) svg.rapier-diagram .pieCircle:nth-of-type(9n+5),:where(.md-render) svg.rapier-diagram .legend:nth-of-type(9n+5){--md-diagram-colour:var(--md-diagram-c5)}
298
- :where(.md-render) svg.rapier-diagram .pieCircle:nth-of-type(9n+6),:where(.md-render) svg.rapier-diagram .legend:nth-of-type(9n+6){--md-diagram-colour:var(--md-diagram-c6)}
299
- :where(.md-render) svg.rapier-diagram .pieCircle:nth-of-type(9n+7),:where(.md-render) svg.rapier-diagram .legend:nth-of-type(9n+7){--md-diagram-colour:var(--md-diagram-c7)}
300
- :where(.md-render) svg.rapier-diagram .pieCircle:nth-of-type(9n+8),:where(.md-render) svg.rapier-diagram .legend:nth-of-type(9n+8){--md-diagram-colour:var(--md-diagram-c8)}
301
- :where(.md-render) svg.rapier-diagram .pieCircle:nth-of-type(9n),:where(.md-render) svg.rapier-diagram .legend:nth-of-type(9n){--md-diagram-colour:var(--md-diagram-c9)}
302
- /* Mindmap and timeline: the node is the colour, its words the colour's ink, the branch to it the
303
- colour. The root is the page's own ink with the paper for its words, the one dark stone in the
304
- middle; a timeline's event keeps no brightening filter (Mermaid lifts it 20%, off the pair). */
305
- :where(.md-render) svg.rapier-diagram :is(.section--1,.section-0,.section-1,.section-2,.section-3,.section-4,.section-5,.section-6,.section-7,.section-8,.section-9,.section-10) :is(rect,path,circle,polygon,ellipse){
306
- fill:var(--md-diagram-colour)!important;stroke:var(--md-diagram-colour)!important;stroke-width:1px!important;
307
- }
308
- :where(.md-render) svg.rapier-diagram :is(.section--1,.section-0,.section-1,.section-2,.section-3,.section-4,.section-5,.section-6,.section-7,.section-8,.section-9,.section-10) :is(text,tspan){fill:var(--md-diagram-on-colour)!important}
309
- :where(.md-render) svg.rapier-diagram :is(.section--1,.section-0,.section-1,.section-2,.section-3,.section-4,.section-5,.section-6,.section-7,.section-8,.section-9,.section-10) line{stroke:var(--md-diagram-colour)!important;stroke-width:1px!important}
310
- :where(.md-render) svg.rapier-diagram :is(.section-edge--1,.section-edge-0,.section-edge-1,.section-edge-2,.section-edge-3,.section-edge-4,.section-edge-5,.section-edge-6,.section-edge-7,.section-edge-8,.section-edge-9,.section-edge-10){stroke:var(--md-diagram-colour)!important}
311
- :where(.md-render) svg.rapier-diagram .section-root :is(rect,path,circle,polygon,ellipse){fill:var(--md-color-text)!important;stroke:var(--md-color-text)!important}
312
- :where(.md-render) svg.rapier-diagram .section-root :is(text,tspan){fill:var(--md-color-bg)!important}
313
- :where(.md-render) svg.rapier-diagram .eventWrapper{filter:none!important}
314
- :where(.md-render) svg.rapier-diagram .lineWrapper line{stroke:var(--md-diagram-line)!important;stroke-width:1px!important}
315
- /* Pie: each slice its colour, cut from the next by a hairline of paper; its share in the colour's
316
- ink; the legend's swatch the same colour. Mermaid draws the slices at 70% over a black rim. */
317
- :where(.md-render) svg.rapier-diagram .pieCircle{fill:var(--md-diagram-colour)!important;stroke:var(--md-color-bg)!important;stroke-width:2px!important;opacity:1!important}
318
- :where(.md-render) svg.rapier-diagram .pieOuterCircle{fill:none!important;stroke:none!important}
319
- :where(.md-render) svg.rapier-diagram .legend rect{fill:var(--md-diagram-colour)!important;stroke:var(--md-diagram-colour)!important}
320
- :where(.md-render) svg.rapier-diagram text.slice{fill:var(--md-diagram-on-colour)!important;font-size:var(--md-text-sm)!important;font-weight:var(--md-fw-medium)!important}
321
- /* A drawing's title is set as the page sets a small heading; Mermaid's timeline writes its title as a bare
322
- <text> at 4ex bold, its pie at 25px and its gantt chart at 18px. */
323
- :where(.md-render) svg.rapier-diagram :is(.pieTitleText,.titleText),:where(.md-render) svg.rapier-diagram[aria-roledescription="timeline"]>text{
324
- fill:var(--md-color-text)!important;font-size:var(--md-text-base)!important;font-weight:var(--md-fw-semibold)!important}
325
- /* Git graph: a branch is one colour -- its line, its commits, its merge arrows, its name's tab. */
326
- :where(.md-render) svg.rapier-diagram :is(.commit0,.commit1,.commit2,.commit3,.commit4,.commit5,.commit6,.commit7){fill:var(--md-diagram-colour)!important;stroke:var(--md-diagram-colour)!important}
327
- :where(.md-render) svg.rapier-diagram :is(.branch0,.branch1,.branch2,.branch3,.branch4,.branch5,.branch6,.branch7,.arrow0,.arrow1,.arrow2,.arrow3,.arrow4,.arrow5,.arrow6,.arrow7){stroke:var(--md-diagram-colour)!important;stroke-width:2px!important}
328
- :where(.md-render) svg.rapier-diagram :is(.label0,.label1,.label2,.label3,.label4,.label5,.label6,.label7){fill:var(--md-diagram-colour)!important;stroke:none!important}
329
- :where(.md-render) svg.rapier-diagram .branchLabel :is(text,tspan){fill:var(--md-diagram-on-colour)!important}
330
- :where(.md-render) svg.rapier-diagram :is(.commit-merge,.commit-reverse,.commit-highlight-inner){fill:var(--md-color-bg)!important}
331
- :where(.md-render) svg.rapier-diagram .commit-label-bkg{fill:var(--md-color-bg)!important;opacity:1!important}
332
- :where(.md-render) svg.rapier-diagram :is(.commit-label,.tag-label){fill:var(--md-diagram-quiet)!important;font-size:var(--md-text-xs)!important}
333
- :where(.md-render) svg.rapier-diagram :is(.tag-label-bkg,.tag-hole){fill:var(--md-diagram-node-fill)!important;stroke:var(--md-diagram-node-line)!important}
334
- /* Gantt: bands of the page's own ladder behind the rows, a plan's bar in the first colour, the one
335
- under way in the third, the critical path in red, the done ones sunk to the quiet step; the grid
336
- the faintest line and its dates the quiet ink, figures tabular so a column of dates lines up. */
337
- :where(.md-render) svg.rapier-diagram :is(.section0,.section2){fill:var(--md-diagram-node-fill)!important;opacity:1!important}
338
- :where(.md-render) svg.rapier-diagram :is(.section1,.section3){fill:var(--md-color-bg)!important;opacity:1!important}
339
- :where(.md-render) svg.rapier-diagram :is(.task0,.task1,.task2,.task3,.task){fill:var(--md-diagram-c1)!important;stroke:var(--md-diagram-c1)!important}
340
- :where(.md-render) svg.rapier-diagram :is(.active0,.active1,.active2,.active3){fill:var(--md-diagram-c3)!important;stroke:var(--md-diagram-c3)!important}
341
- :where(.md-render) svg.rapier-diagram :is(.done0,.done1,.done2,.done3){fill:var(--md-diagram-node-line)!important;stroke:var(--md-diagram-node-line)!important}
342
- :where(.md-render) svg.rapier-diagram :is(.crit0,.crit1,.crit2,.crit3,.activeCrit0,.activeCrit1,.activeCrit2,.activeCrit3,.doneCrit0,.doneCrit1,.doneCrit2,.doneCrit3){fill:var(--md-diagram-c6)!important;stroke:var(--md-diagram-c6)!important}
343
- :where(.md-render) svg.rapier-diagram .taskText{fill:var(--md-diagram-on-colour)!important}
344
- :where(.md-render) svg.rapier-diagram :is(.taskTextOutsideRight,.taskTextOutsideLeft,.sectionTitle){fill:var(--md-color-text)!important}
345
- :where(.md-render) svg.rapier-diagram .grid .tick line{stroke:var(--md-diagram-inner-line)!important;opacity:1!important}
346
- :where(.md-render) svg.rapier-diagram .grid path{stroke:none!important}
347
- :where(.md-render) svg.rapier-diagram .grid .tick text{fill:var(--md-diagram-quiet)!important;font-size:var(--md-text-xs)!important}
348
- :where(.md-render) svg.rapier-diagram .today{stroke:var(--md-diagram-c6)!important}
349
234
  /* Paper cannot be scrolled sideways, so on paper a diagram, and a wide drawing, go back to fitting the page. */
350
235
  @media print{
351
236
  :where(.md-render) .diagram-block{overflow:visible!important}
@@ -603,8 +488,9 @@
603
488
  vertical-align:middle;
604
489
  }
605
490
  .md-render p>.math-display-wrap{margin:calc(var(--md-line) / 4) 0 var(--md-line)}
606
- .md-render math[display="block"]{font-size:1.12em}
607
- .md-render math:not([display="block"]){font-size:1em}
491
+ /* Diagram MathML keeps the metrics used by its renderer. */
492
+ .md-render math[display="block"]:not(svg *){font-size:1.12em}
493
+ .md-render math:not([display="block"]):not(svg *){font-size:1em}
608
494
  .md-render blockquote{margin:0 0 var(--md-line);
609
495
  padding-block:var(--md-space-1);padding-inline-start:var(--md-space-4);padding-inline-end:0;
610
496
  border-inline-start:calc(2 * var(--md-hair)) solid var(--md-color-border-focus);color:var(--md-color-text-secondary)}