diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml
index 80db996..e84a2b9 100644
--- a/.github/workflows/npm-publish.yml
+++ b/.github/workflows/npm-publish.yml
@@ -6,7 +6,7 @@ on:
workflow_dispatch:
inputs:
release_tag:
- description: "Release tag to publish, for example v2.1.1"
+ description: "Release tag to publish, for example v3.0.0"
required: true
type: string
diff --git a/.gitignore b/.gitignore
index e7adf2e..6277e64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ output/
playwright-report/
test-results/
npm-debug.log*
+desktop.ini
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5d8e98..f50fadb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,38 @@
All notable changes to `layout-style-css` are documented here. This project follows semantic versioning.
+## [3.0.0] - 2026-07-29
+
+### Breaking
+
+- Rebuilt the package as a clean-break intrinsic responsive system with attribute-only recipes and one shared container-query engine.
+- Removed `legacy.css`, the deprecated UI Style Kit structural bridge, v1/v2 aliases, recipe class aliases, extensionless export aliases, responsive/order utility families, and the scrollbar-unsafe `.ly-bleed` helper.
+- Reduced the npm tarball to the public generated CSS modules and personality profiles; package metadata, README, and license remain npm-standard package files.
+
+### Added
+
+- Added `foundation.css` for shared reset, tokens, named `ly-scope` containment, dynamic viewport sizing, and the `44rem`/`30rem` height tiers.
+- Made `.ly-root`, every wrapper, and every recipe root a named responsive scope so recipes work without wrappers and respond to the nearest wrapper when nested.
+- Added `data-ly-responsive="manual"` for application-owned topology with a safe stacked fallback.
+- Added device, independent width/height, automatic/manual, dimension, and active-topology controls to the demo.
+
+### Changed
+
+- Replaced breakpoint-heavy primitives with intrinsic Grid and Flexbox behavior and standardized shrink safety.
+- Moved Split Hero, List Detail, Docs, App Shell, and Dashboard topology to the shared `42rem`, `44rem`, `48rem`, `52rem`, and `72rem` query tiers.
+- Converted all sixteen personalities into breakpoint-free token/topology profiles with at least two distinguishing spatial characteristics.
+- Made dynamic viewport and container-relative tokens feature-detected enhancements over valid `vh` and `vw` fallbacks.
+- Made manual Gallery and Card Grid recipes single-column, isolated nested personality split ratios, and aligned gap utilities across Grid, Stack, and Cluster.
+- Restricted deliberate horizontal scrolling to Reel and deliberate bounded vertical scrolling to Scroll.
+- Corrected case-sensitive GitHub Pages metadata and versioned local demo assets to prevent stale v2/v3 asset combinations.
+
+### Tests
+
+- Added package/export/tarball, canonical-selector, removed-surface, generated-parity, ownership, and personality-engine contracts.
+- Added exact flattened/minified parity, actual tarball contents, complete v2 selector migration, nested-profile isolation, and fallback-enhancement contracts.
+- Added threshold-edge, six-device, short-height, root-direct, nearest-wrapper, manual-query, DOM/focus-order, overflow, wrapper, recipe, and all-personality rendered matrices.
+- Made Chromium, Firefox, and WebKit the complete release gate and retained the connected-browser interaction spot check.
+
## [2.1.1] - 2026-07-27
### Fixed
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1bd13dd..086ec58 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -24,9 +24,11 @@ npm run release:verify
- Regenerate `dist/` with `npm run build`; do not hand-edit generated dist files.
- Keep public layout classes prefixed with `ly-`.
- Leave colors, typography, borders, shadows, native controls, focus states, themes, and modes to `ui-style-kit-css`.
-- Add structural aliases in `styles/integrations/ui-style-kit.css` only when they map to layout primitives or layout recipes.
-- Preserve semantic mobile DOM, reading, and focus order; built-in recipes must use named areas instead of `order`.
-- Test container behavior below and above `48rem` and `64rem`.
+- Keep v3 on canonical hooks; do not add legacy, recipe-class, or companion structural aliases.
+- Preserve semantic mobile DOM, reading, and focus order; built-in recipes must use named areas instead of visual order.
+- Test container behavior below and above `42rem`, `44rem`, `48rem`, `52rem`, and `72rem`.
+- Test height behavior below and above `30rem` and `44rem`.
+- Keep personality files limited to tokens and topology templates; they must not declare breakpoints.
- Update README, `docs/wiki`, and `CHANGELOG.md` when a public class, export, recipe, release workflow, or package behavior changes.
## Testing Expectations
diff --git a/README.md b/README.md
index 3dd5f23..e533a72 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
# layout-style-css
-Container-first, dependency-free structural CSS for responsive application layouts.
+Zero-configuration, dependency-free structural CSS that responds to the width and height a layout actually receives.
-`layout-style-css@2.1.1` provides semantic wrappers, composition primitives, seven functional recipes, ordering escape hatches, sixteen spatial personalities, and refreshed ecosystem fixtures for UI Style Kit CSS 2.1 and Interactive Surface CSS 1.5. It owns layout only; color, typography, borders, shadows, component paint, and interactive states belong to other libraries.
+`layout-style-css@3.0.0` is a clean-break release. It provides intrinsic wrappers, composition primitives, seven semantic recipes, and sixteen spatial personalities. Layout owns structure; UI Style Kit owns paint; Interactive Surface owns interaction styling.
## Requirements
@@ -10,74 +10,51 @@ Container-first, dependency-free structural CSS for responsive application layou
- Current evergreen Chromium, Firefox, or WebKit for consumers
- No runtime or peer dependencies
-`ui-style-kit-css@2.1.0` and `interactive-surface-css@1.5.0` are released registry fixtures for optional ecosystem verification. Neither package is installed for consumers.
-
## Install
```bash
-npm install layout-style-css@2.1.1
+npm install layout-style-css@3.0.0
```
-Standalone use needs one import:
+Most applications need one import:
```js
import "layout-style-css";
```
-The default and minified bundles contain the v2 core plus all personalities. Import focused modules when an application needs a smaller surface.
-
-## Ecosystem Imports
+The full bundle includes the core modules and all personality profiles. No breakpoint configuration, wrapper, JavaScript, or companion library is required.
-Layout Style never imports companion packages. Install and import each layer explicitly.
+## Zero-Configuration Start
-Layout plus UI Style Kit:
+Use `.ly-root` as the responsive boundary and keep the mobile DOM order authoritative:
-```js
-import "ui-style-kit-css/visual.css";
-import "layout-style-css";
-```
-
-Layout plus UI Style Kit and Interactive Surface must use this order:
-
-```js
-import "ui-style-kit-css/visual.css";
-import "ui-style-kit-css/interactive-surface-theme.css";
-import "interactive-surface-css/state-core.css";
-import "layout-style-css";
+```html
+
+
+ Documentation
+
+ Guide
+
+
+
+
```
-UI Style Kit establishes visual paint, the UI token bridge maps theme roles for Interactive Surface, Interactive Surface contributes interaction states, and Layout core applies spatial behavior.
+`.ly-root`, wrappers, and recipe roots establish the named `ly-scope` inline-size container. A recipe works directly in the root; when it is nested in a wrapper, it responds to that nearest wrapper.
-## Public Exports
-
-| Import | Contents |
-| --- | --- |
-| `layout-style-css` | Full v2 core plus all personalities. |
-| `layout-style-css/min.css` | Minified full v2 bundle. |
-| `layout-style-css/core.css` | Wrappers, primitives, recipes, and utilities. |
-| `layout-style-css/wrappers.css` | Tokens, reset, and semantic wrappers. |
-| `layout-style-css/primitives.css` | Composition primitives. |
-| `layout-style-css/recipes.css` | Seven named responsive recipes. |
-| `layout-style-css/utilities.css` | Structural utilities and ordering escape hatches. |
-| `layout-style-css/personalities.css` | All sixteen personalities. |
-| `layout-style-css/personalities/minimal-saas.css` | One personality; substitute any public personality name. |
-| `layout-style-css/integrations/ui-style-kit.css` | Deprecated import-free structural bridge for legacy UI Style Kit structural aliases. |
-| `layout-style-css/legacy.css` | Full v2 bundle plus v1 compatibility aliases. |
+## Wrappers
-The old root-level personality files and `all-with-ui-kit*` aggregates were removed. See [Migrating To 2.0](docs/wiki/Migrating-To-2.0.md) for exact mappings.
+Wrappers are optional measure and nesting controls. Every wrapper uses logical properties, fluid container-relative gutters, safe-area compensation, and shrink-safe sizing.
-## Container-First Wrappers
-
-Every `.ly-wrapper` has fluid logical gutters, safe-area compensation, and `container-type: inline-size`. The default is the `72rem` content measure. Personalities may change only the plain-wrapper default; an explicit semantic wrapper variant always retains its documented measure.
-
-| Wrapper | Measure |
+| Wrapper | Purpose |
| --- | --- |
-| `.ly-wrapper--compact` | `40rem` |
-| `.ly-wrapper--prose` | `68ch` |
-| `.ly-wrapper--content` | `72rem` and the default |
-| `.ly-wrapper--wide` | `112rem` |
+| `.ly-wrapper` | Personality-aware content measure |
+| `.ly-wrapper--compact` | `40rem` compact measure |
+| `.ly-wrapper--prose` | `68ch` reading measure |
+| `.ly-wrapper--content` | `72rem` content measure |
+| `.ly-wrapper--wide` | `112rem` wide measure |
| `.ly-wrapper--full` | Full available inline size |
-| `.ly-wrapper--breakout` | Content, feature, and full-width grid lanes |
+| `.ly-wrapper--breakout` | Clamped content, feature, and full lanes |
```html
@@ -87,149 +64,151 @@ Every `.ly-wrapper` has fluid logical gutters, safe-area compensation, and `cont
```
-Wrappers, recipe roots, and personality enhancements respond to the nearest inline-size container. The mobile single-column fallback is authoritative; core recipes and primitives enhance at the `48rem` and `64rem` core thresholds, not viewport widths. Personality grid rhythms retain their authored thresholds, safe two-track application shells retain their authored thresholds, and every three- or four-track application shell waits for a locally feasible `64rem` allocation.
+All lanes clamp to the available inline size, including allocations from 320px through ultrawide screens.
-## Recipes And Areas
+## Composition Primitives
-Use `data-ly-recipe` as the semantic public hook. Each value is independently functional without a matching class; matching classes remain available as an equivalent direct-composition API.
+The core includes:
-- `app-shell`
-- `dashboard`
-- `docs`
-- `list-detail`
-- `split-hero`
-- `gallery`
-- `card-grid`
+- `.ly-stack`, `.ly-cluster`, `.ly-center`, and `.ly-cover`
+- `.ly-switcher`, `.ly-sidebar`, `.ly-grid`, and `.ly-split`
+- `.ly-panes` and `.ly-media`
+- `.ly-reel`, `.ly-frame`, and `.ly-scroll`
-Named regions use `data-ly-area`: `header`, `nav`, `main`, `aside`, `footer`, `content`, `media`, `actions`, `primary`, and `secondary`.
+Grid and flex primitives wrap intrinsically whenever track wrapping can replace a query. Page, cover, and bounded-scroll sizing use `vh` fallbacks followed by `100dvh`-aware behavior. Only `.ly-reel` deliberately scrolls horizontally; only `.ly-scroll` deliberately creates a bounded vertical scroll region.
-```html
-
-
- Dashboard
-
- Primary workspace
-
-
-
-
-```
+## Automatic Recipe Engine
-Keep markup in the correct mobile DOM, reading, and focus order. Built-in recipes rearrange named grid areas at wider container sizes and never use CSS `order`.
+Recipes use attributes only. The stacked semantic source order is always safe, and automatic enhancement is the default.
-## Composition Primitives
+| Recipe | Automatic topology |
+| --- | --- |
+| `data-ly-recipe="split-hero"` | Two tracks at `42rem` |
+| `data-ly-recipe="list-detail"` | Two tracks at `44rem` |
+| `data-ly-recipe="docs"` | Documentation rail at `48rem` |
+| `data-ly-recipe="app-shell"` | Medium at `52rem`, wide at `72rem` |
+| `data-ly-recipe="dashboard"` | Medium at `52rem`, wide at `72rem` |
+| `data-ly-recipe="gallery"` | Intrinsic tracks; no topology breakpoint |
+| `data-ly-recipe="card-grid"` | Intrinsic tracks; no topology breakpoint |
-The v2 composition layer includes:
+Canonical regions use `data-ly-area`, including `header`, `sidebar`, `nav`, `main`, `aside`, `footer`, `content`, `media`, `actions`, `primary`, and `secondary`.
-| Primitive | Purpose |
-| --- | --- |
-| `.ly-stack`, `.ly-cluster`, `.ly-center`, `.ly-cover` | Flow, grouping, centering, and full-height composition. |
-| `.ly-switcher`, `.ly-sidebar`, `.ly-grid`, `.ly-split` | Adaptive multi-item layouts. |
-| `.ly-panes`, `.ly-media` | Workspaces and media-object arrangements. |
-| `.ly-reel`, `.ly-frame`, `.ly-scroll` | Horizontal flow, stable ratios, and bounded scrolling. |
+Recipe class aliases such as `.ly-dashboard` no longer exist. Use:
-All primitives are structural. Pair them with a paint library or application CSS for visuals.
+```html
+
+ Dashboard
+
+ Primary workspace
+
+
+
+```
-## Layout Personalities
+## Custom Responsive Topology
-Set one canonical `data-ly-layout` value on `.ly-root`:
+Add `data-ly-responsive="manual"` to retain the safe stack and disable built-in topology enhancement. Application CSS can then use the same named container:
-```html
-
-
-
+```css
+@container ly-scope (min-width: 56rem) {
+ [data-ly-recipe="docs"][data-ly-responsive="manual"] {
+ /* Application-owned topology. */
+ }
+}
```
-| Family | Personalities |
-| --- | --- |
-| Left-rail applications | Minimal SaaS, Bauhaus, Tactile, Cyberpunk, F-Pattern |
-| Right-rail workspaces | Brutalism, Neumorphism, Y2K, Retro Glass, Z-Pattern |
-| Three-zone layouts | Retrofuturism, Mondrian, Synthwave |
-| Full-width mosaics | Bento, Maximalist |
-| Equal split | Split Screen |
+This opt-out changes topology ownership, not the semantic DOM, shrink safety, gaps, or named regions.
-Each personality changes at least two spatial characteristics while leaving UI paint and DOM order unchanged.
+## Vertical Responsiveness
-## Ordering Utilities And Accessibility
+The system responds to available block size without orientation queries:
-The base, `ly-md-*`, and `ly-lg-*` families expose `order-first`, `order-normal`, `order-last`, and numeric order `1` through `6`. For example: `.ly-order-first`, `.ly-md-order-3`, and `.ly-lg-order-last`.
+- At viewport heights of `44rem` or less, gaps, section padding, header height, and bounded-scroll maxima tighten.
+- At viewport heights of `30rem` or less, recipe-owned sticky behavior becomes normal flow, and cover/shell minimums stop forcing full-height regions.
+- Safe-area block insets remain available, and required regions are never hidden solely because the viewport is short.
-These are escape hatches. Visual reordering can diverge from screen-reader reading order and keyboard focus order. Prefer correct source order plus recipe named areas; verify assistive-technology and keyboard behavior whenever an order utility is used. Built-in recipes never use order utilities.
+Use the public height, gap, measure, ratio, rail, media, card, and grid-minimum custom properties for advanced tuning. Defaults use `100vh` fallbacks followed by `100dvh`.
-## UI Style Kit Naming Compatibility
+## Personalities
-`layout-style-css/integrations/ui-style-kit.css` remains available for legacy code that still uses UI-prefixed structural aliases such as `.saas-container`, `.bento-grid`, and `.cyber-split`. It is frozen and deprecated; new ecosystem imports should use UI Style Kit visual builds plus Layout core instead of the structural bridge.
+Set one of sixteen canonical `data-ly-layout` values on `.ly-root`:
-Deprecated bridge import:
+`minimal-saas`, `bauhaus`, `tactile`, `cyberpunk`, `f-pattern`, `brutalism`, `neumorphism`, `y2k`, `retro-glass`, `z-pattern`, `retrofuturism`, `mondrian`, `synthwave`, `bento`, `maximalist`, or `split-screen`.
-```js
-import "layout-style-css/integrations/ui-style-kit.css";
-```
+Each personality is a token/topology profile consumed by the shared recipe engine. A profile changes at least two spatial characteristics—such as measure, gap, rail, media size, card minimum, or ratio—but does not declare its own container or viewport breakpoint system.
-Supported UI prefixes are `saas`, `bento`, `max`, `bau`, `tactile`, `neo`, `retro`, `brutal`, `cyber`, `y2k`, and `rg`.
+## Public Exports
-## Legacy Compatibility
+| Import | Contents |
+| --- | --- |
+| `layout-style-css` | Full v3 bundle |
+| `layout-style-css/min.css` | Minified full v3 bundle |
+| `layout-style-css/core.css` | Foundation, wrappers, primitives, recipes, and utilities |
+| `layout-style-css/foundation.css` | Reset, shared tokens, containment, and vertical responsiveness |
+| `layout-style-css/wrappers.css` | Semantic wrappers and breakout lanes |
+| `layout-style-css/primitives.css` | Intrinsic composition primitives |
+| `layout-style-css/recipes.css` | Seven attribute-only recipes |
+| `layout-style-css/utilities.css` | Small structural utility set |
+| `layout-style-css/personalities.css` | All sixteen profiles |
+| `layout-style-css/personalities/minimal-saas.css` | One profile; substitute any public personality name |
+| `layout-style-css/package.json` | Package metadata |
+
+The cascade order is `ly.reset`, `ly.tokens`, `ly.wrappers`, `ly.primitives`, `ly.recipes`, `ly.utilities`, and `ly.personalities`.
+
+## Ecosystem Imports
-Applications that cannot migrate all selectors at once may temporarily use:
+Companion libraries are optional and explicit. Layout does not import them.
```js
-import "layout-style-css/legacy.css";
+import "ui-style-kit-css/visual.css";
+import "ui-style-kit-css/interactive-surface-theme.css";
+import "interactive-surface-css/state-core.css";
+import "layout-style-css";
```
-This one import includes the full v2 bundle and aliases for v1 containers, size names, root personality hooks, columns, carousel, button group, sidebar, pane, card, scroll recipes, `.ly-content` shrink safety, and structural `.ly-divider` spacing. It is supported for the v2 line only, with removal in v3. New code should use canonical v2 exports and hooks.
-
-The v1 `.ly-surface--raised` selector is intentionally removed, including from `legacy.css`: raised radius, border, background, and shadow treatment belongs to UI Style Kit or application theme styling. See [Migrating To 2.0](docs/wiki/Migrating-To-2.0.md) for the complete selector mapping.
+This order lets UI Style Kit establish paint and theme roles, Interactive Surface add interaction states, and Layout apply structure.
## CDN
```html
-
-
+
+
```
-Companion CDN styles must appear in the same order as the package imports: UI Style Kit visual CSS, UI Style Kit `interactive-surface-theme.css`, Interactive Surface `state-core.css`, then Layout core. Load `layout-style-css/integrations/ui-style-kit.css` only for deprecated structural aliases.
+## Clean-Break Migration
+
+v3 has no compatibility bundle. It removes `legacy.css`, the deprecated UI Style Kit structural bridge, v1/v2 aliases, responsive `ly-md-*` and `ly-lg-*` utilities, and all visual-order utilities. See [Migrating To 3.0](docs/wiki/Migrating-To-3.0.md) for exact mappings.
-## Development And Verification
+## Demo And Verification
+
+The demo provides independent width and height controls plus phone, tablet, and desktop portrait/landscape presets. It displays rendered dimensions and active topology, compares automatic with manual responsiveness, and generates canonical copy-ready markup.
```bash
npm ci
npm run build
npm run lint
npm run check:demo-js
-npm run test:demo:quick
npm test
+npm run test:full
+npm run release:verify
```
-`npm test` is the local Chromium gate. `npm run test:demo:all` runs Chromium, Firefox, and WebKit. `npm run release:verify` runs the full build, lint, static, Pages, cross-browser, tarball, `npm audit --audit-level=moderate`, and publish-dry-run checks. It does not publish.
+`npm test` runs the quick Chromium gate. `npm run test:full` exercises the rendered matrix in Chromium, Firefox, and WebKit. `npm run release:verify` includes the full build and test gate, tarball verification, `npm audit --audit-level=moderate`, and publish dry-run; it does not publish.
-## Documentation And Wiki
+## Documentation
-| Resource | Purpose |
-| --- | --- |
-| [Wiki home](docs/wiki/Home.md) | Versioned documentation navigation. |
-| [Getting Started](docs/wiki/Getting-Started.md) | First v2 wrapper and recipe. |
-| [Installation And CDN](docs/wiki/Installation-And-CDN.md) | Exact exports and import order. |
-| [Layout Primitives](docs/wiki/Layout-Primitives.md) | Wrapper and composition contracts. |
-| [Layout Recipes](docs/wiki/Layout-Recipes.md) | Recipe and area markup. |
-| [Layout Styles](docs/wiki/Layout-Styles.md) | Sixteen personality families. |
-| [UI Style Kit Compatibility](docs/wiki/UI-Style-Kit-Compatibility.md) | Ownership and bridge rules. |
-| [Migrating To 2.0](docs/wiki/Migrating-To-2.0.md) | Complete 1.x-to-2.0 mapping. |
-| [Demo And GitHub Pages](docs/wiki/Demo-And-GitHub-Pages.md) | Rendered QA and Pages artifact. |
-| [Release And Publishing](docs/wiki/Release-And-Publishing.md) | Local verification and separately approved release steps. |
-| [Security And Support](docs/wiki/Security-And-Support.md) | Supported versions and reporting. |
-| [Contributing](docs/wiki/Contributing.md) | Source, generated output, and review rules. |
-| [Wiki sidebar source](docs/wiki/_Sidebar.md) | Navigation source for a GitHub Wiki mirror. |
-| [Changelog](CHANGELOG.md) | Release history. |
-| [Repository contributing guide](CONTRIBUTING.md) | Contribution workflow. |
-| [Security policy](SECURITY.md) | Security policy. |
-
-## Ownership Boundary
-
-- `layout-style-css` owns wrappers, flow, grids, areas, measures, spans, containment, and structural responsiveness.
-- `ui-style-kit-css` owns theme and component paint.
-- `interactive-surface-css` owns interaction-state styling.
-
-Authored CSS lives in `styles/`; `dist/` is generated. Keep public layout classes prefixed with `ly-`, add tests before changing contracts, and never edit generated CSS directly.
+- [Getting Started](docs/wiki/Getting-Started.md)
+- [Installation And CDN](docs/wiki/Installation-And-CDN.md)
+- [Layout Primitives](docs/wiki/Layout-Primitives.md)
+- [Layout Recipes](docs/wiki/Layout-Recipes.md)
+- [Layout Styles](docs/wiki/Layout-Styles.md)
+- [Migrating To 3.0](docs/wiki/Migrating-To-3.0.md)
+- [Demo And GitHub Pages](docs/wiki/Demo-And-GitHub-Pages.md)
+- [Release And Publishing](docs/wiki/Release-And-Publishing.md)
+- [Security And Support](docs/wiki/Security-And-Support.md)
+- [Changelog](CHANGELOG.md)
+
+Authored CSS lives in `styles/`; `dist/` is generated. Keep application markup in correct DOM, reading, keyboard, and focus order.
## License
diff --git a/demo/demo.css b/demo/demo.css
index 0195d11..6e4b0cd 100644
--- a/demo/demo.css
+++ b/demo/demo.css
@@ -61,7 +61,9 @@ html {
}
body {
+ min-block-size: 100vh;
min-block-size: 100svh;
+ min-block-size: 100dvh;
margin: 0;
overflow-x: clip;
background: var(--demo-bg);
@@ -194,11 +196,17 @@ h3 {
.demo-status,
.demo-copy-status,
-#containerReadout {
+.demo-readouts {
color: var(--demo-muted);
font-size: 0.875rem;
}
+.demo-readouts {
+ display: grid;
+ justify-items: end;
+ gap: 0.125rem;
+}
+
.demo-status {
padding: 0.4rem 0.7rem;
border: 1px solid var(--demo-line);
@@ -305,13 +313,17 @@ body[data-ecosystem="all-three"] .demo-status {
.demo-preview-frame {
--demo-container-inline-size: 100%;
+ --demo-container-block-size: auto;
container-name: demo-preview;
container-type: inline-size;
inline-size: min(100%, var(--demo-container-inline-size));
+ block-size: var(--demo-container-block-size);
+ max-block-size: none;
min-inline-size: 0;
+ min-block-size: 0;
margin-inline: auto;
- overflow: clip;
+ overflow: auto;
border: 1px dashed var(--demo-line);
border-radius: calc(var(--demo-radius) * 0.85);
background: var(--demo-bg);
@@ -319,31 +331,55 @@ body[data-ecosystem="all-three"] .demo-status {
/* The nested root lets personalities respond to preview width, not viewport width. */
.demo-preview-root {
+ --ly-cover-min: 100%;
+ --ly-shell-min: 100%;
+
+ block-size: 100%;
min-block-size: 0;
min-inline-size: 0;
padding-block: 0.75rem;
}
.demo-preview-root > .ly-wrapper {
- /* The width control represents the queried content box exactly at 48rem/64rem. */
- --ly-wrapper-gutter: 0px;
-
+ /*
+ Preview allocations represent the nearest queried content box exactly;
+ safe-area behavior remains exercised by the outer document root.
+ */
+ --ly-wrapper-fluid-gutter: 0px;
+ --ly-wrapper-local-gutter: 0px;
+
+ block-size: 100%;
min-inline-size: 0;
}
.demo-recipe {
- min-block-size: 30rem;
+ min-block-size: 100%;
min-inline-size: 0;
gap: var(--demo-density-gap);
}
-.demo-recipe:is(.ly-gallery, [data-ly-recipe="gallery"]),
-.demo-recipe:is(.ly-card-grid, [data-ly-recipe="card-grid"]) {
+.demo-recipe:is([data-ly-recipe="gallery"], [data-ly-recipe="card-grid"]) {
min-block-size: auto;
}
-.demo-recipe:is(.ly-app-shell, [data-ly-recipe="app-shell"]) {
- min-block-size: 32rem;
+.demo-preview-root[data-demo-height-tier="short"] {
+ --ly-gap: min(var(--demo-density-gap), 1rem);
+ --ly-grid-gap: var(--ly-gap);
+ --ly-section-padding-block: clamp(1.5rem, 6%, 3rem);
+ --ly-header-height: 3.5rem;
+ --ly-scroll-max: min(62%, 34rem);
+}
+
+.demo-preview-root[data-demo-height-tier="shallow"] {
+ --ly-cover-min: auto;
+ --ly-shell-min: auto;
+ --ly-sticky-position: static;
+ --ly-section-padding-block: 1.5rem;
+ --ly-scroll-max: max(12rem, calc(100% - 8rem));
+}
+
+.demo-preview-root[data-demo-height-tier="shallow"] .demo-recipe {
+ min-block-size: auto;
}
.demo-region {
@@ -460,7 +496,9 @@ body[data-ecosystem="all-three"] .demo-status {
position: sticky;
inset-block-start: 6rem;
display: block;
+ max-block-size: calc(100vh - 7rem);
max-block-size: calc(100svh - 7rem);
+ max-block-size: calc(100dvh - 7rem);
overflow: auto;
}
}
@@ -480,7 +518,9 @@ body[data-ecosystem="all-three"] .demo-status {
inset-inline-end: 0;
z-index: 40;
inline-size: min(24rem, calc(100% - 1rem));
+ max-block-size: 100vh;
max-block-size: 100svh;
+ max-block-size: 100dvh;
padding:
max(1rem, env(safe-area-inset-top, 0px))
max(1rem, env(safe-area-inset-right, 0px))
@@ -516,6 +556,33 @@ body[data-ecosystem="all-three"] .demo-status {
}
}
+@media (max-height: 44rem) {
+ .demo-page {
+ padding-block: 0.75rem 2rem;
+ }
+
+ .demo-main {
+ gap: 1rem;
+ }
+
+ .demo-intro,
+ .demo-lab {
+ padding-block: 1rem;
+ }
+}
+
+@media (max-height: 30rem) {
+ .demo-topbar,
+ .demo-controls {
+ position: static;
+ max-block-size: none;
+ }
+
+ .demo-preview-frame {
+ max-block-size: none;
+ }
+}
+
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
diff --git a/demo/demo.js b/demo/demo.js
index 896b5bb..7cf42be 100644
--- a/demo/demo.js
+++ b/demo/demo.js
@@ -78,6 +78,15 @@ async function loadUiStyleKitManifest() {
const UI_STYLE_KIT_MANIFEST = await loadUiStyleKitManifest();
const ALLOWLISTS = Object.freeze({
+ device: Object.freeze([
+ "custom",
+ "phone-portrait",
+ "phone-landscape",
+ "tablet-portrait",
+ "tablet-landscape",
+ "desktop-landscape",
+ "desktop-portrait"
+ ]),
wrapper: Object.freeze(["default", "compact", "prose", "content", "wide", "full", "breakout"]),
recipe: Object.freeze([
"app-shell",
@@ -106,7 +115,24 @@ const ALLOWLISTS = Object.freeze({
"maximalist",
"split-screen"
]),
- container: Object.freeze(["auto", "40rem", "47rem", "49rem", "63rem", "65rem", "80rem"]),
+ container: Object.freeze([
+ "auto",
+ "20rem",
+ "32rem",
+ "40rem",
+ "41rem",
+ "43rem",
+ "45rem",
+ "47rem",
+ "49rem",
+ "51rem",
+ "53rem",
+ "71rem",
+ "73rem",
+ "80rem"
+ ]),
+ height: Object.freeze(["auto", "29rem", "31rem", "43rem", "45rem", "50rem"]),
+ responsive: Object.freeze(["auto", "manual"]),
density: Object.freeze(["compact", "comfortable", "spacious"]),
ui: Object.freeze(UI_STYLE_KIT_MANIFEST.presets.map((preset) => preset.id)),
theme: Object.freeze(UI_STYLE_KIT_MANIFEST.themes),
@@ -115,10 +141,13 @@ const ALLOWLISTS = Object.freeze({
});
const DEFAULT_STATE = Object.freeze({
+ device: "custom",
wrapper: "default",
recipe: "app-shell",
personality: "minimal-saas",
container: "auto",
+ height: "auto",
+ responsive: "auto",
density: "comfortable",
ui: "minimal-saas",
theme: "arctic-indigo",
@@ -128,14 +157,40 @@ const DEFAULT_STATE = Object.freeze({
const CONTAINER_WIDTHS = Object.freeze({
auto: "100%",
+ "20rem": "20rem",
+ "32rem": "32rem",
"40rem": "40rem",
+ "41rem": "41rem",
+ "43rem": "43rem",
+ "45rem": "45rem",
"47rem": "47rem",
"49rem": "49rem",
- "63rem": "63rem",
- "65rem": "65rem",
+ "51rem": "51rem",
+ "53rem": "53rem",
+ "71rem": "71rem",
+ "73rem": "73rem",
"80rem": "80rem"
});
+const CONTAINER_HEIGHTS = Object.freeze({
+ auto: "auto",
+ "29rem": "29rem",
+ "31rem": "31rem",
+ "43rem": "43rem",
+ "45rem": "45rem",
+ "50rem": "50rem"
+});
+
+const DEVICE_PRESETS = Object.freeze({
+ custom: null,
+ "phone-portrait": Object.freeze({ width: 360, height: 800 }),
+ "phone-landscape": Object.freeze({ width: 800, height: 360 }),
+ "tablet-portrait": Object.freeze({ width: 768, height: 1024 }),
+ "tablet-landscape": Object.freeze({ width: 1024, height: 768 }),
+ "desktop-landscape": Object.freeze({ width: 1440, height: 900 }),
+ "desktop-portrait": Object.freeze({ width: 900, height: 1440 })
+});
+
const DENSITY_GAPS = Object.freeze({
compact: "0.5rem",
comfortable: "1rem",
@@ -146,18 +201,8 @@ const UI_CLASS_PREFIXES = Object.freeze(
Object.fromEntries(UI_STYLE_KIT_MANIFEST.presets.map((preset) => [preset.id, preset.prefix]))
);
-const RECIPE_CLASSES = Object.freeze({
- "app-shell": "ly-app-shell",
- dashboard: "ly-dashboard",
- docs: "ly-docs",
- "list-detail": "ly-list-detail",
- "split-hero": "ly-split-hero",
- gallery: "ly-gallery",
- "card-grid": "ly-card-grid"
-});
-
const RECIPE_AREAS = Object.freeze({
- "app-shell": Object.freeze(["header", "nav", "main", "aside", "footer"]),
+ "app-shell": Object.freeze(["header", "sidebar", "main", "aside", "footer"]),
dashboard: Object.freeze(["header", "nav", "main", "aside", "footer"]),
docs: Object.freeze(["header", "nav", "main", "aside", "footer"]),
"list-detail": Object.freeze(["primary", "secondary", "actions"]),
@@ -197,10 +242,10 @@ const markupSnippet = document.querySelector("#markupSnippet");
const copyStatus = document.querySelector("#copyStatus");
const ecosystemStatus = document.querySelector("#ecosystemStatus");
const containerReadout = document.querySelector("#containerReadout");
+const topologyReadout = document.querySelector("#topologyReadout");
const uiKitStylesheet = document.querySelector("#uiKitStylesheet");
const uiKitInteractiveThemeStylesheet = document.querySelector("#uiKitInteractiveThemeStylesheet");
const interactiveSurfaceStylesheet = document.querySelector("#interactiveSurfaceStylesheet");
-const layoutIntegrationStylesheet = document.querySelector("#layoutIntegrationStylesheet");
const layoutCoreStylesheet = document.querySelector("#layoutCoreStylesheet");
const drawerToggle = document.querySelector("#demoControlsToggle");
const drawer = document.querySelector("#demoControlsDrawer");
@@ -216,6 +261,7 @@ let state = readStateFromQuery();
let drawerReturnFocus = null;
let querySyncTimer = null;
let hasSynchronizedQuery = false;
+let readoutFrame = null;
function readStateFromQuery() {
const query = new URLSearchParams(window.location.search);
@@ -287,13 +333,15 @@ function createRegion(area) {
const semanticTags = {
header: "header",
nav: "nav",
+ sidebar: "aside",
aside: "aside",
footer: "footer",
media: "figure",
actions: "div"
};
+ const structuralClass = area === "header" ? "ly-header ly-header--sticky " : "";
const element = createElement(semanticTags[area] ?? "section", {
- className: "demo-region",
+ className: `${structuralClass}demo-region`,
attributes: { "data-ui-kit": "card" },
data: { lyArea: area, demoSequence: area }
});
@@ -340,8 +388,13 @@ function renderRecipe() {
? RECIPE_AREAS[recipe].map((area) => createRegion(area))
: Array.from({ length: recipe === "gallery" ? 5 : 6 }, (_, index) => createGridItem(index + 1));
- recipePreview.className = `${RECIPE_CLASSES[recipe]} demo-recipe`;
+ recipePreview.className = "demo-recipe";
recipePreview.dataset.lyRecipe = recipe;
+ if (state.responsive === "manual") {
+ recipePreview.dataset.lyResponsive = "manual";
+ } else {
+ delete recipePreview.dataset.lyResponsive;
+ }
recipePreview.replaceChildren(...children);
}
@@ -416,15 +469,15 @@ function syncEcosystem() {
uiKitStylesheet.disabled = !includesUi;
uiKitInteractiveThemeStylesheet.disabled = !includesInteractiveSurface;
interactiveSurfaceStylesheet.disabled = !includesInteractiveSurface;
- layoutIntegrationStylesheet.disabled = true;
layoutCoreStylesheet.disabled = false;
ecosystemStatus.textContent = ECOSYSTEM_LABELS[state.ecosystem];
}
function buildMarkupSnippet() {
const wrapperClass = state.wrapper === "default" ? "ly-wrapper" : `ly-wrapper ly-wrapper--${state.wrapper}`;
- const rootClass = RECIPE_CLASSES[state.recipe];
const areas = RECIPE_AREAS[state.recipe];
+ const responsiveAttribute =
+ state.responsive === "manual" ? ' data-ly-responsive="manual"' : "";
const childMarkup = areas
? areas.map((area) => ` ${formatLabel(area)}`).join("\n")
: ` Item 1\n Item 2`;
@@ -432,7 +485,7 @@ function buildMarkupSnippet() {
return [
`
```
-The single-column DOM order is authoritative for mobile reading and keyboard focus. Core named grid areas rearrange at `48rem` and `64rem` container widths without changing source order; a selected personality may apply its own personality-specific enhancement threshold.
+The recipe stays stacked below `42rem` and enhances automatically when its nearest `ly-scope` container has enough room.
-## Switch Personality
+## Optional Wrapper
-```js
-document.querySelector(".ly-root").dataset.lyLayout = "synthwave";
+Use wrappers when a composition needs a named measure or local responsive scope:
+
+```html
+
+
+ One
+ Two
+
+
+```
+
+Available measures are `.ly-wrapper--compact`, `.ly-wrapper--prose`, `.ly-wrapper--content`, `.ly-wrapper--wide`, `.ly-wrapper--full`, and `.ly-wrapper--breakout`.
+
+## Manual Topology
+
+Use `data-ly-responsive="manual"` only when application CSS must choose the topology:
+
+```css
+@container ly-scope (min-width: 56rem) {
+ [data-ly-recipe="docs"][data-ly-responsive="manual"] {
+ /* Application-owned topology. */
+ }
+}
```
-`data-ly-layout` accepts one of the sixteen values listed in [Layout Styles](Layout-Styles.md). UI attributes such as `data-ui`, `data-theme`, and `data-mode` remain independent.
+Keep mobile DOM order authoritative. The package never changes reading or focus order.
-## Migrate Existing Markup
+## Next
-Do not copy v1 root hooks or size-based wrappers into new code. Follow [Migrating To 2.0](Migrating-To-2.0.md), or use `layout-style-css/legacy.css` temporarily while converting an application.
+- [Layout Primitives](Layout-Primitives.md)
+- [Layout Recipes](Layout-Recipes.md)
+- [Layout Styles](Layout-Styles.md)
+- [Migrating To 3.0](Migrating-To-3.0.md)
diff --git a/docs/wiki/Home.md b/docs/wiki/Home.md
index 8b84682..bc3e492 100644
--- a/docs/wiki/Home.md
+++ b/docs/wiki/Home.md
@@ -1,33 +1,27 @@
-# Layout Style CSS Wiki
+# Layout Style CSS v3
-Version 2.1.1 is a container-first, dependency-free layout library. It ships semantic wrappers, composition primitives, seven recipes, sixteen layout personalities, focused exports, a v2-only compatibility bundle, and refreshed ecosystem fixtures for UI Style Kit CSS 2.1 and Interactive Surface CSS 1.5.
+`layout-style-css@3.0.0` is a dependency-free, CSS-only structural system for layouts that adapt to available width and height.
-## Start Here
+## Contract
-| Page | Purpose |
-| --- | --- |
-| [Getting Started](Getting-Started.md) | First wrapper, recipe, and personality. |
-| [Installation And CDN](Installation-And-CDN.md) | Exact package exports and ecosystem import order. |
-| [Layout Primitives](Layout-Primitives.md) | Wrappers and composition primitives. |
-| [Layout Recipes](Layout-Recipes.md) | Named recipes, areas, and mobile ordering. |
-| [Layout Styles](Layout-Styles.md) | Sixteen spatial personalities. |
-| [UI Style Kit Compatibility](UI-Style-Kit-Compatibility.md) | Structural bridge and ownership boundaries. |
-| [Migrating To 2.0](Migrating-To-2.0.md) | Complete 1.x selector and export mapping. |
-| [Demo And GitHub Pages](Demo-And-GitHub-Pages.md) | Interactive lab, browser matrix, and Pages artifact. |
-| [Release And Publishing](Release-And-Publishing.md) | Release verification and separately approved publish steps. |
-| [Security And Support](Security-And-Support.md) | Supported versions and reporting. |
-| [Contributing](Contributing.md) | Source, generated output, testing, and review rules. |
+- `.ly-root` is a usable layout and named `ly-scope` container.
+- Wrappers are optional measure and nesting controls.
+- Seven `data-ly-recipe` values enhance a semantic stacked fallback.
+- `data-ly-responsive="manual"` transfers topology ownership to application CSS.
+- Sixteen `data-ly-layout` profiles tune one shared responsive engine.
+- `100dvh` behavior and the `44rem`/`30rem` height tiers avoid short-screen traps.
+- The mobile DOM order remains the reading, keyboard, and focus order.
-## Ownership
+Layout owns structure. UI Style Kit owns paint. Interactive Surface owns interaction styling.
-Layout Style CSS owns spatial behavior: containment, wrappers, flow, grids, areas, spans, sizing, and responsive arrangement. UI Style Kit owns visual paint. Interactive Surface owns interaction-state styling.
+## Documentation
-The package has no runtime or peer dependencies. `ui-style-kit-css@2.1.0` and `interactive-surface-css@1.5.0` are released registry fixtures used to prove optional integration.
-
-## Supported Baseline
-
-- Node.js 20 or newer for package development
-- Current evergreen Chromium, Firefox, and WebKit
-- Mobile-first DOM order with core thresholds at `48rem` and `64rem`, nearest-container personality overrides, and `64rem` feasibility gates for three- and four-track application shells
-
-The deprecated UI structural bridge remains available for existing UI-prefixed layout aliases, but canonical 2.1 examples use UI Style Kit visual CSS, the UI token bridge, Interactive Surface `state-core.css`, and Layout core.
+- [Getting Started](Getting-Started.md)
+- [Installation And CDN](Installation-And-CDN.md)
+- [Layout Primitives](Layout-Primitives.md)
+- [Layout Recipes](Layout-Recipes.md)
+- [Layout Styles](Layout-Styles.md)
+- [Migrating To 3.0](Migrating-To-3.0.md)
+- [Demo And GitHub Pages](Demo-And-GitHub-Pages.md)
+- [Release And Publishing](Release-And-Publishing.md)
+- [Security And Support](Security-And-Support.md)
diff --git a/docs/wiki/Installation-And-CDN.md b/docs/wiki/Installation-And-CDN.md
index 705d747..f72c840 100644
--- a/docs/wiki/Installation-And-CDN.md
+++ b/docs/wiki/Installation-And-CDN.md
@@ -1,47 +1,51 @@
# Installation And CDN
-Layout Style CSS 2.0 is dependency-free and has no peer dependency contract. Node.js 20 or newer is required only for package development and verification.
+## Requirements
-## npm
+- Node.js 20 or newer for development
+- Evergreen Chromium, Firefox, or WebKit
+- No runtime or peer dependencies
+
+## Package
```bash
-npm install layout-style-css@2.1.1
+npm install layout-style-css@3.0.0
```
-## Focused Exports
+```js
+import "layout-style-css";
+```
-| Import | Purpose |
-| --- | --- |
-| `layout-style-css` | Full v2 core and all personalities. |
-| `layout-style-css/min.css` | Minified full bundle. |
-| `layout-style-css/core.css` | Wrappers, primitives, recipes, and utilities. |
-| `layout-style-css/wrappers.css` | Wrapper tokens and containment. |
-| `layout-style-css/primitives.css` | Composition primitives. |
-| `layout-style-css/recipes.css` | Seven recipe roots and named areas. |
-| `layout-style-css/utilities.css` | Structural utility layer. |
-| `layout-style-css/personalities.css` | All personalities. |
-| `layout-style-css/personalities/minimal-saas.css` | One personality; replace the name as needed. |
-| `layout-style-css/integrations/ui-style-kit.css` | Import-free structural UI bridge. |
-| `layout-style-css/legacy.css` | Full v2 bundle with v1 aliases. |
+The root import is the zero-configuration full bundle. Focused exports are:
-The old `all-with-ui-kit*`, `all.css`, `base.css`, `bridge.css`, and root personality exports do not exist in v2.
+- `layout-style-css/min.css`
+- `layout-style-css/core.css`
+- `layout-style-css/foundation.css`
+- `layout-style-css/wrappers.css`
+- `layout-style-css/primitives.css`
+- `layout-style-css/recipes.css`
+- `layout-style-css/utilities.css`
+- `layout-style-css/personalities.css`
+- `layout-style-css/personalities/minimal-saas.css` and the other fifteen profile names
+- `layout-style-css/package.json`
-## Import Modes
+`core.css` contains Foundation, Wrappers, Primitives, Recipes, and Utilities. The default bundle adds all personality profiles.
-Standalone:
+## CDN
-```js
-import "layout-style-css";
+```html
+
```
-Layout plus UI Style Kit:
-
-```js
-import "ui-style-kit-css/visual.css";
-import "layout-style-css";
+```html
+
```
-All three libraries, in required order:
+The CDN paths include `/dist/` because CDN clients address files in the published tarball, while package import maps use the public exports.
+
+## Ecosystem Order
+
+Layout has no companion imports. When all three libraries are installed, keep ownership explicit:
```js
import "ui-style-kit-css/visual.css";
@@ -50,23 +54,22 @@ import "interactive-surface-css/state-core.css";
import "layout-style-css";
```
-The first import block is deprecated compatibility for legacy UI-prefixed structural aliases. Canonical 2.1 imports use the released `ui-style-kit-css@2.1.0` visual CSS, `ui-style-kit-css/interactive-surface-theme.css`, released `interactive-surface-css@1.5.0` state core, and Layout core.
+Layout owns structure. UI Style Kit owns paint. Interactive Surface owns interaction styling.
-## CDN
-
-Layout only:
-
-```html
-
-
-```
+## Cascade Layers
-For optional companions, preserve the same order as the package imports: UI Style Kit visual CSS, UI Style Kit `interactive-surface-theme.css`, Interactive Surface 1.5.0 `state-core.css`, then Layout core. Load `layout-style-css/integrations/ui-style-kit.css` only for deprecated structural aliases.
+The module order is:
-## Browser Baseline
+1. `ly.reset`
+2. `ly.tokens`
+3. `ly.wrappers`
+4. `ly.primitives`
+5. `ly.recipes`
+6. `ly.utilities`
+7. `ly.personalities`
-Current evergreen Chromium, Firefox, and WebKit are supported. Core container-driven enhancements activate at `48rem` and `64rem`; personalities may use personality-specific thresholds. Unsupported container-query environments retain the mobile source-order fallback.
+Application styles can override public custom properties without reordering the package modules.
-## Source Ownership
+## Clean-Break Note
-`styles/` contains authored CSS. `dist/` is generated. Consumers should use package exports or CDN dist files, never internal source paths.
+v3 does not export a compatibility bundle, legacy aliases, the deprecated structural bridge, extensionless aliases, or responsive/order utility families. See [Migrating To 3.0](Migrating-To-3.0.md).
diff --git a/docs/wiki/Layout-Primitives.md b/docs/wiki/Layout-Primitives.md
index 954a652..49edc87 100644
--- a/docs/wiki/Layout-Primitives.md
+++ b/docs/wiki/Layout-Primitives.md
@@ -1,48 +1,62 @@
# Layout Primitives
-V2 primitives are structural, mobile-first, and safe to use without a visual design system.
+## Foundation And Containment
-## Semantic Wrappers
+`.ly-root` supplies shared structural tokens, shrink safety, the named `ly-scope` inline-size container, and height-aware defaults. Reset and public tokens live in `layout-style-css/foundation.css`.
-`.ly-wrapper` defaults to the `72rem` content measure and establishes an inline-size container. Fluid logical gutters include safe-area insets.
+Every primitive applies `min-inline-size: 0` and `min-block-size: 0` where tracks or children need to shrink.
-Layout personalities can provide a distinct measure for the plain `.ly-wrapper`. Explicit semantic wrapper variants always keep the measures below, so changing the demo wrapper control produces a real structural change under every personality.
+## Wrappers
-| Selector | Measure or behavior |
-| --- | --- |
-| `.ly-wrapper--compact` | `40rem` |
-| `.ly-wrapper--prose` | `68ch` |
-| `.ly-wrapper--content` | `72rem`, also the default |
-| `.ly-wrapper--wide` | `112rem` |
-| `.ly-wrapper--full` | Full available inline size |
-| `.ly-wrapper--breakout` | Content, feature, and full lanes |
+Wrappers are optional local responsive scopes:
-Breakout children use `.ly-lane--content`, `.ly-lane--feature`, `.ly-lane--full`, or equivalent `data-ly-lane` attributes.
+- `.ly-wrapper--compact`
+- `.ly-wrapper--prose`
+- `.ly-wrapper--content`
+- `.ly-wrapper--wide`
+- `.ly-wrapper--full`
+- `.ly-wrapper--breakout`
-## Composition
+Breakout children select clamped lanes with `data-ly-lane="content"`, `data-ly-lane="feature"`, or `data-ly-lane="full"`.
-| Primitive | Contract |
-| --- | --- |
-| `.ly-stack` | Vertical flow with a shared stack gap. |
-| `.ly-cluster` | Wrapping inline group. |
-| `.ly-center` | Centered element with a bounded measure. |
-| `.ly-cover` | Full-height vertical composition with an optional centered child. |
-| `.ly-switcher` | Wrapping equal items based on available inline size. |
-| `.ly-sidebar` | Side and content regions that wrap safely. |
-| `.ly-grid` | Explicit structural grid; `.ly-grid--auto` uses auto-fit. |
-| `.ly-split` | One column, then two columns from `48rem`. |
-| `.ly-panes` | One column with two- and three-pane variants. |
-| `.ly-media` | Media, content, and action areas. |
-| `.ly-reel` | Bounded horizontal flow with scroll snapping. |
-| `.ly-frame` | Stable aspect-ratio frame. |
-| `.ly-scroll` | Bounded scrolling with overscroll containment. |
+## Flow
-Primitives respond to their nearest wrapper or recipe container at the `48rem` and `64rem` core thresholds. They do not set color, typography, borders, shadows, or interaction states.
+- `.ly-stack` creates vertical flow.
+- `.ly-cluster` wraps inline groups.
+- `.ly-center` centers a bounded composition.
+- `.ly-cover` fills available block size while preserving reachable normal flow.
-For v1 migrations, `legacy.css` keeps `.ly-content` as `min-inline-size: 0` and preserves only the minimum block size and spacing of `.ly-divider`. A visible divider is paint and must come from UI Style Kit or the application theme; `.ly-surface--raised` is removed for the same ownership reason.
+## Adaptive Tracks
-## Structural Utilities
+- `.ly-switcher` wraps when its intrinsic threshold is no longer feasible.
+- `.ly-sidebar` keeps a preferred rail while the content can meet its minimum.
+- `.ly-grid` uses auto-fit tracks and `--ly-grid-min`.
+- `.ly-split` creates balanced intrinsic regions.
+- `.ly-panes` creates a preferred workspace rail and flexible pane.
+- `.ly-media` wraps media and content without a viewport breakpoint.
-The utility module includes grid column variables, spans, gaps, padding, sizing, overflow, alignment, frame ratios, visibility, and explicit order escape hatches.
+## Frame And Overflow
-Ordering families are available at base, medium container (`ly-md-*`), and large container (`ly-lg-*`) sizes. They include first, normal, last, and numeric values 1 through 6. Visual reordering can conflict with reading and focus order; see [Migrating To 2.0](Migrating-To-2.0.md) before using them.
+- `.ly-frame` keeps a configurable aspect ratio.
+- `.ly-reel` is the deliberate horizontal-flow primitive.
+- `.ly-scroll` is the deliberate bounded vertical-scroll primitive.
+
+In normal use, only `.ly-reel` introduces intentional horizontal scrolling, and only `.ly-scroll` introduces intentional vertical scrolling. Other wrappers, primitives, and recipes clamp to their available inline size.
+
+## Height Behavior
+
+Page, cover, and bounded scroll behaviors use `vh` fallbacks followed by dynamic viewport units such as `100dvh`.
+
+At `44rem` viewport height or less, gaps and scroll maxima tighten. At `30rem` or less, forced cover/shell minimums and recipe-owned sticky positioning are removed. Required regions remain in normal document flow.
+
+## Public Tuning
+
+Advanced consumers can override stable custom properties for:
+
+- gaps and spacing
+- wrapper measures and gutters
+- sidebar, pane, media, reel, and grid minimums
+- frame ratios
+- shell, cover, and bounded-scroll sizing
+
+These tokens tune behavior without creating a second breakpoint system.
diff --git a/docs/wiki/Layout-Recipes.md b/docs/wiki/Layout-Recipes.md
index 9a4ebe8..ef040ed 100644
--- a/docs/wiki/Layout-Recipes.md
+++ b/docs/wiki/Layout-Recipes.md
@@ -1,49 +1,58 @@
# Layout Recipes
-Recipes are inline-size containers with an authoritative single-column mobile fallback. At the `48rem` and `64rem` core thresholds, named grid areas rearrange without changing DOM, reading, or focus order. Layout personalities can layer personality-specific thresholds over those core recipes.
+Recipes are attribute-only semantic layouts. The mobile DOM order is authoritative, and automatic container enhancement is the zero-configuration default.
-## Public Hooks
+## Automatic Thresholds
-Use `data-ly-recipe` with one of:
+| Recipe | Nearest `ly-scope` threshold |
+| --- | --- |
+| `data-ly-recipe="split-hero"` | `42rem` |
+| `data-ly-recipe="list-detail"` | `44rem` |
+| `data-ly-recipe="docs"` | `48rem` |
+| `data-ly-recipe="app-shell"` | medium `52rem`, wide `72rem` |
+| `data-ly-recipe="dashboard"` | medium `52rem`, wide `72rem` |
+| `data-ly-recipe="gallery"` | intrinsic; no topology query |
+| `data-ly-recipe="card-grid"` | intrinsic; no topology query |
-- `app-shell`
-- `dashboard`
-- `docs`
-- `list-detail`
-- `split-hero`
-- `gallery`
-- `card-grid`
+Recipe roots also establish `ly-scope`, so child compositions can respond without extra setup.
-The attribute is the complete recipe API, not metadata for a class. A root with only `data-ly-recipe="docs"` receives the same mobile fallback, containment, named areas, and responsive geometry as `.ly-docs`; the class form remains available as an equivalent option.
+## Areas
-Use `data-ly-area` with `header`, `nav`, `main`, `aside`, `footer`, `content`, `media`, `actions`, `primary`, or `secondary`.
+Canonical `data-ly-area` values are:
-## Application Recipe
+- App shell: `header`, `sidebar`, `main`, `aside`, `footer`
+- Dashboard and Docs: `header`, `nav`, `main`, `aside`, `footer`
+- List detail: `primary`, `secondary`, `actions`
+- Split hero: `content`, `media`, `actions`
```html
-
-
- Toolbar
-
- Workspace
-
-
-
-
+
+ Docs
+
+ Article
+
+
+
```
-Place regions in the order that makes sense on a narrow screen. The recipe uses named areas for wide-container placement and never uses CSS `order`.
-
-## Content And Media Recipes
+## Manual Responsiveness
-`docs` creates a documentation shell. At `64rem`, its navigation spans the left column while `header`, `main`, `aside`, and `footer` remain in source order and stack in the right column; Dashboard retains its three-column wide shell. `list-detail` arranges primary, secondary, and action regions. `split-hero` arranges content, media, and actions. `gallery` and `card-grid` create responsive repeated-item grids.
+`data-ly-responsive="manual"` disables automatic topology rules while retaining the stacked fallback.
-```html
-
-