layout-style-css 1.1.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +33 -8
  2. package/CONTRIBUTING.md +12 -7
  3. package/README.md +231 -636
  4. package/SECURITY.md +11 -6
  5. package/demo/demo.css +523 -0
  6. package/demo/demo.js +520 -0
  7. package/demo/index.html +323 -976
  8. package/demo/site.webmanifest +1 -1
  9. package/demo/sitemap.xml +1 -1
  10. package/dist/core.css +6 -0
  11. package/dist/{layout-ui-style-kit-bridge.css → integrations/ui-style-kit.css} +13 -8
  12. package/dist/layout-style-css.css +1473 -1903
  13. package/dist/layout-style-css.min.css +1 -1
  14. package/dist/legacy.css +787 -0
  15. package/dist/personalities/bauhaus.css +46 -0
  16. package/dist/personalities/bento.css +43 -0
  17. package/dist/personalities/brutalism.css +36 -0
  18. package/dist/personalities/cyberpunk.css +36 -0
  19. package/dist/personalities/f-pattern.css +48 -0
  20. package/dist/personalities/maximalist.css +51 -0
  21. package/dist/personalities/minimal-saas.css +37 -0
  22. package/dist/personalities/mondrian.css +44 -0
  23. package/dist/personalities/neumorphism.css +46 -0
  24. package/dist/personalities/retro-glass.css +44 -0
  25. package/dist/personalities/retrofuturism.css +36 -0
  26. package/dist/personalities/split-screen.css +41 -0
  27. package/dist/personalities/synthwave.css +48 -0
  28. package/dist/personalities/tactile.css +39 -0
  29. package/dist/personalities/y2k.css +36 -0
  30. package/dist/personalities/z-pattern.css +49 -0
  31. package/dist/personalities.css +18 -0
  32. package/dist/primitives.css +219 -0
  33. package/dist/recipes.css +270 -0
  34. package/dist/utilities.css +162 -0
  35. package/dist/wrappers.css +174 -0
  36. package/docs/wiki/Contributing.md +36 -30
  37. package/docs/wiki/Demo-And-GitHub-Pages.md +53 -39
  38. package/docs/wiki/Getting-Started.md +51 -68
  39. package/docs/wiki/Home.md +33 -48
  40. package/docs/wiki/Installation-And-CDN.md +73 -58
  41. package/docs/wiki/Layout-Primitives.md +48 -57
  42. package/docs/wiki/Layout-Recipes.md +49 -80
  43. package/docs/wiki/Layout-Styles.md +33 -43
  44. package/docs/wiki/Migrating-To-2.0.md +186 -0
  45. package/docs/wiki/Release-And-Publishing.md +75 -69
  46. package/docs/wiki/Security-And-Support.md +36 -34
  47. package/docs/wiki/UI-Style-Kit-Compatibility.md +50 -54
  48. package/docs/wiki/_Sidebar.md +15 -14
  49. package/package.json +36 -45
  50. package/styles/core.css +6 -0
  51. package/styles/{layout-ui-style-kit-bridge.css → integrations/ui-style-kit.css} +13 -8
  52. package/styles/legacy.css +173 -0
  53. package/styles/personalities/bauhaus.css +46 -0
  54. package/styles/personalities/bento.css +43 -0
  55. package/styles/personalities/brutalism.css +36 -0
  56. package/styles/personalities/cyberpunk.css +36 -0
  57. package/styles/personalities/f-pattern.css +48 -0
  58. package/styles/personalities/maximalist.css +51 -0
  59. package/styles/personalities/minimal-saas.css +37 -0
  60. package/styles/personalities/mondrian.css +44 -0
  61. package/styles/personalities/neumorphism.css +46 -0
  62. package/styles/personalities/retro-glass.css +44 -0
  63. package/styles/personalities/retrofuturism.css +36 -0
  64. package/styles/personalities/split-screen.css +41 -0
  65. package/styles/personalities/synthwave.css +48 -0
  66. package/styles/personalities/tactile.css +39 -0
  67. package/styles/personalities/y2k.css +36 -0
  68. package/styles/personalities/z-pattern.css +49 -0
  69. package/styles/personalities.css +18 -0
  70. package/styles/primitives.css +219 -0
  71. package/styles/recipes.css +270 -0
  72. package/styles/utilities.css +162 -0
  73. package/styles/wrappers.css +174 -0
  74. package/dist/layout-all-with-ui-kit-and-interactive-surface.css +0 -3
  75. package/dist/layout-all-with-ui-kit.css +0 -2
  76. package/dist/layout-all.css +0 -18
  77. package/dist/layout-base.css +0 -539
  78. package/dist/layout-style-bauhaus.css +0 -70
  79. package/dist/layout-style-bento.css +0 -76
  80. package/dist/layout-style-brutalism.css +0 -70
  81. package/dist/layout-style-cyberpunk.css +0 -70
  82. package/dist/layout-style-f-pattern.css +0 -76
  83. package/dist/layout-style-maximalist.css +0 -93
  84. package/dist/layout-style-minimal-saas.css +0 -67
  85. package/dist/layout-style-mondrian.css +0 -77
  86. package/dist/layout-style-neumorphism.css +0 -72
  87. package/dist/layout-style-retro-glass.css +0 -82
  88. package/dist/layout-style-retrofuturism.css +0 -71
  89. package/dist/layout-style-split-screen.css +0 -62
  90. package/dist/layout-style-synthwave.css +0 -88
  91. package/dist/layout-style-tactile.css +0 -70
  92. package/dist/layout-style-y2k.css +0 -72
  93. package/dist/layout-style-z-pattern.css +0 -76
  94. package/styles/layout-base.css +0 -539
  95. package/styles/layout-style-bauhaus.css +0 -70
  96. package/styles/layout-style-bento.css +0 -76
  97. package/styles/layout-style-brutalism.css +0 -70
  98. package/styles/layout-style-cyberpunk.css +0 -70
  99. package/styles/layout-style-f-pattern.css +0 -76
  100. package/styles/layout-style-maximalist.css +0 -93
  101. package/styles/layout-style-minimal-saas.css +0 -67
  102. package/styles/layout-style-mondrian.css +0 -77
  103. package/styles/layout-style-neumorphism.css +0 -72
  104. package/styles/layout-style-retro-glass.css +0 -82
  105. package/styles/layout-style-retrofuturism.css +0 -71
  106. package/styles/layout-style-split-screen.css +0 -62
  107. package/styles/layout-style-synthwave.css +0 -88
  108. package/styles/layout-style-tactile.css +0 -70
  109. package/styles/layout-style-y2k.css +0 -72
  110. package/styles/layout-style-z-pattern.css +0 -76
package/demo/index.html CHANGED
@@ -1,976 +1,323 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta http-equiv="x-ua-compatible" content="IE=edge">
6
- <meta http-equiv="content-language" content="en-US">
7
- <meta name="viewport" content="width=device-width, initial-scale=1">
8
- <meta name="title" content="layout-style-css + UI Style Kit CSS Demo">
9
- <meta name="description" content="Interactive shell-first layout demo for layout-style-css, ui-style-kit-css v2.0.1, and optional interactive-surface-css integrations.">
10
- <meta name="keywords" content="CSS layout library, layout styles, UI style kit CSS, shell layouts, responsive CSS, design system layout">
11
- <meta name="author" content="Foscat">
12
- <meta name="creator" content="Foscat">
13
- <meta name="publisher" content="Foscat">
14
- <meta name="abstract" content="Shell-first CSS layout primitives that mix independently with ui-style-kit-css visual systems.">
15
- <meta name="subject" content="CSS layout style library for UI shell composition">
16
- <meta name="classification" content="Developer tools, CSS libraries, design systems">
17
- <meta name="category" content="Software Development">
18
- <meta name="coverage" content="Worldwide">
19
- <meta name="distribution" content="Global">
20
- <meta name="rating" content="General">
21
- <meta name="revisit-after" content="7 days">
22
- <meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
23
- <meta name="googlebot" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
24
- <meta name="bingbot" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
25
- <meta name="referrer" content="strict-origin-when-cross-origin">
26
- <meta name="format-detection" content="telephone=no">
27
- <meta name="application-name" content="layout-style-css">
28
- <meta name="mobile-web-app-capable" content="yes">
29
- <meta name="apple-mobile-web-app-capable" content="yes">
30
- <meta name="apple-mobile-web-app-title" content="layout-style-css">
31
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
32
- <meta name="theme-color" content="#111827" media="(prefers-color-scheme: dark)">
33
- <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
34
- <meta name="msapplication-TileColor" content="#111827">
35
- <meta name="msapplication-config" content="./browserconfig.xml">
36
- <meta name="color-scheme" content="light dark">
37
- <meta property="og:type" content="website">
38
- <meta property="og:locale" content="en_US">
39
- <meta property="og:title" content="layout-style-css + UI Style Kit CSS Demo">
40
- <meta property="og:description" content="Swap layout shells independently from UI styles while keeping ui-style-kit-css in charge of visual identity.">
41
- <meta property="og:image" content="https://foscat.github.io/layout-style-css/assets/social-card.png">
42
- <meta property="og:image:secure_url" content="https://foscat.github.io/layout-style-css/assets/social-card.png">
43
- <meta property="og:image:alt" content="layout-style-css shell-first CSS social card">
44
- <meta property="og:image:type" content="image/png">
45
- <meta property="og:image:width" content="1200">
46
- <meta property="og:image:height" content="630">
47
- <meta property="og:url" content="https://foscat.github.io/layout-style-css/">
48
- <meta property="og:site_name" content="layout-style-css">
49
- <meta property="og:updated_time" content="2026-06-30T00:00:00-05:00">
50
- <meta name="twitter:card" content="summary_large_image">
51
- <meta name="twitter:title" content="layout-style-css + UI Style Kit CSS Demo">
52
- <meta name="twitter:description" content="Shell-first responsive layouts that mix and match with ui-style-kit-css v2.0.1.">
53
- <meta name="twitter:image" content="https://foscat.github.io/layout-style-css/assets/social-card.png">
54
- <meta name="twitter:image:alt" content="layout-style-css shell-first CSS social card">
55
- <meta itemprop="name" content="layout-style-css + UI Style Kit CSS Demo">
56
- <meta itemprop="description" content="Shell-first responsive layouts that mix and match with ui-style-kit-css v2.0.1.">
57
- <meta itemprop="image" content="https://foscat.github.io/layout-style-css/assets/social-card.png">
58
- <link rel="canonical" href="https://foscat.github.io/layout-style-css/">
59
- <link rel="dns-prefetch" href="https://unpkg.com">
60
- <link rel="preconnect" href="https://unpkg.com" crossorigin>
61
- <link rel="image_src" href="./assets/social-card.png">
62
- <link rel="icon" type="image/svg+xml" href="./assets/favicon.svg">
63
- <link rel="shortcut icon" href="./assets/favicon.svg">
64
- <link rel="apple-touch-icon" href="./assets/apple-touch-icon.svg">
65
- <link rel="mask-icon" href="./assets/favicon.svg" color="#111827">
66
- <link rel="manifest" href="./site.webmanifest">
67
- <link rel="sitemap" type="application/xml" title="Sitemap" href="./sitemap.xml">
68
- <title>layout-style-css + UI Style Kit CSS Demo</title>
69
- <link rel="stylesheet" href="https://unpkg.com/ui-style-kit-css@2.0.1/dist/ui-style-kit.with-bridge.min.css">
70
- <link rel="stylesheet" href="../dist/layout-all.css">
71
- <script type="application/ld+json">
72
- {
73
- "@context": "https://schema.org",
74
- "@type": "SoftwareSourceCode",
75
- "name": "layout-style-css",
76
- "description": "A shell-first CSS layout library designed to mix independently with ui-style-kit-css v2.0.1.",
77
- "programmingLanguage": "CSS",
78
- "applicationCategory": "DeveloperApplication",
79
- "url": "https://foscat.github.io/layout-style-css/",
80
- "image": "https://foscat.github.io/layout-style-css/assets/social-card.png",
81
- "datePublished": "2026-06-30",
82
- "dateModified": "2026-06-30",
83
- "keywords": [
84
- "CSS layout library",
85
- "layout styles",
86
- "UI style kit CSS",
87
- "responsive shell layouts",
88
- "design system layout"
89
- ],
90
- "author": {
91
- "@type": "Organization",
92
- "name": "Foscat"
93
- },
94
- "publisher": {
95
- "@type": "Organization",
96
- "name": "Foscat"
97
- }
98
- }
99
- </script>
100
- <style>
101
- /*
102
- Demo CSS is intentionally structural. UI Style Kit classes and native
103
- selectors own paint, typography, borders, shadows, and control styling.
104
- */
105
- .demo-header {
106
- width: 100%;
107
- display: flex;
108
- align-items: center;
109
- justify-content: space-between;
110
- gap: 1rem;
111
- padding: 0.875rem var(--ly-page-padding-inline);
112
- }
113
-
114
- .demo-brand {
115
- display: grid;
116
- gap: 0.125rem;
117
- min-width: 12rem;
118
- }
119
-
120
- .demo-controls {
121
- display: flex;
122
- flex-wrap: wrap;
123
- align-items: center;
124
- justify-content: flex-end;
125
- gap: 0.625rem;
126
- }
127
-
128
- .demo-controls-shell {
129
- min-width: 0;
130
- }
131
-
132
- .demo-controls-panel {
133
- min-width: 0;
134
- }
135
-
136
- .demo-controls-heading {
137
- display: none;
138
- }
139
-
140
- #demoControlsToggle,
141
- #demoControlsClose,
142
- #demoControlsBackdrop {
143
- display: none;
144
- }
145
-
146
- .demo-select {
147
- min-width: 10.5rem;
148
- }
149
-
150
- .demo-sidebar {
151
- padding: var(--ly-space-5);
152
- }
153
-
154
- .demo-sidebar-inner {
155
- display: grid;
156
- grid-auto-rows: max-content;
157
- align-content: start;
158
- gap: var(--ly-space-4);
159
- }
160
-
161
- .demo-sidebar-list {
162
- display: grid;
163
- gap: var(--ly-space-2);
164
- margin: 0;
165
- padding: 0;
166
- list-style: none;
167
- }
168
-
169
- .demo-sidebar-list a {
170
- display: block;
171
- padding: 0.65rem 0.75rem;
172
- }
173
-
174
- .demo-title {
175
- max-width: 12ch;
176
- margin: 0;
177
- }
178
-
179
- .demo-lede {
180
- max-width: 62ch;
181
- margin: 0;
182
- }
183
-
184
- .demo-pill {
185
- display: inline-flex;
186
- align-items: center;
187
- width: fit-content;
188
- min-height: 2rem;
189
- padding-inline: 0.75rem;
190
- }
191
-
192
- .demo-stage {
193
- --ly-frame-ratio: auto;
194
- min-height: 18rem;
195
- display: grid;
196
- align-content: end;
197
- gap: var(--ly-space-4);
198
- }
199
-
200
- .demo-stat {
201
- min-height: 9rem;
202
- display: grid;
203
- align-content: space-between;
204
- gap: var(--ly-space-3);
205
- }
206
-
207
- .demo-panel-title {
208
- margin: 0;
209
- }
210
-
211
- .demo-mini-grid {
212
- display: grid;
213
- grid-template-columns: repeat(3, minmax(0, 1fr));
214
- gap: var(--ly-space-3);
215
- }
216
-
217
- .demo-mini-grid > * {
218
- min-width: 0;
219
- }
220
-
221
- .demo-detail-layout {
222
- grid-template-columns: 1fr;
223
- }
224
-
225
- .demo-recipe-grid {
226
- display: grid;
227
- grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
228
- gap: var(--ly-space-4);
229
- }
230
-
231
- .demo-recipe-card {
232
- display: grid;
233
- align-content: start;
234
- gap: var(--ly-space-3);
235
- }
236
-
237
- .demo-recipe-preview {
238
- display: grid;
239
- gap: var(--ly-space-2);
240
- }
241
-
242
- .demo-recipe-preview code {
243
- overflow-wrap: anywhere;
244
- }
245
-
246
- .demo-recipe-swatch {
247
- min-block-size: 3.75rem;
248
- }
249
-
250
- @media (min-width: 90rem) {
251
- .demo-detail-layout {
252
- grid-template-columns: minmax(10rem, 0.4fr) minmax(0, 1fr);
253
- }
254
- }
255
-
256
- @media (max-width: 74.999rem) {
257
- .demo-header {
258
- align-items: center;
259
- gap: 0.75rem;
260
- }
261
-
262
- .demo-brand {
263
- flex: 1 1 min(100%, 13rem);
264
- min-width: 0;
265
- }
266
-
267
- #demoControlsToggle {
268
- display: inline-flex;
269
- flex: 0 0 auto;
270
- }
271
-
272
- #demoControlsClose {
273
- display: inline-flex;
274
- }
275
-
276
- #demoControlsBackdrop {
277
- position: fixed;
278
- inset: 0;
279
- z-index: calc(var(--ly-z-header) + 10);
280
- }
281
-
282
- #demoControlsBackdrop[data-open="true"] {
283
- display: block;
284
- }
285
-
286
- .demo-controls-shell {
287
- position: fixed;
288
- inset-block: 0;
289
- inset-inline-end: 0;
290
- z-index: calc(var(--ly-z-header) + 20);
291
- width: min(calc(100% - 2rem), 24rem);
292
- padding: var(--ly-space-4);
293
- overflow: auto;
294
- pointer-events: none;
295
- transform: translateX(100%);
296
- transition: transform 160ms ease;
297
- }
298
-
299
- .demo-controls-shell[aria-hidden="false"] {
300
- pointer-events: auto;
301
- transform: translateX(0);
302
- }
303
-
304
- .demo-controls-panel {
305
- min-height: 100%;
306
- display: grid;
307
- grid-auto-rows: max-content;
308
- align-content: start;
309
- gap: var(--ly-space-4);
310
- }
311
-
312
- .demo-controls-heading {
313
- display: flex;
314
- align-items: center;
315
- justify-content: space-between;
316
- gap: var(--ly-space-3);
317
- }
318
-
319
- .demo-controls {
320
- display: grid;
321
- grid-auto-rows: max-content;
322
- align-content: start;
323
- justify-content: stretch;
324
- }
325
-
326
- .demo-controls > * {
327
- min-width: 0;
328
- }
329
-
330
- .demo-select {
331
- width: 100%;
332
- }
333
-
334
- .ly-root[data-demo-controls-open="true"] {
335
- overflow: hidden;
336
- }
337
- }
338
-
339
- @media (min-width: 75rem) {
340
- .demo-controls-panel {
341
- display: contents;
342
- }
343
- }
344
- </style>
345
- </head>
346
- <body class="ly-root" data-ui="minimal-saas" data-layout="minimal-saas" layout-style="minimal-saas" data-theme="arctic-indigo" data-mode="light">
347
- <div class="ly-app-shell">
348
- <header class="ly-header ly-header--sticky ly-app-header">
349
- <div class="demo-header">
350
- <div class="demo-brand">
351
- <strong>layout-style-css</strong>
352
- <span>Independent shell layouts for ui-style-kit-css@2.0.1</span>
353
- </div>
354
-
355
- <button
356
- type="button"
357
- id="demoControlsToggle"
358
- aria-controls="demoControlsDrawer"
359
- aria-expanded="false"
360
- data-ui-kit="button button-secondary"
361
- >Controls</button>
362
-
363
- <span id="demoControlsBackdrop" aria-hidden="true"></span>
364
-
365
- <div class="demo-controls-shell" id="demoControlsDrawer" aria-hidden="true">
366
- <div class="demo-controls-panel" data-ui-kit="panel">
367
- <div class="demo-controls-heading">
368
- <strong>Demo controls</strong>
369
- <button type="button" id="demoControlsClose" data-ui-kit="button">Close</button>
370
- </div>
371
-
372
- <div class="demo-controls">
373
- <label>
374
- <span class="ly-visually-hidden">UI system</span>
375
- <select class="demo-select" id="uiSelect" data-ui-kit="select">
376
- <option value="minimal-saas">Minimal SaaS UI</option>
377
- <option value="bento">Bento UI</option>
378
- <option value="maximalist">Maximalist UI</option>
379
- <option value="bauhaus">Bauhaus UI</option>
380
- <option value="tactile">Tactile UI</option>
381
- <option value="neumorphism">Neumorphism UI</option>
382
- <option value="retrofuturism">Retrofuturism UI</option>
383
- <option value="brutalism">Brutalism UI</option>
384
- <option value="cyberpunk">Cyberpunk UI</option>
385
- <option value="y2k">Y2K UI</option>
386
- <option value="retro-glass">Retro Glass UI</option>
387
- </select>
388
- </label>
389
- <label>
390
- <span class="ly-visually-hidden">Layout style</span>
391
- <select class="demo-select" id="layoutSelect" data-ui-kit="select">
392
- <option value="minimal-saas">Minimal SaaS Layout</option>
393
- <option value="bento">Bento Layout</option>
394
- <option value="maximalist">Maximalist Layout</option>
395
- <option value="bauhaus">Bauhaus Layout</option>
396
- <option value="tactile">Tactile Layout</option>
397
- <option value="neumorphism">Neumorphism Layout</option>
398
- <option value="retrofuturism">Retrofuturism Layout</option>
399
- <option value="brutalism">Brutalism Layout</option>
400
- <option value="cyberpunk">Cyberpunk Layout</option>
401
- <option value="y2k">Y2K Layout</option>
402
- <option value="retro-glass">Retro Glass Layout</option>
403
- <option value="f-pattern">F-pattern Layout</option>
404
- <option value="z-pattern">Z-pattern Layout</option>
405
- <option value="split-screen">Split-Screen Layout</option>
406
- <option value="mondrian">Mondrian Layout</option>
407
- <option value="synthwave">Synthwave Layout</option>
408
- </select>
409
- </label>
410
- <label>
411
- <span class="ly-visually-hidden">Theme</span>
412
- <select class="demo-select" id="themeSelect" data-ui-kit="select">
413
- <option value="arctic-indigo">Arctic Indigo</option>
414
- <option value="midnight-gold">Midnight Gold</option>
415
- <option value="ocean-steel">Ocean Steel</option>
416
- <option value="forest-moss">Forest Moss</option>
417
- <option value="sunset-ember">Sunset Ember</option>
418
- <option value="royal-plum">Royal Plum</option>
419
- <option value="graphite-cyan">Graphite Cyan</option>
420
- <option value="desert-sage">Desert Sage</option>
421
- <option value="rose-quartz">Rose Quartz</option>
422
- <option value="cyber-lime">Cyber Lime</option>
423
- </select>
424
- </label>
425
- <label>
426
- <span class="ly-visually-hidden">Mode</span>
427
- <select class="demo-select" id="modeSelect" data-ui-kit="select">
428
- <option value="light">Light</option>
429
- <option value="dark">Dark</option>
430
- <option value="contrast">Contrast</option>
431
- </select>
432
- </label>
433
- <button type="button" id="mixedPreset" data-ui-kit="button button-secondary">Cyberpunk UI + Maximalist Layout</button>
434
- </div>
435
- </div>
436
- </div>
437
- </div>
438
- </header>
439
-
440
- <aside class="ly-app-sidebar demo-sidebar" data-ui-kit="panel">
441
- <div class="demo-sidebar-inner">
442
- <span class="demo-pill" data-ui-kit="badge badge-secondary">Shell rail</span>
443
- <nav aria-label="Demo sections" data-ui-kit="nav">
444
- <ul class="demo-sidebar-list">
445
- <li><a href="#stage" aria-current="page" data-ui-kit="nav-link">Stage</a></li>
446
- <li><a href="#metrics" data-ui-kit="nav-link">Metrics</a></li>
447
- <li><a href="#panes" data-ui-kit="nav-link">Panes</a></li>
448
- <li><a href="#recipes" data-ui-kit="nav-link">Recipes</a></li>
449
- </ul>
450
- </nav>
451
- <p>
452
- This same rail becomes a SaaS sidebar, Z-pattern support rail, Split-Screen half, Mondrian block, Synthwave dock, or Retro Glass side panel.
453
- </p>
454
- </div>
455
- </aside>
456
-
457
- <main class="ly-app-main">
458
- <section class="ly-section" id="stage">
459
- <div class="ly-wrapper ly-wrapper--wide ly-stack ly-gap-8">
460
- <div class="ly-split">
461
- <div class="ly-stack ly-gap-5 ly-readable">
462
- <span class="demo-pill" data-ui-kit="badge badge-primary">Matched by default, mixed by design</span>
463
- <h1 class="demo-title" data-ui-kit="title">Swap shells without swapping UI style.</h1>
464
- <p class="demo-lede">
465
- UI styles and layout designs work best together, but they are intentionally independent. Try
466
- <code>data-ui="cyberpunk"</code>, <code>data-layout="maximalist"</code>,
467
- <code>data-theme="arctic-indigo"</code>, and <code>data-mode="dark"</code>.
468
- </p>
469
- <div class="ly-cluster">
470
- <button type="button" id="matchedPreset" data-ui-kit="button button-primary">Match UI and Layout</button>
471
- <button type="button" id="contrastPreset" data-ui-kit="button">Try Retro Glass Layout</button>
472
- </div>
473
- </div>
474
-
475
- <aside class="ly-frame ly-surface ly-pad-6 demo-stage" data-ui-kit="panel">
476
- <div class="ly-stack ly-gap-4">
477
- <span class="demo-pill" data-ui-kit="badge">Responsive stage</span>
478
- <p>
479
- The layout style controls shell placement, pane rhythm, and grid behavior while UI Style Kit controls visual identity.
480
- </p>
481
- <fieldset>
482
- <legend>Native controls</legend>
483
- <label>
484
- Preview mode
485
- <select>
486
- <option>Matched pair</option>
487
- <option>Mixed pair</option>
488
- </select>
489
- </label>
490
- <label><input type="checkbox" checked> UI style hooks active</label>
491
- <progress value="72" max="100">72%</progress>
492
- </fieldset>
493
- </div>
494
- </aside>
495
- </div>
496
-
497
- <div class="ly-grid ly-grid--auto" id="metrics">
498
- <article class="ly-surface ly-pad-6 demo-stat" data-ui-kit="card">
499
- <span>Shell mode</span>
500
- <strong>16</strong>
501
- <span>layout styles</span>
502
- </article>
503
- <article class="ly-surface ly-pad-6 demo-stat" data-ui-kit="card">
504
- <span>Contract</span>
505
- <strong>0</strong>
506
- <span>required new classes</span>
507
- </article>
508
- <article class="ly-surface ly-pad-6 demo-stat" data-ui-kit="card">
509
- <span>Switches</span>
510
- <strong>4</strong>
511
- <span>UI, layout, theme, mode</span>
512
- </article>
513
- <article class="ly-surface ly-pad-6 demo-stat" data-ui-kit="card">
514
- <span>Bundle</span>
515
- <strong>3</strong>
516
- <span>optional libraries together</span>
517
- </article>
518
- </div>
519
-
520
- <div class="ly-panes ly-panes--two" id="panes">
521
- <aside class="ly-surface ly-pad-6 ly-stack ly-gap-4" data-ui-kit="panel">
522
- <h2 class="demo-panel-title">Supporting pane</h2>
523
- <p>
524
- Each layout decides whether this feels like a sidecar, dock, island, slab, or glass rail.
525
- </p>
526
- <div class="demo-mini-grid" aria-hidden="true">
527
- <span data-ui-kit="badge">Grid</span>
528
- <span data-ui-kit="badge badge-secondary">Pane</span>
529
- <span data-ui-kit="badge badge-primary">Shell</span>
530
- </div>
531
- </aside>
532
-
533
- <article class="ly-surface ly-pad-6 ly-stack ly-gap-5" data-ui-kit="card">
534
- <h2 class="demo-panel-title">Primary workspace</h2>
535
- <p>
536
- The markup stays fixed while the selected layout style changes the shell, split, pane, and auto-grid composition.
537
- </p>
538
- <div class="ly-sidebar-layout demo-detail-layout">
539
- <aside class="ly-surface ly-pad-4" data-ui-kit="panel">Context</aside>
540
- <article class="ly-surface ly-pad-4" data-ui-kit="panel">Workspace detail</article>
541
- </div>
542
- </article>
543
- </div>
544
-
545
- <section class="ly-stack ly-gap-5" id="recipes" aria-labelledby="recipes-title">
546
- <div class="ly-wrapper ly-wrapper--readable ly-stack ly-gap-3">
547
- <span class="demo-pill" data-ui-kit="badge badge-secondary">Layout Recipes</span>
548
- <h2 class="demo-panel-title" id="recipes-title">Recipe-style organization for major wrapper contracts.</h2>
549
- <p>
550
- Start with a recipe, then mix UI style, layout style, theme, and mode without changing the wrapper contract.
551
- </p>
552
- </div>
553
-
554
- <div class="ly-card-grid demo-recipe-grid">
555
- <article class="ly-surface ly-pad-5 ly-card-md demo-recipe-card" data-ui-kit="card">
556
- <h3 class="demo-panel-title">App shell</h3>
557
- <p>Use one root shell for a persistent header, sidebar, and main workspace.</p>
558
- <div class="ly-wrapper ly-wrapper--readable demo-recipe-preview">
559
- <code>.ly-app-shell</code>
560
- <code>.ly-app-header</code>
561
- <code>.ly-app-sidebar</code>
562
- <code>.ly-app-main</code>
563
- </div>
564
- </article>
565
-
566
- <article class="ly-surface ly-pad-5 ly-card-md demo-recipe-card" data-ui-kit="card">
567
- <h3 class="demo-panel-title">Content page</h3>
568
- <p>Use a readable wrapper for documentation, articles, and focused landing sections.</p>
569
- <div class="ly-wrapper ly-wrapper--readable demo-recipe-preview">
570
- <code>.ly-wrapper</code>
571
- <code>.ly-wrapper--readable</code>
572
- <code>.ly-section</code>
573
- <code>.ly-stack</code>
574
- </div>
575
- </article>
576
-
577
- <article class="ly-surface ly-pad-5 ly-card-md demo-recipe-card" data-ui-kit="card">
578
- <h3 class="demo-panel-title">Card grid</h3>
579
- <p>Use auto-fit tracks for cards that collapse from desktop to tablet and mobile.</p>
580
- <div class="ly-wrapper ly-wrapper--readable demo-recipe-preview">
581
- <code>.ly-wrapper--wide</code>
582
- <code>.ly-card-grid</code>
583
- <code>.ly-surface</code>
584
- </div>
585
- </article>
586
-
587
- <article class="ly-surface ly-pad-5 ly-card-md demo-recipe-card" data-ui-kit="card">
588
- <h3 class="demo-panel-title">Split hero</h3>
589
- <p>Use a split when one message needs a supporting panel or interactive preview.</p>
590
- <div class="ly-wrapper ly-wrapper--readable demo-recipe-preview">
591
- <code>.ly-wrapper--xl</code>
592
- <code>.ly-split</code>
593
- <code>.ly-stack</code>
594
- <code>.ly-frame</code>
595
- </div>
596
- </article>
597
-
598
- <article class="ly-surface ly-pad-5 ly-card-md demo-recipe-card" data-ui-kit="card">
599
- <h3 class="demo-panel-title">Docs sidebar</h3>
600
- <p>Use a local sidebar inside the main content when the global shell is not enough.</p>
601
- <div class="ly-wrapper ly-wrapper--readable demo-recipe-preview">
602
- <code>.ly-sidebar-layout</code>
603
- <code>.ly-sidebar-layout--right</code>
604
- <code>.ly-sidebar</code>
605
- <code>.ly-content</code>
606
- </div>
607
- </article>
608
-
609
- <article class="ly-surface ly-pad-5 ly-card-md demo-recipe-card" data-ui-kit="card">
610
- <h3 class="demo-panel-title">List detail</h3>
611
- <p>Use adaptive panes for inboxes, editors, queues, and preview-driven workflows.</p>
612
- <div class="ly-wrapper ly-wrapper--readable demo-recipe-preview">
613
- <code>.ly-panes</code>
614
- <code>.ly-panes--two</code>
615
- <code>.ly-scroll-area</code>
616
- <code>.ly-surface</code>
617
- </div>
618
- </article>
619
-
620
- <article class="ly-surface ly-pad-5 ly-card-sm demo-recipe-card" data-ui-kit="card">
621
- <h3 class="demo-panel-title">Button group</h3>
622
- <p>Use a wrapping action row without forcing buttons to fill the mobile viewport.</p>
623
- <div class="ly-button-group">
624
- <button type="button" data-ui-kit="button button-primary">Primary</button>
625
- <button type="button" data-ui-kit="button">Secondary</button>
626
- </div>
627
- <div class="demo-recipe-preview">
628
- <code>.ly-button-group</code>
629
- <code>.saas-button-group</code>
630
- </div>
631
- </article>
632
-
633
- <article class="ly-surface ly-pad-5 ly-card-lg demo-recipe-card" data-ui-kit="card">
634
- <h3 class="demo-panel-title">Card size</h3>
635
- <p>Use sizing helpers when cards need consistent rhythm without hard-coded visual styles.</p>
636
- <div class="demo-recipe-preview">
637
- <code>.ly-card-sm</code>
638
- <code>.ly-card-md</code>
639
- <code>.ly-card-lg</code>
640
- <code>.saas-card-grid</code>
641
- </div>
642
- </article>
643
-
644
- <article class="ly-surface ly-pad-5 ly-card-md demo-recipe-card" data-ui-kit="card">
645
- <h3 class="demo-panel-title">Gallery</h3>
646
- <p>Use gallery tracks for image or media groups that should reflow without a script.</p>
647
- <div class="ly-gallery">
648
- <div class="ly-frame ly-frame-4x3 demo-recipe-swatch" data-ui-kit="panel"></div>
649
- <div class="ly-frame ly-frame-4x3 demo-recipe-swatch" data-ui-kit="panel"></div>
650
- <div class="ly-frame ly-frame-4x3 demo-recipe-swatch" data-ui-kit="panel"></div>
651
- </div>
652
- <div class="demo-recipe-preview">
653
- <code>.ly-gallery</code>
654
- <code>.rg-gallery</code>
655
- </div>
656
- </article>
657
-
658
- <article class="ly-surface ly-pad-5 ly-card-md demo-recipe-card" data-ui-kit="card">
659
- <h3 class="demo-panel-title">Carousel</h3>
660
- <p>Use horizontal snap tracks for preview rows while keeping card visuals external.</p>
661
- <div class="ly-carousel">
662
- <div class="ly-surface ly-pad-4 ly-card-sm" data-ui-kit="panel">One</div>
663
- <div class="ly-surface ly-pad-4 ly-card-sm" data-ui-kit="panel">Two</div>
664
- <div class="ly-surface ly-pad-4 ly-card-sm" data-ui-kit="panel">Three</div>
665
- </div>
666
- <div class="demo-recipe-preview">
667
- <code>.ly-carousel</code>
668
- <code>.bento-carousel</code>
669
- </div>
670
- </article>
671
-
672
- <article class="ly-surface ly-pad-5 ly-card-md demo-recipe-card" data-ui-kit="card">
673
- <h3 class="demo-panel-title">Frame and scroll</h3>
674
- <p>Use frames for media ratios and scroll areas for bounded content regions.</p>
675
- <div class="demo-recipe-preview">
676
- <code>.ly-frame</code>
677
- <code>.ly-frame-16x9</code>
678
- <code>.ly-scroll-area</code>
679
- <code>.ly-overflow-auto</code>
680
- </div>
681
- </article>
682
- </div>
683
- </section>
684
- </div>
685
- </section>
686
- </main>
687
- </div>
688
-
689
- <script>
690
- const body = document.body;
691
- const uiSelect = document.querySelector("#uiSelect");
692
- const layoutSelect = document.querySelector("#layoutSelect");
693
- const themeSelect = document.querySelector("#themeSelect");
694
- const modeSelect = document.querySelector("#modeSelect");
695
- const controlsToggle = document.querySelector("#demoControlsToggle");
696
- const controlsDrawer = document.querySelector("#demoControlsDrawer");
697
- const controlsBackdrop = document.querySelector("#demoControlsBackdrop");
698
- const controlsClose = document.querySelector("#demoControlsClose");
699
- const mixedPreset = document.querySelector("#mixedPreset");
700
- const matchedPreset = document.querySelector("#matchedPreset");
701
- const contrastPreset = document.querySelector("#contrastPreset");
702
- const mobileControlsQuery = window.matchMedia("(max-width: 74.999rem)");
703
- let previousDemoControlsFocus = null;
704
- const uiClassPrefixes = {
705
- "minimal-saas": "saas",
706
- bento: "bento",
707
- maximalist: "max",
708
- bauhaus: "bau",
709
- tactile: "tactile",
710
- neumorphism: "neo",
711
- retrofuturism: "retro",
712
- brutalism: "brutal",
713
- cyberpunk: "cyber",
714
- y2k: "y2k",
715
- "retro-glass": "rg"
716
- };
717
-
718
- function syncUiKitClasses(ui) {
719
- const prefix = uiClassPrefixes[ui];
720
-
721
- document.querySelectorAll("[data-ui-kit]").forEach((element) => {
722
- const previousClasses = element.dataset.uiKitApplied?.split(" ").filter(Boolean) || [];
723
-
724
- if (previousClasses.length > 0) {
725
- element.classList.remove(...previousClasses);
726
- }
727
-
728
- const nextClasses = element.dataset.uiKit
729
- .split(/\s+/)
730
- .filter(Boolean)
731
- .map((role) => `${prefix}-${role}`);
732
-
733
- if (nextClasses.length > 0) {
734
- element.classList.add(...nextClasses);
735
- }
736
-
737
- element.dataset.uiKitApplied = nextClasses.join(" ");
738
- });
739
- }
740
-
741
- function applyDemoState({ ui, layout, theme, mode }) {
742
- body.dataset.ui = ui;
743
- body.dataset.layout = layout;
744
- body.setAttribute("layout-style", layout);
745
- body.dataset.theme = theme;
746
- body.dataset.mode = mode;
747
- syncUiKitClasses(ui);
748
-
749
- uiSelect.value = ui;
750
- layoutSelect.value = layout;
751
- themeSelect.value = theme;
752
- modeSelect.value = mode;
753
- }
754
-
755
- // Mobile and tablet controls use a drawer so the sticky header stays compact.
756
- function setDemoControlsOpen(open, { returnFocus = true } = {}) {
757
- if (!mobileControlsQuery.matches) {
758
- controlsToggle.setAttribute("aria-expanded", "false");
759
- controlsDrawer.setAttribute("aria-hidden", "false");
760
- controlsBackdrop.dataset.open = "false";
761
- delete body.dataset.demoControlsOpen;
762
- previousDemoControlsFocus = null;
763
- return;
764
- }
765
-
766
- controlsToggle.setAttribute("aria-expanded", String(open));
767
- controlsDrawer.setAttribute("aria-hidden", String(!open));
768
- controlsBackdrop.dataset.open = String(open);
769
-
770
- if (open) {
771
- previousDemoControlsFocus = document.activeElement;
772
- body.dataset.demoControlsOpen = "true";
773
- controlsDrawer.querySelector("select, button, a, input")?.focus({ preventScroll: true });
774
- return;
775
- }
776
-
777
- delete body.dataset.demoControlsOpen;
778
-
779
- if (returnFocus) {
780
- const focusTarget = previousDemoControlsFocus instanceof HTMLElement
781
- ? previousDemoControlsFocus
782
- : controlsToggle;
783
- focusTarget.focus({ preventScroll: true });
784
- }
785
-
786
- previousDemoControlsFocus = null;
787
- }
788
-
789
- function syncDemoControlsMode() {
790
- setDemoControlsOpen(false, { returnFocus: false });
791
- }
792
-
793
- // Deep-linked state keeps visual regression checks and shared demos reproducible.
794
- const queryState = new URLSearchParams(window.location.search);
795
- const presetState = {
796
- minimalSaas: {
797
- ui: "minimal-saas",
798
- layout: "minimal-saas",
799
- theme: "arctic-indigo",
800
- mode: "light"
801
- },
802
- bento: {
803
- ui: "bento",
804
- layout: "bento",
805
- theme: "ocean-steel",
806
- mode: "light"
807
- },
808
- bauhaus: {
809
- ui: "bauhaus",
810
- layout: "bauhaus",
811
- theme: "graphite-cyan",
812
- mode: "light"
813
- },
814
- tactile: {
815
- ui: "tactile",
816
- layout: "tactile",
817
- theme: "forest-moss",
818
- mode: "light"
819
- },
820
- mixed: {
821
- ui: "cyberpunk",
822
- layout: "maximalist",
823
- theme: "arctic-indigo",
824
- mode: "dark"
825
- },
826
- y2k: {
827
- ui: "y2k",
828
- layout: "y2k",
829
- theme: "rose-quartz",
830
- mode: "light"
831
- },
832
- neumorphism: {
833
- ui: "neumorphism",
834
- layout: "neumorphism",
835
- theme: "desert-sage",
836
- mode: "light"
837
- },
838
- retroGlass: {
839
- ui: "retro-glass",
840
- layout: "retro-glass",
841
- theme: "graphite-cyan",
842
- mode: "dark"
843
- },
844
- retrofuturism: {
845
- ui: "retrofuturism",
846
- layout: "retrofuturism",
847
- theme: "midnight-gold",
848
- mode: "dark"
849
- },
850
- brutalism: {
851
- ui: "brutalism",
852
- layout: "brutalism",
853
- theme: "midnight-gold",
854
- mode: "contrast"
855
- },
856
- cyberpunk: {
857
- ui: "cyberpunk",
858
- layout: "cyberpunk",
859
- theme: "cyber-lime",
860
- mode: "dark"
861
- },
862
- maximalist: {
863
- ui: "maximalist",
864
- layout: "maximalist",
865
- theme: "sunset-ember",
866
- mode: "light"
867
- },
868
- fPattern: {
869
- ui: "minimal-saas",
870
- layout: "f-pattern",
871
- theme: "arctic-indigo",
872
- mode: "light"
873
- },
874
- zPattern: {
875
- ui: "bento",
876
- layout: "z-pattern",
877
- theme: "ocean-steel",
878
- mode: "light"
879
- },
880
- splitScreen: {
881
- ui: "maximalist",
882
- layout: "split-screen",
883
- theme: "sunset-ember",
884
- mode: "light"
885
- },
886
- mondrian: {
887
- ui: "bauhaus",
888
- layout: "mondrian",
889
- theme: "graphite-cyan",
890
- mode: "contrast"
891
- },
892
- synthwave: {
893
- ui: "cyberpunk",
894
- layout: "synthwave",
895
- theme: "cyber-lime",
896
- mode: "dark"
897
- }
898
- };
899
- applyDemoState(presetState[queryState.get("preset")] || {
900
- ui: queryState.get("ui") || body.dataset.ui,
901
- layout: queryState.get("layout") || body.dataset.layout,
902
- theme: queryState.get("theme") || body.dataset.theme,
903
- mode: queryState.get("mode") || body.dataset.mode
904
- });
905
- syncDemoControlsMode();
906
-
907
- uiSelect.addEventListener("change", () => {
908
- body.dataset.ui = uiSelect.value;
909
- syncUiKitClasses(uiSelect.value);
910
- });
911
-
912
- layoutSelect.addEventListener("change", () => {
913
- body.dataset.layout = layoutSelect.value;
914
- body.setAttribute("layout-style", layoutSelect.value);
915
- });
916
-
917
- themeSelect.addEventListener("change", () => {
918
- body.dataset.theme = themeSelect.value;
919
- });
920
-
921
- modeSelect.addEventListener("change", () => {
922
- body.dataset.mode = modeSelect.value;
923
- });
924
-
925
- controlsToggle.addEventListener("click", () => {
926
- setDemoControlsOpen(controlsToggle.getAttribute("aria-expanded") !== "true");
927
- });
928
-
929
- controlsClose.addEventListener("click", () => {
930
- setDemoControlsOpen(false);
931
- });
932
-
933
- controlsBackdrop.addEventListener("click", () => {
934
- setDemoControlsOpen(false);
935
- });
936
-
937
- document.addEventListener("keydown", (event) => {
938
- if (event.key === "Escape" && controlsToggle.getAttribute("aria-expanded") === "true") {
939
- setDemoControlsOpen(false);
940
- }
941
- });
942
-
943
- mobileControlsQuery.addEventListener("change", syncDemoControlsMode);
944
-
945
- mixedPreset.addEventListener("click", () => {
946
- applyDemoState({
947
- ui: "cyberpunk",
948
- layout: "maximalist",
949
- theme: "arctic-indigo",
950
- mode: "dark"
951
- });
952
- setDemoControlsOpen(false);
953
- });
954
-
955
- matchedPreset.addEventListener("click", () => {
956
- applyDemoState({
957
- ui: uiSelect.value,
958
- layout: uiSelect.value,
959
- theme: themeSelect.value,
960
- mode: modeSelect.value
961
- });
962
- setDemoControlsOpen(false);
963
- });
964
-
965
- contrastPreset.addEventListener("click", () => {
966
- applyDemoState({
967
- ui: "bauhaus",
968
- layout: "retro-glass",
969
- theme: "graphite-cyan",
970
- mode: "dark"
971
- });
972
- setDemoControlsOpen(false);
973
- });
974
- </script>
975
- </body>
976
- </html>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="x-ua-compatible" content="IE=edge">
6
+ <meta http-equiv="content-language" content="en-US">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
8
+ <meta name="title" content="layout-style-css 2.0 Interactive Layout Lab">
9
+ <meta name="description" content="Explore container-first wrappers, recipes, and layout personalities in layout-style-css 2.0 with optional UI Style Kit and Interactive Surface integrations.">
10
+ <meta name="keywords" content="CSS layout library, container queries, layout recipes, UI Style Kit CSS, Interactive Surface CSS, responsive CSS">
11
+ <meta name="author" content="Foscat">
12
+ <meta name="creator" content="Foscat">
13
+ <meta name="publisher" content="Foscat">
14
+ <meta name="abstract" content="A container-first layout laboratory for semantic wrappers, responsive recipes, and independent layout personalities.">
15
+ <meta name="subject" content="CSS layout system and responsive composition library">
16
+ <meta name="classification" content="Developer tools, CSS libraries, design systems">
17
+ <meta name="category" content="Software Development">
18
+ <meta name="coverage" content="Worldwide">
19
+ <meta name="distribution" content="Global">
20
+ <meta name="rating" content="General">
21
+ <meta name="revisit-after" content="7 days">
22
+ <meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
23
+ <meta name="googlebot" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
24
+ <meta name="bingbot" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
25
+ <meta name="referrer" content="strict-origin-when-cross-origin">
26
+ <meta name="format-detection" content="telephone=no">
27
+ <meta name="application-name" content="layout-style-css">
28
+ <meta name="mobile-web-app-capable" content="yes">
29
+ <meta name="apple-mobile-web-app-capable" content="yes">
30
+ <meta name="apple-mobile-web-app-title" content="layout-style-css">
31
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
32
+ <meta name="theme-color" content="#111827" media="(prefers-color-scheme: dark)">
33
+ <meta name="theme-color" content="#f8fafc" media="(prefers-color-scheme: light)">
34
+ <meta name="msapplication-TileColor" content="#111827">
35
+ <meta name="msapplication-config" content="./browserconfig.xml">
36
+ <meta name="color-scheme" content="light dark">
37
+ <meta property="og:type" content="website">
38
+ <meta property="og:locale" content="en_US">
39
+ <meta property="og:title" content="layout-style-css 2.0 Interactive Layout Lab">
40
+ <meta property="og:description" content="Test semantic wrappers, container-responsive recipes, and sixteen spatial personalities without coupling layout to paint.">
41
+ <meta property="og:image" content="https://foscat.github.io/layout-style-css/assets/social-card.png">
42
+ <meta property="og:image:secure_url" content="https://foscat.github.io/layout-style-css/assets/social-card.png">
43
+ <meta property="og:image:alt" content="layout-style-css interactive layout lab social card">
44
+ <meta property="og:image:type" content="image/png">
45
+ <meta property="og:image:width" content="1200">
46
+ <meta property="og:image:height" content="630">
47
+ <meta property="og:url" content="https://foscat.github.io/layout-style-css/">
48
+ <meta property="og:site_name" content="layout-style-css">
49
+ <meta property="og:updated_time" content="2026-07-20T00:00:00-05:00">
50
+ <meta name="twitter:card" content="summary_large_image">
51
+ <meta name="twitter:title" content="layout-style-css 2.0 Interactive Layout Lab">
52
+ <meta name="twitter:description" content="Container-first responsive layouts that pair cleanly with UI Style Kit CSS 2.0.1 and Interactive Surface CSS 1.4.0.">
53
+ <meta name="twitter:image" content="https://foscat.github.io/layout-style-css/assets/social-card.png">
54
+ <meta name="twitter:image:alt" content="layout-style-css interactive layout lab social card">
55
+ <meta itemprop="name" content="layout-style-css 2.0 Interactive Layout Lab">
56
+ <meta itemprop="description" content="A live workbench for semantic wrappers, responsive recipes, and spatial personalities.">
57
+ <meta itemprop="image" content="https://foscat.github.io/layout-style-css/assets/social-card.png">
58
+ <link rel="canonical" href="https://foscat.github.io/layout-style-css/">
59
+ <link rel="dns-prefetch" href="https://unpkg.com">
60
+ <link rel="preconnect" href="https://unpkg.com" crossorigin>
61
+ <link rel="image_src" href="./assets/social-card.png">
62
+ <link rel="icon" type="image/svg+xml" href="./assets/favicon.svg">
63
+ <link rel="shortcut icon" href="./assets/favicon.svg">
64
+ <link rel="apple-touch-icon" href="./assets/apple-touch-icon.svg">
65
+ <link rel="mask-icon" href="./assets/favicon.svg" color="#111827">
66
+ <link rel="manifest" href="./site.webmanifest">
67
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="./sitemap.xml">
68
+ <title>layout-style-css 2.0 Interactive Layout Lab</title>
69
+
70
+ <link id="uiKitStylesheet" rel="stylesheet" href="https://unpkg.com/ui-style-kit-css@2.0.1/dist/ui-style-kit.with-bridge.min.css" integrity="sha384-3i/xBAMjaAMQiR/vK1Tq7SzY0TFLUvdYKQKJa4t4zMXXOSfZKY+FOtFtk43F/2J+" crossorigin="anonymous">
71
+ <link id="interactiveSurfaceStylesheet" rel="stylesheet" href="https://unpkg.com/interactive-surface-css@1.4.0/state-core.css" integrity="sha384-D2077FYjcZbu1Mk9p80y2x1I9XdkK3L6ndN1wyvfRq8icCgIXWdpsY0on2NSakA6" crossorigin="anonymous">
72
+ <link id="layoutIntegrationStylesheet" rel="stylesheet" href="../dist/integrations/ui-style-kit.css">
73
+ <link id="layoutCoreStylesheet" rel="stylesheet" href="../dist/layout-style-css.css">
74
+ <link rel="stylesheet" href="./demo.css">
75
+
76
+ <script type="application/ld+json">
77
+ {
78
+ "@context": "https://schema.org",
79
+ "@type": "SoftwareSourceCode",
80
+ "name": "layout-style-css",
81
+ "version": "2.0.0",
82
+ "description": "A dependency-free, container-first CSS layout library for semantic wrappers, composition primitives, responsive recipes, and spatial personalities.",
83
+ "programmingLanguage": "CSS",
84
+ "applicationCategory": "DeveloperApplication",
85
+ "url": "https://foscat.github.io/layout-style-css/",
86
+ "image": "https://foscat.github.io/layout-style-css/assets/social-card.png",
87
+ "datePublished": "2026-07-20",
88
+ "dateModified": "2026-07-20",
89
+ "author": { "@type": "Organization", "name": "Foscat" },
90
+ "publisher": { "@type": "Organization", "name": "Foscat" }
91
+ }
92
+ </script>
93
+ <script type="module" src="./demo.js"></script>
94
+ </head>
95
+ <body class="ly-root" data-ui="minimal-saas" data-theme="arctic-indigo" data-mode="light" data-ly-layout="minimal-saas" data-density="comfortable" data-ecosystem="all-three">
96
+ <a class="demo-skip-link" href="#layoutLab">Skip to the layout lab</a>
97
+
98
+ <header class="demo-topbar">
99
+ <div class="demo-brand">
100
+ <span class="demo-kicker">layout-style-css 2.0</span>
101
+ <strong>Interactive Layout Lab</strong>
102
+ </div>
103
+ <div class="demo-topbar-actions">
104
+ <span id="ecosystemStatus" class="demo-status" role="status">All three libraries</span>
105
+ <button type="button" id="demoControlsToggle" aria-expanded="false" aria-controls="demoControlsDrawer" data-demo-button data-ui-kit="button button-secondary">
106
+ Layout controls
107
+ </button>
108
+ </div>
109
+ </header>
110
+
111
+ <div id="demoControlsBackdrop" class="demo-backdrop" hidden aria-hidden="true"></div>
112
+
113
+ <div class="demo-page">
114
+ <aside id="demoControlsDrawer" class="demo-controls" aria-labelledby="controlsTitle" aria-hidden="true" hidden inert>
115
+ <div class="demo-controls-heading">
116
+ <div>
117
+ <span class="demo-kicker">Workbench</span>
118
+ <h2 id="controlsTitle">Layout controls</h2>
119
+ </div>
120
+ <button type="button" id="demoControlsClose" data-demo-button data-ui-kit="button button-secondary">
121
+ Close
122
+ </button>
123
+ </div>
124
+
125
+ <form class="demo-controls-grid" autocomplete="off">
126
+ <label for="wrapperSelect">Wrapper
127
+ <select id="wrapperSelect" data-query-key="wrapper" data-ui-kit="select">
128
+ <option value="default">Default</option>
129
+ <option value="compact">Compact · 40rem</option>
130
+ <option value="prose">Prose · 68ch</option>
131
+ <option value="content">Content · 72rem</option>
132
+ <option value="wide">Wide · 112rem</option>
133
+ <option value="full">Full width</option>
134
+ <option value="breakout">Breakout lanes</option>
135
+ </select>
136
+ </label>
137
+
138
+ <label for="recipeSelect">Recipe
139
+ <select id="recipeSelect" data-query-key="recipe" data-ui-kit="select">
140
+ <option value="app-shell">App shell</option>
141
+ <option value="dashboard">Dashboard</option>
142
+ <option value="docs">Documentation</option>
143
+ <option value="list-detail">List detail</option>
144
+ <option value="split-hero">Split hero</option>
145
+ <option value="gallery">Gallery</option>
146
+ <option value="card-grid">Card grid</option>
147
+ </select>
148
+ </label>
149
+
150
+ <label for="personalitySelect">Personality
151
+ <select id="personalitySelect" data-query-key="personality" data-ui-kit="select">
152
+ <option value="minimal-saas">Minimal SaaS</option>
153
+ <option value="bauhaus">Bauhaus</option>
154
+ <option value="tactile">Tactile</option>
155
+ <option value="cyberpunk">Cyberpunk</option>
156
+ <option value="f-pattern">F-pattern</option>
157
+ <option value="brutalism">Brutalism</option>
158
+ <option value="neumorphism">Neumorphism</option>
159
+ <option value="y2k">Y2K</option>
160
+ <option value="retro-glass">Retro Glass</option>
161
+ <option value="z-pattern">Z-pattern</option>
162
+ <option value="retrofuturism">Retrofuturism</option>
163
+ <option value="mondrian">Mondrian</option>
164
+ <option value="synthwave">Synthwave</option>
165
+ <option value="bento">Bento</option>
166
+ <option value="maximalist">Maximalist</option>
167
+ <option value="split-screen">Split Screen</option>
168
+ </select>
169
+ </label>
170
+
171
+ <label for="containerSelect">Nested container
172
+ <select id="containerSelect" data-query-key="container" data-ui-kit="select">
173
+ <option value="auto">Auto</option>
174
+ <option value="40rem">40rem · compact</option>
175
+ <option value="47rem">47rem · below medium</option>
176
+ <option value="49rem">49rem · above medium</option>
177
+ <option value="63rem">63rem · below large</option>
178
+ <option value="65rem">65rem · above large</option>
179
+ <option value="80rem">80rem · expansive</option>
180
+ </select>
181
+ </label>
182
+
183
+ <label for="densitySelect">Density
184
+ <select id="densitySelect" data-query-key="density" data-ui-kit="select">
185
+ <option value="compact">Compact</option>
186
+ <option value="comfortable">Comfortable</option>
187
+ <option value="spacious">Spacious</option>
188
+ </select>
189
+ </label>
190
+
191
+ <label for="uiSelect">UI style
192
+ <select id="uiSelect" data-query-key="ui" data-ui-kit="select">
193
+ <option value="minimal-saas">Minimal SaaS</option>
194
+ <option value="bento">Bento</option>
195
+ <option value="maximalist">Maximalist</option>
196
+ <option value="bauhaus">Bauhaus</option>
197
+ <option value="tactile">Tactile</option>
198
+ <option value="neumorphism">Neumorphism</option>
199
+ <option value="retrofuturism">Retrofuturism</option>
200
+ <option value="brutalism">Brutalism</option>
201
+ <option value="cyberpunk">Cyberpunk</option>
202
+ <option value="y2k">Y2K</option>
203
+ <option value="retro-glass">Retro Glass</option>
204
+ </select>
205
+ </label>
206
+
207
+ <label for="themeSelect">Theme
208
+ <select id="themeSelect" data-query-key="theme" data-ui-kit="select">
209
+ <option value="arctic-indigo">Arctic Indigo</option>
210
+ <option value="ocean-steel">Ocean Steel</option>
211
+ <option value="graphite-cyan">Graphite Cyan</option>
212
+ <option value="forest-moss">Forest Moss</option>
213
+ <option value="rose-quartz">Rose Quartz</option>
214
+ <option value="desert-sage">Desert Sage</option>
215
+ <option value="midnight-gold">Midnight Gold</option>
216
+ <option value="cyber-lime">Cyber Lime</option>
217
+ <option value="sunset-ember">Sunset Ember</option>
218
+ </select>
219
+ </label>
220
+
221
+ <label for="modeSelect">Mode
222
+ <select id="modeSelect" data-query-key="mode" data-ui-kit="select">
223
+ <option value="light">Light</option>
224
+ <option value="dark">Dark</option>
225
+ <option value="contrast">High contrast</option>
226
+ </select>
227
+ </label>
228
+
229
+ <label for="ecosystemSelect">Ecosystem
230
+ <select id="ecosystemSelect" data-query-key="ecosystem" data-ui-kit="select">
231
+ <option value="layout-only">Layout only</option>
232
+ <option value="layout-ui">Layout + UI</option>
233
+ <option value="all-three">All three</option>
234
+ </select>
235
+ </label>
236
+ </form>
237
+ </aside>
238
+
239
+ <main id="layoutLab" class="demo-main">
240
+ <section class="demo-intro" aria-labelledby="demoTitle">
241
+ <div>
242
+ <span class="demo-kicker">Container-first · dependency-free</span>
243
+ <h1 id="demoTitle">Compose for the space a component actually has.</h1>
244
+ <p>
245
+ Change wrappers, recipes, personalities, and companion layers independently. The preview keeps semantic mobile order while named areas rearrange at its own 48rem and 64rem container thresholds.
246
+ </p>
247
+ </div>
248
+ <div class="demo-state-panel">
249
+ <span>Interactive Surface 1.4.0 state</span>
250
+ <button type="button" id="stateToggle" class="interactive-surface" aria-pressed="false" data-surface-level="2" data-surface-variant="primary" data-demo-button data-ui-kit="button button-primary">
251
+ Toggle active state
252
+ </button>
253
+ </div>
254
+ </section>
255
+
256
+ <section class="demo-lab" aria-labelledby="stageTitle">
257
+ <div class="demo-section-heading">
258
+ <div>
259
+ <span class="demo-kicker">Live preview</span>
260
+ <h2 id="stageTitle">Responsive recipe stage</h2>
261
+ </div>
262
+ <output id="containerReadout" for="containerSelect">Container: auto</output>
263
+ </div>
264
+
265
+ <div id="previewFrame" class="demo-preview-frame" data-container-width="auto">
266
+ <div id="previewRoot" class="ly-root demo-preview-root" data-ly-layout="minimal-saas">
267
+ <div id="previewWrapper" class="ly-wrapper">
268
+ <div id="recipePreview" class="ly-app-shell demo-recipe" data-ly-recipe="app-shell">
269
+ <header class="demo-region" data-ly-area="header" data-demo-sequence="header">
270
+ <strong>Header</strong>
271
+ <button type="button" data-demo-button data-demo-focus="header" data-ui-kit="button">Header action</button>
272
+ </header>
273
+ <nav class="demo-region" data-ly-area="nav" data-demo-sequence="nav" aria-label="Preview navigation">
274
+ <strong>Navigation</strong>
275
+ <button type="button" data-demo-button data-demo-focus="nav" data-ui-kit="button">Navigation action</button>
276
+ </nav>
277
+ <main class="demo-region" data-ly-area="main" data-demo-sequence="main">
278
+ <strong>Main</strong>
279
+ <button type="button" data-demo-button data-demo-focus="main" data-ui-kit="button">Main action</button>
280
+ </main>
281
+ <aside class="demo-region" data-ly-area="aside" data-demo-sequence="aside">
282
+ <strong>Aside</strong>
283
+ <button type="button" data-demo-button data-demo-focus="aside" data-ui-kit="button">Aside action</button>
284
+ </aside>
285
+ <footer class="demo-region" data-ly-area="footer" data-demo-sequence="footer">
286
+ <strong>Footer</strong>
287
+ <button type="button" data-demo-button data-demo-focus="footer" data-ui-kit="button">Footer action</button>
288
+ </footer>
289
+ </div>
290
+ </div>
291
+ </div>
292
+ </div>
293
+ </section>
294
+
295
+ <section class="demo-code-grid" aria-labelledby="codeTitle">
296
+ <div class="demo-section-heading demo-code-heading">
297
+ <div>
298
+ <span class="demo-kicker">Copy-ready</span>
299
+ <h2 id="codeTitle">Imports and semantic markup</h2>
300
+ </div>
301
+ <p id="copyStatus" class="demo-copy-status" role="status" aria-live="polite">Ready to copy.</p>
302
+ </div>
303
+
304
+ <article class="demo-code-card" data-ui-kit="card">
305
+ <div class="demo-code-card-heading">
306
+ <h3>Imports</h3>
307
+ <button type="button" id="copyImports" data-copy-target="importsSnippet" data-demo-button data-ui-kit="button button-secondary">Copy imports</button>
308
+ </div>
309
+ <pre><code id="importsSnippet"></code></pre>
310
+ </article>
311
+
312
+ <article class="demo-code-card" data-ui-kit="card">
313
+ <div class="demo-code-card-heading">
314
+ <h3>Markup</h3>
315
+ <button type="button" id="copyMarkup" data-copy-target="markupSnippet" data-demo-button data-ui-kit="button button-secondary">Copy markup</button>
316
+ </div>
317
+ <pre><code id="markupSnippet"></code></pre>
318
+ </article>
319
+ </section>
320
+ </main>
321
+ </div>
322
+ </body>
323
+ </html>