diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs
index b179d9b..d7bbfdf 100644
--- a/docs/astro.config.mjs
+++ b/docs/astro.config.mjs
@@ -32,6 +32,7 @@ export default defineConfig({
items: [
{ label: 'Getting Started', slug: 'guides/getting-started' },
{ label: 'Bring Your Own Renderer', slug: 'guides/renderers' },
+ { label: 'Styling', slug: 'guides/styling' },
{ label: 'Attributes', slug: 'guides/attributes' },
{ label: 'Properties', slug: 'guides/properties' },
{ label: 'API', slug: 'guides/api' },
diff --git a/docs/src/content/docs/guides/index.mdx b/docs/src/content/docs/guides/index.mdx
index c2ef52c..a91476f 100644
--- a/docs/src/content/docs/guides/index.mdx
+++ b/docs/src/content/docs/guides/index.mdx
@@ -12,22 +12,25 @@ import { Card, CardGrid } from '@astrojs/starlight/components';
Use your preferred templating library — Lit, htm, or a custom renderer.
-
+
+ Style components with adopted style sheets, css helpers, and CSS modules.
+
+
React to attribute changes on your custom elements.
-
+
Manage reactive properties with type-safe accessors.
-
+
Explore the full pion API reference.
-
+
Emit and listen to custom DOM events from hooks.
-
+
Compose lightweight components without custom element registration.
-
+
Get full type inference for hooks, props, and events.
diff --git a/docs/src/content/docs/guides/styling.md b/docs/src/content/docs/guides/styling.md
new file mode 100644
index 0000000..9ce49ab
--- /dev/null
+++ b/docs/src/content/docs/guides/styling.md
@@ -0,0 +1,147 @@
+---
+title: Styling
+description: Style pion components with constructable stylesheets — the css helper, the styleSheets option, native CSS modules, and light DOM alternatives.
+---
+
+pion components render into a [shadow root](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) by default, so their styles are naturally isolated from the page. pion uses [constructable stylesheets](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#applying_styles_inside_the_shadow_dom): styles are declared with the `css` helper and adopted on the component's shadow root via the `styleSheets` option — constructed once, shared by every instance of the component.
+
+## Component styles
+
+The recommended pattern is a dedicated style file next to your component. The file exports a `css` template; the component imports it and passes it to `component()`:
+
+```js
+// my-app.style.ts
+import { css } from '@pionjs/pion';
+
+export const style = css`
+ :host {
+ display: block;
+ padding: 1rem;
+ }
+ .content {
+ color: var(--my-app-color, currentColor);
+ }
+`;
+```
+
+```js
+// my-app.ts
+import { component, html } from '@pionjs/pion';
+import { style } from './my-app.style';
+
+function App() {
+ return html`Hello!
`;
+}
+
+customElements.define('my-app', component(App, { styleSheets: [style] }));
+```
+
+This keeps the component function focused on behavior, and makes styles reusable across components.
+
+`styleSheets` accepts a mix of strings and `CSSStyleSheet` instances — strings are converted to stylesheets automatically.
+
+### The `css` tagged template
+
+`css` is a tagged template that returns a plain string. It supports interpolation, which makes it easy to compose styles or build themes from parts:
+
+```js
+import { css } from '@pionjs/pion';
+
+const base = css`
+ :host { display: block; }
+`;
+
+const theme = css`
+ :host { --my-app-color: rebeccapurple; }
+`;
+
+export const style = css`
+ ${base}
+ ${theme}
+ .content { color: var(--my-app-color); }
+`;
+```
+
+:::caution
+Since `css` returns a string, interpolating a value like `0` or `false` results in an empty string (falsy values are dropped). Coerce interpolated values to strings when in doubt.
+:::
+
+### Attaching styles to the renderer function
+
+Instead of the options object, you can set `styleSheets` as a static property on the component function itself:
+
+```js
+function App() {
+ return html`Hello!
`;
+}
+
+App.styleSheets = [style];
+
+customElements.define('my-app', component(App));
+```
+
+If both are provided, the renderer's `styleSheets` take precedence over the ones passed to `component()`.
+
+### The `sheet()` helper
+
+If you need a `CSSStyleSheet` directly (for example to adopt it on a document or another shadow root), use the `sheet` helper:
+
+```js
+import { sheet } from '@pionjs/pion';
+
+const styles = sheet(':host { display: block; }', '.content { color: red; }');
+
+document.adoptedStyleSheets = [...document.adoptedStyleSheets, styles];
+```
+
+## Native CSS modules
+
+With the [CSS modules](https://developer.chrome.com/docs/css-ui/css-modules) import attribute (`with { type: 'css' }`), the browser hands you a ready-made `CSSStyleSheet`. Since `styleSheets` accepts existing instances, they work out of the box:
+
+```js
+import { component, html } from '@pionjs/pion';
+import styles from './my-app.css' with { type: 'css' };
+
+function App() {
+ return html`Hello!
`;
+}
+
+customElements.define('my-app', component(App, { styleSheets: [styles] }));
+```
+
+Bundler notes:
+
+- **Vite** and **Rollup** support `with { type: 'css' }` — the imported value is a constructed stylesheet that adopts cleanly into shadow roots.
+- This syntax requires a modern browser or a bundler that transforms it; it does **not** work from a plain `