osi-cards-lib 1.5.32 → 1.5.34

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 (87) hide show
  1. package/fesm2022/osi-cards-lib.mjs +31889 -0
  2. package/fesm2022/osi-cards-lib.mjs.map +1 -0
  3. package/index.d.ts +11528 -0
  4. package/package.json +25 -13
  5. package/scripts/setup-angular-styles.js +169 -0
  6. package/styles/_components.scss +38 -0
  7. package/styles/_index.scss +25 -0
  8. package/styles/_osi-cards-mixins.scss +459 -0
  9. package/styles/_osi-cards-tokens.scss +333 -0
  10. package/styles/_styles-scoped.scss +81 -0
  11. package/styles/_styles.scss +26 -0
  12. package/styles/bundles/_ai-card.scss +245 -0
  13. package/styles/bundles/_all.scss +68 -0
  14. package/styles/bundles/_base.scss +60 -0
  15. package/styles/bundles/_card-skeleton.scss +290 -0
  16. package/styles/bundles/_index.scss +25 -0
  17. package/styles/bundles/_sections.scss +48 -0
  18. package/styles/bundles/_tokens-only.scss +139 -0
  19. package/styles/components/_ai-card-renderer.scss +104 -0
  20. package/styles/components/_badges.scss +317 -0
  21. package/styles/components/_card-actions.scss +169 -0
  22. package/styles/components/_card-footer.scss +47 -0
  23. package/styles/components/_component-styles.scss +205 -0
  24. package/styles/components/_empty-state.scss +630 -0
  25. package/styles/components/_hero-card.scss +422 -0
  26. package/styles/components/_image-fallback.scss +28 -0
  27. package/styles/components/_streaming-effects.scss +518 -0
  28. package/styles/components/cards/_ai-card.scss +718 -0
  29. package/styles/components/sections/_all-sections.generated.scss +41 -0
  30. package/styles/components/sections/_all-sections.scss +1086 -0
  31. package/styles/components/sections/_balanced-compact-system.scss +186 -0
  32. package/styles/components/sections/_compact-mixins.scss +180 -0
  33. package/styles/components/sections/_component-mixins.scss +454 -0
  34. package/styles/components/sections/_design-system.scss +477 -0
  35. package/styles/components/sections/_design-tokens.scss +308 -0
  36. package/styles/components/sections/_enhanced-design-variables.scss +147 -0
  37. package/styles/components/sections/_master-compact-system.scss +302 -0
  38. package/styles/components/sections/_master-dense-system.scss +239 -0
  39. package/styles/components/sections/_minimalistic-design.scss +268 -0
  40. package/styles/components/sections/_modern-effects.scss +392 -0
  41. package/styles/components/sections/_modern-sections.scss +351 -0
  42. package/styles/components/sections/_perfect-system.scss +204 -0
  43. package/styles/components/sections/_section-animations.scss +331 -0
  44. package/styles/components/sections/_section-shell.scss +337 -0
  45. package/styles/components/sections/_section-types.generated.scss +30 -0
  46. package/styles/components/sections/_sections-all.scss +26 -0
  47. package/styles/components/sections/_sections-base.scss +334 -0
  48. package/styles/components/sections/_typography-system.scss +327 -0
  49. package/styles/components/sections/_ultra-compact-tokens.scss +375 -0
  50. package/styles/components/sections/_unified-section-style.scss +157 -0
  51. package/styles/components/sections/_utility-classes.scss +567 -0
  52. package/styles/components/sections/_visual-effects-library.scss +374 -0
  53. package/styles/core/_animations.scss +1498 -0
  54. package/styles/core/_bootstrap-reset.scss +445 -0
  55. package/styles/core/_color-helpers.scss +46 -0
  56. package/styles/core/_global-unified.scss +118 -0
  57. package/styles/core/_global.scss +73 -0
  58. package/styles/core/_mixins.scss +491 -0
  59. package/styles/core/_surface-layers.scss +76 -0
  60. package/styles/core/_utilities.scss +326 -0
  61. package/styles/core/_variables-unified.scss +57 -0
  62. package/styles/core/_variables.scss +36 -0
  63. package/styles/core/variables/_colors-source.scss +34 -0
  64. package/styles/core/variables/_colors-unified.scss +26 -0
  65. package/styles/core/variables/_colors.scss +21 -0
  66. package/styles/critical.scss +353 -0
  67. package/styles/design-system/_compact-theme.scss +159 -0
  68. package/styles/design-system/_section-base.scss +426 -0
  69. package/styles/design-system/_tokens.scss +237 -0
  70. package/styles/design-system/_unified-sections.scss +215 -0
  71. package/styles/layout/_feature-grid.scss +322 -0
  72. package/styles/layout/_masonry.scss +734 -0
  73. package/styles/layout/_tilt.scss +244 -0
  74. package/styles/micro-interactions.scss +583 -0
  75. package/styles/mixins/_section-mixins.scss +280 -0
  76. package/styles/non-critical.scss +643 -0
  77. package/styles/reset/_framework-reset.scss +457 -0
  78. package/styles/reset/_index.scss +14 -0
  79. package/styles/reset/_shadow-reset.scss +383 -0
  80. package/styles/responsive.scss +326 -0
  81. package/styles/themes.scss +573 -0
  82. package/styles/tokens/_index.scss +92 -0
  83. package/styles/tokens/_master.scss +1404 -0
  84. package/styles/tokens/_section-tokens.generated.scss +140 -0
  85. package/postcss.config.js +0 -81
  86. package/section-registry.json +0 -3864
  87. package/section-registry.schema.json +0 -264
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Consolidated Section Styles
3
+ *
4
+ * This file imports all section styles.
5
+ *
6
+ * @import "osi-cards-lib/styles/components/sections/sections-all";
7
+ *
8
+ * Structure:
9
+ * 1. Design System - Core mixins and tokens
10
+ * 2. Sections Base - Card mixin and grid layouts
11
+ * 3. Section Shell - Section container styles
12
+ * 4. All Sections - Unified styles for all section types
13
+ */
14
+
15
+ // ============================================================================
16
+ // CORE FILES
17
+ // ============================================================================
18
+ @import "design-system";
19
+ @import "sections-base";
20
+ @import "section-shell";
21
+ @import "section-animations";
22
+
23
+ // ============================================================================
24
+ // ALL SECTION STYLES (Unified)
25
+ // ============================================================================
26
+ @import "all-sections";
@@ -0,0 +1,334 @@
1
+ // =====================================================================
2
+ // SECTIONS BASE - Clean, Consistent Card Styles
3
+ // =====================================================================
4
+ //
5
+ // Uses CSS variables from master tokens. No hardcoded shadows or effects.
6
+ //
7
+ // =====================================================================
8
+
9
+ @use "../../tokens/master" as *;
10
+
11
+ // =====================================================================
12
+ // GRID MIXINS
13
+ // =====================================================================
14
+
15
+ @mixin section-grid($min-width: var(--section-grid-min-width), $gap: var(--section-card-gap)) {
16
+ display: grid;
17
+ gap: $gap;
18
+ grid-template-columns: repeat(auto-fit, minmax($min-width, 1fr));
19
+ min-height: 0;
20
+ box-sizing: border-box;
21
+
22
+ @media (max-width: 420px) {
23
+ grid-template-columns: 1fr;
24
+ }
25
+ }
26
+
27
+ @mixin section-grid-responsive(
28
+ $min-width: var(--section-grid-min-width),
29
+ $gap: var(--section-card-gap),
30
+ $tablet-breakpoint: 820px
31
+ ) {
32
+ display: grid;
33
+ gap: $gap;
34
+ grid-template-columns: repeat(auto-fit, minmax($min-width, 1fr));
35
+ min-height: 0;
36
+ box-sizing: border-box;
37
+
38
+ @media (max-width: $tablet-breakpoint) {
39
+ grid-template-columns: 1fr;
40
+ }
41
+ }
42
+
43
+ // =====================================================================
44
+ // UNIVERSAL CARD MIXIN - Uses CSS Variables Only
45
+ // =====================================================================
46
+
47
+ @mixin card {
48
+ background: var(--osi-section-item-background);
49
+ border: var(--osi-section-item-border);
50
+ border-radius: var(--osi-section-item-border-radius);
51
+ box-shadow: var(--osi-section-item-shadow);
52
+ padding: var(--card-padding);
53
+
54
+ display: flex;
55
+ flex-direction: column;
56
+ gap: var(--card-gap);
57
+ min-height: var(--card-min-height, auto);
58
+
59
+ cursor: pointer;
60
+ position: relative;
61
+ overflow: hidden;
62
+ box-sizing: border-box;
63
+ text-align: left;
64
+
65
+ transition:
66
+ background var(--duration-base) var(--ease-out),
67
+ box-shadow var(--duration-base) var(--ease-out),
68
+ border-color var(--duration-base) var(--ease-out);
69
+
70
+ // Subtle accent border indicator
71
+ &::before {
72
+ content: "";
73
+ position: absolute;
74
+ top: 0;
75
+ left: 0;
76
+ right: 0;
77
+ height: var(--border-width-default);
78
+ background: linear-gradient(90deg, var(--accent, var(--osi-accent)) 0%, transparent 100%);
79
+ opacity: 0;
80
+ transition: opacity var(--duration-base) var(--ease-out);
81
+ border-radius: var(--osi-section-item-border-radius) var(--osi-section-item-border-radius) 0 0;
82
+ }
83
+
84
+ &:hover {
85
+ background: var(--osi-section-item-background-hover);
86
+ border-color: var(--osi-section-item-border-hover);
87
+ box-shadow: var(--osi-section-item-shadow-hover);
88
+
89
+ &::before {
90
+ opacity: 0.6;
91
+ }
92
+ }
93
+
94
+ &:focus-visible {
95
+ outline: var(--border-width-accent-sm) solid var(--accent, var(--osi-accent));
96
+ outline-offset: var(--border-width-accent-sm);
97
+ }
98
+
99
+ @media (prefers-reduced-motion: reduce) {
100
+ transition: none;
101
+ }
102
+ }
103
+
104
+ // =====================================================================
105
+ // UNIFIED SECTION CARD CLASS
106
+ // =====================================================================
107
+
108
+ .unified-card {
109
+ @include card;
110
+ }
111
+
112
+ .section-card {
113
+ @include card;
114
+ }
115
+
116
+ // =====================================================================
117
+ // TYPOGRAPHY MIXINS - Use CSS Variables
118
+ // =====================================================================
119
+
120
+ @mixin metric-label {
121
+ font-size: var(--card-label-font-size);
122
+ font-weight: 600;
123
+ letter-spacing: 0.04em;
124
+ text-transform: uppercase;
125
+ color: var(--muted-foreground);
126
+ line-height: 1.3;
127
+ font-family: inherit;
128
+ }
129
+
130
+ @mixin metric-value {
131
+ font-size: var(--card-value-font-size);
132
+ font-weight: 600;
133
+ color: var(--foreground);
134
+ letter-spacing: -0.01em;
135
+ line-height: 1.3;
136
+ font-family: inherit;
137
+ }
138
+
139
+ @mixin section-description {
140
+ font-size: var(--card-subtitle-font-size);
141
+ color: var(--muted-foreground);
142
+ line-height: 1.5;
143
+ font-weight: 400;
144
+ font-family: inherit;
145
+ }
146
+
147
+ // Legacy aliases
148
+ @mixin section-label {
149
+ @include metric-label;
150
+ }
151
+
152
+ @mixin section-value {
153
+ @include metric-value;
154
+ }
155
+
156
+ // =====================================================================
157
+ // EMPTY STATE
158
+ // =====================================================================
159
+
160
+ @mixin section-empty-state {
161
+ padding: var(--osi-section-padding);
162
+ text-align: center;
163
+ color: var(--muted-foreground);
164
+ border: var(--border-width-default) dashed var(--border);
165
+ border-radius: var(--osi-section-item-border-radius);
166
+ background: var(--osi-section-item-background);
167
+ min-height: auto;
168
+ }
169
+
170
+ @mixin section-empty-icon {
171
+ margin: 0 auto var(--card-gap);
172
+ opacity: 0.5;
173
+ }
174
+
175
+ // =====================================================================
176
+ // TREND COLORS
177
+ // =====================================================================
178
+
179
+ @mixin trend-colors {
180
+ &.trend--up {
181
+ color: #{$osi-color-trend-up};
182
+ }
183
+
184
+ &.trend--down {
185
+ color: #{$osi-color-trend-down};
186
+ }
187
+
188
+ &.trend--stable {
189
+ color: #{$osi-color-trend-stable};
190
+ }
191
+
192
+ &.trend--neutral {
193
+ color: #{$osi-color-trend-neutral};
194
+ }
195
+ }
196
+
197
+ // =====================================================================
198
+ // STATUS CLASSES
199
+ // =====================================================================
200
+
201
+ .status--completed,
202
+ .status--success {
203
+ color: #{$success-color};
204
+ background: #{$success-color-10};
205
+ }
206
+
207
+ .status--active,
208
+ .status--in-progress {
209
+ color: var(--accent);
210
+ background: #{$brand-color-10};
211
+ }
212
+
213
+ .status--pending,
214
+ .status--warning {
215
+ color: #{$warning-color};
216
+ background: #{$warning-color-10};
217
+ }
218
+
219
+ .status--blocked,
220
+ .status--cancelled,
221
+ .status--delayed,
222
+ .status--inactive,
223
+ .status--error {
224
+ color: #{$error-color};
225
+ background: #{$error-color-10};
226
+ }
227
+
228
+ .status--default {
229
+ color: var(--muted-foreground);
230
+ background: var(--muted);
231
+ }
232
+
233
+ // =====================================================================
234
+ // PRIORITY CLASSES
235
+ // =====================================================================
236
+
237
+ .priority--high {
238
+ color: #{$error-color};
239
+ background: #{$error-color-10};
240
+ }
241
+
242
+ .priority--medium {
243
+ color: #{$warning-color};
244
+ background: #{$warning-color-10};
245
+ }
246
+
247
+ .priority--low {
248
+ color: #{$success-color};
249
+ background: #{$success-color-10};
250
+ }
251
+
252
+ .priority--default {
253
+ color: var(--muted-foreground);
254
+ background: var(--muted);
255
+ }
256
+
257
+ // =====================================================================
258
+ // REDUCED MOTION
259
+ // =====================================================================
260
+
261
+ @media (prefers-reduced-motion: reduce) {
262
+ .unified-card,
263
+ .section-card,
264
+ [class*="__card"],
265
+ [class*="-card"],
266
+ [class*="__item"],
267
+ [class*="-item"] {
268
+ transition: none;
269
+ animation: none;
270
+ }
271
+ }
272
+
273
+ // =====================================================================
274
+ // ANIMATION SYSTEM
275
+ // =====================================================================
276
+
277
+ @keyframes section-item-stream {
278
+ 0% {
279
+ opacity: 0;
280
+ transform: translate3d(0, var(--motion-distance-sm), 0);
281
+ }
282
+ 100% {
283
+ opacity: 1;
284
+ transform: translate3d(0, 0, 0);
285
+ }
286
+ }
287
+
288
+ @mixin section-item-animation {
289
+ &.section-item-streaming {
290
+ animation: section-item-stream 0.25s ease-out forwards;
291
+ }
292
+
293
+ &.section-item-entered {
294
+ animation: none;
295
+ }
296
+
297
+ @for $i from 0 through 15 {
298
+ &.section-item-stagger-#{$i} {
299
+ animation-delay: calc(#{$i} * 30ms);
300
+ }
301
+ }
302
+ }
303
+
304
+ @mixin legacy-item-animation {
305
+ &.item-streaming {
306
+ animation: section-item-stream 0.25s ease-out forwards;
307
+ }
308
+
309
+ &.item-entered {
310
+ animation: none;
311
+ }
312
+
313
+ @for $i from 0 through 15 {
314
+ &.item-stagger-#{$i} {
315
+ animation-delay: calc(#{$i} * 30ms);
316
+ }
317
+ }
318
+ }
319
+
320
+ @mixin legacy-field-animation {
321
+ &.field-streaming {
322
+ animation: section-item-stream 0.25s ease-out forwards;
323
+ }
324
+
325
+ &.field-entered {
326
+ animation: none;
327
+ }
328
+
329
+ @for $i from 0 through 15 {
330
+ &.field-stagger-#{$i} {
331
+ animation-delay: calc(#{$i} * 30ms);
332
+ }
333
+ }
334
+ }
@@ -0,0 +1,327 @@
1
+ // =====================================================================
2
+ // ENHANCED TYPOGRAPHY SYSTEM
3
+ // =====================================================================
4
+ //
5
+ // Comprehensive typography utilities with semantic naming.
6
+ // Uses design tokens for consistency and theme-ability.
7
+ //
8
+ // =====================================================================
9
+
10
+ @use "design-tokens" as *;
11
+
12
+ // =====================================================================
13
+ // HEADING MIXINS
14
+ // =====================================================================
15
+
16
+ @mixin heading-1 {
17
+ font-size: var(--text-4xl);
18
+ font-weight: var(--font-bold);
19
+ line-height: var(--leading-tight);
20
+ letter-spacing: -0.02em;
21
+ color: var(--foreground);
22
+ margin: 0;
23
+ }
24
+
25
+ @mixin heading-2 {
26
+ font-size: var(--text-3xl);
27
+ font-weight: var(--font-bold);
28
+ line-height: var(--leading-tight);
29
+ letter-spacing: -0.015em;
30
+ color: var(--foreground);
31
+ margin: 0;
32
+ }
33
+
34
+ // CONSISTENT HIERARCHY: Section headers and content headers
35
+ @mixin heading-3 {
36
+ // Section Title (main section header)
37
+ font-size: var(--text-xl); // Consistent: 19px
38
+ font-weight: var(--font-bold);
39
+ line-height: var(--leading-tight);
40
+ letter-spacing: -0.01em;
41
+ color: var(--foreground);
42
+ margin: 0;
43
+ }
44
+
45
+ @mixin heading-4 {
46
+ // Sub-section Title
47
+ font-size: var(--text-lg); // Consistent: 17px
48
+ font-weight: var(--font-semibold);
49
+ line-height: var(--leading-snug);
50
+ color: var(--foreground);
51
+ margin: 0;
52
+ }
53
+
54
+ @mixin heading-5 {
55
+ // Card/Item Title (consistent across all sections)
56
+ font-size: var(--text-base); // Consistent: 13px
57
+ font-weight: var(--font-semibold);
58
+ line-height: var(--leading-normal);
59
+ color: var(--foreground);
60
+ margin: 0;
61
+ }
62
+
63
+ @mixin heading-6 {
64
+ // Small Item Title / Label Header
65
+ font-size: var(--text-sm); // Consistent: 11.2px
66
+ font-weight: var(--font-semibold);
67
+ line-height: var(--leading-normal);
68
+ color: var(--foreground);
69
+ margin: 0;
70
+ }
71
+
72
+ // =====================================================================
73
+ // BODY TEXT MIXINS
74
+ // =====================================================================
75
+
76
+ @mixin body-large {
77
+ font-size: var(--text-lg);
78
+ font-weight: var(--font-normal);
79
+ line-height: var(--leading-relaxed);
80
+ color: var(--foreground);
81
+ }
82
+
83
+ @mixin body-base {
84
+ font-size: var(--text-base);
85
+ font-weight: var(--font-normal);
86
+ line-height: var(--leading-normal);
87
+ color: var(--foreground);
88
+ }
89
+
90
+ @mixin body-small {
91
+ font-size: var(--text-sm);
92
+ font-weight: var(--font-normal);
93
+ line-height: var(--leading-normal);
94
+ color: var(--foreground);
95
+ }
96
+
97
+ @mixin body-xs {
98
+ font-size: var(--text-xs);
99
+ font-weight: var(--font-normal);
100
+ line-height: var(--leading-normal);
101
+ color: var(--foreground);
102
+ }
103
+
104
+ // =====================================================================
105
+ // SEMANTIC TEXT VARIANTS
106
+ // =====================================================================
107
+
108
+ @mixin text-primary {
109
+ color: var(--foreground);
110
+ font-weight: var(--font-medium);
111
+ }
112
+
113
+ @mixin text-secondary {
114
+ color: var(--muted-foreground);
115
+ font-weight: var(--font-normal);
116
+ }
117
+
118
+ @mixin text-tertiary {
119
+ color: var(--muted-foreground);
120
+ font-weight: var(--font-normal);
121
+ opacity: var(--opacity-70);
122
+ }
123
+
124
+ @mixin text-disabled {
125
+ color: var(--muted-foreground);
126
+ opacity: var(--state-disabled-opacity);
127
+ }
128
+
129
+ // =====================================================================
130
+ // LABEL & CAPTION MIXINS
131
+ // =====================================================================
132
+
133
+ @mixin label-base {
134
+ font-size: var(--text-sm);
135
+ font-weight: var(--font-semibold);
136
+ color: var(--foreground);
137
+ text-transform: none;
138
+ }
139
+
140
+ @mixin label-uppercase {
141
+ font-size: var(--text-xs);
142
+ font-weight: var(--font-semibold);
143
+ color: var(--muted-foreground);
144
+ text-transform: uppercase;
145
+ letter-spacing: 0.05em;
146
+ }
147
+
148
+ @mixin caption {
149
+ font-size: var(--text-xs);
150
+ font-weight: var(--font-normal);
151
+ line-height: var(--leading-normal);
152
+ color: var(--muted-foreground);
153
+ }
154
+
155
+ @mixin caption-bold {
156
+ font-size: var(--text-xs);
157
+ font-weight: var(--font-semibold);
158
+ line-height: var(--leading-normal);
159
+ color: var(--muted-foreground);
160
+ }
161
+
162
+ // =====================================================================
163
+ // CODE & MONOSPACE
164
+ // =====================================================================
165
+
166
+ @mixin code-inline {
167
+ font-family: "Monaco", "Courier New", monospace;
168
+ font-size: 0.9em;
169
+ padding: 2px 6px;
170
+ background: var(--muted);
171
+ border: 1px solid var(--border);
172
+ border-radius: var(--radius-sm);
173
+ color: var(--foreground);
174
+ }
175
+
176
+ @mixin code-block {
177
+ font-family: "Monaco", "Courier New", monospace;
178
+ font-size: var(--text-sm);
179
+ padding: var(--spacing-md);
180
+ background: var(--muted);
181
+ border: 1px solid var(--border);
182
+ border-radius: var(--radius-md);
183
+ color: var(--foreground);
184
+ overflow-x: auto;
185
+ line-height: var(--leading-relaxed);
186
+ }
187
+
188
+ // =====================================================================
189
+ // LINK STYLES
190
+ // =====================================================================
191
+
192
+ @mixin link-base {
193
+ color: var(--accent);
194
+ text-decoration: none;
195
+ font-weight: var(--font-medium);
196
+ cursor: pointer;
197
+ transition: color var(--duration-fast) var(--ease-out);
198
+
199
+ &:hover {
200
+ color: var(--accent);
201
+ text-decoration: underline;
202
+ }
203
+
204
+ &:focus-visible {
205
+ outline: 2px solid var(--accent);
206
+ outline-offset: 2px;
207
+ border-radius: var(--radius-xs);
208
+ }
209
+ }
210
+
211
+ @mixin link-subtle {
212
+ color: var(--muted-foreground);
213
+ text-decoration: none;
214
+ transition: color var(--duration-fast) var(--ease-out);
215
+
216
+ &:hover {
217
+ color: var(--foreground);
218
+ text-decoration: underline;
219
+ }
220
+ }
221
+
222
+ // =====================================================================
223
+ // NUMBER & STAT DISPLAY
224
+ // =====================================================================
225
+
226
+ @mixin number-display-large {
227
+ font-size: var(--text-4xl);
228
+ font-weight: var(--font-bold);
229
+ line-height: var(--leading-tight);
230
+ letter-spacing: -0.03em;
231
+ color: var(--foreground);
232
+ font-variant-numeric: tabular-nums;
233
+ }
234
+
235
+ @mixin number-display-medium {
236
+ font-size: var(--text-2xl);
237
+ font-weight: var(--font-semibold);
238
+ line-height: var(--leading-tight);
239
+ letter-spacing: -0.02em;
240
+ color: var(--foreground);
241
+ font-variant-numeric: tabular-nums;
242
+ }
243
+
244
+ @mixin number-display-small {
245
+ font-size: var(--text-lg);
246
+ font-weight: var(--font-semibold);
247
+ line-height: var(--leading-snug);
248
+ letter-spacing: -0.01em;
249
+ color: var(--foreground);
250
+ font-variant-numeric: tabular-nums;
251
+ }
252
+
253
+ // =====================================================================
254
+ // TRUNCATION UTILITIES
255
+ // =====================================================================
256
+
257
+ @mixin text-truncate {
258
+ overflow: hidden;
259
+ text-overflow: ellipsis;
260
+ white-space: nowrap;
261
+ }
262
+
263
+ @mixin text-truncate-lines($lines: 2) {
264
+ display: -webkit-box;
265
+ -webkit-line-clamp: $lines;
266
+ -webkit-box-orient: vertical;
267
+ overflow: hidden;
268
+ text-overflow: ellipsis;
269
+ }
270
+
271
+ // =====================================================================
272
+ // READING OPTIMIZATIONS
273
+ // =====================================================================
274
+
275
+ @mixin reading-optimized {
276
+ font-feature-settings:
277
+ "kern" 1,
278
+ "liga" 1,
279
+ "calt" 1;
280
+ -webkit-font-smoothing: antialiased;
281
+ -moz-osx-font-smoothing: grayscale;
282
+ text-rendering: optimizeLegibility;
283
+ }
284
+
285
+ @mixin reading-width {
286
+ max-width: 65ch; // Optimal reading width
287
+ margin-left: auto;
288
+ margin-right: auto;
289
+ }
290
+
291
+ // =====================================================================
292
+ // RESPONSIVE TYPOGRAPHY
293
+ // =====================================================================
294
+
295
+ @mixin fluid-type($min-size, $max-size, $min-width: 320px, $max-width: 1200px) {
296
+ font-size: clamp(
297
+ #{$min-size},
298
+ calc(
299
+ #{$min-size} + (#{strip-unit($max-size)} - #{strip-unit($min-size)}) *
300
+ ((100vw - #{$min-width}) / (#{strip-unit($max-width)} - #{strip-unit($min-width)}))
301
+ ),
302
+ #{$max-size}
303
+ );
304
+ }
305
+
306
+ @function strip-unit($number) {
307
+ @if type-of($number) == "number" and not unitless($number) {
308
+ @return $number / ($number * 0 + 1);
309
+ }
310
+ @return $number;
311
+ }
312
+
313
+ // =====================================================================
314
+ // SELECTION STYLING
315
+ // =====================================================================
316
+
317
+ @mixin selection-style {
318
+ ::selection {
319
+ background: var(--accent-color-30);
320
+ color: var(--foreground);
321
+ }
322
+
323
+ ::-moz-selection {
324
+ background: var(--accent-color-30);
325
+ color: var(--foreground);
326
+ }
327
+ }