@duskmoon-dev/core 1.19.4 → 1.19.6

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 (42) hide show
  1. package/README.md +1 -1
  2. package/dist/components/alert.css +81 -3
  3. package/dist/components/dialog.css +29 -3
  4. package/dist/components/dropdown.css +91 -0
  5. package/dist/components/fab.css +182 -0
  6. package/dist/components/index.css +1119 -232
  7. package/dist/components/loading.css +105 -0
  8. package/dist/components/modal.css +66 -4
  9. package/dist/components/navigation.css +94 -54
  10. package/dist/components/progress.css +74 -0
  11. package/dist/components/radial-progress.css +47 -0
  12. package/dist/components/skeleton.css +13 -1
  13. package/dist/components/snackbar.css +48 -18
  14. package/dist/components/swap.css +116 -0
  15. package/dist/components/toast.css +188 -34
  16. package/dist/components/tooltip.css +2 -47
  17. package/dist/esm/components/alert.js +81 -3
  18. package/dist/esm/components/dialog.js +29 -3
  19. package/dist/esm/components/dropdown.d.ts +5 -0
  20. package/dist/esm/components/dropdown.js +100 -0
  21. package/dist/esm/components/fab.d.ts +5 -0
  22. package/dist/esm/components/fab.js +191 -0
  23. package/dist/esm/components/loading.d.ts +5 -0
  24. package/dist/esm/components/loading.js +114 -0
  25. package/dist/esm/components/modal.js +66 -4
  26. package/dist/esm/components/navigation.js +94 -54
  27. package/dist/esm/components/progress.js +74 -0
  28. package/dist/esm/components/radial-progress.d.ts +5 -0
  29. package/dist/esm/components/radial-progress.js +56 -0
  30. package/dist/esm/components/skeleton.js +13 -1
  31. package/dist/esm/components/snackbar.js +48 -18
  32. package/dist/esm/components/swap.d.ts +5 -0
  33. package/dist/esm/components/swap.js +125 -0
  34. package/dist/esm/components/toast.js +188 -34
  35. package/dist/esm/components/tooltip.js +2 -47
  36. package/dist/index.css +1119 -232
  37. package/dist/index.min.css +1 -1
  38. package/dist/standalone/duskmoonui-themes.css +1 -1
  39. package/dist/standalone/duskmoonui.css +1120 -233
  40. package/dist/standalone/duskmoonui.js +25 -9
  41. package/dist/standalone/duskmoonui.mjs +25 -9
  42. package/package.json +31 -1
package/dist/index.css CHANGED
@@ -1695,6 +1695,308 @@ html {
1695
1695
  }
1696
1696
 
1697
1697
 
1698
+ /* Action composition components */
1699
+ /**
1700
+ * FAB / Speed Dial Component Styles
1701
+ *
1702
+ * FAB owns viewport placement and action layout. Pair its trigger and actions
1703
+ * with Button classes for color, interaction, and disabled states.
1704
+ */
1705
+
1706
+ @layer components {
1707
+ .fab {
1708
+ --fab-offset-block: 1rem;
1709
+ --fab-offset-inline: 1rem;
1710
+ --fab-gap: 0.75rem;
1711
+ --fab-size: 3.5rem;
1712
+
1713
+ position: fixed;
1714
+ inset-block-end: calc(var(--fab-offset-block) + env(safe-area-inset-bottom, 0px));
1715
+ inset-inline-end: calc(var(--fab-offset-inline) + env(safe-area-inset-right, 0px));
1716
+ z-index: 40;
1717
+ display: inline-flex;
1718
+ flex-direction: column-reverse;
1719
+ align-items: flex-end;
1720
+ gap: var(--fab-gap);
1721
+ max-inline-size: calc(100dvw - 2 * var(--fab-offset-inline));
1722
+ }
1723
+
1724
+ .fab-start {
1725
+ inset-inline-start: calc(var(--fab-offset-inline) + env(safe-area-inset-left, 0px));
1726
+ inset-inline-end: auto;
1727
+ align-items: flex-start;
1728
+ }
1729
+
1730
+ .fab-contained {
1731
+ position: absolute;
1732
+ }
1733
+
1734
+ .fab-speed-dial {
1735
+ flex-direction: column-reverse;
1736
+ }
1737
+
1738
+ .fab-trigger {
1739
+ min-inline-size: var(--fab-size);
1740
+ min-block-size: var(--fab-size);
1741
+ padding: 0.875rem;
1742
+ border-radius: var(--radius-lg);
1743
+ box-shadow: var(--shadow-lg);
1744
+ }
1745
+
1746
+ .fab-trigger:not(.fab-extended) {
1747
+ inline-size: var(--fab-size);
1748
+ block-size: var(--fab-size);
1749
+ }
1750
+
1751
+ .fab-extended {
1752
+ inline-size: auto;
1753
+ max-inline-size: 100%;
1754
+ min-block-size: var(--fab-size);
1755
+ padding-inline: 1.25rem;
1756
+ border-radius: var(--radius-lg);
1757
+ }
1758
+
1759
+ .fab-actions {
1760
+ align-items: flex-end;
1761
+ flex-direction: column-reverse;
1762
+ gap: var(--fab-gap);
1763
+ max-inline-size: min(22rem, calc(100dvw - 2rem));
1764
+ }
1765
+
1766
+ .fab-start .fab-actions {
1767
+ align-items: flex-start;
1768
+ }
1769
+
1770
+ /* Controlled mode: application code owns .fab-open and all ARIA state. */
1771
+ .fab-controlled > .fab-actions:not([popover]) {
1772
+ display: none;
1773
+ }
1774
+
1775
+ .fab-controlled.fab-open > .fab-actions:not([popover]) {
1776
+ display: flex;
1777
+ }
1778
+
1779
+ /* Native mode: the browser's popover state is the sole authority. */
1780
+ .fab-actions[popover] {
1781
+ display: none;
1782
+ position: fixed;
1783
+ inset-block-start: auto;
1784
+ inset-block-end: calc(
1785
+ var(--fab-offset-block, 1rem) + env(safe-area-inset-bottom, 0px) +
1786
+ var(--fab-size, 3.5rem) + var(--fab-gap, 0.75rem)
1787
+ );
1788
+ inset-inline-start: auto;
1789
+ inset-inline-end: calc(var(--fab-offset-inline, 1rem) + env(safe-area-inset-right, 0px));
1790
+ margin: 0;
1791
+ padding: 0;
1792
+ border: 0;
1793
+ overflow: visible;
1794
+ color: inherit;
1795
+ background: transparent;
1796
+ opacity: 0;
1797
+ visibility: hidden;
1798
+ pointer-events: none;
1799
+ transform: translateY(0.5rem);
1800
+ transition:
1801
+ opacity 150ms ease-out,
1802
+ transform 150ms ease-out,
1803
+ overlay 150ms ease-out allow-discrete,
1804
+ display 150ms ease-out allow-discrete;
1805
+ }
1806
+
1807
+ .fab-start > .fab-actions[popover] {
1808
+ inset-inline-start: calc(var(--fab-offset-inline, 1rem) + env(safe-area-inset-left, 0px));
1809
+ inset-inline-end: auto;
1810
+ }
1811
+
1812
+ .fab-actions[popover]:popover-open {
1813
+ display: flex;
1814
+ opacity: 1;
1815
+ visibility: visible;
1816
+ pointer-events: auto;
1817
+ transform: translateY(0);
1818
+ }
1819
+
1820
+ @starting-style {
1821
+ .fab-actions[popover]:popover-open {
1822
+ opacity: 0;
1823
+ transform: translateY(0.5rem);
1824
+ }
1825
+ }
1826
+
1827
+ @supports (position-area: top) {
1828
+ .fab-actions[popover] {
1829
+ inset: auto;
1830
+ margin: var(--fab-gap, 0.75rem);
1831
+ position-area: top span-left;
1832
+ position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
1833
+ }
1834
+
1835
+ .fab-start > .fab-actions[popover] {
1836
+ inset: auto;
1837
+ position-area: top span-right;
1838
+ }
1839
+ }
1840
+
1841
+ .fab-action {
1842
+ display: inline-flex;
1843
+ align-items: center;
1844
+ justify-content: flex-end;
1845
+ gap: 0.5rem;
1846
+ max-inline-size: 100%;
1847
+ }
1848
+
1849
+ .fab-start .fab-action {
1850
+ flex-direction: row-reverse;
1851
+ }
1852
+
1853
+ .fab-label {
1854
+ max-inline-size: min(16rem, calc(100dvw - 6rem));
1855
+ padding: 0.375rem 0.625rem;
1856
+ overflow-wrap: anywhere;
1857
+ color: var(--color-on-surface);
1858
+ background-color: var(--color-surface-container-high);
1859
+ border: 1px solid var(--color-outline-variant);
1860
+ border-radius: var(--radius-sm);
1861
+ box-shadow: var(--shadow-sm);
1862
+ font-size: 0.8125rem;
1863
+ font-weight: 500;
1864
+ line-height: 1.125rem;
1865
+ }
1866
+
1867
+ @media (max-width: 30rem) {
1868
+ .fab {
1869
+ --fab-offset-block: 0.75rem;
1870
+ --fab-offset-inline: 0.75rem;
1871
+ }
1872
+ }
1873
+
1874
+ @media (prefers-reduced-motion: reduce) {
1875
+ .fab-actions[popover] {
1876
+ transition: none;
1877
+ transform: none;
1878
+ }
1879
+ }
1880
+ }
1881
+
1882
+ /**
1883
+ * Swap Component Styles
1884
+ * Displays one of two non-interactive state indicators.
1885
+ */
1886
+
1887
+ @layer components {
1888
+ .swap {
1889
+ position: relative;
1890
+ display: inline-grid;
1891
+ place-items: center;
1892
+ vertical-align: middle;
1893
+ cursor: pointer;
1894
+ user-select: none;
1895
+ }
1896
+
1897
+ .swap-input {
1898
+ position: absolute;
1899
+ inset: 0;
1900
+ z-index: 1;
1901
+ width: 100%;
1902
+ height: 100%;
1903
+ margin: 0;
1904
+ opacity: 0;
1905
+ cursor: pointer;
1906
+ }
1907
+
1908
+ .swap-on,
1909
+ .swap-off {
1910
+ grid-area: 1 / 1;
1911
+ display: inline-flex;
1912
+ align-items: center;
1913
+ justify-content: center;
1914
+ inline-size: max-content;
1915
+ max-inline-size: 100%;
1916
+ transition: opacity 150ms ease-out, transform 150ms ease-out;
1917
+ }
1918
+
1919
+ .swap-on {
1920
+ opacity: 0;
1921
+ visibility: hidden;
1922
+ pointer-events: none;
1923
+ }
1924
+
1925
+ .swap-off {
1926
+ opacity: 1;
1927
+ visibility: visible;
1928
+ pointer-events: none;
1929
+ }
1930
+
1931
+ .swap-input:checked ~ .swap-on,
1932
+ .swap[aria-pressed="true"] > .swap-on {
1933
+ opacity: 1;
1934
+ visibility: visible;
1935
+ }
1936
+
1937
+ .swap-input:checked ~ .swap-off,
1938
+ .swap[aria-pressed="true"] > .swap-off {
1939
+ opacity: 0;
1940
+ visibility: hidden;
1941
+ }
1942
+
1943
+ .swap:focus-visible,
1944
+ .swap:has(.swap-input:focus-visible) {
1945
+ outline: none;
1946
+ box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
1947
+ border-radius: var(--radius-sm);
1948
+ }
1949
+
1950
+ .swap:disabled,
1951
+ .swap:has(.swap-input:disabled) {
1952
+ cursor: not-allowed;
1953
+ opacity: 0.5;
1954
+ }
1955
+
1956
+ .swap-input:disabled {
1957
+ cursor: not-allowed;
1958
+ }
1959
+
1960
+ .swap-rotate .swap-on {
1961
+ transform: rotate(-90deg) scale(0.8);
1962
+ }
1963
+
1964
+ .swap-rotate .swap-off {
1965
+ transform: rotate(0deg) scale(1);
1966
+ }
1967
+
1968
+ .swap-rotate .swap-input:checked ~ .swap-on,
1969
+ .swap-rotate[aria-pressed="true"] > .swap-on {
1970
+ transform: rotate(0deg) scale(1);
1971
+ }
1972
+
1973
+ .swap-rotate .swap-input:checked ~ .swap-off,
1974
+ .swap-rotate[aria-pressed="true"] > .swap-off {
1975
+ transform: rotate(90deg) scale(0.8);
1976
+ }
1977
+
1978
+ /* Presentation-only override. It intentionally wins over semantic state. */
1979
+ .swap.swap-active > .swap-on {
1980
+ opacity: 1;
1981
+ visibility: visible;
1982
+ transform: rotate(0deg) scale(1);
1983
+ }
1984
+
1985
+ .swap.swap-active > .swap-off {
1986
+ opacity: 0;
1987
+ visibility: hidden;
1988
+ transform: rotate(90deg) scale(0.8);
1989
+ }
1990
+
1991
+ @media (prefers-reduced-motion: reduce) {
1992
+ .swap-on,
1993
+ .swap-off {
1994
+ transition: none;
1995
+ }
1996
+ }
1997
+ }
1998
+
1999
+
1698
2000
  /* Card Component */
1699
2001
  /**
1700
2002
  * Card Component Styles
@@ -3799,45 +4101,139 @@ html {
3799
4101
 
3800
4102
 
3801
4103
 
3802
- /* Navigation Component - includes navbar, menu, breadcrumbs, tabs, pagination, dropdown */
4104
+ /* Navigation Component - retains the legacy Dropdown import contract */
3803
4105
  /**
3804
4106
  * Navigation Component Styles
3805
4107
  * DuskMoonUI - Material Design 3 inspired navigation system
3806
4108
  */
3807
4109
 
4110
+ /* Preserve the Navigation entrypoint's published Dropdown coverage. */
4111
+ /**
4112
+ * Dropdown Component Styles
4113
+ * Native Popover disclosure with logical CSS anchor positioning.
4114
+ */
4115
+
3808
4116
  @layer components {
3809
- /* Navbar Base */
3810
- .navbar {
3811
- display: flex;
3812
- align-items: center;
3813
- width: 100%;
3814
- min-height: 4rem;
3815
- padding: 0.5rem 1rem;
3816
- background-color: var(--color-surface);
3817
- color: var(--color-on-surface);
4117
+ .dropdown {
4118
+ position: relative;
4119
+ display: inline-block;
3818
4120
  }
3819
4121
 
3820
- .navbar-primary {
3821
- background-color: var(--color-primary);
3822
- color: var(--color-primary-content);
4122
+ .dropdown > .dropdown-content[popover] {
4123
+ display: none;
4124
+ position: fixed;
4125
+ inset-block-start: auto;
4126
+ inset-block-end: max(0.5rem, env(safe-area-inset-bottom, 0px));
4127
+ inset-inline-start: auto;
4128
+ inset-inline-end: max(
4129
+ 0.5rem,
4130
+ env(safe-area-inset-left, 0px),
4131
+ env(safe-area-inset-right, 0px)
4132
+ );
4133
+ z-index: 50;
4134
+ min-inline-size: 12rem;
4135
+ max-inline-size: min(24rem, calc(100dvw - 1rem));
4136
+ max-block-size: calc(100dvh - 1rem);
4137
+ margin: 0;
4138
+ padding: 0.5rem;
4139
+ overflow: auto;
4140
+ color: var(--color-on-surface);
4141
+ background-color: var(--color-surface);
4142
+ border: 1px solid var(--color-outline);
4143
+ border-radius: var(--radius-sm);
4144
+ box-shadow: var(--shadow-lg);
4145
+ opacity: 0;
4146
+ visibility: hidden;
4147
+ pointer-events: none;
4148
+ transform: translateY(-0.5rem);
4149
+ transition:
4150
+ opacity 150ms ease-out,
4151
+ transform 150ms ease-out,
4152
+ overlay 150ms ease-out allow-discrete,
4153
+ display 150ms ease-out allow-discrete;
3823
4154
  }
3824
4155
 
3825
- .navbar-secondary {
3826
- background-color: var(--color-secondary);
3827
- color: var(--color-secondary-content);
4156
+ .dropdown > .dropdown-content[popover]:popover-open {
4157
+ display: block;
4158
+ opacity: 1;
4159
+ visibility: visible;
4160
+ pointer-events: auto;
4161
+ transform: translateY(0);
3828
4162
  }
3829
4163
 
3830
- .navbar-tertiary {
3831
- background-color: var(--color-tertiary);
3832
- color: var(--color-tertiary-content);
4164
+ @starting-style {
4165
+ .dropdown > .dropdown-content[popover]:popover-open {
4166
+ opacity: 0;
4167
+ transform: translateY(-0.5rem);
4168
+ }
3833
4169
  }
3834
4170
 
3835
- .navbar-accent {
3836
- background-color: var(--color-accent);
3837
- color: var(--color-accent-content);
3838
- }
4171
+ @supports (position-area: block-end) {
4172
+ .dropdown > .dropdown-content[popover] {
4173
+ inset: auto;
4174
+ margin: 0.25rem;
4175
+ position-area: block-end span-inline-end;
4176
+ position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
4177
+ }
3839
4178
 
3840
- .navbar-neutral {
4179
+ .dropdown.dropdown-block-start > .dropdown-content[popover] {
4180
+ position-area: block-start span-inline-end;
4181
+ }
4182
+
4183
+ .dropdown.dropdown-block-end > .dropdown-content[popover] {
4184
+ position-area: block-end span-inline-end;
4185
+ }
4186
+
4187
+ .dropdown.dropdown-inline-start > .dropdown-content[popover] {
4188
+ position-area: inline-start span-block-end;
4189
+ }
4190
+
4191
+ .dropdown.dropdown-inline-end > .dropdown-content[popover] {
4192
+ position-area: inline-end span-block-end;
4193
+ }
4194
+ }
4195
+
4196
+ @media (prefers-reduced-motion: reduce) {
4197
+ .dropdown > .dropdown-content[popover] {
4198
+ transition: none;
4199
+ }
4200
+ }
4201
+ }
4202
+
4203
+
4204
+ @layer components {
4205
+ /* Navbar Base */
4206
+ .navbar {
4207
+ display: flex;
4208
+ align-items: center;
4209
+ width: 100%;
4210
+ min-height: 4rem;
4211
+ padding: 0.5rem 1rem;
4212
+ background-color: var(--color-surface);
4213
+ color: var(--color-on-surface);
4214
+ }
4215
+
4216
+ .navbar-primary {
4217
+ background-color: var(--color-primary);
4218
+ color: var(--color-primary-content);
4219
+ }
4220
+
4221
+ .navbar-secondary {
4222
+ background-color: var(--color-secondary);
4223
+ color: var(--color-secondary-content);
4224
+ }
4225
+
4226
+ .navbar-tertiary {
4227
+ background-color: var(--color-tertiary);
4228
+ color: var(--color-tertiary-content);
4229
+ }
4230
+
4231
+ .navbar-accent {
4232
+ background-color: var(--color-accent);
4233
+ color: var(--color-accent-content);
4234
+ }
4235
+
4236
+ .navbar-neutral {
3841
4237
  background-color: var(--color-neutral);
3842
4238
  color: var(--color-neutral-content);
3843
4239
  }
@@ -4391,60 +4787,6 @@ html {
4391
4787
  font-size: 1rem;
4392
4788
  }
4393
4789
 
4394
- /* Dropdown */
4395
- .dropdown {
4396
- position: relative;
4397
- display: inline-block;
4398
- }
4399
-
4400
- .dropdown-content {
4401
- position: absolute;
4402
- z-index: 50;
4403
- min-width: 12rem;
4404
- padding: 0.5rem;
4405
- background-color: var(--color-surface);
4406
- border: 1px solid var(--color-outline);
4407
- border-radius: var(--radius-sm);
4408
- box-shadow: var(--shadow-lg);
4409
- opacity: 0;
4410
- visibility: hidden;
4411
- transform: translateY(-0.5rem);
4412
- transition: all 150ms ease-in-out;
4413
- }
4414
-
4415
- .dropdown:hover .dropdown-content,
4416
- .dropdown:focus-within .dropdown-content,
4417
- .dropdown.dropdown-open .dropdown-content {
4418
- opacity: 1;
4419
- visibility: visible;
4420
- transform: translateY(0);
4421
- }
4422
-
4423
- /* Dropdown Positions */
4424
- .dropdown-end .dropdown-content {
4425
- right: 0;
4426
- }
4427
-
4428
- .dropdown-top .dropdown-content {
4429
- bottom: 100%;
4430
- top: auto;
4431
- margin-bottom: 0.25rem;
4432
- }
4433
-
4434
- .dropdown-left .dropdown-content {
4435
- right: 100%;
4436
- left: auto;
4437
- top: 0;
4438
- margin-right: 0.25rem;
4439
- }
4440
-
4441
- .dropdown-right .dropdown-content {
4442
- left: 100%;
4443
- right: auto;
4444
- top: 0;
4445
- margin-left: 0.25rem;
4446
- }
4447
-
4448
4790
  /* Pagination */
4449
4791
  .pagination {
4450
4792
  display: flex;
@@ -4688,7 +5030,7 @@ html {
4688
5030
  position: relative;
4689
5031
  z-index: 1;
4690
5032
  max-width: 32rem;
4691
- max-height: calc(100vh - 5rem);
5033
+ max-height: calc(100dvh - 5rem);
4692
5034
  padding: 1.5rem;
4693
5035
  background-color: var(--color-surface);
4694
5036
  color: var(--color-on-surface);
@@ -4720,8 +5062,10 @@ html {
4720
5062
  }
4721
5063
 
4722
5064
  /* Modal Action */
4723
- .modal-action {
5065
+ .modal-action,
5066
+ .modal-footer {
4724
5067
  display: flex;
5068
+ flex-wrap: wrap;
4725
5069
  justify-content: flex-end;
4726
5070
  gap: 0.5rem;
4727
5071
  margin-top: 1.5rem;
@@ -4751,10 +5095,18 @@ html {
4751
5095
  max-width: 20rem;
4752
5096
  }
4753
5097
 
5098
+ .modal-md .modal-box {
5099
+ max-width: 32rem;
5100
+ }
5101
+
4754
5102
  .modal-lg .modal-box {
4755
5103
  max-width: 48rem;
4756
5104
  }
4757
5105
 
5106
+ .modal-xl .modal-box {
5107
+ max-width: 64rem;
5108
+ }
5109
+
4758
5110
  .modal-full .modal-box {
4759
5111
  max-width: calc(100vw - 2rem);
4760
5112
  max-height: calc(100vh - 2rem);
@@ -4777,6 +5129,38 @@ html {
4777
5129
  align-items: center;
4778
5130
  }
4779
5131
 
5132
+ /* Animation Variants */
5133
+ .modal-slide-up .modal-box {
5134
+ transform: translateY(6rem) scale(0.95);
5135
+ }
5136
+
5137
+ .modal-slide-down .modal-box {
5138
+ transform: translateY(-6rem) scale(0.95);
5139
+ }
5140
+
5141
+ .modal-zoom .modal-box {
5142
+ transform: scale(0.75);
5143
+ }
5144
+
5145
+ :is(.modal-slide-up, .modal-slide-down, .modal-zoom).modal-open .modal-box,
5146
+ :is(.modal-slide-up, .modal-slide-down, .modal-zoom):target .modal-box {
5147
+ transform: translateY(0) scale(1);
5148
+ }
5149
+
5150
+ /* Backdrop Variants */
5151
+ .modal-backdrop-light {
5152
+ background-color: color-mix(in srgb, white 80%, transparent);
5153
+ }
5154
+
5155
+ .modal-backdrop-blur {
5156
+ background-color: color-mix(in srgb, var(--color-scrim) 30%, transparent);
5157
+ backdrop-filter: blur(8px);
5158
+ }
5159
+
5160
+ .modal-no-backdrop {
5161
+ background-color: transparent;
5162
+ }
5163
+
4780
5164
  /* Modal Close Button */
4781
5165
  .modal-close {
4782
5166
  position: absolute;
@@ -4825,6 +5209,22 @@ html {
4825
5209
  line-height: 1.5;
4826
5210
  }
4827
5211
 
5212
+ .modal-scrollable .modal-body {
5213
+ max-height: 60vh;
5214
+ overflow-y: auto;
5215
+ }
5216
+
5217
+ .modal-no-padding .modal-body {
5218
+ padding: 0;
5219
+ }
5220
+
5221
+ .modal-centered .modal-body {
5222
+ display: flex;
5223
+ align-items: center;
5224
+ justify-content: center;
5225
+ text-align: center;
5226
+ }
5227
+
4828
5228
  /* Responsive Modal */
4829
5229
  @media (max-width: 640px) {
4830
5230
  .modal-box {
@@ -4839,7 +5239,7 @@ html {
4839
5239
 
4840
5240
  .modal-responsive .modal-box {
4841
5241
  max-width: 100%;
4842
- max-height: 90vh;
5242
+ max-height: 90dvh;
4843
5243
  margin: 0;
4844
5244
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
4845
5245
  }
@@ -4854,7 +5254,7 @@ html {
4854
5254
 
4855
5255
  .drawer-modal .modal-box {
4856
5256
  max-width: 20rem;
4857
- max-height: 100vh;
5257
+ max-height: 100dvh;
4858
5258
  height: 100%;
4859
5259
  margin: 0;
4860
5260
  border-radius: 0;
@@ -4946,6 +5346,10 @@ html {
4946
5346
  white-space: nowrap;
4947
5347
  border: 0;
4948
5348
  }
5349
+
5350
+ body.modal-open {
5351
+ overflow: hidden;
5352
+ }
4949
5353
  }
4950
5354
 
4951
5355
 
@@ -13503,8 +13907,11 @@ html {
13503
13907
  @layer components {
13504
13908
  /* Base Alert */
13505
13909
  .alert {
13506
- display: flex;
13507
- align-items: flex-start;
13910
+ display: grid;
13911
+ grid-template-columns: auto minmax(0, 1fr) auto auto;
13912
+ grid-template-areas:
13913
+ "icon content actions close";
13914
+ align-items: center;
13508
13915
  gap: 0.75rem;
13509
13916
  padding: 1rem;
13510
13917
  border-radius: var(--radius-sm);
@@ -13515,6 +13922,7 @@ html {
13515
13922
 
13516
13923
  /* Alert Icon */
13517
13924
  .alert-icon {
13925
+ grid-area: icon;
13518
13926
  display: flex;
13519
13927
  align-items: center;
13520
13928
  justify-content: center;
@@ -13522,10 +13930,12 @@ html {
13522
13930
  height: 1.5rem;
13523
13931
  font-size: 1.25rem;
13524
13932
  flex-shrink: 0;
13933
+ align-self: start;
13525
13934
  }
13526
13935
 
13527
13936
  /* Alert Content */
13528
13937
  .alert-content {
13938
+ grid-area: content;
13529
13939
  display: flex;
13530
13940
  flex-direction: column;
13531
13941
  gap: 0.25rem;
@@ -13533,13 +13943,42 @@ html {
13533
13943
  min-width: 0;
13534
13944
  }
13535
13945
 
13946
+ .alert-content > p {
13947
+ margin: 0;
13948
+ }
13949
+
13950
+ /* Keep the compact single-message form vertically balanced against global typography margins. */
13951
+ .alert > p {
13952
+ margin: 0;
13953
+ }
13954
+
13955
+ .alert-horizontal { display: grid; }
13956
+ .alert-actions-end { grid-template-areas: "icon content actions close"; }
13957
+ .alert-actions-bottom {
13958
+ grid-template-columns: auto minmax(0, 1fr) auto;
13959
+ grid-template-areas:
13960
+ "icon content close"
13961
+ ". actions .";
13962
+ }
13963
+
13964
+ .alert-actions-bottom .alert-actions {
13965
+ justify-self: start;
13966
+ margin-top: 0.5rem;
13967
+ }
13968
+ .alert-vertical {
13969
+ display: flex;
13970
+ flex-direction: column;
13971
+ }
13972
+
13536
13973
  .alert-title {
13974
+ margin: 0;
13537
13975
  font-size: 0.875rem;
13538
13976
  font-weight: 600;
13539
13977
  line-height: 1.25rem;
13540
13978
  }
13541
13979
 
13542
13980
  .alert-description {
13981
+ margin: 0;
13543
13982
  font-size: 0.875rem;
13544
13983
  line-height: 1.25rem;
13545
13984
  opacity: 0.9;
@@ -13547,6 +13986,7 @@ html {
13547
13986
 
13548
13987
  /* Alert Close Button */
13549
13988
  .alert-close {
13989
+ grid-area: close;
13550
13990
  display: flex;
13551
13991
  align-items: center;
13552
13992
  justify-content: center;
@@ -13760,6 +14200,7 @@ html {
13760
14200
  /* Dismissible */
13761
14201
  .alert-dismissible {
13762
14202
  padding-right: 2.5rem;
14203
+ padding-inline-end: 2.5rem;
13763
14204
  position: relative;
13764
14205
  }
13765
14206
 
@@ -13767,6 +14208,7 @@ html {
13767
14208
  position: absolute;
13768
14209
  top: 0.75rem;
13769
14210
  right: 0.75rem;
14211
+ inset-inline-end: 0.75rem;
13770
14212
  }
13771
14213
 
13772
14214
  /* Compact */
@@ -13786,11 +14228,25 @@ html {
13786
14228
  font-size: 0.8125rem;
13787
14229
  }
13788
14230
 
14231
+ .alert-comfortable {
14232
+ padding: 1.25rem;
14233
+ gap: 1rem;
14234
+ }
14235
+
13789
14236
  /* Alert Actions */
13790
14237
  .alert-actions {
14238
+ grid-area: actions;
13791
14239
  display: flex;
13792
14240
  gap: 0.5rem;
13793
- margin-top: 0.5rem;
14241
+ margin-top: 0;
14242
+ flex-wrap: wrap;
14243
+ align-self: center;
14244
+ justify-self: end;
14245
+ }
14246
+
14247
+ .alert-vertical .alert-actions {
14248
+ align-self: stretch;
14249
+ width: 100%;
13794
14250
  }
13795
14251
 
13796
14252
  .alert-filled .alert-actions .btn-text {
@@ -13814,6 +14270,32 @@ html {
13814
14270
  transition: none;
13815
14271
  }
13816
14272
  }
14273
+
14274
+ @media (max-width: 32rem) {
14275
+ .alert:not(.alert-vertical) .alert-content,
14276
+ .alert-horizontal .alert-content {
14277
+ flex-basis: min(100%, 18rem);
14278
+ }
14279
+ .alert:not(.alert-vertical),
14280
+ .alert-horizontal {
14281
+ grid-template-columns: auto minmax(0, 1fr) auto;
14282
+ grid-template-areas:
14283
+ "icon content close"
14284
+ ". actions actions";
14285
+ }
14286
+ .alert:not(.alert-vertical).alert-actions-end,
14287
+ .alert-horizontal.alert-actions-end {
14288
+ grid-template-columns: auto minmax(0, 1fr) auto;
14289
+ grid-template-areas:
14290
+ "icon content close"
14291
+ ". actions actions";
14292
+ }
14293
+ .alert:not(.alert-vertical) .alert-actions,
14294
+ .alert-horizontal .alert-actions {
14295
+ justify-self: start;
14296
+ margin-top: 0.5rem;
14297
+ }
14298
+ }
13817
14299
  }
13818
14300
 
13819
14301
  /**
@@ -13829,9 +14311,10 @@ html {
13829
14311
  margin: auto;
13830
14312
  padding: 0;
13831
14313
  border: none;
13832
- width: 100%;
14314
+ width: calc(100% - 2rem);
13833
14315
  max-width: 28rem;
13834
- max-height: calc(100vh - 4rem);
14316
+ max-height: calc(100dvh - 2rem);
14317
+ box-sizing: border-box;
13835
14318
  background-color: var(--color-surface);
13836
14319
  color: var(--color-on-surface);
13837
14320
  border-radius: var(--radius-2xl);
@@ -13848,7 +14331,7 @@ html {
13848
14331
  .dialog-box {
13849
14332
  display: flex;
13850
14333
  flex-direction: column;
13851
- max-height: calc(100vh - 4rem);
14334
+ max-height: calc(100dvh - 2rem);
13852
14335
  overflow: hidden;
13853
14336
  }
13854
14337
 
@@ -13907,6 +14390,7 @@ html {
13907
14390
  /* Dialog Footer */
13908
14391
  .dialog-footer {
13909
14392
  display: flex;
14393
+ flex-wrap: wrap;
13910
14394
  justify-content: flex-end;
13911
14395
  gap: 0.5rem;
13912
14396
  padding: 1rem 1.5rem 1.5rem;
@@ -13946,6 +14430,30 @@ html {
13946
14430
  margin: 0;
13947
14431
  }
13948
14432
 
14433
+ @media (max-width: 640px) {
14434
+ dialog.dialog {
14435
+ width: calc(100% - 1rem);
14436
+ max-height: calc(100dvh - 1rem);
14437
+ border-radius: var(--radius-lg);
14438
+ }
14439
+
14440
+ .dialog-box {
14441
+ max-height: calc(100dvh - 1rem);
14442
+ }
14443
+
14444
+ .dialog-header {
14445
+ padding: 1rem 1rem 0;
14446
+ }
14447
+
14448
+ .dialog-body {
14449
+ padding: 1rem;
14450
+ }
14451
+
14452
+ .dialog-footer {
14453
+ padding: 0.75rem 1rem 1rem;
14454
+ }
14455
+ }
14456
+
13949
14457
  dialog.dialog.dialog-fullscreen .dialog-box {
13950
14458
  max-height: 100%;
13951
14459
  }
@@ -13991,79 +14499,230 @@ html {
13991
14499
  }
13992
14500
 
13993
14501
  /**
13994
- * Progress Component Styles
13995
- * DuskMoonUI - Material Design 3 inspired progress system
14502
+ * Loading Component Styles
14503
+ * CSS-only activity indicators. State, aria-busy, and disabling remain consumer-owned.
13996
14504
  */
13997
14505
 
13998
14506
  @layer components {
13999
- /* Base Progress (Linear) */
14000
- .progress {
14001
- position: relative;
14002
- width: 100%;
14003
- height: 0.5rem;
14004
- background-color: var(--color-surface-container-highest);
14005
- border-radius: var(--radius-full);
14006
- overflow: hidden;
14507
+ .loading {
14508
+ --loading-size: 1.25rem;
14509
+ display: inline-flex;
14510
+ width: var(--loading-size);
14511
+ height: var(--loading-size);
14512
+ flex: 0 0 var(--loading-size);
14513
+ color: currentColor;
14514
+ vertical-align: middle;
14007
14515
  }
14008
14516
 
14009
- /* Progress Bar */
14010
- .progress-bar {
14011
- position: absolute;
14012
- top: 0;
14013
- left: 0;
14014
- height: 100%;
14015
- background-color: var(--color-primary);
14517
+ .loading-spinner {
14518
+ border: max(2px, calc(var(--loading-size) / 8)) solid color-mix(in oklch, currentColor 25%, transparent);
14519
+ border-top-color: currentColor;
14016
14520
  border-radius: var(--radius-full);
14017
- transition: width 300ms ease-in-out;
14521
+ animation: loading-spin 800ms linear infinite;
14018
14522
  }
14019
14523
 
14020
- /* Color Variants */
14021
- .progress-primary .progress-bar {
14022
- background-color: var(--color-primary);
14524
+ .loading-dots,
14525
+ .loading-bars {
14526
+ align-items: center;
14527
+ justify-content: center;
14528
+ gap: max(2px, calc(var(--loading-size) / 8));
14023
14529
  }
14024
14530
 
14025
- .progress-secondary .progress-bar {
14026
- background-color: var(--color-secondary);
14531
+ .loading-dots::before,
14532
+ .loading-dots::after,
14533
+ .loading-bars::before,
14534
+ .loading-bars::after {
14535
+ content: "";
14536
+ display: block;
14537
+ background: currentColor;
14027
14538
  }
14028
14539
 
14029
- .progress-tertiary .progress-bar {
14030
- background-color: var(--color-tertiary);
14540
+ .loading-dots::before,
14541
+ .loading-dots::after {
14542
+ width: 25%;
14543
+ height: 25%;
14544
+ border-radius: var(--radius-full);
14545
+ box-shadow: calc(var(--loading-size) / 3) 0 currentColor;
14546
+ animation: loading-dots 900ms ease-in-out infinite;
14031
14547
  }
14032
14548
 
14033
- .progress-info .progress-bar {
14034
- background-color: var(--color-info);
14549
+ .loading-dots::after {
14550
+ display: none;
14035
14551
  }
14036
14552
 
14037
- .progress-success .progress-bar {
14038
- background-color: var(--color-success);
14553
+ .loading-bars {
14554
+ padding-inline: 10%;
14039
14555
  }
14040
14556
 
14041
- .progress-warning .progress-bar {
14042
- background-color: var(--color-warning);
14557
+ .loading-bars::before,
14558
+ .loading-bars::after {
14559
+ width: 18%;
14560
+ height: 65%;
14561
+ border-radius: var(--radius-xs);
14562
+ box-shadow: calc(var(--loading-size) / 3) 0 currentColor, calc(var(--loading-size) * 2 / 3) 0 currentColor;
14563
+ animation: loading-bars 900ms ease-in-out infinite;
14043
14564
  }
14044
14565
 
14045
- .progress-error .progress-bar {
14046
- background-color: var(--color-error);
14566
+ .loading-bars::after {
14567
+ display: none;
14047
14568
  }
14048
14569
 
14049
- .progress-accent .progress-bar {
14050
- background-color: var(--color-accent);
14051
- }
14570
+ .loading-xs { --loading-size: 0.75rem; }
14571
+ .loading-sm { --loading-size: 1rem; }
14572
+ .loading-md { --loading-size: 1.25rem; }
14573
+ .loading-lg { --loading-size: 1.75rem; }
14574
+ .loading-xl { --loading-size: 2.5rem; }
14052
14575
 
14053
- .progress-neutral .progress-bar {
14054
- background-color: var(--color-neutral);
14576
+ .loading-primary { color: var(--color-primary); }
14577
+ .loading-secondary { color: var(--color-secondary); }
14578
+ .loading-tertiary { color: var(--color-tertiary); }
14579
+ .loading-info { color: var(--color-info); }
14580
+ .loading-success { color: var(--color-success); }
14581
+ .loading-warning { color: var(--color-warning); }
14582
+ .loading-error { color: var(--color-error); }
14583
+
14584
+ @keyframes loading-spin {
14585
+ to { transform: rotate(360deg); }
14055
14586
  }
14056
14587
 
14057
- .progress-base .progress-bar {
14058
- background-color: var(--color-base-content);
14588
+ @keyframes loading-dots {
14589
+ 0%, 100% { opacity: 0.35; transform: scale(0.75); }
14590
+ 50% { opacity: 1; transform: scale(1); }
14059
14591
  }
14060
14592
 
14061
- /* Size Variants */
14062
- .progress-xs {
14063
- height: 0.25rem;
14593
+ @keyframes loading-bars {
14594
+ 0%, 100% { opacity: 0.35; transform: scaleY(0.65); }
14595
+ 50% { opacity: 1; transform: scaleY(1); }
14064
14596
  }
14065
14597
 
14066
- .progress-sm {
14598
+ @media (prefers-reduced-motion: reduce) {
14599
+ .loading-spinner,
14600
+ .loading-dots::before,
14601
+ .loading-bars::before {
14602
+ animation: none;
14603
+ }
14604
+ }
14605
+ }
14606
+
14607
+ /**
14608
+ * Progress Component Styles
14609
+ * DuskMoonUI - Material Design 3 inspired progress system
14610
+ */
14611
+
14612
+ @layer components {
14613
+ /* Base Progress (Linear) */
14614
+ .progress {
14615
+ position: relative;
14616
+ width: 100%;
14617
+ height: 0.5rem;
14618
+ background-color: var(--color-surface-container-highest);
14619
+ border-radius: var(--radius-full);
14620
+ overflow: hidden;
14621
+ }
14622
+
14623
+ /* Native progress keeps the platform's accessible value/max contract. */
14624
+ progress.progress {
14625
+ appearance: none;
14626
+ border: 0;
14627
+ display: block;
14628
+ }
14629
+
14630
+ progress.progress::-webkit-progress-bar {
14631
+ background: var(--color-surface-container-highest);
14632
+ border-radius: var(--radius-full);
14633
+ }
14634
+
14635
+ progress.progress::-webkit-progress-value {
14636
+ background: var(--color-primary);
14637
+ border-radius: var(--radius-full);
14638
+ transition: width 300ms ease-in-out;
14639
+ }
14640
+
14641
+ progress.progress::-moz-progress-bar {
14642
+ background: var(--color-primary);
14643
+ border-radius: var(--radius-full);
14644
+ transition: width 300ms ease-in-out;
14645
+ }
14646
+
14647
+ progress.progress:indeterminate::-webkit-progress-value,
14648
+ progress.progress:indeterminate::-moz-progress-bar {
14649
+ width: 30%;
14650
+ animation: progress-indeterminate 1.5s infinite ease-in-out;
14651
+ }
14652
+
14653
+ /* Progress Bar */
14654
+ .progress-bar {
14655
+ position: absolute;
14656
+ top: 0;
14657
+ left: 0;
14658
+ height: 100%;
14659
+ background-color: var(--color-primary);
14660
+ border-radius: var(--radius-full);
14661
+ transition: width 300ms ease-in-out;
14662
+ }
14663
+
14664
+ /* Color Variants */
14665
+ .progress-primary .progress-bar {
14666
+ background-color: var(--color-primary);
14667
+ }
14668
+
14669
+ .progress-secondary .progress-bar {
14670
+ background-color: var(--color-secondary);
14671
+ }
14672
+
14673
+ .progress-tertiary .progress-bar {
14674
+ background-color: var(--color-tertiary);
14675
+ }
14676
+
14677
+ .progress-info .progress-bar {
14678
+ background-color: var(--color-info);
14679
+ }
14680
+
14681
+ .progress-success .progress-bar {
14682
+ background-color: var(--color-success);
14683
+ }
14684
+
14685
+ .progress-warning .progress-bar {
14686
+ background-color: var(--color-warning);
14687
+ }
14688
+
14689
+ .progress-error .progress-bar {
14690
+ background-color: var(--color-error);
14691
+ }
14692
+
14693
+ .progress-accent .progress-bar {
14694
+ background-color: var(--color-accent);
14695
+ }
14696
+
14697
+ .progress-neutral .progress-bar {
14698
+ background-color: var(--color-neutral);
14699
+ }
14700
+
14701
+ .progress-base .progress-bar {
14702
+ background-color: var(--color-base-content);
14703
+ }
14704
+
14705
+ progress.progress-primary::-webkit-progress-value,
14706
+ progress.progress-primary::-moz-progress-bar { background: var(--color-primary); }
14707
+ progress.progress-secondary::-webkit-progress-value,
14708
+ progress.progress-secondary::-moz-progress-bar { background: var(--color-secondary); }
14709
+ progress.progress-tertiary::-webkit-progress-value,
14710
+ progress.progress-tertiary::-moz-progress-bar { background: var(--color-tertiary); }
14711
+ progress.progress-info::-webkit-progress-value,
14712
+ progress.progress-info::-moz-progress-bar { background: var(--color-info); }
14713
+ progress.progress-success::-webkit-progress-value,
14714
+ progress.progress-success::-moz-progress-bar { background: var(--color-success); }
14715
+ progress.progress-warning::-webkit-progress-value,
14716
+ progress.progress-warning::-moz-progress-bar { background: var(--color-warning); }
14717
+ progress.progress-error::-webkit-progress-value,
14718
+ progress.progress-error::-moz-progress-bar { background: var(--color-error); }
14719
+
14720
+ /* Size Variants */
14721
+ .progress-xs {
14722
+ height: 0.25rem;
14723
+ }
14724
+
14725
+ .progress-sm {
14067
14726
  height: 0.375rem;
14068
14727
  }
14069
14728
 
@@ -14133,6 +14792,25 @@ html {
14133
14792
  }
14134
14793
  }
14135
14794
 
14795
+ /* Buffer tracks belong to custom markup, not native <progress>. */
14796
+ .progress-buffer {
14797
+ position: relative;
14798
+ }
14799
+
14800
+ .progress-buffer-bar {
14801
+ position: absolute;
14802
+ inset-block: 0;
14803
+ inset-inline-start: 0;
14804
+ width: 0;
14805
+ background: color-mix(in oklch, var(--color-primary) 30%, transparent);
14806
+ border-radius: var(--radius-full);
14807
+ transition: width 300ms ease-in-out;
14808
+ }
14809
+
14810
+ .progress-buffer .progress-bar {
14811
+ z-index: 1;
14812
+ }
14813
+
14136
14814
  /* Circular Progress */
14137
14815
  .progress-circular {
14138
14816
  position: relative;
@@ -14232,7 +14910,17 @@ html {
14232
14910
 
14233
14911
  /* Reduce Motion */
14234
14912
  @media (prefers-reduced-motion: reduce) {
14913
+ .progress-bar,
14914
+ progress.progress::-webkit-progress-value,
14915
+ progress.progress::-moz-progress-bar,
14916
+ .progress-circular-bar,
14917
+ .progress-buffer-bar {
14918
+ transition: none;
14919
+ }
14920
+
14235
14921
  .progress-indeterminate .progress-bar,
14922
+ progress.progress:indeterminate::-webkit-progress-value,
14923
+ progress.progress:indeterminate::-moz-progress-bar,
14236
14924
  .progress-striped.progress-animated .progress-bar,
14237
14925
  .progress-circular-indeterminate svg,
14238
14926
  .progress-circular-indeterminate .progress-circular-bar {
@@ -14241,6 +14929,54 @@ html {
14241
14929
  }
14242
14930
  }
14243
14931
 
14932
+ /**
14933
+ * Radial Progress Component Styles
14934
+ * Determinate percentage progress without circumference arithmetic.
14935
+ */
14936
+
14937
+ @layer components {
14938
+ .radial-progress {
14939
+ --radial-progress-value: 0;
14940
+ --radial-progress-size: 3rem;
14941
+ --radial-progress-thickness: 0.375rem;
14942
+ --radial-progress-track: var(--color-surface-container-highest);
14943
+ position: relative;
14944
+ display: inline-grid;
14945
+ width: var(--radial-progress-size);
14946
+ height: var(--radial-progress-size);
14947
+ place-items: center;
14948
+ color: var(--color-primary);
14949
+ border-radius: var(--radius-full);
14950
+ background: conic-gradient(currentColor calc(clamp(0, var(--radial-progress-value), 100) * 1%), var(--radial-progress-track) 0);
14951
+ isolation: isolate;
14952
+ }
14953
+
14954
+ .radial-progress::before {
14955
+ content: "";
14956
+ position: absolute;
14957
+ inset: var(--radial-progress-thickness);
14958
+ z-index: 0;
14959
+ border-radius: inherit;
14960
+ background: var(--color-surface);
14961
+ }
14962
+
14963
+ .radial-progress-primary { color: var(--color-primary); }
14964
+ .radial-progress-secondary { color: var(--color-secondary); }
14965
+ .radial-progress-tertiary { color: var(--color-tertiary); }
14966
+ .radial-progress-info { color: var(--color-info); }
14967
+ .radial-progress-success { color: var(--color-success); }
14968
+ .radial-progress-warning { color: var(--color-warning); }
14969
+ .radial-progress-error { color: var(--color-error); }
14970
+
14971
+ .radial-progress-sm { --radial-progress-size: 2rem; --radial-progress-thickness: 0.25rem; }
14972
+ .radial-progress-lg { --radial-progress-size: 4rem; --radial-progress-thickness: 0.5rem; }
14973
+ .radial-progress-xl { --radial-progress-size: 6rem; --radial-progress-thickness: 0.625rem; }
14974
+
14975
+ @media (prefers-reduced-motion: reduce) {
14976
+ .radial-progress { transition: none; }
14977
+ }
14978
+ }
14979
+
14244
14980
  /**
14245
14981
  * Skeleton Component Styles
14246
14982
  * DuskMoonUI - Material Design 3 inspired skeleton loading system
@@ -14274,6 +15010,10 @@ html {
14274
15010
  border-radius: var(--radius-sm);
14275
15011
  }
14276
15012
 
15013
+ .skeleton-static {
15014
+ animation: none;
15015
+ }
15016
+
14277
15017
  /* Size Variants */
14278
15018
  .skeleton-xs {
14279
15019
  height: 0.5rem;
@@ -14376,7 +15116,7 @@ html {
14376
15116
  background: linear-gradient(
14377
15117
  90deg,
14378
15118
  transparent,
14379
- rgba(255, 255, 255, 0.3),
15119
+ color-mix(in oklch, var(--color-surface-bright) 35%, transparent),
14380
15120
  transparent
14381
15121
  );
14382
15122
  animation: skeleton-wave 1.5s infinite;
@@ -14454,6 +15194,14 @@ html {
14454
15194
 
14455
15195
  .skeleton-wave::after {
14456
15196
  animation: none;
15197
+ transform: translateX(0);
15198
+ opacity: 0.35;
15199
+ }
15200
+
15201
+ .skeleton-static::after {
15202
+ animation: none;
15203
+ transform: translateX(0);
15204
+ opacity: 0.35;
14457
15205
  }
14458
15206
  }
14459
15207
  }
@@ -14670,49 +15418,49 @@ html {
14670
15418
 
14671
15419
  /* Color Variants */
14672
15420
  .snackbar-info {
14673
- background-color: var(--color-info-container);
14674
- color: var(--color-on-info-container);
15421
+ background-color: var(--color-info);
15422
+ color: var(--color-info-content);
14675
15423
  }
14676
15424
 
14677
15425
  .snackbar-success {
14678
- background-color: var(--color-success-container);
14679
- color: var(--color-on-success-container);
15426
+ background-color: var(--color-success);
15427
+ color: var(--color-success-content);
14680
15428
  }
14681
15429
 
14682
15430
  .snackbar-warning {
14683
- background-color: var(--color-warning-container);
14684
- color: var(--color-on-warning-container);
15431
+ background-color: var(--color-warning);
15432
+ color: var(--color-warning-content);
14685
15433
  }
14686
15434
 
14687
15435
  .snackbar-error {
14688
- background-color: var(--color-error-container);
14689
- color: var(--color-on-error-container);
15436
+ background-color: var(--color-error);
15437
+ color: var(--color-error-content);
14690
15438
  }
14691
15439
 
14692
15440
  /* Brand Color Variants */
14693
15441
  .snackbar-primary {
14694
- background-color: var(--color-primary-container);
14695
- color: var(--color-on-primary-container);
15442
+ background-color: var(--color-primary);
15443
+ color: var(--color-primary-content);
14696
15444
  }
14697
15445
 
14698
15446
  .snackbar-secondary {
14699
- background-color: var(--color-secondary-container);
14700
- color: var(--color-on-secondary-container);
15447
+ background-color: var(--color-secondary);
15448
+ color: var(--color-secondary-content);
14701
15449
  }
14702
15450
 
14703
15451
  .snackbar-tertiary {
14704
- background-color: var(--color-tertiary-container);
14705
- color: var(--color-on-tertiary-container);
15452
+ background-color: var(--color-tertiary);
15453
+ color: var(--color-tertiary-content);
14706
15454
  }
14707
15455
 
14708
15456
  .snackbar-accent {
14709
- background-color: color-mix(in oklch, var(--color-accent) 15%, var(--color-surface));
14710
- color: var(--color-on-surface);
15457
+ background-color: var(--color-accent);
15458
+ color: var(--color-accent-content);
14711
15459
  }
14712
15460
 
14713
15461
  .snackbar-neutral {
14714
- background-color: color-mix(in oklch, var(--color-neutral) 15%, var(--color-surface));
14715
- color: var(--color-on-surface);
15462
+ background-color: var(--color-neutral);
15463
+ color: var(--color-neutral-content);
14716
15464
  }
14717
15465
 
14718
15466
  .snackbar-base {
@@ -14720,6 +15468,36 @@ html {
14720
15468
  color: var(--color-base-content);
14721
15469
  }
14722
15470
 
15471
+ :is(
15472
+ .snackbar-info,
15473
+ .snackbar-success,
15474
+ .snackbar-warning,
15475
+ .snackbar-error,
15476
+ .snackbar-primary,
15477
+ .snackbar-secondary,
15478
+ .snackbar-tertiary,
15479
+ .snackbar-accent,
15480
+ .snackbar-neutral,
15481
+ .snackbar-base
15482
+ ) :is(.snackbar-action, .snackbar-close) {
15483
+ color: inherit;
15484
+ }
15485
+
15486
+ :is(
15487
+ .snackbar-info,
15488
+ .snackbar-success,
15489
+ .snackbar-warning,
15490
+ .snackbar-error,
15491
+ .snackbar-primary,
15492
+ .snackbar-secondary,
15493
+ .snackbar-tertiary,
15494
+ .snackbar-accent,
15495
+ .snackbar-neutral,
15496
+ .snackbar-base
15497
+ ) :is(.snackbar-action, .snackbar-close):hover {
15498
+ background-color: color-mix(in oklch, currentColor 12%, transparent);
15499
+ }
15500
+
14723
15501
  /* Dark Snackbar (default MD3 style) */
14724
15502
  .snackbar-dark {
14725
15503
  background-color: var(--color-on-surface);
@@ -14802,17 +15580,36 @@ html {
14802
15580
  pointer-events: none;
14803
15581
  }
14804
15582
 
15583
+ /* Native command targets use the container as a manual popover. Reset the
15584
+ user-agent popover box while preserving the existing positioning API. */
15585
+ :where(.toast-container[popover]) {
15586
+ inset: auto;
15587
+ width: auto;
15588
+ height: auto;
15589
+ margin: 0;
15590
+ overflow: visible;
15591
+ color: inherit;
15592
+ background: transparent;
15593
+ border: 0;
15594
+ }
15595
+
15596
+ .toast-container[popover]:not(:popover-open) {
15597
+ display: none;
15598
+ }
15599
+
14805
15600
  /* Position Variants */
14806
15601
  .toast-container-top-right {
14807
15602
  top: 0;
14808
15603
  right: 0;
14809
15604
  align-items: flex-end;
15605
+ padding-top: max(1rem, env(safe-area-inset-top));
14810
15606
  }
14811
15607
 
14812
15608
  .toast-container-top-left {
14813
15609
  top: 0;
14814
15610
  left: 0;
14815
15611
  align-items: flex-start;
15612
+ padding-top: max(1rem, env(safe-area-inset-top));
14816
15613
  }
14817
15614
 
14818
15615
  .toast-container-top-center {
@@ -14820,18 +15617,21 @@ html {
14820
15617
  left: 50%;
14821
15618
  transform: translateX(-50%);
14822
15619
  align-items: center;
15620
+ padding-top: max(1rem, env(safe-area-inset-top));
14823
15621
  }
14824
15622
 
14825
15623
  .toast-container-bottom-right {
14826
15624
  bottom: 0;
14827
15625
  right: 0;
14828
15626
  align-items: flex-end;
15627
+ padding-bottom: max(1rem, env(safe-area-inset-bottom));
14829
15628
  }
14830
15629
 
14831
15630
  .toast-container-bottom-left {
14832
15631
  bottom: 0;
14833
15632
  left: 0;
14834
15633
  align-items: flex-start;
15634
+ padding-bottom: max(1rem, env(safe-area-inset-bottom));
14835
15635
  }
14836
15636
 
14837
15637
  .toast-container-bottom-center {
@@ -14839,10 +15639,20 @@ html {
14839
15639
  left: 50%;
14840
15640
  transform: translateX(-50%);
14841
15641
  align-items: center;
15642
+ padding-bottom: max(1rem, env(safe-area-inset-bottom));
14842
15643
  }
14843
15644
 
15645
+ /* Logical aliases add RTL-aware placement without changing left/right. */
15646
+ .toast-container-top-start { top: 0; inset-inline-start: 0; align-items: flex-start; }
15647
+ .toast-container-top-end { top: 0; inset-inline-end: 0; align-items: flex-end; }
15648
+ .toast-container-bottom-start { bottom: 0; inset-inline-start: 0; align-items: flex-start; }
15649
+ .toast-container-bottom-end { bottom: 0; inset-inline-end: 0; align-items: flex-end; }
15650
+
14844
15651
  /* Base Toast */
14845
15652
  .toast {
15653
+ --_toast-accent-color: var(--color-primary);
15654
+
15655
+ position: relative;
14846
15656
  display: flex;
14847
15657
  align-items: flex-start;
14848
15658
  gap: 0.75rem;
@@ -14873,9 +15683,28 @@ html {
14873
15683
  /* Toast Open State */
14874
15684
  .toast.toast-open,
14875
15685
  .toast.show,
14876
- .toast-show {
15686
+ .toast.toast-show {
15687
+ opacity: 1;
15688
+ transform: translateX(0) translateY(0);
15689
+ visibility: visible;
15690
+ pointer-events: auto;
15691
+ }
15692
+
15693
+ /* A closed item cannot intercept input. Consumers should also use hidden,
15694
+ inert, or unmounting when removing it from the accessibility tree. */
15695
+ .toast:not(.toast-open):not(.show):not(.toast-show),
15696
+ .toast[hidden],
15697
+ .toast[inert],
15698
+ .toast[aria-hidden="true"] {
15699
+ pointer-events: none;
15700
+ visibility: hidden;
15701
+ }
15702
+
15703
+ .toast-container[popover]:popover-open .toast {
14877
15704
  opacity: 1;
14878
15705
  transform: translateX(0) translateY(0);
15706
+ visibility: visible;
15707
+ pointer-events: auto;
14879
15708
  }
14880
15709
 
14881
15710
  /* Toast Icon */
@@ -14926,7 +15755,7 @@ html {
14926
15755
  cursor: pointer;
14927
15756
  transition: background-color 150ms ease-in-out, color 150ms ease-in-out;
14928
15757
  flex-shrink: 0;
14929
- margin-left: auto;
15758
+ margin-inline-start: auto;
14930
15759
  }
14931
15760
 
14932
15761
  .toast-close:hover {
@@ -14944,10 +15773,46 @@ html {
14944
15773
  display: flex;
14945
15774
  gap: 0.5rem;
14946
15775
  margin-top: 0.5rem;
15776
+ flex-wrap: wrap;
15777
+ }
15778
+
15779
+ .toast-action {
15780
+ display: inline-flex;
15781
+ align-items: center;
15782
+ justify-content: center;
15783
+ width: fit-content;
15784
+ min-height: 2rem;
15785
+ padding: 0.375rem 0.75rem;
15786
+ color: var(--color-primary);
15787
+ font-size: 0.875rem;
15788
+ font-weight: 500;
15789
+ background-color: transparent;
15790
+ border: 1px solid currentColor;
15791
+ border-radius: var(--radius-sm);
15792
+ cursor: pointer;
15793
+ }
15794
+
15795
+ .toast-action:hover {
15796
+ background-color: color-mix(in oklch, currentColor 10%, transparent);
15797
+ }
15798
+
15799
+ .toast-action:focus-visible {
15800
+ outline: none;
15801
+ box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
14947
15802
  }
14948
15803
 
14949
15804
  /* Type Variants */
15805
+ .toast-accent {
15806
+ --_toast-accent-color: var(--color-accent);
15807
+ border-color: var(--color-accent);
15808
+ }
15809
+
15810
+ .toast-accent .toast-icon {
15811
+ color: var(--color-accent);
15812
+ }
15813
+
14950
15814
  .toast-info {
15815
+ --_toast-accent-color: var(--color-info);
14951
15816
  border-color: var(--color-info);
14952
15817
  }
14953
15818
 
@@ -14956,6 +15821,7 @@ html {
14956
15821
  }
14957
15822
 
14958
15823
  .toast-success {
15824
+ --_toast-accent-color: var(--color-success);
14959
15825
  border-color: var(--color-success);
14960
15826
  }
14961
15827
 
@@ -14964,6 +15830,7 @@ html {
14964
15830
  }
14965
15831
 
14966
15832
  .toast-warning {
15833
+ --_toast-accent-color: var(--color-warning);
14967
15834
  border-color: var(--color-warning);
14968
15835
  }
14969
15836
 
@@ -14972,6 +15839,7 @@ html {
14972
15839
  }
14973
15840
 
14974
15841
  .toast-error {
15842
+ --_toast-accent-color: var(--color-error);
14975
15843
  border-color: var(--color-error);
14976
15844
  }
14977
15845
 
@@ -14980,6 +15848,7 @@ html {
14980
15848
  }
14981
15849
 
14982
15850
  .toast-primary {
15851
+ --_toast-accent-color: var(--color-primary);
14983
15852
  border-color: var(--color-primary);
14984
15853
  }
14985
15854
 
@@ -14988,6 +15857,7 @@ html {
14988
15857
  }
14989
15858
 
14990
15859
  .toast-secondary {
15860
+ --_toast-accent-color: var(--color-secondary);
14991
15861
  border-color: var(--color-secondary);
14992
15862
  }
14993
15863
 
@@ -14996,6 +15866,7 @@ html {
14996
15866
  }
14997
15867
 
14998
15868
  .toast-tertiary {
15869
+ --_toast-accent-color: var(--color-tertiary);
14999
15870
  border-color: var(--color-tertiary);
15000
15871
  }
15001
15872
 
@@ -15003,15 +15874,8 @@ html {
15003
15874
  color: var(--color-tertiary);
15004
15875
  }
15005
15876
 
15006
- .toast-accent {
15007
- border-color: var(--color-accent);
15008
- }
15009
-
15010
- .toast-accent .toast-icon {
15011
- color: var(--color-accent);
15012
- }
15013
-
15014
15877
  .toast-neutral {
15878
+ --_toast-accent-color: var(--color-neutral);
15015
15879
  border-color: var(--color-neutral);
15016
15880
  }
15017
15881
 
@@ -15020,6 +15884,7 @@ html {
15020
15884
  }
15021
15885
 
15022
15886
  .toast-base {
15887
+ --_toast-accent-color: var(--color-base-content);
15023
15888
  border-color: var(--color-base-content);
15024
15889
  }
15025
15890
 
@@ -15028,58 +15893,58 @@ html {
15028
15893
  }
15029
15894
 
15030
15895
  /* Filled Variants */
15896
+ .toast-filled.toast-accent {
15897
+ background-color: var(--color-accent);
15898
+ border-color: transparent;
15899
+ color: var(--color-accent-content);
15900
+ }
15901
+
15031
15902
  .toast-filled.toast-info {
15032
- background-color: var(--color-info-container);
15903
+ background-color: var(--color-info);
15033
15904
  border-color: transparent;
15034
- color: var(--color-on-info-container);
15905
+ color: var(--color-info-content);
15035
15906
  }
15036
15907
 
15037
15908
  .toast-filled.toast-success {
15038
- background-color: var(--color-success-container);
15909
+ background-color: var(--color-success);
15039
15910
  border-color: transparent;
15040
- color: var(--color-on-success-container);
15911
+ color: var(--color-success-content);
15041
15912
  }
15042
15913
 
15043
15914
  .toast-filled.toast-warning {
15044
- background-color: var(--color-warning-container);
15915
+ background-color: var(--color-warning);
15045
15916
  border-color: transparent;
15046
- color: var(--color-on-warning-container);
15917
+ color: var(--color-warning-content);
15047
15918
  }
15048
15919
 
15049
15920
  .toast-filled.toast-error {
15050
- background-color: var(--color-error-container);
15921
+ background-color: var(--color-error);
15051
15922
  border-color: transparent;
15052
- color: var(--color-on-error-container);
15923
+ color: var(--color-error-content);
15053
15924
  }
15054
15925
 
15055
15926
  .toast-filled.toast-primary {
15056
- background-color: var(--color-primary-container);
15927
+ background-color: var(--color-primary);
15057
15928
  border-color: transparent;
15058
- color: var(--color-on-primary-container);
15929
+ color: var(--color-primary-content);
15059
15930
  }
15060
15931
 
15061
15932
  .toast-filled.toast-secondary {
15062
- background-color: var(--color-secondary-container);
15933
+ background-color: var(--color-secondary);
15063
15934
  border-color: transparent;
15064
- color: var(--color-on-secondary-container);
15935
+ color: var(--color-secondary-content);
15065
15936
  }
15066
15937
 
15067
15938
  .toast-filled.toast-tertiary {
15068
- background-color: var(--color-tertiary-container);
15069
- border-color: transparent;
15070
- color: var(--color-on-tertiary-container);
15071
- }
15072
-
15073
- .toast-filled.toast-accent {
15074
- background-color: color-mix(in oklch, var(--color-accent) 15%, var(--color-surface));
15939
+ background-color: var(--color-tertiary);
15075
15940
  border-color: transparent;
15076
- color: var(--color-on-surface);
15941
+ color: var(--color-tertiary-content);
15077
15942
  }
15078
15943
 
15079
15944
  .toast-filled.toast-neutral {
15080
- background-color: color-mix(in oklch, var(--color-neutral) 15%, var(--color-surface));
15945
+ background-color: var(--color-neutral);
15081
15946
  border-color: transparent;
15082
- color: var(--color-on-surface);
15947
+ color: var(--color-neutral-content);
15083
15948
  }
15084
15949
 
15085
15950
  .toast-filled.toast-base {
@@ -15092,8 +15957,16 @@ html {
15092
15957
  .toast-title and .toast-message have explicit color rules that would otherwise
15093
15958
  override the filled variant's inherited on-container color. */
15094
15959
  .toast-filled .toast-title,
15095
- .toast-filled .toast-message {
15960
+ .toast-filled .toast-message,
15961
+ .toast-filled .toast-icon,
15962
+ .toast-filled .toast-close,
15963
+ .toast-filled .toast-action {
15964
+ color: inherit;
15965
+ }
15966
+
15967
+ .toast-filled .toast-close:hover {
15096
15968
  color: inherit;
15969
+ background-color: color-mix(in oklch, currentColor 12%, transparent);
15097
15970
  }
15098
15971
 
15099
15972
  /* Ghost Variant */
@@ -15102,6 +15975,7 @@ html {
15102
15975
  border-color: transparent;
15103
15976
  }
15104
15977
 
15978
+ .toast-ghost.toast-accent { color: var(--color-accent); }
15105
15979
  .toast-ghost.toast-primary { color: var(--color-primary); }
15106
15980
  .toast-ghost.toast-secondary { color: var(--color-secondary); }
15107
15981
  .toast-ghost.toast-tertiary { color: var(--color-tertiary); }
@@ -15109,7 +15983,6 @@ html {
15109
15983
  .toast-ghost.toast-success { color: var(--color-success); }
15110
15984
  .toast-ghost.toast-warning { color: var(--color-warning); }
15111
15985
  .toast-ghost.toast-error { color: var(--color-error); }
15112
- .toast-ghost.toast-accent { color: var(--color-accent); }
15113
15986
  .toast-ghost.toast-neutral { color: var(--color-neutral); }
15114
15987
  .toast-ghost.toast-base { color: var(--color-base-content); }
15115
15988
 
@@ -15118,6 +15991,49 @@ html {
15118
15991
  color: inherit;
15119
15992
  }
15120
15993
 
15994
+ /* Size and density variants retained by the public API. */
15995
+ .toast-sm {
15996
+ width: 18rem;
15997
+ padding: 0.75rem;
15998
+ }
15999
+
16000
+ .toast-lg {
16001
+ width: 26rem;
16002
+ padding: 1.25rem;
16003
+ }
16004
+
16005
+ .toast-compact {
16006
+ padding: 0.75rem;
16007
+ gap: 0.5rem;
16008
+ }
16009
+
16010
+ .toast-compact .toast-icon {
16011
+ width: 1.25rem;
16012
+ height: 1.25rem;
16013
+ font-size: 1rem;
16014
+ }
16015
+
16016
+ .toast-compact .toast-title { font-size: 0.8125rem; }
16017
+ .toast-compact .toast-message { font-size: 0.8125rem; }
16018
+
16019
+ /* Accent edge and stacked presentation. */
16020
+ .toast-accent::before {
16021
+ content: "";
16022
+ position: absolute;
16023
+ inset-block: 0;
16024
+ inset-inline-start: 0;
16025
+ width: 0.25rem;
16026
+ background-color: var(--_toast-accent-color);
16027
+ border-start-start-radius: var(--radius-md);
16028
+ border-end-start-radius: var(--radius-md);
16029
+ }
16030
+
16031
+ .toast-container-stacked .toast:not(:first-child) {
16032
+ margin-top: -0.75rem;
16033
+ transform: scale(0.97);
16034
+ opacity: 0.9;
16035
+ }
16036
+
15121
16037
  /* Progress Bar (for auto-dismiss) */
15122
16038
  .toast-progress {
15123
16039
  position: absolute;
@@ -15148,6 +16064,22 @@ html {
15148
16064
  .toast-progress {
15149
16065
  animation: none;
15150
16066
  }
16067
+
16068
+ .toast-container { scroll-behavior: auto; }
16069
+ }
16070
+
16071
+ @media (max-width: 40rem) {
16072
+ .toast-container[popover] {
16073
+ inset-inline: 0;
16074
+ width: 100%;
16075
+ transform: none;
16076
+ align-items: stretch;
16077
+ }
16078
+
16079
+ .toast {
16080
+ width: 100%;
16081
+ max-width: 100%;
16082
+ }
15151
16083
  }
15152
16084
  }
15153
16085
 
@@ -15229,53 +16161,8 @@ html {
15229
16161
  position-area: right;
15230
16162
  }
15231
16163
 
15232
- /* ========================================
15233
- * Arrow (preferred position only; may be wrong after flip)
15234
- * ======================================== */
15235
-
15236
- .tooltip[popover]::before {
15237
- content: '';
15238
- position: absolute;
15239
- width: 0;
15240
- height: 0;
15241
- border: 0.375rem solid transparent;
15242
- }
15243
-
15244
- .tooltip-top[popover]::before,
15245
- .tooltip[popover]:not(.tooltip-bottom):not(.tooltip-left):not(.tooltip-right)::before {
15246
- top: 100%;
15247
- left: 50%;
15248
- transform: translateX(-50%);
15249
- border-top-color: var(--tooltip-bg);
15250
- }
15251
-
15252
- .tooltip-bottom[popover]::before {
15253
- bottom: 100%;
15254
- top: auto;
15255
- left: 50%;
15256
- transform: translateX(-50%);
15257
- border-bottom-color: var(--tooltip-bg);
15258
- border-top-color: transparent;
15259
- }
15260
-
15261
- .tooltip-left[popover]::before {
15262
- left: 100%;
15263
- top: 50%;
15264
- bottom: auto;
15265
- transform: translateY(-50%);
15266
- border-left-color: var(--tooltip-bg);
15267
- border-top-color: transparent;
15268
- }
15269
-
15270
- .tooltip-right[popover]::before {
15271
- right: 100%;
15272
- left: auto;
15273
- top: 50%;
15274
- bottom: auto;
15275
- transform: translateY(-50%);
15276
- border-right-color: var(--tooltip-bg);
15277
- border-top-color: transparent;
15278
- }
16164
+ /* Automatic placement can flip independently of the preferred side. The
16165
+ core stays arrowless instead of showing a misleading arrow. */
15279
16166
 
15280
16167
  /* ========================================
15281
16168
  * Color variants