@pathmx/core 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/LICENSE.md +172 -0
  2. package/README.md +111 -0
  3. package/actions/actions.ts +307 -0
  4. package/actions/draft.ts +105 -0
  5. package/actions/transaction.ts +164 -0
  6. package/assets.ts +149 -0
  7. package/authority/access.ts +820 -0
  8. package/authority/actors.ts +271 -0
  9. package/authority/agents.ts +95 -0
  10. package/authority/credentials.ts +144 -0
  11. package/authority/model.ts +71 -0
  12. package/authority/sharing.ts +89 -0
  13. package/browser-bundle.ts +61 -0
  14. package/canonical.ts +41 -0
  15. package/cli/dev.ts +134 -0
  16. package/cli/export.ts +74 -0
  17. package/cli/index.ts +52 -0
  18. package/cli/lint.ts +164 -0
  19. package/cli/mv.ts +30 -0
  20. package/cli/perms.ts +182 -0
  21. package/cli/plugin-packages.ts +159 -0
  22. package/cli/plugins.ts +95 -0
  23. package/cli/query.ts +225 -0
  24. package/cli/readme.md +95 -0
  25. package/cli/release.ts +75 -0
  26. package/cli/rm.ts +22 -0
  27. package/cli/serve.ts +100 -0
  28. package/cli/tree.ts +131 -0
  29. package/cli/update.ts +78 -0
  30. package/cli/utils.ts +53 -0
  31. package/core.ts +96 -0
  32. package/database.ts +189 -0
  33. package/dependencies.ts +60 -0
  34. package/dist/pathmx.js +1224 -0
  35. package/document.ts +194 -0
  36. package/environment.ts +110 -0
  37. package/environments/bun-plugins.ts +68 -0
  38. package/environments/bun-publish.ts +194 -0
  39. package/environments/bun.ts +223 -0
  40. package/globals.d.ts +14 -0
  41. package/graph.ts +153 -0
  42. package/host/compiler.ts +314 -0
  43. package/host/create.ts +66 -0
  44. package/host/engine.ts +630 -0
  45. package/host/plugin-host.ts +487 -0
  46. package/host/render.ts +102 -0
  47. package/host/response.ts +20 -0
  48. package/host/shell.html +15 -0
  49. package/host/source-sync.ts +254 -0
  50. package/html-attributes.ts +15 -0
  51. package/html.ts +48 -0
  52. package/icons/LICENSE +43 -0
  53. package/icons/lucide.ts +54 -0
  54. package/index.ts +75 -0
  55. package/invalidation.ts +85 -0
  56. package/log.ts +84 -0
  57. package/ops/href.ts +87 -0
  58. package/ops/index.ts +9 -0
  59. package/ops/move-source.ts +114 -0
  60. package/ops/plan.ts +47 -0
  61. package/ops/remove-source.ts +70 -0
  62. package/package.json +46 -0
  63. package/path.ts +75 -0
  64. package/pattern.ts +314 -0
  65. package/perf.ts +88 -0
  66. package/plugins/actor-path.ts +43 -0
  67. package/plugins/actor-profile.ts +55 -0
  68. package/plugins/agent-browsing.ts +183 -0
  69. package/plugins/app-component.ts +23 -0
  70. package/plugins/block-layout/index.ts +78 -0
  71. package/plugins/block-layout/theme.css +90 -0
  72. package/plugins/callout/index.ts +236 -0
  73. package/plugins/callout/theme.css +138 -0
  74. package/plugins/canonical-links.ts +144 -0
  75. package/plugins/code-highlight/client.ts +89 -0
  76. package/plugins/code-highlight/index.ts +147 -0
  77. package/plugins/code-highlight/theme.css +89 -0
  78. package/plugins/context.ts +131 -0
  79. package/plugins/datatype/Datatype[wdth,wght].woff2 +0 -0
  80. package/plugins/datatype/OFL.txt +96 -0
  81. package/plugins/datatype/index.ts +287 -0
  82. package/plugins/definition-list.ts +236 -0
  83. package/plugins/directive-definitions.ts +13 -0
  84. package/plugins/embedding/client.ts +88 -0
  85. package/plugins/embedding/index.ts +43 -0
  86. package/plugins/image/index.ts +68 -0
  87. package/plugins/image/theme.css +43 -0
  88. package/plugins/include.ts +119 -0
  89. package/plugins/index.ts +91 -0
  90. package/plugins/input/authoring.ts +236 -0
  91. package/plugins/input/config.ts +85 -0
  92. package/plugins/input/index.ts +359 -0
  93. package/plugins/input/model.ts +173 -0
  94. package/plugins/input/state.ts +272 -0
  95. package/plugins/layout.ts +313 -0
  96. package/plugins/literate/client.ts +208 -0
  97. package/plugins/literate/index.ts +742 -0
  98. package/plugins/math/index.ts +140 -0
  99. package/plugins/meta.ts +42 -0
  100. package/plugins/navigation/index.ts +158 -0
  101. package/plugins/navigation/model.ts +364 -0
  102. package/plugins/preset.ts +65 -0
  103. package/plugins/query/index.ts +322 -0
  104. package/plugins/rss/index.ts +46 -0
  105. package/plugins/runtime/actions.ts +62 -0
  106. package/plugins/runtime/client.ts +8 -0
  107. package/plugins/runtime/document.ts +506 -0
  108. package/plugins/runtime/error.ts +154 -0
  109. package/plugins/runtime/heading-links.ts +31 -0
  110. package/plugins/runtime/index.ts +104 -0
  111. package/plugins/runtime/live.ts +51 -0
  112. package/plugins/runtime/navigation.ts +113 -0
  113. package/plugins/runtime/pending.ts +53 -0
  114. package/plugins/runtime/publication.ts +19 -0
  115. package/plugins/runtime/start.ts +177 -0
  116. package/plugins/runtime/static-client.ts +6 -0
  117. package/plugins/runtime/static-live.ts +188 -0
  118. package/plugins/runtime/view-transition.ts +72 -0
  119. package/plugins/runtime/viewport.ts +110 -0
  120. package/plugins/schema.ts +24 -0
  121. package/plugins/scripts.ts +140 -0
  122. package/plugins/source-preview/client.ts +256 -0
  123. package/plugins/source-preview/index.ts +132 -0
  124. package/plugins/source-preview/model.ts +11 -0
  125. package/plugins/source-preview/preview.css +107 -0
  126. package/plugins/styles.ts +145 -0
  127. package/plugins/theme/components.ts +10 -0
  128. package/plugins/theme/foundation.css +358 -0
  129. package/plugins/theme/index.ts +333 -0
  130. package/plugins/theme/prose.css +284 -0
  131. package/plugins/theme/scheme.js +63 -0
  132. package/plugins/theme/toggle.css +44 -0
  133. package/plugins/theme/view-transition.css +68 -0
  134. package/plugins/toc/client.ts +146 -0
  135. package/plugins/toc/index.ts +232 -0
  136. package/plugins/toc/theme.css +172 -0
  137. package/plugins/types.ts +538 -0
  138. package/problem.ts +41 -0
  139. package/project.ts +6 -0
  140. package/publish/build.ts +402 -0
  141. package/publish/concurrent.ts +32 -0
  142. package/publish/identity.ts +63 -0
  143. package/publish/index.ts +11 -0
  144. package/publish/location.ts +167 -0
  145. package/publish/model.ts +58 -0
  146. package/publish/plan.ts +300 -0
  147. package/publish/validate.ts +150 -0
  148. package/query/candidate-index.ts +101 -0
  149. package/query/dependency-index.ts +99 -0
  150. package/query/fields.ts +216 -0
  151. package/query/invalidation.ts +48 -0
  152. package/query/kernel.ts +776 -0
  153. package/query/model.ts +79 -0
  154. package/repository.ts +374 -0
  155. package/runtime-profile.ts +34 -0
  156. package/schema/model.ts +92 -0
  157. package/schema/registry.ts +642 -0
  158. package/schema/standard.ts +226 -0
  159. package/server/context.ts +94 -0
  160. package/server/css-imports.ts +66 -0
  161. package/server/http.ts +333 -0
  162. package/server/page.ts +21 -0
  163. package/server/protocols.ts +12 -0
  164. package/server/representations.ts +66 -0
  165. package/server/router.ts +131 -0
  166. package/server/routes.ts +202 -0
  167. package/server/serve.ts +5 -0
  168. package/server/watch.ts +120 -0
  169. package/source/blocks.ts +71 -0
  170. package/source/format.ts +164 -0
  171. package/source/index.ts +67 -0
  172. package/source/interpolate.ts +63 -0
  173. package/source/markdown/blocks.ts +46 -0
  174. package/source/markdown/comments.ts +32 -0
  175. package/source/markdown/fences.ts +67 -0
  176. package/source/markdown/headings.ts +88 -0
  177. package/source/markdown/index.ts +34 -0
  178. package/source/markdown/inline-code.ts +6 -0
  179. package/source/markdown/links.ts +326 -0
  180. package/source/markdown/lists.ts +223 -0
  181. package/source/markdown/prose.ts +74 -0
  182. package/source/markdown/scan.ts +79 -0
  183. package/source/markdown/text.ts +82 -0
  184. package/source/meta.ts +87 -0
  185. package/source/source.ts +121 -0
  186. package/source/topmatter.ts +57 -0
  187. package/source/utils.ts +21 -0
  188. package/source-diagnostic.ts +63 -0
  189. package/text-file.ts +26 -0
  190. package/util.ts +35 -0
  191. package/view/components.ts +499 -0
  192. package/view/model.ts +91 -0
  193. package/view/projection.ts +162 -0
  194. package/view/session.ts +146 -0
  195. package/view/syntax.ts +372 -0
@@ -0,0 +1,232 @@
1
+ import { headingIdsForBlock } from "../../document.ts"
2
+ import { html, type Html } from "../../html.ts"
3
+ import { authoredViewTag, COMPONENT_ORIGIN_ATTR } from "../../view/syntax.ts"
4
+ import type { StandardSchemaV1 } from "../../schema/standard.ts"
5
+ import type { Source } from "../../source/index.ts"
6
+ import { escapeHtml } from "../../util.ts"
7
+ import { defineViewComponent, type Plugin, type ViewContext } from "../types.ts"
8
+
9
+ type TocOptions = Readonly<{
10
+ minDepth: number
11
+ maxDepth: number
12
+ title: string
13
+ }>
14
+
15
+ type CompiledTocEntry = Readonly<{
16
+ id: string
17
+ text: string
18
+ depth: number
19
+ sourceId: string
20
+ blockPath: string
21
+ }>
22
+
23
+ type CompiledToc = Readonly<{
24
+ title: string
25
+ entries: readonly CompiledTocEntry[]
26
+ }>
27
+
28
+ type TocNode = CompiledTocEntry & { children: TocNode[] }
29
+
30
+ const TOC_ATTRS = new Set(["title", "min-depth", "max-depth"])
31
+ const RENDERED_LEGACY_TOC = /<toc\s*\/?>/gi
32
+ const TOC_COMPONENT = "table-of-contents:toc"
33
+ const TOC_TAG = authoredViewTag(TOC_COMPONENT)
34
+ const clientEntry = new URL("./client.ts", import.meta.url)
35
+
36
+ function configuredOptions(value: unknown): TocOptions | undefined {
37
+ if (value === false) return undefined
38
+ const data =
39
+ value && typeof value === "object" && !Array.isArray(value)
40
+ ? (value as Record<string, unknown>)
41
+ : {}
42
+ const depth = (key: "minDepth" | "maxDepth", fallback: number) => {
43
+ const value = data[key]
44
+ return typeof value === "number" && Number.isInteger(value)
45
+ ? Math.min(6, Math.max(1, value))
46
+ : fallback
47
+ }
48
+ const minDepth = depth("minDepth", 2)
49
+ return {
50
+ minDepth,
51
+ maxDepth: Math.max(minDepth, depth("maxDepth", 6)),
52
+ title:
53
+ typeof data.title === "string" && data.title.trim()
54
+ ? data.title.trim()
55
+ : "On this page",
56
+ }
57
+ }
58
+
59
+ function componentOptions(
60
+ source: Source,
61
+ attrs: Readonly<Record<string, string>>,
62
+ ) {
63
+ const configured = configuredOptions(source.data.toc)
64
+ if (!configured) return
65
+ const minDepth = attrs["min-depth"]
66
+ ? Number(attrs["min-depth"])
67
+ : configured.minDepth
68
+ const maxDepth = attrs["max-depth"]
69
+ ? Number(attrs["max-depth"])
70
+ : configured.maxDepth
71
+ return {
72
+ minDepth,
73
+ maxDepth: Math.max(minDepth, maxDepth),
74
+ title: attrs.title?.trim() || configured.title,
75
+ }
76
+ }
77
+
78
+ function headingEntries(source: Source): CompiledTocEntry[] {
79
+ if (!source.blocks.length) {
80
+ return source.headings.map((heading) => ({
81
+ ...heading,
82
+ sourceId: source.id,
83
+ blockPath: `${source.path}#block-0`,
84
+ }))
85
+ }
86
+
87
+ const entries: CompiledTocEntry[] = []
88
+ for (const block of source.blocks) {
89
+ for (const heading of headingIdsForBlock(source, block)) {
90
+ entries.push({
91
+ ...heading,
92
+ sourceId: source.id,
93
+ blockPath: block.path,
94
+ })
95
+ }
96
+ }
97
+ return entries
98
+ }
99
+
100
+ function buildOutline(headings: readonly CompiledTocEntry[]) {
101
+ const root: { depth: number; children: TocNode[] } = {
102
+ depth: 0,
103
+ children: [],
104
+ }
105
+ const stack: Array<{ depth: number; children: TocNode[] }> = [root]
106
+
107
+ for (const heading of headings) {
108
+ while (stack.length > 1 && stack.at(-1)!.depth >= heading.depth) stack.pop()
109
+ const node: TocNode = { ...heading, children: [] }
110
+ stack.at(-1)!.children.push(node)
111
+ stack.push(node)
112
+ }
113
+
114
+ return root.children
115
+ }
116
+
117
+ function renderOutline(nodes: readonly TocNode[]): Html {
118
+ return html`<ol class="pmx-toc-list">
119
+ ${nodes.map((node) => {
120
+ const children = node.children.length
121
+ ? renderOutline(node.children)
122
+ : null
123
+ return html`<li class="pmx-toc-item">
124
+ <a href="#${node.id}" class="pmx-toc-link">${node.text}</a>${children}
125
+ </li>`
126
+ })}
127
+ </ol>`
128
+ }
129
+
130
+ function visibleEntries(
131
+ entries: readonly CompiledTocEntry[],
132
+ view: ViewContext,
133
+ ) {
134
+ const readable = new Map<string, boolean>()
135
+ return entries.filter((entry) => {
136
+ let allowed = readable.get(entry.sourceId)
137
+ if (allowed == null) {
138
+ allowed = view.view.readSource(entry.sourceId) != null
139
+ readable.set(entry.sourceId, allowed)
140
+ }
141
+ return allowed
142
+ })
143
+ }
144
+
145
+ const tocAttrsSchema: StandardSchemaV1 = {
146
+ "~standard": {
147
+ version: 1,
148
+ vendor: "pathmx",
149
+ validate(value) {
150
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
151
+ return { issues: [{ message: "expected TOC attributes" }] }
152
+ }
153
+ const attrs = value as Record<string, unknown>
154
+ for (const key of Object.keys(attrs)) {
155
+ if (!TOC_ATTRS.has(key)) {
156
+ return { issues: [{ message: `unexpected ${key} attribute` }] }
157
+ }
158
+ }
159
+ if (
160
+ "title" in attrs &&
161
+ (typeof attrs.title !== "string" || !attrs.title.trim())
162
+ ) {
163
+ return { issues: [{ message: "title must not be empty" }] }
164
+ }
165
+ for (const key of ["min-depth", "max-depth"] as const) {
166
+ if (!(key in attrs)) continue
167
+ if (typeof attrs[key] !== "string" || !/^[1-6]$/.test(attrs[key])) {
168
+ return {
169
+ issues: [{ message: `${key} must be an integer from 1 to 6` }],
170
+ }
171
+ }
172
+ }
173
+ if (
174
+ typeof attrs["min-depth"] === "string" &&
175
+ typeof attrs["max-depth"] === "string" &&
176
+ Number(attrs["min-depth"]) > Number(attrs["max-depth"])
177
+ ) {
178
+ return { issues: [{ message: "min-depth must not exceed max-depth" }] }
179
+ }
180
+ return { value }
181
+ },
182
+ },
183
+ }
184
+
185
+ /** A viewer-aware Source/Block outline with `<toc />` migration support. */
186
+ export function TableOfContentsPlugin(): Plugin {
187
+ const TocComponent = defineViewComponent<CompiledToc | undefined>({
188
+ tag: TOC_COMPONENT,
189
+ props: tocAttrsSchema,
190
+ async compile(use, ctx) {
191
+ const options = componentOptions(ctx.source, use.props)
192
+ if (!options) return
193
+ const compiled = {
194
+ title: options.title,
195
+ entries: headingEntries(ctx.source).filter(
196
+ (heading) =>
197
+ heading.depth >= options.minDepth &&
198
+ heading.depth <= options.maxDepth,
199
+ ),
200
+ }
201
+ if (!compiled.entries.length) return
202
+ await ctx.addBrowserBundle(clientEntry, "toc")
203
+ return compiled
204
+ },
205
+ render(_use, compiled, view) {
206
+ if (!compiled) return ""
207
+ const entries = visibleEntries(compiled.entries, view)
208
+ if (!entries.length) return ""
209
+ return html`<nav
210
+ class="pmx-toc"
211
+ aria-label="${compiled.title}"
212
+ data-pmx-toc
213
+ >
214
+ <p class="pmx-toc__title">${compiled.title}</p>
215
+ <div class="pmx-toc-path-frame">
216
+ ${renderOutline(buildOutline(entries))}
217
+ </div>
218
+ </nav>`
219
+ },
220
+ })
221
+
222
+ return {
223
+ id: "table-of-contents",
224
+ components: [TocComponent],
225
+ postcompile(rendered, ctx) {
226
+ if (!ctx.elements.has("toc")) return rendered
227
+ const origin = escapeHtml(ctx.source.path)
228
+ const replacement = `<${TOC_TAG} ${COMPONENT_ORIGIN_ATTR}="${origin}" />`
229
+ return rendered.replace(RENDERED_LEGACY_TOC, replacement)
230
+ },
231
+ }
232
+ }
@@ -0,0 +1,172 @@
1
+ @property --pmx-toc-scroll-progress {
2
+ syntax: "<number>";
3
+ inherits: true;
4
+ initial-value: 0;
5
+ }
6
+
7
+ @keyframes pmx-toc-follow-scroll {
8
+ to {
9
+ --pmx-toc-scroll-progress: 1;
10
+ }
11
+ }
12
+
13
+ :where(.pmx-toc) {
14
+ --pmx-toc-font-size: 0.875rem;
15
+ --pmx-toc-line-height: 1.35;
16
+ --pmx-toc-item-gap: 0.15rem;
17
+ --pmx-toc-indent: 0.9rem;
18
+ --pmx-toc-link-padding: 1.35rem;
19
+ --pmx-toc-link-color: var(--pmx-color-muted, currentColor);
20
+ --pmx-toc-link-active-color: var(
21
+ --pmx-color-accent,
22
+ var(--pmx-color-link, currentColor)
23
+ );
24
+ --pmx-toc-title-color: var(--pmx-color-fg, currentColor);
25
+ --pmx-toc-path-color: var(--pmx-color-border, currentColor);
26
+ --pmx-toc-path-active-color: var(
27
+ --pmx-color-accent,
28
+ var(--pmx-color-link, currentColor)
29
+ );
30
+ --pmx-toc-path-width: 1px;
31
+ --pmx-toc-transition-duration: 160ms;
32
+ --pmx-toc-max-block-size: var(--pmx-sticky-max-block-size, 100dvh);
33
+ --pmx-toc-available-block-size: var(--pmx-toc-max-block-size);
34
+
35
+ color: var(--pmx-toc-link-color);
36
+ font-size: var(--pmx-toc-font-size);
37
+ line-height: var(--pmx-toc-line-height);
38
+ max-block-size: min(
39
+ var(--pmx-toc-max-block-size),
40
+ var(--pmx-toc-available-block-size)
41
+ );
42
+ overflow-y: auto;
43
+ overscroll-behavior-block: contain;
44
+ scrollbar-gutter: stable;
45
+ scrollbar-width: thin;
46
+ }
47
+
48
+ :where(.pmx-toc__title) {
49
+ margin-block: 0 0.75rem;
50
+ color: var(--pmx-toc-title-color);
51
+ font-family: var(--pmx-font-heading, inherit);
52
+ font-weight: 700;
53
+ }
54
+
55
+ :where(.pmx-toc-path-frame) {
56
+ position: relative;
57
+ animation: pmx-toc-follow-scroll linear both;
58
+ animation-timeline: scroll(root block);
59
+ }
60
+
61
+ :where(.pmx-toc-path-frame)::after {
62
+ content: "";
63
+ position: absolute;
64
+ z-index: 1;
65
+ inset-block: 0;
66
+ inset-inline-start: calc(var(--pmx-toc-link-padding) / 2);
67
+ inline-size: var(--pmx-toc-path-width);
68
+ background: var(--pmx-toc-path-active-color);
69
+ pointer-events: none;
70
+ transform: scaleY(var(--pmx-toc-scroll-progress));
71
+ transform-origin: top;
72
+ }
73
+
74
+ :where(.pmx-toc-list) {
75
+ position: relative;
76
+ display: grid;
77
+ gap: var(--pmx-toc-item-gap);
78
+ margin: 0;
79
+ padding: 0;
80
+ list-style: none;
81
+ }
82
+
83
+ :where(.pmx-toc-path-frame > .pmx-toc-list) {
84
+ scroll-target-group: auto;
85
+ }
86
+
87
+ :where(.pmx-toc-list)::before {
88
+ content: "";
89
+ position: absolute;
90
+ inset-block: 0;
91
+ inset-inline-start: calc(var(--pmx-toc-link-padding) / 2);
92
+ inline-size: var(--pmx-toc-path-width);
93
+ background: var(--pmx-toc-path-color);
94
+ pointer-events: none;
95
+ }
96
+
97
+ :where(.pmx-toc-list .pmx-toc-list) {
98
+ margin-inline-start: var(--pmx-toc-indent);
99
+ }
100
+
101
+ :where(.pmx-toc-item) {
102
+ position: relative;
103
+ min-inline-size: 0;
104
+ }
105
+
106
+ :where(.pmx-toc-link) {
107
+ position: relative;
108
+ z-index: 2;
109
+ display: block;
110
+ padding-block: 0.3rem;
111
+ padding-inline-start: var(--pmx-toc-link-padding);
112
+ color: var(--pmx-toc-link-color);
113
+ text-decoration: none;
114
+ overflow-wrap: anywhere;
115
+ transition: color var(--pmx-toc-transition-duration) ease-out;
116
+ }
117
+
118
+ :where(.pmx-toc-link)::before {
119
+ content: "";
120
+ position: absolute;
121
+ inset-block-start: calc(0.3rem + 0.5lh);
122
+ inset-inline-start: calc(var(--pmx-toc-link-padding) / 2);
123
+ inline-size: calc(var(--pmx-toc-link-padding) / 2 - 0.25rem);
124
+ block-size: var(--pmx-toc-path-width);
125
+ background: var(--pmx-toc-path-color);
126
+ transform: translateY(-50%);
127
+ transition: background var(--pmx-toc-transition-duration) ease-out;
128
+ }
129
+
130
+ :where(
131
+ .pmx-toc-link:target-before,
132
+ .pmx-toc-link:target-current,
133
+ .pmx-toc-link[data-pmx-toc-state="passed"],
134
+ .pmx-toc-link[data-pmx-toc-state="active"]
135
+ ) {
136
+ color: var(--pmx-toc-link-active-color);
137
+ }
138
+
139
+ :where(
140
+ .pmx-toc-link:target-before,
141
+ .pmx-toc-link:target-current,
142
+ .pmx-toc-link[data-pmx-toc-state="passed"],
143
+ .pmx-toc-link[data-pmx-toc-state="active"]
144
+ )::before {
145
+ background: var(--pmx-toc-path-active-color);
146
+ }
147
+
148
+ :where(.pmx-toc-link:hover) {
149
+ color: var(--pmx-toc-link-active-color);
150
+ }
151
+
152
+ :where(.pmx-toc-link:focus-visible) {
153
+ color: var(--pmx-toc-link-active-color);
154
+ outline: 2px solid var(--pmx-color-focus, currentColor);
155
+ outline-offset: 2px;
156
+ border-radius: var(--pmx-radius-sm, 0.25rem);
157
+ }
158
+
159
+ @media (prefers-reduced-motion: reduce) {
160
+ :where(.pmx-toc-path-frame) {
161
+ animation: none;
162
+ }
163
+
164
+ :where(.pmx-toc-path-frame)::after {
165
+ display: none;
166
+ }
167
+
168
+ :where(.pmx-toc-link),
169
+ :where(.pmx-toc-link)::before {
170
+ transition: none;
171
+ }
172
+ }