@donotdev/ui 0.0.8 → 0.0.10

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 (194) hide show
  1. package/dist/components/auth/AuthHeader.d.ts +1 -1
  2. package/dist/components/auth/AuthHeader.d.ts.map +1 -1
  3. package/dist/components/auth/AuthMenu.d.ts +2 -1
  4. package/dist/components/auth/AuthMenu.d.ts.map +1 -1
  5. package/dist/components/auth/AuthMenu.js +1 -1
  6. package/dist/components/common/AppLoading.d.ts +1 -1
  7. package/dist/components/common/AppLoading.d.ts.map +1 -1
  8. package/dist/components/common/AppLoading.js +0 -1
  9. package/dist/components/common/Loader.d.ts +4 -4
  10. package/dist/components/common/Loader.d.ts.map +1 -1
  11. package/dist/components/common/Loader.js +11 -12
  12. package/dist/components/common/LoadingMessage.d.ts +1 -9
  13. package/dist/components/common/LoadingMessage.d.ts.map +1 -1
  14. package/dist/components/common/LoadingMessage.js +0 -1
  15. package/dist/components/common/LoadingScreen.d.ts +1 -9
  16. package/dist/components/common/LoadingScreen.d.ts.map +1 -1
  17. package/dist/components/common/LoadingScreen.js +0 -1
  18. package/dist/components/common/RedirectOverlay.js +1 -1
  19. package/dist/components/common/TechBento.d.ts.map +1 -1
  20. package/dist/components/common/TechBento.js +1 -0
  21. package/dist/components/layout/components/FloatingLanguageSwitcher.d.ts +1 -9
  22. package/dist/components/layout/components/FloatingLanguageSwitcher.d.ts.map +1 -1
  23. package/dist/components/layout/components/FloatingLanguageSwitcher.js +0 -1
  24. package/dist/components/layout/components/header/CacheSettings.d.ts.map +1 -1
  25. package/dist/components/layout/components/header/HeaderMenu.d.ts.map +1 -1
  26. package/dist/components/layout/components/header/SettingsMenu.d.ts.map +1 -1
  27. package/dist/components/layout/components/header/SettingsMenu.js +0 -1
  28. package/dist/components/layout/components/header/ThemeToggle.d.ts +1 -1
  29. package/dist/components/layout/components/header/ThemeToggle.d.ts.map +1 -1
  30. package/dist/components/layout/components/header/ThemeToggle.js +5 -4
  31. package/dist/crud/components/DisplayFieldRenderer.d.ts +3 -11
  32. package/dist/crud/components/DisplayFieldRenderer.d.ts.map +1 -1
  33. package/dist/crud/components/DisplayFieldRenderer.js +3 -2
  34. package/dist/crud/components/EntityDisplayRenderer.d.ts +2 -2
  35. package/dist/crud/components/fields/display/AvatarFieldDisplay.d.ts +2 -2
  36. package/dist/crud/components/fields/display/BadgeFieldDisplay.d.ts +2 -2
  37. package/dist/crud/components/fields/display/ButtonFieldDisplay.d.ts +2 -2
  38. package/dist/crud/components/fields/display/CheckboxFieldDisplay.d.ts +2 -2
  39. package/dist/crud/components/fields/display/DateFieldDisplay.d.ts +3 -11
  40. package/dist/crud/components/fields/display/DateFieldDisplay.d.ts.map +1 -1
  41. package/dist/crud/components/fields/display/DateFieldDisplay.js +2 -4
  42. package/dist/crud/components/fields/display/DropdownDisplay.d.ts +2 -2
  43. package/dist/crud/components/fields/display/FileFieldDisplay.d.ts +2 -2
  44. package/dist/crud/components/fields/display/GeoPointFieldDisplay.d.ts +3 -11
  45. package/dist/crud/components/fields/display/GeoPointFieldDisplay.d.ts.map +1 -1
  46. package/dist/crud/components/fields/display/GeoPointFieldDisplay.js +0 -1
  47. package/dist/crud/components/fields/display/HiddenFieldDisplay.d.ts +3 -3
  48. package/dist/crud/components/fields/display/HiddenFieldDisplay.d.ts.map +1 -1
  49. package/dist/crud/components/fields/display/HiddenFieldDisplay.js +0 -9
  50. package/dist/crud/components/fields/display/ImageFieldDisplay.d.ts +3 -11
  51. package/dist/crud/components/fields/display/ImageFieldDisplay.d.ts.map +1 -1
  52. package/dist/crud/components/fields/display/ImageFieldDisplay.js +0 -1
  53. package/dist/crud/components/fields/display/LinkFieldDisplay.d.ts +3 -11
  54. package/dist/crud/components/fields/display/LinkFieldDisplay.d.ts.map +1 -1
  55. package/dist/crud/components/fields/display/LinkFieldDisplay.js +6 -6
  56. package/dist/crud/components/fields/display/MapFieldDisplay.d.ts +3 -11
  57. package/dist/crud/components/fields/display/MapFieldDisplay.d.ts.map +1 -1
  58. package/dist/crud/components/fields/display/MapFieldDisplay.js +0 -1
  59. package/dist/crud/components/fields/display/MultiDropdownDisplay.d.ts +3 -11
  60. package/dist/crud/components/fields/display/MultiDropdownDisplay.d.ts.map +1 -1
  61. package/dist/crud/components/fields/display/MultiDropdownDisplay.js +0 -1
  62. package/dist/crud/components/fields/display/MultiInputTextFieldDisplay.d.ts +3 -11
  63. package/dist/crud/components/fields/display/MultiInputTextFieldDisplay.d.ts.map +1 -1
  64. package/dist/crud/components/fields/display/MultiInputTextFieldDisplay.js +0 -1
  65. package/dist/crud/components/fields/display/NumberFieldDisplay.d.ts +3 -11
  66. package/dist/crud/components/fields/display/NumberFieldDisplay.d.ts.map +1 -1
  67. package/dist/crud/components/fields/display/NumberFieldDisplay.js +2 -4
  68. package/dist/crud/components/fields/display/PasswordFieldDisplay.d.ts +3 -3
  69. package/dist/crud/components/fields/display/PasswordFieldDisplay.d.ts.map +1 -1
  70. package/dist/crud/components/fields/display/PasswordFieldDisplay.js +0 -1
  71. package/dist/crud/components/fields/display/PhoneNumberDisplay.d.ts +3 -11
  72. package/dist/crud/components/fields/display/PhoneNumberDisplay.d.ts.map +1 -1
  73. package/dist/crud/components/fields/display/PhoneNumberDisplay.js +1 -3
  74. package/dist/crud/components/fields/display/RadioFieldDisplay.d.ts +3 -11
  75. package/dist/crud/components/fields/display/RadioFieldDisplay.d.ts.map +1 -1
  76. package/dist/crud/components/fields/display/RadioFieldDisplay.js +0 -1
  77. package/dist/crud/components/fields/display/RangeFieldDisplay.d.ts +3 -11
  78. package/dist/crud/components/fields/display/RangeFieldDisplay.d.ts.map +1 -1
  79. package/dist/crud/components/fields/display/RangeFieldDisplay.js +0 -1
  80. package/dist/crud/components/fields/display/ReferenceFieldDisplay.d.ts +3 -11
  81. package/dist/crud/components/fields/display/ReferenceFieldDisplay.d.ts.map +1 -1
  82. package/dist/crud/components/fields/display/ReferenceFieldDisplay.js +0 -1
  83. package/dist/crud/components/fields/display/RichTextDisplay.d.ts +25 -0
  84. package/dist/crud/components/fields/display/RichTextDisplay.d.ts.map +1 -0
  85. package/dist/crud/components/fields/display/RichTextDisplay.js +104 -0
  86. package/dist/crud/components/fields/display/TextAreaDisplay.d.ts +3 -11
  87. package/dist/crud/components/fields/display/TextAreaDisplay.d.ts.map +1 -1
  88. package/dist/crud/components/fields/display/TextAreaDisplay.js +0 -1
  89. package/dist/crud/components/fields/display/TextFieldDisplay.d.ts +2 -2
  90. package/dist/crud/components/fields/display/TimestampFieldDisplay.d.ts +3 -11
  91. package/dist/crud/components/fields/display/TimestampFieldDisplay.d.ts.map +1 -1
  92. package/dist/crud/components/fields/display/TimestampFieldDisplay.js +0 -1
  93. package/dist/crud/components/fields/display/index.d.ts +1 -0
  94. package/dist/crud/components/fields/display/index.d.ts.map +1 -1
  95. package/dist/crud/components/fields/display/index.js +1 -0
  96. package/dist/dndev.css +618 -156
  97. package/dist/index.js +64 -4
  98. package/dist/internal/common/ErrorFallback.d.ts +1 -10
  99. package/dist/internal/common/ErrorFallback.d.ts.map +1 -1
  100. package/dist/internal/common/GlobalErrorFallback.d.ts +1 -9
  101. package/dist/internal/common/GlobalErrorFallback.d.ts.map +1 -1
  102. package/dist/internal/common/RouteErrorFallback.d.ts.map +1 -1
  103. package/dist/internal/common/RouteErrorFallback.js +2 -3
  104. package/dist/internal/devtools/components/DebugDialog.d.ts.map +1 -1
  105. package/dist/internal/devtools/components/DebugDialog.js +3 -1
  106. package/dist/internal/devtools/components/MaskedValue.d.ts.map +1 -1
  107. package/dist/internal/devtools/components/MaskedValue.js +1 -1
  108. package/dist/internal/devtools/components/StoresTab.js +1 -1
  109. package/dist/internal/initializers/BaseStoresInitializer.d.ts.map +1 -1
  110. package/dist/internal/initializers/BaseStoresInitializer.js +1 -2
  111. package/dist/internal/initializers/NextJsStoresInitializer.d.ts.map +1 -1
  112. package/dist/internal/layout/DnDevLayout.d.ts.map +1 -1
  113. package/dist/internal/layout/DnDevLayout.js +6 -6
  114. package/dist/internal/layout/components/AutoMetaTags.d.ts.map +1 -1
  115. package/dist/internal/layout/components/footer/FooterBranding.d.ts +0 -2
  116. package/dist/internal/layout/components/footer/FooterBranding.d.ts.map +1 -1
  117. package/dist/internal/layout/components/footer/FooterBranding.js +2 -6
  118. package/dist/internal/layout/components/footer/FooterCopyright.d.ts +0 -2
  119. package/dist/internal/layout/components/footer/FooterCopyright.d.ts.map +1 -1
  120. package/dist/internal/layout/components/footer/FooterCopyright.js +2 -6
  121. package/dist/internal/layout/components/footer/FooterLegalLinks.js +2 -2
  122. package/dist/internal/layout/config/defaults.d.ts +0 -10
  123. package/dist/internal/layout/config/defaults.d.ts.map +1 -1
  124. package/dist/internal/layout/config/defaults.js +12 -1
  125. package/dist/internal/layout/config/presets/admin.d.ts.map +1 -1
  126. package/dist/internal/layout/config/presets/admin.js +7 -2
  127. package/dist/internal/layout/config/presets/blog.d.ts.map +1 -1
  128. package/dist/internal/layout/config/presets/blog.js +7 -1
  129. package/dist/internal/layout/config/presets/docs.d.ts.map +1 -1
  130. package/dist/internal/layout/config/presets/docs.js +7 -5
  131. package/dist/internal/layout/config/presets/game.d.ts.map +1 -1
  132. package/dist/internal/layout/config/presets/game.js +7 -2
  133. package/dist/internal/layout/config/presets/moolti.d.ts.map +1 -1
  134. package/dist/internal/layout/config/presets/moolti.js +11 -4
  135. package/dist/internal/layout/zones/DnDevFooter.d.ts +1 -13
  136. package/dist/internal/layout/zones/DnDevFooter.d.ts.map +1 -1
  137. package/dist/internal/layout/zones/DnDevFooter.js +2 -2
  138. package/dist/internal/layout/zones/DnDevHeader.d.ts +1 -14
  139. package/dist/internal/layout/zones/DnDevHeader.d.ts.map +1 -1
  140. package/dist/internal/layout/zones/DnDevMergedBar.d.ts +2 -14
  141. package/dist/internal/layout/zones/DnDevMergedBar.d.ts.map +1 -1
  142. package/dist/internal/layout/zones/DnDevMergedBar.js +11 -3
  143. package/dist/internal/layout/zones/DnDevSidebar.d.ts +1 -14
  144. package/dist/internal/layout/zones/DnDevSidebar.d.ts.map +1 -1
  145. package/dist/routing/AuthGuard.d.ts.map +1 -1
  146. package/dist/routing/GoTo.d.ts +3 -1
  147. package/dist/routing/GoTo.d.ts.map +1 -1
  148. package/dist/routing/GoTo.js +6 -2
  149. package/dist/routing/GoToDialog.d.ts +1 -1
  150. package/dist/routing/GoToDialog.d.ts.map +1 -1
  151. package/dist/routing/GoToDialog.js +3 -5
  152. package/dist/routing/NavigationItem.d.ts +1 -1
  153. package/dist/routing/NavigationItem.d.ts.map +1 -1
  154. package/dist/routing/NavigationItem.js +0 -1
  155. package/dist/routing/hooks/hooks.next.js +1 -1
  156. package/dist/routing/hooks/hooks.vite.js +1 -1
  157. package/dist/routing/hooks/useFormNavigationBlocker.d.ts +14 -0
  158. package/dist/routing/hooks/useFormNavigationBlocker.d.ts.map +1 -0
  159. package/dist/routing/hooks/useFormNavigationBlocker.js +42 -0
  160. package/dist/routing/hooks/useNavigate.next.d.ts +1 -1
  161. package/dist/routing/hooks/useNavigate.next.d.ts.map +1 -1
  162. package/dist/routing/hooks/useNavigate.next.js +8 -2
  163. package/dist/routing/hooks/useNavigate.vite.d.ts +1 -1
  164. package/dist/routing/hooks/useNavigate.vite.d.ts.map +1 -1
  165. package/dist/routing/hooks/useNavigate.vite.js +7 -1
  166. package/dist/routing/useGoTo.d.ts.map +1 -1
  167. package/dist/styles/index.css +618 -156
  168. package/dist/utils/assetResolver.d.ts +1 -1
  169. package/dist/utils/assetResolver.d.ts.map +1 -1
  170. package/dist/utils/assetResolver.js +1 -2
  171. package/dist/utils/index.d.ts +1 -1
  172. package/dist/utils/index.d.ts.map +1 -1
  173. package/dist/utils/index.js +1 -1
  174. package/dist/utils/tList.d.ts +1 -1
  175. package/dist/utils/tList.d.ts.map +1 -1
  176. package/dist/utils/useAuthSafe.d.ts +0 -33
  177. package/dist/utils/useAuthSafe.d.ts.map +1 -1
  178. package/dist/utils/useAuthSafe.js +34 -1
  179. package/dist/utils/useCrudSafe.d.ts +12 -6
  180. package/dist/utils/useCrudSafe.d.ts.map +1 -1
  181. package/dist/utils/useCrudSafe.js +9 -6
  182. package/dist/utils/useFormStoreSafe.d.ts +59 -0
  183. package/dist/utils/useFormStoreSafe.d.ts.map +1 -0
  184. package/dist/utils/useFormStoreSafe.js +115 -0
  185. package/dist/utils/useOAuthSafe.d.ts.map +1 -1
  186. package/dist/utils/useStripeBillingSafe.d.ts +1 -34
  187. package/dist/utils/useStripeBillingSafe.d.ts.map +1 -1
  188. package/dist/utils/useStripeBillingSafe.js +34 -1
  189. package/dist/vite-routing/AppRoutes.d.ts +1 -1
  190. package/dist/vite-routing/AppRoutes.d.ts.map +1 -1
  191. package/dist/vite-routing/AppRoutes.js +0 -1
  192. package/dist/vite-routing/RootLayout.d.ts.map +1 -1
  193. package/dist/vite-routing/RootLayout.js +3 -6
  194. package/package.json +5 -5
@@ -2209,6 +2209,20 @@ em {
2209
2209
  padding-inline-start: var(--gap-md);
2210
2210
  }
2211
2211
 
2212
+ /* Bare mode - no visual chrome, used inside FloatingLabel or custom wrappers */
2213
+
2214
+ [data-bare] {
2215
+ border: none !important;
2216
+ box-shadow: none !important;
2217
+ background: transparent !important;
2218
+ }
2219
+
2220
+ [data-bare]:hover,[data-bare]:focus,[data-bare]:focus-visible {
2221
+ border-color: transparent !important;
2222
+ box-shadow: none !important;
2223
+ outline: none !important;
2224
+ }
2225
+
2212
2226
  /* Password strength bar height override */
2213
2227
 
2214
2228
  .dndev-password-strength-bar {
@@ -2724,6 +2738,34 @@ em {
2724
2738
 
2725
2739
  /* Label styling moved to patterns.css (.dndev-interactive-label) */
2726
2740
 
2741
+ /* Loading state */
2742
+
2743
+ [data-loading] {
2744
+ cursor: wait;
2745
+ pointer-events: none;
2746
+ }
2747
+
2748
+ /* Button spinner - inherits size from button font-size */
2749
+
2750
+ .dndev-button-spinner {
2751
+ flex-shrink: 0;
2752
+ }
2753
+
2754
+ /* Progress ring for upload percentage */
2755
+
2756
+ .dndev-button-progress {
2757
+ display: inline-flex;
2758
+ align-items: center;
2759
+ justify-content: center;
2760
+ flex-shrink: 0;
2761
+ }
2762
+
2763
+ .dndev-progress-ring {
2764
+ width: 1em;
2765
+ height: 1em;
2766
+ transform: rotate(-90deg);
2767
+ }
2768
+
2727
2769
  /* packages/components/src/atomic/Calendar/Calendar.css */
2728
2770
 
2729
2771
  /**
@@ -3282,6 +3324,7 @@ em {
3282
3324
 
3283
3325
  .dndev-collapsible-content[data-state='open'] {
3284
3326
  animation: slideDown var(--dur-normal) var(--ease-in-out);
3327
+ overflow: visible; /* Allow dropdowns/overlays to escape when open */
3285
3328
  }
3286
3329
 
3287
3330
  .dndev-collapsible-content[data-state='closed'] {
@@ -4414,6 +4457,18 @@ em {
4414
4457
 
4415
4458
  /* packages/components/src/atomic/Input/Input.css */
4416
4459
 
4460
+ /* Hide number input spinners - cleaner UI for price/range inputs */
4461
+
4462
+ input[type='number']::-webkit-inner-spin-button,
4463
+ input[type='number']::-webkit-outer-spin-button {
4464
+ -webkit-appearance: none;
4465
+ margin: 0;
4466
+ }
4467
+
4468
+ input[type='number'] {
4469
+ -moz-appearance: textfield;
4470
+ }
4471
+
4417
4472
  /* Input with leading icon (search, etc.) */
4418
4473
 
4419
4474
  .dndev-input-with-leading-icon {
@@ -4612,47 +4667,79 @@ em {
4612
4667
  margin-inline-start: var(--gap-sm);
4613
4668
  }
4614
4669
 
4615
- /* Floating Label - positioned absolutely at top of input fields */
4670
+ /* Floating Fieldset - native border-cutting via legend */
4616
4671
 
4617
- .dndev-floating-label {
4618
- position: absolute;
4619
- inset-inline-start: var(--gap-md);
4620
- top: calc(-1 * var(--font-size-xs) / 2 - 1px);
4672
+ .dndev-floating-fieldset {
4673
+ position: relative;
4674
+ border: var(--border-hairline) solid var(--line-2);
4675
+ border-radius: var(--radius-interactive);
4676
+ margin: 0;
4677
+ padding: 0;
4678
+ background-color: transparent;
4679
+ transition: all var(--dur-normal) var(--ease-in-out);
4680
+ text-align: start;
4681
+ /* Flex-aware: allow fieldset to shrink in flex containers */
4682
+ min-width: 0;
4683
+ width: 100%;
4684
+ }
4685
+
4686
+ .dndev-floating-fieldset:hover {
4687
+ border-color: var(--ring);
4688
+ }
4689
+
4690
+ .dndev-floating-fieldset:focus-within {
4691
+ border-color: var(--ring);
4692
+ }
4693
+
4694
+ .dndev-floating-fieldset[data-disabled='true'] {
4695
+ opacity: var(--opacity-muted);
4696
+ cursor: not-allowed;
4697
+ }
4698
+
4699
+ /* Legend sits on border - browser natively cuts border */
4700
+
4701
+ .dndev-floating-legend {
4702
+ margin-inline-start: var(--gap-sm);
4703
+ padding: 0 var(--gap-sm);
4621
4704
  font-size: var(--font-size-xs);
4622
4705
  font-weight: 500;
4623
- pointer-events: none;
4624
- z-index: 1;
4625
- background-color: var(--background);
4626
- padding: 0 var(--gap-sm);
4627
4706
  line-height: 1;
4628
4707
  color: var(--foreground);
4708
+ /* Ellipsis by default */
4709
+ max-width: 100%;
4710
+ overflow: hidden;
4711
+ text-overflow: ellipsis;
4712
+ white-space: nowrap;
4629
4713
  }
4630
4714
 
4631
- /* Inherit background when inside floating containers (dropdowns, menus, popovers) */
4715
+ .dndev-floating-legend label {
4716
+ cursor: default;
4717
+ display: inline-flex;
4718
+ align-items: center;
4719
+ gap: var(--gap-tight);
4720
+ }
4632
4721
 
4633
- .dndev-floating .dndev-floating-label,
4634
- .dndev-menu-content .dndev-floating-label,
4635
- [class*='dndev-dropdown'] .dndev-floating-label,
4636
- [class*='dndev-navigation'] .dndev-floating-label {
4637
- background-color: var(--popover);
4638
- color: var(--popover-foreground);
4722
+ .dndev-floating-fieldset[data-disabled='true'] .dndev-floating-legend {
4723
+ color: var(--muted-foreground);
4639
4724
  }
4640
4725
 
4641
- /* When floating container has blank glow, use solid popover background */
4726
+ /* Disable truncation when explicitly set to false */
4642
4727
 
4643
- .dndev-floating[data-glow='blank'] .dndev-floating-label {
4644
- background-color: var(--popover);
4728
+ .dndev-floating-legend[data-truncate='false'] {
4729
+ max-width: none;
4730
+ overflow: visible;
4731
+ text-overflow: clip;
4732
+ white-space: normal;
4645
4733
  }
4646
4734
 
4647
- .dndev-floating-label[data-disabled='true'] {
4648
- color: var(--muted-foreground);
4649
- }
4735
+ /* Input inside fieldset uses bare mode via data-bare attribute (set by Input component) */
4650
4736
 
4651
- .dndev-floating-label[data-truncate='true'] {
4652
- max-width: calc(100% - var(--gap-md) * 2);
4653
- overflow: hidden;
4654
- text-overflow: ellipsis;
4655
- white-space: nowrap;
4737
+ /* This rule is kept for non-Input children that might need border removal */
4738
+
4739
+ .dndev-floating-fieldset > .dndev-input:not([data-bare]) {
4740
+ border: none;
4741
+ box-shadow: none;
4742
+ background: transparent;
4656
4743
  }
4657
4744
 
4658
4745
  /* packages/components/src/atomic/List/List.css */
@@ -5003,11 +5090,33 @@ em {
5003
5090
  /* packages/components/src/atomic/Pagination/Pagination.css */
5004
5091
 
5005
5092
  .dndev-pagination {
5093
+ display: flex;
5094
+ flex-direction: row;
5095
+ align-items: center;
5096
+ justify-content: space-between;
5097
+ gap: var(--gap-md);
5098
+ width: 100%;
5099
+ }
5100
+
5101
+ .dndev-pagination-info {
5102
+ display: none;
5103
+ }
5104
+
5105
+ .dndev-pagination-size {
5106
+ display: flex;
5107
+ align-items: center;
5108
+ }
5109
+
5110
+ .dndev-pagination-size-label {
5111
+ display: none;
5112
+ }
5113
+
5114
+ .dndev-pagination-nav {
5006
5115
  display: flex;
5007
5116
  align-items: center;
5008
5117
  justify-content: center;
5009
5118
  gap: var(--gap-sm);
5010
- flex-wrap: wrap;
5119
+ width: 100%;
5011
5120
  }
5012
5121
 
5013
5122
  .dndev-pagination-list {
@@ -5019,57 +5128,36 @@ em {
5019
5128
  margin: 0;
5020
5129
  }
5021
5130
 
5022
- .dndev-pagination-item {
5023
- display: flex;
5024
- align-items: center;
5025
- justify-content: center;
5026
- }
5027
-
5028
5131
  .dndev-pagination-button {
5029
- min-width: var(--touch-target);
5132
+ width: var(--touch-target);
5030
5133
  height: var(--touch-target);
5031
- display: flex;
5134
+ padding: 0;
5135
+ flex-shrink: 0;
5136
+ display: inline-flex;
5032
5137
  align-items: center;
5033
5138
  justify-content: center;
5034
- gap: var(--gap-sm);
5035
- border-radius: var(--radius-interactive);
5036
- font-weight: 500;
5037
- transition: var(--transition-fast);
5038
- cursor: pointer;
5039
- border: var(--border-hairline) solid var(--line-2);
5040
- background: transparent;
5041
- color: var(--foreground);
5042
- padding: var(--gap-sm) var(--gap-md);
5043
5139
  }
5044
5140
 
5045
- .dndev-pagination-button:hover:not(:disabled) {
5046
- background: var(--accent);
5047
- color: var(--accent-foreground);
5048
- }
5141
+ /* Desktop: Show all elements in one row */
5049
5142
 
5050
- .dndev-pagination-button:focus-visible {
5051
- outline: 2px solid var(--ring);
5052
- outline-offset: 2px;
5143
+ @media (min-width: 768px) {
5144
+ .dndev-pagination-info,
5145
+ .dndev-pagination-size {
5146
+ display: flex;
5147
+ align-items: center;
5148
+ white-space: nowrap;
5053
5149
  }
5054
5150
 
5055
- .dndev-pagination-button:disabled {
5056
- opacity: var(--opacity-muted);
5057
- cursor: not-allowed;
5151
+ .dndev-pagination-size-label {
5152
+ margin-right: var(--gap-sm);
5058
5153
  }
5059
5154
 
5060
- .dndev-pagination-button[aria-current='page'] {
5061
- background: var(--primary);
5062
- color: var(--primary-foreground);
5063
- border-color: var(--primary);
5155
+ .dndev-pagination-nav {
5156
+ justify-content: flex-end;
5157
+ width: auto;
5158
+ margin-left: auto;
5159
+ /* Push to right */
5064
5160
  }
5065
-
5066
- .dndev-pagination-ellipsis {
5067
- display: flex;
5068
- align-items: center;
5069
- justify-content: center;
5070
- width: var(--touch-target);
5071
- height: var(--touch-target);
5072
- color: var(--muted-foreground);
5073
5161
  }
5074
5162
 
5075
5163
  /* packages/components/src/atomic/Popover/Popover.css */
@@ -5642,50 +5730,214 @@ em {
5642
5730
  display: flex;
5643
5731
  flex-direction: column;
5644
5732
  z-index: var(--z-modal);
5645
- border-radius: var(--radius-floating); /* Square like floating panels */
5733
+ background: var(--card);
5734
+ /* Ensure background is opaque */
5735
+ color: var(--card-foreground);
5736
+ box-shadow: var(--shadow-xl);
5737
+ /* Focus Tunnel: Deep elevation */
5738
+ overflow: hidden;
5739
+ /* Scroll Trap: Container clips overflow */
5740
+
5741
+ /* Motion Physics: Base state */
5742
+ will-change: transform, opacity;
5646
5743
 
5647
- /* Sheet positioning by side */
5744
+ /* Open state animation - "Heavy" ease for premium feel */
5648
5745
  }
5649
5746
 
5747
+ .dndev-sheet-content[data-state='open'] {
5748
+ animation: sheet-slide-in var(--dur-heavy) var(--ease-heavy);
5749
+ }
5750
+
5751
+ /* Closed state animation */
5752
+
5753
+ .dndev-sheet-content[data-state='closed'] {
5754
+ animation: sheet-slide-out var(--dur-normal) var(--ease-in-out);
5755
+ }
5756
+
5757
+ /* Sheet positioning by side - SPATIAL METAPHOR */
5758
+
5759
+ /* RIGHT / LEFT (Desktop Panels) */
5760
+
5650
5761
  .dndev-sheet-content[data-side='right'],.dndev-sheet-content[data-side='left'] {
5651
5762
  top: 0;
5652
5763
  bottom: 0;
5653
5764
  width: 80%;
5654
5765
  max-width: 56rem;
5766
+ /* Standard panel width */
5767
+ height: 100%;
5768
+ /* Full height */
5769
+ border-radius: 0;
5770
+ /* Square edges for panel metaphor */
5655
5771
  }
5656
5772
 
5657
5773
  .dndev-sheet-content[data-side='right'] {
5774
+ /* Physical positioning: right edge */
5658
5775
  right: 0;
5776
+ left: auto;
5777
+ /* Border on logical start (left in LTR, right in RTL) */
5778
+ border-inline-start: var(--border-hairline) solid var(--line-1);
5659
5779
  }
5660
5780
 
5661
5781
  .dndev-sheet-content[data-side='left'] {
5782
+ /* Physical positioning: left edge */
5662
5783
  left: 0;
5784
+ right: auto;
5785
+ /* Border on logical end (right in LTR, left in RTL) */
5786
+ border-inline-end: var(--border-hairline) solid var(--line-1);
5663
5787
  }
5664
5788
 
5789
+ /* TOP / BOTTOM (Mobile Cards) */
5790
+
5665
5791
  .dndev-sheet-content[data-side='top'],.dndev-sheet-content[data-side='bottom'] {
5666
5792
  left: 0;
5667
5793
  right: 0;
5668
- height: 80%;
5669
- max-height: 56rem;
5670
- overflow: hidden;
5794
+ /* Card metaphor: Detached from opposite edge */
5795
+ height: auto;
5796
+ max-height: 92dvh;
5797
+ /* Never touch top edge */
5798
+ width: 100%;
5799
+ margin-left: auto;
5800
+ margin-right: auto;
5801
+
5802
+ /* On larger screens, constrain width */
5803
+ }
5804
+
5805
+ @media (width >=768px) {
5806
+
5807
+ .dndev-sheet-content[data-side='top'],.dndev-sheet-content[data-side='bottom'] {
5808
+ max-width: 56rem;
5809
+ width: 90%;
5810
+ border-radius: var(--radius-lg);
5811
+ /* Fully rounded card on desktop */
5671
5812
  }
5813
+ }
5672
5814
 
5673
5815
  .dndev-sheet-content[data-side='top'] {
5674
5816
  top: 0;
5817
+ border-bottom: var(--border-hairline) solid var(--line-1);
5818
+ /* Rounded bottom corners only */
5819
+ border-bottom-left-radius: var(--radius-lg);
5820
+ border-bottom-right-radius: var(--radius-lg);
5675
5821
  }
5676
5822
 
5677
5823
  .dndev-sheet-content[data-side='bottom'] {
5678
5824
  bottom: 0;
5825
+ border-top: var(--border-hairline) solid var(--line-1);
5826
+ /* Rounded top corners only */
5827
+ border-top-left-radius: var(--radius-lg);
5828
+ border-top-right-radius: var(--radius-lg);
5679
5829
  }
5680
5830
 
5831
+ /* DRAG HANDLE PILL - Visual affordance for draggable sheets */
5832
+
5833
+ .dndev-sheet-drag-handle {
5834
+ width: 2.5rem;
5835
+ height: 0.25rem;
5836
+ background: var(--line-2);
5837
+ border-radius: var(--radius-full);
5838
+ margin: var(--gap-sm) auto 0;
5839
+ flex-shrink: 0;
5840
+ cursor: grab;
5841
+ transition: background-color var(--dur-fast) var(--ease-in-out);
5842
+ }
5843
+
5844
+ .dndev-sheet-drag-handle:active {
5845
+ cursor: grabbing;
5846
+ }
5847
+
5848
+ /* Positioning for bottom sheets */
5849
+
5850
+ .dndev-sheet-content[data-side='bottom'] > .dndev-sheet-drag-handle {
5851
+ margin-top: var(--gap-sm);
5852
+ margin-bottom: 0;
5853
+ }
5854
+
5855
+ /* Positioning for top sheets */
5856
+
5857
+ .dndev-sheet-content[data-side='top'] > .dndev-sheet-drag-handle {
5858
+ margin-top: max(var(--gap-sm), env(safe-area-inset-top));
5859
+ margin-bottom: 0;
5860
+ }
5861
+
5862
+ /* HEADER - Pinned, No Padding (Tight Layout) */
5863
+
5864
+ /* Industry standard: Title always on start, X always on end (consistent across all sides) */
5865
+
5681
5866
  .dndev-sheet-header {
5682
5867
  display: flex;
5683
5868
  align-items: center;
5684
5869
  justify-content: space-between;
5685
5870
  gap: var(--gap-md);
5686
5871
  flex-shrink: 0;
5872
+ /* Never shrink */
5687
5873
  min-height: var(--touch-target);
5688
- margin-bottom: var(--gap-md);
5874
+ /* No padding - tight layout: [ Title X ] */
5875
+ padding-block: 0;
5876
+ /* RTL-aware: padding on logical start only */
5877
+ padding-inline-start: var(--gap-md);
5878
+ padding-inline-end: 0; /* X button has its own spacing */
5879
+ border-bottom: var(--border-hairline) solid var(--line-1);
5880
+ /* Separator */
5881
+
5882
+ /* Thumb Ergonomics: Top Safe Area (only for top sheets) */
5883
+ }
5884
+
5885
+ .dndev-sheet-content[data-side='top'] .dndev-sheet-header {
5886
+ padding-top: max(0, env(safe-area-inset-top));
5887
+ }
5888
+
5889
+ /* Adjust header padding when drag handle is present (sibling selector) */
5890
+
5891
+ .dndev-sheet-content[data-side='bottom']
5892
+ .dndev-sheet-drag-handle
5893
+ ~ .dndev-sheet-header,
5894
+ .dndev-sheet-content[data-side='top']
5895
+ .dndev-sheet-drag-handle
5896
+ ~ .dndev-sheet-header {
5897
+ padding-top: 0;
5898
+ }
5899
+
5900
+ /* BODY - Scrollable */
5901
+
5902
+ .dndev-sheet-body {
5903
+ flex: 1;
5904
+ /* Consumes available space */
5905
+ overflow-y: auto;
5906
+ /* Independent scroll */
5907
+ overflow-x: hidden;
5908
+ padding: var(--gap-md);
5909
+ overscroll-behavior: contain;
5910
+ /* Prevent body scroll chaining */
5911
+ }
5912
+
5913
+ /* FOOTER - Pinned */
5914
+
5915
+ .dndev-sheet-footer {
5916
+ flex-shrink: 0;
5917
+ /* Never shrink */
5918
+ padding: var(--gap-md);
5919
+ border-top: var(--border-hairline) solid var(--line-1);
5920
+ /* Separator */
5921
+ display: flex;
5922
+ flex-direction: column-reverse;
5923
+ /* Mobile-first stacking */
5924
+ gap: var(--gap-sm);
5925
+
5926
+ /* Desktop: Row layout */
5927
+ }
5928
+
5929
+ @media (width >=640px) {
5930
+
5931
+ .dndev-sheet-footer {
5932
+ flex-direction: row;
5933
+ justify-content: flex-end;
5934
+ }
5935
+ }
5936
+
5937
+ .dndev-sheet-footer {
5938
+
5939
+ /* Thumb Ergonomics: Bottom Safe Area (Home Indicator) */
5940
+ padding-bottom: max(var(--gap-md), env(safe-area-inset-bottom));
5689
5941
  }
5690
5942
 
5691
5943
  .dndev-sheet-title {
@@ -5695,9 +5947,12 @@ em {
5695
5947
  }
5696
5948
 
5697
5949
  .dndev-sheet-close {
5698
- position: absolute;
5699
- top: var(--gap-md);
5700
- inset-inline-end: var(--gap-md);
5950
+ /* Position relative - flex handles alignment */
5951
+ position: relative;
5952
+ margin-inline-start: auto;
5953
+ /* Push to end (RTL-aware: end = right in LTR, left in RTL) */
5954
+ margin-inline-end: var(--gap-sm);
5955
+ /* Spacing from edge - use margin not padding to keep icon centered */
5701
5956
  opacity: var(--opacity-muted);
5702
5957
  }
5703
5958
 
@@ -5705,9 +5960,56 @@ em {
5705
5960
  opacity: 1;
5706
5961
  }
5707
5962
 
5708
- .dndev-sheet-footer {
5709
- flex-shrink: 0;
5710
- margin-top: var(--gap-md);
5963
+ /* ===========================
5964
+ ANIMATIONS (Motion Physics)
5965
+ =========================== */
5966
+
5967
+ /* Slide In/Out Keyframes - Context Aware */
5968
+
5969
+ @keyframes sheet-slide-in {
5970
+ from {
5971
+ opacity: 0;
5972
+ transform: var(--slide-enter-transform);
5973
+ }
5974
+
5975
+ to {
5976
+ opacity: 1;
5977
+ transform: translate(0, 0);
5978
+ }
5979
+ }
5980
+
5981
+ @keyframes sheet-slide-out {
5982
+ from {
5983
+ opacity: 1;
5984
+ transform: translate(0, 0);
5985
+ }
5986
+
5987
+ to {
5988
+ opacity: 0;
5989
+ transform: var(--slide-exit-transform);
5990
+ }
5991
+ }
5992
+
5993
+ /* Define Transforms based on Side */
5994
+
5995
+ .dndev-sheet-content[data-side='right'] {
5996
+ --slide-enter-transform: translateX(100%);
5997
+ --slide-exit-transform: translateX(100%);
5998
+ }
5999
+
6000
+ .dndev-sheet-content[data-side='left'] {
6001
+ --slide-enter-transform: translateX(-100%);
6002
+ --slide-exit-transform: translateX(-100%);
6003
+ }
6004
+
6005
+ .dndev-sheet-content[data-side='bottom'] {
6006
+ --slide-enter-transform: translateY(100%);
6007
+ --slide-exit-transform: translateY(100%);
6008
+ }
6009
+
6010
+ .dndev-sheet-content[data-side='top'] {
6011
+ --slide-enter-transform: translateY(-100%);
6012
+ --slide-exit-transform: translateY(-100%);
5711
6013
  }
5712
6014
 
5713
6015
  /* packages/components/src/atomic/Skeleton/Skeleton.css */
@@ -6380,7 +6682,8 @@ em {
6380
6682
 
6381
6683
  .dndev-switch-label {
6382
6684
  font-size: var(--font-size-sm);
6383
- transition: color var(--dur-normal) var(--ease-in-out),
6685
+ transition:
6686
+ color var(--dur-normal) var(--ease-in-out),
6384
6687
  font-weight var(--dur-normal) var(--ease-in-out);
6385
6688
  white-space: nowrap;
6386
6689
  }
@@ -6389,16 +6692,14 @@ em {
6389
6692
 
6390
6693
  .dndev-switch-with-labels:not(:has(.dndev-switch[data-state='checked']))
6391
6694
  .dndev-switch-label-unchecked,
6392
- .dndev-switch-with-labels[data-checked='false']
6393
- .dndev-switch-label-unchecked {
6695
+ .dndev-switch-with-labels[data-checked='false'] .dndev-switch-label-unchecked {
6394
6696
  color: var(--foreground);
6395
6697
  font-weight: var(--font-weight-medium);
6396
6698
  }
6397
6699
 
6398
6700
  .dndev-switch-with-labels:has(.dndev-switch[data-state='checked'])
6399
6701
  .dndev-switch-label-unchecked,
6400
- .dndev-switch-with-labels[data-checked='true']
6401
- .dndev-switch-label-unchecked {
6702
+ .dndev-switch-with-labels[data-checked='true'] .dndev-switch-label-unchecked {
6402
6703
  color: var(--muted-foreground);
6403
6704
  font-weight: var(--font-weight-normal);
6404
6705
  }
@@ -6407,16 +6708,14 @@ em {
6407
6708
 
6408
6709
  .dndev-switch-with-labels:has(.dndev-switch[data-state='checked'])
6409
6710
  .dndev-switch-label-checked,
6410
- .dndev-switch-with-labels[data-checked='true']
6411
- .dndev-switch-label-checked {
6711
+ .dndev-switch-with-labels[data-checked='true'] .dndev-switch-label-checked {
6412
6712
  color: var(--foreground);
6413
6713
  font-weight: var(--font-weight-medium);
6414
6714
  }
6415
6715
 
6416
6716
  .dndev-switch-with-labels:not(:has(.dndev-switch[data-state='checked']))
6417
6717
  .dndev-switch-label-checked,
6418
- .dndev-switch-with-labels[data-checked='false']
6419
- .dndev-switch-label-checked {
6718
+ .dndev-switch-with-labels[data-checked='false'] .dndev-switch-label-checked {
6420
6719
  color: var(--muted-foreground);
6421
6720
  font-weight: var(--font-weight-normal);
6422
6721
  }
@@ -6439,7 +6738,21 @@ em {
6439
6738
  }
6440
6739
 
6441
6740
  .dndev-table-header {
6442
- /* Base header styles */
6741
+ background-color: var(--accent);
6742
+ }
6743
+
6744
+ /* Filter row above header */
6745
+
6746
+ .dndev-table-filter-row {
6747
+ border: 1px solid var(--border);
6748
+ border-bottom: none;
6749
+ }
6750
+
6751
+ .dndev-table-filter-row .dndev-table-head {
6752
+ background-color: var(--muted);
6753
+ padding: var(--gap-xs);
6754
+ height: auto;
6755
+ min-height: auto;
6443
6756
  }
6444
6757
 
6445
6758
  .dndev-table-body {
@@ -6457,6 +6770,12 @@ em {
6457
6770
  background-color: color-mix(in oklab, var(--accent) 15%, transparent);
6458
6771
  }
6459
6772
 
6773
+ /* Cursor pointer for clickable rows */
6774
+
6775
+ .dndev-table-row.dndev-cursor-pointer {
6776
+ cursor: pointer;
6777
+ }
6778
+
6460
6779
  /* Zebra striping for data tables */
6461
6780
 
6462
6781
  .dndev-table-body .dndev-table-row:nth-child(even) {
@@ -6495,22 +6814,34 @@ em {
6495
6814
  padding-block: var(--gap-sm);
6496
6815
  }
6497
6816
 
6498
- .dndev-table-head[data-sortable='true'] {
6817
+ /* Header cells use accent foreground for contrast */
6818
+
6819
+ .dndev-table-header .dndev-table-head {
6820
+ color: var(--accent-foreground);
6821
+ }
6822
+
6823
+ [data-sortable='true']:is(.dndev-table-header .dndev-table-head) {
6499
6824
  cursor: pointer;
6500
6825
  }
6501
6826
 
6502
- .dndev-table-head[data-align='center'] {
6827
+ [data-align='center']:is(.dndev-table-header .dndev-table-head) {
6503
6828
  text-align: center;
6504
6829
  }
6505
6830
 
6506
- .dndev-table-head[data-align='end'] {
6831
+ [data-align='end']:is(.dndev-table-header .dndev-table-head) {
6507
6832
  text-align: end;
6508
6833
  }
6509
6834
 
6510
- .dndev-table-head[data-align='start'] {
6835
+ [data-align='start']:is(.dndev-table-header .dndev-table-head) {
6511
6836
  text-align: start;
6512
6837
  }
6513
6838
 
6839
+ /* Active filter indicator */
6840
+
6841
+ .dndev-table-filter-active {
6842
+ color: var(--primary);
6843
+ }
6844
+
6514
6845
  /* Table cell (td) styles */
6515
6846
 
6516
6847
  .dndev-table-cell {
@@ -6518,6 +6849,7 @@ em {
6518
6849
  padding-inline: var(--gap-md);
6519
6850
  padding-block: var(--gap-sm);
6520
6851
  min-height: var(--touch-target);
6852
+ line-height: 1.5; /* Ensure consistent line height for empty cells */
6521
6853
  }
6522
6854
 
6523
6855
  .dndev-table-cell[data-align='center'] {
@@ -6551,8 +6883,8 @@ em {
6551
6883
  /* Input components inside grid cells should be borderless and fit snugly */
6552
6884
 
6553
6885
  .dndev-table-grid .dndev-table-cell .dndev-input,
6554
- .dndev-table-grid .dndev-table-cell input[type="text"],
6555
- .dndev-table-grid .dndev-table-cell input[type="number"] {
6886
+ .dndev-table-grid .dndev-table-cell input[type='text'],
6887
+ .dndev-table-grid .dndev-table-cell input[type='number'] {
6556
6888
  border: none;
6557
6889
  background: transparent;
6558
6890
  width: 100%;
@@ -6596,6 +6928,64 @@ em {
6596
6928
  padding-inline-start: calc(var(--gap-md) + var(--icon-md) + var(--gap-sm));
6597
6929
  }
6598
6930
 
6931
+ /* Skeleton rows - apply standard skeleton pulse animation to entire rows */
6932
+
6933
+ /* Keep existing background colors (zebra striping) - just add opacity pulse */
6934
+
6935
+ .dndev-table-body .dndev-table-row.dndev-skeleton-row {
6936
+ animation: dndev-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
6937
+ pointer-events: none;
6938
+
6939
+ /* Keep hover state but disabled (pointer-events: none prevents hover) */
6940
+ }
6941
+
6942
+ :is(.dndev-table-body .dndev-table-row.dndev-skeleton-row):hover {
6943
+ /* Inherit from parent .dndev-table-row hover styles */
6944
+ }
6945
+
6946
+ /* Even rows keep their var(--muted) background, just pulse */
6947
+
6948
+ .dndev-table-body .dndev-table-row.dndev-skeleton-row:nth-child(even) {
6949
+ animation: dndev-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
6950
+ }
6951
+
6952
+ :is(.dndev-table-body .dndev-table-row.dndev-skeleton-row:nth-child(even)):hover {
6953
+ /* Inherit from parent .dndev-table-row:nth-child(even) hover styles */
6954
+ }
6955
+
6956
+ /* Skeleton bars inside cells - adapt to row background for visibility */
6957
+
6958
+ /* Odd rows (transparent background): use default var(--muted) skeleton */
6959
+
6960
+ /* Even rows (var(--muted) background): use lighter skeleton for contrast */
6961
+
6962
+ .dndev-table-body .dndev-table-row.dndev-skeleton-row .dndev-skeleton {
6963
+ background-color: var(--muted);
6964
+ }
6965
+
6966
+ .dndev-table-body
6967
+ .dndev-table-row.dndev-skeleton-row:nth-child(even)
6968
+ .dndev-skeleton {
6969
+ /* Even rows have var(--muted) background, so skeleton should be lighter for contrast */
6970
+ background-color: color-mix(
6971
+ in oklab,
6972
+ var(--muted) 60%,
6973
+ var(--foreground) 40%
6974
+ );
6975
+ }
6976
+
6977
+ /* Use the same pulse animation as standard skeleton (from Skeleton.css) */
6978
+
6979
+ @keyframes dndev-pulse {
6980
+ 0%,
6981
+ 100% {
6982
+ opacity: 1;
6983
+ }
6984
+ 50% {
6985
+ opacity: var(--opacity-muted);
6986
+ }
6987
+ }
6988
+
6599
6989
  /* packages/components/src/atomic/Tabs/Tabs.css */
6600
6990
 
6601
6991
  /* Tabs list: use flexbox for natural wrapping, not grid */
@@ -8155,6 +8545,10 @@ h4[data-variant='code'] {
8155
8545
  pointer-events: auto;
8156
8546
  }
8157
8547
 
8548
+ .dndev-cursor-pointer {
8549
+ cursor: pointer;
8550
+ }
8551
+
8158
8552
  .dndev-aspect-video {
8159
8553
  aspect-ratio: 16 / 9;
8160
8554
  }
@@ -8531,6 +8925,7 @@ h4[data-variant='code'] {
8531
8925
  from {
8532
8926
  opacity: 1;
8533
8927
  }
8928
+
8534
8929
  to {
8535
8930
  opacity: 0;
8536
8931
  }
@@ -8540,6 +8935,7 @@ h4[data-variant='code'] {
8540
8935
  from {
8541
8936
  opacity: 0;
8542
8937
  }
8938
+
8543
8939
  to {
8544
8940
  opacity: 1;
8545
8941
  }
@@ -8552,6 +8948,7 @@ h4[data-variant='code'] {
8552
8948
  opacity: 1;
8553
8949
  transform: translateX(0);
8554
8950
  }
8951
+
8555
8952
  to {
8556
8953
  opacity: 0;
8557
8954
  transform: translateX(-100%);
@@ -8563,6 +8960,7 @@ h4[data-variant='code'] {
8563
8960
  opacity: 0;
8564
8961
  transform: translateX(100%);
8565
8962
  }
8963
+
8566
8964
  to {
8567
8965
  opacity: 1;
8568
8966
  transform: translateX(0);
@@ -8637,7 +9035,7 @@ main[role='main'][data-routing-animation='none'] {
8637
9035
 
8638
9036
  /* Tablet (768px - 1023px) */
8639
9037
 
8640
- @media (width >= 768px) and (width <= 1023px) {
9038
+ @media (width >=768px) and (width <=1023px) {
8641
9039
  main[role='main'][data-routing-animation='fade'] {
8642
9040
  animation: routeFadeIn
8643
9041
  var(--routing-tablet-duration, var(--routing-default-duration, 300ms))
@@ -8653,7 +9051,7 @@ main[role='main'][data-routing-animation='none'] {
8653
9051
 
8654
9052
  /* Desktop (1024px - 1439px) */
8655
9053
 
8656
- @media (width >= 1024px) and (width <= 1439px) {
9054
+ @media (width >=1024px) and (width <=1439px) {
8657
9055
  main[role='main'][data-routing-animation='fade'] {
8658
9056
  animation: routeFadeIn
8659
9057
  var(--routing-desktop-duration, var(--routing-default-duration, 300ms))
@@ -8669,7 +9067,7 @@ main[role='main'][data-routing-animation='none'] {
8669
9067
 
8670
9068
  /* Wide (>= 1440px) */
8671
9069
 
8672
- @media (width >= 1440px) {
9070
+ @media (width >=1440px) {
8673
9071
  main[role='main'][data-routing-animation='fade'] {
8674
9072
  animation: routeFadeIn
8675
9073
  var(--routing-wide-duration, var(--routing-default-duration, 300ms))
@@ -8702,7 +9100,7 @@ main[role='main'][data-routing-animation='none'] {
8702
9100
 
8703
9101
  /* Mobile/Tablet: Hide sidebars - WCAG & Lighthouse best practices */
8704
9102
 
8705
- @media (width <= 1023px) {
9103
+ @media (width <=1023px) {
8706
9104
  .dndev-layout aside[role='navigation'].sidebar,
8707
9105
  aside[role='navigation'].sidebar {
8708
9106
  display: none !important;
@@ -8721,10 +9119,7 @@ main[role='main'][data-routing-animation='none'] {
8721
9119
  max-height: 100dvh;
8722
9120
  overflow: hidden;
8723
9121
  display: grid;
8724
- /* ONE DRY grid structure: 3 rows, 2 columns */
8725
- /* Footer starts at sidebar edge (column 2) - when sidebar-width is 0px, footer starts at left edge */
8726
- /* Footer grows with content wrapping. For pixel-perfect calc() accuracy when footer wraps,
8727
- implement ResizeObserver to update --footer-height dynamically. */
9122
+ /* Grid structure: 3 rows, 2 columns */
8728
9123
  grid-template-areas:
8729
9124
  'header header'
8730
9125
  'sidebar main'
@@ -8735,16 +9130,58 @@ main[role='main'][data-routing-animation='none'] {
8735
9130
  );
8736
9131
  grid-template-columns: var(--sidebar-width) 1fr;
8737
9132
 
8738
- /* Game layout: Grid rows adjust based on breakpoint (footer hidden on tablet/mobile) */
9133
+ /* Mobile: Grid scrolls instead of main - footer scrolls with content */
8739
9134
  }
8740
9135
 
8741
- [data-layout='game']:root .dndev-layout {
8742
- grid-template-rows: var(--header-height) 1fr minmax(
8743
- var(--footer-height),
8744
- auto
8745
- );
9136
+ @media (width <=1023px) {
9137
+
9138
+ .dndev-layout {
9139
+ overflow-y: auto;
9140
+ overflow-x: hidden;
9141
+ /* Keep footer row - grid scrolls so footer scrolls with content */
9142
+ grid-template-areas:
9143
+ 'header header'
9144
+ 'sidebar main'
9145
+ 'footer footer';
9146
+ grid-template-rows: var(--header-height) min-content auto;
9147
+ }
8746
9148
  }
8747
9149
 
9150
+ /* Footer scroll mode - grid scrolls, footer scrolls with content (opt-in for desktop) */
9151
+
9152
+ .dndev-layout[data-footer-mode='scroll'] {
9153
+ overflow-y: auto;
9154
+ overflow-x: hidden;
9155
+ grid-template-rows: var(--header-height) min-content auto;
9156
+ }
9157
+
9158
+ .dndev-layout[data-footer-mode='scroll'] header[role='banner'] {
9159
+ position: sticky;
9160
+ top: 0;
9161
+ }
9162
+
9163
+ .dndev-layout[data-footer-mode='scroll'] main[role='main'] {
9164
+ overflow: visible;
9165
+ min-height: -moz-min-content;
9166
+ min-height: min-content;
9167
+ }
9168
+
9169
+ .dndev-layout[data-footer-mode='scroll'] footer[role='contentinfo'] {
9170
+ height: auto;
9171
+ }
9172
+
9173
+ :is(.dndev-layout[data-footer-mode='scroll'] footer[role='contentinfo']) > * {
9174
+ height: auto;
9175
+ min-height: var(--footer-height);
9176
+ }
9177
+
9178
+ /* Presets with no footer at all */
9179
+
9180
+ [data-layout='moolti'] footer[role='contentinfo'],
9181
+ [data-layout='plain'] footer[role='contentinfo'] {
9182
+ display: none;
9183
+ }
9184
+
8748
9185
  /* ===========================
8749
9186
  LAYOUT ZONE POSITIONING RULES
8750
9187
  Follows logical flow: Header → Sidebar → Main → Footer
@@ -8758,6 +9195,8 @@ header[role='banner'] {
8758
9195
  grid-area: header;
8759
9196
  box-sizing: border-box;
8760
9197
  height: var(--header-height);
9198
+ min-height: var(--header-height);
9199
+ max-height: var(--header-height);
8761
9200
  position: relative;
8762
9201
  z-index: var(--z-header);
8763
9202
  contain: layout style;
@@ -8777,14 +9216,26 @@ header[role='banner'] {
8777
9216
  /* Theme-aware styling - 100% controlled by theme system */
8778
9217
  background: var(--background);
8779
9218
  border-bottom: var(--border-hairline) solid var(--border);
9219
+
9220
+ /* Mobile: Sticky header (for presets that keep header visible) */
8780
9221
  }
8781
9222
 
9223
+ @media (width <=1023px) {
9224
+
9225
+ header[role='banner'] {
9226
+ position: sticky;
9227
+ top: 0;
9228
+ }
9229
+ }
9230
+
8782
9231
  .header-start {
8783
9232
  display: flex;
8784
9233
  align-items: center;
8785
9234
  flex-shrink: 0;
8786
9235
  height: 100%;
9236
+ max-height: 100%;
8787
9237
  gap: var(--gap-sm);
9238
+ overflow: hidden;
8788
9239
  }
8789
9240
 
8790
9241
  .header-end {
@@ -8792,8 +9243,11 @@ header[role='banner'] {
8792
9243
  align-items: center;
8793
9244
  justify-content: flex-end;
8794
9245
  flex-shrink: 0;
9246
+ height: 100%;
9247
+ max-height: 100%;
8795
9248
  margin-inline-start: auto;
8796
9249
  gap: var(--gap-sm);
9250
+ overflow: hidden;
8797
9251
  }
8798
9252
 
8799
9253
  /* Viewport-centered center content - absolutely positioned overlay */
@@ -8827,19 +9281,20 @@ header[role='banner'] .header-center {
8827
9281
  aside[role='navigation'].sidebar {
8828
9282
  grid-area: sidebar;
8829
9283
  box-sizing: border-box;
8830
- min-width: calc(
8831
- var(--sidebar-resize-handle-width) + 48px
8832
- ); /* Min: 48px content + 6px handle = 54px */
8833
- max-width: calc(
8834
- var(--sidebar-resize-handle-width) + 400px
8835
- ); /* Max: 400px content + 6px handle = 406px */
9284
+ min-width: calc(var(--sidebar-resize-handle-width) + 48px);
9285
+ /* Min: 48px content + 6px handle = 54px */
9286
+ max-width: calc(var(--sidebar-resize-handle-width) + 400px);
9287
+ /* Max: 400px content + 6px handle = 406px */
8836
9288
  z-index: var(--z-sidebar);
8837
- overflow: none; /* No clipping needed - handle is in grid */
9289
+ overflow: none;
9290
+ /* No clipping needed - handle is in grid */
8838
9291
  contain: layout style;
8839
9292
  padding: 0;
8840
9293
  display: grid;
8841
- grid-template-columns: auto var(--sidebar-resize-handle-width); /* Content | Handle - column 1 width set inline */
8842
- grid-template-rows: auto 1fr auto; /* Top | Content | Bottom */
9294
+ grid-template-columns: auto var(--sidebar-resize-handle-width);
9295
+ /* Content | Handle - column 1 width set inline */
9296
+ grid-template-rows: auto 1fr auto;
9297
+ /* Top | Content | Bottom */
8843
9298
  height: 100%;
8844
9299
 
8845
9300
  /* Theme-aware styling - 100% controlled by theme system */
@@ -8894,7 +9349,8 @@ aside[role='navigation'].sidebar[data-dragging='true']
8894
9349
 
8895
9350
  @media (hover: none) {
8896
9351
  aside[role='navigation'].sidebar .dndev-sidebar-resize-handle {
8897
- width: calc(var(--sidebar-resize-handle-width) * 2); /* 12px for touch */
9352
+ width: calc(var(--sidebar-resize-handle-width) * 2);
9353
+ /* 12px for touch */
8898
9354
  }
8899
9355
  }
8900
9356
 
@@ -8963,7 +9419,8 @@ aside[role='navigation'].sidebar[data-dragging='true']
8963
9419
  .sidebar-content .dndev-interactive[data-role='menu-item'],.sidebar-content .dndev-interactive[data-role='nav-trigger'] {
8964
9420
  height: var(--touch-target);
8965
9421
  min-height: var(--touch-target);
8966
- padding-block: 0; /* No vertical padding - buttons fill exact 48px */
9422
+ padding-block: 0;
9423
+ /* No vertical padding - buttons fill exact 48px */
8967
9424
  }
8968
9425
 
8969
9426
  /* Other interactive elements (not menu items) - consistent padding */
@@ -9003,7 +9460,8 @@ aside.sidebar[role='navigation'] .sidebar-top,aside.sidebar[role='navigation'] .
9003
9460
  }
9004
9461
 
9005
9462
  aside.sidebar[role='navigation'] .sidebar-content {
9006
- overflow-x: hidden; /* Prevent horizontal scroll, allow vertical */
9463
+ overflow-x: hidden;
9464
+ /* Prevent horizontal scroll, allow vertical */
9007
9465
  }
9008
9466
 
9009
9467
  aside.sidebar[role='navigation'] .dndev-interactive {
@@ -9068,12 +9526,9 @@ aside.sidebar[role='navigation'][data-collapsed='true'] .app-branding {
9068
9526
  main[role='main'] {
9069
9527
  grid-area: main;
9070
9528
  overflow-y: auto;
9071
- /* Default: allow scrolling */
9072
9529
  overflow-x: hidden;
9073
- /* Prevent horizontal scroll from breakthrough components */
9074
9530
  display: flex;
9075
9531
  flex-direction: column;
9076
- /* No automatic padding; spacing handled by gaps */
9077
9532
  padding: 0;
9078
9533
  contain: layout style;
9079
9534
 
@@ -9082,12 +9537,17 @@ main[role='main'] {
9082
9537
 
9083
9538
  main[role='main'] > *:not(.breadcrumbs-container):first-of-type,main[role='main'] > .breadcrumbs-container + * {
9084
9539
  flex: 1 1 auto;
9085
- /* Page content grows */
9086
9540
  }
9087
9541
 
9088
- main[role='main'] > *:last-child {
9089
- flex-shrink: 0;
9090
- /* Footer stays at bottom */
9542
+ /* Mobile: Grid scrolls, main doesn't */
9543
+
9544
+ @media (width <=1023px) {
9545
+
9546
+ main[role='main'] {
9547
+ overflow: visible;
9548
+ min-height: -moz-min-content;
9549
+ min-height: min-content;
9550
+ }
9091
9551
  }
9092
9552
 
9093
9553
  /* Footer: Full width by default, app presets start after sidebar */
@@ -9122,31 +9582,25 @@ footer[role='contentinfo'] > * {
9122
9582
  padding-inline-end: var(--content-padding);
9123
9583
  }
9124
9584
 
9125
- /* Game: Hide footer on tablet/mobile - merged into GameMergedBar */
9585
+ /* Mobile: Allow footer to grow when content wraps */
9126
9586
 
9127
- @media (width <= 1023px) {
9128
- [data-layout='game']:root footer[role='contentinfo'] {
9129
- display: none;
9130
- }
9131
- }
9587
+ @media (width <=1023px) {
9132
9588
 
9133
- /* Moolti: No footer (built into sidebar) */
9134
-
9135
- [data-layout='moolti']:root footer[role='contentinfo'] {
9136
- display: none;
9137
- }
9138
-
9139
- /* Plain: No footer (full-screen apps) */
9589
+ footer[role='contentinfo'] {
9590
+ height: auto;
9591
+ }
9140
9592
 
9141
- [data-layout='plain']:root footer[role='contentinfo'] {
9142
- display: none;
9593
+ footer[role='contentinfo'] > * {
9594
+ height: auto;
9595
+ min-height: var(--footer-height);
9596
+ }
9143
9597
  }
9144
9598
 
9145
9599
  /* Footer text styles */
9146
9600
 
9147
9601
  footer[role='contentinfo'] .footer-copyright {
9148
9602
  color: var(--muted-foreground);
9149
- font-size: var(--font-size-sm);
9603
+ font-size: var(--font-size-xs);
9150
9604
  }
9151
9605
 
9152
9606
  footer[role='contentinfo'] a:not(.dndev-interactive) {
@@ -9186,7 +9640,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9186
9640
 
9187
9641
  .merged-bar[data-position='top'] {
9188
9642
  top: 0;
9189
- height: 64px;
9643
+ height: var(--header-height);
9190
9644
  border-bottom: 2px solid var(--border);
9191
9645
  padding-top: env(safe-area-inset-top);
9192
9646
  }
@@ -9214,9 +9668,9 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9214
9668
  min-height: 0;
9215
9669
  }
9216
9670
 
9217
- /* Mobile (<1024px): Show merged-bar, hide zones, add padding */
9671
+ /* Mobile (<1024px): Show merged-bar, hide zones */
9218
9672
 
9219
- @media (width <= 1023px) {
9673
+ @media (width <=1023px) {
9220
9674
  /* Presets with mergedBar: top (admin, moolti, game, docs) */
9221
9675
  [data-layout='admin'] .merged-bar[data-position='top'],
9222
9676
  [data-layout='moolti'] .merged-bar[data-position='top'],
@@ -9229,7 +9683,8 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9229
9683
  [data-layout='moolti'] .dndev-layout,
9230
9684
  [data-layout='game'] .dndev-layout,
9231
9685
  [data-layout='docs'] .dndev-layout {
9232
- padding-top: calc(64px + env(safe-area-inset-top));
9686
+ /* Remove padding-top - grid already accounts for header-height, mergedBar is fixed and doesn't affect grid flow */
9687
+ /* Content won't go under mergedBar because grid positions main after header row */
9233
9688
  }
9234
9689
 
9235
9690
  [data-layout='admin'] header[role='banner'],
@@ -9255,7 +9710,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9255
9710
 
9256
9711
  /* Desktop (>=1024px): Always hide merged-bar */
9257
9712
 
9258
- @media (width >= 1024px) {
9713
+ @media (width >=1024px) {
9259
9714
  .merged-bar {
9260
9715
  display: none !important;
9261
9716
  }
@@ -9279,7 +9734,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9279
9734
  /* Admin: Mobile/Tablet (<1024px) - only overrides */
9280
9735
  }
9281
9736
 
9282
- @media (width <= 1023px) {
9737
+ @media (width <=1023px) {
9283
9738
 
9284
9739
  [data-layout='admin'] {
9285
9740
  --sidebar-width: 0px;
@@ -9310,7 +9765,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9310
9765
 
9311
9766
  /* Moolti: Mobile/Tablet (<1024px) - only overrides */
9312
9767
 
9313
- @media (width <= 1023px) {
9768
+ @media (width <=1023px) {
9314
9769
 
9315
9770
  [data-layout='moolti'] {
9316
9771
  --header-height: 62px;
@@ -9337,7 +9792,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9337
9792
 
9338
9793
  /* Docs: Mobile/Tablet (<1024px) - only overrides */
9339
9794
 
9340
- @media (width <= 1023px) {
9795
+ @media (width <=1023px) {
9341
9796
 
9342
9797
  [data-layout='docs'] {
9343
9798
  --sidebar-width: 0px;
@@ -9363,7 +9818,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9363
9818
  /* Blog: Mobile/Tablet (<1024px) - only overrides */
9364
9819
  }
9365
9820
 
9366
- @media (width <= 1023px) {
9821
+ @media (width <=1023px) {
9367
9822
 
9368
9823
  [data-layout='blog'] {
9369
9824
  --header-height: 0px;
@@ -9413,7 +9868,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9413
9868
  /* Game: Mobile/Tablet (<1024px) - only overrides */
9414
9869
  }
9415
9870
 
9416
- @media (width <= 1023px) {
9871
+ @media (width <=1023px) {
9417
9872
 
9418
9873
  [data-layout='game'] {
9419
9874
  --footer-height: 0px;
@@ -9534,7 +9989,14 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9534
9989
  padding-top: var(--gap-lg);
9535
9990
  }
9536
9991
 
9992
+ /* First Section child gets gap-md spacing from top */
9993
+
9994
+ .dndev-container > .dndev-section-full-width:first-child {
9995
+ margin-top: var(--gap-md);
9996
+ }
9997
+
9537
9998
  .dndev-container {
9999
+
9538
10000
  min-height: 0;
9539
10001
  display: flex;
9540
10002
  flex-direction: column;
@@ -9569,7 +10031,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9569
10031
  --max-content-width: 100%;
9570
10032
  }
9571
10033
 
9572
- @media (width >= 1024px) {
10034
+ @media (width >=1024px) {
9573
10035
 
9574
10036
  .dndev-container[data-variant='standard'] {
9575
10037
  --max-content-width: 87.5rem;
@@ -9584,7 +10046,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9584
10046
  --max-content-width: 100%;
9585
10047
  }
9586
10048
 
9587
- @media (width >= 1024px) {
10049
+ @media (width >=1024px) {
9588
10050
 
9589
10051
  .dndev-container[data-variant='docs'] {
9590
10052
  --max-content-width: 56.25rem;