aporia 0.1.0 → 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.
package/dist/style.css CHANGED
@@ -1,3 +1,285 @@
1
+ /* Shell for grouped controls: solid black card, generous radius, inset padding. */
2
+
3
+ .aporiaPanel {
4
+ box-sizing: border-box;
5
+ width: 100%;
6
+ min-width: 0;
7
+ background-color: #000000;
8
+ border-radius: 24px;
9
+ padding: 16px;
10
+ box-shadow:
11
+ 0 162px 45px 0 rgba(0, 0, 0, 0),
12
+ 0 103px 41px 0 rgba(0, 0, 0, 0.01),
13
+ 0 58px 35px 0 rgba(0, 0, 0, 0.05),
14
+ 0 26px 26px 0 rgba(0, 0, 0, 0.08),
15
+ 0 6px 14px 0 rgba(0, 0, 0, 0.09);
16
+ display: flex;
17
+ flex-direction: column;
18
+ align-items: stretch;
19
+ justify-content: flex-start;
20
+ align-content: flex-start;
21
+ }
22
+ .category {
23
+ display: flex;
24
+ flex-direction: column;
25
+ gap: 10px;
26
+ min-width: 0;
27
+ }
28
+
29
+ .categoryHeader {
30
+ display: flex;
31
+ align-items: center;
32
+ gap: 8px;
33
+ min-width: 0;
34
+ padding: 0 2px;
35
+ box-sizing: border-box;
36
+ }
37
+
38
+ .categoryHeaderStart {
39
+ display: flex;
40
+ align-items: center;
41
+ gap: 4px;
42
+ flex: 1;
43
+ min-width: 0;
44
+ }
45
+
46
+ .categoryChevronReveal {
47
+ flex-shrink: 0;
48
+ width: 22px;
49
+ }
50
+
51
+ .categoryChevronBtn {
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ width: 22px;
56
+ height: 22px;
57
+ margin: 0;
58
+ padding: 0;
59
+ border: none;
60
+ background: transparent;
61
+ color: var(--color-muted);
62
+ cursor: pointer;
63
+ border-radius: 6px;
64
+ }
65
+
66
+ .categoryChevronBtn:hover {
67
+ color: var(--slider-text-muted);
68
+ background: rgba(255, 255, 255, 0.06);
69
+ }
70
+
71
+ .categoryChevronBtn:focus-visible {
72
+ outline: 2px solid rgba(255, 255, 255, 0.35);
73
+ outline-offset: 2px;
74
+ }
75
+
76
+ .categoryChevronIcon {
77
+ display: block;
78
+ width: 12px;
79
+ height: 12px;
80
+ transform: rotate(0deg);
81
+ transform-origin: 50% 50%;
82
+ transition: transform 0.15s ease-out;
83
+ }
84
+
85
+ .categoryChevronIcon[data-collapsed="true"] {
86
+ transform: rotate(-90deg);
87
+ }
88
+
89
+ /* 4px dot + 8px hit slop on each axis → 20×20 tap target */
90
+ .categoryDisabledDot {
91
+ flex-shrink: 0;
92
+ margin: 0;
93
+ width: 20px;
94
+ height: 20px;
95
+ padding: 0;
96
+ border: none;
97
+ border-radius: 6px;
98
+ background: transparent;
99
+ cursor: pointer;
100
+ box-sizing: border-box;
101
+ display: flex;
102
+ align-items: center;
103
+ justify-content: center;
104
+ transition: opacity 0.15s ease-out;
105
+ }
106
+
107
+ .categoryDisabledDot::after {
108
+ content: "";
109
+ width: 4px;
110
+ height: 4px;
111
+ border-radius: 50%;
112
+ background: rgba(255, 255, 255, 0.85);
113
+ flex-shrink: 0;
114
+ transition:
115
+ transform 0.15s ease-out,
116
+ background-color 0.15s ease-out;
117
+ }
118
+
119
+ .categoryDisabledDot:hover::after {
120
+ background: #ffffff;
121
+ transform: scale(1.15);
122
+ }
123
+
124
+ .categoryDisabledDot:focus-visible {
125
+ outline: 2px solid rgba(255, 255, 255, 0.35);
126
+ outline-offset: 2px;
127
+ }
128
+
129
+ .category[data-disabled="true"] .categoryDisabledDot {
130
+ opacity: 0.35;
131
+ }
132
+
133
+ .categoryTitle {
134
+ margin: 0;
135
+ flex: 1;
136
+ min-width: 0;
137
+ font-size: 12px;
138
+ font-weight: 500;
139
+ letter-spacing: 0.08em;
140
+ text-transform: uppercase;
141
+ color: var(--color-muted);
142
+ text-align: left;
143
+ line-height: 1.2;
144
+ }
145
+
146
+ .categoryBody {
147
+ min-width: 0;
148
+ padding-bottom: 4px;
149
+ }
150
+
151
+ /*
152
+ * .sliderGroup sets display:flex; without this, that rule wins over the [hidden]
153
+ * attribute and the category body stays visible when “collapsed”.
154
+ */
155
+ .categoryBody[hidden] {
156
+ display: none !important;
157
+ }
158
+
159
+ .category[data-disabled="true"] .categoryBody {
160
+ pointer-events: none;
161
+ }
162
+ /* ValueInput - Unified editable value component */
163
+
164
+ .valueInput {
165
+ display: inline-flex;
166
+ align-items: baseline;
167
+ justify-content: flex-start;
168
+ font-size: 14px;
169
+ font-weight: 400;
170
+ letter-spacing: 0.28px;
171
+ white-space: nowrap;
172
+ cursor: text;
173
+ font-variant-numeric: tabular-nums;
174
+ color: var(--slider-text-muted);
175
+ text-decoration: underline;
176
+ text-decoration-color: transparent;
177
+ text-decoration-thickness: 1px;
178
+ text-underline-offset: 3px;
179
+ transition:
180
+ color 0.2s ease-out,
181
+ text-decoration-color 0.2s ease-out;
182
+ min-width: 0;
183
+ }
184
+
185
+ .valueInput--right {
186
+ justify-content: flex-end;
187
+ text-align: right;
188
+ }
189
+
190
+ /* Editing state removes underline */
191
+ .valueInput[data-editing='true'] {
192
+ text-decoration: none;
193
+ }
194
+
195
+ /* Active state (hovered/dragging) - full opacity text */
196
+ .valueInput[data-active='true'] {
197
+ color: var(--slider-text);
198
+ }
199
+
200
+ .valueInput[data-disabled='true'] {
201
+ cursor: default;
202
+ text-decoration: none;
203
+ color: var(--slider-text-muted);
204
+ pointer-events: none;
205
+ }
206
+
207
+ /* Hover shows underline */
208
+ .valueInput:hover,
209
+ .valueInput:focus-visible {
210
+ text-decoration-color: currentColor;
211
+ }
212
+
213
+ /* Focused element has no outline (underline serves as indicator) */
214
+ .valueInput:focus-visible {
215
+ outline: none;
216
+ }
217
+
218
+ /* Prefix (e.g., "#" for hex) - non-interactive, part of display */
219
+ .valueInputPrefix {
220
+ pointer-events: none;
221
+ user-select: none;
222
+ flex-shrink: 0;
223
+ }
224
+
225
+ /* Suffix (e.g., "%" for percentages) - non-interactive */
226
+ .valueInputSuffix {
227
+ pointer-events: none;
228
+ user-select: none;
229
+ flex-shrink: 0;
230
+ }
231
+
232
+ /* The actual value text */
233
+ .valueInputText {
234
+ display: inline;
235
+ pointer-events: none;
236
+ }
237
+
238
+ /* Hidden measure span for auto-width */
239
+ .valueInputMeasure {
240
+ position: absolute;
241
+ left: 0;
242
+ top: 0;
243
+ visibility: hidden;
244
+ pointer-events: none;
245
+ white-space: pre;
246
+ height: 0;
247
+ overflow: hidden;
248
+ font: inherit;
249
+ font-variant-numeric: tabular-nums;
250
+ letter-spacing: inherit;
251
+ }
252
+
253
+ /* Input field when editing */
254
+ .valueInputField {
255
+ min-width: 0;
256
+ padding: 0;
257
+ margin: 0;
258
+ border: none;
259
+ background: transparent;
260
+ font: inherit;
261
+ font-variant-numeric: tabular-nums;
262
+ letter-spacing: inherit;
263
+ color: var(--slider-text);
264
+ outline: none;
265
+ text-decoration: none;
266
+ cursor: text;
267
+ }
268
+
269
+ .valueInput--right .valueInputField {
270
+ text-align: right;
271
+ }
272
+
273
+ /* Selection styling - white bg, black text */
274
+ .valueInputField::selection {
275
+ background: var(--slider-value-selection-bg);
276
+ color: var(--slider-value-selection-fg);
277
+ }
278
+
279
+ .valueInputField::-moz-selection {
280
+ background: var(--slider-value-selection-bg);
281
+ color: var(--slider-value-selection-fg);
282
+ }
1
283
  /* Slider group - sliders with 4px gap */
2
284
  .sliderGroup {
3
285
  display: flex;
@@ -19,6 +301,14 @@
19
301
  overflow: visible;
20
302
  }
21
303
 
304
+ .sliderCardWrap[data-disabled='true'] {
305
+ opacity: 0.45;
306
+ }
307
+
308
+ .sliderCardWrap[data-disabled='true'] .sliderCard {
309
+ cursor: default;
310
+ }
311
+
22
312
  /* ── Slider card ─────────────────────────────────────────────────────────── */
23
313
 
24
314
  .sliderCard {
@@ -42,7 +332,7 @@
42
332
  -webkit-user-drag: none;
43
333
  }
44
334
 
45
- .sliderCard[data-active='true'] {
335
+ .sliderCard[data-active="true"] {
46
336
  background: var(--slider-surface-active);
47
337
  }
48
338
 
@@ -96,7 +386,7 @@
96
386
  transition: background-color 0.2s ease-out;
97
387
  }
98
388
 
99
- .sliderTrack[data-active='true'] {
389
+ .sliderTrack[data-active="true"] {
100
390
  background: var(--slider-track-active);
101
391
  }
102
392
 
@@ -140,7 +430,7 @@
140
430
  transition: background-color 0.15s ease-out;
141
431
  }
142
432
 
143
- .sliderThumb[data-dragging='true'] {
433
+ .sliderThumb[data-dragging="true"] {
144
434
  background: var(--slider-thumb-dragging);
145
435
  }
146
436
 
@@ -166,6 +456,15 @@
166
456
  display: inline;
167
457
  }
168
458
 
459
+ /* Torph root is inline-block; keep typography aligned with .sliderValue */
460
+ .sliderValueMorph {
461
+ display: inline-block;
462
+ font: inherit;
463
+ font-variant-numeric: tabular-nums;
464
+ letter-spacing: inherit;
465
+ vertical-align: baseline;
466
+ }
467
+
169
468
  /* Invisible copy of value text + typography — used to size the edit field to content */
170
469
  .sliderValueMeasure {
171
470
  position: absolute;
@@ -195,105 +494,268 @@
195
494
  -moz-user-select: none;
196
495
  }
197
496
 
198
- /* Value underline: 1px stroke; color fades with SliderRow motion (0.2s ease-out). */
497
+ /* Slider value - uses ValueInput component, overrides for layout */
199
498
  .sliderValue {
499
+ user-select: none;
500
+ }
501
+
502
+ /*
503
+ * SliderRow-only underline.
504
+ * We render it with a pseudo-element so it doesn't shift layout.
505
+ * (In this slider layout, relying on text-decoration hover can be flaky.)
506
+ */
507
+ .sliderValue .valueInputText {
508
+ position: relative;
509
+ display: inline-block;
510
+ }
511
+
512
+ .sliderValue .valueInputText::after {
513
+ content: "";
514
+ position: absolute;
515
+ left: 0;
516
+ right: 0;
517
+ /* Tuned to visually match ValueInput's text-underline-offset: 3px */
518
+ bottom: 2px;
519
+ height: 1px;
520
+ background: currentColor;
521
+ opacity: 0;
522
+ transition: opacity 0.2s ease-out;
523
+ pointer-events: none;
524
+ }
525
+
526
+ .sliderValueZone:hover .valueInputText::after,
527
+ .sliderValueZone:focus-within .valueInputText::after {
528
+ opacity: 1;
529
+ }
530
+
531
+ .sliderValue .valueInputField {
532
+ position: relative;
533
+ z-index: 4;
534
+ max-width: 100%;
535
+ pointer-events: all;
536
+ -moz-appearance: textfield;
537
+ }
538
+
539
+ .sliderValue .valueInputField::-webkit-inner-spin-button,
540
+ .sliderValue .valueInputField::-webkit-outer-spin-button {
541
+ -webkit-appearance: none;
542
+ margin: 0;
543
+ }
544
+
545
+ /* The actual range input — invisible, covers the full card */
546
+ .sliderInput {
547
+ position: absolute;
548
+ inset: 0;
549
+ width: 100%;
550
+ height: 100%;
551
+ opacity: 0;
552
+ cursor: pointer;
553
+ margin: 0;
554
+ z-index: 2;
555
+ touch-action: none;
556
+ user-select: none;
557
+ -webkit-user-select: none;
558
+ }
559
+ .colorPicker {
560
+ position: relative;
561
+ display: flex;
562
+ flex-direction: column;
563
+ width: 190px;
564
+ box-sizing: border-box;
565
+ background: rgba(10, 10, 10, 0.8);
566
+ backdrop-filter: blur(20px);
567
+ border: 0.5px solid rgba(255, 255, 255, 0.06);
568
+ border-radius: 12px;
569
+ overflow: hidden;
570
+ }
571
+
572
+ .colorPickerSpace {
573
+ display: flex;
574
+ gap: 6px;
575
+ align-items: center;
576
+ padding: 6px 6px 0 6px;
577
+ width: 100%;
578
+ box-sizing: border-box;
579
+ }
580
+
581
+ .colorPickerSv {
582
+ position: relative;
583
+ flex: 1 0 0;
584
+ aspect-ratio: 1 / 1;
585
+ border-radius: 6px;
586
+ overflow: hidden;
587
+ cursor: crosshair;
588
+ touch-action: none;
589
+ outline: none;
590
+ }
591
+
592
+ .colorPickerSv:focus-visible {
593
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
594
+ }
595
+
596
+ .colorPickerSvCanvas {
597
+ display: block;
598
+ width: 100%;
599
+ height: 100%;
600
+ vertical-align: top;
601
+ }
602
+
603
+ .colorPickerHueWrap {
604
+ display: flex;
605
+ flex-direction: row;
606
+ align-items: center;
607
+ align-self: stretch;
608
+ }
609
+
610
+ .colorPickerHue {
611
+ position: relative;
612
+ width: 16px;
613
+ height: 100%;
614
+ border-radius: 6px;
615
+ border: 1px solid rgba(255, 255, 255, 0.06);
616
+ cursor: pointer;
617
+ touch-action: none;
618
+ outline: none;
619
+ box-sizing: border-box;
620
+ }
621
+
622
+ .colorPickerHue:focus-visible {
623
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.25);
624
+ }
625
+
626
+ .colorPickerIndicator {
627
+ position: absolute;
628
+ width: 16px;
629
+ height: 16px;
630
+ margin-left: -8px;
631
+ margin-top: -8px;
632
+ border: 2px solid #ffffff;
633
+ border-radius: 50%;
634
+ box-shadow:
635
+ 0 0 0 0.5px rgba(0, 0, 0, 0.06),
636
+ inset 0 0 0 0.5px rgba(0, 0, 0, 0.06);
637
+ pointer-events: none;
638
+ box-sizing: border-box;
639
+ }
640
+
641
+ .colorPickerFooter {
642
+ display: flex;
643
+ align-items: center;
644
+ justify-content: space-between;
645
+ padding: 6px 6px 6px 12px;
646
+ width: 190px;
647
+ box-sizing: border-box;
648
+ }
649
+
650
+ .colorPickerValueZone {
651
+ display: flex;
652
+ flex: 1 0 0;
653
+ align-items: center;
654
+ min-width: 0;
655
+ }
656
+
657
+ /* Hex value - uses ValueInput component */
658
+ .colorPickerHex {
659
+ font-family: 'SF Compact Rounded', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
660
+ }
661
+
662
+ .colorPickerHex .valueInputField {
663
+ width: 72px;
664
+ }
665
+
666
+ .colorPickerTriplet {
667
+ display: flex;
668
+ align-items: center;
669
+ gap: 10px;
670
+ font-family: 'SF Compact Rounded', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
200
671
  font-size: 14px;
201
- font-weight: 400;
202
- color: var(--slider-text-muted);
672
+ line-height: normal;
203
673
  letter-spacing: 0.28px;
204
- white-space: nowrap;
205
- cursor: text;
206
- text-align: right;
207
- font-variant-numeric: tabular-nums;
208
- user-select: none;
209
- text-decoration: underline;
210
- text-decoration-color: transparent;
211
- text-decoration-thickness: 1px;
212
- text-underline-offset: 3px;
213
- transition:
214
- color 0.2s ease-out,
215
- text-decoration-color 0.2s ease-out;
674
+ color: rgba(255, 255, 255, 0.7);
675
+ }
676
+
677
+ /* Triplet values - uses ValueInput component */
678
+ .colorPickerTripletBtn {
679
+ flex: 0 0 auto;
680
+ width: 3ch;
681
+ }
682
+
683
+ .colorPickerTripletBtn .valueInputField {
684
+ width: 3ch;
685
+ }
686
+
687
+ .colorPickerActions {
688
+ display: flex;
689
+ align-items: center;
690
+ border-radius: 9px;
691
+ flex-shrink: 0;
216
692
  }
217
693
 
218
- .sliderValue[data-active='true'] {
219
- color: var(--slider-text);
694
+ .colorPickerIconBtn {
695
+ display: flex;
696
+ align-items: center;
697
+ justify-content: center;
698
+ width: 26px;
699
+ height: 26px;
700
+ padding: 0;
701
+ margin: 0;
702
+ border: none;
703
+ border-radius: 9px;
704
+ background: transparent;
705
+ color: rgba(255, 255, 255, 0.7);
706
+ cursor: pointer;
707
+ transition: background-color 0.15s ease-out, color 0.15s ease-out;
220
708
  }
221
709
 
222
- .sliderValueZone:hover
223
- .sliderValue:not(.sliderValueMeasure) {
224
- text-decoration-color: currentColor;
710
+ .colorPickerIconBtn:hover {
711
+ background: #141414;
712
+ color: #ffffff;
225
713
  }
226
714
 
227
- /* After .sliderValue so width measurement isn’t affected by underline metrics */
228
- .sliderValue.sliderValueMeasure {
229
- text-decoration: none;
715
+ .colorPickerIconBtn:focus-visible {
716
+ outline: 2px solid rgba(255, 255, 255, 0.3);
717
+ outline-offset: 1px;
230
718
  }
231
719
 
232
- .sliderValueInput {
233
- position: relative;
234
- z-index: 4;
235
- width: auto;
236
- max-width: 100%;
237
- min-width: 22px;
238
- flex-shrink: 0;
239
- background: transparent;
720
+ .colorPickerModeBtn {
721
+ display: inline-flex;
722
+ align-items: center;
723
+ justify-content: center;
724
+ height: 26px;
725
+ padding: 0 6px;
240
726
  border: none;
241
- border-radius: 0;
242
- color: var(--slider-text);
243
- font-family: inherit;
727
+ border-radius: 9px;
728
+ background: transparent;
729
+ color: rgba(255, 255, 255, 0.7);
730
+ font-family: 'SF Compact Rounded', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
244
731
  font-size: 14px;
245
- font-weight: 400;
732
+ line-height: normal;
246
733
  letter-spacing: 0.28px;
247
- text-align: right;
248
- outline: none;
249
- padding: 0;
250
- pointer-events: all;
251
- font-variant-numeric: tabular-nums;
252
- -moz-appearance: textfield;
253
- user-select: text;
254
- -webkit-user-select: text;
255
- -moz-user-select: text;
256
- text-decoration: underline;
257
- text-decoration-color: transparent;
258
- text-decoration-thickness: 1px;
259
- text-underline-offset: 3px;
260
- transition: text-decoration-color 0.2s ease-out;
261
- }
262
-
263
- .sliderValueInput:hover,
264
- .sliderValueInput:focus {
265
- text-decoration-color: currentColor;
266
- }
267
-
268
- .sliderValueInput::selection {
269
- background: var(--slider-value-selection-bg);
270
- color: var(--slider-value-selection-fg);
734
+ cursor: pointer;
735
+ user-select: none;
736
+ transition: background-color 0.15s ease-out, color 0.15s ease-out;
271
737
  }
272
738
 
273
- .sliderValueInput::-moz-selection {
274
- background: var(--slider-value-selection-bg);
275
- color: var(--slider-value-selection-fg);
739
+ .colorPickerModeBtn:hover {
740
+ background: #141414;
741
+ color: #ffffff;
276
742
  }
277
743
 
278
- .sliderValueInput::-webkit-inner-spin-button,
279
- .sliderValueInput::-webkit-outer-spin-button {
280
- -webkit-appearance: none;
281
- margin: 0;
744
+ .colorPickerModeBtn:focus-visible {
745
+ outline: 2px solid rgba(255, 255, 255, 0.3);
746
+ outline-offset: 1px;
282
747
  }
283
748
 
284
- /* The actual range input — invisible, covers the full card */
285
- .sliderInput {
749
+ .colorPickerLiveSr {
286
750
  position: absolute;
287
- inset: 0;
288
- width: 100%;
289
- height: 100%;
290
- opacity: 0;
291
- cursor: pointer;
292
- margin: 0;
293
- z-index: 2;
294
- touch-action: none;
295
- user-select: none;
296
- -webkit-user-select: none;
751
+ width: 1px;
752
+ height: 1px;
753
+ padding: 0;
754
+ margin: -1px;
755
+ overflow: hidden;
756
+ clip: rect(0, 0, 0, 0);
757
+ white-space: nowrap;
758
+ border: 0;
297
759
  }
298
760
  /* Stack above slider rows (they use z-index + transform layers). */
299
761
  .swatchPopoverPortal {
@@ -370,6 +832,13 @@
370
832
  color: inherit;
371
833
  }
372
834
 
835
+ .swatchPopoverBody:has(.colorPicker) {
836
+ font-size: inherit;
837
+ line-height: inherit;
838
+ color: inherit;
839
+ padding: 0;
840
+ }
841
+
373
842
  .swatchPopoverBody p {
374
843
  margin: 0 0 10px;
375
844
  }
@@ -426,6 +895,14 @@
426
895
  overflow: visible;
427
896
  }
428
897
 
898
+ .colorRowWrap[data-disabled='true'] {
899
+ opacity: 0.45;
900
+ }
901
+
902
+ .colorRowWrap[data-disabled='true'] .colorCard {
903
+ pointer-events: none;
904
+ }
905
+
429
906
  .colorCard {
430
907
  position: relative;
431
908
  height: 37px;
@@ -480,93 +957,48 @@
480
957
  max-width: 50%;
481
958
  }
482
959
 
483
- /* Hex cluster mirrors .sliderValue underline + hover rules */
960
+ /* Hex value - uses ValueInput component, just needs layout overrides */
484
961
  .colorRowValue {
485
- display: inline-flex;
486
- align-items: baseline;
487
962
  justify-content: flex-end;
488
- font-size: 14px;
489
- font-weight: 400;
490
- letter-spacing: 0.28px;
491
- white-space: nowrap;
492
- cursor: text;
493
- text-align: right;
494
- font-variant-numeric: tabular-nums;
495
- color: var(--slider-text-muted);
496
- text-decoration: underline;
497
- text-decoration-color: transparent;
498
- text-decoration-thickness: 1px;
499
- text-underline-offset: 3px;
500
- transition:
501
- color 0.2s ease-out,
502
- text-decoration-color 0.2s ease-out;
503
- min-width: 0;
504
- }
505
-
506
- .colorCard[data-active='true'] .colorRowValue {
507
- color: var(--slider-text);
508
- }
509
-
510
- .colorValueZone:hover .colorRowValue {
511
- text-decoration-color: currentColor;
512
- }
513
-
514
- .colorHexHash {
515
- pointer-events: none;
516
- user-select: none;
517
- flex-shrink: 0;
518
- }
519
-
520
- .colorHexDigits {
521
- pointer-events: none;
522
963
  }
523
964
 
524
- .colorHexInput {
965
+ .colorRowValue .valueInputField {
525
966
  width: 6.2ch;
526
- min-width: 0;
527
- padding: 0;
528
- margin: 0;
529
- border: none;
530
- background: transparent;
531
- font: inherit;
532
- font-variant-numeric: tabular-nums;
533
- letter-spacing: 0.28px;
534
- color: var(--slider-text);
535
- text-align: left;
536
- outline: none;
537
- text-decoration: underline;
538
- text-decoration-color: transparent;
539
- text-decoration-thickness: 1px;
540
- text-underline-offset: 3px;
541
- transition: text-decoration-color 0.2s ease-out;
542
- cursor: text;
543
- }
544
-
545
- .colorHexInput:hover,
546
- .colorHexInput:focus {
547
- text-decoration-color: currentColor;
548
- }
549
-
550
- .colorHexInput::selection {
551
- background: var(--slider-value-selection-bg);
552
- color: var(--slider-value-selection-fg);
553
- }
554
-
555
- .colorHexInput::-moz-selection {
556
- background: var(--slider-value-selection-bg);
557
- color: var(--slider-value-selection-fg);
558
967
  }
559
968
 
560
969
  /* 16×16 swatch, native picker trigger; inset 0.5px black @ 20% */
561
970
  .colorSwatchBtn {
562
971
  flex-shrink: 0;
972
+ position: relative;
563
973
  width: 16px;
564
974
  height: 16px;
565
975
  padding: 0;
566
976
  border: none;
567
977
  border-radius: 50%;
568
978
  cursor: pointer;
979
+ background: transparent;
980
+ }
981
+
982
+ .colorSwatchBtn::before {
983
+ content: '';
984
+ position: absolute;
985
+ left: 50%;
986
+ top: 50%;
987
+ width: 16px;
988
+ height: 16px;
989
+ margin-left: -8px;
990
+ margin-top: -8px;
991
+ border-radius: 50%;
992
+ background: var(--swatch-color, #808080);
569
993
  box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.2);
994
+ pointer-events: none;
995
+ }
996
+
997
+ .colorSwatchBtn::after {
998
+ content: '';
999
+ position: absolute;
1000
+ inset: -10px;
1001
+ background: transparent;
570
1002
  }
571
1003
 
572
1004
  .colorSwatchBtn:focus-visible {
@@ -583,6 +1015,15 @@
583
1015
  overflow: visible;
584
1016
  }
585
1017
 
1018
+ .toggleRowWrap[data-disabled='true'] {
1019
+ opacity: 0.45;
1020
+ }
1021
+
1022
+ .toggleRowWrap[data-disabled='true'] .toggleCard {
1023
+ cursor: default;
1024
+ pointer-events: none;
1025
+ }
1026
+
586
1027
  .toggleCard {
587
1028
  position: relative;
588
1029
  height: 37px;
@@ -704,6 +1145,18 @@
704
1145
  border-radius: 12px;
705
1146
  }
706
1147
 
1148
+ /* Top preview strip: full-width 32px with 6px padding (no bottom padding) */
1149
+ .gradientPickerPreviewWrap {
1150
+ padding: 6px 6px 0 6px;
1151
+ }
1152
+
1153
+ .gradientPickerPreview {
1154
+ height: 32px;
1155
+ width: 100%;
1156
+ border-radius: 8px;
1157
+ box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.08);
1158
+ }
1159
+
707
1160
  /* Header row */
708
1161
  .gradientPickerHeader {
709
1162
  display: flex;
@@ -712,7 +1165,7 @@
712
1165
  padding: 6px 6px 2px 6px;
713
1166
  }
714
1167
 
715
- /* Left icons group (shuffle + invert) */
1168
+ /* Left icons group (randomize + invert) */
716
1169
  .gradientPickerHeaderIconsLeft {
717
1170
  display: flex;
718
1171
  align-items: center;
@@ -794,109 +1247,27 @@
794
1247
  outline-offset: 2px;
795
1248
  }
796
1249
 
797
- /* Hex text display - matches ColorRow styling */
798
- .gradientPickerStopHex {
799
- display: inline-flex;
800
- align-items: baseline;
801
- font-size: 14px;
802
- font-weight: 400;
803
- font-variant-numeric: tabular-nums;
804
- letter-spacing: 0.28px;
805
- white-space: nowrap;
806
- color: rgba(255, 255, 255, 0.7);
807
- cursor: text;
808
- transition: color 0.2s ease-out;
809
- }
810
-
811
- /* Hash is not selectable */
812
- .gradientPickerStopHexHash {
813
- pointer-events: none;
814
- user-select: none;
815
- flex-shrink: 0;
816
- }
817
-
818
- /* Only the digits get the underline */
819
- .gradientPickerStopHexDigits {
820
- text-decoration: underline;
821
- text-decoration-color: transparent;
822
- text-decoration-thickness: 1px;
823
- text-underline-offset: 3px;
824
- transition: text-decoration-color 0.2s ease-out;
825
- }
826
-
827
- .gradientPickerStopHex:hover .gradientPickerStopHexDigits,
828
- .gradientPickerStopHex:focus .gradientPickerStopHexDigits {
829
- text-decoration-color: currentColor;
830
- }
831
-
832
- /* Wrapper for editing state with hash + input */
833
- .gradientPickerStopHexWrap {
834
- display: inline-flex;
835
- align-items: baseline;
836
- font-size: 14px;
837
- font-weight: 400;
838
- font-variant-numeric: tabular-nums;
839
- letter-spacing: 0.28px;
840
- color: rgba(255, 255, 255, 0.7);
841
- }
842
-
843
- /* Hex input when editing */
844
- .gradientPickerStopHexInput {
1250
+ /* Hex value - uses ValueInput component */
1251
+ .gradientPickerStopHex .valueInputField {
845
1252
  width: 58px;
846
- min-width: 0;
847
- padding: 0;
848
- margin: 0;
849
- border: none;
850
- background: transparent;
851
- font: inherit;
852
- font-size: 14px;
853
- font-variant-numeric: tabular-nums;
854
- letter-spacing: 0.28px;
855
- color: #ffffff;
856
- text-align: left;
857
- outline: none;
858
- cursor: text;
859
- text-decoration: underline;
860
- text-decoration-color: currentColor;
861
- text-decoration-thickness: 1px;
862
- text-underline-offset: 3px;
863
1253
  }
864
1254
 
865
- .gradientPickerStopHexInput::selection {
866
- background: #ffffff;
867
- color: #000000;
868
- }
869
-
870
- /* Delete/minus button - positioned absolutely */
871
- .gradientPickerStopDelete {
1255
+ /* Delete/minus: same 26×26 hover shell as header icons; positioned in row */
1256
+ .gradientPickerStopDelete.gradientPickerIconBtn {
872
1257
  position: absolute;
873
- right: 12px;
874
- top: 12px;
875
- display: flex;
876
- align-items: center;
877
- justify-content: center;
878
- width: 14px;
879
- height: 14px;
880
- padding: 0;
881
- border: none;
882
- background: transparent;
883
- color: rgba(255, 255, 255, 0.7);
884
- cursor: pointer;
885
- transition: color 0.15s ease-out, opacity 0.15s ease-out;
886
- }
887
-
888
- .gradientPickerStopDelete:hover:not(:disabled) {
889
- color: #ffffff;
1258
+ right: 6px;
1259
+ top: 50%;
1260
+ transform: translateY(-50%);
890
1261
  }
891
1262
 
892
- .gradientPickerStopDelete:disabled {
1263
+ .gradientPickerStopDelete.gradientPickerIconBtn:disabled {
893
1264
  opacity: 0.3;
894
1265
  cursor: not-allowed;
895
1266
  }
896
1267
 
897
- .gradientPickerStopDelete:focus-visible {
898
- outline: 2px solid rgba(255, 255, 255, 0.5);
899
- outline-offset: 2px;
1268
+ .gradientPickerStopDelete.gradientPickerIconBtn:disabled:hover {
1269
+ background: transparent;
1270
+ color: rgba(255, 255, 255, 0.7);
900
1271
  }
901
1272
  /* Same shell as ColorRow; swatch only (no hex column). */
902
1273
 
@@ -908,6 +1279,14 @@
908
1279
  overflow: visible;
909
1280
  }
910
1281
 
1282
+ .gradientRowWrap[data-disabled='true'] {
1283
+ opacity: 0.45;
1284
+ }
1285
+
1286
+ .gradientRowWrap[data-disabled='true'] .gradientCard {
1287
+ pointer-events: none;
1288
+ }
1289
+
911
1290
  .gradientCard {
912
1291
  position: relative;
913
1292
  height: 37px;