@n3wth/ui 0.1.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.
Files changed (96) hide show
  1. package/dist/atoms/Badge/Badge.d.ts +8 -0
  2. package/dist/atoms/Badge/Badge.d.ts.map +1 -0
  3. package/dist/atoms/Badge/index.d.ts +3 -0
  4. package/dist/atoms/Badge/index.d.ts.map +1 -0
  5. package/dist/atoms/Button/Button.d.ts +12 -0
  6. package/dist/atoms/Button/Button.d.ts.map +1 -0
  7. package/dist/atoms/Button/index.d.ts +3 -0
  8. package/dist/atoms/Button/index.d.ts.map +1 -0
  9. package/dist/atoms/Icon/Icon.d.ts +8 -0
  10. package/dist/atoms/Icon/Icon.d.ts.map +1 -0
  11. package/dist/atoms/Icon/index.d.ts +3 -0
  12. package/dist/atoms/Icon/index.d.ts.map +1 -0
  13. package/dist/atoms/Input/Input.d.ts +10 -0
  14. package/dist/atoms/Input/Input.d.ts.map +1 -0
  15. package/dist/atoms/Input/index.d.ts +3 -0
  16. package/dist/atoms/Input/index.d.ts.map +1 -0
  17. package/dist/atoms/index.d.ts +9 -0
  18. package/dist/atoms/index.d.ts.map +1 -0
  19. package/dist/fonts/Geist-Medium.woff2 +0 -0
  20. package/dist/fonts/Geist-Regular.woff2 +0 -0
  21. package/dist/fonts/Geist-SemiBold.woff2 +0 -0
  22. package/dist/fonts/GeistMono-Medium.woff2 +0 -0
  23. package/dist/fonts/GeistMono-Regular.woff2 +0 -0
  24. package/dist/fonts/MonaSans-Variable-Italic.woff2 +0 -0
  25. package/dist/fonts/MonaSans-Variable.woff2 +0 -0
  26. package/dist/hooks/index.d.ts +7 -0
  27. package/dist/hooks/index.d.ts.map +1 -0
  28. package/dist/hooks/useKeyboardShortcuts.d.ts +17 -0
  29. package/dist/hooks/useKeyboardShortcuts.d.ts.map +1 -0
  30. package/dist/hooks/useMediaQuery.d.ts +5 -0
  31. package/dist/hooks/useMediaQuery.d.ts.map +1 -0
  32. package/dist/hooks/useReducedMotion.d.ts +2 -0
  33. package/dist/hooks/useReducedMotion.d.ts.map +1 -0
  34. package/dist/hooks/useTheme.d.ts +15 -0
  35. package/dist/hooks/useTheme.d.ts.map +1 -0
  36. package/dist/index.d.ts +33 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +3275 -0
  39. package/dist/molecules/Card/Card.d.ts +29 -0
  40. package/dist/molecules/Card/Card.d.ts.map +1 -0
  41. package/dist/molecules/Card/index.d.ts +3 -0
  42. package/dist/molecules/Card/index.d.ts.map +1 -0
  43. package/dist/molecules/CommandBox/CommandBox.d.ts +9 -0
  44. package/dist/molecules/CommandBox/CommandBox.d.ts.map +1 -0
  45. package/dist/molecules/CommandBox/index.d.ts +3 -0
  46. package/dist/molecules/CommandBox/index.d.ts.map +1 -0
  47. package/dist/molecules/NavLink/NavLink.d.ts +8 -0
  48. package/dist/molecules/NavLink/NavLink.d.ts.map +1 -0
  49. package/dist/molecules/NavLink/index.d.ts +3 -0
  50. package/dist/molecules/NavLink/index.d.ts.map +1 -0
  51. package/dist/molecules/ThemeToggle/ThemeToggle.d.ts +8 -0
  52. package/dist/molecules/ThemeToggle/ThemeToggle.d.ts.map +1 -0
  53. package/dist/molecules/ThemeToggle/index.d.ts +3 -0
  54. package/dist/molecules/ThemeToggle/index.d.ts.map +1 -0
  55. package/dist/molecules/index.d.ts +9 -0
  56. package/dist/molecules/index.d.ts.map +1 -0
  57. package/dist/organisms/Footer/Footer.d.ts +23 -0
  58. package/dist/organisms/Footer/Footer.d.ts.map +1 -0
  59. package/dist/organisms/Footer/index.d.ts +3 -0
  60. package/dist/organisms/Footer/index.d.ts.map +1 -0
  61. package/dist/organisms/Hero/Hero.d.ts +17 -0
  62. package/dist/organisms/Hero/Hero.d.ts.map +1 -0
  63. package/dist/organisms/Hero/index.d.ts +3 -0
  64. package/dist/organisms/Hero/index.d.ts.map +1 -0
  65. package/dist/organisms/Nav/Nav.d.ts +19 -0
  66. package/dist/organisms/Nav/Nav.d.ts.map +1 -0
  67. package/dist/organisms/Nav/index.d.ts +3 -0
  68. package/dist/organisms/Nav/index.d.ts.map +1 -0
  69. package/dist/organisms/Section/Section.d.ts +15 -0
  70. package/dist/organisms/Section/Section.d.ts.map +1 -0
  71. package/dist/organisms/Section/index.d.ts +3 -0
  72. package/dist/organisms/Section/index.d.ts.map +1 -0
  73. package/dist/organisms/index.d.ts +9 -0
  74. package/dist/organisms/index.d.ts.map +1 -0
  75. package/dist/styles.css +851 -0
  76. package/dist/tokens/colors.d.ts +56 -0
  77. package/dist/tokens/colors.d.ts.map +1 -0
  78. package/dist/tokens/effects.d.ts +20 -0
  79. package/dist/tokens/effects.d.ts.map +1 -0
  80. package/dist/tokens/index.d.ts +5 -0
  81. package/dist/tokens/index.d.ts.map +1 -0
  82. package/dist/tokens/spacing.d.ts +28 -0
  83. package/dist/tokens/spacing.d.ts.map +1 -0
  84. package/dist/tokens/typography.d.ts +46 -0
  85. package/dist/tokens/typography.d.ts.map +1 -0
  86. package/dist/utils/cn.d.ts +3 -0
  87. package/dist/utils/cn.d.ts.map +1 -0
  88. package/package.json +61 -0
  89. package/public/fonts/Geist-Medium.woff2 +0 -0
  90. package/public/fonts/Geist-Regular.woff2 +0 -0
  91. package/public/fonts/Geist-SemiBold.woff2 +0 -0
  92. package/public/fonts/GeistMono-Medium.woff2 +0 -0
  93. package/public/fonts/GeistMono-Regular.woff2 +0 -0
  94. package/public/fonts/MonaSans-Variable-Italic.woff2 +0 -0
  95. package/public/fonts/MonaSans-Variable.woff2 +0 -0
  96. package/tailwind.preset.js +59 -0
@@ -0,0 +1,851 @@
1
+ /* ============================================================
2
+ Mona Sans (Display/Titles) - Variable Font
3
+ ============================================================ */
4
+
5
+ @font-face {
6
+ font-family: 'Mona Sans';
7
+ src: url('/fonts/MonaSans-Variable.woff2') format('woff2-variations');
8
+ font-weight: 200 900;
9
+ font-style: normal;
10
+ font-stretch: 75% 125%;
11
+ font-display: swap;
12
+ }
13
+
14
+ @font-face {
15
+ font-family: 'Mona Sans';
16
+ src: url('/fonts/MonaSans-Variable-Italic.woff2') format('woff2-variations');
17
+ font-weight: 200 900;
18
+ font-style: italic;
19
+ font-stretch: 75% 125%;
20
+ font-display: swap;
21
+ }
22
+
23
+ /* ============================================================
24
+ Geist Font Faces (Body/UI)
25
+ ============================================================ */
26
+
27
+ @font-face {
28
+ font-family: 'Geist Sans';
29
+ src: url('/fonts/Geist-Regular.woff2') format('woff2');
30
+ font-weight: 400;
31
+ font-style: normal;
32
+ font-display: swap;
33
+ }
34
+
35
+ @font-face {
36
+ font-family: 'Geist Sans';
37
+ src: url('/fonts/Geist-Medium.woff2') format('woff2');
38
+ font-weight: 500;
39
+ font-style: normal;
40
+ font-display: swap;
41
+ }
42
+
43
+ @font-face {
44
+ font-family: 'Geist Sans';
45
+ src: url('/fonts/Geist-SemiBold.woff2') format('woff2');
46
+ font-weight: 600;
47
+ font-style: normal;
48
+ font-display: swap;
49
+ }
50
+
51
+ @font-face {
52
+ font-family: 'Geist Mono';
53
+ src: url('/fonts/GeistMono-Regular.woff2') format('woff2');
54
+ font-weight: 400;
55
+ font-style: normal;
56
+ font-display: swap;
57
+ }
58
+
59
+ @font-face {
60
+ font-family: 'Geist Mono';
61
+ src: url('/fonts/GeistMono-Medium.woff2') format('woff2');
62
+ font-weight: 500;
63
+ font-style: normal;
64
+ font-display: swap;
65
+ }
66
+
67
+ /* ============================================================
68
+ Tailwind v4 Theme Configuration
69
+ ============================================================ */
70
+
71
+ @theme {
72
+ /* Typography */
73
+ --font-display: 'Mona Sans', system-ui, sans-serif;
74
+ --font-sans: 'Geist Sans', system-ui, sans-serif;
75
+ --font-mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, Monaco, monospace;
76
+
77
+ /* Dark palette (default) */
78
+ --color-bg: #000000;
79
+ --color-bg-secondary: #0a0a0a;
80
+ --color-white: #ffffff;
81
+ --color-grey-100: #f5f5f7;
82
+ --color-grey-200: #e8e8ed;
83
+ --color-grey-300: #c7c7cc;
84
+ --color-grey-400: #86868b;
85
+ --color-grey-600: #6e6e73;
86
+ --color-grey-800: #1d1d1f;
87
+
88
+ /* Accent */
89
+ --color-accent: #ffffff;
90
+ --color-accent-soft: rgba(255, 255, 255, 0.15);
91
+
92
+ /* Category colors */
93
+ --color-sage: #30d158;
94
+ --color-coral: #ff6961;
95
+ --color-mint: #64d2ff;
96
+ --color-gold: #ffd60a;
97
+
98
+ /* Glass effect */
99
+ --glass-bg: rgba(255, 255, 255, 0.05);
100
+ --glass-border: rgba(255, 255, 255, 0.1);
101
+ --glass-highlight: rgba(255, 255, 255, 0.15);
102
+ }
103
+
104
+ /* ============================================================
105
+ CSS Custom Properties (for component usage)
106
+ ============================================================ */
107
+
108
+ :root,
109
+ [data-theme='dark'] {
110
+ --font-display: 'Mona Sans', system-ui, sans-serif;
111
+ --font-sans: 'Geist Sans', system-ui, sans-serif;
112
+ --font-mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, Monaco, monospace;
113
+
114
+ --color-bg: #000000;
115
+ --color-bg-secondary: #0a0a0a;
116
+ --color-white: #ffffff;
117
+ --color-grey-100: #f5f5f7;
118
+ --color-grey-200: #e8e8ed;
119
+ --color-grey-300: #c7c7cc;
120
+ --color-grey-400: #86868b;
121
+ --color-grey-600: #6e6e73;
122
+ --color-grey-800: #1d1d1f;
123
+
124
+ --color-accent: #ffffff;
125
+ --color-accent-soft: rgba(255, 255, 255, 0.15);
126
+
127
+ --color-sage: #30d158;
128
+ --color-coral: #ff6961;
129
+ --color-mint: #64d2ff;
130
+ --color-gold: #ffd60a;
131
+
132
+ --glass-bg: rgba(255, 255, 255, 0.05);
133
+ --glass-border: rgba(255, 255, 255, 0.1);
134
+ --glass-highlight: rgba(255, 255, 255, 0.15);
135
+ }
136
+
137
+ /* ============================================================
138
+ Light Mode Overrides
139
+ ============================================================ */
140
+
141
+ [data-theme='light'] {
142
+ --color-bg: #ffffff;
143
+ --color-bg-secondary: #f5f5f7;
144
+ --color-white: #1d1d1f;
145
+ --color-grey-100: #1d1d1f;
146
+ --color-grey-200: #3a3a3c;
147
+ --color-grey-300: #48484a;
148
+ --color-grey-400: #636366;
149
+ --color-grey-600: #8e8e93;
150
+ --color-grey-800: #e5e5ea;
151
+
152
+ --color-accent: #1d1d1f;
153
+ --color-accent-soft: rgba(0, 0, 0, 0.1);
154
+
155
+ --color-sage: #248a3d;
156
+ --color-coral: #d70015;
157
+ --color-mint: #0071e3;
158
+ --color-gold: #b25000;
159
+
160
+ --glass-bg: rgba(0, 0, 0, 0.03);
161
+ --glass-border: rgba(0, 0, 0, 0.08);
162
+ --glass-highlight: rgba(0, 0, 0, 0.12);
163
+ }
164
+
165
+ /* ============================================================
166
+ Base Styles
167
+ ============================================================ */
168
+
169
+ * {
170
+ box-sizing: border-box;
171
+ }
172
+
173
+ html {
174
+ background: var(--color-bg);
175
+ color: var(--color-white);
176
+ font-family: var(--font-sans);
177
+ -webkit-font-smoothing: antialiased;
178
+ -moz-osx-font-smoothing: grayscale;
179
+ transition: background-color 0.3s ease, color 0.3s ease;
180
+ }
181
+
182
+ body {
183
+ margin: 0;
184
+ min-height: 100vh;
185
+ line-height: 1.5;
186
+ }
187
+
188
+ ::selection {
189
+ background: var(--color-accent);
190
+ color: var(--color-bg);
191
+ }
192
+
193
+ /* ============================================================
194
+ Typography Utilities
195
+ ============================================================ */
196
+
197
+ /* Uppercase label */
198
+ .label {
199
+ font-family: var(--font-sans);
200
+ font-size: 11px;
201
+ letter-spacing: 0.08em;
202
+ text-transform: uppercase;
203
+ color: var(--color-grey-400);
204
+ }
205
+
206
+ /* Number index - tabular figures */
207
+ .index-num {
208
+ font-family: var(--font-sans);
209
+ font-size: 10px;
210
+ color: var(--color-grey-600);
211
+ font-variant-numeric: tabular-nums;
212
+ }
213
+
214
+ /* Hero gradient text animation */
215
+ .hero-gradient-text {
216
+ background: linear-gradient(
217
+ 90deg,
218
+ var(--color-white) 0%,
219
+ var(--color-grey-300) 25%,
220
+ var(--color-white) 50%,
221
+ var(--color-grey-300) 75%,
222
+ var(--color-white) 100%
223
+ );
224
+ background-size: 200% auto;
225
+ -webkit-background-clip: text;
226
+ background-clip: text;
227
+ -webkit-text-fill-color: transparent;
228
+ animation: gradientShift 8s ease-in-out infinite;
229
+ }
230
+
231
+ [data-theme='light'] .hero-gradient-text {
232
+ background: linear-gradient(
233
+ 90deg,
234
+ var(--color-white) 0%,
235
+ var(--color-grey-400) 25%,
236
+ var(--color-white) 50%,
237
+ var(--color-grey-400) 75%,
238
+ var(--color-white) 100%
239
+ );
240
+ background-size: 200% auto;
241
+ -webkit-background-clip: text;
242
+ background-clip: text;
243
+ -webkit-text-fill-color: transparent;
244
+ }
245
+
246
+ /* ============================================================
247
+ Link Utilities
248
+ ============================================================ */
249
+
250
+ /* Underline link animation */
251
+ .link-hover {
252
+ position: relative;
253
+ }
254
+
255
+ .link-hover::after {
256
+ content: '';
257
+ position: absolute;
258
+ bottom: -1px;
259
+ left: 0;
260
+ width: 0;
261
+ height: 1px;
262
+ background: currentColor;
263
+ transition: width 0.35s cubic-bezier(0.4, 0, 0.2, 1);
264
+ }
265
+
266
+ .link-hover:hover::after {
267
+ width: 100%;
268
+ }
269
+
270
+ /* ============================================================
271
+ Glass Components
272
+ ============================================================ */
273
+
274
+ /* Glass Card - flat design, no shadows */
275
+ .glass-card {
276
+ background: transparent;
277
+ border: 1px solid var(--glass-border);
278
+ border-radius: 20px;
279
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
280
+ }
281
+
282
+ .glass-card:hover {
283
+ border-color: var(--glass-highlight);
284
+ }
285
+
286
+ /* Skill Card with hover effects */
287
+ .skill-card {
288
+ transition: border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
289
+ background 0.3s cubic-bezier(0.4, 0, 0.2, 1);
290
+ }
291
+
292
+ .skill-card:hover {
293
+ background: var(--glass-bg);
294
+ }
295
+
296
+ /* Glass Nav */
297
+ .glass-nav {
298
+ background: rgba(0, 0, 0, 0.7);
299
+ backdrop-filter: blur(20px) saturate(180%);
300
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
301
+ }
302
+
303
+ [data-theme='light'] .glass-nav {
304
+ background: rgba(255, 255, 255, 0.8);
305
+ }
306
+
307
+ /* Glass Pill */
308
+ .glass-pill {
309
+ background: var(--glass-bg);
310
+ backdrop-filter: blur(20px);
311
+ -webkit-backdrop-filter: blur(20px);
312
+ border: 1px solid var(--glass-border);
313
+ border-radius: 9999px;
314
+ color: var(--color-grey-400);
315
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
316
+ transform: scale(1);
317
+ }
318
+
319
+ .glass-pill:hover {
320
+ background: rgba(255, 255, 255, 0.1);
321
+ border-color: var(--glass-highlight);
322
+ color: var(--color-white);
323
+ transform: scale(1.02);
324
+ }
325
+
326
+ .glass-pill:active {
327
+ transform: scale(0.96);
328
+ transition-duration: 0.1s;
329
+ }
330
+
331
+ .glass-pill.active {
332
+ background: var(--color-white);
333
+ border-color: var(--color-white);
334
+ color: var(--color-bg);
335
+ }
336
+
337
+ [data-theme='light'] .glass-pill {
338
+ background: rgba(0, 0, 0, 0.03);
339
+ border-color: rgba(0, 0, 0, 0.08);
340
+ }
341
+
342
+ [data-theme='light'] .glass-pill:hover {
343
+ background: rgba(0, 0, 0, 0.06);
344
+ border-color: rgba(0, 0, 0, 0.12);
345
+ }
346
+
347
+ [data-theme='light'] .glass-pill.active {
348
+ background: var(--color-accent);
349
+ border-color: var(--color-accent);
350
+ color: var(--color-bg);
351
+ }
352
+
353
+ /* ============================================================
354
+ Command Box & Interactive Elements
355
+ ============================================================ */
356
+
357
+ /* Install Command Box */
358
+ .command-box {
359
+ background: rgba(255, 255, 255, 0.03);
360
+ backdrop-filter: blur(20px);
361
+ -webkit-backdrop-filter: blur(20px);
362
+ border: 1px solid var(--glass-border);
363
+ border-radius: 16px;
364
+ transition: all 0.2s ease;
365
+ }
366
+
367
+ .command-box:hover {
368
+ background: rgba(255, 255, 255, 0.06);
369
+ border-color: var(--glass-highlight);
370
+ }
371
+
372
+ .command-box.primary {
373
+ background: var(--glass-bg);
374
+ border-color: var(--glass-highlight);
375
+ }
376
+
377
+ .command-box.primary:hover {
378
+ background: rgba(255, 255, 255, 0.12);
379
+ }
380
+
381
+ /* Copy button */
382
+ .copy-btn {
383
+ background: rgba(255, 255, 255, 0.1);
384
+ border: none;
385
+ color: var(--color-grey-400);
386
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
387
+ transform: scale(1);
388
+ }
389
+
390
+ .copy-btn:hover {
391
+ background: rgba(255, 255, 255, 0.15);
392
+ color: var(--color-white);
393
+ transform: scale(1.05);
394
+ }
395
+
396
+ .copy-btn:active {
397
+ transform: scale(0.92);
398
+ transition-duration: 0.1s;
399
+ }
400
+
401
+ .copy-btn.copied {
402
+ background: var(--color-sage);
403
+ color: var(--color-bg);
404
+ transform: scale(1);
405
+ }
406
+
407
+ /* ============================================================
408
+ Background Elements
409
+ ============================================================ */
410
+
411
+ /* Gradient mesh background */
412
+ .mesh-gradient {
413
+ position: fixed;
414
+ inset: 0;
415
+ pointer-events: none;
416
+ z-index: -1;
417
+ background: #000000;
418
+ }
419
+
420
+ [data-theme='light'] .mesh-gradient {
421
+ background: #ffffff;
422
+ }
423
+
424
+ /* Noise texture overlay */
425
+ .noise-overlay {
426
+ position: fixed;
427
+ inset: 0;
428
+ pointer-events: none;
429
+ opacity: 0.015;
430
+ z-index: 9999;
431
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
432
+ }
433
+
434
+ /* ============================================================
435
+ Animations
436
+ ============================================================ */
437
+
438
+ /* Gradient shift for hero text */
439
+ @keyframes gradientShift {
440
+ 0%, 100% {
441
+ background-position: 0% 50%;
442
+ }
443
+ 50% {
444
+ background-position: 100% 50%;
445
+ }
446
+ }
447
+
448
+ /* Fade up entrance animation */
449
+ @keyframes fadeUp {
450
+ from {
451
+ opacity: 0;
452
+ transform: translateY(24px);
453
+ }
454
+ to {
455
+ opacity: 1;
456
+ transform: translateY(0);
457
+ }
458
+ }
459
+
460
+ .animate-in {
461
+ animation: fadeUp 0.6s cubic-bezier(0.4, 0, 0.2, 1) forwards;
462
+ opacity: 0;
463
+ }
464
+
465
+ /* Skeleton loading shimmer */
466
+ @keyframes shimmer {
467
+ 0% {
468
+ opacity: 0.4;
469
+ }
470
+ 50% {
471
+ opacity: 0.8;
472
+ }
473
+ 100% {
474
+ opacity: 0.4;
475
+ }
476
+ }
477
+
478
+ .skeleton-shimmer {
479
+ animation: shimmer 1.8s ease-in-out infinite;
480
+ }
481
+
482
+ /* Skeleton fade out */
483
+ @keyframes skeletonFadeOut {
484
+ from {
485
+ opacity: 1;
486
+ transform: scale(1);
487
+ }
488
+ to {
489
+ opacity: 0;
490
+ transform: scale(0.98);
491
+ }
492
+ }
493
+
494
+ .skeleton-exit {
495
+ animation: skeletonFadeOut 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
496
+ }
497
+
498
+ /* Card entrance animation */
499
+ @keyframes cardEnter {
500
+ from {
501
+ opacity: 0;
502
+ transform: translateY(20px) scale(0.96);
503
+ }
504
+ to {
505
+ opacity: 1;
506
+ transform: translateY(0) scale(1);
507
+ }
508
+ }
509
+
510
+ .card-enter {
511
+ animation: cardEnter 0.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;
512
+ animation-fill-mode: both;
513
+ }
514
+
515
+ /* Content loaded state */
516
+ .content-loaded {
517
+ opacity: 1;
518
+ }
519
+
520
+ /* Page transition animations */
521
+ @keyframes pageEnter {
522
+ from {
523
+ opacity: 0;
524
+ transform: translateY(16px);
525
+ }
526
+ to {
527
+ opacity: 1;
528
+ transform: translateY(0);
529
+ }
530
+ }
531
+
532
+ @keyframes pageExit {
533
+ from {
534
+ opacity: 1;
535
+ transform: translateY(0);
536
+ }
537
+ to {
538
+ opacity: 0;
539
+ transform: translateY(-8px);
540
+ }
541
+ }
542
+
543
+ .page-enter {
544
+ animation: pageEnter 0.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;
545
+ }
546
+
547
+ .page-exit {
548
+ animation: pageExit 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
549
+ }
550
+
551
+ /* Constellation pattern */
552
+ @keyframes constellationTwinkle {
553
+ 0%, 100% {
554
+ opacity: 0.3;
555
+ transform: scale(1);
556
+ }
557
+ 50% {
558
+ opacity: 0.8;
559
+ transform: scale(1.2);
560
+ }
561
+ }
562
+
563
+ @keyframes constellationDrift {
564
+ 0% {
565
+ transform: translateY(0) rotate(0deg);
566
+ }
567
+ 100% {
568
+ transform: translateY(-100vh) rotate(180deg);
569
+ }
570
+ }
571
+
572
+ .constellation-dot {
573
+ animation: constellationTwinkle var(--twinkle-duration, 3s) ease-in-out infinite;
574
+ animation-delay: var(--twinkle-delay, 0s);
575
+ }
576
+
577
+ /* Workflow node animations */
578
+ @keyframes nodeEnter {
579
+ from {
580
+ opacity: 0;
581
+ transform: scale(0.8);
582
+ }
583
+ to {
584
+ opacity: 1;
585
+ transform: scale(1);
586
+ }
587
+ }
588
+
589
+ .workflow-node-enter {
590
+ animation: nodeEnter 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
591
+ }
592
+
593
+ /* Connection line animation */
594
+ @keyframes connectionDraw {
595
+ from {
596
+ stroke-dashoffset: 100%;
597
+ }
598
+ to {
599
+ stroke-dashoffset: 0;
600
+ }
601
+ }
602
+
603
+ .connection-line {
604
+ stroke-dasharray: 100%;
605
+ animation: connectionDraw 0.3s ease-out forwards;
606
+ }
607
+
608
+ /* Hover preview entrance */
609
+ @keyframes hoverPreviewEnter {
610
+ from {
611
+ opacity: 0;
612
+ transform: scale(0.95) translateY(4px);
613
+ }
614
+ to {
615
+ opacity: 1;
616
+ transform: scale(1) translateY(0);
617
+ }
618
+ }
619
+
620
+ /* ============================================================
621
+ Navigation Components
622
+ ============================================================ */
623
+
624
+ /* Mobile Navigation */
625
+ .mobile-nav-link {
626
+ background: transparent;
627
+ -webkit-tap-highlight-color: transparent;
628
+ }
629
+
630
+ .mobile-nav-link:hover,
631
+ .mobile-nav-link:active {
632
+ background: var(--glass-bg);
633
+ }
634
+
635
+ @media (hover: none) {
636
+ .mobile-nav-link:active {
637
+ background: var(--glass-highlight);
638
+ }
639
+ }
640
+
641
+ .mobile-menu-drawer {
642
+ border-left: 1px solid var(--glass-border);
643
+ }
644
+
645
+ [data-theme='light'] .mobile-menu-overlay {
646
+ background-color: rgba(0, 0, 0, 0.3) !important;
647
+ }
648
+
649
+ /* ============================================================
650
+ Hover Preview
651
+ ============================================================ */
652
+
653
+ .hover-preview {
654
+ width: 320px;
655
+ pointer-events: auto;
656
+ }
657
+
658
+ .hover-preview-content {
659
+ background: var(--glass-bg);
660
+ backdrop-filter: blur(20px) saturate(180%);
661
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
662
+ border: 1px solid var(--glass-border);
663
+ border-radius: 16px;
664
+ padding: 16px;
665
+ animation: hoverPreviewEnter 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
666
+ }
667
+
668
+ [data-theme='light'] .hover-preview-content {
669
+ background: rgba(255, 255, 255, 0.9);
670
+ }
671
+
672
+ .hover-preview[data-placement="left"] .hover-preview-content {
673
+ transform-origin: right center;
674
+ }
675
+
676
+ .hover-preview[data-placement="right"] .hover-preview-content {
677
+ transform-origin: left center;
678
+ }
679
+
680
+ .hover-preview[data-placement="top"] .hover-preview-content {
681
+ transform-origin: bottom center;
682
+ }
683
+
684
+ .hover-preview[data-placement="bottom"] .hover-preview-content {
685
+ transform-origin: top center;
686
+ }
687
+
688
+ .hover-preview button:hover {
689
+ background: var(--glass-highlight) !important;
690
+ border-color: var(--glass-highlight) !important;
691
+ }
692
+
693
+ .hover-preview button:active {
694
+ transform: scale(0.98);
695
+ }
696
+
697
+ /* ============================================================
698
+ Utility Classes
699
+ ============================================================ */
700
+
701
+ /* Line clamp */
702
+ .line-clamp-1 {
703
+ display: -webkit-box;
704
+ -webkit-line-clamp: 1;
705
+ -webkit-box-orient: vertical;
706
+ overflow: hidden;
707
+ }
708
+
709
+ .line-clamp-2 {
710
+ display: -webkit-box;
711
+ -webkit-line-clamp: 2;
712
+ -webkit-box-orient: vertical;
713
+ overflow: hidden;
714
+ }
715
+
716
+ .line-clamp-3 {
717
+ display: -webkit-box;
718
+ -webkit-line-clamp: 3;
719
+ -webkit-box-orient: vertical;
720
+ overflow: hidden;
721
+ }
722
+
723
+ /* Hidden scrollbar */
724
+ .scrollbar-hidden {
725
+ -ms-overflow-style: none;
726
+ scrollbar-width: none;
727
+ }
728
+
729
+ .scrollbar-hidden::-webkit-scrollbar {
730
+ display: none;
731
+ }
732
+
733
+ /* Focus visible ring - flat, no glow */
734
+ .focus-ring {
735
+ outline: none;
736
+ }
737
+
738
+ .focus-ring:focus-visible {
739
+ outline: 2px solid var(--color-accent);
740
+ outline-offset: 2px;
741
+ }
742
+
743
+ /* Truncate text */
744
+ .truncate {
745
+ overflow: hidden;
746
+ text-overflow: ellipsis;
747
+ white-space: nowrap;
748
+ }
749
+
750
+ /* Screen reader only */
751
+ .sr-only {
752
+ position: absolute;
753
+ width: 1px;
754
+ height: 1px;
755
+ padding: 0;
756
+ margin: -1px;
757
+ overflow: hidden;
758
+ clip: rect(0, 0, 0, 0);
759
+ white-space: nowrap;
760
+ border-width: 0;
761
+ }
762
+
763
+ /* ============================================================
764
+ Reduced Motion Preferences
765
+ ============================================================ */
766
+
767
+ @media (prefers-reduced-motion: reduce) {
768
+ *,
769
+ *::before,
770
+ *::after {
771
+ animation-duration: 0.01ms !important;
772
+ animation-iteration-count: 1 !important;
773
+ transition-duration: 0.01ms !important;
774
+ scroll-behavior: auto !important;
775
+ }
776
+
777
+ html {
778
+ scroll-behavior: auto;
779
+ }
780
+
781
+ .skill-card,
782
+ .glass-pill,
783
+ .copy-btn,
784
+ .glass-card {
785
+ transform: none !important;
786
+ transition: none !important;
787
+ }
788
+
789
+ .skill-card:hover,
790
+ .skill-card:active {
791
+ transform: none !important;
792
+ }
793
+
794
+ .glass-pill:hover,
795
+ .glass-pill:active {
796
+ transform: none !important;
797
+ }
798
+
799
+ .copy-btn:hover,
800
+ .copy-btn:active {
801
+ transform: none !important;
802
+ }
803
+
804
+ .hero-word {
805
+ opacity: 1 !important;
806
+ transform: none !important;
807
+ }
808
+
809
+ .floating-shape {
810
+ animation: none !important;
811
+ opacity: 0.5 !important;
812
+ }
813
+
814
+ .hero-gradient-text {
815
+ animation: none !important;
816
+ -webkit-text-fill-color: var(--color-white) !important;
817
+ }
818
+
819
+ .constellation-dot {
820
+ animation: none !important;
821
+ opacity: 0.5 !important;
822
+ }
823
+
824
+ .content-loaded,
825
+ .page-enter,
826
+ .page-exit,
827
+ .animate-in,
828
+ .card-enter,
829
+ .skeleton-shimmer,
830
+ .skeleton-exit {
831
+ animation: none !important;
832
+ opacity: 1 !important;
833
+ transform: none !important;
834
+ }
835
+
836
+ .hover-preview-content {
837
+ animation: none !important;
838
+ opacity: 1 !important;
839
+ transform: none !important;
840
+ }
841
+
842
+ .workflow-node-enter {
843
+ animation: none !important;
844
+ opacity: 1 !important;
845
+ transform: none !important;
846
+ }
847
+
848
+ .connection-line {
849
+ animation: none !important;
850
+ }
851
+ }