@hanzo/ui 8.27.44 → 8.27.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/dist/backends/gui/animated-testimonials.cjs +2 -2
  2. package/dist/backends/gui/animated-testimonials.js +2 -2
  3. package/dist/backends/gui/animated-testimonials.js.map +1 -1
  4. package/dist/backends/gui/animated-tooltip.cjs +2 -2
  5. package/dist/backends/gui/animated-tooltip.js +2 -2
  6. package/dist/backends/gui/animated-tooltip.js.map +1 -1
  7. package/dist/backends/gui/carousel.cjs +2 -2
  8. package/dist/backends/gui/carousel.d.ts.map +1 -1
  9. package/dist/backends/gui/carousel.js +2 -2
  10. package/dist/backends/gui/carousel.js.map +1 -1
  11. package/dist/backends/gui/index.cjs +4 -5
  12. package/dist/backends/gui/index.d.ts +1 -1
  13. package/dist/backends/gui/index.d.ts.map +1 -1
  14. package/dist/backends/gui/index.js +1 -1
  15. package/dist/backends/gui/index.js.map +1 -1
  16. package/dist/backends/gui/input-otp.cjs +2 -1
  17. package/dist/backends/gui/input-otp.d.ts.map +1 -1
  18. package/dist/backends/gui/input-otp.js +2 -1
  19. package/dist/backends/gui/input-otp.js.map +1 -1
  20. package/dist/backends/gui/navigation-menu.cjs +24 -6
  21. package/dist/backends/gui/navigation-menu.d.ts +0 -6
  22. package/dist/backends/gui/navigation-menu.d.ts.map +1 -1
  23. package/dist/backends/gui/navigation-menu.js +23 -5
  24. package/dist/backends/gui/navigation-menu.js.map +1 -1
  25. package/dist/backends/gui/prose.cjs +4 -18
  26. package/dist/backends/gui/prose.d.ts +8 -5
  27. package/dist/backends/gui/prose.d.ts.map +1 -1
  28. package/dist/backends/gui/prose.js +4 -18
  29. package/dist/backends/gui/prose.js.map +1 -1
  30. package/dist/backends/gui/skeleton.cjs +1 -1
  31. package/dist/backends/gui/skeleton.d.ts.map +1 -1
  32. package/dist/backends/gui/skeleton.js +1 -1
  33. package/dist/backends/gui/skeleton.js.map +1 -1
  34. package/dist/backends/gui/timeline.cjs +2 -2
  35. package/dist/backends/gui/timeline.d.ts +1 -1
  36. package/dist/backends/gui/timeline.js +2 -2
  37. package/dist/backends/gui/timeline.js.map +1 -1
  38. package/dist/backends/gui/video.cjs +1 -1
  39. package/dist/backends/gui/video.js +1 -1
  40. package/dist/backends/gui/video.js.map +1 -1
  41. package/dist/chat/Composer.cjs +6 -1
  42. package/dist/chat/Composer.d.ts.map +1 -1
  43. package/dist/chat/Composer.js +6 -1
  44. package/dist/chat/Composer.js.map +1 -1
  45. package/dist/chat/SessionRail.cjs +1 -4
  46. package/dist/chat/SessionRail.js +1 -4
  47. package/dist/chat/SessionRail.js.map +1 -1
  48. package/dist/core/cn.cjs +1 -1
  49. package/dist/core/cn.d.ts +1 -1
  50. package/dist/core/cn.js +1 -1
  51. package/dist/gallery.html +481 -598
  52. package/dist/glass.cjs +2 -24
  53. package/dist/glass.css +0 -196
  54. package/dist/glass.d.ts +2 -26
  55. package/dist/glass.d.ts.map +1 -1
  56. package/dist/glass.js +1 -22
  57. package/dist/glass.js.map +1 -1
  58. package/dist/grid.cjs +60 -10
  59. package/dist/grid.d.ts +20 -24
  60. package/dist/grid.d.ts.map +1 -1
  61. package/dist/grid.js +60 -10
  62. package/dist/grid.js.map +1 -1
  63. package/dist/index.cjs +6 -2
  64. package/dist/index.d.ts +2 -1
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +4 -1
  67. package/dist/index.js.map +1 -1
  68. package/dist/index.node.cjs +6 -2
  69. package/dist/index.node.js +4 -1
  70. package/dist/masthead/index.cjs +3 -12
  71. package/dist/masthead/index.d.ts +3 -6
  72. package/dist/masthead/index.d.ts.map +1 -1
  73. package/dist/masthead/index.js +3 -6
  74. package/dist/masthead/index.js.map +1 -1
  75. package/dist/motion.cjs +20 -0
  76. package/dist/motion.d.ts +17 -0
  77. package/dist/motion.d.ts.map +1 -0
  78. package/dist/motion.js +16 -0
  79. package/dist/motion.js.map +1 -0
  80. package/dist/product/DataTable.cjs +24 -4
  81. package/dist/product/DataTable.d.ts +0 -16
  82. package/dist/product/DataTable.d.ts.map +1 -1
  83. package/dist/product/DataTable.js +24 -4
  84. package/dist/product/DataTable.js.map +1 -1
  85. package/dist/product/FadeIn.cjs +1 -1
  86. package/dist/product/FadeIn.js +1 -1
  87. package/dist/product/FadeIn.js.map +1 -1
  88. package/dist/product/Metric.cjs +19 -2
  89. package/dist/product/Metric.d.ts +0 -16
  90. package/dist/product/Metric.d.ts.map +1 -1
  91. package/dist/product/Metric.js +19 -2
  92. package/dist/product/Metric.js.map +1 -1
  93. package/dist/product/Reorder.cjs +1 -1
  94. package/dist/product/Reorder.js +1 -1
  95. package/dist/product/Reorder.js.map +1 -1
  96. package/dist/product/Skeleton.cjs +5 -5
  97. package/dist/product/Skeleton.d.ts +4 -4
  98. package/dist/product/Skeleton.d.ts.map +1 -1
  99. package/dist/product/Skeleton.js +5 -5
  100. package/dist/product/Skeleton.js.map +1 -1
  101. package/dist/product/SlideOver.cjs +2 -10
  102. package/dist/product/SlideOver.d.ts.map +1 -1
  103. package/dist/product/SlideOver.js +2 -10
  104. package/dist/product/SlideOver.js.map +1 -1
  105. package/dist/product/figures.cjs +16 -0
  106. package/dist/product/figures.d.ts +16 -0
  107. package/dist/product/figures.d.ts.map +1 -0
  108. package/dist/product/figures.js +14 -0
  109. package/dist/product/figures.js.map +1 -0
  110. package/dist/product/social/SocialResource.cjs +2 -1
  111. package/dist/product/social/SocialResource.d.ts.map +1 -1
  112. package/dist/product/social/SocialResource.js +2 -1
  113. package/dist/product/social/SocialResource.js.map +1 -1
  114. package/dist/product/social/SocialSummaryBar.cjs +2 -1
  115. package/dist/product/social/SocialSummaryBar.d.ts.map +1 -1
  116. package/dist/product/social/SocialSummaryBar.js +2 -1
  117. package/dist/product/social/SocialSummaryBar.js.map +1 -1
  118. package/dist/style.cjs +1 -4
  119. package/dist/style.d.ts +0 -2
  120. package/dist/style.d.ts.map +1 -1
  121. package/dist/style.js +0 -2
  122. package/dist/style.js.map +1 -1
  123. package/dist/styles/motion.css +61 -283
  124. package/dist/styles.css +478 -595
  125. package/dist/sx.cjs +1 -1
  126. package/dist/sx.js +1 -1
  127. package/dist/theme.css +369 -292
  128. package/package.json +3 -4
  129. package/dist/masthead/Masthead.cjs +0 -168
  130. package/dist/masthead/Masthead.d.ts +0 -54
  131. package/dist/masthead/Masthead.d.ts.map +0 -1
  132. package/dist/masthead/Masthead.js +0 -162
  133. package/dist/masthead/Masthead.js.map +0 -1
  134. package/dist/masthead.css +0 -502
  135. package/dist/primitives/navigationMenuTriggerStyle.cjs +0 -8
  136. package/dist/primitives/navigationMenuTriggerStyle.d.ts +0 -2
  137. package/dist/primitives/navigationMenuTriggerStyle.d.ts.map +0 -1
  138. package/dist/primitives/navigationMenuTriggerStyle.js +0 -5
  139. package/dist/primitives/navigationMenuTriggerStyle.js.map +0 -1
package/dist/styles.css CHANGED
@@ -1332,13 +1332,8 @@
1332
1332
  src/glass.css and are inlined here by scripts/compose-theme.mjs — one home,
1333
1333
  two entry points (`@hanzo/ui/theme.css` and `@hanzo/ui/glass.css`), so a host
1334
1334
  that wants only the chrome material does not have to take the token layer
1335
- with it.
1336
-
1337
- They used to be four `.elevation-*` rules reading `var(--hz-elevation-N, …)`.
1338
- Nothing in this repo, in @hanzo/design or in any consumer ever DEFINED an
1339
- `--hz-elevation-*` variable, so every one of those resolved to its fallback:
1340
- an indirection through a name that does not exist, with a hardcoded shadow
1341
- behind it, next to a design system that publishes real ones. */
1335
+ with it. The ladder reads @hanzo/design's own shadows, never a private
1336
+ variable nothing defines. */
1342
1337
 
1343
1338
  /* ── Prose ───────────────────────────────────────────────────────────────────
1344
1339
  What `<ApplyTypography>` turns on: running text — a heading, a byline, a
@@ -1352,12 +1347,13 @@
1352
1347
  @hanzo/design ramp, which is where every other surface already reads them —
1353
1348
  so prose and a Button now round to the same scale instead of two.
1354
1349
 
1355
- Scoped under `.hz-prose` and applied with `>` only one level down, so a nested
1356
- component keeps its own type. */
1357
- .hz-prose {
1358
- /* One implicit column with a gap — a grid states the stack without also
1359
- having to state a direction to run in. */
1360
- display: grid;
1350
+ Scoped under `[data-slot='prose']` and applied with `>` only one level down,
1351
+ so a nested component keeps its own type. The content arrives as bare tags
1352
+ (a CMS field, an .mdx file), which is the one case a prop cannot reach: the
1353
+ rules have to select by tag from the container. */
1354
+ [data-slot='prose'] {
1355
+ display: flex;
1356
+ flex-direction: column;
1361
1357
  gap: var(--space-3, 0.75rem);
1362
1358
  color: var(--foreground);
1363
1359
  font-family: var(--font-sans), sans-serif;
@@ -1365,8 +1361,8 @@
1365
1361
  line-height: var(--leading-base, var(--leading-normal));
1366
1362
  }
1367
1363
 
1368
- .hz-prose > h1, .hz-prose > h2, .hz-prose > h3,
1369
- .hz-prose > h4, .hz-prose > h5, .hz-prose > h6 {
1364
+ [data-slot='prose'] > h1, [data-slot='prose'] > h2, [data-slot='prose'] > h3,
1365
+ [data-slot='prose'] > h4, [data-slot='prose'] > h5, [data-slot='prose'] > h6 {
1370
1366
  font-family: var(--font-display, var(--font-sans)), sans-serif;
1371
1367
  font-weight: 606;
1372
1368
  line-height: var(--leading-tight);
@@ -1374,37 +1370,37 @@
1374
1370
  margin: 0;
1375
1371
  }
1376
1372
 
1377
- .hz-prose > h1 { font-size: var(--text-4xl) }
1378
- .hz-prose > h2 { font-size: var(--text-3xl) }
1379
- .hz-prose > h3 { font-size: var(--text-2xl) }
1380
- .hz-prose > h4 { font-size: var(--text-xl) }
1381
- .hz-prose > h5 { font-size: var(--text-lg) }
1373
+ [data-slot='prose'] > h1 { font-size: var(--text-4xl) }
1374
+ [data-slot='prose'] > h2 { font-size: var(--text-3xl) }
1375
+ [data-slot='prose'] > h3 { font-size: var(--text-2xl) }
1376
+ [data-slot='prose'] > h4 { font-size: var(--text-xl) }
1377
+ [data-slot='prose'] > h5 { font-size: var(--text-lg) }
1382
1378
  /* h6 is the byline rung: heading TAG, body weight and colour, because that is
1383
1379
  what a byline is — subordinate text that happens to sit in the heading
1384
1380
  stack. */
1385
- .hz-prose > h6 {
1381
+ [data-slot='prose'] > h6 {
1386
1382
  font-size: var(--text-base);
1387
1383
  font-weight: 497;
1388
1384
  color: var(--muted-foreground);
1389
1385
  }
1390
1386
 
1391
- .hz-prose > p { margin: 0 }
1387
+ [data-slot='prose'] > p { margin: 0 }
1392
1388
  /* The marker is RESTORED here. `base.css` takes it off every list in the
1393
1389
  document, because a nav and a card grid are both lists and neither wants one.
1394
1390
  Authored prose is the one place it belongs. Setting only the indent leaves an
1395
1391
  indented list with nothing at the start of the line. */
1396
- .hz-prose > ul, .hz-prose ul ul { list-style: disc }
1397
- .hz-prose > ol, .hz-prose ol ol { list-style: decimal }
1398
- .hz-prose ul, .hz-prose ol { margin: 0; padding-inline-start: 1.5em }
1399
- .hz-prose li { margin-block: 0.25em }
1400
- .hz-prose li::marker { color: var(--muted-foreground) }
1392
+ [data-slot='prose'] > ul, [data-slot='prose'] ul ul { list-style: disc }
1393
+ [data-slot='prose'] > ol, [data-slot='prose'] ol ol { list-style: decimal }
1394
+ [data-slot='prose'] ul, [data-slot='prose'] ol { margin: 0; padding-inline-start: 1.5em }
1395
+ [data-slot='prose'] li { margin-block: 0.25em }
1396
+ [data-slot='prose'] li::marker { color: var(--muted-foreground) }
1401
1397
 
1402
1398
  /* A code block is a SURFACE, not just a change of typeface. Without the panel
1403
1399
  it sits directly on the page ground and reads as body text that happens to be
1404
1400
  monospaced — which is exactly what a reader scanning for the command must not
1405
1401
  have to work out. `pre` already scrolls inside itself (base.css); this gives
1406
1402
  it the ground to scroll on. */
1407
- .hz-prose > pre {
1403
+ [data-slot='prose'] > pre {
1408
1404
  margin: 0;
1409
1405
  padding: var(--space-4, 1rem);
1410
1406
  border: 1px solid var(--border);
@@ -1415,97 +1411,61 @@
1415
1411
  }
1416
1412
  /* Inside a block the panel IS the surface, so the inline treatment would draw a
1417
1413
  second one around every line. */
1418
- .hz-prose > pre code { background: none; padding: 0; border: 0; font-size: inherit }
1419
- .hz-prose :not(pre) > code {
1414
+ [data-slot='prose'] > pre code { background: none; padding: 0; border: 0; font-size: inherit }
1415
+ [data-slot='prose'] :not(pre) > code {
1420
1416
  padding: 0.15em 0.35em;
1421
1417
  border-radius: calc(var(--radius, 0.5rem) / 2);
1422
1418
  background: var(--muted);
1423
1419
  }
1424
- .hz-prose > blockquote {
1420
+ [data-slot='prose'] > blockquote {
1425
1421
  margin: 0;
1426
1422
  padding-inline-start: 1em;
1427
1423
  border-inline-start: 2px solid var(--border);
1428
1424
  color: var(--muted-foreground);
1429
1425
  }
1430
- .hz-prose code {
1426
+ [data-slot='prose'] code {
1431
1427
  font-family: var(--font-mono), ui-monospace, monospace;
1432
1428
  font-size: 0.9em;
1433
1429
  }
1434
- .hz-prose a { color: inherit; text-decoration: underline }
1435
- .hz-prose strong { font-weight: 606 }
1436
- .hz-prose :where(img, video) { max-width: 100%; height: auto }
1430
+ [data-slot='prose'] a { color: inherit; text-decoration: underline }
1431
+ [data-slot='prose'] strong { font-weight: 606 }
1432
+ [data-slot='prose'] :where(img, video) { max-width: 100%; height: auto }
1437
1433
 
1438
1434
  /* The named rungs. `responsive` is the default and is the only one that moves
1439
1435
  with the viewport — a t-shirt size is a DECISION, so it stays put. */
1440
- .hz-prose-sm { font-size: var(--text-sm); gap: var(--space-3, 0.75rem) }
1441
- .hz-prose-sm > h1 { font-size: var(--text-3xl) }
1442
- .hz-prose-sm > h2 { font-size: var(--text-2xl) }
1443
- .hz-prose-sm > h3 { font-size: var(--text-xl) }
1444
- .hz-prose-sm > p { font-size: var(--text-sm) }
1445
-
1446
- .hz-prose-lg { font-size: var(--text-lg); gap: var(--space-5, 1.25rem) }
1447
- .hz-prose-lg > h1 { font-size: var(--text-5xl) }
1448
- .hz-prose-lg > h2 { font-size: var(--text-4xl) }
1449
- .hz-prose-lg > h3 { font-size: var(--text-3xl) }
1450
- .hz-prose-lg > p { font-size: var(--text-lg) }
1451
-
1452
- .hz-prose-xl { font-size: var(--text-lg); gap: var(--space-6, 1.5rem) }
1453
- .hz-prose-xl > h1 { font-size: var(--text-6xl) }
1454
- .hz-prose-xl > h2 { font-size: var(--text-5xl) }
1455
- .hz-prose-xl > h3 { font-size: var(--text-4xl) }
1456
- .hz-prose-xl > p { font-size: var(--text-lg) }
1436
+ [data-slot='prose'][data-size='sm'] { font-size: var(--text-sm); gap: var(--space-3, 0.75rem) }
1437
+ [data-slot='prose'][data-size='sm'] > h1 { font-size: var(--text-3xl) }
1438
+ [data-slot='prose'][data-size='sm'] > h2 { font-size: var(--text-2xl) }
1439
+ [data-slot='prose'][data-size='sm'] > h3 { font-size: var(--text-xl) }
1440
+ [data-slot='prose'][data-size='sm'] > p { font-size: var(--text-sm) }
1441
+
1442
+ [data-slot='prose'][data-size='lg'] { font-size: var(--text-lg); gap: var(--space-5, 1.25rem) }
1443
+ [data-slot='prose'][data-size='lg'] > h1 { font-size: var(--text-5xl) }
1444
+ [data-slot='prose'][data-size='lg'] > h2 { font-size: var(--text-4xl) }
1445
+ [data-slot='prose'][data-size='lg'] > h3 { font-size: var(--text-3xl) }
1446
+ [data-slot='prose'][data-size='lg'] > p { font-size: var(--text-lg) }
1447
+
1448
+ [data-slot='prose'][data-size='xl'] { font-size: var(--text-lg); gap: var(--space-6, 1.5rem) }
1449
+ [data-slot='prose'][data-size='xl'] > h1 { font-size: var(--text-6xl) }
1450
+ [data-slot='prose'][data-size='xl'] > h2 { font-size: var(--text-5xl) }
1451
+ [data-slot='prose'][data-size='xl'] > h3 { font-size: var(--text-4xl) }
1452
+ [data-slot='prose'][data-size='xl'] > p { font-size: var(--text-lg) }
1457
1453
 
1458
1454
  /* Responsive: start at the small rung and climb. Written as min-width so the
1459
1455
  phone case is the unprefixed one and needs no query at all. */
1460
1456
  @media (min-width: 640px) {
1461
- .hz-prose-responsive { gap: var(--space-4, 1rem) }
1457
+ [data-slot='prose'][data-size='responsive'] { gap: var(--space-4, 1rem) }
1462
1458
  }
1463
1459
  @media (min-width: 1024px) {
1464
- .hz-prose-responsive { font-size: var(--text-lg); gap: var(--space-5, 1.25rem) }
1465
- .hz-prose-responsive > h1 { font-size: var(--text-5xl) }
1466
- .hz-prose-responsive > h2 { font-size: var(--text-4xl) }
1467
- .hz-prose-responsive > h3 { font-size: var(--text-3xl) }
1460
+ [data-slot='prose'][data-size='responsive'] { font-size: var(--text-lg); gap: var(--space-5, 1.25rem) }
1461
+ [data-slot='prose'][data-size='responsive'] > h1 { font-size: var(--text-5xl) }
1462
+ [data-slot='prose'][data-size='responsive'] > h2 { font-size: var(--text-4xl) }
1463
+ [data-slot='prose'][data-size='responsive'] > h3 { font-size: var(--text-3xl) }
1468
1464
  }
1469
1465
  @media (min-width: 1280px) {
1470
- .hz-prose-responsive { gap: var(--space-6, 1.5rem) }
1471
- .hz-prose-responsive > h1 { font-size: var(--text-6xl) }
1472
- .hz-prose-responsive > h2 { font-size: var(--text-5xl) }
1473
- }
1474
-
1475
- /* The two things a style PROP cannot say, because neither is a property of an
1476
- element: a keyframe, and a scrollbar. */
1477
-
1478
- /* Skeleton's pulse. Opacity only — animating a colour or a size would repaint
1479
- or reflow every frame for a placeholder nobody is looking at. */
1480
- @keyframes hz-pulse {
1481
- 50% { opacity: 0.5 }
1482
- }
1483
- .hz-pulse { animation: hz-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite }
1484
-
1485
- /* A carousel scrolls but must not show a bar: the arrows and the snap already
1486
- say it scrolls, and a bar that appears mid-drag shifts the slides under the
1487
- pointer. Firefox reads the property, WebKit the pseudo-element, and the
1488
- property rides on the component so only this half needs a sheet. */
1489
- .hz-scroller::-webkit-scrollbar { display: none }
1490
-
1491
- /* The drawn caret in a one-time-code box. The real one is hidden, because it
1492
- would sit at the left edge of an invisible full-width field rather than in
1493
- the box the next keystroke lands in. */
1494
- @keyframes hz-caret {
1495
- 0%, 49% { opacity: 1 }
1496
- 50%, 100% { opacity: 0 }
1497
- }
1498
- .hz-caret {
1499
- background: var(--foreground);
1500
- animation: hz-caret 1s steps(1) infinite;
1501
- }
1502
-
1503
- /* Motion is a preference, and all of the above is decoration. A caret that does
1504
- not blink is still a caret; one that does can trigger a migraine. */
1505
- @media (prefers-reduced-motion: reduce) {
1506
- .hz-pulse { animation: none }
1507
- .hz-caret { animation: none }
1508
- .hz-scroller { scroll-behavior: auto }
1466
+ [data-slot='prose'][data-size='responsive'] { gap: var(--space-6, 1.5rem) }
1467
+ [data-slot='prose'][data-size='responsive'] > h1 { font-size: var(--text-6xl) }
1468
+ [data-slot='prose'][data-size='responsive'] > h2 { font-size: var(--text-5xl) }
1509
1469
  }
1510
1470
 
1511
1471
  /* Glass — the material floating chrome is made of, and the ladder it stands on.
@@ -1754,73 +1714,6 @@
1754
1714
  border-bottom-right-radius: 0 !important;
1755
1715
  }
1756
1716
 
1757
- /* ── The crease — the valley where one sheet lies over another ───────────────
1758
- The ladder lifts a sheet with a drop that falls STRAIGHT DOWN: design's rule
1759
- is one light, above, and `check-tokens.mjs` fails the build on a sideways
1760
- offset. That is right, and it means the ladder has nothing to say about a
1761
- VERTICAL seam — and an app shell is nothing but vertical seams. A rail beside
1762
- a sidebar beside a pane, each a step apart on the ladder, still reads as three
1763
- abutting rectangles with lines ruled between them, because the only mark at
1764
- the seam is the hairline.
1765
-
1766
- What a real sheet lays on the one beneath it, side by side under a light from
1767
- above, is not a cast shadow — it is the valley going dark. Ambient occlusion
1768
- has no direction of its own, which is both why it is honest here and why it is
1769
- NOT spelled as a --shadow-*: those are directional by definition and this is
1770
- not one.
1771
-
1772
- A PSEUDO-ELEMENT, at z-index -1 inside an isolated stacking context, so it
1773
- paints above the sheet's own fill and below every child. That ordering is the
1774
- whole reason it is not a `background-image` (which `.fold` already claims on
1775
- this same element, !important, so the two would silently fight) and not an
1776
- inset `box-shadow` (which `.elevation-*` claims, likewise).
1777
-
1778
- No side named -> both edges, which is what a pane with a neighbour on each
1779
- hand needs. Name one and the other stops being drawn. */
1780
- :root {
1781
- --crease-ink: rgb(0 0 0 / .28);
1782
- --crease-depth: 20px;
1783
- }
1784
-
1785
- .light, :root.t_light, .t_light {
1786
- /* On white the valley is a smudge, not a shadow — the same redistribution the
1787
- drops make, and for the same reason. */
1788
- --crease-ink: rgb(0 0 0 / .05);
1789
- }
1790
-
1791
- .hz-crease {
1792
- position: relative;
1793
- /* Without this the -1 escapes and paints behind an ancestor's fill, which is
1794
- indistinguishable from the crease not being there at all. */
1795
- isolation: isolate;
1796
- }
1797
-
1798
- .hz-crease::before,
1799
- .hz-crease::after {
1800
- content: "";
1801
- position: absolute;
1802
- top: 0;
1803
- bottom: 0;
1804
- width: var(--crease-depth);
1805
- z-index: -1;
1806
- pointer-events: none;
1807
- }
1808
-
1809
- .hz-crease::before {
1810
- left: 0;
1811
- background-image: linear-gradient(to right, var(--crease-ink), transparent);
1812
- }
1813
-
1814
- .hz-crease::after {
1815
- right: 0;
1816
- background-image: linear-gradient(to left, var(--crease-ink), transparent);
1817
- }
1818
-
1819
- .hz-crease[data-crease="left"]::after,
1820
- .hz-crease[data-crease="right"]::before {
1821
- content: none;
1822
- }
1823
-
1824
1717
  /* ── The scrim ──────────────────────────────────────────────────────────────
1825
1718
  The dim that makes a floating panel read as floating rather than as more
1826
1719
  page. gui's overlay dims TWICE — a translucent ground under a further
@@ -1868,135 +1761,6 @@
1868
1761
  border-top: 1px solid var(--borderColor, var(--border));
1869
1762
  }
1870
1763
 
1871
- /* ── The composer prism — the ONE ring on any Hanzo surface ──────────────────
1872
- The composer is where you talk to Hanzo, so it is the thing that should look
1873
- alive, and it earns that with MOTION and LIGHT rather than hue. Every other
1874
- pixel of chrome stays monochrome; there is no second exemption, and the two
1875
- attempts to grant one (a violet ring, then a full-wheel rainbow) each made
1876
- the surface wearing it the only colour in the product.
1877
-
1878
- THIS LIVES HERE BECAUSE IT WAS DECLARED TWICE AND DRIFTED. hanzo.chat's
1879
- client/src/style.css and hanzo.app's assets/globals.css each carried a copy,
1880
- each calling itself "the ONE prism on any Hanzo surface". chat fixed the ring
1881
- to be a rim; hanzo.app's copy kept drawing a filled DISC and never got the
1882
- fix — invisible until a glass panel sat in it, at which point the whole
1883
- spectrum washed up through the composer's interior. chat also quieted the
1884
- halo (0.5 with a pulse -> 0.22, no pulse); hanzo.app kept the loud one. Two
1885
- copies of one look is how that happens, and neither app could see the other
1886
- was wrong.
1887
-
1888
- Structure: `.hz-composer` is a 1.5px-padded host; its direct child is the
1889
- panel. ::before is the ring, ::after the halo. Both are MASKED to exclude the
1890
- panel's footprint, so the ring is a rim BY CONSTRUCTION and the panel is free
1891
- to be any material — opaque, glass, anything. The stops are declared once and
1892
- read by both, because duplicated they drift on the first palette change and
1893
- nobody notices which half moved. */
1894
-
1895
- /* `@property` is what lets a conic angle animate. Where it is unsupported the
1896
- ring is simply static, which is a fine floor. */
1897
- @property --hz-angle {
1898
- syntax: "<angle>";
1899
- initial-value: 0deg;
1900
- inherits: false;
1901
- }
1902
-
1903
- :root {
1904
- /* One sweep, closing on the stop it opened with — a conic gradient whose
1905
- first and last stop differ shows a hard seam.
1906
-
1907
- LUMINANCE, NOT HUE. Four saturated stops at 0.40-0.48 alpha, swept around
1908
- a rounded RECTANGLE, do not distribute evenly: the long top and bottom
1909
- edges each take a wide angular slice and the short sides almost none, so
1910
- one edge wore a bright blue while the opposite wore a burnt orange — a
1911
- ring that highlights half the box and reads as sitting off-centre. White
1912
- at two close alphas removes the bright arc entirely, drops the peak from
1913
- 0.48 to 0.18, and keeps the slow drift as a sheen. hanzo.chat and
1914
- hanzo.app both declare exactly these stops; this is the package catching
1915
- up to its consumers — the copies must not drift again, and this file is
1916
- the home. */
1917
- --hz-spectrum: rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.18),
1918
- rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.18),
1919
- rgba(255, 255, 255, 0.1);
1920
- }
1921
-
1922
- @keyframes hzComposerSpin {
1923
- to {
1924
- --hz-angle: 360deg;
1925
- }
1926
- }
1927
-
1928
- .hz-composer {
1929
- position: relative;
1930
- isolation: isolate;
1931
- padding: 1.5px;
1932
- }
1933
-
1934
- /* The ring DRAWS A RING. `padding` is its thickness; the two-layer mask keeps
1935
- paint outside it — `content-box` is the hole, the full box the plate, and
1936
- `exclude` leaves the lip. */
1937
- .hz-composer::before {
1938
- content: "";
1939
- position: absolute;
1940
- inset: 0;
1941
- padding: 1.5px;
1942
- border-radius: inherit;
1943
- background: conic-gradient(from var(--hz-angle), var(--hz-spectrum));
1944
- animation: hzComposerSpin 10s linear infinite;
1945
- -webkit-mask:
1946
- linear-gradient(#000 0 0) content-box,
1947
- linear-gradient(#000 0 0);
1948
- mask:
1949
- linear-gradient(#000 0 0) content-box,
1950
- linear-gradient(#000 0 0);
1951
- mask-composite: exclude;
1952
- /* After the standard shorthand: WebKit aliases `mask` onto `-webkit-mask`, so
1953
- declaring this first lets the shorthand reset it to `source-over` — the
1954
- filled disc again, on exactly the browsers too old to have `mask-composite`
1955
- at all. */
1956
- -webkit-mask-composite: xor;
1957
- z-index: 0;
1958
- pointer-events: none;
1959
- }
1960
-
1961
- /* The halo lights the air AROUND the box and nothing behind it. */
1962
- .hz-composer::after {
1963
- content: "";
1964
- position: absolute;
1965
- inset: -6px;
1966
- padding: 6px;
1967
- /* Concentric with the box, NOT `inherit`: the halo lives 6px outside, so an
1968
- inherited corner on this larger box curves too tight and reads as a second,
1969
- mismatched rounding just outside the panel. */
1970
- border-radius: calc(1.5rem + 6px);
1971
- background: conic-gradient(from var(--hz-angle), var(--hz-spectrum));
1972
- filter: blur(16px);
1973
- opacity: 0.22;
1974
- animation: hzComposerSpin 10s linear infinite;
1975
- -webkit-mask:
1976
- linear-gradient(#000 0 0) content-box,
1977
- linear-gradient(#000 0 0);
1978
- mask:
1979
- linear-gradient(#000 0 0) content-box,
1980
- linear-gradient(#000 0 0);
1981
- mask-composite: exclude;
1982
- -webkit-mask-composite: xor;
1983
- z-index: -1;
1984
- pointer-events: none;
1985
- }
1986
-
1987
- /* The panel sits above ring and halo. */
1988
- .hz-composer > * {
1989
- position: relative;
1990
- z-index: 1;
1991
- }
1992
-
1993
- @media (prefers-reduced-motion: reduce) {
1994
- .hz-composer::before,
1995
- .hz-composer::after {
1996
- animation: none;
1997
- }
1998
- }
1999
-
2000
1764
  /* FOCUS RINGS THE CONTROL A PERSON SEES, WHICH IS THE WHOLE COMPOSER.
2001
1765
 
2002
1766
  `Composer` is a bordered box holding a field above a toolbar row, so it reads
@@ -2028,6 +1792,319 @@
2028
1792
  --outlineColor: transparent;
2029
1793
  }
2030
1794
 
1795
+ /* @hanzo/ui motion — the calm, restrained animation vocabulary the Hanzo
1796
+ surfaces share. One place defines the easing; components carry the name.
1797
+
1798
+ Import once at the app root: import '@hanzo/ui/styles/motion.css'
1799
+
1800
+ ── KEYED ON `data-motion`, NEVER ON A CLASS ─────────────────────────────────
1801
+ A component says what it does with one attribute — `data-motion="rise"` — and
1802
+ this sheet says how. The paint (a caret's ink, a skeleton's gradient) is the
1803
+ component's own gui props; what is left here is what no prop can say: a
1804
+ keyframe, a transition a preference can switch off, and the preference
1805
+ itself. Every animation is off under `prefers-reduced-motion: reduce`.
1806
+
1807
+ rise enter: fade up 10px over 400ms FadeIn, Timeline, tooltips
1808
+ fade opacity eases 240ms SlideOver's scrim
1809
+ slide transform eases 260ms SlideOver's panel
1810
+ drag a row eases into place while one is held Reorder
1811
+ pulse opacity dims and returns, 2s Pulse, StatusDot, Skeleton
1812
+ blink on/off, 1s Caret
1813
+ shimmer a highlight sweeps a placeholder product Skeleton
1814
+ unfold a sheet turns open about its hinge unfold() */
1815
+
1816
+ @keyframes rise {
1817
+ from {
1818
+ opacity: 0;
1819
+ transform: translateY(10px);
1820
+ }
1821
+ to {
1822
+ opacity: 1;
1823
+ transform: translateY(0);
1824
+ }
1825
+ }
1826
+
1827
+ [data-motion='rise'] {
1828
+ animation: rise 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
1829
+ will-change: transform, opacity;
1830
+ }
1831
+
1832
+ [data-motion='fade'] {
1833
+ transition: opacity 240ms cubic-bezier(0.16, 1, 0.3, 1);
1834
+ will-change: opacity;
1835
+ }
1836
+
1837
+ [data-motion='slide'] {
1838
+ transition: transform 260ms cubic-bezier(0.16, 1, 0.3, 1);
1839
+ will-change: transform;
1840
+ }
1841
+
1842
+ [data-motion='drag'] {
1843
+ touch-action: none;
1844
+ transition: transform 180ms cubic-bezier(0.16, 1, 0.3, 1);
1845
+ }
1846
+
1847
+ @keyframes dim {
1848
+ 50% {
1849
+ opacity: 0.5;
1850
+ }
1851
+ }
1852
+
1853
+ [data-motion='pulse'] {
1854
+ animation: dim 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
1855
+ }
1856
+
1857
+ @keyframes blink {
1858
+ 0%,
1859
+ 49% {
1860
+ opacity: 1;
1861
+ }
1862
+ 50%,
1863
+ 100% {
1864
+ opacity: 0;
1865
+ }
1866
+ }
1867
+
1868
+ [data-motion='blink'] {
1869
+ animation: blink 1s steps(1) infinite;
1870
+ }
1871
+
1872
+ @keyframes shimmer {
1873
+ 0% {
1874
+ background-position: -160px 0;
1875
+ }
1876
+ 100% {
1877
+ background-position: 160px 0;
1878
+ }
1879
+ }
1880
+
1881
+ [data-motion='shimmer'] {
1882
+ animation: shimmer 1.2s ease-in-out infinite;
1883
+ }
1884
+
1885
+ /* Unfold — how a sheet arrives. A panel that appears by fading is a rectangle
1886
+ switching on; a sheet of paper TURNS OPEN about the edge it is hinged on. The
1887
+ hinge is the only knob and the angle follows it, so a turn cannot open the
1888
+ wrong way. `perspective()` inside the transform puts the vanishing point at
1889
+ the sheet's own centre. Seven degrees over 220ms. */
1890
+ @keyframes unfold {
1891
+ from {
1892
+ opacity: 0;
1893
+ transform: perspective(1600px) rotateY(var(--turn, -7deg));
1894
+ }
1895
+ to {
1896
+ opacity: 1;
1897
+ transform: perspective(1600px) rotateY(0deg);
1898
+ }
1899
+ }
1900
+
1901
+ [data-motion='unfold'] {
1902
+ animation: unfold 220ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
1903
+ transform-origin: left center;
1904
+ will-change: transform, opacity;
1905
+ }
1906
+
1907
+ [data-motion='unfold'][data-hinge='right'] {
1908
+ transform-origin: right center;
1909
+ --turn: 7deg;
1910
+ }
1911
+
1912
+ @media (prefers-reduced-motion: reduce) {
1913
+ [data-motion] {
1914
+ animation: none;
1915
+ transition: none;
1916
+ }
1917
+ }
1918
+
1919
+ /* ── Layout guarantee ──────────────────────────────────────────────────────────
1920
+ Structural, so attached to a data attribute: it is the thing the primitive
1921
+ PROMISES, and a class can be lost by forgetting to pass it on. */
1922
+
1923
+ /* Media fills the ratio box instead of setting its own size. Without this an
1924
+ <img> renders at its intrinsic pixel size and either overflows the frame or
1925
+ sits letterboxed inside it, and the ratio the caller asked for is decoration.
1926
+ `display:block` kills the inline-baseline gap under the image. */
1927
+ [data-ratio] > img,
1928
+ [data-ratio] > video {
1929
+ width: 100%;
1930
+ height: 100%;
1931
+ object-fit: cover;
1932
+ display: block;
1933
+ }
1934
+
1935
+
1936
+ /* ─────────────────────────────────────────────────────────────────────────────
1937
+ Scrollbars, on the surfaces this package scrolls.
1938
+
1939
+ Left to the platform this is not neutral: Linux/GTK Chrome draws a wide track
1940
+ with STEPPER ARROWS at both ends, so a dark product grows two grey buttons per
1941
+ scroll region. Windows draws a wide light track. macOS overlays a thin one,
1942
+ which is the behaviour the other two should have had.
1943
+
1944
+ THE TWO HALVES MUST NOT BE DECLARED TOGETHER, and that is the whole subtlety.
1945
+ Chromium supports both the standard properties and the `::-webkit-scrollbar`
1946
+ pseudo-elements — but the moment `scrollbar-width` or `scrollbar-color` is
1947
+ anything other than `auto`, it takes the standard path and DISCARDS the entire
1948
+ webkit block. Shipping both is how 8.1.19 removed nothing: measured headed on
1949
+ Linux, as-shipped gave a 10px gutter with arrows, while the authored webkit
1950
+ rule alone gives 8px with none. Isolated: webkit-only 8px no arrows;
1951
+ standard-only 10px arrows; both together 10px arrows.
1952
+
1953
+ Neither half is redundant, so neither can simply be deleted — Firefox
1954
+ implements ONLY the standard properties, Safari ONLY the webkit ones. They are
1955
+ separated by engine instead: the webkit block applies wherever the selector is
1956
+ understood, and the standard properties apply only where it is not.
1957
+
1958
+ And it is invisible headless. Chromium's headless shell paints OVERLAY
1959
+ scrollbars, so nothing is drawn, `offsetWidth - clientWidth` is 0 on a blank
1960
+ page, and `getComputedStyle(el, '::-webkit-scrollbar-button').display` happily
1961
+ reports `none` for a rule that never ran. This must be checked headed.
1962
+ ───────────────────────────────────────────────────────────────────────────── */
1963
+
1964
+ /* Firefox and anything else with no webkit pseudo-elements. */
1965
+ @supports not selector(::-webkit-scrollbar) {
1966
+ :where(
1967
+ [data-slot='fill'],
1968
+ [data-slot='thread'],
1969
+ [data-slot='sources-strip'],
1970
+ [data-slot='sidebar-scroll'],
1971
+ [data-slot='scroll-area-viewport'],
1972
+ [data-slot='textarea'],
1973
+ [data-slot='composer-field']
1974
+ ) {
1975
+ scrollbar-width: thin;
1976
+ scrollbar-color: rgb(255 255 255 / 0.18) transparent;
1977
+ }
1978
+ .t_light :where(
1979
+ [data-slot='fill'],
1980
+ [data-slot='thread'],
1981
+ [data-slot='sources-strip'],
1982
+ [data-slot='sidebar-scroll'],
1983
+ [data-slot='scroll-area-viewport'],
1984
+ [data-slot='textarea'],
1985
+ [data-slot='composer-field']
1986
+ ) { scrollbar-color: rgb(0 0 0 / 0.20) transparent; }
1987
+ }
1988
+
1989
+ /* Chromium and Safari.
1990
+ The first rule is the load-bearing one and it is a RESET, not a style.
1991
+ @hanzo/design sets `scrollbar-color` and `scrollbar-width` on `:where(html)`
1992
+ (theme.css), and both INHERIT — so every element in the document already
1993
+ carries a non-`auto` value, Chromium takes the standard path, and the whole
1994
+ webkit block below is discarded before it is read. Nothing declared here can
1995
+ win until the inherited value is put back to `auto` on the element itself.
1996
+ That is why the arrows survived 8.1.19: the competing declaration was one
1997
+ level up and inherited, not a rule anyone would find in this file. */
1998
+ @supports selector(::-webkit-scrollbar) {
1999
+ :where(
2000
+ [data-slot='fill'],
2001
+ [data-slot='thread'],
2002
+ [data-slot='sources-strip'],
2003
+ [data-slot='sidebar-scroll'],
2004
+ [data-slot='scroll-area-viewport'],
2005
+ [data-slot='textarea'],
2006
+ [data-slot='composer-field']
2007
+ ) {
2008
+ scrollbar-width: auto;
2009
+ scrollbar-color: auto;
2010
+ }
2011
+
2012
+ :where(
2013
+ [data-slot='fill'],
2014
+ [data-slot='thread'],
2015
+ [data-slot='sources-strip'],
2016
+ [data-slot='sidebar-scroll'],
2017
+ [data-slot='scroll-area-viewport'],
2018
+ [data-slot='textarea'],
2019
+ [data-slot='composer-field']
2020
+ )::-webkit-scrollbar { width: 8px; height: 8px; }
2021
+
2022
+ /* The steppers. This is the rule that removes the arrows, and the reason the
2023
+ two halves had to be separated at all. */
2024
+ :where(
2025
+ [data-slot='fill'],
2026
+ [data-slot='thread'],
2027
+ [data-slot='sources-strip'],
2028
+ [data-slot='sidebar-scroll'],
2029
+ [data-slot='scroll-area-viewport'],
2030
+ [data-slot='textarea'],
2031
+ [data-slot='composer-field']
2032
+ )::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
2033
+
2034
+ :where(
2035
+ [data-slot='fill'],
2036
+ [data-slot='thread'],
2037
+ [data-slot='sources-strip'],
2038
+ [data-slot='sidebar-scroll'],
2039
+ [data-slot='scroll-area-viewport'],
2040
+ [data-slot='textarea'],
2041
+ [data-slot='composer-field']
2042
+ )::-webkit-scrollbar-track { background: transparent; }
2043
+
2044
+ :where(
2045
+ [data-slot='fill'],
2046
+ [data-slot='thread'],
2047
+ [data-slot='sources-strip'],
2048
+ [data-slot='sidebar-scroll'],
2049
+ [data-slot='scroll-area-viewport'],
2050
+ [data-slot='textarea'],
2051
+ [data-slot='composer-field']
2052
+ )::-webkit-scrollbar-thumb {
2053
+ background: rgb(255 255 255 / 0.18);
2054
+ border-radius: 999px;
2055
+ /* A transparent border with background-clip keeps the thumb off the very
2056
+ edge without a track colour doing it, so it reads as an overlay rather
2057
+ than a channel. */
2058
+ border: 2px solid transparent;
2059
+ background-clip: content-box;
2060
+ }
2061
+ :where(
2062
+ [data-slot='fill'],
2063
+ [data-slot='thread'],
2064
+ [data-slot='sources-strip'],
2065
+ [data-slot='sidebar-scroll'],
2066
+ [data-slot='scroll-area-viewport'],
2067
+ [data-slot='textarea'],
2068
+ [data-slot='composer-field']
2069
+ )::-webkit-scrollbar-thumb:hover {
2070
+ background: rgb(255 255 255 / 0.30);
2071
+ background-clip: content-box;
2072
+ }
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
+ )::-webkit-scrollbar-corner { background: transparent; }
2082
+
2083
+ .t_light :where(
2084
+ [data-slot='fill'],
2085
+ [data-slot='thread'],
2086
+ [data-slot='sources-strip'],
2087
+ [data-slot='sidebar-scroll'],
2088
+ [data-slot='scroll-area-viewport'],
2089
+ [data-slot='textarea'],
2090
+ [data-slot='composer-field']
2091
+ )::-webkit-scrollbar-thumb {
2092
+ background: rgb(0 0 0 / 0.20);
2093
+ background-clip: content-box;
2094
+ }
2095
+ }
2096
+
2097
+ /* A carousel scrolls but shows no bar: the arrows and the snap already say it
2098
+ scrolls, and a bar appearing mid-drag shifts the slides under the pointer.
2099
+ Firefox reads `scrollbar-width`, which the component sets; WebKit reads only
2100
+ the pseudo-element, which no prop can reach. */
2101
+ [data-slot='carousel-content']::-webkit-scrollbar { display: none; }
2102
+
2103
+ /* The textarea's resize grip is the other platform artefact in the same family:
2104
+ a diagonal hatch drawn by the UA that matches nothing. A composer that grows
2105
+ with its content does not need one. */
2106
+ :where([data-slot='textarea'], [data-slot='composer-field']) { resize: none; }
2107
+
2031
2108
  [stylesheet-group="0"]{}
2032
2109
  body{margin:0;}
2033
2110
  button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
@@ -2246,10 +2323,10 @@ input::-webkit-search-cancel-button,input::-webkit-search-decoration,input::-web
2246
2323
  is what gives it presence — so only the elements that set paragraphs are
2247
2324
  capped. A max-width can never make something wider, so this is safe inside a
2248
2325
  card or a column that is already narrower. */
2249
- .hz-prose > p,
2250
- .hz-prose > ul,
2251
- .hz-prose > ol,
2252
- .hz-prose > blockquote {
2326
+ [data-slot='prose'] > p,
2327
+ [data-slot='prose'] > ul,
2328
+ [data-slot='prose'] > ol,
2329
+ [data-slot='prose'] > blockquote {
2253
2330
  max-width: var(--measure);
2254
2331
  }
2255
2332
 
@@ -2326,14 +2403,14 @@ input::-webkit-search-cancel-button,input::-webkit-search-decoration,input::-web
2326
2403
  }
2327
2404
 
2328
2405
  /* ── Prose meets a control ────────────────────────────────────────────────
2329
- `.hz-prose a` is underlined on purpose: in running text an underline is what
2406
+ `[data-slot='prose'] a` is underlined on purpose: in running text an underline is what
2330
2407
  marks a link. A link wearing a button is not running text — it already reads
2331
2408
  as a control from its fill and its border — so the underline is noise inside
2332
2409
  it. Measured on every call to action across the lux slides, each of which
2333
2410
  sits inside prose. */
2334
- .hz-prose [data-slot="button"] a,
2335
- .hz-prose a[data-slot="button"],
2336
- .hz-prose button a {
2411
+ [data-slot='prose'] [data-slot="button"] a,
2412
+ [data-slot='prose'] a[data-slot="button"],
2413
+ [data-slot='prose'] button a {
2337
2414
  text-decoration: none;
2338
2415
  }
2339
2416
 
@@ -2342,22 +2419,22 @@ input::-webkit-search-cancel-button,input::-webkit-search-decoration,input::-web
2342
2419
  a 52px display line and a 17px sub-head: 8px under the display line read as
2343
2420
  the byline touching it. `em` here is the heading's own size, so the ratio
2344
2421
  holds at every rung. A caller setting its own margin still wins. */
2345
- .hz-prose > h1 { margin-block-end: .5em }
2346
- .hz-prose > h2 { margin-block-end: .55em }
2347
- .hz-prose > h3 { margin-block-end: .6em }
2348
- .hz-prose > h4,
2349
- .hz-prose > h5,
2350
- .hz-prose > h6 { margin-block-end: .75em }
2422
+ [data-slot='prose'] > h1 { margin-block-end: .5em }
2423
+ [data-slot='prose'] > h2 { margin-block-end: .55em }
2424
+ [data-slot='prose'] > h3 { margin-block-end: .6em }
2425
+ [data-slot='prose'] > h4,
2426
+ [data-slot='prose'] > h5,
2427
+ [data-slot='prose'] > h6 { margin-block-end: .75em }
2351
2428
 
2352
2429
  /* Space ABOVE a heading is larger than the space below it — that asymmetry is
2353
2430
  what groups a heading with the text it introduces rather than the text it
2354
2431
  follows. Not applied to the first child, which has nothing to separate from. */
2355
- .hz-prose > h1:not(:first-child) { margin-block-start: 1.1em }
2356
- .hz-prose > h2:not(:first-child) { margin-block-start: 1.2em }
2357
- .hz-prose > h3:not(:first-child),
2358
- .hz-prose > h4:not(:first-child),
2359
- .hz-prose > h5:not(:first-child),
2360
- .hz-prose > h6:not(:first-child) { margin-block-start: 1.4em }
2432
+ [data-slot='prose'] > h1:not(:first-child) { margin-block-start: 1.1em }
2433
+ [data-slot='prose'] > h2:not(:first-child) { margin-block-start: 1.2em }
2434
+ [data-slot='prose'] > h3:not(:first-child),
2435
+ [data-slot='prose'] > h4:not(:first-child),
2436
+ [data-slot='prose'] > h5:not(:first-child),
2437
+ [data-slot='prose'] > h6:not(:first-child) { margin-block-start: 1.4em }
2361
2438
 
2362
2439
  /* ── The line-height a converted box inherits ─────────────────────────────
2363
2440
  gui's Stack stamps its own leading, which is right for a native view and
@@ -2396,34 +2473,28 @@ a svg,
2396
2473
  flex-shrink: 0;
2397
2474
  }
2398
2475
 
2399
- /* @hanzo/ui motion primitives — the calm, restrained animation vocabulary the
2400
- Hanzo surfaces share. One place defines the easing; components apply the class.
2401
- `className` forwards to the underlying DOM node on web, so the browser
2402
- transitions the Gui-driven inline width/transform/opacity. Every animation is
2403
- guarded by `prefers-reduced-motion: reduce`.
2476
+ /* @hanzo/ui motion — the calm, restrained animation vocabulary the Hanzo
2477
+ surfaces share. One place defines the easing; components carry the name.
2404
2478
 
2405
2479
  Import once at the app root: import '@hanzo/ui/styles/motion.css'
2406
2480
 
2407
- ── EVERY CLASS HERE IS `hz-` PREFIXED, and it was not always ────────────────
2408
- This sheet used to claim `.row`, `.skeleton`, `.fade`, `.mono`, `.drag` and
2409
- `.tnum` — six of the most ordinary words in anyone's CSS — at the document
2410
- level, in a package an app imports once at its root. An app with its own
2411
- `.row` did not get a warning; it got whichever rule the cascade preferred, in
2412
- a stylesheet it never opened. A library's utility classes are its namespace,
2413
- so they carry its name.
2414
-
2415
- The unprefixed selectors are kept as aliases on the SAME rule so nothing
2416
- breaks mid-flight, and are REMOVED IN 8.2.0. Nothing in this package emits
2417
- them any more — they exist only for a consumer who typed
2418
- `className="skeleton"` against the old sheet. (The target was 8.1.0, and
2419
- 8.1.0 went out carrying additions instead. Moving the date is the honest
2420
- edit: shipping the version a comment says removed something, without
2421
- removing it, is how a deprecation note stops being read.) Keyframe names are prefixed too
2422
- and have no alias: nothing outside this file ever referenced them. */
2423
-
2424
- /* Fade-up entrance — <FadeIn> applies the class + a per-item stagger delay.
2425
- ~0.4s ease-out, small upward travel (matches the hanzo.ai marketing feel). */
2426
- @keyframes hz-fade-up {
2481
+ ── KEYED ON `data-motion`, NEVER ON A CLASS ─────────────────────────────────
2482
+ A component says what it does with one attribute — `data-motion="rise"` — and
2483
+ this sheet says how. The paint (a caret's ink, a skeleton's gradient) is the
2484
+ component's own gui props; what is left here is what no prop can say: a
2485
+ keyframe, a transition a preference can switch off, and the preference
2486
+ itself. Every animation is off under `prefers-reduced-motion: reduce`.
2487
+
2488
+ rise enter: fade up 10px over 400ms FadeIn, Timeline, tooltips
2489
+ fade opacity eases 240ms SlideOver's scrim
2490
+ slide transform eases 260ms SlideOver's panel
2491
+ drag a row eases into place while one is held Reorder
2492
+ pulse opacity dims and returns, 2s Pulse, StatusDot, Skeleton
2493
+ blink on/off, 1s Caret
2494
+ shimmer a highlight sweeps a placeholder product Skeleton
2495
+ unfold a sheet turns open about its hinge unfold() */
2496
+
2497
+ @keyframes rise {
2427
2498
  from {
2428
2499
  opacity: 0;
2429
2500
  transform: translateY(10px);
@@ -2434,122 +2505,37 @@ a svg,
2434
2505
  }
2435
2506
  }
2436
2507
 
2437
- .hz-fade-up {
2438
- animation: hz-fade-up 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
2508
+ [data-motion='rise'] {
2509
+ animation: rise 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
2439
2510
  will-change: transform, opacity;
2440
2511
  }
2441
2512
 
2442
- @media (prefers-reduced-motion: reduce) {
2443
- .hz-fade-up {
2444
- animation: none;
2445
- }
2446
- }
2447
-
2448
- /* Shell chrome motion — sidebar collapse (width) and the Linear-style two-level
2449
- nav slide (transform); backdrop cross-fade behind a SlideOver / dialog. */
2450
- .hz-collapse {
2451
- transition: width 220ms cubic-bezier(0.16, 1, 0.3, 1);
2452
- will-change: width;
2513
+ [data-motion='fade'] {
2514
+ transition: opacity 240ms cubic-bezier(0.16, 1, 0.3, 1);
2515
+ will-change: opacity;
2453
2516
  }
2454
2517
 
2455
- .hz-slide {
2518
+ [data-motion='slide'] {
2456
2519
  transition: transform 260ms cubic-bezier(0.16, 1, 0.3, 1);
2457
2520
  will-change: transform;
2458
2521
  }
2459
2522
 
2460
- .hz-fade {
2461
- transition: opacity 240ms cubic-bezier(0.16, 1, 0.3, 1);
2462
- will-change: opacity;
2463
- }
2464
-
2465
- /* Drag-to-reorder — a pinned row while it is being dragged (pointer DnD). The
2466
- lifted row gets a subtle lift; siblings ease into place via `.hz-slide`. */
2467
- .hz-drag {
2523
+ [data-motion='drag'] {
2468
2524
  touch-action: none;
2469
2525
  transition: transform 180ms cubic-bezier(0.16, 1, 0.3, 1);
2470
2526
  }
2471
- .hz-drag[data-dragging='true'] {
2472
- transition: none;
2473
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
2474
- opacity: 0.96;
2475
- cursor: grabbing;
2476
- }
2477
-
2478
- @media (prefers-reduced-motion: reduce) {
2479
- .hz-collapse,
2480
- .hz-slide,
2481
- .hz-fade,
2482
- .hz-drag {
2483
- transition: none;
2484
- }
2485
- }
2486
-
2487
- /* Living-overview motion — the "videogame-like" living dashboard. The count-up +
2488
- live sparkline are driven in JS (rAF, gated by prefers-reduced-motion in the
2489
- hooks); these are the pure-CSS bits: a loading shimmer, a live-feed pulse, and
2490
- a brief highlight when a freshly-arrived row lands. */
2491
2527
 
2492
- /* Skeleton shimmer — an honest "loading", never fabricated content. */
2493
- @keyframes hz-shimmer {
2494
- 0% {
2495
- background-position: -160px 0;
2496
- }
2497
- 100% {
2498
- background-position: 160px 0;
2499
- }
2500
- }
2501
-
2502
- .hz-skeleton {
2503
- background-color: var(--color3, rgba(128, 128, 128, 0.14));
2504
- background-image: linear-gradient(
2505
- 90deg,
2506
- transparent 0%,
2507
- var(--color4, rgba(128, 128, 128, 0.22)) 50%,
2508
- transparent 100%
2509
- );
2510
- background-size: 160px 100%;
2511
- background-repeat: no-repeat;
2512
- animation: hz-shimmer 1.2s ease-in-out infinite;
2513
- }
2514
-
2515
- /* Live-feed pulse — the "Live" dot on a streaming panel.
2516
-
2517
- NAMED APART FROM THE SKELETON'S. Both sheets shipped a `@keyframes hz-pulse`
2518
- and `styles.css` concatenates them, so the later one — this one — won for
2519
- every consumer and `.hz-pulse` animated a placeholder by RESIZING it. That is
2520
- the thing theme.css's own comment forbids: "animating a colour or a size
2521
- would repaint or reflow every frame for a placeholder nobody is looking at".
2522
- Nothing referenced this keyframe by name, which is why it went unnoticed. */
2523
- @keyframes hz-live {
2524
- 0%,
2525
- 100% {
2526
- opacity: 1;
2527
- transform: scale(1);
2528
- }
2529
- 50% {
2530
- opacity: 0.45;
2531
- transform: scale(0.82);
2532
- }
2533
- }
2534
-
2535
- /* THE TWO CLASSES THE COMPONENTS STAMP, in the sheet a host imports.
2536
- `skeleton.js` emits `hz-pulse` and `input-otp.js` emits `hz-caret`, and their
2537
- rules lived only in theme.css — the sheet that inlines the whole design system
2538
- and which a host with its own tokens cannot take. So every host either mounted
2539
- 110KB it did not want or wrote these two rules by hand; hanzo.ai carried them
2540
- for exactly that reason. A library that stamps a class owns its rule, and this
2541
- is the sheet it owns it in. */
2542
- @keyframes hz-dim {
2528
+ @keyframes dim {
2543
2529
  50% {
2544
2530
  opacity: 0.5;
2545
2531
  }
2546
2532
  }
2547
2533
 
2548
- .hz-pulse {
2549
- animation: hz-dim 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
2534
+ [data-motion='pulse'] {
2535
+ animation: dim 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
2550
2536
  }
2551
2537
 
2552
- @keyframes hz-blink {
2538
+ @keyframes blink {
2553
2539
  0%,
2554
2540
  49% {
2555
2541
  opacity: 1;
@@ -2560,138 +2546,32 @@ a svg,
2560
2546
  }
2561
2547
  }
2562
2548
 
2563
- .hz-caret {
2564
- background: var(--foreground);
2565
- animation: hz-blink 1s steps(1) infinite;
2566
- }
2567
-
2568
- /* Entrance for a freshly-arrived activity row (staggerless — one row at a time). */
2569
- @keyframes hz-row-in {
2570
- from {
2571
- opacity: 0;
2572
- transform: translateY(-6px);
2573
- }
2574
- to {
2575
- opacity: 1;
2576
- transform: translateY(0);
2577
- }
2578
- }
2579
-
2580
- .hz-row-in {
2581
- animation: hz-row-in 0.35s cubic-bezier(0.16, 1, 0.3, 1) both;
2549
+ [data-motion='blink'] {
2550
+ animation: blink 1s steps(1) infinite;
2582
2551
  }
2583
2552
 
2584
- @media (prefers-reduced-motion: reduce) {
2585
- .hz-skeleton {
2586
- animation: none;
2587
- }
2588
- .hz-row-in {
2589
- animation: none;
2590
- }
2591
- .hz-pulse {
2592
- animation: none;
2553
+ @keyframes shimmer {
2554
+ 0% {
2555
+ background-position: -160px 0;
2593
2556
  }
2594
- .hz-caret {
2595
- animation: none;
2557
+ 100% {
2558
+ background-position: 160px 0;
2596
2559
  }
2597
2560
  }
2598
2561
 
2599
- /* ── Typography + surface classes the product layer's components reference ──────
2600
- DataTable/Metric typeset numeric cells with `hz-mono`/`hz-tnum`; ComboBox and
2601
- SelectMenu paint their popovers with `hz-paper hz-menu-in`; DataTable rows use
2602
- `hz-row`. They travel WITH the components (this is the package's one
2603
- stylesheet) so any host that imports `@hanzo/ui/styles/motion.css` renders them
2604
- correctly. The elevation/ring variables fall back to sane values, so a host
2605
- that defines its own `--hz-*` theme tokens (the console does) still wins. */
2606
-
2607
- .hz-tnum {
2608
- font-variant-numeric: tabular-nums;
2609
- font-feature-settings: 'tnum' 1;
2610
- }
2611
-
2612
- /* Data/numeric face — Zen Mono + tabular figures for metric values, prices, IDs
2613
- and counts, so numbers read as precise, column-aligned data. */
2614
- .hz-mono {
2615
- font-family: var(--font-mono, 'Zen Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
2616
- font-variant-numeric: tabular-nums;
2617
- font-feature-settings: 'tnum' 1;
2618
- letter-spacing: -0.01em;
2619
- }
2620
-
2621
- /* Paper — a ringed sheet: the ladder's lit edge and drop, plus a hairline all
2622
- the way round. The three values are reached by their real names. They used to
2623
- be `--hz-ring` / `--hz-paper-highlight` / `--hz-elevation-3`, none of which is
2624
- defined in this repo, in @hanzo/design or in any consumer — so all three
2625
- resolved to hardcoded fallbacks, and the comment above promising that "a host
2626
- that defines its own --hz-* tokens still wins" described a hook nobody could
2627
- reach.
2628
-
2629
- The drop is rung 2's, by the ladder's own name. It read `--shadow-lg` — a
2630
- t-shirt size @hanzo/brand also declares, for a white canvas, winning on load
2631
- order — so paper lost its drop on dark exactly the way the rungs did. The
2632
- fallback stays because this sheet ships on its own: a host that imports
2633
- motion.css without glass.css has no ladder to read. */
2634
- .hz-paper {
2635
- box-shadow: var(--shadow-inset-hairline, inset 0 0 0 1px rgb(255 255 255 / .10)),
2636
- var(--edge-highlight, inset 0 1px 0 0 rgb(255 255 255 / .10)),
2637
- var(--glass-shadow-2, 0 10px 15px -3px rgb(0 0 0 / .55), 0 4px 6px -4px rgb(0 0 0 / .55));
2562
+ [data-motion='shimmer'] {
2563
+ animation: shimmer 1.2s ease-in-out infinite;
2638
2564
  }
2639
2565
 
2640
- @keyframes hz-menu-in {
2566
+ /* Unfold — how a sheet arrives. A panel that appears by fading is a rectangle
2567
+ switching on; a sheet of paper TURNS OPEN about the edge it is hinged on. The
2568
+ hinge is the only knob and the angle follows it, so a turn cannot open the
2569
+ wrong way. `perspective()` inside the transform puts the vanishing point at
2570
+ the sheet's own centre. Seven degrees over 220ms. */
2571
+ @keyframes unfold {
2641
2572
  from {
2642
2573
  opacity: 0;
2643
- }
2644
- to {
2645
- opacity: 1;
2646
- }
2647
- }
2648
-
2649
- .hz-menu-in {
2650
- animation: hz-menu-in 140ms ease-out both;
2651
- will-change: opacity;
2652
- }
2653
-
2654
- .hz-row {
2655
- transition: background-color 140ms ease-out;
2656
- }
2657
-
2658
- /* AND WHAT IT TRANSITIONS TO. Stating the transition without the destination
2659
- left every host to invent the affordance — a row that announces it responds
2660
- and then does not. The colour is @hanzo/design's `--surface-card-quiet`,
2661
- which carries a value in both themes, so this needs nothing of the host it
2662
- has not already mounted. */
2663
- .hz-row:hover {
2664
- background-color: var(--surface-card-quiet);
2665
- }
2666
-
2667
- @media (prefers-reduced-motion: reduce) {
2668
- .hz-menu-in {
2669
- animation: none;
2670
- }
2671
- }
2672
-
2673
- /* ── Unfold — how a sheet arrives ─────────────────────────────────────────────
2674
- A panel that appears by fading is a rectangle switching on. A sheet of paper
2675
- arrives by TURNING OPEN about the edge it is hinged on, so its near edge swings
2676
- toward the reader and its far edge stays put — which is the one motion that
2677
- says "this was already here, folded" rather than "this was drawn just now".
2678
-
2679
- The hinge is the ONLY thing that varies, so it is the only knob: a drawer
2680
- coming off the left wall turns about its left edge, a pane folding in from the
2681
- right about its right. The angle follows the hinge — a sheet swings toward you
2682
- from whichever side it is held — so naming the hinge sets both, and there is no
2683
- way to ask for a turn that opens the wrong way.
2684
-
2685
- `perspective()` inside the transform rather than on a parent: the vanishing
2686
- point is then the sheet's own centre, so the turn reads at any size and the
2687
- caller does not have to own a 3D context it did not ask for.
2688
-
2689
- Seven degrees over 220ms. Enough to see the plane; short of the swinging-door
2690
- effect that makes a workspace feel like a slideshow. */
2691
- @keyframes hz-unfold {
2692
- from {
2693
- opacity: 0;
2694
- transform: perspective(1600px) rotateY(var(--hz-turn, -7deg));
2574
+ transform: perspective(1600px) rotateY(var(--turn, -7deg));
2695
2575
  }
2696
2576
  to {
2697
2577
  opacity: 1;
@@ -2699,37 +2579,27 @@ a svg,
2699
2579
  }
2700
2580
  }
2701
2581
 
2702
- .hz-unfold {
2703
- animation: hz-unfold 220ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
2582
+ [data-motion='unfold'] {
2583
+ animation: unfold 220ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
2704
2584
  transform-origin: left center;
2705
2585
  will-change: transform, opacity;
2706
2586
  }
2707
2587
 
2708
- .hz-unfold[data-hinge="right"] {
2588
+ [data-motion='unfold'][data-hinge='right'] {
2709
2589
  transform-origin: right center;
2710
- --hz-turn: 7deg;
2590
+ --turn: 7deg;
2711
2591
  }
2712
2592
 
2713
2593
  @media (prefers-reduced-motion: reduce) {
2714
- .hz-unfold {
2594
+ [data-motion] {
2715
2595
  animation: none;
2596
+ transition: none;
2716
2597
  }
2717
2598
  }
2718
2599
 
2719
- /* ── Layout guarantees ─────────────────────────────────────────────────────────
2720
- Two rules, both structural. They are attached to `data-slot` rather than to a
2721
- class because they are not styling a caller can opt out of — they are the
2722
- thing the primitive PROMISES, and a class can be overwritten by forgetting to
2723
- pass it on. */
2724
-
2725
- /* A grid item's initial `min-width` is `auto`, which floors the track at the
2726
- item's min-content width. One long unbroken string — a hash, a URL, a wide
2727
- <pre> — then pushes its own column wider and squeezes every sibling, which is
2728
- the ragged row Grid exists to prevent. The track sizing in grid.tsx is only
2729
- honoured once this floor is gone. */
2730
- [data-slot='grid'] > * {
2731
- min-width: 0;
2732
- }
2600
+ /* ── Layout guarantee ──────────────────────────────────────────────────────────
2601
+ Structural, so attached to a data attribute: it is the thing the primitive
2602
+ PROMISES, and a class can be lost by forgetting to pass it on. */
2733
2603
 
2734
2604
  /* Media fills the ratio box instead of setting its own size. Without this an
2735
2605
  <img> renders at its intrinsic pixel size and either overflows the frame or
@@ -2905,32 +2775,17 @@ a svg,
2905
2775
  }
2906
2776
  }
2907
2777
 
2778
+ /* A carousel scrolls but shows no bar: the arrows and the snap already say it
2779
+ scrolls, and a bar appearing mid-drag shifts the slides under the pointer.
2780
+ Firefox reads `scrollbar-width`, which the component sets; WebKit reads only
2781
+ the pseudo-element, which no prop can reach. */
2782
+ [data-slot='carousel-content']::-webkit-scrollbar { display: none; }
2783
+
2908
2784
  /* The textarea's resize grip is the other platform artefact in the same family:
2909
2785
  a diagonal hatch drawn by the UA that matches nothing. A composer that grows
2910
2786
  with its content does not need one. */
2911
2787
  :where([data-slot='textarea'], [data-slot='composer-field']) { resize: none; }
2912
2788
 
2913
- /* A top-level nav item.
2914
- *
2915
- * `navigationMenuTriggerStyle()` returns this name, so a trigger with no rule
2916
- * behind it is bare text separated only by the list's gap.
2917
- *
2918
- * Padding rather than a wider gap: the padding is also the hit area, and a nav
2919
- * item wants a target bigger than its glyphs. */
2920
- .hz-nav-menu-trigger {
2921
- padding-inline: 0.75rem;
2922
- padding-block: 0.5rem;
2923
- border-radius: var(--radius, 0.5rem);
2924
- color: var(--muted-foreground);
2925
- transition: color 150ms, background-color 150ms;
2926
- }
2927
-
2928
- .hz-nav-menu-trigger:hover,
2929
- .hz-nav-menu-trigger[data-state='open'] {
2930
- color: var(--foreground);
2931
- background: var(--muted);
2932
- }
2933
-
2934
2789
  ._ovs-contain {overscroll-behavior:contain;}
2935
2790
  .t_unmounted .is_View, .t_unmounted .is_Text { transition: none !important; }
2936
2791
  .is_View { display: flex; align-items: stretch; flex-direction: column; flex-basis: auto; box-sizing: border-box; min-height: 0; min-width: 0; flex-shrink: 0; }
@@ -3141,12 +2996,16 @@ a svg,
3141
2996
  :root ._WebkitBoxOrient-vertical{-webkit-box-orient:vertical;}
3142
2997
  :root ._WebkitLineClamp-2{-webkit-line-clamp:2;}
3143
2998
  :root ._WebkitLineClamp-3{-webkit-line-clamp:3;}
2999
+ :root ._aspectRatio-1{aspect-ratio:1;}
3144
3000
  :root ._aspectRatio-1--6{aspect-ratio:1.6;}
3145
3001
  :root ._aspectRatio-1--77777777771627090080{aspect-ratio:1.7777777777777777;}
3146
3002
  :root ._b-0px{bottom:0px;}
3147
3003
  :root ._b-c-space-4{bottom:var(--c-space-4);}
3148
3004
  :root:root:root:root ._background-0focus-hover:focus{background:var(--hover) !important;}
3149
3005
  @media (hover) {:root:root ._background-0hover-hover:hover{background:var(--hover) !important;}}
3006
+ :root ._backgroundImage-linear-grad1137497498{background-image:linear-gradient(90deg, transparent 0%, var(--color4, rgba(128, 128, 128, 0.22)) 50%, transparent 100%);}
3007
+ :root ._backgroundRepeat-no-repeat{background-repeat:no-repeat;}
3008
+ :root ._backgroundSize-160px1001029{background-size:160px 100%;}
3150
3009
  :root ._bblr-0px{border-bottom-left-radius:0px;}
3151
3010
  :root ._bblr-100000px{border-bottom-left-radius:100000px;}
3152
3011
  :root ._bblr-1000px{border-bottom-left-radius:1000px;}
@@ -3164,6 +3023,7 @@ a svg,
3164
3023
  :root ._bblr-c-radius-5{border-bottom-left-radius:var(--c-radius-5);}
3165
3024
  :root ._bblr-c-radius-6{border-bottom-left-radius:var(--c-radius-6);}
3166
3025
  :root ._bblr-c-radius-tr3728{border-bottom-left-radius:var(--c-radius-true);}
3026
+ :root ._bblr-radius-full604151108{border-bottom-left-radius:var(--radius-full, 9999px);}
3167
3027
  :root ._bblr-radius-lg0--71290927033{border-bottom-left-radius:var(--radius-lg, 0.75rem);}
3168
3028
  :root ._bbrr-0px{border-bottom-right-radius:0px;}
3169
3029
  :root ._bbrr-100000px{border-bottom-right-radius:100000px;}
@@ -3182,12 +3042,14 @@ a svg,
3182
3042
  :root ._bbrr-c-radius-5{border-bottom-right-radius:var(--c-radius-5);}
3183
3043
  :root ._bbrr-c-radius-6{border-bottom-right-radius:var(--c-radius-6);}
3184
3044
  :root ._bbrr-c-radius-tr3728{border-bottom-right-radius:var(--c-radius-true);}
3045
+ :root ._bbrr-radius-full604151108{border-bottom-right-radius:var(--radius-full, 9999px);}
3185
3046
  :root ._bbrr-radius-lg0--71290927033{border-bottom-right-radius:var(--radius-lg, 0.75rem);}
3186
3047
  :root ._bbs-solid._bbs-solid{border-bottom-style:solid;}
3187
3048
  :root:root:root ._bg-0active-background:active{background-color:var(--background) !important;}
3188
3049
  :root:root:root ._bg-0active-backgroundF3405682:active{background-color:var(--backgroundFocus) !important;}
3189
3050
  :root:root:root ._bg-0active-backgroundP3496915:active{background-color:var(--backgroundPress) !important;}
3190
3051
  :root:root:root ._bg-0active-hover:active{background-color:var(--hover) !important;}
3052
+ :root:root:root ._bg-0active-primary:active{background-color:var(--primary) !important;}
3191
3053
  :root:root:root ._bg-0active-raised:active{background-color:var(--raised) !important;}
3192
3054
  :root:root:root:root ._bg-0focus-backgroundH3423444:focus{background-color:var(--backgroundHover) !important;}
3193
3055
  :root:root:root:root ._bg-0focus-edge:focus{background-color:var(--edge) !important;}
@@ -3200,6 +3062,7 @@ a svg,
3200
3062
  @media (hover) {:root:root ._bg-0hover-edge:hover{background-color:var(--edge) !important;}}
3201
3063
  @media (hover) {:root:root ._bg-0hover-hover:hover{background-color:var(--hover) !important;}}
3202
3064
  @media (hover) {:root:root ._bg-0hover-panel:hover{background-color:var(--panel) !important;}}
3065
+ @media (hover) {:root:root ._bg-0hover-primary:hover{background-color:var(--primary) !important;}}
3203
3066
  @media (hover) {:root:root ._bg-0hover-raised:hover{background-color:var(--raised) !important;}}
3204
3067
  @media (hover) {:root:root ._bg-0hover-rim:hover{background-color:var(--rim) !important;}}
3205
3068
  @media (hover) {:root:root ._bg-0hover-transparent:hover{background-color:transparent !important;}}
@@ -3210,6 +3073,7 @@ a svg,
3210
3073
  :root ._bg-borderColor{background-color:var(--borderColor);}
3211
3074
  :root ._bg-color12{background-color:var(--color12);}
3212
3075
  :root ._bg-color3{background-color:var(--color3);}
3076
+ :root ._bg-color3rgba11269896602{background-color:var(--color3, rgba(128, 128, 128, 0.14));}
3213
3077
  :root ._bg-color5{background-color:var(--color5);}
3214
3078
  :root ._bg-edge{background-color:var(--edge);}
3215
3079
  :root ._bg-faint{background-color:var(--faint);}
@@ -3218,6 +3082,7 @@ a svg,
3218
3082
  :root ._bg-hover{background-color:var(--hover);}
3219
3083
  :root ._bg-ink{background-color:var(--ink);}
3220
3084
  :root ._bg-panel{background-color:var(--panel);}
3085
+ :root ._bg-primary{background-color:var(--primary);}
3221
3086
  :root ._bg-quiet{background-color:var(--quiet);}
3222
3087
  :root ._bg-raised{background-color:var(--raised);}
3223
3088
  :root ._bg-red9{background-color:var(--red9);}
@@ -3349,6 +3214,7 @@ a svg,
3349
3214
  :root ._btlr-c-radius-5{border-top-left-radius:var(--c-radius-5);}
3350
3215
  :root ._btlr-c-radius-6{border-top-left-radius:var(--c-radius-6);}
3351
3216
  :root ._btlr-c-radius-tr3728{border-top-left-radius:var(--c-radius-true);}
3217
+ :root ._btlr-radius-full604151108{border-top-left-radius:var(--radius-full, 9999px);}
3352
3218
  :root ._btlr-radius-lg0--71290927033{border-top-left-radius:var(--radius-lg, 0.75rem);}
3353
3219
  :root ._btrr-0px{border-top-right-radius:0px;}
3354
3220
  :root ._btrr-100000px{border-top-right-radius:100000px;}
@@ -3367,6 +3233,7 @@ a svg,
3367
3233
  :root ._btrr-c-radius-5{border-top-right-radius:var(--c-radius-5);}
3368
3234
  :root ._btrr-c-radius-6{border-top-right-radius:var(--c-radius-6);}
3369
3235
  :root ._btrr-c-radius-tr3728{border-top-right-radius:var(--c-radius-true);}
3236
+ :root ._btrr-radius-full604151108{border-top-right-radius:var(--radius-full, 9999px);}
3370
3237
  :root ._btrr-radius-lg0--71290927033{border-top-right-radius:var(--radius-lg, 0.75rem);}
3371
3238
  :root ._bts-solid._bts-solid{border-top-style:solid;}
3372
3239
  :root ._btw-0px._btw-0px{border-top-width:0px;}
@@ -3405,6 +3272,7 @@ a svg,
3405
3272
  @media (min-width: 768px){:root:root:root:root:root:root:root:root:root:root:root:root:root:root:root:root:root:root ._dsp-_md_none{display:none;}}
3406
3273
  :root ._dsp-block{display:block;}
3407
3274
  :root ._dsp-flex{display:flex;}
3275
+ :root ._dsp-grid{display:grid;}
3408
3276
  :root ._dsp-inline-flex{display:inline-flex;}
3409
3277
  :root ._dsp-none{display:none;}
3410
3278
  :root ._fb-0px{flex-basis:0px;}
@@ -3439,6 +3307,7 @@ a svg,
3439
3307
  :root ._fwr-nowrap{flex-wrap:nowrap;}
3440
3308
  :root ._fwr-wrap{flex-wrap:wrap;}
3441
3309
  :root ._gap-0px{gap:0px;}
3310
+ :root ._gap-12px{gap:12px;}
3442
3311
  :root ._gap-16px{gap:16px;}
3443
3312
  :root ._gap-1px{gap:1px;}
3444
3313
  :root ._gap-24px{gap:24px;}
@@ -3458,6 +3327,19 @@ a svg,
3458
3327
  :root ._gap-c-space-6{gap:var(--c-space-6);}
3459
3328
  :root ._gap-calc6pxvar-1380234971{gap:calc(6px * var(--radius-scale, 1));}
3460
3329
  :root ._gap-calc8pxvar-1380234971{gap:calc(8px * var(--radius-scale, 1));}
3330
+ :root ._gap-space-312px1396{gap:var(--space-3, 12px);}
3331
+ :root ._gridColumn-1-132241{grid-column:1 / -1;}
3332
+ :root ._gridColumn-span232{grid-column:span 2;}
3333
+ :root ._gridRow-2432241{grid-row:2 / 4;}
3334
+ :root ._gridRow-span232{grid-row:span 2;}
3335
+ :root ._gridTemplateColumns-2fr1fr32{grid-template-columns:2fr 1fr;}
3336
+ :root ._gridTemplateColumns-repeat31fr1234957{grid-template-columns:repeat(3, 1fr);}
3337
+ :root ._gridTemplateColumns-repeat3minm577740846{grid-template-columns:repeat(3, minmax(0, 1fr));}
3338
+ :root ._gridTemplateColumns-repeatauto-1305671373{grid-template-columns:repeat(auto-fill, minmax(min(280px, 100%), 1fr));}
3339
+ :root ._gridTemplateColumns-repeatauto-827335640{grid-template-columns:repeat(auto-fill, minmax(max(min(160px, 100%), calc((100% - 3 * var(--space-3, 12px)) / 4)), 1fr));}
3340
+ :root ._gridTemplateColumns-repeatauto-924020196{grid-template-columns:repeat(auto-fill, minmax(min(900px, 100%), 1fr));}
3341
+ :root ._gridTemplateColumns-repeatauto-998993489{grid-template-columns:repeat(auto-fill, minmax(min(240px, 100%), 1fr));}
3342
+ :root ._gridTemplateRows-repeat2minm577740846{grid-template-rows:repeat(2, minmax(0, 1fr));}
3461
3343
  :root ._grow-0{flex-grow:0;}
3462
3344
  :root ._grow-1{flex-grow:1;}
3463
3345
  :root ._grow-50{flex-grow:50;}
@@ -3607,6 +3489,7 @@ a svg,
3607
3489
  :root ._o-0--6{opacity:0.6;}
3608
3490
  :root ._o-0--7{opacity:0.7;}
3609
3491
  :root ._o-0--8{opacity:0.8;}
3492
+ :root:root:root ._o-0active-0--85:active{opacity:0.85 !important;}
3610
3493
  @media (hover) {:root:root ._o-0hover-0--8:hover{opacity:0.8 !important;}}
3611
3494
  @media (hover) {:root:root ._o-0hover-0--9:hover{opacity:0.9 !important;}}
3612
3495
  @media (hover) {:root:root ._o-0hover-0--92:hover{opacity:0.92 !important;}}