diff --git a/docs/themes.md.ts b/docs/themes.md.ts
index 7f4d347de..1a8d6d23d 100644
--- a/docs/themes.md.ts
+++ b/docs/themes.md.ts
@@ -101,6 +101,8 @@ ${themes.dark.map((theme) => `- \`${theme}\`${theme === dark ? " (default)" : ""
When both a light and a dark mode theme are specified, theme styles are applied selectively based on the user’s preferred color scheme. This is implemented via [\`prefers-color-scheme\`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) and typically relies on the user’s operating system settings.
+Light themes set the [color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme) property to \`light\`, and dark themes set it to \`dark\`. This property is reflected as a \`light\` or \`dark\` class added to the page’s \`body\` element, allowing you to use the \`.light\` and \`.dark\` CSS selectors. (See also the [dark](./lib/generators#dark) generator.)
+
On macOS, you can create a menubar shortcut to quickly toggle between light and dark mode. This is useful for testing.
Designing charts that work well in both light and dark mode can be challenging. If you’d prefer to design for only one mode, set the theme explicitly to light or dark.
diff --git a/src/client/dark.js b/src/client/dark.js
new file mode 100644
index 000000000..f8832e76e
--- /dev/null
+++ b/src/client/dark.js
@@ -0,0 +1,9 @@
+import {Generators} from "observablehq:stdlib";
+
+(async () => {
+ for await (const dark of Generators.dark()) {
+ const {classList} = document.body;
+ classList.toggle("dark", dark);
+ classList.toggle("light", !dark);
+ }
+})();
diff --git a/src/client/index.js b/src/client/index.js
index a0585a6a7..a74432ea9 100644
--- a/src/client/index.js
+++ b/src/client/index.js
@@ -1,5 +1,6 @@
import "./pre.js";
import "./sidebar.js";
import "./toc.js";
+import "./dark.js";
export {define} from "./main.js";
diff --git a/test/output/build/npm/_observablehq/stdlib/inputs.00000006.js b/test/output/build/duckdb/_observablehq/stdlib/inputs.00000006.js
similarity index 100%
rename from test/output/build/npm/_observablehq/stdlib/inputs.00000006.js
rename to test/output/build/duckdb/_observablehq/stdlib/inputs.00000006.js
diff --git a/test/output/build/duckdb/_observablehq/stdlib/inputs.00000006.css b/test/output/build/duckdb/_observablehq/stdlib/inputs.00000007.css
similarity index 100%
rename from test/output/build/duckdb/_observablehq/stdlib/inputs.00000006.css
rename to test/output/build/duckdb/_observablehq/stdlib/inputs.00000007.css
diff --git a/test/output/build/duckdb/index.html b/test/output/build/duckdb/index.html
index 9028d12f2..b0ceaf67b 100644
--- a/test/output/build/duckdb/index.html
+++ b/test/output/build/duckdb/index.html
@@ -8,15 +8,15 @@
-
+
-
+
-
+
diff --git a/test/output/build/npm/_import/index.4bdc071f.js b/test/output/build/npm/_import/index.4bdc071f.js
index 9b6843f78..108b15a25 100644
--- a/test/output/build/npm/_import/index.4bdc071f.js
+++ b/test/output/build/npm/_import/index.4bdc071f.js
@@ -1 +1 @@
-import "../_observablehq/stdlib/inputs.00000006.js";
+import "../_observablehq/stdlib/inputs.00000005.js";
diff --git a/test/output/build/duckdb/_observablehq/stdlib/inputs.00000007.js b/test/output/build/npm/_observablehq/stdlib/inputs.00000005.js
similarity index 100%
rename from test/output/build/duckdb/_observablehq/stdlib/inputs.00000007.js
rename to test/output/build/npm/_observablehq/stdlib/inputs.00000005.js
diff --git a/test/output/build/sql/_observablehq/stdlib/inputs.00000006.css b/test/output/build/npm/_observablehq/stdlib/inputs.00000006.css
similarity index 100%
rename from test/output/build/sql/_observablehq/stdlib/inputs.00000006.css
rename to test/output/build/npm/_observablehq/stdlib/inputs.00000006.css
diff --git a/test/output/build/npm/index.html b/test/output/build/npm/index.html
index 24dcc3f28..64771f980 100644
--- a/test/output/build/npm/index.html
+++ b/test/output/build/npm/index.html
@@ -7,15 +7,15 @@
-
+
-
+
-
+