@hanzo/ui 8.27.53 → 8.27.54

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/gallery.html CHANGED
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.27.53</title><style>/* @hanzo/ui — generated by scripts/gen-css.mjs. Do not edit. */
1
+ <!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.27.54</title><style>/* @hanzo/ui — generated by scripts/gen-css.mjs. Do not edit. */
2
2
  :root { --hanzo-ui-styles: 1; }
3
3
  /* Hanzo Design System — the entry point. Import THIS one file.
4
4
  *
@@ -1154,34 +1154,35 @@
1154
1154
  ::selection{background:var(--selection);color:var(--text-primary)}
1155
1155
 
1156
1156
  /* ——— the scrollbar ———
1157
- The single largest piece of UNSTYLED chrome left on a dark surface: a
1158
- default 15px light-grey scrollbar down the side of a #0a0a0a panel is the
1159
- one element on the page that did not get the memo, and it is visible on
1160
- every scrolling surface in the product. 6px, no track, thumb on the same
1161
- hairline ladder as everything else. Both syntaxes ship because they are
1162
- disjoint — `scrollbar-*` is Firefox and the `::-webkit-*` pseudos are
1163
- Chromium/Safari; neither engine reads the other.
1157
+ 6px, no track, no stepper buttons, the thumb on the same hairline ladder as
1158
+ everything else. ONE treatment per engine. Chromium 121+ reads the standard
1159
+ `scrollbar-color`/`scrollbar-width` as well as the `::-webkit-*` pseudos,
1160
+ and an element with either standard property set ignores its pseudos —
1161
+ `scrollbar-color` inherits, so stated on html it gives every scroller the
1162
+ native bar, which on Linux/GTK draws a boxed arrow at each end. So the
1163
+ standard pair goes only to an engine without the pseudos (Firefox), and the
1164
+ pseudos serve the rest. Check 1e holds that.
1164
1165
  The thumb is a --white-* rung, so it does not invert; the `.light`
1165
1166
  restatements sit here rather than in colors.css because a scrollbar is an
1166
1167
  element default and this file is where element defaults live. Everything
1167
1168
  stays INSIDE the layer — an unlayered rule here would outrank an app's own
1168
1169
  utilities, which is the defect check 1c exists to catch. */
1169
- :where(html){scrollbar-color:var(--white-15) transparent;scrollbar-width:thin}
1170
- .light, :root.t_light, .t_light{scrollbar-color:rgb(0 0 0 / .18) transparent}
1170
+ @supports not selector(::-webkit-scrollbar){
1171
+ :where(html){scrollbar-color:var(--white-15) transparent;scrollbar-width:thin}
1172
+ .light, :root.t_light, .t_light{scrollbar-color:rgb(0 0 0 / .18) transparent}
1173
+ }
1171
1174
  :where(*)::-webkit-scrollbar{width:6px;height:6px}
1172
1175
  :where(*)::-webkit-scrollbar-track{background:transparent}
1173
1176
  :where(*)::-webkit-scrollbar-thumb{background:var(--white-15);border-radius:var(--radius-full)}
1174
1177
  :where(*)::-webkit-scrollbar-thumb:hover{background:var(--white-30)}
1175
1178
  :where(*)::-webkit-scrollbar-corner{background:transparent}
1176
- /* The stepper arrows, and they are a LINUX defect specifically. Chromium on
1177
- macOS draws no buttons, so styling the track and thumb looks finished there
1178
- and ships a classic GTK scrollbar — a boxed arrow at each end of every
1179
- scroller, on both axes — to everyone on Ubuntu. Styling the other pseudos
1180
- does not suppress them; only this does. Zero width AND height because the
1181
- horizontal and vertical bars each read one of them. */
1179
+ /* The steppers. Styling the other pseudos does not remove them; only this
1180
+ does. Zero width AND height because each axis reads one of them. */
1182
1181
  :where(*)::-webkit-scrollbar-button{display:none;width:0;height:0}
1183
- .light :where(*)::-webkit-scrollbar-thumb{background:rgb(0 0 0 / .18)}
1184
- .light :where(*)::-webkit-scrollbar-thumb:hover{background:rgb(0 0 0 / .32)}
1182
+ /* `.light` itself as well as its subtree: with the theme class on <html>,
1183
+ html's own pseudos draw the page's scrollbar. */
1184
+ .light::-webkit-scrollbar-thumb,.light :where(*)::-webkit-scrollbar-thumb{background:rgb(0 0 0 / .18)}
1185
+ .light::-webkit-scrollbar-thumb:hover,.light :where(*)::-webkit-scrollbar-thumb:hover{background:rgb(0 0 0 / .32)}
1185
1186
  }
1186
1187
 
1187
1188
  /**
@@ -2042,166 +2043,8 @@
2042
2043
  }
2043
2044
 
2044
2045
 
2045
- /* ─────────────────────────────────────────────────────────────────────────────
2046
- Scrollbars, on the surfaces this package scrolls.
2047
-
2048
- Left to the platform this is not neutral: Linux/GTK Chrome draws a wide track
2049
- with STEPPER ARROWS at both ends, so a dark product grows two grey buttons per
2050
- scroll region. Windows draws a wide light track. macOS overlays a thin one,
2051
- which is the behaviour the other two should have had.
2052
-
2053
- THE TWO HALVES MUST NOT BE DECLARED TOGETHER, and that is the whole subtlety.
2054
- Chromium supports both the standard properties and the `::-webkit-scrollbar`
2055
- pseudo-elements — but the moment `scrollbar-width` or `scrollbar-color` is
2056
- anything other than `auto`, it takes the standard path and DISCARDS the entire
2057
- webkit block. Shipping both is how 8.1.19 removed nothing: measured headed on
2058
- Linux, as-shipped gave a 10px gutter with arrows, while the authored webkit
2059
- rule alone gives 8px with none. Isolated: webkit-only 8px no arrows;
2060
- standard-only 10px arrows; both together 10px arrows.
2061
-
2062
- Neither half is redundant, so neither can simply be deleted — Firefox
2063
- implements ONLY the standard properties, Safari ONLY the webkit ones. They are
2064
- separated by engine instead: the webkit block applies wherever the selector is
2065
- understood, and the standard properties apply only where it is not.
2066
-
2067
- And it is invisible headless. Chromium's headless shell paints OVERLAY
2068
- scrollbars, so nothing is drawn, `offsetWidth - clientWidth` is 0 on a blank
2069
- page, and `getComputedStyle(el, '::-webkit-scrollbar-button').display` happily
2070
- reports `none` for a rule that never ran. This must be checked headed.
2071
- ───────────────────────────────────────────────────────────────────────────── */
2072
-
2073
- /* Firefox and anything else with no webkit pseudo-elements. */
2074
- @supports not selector(::-webkit-scrollbar) {
2075
- :where(
2076
- [data-slot='fill'],
2077
- [data-slot='thread'],
2078
- [data-slot='sources-strip'],
2079
- [data-slot='sidebar-scroll'],
2080
- [data-slot='scroll-area-viewport'],
2081
- [data-slot='textarea'],
2082
- [data-slot='composer-field']
2083
- ) {
2084
- scrollbar-width: thin;
2085
- scrollbar-color: rgb(255 255 255 / 0.18) transparent;
2086
- }
2087
- .t_light :where(
2088
- [data-slot='fill'],
2089
- [data-slot='thread'],
2090
- [data-slot='sources-strip'],
2091
- [data-slot='sidebar-scroll'],
2092
- [data-slot='scroll-area-viewport'],
2093
- [data-slot='textarea'],
2094
- [data-slot='composer-field']
2095
- ) { scrollbar-color: rgb(0 0 0 / 0.20) transparent; }
2096
- }
2097
-
2098
- /* Chromium and Safari.
2099
- The first rule is the load-bearing one and it is a RESET, not a style.
2100
- @hanzo/design sets `scrollbar-color` and `scrollbar-width` on `:where(html)`
2101
- (theme.css), and both INHERIT — so every element in the document already
2102
- carries a non-`auto` value, Chromium takes the standard path, and the whole
2103
- webkit block below is discarded before it is read. Nothing declared here can
2104
- win until the inherited value is put back to `auto` on the element itself.
2105
- That is why the arrows survived 8.1.19: the competing declaration was one
2106
- level up and inherited, not a rule anyone would find in this file. */
2107
- @supports selector(::-webkit-scrollbar) {
2108
- :where(
2109
- [data-slot='fill'],
2110
- [data-slot='thread'],
2111
- [data-slot='sources-strip'],
2112
- [data-slot='sidebar-scroll'],
2113
- [data-slot='scroll-area-viewport'],
2114
- [data-slot='textarea'],
2115
- [data-slot='composer-field']
2116
- ) {
2117
- scrollbar-width: auto;
2118
- scrollbar-color: auto;
2119
- }
2120
-
2121
- :where(
2122
- [data-slot='fill'],
2123
- [data-slot='thread'],
2124
- [data-slot='sources-strip'],
2125
- [data-slot='sidebar-scroll'],
2126
- [data-slot='scroll-area-viewport'],
2127
- [data-slot='textarea'],
2128
- [data-slot='composer-field']
2129
- )::-webkit-scrollbar { width: 8px; height: 8px; }
2130
-
2131
- /* The steppers. This is the rule that removes the arrows, and the reason the
2132
- two halves had to be separated at all. */
2133
- :where(
2134
- [data-slot='fill'],
2135
- [data-slot='thread'],
2136
- [data-slot='sources-strip'],
2137
- [data-slot='sidebar-scroll'],
2138
- [data-slot='scroll-area-viewport'],
2139
- [data-slot='textarea'],
2140
- [data-slot='composer-field']
2141
- )::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
2142
-
2143
- :where(
2144
- [data-slot='fill'],
2145
- [data-slot='thread'],
2146
- [data-slot='sources-strip'],
2147
- [data-slot='sidebar-scroll'],
2148
- [data-slot='scroll-area-viewport'],
2149
- [data-slot='textarea'],
2150
- [data-slot='composer-field']
2151
- )::-webkit-scrollbar-track { background: transparent; }
2152
-
2153
- :where(
2154
- [data-slot='fill'],
2155
- [data-slot='thread'],
2156
- [data-slot='sources-strip'],
2157
- [data-slot='sidebar-scroll'],
2158
- [data-slot='scroll-area-viewport'],
2159
- [data-slot='textarea'],
2160
- [data-slot='composer-field']
2161
- )::-webkit-scrollbar-thumb {
2162
- background: rgb(255 255 255 / 0.18);
2163
- border-radius: 999px;
2164
- /* A transparent border with background-clip keeps the thumb off the very
2165
- edge without a track colour doing it, so it reads as an overlay rather
2166
- than a channel. */
2167
- border: 2px solid transparent;
2168
- background-clip: content-box;
2169
- }
2170
- :where(
2171
- [data-slot='fill'],
2172
- [data-slot='thread'],
2173
- [data-slot='sources-strip'],
2174
- [data-slot='sidebar-scroll'],
2175
- [data-slot='scroll-area-viewport'],
2176
- [data-slot='textarea'],
2177
- [data-slot='composer-field']
2178
- )::-webkit-scrollbar-thumb:hover {
2179
- background: rgb(255 255 255 / 0.30);
2180
- background-clip: content-box;
2181
- }
2182
- :where(
2183
- [data-slot='fill'],
2184
- [data-slot='thread'],
2185
- [data-slot='sources-strip'],
2186
- [data-slot='sidebar-scroll'],
2187
- [data-slot='scroll-area-viewport'],
2188
- [data-slot='textarea'],
2189
- [data-slot='composer-field']
2190
- )::-webkit-scrollbar-corner { background: transparent; }
2191
-
2192
- .t_light :where(
2193
- [data-slot='fill'],
2194
- [data-slot='thread'],
2195
- [data-slot='sources-strip'],
2196
- [data-slot='sidebar-scroll'],
2197
- [data-slot='scroll-area-viewport'],
2198
- [data-slot='textarea'],
2199
- [data-slot='composer-field']
2200
- )::-webkit-scrollbar-thumb {
2201
- background: rgb(0 0 0 / 0.20);
2202
- background-clip: content-box;
2203
- }
2204
- }
2046
+ /* Scrollbars are @hanzo/design's (base.css, ≥ 0.5.34): a thin thumb on every
2047
+ scroller and no stepper buttons, stated once for the page. */
2205
2048
 
2206
2049
  /* A carousel scrolls but shows no bar: the arrows and the snap already say it
2207
2050
  scrolls, and a bar appearing mid-drag shifts the slides under the pointer.
@@ -2773,166 +2616,8 @@ a svg,
2773
2616
  }
2774
2617
 
2775
2618
 
2776
- /* ─────────────────────────────────────────────────────────────────────────────
2777
- Scrollbars, on the surfaces this package scrolls.
2778
-
2779
- Left to the platform this is not neutral: Linux/GTK Chrome draws a wide track
2780
- with STEPPER ARROWS at both ends, so a dark product grows two grey buttons per
2781
- scroll region. Windows draws a wide light track. macOS overlays a thin one,
2782
- which is the behaviour the other two should have had.
2783
-
2784
- THE TWO HALVES MUST NOT BE DECLARED TOGETHER, and that is the whole subtlety.
2785
- Chromium supports both the standard properties and the `::-webkit-scrollbar`
2786
- pseudo-elements — but the moment `scrollbar-width` or `scrollbar-color` is
2787
- anything other than `auto`, it takes the standard path and DISCARDS the entire
2788
- webkit block. Shipping both is how 8.1.19 removed nothing: measured headed on
2789
- Linux, as-shipped gave a 10px gutter with arrows, while the authored webkit
2790
- rule alone gives 8px with none. Isolated: webkit-only 8px no arrows;
2791
- standard-only 10px arrows; both together 10px arrows.
2792
-
2793
- Neither half is redundant, so neither can simply be deleted — Firefox
2794
- implements ONLY the standard properties, Safari ONLY the webkit ones. They are
2795
- separated by engine instead: the webkit block applies wherever the selector is
2796
- understood, and the standard properties apply only where it is not.
2797
-
2798
- And it is invisible headless. Chromium's headless shell paints OVERLAY
2799
- scrollbars, so nothing is drawn, `offsetWidth - clientWidth` is 0 on a blank
2800
- page, and `getComputedStyle(el, '::-webkit-scrollbar-button').display` happily
2801
- reports `none` for a rule that never ran. This must be checked headed.
2802
- ───────────────────────────────────────────────────────────────────────────── */
2803
-
2804
- /* Firefox and anything else with no webkit pseudo-elements. */
2805
- @supports not selector(::-webkit-scrollbar) {
2806
- :where(
2807
- [data-slot='fill'],
2808
- [data-slot='thread'],
2809
- [data-slot='sources-strip'],
2810
- [data-slot='sidebar-scroll'],
2811
- [data-slot='scroll-area-viewport'],
2812
- [data-slot='textarea'],
2813
- [data-slot='composer-field']
2814
- ) {
2815
- scrollbar-width: thin;
2816
- scrollbar-color: rgb(255 255 255 / 0.18) transparent;
2817
- }
2818
- .t_light :where(
2819
- [data-slot='fill'],
2820
- [data-slot='thread'],
2821
- [data-slot='sources-strip'],
2822
- [data-slot='sidebar-scroll'],
2823
- [data-slot='scroll-area-viewport'],
2824
- [data-slot='textarea'],
2825
- [data-slot='composer-field']
2826
- ) { scrollbar-color: rgb(0 0 0 / 0.20) transparent; }
2827
- }
2828
-
2829
- /* Chromium and Safari.
2830
- The first rule is the load-bearing one and it is a RESET, not a style.
2831
- @hanzo/design sets `scrollbar-color` and `scrollbar-width` on `:where(html)`
2832
- (theme.css), and both INHERIT — so every element in the document already
2833
- carries a non-`auto` value, Chromium takes the standard path, and the whole
2834
- webkit block below is discarded before it is read. Nothing declared here can
2835
- win until the inherited value is put back to `auto` on the element itself.
2836
- That is why the arrows survived 8.1.19: the competing declaration was one
2837
- level up and inherited, not a rule anyone would find in this file. */
2838
- @supports selector(::-webkit-scrollbar) {
2839
- :where(
2840
- [data-slot='fill'],
2841
- [data-slot='thread'],
2842
- [data-slot='sources-strip'],
2843
- [data-slot='sidebar-scroll'],
2844
- [data-slot='scroll-area-viewport'],
2845
- [data-slot='textarea'],
2846
- [data-slot='composer-field']
2847
- ) {
2848
- scrollbar-width: auto;
2849
- scrollbar-color: auto;
2850
- }
2851
-
2852
- :where(
2853
- [data-slot='fill'],
2854
- [data-slot='thread'],
2855
- [data-slot='sources-strip'],
2856
- [data-slot='sidebar-scroll'],
2857
- [data-slot='scroll-area-viewport'],
2858
- [data-slot='textarea'],
2859
- [data-slot='composer-field']
2860
- )::-webkit-scrollbar { width: 8px; height: 8px; }
2861
-
2862
- /* The steppers. This is the rule that removes the arrows, and the reason the
2863
- two halves had to be separated at all. */
2864
- :where(
2865
- [data-slot='fill'],
2866
- [data-slot='thread'],
2867
- [data-slot='sources-strip'],
2868
- [data-slot='sidebar-scroll'],
2869
- [data-slot='scroll-area-viewport'],
2870
- [data-slot='textarea'],
2871
- [data-slot='composer-field']
2872
- )::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
2873
-
2874
- :where(
2875
- [data-slot='fill'],
2876
- [data-slot='thread'],
2877
- [data-slot='sources-strip'],
2878
- [data-slot='sidebar-scroll'],
2879
- [data-slot='scroll-area-viewport'],
2880
- [data-slot='textarea'],
2881
- [data-slot='composer-field']
2882
- )::-webkit-scrollbar-track { background: transparent; }
2883
-
2884
- :where(
2885
- [data-slot='fill'],
2886
- [data-slot='thread'],
2887
- [data-slot='sources-strip'],
2888
- [data-slot='sidebar-scroll'],
2889
- [data-slot='scroll-area-viewport'],
2890
- [data-slot='textarea'],
2891
- [data-slot='composer-field']
2892
- )::-webkit-scrollbar-thumb {
2893
- background: rgb(255 255 255 / 0.18);
2894
- border-radius: 999px;
2895
- /* A transparent border with background-clip keeps the thumb off the very
2896
- edge without a track colour doing it, so it reads as an overlay rather
2897
- than a channel. */
2898
- border: 2px solid transparent;
2899
- background-clip: content-box;
2900
- }
2901
- :where(
2902
- [data-slot='fill'],
2903
- [data-slot='thread'],
2904
- [data-slot='sources-strip'],
2905
- [data-slot='sidebar-scroll'],
2906
- [data-slot='scroll-area-viewport'],
2907
- [data-slot='textarea'],
2908
- [data-slot='composer-field']
2909
- )::-webkit-scrollbar-thumb:hover {
2910
- background: rgb(255 255 255 / 0.30);
2911
- background-clip: content-box;
2912
- }
2913
- :where(
2914
- [data-slot='fill'],
2915
- [data-slot='thread'],
2916
- [data-slot='sources-strip'],
2917
- [data-slot='sidebar-scroll'],
2918
- [data-slot='scroll-area-viewport'],
2919
- [data-slot='textarea'],
2920
- [data-slot='composer-field']
2921
- )::-webkit-scrollbar-corner { background: transparent; }
2922
-
2923
- .t_light :where(
2924
- [data-slot='fill'],
2925
- [data-slot='thread'],
2926
- [data-slot='sources-strip'],
2927
- [data-slot='sidebar-scroll'],
2928
- [data-slot='scroll-area-viewport'],
2929
- [data-slot='textarea'],
2930
- [data-slot='composer-field']
2931
- )::-webkit-scrollbar-thumb {
2932
- background: rgb(0 0 0 / 0.20);
2933
- background-clip: content-box;
2934
- }
2935
- }
2619
+ /* Scrollbars are @hanzo/design's (base.css, ≥ 0.5.34): a thin thumb on every
2620
+ scroller and no stepper buttons, stated once for the page. */
2936
2621
 
2937
2622
  /* A carousel scrolls but shows no bar: the arrows and the snap already say it
2938
2623
  scrolls, and a bar appearing mid-drag shifts the slides under the pointer.
@@ -189,166 +189,8 @@
189
189
  }
190
190
 
191
191
 
192
- /* ─────────────────────────────────────────────────────────────────────────────
193
- Scrollbars, on the surfaces this package scrolls.
194
-
195
- Left to the platform this is not neutral: Linux/GTK Chrome draws a wide track
196
- with STEPPER ARROWS at both ends, so a dark product grows two grey buttons per
197
- scroll region. Windows draws a wide light track. macOS overlays a thin one,
198
- which is the behaviour the other two should have had.
199
-
200
- THE TWO HALVES MUST NOT BE DECLARED TOGETHER, and that is the whole subtlety.
201
- Chromium supports both the standard properties and the `::-webkit-scrollbar`
202
- pseudo-elements — but the moment `scrollbar-width` or `scrollbar-color` is
203
- anything other than `auto`, it takes the standard path and DISCARDS the entire
204
- webkit block. Shipping both is how 8.1.19 removed nothing: measured headed on
205
- Linux, as-shipped gave a 10px gutter with arrows, while the authored webkit
206
- rule alone gives 8px with none. Isolated: webkit-only 8px no arrows;
207
- standard-only 10px arrows; both together 10px arrows.
208
-
209
- Neither half is redundant, so neither can simply be deleted — Firefox
210
- implements ONLY the standard properties, Safari ONLY the webkit ones. They are
211
- separated by engine instead: the webkit block applies wherever the selector is
212
- understood, and the standard properties apply only where it is not.
213
-
214
- And it is invisible headless. Chromium's headless shell paints OVERLAY
215
- scrollbars, so nothing is drawn, `offsetWidth - clientWidth` is 0 on a blank
216
- page, and `getComputedStyle(el, '::-webkit-scrollbar-button').display` happily
217
- reports `none` for a rule that never ran. This must be checked headed.
218
- ───────────────────────────────────────────────────────────────────────────── */
219
-
220
- /* Firefox and anything else with no webkit pseudo-elements. */
221
- @supports not selector(::-webkit-scrollbar) {
222
- :where(
223
- [data-slot='fill'],
224
- [data-slot='thread'],
225
- [data-slot='sources-strip'],
226
- [data-slot='sidebar-scroll'],
227
- [data-slot='scroll-area-viewport'],
228
- [data-slot='textarea'],
229
- [data-slot='composer-field']
230
- ) {
231
- scrollbar-width: thin;
232
- scrollbar-color: rgb(255 255 255 / 0.18) transparent;
233
- }
234
- .t_light :where(
235
- [data-slot='fill'],
236
- [data-slot='thread'],
237
- [data-slot='sources-strip'],
238
- [data-slot='sidebar-scroll'],
239
- [data-slot='scroll-area-viewport'],
240
- [data-slot='textarea'],
241
- [data-slot='composer-field']
242
- ) { scrollbar-color: rgb(0 0 0 / 0.20) transparent; }
243
- }
244
-
245
- /* Chromium and Safari.
246
- The first rule is the load-bearing one and it is a RESET, not a style.
247
- @hanzo/design sets `scrollbar-color` and `scrollbar-width` on `:where(html)`
248
- (theme.css), and both INHERIT — so every element in the document already
249
- carries a non-`auto` value, Chromium takes the standard path, and the whole
250
- webkit block below is discarded before it is read. Nothing declared here can
251
- win until the inherited value is put back to `auto` on the element itself.
252
- That is why the arrows survived 8.1.19: the competing declaration was one
253
- level up and inherited, not a rule anyone would find in this file. */
254
- @supports selector(::-webkit-scrollbar) {
255
- :where(
256
- [data-slot='fill'],
257
- [data-slot='thread'],
258
- [data-slot='sources-strip'],
259
- [data-slot='sidebar-scroll'],
260
- [data-slot='scroll-area-viewport'],
261
- [data-slot='textarea'],
262
- [data-slot='composer-field']
263
- ) {
264
- scrollbar-width: auto;
265
- scrollbar-color: auto;
266
- }
267
-
268
- :where(
269
- [data-slot='fill'],
270
- [data-slot='thread'],
271
- [data-slot='sources-strip'],
272
- [data-slot='sidebar-scroll'],
273
- [data-slot='scroll-area-viewport'],
274
- [data-slot='textarea'],
275
- [data-slot='composer-field']
276
- )::-webkit-scrollbar { width: 8px; height: 8px; }
277
-
278
- /* The steppers. This is the rule that removes the arrows, and the reason the
279
- two halves had to be separated at all. */
280
- :where(
281
- [data-slot='fill'],
282
- [data-slot='thread'],
283
- [data-slot='sources-strip'],
284
- [data-slot='sidebar-scroll'],
285
- [data-slot='scroll-area-viewport'],
286
- [data-slot='textarea'],
287
- [data-slot='composer-field']
288
- )::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
289
-
290
- :where(
291
- [data-slot='fill'],
292
- [data-slot='thread'],
293
- [data-slot='sources-strip'],
294
- [data-slot='sidebar-scroll'],
295
- [data-slot='scroll-area-viewport'],
296
- [data-slot='textarea'],
297
- [data-slot='composer-field']
298
- )::-webkit-scrollbar-track { background: transparent; }
299
-
300
- :where(
301
- [data-slot='fill'],
302
- [data-slot='thread'],
303
- [data-slot='sources-strip'],
304
- [data-slot='sidebar-scroll'],
305
- [data-slot='scroll-area-viewport'],
306
- [data-slot='textarea'],
307
- [data-slot='composer-field']
308
- )::-webkit-scrollbar-thumb {
309
- background: rgb(255 255 255 / 0.18);
310
- border-radius: 999px;
311
- /* A transparent border with background-clip keeps the thumb off the very
312
- edge without a track colour doing it, so it reads as an overlay rather
313
- than a channel. */
314
- border: 2px solid transparent;
315
- background-clip: content-box;
316
- }
317
- :where(
318
- [data-slot='fill'],
319
- [data-slot='thread'],
320
- [data-slot='sources-strip'],
321
- [data-slot='sidebar-scroll'],
322
- [data-slot='scroll-area-viewport'],
323
- [data-slot='textarea'],
324
- [data-slot='composer-field']
325
- )::-webkit-scrollbar-thumb:hover {
326
- background: rgb(255 255 255 / 0.30);
327
- background-clip: content-box;
328
- }
329
- :where(
330
- [data-slot='fill'],
331
- [data-slot='thread'],
332
- [data-slot='sources-strip'],
333
- [data-slot='sidebar-scroll'],
334
- [data-slot='scroll-area-viewport'],
335
- [data-slot='textarea'],
336
- [data-slot='composer-field']
337
- )::-webkit-scrollbar-corner { background: transparent; }
338
-
339
- .t_light :where(
340
- [data-slot='fill'],
341
- [data-slot='thread'],
342
- [data-slot='sources-strip'],
343
- [data-slot='sidebar-scroll'],
344
- [data-slot='scroll-area-viewport'],
345
- [data-slot='textarea'],
346
- [data-slot='composer-field']
347
- )::-webkit-scrollbar-thumb {
348
- background: rgb(0 0 0 / 0.20);
349
- background-clip: content-box;
350
- }
351
- }
192
+ /* Scrollbars are @hanzo/design's (base.css, ≥ 0.5.34): a thin thumb on every
193
+ scroller and no stepper buttons, stated once for the page. */
352
194
 
353
195
  /* A carousel scrolls but shows no bar: the arrows and the snap already say it
354
196
  scrolls, and a bar appearing mid-drag shifts the slides under the pointer.
package/dist/styles.css CHANGED
@@ -1154,34 +1154,35 @@
1154
1154
  ::selection{background:var(--selection);color:var(--text-primary)}
1155
1155
 
1156
1156
  /* ——— the scrollbar ———
1157
- The single largest piece of UNSTYLED chrome left on a dark surface: a
1158
- default 15px light-grey scrollbar down the side of a #0a0a0a panel is the
1159
- one element on the page that did not get the memo, and it is visible on
1160
- every scrolling surface in the product. 6px, no track, thumb on the same
1161
- hairline ladder as everything else. Both syntaxes ship because they are
1162
- disjoint — `scrollbar-*` is Firefox and the `::-webkit-*` pseudos are
1163
- Chromium/Safari; neither engine reads the other.
1157
+ 6px, no track, no stepper buttons, the thumb on the same hairline ladder as
1158
+ everything else. ONE treatment per engine. Chromium 121+ reads the standard
1159
+ `scrollbar-color`/`scrollbar-width` as well as the `::-webkit-*` pseudos,
1160
+ and an element with either standard property set ignores its pseudos —
1161
+ `scrollbar-color` inherits, so stated on html it gives every scroller the
1162
+ native bar, which on Linux/GTK draws a boxed arrow at each end. So the
1163
+ standard pair goes only to an engine without the pseudos (Firefox), and the
1164
+ pseudos serve the rest. Check 1e holds that.
1164
1165
  The thumb is a --white-* rung, so it does not invert; the `.light`
1165
1166
  restatements sit here rather than in colors.css because a scrollbar is an
1166
1167
  element default and this file is where element defaults live. Everything
1167
1168
  stays INSIDE the layer — an unlayered rule here would outrank an app's own
1168
1169
  utilities, which is the defect check 1c exists to catch. */
1169
- :where(html){scrollbar-color:var(--white-15) transparent;scrollbar-width:thin}
1170
- .light, :root.t_light, .t_light{scrollbar-color:rgb(0 0 0 / .18) transparent}
1170
+ @supports not selector(::-webkit-scrollbar){
1171
+ :where(html){scrollbar-color:var(--white-15) transparent;scrollbar-width:thin}
1172
+ .light, :root.t_light, .t_light{scrollbar-color:rgb(0 0 0 / .18) transparent}
1173
+ }
1171
1174
  :where(*)::-webkit-scrollbar{width:6px;height:6px}
1172
1175
  :where(*)::-webkit-scrollbar-track{background:transparent}
1173
1176
  :where(*)::-webkit-scrollbar-thumb{background:var(--white-15);border-radius:var(--radius-full)}
1174
1177
  :where(*)::-webkit-scrollbar-thumb:hover{background:var(--white-30)}
1175
1178
  :where(*)::-webkit-scrollbar-corner{background:transparent}
1176
- /* The stepper arrows, and they are a LINUX defect specifically. Chromium on
1177
- macOS draws no buttons, so styling the track and thumb looks finished there
1178
- and ships a classic GTK scrollbar — a boxed arrow at each end of every
1179
- scroller, on both axes — to everyone on Ubuntu. Styling the other pseudos
1180
- does not suppress them; only this does. Zero width AND height because the
1181
- horizontal and vertical bars each read one of them. */
1179
+ /* The steppers. Styling the other pseudos does not remove them; only this
1180
+ does. Zero width AND height because each axis reads one of them. */
1182
1181
  :where(*)::-webkit-scrollbar-button{display:none;width:0;height:0}
1183
- .light :where(*)::-webkit-scrollbar-thumb{background:rgb(0 0 0 / .18)}
1184
- .light :where(*)::-webkit-scrollbar-thumb:hover{background:rgb(0 0 0 / .32)}
1182
+ /* `.light` itself as well as its subtree: with the theme class on <html>,
1183
+ html's own pseudos draw the page's scrollbar. */
1184
+ .light::-webkit-scrollbar-thumb,.light :where(*)::-webkit-scrollbar-thumb{background:rgb(0 0 0 / .18)}
1185
+ .light::-webkit-scrollbar-thumb:hover,.light :where(*)::-webkit-scrollbar-thumb:hover{background:rgb(0 0 0 / .32)}
1185
1186
  }
1186
1187
 
1187
1188
  /**
@@ -2042,166 +2043,8 @@
2042
2043
  }
2043
2044
 
2044
2045
 
2045
- /* ─────────────────────────────────────────────────────────────────────────────
2046
- Scrollbars, on the surfaces this package scrolls.
2047
-
2048
- Left to the platform this is not neutral: Linux/GTK Chrome draws a wide track
2049
- with STEPPER ARROWS at both ends, so a dark product grows two grey buttons per
2050
- scroll region. Windows draws a wide light track. macOS overlays a thin one,
2051
- which is the behaviour the other two should have had.
2052
-
2053
- THE TWO HALVES MUST NOT BE DECLARED TOGETHER, and that is the whole subtlety.
2054
- Chromium supports both the standard properties and the `::-webkit-scrollbar`
2055
- pseudo-elements — but the moment `scrollbar-width` or `scrollbar-color` is
2056
- anything other than `auto`, it takes the standard path and DISCARDS the entire
2057
- webkit block. Shipping both is how 8.1.19 removed nothing: measured headed on
2058
- Linux, as-shipped gave a 10px gutter with arrows, while the authored webkit
2059
- rule alone gives 8px with none. Isolated: webkit-only 8px no arrows;
2060
- standard-only 10px arrows; both together 10px arrows.
2061
-
2062
- Neither half is redundant, so neither can simply be deleted — Firefox
2063
- implements ONLY the standard properties, Safari ONLY the webkit ones. They are
2064
- separated by engine instead: the webkit block applies wherever the selector is
2065
- understood, and the standard properties apply only where it is not.
2066
-
2067
- And it is invisible headless. Chromium's headless shell paints OVERLAY
2068
- scrollbars, so nothing is drawn, `offsetWidth - clientWidth` is 0 on a blank
2069
- page, and `getComputedStyle(el, '::-webkit-scrollbar-button').display` happily
2070
- reports `none` for a rule that never ran. This must be checked headed.
2071
- ───────────────────────────────────────────────────────────────────────────── */
2072
-
2073
- /* Firefox and anything else with no webkit pseudo-elements. */
2074
- @supports not selector(::-webkit-scrollbar) {
2075
- :where(
2076
- [data-slot='fill'],
2077
- [data-slot='thread'],
2078
- [data-slot='sources-strip'],
2079
- [data-slot='sidebar-scroll'],
2080
- [data-slot='scroll-area-viewport'],
2081
- [data-slot='textarea'],
2082
- [data-slot='composer-field']
2083
- ) {
2084
- scrollbar-width: thin;
2085
- scrollbar-color: rgb(255 255 255 / 0.18) transparent;
2086
- }
2087
- .t_light :where(
2088
- [data-slot='fill'],
2089
- [data-slot='thread'],
2090
- [data-slot='sources-strip'],
2091
- [data-slot='sidebar-scroll'],
2092
- [data-slot='scroll-area-viewport'],
2093
- [data-slot='textarea'],
2094
- [data-slot='composer-field']
2095
- ) { scrollbar-color: rgb(0 0 0 / 0.20) transparent; }
2096
- }
2097
-
2098
- /* Chromium and Safari.
2099
- The first rule is the load-bearing one and it is a RESET, not a style.
2100
- @hanzo/design sets `scrollbar-color` and `scrollbar-width` on `:where(html)`
2101
- (theme.css), and both INHERIT — so every element in the document already
2102
- carries a non-`auto` value, Chromium takes the standard path, and the whole
2103
- webkit block below is discarded before it is read. Nothing declared here can
2104
- win until the inherited value is put back to `auto` on the element itself.
2105
- That is why the arrows survived 8.1.19: the competing declaration was one
2106
- level up and inherited, not a rule anyone would find in this file. */
2107
- @supports selector(::-webkit-scrollbar) {
2108
- :where(
2109
- [data-slot='fill'],
2110
- [data-slot='thread'],
2111
- [data-slot='sources-strip'],
2112
- [data-slot='sidebar-scroll'],
2113
- [data-slot='scroll-area-viewport'],
2114
- [data-slot='textarea'],
2115
- [data-slot='composer-field']
2116
- ) {
2117
- scrollbar-width: auto;
2118
- scrollbar-color: auto;
2119
- }
2120
-
2121
- :where(
2122
- [data-slot='fill'],
2123
- [data-slot='thread'],
2124
- [data-slot='sources-strip'],
2125
- [data-slot='sidebar-scroll'],
2126
- [data-slot='scroll-area-viewport'],
2127
- [data-slot='textarea'],
2128
- [data-slot='composer-field']
2129
- )::-webkit-scrollbar { width: 8px; height: 8px; }
2130
-
2131
- /* The steppers. This is the rule that removes the arrows, and the reason the
2132
- two halves had to be separated at all. */
2133
- :where(
2134
- [data-slot='fill'],
2135
- [data-slot='thread'],
2136
- [data-slot='sources-strip'],
2137
- [data-slot='sidebar-scroll'],
2138
- [data-slot='scroll-area-viewport'],
2139
- [data-slot='textarea'],
2140
- [data-slot='composer-field']
2141
- )::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
2142
-
2143
- :where(
2144
- [data-slot='fill'],
2145
- [data-slot='thread'],
2146
- [data-slot='sources-strip'],
2147
- [data-slot='sidebar-scroll'],
2148
- [data-slot='scroll-area-viewport'],
2149
- [data-slot='textarea'],
2150
- [data-slot='composer-field']
2151
- )::-webkit-scrollbar-track { background: transparent; }
2152
-
2153
- :where(
2154
- [data-slot='fill'],
2155
- [data-slot='thread'],
2156
- [data-slot='sources-strip'],
2157
- [data-slot='sidebar-scroll'],
2158
- [data-slot='scroll-area-viewport'],
2159
- [data-slot='textarea'],
2160
- [data-slot='composer-field']
2161
- )::-webkit-scrollbar-thumb {
2162
- background: rgb(255 255 255 / 0.18);
2163
- border-radius: 999px;
2164
- /* A transparent border with background-clip keeps the thumb off the very
2165
- edge without a track colour doing it, so it reads as an overlay rather
2166
- than a channel. */
2167
- border: 2px solid transparent;
2168
- background-clip: content-box;
2169
- }
2170
- :where(
2171
- [data-slot='fill'],
2172
- [data-slot='thread'],
2173
- [data-slot='sources-strip'],
2174
- [data-slot='sidebar-scroll'],
2175
- [data-slot='scroll-area-viewport'],
2176
- [data-slot='textarea'],
2177
- [data-slot='composer-field']
2178
- )::-webkit-scrollbar-thumb:hover {
2179
- background: rgb(255 255 255 / 0.30);
2180
- background-clip: content-box;
2181
- }
2182
- :where(
2183
- [data-slot='fill'],
2184
- [data-slot='thread'],
2185
- [data-slot='sources-strip'],
2186
- [data-slot='sidebar-scroll'],
2187
- [data-slot='scroll-area-viewport'],
2188
- [data-slot='textarea'],
2189
- [data-slot='composer-field']
2190
- )::-webkit-scrollbar-corner { background: transparent; }
2191
-
2192
- .t_light :where(
2193
- [data-slot='fill'],
2194
- [data-slot='thread'],
2195
- [data-slot='sources-strip'],
2196
- [data-slot='sidebar-scroll'],
2197
- [data-slot='scroll-area-viewport'],
2198
- [data-slot='textarea'],
2199
- [data-slot='composer-field']
2200
- )::-webkit-scrollbar-thumb {
2201
- background: rgb(0 0 0 / 0.20);
2202
- background-clip: content-box;
2203
- }
2204
- }
2046
+ /* Scrollbars are @hanzo/design's (base.css, ≥ 0.5.34): a thin thumb on every
2047
+ scroller and no stepper buttons, stated once for the page. */
2205
2048
 
2206
2049
  /* A carousel scrolls but shows no bar: the arrows and the snap already say it
2207
2050
  scrolls, and a bar appearing mid-drag shifts the slides under the pointer.
@@ -2773,166 +2616,8 @@ a svg,
2773
2616
  }
2774
2617
 
2775
2618
 
2776
- /* ─────────────────────────────────────────────────────────────────────────────
2777
- Scrollbars, on the surfaces this package scrolls.
2778
-
2779
- Left to the platform this is not neutral: Linux/GTK Chrome draws a wide track
2780
- with STEPPER ARROWS at both ends, so a dark product grows two grey buttons per
2781
- scroll region. Windows draws a wide light track. macOS overlays a thin one,
2782
- which is the behaviour the other two should have had.
2783
-
2784
- THE TWO HALVES MUST NOT BE DECLARED TOGETHER, and that is the whole subtlety.
2785
- Chromium supports both the standard properties and the `::-webkit-scrollbar`
2786
- pseudo-elements — but the moment `scrollbar-width` or `scrollbar-color` is
2787
- anything other than `auto`, it takes the standard path and DISCARDS the entire
2788
- webkit block. Shipping both is how 8.1.19 removed nothing: measured headed on
2789
- Linux, as-shipped gave a 10px gutter with arrows, while the authored webkit
2790
- rule alone gives 8px with none. Isolated: webkit-only 8px no arrows;
2791
- standard-only 10px arrows; both together 10px arrows.
2792
-
2793
- Neither half is redundant, so neither can simply be deleted — Firefox
2794
- implements ONLY the standard properties, Safari ONLY the webkit ones. They are
2795
- separated by engine instead: the webkit block applies wherever the selector is
2796
- understood, and the standard properties apply only where it is not.
2797
-
2798
- And it is invisible headless. Chromium's headless shell paints OVERLAY
2799
- scrollbars, so nothing is drawn, `offsetWidth - clientWidth` is 0 on a blank
2800
- page, and `getComputedStyle(el, '::-webkit-scrollbar-button').display` happily
2801
- reports `none` for a rule that never ran. This must be checked headed.
2802
- ───────────────────────────────────────────────────────────────────────────── */
2803
-
2804
- /* Firefox and anything else with no webkit pseudo-elements. */
2805
- @supports not selector(::-webkit-scrollbar) {
2806
- :where(
2807
- [data-slot='fill'],
2808
- [data-slot='thread'],
2809
- [data-slot='sources-strip'],
2810
- [data-slot='sidebar-scroll'],
2811
- [data-slot='scroll-area-viewport'],
2812
- [data-slot='textarea'],
2813
- [data-slot='composer-field']
2814
- ) {
2815
- scrollbar-width: thin;
2816
- scrollbar-color: rgb(255 255 255 / 0.18) transparent;
2817
- }
2818
- .t_light :where(
2819
- [data-slot='fill'],
2820
- [data-slot='thread'],
2821
- [data-slot='sources-strip'],
2822
- [data-slot='sidebar-scroll'],
2823
- [data-slot='scroll-area-viewport'],
2824
- [data-slot='textarea'],
2825
- [data-slot='composer-field']
2826
- ) { scrollbar-color: rgb(0 0 0 / 0.20) transparent; }
2827
- }
2828
-
2829
- /* Chromium and Safari.
2830
- The first rule is the load-bearing one and it is a RESET, not a style.
2831
- @hanzo/design sets `scrollbar-color` and `scrollbar-width` on `:where(html)`
2832
- (theme.css), and both INHERIT — so every element in the document already
2833
- carries a non-`auto` value, Chromium takes the standard path, and the whole
2834
- webkit block below is discarded before it is read. Nothing declared here can
2835
- win until the inherited value is put back to `auto` on the element itself.
2836
- That is why the arrows survived 8.1.19: the competing declaration was one
2837
- level up and inherited, not a rule anyone would find in this file. */
2838
- @supports selector(::-webkit-scrollbar) {
2839
- :where(
2840
- [data-slot='fill'],
2841
- [data-slot='thread'],
2842
- [data-slot='sources-strip'],
2843
- [data-slot='sidebar-scroll'],
2844
- [data-slot='scroll-area-viewport'],
2845
- [data-slot='textarea'],
2846
- [data-slot='composer-field']
2847
- ) {
2848
- scrollbar-width: auto;
2849
- scrollbar-color: auto;
2850
- }
2851
-
2852
- :where(
2853
- [data-slot='fill'],
2854
- [data-slot='thread'],
2855
- [data-slot='sources-strip'],
2856
- [data-slot='sidebar-scroll'],
2857
- [data-slot='scroll-area-viewport'],
2858
- [data-slot='textarea'],
2859
- [data-slot='composer-field']
2860
- )::-webkit-scrollbar { width: 8px; height: 8px; }
2861
-
2862
- /* The steppers. This is the rule that removes the arrows, and the reason the
2863
- two halves had to be separated at all. */
2864
- :where(
2865
- [data-slot='fill'],
2866
- [data-slot='thread'],
2867
- [data-slot='sources-strip'],
2868
- [data-slot='sidebar-scroll'],
2869
- [data-slot='scroll-area-viewport'],
2870
- [data-slot='textarea'],
2871
- [data-slot='composer-field']
2872
- )::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
2873
-
2874
- :where(
2875
- [data-slot='fill'],
2876
- [data-slot='thread'],
2877
- [data-slot='sources-strip'],
2878
- [data-slot='sidebar-scroll'],
2879
- [data-slot='scroll-area-viewport'],
2880
- [data-slot='textarea'],
2881
- [data-slot='composer-field']
2882
- )::-webkit-scrollbar-track { background: transparent; }
2883
-
2884
- :where(
2885
- [data-slot='fill'],
2886
- [data-slot='thread'],
2887
- [data-slot='sources-strip'],
2888
- [data-slot='sidebar-scroll'],
2889
- [data-slot='scroll-area-viewport'],
2890
- [data-slot='textarea'],
2891
- [data-slot='composer-field']
2892
- )::-webkit-scrollbar-thumb {
2893
- background: rgb(255 255 255 / 0.18);
2894
- border-radius: 999px;
2895
- /* A transparent border with background-clip keeps the thumb off the very
2896
- edge without a track colour doing it, so it reads as an overlay rather
2897
- than a channel. */
2898
- border: 2px solid transparent;
2899
- background-clip: content-box;
2900
- }
2901
- :where(
2902
- [data-slot='fill'],
2903
- [data-slot='thread'],
2904
- [data-slot='sources-strip'],
2905
- [data-slot='sidebar-scroll'],
2906
- [data-slot='scroll-area-viewport'],
2907
- [data-slot='textarea'],
2908
- [data-slot='composer-field']
2909
- )::-webkit-scrollbar-thumb:hover {
2910
- background: rgb(255 255 255 / 0.30);
2911
- background-clip: content-box;
2912
- }
2913
- :where(
2914
- [data-slot='fill'],
2915
- [data-slot='thread'],
2916
- [data-slot='sources-strip'],
2917
- [data-slot='sidebar-scroll'],
2918
- [data-slot='scroll-area-viewport'],
2919
- [data-slot='textarea'],
2920
- [data-slot='composer-field']
2921
- )::-webkit-scrollbar-corner { background: transparent; }
2922
-
2923
- .t_light :where(
2924
- [data-slot='fill'],
2925
- [data-slot='thread'],
2926
- [data-slot='sources-strip'],
2927
- [data-slot='sidebar-scroll'],
2928
- [data-slot='scroll-area-viewport'],
2929
- [data-slot='textarea'],
2930
- [data-slot='composer-field']
2931
- )::-webkit-scrollbar-thumb {
2932
- background: rgb(0 0 0 / 0.20);
2933
- background-clip: content-box;
2934
- }
2935
- }
2619
+ /* Scrollbars are @hanzo/design's (base.css, ≥ 0.5.34): a thin thumb on every
2620
+ scroller and no stepper buttons, stated once for the page. */
2936
2621
 
2937
2622
  /* A carousel scrolls but shows no bar: the arrows and the snap already say it
2938
2623
  scrolls, and a bar appearing mid-drag shifts the slides under the pointer.
package/dist/theme.css CHANGED
@@ -1152,34 +1152,35 @@
1152
1152
  ::selection{background:var(--selection);color:var(--text-primary)}
1153
1153
 
1154
1154
  /* ——— the scrollbar ———
1155
- The single largest piece of UNSTYLED chrome left on a dark surface: a
1156
- default 15px light-grey scrollbar down the side of a #0a0a0a panel is the
1157
- one element on the page that did not get the memo, and it is visible on
1158
- every scrolling surface in the product. 6px, no track, thumb on the same
1159
- hairline ladder as everything else. Both syntaxes ship because they are
1160
- disjoint — `scrollbar-*` is Firefox and the `::-webkit-*` pseudos are
1161
- Chromium/Safari; neither engine reads the other.
1155
+ 6px, no track, no stepper buttons, the thumb on the same hairline ladder as
1156
+ everything else. ONE treatment per engine. Chromium 121+ reads the standard
1157
+ `scrollbar-color`/`scrollbar-width` as well as the `::-webkit-*` pseudos,
1158
+ and an element with either standard property set ignores its pseudos —
1159
+ `scrollbar-color` inherits, so stated on html it gives every scroller the
1160
+ native bar, which on Linux/GTK draws a boxed arrow at each end. So the
1161
+ standard pair goes only to an engine without the pseudos (Firefox), and the
1162
+ pseudos serve the rest. Check 1e holds that.
1162
1163
  The thumb is a --white-* rung, so it does not invert; the `.light`
1163
1164
  restatements sit here rather than in colors.css because a scrollbar is an
1164
1165
  element default and this file is where element defaults live. Everything
1165
1166
  stays INSIDE the layer — an unlayered rule here would outrank an app's own
1166
1167
  utilities, which is the defect check 1c exists to catch. */
1167
- :where(html){scrollbar-color:var(--white-15) transparent;scrollbar-width:thin}
1168
- .light, :root.t_light, .t_light{scrollbar-color:rgb(0 0 0 / .18) transparent}
1168
+ @supports not selector(::-webkit-scrollbar){
1169
+ :where(html){scrollbar-color:var(--white-15) transparent;scrollbar-width:thin}
1170
+ .light, :root.t_light, .t_light{scrollbar-color:rgb(0 0 0 / .18) transparent}
1171
+ }
1169
1172
  :where(*)::-webkit-scrollbar{width:6px;height:6px}
1170
1173
  :where(*)::-webkit-scrollbar-track{background:transparent}
1171
1174
  :where(*)::-webkit-scrollbar-thumb{background:var(--white-15);border-radius:var(--radius-full)}
1172
1175
  :where(*)::-webkit-scrollbar-thumb:hover{background:var(--white-30)}
1173
1176
  :where(*)::-webkit-scrollbar-corner{background:transparent}
1174
- /* The stepper arrows, and they are a LINUX defect specifically. Chromium on
1175
- macOS draws no buttons, so styling the track and thumb looks finished there
1176
- and ships a classic GTK scrollbar — a boxed arrow at each end of every
1177
- scroller, on both axes — to everyone on Ubuntu. Styling the other pseudos
1178
- does not suppress them; only this does. Zero width AND height because the
1179
- horizontal and vertical bars each read one of them. */
1177
+ /* The steppers. Styling the other pseudos does not remove them; only this
1178
+ does. Zero width AND height because each axis reads one of them. */
1180
1179
  :where(*)::-webkit-scrollbar-button{display:none;width:0;height:0}
1181
- .light :where(*)::-webkit-scrollbar-thumb{background:rgb(0 0 0 / .18)}
1182
- .light :where(*)::-webkit-scrollbar-thumb:hover{background:rgb(0 0 0 / .32)}
1180
+ /* `.light` itself as well as its subtree: with the theme class on <html>,
1181
+ html's own pseudos draw the page's scrollbar. */
1182
+ .light::-webkit-scrollbar-thumb,.light :where(*)::-webkit-scrollbar-thumb{background:rgb(0 0 0 / .18)}
1183
+ .light::-webkit-scrollbar-thumb:hover,.light :where(*)::-webkit-scrollbar-thumb:hover{background:rgb(0 0 0 / .32)}
1183
1184
  }
1184
1185
 
1185
1186
  /**
@@ -2040,166 +2041,8 @@
2040
2041
  }
2041
2042
 
2042
2043
 
2043
- /* ─────────────────────────────────────────────────────────────────────────────
2044
- Scrollbars, on the surfaces this package scrolls.
2045
-
2046
- Left to the platform this is not neutral: Linux/GTK Chrome draws a wide track
2047
- with STEPPER ARROWS at both ends, so a dark product grows two grey buttons per
2048
- scroll region. Windows draws a wide light track. macOS overlays a thin one,
2049
- which is the behaviour the other two should have had.
2050
-
2051
- THE TWO HALVES MUST NOT BE DECLARED TOGETHER, and that is the whole subtlety.
2052
- Chromium supports both the standard properties and the `::-webkit-scrollbar`
2053
- pseudo-elements — but the moment `scrollbar-width` or `scrollbar-color` is
2054
- anything other than `auto`, it takes the standard path and DISCARDS the entire
2055
- webkit block. Shipping both is how 8.1.19 removed nothing: measured headed on
2056
- Linux, as-shipped gave a 10px gutter with arrows, while the authored webkit
2057
- rule alone gives 8px with none. Isolated: webkit-only 8px no arrows;
2058
- standard-only 10px arrows; both together 10px arrows.
2059
-
2060
- Neither half is redundant, so neither can simply be deleted — Firefox
2061
- implements ONLY the standard properties, Safari ONLY the webkit ones. They are
2062
- separated by engine instead: the webkit block applies wherever the selector is
2063
- understood, and the standard properties apply only where it is not.
2064
-
2065
- And it is invisible headless. Chromium's headless shell paints OVERLAY
2066
- scrollbars, so nothing is drawn, `offsetWidth - clientWidth` is 0 on a blank
2067
- page, and `getComputedStyle(el, '::-webkit-scrollbar-button').display` happily
2068
- reports `none` for a rule that never ran. This must be checked headed.
2069
- ───────────────────────────────────────────────────────────────────────────── */
2070
-
2071
- /* Firefox and anything else with no webkit pseudo-elements. */
2072
- @supports not selector(::-webkit-scrollbar) {
2073
- :where(
2074
- [data-slot='fill'],
2075
- [data-slot='thread'],
2076
- [data-slot='sources-strip'],
2077
- [data-slot='sidebar-scroll'],
2078
- [data-slot='scroll-area-viewport'],
2079
- [data-slot='textarea'],
2080
- [data-slot='composer-field']
2081
- ) {
2082
- scrollbar-width: thin;
2083
- scrollbar-color: rgb(255 255 255 / 0.18) transparent;
2084
- }
2085
- .t_light :where(
2086
- [data-slot='fill'],
2087
- [data-slot='thread'],
2088
- [data-slot='sources-strip'],
2089
- [data-slot='sidebar-scroll'],
2090
- [data-slot='scroll-area-viewport'],
2091
- [data-slot='textarea'],
2092
- [data-slot='composer-field']
2093
- ) { scrollbar-color: rgb(0 0 0 / 0.20) transparent; }
2094
- }
2095
-
2096
- /* Chromium and Safari.
2097
- The first rule is the load-bearing one and it is a RESET, not a style.
2098
- @hanzo/design sets `scrollbar-color` and `scrollbar-width` on `:where(html)`
2099
- (theme.css), and both INHERIT — so every element in the document already
2100
- carries a non-`auto` value, Chromium takes the standard path, and the whole
2101
- webkit block below is discarded before it is read. Nothing declared here can
2102
- win until the inherited value is put back to `auto` on the element itself.
2103
- That is why the arrows survived 8.1.19: the competing declaration was one
2104
- level up and inherited, not a rule anyone would find in this file. */
2105
- @supports selector(::-webkit-scrollbar) {
2106
- :where(
2107
- [data-slot='fill'],
2108
- [data-slot='thread'],
2109
- [data-slot='sources-strip'],
2110
- [data-slot='sidebar-scroll'],
2111
- [data-slot='scroll-area-viewport'],
2112
- [data-slot='textarea'],
2113
- [data-slot='composer-field']
2114
- ) {
2115
- scrollbar-width: auto;
2116
- scrollbar-color: auto;
2117
- }
2118
-
2119
- :where(
2120
- [data-slot='fill'],
2121
- [data-slot='thread'],
2122
- [data-slot='sources-strip'],
2123
- [data-slot='sidebar-scroll'],
2124
- [data-slot='scroll-area-viewport'],
2125
- [data-slot='textarea'],
2126
- [data-slot='composer-field']
2127
- )::-webkit-scrollbar { width: 8px; height: 8px; }
2128
-
2129
- /* The steppers. This is the rule that removes the arrows, and the reason the
2130
- two halves had to be separated at all. */
2131
- :where(
2132
- [data-slot='fill'],
2133
- [data-slot='thread'],
2134
- [data-slot='sources-strip'],
2135
- [data-slot='sidebar-scroll'],
2136
- [data-slot='scroll-area-viewport'],
2137
- [data-slot='textarea'],
2138
- [data-slot='composer-field']
2139
- )::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
2140
-
2141
- :where(
2142
- [data-slot='fill'],
2143
- [data-slot='thread'],
2144
- [data-slot='sources-strip'],
2145
- [data-slot='sidebar-scroll'],
2146
- [data-slot='scroll-area-viewport'],
2147
- [data-slot='textarea'],
2148
- [data-slot='composer-field']
2149
- )::-webkit-scrollbar-track { background: transparent; }
2150
-
2151
- :where(
2152
- [data-slot='fill'],
2153
- [data-slot='thread'],
2154
- [data-slot='sources-strip'],
2155
- [data-slot='sidebar-scroll'],
2156
- [data-slot='scroll-area-viewport'],
2157
- [data-slot='textarea'],
2158
- [data-slot='composer-field']
2159
- )::-webkit-scrollbar-thumb {
2160
- background: rgb(255 255 255 / 0.18);
2161
- border-radius: 999px;
2162
- /* A transparent border with background-clip keeps the thumb off the very
2163
- edge without a track colour doing it, so it reads as an overlay rather
2164
- than a channel. */
2165
- border: 2px solid transparent;
2166
- background-clip: content-box;
2167
- }
2168
- :where(
2169
- [data-slot='fill'],
2170
- [data-slot='thread'],
2171
- [data-slot='sources-strip'],
2172
- [data-slot='sidebar-scroll'],
2173
- [data-slot='scroll-area-viewport'],
2174
- [data-slot='textarea'],
2175
- [data-slot='composer-field']
2176
- )::-webkit-scrollbar-thumb:hover {
2177
- background: rgb(255 255 255 / 0.30);
2178
- background-clip: content-box;
2179
- }
2180
- :where(
2181
- [data-slot='fill'],
2182
- [data-slot='thread'],
2183
- [data-slot='sources-strip'],
2184
- [data-slot='sidebar-scroll'],
2185
- [data-slot='scroll-area-viewport'],
2186
- [data-slot='textarea'],
2187
- [data-slot='composer-field']
2188
- )::-webkit-scrollbar-corner { background: transparent; }
2189
-
2190
- .t_light :where(
2191
- [data-slot='fill'],
2192
- [data-slot='thread'],
2193
- [data-slot='sources-strip'],
2194
- [data-slot='sidebar-scroll'],
2195
- [data-slot='scroll-area-viewport'],
2196
- [data-slot='textarea'],
2197
- [data-slot='composer-field']
2198
- )::-webkit-scrollbar-thumb {
2199
- background: rgb(0 0 0 / 0.20);
2200
- background-clip: content-box;
2201
- }
2202
- }
2044
+ /* Scrollbars are @hanzo/design's (base.css, ≥ 0.5.34): a thin thumb on every
2045
+ scroller and no stepper buttons, stated once for the page. */
2203
2046
 
2204
2047
  /* A carousel scrolls but shows no bar: the arrows and the snap already say it
2205
2048
  scrolls, and a bar appearing mid-drag shifts the slides under the pointer.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/ui",
3
- "version": "8.27.53",
3
+ "version": "8.27.54",
4
4
  "type": "module",
5
5
  "description": "Hanzo UI — the one canonical Hanzo component library, on @hanzo/gui + @hanzo/design. ONE substrate: every component renders through @hanzo/gui primitives, so the same import works on web, native (expo) and desktop (Tauri). Self-contained (theme.css), presentational, host-agnostic, clean-room.",
6
6
  "exports": {
@@ -305,7 +305,7 @@
305
305
  "dependencies": {
306
306
  "@hanzo/appearance": "0.2.7",
307
307
  "@hanzo/brand": "1.4.8",
308
- "@hanzo/design": "0.5.33",
308
+ "@hanzo/design": "0.5.34",
309
309
  "@hanzo/font": "1.9.2",
310
310
  "@hanzo/logo": "1.0.26",
311
311
  "@hanzo/products": "0.2.6",