@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
package/dist/dndev.css CHANGED
@@ -2213,6 +2213,20 @@ em {
2213
2213
  padding-inline-start: var(--gap-md);
2214
2214
  }
2215
2215
 
2216
+ /* Bare mode - no visual chrome, used inside FloatingLabel or custom wrappers */
2217
+
2218
+ [data-bare] {
2219
+ border: none !important;
2220
+ box-shadow: none !important;
2221
+ background: transparent !important;
2222
+ }
2223
+
2224
+ [data-bare]:hover,[data-bare]:focus,[data-bare]:focus-visible {
2225
+ border-color: transparent !important;
2226
+ box-shadow: none !important;
2227
+ outline: none !important;
2228
+ }
2229
+
2216
2230
  /* Password strength bar height override */
2217
2231
 
2218
2232
  .dndev-password-strength-bar {
@@ -2728,6 +2742,34 @@ em {
2728
2742
 
2729
2743
  /* Label styling moved to patterns.css (.dndev-interactive-label) */
2730
2744
 
2745
+ /* Loading state */
2746
+
2747
+ [data-loading] {
2748
+ cursor: wait;
2749
+ pointer-events: none;
2750
+ }
2751
+
2752
+ /* Button spinner - inherits size from button font-size */
2753
+
2754
+ .dndev-button-spinner {
2755
+ flex-shrink: 0;
2756
+ }
2757
+
2758
+ /* Progress ring for upload percentage */
2759
+
2760
+ .dndev-button-progress {
2761
+ display: inline-flex;
2762
+ align-items: center;
2763
+ justify-content: center;
2764
+ flex-shrink: 0;
2765
+ }
2766
+
2767
+ .dndev-progress-ring {
2768
+ width: 1em;
2769
+ height: 1em;
2770
+ transform: rotate(-90deg);
2771
+ }
2772
+
2731
2773
  /* packages/components/src/atomic/Calendar/Calendar.css */
2732
2774
 
2733
2775
  /**
@@ -3286,6 +3328,7 @@ em {
3286
3328
 
3287
3329
  .dndev-collapsible-content[data-state='open'] {
3288
3330
  animation: slideDown var(--dur-normal) var(--ease-in-out);
3331
+ overflow: visible; /* Allow dropdowns/overlays to escape when open */
3289
3332
  }
3290
3333
 
3291
3334
  .dndev-collapsible-content[data-state='closed'] {
@@ -4418,6 +4461,18 @@ em {
4418
4461
 
4419
4462
  /* packages/components/src/atomic/Input/Input.css */
4420
4463
 
4464
+ /* Hide number input spinners - cleaner UI for price/range inputs */
4465
+
4466
+ input[type='number']::-webkit-inner-spin-button,
4467
+ input[type='number']::-webkit-outer-spin-button {
4468
+ -webkit-appearance: none;
4469
+ margin: 0;
4470
+ }
4471
+
4472
+ input[type='number'] {
4473
+ -moz-appearance: textfield;
4474
+ }
4475
+
4421
4476
  /* Input with leading icon (search, etc.) */
4422
4477
 
4423
4478
  .dndev-input-with-leading-icon {
@@ -4616,47 +4671,79 @@ em {
4616
4671
  margin-inline-start: var(--gap-sm);
4617
4672
  }
4618
4673
 
4619
- /* Floating Label - positioned absolutely at top of input fields */
4674
+ /* Floating Fieldset - native border-cutting via legend */
4620
4675
 
4621
- .dndev-floating-label {
4622
- position: absolute;
4623
- inset-inline-start: var(--gap-md);
4624
- top: calc(-1 * var(--font-size-xs) / 2 - 1px);
4676
+ .dndev-floating-fieldset {
4677
+ position: relative;
4678
+ border: var(--border-hairline) solid var(--line-2);
4679
+ border-radius: var(--radius-interactive);
4680
+ margin: 0;
4681
+ padding: 0;
4682
+ background-color: transparent;
4683
+ transition: all var(--dur-normal) var(--ease-in-out);
4684
+ text-align: start;
4685
+ /* Flex-aware: allow fieldset to shrink in flex containers */
4686
+ min-width: 0;
4687
+ width: 100%;
4688
+ }
4689
+
4690
+ .dndev-floating-fieldset:hover {
4691
+ border-color: var(--ring);
4692
+ }
4693
+
4694
+ .dndev-floating-fieldset:focus-within {
4695
+ border-color: var(--ring);
4696
+ }
4697
+
4698
+ .dndev-floating-fieldset[data-disabled='true'] {
4699
+ opacity: var(--opacity-muted);
4700
+ cursor: not-allowed;
4701
+ }
4702
+
4703
+ /* Legend sits on border - browser natively cuts border */
4704
+
4705
+ .dndev-floating-legend {
4706
+ margin-inline-start: var(--gap-sm);
4707
+ padding: 0 var(--gap-sm);
4625
4708
  font-size: var(--font-size-xs);
4626
4709
  font-weight: 500;
4627
- pointer-events: none;
4628
- z-index: 1;
4629
- background-color: var(--background);
4630
- padding: 0 var(--gap-sm);
4631
4710
  line-height: 1;
4632
4711
  color: var(--foreground);
4712
+ /* Ellipsis by default */
4713
+ max-width: 100%;
4714
+ overflow: hidden;
4715
+ text-overflow: ellipsis;
4716
+ white-space: nowrap;
4633
4717
  }
4634
4718
 
4635
- /* Inherit background when inside floating containers (dropdowns, menus, popovers) */
4719
+ .dndev-floating-legend label {
4720
+ cursor: default;
4721
+ display: inline-flex;
4722
+ align-items: center;
4723
+ gap: var(--gap-tight);
4724
+ }
4636
4725
 
4637
- .dndev-floating .dndev-floating-label,
4638
- .dndev-menu-content .dndev-floating-label,
4639
- [class*='dndev-dropdown'] .dndev-floating-label,
4640
- [class*='dndev-navigation'] .dndev-floating-label {
4641
- background-color: var(--popover);
4642
- color: var(--popover-foreground);
4726
+ .dndev-floating-fieldset[data-disabled='true'] .dndev-floating-legend {
4727
+ color: var(--muted-foreground);
4643
4728
  }
4644
4729
 
4645
- /* When floating container has blank glow, use solid popover background */
4730
+ /* Disable truncation when explicitly set to false */
4646
4731
 
4647
- .dndev-floating[data-glow='blank'] .dndev-floating-label {
4648
- background-color: var(--popover);
4732
+ .dndev-floating-legend[data-truncate='false'] {
4733
+ max-width: none;
4734
+ overflow: visible;
4735
+ text-overflow: clip;
4736
+ white-space: normal;
4649
4737
  }
4650
4738
 
4651
- .dndev-floating-label[data-disabled='true'] {
4652
- color: var(--muted-foreground);
4653
- }
4739
+ /* Input inside fieldset uses bare mode via data-bare attribute (set by Input component) */
4654
4740
 
4655
- .dndev-floating-label[data-truncate='true'] {
4656
- max-width: calc(100% - var(--gap-md) * 2);
4657
- overflow: hidden;
4658
- text-overflow: ellipsis;
4659
- white-space: nowrap;
4741
+ /* This rule is kept for non-Input children that might need border removal */
4742
+
4743
+ .dndev-floating-fieldset > .dndev-input:not([data-bare]) {
4744
+ border: none;
4745
+ box-shadow: none;
4746
+ background: transparent;
4660
4747
  }
4661
4748
 
4662
4749
  /* packages/components/src/atomic/List/List.css */
@@ -5007,11 +5094,33 @@ em {
5007
5094
  /* packages/components/src/atomic/Pagination/Pagination.css */
5008
5095
 
5009
5096
  .dndev-pagination {
5097
+ display: flex;
5098
+ flex-direction: row;
5099
+ align-items: center;
5100
+ justify-content: space-between;
5101
+ gap: var(--gap-md);
5102
+ width: 100%;
5103
+ }
5104
+
5105
+ .dndev-pagination-info {
5106
+ display: none;
5107
+ }
5108
+
5109
+ .dndev-pagination-size {
5110
+ display: flex;
5111
+ align-items: center;
5112
+ }
5113
+
5114
+ .dndev-pagination-size-label {
5115
+ display: none;
5116
+ }
5117
+
5118
+ .dndev-pagination-nav {
5010
5119
  display: flex;
5011
5120
  align-items: center;
5012
5121
  justify-content: center;
5013
5122
  gap: var(--gap-sm);
5014
- flex-wrap: wrap;
5123
+ width: 100%;
5015
5124
  }
5016
5125
 
5017
5126
  .dndev-pagination-list {
@@ -5023,57 +5132,36 @@ em {
5023
5132
  margin: 0;
5024
5133
  }
5025
5134
 
5026
- .dndev-pagination-item {
5027
- display: flex;
5028
- align-items: center;
5029
- justify-content: center;
5030
- }
5031
-
5032
5135
  .dndev-pagination-button {
5033
- min-width: var(--touch-target);
5136
+ width: var(--touch-target);
5034
5137
  height: var(--touch-target);
5035
- display: flex;
5138
+ padding: 0;
5139
+ flex-shrink: 0;
5140
+ display: inline-flex;
5036
5141
  align-items: center;
5037
5142
  justify-content: center;
5038
- gap: var(--gap-sm);
5039
- border-radius: var(--radius-interactive);
5040
- font-weight: 500;
5041
- transition: var(--transition-fast);
5042
- cursor: pointer;
5043
- border: var(--border-hairline) solid var(--line-2);
5044
- background: transparent;
5045
- color: var(--foreground);
5046
- padding: var(--gap-sm) var(--gap-md);
5047
5143
  }
5048
5144
 
5049
- .dndev-pagination-button:hover:not(:disabled) {
5050
- background: var(--accent);
5051
- color: var(--accent-foreground);
5052
- }
5145
+ /* Desktop: Show all elements in one row */
5053
5146
 
5054
- .dndev-pagination-button:focus-visible {
5055
- outline: 2px solid var(--ring);
5056
- outline-offset: 2px;
5147
+ @media (min-width: 768px) {
5148
+ .dndev-pagination-info,
5149
+ .dndev-pagination-size {
5150
+ display: flex;
5151
+ align-items: center;
5152
+ white-space: nowrap;
5057
5153
  }
5058
5154
 
5059
- .dndev-pagination-button:disabled {
5060
- opacity: var(--opacity-muted);
5061
- cursor: not-allowed;
5155
+ .dndev-pagination-size-label {
5156
+ margin-right: var(--gap-sm);
5062
5157
  }
5063
5158
 
5064
- .dndev-pagination-button[aria-current='page'] {
5065
- background: var(--primary);
5066
- color: var(--primary-foreground);
5067
- border-color: var(--primary);
5159
+ .dndev-pagination-nav {
5160
+ justify-content: flex-end;
5161
+ width: auto;
5162
+ margin-left: auto;
5163
+ /* Push to right */
5068
5164
  }
5069
-
5070
- .dndev-pagination-ellipsis {
5071
- display: flex;
5072
- align-items: center;
5073
- justify-content: center;
5074
- width: var(--touch-target);
5075
- height: var(--touch-target);
5076
- color: var(--muted-foreground);
5077
5165
  }
5078
5166
 
5079
5167
  /* packages/components/src/atomic/Popover/Popover.css */
@@ -5646,50 +5734,214 @@ em {
5646
5734
  display: flex;
5647
5735
  flex-direction: column;
5648
5736
  z-index: var(--z-modal);
5649
- border-radius: var(--radius-floating); /* Square like floating panels */
5737
+ background: var(--card);
5738
+ /* Ensure background is opaque */
5739
+ color: var(--card-foreground);
5740
+ box-shadow: var(--shadow-xl);
5741
+ /* Focus Tunnel: Deep elevation */
5742
+ overflow: hidden;
5743
+ /* Scroll Trap: Container clips overflow */
5744
+
5745
+ /* Motion Physics: Base state */
5746
+ will-change: transform, opacity;
5650
5747
 
5651
- /* Sheet positioning by side */
5748
+ /* Open state animation - "Heavy" ease for premium feel */
5652
5749
  }
5653
5750
 
5751
+ .dndev-sheet-content[data-state='open'] {
5752
+ animation: sheet-slide-in var(--dur-heavy) var(--ease-heavy);
5753
+ }
5754
+
5755
+ /* Closed state animation */
5756
+
5757
+ .dndev-sheet-content[data-state='closed'] {
5758
+ animation: sheet-slide-out var(--dur-normal) var(--ease-in-out);
5759
+ }
5760
+
5761
+ /* Sheet positioning by side - SPATIAL METAPHOR */
5762
+
5763
+ /* RIGHT / LEFT (Desktop Panels) */
5764
+
5654
5765
  .dndev-sheet-content[data-side='right'],.dndev-sheet-content[data-side='left'] {
5655
5766
  top: 0;
5656
5767
  bottom: 0;
5657
5768
  width: 80%;
5658
5769
  max-width: 56rem;
5770
+ /* Standard panel width */
5771
+ height: 100%;
5772
+ /* Full height */
5773
+ border-radius: 0;
5774
+ /* Square edges for panel metaphor */
5659
5775
  }
5660
5776
 
5661
5777
  .dndev-sheet-content[data-side='right'] {
5778
+ /* Physical positioning: right edge */
5662
5779
  right: 0;
5780
+ left: auto;
5781
+ /* Border on logical start (left in LTR, right in RTL) */
5782
+ border-inline-start: var(--border-hairline) solid var(--line-1);
5663
5783
  }
5664
5784
 
5665
5785
  .dndev-sheet-content[data-side='left'] {
5786
+ /* Physical positioning: left edge */
5666
5787
  left: 0;
5788
+ right: auto;
5789
+ /* Border on logical end (right in LTR, left in RTL) */
5790
+ border-inline-end: var(--border-hairline) solid var(--line-1);
5667
5791
  }
5668
5792
 
5793
+ /* TOP / BOTTOM (Mobile Cards) */
5794
+
5669
5795
  .dndev-sheet-content[data-side='top'],.dndev-sheet-content[data-side='bottom'] {
5670
5796
  left: 0;
5671
5797
  right: 0;
5672
- height: 80%;
5673
- max-height: 56rem;
5674
- overflow: hidden;
5798
+ /* Card metaphor: Detached from opposite edge */
5799
+ height: auto;
5800
+ max-height: 92dvh;
5801
+ /* Never touch top edge */
5802
+ width: 100%;
5803
+ margin-left: auto;
5804
+ margin-right: auto;
5805
+
5806
+ /* On larger screens, constrain width */
5807
+ }
5808
+
5809
+ @media (width >=768px) {
5810
+
5811
+ .dndev-sheet-content[data-side='top'],.dndev-sheet-content[data-side='bottom'] {
5812
+ max-width: 56rem;
5813
+ width: 90%;
5814
+ border-radius: var(--radius-lg);
5815
+ /* Fully rounded card on desktop */
5675
5816
  }
5817
+ }
5676
5818
 
5677
5819
  .dndev-sheet-content[data-side='top'] {
5678
5820
  top: 0;
5821
+ border-bottom: var(--border-hairline) solid var(--line-1);
5822
+ /* Rounded bottom corners only */
5823
+ border-bottom-left-radius: var(--radius-lg);
5824
+ border-bottom-right-radius: var(--radius-lg);
5679
5825
  }
5680
5826
 
5681
5827
  .dndev-sheet-content[data-side='bottom'] {
5682
5828
  bottom: 0;
5829
+ border-top: var(--border-hairline) solid var(--line-1);
5830
+ /* Rounded top corners only */
5831
+ border-top-left-radius: var(--radius-lg);
5832
+ border-top-right-radius: var(--radius-lg);
5683
5833
  }
5684
5834
 
5835
+ /* DRAG HANDLE PILL - Visual affordance for draggable sheets */
5836
+
5837
+ .dndev-sheet-drag-handle {
5838
+ width: 2.5rem;
5839
+ height: 0.25rem;
5840
+ background: var(--line-2);
5841
+ border-radius: var(--radius-full);
5842
+ margin: var(--gap-sm) auto 0;
5843
+ flex-shrink: 0;
5844
+ cursor: grab;
5845
+ transition: background-color var(--dur-fast) var(--ease-in-out);
5846
+ }
5847
+
5848
+ .dndev-sheet-drag-handle:active {
5849
+ cursor: grabbing;
5850
+ }
5851
+
5852
+ /* Positioning for bottom sheets */
5853
+
5854
+ .dndev-sheet-content[data-side='bottom'] > .dndev-sheet-drag-handle {
5855
+ margin-top: var(--gap-sm);
5856
+ margin-bottom: 0;
5857
+ }
5858
+
5859
+ /* Positioning for top sheets */
5860
+
5861
+ .dndev-sheet-content[data-side='top'] > .dndev-sheet-drag-handle {
5862
+ margin-top: max(var(--gap-sm), env(safe-area-inset-top));
5863
+ margin-bottom: 0;
5864
+ }
5865
+
5866
+ /* HEADER - Pinned, No Padding (Tight Layout) */
5867
+
5868
+ /* Industry standard: Title always on start, X always on end (consistent across all sides) */
5869
+
5685
5870
  .dndev-sheet-header {
5686
5871
  display: flex;
5687
5872
  align-items: center;
5688
5873
  justify-content: space-between;
5689
5874
  gap: var(--gap-md);
5690
5875
  flex-shrink: 0;
5876
+ /* Never shrink */
5691
5877
  min-height: var(--touch-target);
5692
- margin-bottom: var(--gap-md);
5878
+ /* No padding - tight layout: [ Title X ] */
5879
+ padding-block: 0;
5880
+ /* RTL-aware: padding on logical start only */
5881
+ padding-inline-start: var(--gap-md);
5882
+ padding-inline-end: 0; /* X button has its own spacing */
5883
+ border-bottom: var(--border-hairline) solid var(--line-1);
5884
+ /* Separator */
5885
+
5886
+ /* Thumb Ergonomics: Top Safe Area (only for top sheets) */
5887
+ }
5888
+
5889
+ .dndev-sheet-content[data-side='top'] .dndev-sheet-header {
5890
+ padding-top: max(0, env(safe-area-inset-top));
5891
+ }
5892
+
5893
+ /* Adjust header padding when drag handle is present (sibling selector) */
5894
+
5895
+ .dndev-sheet-content[data-side='bottom']
5896
+ .dndev-sheet-drag-handle
5897
+ ~ .dndev-sheet-header,
5898
+ .dndev-sheet-content[data-side='top']
5899
+ .dndev-sheet-drag-handle
5900
+ ~ .dndev-sheet-header {
5901
+ padding-top: 0;
5902
+ }
5903
+
5904
+ /* BODY - Scrollable */
5905
+
5906
+ .dndev-sheet-body {
5907
+ flex: 1;
5908
+ /* Consumes available space */
5909
+ overflow-y: auto;
5910
+ /* Independent scroll */
5911
+ overflow-x: hidden;
5912
+ padding: var(--gap-md);
5913
+ overscroll-behavior: contain;
5914
+ /* Prevent body scroll chaining */
5915
+ }
5916
+
5917
+ /* FOOTER - Pinned */
5918
+
5919
+ .dndev-sheet-footer {
5920
+ flex-shrink: 0;
5921
+ /* Never shrink */
5922
+ padding: var(--gap-md);
5923
+ border-top: var(--border-hairline) solid var(--line-1);
5924
+ /* Separator */
5925
+ display: flex;
5926
+ flex-direction: column-reverse;
5927
+ /* Mobile-first stacking */
5928
+ gap: var(--gap-sm);
5929
+
5930
+ /* Desktop: Row layout */
5931
+ }
5932
+
5933
+ @media (width >=640px) {
5934
+
5935
+ .dndev-sheet-footer {
5936
+ flex-direction: row;
5937
+ justify-content: flex-end;
5938
+ }
5939
+ }
5940
+
5941
+ .dndev-sheet-footer {
5942
+
5943
+ /* Thumb Ergonomics: Bottom Safe Area (Home Indicator) */
5944
+ padding-bottom: max(var(--gap-md), env(safe-area-inset-bottom));
5693
5945
  }
5694
5946
 
5695
5947
  .dndev-sheet-title {
@@ -5699,9 +5951,12 @@ em {
5699
5951
  }
5700
5952
 
5701
5953
  .dndev-sheet-close {
5702
- position: absolute;
5703
- top: var(--gap-md);
5704
- inset-inline-end: var(--gap-md);
5954
+ /* Position relative - flex handles alignment */
5955
+ position: relative;
5956
+ margin-inline-start: auto;
5957
+ /* Push to end (RTL-aware: end = right in LTR, left in RTL) */
5958
+ margin-inline-end: var(--gap-sm);
5959
+ /* Spacing from edge - use margin not padding to keep icon centered */
5705
5960
  opacity: var(--opacity-muted);
5706
5961
  }
5707
5962
 
@@ -5709,9 +5964,56 @@ em {
5709
5964
  opacity: 1;
5710
5965
  }
5711
5966
 
5712
- .dndev-sheet-footer {
5713
- flex-shrink: 0;
5714
- margin-top: var(--gap-md);
5967
+ /* ===========================
5968
+ ANIMATIONS (Motion Physics)
5969
+ =========================== */
5970
+
5971
+ /* Slide In/Out Keyframes - Context Aware */
5972
+
5973
+ @keyframes sheet-slide-in {
5974
+ from {
5975
+ opacity: 0;
5976
+ transform: var(--slide-enter-transform);
5977
+ }
5978
+
5979
+ to {
5980
+ opacity: 1;
5981
+ transform: translate(0, 0);
5982
+ }
5983
+ }
5984
+
5985
+ @keyframes sheet-slide-out {
5986
+ from {
5987
+ opacity: 1;
5988
+ transform: translate(0, 0);
5989
+ }
5990
+
5991
+ to {
5992
+ opacity: 0;
5993
+ transform: var(--slide-exit-transform);
5994
+ }
5995
+ }
5996
+
5997
+ /* Define Transforms based on Side */
5998
+
5999
+ .dndev-sheet-content[data-side='right'] {
6000
+ --slide-enter-transform: translateX(100%);
6001
+ --slide-exit-transform: translateX(100%);
6002
+ }
6003
+
6004
+ .dndev-sheet-content[data-side='left'] {
6005
+ --slide-enter-transform: translateX(-100%);
6006
+ --slide-exit-transform: translateX(-100%);
6007
+ }
6008
+
6009
+ .dndev-sheet-content[data-side='bottom'] {
6010
+ --slide-enter-transform: translateY(100%);
6011
+ --slide-exit-transform: translateY(100%);
6012
+ }
6013
+
6014
+ .dndev-sheet-content[data-side='top'] {
6015
+ --slide-enter-transform: translateY(-100%);
6016
+ --slide-exit-transform: translateY(-100%);
5715
6017
  }
5716
6018
 
5717
6019
  /* packages/components/src/atomic/Skeleton/Skeleton.css */
@@ -6384,7 +6686,8 @@ em {
6384
6686
 
6385
6687
  .dndev-switch-label {
6386
6688
  font-size: var(--font-size-sm);
6387
- transition: color var(--dur-normal) var(--ease-in-out),
6689
+ transition:
6690
+ color var(--dur-normal) var(--ease-in-out),
6388
6691
  font-weight var(--dur-normal) var(--ease-in-out);
6389
6692
  white-space: nowrap;
6390
6693
  }
@@ -6393,16 +6696,14 @@ em {
6393
6696
 
6394
6697
  .dndev-switch-with-labels:not(:has(.dndev-switch[data-state='checked']))
6395
6698
  .dndev-switch-label-unchecked,
6396
- .dndev-switch-with-labels[data-checked='false']
6397
- .dndev-switch-label-unchecked {
6699
+ .dndev-switch-with-labels[data-checked='false'] .dndev-switch-label-unchecked {
6398
6700
  color: var(--foreground);
6399
6701
  font-weight: var(--font-weight-medium);
6400
6702
  }
6401
6703
 
6402
6704
  .dndev-switch-with-labels:has(.dndev-switch[data-state='checked'])
6403
6705
  .dndev-switch-label-unchecked,
6404
- .dndev-switch-with-labels[data-checked='true']
6405
- .dndev-switch-label-unchecked {
6706
+ .dndev-switch-with-labels[data-checked='true'] .dndev-switch-label-unchecked {
6406
6707
  color: var(--muted-foreground);
6407
6708
  font-weight: var(--font-weight-normal);
6408
6709
  }
@@ -6411,16 +6712,14 @@ em {
6411
6712
 
6412
6713
  .dndev-switch-with-labels:has(.dndev-switch[data-state='checked'])
6413
6714
  .dndev-switch-label-checked,
6414
- .dndev-switch-with-labels[data-checked='true']
6415
- .dndev-switch-label-checked {
6715
+ .dndev-switch-with-labels[data-checked='true'] .dndev-switch-label-checked {
6416
6716
  color: var(--foreground);
6417
6717
  font-weight: var(--font-weight-medium);
6418
6718
  }
6419
6719
 
6420
6720
  .dndev-switch-with-labels:not(:has(.dndev-switch[data-state='checked']))
6421
6721
  .dndev-switch-label-checked,
6422
- .dndev-switch-with-labels[data-checked='false']
6423
- .dndev-switch-label-checked {
6722
+ .dndev-switch-with-labels[data-checked='false'] .dndev-switch-label-checked {
6424
6723
  color: var(--muted-foreground);
6425
6724
  font-weight: var(--font-weight-normal);
6426
6725
  }
@@ -6443,7 +6742,21 @@ em {
6443
6742
  }
6444
6743
 
6445
6744
  .dndev-table-header {
6446
- /* Base header styles */
6745
+ background-color: var(--accent);
6746
+ }
6747
+
6748
+ /* Filter row above header */
6749
+
6750
+ .dndev-table-filter-row {
6751
+ border: 1px solid var(--border);
6752
+ border-bottom: none;
6753
+ }
6754
+
6755
+ .dndev-table-filter-row .dndev-table-head {
6756
+ background-color: var(--muted);
6757
+ padding: var(--gap-xs);
6758
+ height: auto;
6759
+ min-height: auto;
6447
6760
  }
6448
6761
 
6449
6762
  .dndev-table-body {
@@ -6461,6 +6774,12 @@ em {
6461
6774
  background-color: color-mix(in oklab, var(--accent) 15%, transparent);
6462
6775
  }
6463
6776
 
6777
+ /* Cursor pointer for clickable rows */
6778
+
6779
+ .dndev-table-row.dndev-cursor-pointer {
6780
+ cursor: pointer;
6781
+ }
6782
+
6464
6783
  /* Zebra striping for data tables */
6465
6784
 
6466
6785
  .dndev-table-body .dndev-table-row:nth-child(even) {
@@ -6499,22 +6818,34 @@ em {
6499
6818
  padding-block: var(--gap-sm);
6500
6819
  }
6501
6820
 
6502
- .dndev-table-head[data-sortable='true'] {
6821
+ /* Header cells use accent foreground for contrast */
6822
+
6823
+ .dndev-table-header .dndev-table-head {
6824
+ color: var(--accent-foreground);
6825
+ }
6826
+
6827
+ [data-sortable='true']:is(.dndev-table-header .dndev-table-head) {
6503
6828
  cursor: pointer;
6504
6829
  }
6505
6830
 
6506
- .dndev-table-head[data-align='center'] {
6831
+ [data-align='center']:is(.dndev-table-header .dndev-table-head) {
6507
6832
  text-align: center;
6508
6833
  }
6509
6834
 
6510
- .dndev-table-head[data-align='end'] {
6835
+ [data-align='end']:is(.dndev-table-header .dndev-table-head) {
6511
6836
  text-align: end;
6512
6837
  }
6513
6838
 
6514
- .dndev-table-head[data-align='start'] {
6839
+ [data-align='start']:is(.dndev-table-header .dndev-table-head) {
6515
6840
  text-align: start;
6516
6841
  }
6517
6842
 
6843
+ /* Active filter indicator */
6844
+
6845
+ .dndev-table-filter-active {
6846
+ color: var(--primary);
6847
+ }
6848
+
6518
6849
  /* Table cell (td) styles */
6519
6850
 
6520
6851
  .dndev-table-cell {
@@ -6522,6 +6853,7 @@ em {
6522
6853
  padding-inline: var(--gap-md);
6523
6854
  padding-block: var(--gap-sm);
6524
6855
  min-height: var(--touch-target);
6856
+ line-height: 1.5; /* Ensure consistent line height for empty cells */
6525
6857
  }
6526
6858
 
6527
6859
  .dndev-table-cell[data-align='center'] {
@@ -6555,8 +6887,8 @@ em {
6555
6887
  /* Input components inside grid cells should be borderless and fit snugly */
6556
6888
 
6557
6889
  .dndev-table-grid .dndev-table-cell .dndev-input,
6558
- .dndev-table-grid .dndev-table-cell input[type="text"],
6559
- .dndev-table-grid .dndev-table-cell input[type="number"] {
6890
+ .dndev-table-grid .dndev-table-cell input[type='text'],
6891
+ .dndev-table-grid .dndev-table-cell input[type='number'] {
6560
6892
  border: none;
6561
6893
  background: transparent;
6562
6894
  width: 100%;
@@ -6600,6 +6932,64 @@ em {
6600
6932
  padding-inline-start: calc(var(--gap-md) + var(--icon-md) + var(--gap-sm));
6601
6933
  }
6602
6934
 
6935
+ /* Skeleton rows - apply standard skeleton pulse animation to entire rows */
6936
+
6937
+ /* Keep existing background colors (zebra striping) - just add opacity pulse */
6938
+
6939
+ .dndev-table-body .dndev-table-row.dndev-skeleton-row {
6940
+ animation: dndev-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
6941
+ pointer-events: none;
6942
+
6943
+ /* Keep hover state but disabled (pointer-events: none prevents hover) */
6944
+ }
6945
+
6946
+ :is(.dndev-table-body .dndev-table-row.dndev-skeleton-row):hover {
6947
+ /* Inherit from parent .dndev-table-row hover styles */
6948
+ }
6949
+
6950
+ /* Even rows keep their var(--muted) background, just pulse */
6951
+
6952
+ .dndev-table-body .dndev-table-row.dndev-skeleton-row:nth-child(even) {
6953
+ animation: dndev-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
6954
+ }
6955
+
6956
+ :is(.dndev-table-body .dndev-table-row.dndev-skeleton-row:nth-child(even)):hover {
6957
+ /* Inherit from parent .dndev-table-row:nth-child(even) hover styles */
6958
+ }
6959
+
6960
+ /* Skeleton bars inside cells - adapt to row background for visibility */
6961
+
6962
+ /* Odd rows (transparent background): use default var(--muted) skeleton */
6963
+
6964
+ /* Even rows (var(--muted) background): use lighter skeleton for contrast */
6965
+
6966
+ .dndev-table-body .dndev-table-row.dndev-skeleton-row .dndev-skeleton {
6967
+ background-color: var(--muted);
6968
+ }
6969
+
6970
+ .dndev-table-body
6971
+ .dndev-table-row.dndev-skeleton-row:nth-child(even)
6972
+ .dndev-skeleton {
6973
+ /* Even rows have var(--muted) background, so skeleton should be lighter for contrast */
6974
+ background-color: color-mix(
6975
+ in oklab,
6976
+ var(--muted) 60%,
6977
+ var(--foreground) 40%
6978
+ );
6979
+ }
6980
+
6981
+ /* Use the same pulse animation as standard skeleton (from Skeleton.css) */
6982
+
6983
+ @keyframes dndev-pulse {
6984
+ 0%,
6985
+ 100% {
6986
+ opacity: 1;
6987
+ }
6988
+ 50% {
6989
+ opacity: var(--opacity-muted);
6990
+ }
6991
+ }
6992
+
6603
6993
  /* packages/components/src/atomic/Tabs/Tabs.css */
6604
6994
 
6605
6995
  /* Tabs list: use flexbox for natural wrapping, not grid */
@@ -8159,6 +8549,10 @@ h4[data-variant='code'] {
8159
8549
  pointer-events: auto;
8160
8550
  }
8161
8551
 
8552
+ .dndev-cursor-pointer {
8553
+ cursor: pointer;
8554
+ }
8555
+
8162
8556
  .dndev-aspect-video {
8163
8557
  aspect-ratio: 16 / 9;
8164
8558
  }
@@ -8535,6 +8929,7 @@ h4[data-variant='code'] {
8535
8929
  from {
8536
8930
  opacity: 1;
8537
8931
  }
8932
+
8538
8933
  to {
8539
8934
  opacity: 0;
8540
8935
  }
@@ -8544,6 +8939,7 @@ h4[data-variant='code'] {
8544
8939
  from {
8545
8940
  opacity: 0;
8546
8941
  }
8942
+
8547
8943
  to {
8548
8944
  opacity: 1;
8549
8945
  }
@@ -8556,6 +8952,7 @@ h4[data-variant='code'] {
8556
8952
  opacity: 1;
8557
8953
  transform: translateX(0);
8558
8954
  }
8955
+
8559
8956
  to {
8560
8957
  opacity: 0;
8561
8958
  transform: translateX(-100%);
@@ -8567,6 +8964,7 @@ h4[data-variant='code'] {
8567
8964
  opacity: 0;
8568
8965
  transform: translateX(100%);
8569
8966
  }
8967
+
8570
8968
  to {
8571
8969
  opacity: 1;
8572
8970
  transform: translateX(0);
@@ -8641,7 +9039,7 @@ main[role='main'][data-routing-animation='none'] {
8641
9039
 
8642
9040
  /* Tablet (768px - 1023px) */
8643
9041
 
8644
- @media (width >= 768px) and (width <= 1023px) {
9042
+ @media (width >=768px) and (width <=1023px) {
8645
9043
  main[role='main'][data-routing-animation='fade'] {
8646
9044
  animation: routeFadeIn
8647
9045
  var(--routing-tablet-duration, var(--routing-default-duration, 300ms))
@@ -8657,7 +9055,7 @@ main[role='main'][data-routing-animation='none'] {
8657
9055
 
8658
9056
  /* Desktop (1024px - 1439px) */
8659
9057
 
8660
- @media (width >= 1024px) and (width <= 1439px) {
9058
+ @media (width >=1024px) and (width <=1439px) {
8661
9059
  main[role='main'][data-routing-animation='fade'] {
8662
9060
  animation: routeFadeIn
8663
9061
  var(--routing-desktop-duration, var(--routing-default-duration, 300ms))
@@ -8673,7 +9071,7 @@ main[role='main'][data-routing-animation='none'] {
8673
9071
 
8674
9072
  /* Wide (>= 1440px) */
8675
9073
 
8676
- @media (width >= 1440px) {
9074
+ @media (width >=1440px) {
8677
9075
  main[role='main'][data-routing-animation='fade'] {
8678
9076
  animation: routeFadeIn
8679
9077
  var(--routing-wide-duration, var(--routing-default-duration, 300ms))
@@ -8706,7 +9104,7 @@ main[role='main'][data-routing-animation='none'] {
8706
9104
 
8707
9105
  /* Mobile/Tablet: Hide sidebars - WCAG & Lighthouse best practices */
8708
9106
 
8709
- @media (width <= 1023px) {
9107
+ @media (width <=1023px) {
8710
9108
  .dndev-layout aside[role='navigation'].sidebar,
8711
9109
  aside[role='navigation'].sidebar {
8712
9110
  display: none !important;
@@ -8725,10 +9123,7 @@ main[role='main'][data-routing-animation='none'] {
8725
9123
  max-height: 100dvh;
8726
9124
  overflow: hidden;
8727
9125
  display: grid;
8728
- /* ONE DRY grid structure: 3 rows, 2 columns */
8729
- /* Footer starts at sidebar edge (column 2) - when sidebar-width is 0px, footer starts at left edge */
8730
- /* Footer grows with content wrapping. For pixel-perfect calc() accuracy when footer wraps,
8731
- implement ResizeObserver to update --footer-height dynamically. */
9126
+ /* Grid structure: 3 rows, 2 columns */
8732
9127
  grid-template-areas:
8733
9128
  'header header'
8734
9129
  'sidebar main'
@@ -8739,16 +9134,58 @@ main[role='main'][data-routing-animation='none'] {
8739
9134
  );
8740
9135
  grid-template-columns: var(--sidebar-width) 1fr;
8741
9136
 
8742
- /* Game layout: Grid rows adjust based on breakpoint (footer hidden on tablet/mobile) */
9137
+ /* Mobile: Grid scrolls instead of main - footer scrolls with content */
8743
9138
  }
8744
9139
 
8745
- [data-layout='game']:root .dndev-layout {
8746
- grid-template-rows: var(--header-height) 1fr minmax(
8747
- var(--footer-height),
8748
- auto
8749
- );
9140
+ @media (width <=1023px) {
9141
+
9142
+ .dndev-layout {
9143
+ overflow-y: auto;
9144
+ overflow-x: hidden;
9145
+ /* Keep footer row - grid scrolls so footer scrolls with content */
9146
+ grid-template-areas:
9147
+ 'header header'
9148
+ 'sidebar main'
9149
+ 'footer footer';
9150
+ grid-template-rows: var(--header-height) min-content auto;
9151
+ }
8750
9152
  }
8751
9153
 
9154
+ /* Footer scroll mode - grid scrolls, footer scrolls with content (opt-in for desktop) */
9155
+
9156
+ .dndev-layout[data-footer-mode='scroll'] {
9157
+ overflow-y: auto;
9158
+ overflow-x: hidden;
9159
+ grid-template-rows: var(--header-height) min-content auto;
9160
+ }
9161
+
9162
+ .dndev-layout[data-footer-mode='scroll'] header[role='banner'] {
9163
+ position: sticky;
9164
+ top: 0;
9165
+ }
9166
+
9167
+ .dndev-layout[data-footer-mode='scroll'] main[role='main'] {
9168
+ overflow: visible;
9169
+ min-height: -moz-min-content;
9170
+ min-height: min-content;
9171
+ }
9172
+
9173
+ .dndev-layout[data-footer-mode='scroll'] footer[role='contentinfo'] {
9174
+ height: auto;
9175
+ }
9176
+
9177
+ :is(.dndev-layout[data-footer-mode='scroll'] footer[role='contentinfo']) > * {
9178
+ height: auto;
9179
+ min-height: var(--footer-height);
9180
+ }
9181
+
9182
+ /* Presets with no footer at all */
9183
+
9184
+ [data-layout='moolti'] footer[role='contentinfo'],
9185
+ [data-layout='plain'] footer[role='contentinfo'] {
9186
+ display: none;
9187
+ }
9188
+
8752
9189
  /* ===========================
8753
9190
  LAYOUT ZONE POSITIONING RULES
8754
9191
  Follows logical flow: Header → Sidebar → Main → Footer
@@ -8762,6 +9199,8 @@ header[role='banner'] {
8762
9199
  grid-area: header;
8763
9200
  box-sizing: border-box;
8764
9201
  height: var(--header-height);
9202
+ min-height: var(--header-height);
9203
+ max-height: var(--header-height);
8765
9204
  position: relative;
8766
9205
  z-index: var(--z-header);
8767
9206
  contain: layout style;
@@ -8781,14 +9220,26 @@ header[role='banner'] {
8781
9220
  /* Theme-aware styling - 100% controlled by theme system */
8782
9221
  background: var(--background);
8783
9222
  border-bottom: var(--border-hairline) solid var(--border);
9223
+
9224
+ /* Mobile: Sticky header (for presets that keep header visible) */
8784
9225
  }
8785
9226
 
9227
+ @media (width <=1023px) {
9228
+
9229
+ header[role='banner'] {
9230
+ position: sticky;
9231
+ top: 0;
9232
+ }
9233
+ }
9234
+
8786
9235
  .header-start {
8787
9236
  display: flex;
8788
9237
  align-items: center;
8789
9238
  flex-shrink: 0;
8790
9239
  height: 100%;
9240
+ max-height: 100%;
8791
9241
  gap: var(--gap-sm);
9242
+ overflow: hidden;
8792
9243
  }
8793
9244
 
8794
9245
  .header-end {
@@ -8796,8 +9247,11 @@ header[role='banner'] {
8796
9247
  align-items: center;
8797
9248
  justify-content: flex-end;
8798
9249
  flex-shrink: 0;
9250
+ height: 100%;
9251
+ max-height: 100%;
8799
9252
  margin-inline-start: auto;
8800
9253
  gap: var(--gap-sm);
9254
+ overflow: hidden;
8801
9255
  }
8802
9256
 
8803
9257
  /* Viewport-centered center content - absolutely positioned overlay */
@@ -8831,19 +9285,20 @@ header[role='banner'] .header-center {
8831
9285
  aside[role='navigation'].sidebar {
8832
9286
  grid-area: sidebar;
8833
9287
  box-sizing: border-box;
8834
- min-width: calc(
8835
- var(--sidebar-resize-handle-width) + 48px
8836
- ); /* Min: 48px content + 6px handle = 54px */
8837
- max-width: calc(
8838
- var(--sidebar-resize-handle-width) + 400px
8839
- ); /* Max: 400px content + 6px handle = 406px */
9288
+ min-width: calc(var(--sidebar-resize-handle-width) + 48px);
9289
+ /* Min: 48px content + 6px handle = 54px */
9290
+ max-width: calc(var(--sidebar-resize-handle-width) + 400px);
9291
+ /* Max: 400px content + 6px handle = 406px */
8840
9292
  z-index: var(--z-sidebar);
8841
- overflow: none; /* No clipping needed - handle is in grid */
9293
+ overflow: none;
9294
+ /* No clipping needed - handle is in grid */
8842
9295
  contain: layout style;
8843
9296
  padding: 0;
8844
9297
  display: grid;
8845
- grid-template-columns: auto var(--sidebar-resize-handle-width); /* Content | Handle - column 1 width set inline */
8846
- grid-template-rows: auto 1fr auto; /* Top | Content | Bottom */
9298
+ grid-template-columns: auto var(--sidebar-resize-handle-width);
9299
+ /* Content | Handle - column 1 width set inline */
9300
+ grid-template-rows: auto 1fr auto;
9301
+ /* Top | Content | Bottom */
8847
9302
  height: 100%;
8848
9303
 
8849
9304
  /* Theme-aware styling - 100% controlled by theme system */
@@ -8898,7 +9353,8 @@ aside[role='navigation'].sidebar[data-dragging='true']
8898
9353
 
8899
9354
  @media (hover: none) {
8900
9355
  aside[role='navigation'].sidebar .dndev-sidebar-resize-handle {
8901
- width: calc(var(--sidebar-resize-handle-width) * 2); /* 12px for touch */
9356
+ width: calc(var(--sidebar-resize-handle-width) * 2);
9357
+ /* 12px for touch */
8902
9358
  }
8903
9359
  }
8904
9360
 
@@ -8967,7 +9423,8 @@ aside[role='navigation'].sidebar[data-dragging='true']
8967
9423
  .sidebar-content .dndev-interactive[data-role='menu-item'],.sidebar-content .dndev-interactive[data-role='nav-trigger'] {
8968
9424
  height: var(--touch-target);
8969
9425
  min-height: var(--touch-target);
8970
- padding-block: 0; /* No vertical padding - buttons fill exact 48px */
9426
+ padding-block: 0;
9427
+ /* No vertical padding - buttons fill exact 48px */
8971
9428
  }
8972
9429
 
8973
9430
  /* Other interactive elements (not menu items) - consistent padding */
@@ -9007,7 +9464,8 @@ aside.sidebar[role='navigation'] .sidebar-top,aside.sidebar[role='navigation'] .
9007
9464
  }
9008
9465
 
9009
9466
  aside.sidebar[role='navigation'] .sidebar-content {
9010
- overflow-x: hidden; /* Prevent horizontal scroll, allow vertical */
9467
+ overflow-x: hidden;
9468
+ /* Prevent horizontal scroll, allow vertical */
9011
9469
  }
9012
9470
 
9013
9471
  aside.sidebar[role='navigation'] .dndev-interactive {
@@ -9072,12 +9530,9 @@ aside.sidebar[role='navigation'][data-collapsed='true'] .app-branding {
9072
9530
  main[role='main'] {
9073
9531
  grid-area: main;
9074
9532
  overflow-y: auto;
9075
- /* Default: allow scrolling */
9076
9533
  overflow-x: hidden;
9077
- /* Prevent horizontal scroll from breakthrough components */
9078
9534
  display: flex;
9079
9535
  flex-direction: column;
9080
- /* No automatic padding; spacing handled by gaps */
9081
9536
  padding: 0;
9082
9537
  contain: layout style;
9083
9538
 
@@ -9086,12 +9541,17 @@ main[role='main'] {
9086
9541
 
9087
9542
  main[role='main'] > *:not(.breadcrumbs-container):first-of-type,main[role='main'] > .breadcrumbs-container + * {
9088
9543
  flex: 1 1 auto;
9089
- /* Page content grows */
9090
9544
  }
9091
9545
 
9092
- main[role='main'] > *:last-child {
9093
- flex-shrink: 0;
9094
- /* Footer stays at bottom */
9546
+ /* Mobile: Grid scrolls, main doesn't */
9547
+
9548
+ @media (width <=1023px) {
9549
+
9550
+ main[role='main'] {
9551
+ overflow: visible;
9552
+ min-height: -moz-min-content;
9553
+ min-height: min-content;
9554
+ }
9095
9555
  }
9096
9556
 
9097
9557
  /* Footer: Full width by default, app presets start after sidebar */
@@ -9126,31 +9586,25 @@ footer[role='contentinfo'] > * {
9126
9586
  padding-inline-end: var(--content-padding);
9127
9587
  }
9128
9588
 
9129
- /* Game: Hide footer on tablet/mobile - merged into GameMergedBar */
9589
+ /* Mobile: Allow footer to grow when content wraps */
9130
9590
 
9131
- @media (width <= 1023px) {
9132
- [data-layout='game']:root footer[role='contentinfo'] {
9133
- display: none;
9134
- }
9135
- }
9591
+ @media (width <=1023px) {
9136
9592
 
9137
- /* Moolti: No footer (built into sidebar) */
9138
-
9139
- [data-layout='moolti']:root footer[role='contentinfo'] {
9140
- display: none;
9141
- }
9142
-
9143
- /* Plain: No footer (full-screen apps) */
9593
+ footer[role='contentinfo'] {
9594
+ height: auto;
9595
+ }
9144
9596
 
9145
- [data-layout='plain']:root footer[role='contentinfo'] {
9146
- display: none;
9597
+ footer[role='contentinfo'] > * {
9598
+ height: auto;
9599
+ min-height: var(--footer-height);
9600
+ }
9147
9601
  }
9148
9602
 
9149
9603
  /* Footer text styles */
9150
9604
 
9151
9605
  footer[role='contentinfo'] .footer-copyright {
9152
9606
  color: var(--muted-foreground);
9153
- font-size: var(--font-size-sm);
9607
+ font-size: var(--font-size-xs);
9154
9608
  }
9155
9609
 
9156
9610
  footer[role='contentinfo'] a:not(.dndev-interactive) {
@@ -9190,7 +9644,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9190
9644
 
9191
9645
  .merged-bar[data-position='top'] {
9192
9646
  top: 0;
9193
- height: 64px;
9647
+ height: var(--header-height);
9194
9648
  border-bottom: 2px solid var(--border);
9195
9649
  padding-top: env(safe-area-inset-top);
9196
9650
  }
@@ -9218,9 +9672,9 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9218
9672
  min-height: 0;
9219
9673
  }
9220
9674
 
9221
- /* Mobile (<1024px): Show merged-bar, hide zones, add padding */
9675
+ /* Mobile (<1024px): Show merged-bar, hide zones */
9222
9676
 
9223
- @media (width <= 1023px) {
9677
+ @media (width <=1023px) {
9224
9678
  /* Presets with mergedBar: top (admin, moolti, game, docs) */
9225
9679
  [data-layout='admin'] .merged-bar[data-position='top'],
9226
9680
  [data-layout='moolti'] .merged-bar[data-position='top'],
@@ -9233,7 +9687,8 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9233
9687
  [data-layout='moolti'] .dndev-layout,
9234
9688
  [data-layout='game'] .dndev-layout,
9235
9689
  [data-layout='docs'] .dndev-layout {
9236
- padding-top: calc(64px + env(safe-area-inset-top));
9690
+ /* Remove padding-top - grid already accounts for header-height, mergedBar is fixed and doesn't affect grid flow */
9691
+ /* Content won't go under mergedBar because grid positions main after header row */
9237
9692
  }
9238
9693
 
9239
9694
  [data-layout='admin'] header[role='banner'],
@@ -9259,7 +9714,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9259
9714
 
9260
9715
  /* Desktop (>=1024px): Always hide merged-bar */
9261
9716
 
9262
- @media (width >= 1024px) {
9717
+ @media (width >=1024px) {
9263
9718
  .merged-bar {
9264
9719
  display: none !important;
9265
9720
  }
@@ -9283,7 +9738,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9283
9738
  /* Admin: Mobile/Tablet (<1024px) - only overrides */
9284
9739
  }
9285
9740
 
9286
- @media (width <= 1023px) {
9741
+ @media (width <=1023px) {
9287
9742
 
9288
9743
  [data-layout='admin'] {
9289
9744
  --sidebar-width: 0px;
@@ -9314,7 +9769,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9314
9769
 
9315
9770
  /* Moolti: Mobile/Tablet (<1024px) - only overrides */
9316
9771
 
9317
- @media (width <= 1023px) {
9772
+ @media (width <=1023px) {
9318
9773
 
9319
9774
  [data-layout='moolti'] {
9320
9775
  --header-height: 62px;
@@ -9341,7 +9796,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9341
9796
 
9342
9797
  /* Docs: Mobile/Tablet (<1024px) - only overrides */
9343
9798
 
9344
- @media (width <= 1023px) {
9799
+ @media (width <=1023px) {
9345
9800
 
9346
9801
  [data-layout='docs'] {
9347
9802
  --sidebar-width: 0px;
@@ -9367,7 +9822,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9367
9822
  /* Blog: Mobile/Tablet (<1024px) - only overrides */
9368
9823
  }
9369
9824
 
9370
- @media (width <= 1023px) {
9825
+ @media (width <=1023px) {
9371
9826
 
9372
9827
  [data-layout='blog'] {
9373
9828
  --header-height: 0px;
@@ -9417,7 +9872,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9417
9872
  /* Game: Mobile/Tablet (<1024px) - only overrides */
9418
9873
  }
9419
9874
 
9420
- @media (width <= 1023px) {
9875
+ @media (width <=1023px) {
9421
9876
 
9422
9877
  [data-layout='game'] {
9423
9878
  --footer-height: 0px;
@@ -9538,7 +9993,14 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9538
9993
  padding-top: var(--gap-lg);
9539
9994
  }
9540
9995
 
9996
+ /* First Section child gets gap-md spacing from top */
9997
+
9998
+ .dndev-container > .dndev-section-full-width:first-child {
9999
+ margin-top: var(--gap-md);
10000
+ }
10001
+
9541
10002
  .dndev-container {
10003
+
9542
10004
  min-height: 0;
9543
10005
  display: flex;
9544
10006
  flex-direction: column;
@@ -9573,7 +10035,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9573
10035
  --max-content-width: 100%;
9574
10036
  }
9575
10037
 
9576
- @media (width >= 1024px) {
10038
+ @media (width >=1024px) {
9577
10039
 
9578
10040
  .dndev-container[data-variant='standard'] {
9579
10041
  --max-content-width: 87.5rem;
@@ -9588,7 +10050,7 @@ footer[role='contentinfo'] a:not(.dndev-interactive):hover {
9588
10050
  --max-content-width: 100%;
9589
10051
  }
9590
10052
 
9591
- @media (width >= 1024px) {
10053
+ @media (width >=1024px) {
9592
10054
 
9593
10055
  .dndev-container[data-variant='docs'] {
9594
10056
  --max-content-width: 56.25rem;