@hanzo/ui 8.0.76 → 8.0.81

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/styles.css CHANGED
@@ -590,6 +590,51 @@
590
590
  --shadow-lg:0 10px 15px -3px rgb(0 0 0 / .55), 0 4px 6px -4px rgb(0 0 0 / .55);
591
591
  --shadow-xl:0 20px 25px -5px rgb(0 0 0 / .60), 0 8px 10px -6px rgb(0 0 0 / .60);
592
592
  --shadow-2xl:var(--shadow-floating);
593
+
594
+ /* ——— the paper ——— */
595
+ /* Depth carries STATE, not decoration: which sheet is the workspace, which is
596
+ the tool in use, which one opened. Reach for a level before a border — if
597
+ two surfaces need separating, RAISE one rather than outline both, and a
598
+ surface that is already raised does not also need a box drawn round it.
599
+
600
+ A level is a tint AND the light on it, published as a pair, because the
601
+ alternative — every component composing its own `--edge-highlight,
602
+ --shadow-*` — is how two panels on one screen end up lit from two
603
+ directions. Every rung here is pure vertical: a 1px inset line along the
604
+ top edge, a drop straight down. One origin, above and slightly in front.
605
+
606
+ The tints are the surface recipes rather than new values, so sheets stack
607
+ the way paper does: each is an alpha-white wash, one laid on another lands
608
+ a step lighter, and the stack converges on #262626 instead of blowing out.
609
+
610
+ Nothing here is restated in `.light`, deliberately: every part defers to a
611
+ token that already flips, so the ramp inverts with the theme for free. */
612
+ --sheet-0:var(--surface-page); /* the workspace ground */
613
+ --sheet-1:var(--surface-card); /* an active tool */
614
+ --sheet-2:var(--surface-card-emphasis); /* what opened, or what is inside */
615
+ /* The drops are spelled out rather than read from the t-shirt ramp above, and
616
+ that is the whole reason this ladder can be shared. `--shadow-sm` is a name
617
+ this package does not own — @hanzo/brand declares the same names at :root
618
+ with white-canvas alphas, and load order decides who wins — so a rung built
619
+ on one is a rung somebody else can flatten. `--shadow-sheet-*` is ours
620
+ alone, which is what lets @hanzo/ui's `.elevation-*` read it instead of
621
+ keeping a private copy. The numbers ARE rung 1 and rung 2 of the ramp; if
622
+ one moves, move both. `--edge-highlight` stays deferred: it is role-named,
623
+ uncollided, and its `.light` zeroing is what makes one value work on both
624
+ canvases. */
625
+ --shadow-sheet-1:var(--edge-highlight),0 1px 2px 0 rgb(0 0 0 / .40);
626
+ --shadow-sheet-2:var(--edge-highlight),0 10px 15px -3px rgb(0 0 0 / .55),0 4px 6px -4px rgb(0 0 0 / .55);
627
+
628
+ /* The fold — a corner turned back, and the one mark that means THIS OPENS.
629
+ Ornament nowhere: a sheet that does not expand does not wear one.
630
+ It is a background-image, so it costs no element and no pseudo-element —
631
+ paint it on the sheet itself and square that corner
632
+ (`border-bottom-right-radius:0`), because a folded corner is not round.
633
+ The flap catches the light like every other surface; the crease is the
634
+ hairline; both defer, so both invert. */
635
+ --fold:12px;
636
+ --fold-face:linear-gradient(315deg,var(--glass-strong) 0,var(--glass-strong) calc(var(--fold) - 1px),var(--border-strong) calc(var(--fold) - 1px),var(--border-strong) var(--fold),transparent var(--fold)); /* @kind color */
637
+
593
638
  /* Ambient hero glow — a single white radial, blurred 120px, low opacity. */
594
639
  --glow-hero:radial-gradient(circle,rgb(255 255 255 / .12) 0%,transparent 68%); /* @kind color */
595
640
  --glow-hero-blur:120px;
@@ -622,6 +667,11 @@
622
667
  costs nothing. */
623
668
  .light, :root.t_light, .t_light{
624
669
  --shadow-floating:0 24px 60px -16px rgb(0 0 0 / .18);
670
+ /* On white the drop does all of it, so the paper rungs are restated here even
671
+ though check 4 does not demand it — their white is inside --edge-highlight,
672
+ which flips underneath. Rung 1 and rung 2 of the light ramp, same as dark. */
673
+ --shadow-sheet-1:var(--edge-highlight),0 1px 2px 0 rgb(0 0 0 / .06);
674
+ --shadow-sheet-2:var(--edge-highlight),0 10px 15px -3px rgb(0 0 0 / .09),0 4px 6px -4px rgb(0 0 0 / .07);
625
675
  --shadow-inset-hairline:inset 0 0 0 1px rgb(0 0 0 / .10);
626
676
  --edge-highlight:inset 0 0 0 0 transparent;
627
677
  --bloom:0 6px 20px -4px rgb(0 0 0 / .18);
@@ -1162,19 +1212,66 @@
1162
1212
  from inside it, and a menu with no background is a menu you read the page
1163
1213
  through. !important beats the compiled atomic background class, which lands
1164
1214
  in an inline <style> a bundler orders after this sheet, and it beats the call
1165
- sites that pin a fill by hand — those become no-ops instead of holes. */
1215
+ sites that pin a fill by hand — those become no-ops instead of holes.
1216
+
1217
+ EVERY floating slot the package emits is here. It was seven, and the three it
1218
+ left out were not obscure: AlertDialog is a MODAL — the one surface that
1219
+ cannot be anything but floating — and it was opaque beside a glass Dialog.
1220
+ ContextMenu and HoverCard are anchored menus beside glass DropdownMenu and
1221
+ glass Popover. That is precisely the drift this file exists to stop, still
1222
+ present in the file that stops it, which is worth stating plainly: a rule
1223
+ that attaches the material to the slot only holds if every slot is named.
1224
+ The list is checked against what the components actually emit, so the next
1225
+ floating slot somebody adds fails the test rather than the eye. */
1166
1226
  @supports (backdrop-filter: blur(8px)) {
1167
1227
  .glass,
1168
1228
  [data-slot="glass"],
1169
1229
  [data-slot="dialog-content"],
1230
+ [data-slot="alert-dialog-content"],
1170
1231
  [data-slot="popover-content"],
1171
1232
  [data-slot="select-content"],
1172
1233
  [data-slot="dropdown-menu-content"],
1173
1234
  [data-slot="dropdown-menu-sub-content"],
1235
+ [data-slot="context-menu-content"],
1236
+ [data-slot="context-menu-sub-content"],
1237
+ [data-slot="hover-card-content"],
1174
1238
  [data-slot="tooltip-content"] {
1175
1239
  background-color: color-mix(in oklab, var(--background) 72%, transparent) !important;
1176
1240
  -webkit-backdrop-filter: blur(20px) saturate(1.8);
1177
1241
  backdrop-filter: blur(20px) saturate(1.8);
1242
+ /* ── The dispersion ──────────────────────────────────────────────────────
1243
+ Glass splits light at the EDGE. That is the whole of the physics and the
1244
+ whole of the rule: the body of a pane shows you what is behind it, and the
1245
+ rim is where the angle is steep enough to spread the spectrum. So the fill
1246
+ stays monochrome — the brand is monochrome and text has to sit on it — and
1247
+ the colour lives in one pixel at the top lip.
1248
+
1249
+ LINEAR, ACROSS THE LIP — never conic around the box. The composer's note
1250
+ below records what conic costs on a rectangle: the long edges take a wide
1251
+ angular slice and the short sides almost none, so one side wears blue and
1252
+ the opposite burnt orange, and the ring reads as off-centre. Swept along
1253
+ one edge instead, the stops are evenly spaced at any aspect ratio, so a
1254
+ 1000px dialog and a 90px tooltip disperse alike.
1255
+
1256
+ Peak alpha .16, on a band two pixels tall, one pixel DOWN. Both numbers
1257
+ were measured rather than chosen. The lit edge is an inset box-shadow, and
1258
+ a box-shadow paints over the background — so the first version put the
1259
+ spectrum in the same pixel the white lip occupies and the lip won: at ×6
1260
+ the rim was a neutral hairline with no colour in it at all. Sitting the
1261
+ band one pixel inside puts it where a real pane disperses anyway, just
1262
+ behind the specular line, and it is legible there at half the alpha a
1263
+ collision would have needed. Three pixels at .22 was tried too and reads
1264
+ as a coloured stroke somebody drew, which is a different thing entirely.
1265
+
1266
+ That is also the difference between this and the full-wheel rainbow that
1267
+ was tried and reverted: not a different palette, a different AREA. Colour
1268
+ over a whole surface makes that surface the only coloured thing in the
1269
+ product; colour along its rim reads as the material catching light, which
1270
+ is the one thing chrome is allowed to say. */
1271
+ background-image: var(--glass-prism) !important;
1272
+ background-repeat: no-repeat !important;
1273
+ background-size: 100% 2px !important;
1274
+ background-position: 0 1px !important;
1178
1275
  }
1179
1276
  }
1180
1277
 
@@ -1228,6 +1325,24 @@
1228
1325
  --glass-shadow-1: 0 1px 2px 0 rgb(0 0 0 / .40);
1229
1326
  --glass-shadow-2: 0 10px 15px -3px rgb(0 0 0 / .55), 0 4px 6px -4px rgb(0 0 0 / .55);
1230
1327
  --glass-shadow-3: 0 24px 60px -16px rgb(0 0 0 / .75);
1328
+
1329
+ /* The spectrum the lip disperses. Declared here for the same reason the drops
1330
+ above are: a name this package owns cannot be outranked by a sheet that
1331
+ happens to load later. Nothing else ships a --glass-prism.
1332
+
1333
+ Five stops, blue through violet, rose, amber, to a cool green — the order
1334
+ light actually comes apart in, so it reads as refraction rather than as a
1335
+ palette somebody chose. Alphas .13-.16: measured at ×6 against the white lip
1336
+ that sits a pixel above, high enough to read there and low enough that at
1337
+ 1:1 it is a tinge. A theme that wants none of it sets this to `none` and the
1338
+ rim goes back to being the lit edge alone. */
1339
+ --glass-prism:
1340
+ linear-gradient(90deg,
1341
+ rgb(120 170 255 / .16) 0%,
1342
+ rgb(178 142 255 / .15) 24%,
1343
+ rgb(255 146 198 / .13) 48%,
1344
+ rgb(255 190 124 / .15) 72%,
1345
+ rgb(138 228 208 / .16) 100%);
1231
1346
  }
1232
1347
 
1233
1348
  .light, :root.t_light, .t_light {
@@ -1247,6 +1362,9 @@
1247
1362
  [data-slot="select-content"],
1248
1363
  [data-slot="dropdown-menu-content"],
1249
1364
  [data-slot="dropdown-menu-sub-content"],
1365
+ [data-slot="context-menu-content"],
1366
+ [data-slot="context-menu-sub-content"],
1367
+ [data-slot="hover-card-content"],
1250
1368
  [data-slot="tooltip-content"] {
1251
1369
  box-shadow:
1252
1370
  var(--edge-highlight, inset 0 1px 0 0 rgb(255 255 255 / .10)),
@@ -1254,12 +1372,38 @@
1254
1372
  }
1255
1373
 
1256
1374
  .elevation-3,
1257
- [data-slot="dialog-content"] {
1375
+ [data-slot="dialog-content"],
1376
+ [data-slot="alert-dialog-content"] {
1258
1377
  box-shadow:
1259
1378
  var(--edge-highlight, inset 0 1px 0 0 rgb(255 255 255 / .10)),
1260
1379
  var(--glass-shadow-3) !important;
1261
1380
  }
1262
1381
 
1382
+ /* ── The fold — the one mark that means an item opens ────────────────────────
1383
+ A corner turned back, painted onto the sheet itself. It is a class and not a
1384
+ pair of style props because gui compiles those into atomic classes and a
1385
+ background-image is not one of the properties it maps; and because a fold has
1386
+ exactly one spelling, so the call site should not be able to invent a second
1387
+ one. `--fold-face` is @hanzo/design's, with the dark value inline so a host
1388
+ that took this sheet without the token layer still gets a corner rather than
1389
+ a silently-dropped declaration.
1390
+
1391
+ The corner is SQUARED, not rounded: a folded corner is a straight crease, and
1392
+ a rounded one under a triangle reads as a rendering fault. That is also why
1393
+ this carries !important — the radius it has to beat is a compiled style prop.
1394
+
1395
+ Spend it only where the thing expands. A fold on a surface that opens nothing
1396
+ is a chevron that never turns. */
1397
+ .fold {
1398
+ background-image: var(--fold-face,
1399
+ linear-gradient(315deg,
1400
+ rgb(255 255 255 / .08) 0, rgb(255 255 255 / .08) 11px,
1401
+ rgb(255 255 255 / .16) 11px, rgb(255 255 255 / .16) 12px,
1402
+ transparent 12px)) !important;
1403
+ background-repeat: no-repeat !important;
1404
+ border-bottom-right-radius: 0 !important;
1405
+ }
1406
+
1263
1407
  /* ── The scrim ──────────────────────────────────────────────────────────────
1264
1408
  The dim that makes a floating panel read as floating rather than as more
1265
1409
  page. gui's overlay dims TWICE — a translucent ground under a further
@@ -1279,7 +1423,8 @@
1279
1423
  palette: `rgba(0,0,0,.5)` under `opacity: .5` — a quarter black, exactly the
1280
1424
  double dim these two lines exist to end. A rule written to beat a compiled
1281
1425
  class has to be written with the weight to beat one. */
1282
- [data-slot="dialog-overlay"] {
1426
+ [data-slot="dialog-overlay"],
1427
+ [data-slot="alert-dialog-overlay"] {
1283
1428
  opacity: 1 !important;
1284
1429
  background-color: var(--surface-scrim, rgb(0 0 0 / .8)) !important;
1285
1430
  }
@@ -2315,6 +2460,7 @@
2315
2460
  :root ._bg-background{background-color:var(--background);}
2316
2461
  :root ._bg-backgroundA94988999{background-color:var(--backgroundActive);}
2317
2462
  :root ._bg-borderColor{background-color:var(--borderColor);}
2463
+ :root ._bg-color1{background-color:var(--color1);}
2318
2464
  :root ._bg-color12{background-color:var(--color12);}
2319
2465
  :root ._bg-color2{background-color:var(--color2);}
2320
2466
  :root ._bg-color3{background-color:var(--color3);}
@@ -2322,6 +2468,8 @@
2322
2468
  :root ._bg-color5{background-color:var(--color5);}
2323
2469
  :root ._bg-color6{background-color:var(--color6);}
2324
2470
  :root ._bg-red9{background-color:var(--red9);}
2471
+ :root ._bg-sheet-1rgb31918056171{background-color:var(--sheet-1, rgb(38 38 38 / .5));}
2472
+ :root ._bg-sheet-2rgb3669803178{background-color:var(--sheet-2, rgb(38 38 38 / .75));}
2325
2473
  :root ._bg-transparent{background-color:transparent;}
2326
2474
  :root ._bls-solid._bls-solid{border-left-style:solid;}
2327
2475
  :root:root:root ._borderBottomColor-0active-borderColor._borderBottomColor-0active-borderColor:active{border-bottom-color:var(--borderColor) !important;}
@@ -2338,6 +2486,7 @@
2338
2486
  @media (hover) {:root:root ._borderBottomColor-0hover-color6._borderBottomColor-0hover-color6:hover{border-bottom-color:var(--color6) !important;}}
2339
2487
  @media (hover) {:root:root ._borderBottomColor-0hover-color7._borderBottomColor-0hover-color7:hover{border-bottom-color:var(--color7) !important;}}
2340
2488
  @media (hover) {:root:root ._borderBottomColor-0hover-color8._borderBottomColor-0hover-color8:hover{border-bottom-color:var(--color8) !important;}}
2489
+ @media (hover) {:root:root ._borderBottomColor-0hover-transparent._borderBottomColor-0hover-transparent:hover{border-bottom-color:transparent !important;}}
2341
2490
  :root ._borderBottomColor-backgroundF3405682._borderBottomColor-backgroundF3405682{border-bottom-color:var(--backgroundFocus);}
2342
2491
  :root ._borderBottomColor-borderColor._borderBottomColor-borderColor{border-bottom-color:var(--borderColor);}
2343
2492
  :root ._borderBottomColor-color12._borderBottomColor-color12{border-bottom-color:var(--color12);}
@@ -2360,6 +2509,7 @@
2360
2509
  @media (hover) {:root:root ._borderLeftColor-0hover-color6._borderLeftColor-0hover-color6:hover{border-left-color:var(--color6) !important;}}
2361
2510
  @media (hover) {:root:root ._borderLeftColor-0hover-color7._borderLeftColor-0hover-color7:hover{border-left-color:var(--color7) !important;}}
2362
2511
  @media (hover) {:root:root ._borderLeftColor-0hover-color8._borderLeftColor-0hover-color8:hover{border-left-color:var(--color8) !important;}}
2512
+ @media (hover) {:root:root ._borderLeftColor-0hover-transparent._borderLeftColor-0hover-transparent:hover{border-left-color:transparent !important;}}
2363
2513
  :root ._borderLeftColor-backgroundF3405682._borderLeftColor-backgroundF3405682{border-left-color:var(--backgroundFocus);}
2364
2514
  :root ._borderLeftColor-borderColor._borderLeftColor-borderColor{border-left-color:var(--borderColor);}
2365
2515
  :root ._borderLeftColor-color12._borderLeftColor-color12{border-left-color:var(--color12);}
@@ -2382,6 +2532,7 @@
2382
2532
  @media (hover) {:root:root ._brc-0hover-color6._brc-0hover-color6:hover{border-right-color:var(--color6) !important;}}
2383
2533
  @media (hover) {:root:root ._brc-0hover-color7._brc-0hover-color7:hover{border-right-color:var(--color7) !important;}}
2384
2534
  @media (hover) {:root:root ._brc-0hover-color8._brc-0hover-color8:hover{border-right-color:var(--color8) !important;}}
2535
+ @media (hover) {:root:root ._brc-0hover-transparent._brc-0hover-transparent:hover{border-right-color:transparent !important;}}
2385
2536
  :root ._brc-backgroundF3405682._brc-backgroundF3405682{border-right-color:var(--backgroundFocus);}
2386
2537
  :root ._brc-borderColor._brc-borderColor{border-right-color:var(--borderColor);}
2387
2538
  :root ._brc-color12._brc-color12{border-right-color:var(--color12);}
@@ -2405,6 +2556,7 @@
2405
2556
  @media (hover) {:root:root ._btc-0hover-color6._btc-0hover-color6:hover{border-top-color:var(--color6) !important;}}
2406
2557
  @media (hover) {:root:root ._btc-0hover-color7._btc-0hover-color7:hover{border-top-color:var(--color7) !important;}}
2407
2558
  @media (hover) {:root:root ._btc-0hover-color8._btc-0hover-color8:hover{border-top-color:var(--color8) !important;}}
2559
+ @media (hover) {:root:root ._btc-0hover-transparent._btc-0hover-transparent:hover{border-top-color:transparent !important;}}
2408
2560
  :root ._btc-backgroundF3405682._btc-backgroundF3405682{border-top-color:var(--backgroundFocus);}
2409
2561
  :root ._btc-borderColor._btc-borderColor{border-top-color:var(--borderColor);}
2410
2562
  :root ._btc-color12._btc-color12{border-top-color:var(--color12);}
@@ -2432,6 +2584,7 @@
2432
2584
  :root ._bts-solid._bts-solid{border-top-style:solid;}
2433
2585
  :root ._btw-0px._btw-0px{border-top-width:0px;}
2434
2586
  :root ._btw-1px._btw-1px{border-top-width:1px;}
2587
+ :root ._bxsh-0px0px0pxrg933189164{box-shadow:0px 0px 0px rgba(0, 0, 0, 0);}
2435
2588
  :root:root:root ._col-0active-colorPress:active{color:var(--colorPress) !important;}
2436
2589
  @media (hover) {:root:root ._col-0hover-color12:hover{color:var(--color12) !important;}}
2437
2590
  :root ._col-color{color:var(--color);}
@@ -2445,6 +2598,7 @@
2445
2598
  :root ._cur-inherit{cursor:inherit;}
2446
2599
  :root ._cur-not-allowed{cursor:not-allowed;}
2447
2600
  :root ._cur-pointer{cursor:pointer;}
2601
+ :root ._cur-row-resize{cursor:row-resize;}
2448
2602
  :root ._direction-ltr{direction:ltr;}
2449
2603
  :root ._dsp-flex{display:flex;}
2450
2604
  :root ._dsp-inline-flex{display:inline-flex;}
@@ -2466,6 +2620,7 @@
2466
2620
  :root ._fwr-nowrap{flex-wrap:nowrap;}
2467
2621
  :root ._gap-24px{gap:24px;}
2468
2622
  :root ._gap-2px{gap:2px;}
2623
+ :root ._gap-6px{gap:6px;}
2469
2624
  :root ._gap-c-space-1{gap:var(--c-space-1);}
2470
2625
  :root ._gap-c-space-1--53{gap:var(--c-space-1--5);}
2471
2626
  :root ._gap-c-space-2{gap:var(--c-space-2);}
@@ -2476,16 +2631,19 @@
2476
2631
  :root ._height-10037{height:100%;}
2477
2632
  :root ._height-16px{height:16px;}
2478
2633
  :root ._height-20px{height:20px;}
2634
+ :root ._height-220px{height:220px;}
2479
2635
  :root ._height-32px{height:32px;}
2480
2636
  :root ._height-36px{height:36px;}
2481
2637
  :root ._height-40px{height:40px;}
2482
2638
  :root ._height-44px{height:44px;}
2639
+ :root ._height-5px{height:5px;}
2483
2640
  :root ._height-6px{height:6px;}
2484
2641
  :root ._height-7px{height:7px;}
2485
2642
  :root ._height-80px{height:80px;}
2486
2643
  :root ._height-8px{height:8px;}
2487
2644
  :root ._height-NaNpx{height:NaNpx;}
2488
2645
  :root ._height-auto{height:auto;}
2646
+ :root ._height-c-size-1{height:var(--c-size-1);}
2489
2647
  :root ._height-initial{height:initial;}
2490
2648
  :root ._items-center{align-items:center;}
2491
2649
  :root ._items-flex-start{align-items:flex-start;}
@@ -2509,12 +2667,14 @@
2509
2667
  :root ._maxH-16px{max-height:16px;}
2510
2668
  :root ._maxH-300px{max-height:300px;}
2511
2669
  :root ._maxH-32px{max-height:32px;}
2670
+ :root ._maxH-c-size-1{max-height:var(--c-size-1);}
2512
2671
  :root ._maxH-initial{max-height:initial;}
2513
2672
  :root ._maxW-0px{max-width:0px;}
2514
2673
  :root ._maxW-10037{max-width:100%;}
2515
2674
  :root ._maxW-16px{max-width:16px;}
2516
2675
  :root ._maxW-32px{max-width:32px;}
2517
2676
  :root ._maxW-600px{max-width:600px;}
2677
+ :root ._maxW-c-size-1{max-width:var(--c-size-1);}
2518
2678
  :root ._mb-0px{margin-bottom:0px;}
2519
2679
  :root ._minH-16px{min-height:16px;}
2520
2680
  :root ._minH-20px{min-height:20px;}
@@ -2524,20 +2684,24 @@
2524
2684
  :root ._minH-40px{min-height:40px;}
2525
2685
  :root ._minH-44px{min-height:44px;}
2526
2686
  :root ._minH-64px{min-height:64px;}
2687
+ :root ._minH-c-size-1{min-height:var(--c-size-1);}
2527
2688
  :root ._minW-0px{min-width:0px;}
2528
2689
  :root ._minW-16px{min-width:16px;}
2529
2690
  :root ._minW-220px{min-width:220px;}
2530
2691
  :root ._minW-32px{min-width:32px;}
2531
2692
  :root ._minW-36px{min-width:36px;}
2532
2693
  :root ._minW-40px{min-width:40px;}
2694
+ :root ._minW-c-size-1{min-width:var(--c-size-1);}
2533
2695
  :root ._ml-0px{margin-left:0px;}
2534
2696
  :root ._ml-auto{margin-left:auto;}
2535
2697
  :root ._mr-0px{margin-right:0px;}
2536
2698
  :root ._mt--24px{margin-top:-24px;}
2537
2699
  :root ._mt-0px{margin-top:0px;}
2538
2700
  :root ._o-0{opacity:0;}
2701
+ :root ._o-0--4{opacity:0.4;}
2539
2702
  :root ._o-0--5{opacity:0.5;}
2540
2703
  :root ._o-0--6{opacity:0.6;}
2704
+ :root ._o-0--7{opacity:0.7;}
2541
2705
  @media (hover) {:root:root ._o-0hover-0--8:hover{opacity:0.8 !important;}}
2542
2706
  @media (hover) {:root:root ._o-0hover-0--9:hover{opacity:0.9 !important;}}
2543
2707
  :root ._o-1{opacity:1;}
@@ -2644,11 +2808,15 @@
2644
2808
  :root ._width-10px{width:10px;}
2645
2809
  :root ._width-16px{width:16px;}
2646
2810
  :root ._width-20037{width:200%;}
2811
+ :root ._width-260px{width:260px;}
2647
2812
  :root ._width-32px{width:32px;}
2648
2813
  :root ._width-36px{width:36px;}
2814
+ :root ._width-380px{width:380px;}
2649
2815
  :root ._width-4px{width:4px;}
2816
+ :root ._width-5px{width:5px;}
2650
2817
  :root ._width-8px{width:8px;}
2651
2818
  :root ._width-auto{width:auto;}
2819
+ :root ._width-c-size-1{width:var(--c-size-1);}
2652
2820
  :root ._ws-normal{white-space:normal;}
2653
2821
  :root ._ws-nowrap{white-space:nowrap;}
2654
2822
  :root ._ws-pre-wrap{white-space:pre-wrap;}
package/dist/theme.css CHANGED
@@ -588,6 +588,51 @@
588
588
  --shadow-lg:0 10px 15px -3px rgb(0 0 0 / .55), 0 4px 6px -4px rgb(0 0 0 / .55);
589
589
  --shadow-xl:0 20px 25px -5px rgb(0 0 0 / .60), 0 8px 10px -6px rgb(0 0 0 / .60);
590
590
  --shadow-2xl:var(--shadow-floating);
591
+
592
+ /* ——— the paper ——— */
593
+ /* Depth carries STATE, not decoration: which sheet is the workspace, which is
594
+ the tool in use, which one opened. Reach for a level before a border — if
595
+ two surfaces need separating, RAISE one rather than outline both, and a
596
+ surface that is already raised does not also need a box drawn round it.
597
+
598
+ A level is a tint AND the light on it, published as a pair, because the
599
+ alternative — every component composing its own `--edge-highlight,
600
+ --shadow-*` — is how two panels on one screen end up lit from two
601
+ directions. Every rung here is pure vertical: a 1px inset line along the
602
+ top edge, a drop straight down. One origin, above and slightly in front.
603
+
604
+ The tints are the surface recipes rather than new values, so sheets stack
605
+ the way paper does: each is an alpha-white wash, one laid on another lands
606
+ a step lighter, and the stack converges on #262626 instead of blowing out.
607
+
608
+ Nothing here is restated in `.light`, deliberately: every part defers to a
609
+ token that already flips, so the ramp inverts with the theme for free. */
610
+ --sheet-0:var(--surface-page); /* the workspace ground */
611
+ --sheet-1:var(--surface-card); /* an active tool */
612
+ --sheet-2:var(--surface-card-emphasis); /* what opened, or what is inside */
613
+ /* The drops are spelled out rather than read from the t-shirt ramp above, and
614
+ that is the whole reason this ladder can be shared. `--shadow-sm` is a name
615
+ this package does not own — @hanzo/brand declares the same names at :root
616
+ with white-canvas alphas, and load order decides who wins — so a rung built
617
+ on one is a rung somebody else can flatten. `--shadow-sheet-*` is ours
618
+ alone, which is what lets @hanzo/ui's `.elevation-*` read it instead of
619
+ keeping a private copy. The numbers ARE rung 1 and rung 2 of the ramp; if
620
+ one moves, move both. `--edge-highlight` stays deferred: it is role-named,
621
+ uncollided, and its `.light` zeroing is what makes one value work on both
622
+ canvases. */
623
+ --shadow-sheet-1:var(--edge-highlight),0 1px 2px 0 rgb(0 0 0 / .40);
624
+ --shadow-sheet-2:var(--edge-highlight),0 10px 15px -3px rgb(0 0 0 / .55),0 4px 6px -4px rgb(0 0 0 / .55);
625
+
626
+ /* The fold — a corner turned back, and the one mark that means THIS OPENS.
627
+ Ornament nowhere: a sheet that does not expand does not wear one.
628
+ It is a background-image, so it costs no element and no pseudo-element —
629
+ paint it on the sheet itself and square that corner
630
+ (`border-bottom-right-radius:0`), because a folded corner is not round.
631
+ The flap catches the light like every other surface; the crease is the
632
+ hairline; both defer, so both invert. */
633
+ --fold:12px;
634
+ --fold-face:linear-gradient(315deg,var(--glass-strong) 0,var(--glass-strong) calc(var(--fold) - 1px),var(--border-strong) calc(var(--fold) - 1px),var(--border-strong) var(--fold),transparent var(--fold)); /* @kind color */
635
+
591
636
  /* Ambient hero glow — a single white radial, blurred 120px, low opacity. */
592
637
  --glow-hero:radial-gradient(circle,rgb(255 255 255 / .12) 0%,transparent 68%); /* @kind color */
593
638
  --glow-hero-blur:120px;
@@ -620,6 +665,11 @@
620
665
  costs nothing. */
621
666
  .light, :root.t_light, .t_light{
622
667
  --shadow-floating:0 24px 60px -16px rgb(0 0 0 / .18);
668
+ /* On white the drop does all of it, so the paper rungs are restated here even
669
+ though check 4 does not demand it — their white is inside --edge-highlight,
670
+ which flips underneath. Rung 1 and rung 2 of the light ramp, same as dark. */
671
+ --shadow-sheet-1:var(--edge-highlight),0 1px 2px 0 rgb(0 0 0 / .06);
672
+ --shadow-sheet-2:var(--edge-highlight),0 10px 15px -3px rgb(0 0 0 / .09),0 4px 6px -4px rgb(0 0 0 / .07);
623
673
  --shadow-inset-hairline:inset 0 0 0 1px rgb(0 0 0 / .10);
624
674
  --edge-highlight:inset 0 0 0 0 transparent;
625
675
  --bloom:0 6px 20px -4px rgb(0 0 0 / .18);
@@ -1160,19 +1210,66 @@
1160
1210
  from inside it, and a menu with no background is a menu you read the page
1161
1211
  through. !important beats the compiled atomic background class, which lands
1162
1212
  in an inline <style> a bundler orders after this sheet, and it beats the call
1163
- sites that pin a fill by hand — those become no-ops instead of holes. */
1213
+ sites that pin a fill by hand — those become no-ops instead of holes.
1214
+
1215
+ EVERY floating slot the package emits is here. It was seven, and the three it
1216
+ left out were not obscure: AlertDialog is a MODAL — the one surface that
1217
+ cannot be anything but floating — and it was opaque beside a glass Dialog.
1218
+ ContextMenu and HoverCard are anchored menus beside glass DropdownMenu and
1219
+ glass Popover. That is precisely the drift this file exists to stop, still
1220
+ present in the file that stops it, which is worth stating plainly: a rule
1221
+ that attaches the material to the slot only holds if every slot is named.
1222
+ The list is checked against what the components actually emit, so the next
1223
+ floating slot somebody adds fails the test rather than the eye. */
1164
1224
  @supports (backdrop-filter: blur(8px)) {
1165
1225
  .glass,
1166
1226
  [data-slot="glass"],
1167
1227
  [data-slot="dialog-content"],
1228
+ [data-slot="alert-dialog-content"],
1168
1229
  [data-slot="popover-content"],
1169
1230
  [data-slot="select-content"],
1170
1231
  [data-slot="dropdown-menu-content"],
1171
1232
  [data-slot="dropdown-menu-sub-content"],
1233
+ [data-slot="context-menu-content"],
1234
+ [data-slot="context-menu-sub-content"],
1235
+ [data-slot="hover-card-content"],
1172
1236
  [data-slot="tooltip-content"] {
1173
1237
  background-color: color-mix(in oklab, var(--background) 72%, transparent) !important;
1174
1238
  -webkit-backdrop-filter: blur(20px) saturate(1.8);
1175
1239
  backdrop-filter: blur(20px) saturate(1.8);
1240
+ /* ── The dispersion ──────────────────────────────────────────────────────
1241
+ Glass splits light at the EDGE. That is the whole of the physics and the
1242
+ whole of the rule: the body of a pane shows you what is behind it, and the
1243
+ rim is where the angle is steep enough to spread the spectrum. So the fill
1244
+ stays monochrome — the brand is monochrome and text has to sit on it — and
1245
+ the colour lives in one pixel at the top lip.
1246
+
1247
+ LINEAR, ACROSS THE LIP — never conic around the box. The composer's note
1248
+ below records what conic costs on a rectangle: the long edges take a wide
1249
+ angular slice and the short sides almost none, so one side wears blue and
1250
+ the opposite burnt orange, and the ring reads as off-centre. Swept along
1251
+ one edge instead, the stops are evenly spaced at any aspect ratio, so a
1252
+ 1000px dialog and a 90px tooltip disperse alike.
1253
+
1254
+ Peak alpha .16, on a band two pixels tall, one pixel DOWN. Both numbers
1255
+ were measured rather than chosen. The lit edge is an inset box-shadow, and
1256
+ a box-shadow paints over the background — so the first version put the
1257
+ spectrum in the same pixel the white lip occupies and the lip won: at ×6
1258
+ the rim was a neutral hairline with no colour in it at all. Sitting the
1259
+ band one pixel inside puts it where a real pane disperses anyway, just
1260
+ behind the specular line, and it is legible there at half the alpha a
1261
+ collision would have needed. Three pixels at .22 was tried too and reads
1262
+ as a coloured stroke somebody drew, which is a different thing entirely.
1263
+
1264
+ That is also the difference between this and the full-wheel rainbow that
1265
+ was tried and reverted: not a different palette, a different AREA. Colour
1266
+ over a whole surface makes that surface the only coloured thing in the
1267
+ product; colour along its rim reads as the material catching light, which
1268
+ is the one thing chrome is allowed to say. */
1269
+ background-image: var(--glass-prism) !important;
1270
+ background-repeat: no-repeat !important;
1271
+ background-size: 100% 2px !important;
1272
+ background-position: 0 1px !important;
1176
1273
  }
1177
1274
  }
1178
1275
 
@@ -1226,6 +1323,24 @@
1226
1323
  --glass-shadow-1: 0 1px 2px 0 rgb(0 0 0 / .40);
1227
1324
  --glass-shadow-2: 0 10px 15px -3px rgb(0 0 0 / .55), 0 4px 6px -4px rgb(0 0 0 / .55);
1228
1325
  --glass-shadow-3: 0 24px 60px -16px rgb(0 0 0 / .75);
1326
+
1327
+ /* The spectrum the lip disperses. Declared here for the same reason the drops
1328
+ above are: a name this package owns cannot be outranked by a sheet that
1329
+ happens to load later. Nothing else ships a --glass-prism.
1330
+
1331
+ Five stops, blue through violet, rose, amber, to a cool green — the order
1332
+ light actually comes apart in, so it reads as refraction rather than as a
1333
+ palette somebody chose. Alphas .13-.16: measured at ×6 against the white lip
1334
+ that sits a pixel above, high enough to read there and low enough that at
1335
+ 1:1 it is a tinge. A theme that wants none of it sets this to `none` and the
1336
+ rim goes back to being the lit edge alone. */
1337
+ --glass-prism:
1338
+ linear-gradient(90deg,
1339
+ rgb(120 170 255 / .16) 0%,
1340
+ rgb(178 142 255 / .15) 24%,
1341
+ rgb(255 146 198 / .13) 48%,
1342
+ rgb(255 190 124 / .15) 72%,
1343
+ rgb(138 228 208 / .16) 100%);
1229
1344
  }
1230
1345
 
1231
1346
  .light, :root.t_light, .t_light {
@@ -1245,6 +1360,9 @@
1245
1360
  [data-slot="select-content"],
1246
1361
  [data-slot="dropdown-menu-content"],
1247
1362
  [data-slot="dropdown-menu-sub-content"],
1363
+ [data-slot="context-menu-content"],
1364
+ [data-slot="context-menu-sub-content"],
1365
+ [data-slot="hover-card-content"],
1248
1366
  [data-slot="tooltip-content"] {
1249
1367
  box-shadow:
1250
1368
  var(--edge-highlight, inset 0 1px 0 0 rgb(255 255 255 / .10)),
@@ -1252,12 +1370,38 @@
1252
1370
  }
1253
1371
 
1254
1372
  .elevation-3,
1255
- [data-slot="dialog-content"] {
1373
+ [data-slot="dialog-content"],
1374
+ [data-slot="alert-dialog-content"] {
1256
1375
  box-shadow:
1257
1376
  var(--edge-highlight, inset 0 1px 0 0 rgb(255 255 255 / .10)),
1258
1377
  var(--glass-shadow-3) !important;
1259
1378
  }
1260
1379
 
1380
+ /* ── The fold — the one mark that means an item opens ────────────────────────
1381
+ A corner turned back, painted onto the sheet itself. It is a class and not a
1382
+ pair of style props because gui compiles those into atomic classes and a
1383
+ background-image is not one of the properties it maps; and because a fold has
1384
+ exactly one spelling, so the call site should not be able to invent a second
1385
+ one. `--fold-face` is @hanzo/design's, with the dark value inline so a host
1386
+ that took this sheet without the token layer still gets a corner rather than
1387
+ a silently-dropped declaration.
1388
+
1389
+ The corner is SQUARED, not rounded: a folded corner is a straight crease, and
1390
+ a rounded one under a triangle reads as a rendering fault. That is also why
1391
+ this carries !important — the radius it has to beat is a compiled style prop.
1392
+
1393
+ Spend it only where the thing expands. A fold on a surface that opens nothing
1394
+ is a chevron that never turns. */
1395
+ .fold {
1396
+ background-image: var(--fold-face,
1397
+ linear-gradient(315deg,
1398
+ rgb(255 255 255 / .08) 0, rgb(255 255 255 / .08) 11px,
1399
+ rgb(255 255 255 / .16) 11px, rgb(255 255 255 / .16) 12px,
1400
+ transparent 12px)) !important;
1401
+ background-repeat: no-repeat !important;
1402
+ border-bottom-right-radius: 0 !important;
1403
+ }
1404
+
1261
1405
  /* ── The scrim ──────────────────────────────────────────────────────────────
1262
1406
  The dim that makes a floating panel read as floating rather than as more
1263
1407
  page. gui's overlay dims TWICE — a translucent ground under a further
@@ -1277,7 +1421,8 @@
1277
1421
  palette: `rgba(0,0,0,.5)` under `opacity: .5` — a quarter black, exactly the
1278
1422
  double dim these two lines exist to end. A rule written to beat a compiled
1279
1423
  class has to be written with the weight to beat one. */
1280
- [data-slot="dialog-overlay"] {
1424
+ [data-slot="dialog-overlay"],
1425
+ [data-slot="alert-dialog-overlay"] {
1281
1426
  opacity: 1 !important;
1282
1427
  background-color: var(--surface-scrim, rgb(0 0 0 / .8)) !important;
1283
1428
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/ui",
3
- "version": "8.0.76",
3
+ "version": "8.0.81",
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": {
@@ -188,7 +188,7 @@
188
188
  ],
189
189
  "dependencies": {
190
190
  "@hanzo/appearance": "^0.1.4",
191
- "@hanzo/design": "^0.5.1",
191
+ "@hanzo/design": "^0.5.3",
192
192
  "@hanzo/logo": "^1.0.13",
193
193
  "@hanzo/products": "^0.2.0",
194
194
  "@hanzogui/lucide-icons-2": "^8.1.0",