@fangxinyan/lumina 0.1.5 → 0.2.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 (220) hide show
  1. package/dist/{Accordion-GSBY5T5U.css → Accordion-3TQPKNN3.css} +8 -1
  2. package/dist/Accordion.cjs +2 -2
  3. package/dist/Accordion.d.cts +12 -0
  4. package/dist/Accordion.d.ts +12 -0
  5. package/dist/Accordion.js +1 -1
  6. package/dist/{Alert-LSKBYDRI.css → Alert-JJ7GB3UU.css} +11 -0
  7. package/dist/Alert.cjs +2 -2
  8. package/dist/Alert.d.cts +4 -0
  9. package/dist/Alert.d.ts +4 -0
  10. package/dist/Alert.js +1 -1
  11. package/dist/{Avatar-OXDSG5Q6.css → Avatar-R5A4AFKZ.css} +4 -0
  12. package/dist/Avatar.cjs +2 -2
  13. package/dist/Avatar.d.cts +2 -0
  14. package/dist/Avatar.d.ts +2 -0
  15. package/dist/Avatar.js +1 -1
  16. package/dist/{Button-5UI7QXGU.css → Button-SDQD25AG.css} +2 -0
  17. package/dist/Button.cjs +3 -3
  18. package/dist/Button.d.cts +2 -0
  19. package/dist/Button.d.ts +2 -0
  20. package/dist/Button.js +1 -1
  21. package/dist/Calendar.cjs +2 -2
  22. package/dist/Calendar.d.cts +8 -0
  23. package/dist/Calendar.d.ts +8 -0
  24. package/dist/Calendar.js +1 -1
  25. package/dist/{Card-2CHHFD4Y.css → Card-RG7ECXL2.css} +11 -0
  26. package/dist/Card.cjs +3 -3
  27. package/dist/Card.d.cts +2 -0
  28. package/dist/Card.d.ts +2 -0
  29. package/dist/Card.js +1 -1
  30. package/dist/{Divider-Z37INS5E.css → Divider-OEE4Q2KS.css} +31 -0
  31. package/dist/Divider.cjs +2 -2
  32. package/dist/Divider.d.cts +7 -0
  33. package/dist/Divider.d.ts +7 -0
  34. package/dist/Divider.js +1 -1
  35. package/dist/Drawer-IPGB4CXH.css +101 -0
  36. package/dist/Drawer.cjs +13 -0
  37. package/dist/Drawer.cjs.map +1 -0
  38. package/dist/Drawer.d.cts +45 -0
  39. package/dist/Drawer.d.ts +45 -0
  40. package/dist/Drawer.js +4 -0
  41. package/dist/Drawer.js.map +1 -0
  42. package/dist/{Empty-VM23UNLQ.css → Empty-NQ72W3D7.css} +22 -0
  43. package/dist/Empty.cjs +4 -4
  44. package/dist/Empty.d.cts +42 -2
  45. package/dist/Empty.d.ts +42 -2
  46. package/dist/Empty.js +1 -1
  47. package/dist/Input-33CAH4O6.css +134 -0
  48. package/dist/Input.cjs +3 -3
  49. package/dist/Input.d.cts +17 -1
  50. package/dist/Input.d.ts +17 -1
  51. package/dist/Input.js +1 -1
  52. package/dist/Modal-N4YVLEWW.css +72 -0
  53. package/dist/Modal.cjs +3 -7
  54. package/dist/Modal.d.cts +37 -8
  55. package/dist/Modal.d.ts +37 -8
  56. package/dist/Modal.js +2 -2
  57. package/dist/{Pagination-6FFOI4NM.css → Pagination-YIRYJUXP.css} +33 -0
  58. package/dist/Pagination.cjs +5 -2
  59. package/dist/Pagination.d.cts +14 -0
  60. package/dist/Pagination.d.ts +14 -0
  61. package/dist/Pagination.js +4 -1
  62. package/dist/Select.cjs +3 -3
  63. package/dist/Select.js +2 -2
  64. package/dist/{Slider-RE4HZQKF.css → Slider-X4PVA65R.css} +51 -2
  65. package/dist/Slider.cjs +2 -2
  66. package/dist/Slider.d.cts +20 -5
  67. package/dist/Slider.d.ts +20 -5
  68. package/dist/Slider.js +1 -1
  69. package/dist/Switch-36KJNDXM.css +92 -0
  70. package/dist/Switch.cjs +2 -2
  71. package/dist/Switch.d.cts +4 -0
  72. package/dist/Switch.d.ts +4 -0
  73. package/dist/Switch.js +1 -1
  74. package/dist/Table-ADVN6LXP.css +295 -0
  75. package/dist/Table.cjs +7 -3
  76. package/dist/Table.d.cts +103 -7
  77. package/dist/Table.d.ts +103 -7
  78. package/dist/Table.js +5 -1
  79. package/dist/{Tabs-A27TSZOP.css → Tabs-RHK6XAFF.css} +7 -0
  80. package/dist/Tabs.cjs +3 -3
  81. package/dist/Tabs.d.cts +2 -0
  82. package/dist/Tabs.d.ts +2 -0
  83. package/dist/Tabs.js +1 -1
  84. package/dist/{Tag-EYOY3UWG.css → Tag-FGDY3W7E.css} +2 -0
  85. package/dist/Tag.cjs +3 -3
  86. package/dist/Tag.d.cts +5 -0
  87. package/dist/Tag.d.ts +5 -0
  88. package/dist/Tag.js +1 -1
  89. package/dist/chunk-437LB2V4.js +111 -0
  90. package/dist/chunk-437LB2V4.js.map +1 -0
  91. package/dist/chunk-4MR4GVTD.js +73 -0
  92. package/dist/chunk-4MR4GVTD.js.map +1 -0
  93. package/dist/{chunk-OXYFB2ZI.js → chunk-4U4OY5RA.js} +11 -5
  94. package/dist/chunk-4U4OY5RA.js.map +1 -0
  95. package/dist/chunk-55NTFU7Y.js +476 -0
  96. package/dist/chunk-55NTFU7Y.js.map +1 -0
  97. package/dist/{chunk-5EYI27B6.js → chunk-77BVQNAQ.js} +5 -3
  98. package/dist/chunk-77BVQNAQ.js.map +1 -0
  99. package/dist/chunk-AEJJGUEN.cjs +127 -0
  100. package/dist/chunk-AEJJGUEN.cjs.map +1 -0
  101. package/dist/{chunk-3QWHDCHJ.js → chunk-AJZKESHB.js} +13 -4
  102. package/dist/chunk-AJZKESHB.js.map +1 -0
  103. package/dist/{chunk-NZPJ7BUB.cjs → chunk-AXMEZGEG.cjs} +13 -4
  104. package/dist/chunk-AXMEZGEG.cjs.map +1 -0
  105. package/dist/{chunk-HTP6UEVR.js → chunk-BBPNQ44M.js} +22 -6
  106. package/dist/chunk-BBPNQ44M.js.map +1 -0
  107. package/dist/chunk-CCBHZYE6.cjs +150 -0
  108. package/dist/chunk-CCBHZYE6.cjs.map +1 -0
  109. package/dist/{chunk-KGYLUZOU.cjs → chunk-EPFYIR63.cjs} +5 -5
  110. package/dist/{chunk-KGYLUZOU.cjs.map → chunk-EPFYIR63.cjs.map} +1 -1
  111. package/dist/chunk-F7HW2PYR.cjs +119 -0
  112. package/dist/chunk-F7HW2PYR.cjs.map +1 -0
  113. package/dist/chunk-GIVMKGZN.js +39 -0
  114. package/dist/chunk-GIVMKGZN.js.map +1 -0
  115. package/dist/{chunk-FMG3ZPGK.js → chunk-H6FCIJOP.js} +5 -3
  116. package/dist/chunk-H6FCIJOP.js.map +1 -0
  117. package/dist/{chunk-ALFDP5WX.cjs → chunk-IDM6JJLP.cjs} +22 -6
  118. package/dist/chunk-IDM6JJLP.cjs.map +1 -0
  119. package/dist/chunk-IFERLHCL.cjs +499 -0
  120. package/dist/chunk-IFERLHCL.cjs.map +1 -0
  121. package/dist/chunk-IWVKITPN.js +102 -0
  122. package/dist/chunk-IWVKITPN.js.map +1 -0
  123. package/dist/{chunk-I2ERCHFV.cjs → chunk-JKLQOB2F.cjs} +11 -5
  124. package/dist/chunk-JKLQOB2F.cjs.map +1 -0
  125. package/dist/{chunk-IGHLSNXT.cjs → chunk-K7PVJLW4.cjs} +51 -4
  126. package/dist/chunk-K7PVJLW4.cjs.map +1 -0
  127. package/dist/chunk-LDENBYRC.cjs +210 -0
  128. package/dist/chunk-LDENBYRC.cjs.map +1 -0
  129. package/dist/chunk-LSLYY5FN.js +125 -0
  130. package/dist/chunk-LSLYY5FN.js.map +1 -0
  131. package/dist/chunk-NSUD5B22.js +187 -0
  132. package/dist/chunk-NSUD5B22.js.map +1 -0
  133. package/dist/{chunk-AAMYURWQ.cjs → chunk-OPTTHURA.cjs} +5 -3
  134. package/dist/chunk-OPTTHURA.cjs.map +1 -0
  135. package/dist/{chunk-F3NHM4GX.js → chunk-OYGFMXAA.js} +13 -4
  136. package/dist/chunk-OYGFMXAA.js.map +1 -0
  137. package/dist/chunk-PBBHUUXU.cjs +133 -0
  138. package/dist/chunk-PBBHUUXU.cjs.map +1 -0
  139. package/dist/chunk-RDLPX7RK.cjs +95 -0
  140. package/dist/chunk-RDLPX7RK.cjs.map +1 -0
  141. package/dist/{chunk-XFRP2MBR.js → chunk-TYQ5CN2C.js} +51 -4
  142. package/dist/chunk-TYQ5CN2C.js.map +1 -0
  143. package/dist/{chunk-7CKHWCEA.cjs → chunk-TZSWDH5T.cjs} +5 -3
  144. package/dist/chunk-TZSWDH5T.cjs.map +1 -0
  145. package/dist/{chunk-VMHNKD3N.cjs → chunk-URF6RBW6.cjs} +13 -4
  146. package/dist/chunk-URF6RBW6.cjs.map +1 -0
  147. package/dist/{chunk-G3UWXSNQ.js → chunk-V34OPWKZ.js} +5 -4
  148. package/dist/chunk-V34OPWKZ.js.map +1 -0
  149. package/dist/{chunk-ITGCHU3Y.cjs → chunk-VICGQC6G.cjs} +5 -4
  150. package/dist/chunk-VICGQC6G.cjs.map +1 -0
  151. package/dist/chunk-YEOARJKR.cjs +40 -0
  152. package/dist/chunk-YEOARJKR.cjs.map +1 -0
  153. package/dist/chunk-Z5X5AMLA.cjs +41 -0
  154. package/dist/chunk-Z5X5AMLA.cjs.map +1 -0
  155. package/dist/chunk-Z7P6QGMT.js +115 -0
  156. package/dist/chunk-Z7P6QGMT.js.map +1 -0
  157. package/dist/{chunk-OYH6A7IQ.js → chunk-ZVCMXDTP.js} +3 -3
  158. package/dist/{chunk-OYH6A7IQ.js.map → chunk-ZVCMXDTP.js.map} +1 -1
  159. package/dist/chunk-ZWP4LSS3.js +38 -0
  160. package/dist/chunk-ZWP4LSS3.js.map +1 -0
  161. package/dist/index.cjs +57 -56
  162. package/dist/index.cjs.map +1 -1
  163. package/dist/index.d.cts +6 -5
  164. package/dist/index.d.ts +6 -5
  165. package/dist/index.js +19 -18
  166. package/dist/index.js.map +1 -1
  167. package/dist/styles.css +566 -50
  168. package/package.json +1 -1
  169. package/dist/Input-Z526ARZP.css +0 -66
  170. package/dist/Modal-AYKNIWWQ.css +0 -79
  171. package/dist/Switch-NP7KKJOX.css +0 -44
  172. package/dist/Table-ZDPGWLH3.css +0 -139
  173. package/dist/chunk-2VA2HSL4.cjs +0 -121
  174. package/dist/chunk-2VA2HSL4.cjs.map +0 -1
  175. package/dist/chunk-2W2AJUZW.js +0 -118
  176. package/dist/chunk-2W2AJUZW.js.map +0 -1
  177. package/dist/chunk-3QWHDCHJ.js.map +0 -1
  178. package/dist/chunk-4AA22BOG.js +0 -63
  179. package/dist/chunk-4AA22BOG.js.map +0 -1
  180. package/dist/chunk-5EYI27B6.js.map +0 -1
  181. package/dist/chunk-77NP67ML.cjs +0 -70
  182. package/dist/chunk-77NP67ML.cjs.map +0 -1
  183. package/dist/chunk-7CKHWCEA.cjs.map +0 -1
  184. package/dist/chunk-7NM5BRUX.js +0 -91
  185. package/dist/chunk-7NM5BRUX.js.map +0 -1
  186. package/dist/chunk-7UJI437T.js +0 -49
  187. package/dist/chunk-7UJI437T.js.map +0 -1
  188. package/dist/chunk-AAMYURWQ.cjs.map +0 -1
  189. package/dist/chunk-ALFDP5WX.cjs.map +0 -1
  190. package/dist/chunk-F3NHM4GX.js.map +0 -1
  191. package/dist/chunk-FMG3ZPGK.js.map +0 -1
  192. package/dist/chunk-G3UWXSNQ.js.map +0 -1
  193. package/dist/chunk-HTP6UEVR.js.map +0 -1
  194. package/dist/chunk-I2ERCHFV.cjs.map +0 -1
  195. package/dist/chunk-IBZAGURN.cjs +0 -71
  196. package/dist/chunk-IBZAGURN.cjs.map +0 -1
  197. package/dist/chunk-IGHLSNXT.cjs.map +0 -1
  198. package/dist/chunk-ITGCHU3Y.cjs.map +0 -1
  199. package/dist/chunk-JNFCTYJT.cjs +0 -31
  200. package/dist/chunk-JNFCTYJT.cjs.map +0 -1
  201. package/dist/chunk-JWFVSBVX.cjs +0 -30
  202. package/dist/chunk-JWFVSBVX.cjs.map +0 -1
  203. package/dist/chunk-K67KIKX4.cjs +0 -67
  204. package/dist/chunk-K67KIKX4.cjs.map +0 -1
  205. package/dist/chunk-KF4MCHZL.cjs +0 -105
  206. package/dist/chunk-KF4MCHZL.cjs.map +0 -1
  207. package/dist/chunk-M6OTFXZA.js +0 -48
  208. package/dist/chunk-M6OTFXZA.js.map +0 -1
  209. package/dist/chunk-NWJW5KLN.js +0 -29
  210. package/dist/chunk-NWJW5KLN.js.map +0 -1
  211. package/dist/chunk-NZPJ7BUB.cjs.map +0 -1
  212. package/dist/chunk-OXYFB2ZI.js.map +0 -1
  213. package/dist/chunk-Q33V7MSK.js +0 -79
  214. package/dist/chunk-Q33V7MSK.js.map +0 -1
  215. package/dist/chunk-QT7SJITQ.cjs +0 -114
  216. package/dist/chunk-QT7SJITQ.cjs.map +0 -1
  217. package/dist/chunk-VMHNKD3N.cjs.map +0 -1
  218. package/dist/chunk-VXITDXLW.js +0 -28
  219. package/dist/chunk-VXITDXLW.js.map +0 -1
  220. package/dist/chunk-XFRP2MBR.js.map +0 -1
package/dist/styles.css CHANGED
@@ -277,6 +277,7 @@ input, textarea, select { font-family: inherit; color: inherit; }
277
277
  .btn.sm.icon { width: 30px; padding: 0; }
278
278
  .btn.lg { height: 52px; padding: 0 24px; font-size: 15px; border-radius: var(--r-lg); }
279
279
  .btn.lg.icon { width: 52px; padding: 0; }
280
+ .btn.block { width: 100%; flex-shrink: 1; }
280
281
  .btn[disabled], .btn.disabled, .btn:disabled {
281
282
  color: var(--fg-subtle);
282
283
  cursor: not-allowed;
@@ -294,50 +295,113 @@ input, textarea, select { font-family: inherit; color: inherit; }
294
295
  display: inline-block;
295
296
  }
296
297
  /* ============ Input / Textarea ============ */
298
+ .input-shell {
299
+ display: inline-flex;
300
+ flex-direction: column;
301
+ gap: 4px;
302
+ width: 100%;
303
+ }
304
+ .input-count {
305
+ font-size: 11px;
306
+ color: var(--fg-subtle);
307
+ font-variant-numeric: tabular-nums;
308
+ text-align: right;
309
+ }
297
310
  .input-wrap {
298
311
  position: relative;
299
312
  display: inline-flex;
300
313
  align-items: center;
301
314
  width: 100%;
315
+ height: var(--ctrl-h);
316
+ padding: 0 var(--ctrl-pad-x);
317
+ border-radius: var(--r-md);
318
+ background: var(--bg);
319
+ box-shadow: var(--neu-in-sm);
320
+ transition: box-shadow var(--dur) var(--ease);
321
+ gap: 8px;
302
322
  }
323
+ .input-wrap.sm { height: 32px; padding: 0 12px; border-radius: var(--r-sm); gap: 6px; }
324
+ .input-wrap.lg { height: 48px; padding: 0 18px; border-radius: var(--r-lg); gap: 10px; }
325
+ .input-wrap:focus-within { box-shadow: var(--neu-in-sm), 0 0 0 2px var(--accent-glow); }
326
+ .input-wrap.invalid { box-shadow: var(--neu-in-sm), 0 0 0 2px color-mix(in oklch, var(--danger) 30%, transparent); }
327
+ .input-wrap.disabled { opacity: 0.6; cursor: not-allowed; }
303
328
  .input-wrap .lead,
304
329
  .input-wrap .trail {
305
- position: absolute;
306
330
  color: var(--fg-subtle);
307
- pointer-events: none;
331
+ flex-shrink: 0;
332
+ display: inline-flex;
308
333
  }
309
- .input-wrap .lead { left: 14px; }
310
- .input-wrap .trail { right: 14px; pointer-events: auto; cursor: pointer; }
334
+ .input-wrap .lead.interactive,
335
+ .input-wrap .trail.interactive { cursor: pointer; pointer-events: auto; }
311
336
  .input-wrap .trail:hover { color: var(--fg); }
312
- .input,
313
- .input-wrap > input {
337
+ .input-wrap .lead:not(.interactive),
338
+ .input-wrap .trail:not(.interactive) { pointer-events: none; }
339
+ .input-wrap .input-affix {
340
+ display: inline-flex;
341
+ align-items: center;
342
+ color: var(--fg-muted);
343
+ font-size: 13px;
344
+ white-space: nowrap;
345
+ user-select: none;
346
+ flex-shrink: 0;
347
+ }
348
+ .input-wrap.sm .input-affix { font-size: 12px; }
349
+ .input-wrap.lg .input-affix { font-size: 14px; }
350
+ .input-wrap .input-clear {
351
+ display: inline-flex;
352
+ align-items: center;
353
+ justify-content: center;
354
+ width: 18px;
355
+ height: 18px;
356
+ border-radius: 999px;
357
+ color: var(--fg-subtle);
358
+ background: transparent;
359
+ cursor: pointer;
360
+ flex-shrink: 0;
361
+ transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
362
+ }
363
+ .input-wrap .input-clear:hover {
364
+ color: var(--fg);
365
+ background: var(--bg-sunken);
366
+ }
367
+ .input-wrap > .input {
368
+ flex: 1;
369
+ min-width: 0;
314
370
  width: 100%;
315
- height: var(--ctrl-h);
316
- padding: 0 var(--ctrl-pad-x);
371
+ height: 100%;
372
+ padding: 0;
317
373
  border: none;
318
- border-radius: var(--r-md);
319
- background: var(--bg);
320
- box-shadow: var(--neu-in-sm);
374
+ background: transparent;
375
+ box-shadow: none;
321
376
  color: var(--fg);
322
377
  font-size: 13px;
323
378
  font-family: inherit;
324
379
  outline: none;
325
- transition: box-shadow var(--dur) var(--ease);
326
380
  }
327
- .input-wrap:has(.lead) > input,
328
- .input-wrap.with-leading > input { padding-left: 40px; }
329
- .input-wrap:has(.trail) > input,
330
- .input-wrap.with-trailing > input { padding-right: 40px; }
331
- .input:focus,
332
- .input-wrap > input:focus { box-shadow: var(--neu-in-sm), 0 0 0 2px var(--accent-glow); }
333
- .input::placeholder,
334
- .input-wrap > input::placeholder { color: var(--fg-subtle); }
335
- .input[disabled],
336
- .input-wrap.disabled > input { opacity: 0.6; cursor: not-allowed; }
337
- .input-wrap.invalid > input,
338
- .input.invalid { box-shadow: var(--neu-in-sm), 0 0 0 2px color-mix(in oklch, var(--danger) 30%, transparent); }
339
- .input-wrap.sm > input { height: 32px; padding-left: 12px; padding-right: 12px; font-size: 12px; border-radius: var(--r-sm); }
340
- .input-wrap.lg > input { height: 48px; padding-left: 18px; padding-right: 18px; font-size: 14px; border-radius: var(--r-lg); }
381
+ .input-wrap.sm > .input { font-size: 12px; }
382
+ .input-wrap.lg > .input { font-size: 14px; }
383
+ .input-wrap > .input::placeholder { color: var(--fg-subtle); }
384
+ .input-wrap.disabled > .input { cursor: not-allowed; }
385
+ .textarea-wrap { position: relative; width: 100%; }
386
+ .textarea-wrap .textarea-clear {
387
+ position: absolute;
388
+ top: 10px;
389
+ right: 10px;
390
+ display: inline-flex;
391
+ align-items: center;
392
+ justify-content: center;
393
+ width: 18px;
394
+ height: 18px;
395
+ border-radius: 999px;
396
+ color: var(--fg-subtle);
397
+ background: transparent;
398
+ cursor: pointer;
399
+ transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
400
+ }
401
+ .textarea-wrap .textarea-clear:hover {
402
+ color: var(--fg);
403
+ background: var(--bg-sunken);
404
+ }
341
405
  .textarea {
342
406
  width: 100%;
343
407
  min-height: 96px;
@@ -385,6 +449,10 @@ input, textarea, select { font-family: inherit; color: inherit; }
385
449
  }
386
450
  .switch.sm { --w: 36px; --h: 20px; }
387
451
  .switch.lg { --w: 58px; --h: 32px; }
452
+ /* When checkedChildren / unCheckedChildren are present, widen the track to fit. */
453
+ .switch.with-children { --w: 60px; }
454
+ .switch.with-children.sm { --w: 46px; }
455
+ .switch.with-children.lg { --w: 74px; }
388
456
  .switch-thumb {
389
457
  position: absolute;
390
458
  top: 3px;
@@ -395,12 +463,54 @@ input, textarea, select { font-family: inherit; color: inherit; }
395
463
  background: var(--bg-raised);
396
464
  box-shadow: var(--neu-out-sm);
397
465
  transition: all var(--dur) var(--ease);
466
+ z-index: 1;
398
467
  }
399
468
  .switch.on .switch-thumb {
400
469
  transform: translateX(calc(var(--w) - var(--h)));
401
470
  background: var(--accent);
402
471
  box-shadow: 0 2px 8px var(--accent-glow), 0 0 0 1px color-mix(in oklch, var(--accent) 40%, transparent);
403
472
  }
473
+ /* Inline content (checkedChildren / unCheckedChildren) */
474
+ .switch-inner {
475
+ position: absolute;
476
+ inset: 0;
477
+ display: flex;
478
+ align-items: center;
479
+ font-size: 11px;
480
+ font-weight: 500;
481
+ font-family: inherit;
482
+ line-height: 1;
483
+ pointer-events: none;
484
+ }
485
+ .switch.sm .switch-inner { font-size: 10px; }
486
+ .switch-inner-on,
487
+ .switch-inner-off {
488
+ position: absolute;
489
+ display: inline-flex;
490
+ align-items: center;
491
+ justify-content: center;
492
+ transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
493
+ }
494
+ /* Checked label sits on the left side of the track (thumb pushes right). */
495
+ .switch-inner-on {
496
+ left: 8px;
497
+ right: calc(var(--h) - 2px);
498
+ color: white;
499
+ opacity: 0;
500
+ transform: translateX(-4px);
501
+ }
502
+ /* Unchecked label sits on the right side (thumb is at left). */
503
+ .switch-inner-off {
504
+ right: 8px;
505
+ left: calc(var(--h) - 2px);
506
+ color: var(--fg-muted);
507
+ opacity: 1;
508
+ transform: translateX(0);
509
+ }
510
+ .switch.sm .switch-inner-on { left: 5px; right: calc(var(--h) - 2px); }
511
+ .switch.sm .switch-inner-off { right: 5px; left: calc(var(--h) - 2px); }
512
+ .switch.on .switch-inner-on { opacity: 1; transform: translateX(0); }
513
+ .switch.on .switch-inner-off { opacity: 0; transform: translateX(4px); }
404
514
  /* ============ Checkbox & Radio ============ */
405
515
  .checkbox, .radio {
406
516
  display: inline-flex;
@@ -480,6 +590,7 @@ input, textarea, select { font-family: inherit; color: inherit; }
480
590
  align-items: center;
481
591
  cursor: pointer;
482
592
  }
593
+ .slider.has-marks { padding-bottom: 26px; }
483
594
  .slider.disabled { opacity: 0.5; cursor: not-allowed; }
484
595
  .slider-track {
485
596
  position: relative;
@@ -492,11 +603,11 @@ input, textarea, select { font-family: inherit; color: inherit; }
492
603
  }
493
604
  .slider-fill {
494
605
  position: absolute;
495
- top: 0; left: 0; bottom: 0;
606
+ top: 0; bottom: 0;
496
607
  background: linear-gradient(90deg, color-mix(in oklch, var(--accent) 70%, white), var(--accent));
497
608
  box-shadow: 0 0 12px var(--accent-glow);
498
609
  border-radius: 999px;
499
- transition: width var(--dur-fast) var(--ease);
610
+ transition: left var(--dur-fast) var(--ease), right var(--dur-fast) var(--ease);
500
611
  }
501
612
  .slider-thumb {
502
613
  position: absolute;
@@ -508,7 +619,10 @@ input, textarea, select { font-family: inherit; color: inherit; }
508
619
  transform: translate(-50%, -50%);
509
620
  transition: all var(--dur-fast) var(--ease);
510
621
  display: grid; place-items: center;
622
+ pointer-events: none;
511
623
  }
624
+ .slider.has-marks .slider-thumb { top: calc(50% - 13px); }
625
+ .slider.has-marks .slider-track { margin-top: -26px; }
512
626
  .slider-thumb::after {
513
627
  content: "";
514
628
  width: 6px; height: 6px;
@@ -522,7 +636,13 @@ input, textarea, select { font-family: inherit; color: inherit; }
522
636
  width: 100%; height: 100%;
523
637
  opacity: 0;
524
638
  cursor: inherit;
639
+ margin: 0;
640
+ pointer-events: auto;
525
641
  }
642
+ /* In range mode (two stacked inputs), split the hit zones by half so the user can drag either thumb */
643
+ .slider input[type="range"]:nth-of-type(1):not(:only-of-type) { right: 50%; }
644
+ .slider input[type="range"]:nth-of-type(2) { left: 50%; }
645
+ .slider.has-marks input[type="range"] { height: calc(100% - 26px); }
526
646
  .slider-value { font-family: var(--font-mono); font-size: 12px; color: var(--accent-ink); margin-left: 10px; }
527
647
  .slider.success .slider-fill { background: linear-gradient(90deg, color-mix(in oklch, var(--success) 70%, white), var(--success)); box-shadow: 0 0 10px color-mix(in oklch, var(--success) 35%, transparent); }
528
648
  .slider.success .slider-thumb::after { background: var(--success); }
@@ -530,6 +650,44 @@ input, textarea, select { font-family: inherit; color: inherit; }
530
650
  .slider.warning .slider-thumb::after { background: var(--warning); }
531
651
  .slider.danger .slider-fill { background: linear-gradient(90deg, color-mix(in oklch, var(--danger) 70%, white), var(--danger)); box-shadow: 0 0 10px color-mix(in oklch, var(--danger) 35%, transparent); }
532
652
  .slider.danger .slider-thumb::after { background: var(--danger); }
653
+ /* Marks */
654
+ .slider-marks {
655
+ position: absolute;
656
+ left: 0; right: 0;
657
+ bottom: 0;
658
+ height: 22px;
659
+ pointer-events: none;
660
+ }
661
+ .slider-mark {
662
+ position: absolute;
663
+ transform: translateX(-50%);
664
+ display: inline-flex;
665
+ flex-direction: column;
666
+ align-items: center;
667
+ gap: 4px;
668
+ pointer-events: auto;
669
+ cursor: pointer;
670
+ color: var(--fg-subtle);
671
+ font-size: 11px;
672
+ user-select: none;
673
+ }
674
+ .slider-mark-dot {
675
+ width: 6px; height: 6px;
676
+ border-radius: 999px;
677
+ background: var(--bg);
678
+ box-shadow: var(--neu-in-sm);
679
+ margin-top: -18px;
680
+ position: relative;
681
+ z-index: 1;
682
+ }
683
+ .slider-mark.active .slider-mark-dot { background: var(--accent); box-shadow: 0 0 6px var(--accent-glow); }
684
+ .slider.success .slider-mark.active .slider-mark-dot { background: var(--success); box-shadow: 0 0 6px color-mix(in oklch, var(--success) 35%, transparent); }
685
+ .slider.warning .slider-mark.active .slider-mark-dot { background: var(--warning); box-shadow: 0 0 6px color-mix(in oklch, var(--warning) 35%, transparent); }
686
+ .slider.danger .slider-mark.active .slider-mark-dot { background: var(--danger); box-shadow: 0 0 6px color-mix(in oklch, var(--danger) 35%, transparent); }
687
+ .slider-mark-label { white-space: nowrap; }
688
+ .slider-mark.active .slider-mark-label { color: var(--accent-ink); font-weight: 500; }
689
+ .slider-mark:hover .slider-mark-label { color: var(--fg); }
690
+ .slider.disabled .slider-mark { pointer-events: none; }
533
691
  /* ============ Progress ============ */
534
692
  .progress {
535
693
  width: 100%;
@@ -616,7 +774,9 @@ input, textarea, select { font-family: inherit; color: inherit; }
616
774
  .tag.solid.success { background: var(--success); color: white; box-shadow: 0 2px 6px color-mix(in oklch, var(--success) 35%, transparent); }
617
775
  .tag.solid.warning { background: var(--warning); color: white; box-shadow: 0 2px 6px color-mix(in oklch, var(--warning) 35%, transparent); }
618
776
  .tag.solid.danger { background: var(--danger); color: white; box-shadow: 0 2px 6px color-mix(in oklch, var(--danger) 35%, transparent); }
777
+ .tag.borderless { background: transparent; box-shadow: none; }
619
778
  .tag .dot { width: 6px; height: 6px; border-radius: 999px; background: currentColor; }
779
+ .tag .tag-ico { color: currentColor; display: inline-flex; }
620
780
  .tag .x { cursor: pointer; color: var(--fg-subtle); margin-left: 2px; display: inline-flex; }
621
781
  .tag .x:hover { color: var(--fg); }
622
782
  .badge {
@@ -658,6 +818,10 @@ input, textarea, select { font-family: inherit; color: inherit; }
658
818
  .avatar.sm { --size: 28px; }
659
819
  .avatar.lg { --size: 56px; }
660
820
  .avatar.xl { --size: 80px; }
821
+ .avatar.square { border-radius: var(--r-md); }
822
+ .avatar.square.sm { border-radius: var(--r-sm); }
823
+ .avatar.square.lg,
824
+ .avatar.square.xl { border-radius: var(--r-lg); }
661
825
  .avatar img { width: 100%; height: 100%; object-fit: cover; }
662
826
  .avatar-status {
663
827
  position: absolute;
@@ -701,6 +865,28 @@ input, textarea, select { font-family: inherit; color: inherit; }
701
865
  .divider.sunken:has(.divider-label) { background: transparent; box-shadow: none; }
702
866
  .divider.sunken:has(.divider-label)::before,
703
867
  .divider.sunken:has(.divider-label)::after { height: 2px; background: transparent; box-shadow: var(--neu-in-sm); }
868
+ /* ---- Dashed variant ---- */
869
+ .divider.dashed {
870
+ background: transparent;
871
+ box-shadow: none;
872
+ border-top: 1px dashed var(--divider);
873
+ border-radius: 0;
874
+ height: 0;
875
+ }
876
+ .divider.dashed.vertical {
877
+ width: 0;
878
+ border-top: none;
879
+ border-left: 1px dashed var(--divider);
880
+ }
881
+ .divider.dashed:has(.divider-label) { border-top: none; }
882
+ .divider.dashed:has(.divider-label)::before,
883
+ .divider.dashed:has(.divider-label)::after {
884
+ background: transparent;
885
+ box-shadow: none;
886
+ border-top: 1px dashed var(--divider);
887
+ height: 0;
888
+ border-radius: 0;
889
+ }
704
890
  .divider-label {
705
891
  display: flex; align-items: center; gap: 12px;
706
892
  height: auto; background: transparent; box-shadow: none;
@@ -724,6 +910,12 @@ input, textarea, select { font-family: inherit; color: inherit; }
724
910
  border-radius: 999px;
725
911
  box-shadow: 0 1px 0 var(--shadow-light);
726
912
  }
913
+ /* ---- Label orientation ---- */
914
+ .divider.orient-left::before { flex: 0 0 var(--gap-4); }
915
+ .divider.orient-left::after { flex: 1; }
916
+ .divider.orient-right::before { flex: 1; }
917
+ .divider.orient-right::after { flex: 0 0 var(--gap-4); }
918
+ /* center is default (both flex: 1) */
727
919
  /* ============ Card & Panel ============ */
728
920
  .card {
729
921
  background: var(--bg);
@@ -736,6 +928,16 @@ input, textarea, select { font-family: inherit; color: inherit; }
736
928
  .card.pad-none { padding: 0; }
737
929
  .card.pad-sm { padding: var(--gap-3); }
738
930
  .card.pad-lg { padding: var(--gap-6); }
931
+ .card.hoverable {
932
+ cursor: pointer;
933
+ transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
934
+ }
935
+ .card.hoverable:hover {
936
+ transform: translateY(-3px);
937
+ box-shadow: var(--neu-out-lg);
938
+ }
939
+ .card.hoverable.flat:hover { box-shadow: var(--neu-out-sm); }
940
+ .card.hoverable.sunken:hover { box-shadow: var(--neu-out); }
739
941
  .panel {
740
942
  background: var(--bg);
741
943
  border-radius: var(--r-lg);
@@ -809,6 +1011,12 @@ input, textarea, select { font-family: inherit; color: inherit; }
809
1011
  background: var(--accent); border-radius: 999px;
810
1012
  box-shadow: 0 0 8px var(--accent-glow);
811
1013
  }
1014
+ /* Centered nav — works for pill / segmented (self-align) and line (flex-center) */
1015
+ .tabs.centered .tabs-nav { align-self: center; }
1016
+ .tabs.centered.line .tabs-nav,
1017
+ .tabs.centered.underline .tabs-nav { align-self: stretch; justify-content: center; }
1018
+ .tabs.centered.line .tabs-nav .tab,
1019
+ .tabs.centered.underline .tabs-nav .tab { margin-right: 11px; margin-left: 11px; }
812
1020
  .tabs-content { padding: var(--gap-2) 0; }
813
1021
  /* Segmented (owned by Tabs.tsx — Segmented is co-exported) */
814
1022
  .segmented {
@@ -851,6 +1059,7 @@ input, textarea, select { font-family: inherit; color: inherit; }
851
1059
  box-shadow: var(--neu-out-sm);
852
1060
  overflow: hidden;
853
1061
  }
1062
+ .accordion-item.disabled { opacity: 0.5; }
854
1063
  .accordion-head {
855
1064
  width: 100%;
856
1065
  border: none;
@@ -866,6 +1075,8 @@ input, textarea, select { font-family: inherit; color: inherit; }
866
1075
  color: var(--fg);
867
1076
  text-align: left;
868
1077
  }
1078
+ .accordion-item.disabled .accordion-head { cursor: not-allowed; }
1079
+ .accordion-item.icon-only .accordion-head:not(:disabled) { cursor: default; }
869
1080
  .accordion-body {
870
1081
  max-height: 0;
871
1082
  overflow: hidden;
@@ -876,10 +1087,14 @@ input, textarea, select { font-family: inherit; color: inherit; }
876
1087
  .accordion-item.open .accordion-body { max-height: 320px; }
877
1088
  .accordion-body-inner { padding: 0 18px 16px; }
878
1089
  .accordion-chev {
879
- transition: transform var(--dur) var(--ease);
1090
+ transition: transform var(--dur) var(--ease), color var(--dur) var(--ease);
880
1091
  color: var(--fg-subtle);
881
1092
  display: inline-flex;
1093
+ border-radius: 6px;
1094
+ padding: 2px;
882
1095
  }
1096
+ .accordion-chev.clickable { cursor: pointer; }
1097
+ .accordion-chev.clickable:hover { color: var(--fg); background: var(--bg); box-shadow: var(--neu-flat); }
883
1098
  .accordion-item.open .accordion-chev { transform: rotate(180deg); color: var(--accent); }
884
1099
  /* ============ Select ============ */
885
1100
  .select {
@@ -1145,10 +1360,13 @@ input, textarea, select { font-family: inherit; color: inherit; }
1145
1360
  z-index: 200;
1146
1361
  animation: fadeIn var(--dur) var(--ease);
1147
1362
  }
1363
+ .modal-overlay.hidden {
1364
+ display: none;
1365
+ }
1148
1366
  .modal {
1149
1367
  background: var(--bg);
1150
1368
  border-radius: var(--r-xl);
1151
- box-shadow: var(--neu-out-lg), 0 24px 60px -20px rgba(40,55,80,0.3);
1369
+ box-shadow: var(--neu-out-lg), 0 24px 60px -20px rgba(40, 55, 80, 0.3);
1152
1370
  padding: var(--gap-6);
1153
1371
  width: min(480px, 92vw);
1154
1372
  animation: modalIn var(--dur-slow) var(--ease);
@@ -1156,37 +1374,65 @@ input, textarea, select { font-family: inherit; color: inherit; }
1156
1374
  display: flex;
1157
1375
  flex-direction: column;
1158
1376
  }
1159
- @keyframes modalIn { from { opacity: 0; transform: translateY(8px) scale(0.97); } }
1377
+ @keyframes modalIn {
1378
+ from { opacity: 0; transform: translateY(8px) scale(0.97); }
1379
+ }
1160
1380
  .modal-head {
1161
- display: flex; align-items: flex-start; justify-content: space-between;
1162
- gap: var(--gap-3); margin-bottom: var(--gap-3);
1381
+ display: flex;
1382
+ align-items: flex-start;
1383
+ justify-content: space-between;
1384
+ gap: var(--gap-3);
1385
+ margin-bottom: var(--gap-3);
1386
+ }
1387
+ .modal-titles {
1388
+ display: flex;
1389
+ flex-direction: column;
1390
+ gap: 4px;
1163
1391
  }
1164
- .modal-titles { display: flex; flex-direction: column; gap: 4px; }
1165
1392
  .modal-title { font-size: 17px; font-weight: 600; }
1166
1393
  .modal-desc { font-size: 13px; color: var(--fg-muted); }
1167
- .modal-body { padding: var(--gap-3) 0; color: var(--fg-muted); font-size: 13px; line-height: 1.6; flex: 1; overflow-y: auto; }
1168
- .modal-foot {
1169
- display: flex; gap: 10px; justify-content: flex-end;
1394
+ .modal-body {
1395
+ padding: var(--gap-3) 0;
1396
+ color: var(--fg-muted);
1397
+ font-size: 13px;
1398
+ line-height: 1.6;
1399
+ flex: 1;
1400
+ overflow-y: auto;
1401
+ }
1402
+ .modal-foot {
1403
+ display: flex;
1404
+ gap: 10px;
1405
+ justify-content: flex-end;
1170
1406
  margin-top: var(--gap-4);
1171
1407
  }
1172
1408
  .modal-close {
1173
1409
  width: 28px; height: 28px;
1174
- border: none; background: transparent;
1410
+ border: none;
1411
+ background: transparent;
1175
1412
  border-radius: var(--r-sm);
1176
- display: grid; place-items: center;
1413
+ display: grid;
1414
+ place-items: center;
1177
1415
  color: var(--fg-subtle);
1178
1416
  cursor: pointer;
1179
1417
  transition: all var(--dur-fast) var(--ease);
1180
1418
  }
1181
- .modal-close:hover { color: var(--fg); background: var(--bg); box-shadow: var(--neu-flat); }
1182
- /* ============ Drawer (co-exported from Modal.tsx) ============ */
1419
+ .modal-close:hover {
1420
+ color: var(--fg);
1421
+ background: var(--bg);
1422
+ box-shadow: var(--neu-flat);
1423
+ }
1424
+ /* ============ Drawer ============ */
1183
1425
  .drawer-overlay {
1184
- position: fixed; inset: 0;
1426
+ position: fixed;
1427
+ inset: 0;
1185
1428
  background: color-mix(in oklch, var(--bg-sunken) 50%, transparent);
1186
1429
  backdrop-filter: blur(4px);
1187
1430
  z-index: 150;
1188
1431
  animation: fadeIn var(--dur) var(--ease);
1189
1432
  }
1433
+ .drawer-overlay.hidden {
1434
+ display: none;
1435
+ }
1190
1436
  .drawer {
1191
1437
  position: fixed;
1192
1438
  background: var(--bg);
@@ -1196,22 +1442,82 @@ input, textarea, select { font-family: inherit; color: inherit; }
1196
1442
  display: flex;
1197
1443
  flex-direction: column;
1198
1444
  }
1199
- .drawer.right { top: 0; right: 0; bottom: 0; width: min(420px, 92vw); animation: drawerInRight var(--dur-slow) var(--ease); box-shadow: -24px 0 60px -20px rgba(40,55,80,0.25); }
1200
- .drawer.left { top: 0; left: 0; bottom: 0; width: min(420px, 92vw); animation: drawerInLeft var(--dur-slow) var(--ease); box-shadow: 24px 0 60px -20px rgba(40,55,80,0.25); }
1201
- .drawer.top { top: 0; left: 0; right: 0; height: min(320px, 80vh); animation: drawerInTop var(--dur-slow) var(--ease); box-shadow: 0 24px 60px -20px rgba(40,55,80,0.25); }
1202
- .drawer.bottom { bottom: 0; left: 0; right: 0; height: min(320px, 80vh); animation: drawerInBottom var(--dur-slow) var(--ease); box-shadow: 0 -24px 60px -20px rgba(40,55,80,0.25); }
1445
+ .drawer.hidden {
1446
+ display: none;
1447
+ }
1448
+ .drawer.right {
1449
+ top: 0; right: 0; bottom: 0;
1450
+ width: min(420px, 92vw);
1451
+ animation: drawerInRight var(--dur-slow) var(--ease);
1452
+ box-shadow: -24px 0 60px -20px rgba(40, 55, 80, 0.25);
1453
+ }
1454
+ .drawer.left {
1455
+ top: 0; left: 0; bottom: 0;
1456
+ width: min(420px, 92vw);
1457
+ animation: drawerInLeft var(--dur-slow) var(--ease);
1458
+ box-shadow: 24px 0 60px -20px rgba(40, 55, 80, 0.25);
1459
+ }
1460
+ .drawer.top {
1461
+ top: 0; left: 0; right: 0;
1462
+ height: min(320px, 80vh);
1463
+ animation: drawerInTop var(--dur-slow) var(--ease);
1464
+ box-shadow: 0 24px 60px -20px rgba(40, 55, 80, 0.25);
1465
+ }
1466
+ .drawer.bottom {
1467
+ bottom: 0; left: 0; right: 0;
1468
+ height: min(320px, 80vh);
1469
+ animation: drawerInBottom var(--dur-slow) var(--ease);
1470
+ box-shadow: 0 -24px 60px -20px rgba(40, 55, 80, 0.25);
1471
+ }
1203
1472
  @keyframes drawerInRight { from { transform: translateX( 20px); opacity: 0; } }
1204
1473
  @keyframes drawerInLeft { from { transform: translateX(-20px); opacity: 0; } }
1205
1474
  @keyframes drawerInTop { from { transform: translateY(-20px); opacity: 0; } }
1206
1475
  @keyframes drawerInBottom { from { transform: translateY( 20px); opacity: 0; } }
1207
1476
  .drawer-head {
1208
- display: flex; align-items: center; justify-content: space-between;
1477
+ display: flex;
1478
+ align-items: center;
1479
+ justify-content: space-between;
1480
+ gap: var(--gap-3);
1209
1481
  margin-bottom: var(--gap-4);
1210
1482
  padding-bottom: var(--gap-4);
1211
1483
  border-bottom: 1px solid var(--divider);
1212
1484
  }
1213
- .drawer-title { font-size: 16px; font-weight: 600; }
1214
- .drawer-body { flex: 1; }
1485
+ .drawer-head-right {
1486
+ display: inline-flex;
1487
+ align-items: center;
1488
+ gap: var(--gap-3);
1489
+ }
1490
+ .drawer-title {
1491
+ font-size: 16px;
1492
+ font-weight: 600;
1493
+ }
1494
+ .drawer-close {
1495
+ width: 28px; height: 28px;
1496
+ border: none;
1497
+ background: transparent;
1498
+ border-radius: var(--r-sm);
1499
+ display: grid;
1500
+ place-items: center;
1501
+ color: var(--fg-subtle);
1502
+ cursor: pointer;
1503
+ transition: all var(--dur-fast) var(--ease);
1504
+ }
1505
+ .drawer-close:hover {
1506
+ color: var(--fg);
1507
+ background: var(--bg);
1508
+ box-shadow: var(--neu-flat);
1509
+ }
1510
+ .drawer-body {
1511
+ flex: 1;
1512
+ }
1513
+ .drawer-foot {
1514
+ display: flex;
1515
+ gap: 10px;
1516
+ justify-content: flex-end;
1517
+ margin-top: var(--gap-4);
1518
+ padding-top: var(--gap-4);
1519
+ border-top: 1px solid var(--divider);
1520
+ }
1215
1521
  /* ============ Tooltip ============ */
1216
1522
  .tip-anchor {
1217
1523
  position: relative;
@@ -1311,6 +1617,15 @@ input, textarea, select { font-family: inherit; color: inherit; }
1311
1617
  .alert-desc { font-size: 12px; color: var(--fg-muted); line-height: 1.55; }
1312
1618
  .alert.no-title { align-items: center; }
1313
1619
  .alert.no-title .alert-ico { margin-top: 0; }
1620
+ .alert.no-icon { gap: 0; }
1621
+ .alert-action {
1622
+ display: flex;
1623
+ align-items: center;
1624
+ gap: 6px;
1625
+ flex-shrink: 0;
1626
+ margin-left: 4px;
1627
+ }
1628
+ .alert:has(.alert-close) .alert-action { margin-right: 26px; }
1314
1629
  .alert-close {
1315
1630
  position: absolute; top: 10px; right: 10px;
1316
1631
  width: 22px; height: 22px; border-radius: 7px;
@@ -1333,6 +1648,9 @@ input, textarea, select { font-family: inherit; color: inherit; }
1333
1648
  box-shadow: var(--neu-in-sm);
1334
1649
  overflow: auto;
1335
1650
  }
1651
+ /* When scroll=y is on, the wrap itself becomes the scroll region. */
1652
+ .table-wrap.scroll-y { overflow-y: auto; }
1653
+ .table-wrap.scroll-x { overflow-x: auto; }
1336
1654
  .table {
1337
1655
  width: 100%;
1338
1656
  border-collapse: separate;
@@ -1352,8 +1670,13 @@ input, textarea, select { font-family: inherit; color: inherit; }
1352
1670
  position: sticky; top: 0;
1353
1671
  z-index: 1;
1354
1672
  }
1673
+ /* When the wrap is the scroll container (scroll.y), position:sticky on th needs
1674
+ top:0 relative to the wrap — browsers already handle that. Adding a stronger
1675
+ bg so content under the header doesn't bleed through. */
1676
+ .table.sticky-head th { background: var(--bg); }
1355
1677
  .table th.sortable { cursor: pointer; user-select: none; }
1356
1678
  .table th.sortable:hover { color: var(--fg); }
1679
+ .table th .th-label { vertical-align: middle; }
1357
1680
  .table th .sort-ind {
1358
1681
  display: inline-flex;
1359
1682
  width: 16px; height: 16px;
@@ -1414,8 +1737,142 @@ input, textarea, select { font-family: inherit; color: inherit; }
1414
1737
  box-shadow: 0 4px 8px var(--shadow-dark), 0 -4px 8px var(--shadow-light);
1415
1738
  }
1416
1739
  .table.cards.hoverable tbody tr:hover td { background: var(--bg); transform: translateY(-1px); }
1417
- .table .row-check { width: 36px; }
1740
+ .table .row-check { width: 44px; }
1741
+ .table .row-check .checkbox { display: inline-flex; }
1742
+ .table .row-expand { width: 40px; text-align: center; }
1418
1743
  .table-empty { padding: 60px 20px; text-align: center; color: var(--fg-muted); }
1744
+ /* Expand button */
1745
+ .expand-btn {
1746
+ width: 22px; height: 22px;
1747
+ border: none;
1748
+ border-radius: var(--r-sm);
1749
+ background: var(--bg);
1750
+ box-shadow: var(--neu-flat);
1751
+ color: var(--fg-subtle);
1752
+ display: inline-flex; align-items: center; justify-content: center;
1753
+ cursor: pointer;
1754
+ transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
1755
+ }
1756
+ .expand-btn:hover { color: var(--accent-ink); box-shadow: var(--neu-out-sm); }
1757
+ .expand-btn.open { transform: rotate(90deg); color: var(--accent-ink); box-shadow: var(--neu-in-sm); }
1758
+ /* Expanded row panel */
1759
+ .table tbody tr.expanded-row td {
1760
+ padding: 0 18px 14px 18px;
1761
+ border-bottom: 1px solid var(--divider);
1762
+ background: color-mix(in oklch, var(--bg-sunken) 25%, transparent);
1763
+ }
1764
+ .expanded-panel {
1765
+ padding: 14px 16px;
1766
+ border-radius: var(--r-md);
1767
+ background: var(--bg);
1768
+ box-shadow: var(--neu-in-sm);
1769
+ color: var(--fg);
1770
+ font-size: 13px;
1771
+ }
1772
+ /* Radio-style row selector */
1773
+ .table .row-check .radio-dot {
1774
+ width: 16px; height: 16px;
1775
+ border-radius: 50%;
1776
+ border: none;
1777
+ padding: 0;
1778
+ background: var(--bg);
1779
+ box-shadow: var(--neu-in-sm);
1780
+ display: inline-flex; align-items: center; justify-content: center;
1781
+ cursor: pointer;
1782
+ transition: box-shadow var(--dur-fast) var(--ease);
1783
+ }
1784
+ .table .row-check .radio-dot:disabled { opacity: 0.5; cursor: not-allowed; }
1785
+ .table .row-check .radio-dot.checked {
1786
+ box-shadow: var(--neu-out-sm);
1787
+ }
1788
+ .table .row-check .radio-dot.checked::after {
1789
+ content: "";
1790
+ width: 8px; height: 8px;
1791
+ border-radius: 50%;
1792
+ background: var(--accent);
1793
+ }
1794
+ /* Filter button on header */
1795
+ .table th.filterable .filter-ind {
1796
+ display: inline-flex;
1797
+ width: 18px; height: 18px;
1798
+ border-radius: 5px;
1799
+ background: var(--bg);
1800
+ box-shadow: var(--neu-flat);
1801
+ color: var(--fg-subtle);
1802
+ align-items: center; justify-content: center;
1803
+ margin-left: 6px;
1804
+ cursor: pointer;
1805
+ border: none;
1806
+ vertical-align: middle;
1807
+ padding: 0;
1808
+ transition: color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
1809
+ }
1810
+ .table th.filterable .filter-ind:hover { color: var(--fg); }
1811
+ .table th.filterable .filter-ind.active {
1812
+ color: var(--accent-ink);
1813
+ box-shadow: var(--neu-in-sm);
1814
+ }
1815
+ /* Filter popover panel (portaled to body) */
1816
+ .table-filter-panel {
1817
+ z-index: 1001;
1818
+ min-width: 200px;
1819
+ max-width: 260px;
1820
+ background: var(--bg);
1821
+ border-radius: var(--r-md);
1822
+ box-shadow: var(--neu-out-lg);
1823
+ padding: 10px;
1824
+ animation: menuIn var(--dur) var(--ease);
1825
+ }
1826
+ .table-filter-options {
1827
+ display: flex;
1828
+ flex-direction: column;
1829
+ max-height: 220px;
1830
+ overflow-y: auto;
1831
+ gap: 4px;
1832
+ padding: 4px;
1833
+ }
1834
+ .table-filter-item {
1835
+ display: flex;
1836
+ align-items: center;
1837
+ gap: 8px;
1838
+ padding: 6px 8px;
1839
+ border-radius: var(--r-sm);
1840
+ font-size: 13px;
1841
+ color: var(--fg);
1842
+ cursor: pointer;
1843
+ transition: background var(--dur-fast) var(--ease);
1844
+ }
1845
+ .table-filter-item:hover {
1846
+ background: color-mix(in oklch, var(--accent-soft) 40%, transparent);
1847
+ }
1848
+ .table-filter-actions {
1849
+ display: flex;
1850
+ justify-content: flex-end;
1851
+ gap: 6px;
1852
+ margin-top: 6px;
1853
+ padding-top: 8px;
1854
+ border-top: 1px solid var(--divider);
1855
+ }
1856
+ .table-filter-actions .tf-btn {
1857
+ border: none;
1858
+ padding: 6px 12px;
1859
+ border-radius: var(--r-sm);
1860
+ background: var(--bg);
1861
+ box-shadow: var(--neu-out-sm);
1862
+ font-size: 12px;
1863
+ font-family: inherit;
1864
+ color: var(--fg);
1865
+ cursor: pointer;
1866
+ transition: box-shadow var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
1867
+ }
1868
+ .table-filter-actions .tf-btn:hover { box-shadow: var(--neu-in-sm); }
1869
+ .table-filter-actions .tf-btn.primary { color: var(--accent-ink); font-weight: 600; }
1870
+ .table-filter-actions .tf-btn.ghost { color: var(--fg-muted); box-shadow: var(--neu-flat); }
1871
+ .table-filter-actions .tf-btn.ghost:hover { box-shadow: var(--neu-in-sm); }
1872
+ /* Built-in pagination bar */
1873
+ .table-pagination {
1874
+ margin-top: 12px;
1875
+ }
1419
1876
  /* Pro: card-wrap with toolbar + table + footer */
1420
1877
  .table-card {
1421
1878
  border-radius: var(--r-lg);
@@ -1425,6 +1882,13 @@ input, textarea, select { font-family: inherit; color: inherit; }
1425
1882
  }
1426
1883
  .table-card .table-wrap { background: transparent; box-shadow: none; border-radius: 0; }
1427
1884
  .table-card .table-wrap.joined { border-radius: 0; }
1885
+ /* When TablePro hosts the built-in pagination, seat it inside the card. */
1886
+ .table-card .table-pagination {
1887
+ margin-top: 0;
1888
+ padding: 6px 16px;
1889
+ border-top: 1px solid var(--divider);
1890
+ background: color-mix(in oklch, var(--bg-sunken) 30%, transparent);
1891
+ }
1428
1892
  .table-toolbar {
1429
1893
  display: flex;
1430
1894
  align-items: center;
@@ -1490,6 +1954,37 @@ input, textarea, select { font-family: inherit; color: inherit; }
1490
1954
  }
1491
1955
  .pagination .pg.disabled { color: var(--fg-subtle); cursor: not-allowed; box-shadow: var(--neu-flat); }
1492
1956
  .pagination .ellipsis { padding: 0 4px; color: var(--fg-subtle); }
1957
+ /* size changer — compact Select inline with the page buttons */
1958
+ .pagination .pg-size-changer { margin-left: 8px; min-width: 108px; }
1959
+ /* quick jumper */
1960
+ .pagination .pg-jumper {
1961
+ display: inline-flex;
1962
+ align-items: center;
1963
+ gap: 6px;
1964
+ margin-left: 8px;
1965
+ color: var(--fg-muted);
1966
+ font-size: 12px;
1967
+ }
1968
+ .pagination .pg-jumper-label { color: var(--fg-muted); }
1969
+ .pagination .pg-jumper-input {
1970
+ width: 44px;
1971
+ height: 28px;
1972
+ padding: 0 8px;
1973
+ border: none;
1974
+ border-radius: var(--r-sm);
1975
+ background: var(--bg);
1976
+ box-shadow: var(--neu-in-sm);
1977
+ color: var(--fg);
1978
+ font-family: inherit;
1979
+ font-size: 12px;
1980
+ font-variant-numeric: tabular-nums;
1981
+ text-align: center;
1982
+ outline: none;
1983
+ transition: box-shadow var(--dur-fast) var(--ease);
1984
+ }
1985
+ .pagination .pg-jumper-input:focus-visible {
1986
+ box-shadow: var(--neu-in-sm), 0 0 0 2px var(--accent-glow);
1987
+ }
1493
1988
  /* ============ List ============ */
1494
1989
  .list {
1495
1990
  display: flex;
@@ -1648,6 +2143,27 @@ input, textarea, select { font-family: inherit; color: inherit; }
1648
2143
  .skeleton.circle { border-radius: 999px; }
1649
2144
  @keyframes skel-wave { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
1650
2145
  @keyframes skel-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
2146
+ /* Composite skeleton — avatar + title + paragraph layout */
2147
+ .skeleton-box {
2148
+ display: flex;
2149
+ align-items: flex-start;
2150
+ gap: 16px;
2151
+ width: 100%;
2152
+ }
2153
+ .skeleton-content {
2154
+ flex: 1;
2155
+ min-width: 0;
2156
+ display: flex;
2157
+ flex-direction: column;
2158
+ gap: 12px;
2159
+ }
2160
+ .skeleton-box .skeleton-title {
2161
+ display: block;
2162
+ margin-bottom: 4px;
2163
+ }
2164
+ .skeleton-box .skeleton-row {
2165
+ display: block;
2166
+ }
1651
2167
  /* ============ Calendar ============ */
1652
2168
  .calendar {
1653
2169
  background: var(--bg);