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,268 @@
1
+ // =====================================================================
2
+ // MINIMALISTIC DESIGN SYSTEM - Clean, Compact, Modern
3
+ // =====================================================================
4
+ // Philosophy: Less is more. Remove visual noise, maximize clarity.
5
+
6
+ @use "design-tokens" as *;
7
+
8
+ // ═══════════════════════════════════════════════════════════════════
9
+ // MINIMALISTIC SPACING - Tight but Breathable
10
+ // ═══════════════════════════════════════════════════════════════════
11
+
12
+ :root {
13
+ // Minimalistic spacing (tighter than comfortable, but not cramped)
14
+ --minimal-spacing-xs: 3px;
15
+ --minimal-spacing-sm: 6px;
16
+ --minimal-spacing-md: 9px;
17
+ --minimal-spacing-lg: 12px;
18
+ --minimal-spacing-xl: 18px;
19
+
20
+ // Card/Item spacing
21
+ --minimal-card-padding: 10px; // Balanced compact
22
+ --minimal-card-gap: 10px; // Visual separation
23
+ --minimal-item-gap: 6px; // Between elements
24
+
25
+ // Heights
26
+ --minimal-card-height: 95px; // Compact but not cramped
27
+ --minimal-card-height-mobile: auto; // Flexible on mobile
28
+ }
29
+
30
+ // ═══════════════════════════════════════════════════════════════════
31
+ // MINIMALISTIC COLORS - Subtle, Clean
32
+ // ═══════════════════════════════════════════════════════════════════
33
+
34
+ :root {
35
+ // Subtle backgrounds (less contrast = cleaner)
36
+ --minimal-surface: var(--surface);
37
+ --minimal-surface-hover: rgba(var(--foreground-rgb), 0.03); // Very subtle
38
+ --minimal-border: rgba(var(--foreground-rgb), 0.06); // Subtle borders
39
+ --minimal-border-hover: rgba(var(--foreground-rgb), 0.1);
40
+
41
+ // Accent usage (minimal, strategic)
42
+ --minimal-accent-subtle: rgba(var(--accent-rgb), 0.1);
43
+ --minimal-accent-line: 2px; // Thin accent
44
+ }
45
+
46
+ // ═══════════════════════════════════════════════════════════════════
47
+ // MINIMALISTIC CARD STYLES
48
+ // ═══════════════════════════════════════════════════════════════════
49
+
50
+ // Minimal card - clean, subtle
51
+ @mixin minimal-card {
52
+ background: transparent; // No background
53
+ border: 1px solid var(--minimal-border); // Subtle border
54
+ border-radius: var(--radius-sm); // Small radius
55
+ padding: var(--minimal-card-padding); // 10px
56
+ transition: all 200ms var(--ease-out);
57
+
58
+ &:hover {
59
+ border-color: var(--minimal-border-hover);
60
+ background: var(--minimal-surface-hover); // Very subtle
61
+ transform: translateY(-1px); // Subtle lift
62
+ }
63
+ }
64
+
65
+ // Minimal card elevated - with subtle shadow
66
+ @mixin minimal-card-elevated {
67
+ @include minimal-card;
68
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); // Very subtle
69
+
70
+ &:hover {
71
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); // Subtle elevation
72
+ }
73
+ }
74
+
75
+ // Minimal card accent - left border only
76
+ @mixin minimal-card-accent {
77
+ background: transparent;
78
+ border: none;
79
+ border-left: var(--minimal-accent-line) solid var(--accent);
80
+ padding: var(--minimal-card-padding);
81
+ padding-left: calc(var(--minimal-card-padding) + 4px);
82
+ transition: all 200ms var(--ease-out);
83
+
84
+ &:hover {
85
+ background: var(--minimal-surface-hover);
86
+ padding-left: calc(var(--minimal-card-padding) + 6px);
87
+ }
88
+ }
89
+
90
+ // ═══════════════════════════════════════════════════════════════════
91
+ // MINIMALISTIC GRID - Optimal Column Usage
92
+ // ═══════════════════════════════════════════════════════════════════
93
+
94
+ // Small metrics (3-4 columns desktop, 2 mobile)
95
+ @mixin minimal-grid-metrics {
96
+ display: grid;
97
+ grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
98
+ gap: var(--minimal-card-gap);
99
+
100
+ @media (max-width: 768px) {
101
+ grid-template-columns: repeat(3, 1fr); // 3 columns on tablet
102
+ }
103
+
104
+ @media (max-width: 480px) {
105
+ grid-template-columns: repeat(2, 1fr); // 2 columns on mobile
106
+ }
107
+ }
108
+
109
+ // Medium cards (2-3 columns desktop, 1-2 mobile)
110
+ @mixin minimal-grid-cards {
111
+ display: grid;
112
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
113
+ gap: var(--minimal-card-gap);
114
+
115
+ @media (max-width: 768px) {
116
+ grid-template-columns: repeat(2, 1fr); // 2 columns on tablet
117
+ }
118
+
119
+ @media (max-width: 480px) {
120
+ grid-template-columns: 1fr; // 1 column on mobile
121
+ }
122
+ }
123
+
124
+ // List layout - no grid, vertical stack
125
+ @mixin minimal-list {
126
+ display: flex;
127
+ flex-direction: column;
128
+ gap: 0; // Seamless with borders
129
+ }
130
+
131
+ // ═══════════════════════════════════════════════════════════════════
132
+ // MINIMALISTIC TYPOGRAPHY - Clean Hierarchy
133
+ // ═══════════════════════════════════════════════════════════════════
134
+
135
+ @mixin minimal-section-title {
136
+ font-size: var(--text-lg); // 17px - not too large
137
+ font-weight: var(--font-semibold); // 600 - not too bold
138
+ line-height: var(--leading-tight);
139
+ color: var(--foreground);
140
+ margin: 0;
141
+ }
142
+
143
+ @mixin minimal-item-title {
144
+ font-size: var(--text-base); // 13px
145
+ font-weight: var(--font-medium); // 500 - subtle
146
+ line-height: var(--leading-snug);
147
+ color: var(--foreground);
148
+ margin: 0;
149
+ }
150
+
151
+ @mixin minimal-label {
152
+ font-size: var(--text-xs); // 11px
153
+ font-weight: var(--font-normal); // 400 - light
154
+ line-height: var(--leading-tight);
155
+ color: var(--muted-foreground);
156
+ text-transform: uppercase;
157
+ letter-spacing: 0.06em;
158
+ }
159
+
160
+ @mixin minimal-value {
161
+ font-size: var(--text-md); // 14px
162
+ font-weight: var(--font-medium); // 500 - not too bold
163
+ line-height: var(--leading-normal);
164
+ color: var(--foreground);
165
+ }
166
+
167
+ @mixin minimal-number {
168
+ font-size: var(--text-2xl); // 22px
169
+ font-weight: var(--font-semibold); // 600 - not too bold
170
+ line-height: 1;
171
+ letter-spacing: -0.01em;
172
+ font-variant-numeric: tabular-nums;
173
+ color: var(--foreground);
174
+ }
175
+
176
+ // ═══════════════════════════════════════════════════════════════════
177
+ // MINIMALISTIC ITEM - Clean List Item
178
+ // ═══════════════════════════════════════════════════════════════════
179
+
180
+ @mixin minimal-item {
181
+ padding: var(--minimal-card-padding);
182
+ border: none;
183
+ border-bottom: 1px solid var(--minimal-border);
184
+ transition: all 150ms var(--ease-out);
185
+
186
+ &:last-child {
187
+ border-bottom: none;
188
+ }
189
+
190
+ &:hover {
191
+ background: var(--minimal-surface-hover);
192
+ padding-left: calc(var(--minimal-card-padding) + 4px);
193
+ }
194
+ }
195
+
196
+ // ═══════════════════════════════════════════════════════════════════
197
+ // MINIMALISTIC EFFECTS - Subtle Interactions
198
+ // ═══════════════════════════════════════════════════════════════════
199
+
200
+ // Subtle lift (minimalistic)
201
+ @mixin minimal-lift {
202
+ transition: all 200ms var(--ease-out);
203
+
204
+ &:hover {
205
+ transform: translateY(-2px);
206
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
207
+ }
208
+ }
209
+
210
+ // Accent line reveal (minimalistic)
211
+ @mixin minimal-accent-reveal {
212
+ position: relative;
213
+
214
+ &::after {
215
+ content: "";
216
+ position: absolute;
217
+ bottom: 0;
218
+ left: 0;
219
+ right: 100%;
220
+ height: 1px;
221
+ background: var(--accent);
222
+ transition: right 300ms var(--ease-out);
223
+ }
224
+
225
+ &:hover::after {
226
+ right: 0;
227
+ }
228
+ }
229
+
230
+ // Fade background (minimalistic)
231
+ @mixin minimal-fade-bg {
232
+ background: transparent;
233
+ transition: background 200ms var(--ease-out);
234
+
235
+ &:hover {
236
+ background: var(--minimal-surface-hover);
237
+ }
238
+ }
239
+
240
+ // ═══════════════════════════════════════════════════════════════════
241
+ // MINIMALISTIC RESPONSIVE - Mobile-First
242
+ // ═══════════════════════════════════════════════════════════════════
243
+
244
+ @mixin minimal-mobile {
245
+ @media (max-width: 480px) {
246
+ padding: var(--minimal-spacing-sm); // 6px on mobile
247
+ gap: var(--minimal-spacing-xs); // 3px between elements
248
+ }
249
+ }
250
+
251
+ // ═══════════════════════════════════════════════════════════════════
252
+ // COMPLETE MINIMALISTIC CARD - Ready to Use
253
+ // ═══════════════════════════════════════════════════════════════════
254
+
255
+ @mixin minimalistic-card-complete {
256
+ @include minimal-card-elevated;
257
+ @include minimal-lift;
258
+
259
+ display: flex;
260
+ flex-direction: column;
261
+ gap: var(--minimal-item-gap);
262
+ min-height: var(--minimal-card-height);
263
+
264
+ @media (max-width: 480px) {
265
+ min-height: var(--minimal-card-height-mobile);
266
+ padding: var(--minimal-spacing-sm);
267
+ }
268
+ }
@@ -0,0 +1,392 @@
1
+ // =====================================================================
2
+ // MODERN EFFECTS & INTERACTIONS
3
+ // =====================================================================
4
+ //
5
+ // Advanced visual effects, micro-interactions, and modern UI patterns.
6
+ // Uses design tokens for consistency.
7
+ //
8
+ // =====================================================================
9
+
10
+ @use "design-tokens" as *;
11
+
12
+ // =====================================================================
13
+ // GLASS MORPHISM
14
+ // =====================================================================
15
+
16
+ @mixin glass-card {
17
+ background: var(--glass-bg);
18
+ border: 1px solid var(--glass-border);
19
+ backdrop-filter: blur(var(--glass-blur));
20
+ -webkit-backdrop-filter: blur(var(--glass-blur));
21
+ box-shadow: var(--shadow-md);
22
+ transition: var(--transition-colors), var(--transition-shadow);
23
+
24
+ &:hover {
25
+ background: rgba(255, 255, 255, 0.75);
26
+ border-color: rgba(255, 255, 255, 0.3);
27
+ box-shadow: var(--shadow-lg);
28
+ }
29
+
30
+ @media (prefers-color-scheme: dark) {
31
+ &:hover {
32
+ background: rgba(0, 0, 0, 0.5);
33
+ border-color: rgba(255, 255, 255, 0.15);
34
+ }
35
+ }
36
+ }
37
+
38
+ // =====================================================================
39
+ // SUBTLE GRADIENT ACCENTS
40
+ // =====================================================================
41
+
42
+ @mixin gradient-accent-top {
43
+ position: relative;
44
+
45
+ &::before {
46
+ content: "";
47
+ position: absolute;
48
+ top: 0;
49
+ left: 0;
50
+ right: 0;
51
+ height: 2px;
52
+ background: linear-gradient(90deg, transparent 0%, var(--accent) 50%, transparent 100%);
53
+ opacity: 0;
54
+ transition: opacity var(--duration-base) var(--ease-out);
55
+ }
56
+
57
+ &:hover::before {
58
+ opacity: 1;
59
+ }
60
+ }
61
+
62
+ @mixin gradient-background {
63
+ background: linear-gradient(
64
+ 135deg,
65
+ var(--osi-section-item-background) 0%,
66
+ var(--osi-section-item-background-hover) 100%
67
+ );
68
+ }
69
+
70
+ // =====================================================================
71
+ // SHINE/SHIMMER EFFECT
72
+ // =====================================================================
73
+
74
+ @mixin shimmer-effect {
75
+ position: relative;
76
+ overflow: hidden;
77
+
78
+ &::after {
79
+ content: "";
80
+ position: absolute;
81
+ top: 0;
82
+ left: -100%;
83
+ width: 100%;
84
+ height: 100%;
85
+ background: linear-gradient(
86
+ 90deg,
87
+ transparent 0%,
88
+ rgba(255, 255, 255, 0.1) 50%,
89
+ transparent 100%
90
+ );
91
+ transition: left var(--duration-slower) var(--ease-out);
92
+ pointer-events: none;
93
+ }
94
+
95
+ &:hover::after {
96
+ left: 100%;
97
+ }
98
+
99
+ @media (prefers-reduced-motion: reduce) {
100
+ &::after {
101
+ display: none;
102
+ }
103
+ }
104
+ }
105
+
106
+ // =====================================================================
107
+ // ELEVATION (Lifted Card Effect)
108
+ // =====================================================================
109
+
110
+ @mixin elevated-card {
111
+ transition: var(--transition-shadow), var(--transition-colors);
112
+
113
+ &:hover {
114
+ box-shadow: var(--shadow-xl);
115
+ background: var(--osi-section-item-background-hover);
116
+ }
117
+
118
+ &:active {
119
+ box-shadow: var(--shadow-md);
120
+ }
121
+
122
+ @media (prefers-reduced-motion: reduce) {
123
+ transition: none;
124
+ }
125
+ }
126
+
127
+ // =====================================================================
128
+ // GLOW EFFECT
129
+ // =====================================================================
130
+
131
+ @mixin glow-on-hover($intensity: "md") {
132
+ transition: box-shadow var(--duration-base) var(--ease-out);
133
+
134
+ &:hover {
135
+ box-shadow: var(--glow-#{$intensity});
136
+ }
137
+ }
138
+
139
+ // =====================================================================
140
+ // INTERACTIVE STATES (Modern)
141
+ // =====================================================================
142
+
143
+ @mixin interactive-surface {
144
+ position: relative;
145
+ cursor: pointer;
146
+ transition: var(--transition-colors);
147
+
148
+ // Hover state
149
+ &:hover {
150
+ background: color-mix(in srgb, var(--osi-section-item-background) 90%, var(--foreground) 10%);
151
+ }
152
+
153
+ // Active state
154
+ &:active {
155
+ background: color-mix(in srgb, var(--osi-section-item-background) 85%, var(--foreground) 15%);
156
+ }
157
+
158
+ // Focus state (keyboard navigation)
159
+ &:focus-visible {
160
+ outline: 2px solid var(--accent);
161
+ outline-offset: 2px;
162
+ box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.1);
163
+ }
164
+
165
+ // Disabled state
166
+ &:disabled,
167
+ &[aria-disabled="true"] {
168
+ opacity: var(--state-disabled-opacity);
169
+ cursor: not-allowed;
170
+ pointer-events: none;
171
+ }
172
+ }
173
+
174
+ // =====================================================================
175
+ // BORDER ANIMATIONS
176
+ // =====================================================================
177
+
178
+ @mixin animated-border {
179
+ position: relative;
180
+ border: 1px solid transparent;
181
+
182
+ &::before {
183
+ content: "";
184
+ position: absolute;
185
+ inset: 0;
186
+ border-radius: inherit;
187
+ padding: 1px;
188
+ background: linear-gradient(135deg, transparent 0%, var(--accent) 50%, transparent 100%);
189
+ -webkit-mask:
190
+ linear-gradient(#fff 0 0) content-box,
191
+ linear-gradient(#fff 0 0);
192
+ -webkit-mask-composite: xor;
193
+ mask-composite: exclude;
194
+ opacity: 0;
195
+ transition: opacity var(--duration-base) var(--ease-out);
196
+ }
197
+
198
+ &:hover::before {
199
+ opacity: 1;
200
+ }
201
+ }
202
+
203
+ // =====================================================================
204
+ // RIPPLE EFFECT
205
+ // =====================================================================
206
+
207
+ @mixin ripple-effect {
208
+ position: relative;
209
+ overflow: hidden;
210
+
211
+ &::after {
212
+ content: "";
213
+ position: absolute;
214
+ top: 50%;
215
+ left: 50%;
216
+ width: 0;
217
+ height: 0;
218
+ border-radius: 50%;
219
+ background: rgba(255, 255, 255, 0.5);
220
+ transform: translate(-50%, -50%);
221
+ opacity: 0;
222
+ pointer-events: none;
223
+ }
224
+
225
+ &:active::after {
226
+ width: 200%;
227
+ height: 200%;
228
+ opacity: 1;
229
+ transition:
230
+ width var(--duration-slow) var(--ease-out),
231
+ height var(--duration-slow) var(--ease-out),
232
+ opacity var(--duration-fast) var(--ease-out);
233
+ }
234
+
235
+ @media (prefers-reduced-motion: reduce) {
236
+ &::after {
237
+ display: none;
238
+ }
239
+ }
240
+ }
241
+
242
+ // =====================================================================
243
+ // SKELETON LOADING
244
+ // =====================================================================
245
+
246
+ @keyframes skeleton-pulse {
247
+ 0%,
248
+ 100% {
249
+ opacity: 1;
250
+ }
251
+ 50% {
252
+ opacity: 0.4;
253
+ }
254
+ }
255
+
256
+ @mixin skeleton-loading {
257
+ background: var(--muted);
258
+ border-radius: var(--radius-md);
259
+ animation: skeleton-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
260
+
261
+ @media (prefers-reduced-motion: reduce) {
262
+ animation: none;
263
+ }
264
+ }
265
+
266
+ // =====================================================================
267
+ // SMOOTH CORNERS (iOS-style)
268
+ // =====================================================================
269
+
270
+ @mixin smooth-corners($radius: var(--radius-lg)) {
271
+ border-radius: $radius;
272
+
273
+ // Enhanced for supporting browsers
274
+ @supports (border-radius: var(--radius-lg) / var(--radius-lg)) {
275
+ border-radius: $radius / calc($radius * 1.5);
276
+ }
277
+ }
278
+
279
+ // =====================================================================
280
+ // FADE IN ANIMATIONS
281
+ // =====================================================================
282
+
283
+ @keyframes fade-in-up {
284
+ from {
285
+ opacity: 0;
286
+ transform: translate3d(0, 10px, 0);
287
+ }
288
+ to {
289
+ opacity: 1;
290
+ transform: translate3d(0, 0, 0);
291
+ }
292
+ }
293
+
294
+ @keyframes fade-in-scale {
295
+ from {
296
+ opacity: 0;
297
+ transform: translate3d(0, 0, 0) scale(0.95);
298
+ }
299
+ to {
300
+ opacity: 1;
301
+ transform: translate3d(0, 0, 0) scale(1);
302
+ }
303
+ }
304
+
305
+ @mixin fade-in-animation($type: "up", $delay: 0ms) {
306
+ animation: fade-in-#{$type} var(--duration-base) var(--ease-out) $delay forwards;
307
+
308
+ @media (prefers-reduced-motion: reduce) {
309
+ animation: none;
310
+ opacity: 1;
311
+ transform: none;
312
+ }
313
+ }
314
+
315
+ // =====================================================================
316
+ // STAGGER ANIMATION UTILITIES
317
+ // =====================================================================
318
+
319
+ @mixin stagger-children($max: 10, $delay-increment: 50ms) {
320
+ @for $i from 1 through $max {
321
+ &:nth-child(#{$i}) {
322
+ animation-delay: calc(#{$i - 1} * #{$delay-increment});
323
+ }
324
+ }
325
+ }
326
+
327
+ // =====================================================================
328
+ // FROSTED GLASS EFFECT
329
+ // =====================================================================
330
+
331
+ @mixin frosted-glass($blur: var(--blur-md), $opacity: 0.8) {
332
+ background: rgba(255, 255, 255, $opacity);
333
+ backdrop-filter: blur($blur) saturate(180%);
334
+ -webkit-backdrop-filter: blur($blur) saturate(180%);
335
+ border: 1px solid rgba(255, 255, 255, 0.3);
336
+
337
+ @media (prefers-color-scheme: dark) {
338
+ background: rgba(0, 0, 0, $opacity);
339
+ border-color: rgba(255, 255, 255, 0.1);
340
+ }
341
+ }
342
+
343
+ // =====================================================================
344
+ // NEUMORPHISM (Soft UI)
345
+ // =====================================================================
346
+
347
+ @mixin neumorphic-card($raised: true) {
348
+ background: var(--osi-section-item-background);
349
+ border-radius: var(--radius-xl);
350
+
351
+ @if $raised {
352
+ box-shadow:
353
+ 8px 8px 16px rgba(0, 0, 0, 0.1),
354
+ -8px -8px 16px rgba(255, 255, 255, 0.7);
355
+ } @else {
356
+ box-shadow:
357
+ inset 8px 8px 16px rgba(0, 0, 0, 0.1),
358
+ inset -8px -8px 16px rgba(255, 255, 255, 0.7);
359
+ }
360
+
361
+ transition: box-shadow var(--duration-base) var(--ease-out);
362
+
363
+ &:hover {
364
+ @if $raised {
365
+ box-shadow:
366
+ 12px 12px 24px rgba(0, 0, 0, 0.12),
367
+ -12px -12px 24px rgba(255, 255, 255, 0.8);
368
+ }
369
+ }
370
+ }
371
+
372
+ // =====================================================================
373
+ // SCROLL REVEAL (Intersection Observer Companion)
374
+ // =====================================================================
375
+
376
+ @mixin scroll-reveal {
377
+ opacity: 0;
378
+ transform: translate3d(0, 20px, 0);
379
+ transition:
380
+ opacity var(--duration-slow) var(--ease-out),
381
+ transform var(--duration-slow) var(--ease-out);
382
+
383
+ &.is-revealed {
384
+ opacity: 1;
385
+ transform: translate3d(0, 0, 0);
386
+ }
387
+
388
+ @media (prefers-reduced-motion: reduce) {
389
+ opacity: 1;
390
+ transform: none;
391
+ }
392
+ }