Boundary#
Component <neo-boundary> is a logical scoping region for overlays. An overlay inside it (Popover, Menu, Select, Combobox, or Text input suggestions) treats the boundary as its local document and viewport. Its scope attribute is a space-separated token list that defaults to "dismiss positioning": outside clicks and focus no longer dismiss the overlay, and its panel clamps to the region instead of the viewport. Setting scope replaces that default, so add a token to opt into a scope or drop one to turn it off. The scroll token lets independent scrollers outside the region move without closing the overlay; stacking layers the region's overlays inside it rather than the document root. Both are off by default. The element is layout-neutral (display: contents) until stacking gives it a box, and never clips a panel. Escape and trigger toggles always close an overlay.
Reference#
Attributes #
| Name | Type | Default | Description |
|---|---|---|---|
scope | "dismiss" | "positioning" | "scroll" | "stacking" (space-separated) | "dismiss positioning" | Space-separated list of the scopes this region applies. Setting it replaces the default (dismiss positioning) entirely, so list every scope you want; omit a token to fall back to the document / viewport default for it, and scope="" scopes nothing. Tokens: dismiss: a pointer or focus event outside the boundary does not close an overlay inside it (only events inside the boundary but outside the overlay do). positioning: overlay panels clamp and flip against this region's box (the union of the boundary's laid-out descendant rects) instead of the viewport. scroll: a genuinely independent scroll container outside this region can move without closing an embedded overlay; a scroll inside the region, or on an ancestor scroller that carries the region, still dismisses. stacking: the region establishes a local stacking context (isolation: isolate) so its overlays layer inside it, not the document root; this is the one scope that drops display: contents for a box. |
Slots #
| Name | Description |
|---|---|
| default | The content the boundary scopes. Each overlay inside reads its nearest <neo-boundary> ancestor (via closest("neo-boundary")) and obeys that boundary's scopes only. Rules are not inherited: a closer boundary that turns a scope off falls back to the document or viewport default for that scope, not to an outer boundary. Scoping is purely logical (composed-path containment) and non-visual, so a fixed or top-layer panel still counts as inside through its host even though it paints outside the boundary's box. |
Examples#
Scoped dismiss#
Two regions, each a <neo-boundary>. Open an overlay in one, then click or open something in the other: the first stays open, because each boundary scopes dismiss to itself. Without boundaries, the second interaction would close the first.
Actions
Rename, archive, or delete.
Actions
Rename, archive, or delete.
<neo-layout row wrap align-items="stretch" gap="lg">
<neo-boundary>
<div
neo-flex-grow="1"
neo-flex-basis="0"
class="boundary-scoped-dismiss-panel"
>
<strong>Project A</strong>
<neo-popover
placement="bottom-start"
follow-scroll="until-trigger-invisible"
>
<neo-button data-neo-popover-trigger>Actions</neo-button>
<div data-neo-popover-content>
<h3 class="boundary-scoped-dismiss-heading">Actions</h3>
<p class="boundary-scoped-dismiss-note">Rename, archive, or delete.</p>
</div>
</neo-popover>
<neo-select
placeholder="Pick a status"
aria-label="Status (Project A)"
follow-scroll="until-trigger-invisible"
class="boundary-scoped-dismiss-field"
>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="todo"
data-neo-value="todo"
>To do</neo-option>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="doing"
data-neo-value="doing"
>In progress</neo-option>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="done"
data-neo-value="done"
>Done</neo-option>
</neo-select>
<neo-combobox
placeholder="Pick an assignee"
search-placeholder="Search…"
aria-label="Assignee (Project A)"
follow-scroll="until-trigger-invisible"
class="boundary-scoped-dismiss-field"
>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="alice"
data-neo-value="alice"
>Alice Larsson</neo-option>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="diego"
data-neo-value="diego"
>Diego Vega</neo-option>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="evelyn"
data-neo-value="evelyn"
>Evelyn Kone</neo-option>
</neo-combobox>
</div>
</neo-boundary>
<neo-boundary>
<div
neo-flex-grow="1"
neo-flex-basis="0"
class="boundary-scoped-dismiss-panel"
>
<strong>Project B</strong>
<neo-popover
placement="bottom-start"
follow-scroll="until-trigger-invisible"
>
<neo-button data-neo-popover-trigger>Actions</neo-button>
<div data-neo-popover-content>
<h3 class="boundary-scoped-dismiss-heading">Actions</h3>
<p class="boundary-scoped-dismiss-note">Rename, archive, or delete.</p>
</div>
</neo-popover>
<neo-select
placeholder="Pick a status"
aria-label="Status (Project B)"
follow-scroll="until-trigger-invisible"
class="boundary-scoped-dismiss-field"
>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="backlog"
data-neo-value="backlog"
>Backlog</neo-option>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="active"
data-neo-value="active"
>Active</neo-option>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="shipped"
data-neo-value="shipped"
>Shipped</neo-option>
</neo-select>
<neo-combobox
placeholder="Pick an assignee"
search-placeholder="Search…"
aria-label="Assignee (Project B)"
follow-scroll="until-trigger-invisible"
class="boundary-scoped-dismiss-field"
>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="samira"
data-neo-value="samira"
>Samira Khalil</neo-option>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="theo"
data-neo-value="theo"
>Theo Becker</neo-option>
<neo-option
role="option"
tabindex="-1"
aria-selected="false"
value="jan"
data-neo-value="jan"
>Jan O'Sullivan</neo-option>
</neo-combobox>
</div>
</neo-boundary>
</neo-layout>package examples
import "github.com/romshark/morpheus/neo"
templ BoundaryScopedDismiss() {
@neo.Layout(neo.LayoutOpts{
Direction: neo.Set(neo.Row),
Wrap: neo.Set(neo.Wrap),
Gap: neo.Set(neo.GapLg),
AlignItems: neo.Set(neo.AlignItemsStretch),
}) {
@neo.Boundary(neo.BoundaryOpts{}) {
<div neo-flex-grow="1" neo-flex-basis="0" class="boundary-scoped-dismiss-panel">
<strong>Project A</strong>
@neo.Popover(neo.PopoverOpts{
Placement: neo.Set(neo.PlacementBottomStart),
FollowScroll: neo.Set(neo.PopoverFollowScrollUntilTriggerInvisible),
}) {
<neo-button { neo.PopoverTrigger()... }>Actions</neo-button>
<div { neo.PopoverContent()... }>
<h3 class="boundary-scoped-dismiss-heading">Actions</h3>
<p class="boundary-scoped-dismiss-note">Rename, archive, or delete.</p>
</div>
}
@neo.SelectAttrs(neo.SelectOpts{
AriaLabel: neo.Set("Status (Project A)"),
Placeholder: neo.Set("Pick a status"),
}, templ.Attributes{"class": "boundary-scoped-dismiss-field"}) {
@neo.Option(neo.OptionOpts{Value: neo.Set("todo")}) {
To do
}
@neo.Option(neo.OptionOpts{Value: neo.Set("doing")}) {
In progress
}
@neo.Option(neo.OptionOpts{Value: neo.Set("done")}) {
Done
}
}
@neo.ComboboxAttrs(neo.ComboboxOpts{
AriaLabel: neo.Set("Assignee (Project A)"),
Placeholder: neo.Set("Pick an assignee"),
SearchPlaceholder: neo.Set("Search…"),
}, templ.Attributes{"class": "boundary-scoped-dismiss-field"}) {
@neo.Option(neo.OptionOpts{Value: neo.Set("alice")}) {
Alice Larsson
}
@neo.Option(neo.OptionOpts{Value: neo.Set("diego")}) {
Diego Vega
}
@neo.Option(neo.OptionOpts{Value: neo.Set("evelyn")}) {
Evelyn Kone
}
}
</div>
}
@neo.Boundary(neo.BoundaryOpts{}) {
<div neo-flex-grow="1" neo-flex-basis="0" class="boundary-scoped-dismiss-panel">
<strong>Project B</strong>
@neo.Popover(neo.PopoverOpts{
Placement: neo.Set(neo.PlacementBottomStart),
FollowScroll: neo.Set(neo.PopoverFollowScrollUntilTriggerInvisible),
}) {
<neo-button { neo.PopoverTrigger()... }>Actions</neo-button>
<div { neo.PopoverContent()... }>
<h3 class="boundary-scoped-dismiss-heading">Actions</h3>
<p class="boundary-scoped-dismiss-note">Rename, archive, or delete.</p>
</div>
}
@neo.SelectAttrs(neo.SelectOpts{
AriaLabel: neo.Set("Status (Project B)"),
Placeholder: neo.Set("Pick a status"),
}, templ.Attributes{"class": "boundary-scoped-dismiss-field"}) {
@neo.Option(neo.OptionOpts{Value: neo.Set("backlog")}) {
Backlog
}
@neo.Option(neo.OptionOpts{Value: neo.Set("active")}) {
Active
}
@neo.Option(neo.OptionOpts{Value: neo.Set("shipped")}) {
Shipped
}
}
@neo.ComboboxAttrs(neo.ComboboxOpts{
AriaLabel: neo.Set("Assignee (Project B)"),
Placeholder: neo.Set("Pick an assignee"),
SearchPlaceholder: neo.Set("Search…"),
}, templ.Attributes{"class": "boundary-scoped-dismiss-field"}) {
@neo.Option(neo.OptionOpts{Value: neo.Set("samira")}) {
Samira Khalil
}
@neo.Option(neo.OptionOpts{Value: neo.Set("theo")}) {
Theo Becker
}
@neo.Option(neo.OptionOpts{Value: neo.Set("jan")}) {
Jan O'Sullivan
}
}
</div>
}
}
}
.boundary-scoped-dismiss-panel {
min-width: 15rem;
padding: 1.25rem;
border: 1px dashed var(--muted);
border-radius: var(--page-radius);
display: flex;
flex-direction: column;
gap: 0.75rem;
align-items: flex-start;
}
.boundary-scoped-dismiss-heading {
margin: 0 0 0.25rem;
}
.boundary-scoped-dismiss-note {
margin: 0;
color: var(--muted);
}
.boundary-scoped-dismiss-field {
width: 12rem;
}
Positioning containment#
Open the popover. The panel clamps and flips against the dashed region instead of the viewport. The trigger sits at the region's bottom edge, so the panel flips above it to stay inside. Set scope="dismiss" to clamp to the viewport instead.
Filters
The panel is clamped to the dashed region instead of the viewport, so it flips above the trigger to stay inside. Drop the positioning token from scope to clamp to the viewport instead.
<neo-boundary>
<div class="boundary-positioning-region">
<neo-popover placement="bottom" follow-scroll="until-trigger-invisible">
<neo-button data-neo-popover-trigger>Filters</neo-button>
<div data-neo-popover-content>
<h3 class="boundary-positioning-heading">Filters</h3>
<p class="boundary-positioning-body">The panel is clamped to the dashed region instead of the viewport, so it flips above the trigger to stay inside. Drop the <code>positioning</code> token from <code>scope</code> to clamp to the viewport instead.</p>
</div>
</neo-popover>
</div>
</neo-boundary>package examples
import "github.com/romshark/morpheus/neo"
templ BoundaryPositioning() {
@neo.Boundary(neo.BoundaryOpts{}) {
<div class="boundary-positioning-region">
@neo.Popover(neo.PopoverOpts{
Placement: neo.Set(neo.PlacementBottom),
FollowScroll: neo.Set(neo.PopoverFollowScrollUntilTriggerInvisible),
}) {
<neo-button { neo.PopoverTrigger()... }>Filters</neo-button>
<div { neo.PopoverContent()... }>
<h3 class="boundary-positioning-heading">Filters</h3>
<p class="boundary-positioning-body">
The panel is clamped to the dashed region instead of the viewport, so it
flips above the trigger to stay inside. Drop the <code>positioning</code>
token from <code>scope</code> to clamp to the viewport instead.
</p>
</div>
}
</div>
}
}
.boundary-positioning-region {
height: 13rem;
padding: 1rem;
border: 1px dashed var(--muted);
border-radius: var(--page-radius);
display: flex;
align-items: flex-end;
justify-content: center;
}
.boundary-positioning-heading {
margin: 0 0 0.25rem;
}
.boundary-positioning-body {
margin: 0;
}
Scroll scope#
The Account menu is an embedded widget inside a scrollable panel; its boundary adds the scroll token (scope="dismiss positioning scroll"). Open the menu, then scroll the panel around it: because that scroller carries the boundary itself, the popover closes instead of floating through the container. Independent scrollers outside the boundary can move without dismissing it.
Diego Vega commented on Onboarding flow.
Evelyn Kone merged Release 2.4.
Account
Signed in as Alice Larsson.
An embedded widget, scoped by its own <neo-boundary>.
Samira Khalil opened Billing audit.
Theo Becker closed Flaky e2e test.
Jan O'Sullivan updated Design tokens.
Alice Larsson archived Q3 planning.
Maya Lindqvist pinned the Roadmap.
<div class="boundary-scroll">
<p class="boundary-scroll-line">Diego Vega commented on Onboarding flow.</p>
<p class="boundary-scroll-line">Evelyn Kone merged Release 2.4.</p>
<neo-boundary scope="dismiss positioning scroll">
<div class="boundary-scroll-widget">
<neo-popover placement="bottom-start">
<neo-button data-neo-popover-trigger>Account</neo-button>
<div data-neo-popover-content>
<h3 class="boundary-scroll-heading">Account</h3>
<p class="boundary-scroll-line">Signed in as Alice Larsson.</p>
</div>
</neo-popover>
<p class="boundary-scroll-line">An embedded widget, scoped by its own <code><neo-boundary></code>.</p>
</div>
</neo-boundary>
<p class="boundary-scroll-line">Samira Khalil opened Billing audit.</p>
<p class="boundary-scroll-line">Theo Becker closed Flaky e2e test.</p>
<p class="boundary-scroll-line">Jan O'Sullivan updated Design tokens.</p>
<p class="boundary-scroll-line">Alice Larsson archived Q3 planning.</p>
<p class="boundary-scroll-line">Maya Lindqvist pinned the Roadmap.</p>
</div>package examples
import "github.com/romshark/morpheus/neo"
templ BoundaryScroll() {
<div class="boundary-scroll">
<p class="boundary-scroll-line">Diego Vega commented on Onboarding flow.</p>
<p class="boundary-scroll-line">Evelyn Kone merged Release 2.4.</p>
@neo.Boundary(neo.BoundaryOpts{Scopes: neo.Set(neo.BoundaryScopes{Scroll: true})}) {
<div class="boundary-scroll-widget">
@neo.Popover(neo.PopoverOpts{Placement: neo.Set(neo.PlacementBottomStart)}) {
<neo-button { neo.PopoverTrigger()... }>Account</neo-button>
<div { neo.PopoverContent()... }>
<h3 class="boundary-scroll-heading">Account</h3>
<p class="boundary-scroll-line">Signed in as Alice Larsson.</p>
</div>
}
<p class="boundary-scroll-line">An embedded widget, scoped by its own <code>{ "<neo-boundary>" }</code>.</p>
</div>
}
<p class="boundary-scroll-line">Samira Khalil opened Billing audit.</p>
<p class="boundary-scroll-line">Theo Becker closed Flaky e2e test.</p>
<p class="boundary-scroll-line">Jan O'Sullivan updated Design tokens.</p>
<p class="boundary-scroll-line">Alice Larsson archived Q3 planning.</p>
<p class="boundary-scroll-line">Maya Lindqvist pinned the Roadmap.</p>
</div>
}
.boundary-scroll {
height: 14rem;
overflow-y: auto;
padding: 1.25rem;
border: 1px solid var(--muted);
border-radius: var(--page-radius);
display: flex;
flex-direction: column;
gap: 1rem;
}
.boundary-scroll-line {
margin: 0;
color: var(--muted);
}
.boundary-scroll-widget {
padding: 1rem;
border: 1px dashed var(--muted);
border-radius: var(--page-radius);
display: flex;
flex-direction: column;
gap: 0.6rem;
align-items: flex-start;
}
.boundary-scroll-heading {
margin: 0 0 0.25rem;
}
Stacking scope#
Stacking scope is opt-in: the right widget adds the stacking token to establish a local stacking context, so its overlays layer inside the region instead of the document root. Both widgets open the same popover (global z-index: 1000) across a host overlay at z-index: 100.
- Left (default): no stacking context, so the panel outranks the host overlay and paints over it.
- Right (
stacking): the panel is confined to the region's context, so the host overlay paints over it instead.
Open both popovers to compare. Enabling stacking gives the region a box (isolation: isolate), the one scope that drops display: contents.
Default
Account
Signed in as Alice Larsson.
Plan: Team · 4 seats
No stacking context, so the panel's z-index 1000 paints over the host overlay.
stacking
Account
Signed in as Alice Larsson.
Plan: Team · 4 seats
A local stacking context confines the panel, so the host overlay paints over it.
<div class="boundary-stacking">
<div class="boundary-stacking-overlay">Host app overlay · z-index 100</div>
<div class="boundary-stacking-row">
<div class="boundary-stacking-col">
<neo-boundary>
<div class="boundary-stacking-panel">
<p class="boundary-stacking-label">Default</p>
<neo-popover placement="bottom-start">
<neo-button data-neo-popover-trigger>Account</neo-button>
<div data-neo-popover-content>
<h3 class="boundary-stacking-heading">Account</h3>
<p class="boundary-stacking-line">Signed in as Alice Larsson.</p>
<p class="boundary-stacking-line-sm">Plan: Team · 4 seats</p>
<p class="boundary-stacking-line-muted">No stacking context, so the panel's z-index 1000 paints over the host overlay.</p>
</div>
</neo-popover>
</div>
</neo-boundary>
</div>
<div class="boundary-stacking-col">
<neo-boundary scope="dismiss positioning stacking">
<div class="boundary-stacking-panel">
<p class="boundary-stacking-label">stacking</p>
<neo-popover placement="bottom-start">
<neo-button data-neo-popover-trigger>Account</neo-button>
<div data-neo-popover-content>
<h3 class="boundary-stacking-heading">Account</h3>
<p class="boundary-stacking-line">Signed in as Alice Larsson.</p>
<p class="boundary-stacking-line-sm">Plan: Team · 4 seats</p>
<p class="boundary-stacking-line-muted">A local stacking context confines the panel, so the host overlay paints over it.</p>
</div>
</neo-popover>
</div>
</neo-boundary>
</div>
</div>
</div>package examples
import "github.com/romshark/morpheus/neo"
templ BoundaryStacking() {
<div class="boundary-stacking">
<div class="boundary-stacking-overlay">
Host app overlay · z-index 100
</div>
<div class="boundary-stacking-row">
<div class="boundary-stacking-col">
@neo.Boundary(neo.BoundaryOpts{}) {
<div class="boundary-stacking-panel">
<p class="boundary-stacking-label">Default</p>
@neo.Popover(neo.PopoverOpts{Placement: neo.Set(neo.PlacementBottomStart)}) {
<neo-button { neo.PopoverTrigger()... }>Account</neo-button>
<div { neo.PopoverContent()... }>
<h3 class="boundary-stacking-heading">Account</h3>
<p class="boundary-stacking-line">Signed in as Alice Larsson.</p>
<p class="boundary-stacking-line-sm">Plan: Team · 4 seats</p>
<p class="boundary-stacking-line-muted">No stacking context, so the panel's z-index 1000 paints over the host overlay.</p>
</div>
}
</div>
}
</div>
<div class="boundary-stacking-col">
@neo.Boundary(neo.BoundaryOpts{Scopes: neo.Set(neo.BoundaryScopes{Stacking: true})}) {
<div class="boundary-stacking-panel">
<p class="boundary-stacking-label">stacking</p>
@neo.Popover(neo.PopoverOpts{Placement: neo.Set(neo.PlacementBottomStart)}) {
<neo-button { neo.PopoverTrigger()... }>Account</neo-button>
<div { neo.PopoverContent()... }>
<h3 class="boundary-stacking-heading">Account</h3>
<p class="boundary-stacking-line">Signed in as Alice Larsson.</p>
<p class="boundary-stacking-line-sm">Plan: Team · 4 seats</p>
<p class="boundary-stacking-line-muted">A local stacking context confines the panel, so the host overlay paints over it.</p>
</div>
}
</div>
}
</div>
</div>
</div>
}
.boundary-stacking {
position: relative;
padding: 1.5rem;
min-height: 18rem;
}
.boundary-stacking-overlay {
position: absolute;
left: 1.5rem;
right: 1.5rem;
top: 8rem;
height: 2.75rem;
z-index: 100;
display: flex;
align-items: center;
justify-content: center;
padding: 0 1rem;
border-radius: var(--page-radius);
background: #4f46e5;
box-shadow: 0 6px 16px -6px rgba(0, 0, 0, 0.45);
font-size: 0.85rem;
font-weight: 600;
color: #ffffff;
}
.boundary-stacking-row {
display: flex;
gap: 1rem;
align-items: flex-start;
}
.boundary-stacking-col {
flex: 1;
}
.boundary-stacking-panel {
min-height: 14rem;
padding: 1rem;
border: 1px dashed var(--muted);
border-radius: var(--page-radius);
}
.boundary-stacking-label {
margin: 0 0 0.75rem;
font-weight: 600;
}
.boundary-stacking-heading {
margin: 0 0 0.5rem;
}
.boundary-stacking-line {
margin: 0;
}
.boundary-stacking-line-sm {
margin: 0.5rem 0 0;
}
.boundary-stacking-line-muted {
margin: 0.5rem 0 0;
color: var(--muted);
}
Nested boundaries#
The closest boundary defines the rules; they are not inherited. The inner boundary uses scope="positioning" (no dismiss), so its popover closes on any outside click (document scope), even though the outer boundary enables dismiss scoping. A closer boundary that turns a scope off falls back to the document or viewport default, never to the outer boundary. Open the popover, then click outside it to see it close.
Outer boundary: default scope.
The closest boundary defines the rules. Dismiss is off here, so a click anywhere outside this popover closes it, even though the outer boundary enables dismiss scoping. Rules are not inherited.
Inner boundary: scope="positioning" (no dismiss).
<neo-boundary>
<div class="boundary-nested-outer">
<p class="boundary-nested-intro">Outer boundary: default scope.</p>
<neo-boundary scope="positioning">
<div class="boundary-nested-inner">
<neo-popover
placement="bottom-start"
follow-scroll="until-trigger-invisible"
>
<neo-button data-neo-popover-trigger>Menu</neo-button>
<div data-neo-popover-content>
<p class="boundary-nested-body">The closest boundary defines the rules. Dismiss is off here, so a click anywhere outside this popover closes it, even though the outer boundary enables dismiss scoping. Rules are not inherited.</p>
</div>
</neo-popover>
<p class="boundary-nested-caption">Inner boundary: <code>scope="positioning"</code> (no dismiss).</p>
</div>
</neo-boundary>
</div>
</neo-boundary>package examples
import "github.com/romshark/morpheus/neo"
templ BoundaryNested() {
@neo.Boundary(neo.BoundaryOpts{}) {
<div class="boundary-nested-outer">
<p class="boundary-nested-intro">Outer boundary: default scope.</p>
@neo.Boundary(neo.BoundaryOpts{Scopes: neo.Set(neo.BoundaryScopes{NoDismiss: true})}) {
<div class="boundary-nested-inner">
@neo.Popover(neo.PopoverOpts{
Placement: neo.Set(neo.PlacementBottomStart),
FollowScroll: neo.Set(neo.PopoverFollowScrollUntilTriggerInvisible),
}) {
<neo-button { neo.PopoverTrigger()... }>Menu</neo-button>
<div { neo.PopoverContent()... }>
<p class="boundary-nested-body">
The closest boundary defines the rules. Dismiss is off here, so a click
anywhere outside this popover closes it, even though the outer boundary
enables dismiss scoping. Rules are not inherited.
</p>
</div>
}
<p class="boundary-nested-caption">Inner boundary: <code>{ `scope="positioning"` }</code> (no dismiss).</p>
</div>
}
</div>
}
}
.boundary-nested-outer {
padding: 2rem;
border: 1px dashed var(--muted);
border-radius: var(--page-radius);
}
.boundary-nested-intro {
margin: 0 0 1rem;
color: var(--muted);
}
.boundary-nested-inner {
min-height: 12rem;
padding: 1rem;
border: 1px dashed var(--muted);
border-radius: var(--page-radius);
}
.boundary-nested-body {
margin: 0;
}
.boundary-nested-caption {
margin-top: 2rem;
color: var(--muted);
}