@ikonai/sdk-react-ui 1.2.0 → 1.3.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 (73) hide show
  1. package/app/use-ikon-app.d.ts +6 -0
  2. package/auth/auth-service.d.ts +46 -2
  3. package/auth/index.d.ts +1 -1
  4. package/fonts/files/crimson-pro-latin-ext-italic.woff2 +0 -0
  5. package/fonts/files/crimson-pro-latin-ext-normal.woff2 +0 -0
  6. package/fonts/files/crimson-pro-latin-italic.woff2 +0 -0
  7. package/fonts/files/crimson-pro-latin-normal.woff2 +0 -0
  8. package/fonts/files/crimson-pro-vietnamese-italic.woff2 +0 -0
  9. package/fonts/files/crimson-pro-vietnamese-normal.woff2 +0 -0
  10. package/fonts/files/inter-cyrillic-ext-italic.woff2 +0 -0
  11. package/fonts/files/inter-cyrillic-ext-normal.woff2 +0 -0
  12. package/fonts/files/inter-cyrillic-italic.woff2 +0 -0
  13. package/fonts/files/inter-cyrillic-normal.woff2 +0 -0
  14. package/fonts/files/inter-greek-ext-italic.woff2 +0 -0
  15. package/fonts/files/inter-greek-ext-normal.woff2 +0 -0
  16. package/fonts/files/inter-greek-italic.woff2 +0 -0
  17. package/fonts/files/inter-greek-normal.woff2 +0 -0
  18. package/fonts/files/inter-latin-ext-italic.woff2 +0 -0
  19. package/fonts/files/inter-latin-ext-normal.woff2 +0 -0
  20. package/fonts/files/inter-latin-italic.woff2 +0 -0
  21. package/fonts/files/inter-latin-normal.woff2 +0 -0
  22. package/fonts/files/inter-vietnamese-italic.woff2 +0 -0
  23. package/fonts/files/inter-vietnamese-normal.woff2 +0 -0
  24. package/fonts/files/jetbrains-mono-cyrillic-ext-italic.woff2 +0 -0
  25. package/fonts/files/jetbrains-mono-cyrillic-ext-normal.woff2 +0 -0
  26. package/fonts/files/jetbrains-mono-cyrillic-italic.woff2 +0 -0
  27. package/fonts/files/jetbrains-mono-cyrillic-normal.woff2 +0 -0
  28. package/fonts/files/jetbrains-mono-greek-italic.woff2 +0 -0
  29. package/fonts/files/jetbrains-mono-greek-normal.woff2 +0 -0
  30. package/fonts/files/jetbrains-mono-latin-ext-italic.woff2 +0 -0
  31. package/fonts/files/jetbrains-mono-latin-ext-normal.woff2 +0 -0
  32. package/fonts/files/jetbrains-mono-latin-italic.woff2 +0 -0
  33. package/fonts/files/jetbrains-mono-latin-normal.woff2 +0 -0
  34. package/fonts/files/jetbrains-mono-vietnamese-italic.woff2 +0 -0
  35. package/fonts/files/jetbrains-mono-vietnamese-normal.woff2 +0 -0
  36. package/fonts/files/poppins-devanagari-400-italic.woff2 +0 -0
  37. package/fonts/files/poppins-devanagari-400-normal.woff2 +0 -0
  38. package/fonts/files/poppins-devanagari-500-italic.woff2 +0 -0
  39. package/fonts/files/poppins-devanagari-500-normal.woff2 +0 -0
  40. package/fonts/files/poppins-devanagari-600-italic.woff2 +0 -0
  41. package/fonts/files/poppins-devanagari-600-normal.woff2 +0 -0
  42. package/fonts/files/poppins-devanagari-700-italic.woff2 +0 -0
  43. package/fonts/files/poppins-devanagari-700-normal.woff2 +0 -0
  44. package/fonts/files/poppins-latin-400-italic.woff2 +0 -0
  45. package/fonts/files/poppins-latin-400-normal.woff2 +0 -0
  46. package/fonts/files/poppins-latin-500-italic.woff2 +0 -0
  47. package/fonts/files/poppins-latin-500-normal.woff2 +0 -0
  48. package/fonts/files/poppins-latin-600-italic.woff2 +0 -0
  49. package/fonts/files/poppins-latin-600-normal.woff2 +0 -0
  50. package/fonts/files/poppins-latin-700-italic.woff2 +0 -0
  51. package/fonts/files/poppins-latin-700-normal.woff2 +0 -0
  52. package/fonts/files/poppins-latin-ext-400-italic.woff2 +0 -0
  53. package/fonts/files/poppins-latin-ext-400-normal.woff2 +0 -0
  54. package/fonts/files/poppins-latin-ext-500-italic.woff2 +0 -0
  55. package/fonts/files/poppins-latin-ext-500-normal.woff2 +0 -0
  56. package/fonts/files/poppins-latin-ext-600-italic.woff2 +0 -0
  57. package/fonts/files/poppins-latin-ext-600-normal.woff2 +0 -0
  58. package/fonts/files/poppins-latin-ext-700-italic.woff2 +0 -0
  59. package/fonts/files/poppins-latin-ext-700-normal.woff2 +0 -0
  60. package/fonts/ikon-fonts.css +1379 -0
  61. package/fonts/licenses/crimson-pro-OFL.txt +93 -0
  62. package/fonts/licenses/inter-OFL.txt +93 -0
  63. package/fonts/licenses/jetbrains-mono-OFL.txt +93 -0
  64. package/fonts/licenses/poppins-OFL.txt +93 -0
  65. package/hooks/index.d.ts +0 -1
  66. package/index.d.ts +1 -1
  67. package/index.js +840 -797
  68. package/package.json +8 -3
  69. package/theme/ikon-app.css +246 -0
  70. package/theme/ikon-auth.css +311 -0
  71. package/theme/ikon-surface.css +111 -0
  72. package/theme/ikon-tokens.css +132 -0
  73. package/hooks/use-lazy-font.d.ts +0 -18
package/package.json CHANGED
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "name": "@ikonai/sdk-react-ui",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
7
- "sideEffects": false,
7
+ "sideEffects": [
8
+ "fonts/**/*.css",
9
+ "theme/**/*.css"
10
+ ],
8
11
  "exports": {
9
12
  ".": {
10
13
  "import": "./index.js",
11
14
  "types": "./index.d.ts"
12
- }
15
+ },
16
+ "./fonts/*": "./fonts/*",
17
+ "./theme/*": "./theme/*"
13
18
  },
14
19
  "peerDependencies": {
15
20
  "@ikonai/sdk": "*",
@@ -0,0 +1,246 @@
1
+ /* Ikon app-shell styles: the connection overlays, the toast strip and the hero layout.
2
+
3
+ Override any of this from your own src/app.css — unlayered rules always win over these,
4
+ whatever their specificity or import order. */
5
+ @layer ikon {
6
+ .ikon-app {
7
+ display: flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ padding: 32px max(20px, env(safe-area-inset-left)) calc(32px + env(safe-area-inset-bottom));
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ .ikon-hero {
15
+ position: relative;
16
+ z-index: 1;
17
+ display: flex;
18
+ flex-direction: column;
19
+ align-items: center;
20
+ gap: 16px;
21
+ max-width: 460px;
22
+ text-align: center;
23
+ }
24
+
25
+ .ikon-hero h1 {
26
+ margin: 0;
27
+ font-family: var(--ikon-font-display);
28
+ font-size: clamp(24px, 7vw, 40px);
29
+ font-weight: 600;
30
+ line-height: 1.15;
31
+ letter-spacing: -0.02em;
32
+ color: var(--ikon-text-primary);
33
+ text-wrap: balance;
34
+ }
35
+
36
+ .ikon-info {
37
+ margin: 0;
38
+ font-size: 15px;
39
+ line-height: 1.6;
40
+ color: var(--ikon-text-secondary);
41
+ text-wrap: pretty;
42
+ }
43
+
44
+ .ikon-error {
45
+ margin: 0;
46
+ font-family: var(--ikon-font-mono);
47
+ font-size: 13px;
48
+ line-height: 1.5;
49
+ color: var(--ikon-status-error);
50
+ word-break: break-word;
51
+ }
52
+
53
+ .ikon-connecting-overlay {
54
+ position: fixed;
55
+ top: 0;
56
+ left: 0;
57
+ right: 0;
58
+ display: flex;
59
+ justify-content: center;
60
+ padding-top: max(16px, env(safe-area-inset-top));
61
+ z-index: 9998;
62
+ pointer-events: none;
63
+ }
64
+
65
+ .ikon-connecting-chip {
66
+ display: flex;
67
+ align-items: center;
68
+ gap: 8px;
69
+ padding: 8px 14px;
70
+ background: var(--ikon-bg-card);
71
+ border: 1px solid var(--ikon-border-secondary);
72
+ border-radius: var(--ikon-radius-full);
73
+ color: var(--ikon-text-secondary);
74
+ font-family: var(--ikon-font-body);
75
+ font-size: 13px;
76
+ font-weight: 500;
77
+ pointer-events: auto;
78
+ animation: ikon-fade-in 0.3s ease-out;
79
+ }
80
+
81
+ .ikon-connecting-spinner {
82
+ width: 13px;
83
+ height: 13px;
84
+ border: 2px solid var(--ikon-border-primary);
85
+ border-top-color: var(--ikon-text-tertiary);
86
+ border-radius: var(--ikon-radius-full);
87
+ animation: ikon-spin 0.9s linear infinite;
88
+ }
89
+
90
+ .ikon-reconnecting-overlay,
91
+ .ikon-offline-overlay {
92
+ position: fixed;
93
+ inset: 0;
94
+ display: flex;
95
+ align-items: center;
96
+ justify-content: center;
97
+ padding: 24px;
98
+ z-index: 9999;
99
+ background: var(--ikon-overlay-scrim);
100
+ backdrop-filter: blur(8px);
101
+ -webkit-backdrop-filter: blur(8px);
102
+ animation: ikon-fade-in 0.4s ease-out;
103
+ }
104
+
105
+ .ikon-reconnecting-chip,
106
+ .ikon-offline-chip {
107
+ box-sizing: border-box;
108
+ display: flex;
109
+ flex-direction: column;
110
+ align-items: center;
111
+ gap: 8px;
112
+ width: 100%;
113
+ max-width: 380px;
114
+ text-align: center;
115
+ color: var(--ikon-text-primary);
116
+ font-family: var(--ikon-font-body);
117
+ }
118
+
119
+ .ikon-reconnecting-spinner {
120
+ width: 28px;
121
+ height: 28px;
122
+ margin-bottom: 4px;
123
+ border: 2px solid var(--ikon-border-primary);
124
+ border-top-color: var(--ikon-text-tertiary);
125
+ border-radius: var(--ikon-radius-full);
126
+ animation: ikon-spin 0.9s linear infinite;
127
+ }
128
+
129
+ .ikon-reconnecting-chip span {
130
+ font-size: 15px;
131
+ font-weight: 500;
132
+ color: var(--ikon-text-secondary);
133
+ }
134
+
135
+ .ikon-offline-title {
136
+ font-family: var(--ikon-font-display);
137
+ font-size: clamp(20px, 5.5vw, 24px);
138
+ font-weight: 600;
139
+ line-height: 1.25;
140
+ letter-spacing: -0.015em;
141
+ text-wrap: balance;
142
+ }
143
+
144
+ .ikon-offline-message {
145
+ font-size: 14px;
146
+ line-height: 1.6;
147
+ color: var(--ikon-text-secondary);
148
+ text-wrap: pretty;
149
+ }
150
+
151
+ .ikon-offline-error {
152
+ margin-top: 6px;
153
+ font-family: var(--ikon-font-mono);
154
+ font-size: 12px;
155
+ line-height: 1.5;
156
+ color: var(--ikon-text-quaternary);
157
+ max-width: 100%;
158
+ word-break: break-word;
159
+ }
160
+
161
+ @keyframes ikon-fade-in {
162
+ from { opacity: 0; }
163
+ to { opacity: 1; }
164
+ }
165
+
166
+ @media (prefers-reduced-motion: reduce) {
167
+ .ikon-connecting-spinner,
168
+ .ikon-reconnecting-spinner {
169
+ animation-duration: 2.4s;
170
+ }
171
+ }
172
+
173
+ .ikon-toast-overlay {
174
+ position: fixed;
175
+ top: 0;
176
+ left: 0;
177
+ right: 0;
178
+ display: flex;
179
+ flex-direction: column;
180
+ align-items: center;
181
+ gap: 8px;
182
+ padding-top: max(16px, env(safe-area-inset-top));
183
+ z-index: 9998;
184
+ pointer-events: none;
185
+ }
186
+
187
+ .ikon-toast-overlay-chip {
188
+ display: flex;
189
+ align-items: center;
190
+ gap: 8px;
191
+ max-width: min(440px, calc(100vw - 32px));
192
+ padding: 8px 14px;
193
+ border: 1px solid var(--ikon-border-secondary);
194
+ border-radius: var(--ikon-radius-lg);
195
+ background: var(--ikon-bg-card);
196
+ color: var(--ikon-text-primary);
197
+ font-family: var(--ikon-font-body);
198
+ font-size: 13px;
199
+ font-weight: 500;
200
+ pointer-events: auto;
201
+ cursor: pointer;
202
+ animation: ikon-fade-in 0.3s ease-out;
203
+ }
204
+
205
+ .ikon-toast-overlay-chip--warn {
206
+ border-left: 3px solid var(--ikon-status-warning);
207
+ }
208
+
209
+ .ikon-toast-overlay-chip--warn .ikon-toast-overlay-icon {
210
+ color: var(--ikon-status-warning);
211
+ }
212
+
213
+ .ikon-toast-overlay-chip--error {
214
+ border-left: 3px solid var(--ikon-status-error);
215
+ }
216
+
217
+ .ikon-toast-overlay-chip--error .ikon-toast-overlay-icon {
218
+ color: var(--ikon-status-error);
219
+ }
220
+
221
+ .ikon-toast-overlay-icon {
222
+ flex-shrink: 0;
223
+ font-size: 13px;
224
+ line-height: 1;
225
+ }
226
+
227
+ .ikon-toast-overlay-content {
228
+ display: flex;
229
+ align-items: baseline;
230
+ gap: 6px;
231
+ min-width: 0;
232
+ }
233
+
234
+ .ikon-toast-overlay-component {
235
+ flex: none;
236
+ font-family: var(--ikon-font-mono);
237
+ font-size: 11px;
238
+ color: var(--ikon-text-quaternary);
239
+ }
240
+
241
+ .ikon-toast-overlay-message {
242
+ font-size: 13px;
243
+ white-space: pre-wrap;
244
+ word-break: break-word;
245
+ }
246
+ }
@@ -0,0 +1,311 @@
1
+ /* Ikon sign-in screen styles.
2
+
3
+ Override any of this from your own src/auth/auth.css — unlayered rules always win over
4
+ these, whatever their specificity or import order. */
5
+ @layer ikon {
6
+ .ikon-auth-screen {
7
+ display: flex;
8
+ padding: 32px max(20px, env(safe-area-inset-left)) calc(32px + env(safe-area-inset-bottom));
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ .ikon-auth-container {
13
+ position: relative;
14
+ z-index: 1;
15
+ margin: auto;
16
+ box-sizing: border-box;
17
+ display: flex;
18
+ flex-direction: column;
19
+ align-items: stretch;
20
+ width: 100%;
21
+ max-width: 400px;
22
+ padding: 36px 32px;
23
+ background: var(--ikon-bg-card);
24
+ border: 1px solid var(--ikon-border-secondary);
25
+ border-radius: var(--ikon-radius-xl);
26
+ }
27
+
28
+ .ikon-auth-logo {
29
+ align-self: center;
30
+ width: 64px;
31
+ height: 64px;
32
+ margin-bottom: 20px;
33
+ object-fit: contain;
34
+ }
35
+
36
+ .ikon-auth-title {
37
+ margin: 0 0 6px;
38
+ font-family: var(--ikon-font-display);
39
+ font-size: 24px;
40
+ font-weight: 600;
41
+ line-height: 1.25;
42
+ letter-spacing: -0.015em;
43
+ color: var(--ikon-text-primary);
44
+ text-align: center;
45
+ }
46
+
47
+ .ikon-auth-subtitle {
48
+ margin: 0 0 28px;
49
+ font-size: 14px;
50
+ line-height: 1.5;
51
+ color: var(--ikon-text-tertiary);
52
+ text-align: center;
53
+ }
54
+
55
+ .ikon-auth-error {
56
+ box-sizing: border-box;
57
+ width: 100%;
58
+ margin-bottom: 12px;
59
+ padding: 10px 12px;
60
+ background: var(--ikon-error-surface);
61
+ border: 1px solid var(--ikon-error-border);
62
+ border-radius: var(--ikon-radius-md);
63
+ color: var(--ikon-error-text);
64
+ font-size: 13px;
65
+ line-height: 1.45;
66
+ text-align: left;
67
+ }
68
+
69
+ .ikon-auth-buttons {
70
+ display: flex;
71
+ flex-direction: column;
72
+ gap: 8px;
73
+ width: 100%;
74
+ }
75
+
76
+ .ikon-auth-login-button {
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ gap: 10px;
81
+ width: 100%;
82
+ min-height: 44px;
83
+ padding: 0 16px;
84
+ background: var(--ikon-bg-card);
85
+ border: 1px solid var(--ikon-border-primary);
86
+ border-radius: var(--ikon-radius-md);
87
+ color: var(--ikon-text-primary);
88
+ font-family: inherit;
89
+ font-size: 15px;
90
+ font-weight: 500;
91
+ line-height: 1;
92
+ cursor: pointer;
93
+ transition: background-color 0.15s ease, border-color 0.15s ease;
94
+ }
95
+
96
+ .ikon-auth-login-button svg {
97
+ flex: none;
98
+ }
99
+
100
+ .ikon-auth-login-button:hover:not(:disabled) {
101
+ background: var(--ikon-bg-hover);
102
+ }
103
+
104
+ .ikon-auth-login-button:focus-visible {
105
+ outline: 2px solid var(--ikon-focus-ring);
106
+ outline-offset: 2px;
107
+ }
108
+
109
+ .ikon-auth-login-button:disabled {
110
+ cursor: not-allowed;
111
+ opacity: 0.55;
112
+ }
113
+
114
+ .ikon-auth-login-button-guest,
115
+ .ikon-auth-login-button-global {
116
+ background: transparent;
117
+ border-color: transparent;
118
+ color: var(--ikon-text-tertiary);
119
+ }
120
+
121
+ .ikon-auth-login-button-guest:hover:not(:disabled),
122
+ .ikon-auth-login-button-global:hover:not(:disabled) {
123
+ background: var(--ikon-bg-hover);
124
+ color: var(--ikon-text-primary);
125
+ }
126
+
127
+ .ikon-auth-divider {
128
+ display: flex;
129
+ align-items: center;
130
+ gap: 12px;
131
+ width: 100%;
132
+ margin: 20px 0;
133
+ }
134
+
135
+ .ikon-auth-divider::before,
136
+ .ikon-auth-divider::after {
137
+ content: '';
138
+ flex: 1;
139
+ height: 1px;
140
+ background: var(--ikon-border-secondary);
141
+ }
142
+
143
+ .ikon-auth-divider span {
144
+ font-size: 11px;
145
+ font-weight: 600;
146
+ letter-spacing: 0.09em;
147
+ text-transform: uppercase;
148
+ color: var(--ikon-text-quaternary);
149
+ }
150
+
151
+ .ikon-auth-email-form {
152
+ display: flex;
153
+ flex-direction: column;
154
+ gap: 8px;
155
+ width: 100%;
156
+ }
157
+
158
+ .ikon-auth-email-input,
159
+ .ikon-auth-code-input {
160
+ box-sizing: border-box;
161
+ width: 100%;
162
+ min-height: 44px;
163
+ padding: 0 14px;
164
+ background: var(--ikon-bg-card);
165
+ border: 1px solid var(--ikon-border-primary);
166
+ border-radius: var(--ikon-radius-md);
167
+ color: var(--ikon-text-primary);
168
+ font-family: inherit;
169
+ font-size: 16px;
170
+ transition: border-color 0.15s ease;
171
+ }
172
+
173
+ .ikon-auth-email-input::placeholder,
174
+ .ikon-auth-code-input::placeholder {
175
+ color: var(--ikon-text-quaternary);
176
+ }
177
+
178
+ .ikon-auth-email-input:focus-visible,
179
+ .ikon-auth-code-input:focus-visible {
180
+ outline: 2px solid var(--ikon-focus-ring);
181
+ outline-offset: -1px;
182
+ border-color: transparent;
183
+ }
184
+
185
+ .ikon-auth-code-input {
186
+ min-height: 52px;
187
+ font-family: var(--ikon-font-mono);
188
+ font-size: 20px;
189
+ font-weight: 500;
190
+ letter-spacing: 0.3em;
191
+ text-indent: 0.3em;
192
+ text-align: center;
193
+ text-transform: uppercase;
194
+ }
195
+
196
+ .ikon-auth-email-code-hint {
197
+ margin: 0 0 4px;
198
+ font-size: 13px;
199
+ line-height: 1.5;
200
+ color: var(--ikon-text-tertiary);
201
+ text-align: center;
202
+ word-break: break-word;
203
+ }
204
+
205
+ .ikon-auth-email-code-hint strong {
206
+ color: var(--ikon-text-primary);
207
+ font-weight: 500;
208
+ }
209
+
210
+ .ikon-auth-email-button {
211
+ display: flex;
212
+ align-items: center;
213
+ justify-content: center;
214
+ gap: 8px;
215
+ width: 100%;
216
+ min-height: 44px;
217
+ padding: 0 16px;
218
+ background: var(--ikon-bg-solid);
219
+ border: 1px solid transparent;
220
+ border-radius: var(--ikon-radius-md);
221
+ color: var(--ikon-text-on-solid);
222
+ font-family: inherit;
223
+ font-size: 15px;
224
+ font-weight: 500;
225
+ line-height: 1;
226
+ cursor: pointer;
227
+ transition: background-color 0.15s ease;
228
+ }
229
+
230
+ .ikon-auth-email-button:hover:not(:disabled) {
231
+ background: var(--ikon-bg-solid-hover);
232
+ }
233
+
234
+ .ikon-auth-email-button:focus-visible {
235
+ outline: 2px solid var(--ikon-focus-ring);
236
+ outline-offset: 2px;
237
+ }
238
+
239
+ .ikon-auth-email-button:disabled {
240
+ cursor: not-allowed;
241
+ opacity: 0.55;
242
+ }
243
+
244
+ .ikon-auth-email-spinner {
245
+ width: 14px;
246
+ height: 14px;
247
+ border: 2px solid currentColor;
248
+ border-top-color: transparent;
249
+ border-radius: var(--ikon-radius-full);
250
+ opacity: 0.7;
251
+ animation: ikon-spin 0.9s linear infinite;
252
+ }
253
+
254
+ .ikon-auth-email-resend {
255
+ margin-top: 2px;
256
+ padding: 8px;
257
+ background: none;
258
+ border: none;
259
+ border-radius: var(--ikon-radius-md);
260
+ color: var(--ikon-text-tertiary);
261
+ font-family: inherit;
262
+ font-size: 13px;
263
+ cursor: pointer;
264
+ }
265
+
266
+ .ikon-auth-email-resend:hover:not(:disabled) {
267
+ color: var(--ikon-text-primary);
268
+ }
269
+
270
+ .ikon-auth-email-resend:focus-visible {
271
+ outline: 2px solid var(--ikon-focus-ring);
272
+ outline-offset: 2px;
273
+ }
274
+
275
+ .ikon-auth-dismiss {
276
+ margin-top: 16px;
277
+ padding: 8px;
278
+ background: none;
279
+ border: none;
280
+ border-radius: var(--ikon-radius-md);
281
+ color: var(--ikon-text-tertiary);
282
+ font-family: inherit;
283
+ font-size: 13px;
284
+ cursor: pointer;
285
+ }
286
+
287
+ .ikon-auth-dismiss:hover {
288
+ color: var(--ikon-text-primary);
289
+ }
290
+
291
+ .ikon-auth-dismiss:focus-visible {
292
+ outline: 2px solid var(--ikon-focus-ring);
293
+ outline-offset: 2px;
294
+ }
295
+
296
+ @media (max-width: 480px) {
297
+ .ikon-auth-screen {
298
+ padding: 0;
299
+ }
300
+
301
+ .ikon-auth-container {
302
+ max-width: none;
303
+ min-height: 100dvh;
304
+ justify-content: center;
305
+ padding: 32px 24px calc(32px + env(safe-area-inset-bottom));
306
+ background: transparent;
307
+ border: 0;
308
+ border-radius: 0;
309
+ }
310
+ }
311
+ }
@@ -0,0 +1,111 @@
1
+ /* Ikon surface primitives: page background, typography baseline and buttons.
2
+
3
+ Override any of this from your own CSS — every rule here sits in a `@layer ikon` cascade layer,
4
+ and unlayered rules always win. */
5
+ @layer ikon {
6
+ .ikon-surface {
7
+ position: relative;
8
+ min-height: 100dvh;
9
+ margin: 0;
10
+ background-color: var(--ikon-bg-background);
11
+ color: var(--ikon-text-primary);
12
+ font-family: var(--ikon-font-body);
13
+ font-size: 16px;
14
+ line-height: 1.6;
15
+ -webkit-font-smoothing: antialiased;
16
+ -moz-osx-font-smoothing: grayscale;
17
+ text-rendering: optimizeLegibility;
18
+ }
19
+
20
+ /* A fine dot field, faded out by a radial mask. */
21
+ .ikon-surface::before {
22
+ content: '';
23
+ position: fixed;
24
+ inset: 0;
25
+ z-index: 0;
26
+ pointer-events: none;
27
+ background-image: radial-gradient(circle at center, var(--ikon-grid-dot) 1px, transparent 1.5px);
28
+ background-size: 24px 24px;
29
+ -webkit-mask-image: radial-gradient(115% 85% at 50% 0%, #000 0%, transparent 72%);
30
+ mask-image: radial-gradient(115% 85% at 50% 0%, #000 0%, transparent 72%);
31
+ }
32
+
33
+ @media (prefers-reduced-motion: no-preference) {
34
+ .ikon-surface > * {
35
+ animation: ikon-rise 0.32s cubic-bezier(0.2, 0.8, 0.3, 1) both;
36
+ }
37
+ }
38
+
39
+ @keyframes ikon-rise {
40
+ from { opacity: 0; transform: translateY(6px); }
41
+ to { opacity: 1; transform: none; }
42
+ }
43
+
44
+ @keyframes ikon-spin {
45
+ to { transform: rotate(360deg); }
46
+ }
47
+
48
+ .ikon-mark {
49
+ display: block;
50
+ width: 74px;
51
+ height: auto;
52
+ color: var(--ikon-text-primary);
53
+ }
54
+
55
+ .ikon-button {
56
+ display: inline-flex;
57
+ align-items: center;
58
+ justify-content: center;
59
+ gap: 8px;
60
+ min-height: 40px;
61
+ padding: 0 16px;
62
+ border: 1px solid transparent;
63
+ border-radius: var(--ikon-radius-md);
64
+ font-family: inherit;
65
+ font-size: 15px;
66
+ font-weight: 500;
67
+ line-height: 1;
68
+ text-decoration: none;
69
+ cursor: pointer;
70
+ transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
71
+ }
72
+
73
+ .ikon-button:focus-visible {
74
+ outline: 2px solid var(--ikon-focus-ring);
75
+ outline-offset: 2px;
76
+ }
77
+
78
+ .ikon-button--primary {
79
+ background: var(--ikon-bg-solid);
80
+ color: var(--ikon-text-on-solid);
81
+ }
82
+
83
+ .ikon-button--primary:hover:not(:disabled) {
84
+ background: var(--ikon-bg-solid-hover);
85
+ }
86
+
87
+ .ikon-button--secondary {
88
+ background: transparent;
89
+ border-color: var(--ikon-border-primary);
90
+ color: var(--ikon-text-primary);
91
+ }
92
+
93
+ .ikon-button--secondary:hover:not(:disabled) {
94
+ background: var(--ikon-bg-hover);
95
+ }
96
+
97
+ .ikon-button--ghost {
98
+ background: transparent;
99
+ color: var(--ikon-text-tertiary);
100
+ }
101
+
102
+ .ikon-button--ghost:hover:not(:disabled) {
103
+ background: var(--ikon-bg-hover);
104
+ color: var(--ikon-text-primary);
105
+ }
106
+
107
+ .ikon-button:disabled {
108
+ cursor: not-allowed;
109
+ opacity: 0.55;
110
+ }
111
+ }