@digiko-npm/designsystem 0.8.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digiko-npm/designsystem",
3
- "version": "0.8.3",
3
+ "version": "0.9.0",
4
4
  "description": "Design system — installable, extensible, indestructible.",
5
5
  "main": "dist/designsystem.css",
6
6
  "style": "dist/designsystem.css",
@@ -35,6 +35,7 @@
35
35
  "./components/empty-state": "./src/components/empty-state.css",
36
36
  "./components/field": "./src/components/field.css",
37
37
  "./components/gallery": "./src/components/gallery.css",
38
+ "./components/hero": "./src/components/hero.css",
38
39
  "./components/icon-btn": "./src/components/icon-btn.css",
39
40
  "./components/input": "./src/components/input.css",
40
41
  "./components/kbd": "./src/components/kbd.css",
@@ -45,6 +46,7 @@
45
46
  "./components/pin-input": "./src/components/pin-input.css",
46
47
  "./components/popover": "./src/components/popover.css",
47
48
  "./components/progress": "./src/components/progress.css",
49
+ "./components/prose": "./src/components/prose.css",
48
50
  "./components/result": "./src/components/result.css",
49
51
  "./components/scroll-area": "./src/components/scroll-area.css",
50
52
  "./components/search": "./src/components/search.css",
@@ -0,0 +1,113 @@
1
+ /* ==========================================================================
2
+ Component: Hero
3
+ Full-width hero section with background image, gradient overlay,
4
+ and optional frosted glass backdrop.
5
+
6
+ Intentionally uses theme-independent colors for text on photo backgrounds.
7
+ The overlay uses color-mix() with --ds-color-bg for theme-aware darkening
8
+ while title/subtitle stay white for readability on any photo.
9
+
10
+ Usage:
11
+ <section class="ds-hero" style="background-image: url(...)">
12
+ <div class="ds-hero__overlay"></div>
13
+ <div class="ds-hero__content ds-container">
14
+ <div class="ds-hero__backdrop">
15
+ <h1 class="ds-hero__title ds-hero-title">Heading</h1>
16
+ <p class="ds-hero__subtitle">Subheading</p>
17
+ </div>
18
+ </div>
19
+ </section>
20
+
21
+ Variants:
22
+ ds-hero--full Generous padding, auto height (no min-height)
23
+ ds-hero__overlay--subtle Lighter overlay, photo shows through more
24
+
25
+ ARIA: role="banner" or within <header>. Background images are decorative
26
+ — add meaningful content in the markup, not in CSS.
27
+ ========================================================================== */
28
+
29
+ .ds-hero {
30
+ position: relative;
31
+ min-height: 28rem;
32
+ display: flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ text-align: center;
36
+ background-size: cover;
37
+ background-position: center;
38
+ }
39
+
40
+ /* --- Full variant (generous padding, no min-height) --- */
41
+ .ds-hero--full {
42
+ min-height: auto;
43
+ padding-block: var(--ds-space-16);
44
+ }
45
+
46
+ @media (min-width: 768px) {
47
+ .ds-hero--full {
48
+ padding-block: var(--ds-space-20);
49
+ }
50
+ }
51
+
52
+ /* --- Gradient overlay (theme-aware darkening) --- */
53
+ .ds-hero__overlay {
54
+ position: absolute;
55
+ inset: 0;
56
+ background: linear-gradient(
57
+ to bottom,
58
+ color-mix(in srgb, var(--ds-color-bg) 70%, transparent),
59
+ color-mix(in srgb, var(--ds-color-bg) 92%, transparent)
60
+ );
61
+ }
62
+
63
+ .ds-hero__overlay--subtle {
64
+ background: linear-gradient(
65
+ to bottom,
66
+ color-mix(in srgb, var(--ds-color-bg) 20%, transparent),
67
+ color-mix(in srgb, var(--ds-color-bg) 40%, transparent)
68
+ );
69
+ }
70
+
71
+ [data-theme="dark"] .ds-hero__overlay {
72
+ background: linear-gradient(
73
+ to bottom,
74
+ color-mix(in srgb, var(--ds-color-bg) 80%, transparent),
75
+ color-mix(in srgb, var(--ds-color-bg) 95%, transparent)
76
+ );
77
+ }
78
+
79
+ [data-theme="dark"] .ds-hero__overlay--subtle {
80
+ background: linear-gradient(
81
+ to bottom,
82
+ color-mix(in srgb, var(--ds-color-bg) 30%, transparent),
83
+ color-mix(in srgb, var(--ds-color-bg) 50%, transparent)
84
+ );
85
+ }
86
+
87
+ /* --- Content wrapper (above overlay) --- */
88
+ .ds-hero__content {
89
+ position: relative;
90
+ z-index: 1;
91
+ width: 100%;
92
+ }
93
+
94
+ /* --- Frosted glass backdrop --- */
95
+ .ds-hero__backdrop {
96
+ display: block;
97
+ padding: var(--ds-space-8);
98
+ border-radius: var(--ds-radius-2xl);
99
+ background: rgba(0, 0, 0, 0.35);
100
+ backdrop-filter: blur(32px) saturate(1.6);
101
+ -webkit-backdrop-filter: blur(32px) saturate(1.6);
102
+ max-width: 40rem;
103
+ margin-inline: auto;
104
+ }
105
+
106
+ /* --- Title & subtitle (theme-independent white for photo readability) --- */
107
+ .ds-hero__title {
108
+ color: #fff;
109
+ }
110
+
111
+ .ds-hero__subtitle {
112
+ color: rgba(255, 255, 255, 0.85);
113
+ }
@@ -57,6 +57,10 @@
57
57
  @import './collapsible.css';
58
58
  @import './scroll-area.css';
59
59
  @import './gallery.css';
60
+ @import './hero.css';
61
+
62
+ /* === Content — Rich text and prose === */
63
+ @import './prose.css';
60
64
 
61
65
  /* === Action — Trigger operations and commands === */
62
66
  @import './button.css';
@@ -0,0 +1,119 @@
1
+ /* ==========================================================================
2
+ Component: Prose Block
3
+ Full markdown-rendered content styling. Use for CMS output, blog posts,
4
+ documentation, or any container with user-generated rich text.
5
+
6
+ Note: The lighter `.ds-prose` in base/typography.css handles simple
7
+ inline rich text (p + p spacing, links, lists). This component is for
8
+ comprehensive markdown rendering with headings, code blocks, blockquotes,
9
+ images, and horizontal rules.
10
+
11
+ Usage:
12
+ <div class="ds-prose-block">
13
+ <h2>Title</h2>
14
+ <p>Paragraph with <a href="#">link</a> and <code>code</code>.</p>
15
+ <pre><code>code block</code></pre>
16
+ <blockquote>Quote</blockquote>
17
+ </div>
18
+ ========================================================================== */
19
+
20
+ .ds-prose-block {
21
+ line-height: var(--ds-leading-relaxed);
22
+ }
23
+
24
+ .ds-prose-block :is(h1, h2, h3, h4, h5, h6) {
25
+ font-family: var(--ds-font-display);
26
+ font-weight: var(--ds-font-display-weight);
27
+ letter-spacing: var(--ds-tracking-tight);
28
+ color: var(--ds-color-text);
29
+ margin-block-start: 1.5em;
30
+ margin-block-end: 0.5em;
31
+ }
32
+
33
+ .ds-prose-block :is(h1, h2, h3, h4, h5, h6):first-child {
34
+ margin-block-start: 0;
35
+ }
36
+
37
+ .ds-prose-block p {
38
+ color: var(--ds-color-text-secondary);
39
+ margin-block-end: 1em;
40
+ }
41
+
42
+ .ds-prose-block p:last-child {
43
+ margin-block-end: 0;
44
+ }
45
+
46
+ .ds-prose-block a {
47
+ color: var(--ds-color-interactive);
48
+ text-decoration: none;
49
+ }
50
+
51
+ .ds-prose-block a:hover {
52
+ text-decoration: underline;
53
+ }
54
+
55
+ .ds-prose-block strong {
56
+ color: var(--ds-color-text);
57
+ font-weight: var(--ds-weight-semibold);
58
+ }
59
+
60
+ .ds-prose-block code {
61
+ font-family: var(--ds-font-mono);
62
+ font-size: var(--ds-text-sm);
63
+ background-color: var(--ds-color-bg-elevated);
64
+ padding: 0.125em 0.375em;
65
+ border-radius: var(--ds-radius-sm);
66
+ }
67
+
68
+ .ds-prose-block pre {
69
+ background-color: var(--ds-color-bg-elevated);
70
+ padding: var(--ds-space-4);
71
+ border-radius: var(--ds-radius-lg);
72
+ overflow-x: auto;
73
+ margin-block-end: 1em;
74
+ }
75
+
76
+ .ds-prose-block pre code {
77
+ background: none;
78
+ padding: 0;
79
+ border-radius: 0;
80
+ }
81
+
82
+ .ds-prose-block ul,
83
+ .ds-prose-block ol {
84
+ padding-inline-start: 1.5em;
85
+ margin-block-end: 1em;
86
+ color: var(--ds-color-text-secondary);
87
+ }
88
+
89
+ .ds-prose-block li {
90
+ margin-block-end: 0.25em;
91
+ }
92
+
93
+ .ds-prose-block ul {
94
+ list-style-type: disc;
95
+ }
96
+
97
+ .ds-prose-block ol {
98
+ list-style-type: decimal;
99
+ }
100
+
101
+ .ds-prose-block blockquote {
102
+ border-inline-start: 3px solid var(--ds-color-border);
103
+ padding-inline-start: var(--ds-space-4);
104
+ color: var(--ds-color-text-secondary);
105
+ font-style: italic;
106
+ margin-block-end: 1em;
107
+ }
108
+
109
+ .ds-prose-block hr {
110
+ border: none;
111
+ border-block-start: 1px solid var(--ds-color-border);
112
+ margin-block: var(--ds-space-6);
113
+ }
114
+
115
+ .ds-prose-block img {
116
+ max-width: 100%;
117
+ border-radius: var(--ds-radius-lg);
118
+ margin-block-end: 1em;
119
+ }
@@ -1,5 +1,7 @@
1
1
  @import './layout.css';
2
2
  @import './spacing.css';
3
+ @import './sizing.css';
3
4
  @import './text.css';
4
5
  @import './interactive.css';
6
+ @import './states.css';
5
7
  @import './a11y.css';
@@ -246,6 +246,27 @@
246
246
  .ds-xl\:grid-cols-6 { grid-template-columns: repeat(6, 1fr); }
247
247
  }
248
248
 
249
+ /* --- Responsive: Flex (extended) --- */
250
+ @media (min-width: 640px) {
251
+ .ds-sm\:flex-none { flex: none; }
252
+ .ds-sm\:items-center { align-items: center; }
253
+ .ds-sm\:justify-between { justify-content: space-between; }
254
+ .ds-sm\:gap-4 { gap: var(--ds-space-4); }
255
+ .ds-sm\:gap-8 { gap: var(--ds-space-8); }
256
+ .ds-sm\:inline { display: inline; }
257
+ }
258
+
259
+ @media (min-width: 768px) {
260
+ .ds-md\:grid-cols-5 { grid-template-columns: repeat(5, 1fr); }
261
+ }
262
+
263
+ @media (min-width: 1024px) /* --ds-breakpoint-lg */ {
264
+ .ds-lg\:flex-row { flex-direction: row; }
265
+ .ds-lg\:gap-4 { gap: var(--ds-space-4); }
266
+ .ds-lg\:gap-6 { gap: var(--ds-space-6); }
267
+ .ds-lg\:gap-8 { gap: var(--ds-space-8); }
268
+ }
269
+
249
270
  /* --- Aspect Ratio --- */
250
271
  .ds-aspect-square { aspect-ratio: 1; }
251
272
  .ds-aspect-video { aspect-ratio: 16/9; }
@@ -0,0 +1,71 @@
1
+ /* ==========================================================================
2
+ Utilities: Sizing
3
+ Width, height, min/max constraints.
4
+ Extends the base sizing in layout.css with the full spacing scale.
5
+ ========================================================================== */
6
+
7
+ /* --- Width (values not already in layout.css) --- */
8
+ .ds-w-0 { width: var(--ds-space-0); }
9
+ .ds-w-1 { width: var(--ds-space-1); }
10
+ .ds-w-1\.5 { width: var(--ds-space-1-5); }
11
+ .ds-w-2 { width: var(--ds-space-2); }
12
+ .ds-w-3\.5 { width: 0.875rem; }
13
+ .ds-w-6 { width: var(--ds-space-6); }
14
+ .ds-w-12 { width: var(--ds-space-12); }
15
+ .ds-w-16 { width: var(--ds-space-16); }
16
+ .ds-w-20 { width: var(--ds-space-20); }
17
+ .ds-w-24 { width: var(--ds-space-24); }
18
+ .ds-w-28 { width: 7rem; }
19
+ .ds-w-32 { width: var(--ds-space-32); }
20
+ .ds-w-48 { width: 12rem; }
21
+ .ds-w-56 { width: 14rem; }
22
+ .ds-w-64 { width: 16rem; }
23
+ .ds-w-80 { width: 20rem; }
24
+ .ds-w-96 { width: 24rem; }
25
+ .ds-w-auto { width: auto; }
26
+ .ds-w-screen { width: 100vw; }
27
+
28
+ /* --- Height (values not already in layout.css) --- */
29
+ .ds-h-0 { height: var(--ds-space-0); }
30
+ .ds-h-0\.5 { height: var(--ds-space-0-5); }
31
+ .ds-h-1 { height: var(--ds-space-1); }
32
+ .ds-h-1\.5 { height: var(--ds-space-1-5); }
33
+ .ds-h-2 { height: var(--ds-space-2); }
34
+ .ds-h-3\.5 { height: 0.875rem; }
35
+ .ds-h-6 { height: var(--ds-space-6); }
36
+ .ds-h-12 { height: var(--ds-space-12); }
37
+ .ds-h-14 { height: 3.5rem; }
38
+ .ds-h-20 { height: var(--ds-space-20); }
39
+ .ds-h-24 { height: var(--ds-space-24); }
40
+ .ds-h-28 { height: 7rem; }
41
+ .ds-h-32 { height: var(--ds-space-32); }
42
+ .ds-h-48 { height: 12rem; }
43
+ .ds-h-64 { height: 16rem; }
44
+ .ds-h-96 { height: 24rem; }
45
+ .ds-h-auto { height: auto; }
46
+ .ds-h-px { height: 1px; }
47
+
48
+ /* --- Max Width (extended) --- */
49
+ .ds-max-w-4xl { max-width: 56rem; }
50
+ .ds-max-w-5xl { max-width: 64rem; }
51
+ .ds-max-w-6xl { max-width: 72rem; }
52
+ .ds-max-w-7xl { max-width: 80rem; }
53
+ .ds-max-w-full { max-width: 100%; }
54
+
55
+ /* --- Max Height --- */
56
+ .ds-max-h-64 { max-height: 16rem; }
57
+ .ds-max-h-80 { max-height: 20rem; }
58
+ .ds-max-h-96 { max-height: 24rem; }
59
+ .ds-max-h-screen { max-height: 100dvh; }
60
+
61
+ /* --- Responsive: Sizing --- */
62
+ @media (min-width: 640px) {
63
+ .ds-sm\:w-12 { width: var(--ds-space-12); }
64
+ .ds-sm\:w-16 { width: var(--ds-space-16); }
65
+ .ds-sm\:w-32 { width: var(--ds-space-32); }
66
+ .ds-sm\:w-64 { width: 16rem; }
67
+ .ds-sm\:w-96 { width: 24rem; }
68
+ .ds-sm\:w-auto { width: auto; }
69
+ .ds-sm\:h-12 { height: var(--ds-space-12); }
70
+ .ds-sm\:h-32 { height: var(--ds-space-32); }
71
+ }
@@ -85,8 +85,15 @@
85
85
 
86
86
  .ds-mt-0\.5 { margin-block-start: var(--ds-space-0-5); }
87
87
  .ds-mt-3 { margin-block-start: var(--ds-space-3); }
88
+ .ds-mt-10 { margin-block-start: var(--ds-space-10); }
89
+ .ds-mt-12 { margin-block-start: var(--ds-space-12); }
90
+ .ds-mt-16 { margin-block-start: var(--ds-space-16); }
88
91
  .ds-mb-0\.5 { margin-block-end: var(--ds-space-0-5); }
89
92
  .ds-mb-3 { margin-block-end: var(--ds-space-3); }
93
+ .ds-mb-10 { margin-block-end: var(--ds-space-10); }
94
+ .ds-mb-12 { margin-block-end: var(--ds-space-12); }
95
+ .ds-mb-16 { margin-block-end: var(--ds-space-16); }
96
+ .ds-mb-20 { margin-block-end: var(--ds-space-20); }
90
97
 
91
98
  /* --- Padding (granular) --- */
92
99
  .ds-p-0\.5 { padding: var(--ds-space-0-5); }
@@ -123,7 +130,19 @@
123
130
  .ds-space-y-6 > * + * { margin-block-start: var(--ds-space-6); }
124
131
  .ds-space-y-8 > * + * { margin-block-start: var(--ds-space-8); }
125
132
 
133
+ /* --- Space-Y (fractional) --- */
134
+ .ds-space-y-1\.5 > * + * { margin-block-start: var(--ds-space-1-5); }
135
+
126
136
  /* --- Responsive: Padding --- */
137
+ @media (min-width: 640px) {
138
+ .ds-sm\:p-6 { padding: var(--ds-space-6); }
139
+ .ds-sm\:px-0 { padding-inline: var(--ds-space-0); }
140
+ .ds-sm\:px-3 { padding-inline: var(--ds-space-3); }
141
+ .ds-sm\:px-4 { padding-inline: var(--ds-space-4); }
142
+ .ds-sm\:px-6 { padding-inline: var(--ds-space-6); }
143
+ .ds-sm\:py-3 { padding-block: var(--ds-space-3); }
144
+ }
145
+
127
146
  @media (min-width: 768px) {
128
147
  .ds-md\:px-4 { padding-inline: var(--ds-space-4); }
129
148
  .ds-md\:px-6 { padding-inline: var(--ds-space-6); }
@@ -0,0 +1,74 @@
1
+ /* ==========================================================================
2
+ Utilities: State Variants
3
+ Hover, focus, active, focus-within, placeholder, and group-hover
4
+ modifiers for DS utility classes.
5
+ ========================================================================== */
6
+
7
+ /* --- Group Marker (enables group-hover on descendants) ---
8
+ Supports both .group and .ds-group for compatibility. */
9
+ .ds-group { /* marker — no styles */ }
10
+
11
+ /* --- Hover: Background --- */
12
+ .hover\:ds-bg-base:hover { background-color: var(--ds-color-bg); }
13
+ .hover\:ds-bg-elevated:hover { background-color: var(--ds-color-bg-elevated); }
14
+ .hover\:ds-bg-muted:hover { background-color: var(--ds-color-bg-muted); }
15
+ .hover\:ds-bg-subtle:hover { background-color: var(--ds-color-bg-subtle); }
16
+ .hover\:ds-bg-surface:hover { background-color: var(--ds-color-surface); }
17
+ .hover\:ds-bg-inverted:hover { background-color: var(--ds-color-inverted); }
18
+ .hover\:ds-bg-info:hover { background-color: var(--ds-color-info); }
19
+
20
+ /* --- Hover: Text --- */
21
+ .hover\:ds-text-primary:hover { color: var(--ds-color-text); }
22
+ .hover\:ds-text-secondary:hover { color: var(--ds-color-text-secondary); }
23
+ .hover\:ds-text-interactive:hover { color: var(--ds-color-interactive); }
24
+
25
+ /* --- Hover: Border --- */
26
+ .hover\:ds-border-hover:hover { border-color: var(--ds-color-border-hover); }
27
+ .hover\:ds-border-interactive:hover { border-color: var(--ds-color-interactive); }
28
+
29
+ /* --- Hover: Decoration --- */
30
+ .hover\:ds-underline:hover { text-decoration: underline; text-underline-offset: 2px; }
31
+
32
+ /* --- Focus --- */
33
+ .focus\:ds-outline-none:focus { outline: none; }
34
+ .focus\:ds-ring-0:focus { box-shadow: none; }
35
+ .focus\:ds-ring-2:focus { box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-color-interactive); }
36
+
37
+ /* --- Focus-Within --- */
38
+ .focus-within\:ds-border-interactive:focus-within { border-color: var(--ds-color-interactive); }
39
+
40
+ /* --- Active --- */
41
+ .active\:ds-bg-elevated:active { background-color: var(--ds-color-bg-elevated); }
42
+ .active\:ds-text-secondary:active { color: var(--ds-color-text-secondary); }
43
+
44
+ /* --- Placeholder --- */
45
+ .placeholder\:ds-text-tertiary::placeholder { color: var(--ds-color-text-tertiary); }
46
+
47
+ /* --- Group Hover (descendants of .group or .ds-group on hover) --- */
48
+ .group:hover > .group-hover\:ds-text-interactive,
49
+ .group:hover .group-hover\:ds-text-interactive,
50
+ .ds-group:hover > .group-hover\:ds-text-interactive,
51
+ .ds-group:hover .group-hover\:ds-text-interactive {
52
+ color: var(--ds-color-interactive);
53
+ }
54
+
55
+ .group:hover > .group-hover\:ds-scale-110,
56
+ .group:hover .group-hover\:ds-scale-110,
57
+ .ds-group:hover > .group-hover\:ds-scale-110,
58
+ .ds-group:hover .group-hover\:ds-scale-110 {
59
+ transform: scale(1.1);
60
+ }
61
+
62
+ .group:hover > .group-hover\:ds-translate-x-1,
63
+ .group:hover .group-hover\:ds-translate-x-1,
64
+ .ds-group:hover > .group-hover\:ds-translate-x-1,
65
+ .ds-group:hover .group-hover\:ds-translate-x-1 {
66
+ transform: translateX(0.25rem);
67
+ }
68
+
69
+ .group:hover > .group-hover\:ds-opacity-100,
70
+ .group:hover .group-hover\:ds-opacity-100,
71
+ .ds-group:hover > .group-hover\:ds-opacity-100,
72
+ .ds-group:hover .group-hover\:ds-opacity-100 {
73
+ opacity: 1;
74
+ }
@@ -151,6 +151,13 @@
151
151
  overflow: hidden;
152
152
  }
153
153
 
154
+ .ds-line-clamp-1 {
155
+ display: -webkit-box;
156
+ -webkit-line-clamp: 1;
157
+ -webkit-box-orient: vertical;
158
+ overflow: hidden;
159
+ }
160
+
154
161
  .ds-line-clamp-3 {
155
162
  display: -webkit-box;
156
163
  -webkit-line-clamp: 3;
@@ -158,6 +165,12 @@
158
165
  overflow: hidden;
159
166
  }
160
167
 
168
+ /* --- Text Extras --- */
169
+ .ds-line-through { text-decoration: line-through; }
170
+ .ds-break-all { word-break: break-all; }
171
+ .ds-list-disc { list-style-type: disc; }
172
+ .ds-list-inside { list-style-position: inside; }
173
+
161
174
  /* --- Font Family --- */
162
175
  .ds-font-mono { font-family: var(--ds-font-mono); }
163
176
  .ds-font-sans { font-family: var(--ds-font-sans); }
@@ -168,6 +181,7 @@
168
181
  .ds-border-b { border-block-end: 1px solid var(--ds-color-border); }
169
182
  .ds-border-l { border-inline-start: 1px solid var(--ds-color-border); }
170
183
  .ds-border-r { border-inline-end: 1px solid var(--ds-color-border); }
184
+ .ds-border-y { border-block-start: 1px solid var(--ds-color-border); border-block-end: 1px solid var(--ds-color-border); }
171
185
  .ds-border-none { border: none; }
172
186
 
173
187
  /* --- Border Color --- */
@@ -188,8 +202,15 @@
188
202
  .ds-rounded-lg { border-radius: var(--ds-radius-lg); }
189
203
  .ds-rounded-xl { border-radius: var(--ds-radius-xl); }
190
204
  .ds-rounded-2xl { border-radius: var(--ds-radius-2xl); }
205
+ .ds-rounded-3xl { border-radius: 1.5rem; }
191
206
  .ds-rounded-full { border-radius: var(--ds-radius-full); }
192
207
 
208
+ /* --- Border Radius (directional) --- */
209
+ .ds-rounded-t { border-start-start-radius: var(--ds-radius-md); border-start-end-radius: var(--ds-radius-md); }
210
+ .ds-rounded-b { border-end-start-radius: var(--ds-radius-md); border-end-end-radius: var(--ds-radius-md); }
211
+ .ds-rounded-t-2xl { border-start-start-radius: var(--ds-radius-2xl); border-start-end-radius: var(--ds-radius-2xl); }
212
+ .ds-rounded-b-2xl { border-end-start-radius: var(--ds-radius-2xl); border-end-end-radius: var(--ds-radius-2xl); }
213
+
193
214
  /* --- Shadow --- */
194
215
  .ds-shadow-sm { box-shadow: var(--ds-shadow-sm); }
195
216
  .ds-shadow { box-shadow: var(--ds-shadow-md); }
@@ -198,7 +219,11 @@
198
219
 
199
220
  /* --- Opacity --- */
200
221
  .ds-opacity-0 { opacity: 0; }
222
+ .ds-opacity-25 { opacity: 0.25; }
201
223
  .ds-opacity-50 { opacity: 0.5; }
224
+ .ds-opacity-60 { opacity: 0.6; }
225
+ .ds-opacity-70 { opacity: 0.7; }
226
+ .ds-opacity-75 { opacity: 0.75; }
202
227
  .ds-opacity-100 { opacity: 1; }
203
228
 
204
229
  /* --- Cursor --- */
@@ -212,6 +237,7 @@
212
237
  .ds-pointer-events-none { pointer-events: none; }
213
238
  .ds-select-none { user-select: none; }
214
239
  .ds-whitespace-nowrap { white-space: nowrap; }
240
+ .ds-whitespace-pre-wrap { white-space: pre-wrap; }
215
241
 
216
242
  /* --- Backdrop --- */
217
243
  .ds-backdrop-blur {
@@ -219,6 +245,14 @@
219
245
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
220
246
  }
221
247
 
248
+ .ds-backdrop-blur-sm {
249
+ backdrop-filter: blur(4px);
250
+ -webkit-backdrop-filter: blur(4px);
251
+ }
252
+
253
+ /* --- Outline --- */
254
+ .ds-outline-none { outline: none; }
255
+
222
256
  /* --- Transform --- */
223
257
  .-ds-translate-y-1\/2 { transform: translateY(-50%); }
224
258
  .-ds-translate-x-1\/2 { transform: translateX(-50%); }
@@ -249,6 +283,17 @@
249
283
  transition: transform var(--ds-duration-normal) var(--ds-ease-default);
250
284
  }
251
285
 
286
+ /* --- Duration --- */
287
+ .ds-duration-fast { transition-duration: var(--ds-duration-fast); }
288
+ .ds-duration-normal { transition-duration: var(--ds-duration-normal); }
289
+ .ds-duration-slow { transition-duration: var(--ds-duration-slow); }
290
+ .ds-duration-slower { transition-duration: var(--ds-duration-slower); }
291
+
292
+ /* --- Easing --- */
293
+ .ds-ease-default { transition-timing-function: var(--ds-ease-default); }
294
+ .ds-ease-out { transition-timing-function: var(--ds-ease-out); }
295
+ .ds-ease-out-expo { transition-timing-function: var(--ds-ease-out-expo); }
296
+
252
297
  /* --- Animations --- */
253
298
  @keyframes ds-fade-in {
254
299
  from { opacity: 0; }