kmcom-nuxt-layers 2.7.4 → 3.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 (773) hide show
  1. package/docs/FALLOW-COMPLEXITY-DUPLICATION-AUDIT.md +0 -1
  2. package/docs/LAYOUT.md +34 -61
  3. package/docs/MIGRATION.md +1 -1
  4. package/docs/UPAGE-GRID-INTEGRATION.md +6 -6
  5. package/docs/layout-shift-causes.md +1 -1
  6. package/docs/superpowers/plans/2026-09-03-layout-layer-fluid-rebuild.md +1850 -0
  7. package/docs/superpowers/plans/2026-09-03-vue-element-system.md +1019 -0
  8. package/docs/superpowers/plans/2026-09-04-grid-layer.md +977 -0
  9. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-0-1-design.md +533 -0
  10. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-2-design.md +154 -0
  11. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-3-design.md +109 -0
  12. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-4-design.md +124 -0
  13. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-5-design.md +121 -0
  14. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-6-design.md +77 -0
  15. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-7-design.md +73 -0
  16. package/docs/superpowers/specs/2026-08-31-swiss-grid-layer-design.md +190 -0
  17. package/docs/superpowers/specs/2026-09-03-layout-layer-fluid-rebuild-design.md +312 -0
  18. package/docs/superpowers/specs/2026-09-03-vue-element-system-design.md +342 -0
  19. package/docs/superpowers/specs/2026-09-04-grid-layer-design.md +236 -0
  20. package/layers/content/app/app.config.ts +10 -2
  21. package/layers/content/app/components/Blog/ItemPage.vue +21 -0
  22. package/layers/content/app/components/Blog/Page.vue +25 -0
  23. package/layers/content/app/components/Gallery/ImagePage.vue +5 -1
  24. package/layers/content/app/components/Gallery/Page.vue +4 -1
  25. package/layers/content/app/components/Gallery/SlugPage.vue +5 -1
  26. package/layers/content/app/components/Portfolio/ItemPage.vue +4 -1
  27. package/layers/content/app/components/Portfolio/List.vue +14 -2
  28. package/layers/content/app/components/Portfolio/Page.vue +4 -1
  29. package/layers/content/app/composables/useBlogPosts.ts +6 -19
  30. package/layers/content/app/composables/useCollectionItems.ts +63 -0
  31. package/layers/content/app/composables/useGalleryItems.ts +1 -16
  32. package/layers/content/app/types/content.ts +9 -0
  33. package/layers/content/package.json +3 -0
  34. package/layers/core/app/app.config.ts +34 -17
  35. package/layers/core/app/app.vue +1 -0
  36. package/layers/core/app/assets/css/core.css +10 -0
  37. package/layers/core/app/assets/css/tokens/breakpoints.css +13 -0
  38. package/layers/core/app/assets/css/tokens/container.css +36 -0
  39. package/layers/core/app/assets/css/tokens/spacing-fluid.css +25 -0
  40. package/layers/core/app/components/AppContainer.vue +32 -0
  41. package/layers/core/app/components/Element.test.ts +90 -0
  42. package/layers/core/app/components/Element.vue +78 -0
  43. package/layers/core/app/components/ElementTw.test.ts +64 -0
  44. package/layers/core/app/components/ElementTw.vue +86 -0
  45. package/layers/core/app/components/LoadingScreen.vue +0 -15
  46. package/layers/core/app/composables/useElementGrid.test.ts +33 -0
  47. package/layers/core/app/composables/useElementGrid.ts +29 -0
  48. package/layers/core/app/composables/useElementInteraction.test.ts +27 -0
  49. package/layers/core/app/composables/useElementInteraction.ts +17 -0
  50. package/layers/core/app/composables/useElementLayout.test.ts +41 -0
  51. package/layers/core/app/composables/useElementLayout.ts +26 -0
  52. package/layers/core/app/composables/useElementSizing.test.ts +39 -0
  53. package/layers/core/app/composables/useElementSizing.ts +25 -0
  54. package/layers/core/app/composables/useElementStyle.ts +65 -0
  55. package/layers/core/app/composables/useElementSurface.test.ts +33 -0
  56. package/layers/core/app/composables/useElementSurface.ts +21 -0
  57. package/layers/core/app/composables/useErrorLog.ts +6 -4
  58. package/layers/core/app/composables/useLayoutAttrs.test.ts +47 -0
  59. package/layers/core/app/composables/useLayoutAttrs.ts +94 -0
  60. package/layers/core/app/composables/useLoading.ts +3 -1
  61. package/layers/core/app/error.vue +27 -57
  62. package/layers/core/app/pages/[...slug].vue +1 -29
  63. package/layers/core/app/plugins/icon-fetch-fix.ts +12 -0
  64. package/layers/core/app/plugins/loading.client.ts +0 -6
  65. package/layers/core/app/types/element.ts +25 -0
  66. package/layers/core/app/types/index.ts +0 -1
  67. package/layers/core/app/types/notFound.ts +24 -0
  68. package/layers/core/app/types/responsive.ts +15 -0
  69. package/layers/core/app/types/responsive.type-test.ts +22 -0
  70. package/layers/core/app/types/runtime-config.ts +1 -17
  71. package/layers/core/app/types/tokens.ts +29 -0
  72. package/layers/core/app/utils/index.ts +4 -2
  73. package/layers/core/app/utils/scrollGuardClamp.test.ts +36 -0
  74. package/layers/core/app/utils/scrollGuardClamp.ts +22 -0
  75. package/layers/core/app/utils/styleToTailwindClasses.test.ts +31 -0
  76. package/layers/core/app/utils/styleToTailwindClasses.ts +16 -0
  77. package/layers/core/nuxt.config.ts +15 -11
  78. package/layers/core/package.json +5 -1
  79. package/layers/{auth → data/auth}/nuxt.config.ts +1 -1
  80. package/layers/{auth → data/auth}/package.json +1 -1
  81. package/layers/{baseline → data/auth}/tsconfig.json +1 -1
  82. package/layers/{database → data/database}/nuxt.config.ts +1 -1
  83. package/layers/{database → data/database}/package.json +1 -1
  84. package/layers/{database → data/database}/tsconfig.json +1 -1
  85. package/layers/{forms/app/types/app-config.d.ts → data/forms/app/app.config.ts} +4 -0
  86. package/layers/{forms → data/forms}/package.json +1 -1
  87. package/layers/{forms → data/forms}/server/api/forms/status.get.ts +3 -1
  88. package/layers/{animations → data/forms}/tsconfig.json +1 -1
  89. package/layers/{mailer → data/mailer}/nuxt.config.ts +11 -1
  90. package/layers/{mailer → data/mailer}/package.json +1 -1
  91. package/layers/{auth → data/mailer}/tsconfig.json +1 -1
  92. package/layers/data/metadata/app/composables/useMetadataItem.ts +18 -0
  93. package/layers/data/metadata/app/composables/useMetadataSearch.ts +37 -0
  94. package/layers/{metadata → data/metadata}/nuxt.config.ts +1 -1
  95. package/layers/{metadata → data/metadata}/package.json +1 -1
  96. package/layers/{metadata → data/metadata}/providers/comicvine/nuxt.config.ts +1 -1
  97. package/layers/{metadata → data/metadata}/providers/comicvine/package.json +1 -1
  98. package/layers/data/metadata/providers/comicvine/tsconfig.json +7 -0
  99. package/layers/{metadata → data/metadata}/providers/google-books/nuxt.config.ts +1 -1
  100. package/layers/{metadata → data/metadata}/providers/google-books/package.json +1 -1
  101. package/layers/{metadata → data/metadata}/providers/google-books/server/utils/metadata-google-books/client.ts +10 -2
  102. package/layers/data/metadata/providers/google-books/tsconfig.json +7 -0
  103. package/layers/{metadata → data/metadata}/providers/openlibrary/package.json +1 -1
  104. package/layers/{metadata → data/metadata}/providers/openlibrary/server/utils/metadata-openlibrary/client.ts +23 -11
  105. package/layers/data/metadata/providers/openlibrary/tsconfig.json +7 -0
  106. package/layers/{metadata → data/metadata}/providers/themoviedb/nuxt.config.ts +1 -1
  107. package/layers/{metadata → data/metadata}/providers/themoviedb/package.json +1 -1
  108. package/layers/{metadata → data/metadata}/providers/themoviedb/tsconfig.json +1 -1
  109. package/layers/{metadata → data/metadata}/server/utils/metadata/search.ts +11 -4
  110. package/layers/data/metadata/tsconfig.json +7 -0
  111. package/layers/{feeds → delivery/feeds}/app/components/Feeds/Index.vue +6 -2
  112. package/layers/{feeds → delivery/feeds}/app/components/Feeds/RouteCard.vue +2 -0
  113. package/layers/{feeds → delivery/feeds}/app/plugins/feed-head.ts +6 -2
  114. package/layers/{feeds → delivery/feeds}/app/utils/feed-catalog.ts +8 -6
  115. package/layers/{feeds → delivery/feeds}/nuxt.config.ts +1 -1
  116. package/layers/{feeds → delivery/feeds}/package.json +1 -1
  117. package/layers/{feeds → delivery/feeds}/server/utils/feed-config.ts +1 -1
  118. package/layers/{feeds → delivery/feeds}/server/utils/feed-service.ts +2 -1
  119. package/layers/delivery/feeds/tsconfig.json +7 -0
  120. package/layers/{scripts → delivery/scripts}/app/composables/useAnalytics.ts +3 -1
  121. package/layers/{scripts → delivery/scripts}/app/composables/useGtm.ts +8 -2
  122. package/layers/{scripts → delivery/scripts}/app/composables/useScriptsConsent.ts +4 -1
  123. package/layers/{scripts → delivery/scripts}/app/utils/scriptClients.ts +19 -0
  124. package/layers/{scripts → delivery/scripts}/nuxt.config.ts +7 -2
  125. package/layers/{scripts → delivery/scripts}/package.json +3 -2
  126. package/layers/delivery/scripts/tsconfig.json +7 -0
  127. package/layers/delivery/seo/app/composables/useSeoConfig.ts +8 -0
  128. package/layers/{seo → delivery/seo}/app/utils/seoConfig.test.ts +2 -2
  129. package/layers/{seo → delivery/seo}/app/utils/seoConfig.ts +2 -2
  130. package/layers/{seo → delivery/seo}/nuxt.config.ts +1 -1
  131. package/layers/{seo → delivery/seo}/package.json +1 -1
  132. package/layers/delivery/seo/tsconfig.json +7 -0
  133. package/layers/design-system/theming/app/app.config.ts +35 -0
  134. package/layers/design-system/theming/app/assets/css/tokens.css +26 -0
  135. package/layers/{theme → design-system/theming}/app/components/ThemePicker/AccentButton.vue +3 -22
  136. package/layers/{theme → design-system/theming}/app/components/ThemePicker/Colors.vue +3 -4
  137. package/layers/{theme → design-system/theming}/app/composables/useAccentColor.ts +5 -2
  138. package/layers/{theme → design-system/theming}/app/composables/useThemeContrast.ts +1 -1
  139. package/layers/{theme → design-system/theming}/app/composables/useThemeMotion.ts +1 -1
  140. package/layers/{theme → design-system/theming}/app/composables/useThemeTransparency.ts +1 -1
  141. package/layers/{theme → design-system/theming}/app/plugins/theme.client.ts +2 -1
  142. package/layers/design-system/theming/app/types/designSystem.ts +102 -0
  143. package/layers/design-system/theming/app/types/semanticColor.ts +20 -0
  144. package/layers/design-system/theming/app/types/theme.ts +12 -0
  145. package/layers/design-system/theming/app/utils/accentPalette.ts +28 -0
  146. package/layers/design-system/theming/app/utils/themeAdapter.ts +20 -0
  147. package/layers/design-system/theming/nuxt.config.ts +49 -0
  148. package/layers/{ui → design-system/theming}/package.json +5 -6
  149. package/layers/{theme → design-system/theming}/server/plugins/theme-fouc.ts +2 -0
  150. package/layers/{theme → design-system/theming}/server/utils/accent-css.ts +2 -2
  151. package/layers/{theme → design-system/theming}/tsconfig.json +1 -1
  152. package/layers/{typography → design-system/typography}/app/assets/css/typography.css +13 -10
  153. package/layers/design-system/typography/app/components/Typography/CodeBlock.vue +65 -0
  154. package/layers/{typography → design-system/typography}/app/components/Typography/Headline.vue +16 -31
  155. package/layers/{typography/app/components/Typography/HeadlineScreen.vue → design-system/typography/app/components/Typography/QuoteBlock.vue} +27 -29
  156. package/layers/design-system/typography/app/components/Typography/RepeatText.vue +147 -0
  157. package/layers/{typography → design-system/typography}/app/components/Typography/index.vue +6 -4
  158. package/layers/design-system/typography/app/composables/repeatFill.ts +51 -0
  159. package/layers/{typography → design-system/typography}/app/composables/typography.ts +4 -0
  160. package/layers/{typography → design-system/typography}/app/types/typography.ts +8 -0
  161. package/layers/{typography → design-system/typography}/nuxt.config.ts +1 -3
  162. package/layers/design-system/typography/tsconfig.json +7 -0
  163. package/layers/{visual → design-system/visual}/app/app.config.ts +2 -2
  164. package/layers/{visual → design-system/visual}/app/components/Accent/Blob.vue +1 -1
  165. package/layers/{visual → design-system/visual}/app/components/Accent/Scene.vue +2 -3
  166. package/layers/{visual → design-system/visual}/app/components/Gradient/Background.vue +2 -2
  167. package/layers/{visual → design-system/visual}/app/components/Gradient/Text.vue +2 -2
  168. package/layers/{visual → design-system/visual}/app/composables/gradient.ts +1 -1
  169. package/layers/design-system/visual/app/types/breakpoints.ts +67 -0
  170. package/layers/{visual → design-system/visual}/app/types/media.ts +0 -11
  171. package/layers/{visual → design-system/visual}/nuxt.config.ts +1 -1
  172. package/layers/design-system/visual/tsconfig.json +7 -0
  173. package/layers/{animations → motion/animations}/app/components/Motion/Marquee.vue +0 -7
  174. package/layers/{animations → motion/animations}/app/components/Motion/Staggered.vue +4 -1
  175. package/layers/{animations → motion/animations}/nuxt.config.ts +1 -2
  176. package/layers/motion/animations/tsconfig.json +7 -0
  177. package/layers/motion/{package.json → motion/package.json} +1 -1
  178. package/layers/motion/{tsconfig.json → motion/tsconfig.json} +1 -1
  179. package/layers/motion/page-transitions/app/assets/css/page-transitions.css +30 -0
  180. package/layers/{page-transitions → motion/page-transitions}/app/composables/usePageTransition.ts +14 -2
  181. package/layers/{page-transitions → motion/page-transitions}/app/plugins/page-transitions.client.ts +5 -2
  182. package/layers/{page-transitions → motion/page-transitions}/nuxt.config.ts +3 -1
  183. package/layers/motion/page-transitions/tsconfig.json +7 -0
  184. package/layers/motion/scroll/app/app.config.ts +13 -0
  185. package/layers/{scroll → motion/scroll}/app/composables/useSmoothScroll.ts +2 -1
  186. package/layers/{scroll → motion/scroll}/app/plugins/locomotive-scroll.client.ts +2 -1
  187. package/layers/{scroll → motion/scroll}/nuxt.config.ts +1 -1
  188. package/layers/motion/scroll/tsconfig.json +7 -0
  189. package/layers/{transitions → motion/transitions}/nuxt.config.ts +1 -1
  190. package/layers/motion/transitions/tsconfig.json +7 -0
  191. package/layers/{canvas → render/canvas}/app/composables/useRendererCapabilities.ts +0 -8
  192. package/layers/{canvas → render/canvas}/app/composables/useShaderTime.ts +0 -12
  193. package/layers/{canvas → render/canvas}/nuxt.config.ts +1 -4
  194. package/layers/{canvas → render/canvas}/package.json +3 -2
  195. package/layers/{canvas → render/canvas}/tsconfig.json +1 -1
  196. package/layers/render/shader/app/app.config.ts +21 -0
  197. package/layers/{shader → render/shader}/app/shaders/layers/paperShading.ts +1 -1
  198. package/layers/{shader → render/shader}/package.json +1 -1
  199. package/layers/render/shader/tsconfig.json +7 -0
  200. package/layers/structure/grid/app/app.config.ts +92 -0
  201. package/layers/structure/grid/app/assets/css/grid.css +38 -0
  202. package/layers/structure/grid/app/composables/useGridTracks.test.ts +94 -0
  203. package/layers/structure/grid/app/composables/useGridTracks.ts +74 -0
  204. package/layers/structure/grid/app/types/tracks.test.ts +32 -0
  205. package/layers/structure/grid/app/types/tracks.ts +18 -0
  206. package/layers/structure/grid/app/utils/placement.test.ts +19 -0
  207. package/layers/structure/grid/app/utils/placement.ts +15 -0
  208. package/layers/structure/grid/nuxt.config.ts +22 -0
  209. package/layers/{theme → structure/grid}/package.json +3 -3
  210. package/layers/structure/layout/app/app.config.ts +116 -0
  211. package/layers/{layout → structure/layout}/app/assets/css/layout/grids.css +11 -6
  212. package/layers/structure/layout/app/assets/css/layout.css +1 -0
  213. package/layers/structure/layout/app/components/HStack.vue +41 -0
  214. package/layers/{layout → structure/layout}/app/components/Layout/Grid/Debug.vue +5 -3
  215. package/layers/{layout → structure/layout}/app/components/Layout/Grid/Item.vue +4 -10
  216. package/layers/{layout → structure/layout}/app/components/Layout/Main.vue +3 -3
  217. package/layers/{layout → structure/layout}/app/components/Layout/Page/Header.vue +1 -1
  218. package/layers/{layout → structure/layout}/app/components/Layout/Page/index.vue +3 -3
  219. package/layers/{layout → structure/layout}/app/components/Layout/Section/index.vue +1 -1
  220. package/layers/structure/layout/app/components/Spacer.vue +21 -0
  221. package/layers/structure/layout/app/components/VStack.vue +37 -0
  222. package/layers/structure/layout/app/components/ZStack.vue +28 -0
  223. package/layers/structure/layout/app/layouts/default.vue +5 -0
  224. package/layers/{layout → structure/layout}/app/types/layouts.ts +2 -3
  225. package/layers/{layout → structure/layout}/app/utils/gridPlacementStyle.test.ts +7 -42
  226. package/layers/{layout → structure/layout}/app/utils/gridPlacementStyle.ts +4 -18
  227. package/layers/{layout → structure/layout}/nuxt.config.ts +1 -1
  228. package/layers/{layout → structure/layout}/package.json +1 -1
  229. package/layers/structure/layout/tsconfig.json +7 -0
  230. package/layers/{navigation → structure/navigation}/app/app.config.ts +4 -6
  231. package/layers/structure/navigation/app/components/Mast/Header.vue +11 -0
  232. package/layers/{navigation → structure/navigation}/app/components/Mast/Nav.vue +1 -1
  233. package/layers/structure/navigation/app/composables/mastNav.ts +15 -0
  234. package/layers/{navigation → structure/navigation}/app/utils/createModal.ts +22 -3
  235. package/layers/{navigation → structure/navigation}/nuxt.config.ts +1 -1
  236. package/layers/structure/navigation/tsconfig.json +7 -0
  237. package/layers/{routing → structure/routing}/app/app.config.ts +11 -2
  238. package/layers/{routing → structure/routing}/nuxt.config.ts +1 -1
  239. package/layers/{routing → structure/routing}/package.json +1 -1
  240. package/layers/structure/routing/tsconfig.json +7 -0
  241. package/package.json +56 -56
  242. package/docs/fallow-refactor/layers-ui.md +0 -27
  243. package/layers/animations/app/types/animations.ts +0 -8
  244. package/layers/animations/app/types/index.ts +0 -1
  245. package/layers/baseline/nuxt.config.ts +0 -24
  246. package/layers/baseline/package.json +0 -14
  247. package/layers/content/app/components/Blog/Card.vue +0 -43
  248. package/layers/content/app/components/Gallery/AmbientImage.vue +0 -44
  249. package/layers/content/app/components/Gallery/Card.vue +0 -43
  250. package/layers/content/app/components/NuxtContent/Renderer.vue +0 -14
  251. package/layers/content/app/components/Portfolio/Card.vue +0 -43
  252. package/layers/content/app/composables/createPortfolioComposables.ts +0 -50
  253. package/layers/content/app/composables/useBlogPost.ts +0 -3
  254. package/layers/content/app/composables/useGalleryItem.ts +0 -3
  255. package/layers/content/app/composables/usePortfolioItem.ts +0 -3
  256. package/layers/content/app/composables/usePortfolioItems.ts +0 -26
  257. package/layers/content/app/types/app-config.d.ts +0 -14
  258. package/layers/core/app/assets/css-backup.zip +0 -0
  259. package/layers/core/app/composables/useEnv.ts +0 -23
  260. package/layers/core/app/composables/useScrollGuard.ts +0 -243
  261. package/layers/core/app/plugins/feature-detection.client.ts +0 -34
  262. package/layers/core/app/plugins/init.ts +0 -192
  263. package/layers/core/app/plugins/scroll-guard.client.ts +0 -56
  264. package/layers/core/app/types/app-config.d.ts +0 -63
  265. package/layers/core/app/types/scroll-guard.ts +0 -25
  266. package/layers/core/app/utils/helpers.test.ts +0 -55
  267. package/layers/core/app/utils/helpers.ts +0 -248
  268. package/layers/core/app/utils/regex.test.ts +0 -31
  269. package/layers/feeds/tsconfig.json +0 -7
  270. package/layers/forms/app/app.config.ts +0 -3
  271. package/layers/forms/tsconfig.json +0 -7
  272. package/layers/layout/app/app.config.ts +0 -180
  273. package/layers/layout/app/assets/css/layout/modes/fluid.css +0 -109
  274. package/layers/layout/app/assets/css/layout.css +0 -2
  275. package/layers/layout/app/components/Layout/Container.vue +0 -46
  276. package/layers/layout/app/components/Layout/Page/Container.vue +0 -103
  277. package/layers/layout/app/components/Layout/Section/Grid.vue +0 -46
  278. package/layers/layout/app/components/Layout/Section/Sidebar.vue +0 -84
  279. package/layers/layout/app/components/Layout/Section/Stack.vue +0 -63
  280. package/layers/layout/app/components/Layout/Section/Title.vue +0 -33
  281. package/layers/layout/app/composables/GridPlacement.ts +0 -31
  282. package/layers/layout/app/types/app-config.d.ts +0 -14
  283. package/layers/layout/tsconfig.json +0 -7
  284. package/layers/mailer/server/types.d.ts +0 -11
  285. package/layers/mailer/tsconfig.json +0 -7
  286. package/layers/metadata/app/composables/useMetadataItem.ts +0 -15
  287. package/layers/metadata/app/composables/useMetadataSearch.ts +0 -29
  288. package/layers/metadata/providers/comicvine/tsconfig.json +0 -7
  289. package/layers/metadata/providers/google-books/tsconfig.json +0 -7
  290. package/layers/metadata/providers/openlibrary/tsconfig.json +0 -7
  291. package/layers/metadata/tsconfig.json +0 -7
  292. package/layers/motion/app/components/Motion/index.vue +0 -16
  293. package/layers/navigation/app/components/Mast/Header.vue +0 -18
  294. package/layers/navigation/app/components/Mast/Main.vue +0 -7
  295. package/layers/navigation/app/composables/mastNav.ts +0 -26
  296. package/layers/navigation/app/utils/regex.ts +0 -6
  297. package/layers/navigation/tsconfig.json +0 -7
  298. package/layers/page-transitions/tsconfig.json +0 -7
  299. package/layers/routing/app/types/app-config.d.ts +0 -7
  300. package/layers/routing/tsconfig.json +0 -7
  301. package/layers/scripts/app/types/index.ts +0 -1
  302. package/layers/scripts/app/types/scripts.ts +0 -14
  303. package/layers/scripts/tsconfig.json +0 -7
  304. package/layers/scroll/app/app.config.ts +0 -31
  305. package/layers/scroll/tsconfig.json +0 -7
  306. package/layers/seo/app/composables/useSeoConfig.ts +0 -7
  307. package/layers/seo/tsconfig.json +0 -7
  308. package/layers/shader/app/app.config.ts +0 -9
  309. package/layers/shader/app/types/app-config.d.ts +0 -7
  310. package/layers/shader/tsconfig.json +0 -7
  311. package/layers/starter/app/app.config.ts +0 -10
  312. package/layers/starter/app/components/StarterDesignSystem.vue +0 -1913
  313. package/layers/starter/app/components/StarterHome.vue +0 -441
  314. package/layers/starter/nuxt.config.ts +0 -15
  315. package/layers/starter/package.json +0 -10
  316. package/layers/theme/app/app.config.ts +0 -3
  317. package/layers/theme/app/types/app-config.d.ts +0 -10
  318. package/layers/theme/app/types/theme.ts +0 -23
  319. package/layers/theme/nuxt.config.ts +0 -74
  320. package/layers/transitions/tsconfig.json +0 -7
  321. package/layers/typography/app/components/Typography/CodeBlock.vue +0 -41
  322. package/layers/typography/app/components/Typography/QuoteBlock.vue +0 -23
  323. package/layers/typography/tsconfig.json +0 -7
  324. package/layers/ui/app/assets/css/ui.css +0 -4
  325. package/layers/ui/app/layouts/default.vue +0 -8
  326. package/layers/ui/nuxt.config.ts +0 -22
  327. package/layers/ui/tsconfig.json +0 -7
  328. package/layers/visual/app/types/breakpoints.ts +0 -179
  329. package/layers/visual/tsconfig.json +0 -7
  330. /package/layers/{auth → data/auth}/app/middleware/auth.ts +0 -0
  331. /package/layers/{auth → data/auth}/server/routes/auth/github.get.ts +0 -0
  332. /package/layers/{database → data/database}/server/utils/drizzle.ts +0 -0
  333. /package/layers/{database → data/database}/server/utils/sql.ts +0 -0
  334. /package/layers/{forms → data/forms}/app/components/Form/Contact.vue +0 -0
  335. /package/layers/{forms → data/forms}/app/components/Form/Field.vue +0 -0
  336. /package/layers/{forms → data/forms}/app/composables/useFormSchema.ts +0 -0
  337. /package/layers/{forms → data/forms}/app/composables/useFormsFetch.ts +0 -0
  338. /package/layers/{forms → data/forms}/app/config/fields.ts +0 -0
  339. /package/layers/{forms → data/forms}/app/types/fields.ts +0 -0
  340. /package/layers/{forms → data/forms}/app/types/index.ts +0 -0
  341. /package/layers/{forms → data/forms}/app/utils/contact-schema.test.ts +0 -0
  342. /package/layers/{forms → data/forms}/app/utils/contact-schema.ts +0 -0
  343. /package/layers/{forms → data/forms}/app/utils/fieldProps.test.ts +0 -0
  344. /package/layers/{forms → data/forms}/app/utils/fieldProps.ts +0 -0
  345. /package/layers/{forms → data/forms}/nuxt.config.ts +0 -0
  346. /package/layers/{forms → data/forms}/server/api/contact.post.ts +0 -0
  347. /package/layers/{mailer → data/mailer}/app/types/index.ts +0 -0
  348. /package/layers/{mailer → data/mailer}/app/types/mailer.ts +0 -0
  349. /package/layers/{mailer → data/mailer}/server/utils/config.ts +0 -0
  350. /package/layers/{mailer → data/mailer}/server/utils/email.ts +0 -0
  351. /package/layers/{mailer → data/mailer}/server/utils/hooks.ts +0 -0
  352. /package/layers/{metadata → data/metadata}/providers/comicvine/server/plugins/comicvine-register.ts +0 -0
  353. /package/layers/{metadata → data/metadata}/providers/comicvine/server/utils/metadata-comicvine/client.ts +0 -0
  354. /package/layers/{metadata → data/metadata}/providers/comicvine/server/utils/metadata-comicvine/normalise.test.ts +0 -0
  355. /package/layers/{metadata → data/metadata}/providers/comicvine/server/utils/metadata-comicvine/normalise.ts +0 -0
  356. /package/layers/{metadata → data/metadata}/providers/comicvine/server/utils/metadata-comicvine/provider.ts +0 -0
  357. /package/layers/{metadata → data/metadata}/providers/comicvine/server/utils/metadata-comicvine/types.ts +0 -0
  358. /package/layers/{metadata → data/metadata}/providers/google-books/server/plugins/google-books-register.ts +0 -0
  359. /package/layers/{metadata → data/metadata}/providers/google-books/server/utils/metadata-google-books/client.test.ts +0 -0
  360. /package/layers/{metadata → data/metadata}/providers/google-books/server/utils/metadata-google-books/normalise.test.ts +0 -0
  361. /package/layers/{metadata → data/metadata}/providers/google-books/server/utils/metadata-google-books/normalise.ts +0 -0
  362. /package/layers/{metadata → data/metadata}/providers/google-books/server/utils/metadata-google-books/provider.ts +0 -0
  363. /package/layers/{metadata → data/metadata}/providers/google-books/server/utils/metadata-google-books/types.ts +0 -0
  364. /package/layers/{metadata → data/metadata}/providers/openlibrary/nuxt.config.ts +0 -0
  365. /package/layers/{metadata → data/metadata}/providers/openlibrary/server/plugins/openlibrary-register.ts +0 -0
  366. /package/layers/{metadata → data/metadata}/providers/openlibrary/server/utils/metadata-openlibrary/client.test.ts +0 -0
  367. /package/layers/{metadata → data/metadata}/providers/openlibrary/server/utils/metadata-openlibrary/normalise.test.ts +0 -0
  368. /package/layers/{metadata → data/metadata}/providers/openlibrary/server/utils/metadata-openlibrary/normalise.ts +0 -0
  369. /package/layers/{metadata → data/metadata}/providers/openlibrary/server/utils/metadata-openlibrary/provider.ts +0 -0
  370. /package/layers/{metadata → data/metadata}/providers/openlibrary/server/utils/metadata-openlibrary/types.ts +0 -0
  371. /package/layers/{metadata → data/metadata}/providers/themoviedb/server/plugins/tmdb-register.ts +0 -0
  372. /package/layers/{metadata → data/metadata}/providers/themoviedb/server/utils/metadata-tmdb/client.test.ts +0 -0
  373. /package/layers/{metadata → data/metadata}/providers/themoviedb/server/utils/metadata-tmdb/client.ts +0 -0
  374. /package/layers/{metadata → data/metadata}/providers/themoviedb/server/utils/metadata-tmdb/normalise.test.ts +0 -0
  375. /package/layers/{metadata → data/metadata}/providers/themoviedb/server/utils/metadata-tmdb/normalise.ts +0 -0
  376. /package/layers/{metadata → data/metadata}/providers/themoviedb/server/utils/metadata-tmdb/provider.ts +0 -0
  377. /package/layers/{metadata → data/metadata}/providers/themoviedb/server/utils/metadata-tmdb/types.ts +0 -0
  378. /package/layers/{metadata → data/metadata}/server/api/metadata/lookup.get.ts +0 -0
  379. /package/layers/{metadata → data/metadata}/server/api/metadata/providers.get.ts +0 -0
  380. /package/layers/{metadata → data/metadata}/server/api/metadata/search.get.ts +0 -0
  381. /package/layers/{metadata → data/metadata}/server/api/metadata/status.get.ts +0 -0
  382. /package/layers/{metadata → data/metadata}/server/api/metadata/sync.post.ts +0 -0
  383. /package/layers/{metadata → data/metadata}/server/utils/metadata/cache.test.ts +0 -0
  384. /package/layers/{metadata → data/metadata}/server/utils/metadata/cache.ts +0 -0
  385. /package/layers/{metadata → data/metadata}/server/utils/metadata/errors.ts +0 -0
  386. /package/layers/{metadata → data/metadata}/server/utils/metadata/provider-registry.test.ts +0 -0
  387. /package/layers/{metadata → data/metadata}/server/utils/metadata/provider-registry.ts +0 -0
  388. /package/layers/{metadata → data/metadata}/server/utils/metadata/search.test.ts +0 -0
  389. /package/layers/{feeds → delivery/feeds}/app/app.config.ts +0 -0
  390. /package/layers/{feeds → delivery/feeds}/app/assets/css/feeds.css +0 -0
  391. /package/layers/{feeds → delivery/feeds}/public/feed/style.css +0 -0
  392. /package/layers/{feeds → delivery/feeds}/server/routes/feed/[collection]/atom/all.get.ts +0 -0
  393. /package/layers/{feeds → delivery/feeds}/server/routes/feed/[collection]/atom.get.ts +0 -0
  394. /package/layers/{feeds → delivery/feeds}/server/routes/feed/[collection]/json/all.get.ts +0 -0
  395. /package/layers/{feeds → delivery/feeds}/server/routes/feed/[collection]/json.get.ts +0 -0
  396. /package/layers/{feeds → delivery/feeds}/server/routes/feed/[collection]/rss/all.get.ts +0 -0
  397. /package/layers/{feeds → delivery/feeds}/server/routes/feed/[collection]/rss.get.ts +0 -0
  398. /package/layers/{feeds → delivery/feeds}/server/routes/feed/atom/all.get.ts +0 -0
  399. /package/layers/{feeds → delivery/feeds}/server/routes/feed/atom.get.ts +0 -0
  400. /package/layers/{feeds → delivery/feeds}/server/routes/feed/demo.get.ts +0 -0
  401. /package/layers/{feeds → delivery/feeds}/server/routes/feed/index.get.ts +0 -0
  402. /package/layers/{feeds → delivery/feeds}/server/routes/feed/json/all.get.ts +0 -0
  403. /package/layers/{feeds → delivery/feeds}/server/routes/feed/json.get.ts +0 -0
  404. /package/layers/{feeds → delivery/feeds}/server/routes/feed/rss/all.get.ts +0 -0
  405. /package/layers/{feeds → delivery/feeds}/server/routes/feed/rss.get.ts +0 -0
  406. /package/layers/{feeds → delivery/feeds}/server/routes/feed/style.xsl.get.ts +0 -0
  407. /package/layers/{feeds → delivery/feeds}/server/utils/cache.ts +0 -0
  408. /package/layers/{feeds → delivery/feeds}/server/utils/content-adapter.test.ts +0 -0
  409. /package/layers/{feeds → delivery/feeds}/server/utils/content-adapter.ts +0 -0
  410. /package/layers/{feeds → delivery/feeds}/server/utils/feed-author.test.ts +0 -0
  411. /package/layers/{feeds → delivery/feeds}/server/utils/feed-author.ts +0 -0
  412. /package/layers/{feeds → delivery/feeds}/server/utils/feed-config.test.ts +0 -0
  413. /package/layers/{feeds → delivery/feeds}/server/utils/feed-xml.ts +0 -0
  414. /package/layers/{feeds → delivery/feeds}/server/utils/formats/atom.ts +0 -0
  415. /package/layers/{feeds → delivery/feeds}/server/utils/formats/json.ts +0 -0
  416. /package/layers/{feeds → delivery/feeds}/server/utils/formats/rss.ts +0 -0
  417. /package/layers/{feeds → delivery/feeds}/server/utils/formats.test.ts +0 -0
  418. /package/layers/{feeds → delivery/feeds}/server/utils/types.ts +0 -0
  419. /package/layers/{scripts → delivery/scripts}/app/app.config.ts +0 -0
  420. /package/layers/{baseline → delivery/scripts}/app/components/BaselineStatus.vue +0 -0
  421. /package/layers/{scripts → delivery/scripts}/app/composables/useScriptLoader.ts +0 -0
  422. /package/layers/{scripts → delivery/scripts}/app/composables/useYoutubeEmbed.ts +0 -0
  423. /package/layers/{baseline → delivery/scripts}/app/plugins/baseline-status.client.ts +0 -0
  424. /package/layers/{seo → delivery/seo}/app/app.config.ts +0 -0
  425. /package/layers/{theme → design-system/theming}/app/assets/css/theme.css +0 -0
  426. /package/layers/{theme → design-system/theming}/app/components/ThemePicker/Menu.vue +0 -0
  427. /package/layers/{theme → design-system/theming}/app/components/ThemePicker/MenuButton.vue +0 -0
  428. /package/layers/{theme → design-system/theming}/app/composables/useTheme.ts +0 -0
  429. /package/layers/{theme → design-system/theming}/app/composables/useThemePreferenceModels.ts +0 -0
  430. /package/layers/{theme → design-system/theming}/app/composables/useThemePreferences.ts +0 -0
  431. /package/layers/{theme → design-system/theming}/app/types/index.ts +0 -0
  432. /package/layers/{theme → design-system/theming}/server/utils/accent-css.test.ts +0 -0
  433. /package/layers/{theme → design-system/theming}/server/utils/fouc-config.test.ts +0 -0
  434. /package/layers/{theme → design-system/theming}/server/utils/fouc-config.ts +0 -0
  435. /package/layers/{typography → design-system/typography}/app/components/Typography/TextStroke.vue +0 -0
  436. /package/layers/{typography → design-system/typography}/app/composables/color.ts +0 -0
  437. /package/layers/{typography → design-system/typography}/app/types/colors.ts +0 -0
  438. /package/layers/{typography → design-system/typography}/app/types/index.ts +0 -0
  439. /package/layers/{typography → design-system/typography}/package.json +0 -0
  440. /package/layers/{visual → design-system/visual}/app/assets/css/visual.css +0 -0
  441. /package/layers/{visual → design-system/visual}/app/components/Base/Modal.vue +0 -0
  442. /package/layers/{visual → design-system/visual}/app/components/Media/Picture.vue +0 -0
  443. /package/layers/{visual → design-system/visual}/app/components/Progress/Bar.vue +0 -0
  444. /package/layers/{visual → design-system/visual}/app/components/Progress/Circular.vue +0 -0
  445. /package/layers/{visual → design-system/visual}/app/components/Tint/Overlay.vue +0 -0
  446. /package/layers/{visual → design-system/visual}/app/composables/accent.ts +0 -0
  447. /package/layers/{visual → design-system/visual}/app/composables/picture.ts +0 -0
  448. /package/layers/{visual → design-system/visual}/app/composables/tint.ts +0 -0
  449. /package/layers/{visual → design-system/visual}/app/types/accent.ts +0 -0
  450. /package/layers/{visual → design-system/visual}/app/types/gradient.ts +0 -0
  451. /package/layers/{visual → design-system/visual}/app/types/index.ts +0 -0
  452. /package/layers/{visual → design-system/visual}/app/types/tint.ts +0 -0
  453. /package/layers/{visual → design-system/visual}/app/utils/colorTokens.test.ts +0 -0
  454. /package/layers/{visual → design-system/visual}/app/utils/colorTokens.ts +0 -0
  455. /package/layers/{visual → design-system/visual}/app/utils/gradientStyle.test.ts +0 -0
  456. /package/layers/{visual → design-system/visual}/app/utils/gradientStyle.ts +0 -0
  457. /package/layers/{visual → design-system/visual}/app/utils/responsiveSizes.test.ts +0 -0
  458. /package/layers/{visual → design-system/visual}/app/utils/responsiveSizes.ts +0 -0
  459. /package/layers/{visual → design-system/visual}/package.json +0 -0
  460. /package/layers/{animations → motion/animations}/app/components/Motion/CountUp.vue +0 -0
  461. /package/layers/{animations → motion/animations}/app/components/Motion/Cursor.vue +0 -0
  462. /package/layers/{animations → motion/animations}/app/components/Motion/Magnetic.vue +0 -0
  463. /package/layers/{animations → motion/animations}/app/components/Motion/MarqueeText.vue +0 -0
  464. /package/layers/{animations → motion/animations}/app/components/Motion/TextReveal.vue +0 -0
  465. /package/layers/{animations → motion/animations}/app/components/Motion/Tilt.vue +0 -0
  466. /package/layers/{animations → motion/animations}/app/components/Motion/VelocityEffect.vue +0 -0
  467. /package/layers/{animations → motion/animations}/app/composables/useCountUp.ts +0 -0
  468. /package/layers/{animations → motion/animations}/app/composables/useCursorFollower.ts +0 -0
  469. /package/layers/{animations → motion/animations}/app/composables/useMagneticElement.ts +0 -0
  470. /package/layers/{animations → motion/animations}/app/composables/useMarqueeCopies.ts +0 -0
  471. /package/layers/{animations → motion/animations}/app/composables/useMarqueeVelocity.ts +0 -0
  472. /package/layers/{animations → motion/animations}/app/composables/useTiltEffect.ts +0 -0
  473. /package/layers/{animations → motion/animations}/app/utils/pointerMotion.ts +0 -0
  474. /package/layers/{animations → motion/animations}/package.json +0 -0
  475. /package/layers/motion/{nuxt.config.ts → motion/nuxt.config.ts} +0 -0
  476. /package/layers/{page-transitions → motion/page-transitions}/app/app.config.ts +0 -0
  477. /package/layers/{page-transitions → motion/page-transitions}/package.json +0 -0
  478. /package/layers/{scroll → motion/scroll}/app/components/Motion/HorizontalScroll.vue +0 -0
  479. /package/layers/{scroll → motion/scroll}/app/components/Motion/Parallax.vue +0 -0
  480. /package/layers/{scroll → motion/scroll}/app/components/Motion/PinnedSection.vue +0 -0
  481. /package/layers/{scroll → motion/scroll}/app/components/Motion/ScrollLink.vue +0 -0
  482. /package/layers/{scroll → motion/scroll}/app/components/Motion/ScrollProgress.vue +0 -0
  483. /package/layers/{scroll → motion/scroll}/app/components/Motion/ScrollScene.vue +0 -0
  484. /package/layers/{scroll → motion/scroll}/app/components/Motion/ScrollStats.vue +0 -0
  485. /package/layers/{scroll → motion/scroll}/app/components/Motion/ScrollStep.vue +0 -0
  486. /package/layers/{scroll → motion/scroll}/app/composables/useGsap.ts +0 -0
  487. /package/layers/{scroll → motion/scroll}/app/composables/useScrollSteps.ts +0 -0
  488. /package/layers/{scroll → motion/scroll}/app/composables/useSectionProgress.ts +0 -0
  489. /package/layers/{scroll → motion/scroll}/app/types/index.ts +0 -0
  490. /package/layers/{scroll → motion/scroll}/app/types/scroll.ts +0 -0
  491. /package/layers/{scroll → motion/scroll}/app/utils/scroll.ts +0 -0
  492. /package/layers/{scroll → motion/scroll}/package.json +0 -0
  493. /package/layers/{transitions → motion/transitions}/app/assets/css/transitions.css +0 -0
  494. /package/layers/{transitions → motion/transitions}/app/components/Motion/Transition.vue +0 -0
  495. /package/layers/{transitions → motion/transitions}/package.json +0 -0
  496. /package/layers/{canvas → render/canvas}/app/components/ShaderCanvas.vue +0 -0
  497. /package/layers/{canvas → render/canvas}/app/types/index.ts +0 -0
  498. /package/layers/{canvas → render/canvas}/app/types/renderer.ts +0 -0
  499. /package/layers/{shader → render/shader}/app/assets/css/shader.css +0 -0
  500. /package/layers/{shader → render/shader}/app/components/Effect/Bloom.vue +0 -0
  501. /package/layers/{shader → render/shader}/app/components/Effect/ChromaticAberration.vue +0 -0
  502. /package/layers/{shader → render/shader}/app/components/Effect/PostProcessing.vue +0 -0
  503. /package/layers/{shader → render/shader}/app/components/Material/AmbientAurora.client.vue +0 -0
  504. /package/layers/{shader → render/shader}/app/components/Material/AmbientFlow.client.vue +0 -0
  505. /package/layers/{shader → render/shader}/app/components/Material/AmbientGradientMesh.client.vue +0 -0
  506. /package/layers/{shader → render/shader}/app/components/Material/AmbientNebula.client.vue +0 -0
  507. /package/layers/{shader → render/shader}/app/components/Material/AmbientOcean.client.vue +0 -0
  508. /package/layers/{shader → render/shader}/app/components/Material/Fresnel.client.vue +0 -0
  509. /package/layers/{shader → render/shader}/app/components/Material/Gradient.client.vue +0 -0
  510. /package/layers/{shader → render/shader}/app/components/Material/Image.client.vue +0 -0
  511. /package/layers/{shader → render/shader}/app/components/Material/Node.client.vue +0 -0
  512. /package/layers/{shader → render/shader}/app/components/Material/Noise.client.vue +0 -0
  513. /package/layers/{shader → render/shader}/app/components/Mesh/Plane.vue +0 -0
  514. /package/layers/{shader → render/shader}/app/components/Node/Color.client.vue +0 -0
  515. /package/layers/{shader → render/shader}/app/components/Node/Fresnel.client.vue +0 -0
  516. /package/layers/{shader → render/shader}/app/components/Node/Gradient.client.vue +0 -0
  517. /package/layers/{shader → render/shader}/app/components/Node/Mix.client.vue +0 -0
  518. /package/layers/{shader → render/shader}/app/components/Node/Noise.client.vue +0 -0
  519. /package/layers/{shader → render/shader}/app/components/Pipeline/ACESTonemap.client.vue +0 -0
  520. /package/layers/{shader → render/shader}/app/components/Pipeline/AddBlend.client.vue +0 -0
  521. /package/layers/{shader → render/shader}/app/components/Pipeline/AgedFilm.client.vue +0 -0
  522. /package/layers/{shader → render/shader}/app/components/Pipeline/Aurora.client.vue +0 -0
  523. /package/layers/{shader → render/shader}/app/components/Pipeline/BilinearGradient.client.vue +0 -0
  524. /package/layers/{shader → render/shader}/app/components/Pipeline/BillowNoise.client.vue +0 -0
  525. /package/layers/{shader → render/shader}/app/components/Pipeline/BrightnessContrast.client.vue +0 -0
  526. /package/layers/{shader → render/shader}/app/components/Pipeline/CellularNoise.client.vue +0 -0
  527. /package/layers/{shader → render/shader}/app/components/Pipeline/ChannelMixer.client.vue +0 -0
  528. /package/layers/{shader → render/shader}/app/components/Pipeline/ChebyshevNoiseField.client.vue +0 -0
  529. /package/layers/{shader → render/shader}/app/components/Pipeline/Checkerboard.client.vue +0 -0
  530. /package/layers/{shader → render/shader}/app/components/Pipeline/ChromaticAberration.client.vue +0 -0
  531. /package/layers/{shader → render/shader}/app/components/Pipeline/ChromaticScreenWaves.client.vue +0 -0
  532. /package/layers/{shader → render/shader}/app/components/Pipeline/Circle.client.vue +0 -0
  533. /package/layers/{shader → render/shader}/app/components/Pipeline/Clouds.client.vue +0 -0
  534. /package/layers/{shader → render/shader}/app/components/Pipeline/ColorBurnBlend.client.vue +0 -0
  535. /package/layers/{shader → render/shader}/app/components/Pipeline/ColorDodgeBlend.client.vue +0 -0
  536. /package/layers/{shader → render/shader}/app/components/Pipeline/ColourRamp.client.vue +0 -0
  537. /package/layers/{shader → render/shader}/app/components/Pipeline/ComplexPlaneField.client.vue +0 -0
  538. /package/layers/{shader → render/shader}/app/components/Pipeline/ConicGradient.client.vue +0 -0
  539. /package/layers/{shader → render/shader}/app/components/Pipeline/CosinePalette.client.vue +0 -0
  540. /package/layers/{shader → render/shader}/app/components/Pipeline/CoverageAlpha.client.vue +0 -0
  541. /package/layers/{shader → render/shader}/app/components/Pipeline/Cross.client.vue +0 -0
  542. /package/layers/{shader → render/shader}/app/components/Pipeline/CurlNoise.client.vue +0 -0
  543. /package/layers/{shader → render/shader}/app/components/Pipeline/DarkenBlend.client.vue +0 -0
  544. /package/layers/{shader → render/shader}/app/components/Pipeline/DayNightCycle.client.vue +0 -0
  545. /package/layers/{shader → render/shader}/app/components/Pipeline/Desaturate.client.vue +0 -0
  546. /package/layers/{shader → render/shader}/app/components/Pipeline/DiagonalGradient.client.vue +0 -0
  547. /package/layers/{shader → render/shader}/app/components/Pipeline/DiamondGradient.client.vue +0 -0
  548. /package/layers/{shader → render/shader}/app/components/Pipeline/DifferenceBlend.client.vue +0 -0
  549. /package/layers/{shader → render/shader}/app/components/Pipeline/DivideBlend.client.vue +0 -0
  550. /package/layers/{shader → render/shader}/app/components/Pipeline/DomainWarpedNoise.client.vue +0 -0
  551. /package/layers/{shader → render/shader}/app/components/Pipeline/Dots.client.vue +0 -0
  552. /package/layers/{shader → render/shader}/app/components/Pipeline/DuoTone.client.vue +0 -0
  553. /package/layers/{shader → render/shader}/app/components/Pipeline/ExclusionBlend.client.vue +0 -0
  554. /package/layers/{shader → render/shader}/app/components/Pipeline/ExponentialFog.client.vue +0 -0
  555. /package/layers/{shader → render/shader}/app/components/Pipeline/Exposure.client.vue +0 -0
  556. /package/layers/{shader → render/shader}/app/components/Pipeline/FBMNoise.client.vue +0 -0
  557. /package/layers/{shader → render/shader}/app/components/Pipeline/FilmBurn.client.vue +0 -0
  558. /package/layers/{shader → render/shader}/app/components/Pipeline/FilmGrain.client.vue +0 -0
  559. /package/layers/{shader → render/shader}/app/components/Pipeline/FisheyeRay.client.vue +0 -0
  560. /package/layers/{shader → render/shader}/app/components/Pipeline/Flame.client.vue +0 -0
  561. /package/layers/{shader → render/shader}/app/components/Pipeline/FocalGradient.client.vue +0 -0
  562. /package/layers/{shader → render/shader}/app/components/Pipeline/Gamma.client.vue +0 -0
  563. /package/layers/{shader → render/shader}/app/components/Pipeline/GodRays.client.vue +0 -0
  564. /package/layers/{shader → render/shader}/app/components/Pipeline/GradientNoise.client.vue +0 -0
  565. /package/layers/{shader → render/shader}/app/components/Pipeline/Grain.client.vue +0 -0
  566. /package/layers/{shader → render/shader}/app/components/Pipeline/Grid.client.vue +0 -0
  567. /package/layers/{shader → render/shader}/app/components/Pipeline/Halation.client.vue +0 -0
  568. /package/layers/{shader → render/shader}/app/components/Pipeline/Halftone.client.vue +0 -0
  569. /package/layers/{shader → render/shader}/app/components/Pipeline/HardLightBlend.client.vue +0 -0
  570. /package/layers/{shader → render/shader}/app/components/Pipeline/Haze.client.vue +0 -0
  571. /package/layers/{shader → render/shader}/app/components/Pipeline/Hexagon.client.vue +0 -0
  572. /package/layers/{shader → render/shader}/app/components/Pipeline/Hue.client.vue +0 -0
  573. /package/layers/{shader → render/shader}/app/components/Pipeline/Invert.client.vue +0 -0
  574. /package/layers/{shader → render/shader}/app/components/Pipeline/LensFlare.client.vue +0 -0
  575. /package/layers/{shader → render/shader}/app/components/Pipeline/LightenBlend.client.vue +0 -0
  576. /package/layers/{shader → render/shader}/app/components/Pipeline/LinearGradient.client.vue +0 -0
  577. /package/layers/{shader → render/shader}/app/components/Pipeline/LinearGradient4.client.vue +0 -0
  578. /package/layers/{shader → render/shader}/app/components/Pipeline/LinearToSRGB.client.vue +0 -0
  579. /package/layers/{shader → render/shader}/app/components/Pipeline/Marble.client.vue +0 -0
  580. /package/layers/{shader → render/shader}/app/components/Pipeline/MixBlend.client.vue +0 -0
  581. /package/layers/{shader → render/shader}/app/components/Pipeline/MonochromeTint.client.vue +0 -0
  582. /package/layers/{shader → render/shader}/app/components/Pipeline/MultiplyBlend.client.vue +0 -0
  583. /package/layers/{shader → render/shader}/app/components/Pipeline/NoisyGradient.client.vue +0 -0
  584. /package/layers/{shader → render/shader}/app/components/Pipeline/NoisyGradientBlend.client.vue +0 -0
  585. /package/layers/{shader → render/shader}/app/components/Pipeline/OverlayBlend.client.vue +0 -0
  586. /package/layers/{shader → render/shader}/app/components/Pipeline/PaperTexture.client.vue +0 -0
  587. /package/layers/{shader → render/shader}/app/components/Pipeline/Polygon.client.vue +0 -0
  588. /package/layers/{shader → render/shader}/app/components/Pipeline/Posterise.client.vue +0 -0
  589. /package/layers/{shader → render/shader}/app/components/Pipeline/RadialGradient.client.vue +0 -0
  590. /package/layers/{shader → render/shader}/app/components/Pipeline/RayAutoOrbit.client.vue +0 -0
  591. /package/layers/{shader → render/shader}/app/components/Pipeline/RayMouseOrbit.client.vue +0 -0
  592. /package/layers/{shader → render/shader}/app/components/Pipeline/RayRotateX.client.vue +0 -0
  593. /package/layers/{shader → render/shader}/app/components/Pipeline/RayRotateY.client.vue +0 -0
  594. /package/layers/{shader → render/shader}/app/components/Pipeline/RayRotateZ.client.vue +0 -0
  595. /package/layers/{shader → render/shader}/app/components/Pipeline/RayTiltBasis.client.vue +0 -0
  596. /package/layers/{shader → render/shader}/app/components/Pipeline/RaymarchTunnel.client.vue +0 -0
  597. /package/layers/{shader → render/shader}/app/components/Pipeline/Rectangle.client.vue +0 -0
  598. /package/layers/{shader → render/shader}/app/components/Pipeline/ReinhardTonemap.client.vue +0 -0
  599. /package/layers/{shader → render/shader}/app/components/Pipeline/RidgedNoise.client.vue +0 -0
  600. /package/layers/{shader → render/shader}/app/components/Pipeline/Ring.client.vue +0 -0
  601. /package/layers/{shader → render/shader}/app/components/Pipeline/RingField.client.vue +0 -0
  602. /package/layers/{shader → render/shader}/app/components/Pipeline/RisographGrain.client.vue +0 -0
  603. /package/layers/{shader → render/shader}/app/components/Pipeline/RotatedGradientBlend.client.vue +0 -0
  604. /package/layers/{shader → render/shader}/app/components/Pipeline/SDFColourMask.client.vue +0 -0
  605. /package/layers/{shader → render/shader}/app/components/Pipeline/SDFRadialMask.client.vue +0 -0
  606. /package/layers/{shader → render/shader}/app/components/Pipeline/SRGBToLinear.client.vue +0 -0
  607. /package/layers/{shader → render/shader}/app/components/Pipeline/Saturation.client.vue +0 -0
  608. /package/layers/{shader → render/shader}/app/components/Pipeline/Scanlines.client.vue +0 -0
  609. /package/layers/{shader → render/shader}/app/components/Pipeline/ScreenBlend.client.vue +0 -0
  610. /package/layers/{shader → render/shader}/app/components/Pipeline/ShaderDebugger.client.vue +0 -0
  611. /package/layers/{shader → render/shader}/app/components/Pipeline/SimplexNoise.client.vue +0 -0
  612. /package/layers/{shader → render/shader}/app/components/Pipeline/SkyAtmosphere.client.vue +0 -0
  613. /package/layers/{shader → render/shader}/app/components/Pipeline/SoftLightBlend.client.vue +0 -0
  614. /package/layers/{shader → render/shader}/app/components/Pipeline/SolidColour.client.vue +0 -0
  615. /package/layers/{shader → render/shader}/app/components/Pipeline/SplitTone.client.vue +0 -0
  616. /package/layers/{shader → render/shader}/app/components/Pipeline/Star.client.vue +0 -0
  617. /package/layers/{shader → render/shader}/app/components/Pipeline/Starfield.client.vue +0 -0
  618. /package/layers/{shader → render/shader}/app/components/Pipeline/Stripes.client.vue +0 -0
  619. /package/layers/{shader → render/shader}/app/components/Pipeline/SubtractBlend.client.vue +0 -0
  620. /package/layers/{shader → render/shader}/app/components/Pipeline/TanhTonemap.client.vue +0 -0
  621. /package/layers/{shader → render/shader}/app/components/Pipeline/Threshold.client.vue +0 -0
  622. /package/layers/{shader → render/shader}/app/components/Pipeline/Tint.client.vue +0 -0
  623. /package/layers/{shader → render/shader}/app/components/Pipeline/Triangle.client.vue +0 -0
  624. /package/layers/{shader → render/shader}/app/components/Pipeline/UVAspectCorrect.client.vue +0 -0
  625. /package/layers/{shader → render/shader}/app/components/Pipeline/UVBreath.client.vue +0 -0
  626. /package/layers/{shader → render/shader}/app/components/Pipeline/UVBulge.client.vue +0 -0
  627. /package/layers/{shader → render/shader}/app/components/Pipeline/UVClamp.client.vue +0 -0
  628. /package/layers/{shader → render/shader}/app/components/Pipeline/UVColumnOffset.client.vue +0 -0
  629. /package/layers/{shader → render/shader}/app/components/Pipeline/UVFlipX.client.vue +0 -0
  630. /package/layers/{shader → render/shader}/app/components/Pipeline/UVFlipXY.client.vue +0 -0
  631. /package/layers/{shader → render/shader}/app/components/Pipeline/UVFlipY.client.vue +0 -0
  632. /package/layers/{shader → render/shader}/app/components/Pipeline/UVFractBand.client.vue +0 -0
  633. /package/layers/{shader → render/shader}/app/components/Pipeline/UVMousePull.client.vue +0 -0
  634. /package/layers/{shader → render/shader}/app/components/Pipeline/UVNoiseRotate.client.vue +0 -0
  635. /package/layers/{shader → render/shader}/app/components/Pipeline/UVNoiseWarp.client.vue +0 -0
  636. /package/layers/{shader → render/shader}/app/components/Pipeline/UVOrbit.client.vue +0 -0
  637. /package/layers/{shader → render/shader}/app/components/Pipeline/UVParallax.client.vue +0 -0
  638. /package/layers/{shader → render/shader}/app/components/Pipeline/UVPixelate.client.vue +0 -0
  639. /package/layers/{shader → render/shader}/app/components/Pipeline/UVPulse.client.vue +0 -0
  640. /package/layers/{shader → render/shader}/app/components/Pipeline/UVRipple.client.vue +0 -0
  641. /package/layers/{shader → render/shader}/app/components/Pipeline/UVRotate.client.vue +0 -0
  642. /package/layers/{shader → render/shader}/app/components/Pipeline/UVScale.client.vue +0 -0
  643. /package/layers/{shader → render/shader}/app/components/Pipeline/UVScroll.client.vue +0 -0
  644. /package/layers/{shader → render/shader}/app/components/Pipeline/UVScrollX.client.vue +0 -0
  645. /package/layers/{shader → render/shader}/app/components/Pipeline/UVScrollY.client.vue +0 -0
  646. /package/layers/{shader → render/shader}/app/components/Pipeline/UVShear.client.vue +0 -0
  647. /package/layers/{shader → render/shader}/app/components/Pipeline/UVSineWarpXY.client.vue +0 -0
  648. /package/layers/{shader → render/shader}/app/components/Pipeline/UVSwapAxes.client.vue +0 -0
  649. /package/layers/{shader → render/shader}/app/components/Pipeline/UVTile.client.vue +0 -0
  650. /package/layers/{shader → render/shader}/app/components/Pipeline/UVTwirl.client.vue +0 -0
  651. /package/layers/{shader → render/shader}/app/components/Pipeline/UVWarp.client.vue +0 -0
  652. /package/layers/{shader → render/shader}/app/components/Pipeline/VHSBleed.client.vue +0 -0
  653. /package/layers/{shader → render/shader}/app/components/Pipeline/ValueNoise.client.vue +0 -0
  654. /package/layers/{shader → render/shader}/app/components/Pipeline/Vibrance.client.vue +0 -0
  655. /package/layers/{shader → render/shader}/app/components/Pipeline/Vignette.client.vue +0 -0
  656. /package/layers/{shader → render/shader}/app/components/Pipeline/VoronoiEdges.client.vue +0 -0
  657. /package/layers/{shader → render/shader}/app/components/Pipeline/Water.client.vue +0 -0
  658. /package/layers/{shader → render/shader}/app/components/Pipeline/WaveBendLayer.client.vue +0 -0
  659. /package/layers/{shader → render/shader}/app/components/Pipeline/WaveColourLayer.client.vue +0 -0
  660. /package/layers/{shader → render/shader}/app/components/Pipeline/WhiteBalance.client.vue +0 -0
  661. /package/layers/{shader → render/shader}/app/components/Pipeline/Wood.client.vue +0 -0
  662. /package/layers/{shader → render/shader}/app/components/Preset/Aurora.client.vue +0 -0
  663. /package/layers/{shader → render/shader}/app/components/Preset/Flow.client.vue +0 -0
  664. /package/layers/{shader → render/shader}/app/components/Preset/GradientMesh.client.vue +0 -0
  665. /package/layers/{shader → render/shader}/app/components/Preset/Nebula.client.vue +0 -0
  666. /package/layers/{shader → render/shader}/app/components/Preset/Ocean.client.vue +0 -0
  667. /package/layers/{shader → render/shader}/app/components/Preset/ThemeAurora.client.vue +0 -0
  668. /package/layers/{shader → render/shader}/app/components/Preset/ThemeBubble.client.vue +0 -0
  669. /package/layers/{shader → render/shader}/app/components/Preset/ThemeFlow.client.vue +0 -0
  670. /package/layers/{shader → render/shader}/app/components/Preset/ThemeGradient.client.vue +0 -0
  671. /package/layers/{shader → render/shader}/app/components/Preset/ThemeLavaLamp.client.vue +0 -0
  672. /package/layers/{shader → render/shader}/app/components/Preset/ThemePlasma.client.vue +0 -0
  673. /package/layers/{shader → render/shader}/app/components/Preset/ThemeWave.client.vue +0 -0
  674. /package/layers/{shader → render/shader}/app/components/Shader/Background.client.vue +0 -0
  675. /package/layers/{shader → render/shader}/app/components/Shader/Debug.vue +0 -0
  676. /package/layers/{shader → render/shader}/app/components/Shader/Host.client.vue +0 -0
  677. /package/layers/{shader → render/shader}/app/components/Shader/Material.client.vue +0 -0
  678. /package/layers/{shader → render/shader}/app/components/Shader/Pipeline.client.vue +0 -0
  679. /package/layers/{shader → render/shader}/app/components/Shader/PipelineContext.vue +0 -0
  680. /package/layers/{shader → render/shader}/app/components/Shader/Runtime.client.vue +0 -0
  681. /package/layers/{shader → render/shader}/app/composables/useAmbientMaterials.ts +0 -0
  682. /package/layers/{shader → render/shader}/app/composables/useCSSColourUniform.ts +0 -0
  683. /package/layers/{shader → render/shader}/app/composables/useCSSFloatUniform.ts +0 -0
  684. /package/layers/{shader → render/shader}/app/composables/useMousePosition.ts +0 -0
  685. /package/layers/{shader → render/shader}/app/composables/useShader.ts +0 -0
  686. /package/layers/{shader → render/shader}/app/composables/useShaderColor.ts +0 -0
  687. /package/layers/{shader → render/shader}/app/composables/useShaderFloat.ts +0 -0
  688. /package/layers/{shader → render/shader}/app/composables/useShaderGraph.ts +0 -0
  689. /package/layers/{shader → render/shader}/app/composables/useShaderMixBlend.ts +0 -0
  690. /package/layers/{shader → render/shader}/app/composables/useShaderPerf.ts +0 -0
  691. /package/layers/{shader → render/shader}/app/composables/useShaderPipeline.ts +0 -0
  692. /package/layers/{shader → render/shader}/app/composables/useShaderRuntime.ts +0 -0
  693. /package/layers/{shader → render/shader}/app/composables/useShaderVec2.ts +0 -0
  694. /package/layers/{shader → render/shader}/app/composables/useSunDirectionUniform.ts +0 -0
  695. /package/layers/{shader → render/shader}/app/composables/useTSLNodes.ts +0 -0
  696. /package/layers/{shader → render/shader}/app/composables/useThemeColors.ts +0 -0
  697. /package/layers/{shader → render/shader}/app/composables/useThemePreset.ts +0 -0
  698. /package/layers/{shader → render/shader}/app/composables/useUniformWatchers.ts +0 -0
  699. /package/layers/{shader → render/shader}/app/composables/useUniforms.ts +0 -0
  700. /package/layers/{shader → render/shader}/app/plugins/shader.client.ts +0 -0
  701. /package/layers/{shader → render/shader}/app/shaders/common/blend.ts +0 -0
  702. /package/layers/{shader → render/shader}/app/shaders/common/complex.ts +0 -0
  703. /package/layers/{shader → render/shader}/app/shaders/common/effects.ts +0 -0
  704. /package/layers/{shader → render/shader}/app/shaders/common/grain.ts +0 -0
  705. /package/layers/{shader → render/shader}/app/shaders/common/index.ts +0 -0
  706. /package/layers/{shader → render/shader}/app/shaders/common/lighting.ts +0 -0
  707. /package/layers/{shader → render/shader}/app/shaders/common/math.ts +0 -0
  708. /package/layers/{shader → render/shader}/app/shaders/common/nodes.ts +0 -0
  709. /package/layers/{shader → render/shader}/app/shaders/common/noise.ts +0 -0
  710. /package/layers/{shader → render/shader}/app/shaders/common/noiseHelpers.ts +0 -0
  711. /package/layers/{shader → render/shader}/app/shaders/common/palette.ts +0 -0
  712. /package/layers/{shader → render/shader}/app/shaders/common/patterns.ts +0 -0
  713. /package/layers/{shader → render/shader}/app/shaders/common/sdf.ts +0 -0
  714. /package/layers/{shader → render/shader}/app/shaders/common/shapes.ts +0 -0
  715. /package/layers/{shader → render/shader}/app/shaders/common/tonemapping.ts +0 -0
  716. /package/layers/{shader → render/shader}/app/shaders/common/uv.ts +0 -0
  717. /package/layers/{shader → render/shader}/app/shaders/createMaterial.ts +0 -0
  718. /package/layers/{shader → render/shader}/app/shaders/index.ts +0 -0
  719. /package/layers/{shader → render/shader}/app/shaders/layers/aurora.ts +0 -0
  720. /package/layers/{shader → render/shader}/app/shaders/layers/index.ts +0 -0
  721. /package/layers/{shader → render/shader}/app/shaders/layers/meshGradient.ts +0 -0
  722. /package/layers/{shader → render/shader}/app/shaders/layers/shaderGradient.ts +0 -0
  723. /package/layers/{shader → render/shader}/app/shaders/layers/stripe.ts +0 -0
  724. /package/layers/{shader → render/shader}/app/shaders/types.ts +0 -0
  725. /package/layers/{shader → render/shader}/app/types/index.ts +0 -0
  726. /package/layers/{shader → render/shader}/app/types/materials.ts +0 -0
  727. /package/layers/{shader → render/shader}/app/types/renderer.ts +0 -0
  728. /package/layers/{shader → render/shader}/app/types/tsl.ts +0 -0
  729. /package/layers/{shader → render/shader}/app/types/uniforms.ts +0 -0
  730. /package/layers/{shader → render/shader}/app/utils/tsl/animation.ts +0 -0
  731. /package/layers/{shader → render/shader}/app/utils/tsl/color.ts +0 -0
  732. /package/layers/{shader → render/shader}/app/utils/tsl/index.ts +0 -0
  733. /package/layers/{shader → render/shader}/app/utils/tsl/math.ts +0 -0
  734. /package/layers/{shader → render/shader}/app/utils/tsl/noise.ts +0 -0
  735. /package/layers/{shader → render/shader}/app/utils/tsl/oklch.ts +0 -0
  736. /package/layers/{shader → render/shader}/app/utils/tsl/patterns.ts +0 -0
  737. /package/layers/{shader → render/shader}/app/utils/tsl/tween.ts +0 -0
  738. /package/layers/{shader → render/shader}/app/utils/tsl/uv.ts +0 -0
  739. /package/layers/{shader → render/shader}/nuxt.config.ts +0 -0
  740. /package/layers/{layout → structure/layout}/app/components/Layout/Section/Gallery.vue +0 -0
  741. /package/layers/{layout → structure/layout}/app/components/Layout/Section/Hero.vue +0 -0
  742. /package/layers/{layout → structure/layout}/app/components/Layout/Section/Split.vue +0 -0
  743. /package/layers/{layout → structure/layout}/app/composables/useGridConfig.ts +0 -0
  744. /package/layers/{layout → structure/layout}/app/types/index.ts +0 -0
  745. /package/layers/{layout → structure/layout}/tailwind.config.js +0 -0
  746. /package/layers/{navigation → structure/navigation}/app/assets/css/navigation.css +0 -0
  747. /package/layers/{navigation → structure/navigation}/app/components/Links/Group.vue +0 -0
  748. /package/layers/{navigation → structure/navigation}/app/components/Links/Named.vue +0 -0
  749. /package/layers/{navigation → structure/navigation}/app/components/Mast/Footer.vue +0 -0
  750. /package/layers/{navigation → structure/navigation}/app/components/Mast/NavModal.vue +0 -0
  751. /package/layers/{navigation → structure/navigation}/app/components/Site/Subtitle.vue +0 -0
  752. /package/layers/{navigation → structure/navigation}/app/components/Site/Title.vue +0 -0
  753. /package/layers/{navigation → structure/navigation}/app/composables/toast.ts +0 -0
  754. /package/layers/{navigation → structure/navigation}/app/composables/useSite.ts +0 -0
  755. /package/layers/{navigation → structure/navigation}/app/types/index.ts +0 -0
  756. /package/layers/{navigation → structure/navigation}/app/types/nav.ts +0 -0
  757. /package/layers/{core → structure/navigation}/app/utils/regex.ts +0 -0
  758. /package/layers/{navigation → structure/navigation}/app/utils/site.test.ts +0 -0
  759. /package/layers/{navigation → structure/navigation}/app/utils/site.ts +0 -0
  760. /package/layers/{navigation → structure/navigation}/package.json +0 -0
  761. /package/layers/{routing → structure/routing}/app/composables/useFeatureFlags.ts +0 -0
  762. /package/layers/{routing → structure/routing}/app/composables/useMaintenance.ts +0 -0
  763. /package/layers/{routing → structure/routing}/app/composables/useRoutingConfig.ts +0 -0
  764. /package/layers/{routing → structure/routing}/app/middleware/01.maintenance.global.ts +0 -0
  765. /package/layers/{routing → structure/routing}/app/middleware/02.governance.global.ts +0 -0
  766. /package/layers/{routing → structure/routing}/app/plugins/feature-flags.client.ts +0 -0
  767. /package/layers/{routing → structure/routing}/app/plugins/scroll-routing.client.ts +0 -0
  768. /package/layers/{routing → structure/routing}/app/types/index.ts +0 -0
  769. /package/layers/{routing → structure/routing}/app/types/route-meta.d.ts +0 -0
  770. /package/layers/{routing → structure/routing}/app/types/routing.ts +0 -0
  771. /package/layers/{routing → structure/routing}/app/utils/resolveRoute.test.ts +0 -0
  772. /package/layers/{routing → structure/routing}/app/utils/resolveRoute.ts +0 -0
  773. /package/layers/{routing → structure/routing}/server/api/feature-flags.get.ts +0 -0
@@ -0,0 +1,977 @@
1
+ # Grid Layer Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Add a new `grid` layer (Tier 2 — Structure) providing font-size-derived vertical rhythm plus data-driven, arbitrary-width column composition (named presets and custom track arrays), with a dev-only visual builder for constructing custom compositions.
6
+
7
+ **Architecture:** Two independent, composable concerns. (1) Rhythm — CSS custom properties on `.grid-root`, derived unconditionally from `--fs`, reimplementing `LAYOUT-SYSTEM.md`'s derivation chain (steps 1–6 only; column derivation is replaced by (2)). (2) Column composition — a `TrackSegment[]` data shape, resolved from a named preset registry (`app.config.ts`) or passed inline, converted to a `grid-template-columns` string by a pure function. Named CSS grid lines are the primary addressing mechanism (they survive `subgrid` boundaries); numeric index/span is a fallback util only, no component ships for it in this phase.
8
+
9
+ **Tech Stack:** Nuxt 4 layer conventions (`app/` srcDir, `#layers/grid` alias), TypeScript, Vitest (`layers/**/*.test.ts` auto-discovered by root `vitest.config.mts`), Vue 3 `<script setup lang="ts">` for the playground builder page only (no components ship in the layer itself).
10
+
11
+ **Spec:** `docs/superpowers/specs/2026-09-04-grid-layer-design.md`
12
+
13
+ ## Global Constraints
14
+
15
+ - New layer only — do not modify `layers/structure/layout/**` (its `LayoutMain`/`LayoutGridItem`/`Section`/`Hero`/`Split`/`Gallery`/`useGridConfig` are explicitly out of scope; reworking them to consume this layer is a future pass).
16
+ - Do not carry forward the `layout-fluid-rebuild` worktree's uncommitted `app.config.ts`/`types/layouts.ts` changes — this layer reimplements the rhythm math fresh, independent of that worktree.
17
+ - Rhythm CSS constraints (from `LAYOUT-SYSTEM.md`, carried forward unconditionally): every `clamp()` keeps a `rem`/`rlh` term (WCAG 1.4.4 zoom safety); `svh`/`svi` only, never `dvh`/`vw`/`vh`; `rlh` not `lh`; `container-type` never on `body`.
18
+ - No component ships in the `grid` layer itself in this phase — only CSS, a composable, and pure utils. The only Vue component is the playground's dev-only builder page.
19
+ - No Bento-grid preset, no row-track presets beyond the rhythm floor, no save-to-registry automation from the builder UI — all explicitly out of scope per spec.
20
+ - Package name: `kmcom-layer-grid`. Layer path: `layers/structure/grid`. Alias: `#layers/grid` (root), `#layers/grid/types` (types dir).
21
+ - Style: no semicolons, single quotes, ES5 trailing commas, max 100 char lines, `<script setup lang="ts">` block order script → template → style (per `.claude/rules/typescript.md` and `.claude/rules/vue-components.md`).
22
+
23
+ ---
24
+
25
+ ## File Structure
26
+
27
+ ```
28
+ layers/structure/grid/
29
+ ├── app/
30
+ │ ├── assets/css/
31
+ │ │ └── grid.css # Task 2 — rhythm custom properties, .grid-root
32
+ │ ├── composables/
33
+ │ │ └── useGridTracks.ts # Task 3 — resolve() + toColumnsCss(), composable wrapper
34
+ │ ├── types/
35
+ │ │ └── tracks.ts # Task 1 — TrackSegment, TrackConfig, GridPreset
36
+ │ ├── utils/
37
+ │ │ ├── placement.ts # Task 4 — placementFromLines, placementFromIndex
38
+ │ │ └── placement.test.ts # Task 4
39
+ │ └── app.config.ts # Task 5 — gridLayer.presets registry (swiss, editorial)
40
+ ├── nuxt.config.ts # Task 1 — $meta.name: 'grid', extends core, alias, css
41
+ ├── package.json # Task 1 — kmcom-layer-grid
42
+ └── CLAUDE.md # Task 1 — layer reference doc
43
+
44
+ layers/structure/grid/app/composables/useGridTracks.test.ts # Task 3
45
+
46
+ apps/playground/nuxt.config.ts # Task 6 — MODIFY: register grid in layer resolver
47
+ apps/playground/app/pages/grid-builder.vue # Task 7 — dev-only visual builder page
48
+ ```
49
+
50
+ **Boundary rationale:** `types/tracks.ts` has zero runtime dependents outside this layer's own composable/utils, so it's the natural first task (nothing else compiles without it). `useGridTracks.ts` and `utils/placement.ts` are independent pure-function modules — neither imports the other — so they're separate tasks or could run in parallel. `app.config.ts` depends on `types/tracks.ts` (for `GridPreset`) but not on the composable, so it's its own task. The playground builder page is last because it's the only consumer that needs the full composable + utils surface working end to end.
51
+
52
+ ---
53
+
54
+ ### Task 1: Layer scaffold + track types
55
+
56
+ **Files:**
57
+
58
+ - Create: `layers/structure/grid/nuxt.config.ts`
59
+ - Create: `layers/structure/grid/package.json`
60
+ - Create: `layers/structure/grid/CLAUDE.md`
61
+ - Create: `layers/structure/grid/app/types/tracks.ts`
62
+ - Test: `layers/structure/grid/app/types/tracks.test.ts`
63
+
64
+ **Interfaces:**
65
+
66
+ - Produces: `TrackSegment` (`{ size: number; lineStart?: string | string[]; lineEnd?: string | string[] }`), `TrackConfig` (`{ columns: TrackSegment[]; minTrackWidth?: string }`), `GridPreset` (`TrackConfig & { name: string }`) — all subsequent tasks import from `#layers/grid/types/tracks` (or relative `../types/tracks` within the layer).
67
+
68
+ - [ ] **Step 1: Create the layer directories**
69
+
70
+ Run: `mkdir -p layers/structure/grid/app/types layers/structure/grid/app/assets/css layers/structure/grid/app/composables layers/structure/grid/app/utils`
71
+
72
+ - [ ] **Step 2: Write `app/types/tracks.ts`**
73
+
74
+ ```ts
75
+ export type TrackSegment = {
76
+ /** Relative size, same unit as CSS `fr`. 1 = one equal column. */
77
+ size: number
78
+ /** Optional named line(s) at the start of this segment, e.g. 'feature-start'. */
79
+ lineStart?: string | string[]
80
+ /** Optional named line(s) at the end of this segment. */
81
+ lineEnd?: string | string[]
82
+ }
83
+
84
+ export type TrackConfig = {
85
+ columns: TrackSegment[]
86
+ /** Track floor — reuses --measure-min unless overridden. */
87
+ minTrackWidth?: string
88
+ }
89
+
90
+ export type GridPreset = TrackConfig & {
91
+ name: string
92
+ }
93
+ ```
94
+
95
+ - [ ] **Step 3: Write the failing test for the type shapes**
96
+
97
+ Types have no runtime behavior, so the test is a compile-time shape check: it fails if the file
98
+ doesn't exist yet, and catches accidental breaking changes to the shape later (e.g. renaming
99
+ `lineStart`).
100
+
101
+ ```ts
102
+ // layers/structure/grid/app/types/tracks.test.ts
103
+ import { describe, expect, it } from 'vitest'
104
+
105
+ import type { GridPreset, TrackConfig, TrackSegment } from './tracks'
106
+
107
+ describe('track types', () => {
108
+ it('accepts a minimal equal-width segment', () => {
109
+ const segment: TrackSegment = { size: 1 }
110
+ expect(segment.size).toBe(1)
111
+ })
112
+
113
+ it('accepts a segment with named lines', () => {
114
+ const segment: TrackSegment = {
115
+ size: 2,
116
+ lineStart: 'feature-start',
117
+ lineEnd: ['feature-end', 'aside-start'],
118
+ }
119
+ expect(segment.lineEnd).toEqual(['feature-end', 'aside-start'])
120
+ })
121
+
122
+ it('accepts a TrackConfig with optional minTrackWidth', () => {
123
+ const config: TrackConfig = {
124
+ columns: [{ size: 1 }, { size: 2 }],
125
+ minTrackWidth: '20rem',
126
+ }
127
+ expect(config.columns).toHaveLength(2)
128
+ })
129
+
130
+ it('a GridPreset is a named TrackConfig', () => {
131
+ const preset: GridPreset = { name: 'swiss', columns: [{ size: 1 }] }
132
+ expect(preset.name).toBe('swiss')
133
+ })
134
+ })
135
+ ```
136
+
137
+ - [ ] **Step 4: Run test to verify it fails**
138
+
139
+ Run: `pnpm vitest run layers/structure/grid/app/types/tracks.test.ts`
140
+ Expected: FAIL — cannot find module `./tracks` (file doesn't exist yet until Step 2 lands; if
141
+ Step 2 already ran, run this before Step 2 instead, or trust the type-checker catches shape
142
+ regressions on the next `pnpm typecheck` run — either ordering is fine for a types-only file).
143
+
144
+ - [ ] **Step 5: Run test to verify it passes**
145
+
146
+ Run: `pnpm vitest run layers/structure/grid/app/types/tracks.test.ts`
147
+ Expected: PASS (4 tests)
148
+
149
+ - [ ] **Step 6: Write `nuxt.config.ts`**
150
+
151
+ ```ts
152
+ // https://nuxt.com/docs/api/configuration/nuxt-config
153
+ export default defineNuxtConfig({
154
+ $meta: {
155
+ name: 'grid',
156
+ },
157
+
158
+ extends: ['../../core'],
159
+
160
+ alias: {
161
+ '#layers/grid': import.meta.dirname,
162
+ '#layers/grid/types': `${import.meta.dirname}/app/types`,
163
+ },
164
+
165
+ css: ['#layers/grid/app/assets/css/grid.css'],
166
+
167
+ compatibilityDate: '2026-01-20',
168
+
169
+ typescript: {
170
+ typeCheck: false,
171
+ strict: true,
172
+ },
173
+ })
174
+ ```
175
+
176
+ - [ ] **Step 7: Write `package.json`**
177
+
178
+ ```json
179
+ {
180
+ "name": "kmcom-layer-grid",
181
+ "type": "module",
182
+ "version": "0.0.1",
183
+ "main": "./nuxt.config.ts",
184
+ "scripts": {
185
+ "typecheck": "vue-tsc --noEmit -p ../../../tsconfig.typecheck.json",
186
+ "dev": "nuxi dev .playground",
187
+ "dev:prepare": "nuxt prepare .playground",
188
+ "build": "nuxt build .playground",
189
+ "generate": "nuxt generate .playground",
190
+ "preview": "nuxt preview .playground",
191
+ "lint": "eslint ."
192
+ }
193
+ }
194
+ ```
195
+
196
+ - [ ] **Step 8: Write `CLAUDE.md`**
197
+
198
+ ```markdown
199
+ # Grid Layer
200
+
201
+ Font-size-derived vertical rhythm + data-driven column composition for Nuxt 4 applications.
202
+ Named presets (`swiss`, `editorial`) or custom `TrackSegment[]` arrays resolve to
203
+ `grid-template-columns` strings via `useGridTracks()`. See
204
+ `docs/superpowers/specs/2026-09-04-grid-layer-design.md` for the full design.
205
+
206
+ ## Layer Structure
207
+
208
+ \`\`\`
209
+ layers/structure/grid/
210
+ ├── app/
211
+ │ ├── assets/css/grid.css # .grid-root rhythm custom properties
212
+ │ ├── composables/useGridTracks.ts # resolve() + toColumnsCss()
213
+ │ ├── types/tracks.ts # TrackSegment, TrackConfig, GridPreset
214
+ │ ├── utils/placement.ts # placementFromLines, placementFromIndex
215
+ │ └── app.config.ts # gridLayer.presets registry
216
+ ├── nuxt.config.ts
217
+ └── package.json
218
+ \`\`\`
219
+
220
+ ## Quick Reference
221
+
222
+ \`\`\`ts
223
+ const { resolve, toColumnsCss } = useGridTracks()
224
+
225
+ const config = resolve('swiss') // named preset from app.config
226
+ const custom = resolve({ columns: [{ size: 1 }, { size: 2 }] }) // passthrough
227
+
228
+ const css = toColumnsCss(config)
229
+ // → 'minmax(var(--measure-min), 1fr) minmax(var(--measure-min), 1fr) ...'
230
+ \`\`\`
231
+
232
+ \`\`\`ts
233
+ import { placementFromIndex, placementFromLines } from '#layers/grid/app/utils/placement'
234
+
235
+ placementFromLines('feature-start', 'aside-end') // → 'feature-start / aside-end'
236
+ placementFromIndex(2, 3) // → '2 / span 3'
237
+ placementFromIndex(2, 'full') // → '2 / -1'
238
+ \`\`\`
239
+
240
+ ## Out of scope (this layer, this phase)
241
+
242
+ - No `LayoutGridItem`-equivalent component — that's `layout`'s territory, deferred.
243
+ - No row-track presets beyond the rhythm-derived floor.
244
+ - No Bento-grid preset.
245
+ - `layers/structure/layout/**` is untouched — reworking it to consume this layer is a future pass.
246
+ ```
247
+
248
+ - [ ] **Step 9: Commit**
249
+
250
+ ```bash
251
+ git add layers/structure/grid/nuxt.config.ts layers/structure/grid/package.json \
252
+ layers/structure/grid/CLAUDE.md layers/structure/grid/app/types/tracks.ts \
253
+ layers/structure/grid/app/types/tracks.test.ts
254
+ git commit -m "feat(grid): scaffold new grid layer, add track types"
255
+ ```
256
+
257
+ ---
258
+
259
+ ### Task 2: Rhythm CSS
260
+
261
+ **Files:**
262
+
263
+ - Create: `layers/structure/grid/app/assets/css/grid.css`
264
+
265
+ **Interfaces:**
266
+
267
+ - Consumes: nothing (pure CSS, no TS dependency).
268
+ - Produces: `.grid-root` class with `--unit`, `--measure-min`, `--edge-min`, `--lines`, `--lpf`,
269
+ `--fields` custom properties, consumed visually by Task 7's builder page (no TS import — CSS
270
+ classes are used by `class="grid-root"` in markup).
271
+
272
+ - [ ] **Step 1: Write `app/assets/css/grid.css`**
273
+
274
+ Reimplements `LAYOUT-SYSTEM.md`'s derivation chain, steps 1–6 (step 7, column derivation via
275
+ `auto-fill`, is intentionally NOT included — column composition comes from `toColumnsCss()`
276
+ instead, applied per-consumer via inline `style="grid-template-columns: ..."`).
277
+
278
+ ```css
279
+ /* Grid layer rhythm — derives all vertical spacing from --fs. See
280
+ docs/superpowers/specs/2026-09-04-grid-layer-design.md and root LAYOUT-SYSTEM.md
281
+ for the full derivation rationale. Column composition is NOT here — it comes from
282
+ useGridTracks().toColumnsCss(), applied inline per grid-root instance. */
283
+
284
+ @property --fs {
285
+ syntax: '<length>';
286
+ inherits: true;
287
+ initial-value: 1rem;
288
+ }
289
+
290
+ :root {
291
+ /* rem term keeps this WCAG 1.4.4 zoom-safe; svi never vw (viewport-bar-collapse safe) */
292
+ --fs: clamp(1rem, 0.95rem + 0.25svi, 1.125rem);
293
+ font-size: var(--fs);
294
+ /* rounded, not raw, so grid boundaries land on-pixel */
295
+ line-height: round(nearest, var(--fs) * 1.5, 1px);
296
+ }
297
+
298
+ .grid-root {
299
+ /* rlh not lh: always resolves against root, unaffected by a nested element's own
300
+ line-height */
301
+ --unit: 1rlh;
302
+ --measure-min: 22rem;
303
+ /* margin floor > 0, steep svi slope so it shrinks fast on narrow screens */
304
+ --edge-min: clamp(1rlh, 8svi, 3rlh);
305
+ --avail-b: calc(100svh - 2 * var(--edge-min));
306
+ --lines: calc(round(down, var(--avail-b), var(--unit)) / var(--unit));
307
+ --lpf: clamp(4, round(down, calc(100svh / var(--unit) / 4.5), 1), 8);
308
+ --fields: max(1, round(down, calc((var(--lines) + 1) / (var(--lpf) + 1)), 1));
309
+
310
+ display: grid;
311
+ grid-auto-rows: minmax(calc(var(--lpf) * var(--unit)), max-content);
312
+ gap: var(--unit);
313
+ container-name: grid-root;
314
+ container-type: inline-size;
315
+ padding-inline: var(--edge-min);
316
+ padding-block: var(--edge-min);
317
+ }
318
+ ```
319
+
320
+ - [ ] **Step 2: Verify it's wired into the layer's `nuxt.config.ts`**
321
+
322
+ Task 1 Step 6 already added `css: ['#layers/grid/app/assets/css/grid.css']` — confirm the path
323
+ matches this file's actual location:
324
+
325
+ Run: `grep -n "grid.css" layers/structure/grid/nuxt.config.ts`
326
+ Expected: `css: ['#layers/grid/app/assets/css/grid.css'],`
327
+
328
+ - [ ] **Step 3: Commit**
329
+
330
+ ```bash
331
+ git add layers/structure/grid/app/assets/css/grid.css
332
+ git commit -m "feat(grid): add rhythm CSS derived from --fs"
333
+ ```
334
+
335
+ (Manual/visual verification of this CSS happens in Task 7, once a page actually renders
336
+ `.grid-root` — CSS custom-property derivation chains can't be meaningfully unit-tested in
337
+ Vitest, and a computed-style assertion would need a real browser per `LAYOUT-SYSTEM.md`
338
+ Pitfall 1's own lesson: `pnpm build`/static checks don't catch computed-value failures.)
339
+
340
+ ---
341
+
342
+ ### Task 3: `useGridTracks()` — track resolution and CSS generation
343
+
344
+ **Files:**
345
+
346
+ - Create: `layers/structure/grid/app/composables/useGridTracks.ts`
347
+ - Test: `layers/structure/grid/app/composables/useGridTracks.test.ts`
348
+
349
+ **Interfaces:**
350
+
351
+ - Consumes: `TrackSegment`, `TrackConfig`, `GridPreset` from `../types/tracks` (Task 1).
352
+ - Produces: `resolve(input: string | TrackConfig, presets?: Record<string, GridPreset>): TrackConfig`
353
+ and `toColumnsCss(config: TrackConfig): string` — both exported as standalone pure functions
354
+ (unit-testable without Nuxt context) — plus the `useGridTracks()` composable that wraps them
355
+ against `useAppConfig().gridLayer.presets`. Task 5 (`app.config.ts`) and Task 7 (builder page)
356
+ both call `useGridTracks()`; Task 6 does not.
357
+
358
+ - [ ] **Step 1: Write the failing tests**
359
+
360
+ ```ts
361
+ // layers/structure/grid/app/composables/useGridTracks.test.ts
362
+ import { describe, expect, it } from 'vitest'
363
+
364
+ import type { GridPreset, TrackConfig } from '../types/tracks'
365
+ import { resolve, toColumnsCss } from './useGridTracks'
366
+
367
+ describe('toColumnsCss', () => {
368
+ it('renders equal segments with no line names', () => {
369
+ const config: TrackConfig = { columns: [{ size: 1 }, { size: 1 }, { size: 1 }] }
370
+ expect(toColumnsCss(config)).toBe(
371
+ 'minmax(var(--measure-min), 1fr) minmax(var(--measure-min), 1fr) ' +
372
+ 'minmax(var(--measure-min), 1fr)'
373
+ )
374
+ })
375
+
376
+ it('renders mixed sizes (8 equal + double + triple)', () => {
377
+ const config: TrackConfig = {
378
+ columns: [
379
+ { size: 1 },
380
+ { size: 1 },
381
+ { size: 1 },
382
+ { size: 1 },
383
+ { size: 1 },
384
+ { size: 1 },
385
+ { size: 1 },
386
+ { size: 2 },
387
+ { size: 3 },
388
+ ],
389
+ }
390
+ const css = toColumnsCss(config)
391
+ expect(css.split(' ').filter((s) => s.startsWith('minmax'))).toHaveLength(9)
392
+ expect(css).toContain('minmax(var(--measure-min), 2fr)')
393
+ expect(css).toContain('minmax(var(--measure-min), 3fr)')
394
+ })
395
+
396
+ it('brackets a leading lineStart and trailing lineEnd', () => {
397
+ const config: TrackConfig = {
398
+ columns: [{ size: 1, lineStart: 'a-start', lineEnd: 'a-end' }],
399
+ }
400
+ expect(toColumnsCss(config)).toBe('[a-start] minmax(var(--measure-min), 1fr) [a-end]')
401
+ })
402
+
403
+ it('merges an adjacent lineEnd and lineStart into one bracket', () => {
404
+ const config: TrackConfig = {
405
+ columns: [
406
+ { size: 2, lineStart: 'feature-start', lineEnd: 'feature-end' },
407
+ { size: 1, lineStart: 'aside-start', lineEnd: 'aside-end' },
408
+ ],
409
+ }
410
+ expect(toColumnsCss(config)).toBe(
411
+ '[feature-start] minmax(var(--measure-min), 2fr) ' +
412
+ '[feature-end aside-start] minmax(var(--measure-min), 1fr) [aside-end]'
413
+ )
414
+ })
415
+
416
+ it('supports a segment with only lineStart set', () => {
417
+ const config: TrackConfig = {
418
+ columns: [{ size: 1, lineStart: 'only-start' }, { size: 1 }],
419
+ }
420
+ expect(toColumnsCss(config)).toBe(
421
+ '[only-start] minmax(var(--measure-min), 1fr) minmax(var(--measure-min), 1fr)'
422
+ )
423
+ })
424
+
425
+ it('accepts an array of line names', () => {
426
+ const config: TrackConfig = {
427
+ columns: [{ size: 1, lineStart: ['a', 'b'] }],
428
+ }
429
+ expect(toColumnsCss(config)).toBe('[a b] minmax(var(--measure-min), 1fr)')
430
+ })
431
+
432
+ it('uses minTrackWidth override instead of the --measure-min default', () => {
433
+ const config: TrackConfig = { columns: [{ size: 1 }], minTrackWidth: '20rem' }
434
+ expect(toColumnsCss(config)).toBe('minmax(20rem, 1fr)')
435
+ })
436
+ })
437
+
438
+ describe('resolve', () => {
439
+ const presets: Record<string, GridPreset> = {
440
+ swiss: { name: 'swiss', columns: [{ size: 1 }] },
441
+ }
442
+
443
+ it('looks up a named preset from the registry', () => {
444
+ expect(resolve('swiss', presets)).toBe(presets.swiss)
445
+ })
446
+
447
+ it('throws for an unknown preset name', () => {
448
+ expect(() => resolve('nope', presets)).toThrow('Unknown grid preset: "nope"')
449
+ })
450
+
451
+ it('passes a TrackConfig object through unchanged', () => {
452
+ const custom: TrackConfig = { columns: [{ size: 1 }, { size: 2 }] }
453
+ expect(resolve(custom, presets)).toBe(custom)
454
+ })
455
+ })
456
+ ```
457
+
458
+ - [ ] **Step 2: Run tests to verify they fail**
459
+
460
+ Run: `pnpm vitest run layers/structure/grid/app/composables/useGridTracks.test.ts`
461
+ Expected: FAIL — cannot find module `./useGridTracks`
462
+
463
+ - [ ] **Step 3: Write `app/composables/useGridTracks.ts`**
464
+
465
+ ```ts
466
+ import type { GridPreset, TrackConfig } from '../types/tracks'
467
+
468
+ type GridLayerAppConfig = {
469
+ gridLayer?: {
470
+ presets?: Record<string, GridPreset>
471
+ }
472
+ }
473
+
474
+ function normalizeNames(names: string | string[] | undefined): string[] {
475
+ if (!names) return []
476
+ return Array.isArray(names) ? names : [names]
477
+ }
478
+
479
+ function toBracket(names: string[]): string {
480
+ return names.length > 0 ? `[${names.join(' ')}]` : ''
481
+ }
482
+
483
+ /**
484
+ * Builds a `grid-template-columns` value from a TrackConfig. Each segment becomes a
485
+ * `minmax(floor, Nfr)` track; adjacent lineEnd/lineStart names merge into one bracket,
486
+ * per standard named-grid-line syntax.
487
+ */
488
+ export function toColumnsCss(config: TrackConfig): string {
489
+ const minWidth = config.minTrackWidth ?? 'var(--measure-min)'
490
+ const segments = config.columns
491
+
492
+ const parts: string[] = []
493
+
494
+ segments.forEach((segment, index) => {
495
+ const previous = index > 0 ? segments[index - 1] : undefined
496
+ const leadNames = [...normalizeNames(previous?.lineEnd), ...normalizeNames(segment.lineStart)]
497
+ const leadBracket = toBracket(leadNames)
498
+ if (leadBracket) parts.push(leadBracket)
499
+ parts.push(`minmax(${minWidth}, ${segment.size}fr)`)
500
+ })
501
+
502
+ const lastSegment = segments[segments.length - 1]
503
+ const trailBracket = toBracket(normalizeNames(lastSegment?.lineEnd))
504
+ if (trailBracket) parts.push(trailBracket)
505
+
506
+ return parts.join(' ')
507
+ }
508
+
509
+ /**
510
+ * Resolves a preset name against a registry, or passes a TrackConfig object through
511
+ * unchanged. Exported standalone so it's testable without Nuxt's useAppConfig context.
512
+ */
513
+ export function resolve(
514
+ input: string | TrackConfig,
515
+ presets?: Record<string, GridPreset>
516
+ ): TrackConfig {
517
+ if (typeof input === 'string') {
518
+ const found = presets?.[input]
519
+ if (!found) {
520
+ throw new Error(`Unknown grid preset: "${input}"`)
521
+ }
522
+ return found
523
+ }
524
+ return input
525
+ }
526
+
527
+ export function useGridTracks() {
528
+ const appConfig = useAppConfig() as GridLayerAppConfig
529
+ const presets = computed(() => appConfig.gridLayer?.presets)
530
+
531
+ return {
532
+ resolve: (input: string | TrackConfig) => resolve(input, presets.value),
533
+ toColumnsCss,
534
+ }
535
+ }
536
+ ```
537
+
538
+ - [ ] **Step 4: Run tests to verify they pass**
539
+
540
+ Run: `pnpm vitest run layers/structure/grid/app/composables/useGridTracks.test.ts`
541
+ Expected: PASS (10 tests)
542
+
543
+ - [ ] **Step 5: Commit**
544
+
545
+ ```bash
546
+ git add layers/structure/grid/app/composables/useGridTracks.ts \
547
+ layers/structure/grid/app/composables/useGridTracks.test.ts
548
+ git commit -m "feat(grid): add useGridTracks composable (resolve, toColumnsCss)"
549
+ ```
550
+
551
+ ---
552
+
553
+ ### Task 4: Placement utils
554
+
555
+ **Files:**
556
+
557
+ - Create: `layers/structure/grid/app/utils/placement.ts`
558
+ - Test: `layers/structure/grid/app/utils/placement.test.ts`
559
+
560
+ **Interfaces:**
561
+
562
+ - Consumes: nothing (pure string functions, no type imports needed).
563
+ - Produces: `placementFromLines(startLine: string, endLine: string): string`,
564
+ `placementFromIndex(colStart: number, colSpan: number | 'full'): string` — used by Task 7's
565
+ builder page preview cells (named-line path) and available as the numeric fallback for future
566
+ `layout` migration (not consumed anywhere else in this plan).
567
+
568
+ - [ ] **Step 1: Write the failing tests**
569
+
570
+ ```ts
571
+ // layers/structure/grid/app/utils/placement.test.ts
572
+ import { describe, expect, it } from 'vitest'
573
+
574
+ import { placementFromIndex, placementFromLines } from './placement'
575
+
576
+ describe('placementFromLines', () => {
577
+ it('joins two named lines with a slash', () => {
578
+ expect(placementFromLines('feature-start', 'aside-end')).toBe('feature-start / aside-end')
579
+ })
580
+ })
581
+
582
+ describe('placementFromIndex', () => {
583
+ it('builds a numeric span from colStart and colSpan', () => {
584
+ expect(placementFromIndex(2, 3)).toBe('2 / span 3')
585
+ })
586
+
587
+ it('spans to the last line when colSpan is "full"', () => {
588
+ expect(placementFromIndex(4, 'full')).toBe('4 / -1')
589
+ })
590
+ })
591
+ ```
592
+
593
+ - [ ] **Step 2: Run tests to verify they fail**
594
+
595
+ Run: `pnpm vitest run layers/structure/grid/app/utils/placement.test.ts`
596
+ Expected: FAIL — cannot find module `./placement`
597
+
598
+ - [ ] **Step 3: Write `app/utils/placement.ts`**
599
+
600
+ ```ts
601
+ /** Grid-column value addressing a named-line range. Primary placement method — named
602
+ * lines survive CSS subgrid boundaries, unlike grid-template-areas. */
603
+ export function placementFromLines(startLine: string, endLine: string): string {
604
+ return `${startLine} / ${endLine}`
605
+ }
606
+
607
+ /** Numeric fallback for auto-flowing content with no named slot to target. `'full'`
608
+ * spans to the grid's last line (-1), matching the shape of layout's current
609
+ * GridItem colSpan prop for an additive future migration. */
610
+ export function placementFromIndex(colStart: number, colSpan: number | 'full'): string {
611
+ if (colSpan === 'full') {
612
+ return `${colStart} / -1`
613
+ }
614
+ return `${colStart} / span ${colSpan}`
615
+ }
616
+ ```
617
+
618
+ - [ ] **Step 4: Run tests to verify they pass**
619
+
620
+ Run: `pnpm vitest run layers/structure/grid/app/utils/placement.test.ts`
621
+ Expected: PASS (3 tests)
622
+
623
+ - [ ] **Step 5: Commit**
624
+
625
+ ```bash
626
+ git add layers/structure/grid/app/utils/placement.ts \
627
+ layers/structure/grid/app/utils/placement.test.ts
628
+ git commit -m "feat(grid): add placement utils (named-line and numeric fallback)"
629
+ ```
630
+
631
+ ---
632
+
633
+ ### Task 5: Preset registry (`app.config.ts`)
634
+
635
+ **Files:**
636
+
637
+ - Create: `layers/structure/grid/app/app.config.ts`
638
+
639
+ **Interfaces:**
640
+
641
+ - Consumes: `GridPreset` from `./types/tracks` (Task 1).
642
+ - Produces: `gridLayer.presets.swiss` and `gridLayer.presets.editorial`, read by
643
+ `useGridTracks()` (Task 3) via `useAppConfig()`. Task 7's builder page uses `resolve('swiss')`
644
+ and `resolve('editorial')` to render the two known-shape previews mentioned in the spec's
645
+ testing section.
646
+
647
+ - [ ] **Step 1: Write `app/app.config.ts`**
648
+
649
+ No unit test for this file — it's static data plus a type augmentation, and its correctness is
650
+ exercised end to end by Task 7 (visually rendering both presets) per the spec's own testing
651
+ plan, which explicitly scopes preset verification to that visual check rather than a unit test.
652
+
653
+ ```ts
654
+ import type { GridPreset } from './types/tracks'
655
+
656
+ const SWISS_COLUMNS = Array.from({ length: 18 }, () => ({ size: 1 }))
657
+
658
+ export default defineAppConfig({
659
+ gridLayer: {
660
+ presets: {
661
+ swiss: {
662
+ name: 'swiss',
663
+ columns: SWISS_COLUMNS,
664
+ },
665
+ editorial: {
666
+ name: 'editorial',
667
+ columns: [
668
+ { size: 2, lineStart: 'feature-start', lineEnd: 'feature-end' },
669
+ { size: 1, lineStart: 'aside-start', lineEnd: 'aside-end' },
670
+ ],
671
+ },
672
+ },
673
+ },
674
+ })
675
+
676
+ declare module '@nuxt/schema' {
677
+ interface AppConfigInput {
678
+ gridLayer?: {
679
+ presets?: Record<string, GridPreset>
680
+ }
681
+ }
682
+ }
683
+ ```
684
+
685
+ - [ ] **Step 2: Verify the shape matches the tested `toColumnsCss` behavior**
686
+
687
+ Run: `pnpm vitest run layers/structure/grid/app/composables/useGridTracks.test.ts`
688
+ Expected: PASS (still 10 tests — this step is a regression check, not new coverage; the
689
+ "mixed sizes" and "merges an adjacent lineEnd and lineStart" test cases in Task 3 already cover
690
+ the exact shapes used here for `swiss` and `editorial`)
691
+
692
+ - [ ] **Step 3: Commit**
693
+
694
+ ```bash
695
+ git add layers/structure/grid/app/app.config.ts
696
+ git commit -m "feat(grid): add swiss and editorial preset registry"
697
+ ```
698
+
699
+ ---
700
+
701
+ ### Task 6: Register `grid` in the playground layer resolver
702
+
703
+ **Files:**
704
+
705
+ - Modify: `apps/playground/nuxt.config.ts:2-95`
706
+
707
+ **Interfaces:**
708
+
709
+ - Consumes: nothing new — this task only wires the layer path into the existing
710
+ `AVAILABLE_LAYERS`/`LAYER_PATHS`/`LAYER_DEPENDENCIES` resolver so
711
+ `PLAYGROUND_LAYERS=core,grid pnpm dev` (Task 7's manual verification) can load it.
712
+ - Produces: nothing new for later tasks to consume — this is pure registration.
713
+
714
+ - [ ] **Step 1: Add `'grid'` to `AVAILABLE_LAYERS`**
715
+
716
+ In `apps/playground/nuxt.config.ts`, add `'grid'` to the `AVAILABLE_LAYERS` array (alongside
717
+ `'layout'`, since it's the same tier):
718
+
719
+ ```ts
720
+ const AVAILABLE_LAYERS = [
721
+ 'core',
722
+ 'seo',
723
+ 'scripts',
724
+ 'element',
725
+ 'typography',
726
+ 'navigation',
727
+ 'visual',
728
+ 'layout',
729
+ 'grid',
730
+ 'scroll',
731
+ // ...unchanged rest
732
+ ] as const
733
+ ```
734
+
735
+ - [ ] **Step 2: Add the path to `LAYER_PATHS`**
736
+
737
+ ```ts
738
+ const LAYER_PATHS: Record<LayerName, string> = {
739
+ // ...unchanged entries
740
+ layout: '../../layers/structure/layout',
741
+ grid: '../../layers/structure/grid',
742
+ // ...unchanged rest
743
+ }
744
+ ```
745
+
746
+ - [ ] **Step 3: Add the dependency entry to `LAYER_DEPENDENCIES`**
747
+
748
+ `grid` depends only on `core`, same as `layout`:
749
+
750
+ ```ts
751
+ const LAYER_DEPENDENCIES: Record<LayerName, LayerName[]> = {
752
+ // ...unchanged entries
753
+ layout: ['core'],
754
+ grid: ['core'],
755
+ // ...unchanged rest
756
+ }
757
+ ```
758
+
759
+ - [ ] **Step 4: Verify the registration typechecks**
760
+
761
+ Run: `pnpm --filter kmcom-playground typecheck`
762
+ Expected: no new errors (the `LayerName` union, `Record` types, and `resolveExtendedLayers()`
763
+ all derive from `AVAILABLE_LAYERS`, so a missing `LAYER_PATHS`/`LAYER_DEPENDENCIES` entry for
764
+ `'grid'` would be a TS error here — this is the automated check standing in for a runtime test,
765
+ since layer registration has no unit-testable behavior of its own)
766
+
767
+ - [ ] **Step 5: Verify the layer loads at dev time**
768
+
769
+ Run: `PLAYGROUND_LAYERS=core,grid pnpm dev` (from `apps/playground/`), then stop it once the
770
+ dev server prints its ready message with no errors — full page verification happens in Task 7
771
+ once there's a page to load.
772
+ Expected: dev server starts cleanly, no "layer not found" or CSS resolution errors in the
773
+ console.
774
+
775
+ - [ ] **Step 6: Commit**
776
+
777
+ ```bash
778
+ git add apps/playground/nuxt.config.ts
779
+ git commit -m "feat(grid): register grid layer in playground resolver"
780
+ ```
781
+
782
+ ---
783
+
784
+ ### Task 7: Playground visual builder (`/grid-builder`)
785
+
786
+ **Files:**
787
+
788
+ - Create: `apps/playground/app/pages/grid-builder.vue`
789
+
790
+ **Interfaces:**
791
+
792
+ - Consumes: `useGridTracks()` (Task 3, `resolve`/`toColumnsCss`), `TrackSegment`/`TrackConfig`
793
+ types (Task 1), `.grid-root` CSS class (Task 2), `gridLayer.presets` (Task 5), the `grid`
794
+ layer registration (Task 6).
795
+ - Produces: nothing further downstream — this is the terminal consumer and the spec's
796
+ manual/visual verification point.
797
+
798
+ - [ ] **Step 1: Write `apps/playground/app/pages/grid-builder.vue`**
799
+
800
+ Dev-only page: add/remove/resize `TrackSegment`s (no drag library — up/down reorder buttons,
801
+ per YAGNI, since drag-and-drop is a UX nicety the spec doesn't require), a live `.grid-root`
802
+ preview with placeholder cells, and a copyable TS output panel. No persistence, no
803
+ save-to-registry — copy/paste is the hand-off, matching the spec's scope.
804
+
805
+ ```vue
806
+ <script setup lang="ts">
807
+ import type { TrackConfig, TrackSegment } from '#layers/grid/types/tracks'
808
+
809
+ definePageMeta({ layout: false })
810
+
811
+ const { resolve, toColumnsCss } = useGridTracks()
812
+
813
+ const activePresetName = ref<'swiss' | 'editorial' | 'custom'>('custom')
814
+ const customSegments = ref<TrackSegment[]>([{ size: 1 }, { size: 1 }, { size: 2 }])
815
+
816
+ const activeConfig = computed<TrackConfig>(() => {
817
+ if (activePresetName.value === 'custom') {
818
+ return { columns: customSegments.value }
819
+ }
820
+ return resolve(activePresetName.value)
821
+ })
822
+
823
+ const columnsCss = computed(() => toColumnsCss(activeConfig.value))
824
+
825
+ const isCustom = computed(() => activePresetName.value === 'custom')
826
+
827
+ function addSegment() {
828
+ customSegments.value.push({ size: 1 })
829
+ }
830
+
831
+ function removeSegment(index: number) {
832
+ customSegments.value.splice(index, 1)
833
+ }
834
+
835
+ function moveSegment(index: number, direction: -1 | 1) {
836
+ const target = index + direction
837
+ if (target < 0 || target >= customSegments.value.length) return
838
+ const segments = customSegments.value
839
+ ;[segments[index], segments[target]] = [segments[target], segments[index]]
840
+ }
841
+
842
+ function updateSize(index: number, value: number) {
843
+ customSegments.value[index].size = Math.max(1, value)
844
+ }
845
+
846
+ function updateLineStart(index: number, value: string) {
847
+ customSegments.value[index].lineStart = value || undefined
848
+ }
849
+
850
+ function updateLineEnd(index: number, value: string) {
851
+ customSegments.value[index].lineEnd = value || undefined
852
+ }
853
+
854
+ const outputCode = computed(() => {
855
+ const lines = customSegments.value.map((segment) => {
856
+ const parts = [`size: ${segment.size}`]
857
+ if (segment.lineStart) parts.push(`lineStart: '${segment.lineStart}'`)
858
+ if (segment.lineEnd) parts.push(`lineEnd: '${segment.lineEnd}'`)
859
+ return ` { ${parts.join(', ')} },`
860
+ })
861
+ return `{\n columns: [\n${lines.join('\n')}\n ],\n}`
862
+ })
863
+ </script>
864
+
865
+ <template>
866
+ <div style="padding: 2rem; display: grid; gap: 2rem">
867
+ <h1>Grid builder</h1>
868
+
869
+ <div style="display: flex; gap: 0.5rem">
870
+ <button type="button" @click="activePresetName = 'swiss'">Swiss (18 equal)</button>
871
+ <button type="button" @click="activePresetName = 'editorial'">Editorial</button>
872
+ <button type="button" @click="activePresetName = 'custom'">Custom</button>
873
+ </div>
874
+
875
+ <section v-if="isCustom" style="display: grid; gap: 0.5rem">
876
+ <div
877
+ v-for="(segment, index) in customSegments"
878
+ :key="index"
879
+ style="display: flex; gap: 0.5rem; align-items: center"
880
+ >
881
+ <span>#{{ index + 1 }}</span>
882
+ <label>
883
+ size
884
+ <input
885
+ type="number"
886
+ min="1"
887
+ :value="segment.size"
888
+ @input="updateSize(index, Number(($event.target as HTMLInputElement).value))"
889
+ />
890
+ </label>
891
+ <label>
892
+ lineStart
893
+ <input
894
+ type="text"
895
+ :value="segment.lineStart ?? ''"
896
+ @input="updateLineStart(index, ($event.target as HTMLInputElement).value)"
897
+ />
898
+ </label>
899
+ <label>
900
+ lineEnd
901
+ <input
902
+ type="text"
903
+ :value="segment.lineEnd ?? ''"
904
+ @input="updateLineEnd(index, ($event.target as HTMLInputElement).value)"
905
+ />
906
+ </label>
907
+ <button type="button" @click="moveSegment(index, -1)">↑</button>
908
+ <button type="button" @click="moveSegment(index, 1)">↓</button>
909
+ <button type="button" @click="removeSegment(index)">Remove</button>
910
+ </div>
911
+ <button type="button" @click="addSegment">Add segment</button>
912
+ </section>
913
+
914
+ <section>
915
+ <h2>Preview</h2>
916
+ <div class="grid-root" :style="{ gridTemplateColumns: columnsCss }">
917
+ <div
918
+ v-for="(segment, index) in activeConfig.columns"
919
+ :key="index"
920
+ style="border: 1px solid currentColor; padding: 0.5rem; text-align: center"
921
+ >
922
+ {{ segment.size }}fr
923
+ </div>
924
+ </div>
925
+ </section>
926
+
927
+ <section v-if="isCustom">
928
+ <h2>Output — paste into app.config.ts as a new preset</h2>
929
+ <pre><code>{{ outputCode }}</code></pre>
930
+ </section>
931
+ </div>
932
+ </template>
933
+ ```
934
+
935
+ - [ ] **Step 2: Run typecheck**
936
+
937
+ Run: `pnpm --filter kmcom-playground typecheck`
938
+ Expected: no errors
939
+
940
+ - [ ] **Step 3: Manual visual verification — the three known shapes from the spec's testing plan**
941
+
942
+ Run: `PLAYGROUND_LAYERS=core,grid pnpm dev` (from `apps/playground/`), open
943
+ `http://localhost:3000/grid-builder`.
944
+
945
+ Expected, checked by eye:
946
+
947
+ 1. Click "Swiss (18 equal)" — 18 equal-width preview cells render, all the same width.
948
+ 2. Click "Editorial" — 2 preview cells render, the first roughly twice the width of the second.
949
+ 3. Click "Custom", adjust segment sizes/add a segment (e.g. the 8-equal + double + triple shape
950
+ from the spec) — proportions in the preview visibly match the configured sizes, and the
951
+ output panel shows valid-looking TS matching the current segments.
952
+
953
+ - [ ] **Step 4: Commit**
954
+
955
+ ```bash
956
+ git add apps/playground/app/pages/grid-builder.vue
957
+ git commit -m "feat(grid): add playground visual grid builder"
958
+ ```
959
+
960
+ ---
961
+
962
+ ## Plan Self-Review Notes
963
+
964
+ - **Spec coverage:** rhythm CSS (Task 2), track types (Task 1), presets registry (Task 5),
965
+ `useGridTracks()`/`resolve`/`toColumnsCss` (Task 3), placement utils (Task 4), visual builder
966
+ (Task 7) — all spec sections have a task. Out-of-scope items (layout rework, row presets,
967
+ save-to-registry, Bento preset) are called out in Global Constraints and not implemented.
968
+ - **`toColumnsCss` example correction:** the spec's inline example string
969
+ (`'minmax(min-content, [feature-start] 2fr [feature-end aside-start] 1fr [aside-end])'`) is
970
+ not valid `grid-template-columns` syntax (a single `minmax()` can't wrap multiple tracks).
971
+ This plan implements the spec's own prose description instead — "each segment's
972
+ lineStart/lineEnd become bracketed line names positioned around its fr value, per standard
973
+ named-grid-line syntax" — which Task 3's tests encode as one `minmax(floor, Nfr)` per segment
974
+ with brackets between them. Flagged here rather than silently deviating.
975
+ - **Type consistency:** `TrackSegment`/`TrackConfig`/`GridPreset` (Task 1) are used identically
976
+ in Task 3's function signatures, Task 5's `app.config.ts`, and Task 7's builder page — no
977
+ renames across tasks.