@octane-xplat/ui 0.3.0 → 0.4.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 (123) hide show
  1. package/README.md +46 -0
  2. package/dist/native/octane-client-build.json +1 -1
  3. package/dist/native/ui.js +52 -40
  4. package/dist/native/ui10.js +20 -11
  5. package/dist/native/ui11.js +42 -109
  6. package/dist/native/ui12.js +17 -84
  7. package/dist/native/ui13.js +11 -41
  8. package/dist/native/ui14.js +118 -76
  9. package/dist/native/ui15.js +43 -92
  10. package/dist/native/ui16.js +106 -45
  11. package/dist/native/ui17.js +29 -42
  12. package/dist/native/ui18.js +34 -53
  13. package/dist/native/ui19.js +246 -32
  14. package/dist/native/ui20.js +27 -16
  15. package/dist/native/ui21.js +376 -86
  16. package/dist/native/ui22.js +26 -114
  17. package/dist/native/ui23.js +49 -97
  18. package/dist/native/ui24.js +78 -53
  19. package/dist/native/ui25.js +138 -16
  20. package/dist/native/ui26.js +8 -23
  21. package/dist/native/ui27.js +60 -34
  22. package/dist/native/ui28.js +36 -142
  23. package/dist/native/ui29.js +101 -21
  24. package/dist/native/ui30.js +14 -31
  25. package/dist/native/ui31.js +55 -36
  26. package/dist/native/ui32.js +49 -61
  27. package/dist/native/ui33.js +36 -28
  28. package/dist/native/ui34.js +51 -8
  29. package/dist/native/ui35.js +98 -20
  30. package/dist/native/ui36.js +9 -33
  31. package/dist/native/ui37.js +42 -15
  32. package/dist/native/ui38.js +186 -57
  33. package/dist/native/ui39.js +96 -24
  34. package/dist/native/ui4.js +22 -20
  35. package/dist/native/ui40.js +57 -13
  36. package/dist/native/ui41.js +15 -100
  37. package/dist/native/ui42.js +6 -146
  38. package/dist/native/ui43.js +37 -21
  39. package/dist/native/ui44.js +265 -6
  40. package/dist/native/ui45.js +28 -0
  41. package/dist/native/ui46.js +35 -0
  42. package/dist/native/ui47.js +41 -0
  43. package/dist/native/ui48.js +72 -0
  44. package/dist/native/ui49.js +66 -0
  45. package/dist/native/ui5.js +37 -77
  46. package/dist/native/ui50.js +27 -0
  47. package/dist/native/ui51.js +13 -0
  48. package/dist/native/ui52.js +92 -0
  49. package/dist/native/ui53.js +34 -0
  50. package/dist/native/ui54.js +17 -0
  51. package/dist/native/ui55.js +156 -0
  52. package/dist/native/ui56.js +33 -0
  53. package/dist/native/ui57.js +14 -0
  54. package/dist/native/ui58.js +22 -0
  55. package/dist/native/ui59.js +8 -0
  56. package/dist/native/ui6.js +52 -9
  57. package/dist/native/ui60.js +108 -0
  58. package/dist/native/ui61.js +76 -0
  59. package/dist/native/ui7.js +42 -26
  60. package/dist/native/ui8.js +22 -12
  61. package/dist/native/ui9.js +18 -9
  62. package/dist/web/octane-client-build.json +1 -1
  63. package/dist/web/ui.js +51 -40
  64. package/dist/web/ui10.js +33 -186
  65. package/dist/web/ui11.js +28 -409
  66. package/dist/web/ui12.js +21 -68
  67. package/dist/web/ui13.js +201 -97
  68. package/dist/web/ui14.js +85 -95
  69. package/dist/web/ui15.js +368 -25
  70. package/dist/web/ui16.js +13 -101
  71. package/dist/web/ui17.js +246 -42
  72. package/dist/web/ui18.js +237 -28
  73. package/dist/web/ui19.js +36 -10
  74. package/dist/web/ui20.js +73 -102
  75. package/dist/web/ui21.js +102 -73
  76. package/dist/web/ui22.js +95 -55
  77. package/dist/web/ui23.js +94 -55
  78. package/dist/web/ui24.js +31 -15
  79. package/dist/web/ui25.js +105 -19
  80. package/dist/web/ui26.js +29 -23
  81. package/dist/web/ui27.js +12 -123
  82. package/dist/web/ui28.js +9 -110
  83. package/dist/web/ui29.js +52 -102
  84. package/dist/web/ui3.js +29 -18
  85. package/dist/web/ui30.js +32 -41
  86. package/dist/web/ui31.js +120 -39
  87. package/dist/web/ui32.js +41 -74
  88. package/dist/web/ui33.js +148 -32
  89. package/dist/web/ui34.js +54 -51
  90. package/dist/web/ui35.js +55 -7
  91. package/dist/web/ui36.js +18 -41
  92. package/dist/web/ui37.js +6 -46
  93. package/dist/web/ui38.js +37 -16
  94. package/dist/web/ui39.js +135 -81
  95. package/dist/web/ui4.js +46 -152
  96. package/dist/web/ui40.js +39 -37
  97. package/dist/web/ui41.js +41 -16
  98. package/dist/web/ui42.js +74 -7
  99. package/dist/web/ui43.js +40 -20
  100. package/dist/web/ui44.js +60 -6
  101. package/dist/web/ui45.js +9 -0
  102. package/dist/web/ui46.js +45 -0
  103. package/dist/web/ui47.js +13 -0
  104. package/dist/web/ui48.js +63 -0
  105. package/dist/web/ui49.js +47 -0
  106. package/dist/web/ui5.js +131 -27
  107. package/dist/web/ui50.js +17 -0
  108. package/dist/web/ui51.js +149 -0
  109. package/dist/web/ui52.js +42 -0
  110. package/dist/web/ui53.js +17 -0
  111. package/dist/web/ui54.js +9 -0
  112. package/dist/web/ui55.js +22 -0
  113. package/dist/web/ui56.js +8 -0
  114. package/dist/web/ui57.js +44 -0
  115. package/dist/web/ui58.js +46 -0
  116. package/dist/web/ui6.js +81 -45
  117. package/dist/web/ui7.js +43 -21
  118. package/dist/web/ui8.js +27 -21
  119. package/dist/web/ui9.js +29 -18
  120. package/package.json +13 -4
  121. package/src/theme/tokens.css +369 -138
  122. package/types/index.d.ts +102 -58
  123. package/types/props.d.ts +233 -13
@@ -3,274 +3,505 @@
3
3
 
4
4
  :root,
5
5
  .ns-root {
6
- --color-primary: #4f46e5;
7
- --color-on-primary: #ffffff;
8
- --color-surface: #ffffff;
9
- --color-text: #111827;
10
- --space-4: 16px;
6
+ --color-primary: #4f46e5;
7
+ --color-on-primary: #ffffff;
8
+ --color-surface: #ffffff;
9
+ --color-text: #111827;
10
+ --space-4: 16px;
11
+ /* Corner scale — rounded-rectangle radii. Smooth (squircle) corners are
12
+ the default corner treatment: every class that consumes a token also
13
+ declares `corner-shape: squircle`. Full-radius circles opt out —
14
+ `corner-shape` would reshape them into squircle disks on iOS/Chromium. */
15
+ --radius-sm: 6px;
16
+ --radius-md: 8px;
17
+ --radius-lg: 12px;
18
+ --radius-xl: 16px;
11
19
  }
12
20
 
13
21
  .ns-dark,
14
22
  .dark {
15
- --color-surface: #0f172a;
16
- --color-text: #f8fafc;
23
+ --color-surface: #0f172a;
24
+ --color-text: #f8fafc;
17
25
  }
18
26
 
19
27
  /* vocabulary base styles */
20
28
 
21
29
  .vx-view,
22
30
  .vx-row {
23
- display: flex;
31
+ display: flex;
24
32
  }
25
33
 
26
34
  .vx-view {
27
- flex-direction: column;
35
+ flex-direction: column;
28
36
  }
29
37
 
30
38
  /* Safe-area values are zero when the viewport has no display cutout. */
31
39
  .vx-safe-area {
32
- padding-top: constant(safe-area-inset-top);
33
- padding-right: constant(safe-area-inset-right);
34
- padding-bottom: constant(safe-area-inset-bottom);
35
- padding-left: constant(safe-area-inset-left);
40
+ padding-top: constant(safe-area-inset-top);
41
+ padding-right: constant(safe-area-inset-right);
42
+ padding-bottom: constant(safe-area-inset-bottom);
43
+ padding-left: constant(safe-area-inset-left);
36
44
  }
37
45
 
38
46
  .vx-safe-area {
39
- padding-top: env(safe-area-inset-top);
40
- padding-right: env(safe-area-inset-right);
41
- padding-bottom: env(safe-area-inset-bottom);
42
- padding-left: env(safe-area-inset-left);
47
+ padding-top: env(safe-area-inset-top);
48
+ padding-right: env(safe-area-inset-right);
49
+ padding-bottom: env(safe-area-inset-bottom);
50
+ padding-left: env(safe-area-inset-left);
51
+ }
52
+
53
+ .vx-keyboard-avoiding {
54
+ display: flex;
55
+ flex-direction: column;
56
+ }
57
+ /* xplat-web-only:start — the native Drawer leaf is the ui-drawer widget;
58
+ these rules style the web DOM drawer overlay */
59
+ .vx-drawer {
60
+ display: flex;
61
+ flex-direction: row;
62
+ position: relative;
63
+ overflow: hidden;
64
+ }
65
+ .vx-drawer-main {
66
+ display: flex;
67
+ flex: 1;
68
+ min-width: 0;
69
+ }
70
+ .vx-drawer-backdrop {
71
+ position: absolute;
72
+ inset: 0;
73
+ background: rgba(15, 23, 42, 0.35);
43
74
  }
44
-
45
- .vx-keyboard-avoiding { display: flex; flex-direction: column; }
46
- .vx-drawer { display: flex; flex-direction: row; position: relative; overflow: hidden; }
47
- .vx-drawer-main { display: flex; flex: 1; min-width: 0; }
48
- .vx-drawer-backdrop { position: absolute; inset: 0; background: rgba(15, 23, 42, 0.35); }
49
75
  .vx-drawer-panel {
50
- position: absolute;
51
- z-index: 1;
52
- top: 0;
53
- bottom: 0;
54
- left: 0;
55
- width: 280px;
56
- overflow: auto;
57
- background: var(--color-surface);
58
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
59
- }
76
+ position: absolute;
77
+ z-index: 1;
78
+ top: 0;
79
+ bottom: 0;
80
+ left: 0;
81
+ width: 280px;
82
+ overflow: auto;
83
+ background: var(--color-surface);
84
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
85
+ }
86
+ /* xplat-web-only:end */
60
87
 
61
88
  .vx-row {
62
- flex-direction: row;
89
+ flex-direction: row;
63
90
  }
64
91
 
65
92
  .vx-grid,
66
93
  .vx-stack {
67
- display: grid;
94
+ display: grid;
68
95
  }
69
96
 
70
97
  .vx-stack > * {
71
- grid-area: 1 / 1;
98
+ grid-area: 1 / 1;
72
99
  }
73
100
 
101
+ /* xplat-web-only:start — Absolute's native leaf is absolutelayout; CSS
102
+ positioning is web-only (children position via left/top props) */
74
103
  .vx-absolute {
75
- position: relative;
104
+ position: relative;
76
105
  }
77
106
 
78
107
  .vx-absolute > * {
79
- position: absolute;
108
+ position: absolute;
80
109
  }
110
+ /* xplat-web-only:end */
81
111
 
82
112
  .vx-spacer {
83
- flex-grow: 1;
113
+ flex-grow: 1;
84
114
  }
85
115
 
86
116
  .vx-pressable {
87
- display: flex;
88
- flex-direction: column;
89
- user-select: none;
117
+ display: flex;
118
+ flex-direction: column;
119
+ user-select: none;
90
120
  }
91
121
 
92
122
  /* web press feedback */
93
123
  .vx-pressable:active {
94
- opacity: 0.85;
124
+ opacity: 0.85;
95
125
  }
96
126
  .vx-pressable-no-feedback:active {
97
- opacity: 1;
127
+ opacity: 1;
98
128
  }
99
129
  /* native press feedback (NS pseudo — dead rule on web, and vice versa) */
100
130
  .vx-pressable:pressed {
101
- opacity: 0.85;
131
+ opacity: 0.85;
102
132
  }
103
133
 
134
+ /* xplat-web-only:start — overlays/toasts/popovers render through RootLayout
135
+ or showModal on native; these portal/positioning rules are web-only */
104
136
  .vx-overlay {
105
- z-index: 1000;
137
+ z-index: 1000;
106
138
  }
107
139
 
108
140
  .vx-overlay-shade {
109
- position: absolute;
110
- inset: 0;
111
- background-color: rgba(0, 0, 0, 0.45);
141
+ position: absolute;
142
+ inset: 0;
143
+ background-color: rgba(0, 0, 0, 0.45);
112
144
  }
113
145
 
114
146
  .vx-overlay-content {
115
- position: relative;
116
- z-index: 1;
147
+ position: relative;
148
+ z-index: 1;
117
149
  }
118
150
 
119
151
  .vx-popover {
120
- z-index: 1001;
152
+ z-index: 1001;
153
+ }
154
+
155
+ .vx-popover-backdrop {
156
+ background-color: transparent;
121
157
  }
122
158
 
123
159
  .vx-toast-host {
124
- position: fixed;
125
- z-index: 1002;
126
- left: 0;
127
- right: 0;
128
- display: flex;
129
- justify-content: center;
130
- pointer-events: none;
160
+ position: fixed;
161
+ z-index: 1002;
162
+ left: 0;
163
+ right: 0;
164
+ display: flex;
165
+ justify-content: center;
166
+ pointer-events: none;
131
167
  }
132
168
 
133
- .vx-toast-top { top: 24px; }
134
- .vx-toast-bottom { bottom: 24px; }
169
+ .vx-toast-top {
170
+ top: 24px;
171
+ }
172
+ .vx-toast-bottom {
173
+ bottom: 24px;
174
+ }
135
175
 
136
176
  .vx-toast {
137
- pointer-events: auto;
177
+ pointer-events: auto;
138
178
  }
179
+ /* xplat-web-only:end */
139
180
 
140
181
  /* auto-grow owns height — the manual resize handle has no native analog */
182
+ /* xplat-web-only:start */
141
183
  .vx-textarea {
142
- resize: none;
184
+ resize: none;
143
185
  }
186
+ /* xplat-web-only:end */
144
187
 
145
188
  /* Modal is a real top-layer dialog on web. Presentation variants keep their
146
189
  sizing and anchoring in tokens so both the component and openModal share it. */
190
+ /* xplat-web-only:start */
147
191
  .vx-modal {
148
- width: 480px;
149
- max-width: 90%;
150
- max-height: 90%;
151
- padding: 24px;
152
- border: 0;
153
- border-radius: 16px;
154
- color: var(--color-text);
155
- background-color: var(--color-surface);
192
+ width: 480px;
193
+ max-width: 90%;
194
+ max-height: 90%;
195
+ padding: 24px;
196
+ border: 0;
197
+ border-radius: var(--radius-xl);
198
+ corner-shape: squircle;
199
+ color: var(--color-text);
200
+ background-color: var(--color-surface);
156
201
  }
157
202
 
158
203
  .vx-modal::backdrop {
159
- background: rgba(15, 23, 42, 0.45);
204
+ background: rgba(15, 23, 42, 0.45);
160
205
  }
161
206
 
162
207
  .vx-modal--dialog {
163
- width: 480px;
164
- max-width: 90%;
208
+ width: 480px;
209
+ max-width: 90%;
165
210
  }
166
211
 
167
212
  .vx-modal--sheet {
168
- width: 100%;
169
- max-width: none;
170
- max-height: 85%;
171
- position: fixed;
172
- inset: auto 0 0;
173
- margin: 0;
174
- border-radius: 16px 16px 0 0;
213
+ width: 100%;
214
+ max-width: none;
215
+ max-height: 85%;
216
+ position: fixed;
217
+ inset: auto 0 0;
218
+ margin: 0;
219
+ border-top-left-radius: var(--radius-xl);
220
+ border-top-right-radius: var(--radius-xl);
221
+ corner-shape: squircle;
175
222
  }
176
223
 
177
224
  .vx-modal--fullscreen {
178
- width: 100%;
179
- max-width: none;
180
- height: 100%;
181
- max-height: none;
182
- margin: 0;
183
- border-radius: 0;
184
- }
185
-
225
+ width: 100%;
226
+ max-width: none;
227
+ height: 100%;
228
+ max-height: none;
229
+ margin: 0;
230
+ border-radius: 0;
231
+ }
232
+
233
+ /* Modal ROUTES (pushRoute presentation:'modal') — the URL stays underneath,
234
+ so the overlay is a fixed layer over the shell rather than a dialog. */
235
+ .vx-modalroute {
236
+ position: fixed;
237
+ inset: 0;
238
+ z-index: 1000;
239
+ display: flex;
240
+ align-items: stretch;
241
+ justify-content: stretch;
242
+ }
243
+
244
+ .vx-modalroute-shade {
245
+ position: absolute;
246
+ inset: 0;
247
+ border: 0;
248
+ padding: 0;
249
+ background: rgba(15, 23, 42, 0.45);
250
+ cursor: default;
251
+ }
252
+
253
+ .vx-modalroute-body {
254
+ position: relative;
255
+ flex: 1;
256
+ min-width: 0;
257
+ overflow: auto;
258
+ color: var(--color-text);
259
+ background-color: var(--color-surface);
260
+ }
261
+ /* xplat-web-only:end */
262
+
263
+ /* xplat-web-only:start — placeholder pseudos are DOM-only */
186
264
  input::placeholder,
187
265
  textarea::placeholder {
188
- color: var(--placeholder-color, currentColor);
266
+ color: var(--placeholder-color, currentColor);
189
267
  }
268
+ /* xplat-web-only:end */
190
269
 
270
+ /* xplat-web-only:start — native ActivityIndicator is the NS widget */
191
271
  .vx-spinner {
192
- display: inline-block;
193
- width: 1em;
194
- height: 1em;
195
- box-sizing: border-box;
196
- border: 2px solid currentColor;
197
- border-right-color: transparent;
198
- border-radius: 50%;
199
- animation: vx-spinner-turn 0.8s linear infinite;
272
+ display: inline-block;
273
+ width: 1em;
274
+ height: 1em;
275
+ box-sizing: border-box;
276
+ border: 2px solid currentColor;
277
+ border-right-color: transparent;
278
+ border-radius: 50%;
279
+ animation: vx-spinner-turn 0.8s linear infinite;
200
280
  }
201
281
 
202
282
  @keyframes vx-spinner-turn {
203
- to { transform: rotate(360deg); }
283
+ to {
284
+ transform: rotate(360deg);
285
+ }
204
286
  }
287
+ /* xplat-web-only:end */
205
288
 
206
- .vx-h1 { font-size: 2em; font-weight: bold; }
207
- .vx-h2 { font-size: 1.5em; font-weight: bold; }
208
- .vx-h3 { font-size: 1.17em; font-weight: bold; }
209
- .vx-h4 { font-size: 1em; font-weight: bold; }
210
- .vx-h5 { font-size: 0.83em; font-weight: bold; }
211
- .vx-h6 { font-size: 0.67em; font-weight: bold; }
289
+ .vx-h1 {
290
+ font-size: 2em;
291
+ font-weight: bold;
292
+ }
293
+ .vx-h2 {
294
+ font-size: 1.5em;
295
+ font-weight: bold;
296
+ }
297
+ .vx-h3 {
298
+ font-size: 1.17em;
299
+ font-weight: bold;
300
+ }
301
+ .vx-h4 {
302
+ font-size: 1em;
303
+ font-weight: bold;
304
+ }
305
+ .vx-h5 {
306
+ font-size: 0.83em;
307
+ font-weight: bold;
308
+ }
309
+ .vx-h6 {
310
+ font-size: 0.67em;
311
+ font-weight: bold;
312
+ }
313
+
314
+ /* xplat-web-only:start — glass material is real on iOS 26+; web approximates
315
+ with backdrop-filter. The class also lands on native elements (inert) so
316
+ apps can style their own fallback — but these rules are DOM-only. */
317
+ .vx-glass {
318
+ background-color: color-mix(in srgb, var(--color-surface) 30%, transparent);
319
+ border: 1px solid rgba(255, 255, 255, 0.25);
320
+ }
321
+
322
+ @supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
323
+ .vx-glass {
324
+ background-color: color-mix(in srgb, var(--color-surface) 20%, transparent);
325
+ -webkit-backdrop-filter: blur(20px) saturate(1.6);
326
+ backdrop-filter: blur(20px) saturate(1.6);
327
+ }
328
+ }
329
+
330
+ .vx-glass--clear {
331
+ background-color: color-mix(in srgb, var(--color-surface) 12%, transparent);
332
+ border-color: rgba(255, 255, 255, 0.15);
333
+ }
334
+
335
+ @supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
336
+ .vx-glass--clear {
337
+ -webkit-backdrop-filter: blur(8px) saturate(1.3);
338
+ backdrop-filter: blur(8px) saturate(1.3);
339
+ }
340
+ }
341
+ /* xplat-web-only:end */
212
342
 
213
343
  /* utilities (hand-written subset for the harness; Tailwind later) */
214
344
 
215
- .flex-1 { flex-grow: 1; }
216
- .items-center { align-items: center; }
217
- .justify-center { justify-content: center; }
218
- .gap-4 { gap: 16px; }
345
+ .flex-1 {
346
+ flex-grow: 1;
347
+ }
348
+ /* Flex divergence guards — NS FlexboxLayout diverges from web flexbox on
349
+ * shrinkability: grow children never shrink below intrinsic width, fixed
350
+ * children get crushed, and auto-height rows re-measure grow children at
351
+ * zero height. min-w-0/min-h-0 let a grow child shrink; shrink-0 protects
352
+ * a fixed-size child. All three are plain CSS on web. */
353
+ .min-w-0 {
354
+ min-width: 0;
355
+ }
356
+ .min-h-0 {
357
+ min-height: 0;
358
+ }
359
+ .shrink-0 {
360
+ flex-shrink: 0;
361
+ }
362
+ .grow {
363
+ flex-grow: 1;
364
+ }
365
+ .items-center {
366
+ align-items: center;
367
+ }
368
+ .justify-center {
369
+ justify-content: center;
370
+ }
371
+ .gap-4 {
372
+ gap: 16px;
373
+ }
374
+
375
+ .text-xl {
376
+ font-size: 20px;
377
+ }
378
+ .font-bold {
379
+ font-weight: bold;
380
+ }
219
381
 
220
- .text-xl { font-size: 20px; }
221
- .font-bold { font-weight: bold; }
382
+ /* Corner utilities — consume the --radius-* scale and carry the smooth
383
+ (squircle) corner treatment. Circles stay circular: .rounded-full omits
384
+ corner-shape deliberately (squircle at full radius = a squircle disk,
385
+ not a circle). Opt out per element with `corner-shape: round`. */
386
+ .rounded-sm {
387
+ border-radius: var(--radius-sm);
388
+ corner-shape: squircle;
389
+ }
390
+ .rounded-md {
391
+ border-radius: var(--radius-md);
392
+ corner-shape: squircle;
393
+ }
394
+ .rounded-lg {
395
+ border-radius: var(--radius-lg);
396
+ corner-shape: squircle;
397
+ }
398
+ .rounded-xl {
399
+ border-radius: var(--radius-xl);
400
+ corner-shape: squircle;
401
+ }
402
+ .rounded-full {
403
+ border-radius: 9999px;
404
+ }
222
405
 
223
- .bg-primary { background-color: var(--color-primary); }
224
- .text-onprimary { color: var(--color-on-primary); }
225
- .bg-danger { background-color: #dc2626; }
226
- .shadow-2 { box-shadow: 0 4px 12px rgba(0,0,0,0.25); }
406
+ .bg-primary {
407
+ background-color: var(--color-primary);
408
+ }
409
+ .text-onprimary {
410
+ color: var(--color-on-primary);
411
+ }
412
+ .bg-danger {
413
+ background-color: #dc2626;
414
+ }
415
+ /* xplat-web-only:start — box-shadow is inert on native (elevation is
416
+ Android-only; no shared mapping yet) */
417
+ .shadow-2 {
418
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
419
+ }
420
+ /* xplat-web-only:end */
227
421
 
228
422
  .btn {
229
- padding-top: 12px;
230
- padding-right: 20px;
231
- padding-bottom: 12px;
232
- padding-left: 20px;
233
- border-radius: 8px;
423
+ padding-top: 12px;
424
+ padding-right: 20px;
425
+ padding-bottom: 12px;
426
+ padding-left: 20px;
427
+ border-radius: var(--radius-md);
428
+ corner-shape: squircle;
234
429
  }
235
430
 
236
431
  /* harness experiment styles */
237
432
 
238
433
  .vx-app {
239
- padding: 24px;
240
- background-color: var(--color-surface);
241
- color: var(--color-text);
434
+ padding: 24px;
435
+ background-color: var(--color-surface);
436
+ color: var(--color-text);
242
437
  }
243
438
 
244
439
  .vx-app .text-xl,
245
440
  .vx-app Text,
246
441
  .vx-app label {
247
- color: var(--color-text);
442
+ color: var(--color-text);
248
443
  }
249
444
 
250
445
  .input {
251
- padding: 10px;
252
- border-width: 1px;
253
- border-color: #94a3b8;
254
- border-radius: 6px;
255
- font-size: 16px;
446
+ padding: 10px;
447
+ border-width: 1px;
448
+ border-color: #94a3b8;
449
+ border-radius: var(--radius-sm);
450
+ corner-shape: squircle;
451
+ font-size: 16px;
256
452
  }
257
453
 
258
454
  .chip {
259
- background-color: var(--color-primary);
260
- color: var(--color-on-primary);
261
- padding: 4px 10px;
262
- border-radius: 12px;
263
- font-size: 13px;
455
+ background-color: var(--color-primary);
456
+ color: var(--color-on-primary);
457
+ padding: 4px 10px;
458
+ border-radius: var(--radius-lg);
459
+ corner-shape: squircle;
460
+ font-size: 13px;
264
461
  }
265
462
 
266
463
  .cell {
267
- padding: 12px;
268
- border-bottom-width: 1px;
269
- border-bottom-color: #e2e8f0;
464
+ padding: 12px;
465
+ border-bottom-width: 1px;
466
+ border-bottom-color: #e2e8f0;
270
467
  }
271
468
 
272
469
  .vx-list {
273
- flex-grow: 1;
470
+ flex-grow: 1;
471
+ }
472
+
473
+ .gap-2 {
474
+ gap: 8px;
475
+ }
476
+
477
+ /* In-window sheet — bottom-anchored panel (matches the native RootLayout
478
+ sheet). Layer is pointer-events:none; backdrop + panel re-enable. */
479
+ .vx-sheet-layer {
480
+ position: fixed;
481
+ inset: 0;
482
+ z-index: 1100;
483
+ pointer-events: none;
274
484
  }
275
485
 
276
- .gap-2 { gap: 8px; }
486
+ .vx-sheet-backdrop {
487
+ position: absolute;
488
+ inset: 0;
489
+ background: rgba(15, 23, 42, 0.45);
490
+ pointer-events: auto;
491
+ }
492
+
493
+ .vx-sheet {
494
+ position: absolute;
495
+ left: 0;
496
+ right: 0;
497
+ bottom: 0;
498
+ max-height: 85%;
499
+ padding: 24px;
500
+ overflow: auto;
501
+ border-top-left-radius: var(--radius-xl);
502
+ border-top-right-radius: var(--radius-xl);
503
+ corner-shape: squircle;
504
+ background-color: var(--color-surface);
505
+ color: var(--color-text);
506
+ pointer-events: auto;
507
+ }