diff --git a/resources/boost/skills/livewire-material-development/SKILL.md b/resources/boost/skills/livewire-material-development/SKILL.md
index 751cb3d8..e8ba0de9 100644
--- a/resources/boost/skills/livewire-material-development/SKILL.md
+++ b/resources/boost/skills/livewire-material-development/SKILL.md
@@ -783,6 +783,25 @@ Breakpoints are M3's five, in px: compact below 600, `medium` 600, `expanded` 84
M3's margin — 16px on a compact window, 24px from `medium` — is drawn once: by the scaffold's content region, or by the outermost pane or canonical layout when there is no scaffold. A pane inside one of those draws none, and one on an ``, a new edge, draws it again.
+#### ``
+
+A content region: M3 puts all content in panes, and each may carry its own top app bar.
+
+```blade
+
+
+
+
+ …
+
+```
+
+- The body keeps M3's margin (16px below `medium`, 24px from it) unless something around it already does — the scaffold's content region, a canonical layout, another pane's body; on an `` it keeps it again.
+- `width`: `full` (default, the room it has), `narrow` (40rem, M3's 40–60 characters a line), `medium` (60rem), `wide` (80rem); capped widths are centred.
+- The app bar is an ``, a direct child of the pane so it spans the pane and stays sticky for its height; it is drawn when there is a `title`, `actions`, a `leading` slot or `back`. `title`, `subtitle`, `heading` (`h1` default — the second pane of a canonical layout passes `h2`), `sticky` (default true), the `actions` slot.
+- The bar's leading button: the `leading` slot, or `back` — a URL makes it a link, `true` calls `back()` from `` around it (hidden there where both panes show). The arrow mirrors in a right-to-left document.
+- `navigation` is the pane's section navigation (``, ``), under the bar and above the body with the body's margins — not the bar's leading button.
+
#### ``
A tonal region: `…`.
diff --git a/resources/css/layout.css b/resources/css/layout.css
index ab0f41e5..5a1dc00a 100644
--- a/resources/css/layout.css
+++ b/resources/css/layout.css
@@ -10,3 +10,4 @@
@import './layout/row.css';
@import './layout/grid.css';
@import './layout/surface.css';
+@import './layout/pane.css';
diff --git a/resources/css/layout/pane.css b/resources/css/layout/pane.css
new file mode 100644
index 00000000..3f3ac44a
--- /dev/null
+++ b/resources/css/layout/pane.css
@@ -0,0 +1,72 @@
+/*
+ * : a content region, with M3's margins and, optionally, a top app bar of its own.
+ *
+ * M3 puts all content in panes (docs/reference/m3/foundations.md § Layout → Scaffold, "all content
+ * must live in a pane") and lets each carry its own app bar. The margin is the space between the
+ * window's edge and what is inside: 16px below medium and 24px from it (600px), from the
+ * per-breakpoint table in docs/reference/m3/foundations-supplement.md § Breakpoints, as
+ * `--md-sys-measurement-space200` and `space300`.
+ *
+ * The margin sits on the pane's body and its section navigation, not on the pane: the app bar is a
+ * direct child of the pane, so it spans the pane from edge to edge and its `position: sticky` holds
+ * for the pane's whole height (a sticky element never leaves its parent). A margin is drawn once:
+ * a region that already keeps its content off the window's edge — a pane's body, the canonical
+ * layouts, the scaffold's content region — sets `--md-layout-margin` to 0px for what is inside it,
+ * and a pane there draws none of its own, until an gives it a new edge to keep off.
+ *
+ * `data-md-width` caps the pane and centres it: `narrow` 40rem, M3's 40–60 characters a line
+ * (§ Layout → Breakpoints, "keep text to 40–60 characters per line"), in rem because it is a measure
+ * of text; `medium` 60rem and `wide` 80rem are the package's steps above it; `full` (the default)
+ * fills the room it has, M3's flexible pane. The back button of `data-md-pane-back` points the
+ * way it goes, so it mirrors in a right-to-left document (§ Layout → Bidirectionality / RTL).
+ *
+ * In `material.layout`; `hide-below`/`hide-from` come from visibility.css.
+ */
+
+@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
+
+@import './visibility.css';
+
+@layer material.layout {
+ [data-md-pane] {
+ display: flex;
+ flex-direction: column;
+ inline-size: 100%;
+ min-inline-size: 0;
+ margin-inline: auto;
+ }
+
+ [data-md-pane][data-md-width='narrow'] {
+ max-inline-size: 40rem;
+ }
+
+ [data-md-pane][data-md-width='medium'] {
+ max-inline-size: 60rem;
+ }
+
+ [data-md-pane][data-md-width='wide'] {
+ max-inline-size: 80rem;
+ }
+
+ [data-md-pane-navigation],
+ [data-md-pane-body] {
+ padding-inline: var(--md-layout-margin, var(--md-sys-measurement-space200));
+
+ @media (width >= 600px) {
+ padding-inline: var(--md-layout-margin, var(--md-sys-measurement-space300));
+ }
+ }
+
+ [data-md-pane-body] {
+ flex: 1 1 auto;
+ min-inline-size: 0;
+ }
+
+ [data-md-pane-body] > * {
+ --md-layout-margin: 0px;
+ }
+
+ [data-md-pane-back] [data-md-icon]:dir(rtl) {
+ transform: scaleX(-1);
+ }
+}
diff --git a/resources/views/components/pane.blade.php b/resources/views/components/pane.blade.php
new file mode 100644
index 00000000..e978c360
--- /dev/null
+++ b/resources/views/components/pane.blade.php
@@ -0,0 +1,88 @@
+{{-- A pane: a content region with M3's margins, and its own top app bar if it has a title.
+
+
+
+
+ …
+
+
+ M3 puts every piece of content in a pane and lets each carry its own top app bar
+ (docs/reference/m3/foundations.md § Layout → Scaffold). The body is kept off the window's edge
+ by M3's margin, 16px below medium (600px) and 24px from it
+ (docs/reference/m3/foundations-supplement.md § Breakpoints); a pane inside something that
+ already keeps that margin — the scaffold's content region, a canonical layout, another pane's
+ body — draws none, so the margin is never doubled; on an `` it draws it again.
+
+ `width` caps the pane and centres it: `narrow` (40rem, M3's 40–60 characters a line),
+ `medium` (60rem), `wide` (80rem) or `full` (the default, all the room it has).
+
+ The app bar is ``, drawn when there is a `title`, `actions`, a `leading` slot or
+ `back`: `title` and `subtitle`, `heading` (`h1` by default; the second pane of a canonical
+ layout passes `h2`), `sticky` (true: it holds to the top of the window for as long as the pane
+ is on screen), the `actions` slot at its end. Its leading icon button is the `leading` slot,
+ or `back`: a URL makes it a link back there, and `true` calls `back()` in the Alpine scope
+ around it, which `` provides — and which it hides where both panes show, as M3
+ shows a back button only in a single-pane list-detail. The back arrow mirrors in a
+ right-to-left document.
+
+ `navigation` is the pane's section navigation (``, ``), under the bar
+ and above the body, with the body's margins; it is not the bar's leading button.
+
+ It takes `as` (`div` by default: `section`, `article`, `main` …), `hide-below` and `hide-from`
+ like every layout component, and the caller's `class` and `style` land on it untouched. Drawn
+ by resources/css/layout/pane.css. --}}
+
+@props([
+ 'as' => null,
+ 'title' => null,
+ 'subtitle' => null,
+ 'heading' => 'h1',
+ 'sticky' => true,
+ 'back' => null,
+ 'width' => null,
+ 'hideBelow' => null,
+ 'hideFrom' => null,
+])
+
+@php
+ $layout = \NoNameWeb\LivewireMaterial\Support\Layout::class;
+ $element = $layout::element($as);
+ $backLink = is_string($back) && $back !== '' ? $back : null;
+ $backAction = $back === true;
+ $bar = filled($title) || isset($actions) || isset($leading) || $backLink !== null || $backAction;
+
+ $attributes = $attributes->merge(array_filter([
+ 'data-md-pane' => true,
+ 'data-md-width' => $layout::choice($width, ['full', 'narrow', 'medium', 'wide']),
+ ] + $layout::visibility($hideBelow, $hideFrom), fn ($value): bool => $value !== null));
+@endphp
+
+<{{ $element }} {{ $attributes }}>
+ @if ($bar)
+
+ @if (isset($leading))
+ {{ $leading }}
+ @elseif ($backLink !== null || $backAction)
+
+
+ @if ($backLink !== null)
+
+ @else
+
+ @endif
+
+
+ @endif
+
+ @isset($actions)
+ {{ $actions }}
+ @endisset
+
+ @endif
+
+ @isset($navigation)
+
<x-pane> — a content region with M3's margins and its own app bar.
<x-surface> — a tonal region: a surface role, padding, a corner and an outline.
<x-stack>, <x-row> and <x-grid> — arrangement inside a pane.
diff --git a/tests/Browser/LayoutTest.php b/tests/Browser/LayoutTest.php
index d4ae986e..48638a9d 100644
--- a/tests/Browser/LayoutTest.php
+++ b/tests/Browser/LayoutTest.php
@@ -142,3 +142,31 @@ it('draws a surface in its role, padding and corner, and hides it below a breakp
->assertScript(layoutStyle('#surface', 'borderTopWidth')." === '1px'")
->assertNoJavaScriptErrors();
});
+
+it('keeps M3\'s margin in a pane, once, with its app bar across the whole pane', function () {
+ $body = <<<'BLADE'
+
+
The page<\/div>/')
+ ->not->toContain('data-app-bar')
+ ->not->toContain('data-md-pane-navigation');
+});
+
+it('gives the pane its own app bar, a direct child spanning it, with the title, subtitle and actions', function () {
+ $html = (string) $this->blade(<<<'BLADE'
+
+ ACTIONS
+ BODY
+
+ BLADE);
+
+ expect($html)
+ ->toMatch('/^\s*
\s*BODY\s*<\/div>/s')
+ ->and((string) $this->blade(''))->not->toContain('data-sticky');
+});
+
+it('draws a bar for actions alone, and names the heading h1 by default', function () {
+ expect((string) $this->blade('ACTIONS'))->toContain('data-md-pane-bar')
+ ->and((string) $this->blade(''))->toContain('
Inbox
');
+});
+
+it('puts the section navigation under the bar and above the body', function () {
+ $html = (string) $this->blade(<<<'BLADE'
+
+
+ BODY
+
+ BLADE);
+
+ expect($html)->toMatch('/<\/header>\s*