blume 0.0.0 → 0.1.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 (330) hide show
  1. package/bin/blume.mjs +18 -0
  2. package/dist/cli/index.js +12696 -0
  3. package/dist/cli/index.js.map +145 -0
  4. package/dist/types/core/bridge.d.ts +24 -0
  5. package/dist/types/core/config.d.ts +35 -0
  6. package/dist/types/core/data.d.ts +129 -0
  7. package/dist/types/core/define-components.d.ts +27 -0
  8. package/dist/types/core/define-meta.d.ts +16 -0
  9. package/dist/types/core/deployment-env.d.ts +9 -0
  10. package/dist/types/core/diagnostics.d.ts +17 -0
  11. package/dist/types/core/i18n-ui.d.ts +500 -0
  12. package/dist/types/core/load-module.d.ts +7 -0
  13. package/dist/types/core/package-root.d.ts +17 -0
  14. package/dist/types/core/project.d.ts +9 -0
  15. package/dist/types/core/schema.d.ts +3451 -0
  16. package/dist/types/core/sources/types.d.ts +107 -0
  17. package/dist/types/core/types.d.ts +245 -0
  18. package/dist/types/core/ui-packs/ar.d.ts +3 -0
  19. package/dist/types/core/ui-packs/bg.d.ts +3 -0
  20. package/dist/types/core/ui-packs/bn.d.ts +3 -0
  21. package/dist/types/core/ui-packs/ca.d.ts +3 -0
  22. package/dist/types/core/ui-packs/cs.d.ts +3 -0
  23. package/dist/types/core/ui-packs/da.d.ts +3 -0
  24. package/dist/types/core/ui-packs/de.d.ts +3 -0
  25. package/dist/types/core/ui-packs/el.d.ts +3 -0
  26. package/dist/types/core/ui-packs/es.d.ts +3 -0
  27. package/dist/types/core/ui-packs/fa.d.ts +3 -0
  28. package/dist/types/core/ui-packs/fi.d.ts +3 -0
  29. package/dist/types/core/ui-packs/fr.d.ts +3 -0
  30. package/dist/types/core/ui-packs/he.d.ts +3 -0
  31. package/dist/types/core/ui-packs/hi.d.ts +3 -0
  32. package/dist/types/core/ui-packs/hr.d.ts +3 -0
  33. package/dist/types/core/ui-packs/hu.d.ts +3 -0
  34. package/dist/types/core/ui-packs/id.d.ts +3 -0
  35. package/dist/types/core/ui-packs/index.d.ts +13 -0
  36. package/dist/types/core/ui-packs/it.d.ts +3 -0
  37. package/dist/types/core/ui-packs/ja.d.ts +3 -0
  38. package/dist/types/core/ui-packs/ko.d.ts +3 -0
  39. package/dist/types/core/ui-packs/nl.d.ts +3 -0
  40. package/dist/types/core/ui-packs/no.d.ts +3 -0
  41. package/dist/types/core/ui-packs/pl.d.ts +3 -0
  42. package/dist/types/core/ui-packs/pt-br.d.ts +3 -0
  43. package/dist/types/core/ui-packs/pt.d.ts +3 -0
  44. package/dist/types/core/ui-packs/ro.d.ts +3 -0
  45. package/dist/types/core/ui-packs/ru.d.ts +3 -0
  46. package/dist/types/core/ui-packs/sk.d.ts +3 -0
  47. package/dist/types/core/ui-packs/sr.d.ts +3 -0
  48. package/dist/types/core/ui-packs/sv.d.ts +3 -0
  49. package/dist/types/core/ui-packs/th.d.ts +3 -0
  50. package/dist/types/core/ui-packs/tr.d.ts +3 -0
  51. package/dist/types/core/ui-packs/uk.d.ts +3 -0
  52. package/dist/types/core/ui-packs/vi.d.ts +3 -0
  53. package/dist/types/core/ui-packs/zh-tw.d.ts +3 -0
  54. package/dist/types/core/ui-packs/zh.d.ts +3 -0
  55. package/dist/types/core/version.d.ts +8 -0
  56. package/dist/types/index.d.ts +10 -0
  57. package/dist/types/migrate/mintlify/config.d.ts +2 -0
  58. package/dist/types/migrate/mintlify/i18n.d.ts +7 -0
  59. package/dist/types/theme/fonts.d.ts +163 -0
  60. package/docs/01-quickstart.mdx +99 -0
  61. package/docs/02-deployment.mdx +129 -0
  62. package/docs/advanced/api-reference.mdx +114 -0
  63. package/docs/advanced/blog.mdx +121 -0
  64. package/docs/advanced/changelog.mdx +113 -0
  65. package/docs/advanced/custom-pages.mdx +268 -0
  66. package/docs/advanced/meta.ts +7 -0
  67. package/docs/changelog/v0-1-0.mdx +12 -0
  68. package/docs/changelog/v0-2-0.mdx +16 -0
  69. package/docs/configuration/ai.mdx +228 -0
  70. package/docs/configuration/analytics.mdx +98 -0
  71. package/docs/configuration/customization.mdx +91 -0
  72. package/docs/configuration/export.mdx +70 -0
  73. package/docs/configuration/index.mdx +290 -0
  74. package/docs/configuration/meta.ts +15 -0
  75. package/docs/configuration/search.mdx +172 -0
  76. package/docs/configuration/seo.mdx +196 -0
  77. package/docs/configuration/theming.mdx +178 -0
  78. package/docs/content/components.mdx +651 -0
  79. package/docs/content/i18n.mdx +205 -0
  80. package/docs/content/index.mdx +161 -0
  81. package/docs/content/islands.mdx +94 -0
  82. package/docs/content/meta.mdx +119 -0
  83. package/docs/content/meta.ts +15 -0
  84. package/docs/content/navigation.mdx +168 -0
  85. package/docs/content/sources.mdx +216 -0
  86. package/docs/content/syntax.mdx +445 -0
  87. package/docs/index.mdx +112 -0
  88. package/docs/reference/cli.mdx +43 -0
  89. package/docs/reference/frontmatter.mdx +74 -0
  90. package/docs/reference/meta.ts +7 -0
  91. package/package.json +150 -6
  92. package/src/ai/ask.ts +93 -0
  93. package/src/ai/llms.ts +64 -0
  94. package/src/ai/markdown.ts +31 -0
  95. package/src/ai/mcp/data.ts +74 -0
  96. package/src/ai/mcp/discovery.ts +49 -0
  97. package/src/ai/mcp/server.ts +225 -0
  98. package/src/ai/mcp/tools.ts +47 -0
  99. package/src/assets/icon.png +0 -0
  100. package/src/astro/examples.ts +104 -0
  101. package/src/astro/generate.ts +1006 -0
  102. package/src/astro/index.ts +4 -0
  103. package/src/astro/integration.ts +74 -0
  104. package/src/astro/islands.ts +131 -0
  105. package/src/astro/markdown-negotiation.ts +68 -0
  106. package/src/astro/pages.ts +87 -0
  107. package/src/astro/templates.ts +1326 -0
  108. package/src/cli/commands/add.ts +81 -0
  109. package/src/cli/commands/build.ts +103 -0
  110. package/src/cli/commands/dev.ts +108 -0
  111. package/src/cli/commands/doctor.ts +74 -0
  112. package/src/cli/commands/eject.ts +57 -0
  113. package/src/cli/commands/init.ts +98 -0
  114. package/src/cli/commands/migrate.ts +39 -0
  115. package/src/cli/commands/preview.ts +39 -0
  116. package/src/cli/commands/sync.ts +52 -0
  117. package/src/cli/commands/validate.ts +61 -0
  118. package/src/cli/index.ts +35 -0
  119. package/src/cli/log.ts +37 -0
  120. package/src/cli/prepare.ts +80 -0
  121. package/src/components/Icon.astro +99 -0
  122. package/src/components/content/Accordion.astro +8 -0
  123. package/src/components/content/AccordionItem.astro +121 -0
  124. package/src/components/content/AutoTypeTable.astro +51 -0
  125. package/src/components/content/Badge.astro +124 -0
  126. package/src/components/content/Callout.astro +73 -0
  127. package/src/components/content/Card.astro +104 -0
  128. package/src/components/content/CardGroup.astro +14 -0
  129. package/src/components/content/CodeBlock.astro +28 -0
  130. package/src/components/content/CodeGroup.astro +13 -0
  131. package/src/components/content/Color.astro +15 -0
  132. package/src/components/content/ColorItem.astro +87 -0
  133. package/src/components/content/ColorRow.astro +10 -0
  134. package/src/components/content/Column.astro +6 -0
  135. package/src/components/content/Columns.astro +9 -0
  136. package/src/components/content/Component.astro +65 -0
  137. package/src/components/content/Diff.astro +44 -0
  138. package/src/components/content/Expandable.astro +11 -0
  139. package/src/components/content/FileTree.astro +8 -0
  140. package/src/components/content/Frame.astro +70 -0
  141. package/src/components/content/GithubInfo.astro +110 -0
  142. package/src/components/content/Math.astro +24 -0
  143. package/src/components/content/Panel.astro +20 -0
  144. package/src/components/content/Prompt.astro +129 -0
  145. package/src/components/content/Step.astro +34 -0
  146. package/src/components/content/Steps.astro +20 -0
  147. package/src/components/content/Tab.astro +46 -0
  148. package/src/components/content/Tabs.astro +273 -0
  149. package/src/components/content/Tile.astro +42 -0
  150. package/src/components/content/Tooltip.astro +68 -0
  151. package/src/components/content/Tree.astro +300 -0
  152. package/src/components/content/TreeFile.astro +15 -0
  153. package/src/components/content/TreeFolder.astro +62 -0
  154. package/src/components/content/TypeTable.astro +106 -0
  155. package/src/components/content/Update.astro +66 -0
  156. package/src/components/content/Visibility.astro +12 -0
  157. package/src/components/content/Warning.astro +9 -0
  158. package/src/components/content/auto-type-table.ts +141 -0
  159. package/src/components/content/diff.ts +95 -0
  160. package/src/components/content/github-info.ts +79 -0
  161. package/src/components/content/mermaid-element.ts +68 -0
  162. package/src/components/github-mark.ts +9 -0
  163. package/src/components/index.ts +14 -0
  164. package/src/components/islands/AskAI.astro +12 -0
  165. package/src/components/islands/ask-ai.tsx +156 -0
  166. package/src/components/layout/Analytics.astro +63 -0
  167. package/src/components/layout/Banner.astro +50 -0
  168. package/src/components/layout/Breadcrumbs.astro +31 -0
  169. package/src/components/layout/Favicon.astro +22 -0
  170. package/src/components/layout/Fonts.astro +14 -0
  171. package/src/components/layout/Header.astro +188 -0
  172. package/src/components/layout/LanguageSwitcher.astro +56 -0
  173. package/src/components/layout/NavTree.astro +462 -0
  174. package/src/components/layout/PageActions.astro +438 -0
  175. package/src/components/layout/PageFeedback.astro +58 -0
  176. package/src/components/layout/PageLayout.astro +173 -0
  177. package/src/components/layout/Pagination.astro +56 -0
  178. package/src/components/layout/ReferenceLayout.astro +107 -0
  179. package/src/components/layout/RootLayout.astro +537 -0
  180. package/src/components/layout/Search.astro +608 -0
  181. package/src/components/layout/TableOfContents.astro +68 -0
  182. package/src/components/layout/analytics-client.ts +38 -0
  183. package/src/components/layout/head-scripts.ts +19 -0
  184. package/src/components/layout/nav-utils.ts +87 -0
  185. package/src/components/layout/overrides.ts +32 -0
  186. package/src/components/layout/search/algolia.ts +43 -0
  187. package/src/components/layout/search/endpoint.ts +22 -0
  188. package/src/components/layout/search/flexsearch.ts +52 -0
  189. package/src/components/layout/search/orama-cloud.ts +41 -0
  190. package/src/components/layout/search/orama.ts +26 -0
  191. package/src/components/layout/search/pagefind.ts +43 -0
  192. package/src/components/layout/search/types.ts +163 -0
  193. package/src/components/layout/search/typesense.ts +60 -0
  194. package/src/components/layout/toc-element.ts +108 -0
  195. package/src/core/bridge.ts +92 -0
  196. package/src/core/config.ts +112 -0
  197. package/src/core/content.ts +50 -0
  198. package/src/core/data.ts +128 -0
  199. package/src/core/define-components.ts +34 -0
  200. package/src/core/define-meta.ts +20 -0
  201. package/src/core/deployment-env.ts +73 -0
  202. package/src/core/diagnostics.ts +104 -0
  203. package/src/core/frontmatter.ts +43 -0
  204. package/src/core/graph.ts +128 -0
  205. package/src/core/i18n-ui.ts +171 -0
  206. package/src/core/i18n.ts +169 -0
  207. package/src/core/last-modified.ts +88 -0
  208. package/src/core/links.ts +352 -0
  209. package/src/core/load-module.ts +15 -0
  210. package/src/core/manifest.ts +126 -0
  211. package/src/core/meta.ts +97 -0
  212. package/src/core/navigation.ts +392 -0
  213. package/src/core/package-root.ts +37 -0
  214. package/src/core/project-graph.ts +153 -0
  215. package/src/core/project.ts +56 -0
  216. package/src/core/schema.ts +1057 -0
  217. package/src/core/server-features.ts +23 -0
  218. package/src/core/sources/assets.ts +77 -0
  219. package/src/core/sources/cache.ts +122 -0
  220. package/src/core/sources/filesystem.ts +99 -0
  221. package/src/core/sources/mdx-remote.ts +215 -0
  222. package/src/core/sources/mintlify.ts +161 -0
  223. package/src/core/sources/normalize.ts +243 -0
  224. package/src/core/sources/notion.ts +440 -0
  225. package/src/core/sources/portable-text.ts +143 -0
  226. package/src/core/sources/read.ts +36 -0
  227. package/src/core/sources/resolve.ts +158 -0
  228. package/src/core/sources/sanity.ts +218 -0
  229. package/src/core/sources/types.ts +105 -0
  230. package/src/core/tsconfig-aliases.ts +201 -0
  231. package/src/core/types.ts +261 -0
  232. package/src/core/ui-packs/ar.ts +47 -0
  233. package/src/core/ui-packs/bg.ts +47 -0
  234. package/src/core/ui-packs/bn.ts +47 -0
  235. package/src/core/ui-packs/ca.ts +47 -0
  236. package/src/core/ui-packs/cs.ts +47 -0
  237. package/src/core/ui-packs/da.ts +47 -0
  238. package/src/core/ui-packs/de.ts +47 -0
  239. package/src/core/ui-packs/el.ts +47 -0
  240. package/src/core/ui-packs/es.ts +47 -0
  241. package/src/core/ui-packs/fa.ts +47 -0
  242. package/src/core/ui-packs/fi.ts +47 -0
  243. package/src/core/ui-packs/fr.ts +47 -0
  244. package/src/core/ui-packs/he.ts +47 -0
  245. package/src/core/ui-packs/hi.ts +47 -0
  246. package/src/core/ui-packs/hr.ts +47 -0
  247. package/src/core/ui-packs/hu.ts +47 -0
  248. package/src/core/ui-packs/id.ts +47 -0
  249. package/src/core/ui-packs/index.ts +87 -0
  250. package/src/core/ui-packs/it.ts +47 -0
  251. package/src/core/ui-packs/ja.ts +47 -0
  252. package/src/core/ui-packs/ko.ts +47 -0
  253. package/src/core/ui-packs/nl.ts +47 -0
  254. package/src/core/ui-packs/no.ts +47 -0
  255. package/src/core/ui-packs/pl.ts +47 -0
  256. package/src/core/ui-packs/pt-br.ts +47 -0
  257. package/src/core/ui-packs/pt.ts +47 -0
  258. package/src/core/ui-packs/ro.ts +47 -0
  259. package/src/core/ui-packs/ru.ts +47 -0
  260. package/src/core/ui-packs/sk.ts +47 -0
  261. package/src/core/ui-packs/sr.ts +47 -0
  262. package/src/core/ui-packs/sv.ts +47 -0
  263. package/src/core/ui-packs/th.ts +47 -0
  264. package/src/core/ui-packs/tr.ts +47 -0
  265. package/src/core/ui-packs/uk.ts +47 -0
  266. package/src/core/ui-packs/vi.ts +47 -0
  267. package/src/core/ui-packs/zh-tw.ts +47 -0
  268. package/src/core/ui-packs/zh.ts +47 -0
  269. package/src/core/version.ts +23 -0
  270. package/src/deploy/robots.ts +20 -0
  271. package/src/deploy/rss.ts +128 -0
  272. package/src/deploy/sitemap.ts +28 -0
  273. package/src/index.ts +39 -0
  274. package/src/markdown/code-title.ts +71 -0
  275. package/src/markdown/directives.ts +83 -0
  276. package/src/markdown/heading-anchors.ts +137 -0
  277. package/src/markdown/index.ts +228 -0
  278. package/src/markdown/inline-code.ts +108 -0
  279. package/src/markdown/language-icon.ts +172 -0
  280. package/src/markdown/math.ts +32 -0
  281. package/src/markdown/mdast.ts +48 -0
  282. package/src/markdown/mermaid.ts +37 -0
  283. package/src/markdown/package-commands.ts +159 -0
  284. package/src/markdown/package-install.ts +40 -0
  285. package/src/migrate/fumadocs/config.ts +155 -0
  286. package/src/migrate/fumadocs/content.ts +365 -0
  287. package/src/migrate/fumadocs/frontmatter.ts +18 -0
  288. package/src/migrate/fumadocs/groups.ts +230 -0
  289. package/src/migrate/fumadocs/index.ts +337 -0
  290. package/src/migrate/fumadocs/meta.ts +244 -0
  291. package/src/migrate/migrate.ts +53 -0
  292. package/src/migrate/mintlify/config.ts +1040 -0
  293. package/src/migrate/mintlify/content.ts +98 -0
  294. package/src/migrate/mintlify/frontmatter.ts +126 -0
  295. package/src/migrate/mintlify/i18n.ts +51 -0
  296. package/src/migrate/mintlify/icons.ts +128 -0
  297. package/src/migrate/mintlify/index.ts +266 -0
  298. package/src/migrate/mintlify/snippets.ts +306 -0
  299. package/src/migrate/mintlify/transform.ts +80 -0
  300. package/src/migrate/nextra/content.ts +46 -0
  301. package/src/migrate/nextra/frontmatter.ts +40 -0
  302. package/src/migrate/nextra/index.ts +374 -0
  303. package/src/migrate/nextra/meta.ts +266 -0
  304. package/src/migrate/shared.ts +720 -0
  305. package/src/migrate/starlight/config.ts +459 -0
  306. package/src/migrate/starlight/content.ts +78 -0
  307. package/src/migrate/starlight/frontmatter.ts +111 -0
  308. package/src/migrate/starlight/i18n.ts +54 -0
  309. package/src/migrate/starlight/index.ts +131 -0
  310. package/src/og/card.ts +92 -0
  311. package/src/og/index.ts +2 -0
  312. package/src/openapi/scalar.ts +246 -0
  313. package/src/registry/eject.ts +310 -0
  314. package/src/registry/registry.ts +100 -0
  315. package/src/registry/rewrite-imports.ts +39 -0
  316. package/src/runtime/index.ts +14 -0
  317. package/src/search/build.ts +23 -0
  318. package/src/search/documents.ts +164 -0
  319. package/src/search/orama-index.ts +66 -0
  320. package/src/search/providers.ts +91 -0
  321. package/src/search/sync/algolia.ts +30 -0
  322. package/src/search/sync/index.ts +50 -0
  323. package/src/search/sync/orama-cloud.ts +40 -0
  324. package/src/search/sync/typesense.ts +65 -0
  325. package/src/seo/jsonld.ts +113 -0
  326. package/src/theme/entry.ts +637 -0
  327. package/src/theme/fonts.ts +198 -0
  328. package/src/theme/icons.ts +184 -0
  329. package/src/theme/palette.ts +143 -0
  330. package/src/theme/twoslash.ts +81 -0
@@ -0,0 +1,637 @@
1
+ interface TailwindEntryOptions {
2
+ /**
3
+ * Globs to scan for utility classes. Typically the Blume package source and
4
+ * the user's project (node_modules is skipped automatically).
5
+ */
6
+ sources: string[];
7
+ /** Config-derived token overrides (`:root { --blume-accent: ... }`). */
8
+ configTokens: string;
9
+ /** Raw contents of the user's theme.css, if any. */
10
+ userTheme: string;
11
+ /** Twoslash rich-renderer styles (for fences with the `twoslash` meta). */
12
+ twoslashCss?: string;
13
+ }
14
+
15
+ /**
16
+ * Build the single Tailwind v4 entry stylesheet for the generated runtime.
17
+ *
18
+ * Everything flows through one Tailwind-processed file so utilities are
19
+ * generated and design tokens cascade deterministically:
20
+ * base defaults -> config tokens -> user theme.css.
21
+ */
22
+ export const tailwindEntryTemplate = (options: TailwindEntryOptions): string =>
23
+ `/* Generated by Blume. Do not edit. */
24
+ @import "tailwindcss";
25
+ @plugin "@tailwindcss/typography";
26
+
27
+ /* Scan Blume's components and the user's project for utility classes. */
28
+ ${options.sources.map((source) => `@source "${source}";`).join("\n")}
29
+
30
+ /* Dark mode is driven by data-theme on the <html> element. */
31
+ @custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
32
+
33
+ :root {
34
+ --blume-background: oklch(1 0 0);
35
+ --blume-background-decoration: none;
36
+ --blume-background-decoration-repeat: no-repeat;
37
+ --blume-background-decoration-size: auto;
38
+ --blume-background-image: none;
39
+ --blume-background-image-repeat: no-repeat;
40
+ --blume-background-image-size: cover;
41
+ --blume-foreground: oklch(0.145 0 0);
42
+ --blume-muted: oklch(0.965 0 0);
43
+ --blume-muted-foreground: oklch(0.54 0 0);
44
+ --blume-border: oklch(0.88 0.006 260 / 0.72);
45
+ --blume-accent: oklch(0.145 0 0);
46
+ --blume-accent-foreground: oklch(1 0 0);
47
+ --blume-action: var(--blume-accent);
48
+ --blume-action-foreground: var(--blume-accent-foreground);
49
+ --blume-code-background: oklch(0.99 0 0);
50
+ /* Shiki notation transformers: line/word highlight, diff add/remove. */
51
+ --blume-code-highlight: oklch(0.55 0.16 255 / 0.1);
52
+ --blume-code-highlight-border: oklch(0.55 0.16 255 / 0.55);
53
+ --blume-code-add: oklch(0.72 0.16 150 / 0.16);
54
+ --blume-code-add-border: oklch(0.52 0.15 150 / 0.7);
55
+ --blume-code-remove: oklch(0.66 0.21 22 / 0.16);
56
+ --blume-code-remove-border: oklch(0.55 0.2 22 / 0.7);
57
+ --blume-code-word: oklch(0.55 0.16 255 / 0.16);
58
+ --blume-code-word-border: oklch(0.55 0.16 255 / 0.5);
59
+ --blume-radius: 0.75rem;
60
+
61
+ /*
62
+ * Font tokens resolve through optional src variables that Astro's Fonts API
63
+ * populates (via theme.fonts). When unset they fall back to the system
64
+ * stacks, so the default look is unchanged. The display font defaults to the
65
+ * body font.
66
+ */
67
+ --blume-font-body: var(
68
+ --blume-font-body-src,
69
+ ui-sans-serif,
70
+ system-ui,
71
+ -apple-system,
72
+ "Segoe UI",
73
+ Roboto,
74
+ Helvetica,
75
+ Arial,
76
+ sans-serif
77
+ );
78
+ --blume-font-mono: var(
79
+ --blume-font-mono-src,
80
+ ui-monospace,
81
+ "SF Mono",
82
+ "Cascadia Code",
83
+ "Source Code Pro",
84
+ Menlo,
85
+ Consolas,
86
+ monospace
87
+ );
88
+ --blume-font-display: var(--blume-font-display-src, var(--blume-font-body));
89
+ }
90
+
91
+ :root[data-theme="dark"] {
92
+ --blume-background: oklch(0.085 0 0);
93
+ --blume-background-decoration: none;
94
+ --blume-background-decoration-repeat: no-repeat;
95
+ --blume-background-decoration-size: auto;
96
+ --blume-background-image: none;
97
+ --blume-background-image-repeat: no-repeat;
98
+ --blume-background-image-size: cover;
99
+ --blume-foreground: oklch(0.96 0 0);
100
+ --blume-muted: oklch(0.16 0 0);
101
+ --blume-muted-foreground: oklch(0.68 0 0);
102
+ --blume-border: oklch(0.24 0 0 / 0.8);
103
+ --blume-accent: oklch(0.96 0 0);
104
+ --blume-accent-foreground: oklch(0.085 0 0);
105
+ --blume-action: var(--blume-accent);
106
+ --blume-action-foreground: var(--blume-accent-foreground);
107
+ --blume-code-background: oklch(0.12 0 0);
108
+ /* Brighter tints read better over the dark code surface. */
109
+ --blume-code-highlight: oklch(0.7 0.14 255 / 0.16);
110
+ --blume-code-highlight-border: oklch(0.7 0.14 255 / 0.6);
111
+ --blume-code-add: oklch(0.78 0.17 150 / 0.2);
112
+ --blume-code-add-border: oklch(0.72 0.16 150 / 0.7);
113
+ --blume-code-remove: oklch(0.72 0.21 22 / 0.22);
114
+ --blume-code-remove-border: oklch(0.7 0.2 22 / 0.7);
115
+ --blume-code-word: oklch(0.7 0.14 255 / 0.22);
116
+ --blume-code-word-border: oklch(0.7 0.14 255 / 0.55);
117
+ }
118
+
119
+ @theme inline {
120
+ --color-background: var(--blume-background);
121
+ --color-foreground: var(--blume-foreground);
122
+ --color-muted: var(--blume-muted);
123
+ --color-muted-foreground: var(--blume-muted-foreground);
124
+ --color-border: var(--blume-border);
125
+ --color-accent: var(--blume-accent);
126
+ --color-accent-foreground: var(--blume-accent-foreground);
127
+ --color-action: var(--blume-action);
128
+ --color-action-foreground: var(--blume-action-foreground);
129
+ --color-code: var(--blume-code-background);
130
+ --radius-blume: var(--blume-radius);
131
+ --font-sans: var(--blume-font-body);
132
+ --font-mono: var(--blume-font-mono);
133
+ --font-display: var(--blume-font-display);
134
+ }
135
+
136
+ @layer base {
137
+ html {
138
+ scroll-behavior: smooth;
139
+ scroll-padding-top: 4.5rem;
140
+ }
141
+ /* Headings use the display font (defaults to the body font when unset). */
142
+ h1,
143
+ h2,
144
+ h3,
145
+ h4,
146
+ h5,
147
+ h6 {
148
+ font-family: var(--font-display);
149
+ }
150
+ :focus-visible {
151
+ outline: 2px solid var(--blume-accent);
152
+ outline-offset: 2px;
153
+ border-radius: 2px;
154
+ }
155
+ body {
156
+ background-attachment: fixed, fixed;
157
+ background-image:
158
+ var(--blume-background-image), var(--blume-background-decoration);
159
+ background-position: center top, top center;
160
+ background-repeat:
161
+ var(--blume-background-image-repeat),
162
+ var(--blume-background-decoration-repeat);
163
+ background-size:
164
+ var(--blume-background-image-size),
165
+ var(--blume-background-decoration-size);
166
+ }
167
+ @media (prefers-reduced-motion: reduce) {
168
+ html {
169
+ scroll-behavior: auto;
170
+ }
171
+ }
172
+ }
173
+
174
+ /* Code reads left-to-right regardless of page direction; only the surrounding
175
+ chrome mirrors for RTL. Inline code is isolated so LTR identifiers don't
176
+ disturb the bidi flow of right-to-left prose. */
177
+ [dir="rtl"] pre,
178
+ [dir="rtl"] .prose pre {
179
+ direction: ltr;
180
+ text-align: left;
181
+ }
182
+ [dir="rtl"] :not(pre) > code {
183
+ unicode-bidi: isolate;
184
+ }
185
+
186
+ /* Theme Tailwind Typography (prose) with Blume tokens. */
187
+ .prose {
188
+ --tw-prose-body: var(--blume-foreground);
189
+ --tw-prose-headings: var(--blume-foreground);
190
+ --tw-prose-lead: var(--blume-muted-foreground);
191
+ --tw-prose-links: var(--blume-foreground);
192
+ --tw-prose-bold: var(--blume-foreground);
193
+ --tw-prose-counters: var(--blume-muted-foreground);
194
+ --tw-prose-bullets: var(--blume-border);
195
+ --tw-prose-hr: var(--blume-border);
196
+ --tw-prose-quotes: var(--blume-muted-foreground);
197
+ --tw-prose-quote-borders: var(--blume-border);
198
+ --tw-prose-captions: var(--blume-muted-foreground);
199
+ --tw-prose-code: var(--blume-foreground);
200
+ --tw-prose-pre-code: var(--blume-foreground);
201
+ --tw-prose-pre-bg: var(--blume-code-background);
202
+ --tw-prose-th-borders: var(--blume-border);
203
+ --tw-prose-td-borders: var(--blume-border);
204
+ color: var(--blume-muted-foreground);
205
+ font-size: 0.875rem;
206
+ line-height: 1.7;
207
+ }
208
+
209
+ .prose :where(h1, h2, h3, h4) {
210
+ font-weight: 500;
211
+ letter-spacing: 0;
212
+ }
213
+
214
+ .prose :where(h1) {
215
+ font-size: 3rem;
216
+ line-height: 1.1;
217
+ margin: 0 0 1rem;
218
+ }
219
+
220
+ .prose :where(h2) {
221
+ font-size: 1.875rem;
222
+ line-height: 1.2;
223
+ margin-top: 3rem;
224
+ }
225
+
226
+ .prose :where(h3) {
227
+ font-size: 1.25rem;
228
+ line-height: 1.35;
229
+ }
230
+
231
+ .prose :where(h4) {
232
+ color: var(--blume-muted-foreground);
233
+ font-size: 0.875rem;
234
+ line-height: 1.4;
235
+ }
236
+
237
+ .prose :where(h1, h2, h3, h4, h5, h6) a {
238
+ color: inherit;
239
+ font-weight: inherit;
240
+ text-decoration: none;
241
+ }
242
+
243
+ /* Auto-generated heading permalinks (markdown.headingAnchors): the whole
244
+ heading links to its own id, with a muted “#” revealed on hover or keyboard
245
+ focus so the link is discoverable without cluttering the heading at rest. */
246
+ .prose :where(h2, h3, h4, h5, h6) a.blume-heading-anchor::after {
247
+ content: "#";
248
+ color: var(--blume-muted-foreground);
249
+ margin-inline-start: 0.35em;
250
+ opacity: 0;
251
+ transition: opacity 0.15s ease;
252
+ }
253
+ .prose :where(h2, h3, h4, h5, h6) a.blume-heading-anchor:hover::after,
254
+ .prose :where(h2, h3, h4, h5, h6) a.blume-heading-anchor:focus-visible::after {
255
+ opacity: 1;
256
+ }
257
+
258
+ .prose :where(h2:first-child) {
259
+ border-top: 0;
260
+ padding-top: 0;
261
+ }
262
+
263
+ .prose :where(p, ul, ol) {
264
+ margin-top: 1rem;
265
+ margin-bottom: 1rem;
266
+ }
267
+
268
+ .prose :where(strong) {
269
+ font-weight: 600;
270
+ }
271
+
272
+ .prose :where(a) {
273
+ color: var(--blume-foreground);
274
+ font-weight: 500;
275
+ text-decoration-line: underline;
276
+ text-decoration-style: dotted;
277
+ text-decoration-thickness: 1px;
278
+ text-underline-offset: 0.2em;
279
+ }
280
+
281
+ .prose :where(a[data-blume-card]) {
282
+ color: inherit;
283
+ font-weight: inherit;
284
+ text-decoration: none;
285
+ }
286
+
287
+ .prose :where(hr) {
288
+ margin: 2.5rem 0;
289
+ }
290
+
291
+ .prose :where(pre) {
292
+ background: transparent;
293
+ border: 1px solid var(--blume-border);
294
+ border-radius: var(--blume-radius);
295
+ color: var(--blume-foreground);
296
+ font-family: var(--font-mono);
297
+ font-size: 0.8125rem;
298
+ line-height: 1.55;
299
+ margin: 1.5rem 0;
300
+ overflow-x: auto;
301
+ padding: 1rem 1.25rem;
302
+ position: relative;
303
+ }
304
+
305
+ .prose :where(pre.astro-code) {
306
+ background: transparent !important;
307
+ color: var(--shiki-light, var(--blume-foreground)) !important;
308
+ }
309
+
310
+ :root[data-theme="dark"] .prose :where(pre.astro-code) {
311
+ color: var(--shiki-dark, var(--blume-foreground)) !important;
312
+ }
313
+
314
+ .prose :where(pre.astro-code span) {
315
+ background: transparent !important;
316
+ color: var(--shiki-light, inherit);
317
+ font-style: var(--shiki-light-font-style, inherit);
318
+ font-weight: var(--shiki-light-font-weight, inherit);
319
+ text-decoration: var(--shiki-light-text-decoration, inherit);
320
+ }
321
+
322
+ :root[data-theme="dark"] .prose :where(pre.astro-code span) {
323
+ color: var(--shiki-dark, inherit);
324
+ font-style: var(--shiki-dark-font-style, inherit);
325
+ font-weight: var(--shiki-dark-font-weight, inherit);
326
+ text-decoration: var(--shiki-dark-text-decoration, inherit);
327
+ }
328
+
329
+ /* The Diff component (@pierre/diffs) renders into a declarative shadow root and
330
+ themes itself with light-dark(). Drive that from Blume's data-theme instead
331
+ of the OS, scoped to the diff host: the custom property pierces the shadow
332
+ boundary, where the appended host color-scheme rule consumes it. */
333
+ blume-diff {
334
+ --blume-diff-color-scheme: light;
335
+ display: block;
336
+ }
337
+
338
+ :root[data-theme="dark"] blume-diff {
339
+ --blume-diff-color-scheme: dark;
340
+ }
341
+
342
+ .prose :where(pre[data-language]) {
343
+ padding-top: 3.75rem;
344
+ }
345
+
346
+ .prose :where(pre[data-language])::before {
347
+ align-items: center;
348
+ border-bottom: 1px solid var(--blume-border);
349
+ color: var(--blume-muted-foreground);
350
+ content: attr(data-language);
351
+ display: flex;
352
+ font-family: var(--font-sans);
353
+ font-size: 0.75rem;
354
+ font-weight: 500;
355
+ height: 2.75rem;
356
+ left: 0;
357
+ padding: 0 3.25rem 0 1rem;
358
+ position: absolute;
359
+ right: 0;
360
+ top: 0;
361
+ }
362
+
363
+ .prose :where(pre[data-title])::before {
364
+ content: attr(data-title);
365
+ }
366
+
367
+ /* Language icon (simple-icons) sits at the header's left edge; the label shifts
368
+ right to make room. Injected at build time by the language-icon transformer.
369
+ Shown only for top-level prose blocks, which have a header — flush code in
370
+ tabs and API panels is nested deeper, so the child combinator skips it. */
371
+ .blume-lang-icon {
372
+ display: none;
373
+ }
374
+
375
+ .prose > :where(pre[data-icon]) > .blume-lang-icon {
376
+ color: var(--blume-muted-foreground);
377
+ display: block;
378
+ height: 0.875rem;
379
+ left: 1rem;
380
+ position: absolute;
381
+ top: 0.875rem;
382
+ width: 0.875rem;
383
+ }
384
+
385
+ .prose > :where(pre[data-icon])::before {
386
+ padding-left: 2.5rem;
387
+ }
388
+
389
+ .prose :where(pre code) {
390
+ background: transparent;
391
+ border-radius: 0;
392
+ color: inherit;
393
+ font-size: inherit;
394
+ font-weight: 400;
395
+ padding: 0;
396
+ }
397
+
398
+ /* Word wrap (markdown.code.wrap): long lines wrap instead of scrolling. The
399
+ attribute is set on <body> from config; default code keeps \`white-space: pre\`. */
400
+ [data-blume-code-wrap] pre,
401
+ [data-blume-code-wrap] pre code {
402
+ overflow-wrap: break-word;
403
+ white-space: pre-wrap;
404
+ }
405
+
406
+ .prose :where(table) {
407
+ font-size: 0.8125rem;
408
+ }
409
+
410
+ blume-tabs pre,
411
+ .not-prose > div > pre {
412
+ background: var(--blume-code-background);
413
+ }
414
+
415
+ /* The Component source pane fills its tab's fixed height (set inline to match the
416
+ preview tab) and scrolls the inner code element, leaving the pre static so the
417
+ copy button — absolute, pinned to the pre — doesn't drift while it scrolls. */
418
+ pre.blume-source {
419
+ display: flex;
420
+ flex-direction: column;
421
+ height: 100%;
422
+ overflow: hidden;
423
+ }
424
+
425
+ pre.blume-source > code {
426
+ flex: 1;
427
+ min-height: 0;
428
+ overflow: auto;
429
+ }
430
+
431
+ /* Code blocks inside tabs sit flush; the tab container owns the frame. These
432
+ rules are unlayered like the base \`pre\` styles, so they win over Tailwind's
433
+ layered utilities (which a class on the panel cannot). The second selector
434
+ covers <CodeGroup>, where each code block IS the panel (a direct child of the
435
+ tab content wrapper) rather than a <pre> nested inside a <Tab>. */
436
+ blume-tabs [data-blume-tab-panel] > pre,
437
+ blume-tabs [data-blume-tab-content] > pre {
438
+ /* Important to beat the astro-code background rule above; the tab container
439
+ owns the surface, so the code sits directly on it. */
440
+ background: transparent !important;
441
+ border: 0;
442
+ border-radius: 0;
443
+ margin: 0;
444
+ }
445
+
446
+ blume-tabs pre[data-language],
447
+ .not-prose pre[data-language] {
448
+ padding-top: 1rem;
449
+ }
450
+
451
+ blume-tabs pre[data-language]::before,
452
+ .not-prose pre[data-language]::before {
453
+ content: none;
454
+ }
455
+
456
+ /* Pre-hydration layout-shift guard. The horizontal trigger row and
457
+ single-panel visibility are built by the <blume-tabs> custom element's JS:
458
+ until it upgrades, the trigger row is empty and every panel is in normal flow,
459
+ so the browser paints all panels stacked vertically (e.g. all four
460
+ package-manager commands at once) before JS hides them. While the element is
461
+ :not(:defined), show only the first panel and reserve the trigger row's height
462
+ so nothing jumps when JS takes over. The child selector covers both <Tab>
463
+ panels and <CodeGroup> raw code blocks (which only gain
464
+ [data-blume-tab-panel] from JS). */
465
+ blume-tabs:not(:defined) [data-blume-tab-content] > *:nth-child(n + 2) {
466
+ display: none;
467
+ }
468
+
469
+ blume-tabs:not(:defined) [data-blume-tablist] {
470
+ /* Matches a trigger's height: py-2.5 + text-xs line-height + border-b-2. */
471
+ min-height: 2.375rem;
472
+ }
473
+
474
+ blume-tabs:not(:defined)[data-dropdown="true"] [data-blume-tablist] {
475
+ /* Dropdown variant: p-3 padding around a select (py-2 + text-sm + border). */
476
+ min-height: 3.875rem;
477
+ }
478
+
479
+ /* Code blocks inside request/response example panels sit flush; the panel owns
480
+ the frame. Unlayered (like the tab rules) so they beat the base \`pre\` styles
481
+ that a class on the panel cannot. */
482
+ [data-blume-code-panel] pre {
483
+ background: transparent !important;
484
+ border: 0;
485
+ border-radius: 0;
486
+ margin: 0;
487
+ }
488
+
489
+ /* Opt-in line numbers (\`\`\`ts file.ts lineNumbers): a counter-driven gutter that
490
+ works in prose and flush (tab / API panel) code blocks alike. */
491
+ pre[data-line-numbers] code {
492
+ counter-reset: line;
493
+ }
494
+
495
+ pre[data-line-numbers] .line::before {
496
+ color: var(--blume-muted-foreground);
497
+ content: counter(line);
498
+ counter-increment: line;
499
+ display: inline-block;
500
+ margin-right: 1.25rem;
501
+ text-align: right;
502
+ user-select: none;
503
+ width: 1.25rem;
504
+ }
505
+
506
+ /* Shiki notation transformers (on by default). The notation comments are
507
+ stripped from the output; these style the classes they leave behind. A styled
508
+ line becomes a full-width inline-block so its background fills the row; plain
509
+ lines are left untouched, so blocks without notations render as before. */
510
+ .line.highlighted,
511
+ .line.diff {
512
+ display: inline-block;
513
+ width: 100%;
514
+ }
515
+
516
+ /* The backgrounds need !important to beat the \`pre.astro-code span\` rule above,
517
+ which forces token spans transparent; these line/word spans are exceptions. */
518
+ .line.highlighted {
519
+ background-color: var(--blume-code-highlight) !important;
520
+ box-shadow: inset 2px 0 0 0 var(--blume-code-highlight-border);
521
+ }
522
+
523
+ .line.diff.add {
524
+ background-color: var(--blume-code-add) !important;
525
+ box-shadow: inset 2px 0 0 0 var(--blume-code-add-border);
526
+ }
527
+
528
+ .line.diff.remove {
529
+ background-color: var(--blume-code-remove) !important;
530
+ box-shadow: inset 2px 0 0 0 var(--blume-code-remove-border);
531
+ }
532
+
533
+ /* Word highlight (\`// [!code word:x]\`) wraps matches in an inline span. The
534
+ element selector keeps it ahead of the transparent token-span rule. */
535
+ span.highlighted-word {
536
+ background-color: var(--blume-code-word) !important;
537
+ border-radius: 0.25rem;
538
+ box-shadow: 0 0 0 1px var(--blume-code-word-border);
539
+ padding: 0.1em 0.2em;
540
+ }
541
+
542
+ /* Focus (\`// [!code focus]\`): dim and blur the rest; reveal on hover. */
543
+ pre:has(.line.focused) .line:not(.focused) {
544
+ filter: blur(0.085rem);
545
+ opacity: 0.5;
546
+ transition:
547
+ filter 0.2s ease,
548
+ opacity 0.2s ease;
549
+ }
550
+
551
+ pre:has(.line.focused):hover .line:not(.focused) {
552
+ filter: none;
553
+ opacity: 1;
554
+ }
555
+
556
+ @media (prefers-reduced-motion: reduce) {
557
+ pre:has(.line.focused) .line:not(.focused) {
558
+ transition: none;
559
+ }
560
+ }
561
+
562
+ @media (max-width: 640px) {
563
+ .prose :where(h1) {
564
+ font-size: 2.25rem;
565
+ }
566
+
567
+ .prose :where(h2) {
568
+ font-size: 1.625rem;
569
+ }
570
+ }
571
+
572
+ .prose :not(pre) > code {
573
+ background: var(--blume-code-background);
574
+ padding: 0.15em 0.35em;
575
+ border-radius: 0.3rem;
576
+ font-family: var(--font-mono);
577
+ font-weight: 500;
578
+ }
579
+
580
+ .prose :not(pre) > code::before,
581
+ .prose :not(pre) > code::after {
582
+ content: none;
583
+ }
584
+
585
+ /* Inline code highlighting (markdown.code.inline): Shiki colors the tokens of a
586
+ \`code\`{:lang} snippet via the same dual-theme CSS variables as fenced blocks,
587
+ keeping the inline pill background. */
588
+ .prose code.blume-inline-code span {
589
+ color: var(--shiki-light);
590
+ }
591
+
592
+ :root[data-theme="dark"] .prose code.blume-inline-code span {
593
+ color: var(--shiki-dark);
594
+ }
595
+
596
+ /* Print / "Save as PDF" (the page-actions Export → PDF runs window.print()).
597
+ Strip the surrounding chrome so the printout is just the article. */
598
+ @media print {
599
+ [data-blume-banner],
600
+ header,
601
+ aside,
602
+ [data-blume-page-actions],
603
+ #blume-content > nav,
604
+ #blume-content > details {
605
+ display: none !important;
606
+ }
607
+
608
+ #blume-content {
609
+ padding: 0 !important;
610
+ }
611
+
612
+ .prose {
613
+ margin: 0 !important;
614
+ max-width: none !important;
615
+ }
616
+
617
+ /* Reveal collapsed tab panels so their content isn't dropped from the print. */
618
+ blume-tabs [data-blume-tab-panel] {
619
+ display: block !important;
620
+ }
621
+
622
+ /* Keep code/callout backgrounds (subject to the dialog's "Background graphics"
623
+ toggle). */
624
+ pre,
625
+ .prose :not(pre) > code {
626
+ -webkit-print-color-adjust: exact;
627
+ print-color-adjust: exact;
628
+ }
629
+ }
630
+
631
+ /* Twoslash rich-renderer styles (used by fences with the \`twoslash\` meta). */
632
+ ${options.twoslashCss ?? ""}
633
+
634
+ /* Token overrides: config first, then the user's theme.css (highest priority). */
635
+ ${options.configTokens}
636
+ ${options.userTheme}
637
+ `;