@twentyfirstmedia/pro 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/scoped.css CHANGED
@@ -62,6 +62,10 @@
62
62
  --dur-enter: var(--duration-base);
63
63
  --dur-slow: var(--duration-base);
64
64
  --stagger-step: 0ms;
65
+ --dur-exit: var(--duration-fast);
66
+ --motion-time: 1;
67
+ --motion-travel: 1;
68
+ --motion-blur: 0px;
65
69
  --ease-out: var(--ease-standard);
66
70
  --ease-spring: var(--ease-standard);
67
71
  --ease-in-out: var(--ease-standard);
@@ -268,6 +272,20 @@
268
272
  --on-frame-danger: var(--danger);
269
273
  --scrim: rgba(0,0,0,0.62);
270
274
  --scrim-strong: var(--scrim);
275
+ --glass: color-mix(in srgb, var(--card) 72%, transparent);
276
+ --glass-strong: color-mix(in srgb, var(--card) 88%, transparent);
277
+ --glass-control: color-mix(in srgb, var(--foreground) 7%, transparent);
278
+ --glass-well: color-mix(in srgb, var(--foreground) 5%, transparent);
279
+ --glass-hover: color-mix(in srgb, var(--foreground) 9%, transparent);
280
+ --glass-border: color-mix(in srgb, var(--foreground) 14%, transparent);
281
+ --glass-highlight: rgba(255, 255, 255, 0.07);
282
+ --glass-sheen: transparent;
283
+ --ambient-base: var(--background);
284
+ --ambient-1: color-mix(in oklab, var(--chart-1) 30%, var(--background));
285
+ --ambient-2: color-mix(in oklab, var(--chart-4) 26%, var(--background));
286
+ --ambient-3: color-mix(in oklab, var(--chart-2) 22%, var(--background));
287
+ --ambient-4: color-mix(in oklab, var(--foreground) 8%, var(--background));
288
+ --ambient-scrim: rgba(9, 9, 11, 0.55);
271
289
  --bg-000: var(--background);
272
290
  --bg-100: var(--card);
273
291
  --bg-200: var(--muted);
@@ -325,6 +343,7 @@
325
343
  --shadow-lift: none;
326
344
  --shadow-float: 0 16px 40px rgba(0,0,0,0.55);
327
345
  --shadow-overlay: 0 16px 40px rgba(0,0,0,0.55);
346
+ --shadow-glass: 0 12px 32px rgba(0, 0, 0, 0.5);
328
347
  --button-radius: var(--radius-1);
329
348
  --field-radius: var(--radius-1);
330
349
  --badge-radius: var(--radius-1);
@@ -334,6 +353,8 @@
334
353
  --panel-shadow: none;
335
354
  --panel-pad: var(--space-4);
336
355
  --panel-gap: 1px;
356
+ --glass-filter: blur(16px) saturate(120%) brightness(0.8);
357
+ --glass-tint: 40%;
337
358
  color-scheme: dark;
338
359
  }
339
360
  @media (prefers-color-scheme: dark) {
@@ -399,6 +420,20 @@
399
420
  --on-frame-danger: var(--danger);
400
421
  --scrim: rgba(0,0,0,0.62);
401
422
  --scrim-strong: var(--scrim);
423
+ --glass: color-mix(in srgb, var(--card) 72%, transparent);
424
+ --glass-strong: color-mix(in srgb, var(--card) 88%, transparent);
425
+ --glass-control: color-mix(in srgb, var(--foreground) 7%, transparent);
426
+ --glass-well: color-mix(in srgb, var(--foreground) 5%, transparent);
427
+ --glass-hover: color-mix(in srgb, var(--foreground) 9%, transparent);
428
+ --glass-border: color-mix(in srgb, var(--foreground) 14%, transparent);
429
+ --glass-highlight: rgba(255, 255, 255, 0.07);
430
+ --glass-sheen: transparent;
431
+ --ambient-base: var(--background);
432
+ --ambient-1: color-mix(in oklab, var(--chart-1) 30%, var(--background));
433
+ --ambient-2: color-mix(in oklab, var(--chart-4) 26%, var(--background));
434
+ --ambient-3: color-mix(in oklab, var(--chart-2) 22%, var(--background));
435
+ --ambient-4: color-mix(in oklab, var(--foreground) 8%, var(--background));
436
+ --ambient-scrim: rgba(9, 9, 11, 0.55);
402
437
  --bg-000: var(--background);
403
438
  --bg-100: var(--card);
404
439
  --bg-200: var(--muted);
@@ -456,6 +491,7 @@
456
491
  --shadow-lift: none;
457
492
  --shadow-float: 0 16px 40px rgba(0,0,0,0.55);
458
493
  --shadow-overlay: 0 16px 40px rgba(0,0,0,0.55);
494
+ --shadow-glass: 0 12px 32px rgba(0, 0, 0, 0.5);
459
495
  --button-radius: var(--radius-1);
460
496
  --field-radius: var(--radius-1);
461
497
  --badge-radius: var(--radius-1);
@@ -465,6 +501,8 @@
465
501
  --panel-shadow: none;
466
502
  --panel-pad: var(--space-4);
467
503
  --panel-gap: 1px;
504
+ --glass-filter: blur(16px) saturate(120%) brightness(0.8);
505
+ --glass-tint: 40%;
468
506
  color-scheme: dark;
469
507
  }
470
508
  }
@@ -531,6 +569,20 @@
531
569
  --on-frame-danger: var(--danger);
532
570
  --scrim: rgba(17,17,20,0.36);
533
571
  --scrim-strong: var(--scrim);
572
+ --glass: color-mix(in srgb, var(--card) 74%, transparent);
573
+ --glass-strong: color-mix(in srgb, var(--card) 88%, transparent);
574
+ --glass-control: color-mix(in srgb, var(--card) 55%, transparent);
575
+ --glass-well: color-mix(in srgb, var(--foreground) 5%, transparent);
576
+ --glass-hover: color-mix(in srgb, var(--foreground) 7%, transparent);
577
+ --glass-border: color-mix(in srgb, var(--foreground) 12%, transparent);
578
+ --glass-highlight: rgba(255, 255, 255, 0.7);
579
+ --glass-sheen: transparent;
580
+ --ambient-base: var(--background);
581
+ --ambient-1: color-mix(in oklab, var(--chart-1) 22%, var(--background));
582
+ --ambient-2: color-mix(in oklab, var(--chart-4) 18%, var(--background));
583
+ --ambient-3: color-mix(in oklab, var(--chart-2) 16%, var(--background));
584
+ --ambient-4: color-mix(in oklab, var(--foreground) 6%, var(--background));
585
+ --ambient-scrim: rgba(246, 246, 247, 0.4);
534
586
  --bg-000: var(--background);
535
587
  --bg-100: var(--card);
536
588
  --bg-200: var(--muted);
@@ -588,6 +640,7 @@
588
640
  --shadow-lift: none;
589
641
  --shadow-float: 0 16px 40px rgba(17,17,20,0.12);
590
642
  --shadow-overlay: 0 16px 40px rgba(17,17,20,0.12);
643
+ --shadow-glass: 0 8px 24px rgba(17, 17, 20, 0.1);
591
644
  --button-radius: var(--radius-1);
592
645
  --field-radius: var(--radius-1);
593
646
  --badge-radius: var(--radius-1);
@@ -597,6 +650,8 @@
597
650
  --panel-shadow: none;
598
651
  --panel-pad: var(--space-4);
599
652
  --panel-gap: 1px;
653
+ --glass-filter: blur(16px) saturate(130%) brightness(1.04);
654
+ --glass-tint: 40%;
600
655
  color-scheme: light;
601
656
  }
602
657
  }
@@ -662,6 +717,20 @@
662
717
  --on-frame-danger: var(--danger);
663
718
  --scrim: rgba(0,0,0,0.62);
664
719
  --scrim-strong: var(--scrim);
720
+ --glass: color-mix(in srgb, var(--card) 72%, transparent);
721
+ --glass-strong: color-mix(in srgb, var(--card) 88%, transparent);
722
+ --glass-control: color-mix(in srgb, var(--foreground) 7%, transparent);
723
+ --glass-well: color-mix(in srgb, var(--foreground) 5%, transparent);
724
+ --glass-hover: color-mix(in srgb, var(--foreground) 9%, transparent);
725
+ --glass-border: color-mix(in srgb, var(--foreground) 14%, transparent);
726
+ --glass-highlight: rgba(255, 255, 255, 0.07);
727
+ --glass-sheen: transparent;
728
+ --ambient-base: var(--background);
729
+ --ambient-1: color-mix(in oklab, var(--chart-1) 30%, var(--background));
730
+ --ambient-2: color-mix(in oklab, var(--chart-4) 26%, var(--background));
731
+ --ambient-3: color-mix(in oklab, var(--chart-2) 22%, var(--background));
732
+ --ambient-4: color-mix(in oklab, var(--foreground) 8%, var(--background));
733
+ --ambient-scrim: rgba(9, 9, 11, 0.55);
665
734
  --bg-000: var(--background);
666
735
  --bg-100: var(--card);
667
736
  --bg-200: var(--muted);
@@ -719,6 +788,7 @@
719
788
  --shadow-lift: none;
720
789
  --shadow-float: 0 16px 40px rgba(0,0,0,0.55);
721
790
  --shadow-overlay: 0 16px 40px rgba(0,0,0,0.55);
791
+ --shadow-glass: 0 12px 32px rgba(0, 0, 0, 0.5);
722
792
  --button-radius: var(--radius-1);
723
793
  --field-radius: var(--radius-1);
724
794
  --badge-radius: var(--radius-1);
@@ -728,6 +798,8 @@
728
798
  --panel-shadow: none;
729
799
  --panel-pad: var(--space-4);
730
800
  --panel-gap: 1px;
801
+ --glass-filter: blur(16px) saturate(120%) brightness(0.8);
802
+ --glass-tint: 40%;
731
803
  color-scheme: dark;
732
804
  }
733
805
  :where([data-kit="pro"][data-theme="light"], [data-kit="pro"] [data-theme="light"], [data-kit="pro"].light, [data-kit="pro"] .light) {
@@ -792,6 +864,20 @@
792
864
  --on-frame-danger: var(--danger);
793
865
  --scrim: rgba(17,17,20,0.36);
794
866
  --scrim-strong: var(--scrim);
867
+ --glass: color-mix(in srgb, var(--card) 74%, transparent);
868
+ --glass-strong: color-mix(in srgb, var(--card) 88%, transparent);
869
+ --glass-control: color-mix(in srgb, var(--card) 55%, transparent);
870
+ --glass-well: color-mix(in srgb, var(--foreground) 5%, transparent);
871
+ --glass-hover: color-mix(in srgb, var(--foreground) 7%, transparent);
872
+ --glass-border: color-mix(in srgb, var(--foreground) 12%, transparent);
873
+ --glass-highlight: rgba(255, 255, 255, 0.7);
874
+ --glass-sheen: transparent;
875
+ --ambient-base: var(--background);
876
+ --ambient-1: color-mix(in oklab, var(--chart-1) 22%, var(--background));
877
+ --ambient-2: color-mix(in oklab, var(--chart-4) 18%, var(--background));
878
+ --ambient-3: color-mix(in oklab, var(--chart-2) 16%, var(--background));
879
+ --ambient-4: color-mix(in oklab, var(--foreground) 6%, var(--background));
880
+ --ambient-scrim: rgba(246, 246, 247, 0.4);
795
881
  --bg-000: var(--background);
796
882
  --bg-100: var(--card);
797
883
  --bg-200: var(--muted);
@@ -849,6 +935,7 @@
849
935
  --shadow-lift: none;
850
936
  --shadow-float: 0 16px 40px rgba(17,17,20,0.12);
851
937
  --shadow-overlay: 0 16px 40px rgba(17,17,20,0.12);
938
+ --shadow-glass: 0 8px 24px rgba(17, 17, 20, 0.1);
852
939
  --button-radius: var(--radius-1);
853
940
  --field-radius: var(--radius-1);
854
941
  --badge-radius: var(--radius-1);
@@ -858,6 +945,8 @@
858
945
  --panel-shadow: none;
859
946
  --panel-pad: var(--space-4);
860
947
  --panel-gap: 1px;
948
+ --glass-filter: blur(16px) saturate(130%) brightness(1.04);
949
+ --glass-tint: 40%;
861
950
  color-scheme: light;
862
951
  }
863
952
  @media (pointer: coarse) {
@@ -883,6 +972,70 @@
883
972
  --density-font-size: 14px;
884
973
  --density-line-height: 20px;
885
974
  }
975
+ :where([data-kit="pro"][data-motion="expressive"], [data-kit="pro"] [data-motion="expressive"]) {
976
+ --dur-enter: 360ms;
977
+ --dur-slow: 560ms;
978
+ --dur-exit: 140ms;
979
+ --stagger-step: 45ms;
980
+ --motion-time: 1;
981
+ --motion-travel: 0.8;
982
+ --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
983
+ --motion-blur: 0px;
984
+ }
985
+ :where([data-kit="pro"][data-motion="off"], [data-kit="pro"] [data-motion="off"]) {
986
+ --duration-fast: 0ms;
987
+ --duration-base: 0ms;
988
+ --dur-fast: 0ms;
989
+ --dur-base: 0ms;
990
+ --dur-enter: 0ms;
991
+ --dur-slow: 0ms;
992
+ --dur-exit: 0ms;
993
+ --stagger-step: 0ms;
994
+ --motion-time: 0;
995
+ --motion-travel: 0;
996
+ --motion-blur: 0px;
997
+ }
998
+ @media (prefers-reduced-motion: reduce) {
999
+ :where([data-kit="pro"], [data-kit="pro"][data-motion], [data-kit="pro"] [data-motion], [data-kit="pro"][data-theme], [data-kit="pro"] [data-theme]) {
1000
+ --duration-fast: 0ms;
1001
+ --duration-base: 0ms;
1002
+ --dur-fast: 0ms;
1003
+ --dur-base: 0ms;
1004
+ --dur-enter: 0ms;
1005
+ --dur-slow: 0ms;
1006
+ --dur-exit: 0ms;
1007
+ --stagger-step: 0ms;
1008
+ --motion-time: 0;
1009
+ --motion-travel: 0;
1010
+ --motion-blur: 0px;
1011
+ }
1012
+ }
1013
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
1014
+ :where([data-kit="pro"], [data-kit="pro"][data-theme], [data-kit="pro"] [data-theme], [data-kit="pro"].dark, [data-kit="pro"] .dark, [data-kit="pro"].light, [data-kit="pro"] .light) {
1015
+ --glass: var(--glass-strong);
1016
+ }
1017
+ }
1018
+ @media (prefers-contrast: more) {
1019
+ :where([data-kit="pro"], [data-kit="pro"][data-theme], [data-kit="pro"] [data-theme], [data-kit="pro"].dark, [data-kit="pro"] .dark, [data-kit="pro"].light, [data-kit="pro"] .light) {
1020
+ --glass: var(--glass-strong);
1021
+ }
1022
+ }
1023
+ @media (prefers-reduced-transparency: reduce) {
1024
+ :where([data-kit="pro"], [data-kit="pro"][data-theme], [data-kit="pro"] [data-theme], [data-kit="pro"].dark, [data-kit="pro"] .dark, [data-kit="pro"].light, [data-kit="pro"] .light) {
1025
+ --glass: var(--card);
1026
+ --glass-strong: var(--popover);
1027
+ --glass-sheen: transparent;
1028
+ --glass-filter: none;
1029
+ }
1030
+ }
1031
+ @media (forced-colors: active) {
1032
+ :where([data-kit="pro"], [data-kit="pro"][data-theme], [data-kit="pro"] [data-theme], [data-kit="pro"].dark, [data-kit="pro"] .dark, [data-kit="pro"].light, [data-kit="pro"] .light) {
1033
+ --glass: var(--card);
1034
+ --glass-strong: var(--popover);
1035
+ --glass-sheen: transparent;
1036
+ --glass-filter: none;
1037
+ }
1038
+ }
886
1039
 
887
1040
  /* 01-foundation.css */
888
1041
  /* Generated by scripts/pro-css.ts from packages/halo/css. Do not edit; the Pro look lives in 90-pro-look.css. */
@@ -1429,18 +1582,23 @@
1429
1582
  box-shadow: none;
1430
1583
  }
1431
1584
  :where([data-kit="pro"]) .tf-bg-sky {
1585
+ --tint: var(--sky);
1432
1586
  background: var(--sky);
1433
1587
  }
1434
1588
  :where([data-kit="pro"]) .tf-bg-mint {
1589
+ --tint: var(--mint);
1435
1590
  background: var(--mint);
1436
1591
  }
1437
1592
  :where([data-kit="pro"]) .tf-bg-lilac {
1593
+ --tint: var(--lilac);
1438
1594
  background: var(--lilac);
1439
1595
  }
1440
1596
  :where([data-kit="pro"]) .tf-bg-butter {
1597
+ --tint: var(--butter);
1441
1598
  background: var(--butter);
1442
1599
  }
1443
1600
  :where([data-kit="pro"]) .tf-bg-blush {
1601
+ --tint: var(--blush);
1444
1602
  background: var(--blush);
1445
1603
  }
1446
1604
  :where([data-kit="pro"]) .tf-bg-surface {
@@ -1862,7 +2020,7 @@
1862
2020
  @keyframes tf-pro-rise {
1863
2021
  from {
1864
2022
  opacity: 0;
1865
- transform: translateY(14px) scale(0.985);
2023
+ transform: translateY(calc(14px * var(--motion-travel))) scale(0.985);
1866
2024
  }
1867
2025
  to {
1868
2026
  opacity: 1;
@@ -1880,7 +2038,7 @@
1880
2038
  @keyframes tf-pro-drop {
1881
2039
  from {
1882
2040
  opacity: 0;
1883
- transform: translateY(-10px);
2041
+ transform: translateY(calc(-10px * var(--motion-travel)));
1884
2042
  }
1885
2043
  to {
1886
2044
  opacity: 1;
@@ -1890,7 +2048,7 @@
1890
2048
  @keyframes tf-pro-slide-in {
1891
2049
  from {
1892
2050
  opacity: 0;
1893
- transform: translateX(24px);
2051
+ transform: translateX(calc(24px * var(--motion-travel)));
1894
2052
  }
1895
2053
  to {
1896
2054
  opacity: 1;
@@ -1900,7 +2058,8 @@
1900
2058
  @keyframes tf-pro-slide-up {
1901
2059
  from {
1902
2060
  opacity: 0;
1903
- transform: translate(0, 28px) scale(0.9);
2061
+ transform: translate(calc(0px * var(--motion-travel)), calc(28px * var(--motion-travel)))
2062
+ scale(0.9);
1904
2063
  }
1905
2064
  to {
1906
2065
  opacity: 1;
@@ -1959,47 +2118,60 @@
1959
2118
  }
1960
2119
 
1961
2120
  :where([data-kit="pro"]) .tf-in {
2121
+ --enter-delay: var(--d, 0ms);
1962
2122
  animation: tf-pro-rise var(--dur-enter) var(--ease-out) both;
1963
- animation-delay: var(--d, 0ms);
2123
+ animation-delay: var(--enter-delay);
1964
2124
  }
1965
2125
  :where([data-kit="pro"]) .tf-stagger > * {
1966
2126
  animation: tf-pro-rise var(--dur-enter) var(--ease-out) both;
1967
2127
  }
1968
2128
  :where([data-kit="pro"]) .tf-stagger > :nth-child(1) {
1969
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 0);
2129
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 0);
2130
+ animation-delay: var(--enter-delay);
1970
2131
  }
1971
2132
  :where([data-kit="pro"]) .tf-stagger > :nth-child(2) {
1972
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 1);
2133
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 1);
2134
+ animation-delay: var(--enter-delay);
1973
2135
  }
1974
2136
  :where([data-kit="pro"]) .tf-stagger > :nth-child(3) {
1975
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 2);
2137
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 2);
2138
+ animation-delay: var(--enter-delay);
1976
2139
  }
1977
2140
  :where([data-kit="pro"]) .tf-stagger > :nth-child(4) {
1978
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 3);
2141
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 3);
2142
+ animation-delay: var(--enter-delay);
1979
2143
  }
1980
2144
  :where([data-kit="pro"]) .tf-stagger > :nth-child(5) {
1981
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 4);
2145
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 4);
2146
+ animation-delay: var(--enter-delay);
1982
2147
  }
1983
2148
  :where([data-kit="pro"]) .tf-stagger > :nth-child(6) {
1984
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 5);
2149
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 5);
2150
+ animation-delay: var(--enter-delay);
1985
2151
  }
1986
2152
  :where([data-kit="pro"]) .tf-stagger > :nth-child(7) {
1987
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 6);
2153
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 6);
2154
+ animation-delay: var(--enter-delay);
1988
2155
  }
1989
2156
  :where([data-kit="pro"]) .tf-stagger > :nth-child(8) {
1990
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 7);
2157
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 7);
2158
+ animation-delay: var(--enter-delay);
1991
2159
  }
1992
2160
  :where([data-kit="pro"]) .tf-stagger > :nth-child(9) {
1993
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 8);
2161
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 8);
2162
+ animation-delay: var(--enter-delay);
1994
2163
  }
1995
2164
  :where([data-kit="pro"]) .tf-stagger > :nth-child(10) {
1996
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 9);
2165
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 9);
2166
+ animation-delay: var(--enter-delay);
1997
2167
  }
1998
2168
  :where([data-kit="pro"]) .tf-stagger > :nth-child(11) {
1999
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 10);
2169
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 10);
2170
+ animation-delay: var(--enter-delay);
2000
2171
  }
2001
2172
  :where([data-kit="pro"]) .tf-stagger > :nth-child(n + 12) {
2002
- animation-delay: calc(var(--base, 0ms) + var(--stagger-step) * 11);
2173
+ --enter-delay: calc(var(--base, 0ms) + var(--stagger-step) * 11);
2174
+ animation-delay: var(--enter-delay);
2003
2175
  }
2004
2176
  :where([data-kit="pro"]) .tf-topbar {
2005
2177
  animation: tf-pro-drop var(--dur-enter) var(--ease-out) both;
@@ -2009,32 +2181,32 @@
2009
2181
  }
2010
2182
  :where([data-kit="pro"]) .tf-panel.tf-side {
2011
2183
  animation: tf-pro-slide-in var(--dur-enter) var(--ease-out) both;
2012
- animation-delay: 160ms;
2184
+ animation-delay: calc(160ms * var(--motion-time));
2013
2185
  }
2014
2186
  :where([data-kit="pro"]) .tf-dock {
2015
2187
  animation: tf-pro-slide-up var(--dur-enter) var(--ease-spring) both;
2016
- animation-delay: 420ms;
2188
+ animation-delay: calc(420ms * var(--motion-time));
2017
2189
  }
2018
2190
  :where([data-kit="pro"]) .tf-dock .tf-dock-btn {
2019
2191
  animation: tf-pro-pop var(--dur-base) var(--ease-spring) both;
2020
2192
  }
2021
2193
  :where([data-kit="pro"]) .tf-dock .tf-dock-btn:nth-child(1) {
2022
- animation-delay: 520ms;
2194
+ animation-delay: calc(520ms * var(--motion-time));
2023
2195
  }
2024
2196
  :where([data-kit="pro"]) .tf-dock .tf-dock-btn:nth-child(2) {
2025
- animation-delay: 570ms;
2197
+ animation-delay: calc(570ms * var(--motion-time));
2026
2198
  }
2027
2199
  :where([data-kit="pro"]) .tf-dock .tf-dock-btn:nth-child(3) {
2028
- animation-delay: 620ms;
2200
+ animation-delay: calc(620ms * var(--motion-time));
2029
2201
  }
2030
2202
  :where([data-kit="pro"]) .tf-dock .tf-dock-btn:nth-child(4) {
2031
- animation-delay: 670ms;
2203
+ animation-delay: calc(670ms * var(--motion-time));
2032
2204
  }
2033
2205
  :where([data-kit="pro"]) .tf-dock .tf-dock-btn:nth-child(5) {
2034
- animation-delay: 720ms;
2206
+ animation-delay: calc(720ms * var(--motion-time));
2035
2207
  }
2036
2208
  :where([data-kit="pro"]) .tf-dock .tf-dock-btn:nth-child(n + 6) {
2037
- animation-delay: 770ms;
2209
+ animation-delay: calc(770ms * var(--motion-time));
2038
2210
  }
2039
2211
  :where([data-kit="pro"]) .tf-rail-btn {
2040
2212
  animation: tf-pro-pop var(--dur-base) var(--ease-spring) both;
@@ -2071,7 +2243,7 @@
2071
2243
  :where([data-kit="pro"]) .tf-progress > span {
2072
2244
  transform-origin: left;
2073
2245
  animation: tf-pro-grow-x var(--dur-slow) var(--ease-out) both;
2074
- animation-delay: 200ms;
2246
+ animation-delay: calc(var(--enter-delay, 0ms) + calc(200ms * var(--motion-time)));
2075
2247
  }
2076
2248
 
2077
2249
  /* Sliding tab indicator */
@@ -2150,6 +2322,7 @@
2150
2322
  transform-box: fill-box;
2151
2323
  transform-origin: bottom;
2152
2324
  animation: tf-pro-grow-y var(--dur-slow) var(--ease-out) both;
2325
+ animation-delay: var(--enter-delay, 0ms);
2153
2326
  }
2154
2327
  :where([data-kit="pro"]) .tf-bar-ink {
2155
2328
  fill: var(--primary);
@@ -2177,7 +2350,7 @@
2177
2350
  stroke-dasharray: 1;
2178
2351
  stroke-dashoffset: 1;
2179
2352
  animation: tf-pro-draw var(--dur-slow) var(--ease-out) forwards;
2180
- animation-delay: 150ms;
2353
+ animation-delay: calc(var(--enter-delay, 0ms) + calc(150ms * var(--motion-time)));
2181
2354
  }
2182
2355
  :where([data-kit="pro"]) .tf-line-ink {
2183
2356
  stroke: var(--primary);
@@ -2200,7 +2373,7 @@
2200
2373
  :where([data-kit="pro"]) .tf-area {
2201
2374
  opacity: 0;
2202
2375
  animation: tf-pro-fade var(--dur-slow) var(--ease-out) forwards;
2203
- animation-delay: 500ms;
2376
+ animation-delay: calc(var(--enter-delay, 0ms) + calc(500ms * var(--motion-time)));
2204
2377
  }
2205
2378
  :where([data-kit="pro"]) .tf-area-sky {
2206
2379
  fill: var(--sky);
@@ -2221,7 +2394,7 @@
2221
2394
  fill: var(--surface);
2222
2395
  stroke-width: 2.5;
2223
2396
  animation: tf-pro-pop var(--dur-base) var(--ease-spring) both;
2224
- animation-delay: 900ms;
2397
+ animation-delay: calc(var(--enter-delay, 0ms) + calc(900ms * var(--motion-time)));
2225
2398
  transform-box: fill-box;
2226
2399
  transform-origin: center;
2227
2400
  }
@@ -2650,6 +2823,22 @@
2650
2823
  }
2651
2824
  }
2652
2825
 
2826
+ /* the same for an app that turns motion off: data-motion="off" */
2827
+ :where([data-kit="pro"])[data-motion="off"] *,
2828
+ :where([data-kit="pro"]) [data-motion="off"] *,
2829
+ :where([data-kit="pro"])[data-motion="off"] *::before,
2830
+ :where([data-kit="pro"]) [data-motion="off"] *::before,
2831
+ :where([data-kit="pro"])[data-motion="off"] *::after,
2832
+ :where([data-kit="pro"]) [data-motion="off"] *::after {
2833
+ animation-duration: 1ms !important;
2834
+ animation-delay: 0ms !important;
2835
+ animation-iteration-count: 1 !important;
2836
+ transition-duration: 1ms !important;
2837
+ }
2838
+ :where([data-kit="pro"])[data-motion="off"] .tf-line, :where([data-kit="pro"]) [data-motion="off"] .tf-line {
2839
+ stroke-dashoffset: 0;
2840
+ }
2841
+
2653
2842
  /* ───────── Refinements ───────── */
2654
2843
  :where([data-kit="pro"]) .tf-nav-label {
2655
2844
  white-space: nowrap;
@@ -2681,7 +2870,7 @@
2681
2870
  :where([data-kit="pro"]) .tf-area {
2682
2871
  opacity: 0;
2683
2872
  animation: tf-pro-area-in var(--dur-slow) var(--ease-out) forwards;
2684
- animation-delay: 500ms;
2873
+ animation-delay: calc(var(--enter-delay, 0ms) + calc(500ms * var(--motion-time)));
2685
2874
  }
2686
2875
  @keyframes tf-pro-area-in {
2687
2876
  to {
@@ -3243,7 +3432,7 @@
3243
3432
  }
3244
3433
  @keyframes tf-pro-drawer-in {
3245
3434
  from {
3246
- transform: translateX(40px);
3435
+ transform: translateX(calc(40px * var(--motion-travel)));
3247
3436
  opacity: 0;
3248
3437
  }
3249
3438
  to {
@@ -4118,7 +4307,7 @@
4118
4307
  box-shadow:
4119
4308
  var(--shadow-float), 0 0 0 var(--line-width) var(--line),
4120
4309
  0 0 0 1px var(--line);
4121
- animation: tf-pop var(--dur-base) var(--ease-spring) both;
4310
+ animation: tf-pro-pop var(--dur-base) var(--ease-spring) both;
4122
4311
  transform-origin: top left;
4123
4312
  }
4124
4313
  :where([data-kit="pro"]) .tf-popover.tf-pop-end {
@@ -5118,7 +5307,7 @@
5118
5307
  color: var(--on-frame);
5119
5308
  box-shadow: var(--shadow-float), 0 0 0 var(--line-width) var(--line);
5120
5309
  font: 500 13px/18px var(--font-sans);
5121
- animation: tf-slide-up var(--dur-base) var(--ease-spring) both;
5310
+ animation: tf-pro-slide-up var(--dur-base) var(--ease-spring) both;
5122
5311
  margin-bottom: 8px;
5123
5312
  }
5124
5313
  :where([data-kit="pro"]) .tf-bulkbar > b {
@@ -5218,7 +5407,8 @@
5218
5407
  :where([data-kit="pro"]) .tf-seg-bar {
5219
5408
  transform-box: fill-box;
5220
5409
  transform-origin: bottom;
5221
- animation: tf-grow-y var(--dur-slow) var(--ease-out) both;
5410
+ animation: tf-pro-grow-y var(--dur-slow) var(--ease-out) both;
5411
+ animation-delay: var(--enter-delay, 0ms);
5222
5412
  transition: opacity var(--dur-fast);
5223
5413
  }
5224
5414
  :where([data-kit="pro"]) .tf-chart g.dim .tf-seg-bar {
@@ -5264,7 +5454,7 @@
5264
5454
  :where([data-kit="pro"]) .tf-area2 {
5265
5455
  opacity: 0;
5266
5456
  animation: tf-pro-area2-in var(--dur-slow) var(--ease-out) forwards;
5267
- animation-delay: 400ms;
5457
+ animation-delay: calc(var(--enter-delay, 0ms) + calc(400ms * var(--motion-time)));
5268
5458
  }
5269
5459
  @keyframes tf-pro-area2-in {
5270
5460
  to {
@@ -5326,7 +5516,7 @@
5326
5516
  height: 20px;
5327
5517
  border-radius: var(--radius-1);
5328
5518
  background: var(--surface-sunken);
5329
- animation: tf-fade var(--dur-base) var(--ease-out) both;
5519
+ animation: tf-pro-fade var(--dur-base) var(--ease-out) both;
5330
5520
  transition: box-shadow var(--dur-fast);
5331
5521
  }
5332
5522
  :where([data-kit="pro"]) .tf-heat-cell.l1 {
@@ -5501,6 +5691,23 @@
5501
5691
  display: none;
5502
5692
  }
5503
5693
  }
5694
+ /* the same for an app that turns motion off: data-motion="off" */
5695
+ :where([data-kit="pro"])[data-motion="off"] .tf-seg-bar,
5696
+ :where([data-kit="pro"]) [data-motion="off"] .tf-seg-bar,
5697
+ :where([data-kit="pro"])[data-motion="off"] .tf-area2,
5698
+ :where([data-kit="pro"]) [data-motion="off"] .tf-area2,
5699
+ :where([data-kit="pro"])[data-motion="off"] .tf-heat-cell,
5700
+ :where([data-kit="pro"]) [data-motion="off"] .tf-heat-cell,
5701
+ :where([data-kit="pro"])[data-motion="off"] .tf-tooltip,
5702
+ :where([data-kit="pro"]) [data-motion="off"] .tf-tooltip,
5703
+ :where([data-kit="pro"])[data-motion="off"] .tf-popover,
5704
+ :where([data-kit="pro"]) [data-motion="off"] .tf-popover {
5705
+ animation: none !important;
5706
+ opacity: 1;
5707
+ }
5708
+ :where([data-kit="pro"])[data-motion="off"] .tf-toast-timer, :where([data-kit="pro"]) [data-motion="off"] .tf-toast-timer {
5709
+ display: none;
5710
+ }
5504
5711
  @media (max-width: 640px) {
5505
5712
  :where([data-kit="pro"]) .tf-dp {
5506
5713
  flex-direction: column;
@@ -5663,7 +5870,7 @@
5663
5870
  gap: 12px;
5664
5871
  align-items: flex-start;
5665
5872
  min-width: 0;
5666
- animation: tf-rise var(--dur-base) var(--ease-out) both;
5873
+ animation: tf-pro-rise var(--dur-base) var(--ease-out) both;
5667
5874
  }
5668
5875
  :where([data-kit="pro"]) .tf-msg.me {
5669
5876
  flex-direction: row-reverse;
@@ -5879,7 +6086,7 @@
5879
6086
  border-radius: var(--radius-full);
5880
6087
  background: var(--mint-ink);
5881
6088
  box-shadow: 0 0 0 2px var(--surface);
5882
- animation: tf-pulse 1.8s ease-out infinite;
6089
+ animation: tf-pro-pulse 1.8s ease-out infinite;
5883
6090
  }
5884
6091
 
5885
6092
  /* Tool calls, reasoning, approvals */
@@ -6026,7 +6233,7 @@
6026
6233
  :where([data-kit="pro"]) .tf-reason.live .tf-reason-head {
6027
6234
  background: linear-gradient(90deg, var(--surface-sunken), var(--line), var(--surface-sunken));
6028
6235
  background-size: 200% 100%;
6029
- animation: tf-shimmer 1.6s linear infinite;
6236
+ animation: tf-pro-shimmer 1.6s linear infinite;
6030
6237
  }
6031
6238
  :where([data-kit="pro"]) .tf-reason-head:focus-visible {
6032
6239
  outline: 2px solid var(--focus);
@@ -6404,7 +6611,7 @@
6404
6611
  }
6405
6612
  :where([data-kit="pro"]) .tf-trace-row.is-running .tf-trace-bar i {
6406
6613
  background: var(--sky-ink);
6407
- animation: tf-pulse 1.4s ease-in-out infinite;
6614
+ animation: tf-pro-pulse 1.4s ease-in-out infinite;
6408
6615
  }
6409
6616
  :where([data-kit="pro"]) .tf-trace-bar em {
6410
6617
  position: absolute;
@@ -7270,6 +7477,19 @@
7270
7477
  animation: none !important;
7271
7478
  }
7272
7479
  }
7480
+ /* the same for an app that turns motion off: data-motion="off" */
7481
+ :where([data-kit="pro"])[data-motion="off"] .tf-msg,
7482
+ :where([data-kit="pro"]) [data-motion="off"] .tf-msg,
7483
+ :where([data-kit="pro"])[data-motion="off"] .tf-caret,
7484
+ :where([data-kit="pro"]) [data-motion="off"] .tf-caret,
7485
+ :where([data-kit="pro"])[data-motion="off"] .tf-typing i,
7486
+ :where([data-kit="pro"]) [data-motion="off"] .tf-typing i,
7487
+ :where([data-kit="pro"])[data-motion="off"] .tf-spin,
7488
+ :where([data-kit="pro"]) [data-motion="off"] .tf-spin,
7489
+ :where([data-kit="pro"])[data-motion="off"] .tf-reason.live .tf-reason-head,
7490
+ :where([data-kit="pro"]) [data-motion="off"] .tf-reason.live .tf-reason-head {
7491
+ animation: none !important;
7492
+ }
7273
7493
 
7274
7494
  /* 04-status-agents-operations.css */
7275
7495
  /* Generated by scripts/pro-css.ts from packages/halo/css. Do not edit; the Pro look lives in 90-pro-look.css. */
@@ -7287,7 +7507,7 @@
7287
7507
  border-radius: var(--radius-full);
7288
7508
  }
7289
7509
  :where([data-kit="pro"]) .tf-shape-pulse {
7290
- animation: tf-pulse 1.8s ease-out infinite;
7510
+ animation: tf-pro-pulse 1.8s ease-out infinite;
7291
7511
  }
7292
7512
  :where([data-kit="pro"]) .tf-shape-diamond {
7293
7513
  width: 7px;
@@ -7668,7 +7888,7 @@
7668
7888
  border-radius: var(--radius-full);
7669
7889
  border: 2px solid var(--line-strong);
7670
7890
  border-top-color: var(--ink);
7671
- animation: tf-spin 0.8s linear infinite;
7891
+ animation: tf-pro-spin 0.8s linear infinite;
7672
7892
  flex: none;
7673
7893
  }
7674
7894
  :where([data-kit="pro"]) .tf-spinner.lg {
@@ -8844,7 +9064,7 @@
8844
9064
  }
8845
9065
  :where([data-kit="pro"]) .tf-stage.st-running::after {
8846
9066
  background: var(--info);
8847
- animation: tf-pulse 1.4s ease-in-out infinite;
9067
+ animation: tf-pro-pulse 1.4s ease-in-out infinite;
8848
9068
  }
8849
9069
  :where([data-kit="pro"]) .tf-stage.st-danger::after {
8850
9070
  background: var(--danger);
@@ -9441,6 +9661,17 @@
9441
9661
  animation: none !important;
9442
9662
  }
9443
9663
  }
9664
+ /* the same for an app that turns motion off: data-motion="off" */
9665
+ :where([data-kit="pro"])[data-motion="off"] .tf-shape-pulse,
9666
+ :where([data-kit="pro"]) [data-motion="off"] .tf-shape-pulse,
9667
+ :where([data-kit="pro"])[data-motion="off"] .tf-voice-wave i,
9668
+ :where([data-kit="pro"]) [data-motion="off"] .tf-voice-wave i,
9669
+ :where([data-kit="pro"])[data-motion="off"] .tf-stage.st-running::after,
9670
+ :where([data-kit="pro"]) [data-motion="off"] .tf-stage.st-running::after,
9671
+ :where([data-kit="pro"])[data-motion="off"] .tf-log-line.fresh,
9672
+ :where([data-kit="pro"]) [data-motion="off"] .tf-log-line.fresh {
9673
+ animation: none !important;
9674
+ }
9444
9675
  :where([data-kit="pro"]) .tf-approval-mail {
9445
9676
  padding: 12px 16px;
9446
9677
  border-radius: var(--radius-md);
@@ -9796,7 +10027,7 @@
9796
10027
  @keyframes tf-pro-fresh {
9797
10028
  0% {
9798
10029
  background: var(--surface-sunken);
9799
- transform: translateY(-4px);
10030
+ transform: translateY(calc(-4px * var(--motion-travel)));
9800
10031
  opacity: 0;
9801
10032
  }
9802
10033
  15% {
@@ -11525,7 +11756,7 @@
11525
11756
  background: var(--surface);
11526
11757
  box-shadow: var(--shadow-float), 0 0 0 var(--line-width) var(--line);
11527
11758
  overflow: hidden;
11528
- animation: tf-pop var(--dur-base) var(--ease-spring) both;
11759
+ animation: tf-pro-pop var(--dur-base) var(--ease-spring) both;
11529
11760
  transform-origin: bottom right;
11530
11761
  }
11531
11762
  :where([data-kit="pro"]) .tf-launch-head {
@@ -11700,6 +11931,17 @@
11700
11931
  animation: none;
11701
11932
  }
11702
11933
  }
11934
+ /* the same for an app that turns motion off: data-motion="off" */
11935
+ :where([data-kit="pro"])[data-motion="off"] .tf-live-dot,
11936
+ :where([data-kit="pro"]) [data-motion="off"] .tf-live-dot,
11937
+ :where([data-kit="pro"])[data-motion="off"] .tf-map-bubble.pulse::after,
11938
+ :where([data-kit="pro"]) [data-motion="off"] .tf-map-bubble.pulse::after,
11939
+ :where([data-kit="pro"])[data-motion="off"] .tf-map-pin.pulse::after,
11940
+ :where([data-kit="pro"]) [data-motion="off"] .tf-map-pin.pulse::after,
11941
+ :where([data-kit="pro"])[data-motion="off"] .tf-livefeed-row.fresh,
11942
+ :where([data-kit="pro"]) [data-motion="off"] .tf-livefeed-row.fresh {
11943
+ animation: none;
11944
+ }
11703
11945
  :where([data-kit="pro"]) .tf-map-world {
11704
11946
  position: absolute;
11705
11947
  inset: 0;
@@ -11817,7 +12059,7 @@
11817
12059
  padding: 0 20px 20px;
11818
12060
  font: 500 14px/20px var(--font-sans);
11819
12061
  color: var(--ink-muted);
11820
- animation: tf-fade var(--dur-base) var(--ease-out) both;
12062
+ animation: tf-pro-fade var(--dur-base) var(--ease-out) both;
11821
12063
  }
11822
12064
  :where([data-kit="pro"]) .tf-accordion.flush {
11823
12065
  gap: 0;
@@ -11950,6 +12192,8 @@
11950
12192
  }
11951
12193
  :where([data-kit="pro"]) .tf-togglegroup {
11952
12194
  display: inline-flex;
12195
+ flex-wrap: wrap;
12196
+ width: fit-content;
11953
12197
  align-items: center;
11954
12198
  gap: 4px;
11955
12199
  padding: 4px;
@@ -12072,7 +12316,7 @@
12072
12316
  box-shadow:
12073
12317
  var(--shadow-float), 0 0 0 var(--line-width) var(--line),
12074
12318
  0 0 0 1px var(--line);
12075
- animation: tf-fade var(--dur-base) var(--ease-out) both;
12319
+ animation: tf-pro-fade var(--dur-base) var(--ease-out) both;
12076
12320
  }
12077
12321
  :where([data-kit="pro"]) .tf-hovercard.tf-hc-top {
12078
12322
  top: auto;
@@ -12397,7 +12641,7 @@
12397
12641
  box-shadow:
12398
12642
  var(--shadow-float), 0 0 0 var(--line-width) var(--line),
12399
12643
  0 0 0 1px var(--line);
12400
- animation: tf-drop var(--dur-base) var(--ease-out) both;
12644
+ animation: tf-pro-drop var(--dur-base) var(--ease-out) both;
12401
12645
  }
12402
12646
  :where([data-kit="pro"]) .tf-navmenu-panel.with-feature {
12403
12647
  grid-template-columns: 200px minmax(0, 1fr);
@@ -12612,19 +12856,19 @@
12612
12856
  @keyframes tf-pro-sheet-left {
12613
12857
  from {
12614
12858
  opacity: 0;
12615
- transform: translateX(-24px);
12859
+ transform: translateX(calc(-24px * var(--motion-travel)));
12616
12860
  }
12617
12861
  }
12618
12862
  @keyframes tf-pro-sheet-top {
12619
12863
  from {
12620
12864
  opacity: 0;
12621
- transform: translateY(-24px);
12865
+ transform: translateY(calc(-24px * var(--motion-travel)));
12622
12866
  }
12623
12867
  }
12624
12868
  @keyframes tf-pro-sheet-bottom {
12625
12869
  from {
12626
12870
  opacity: 0;
12627
- transform: translateY(24px);
12871
+ transform: translateY(calc(24px * var(--motion-travel)));
12628
12872
  }
12629
12873
  }
12630
12874
 
@@ -13354,6 +13598,615 @@
13354
13598
  box-sizing: border-box;
13355
13599
  }
13356
13600
 
13601
+ /* 08-glass.css */
13602
+ /* Generated by scripts/pro-css.ts from packages/halo/css. Do not edit; the Pro look lives in 90-pro-look.css. */
13603
+ /* Glass: translucent surfaces for UI that floats over content (maps, 3D scenes, video, photos).
13604
+ *
13605
+ * A glass surface shows a blurred, colour-lifted view of what is behind it, with a light edge on
13606
+ * top. What sits on it reads the glass tokens too (inputs, chips, tab tracks, hover highlights,
13607
+ * nested cards), so the surface stays one piece of glass instead of opaque blocks on glass.
13608
+ *
13609
+ * - `.tf-glass` (the `surface="glass"` prop) makes one surface glass.
13610
+ * - `[data-surface="glass"]` (`<UIProvider surface="glass">`) makes every top-level surface and
13611
+ * every floating layer inside it glass. Surfaces nested in a surface stay clear instead of
13612
+ * stacking glass on glass; `.tf-solid` (`surface="solid"`) opts one surface out.
13613
+ *
13614
+ * Floating layers (menus, popovers, dialogs, drawers) use the stronger `--glass-strong` fill: they
13615
+ * carry more text. The fills are opaque enough for 4.5:1 body text over any backdrop; reduced
13616
+ * transparency, high contrast and forced colours fall back to solid surfaces.
13617
+ */
13618
+
13619
+ /* the surface itself */
13620
+ :where([data-kit="pro"]) .tf-glass:not(.tf-solid),
13621
+ :where([data-kit="pro"])[data-surface="glass"]
13622
+ :is(
13623
+ .tf-panel,
13624
+ .tf-card,
13625
+ .tf-stat,
13626
+ .tf-dock,
13627
+ .tf-sidebar,
13628
+ .tf-map-legend,
13629
+ .tf-map-ctl,
13630
+ .tf-map-pop
13631
+ ):not(
13632
+ :is(
13633
+ .tf-panel,
13634
+ .tf-card,
13635
+ .tf-stat,
13636
+ .tf-dock,
13637
+ .tf-sidebar,
13638
+ .tf-popover,
13639
+ .tf-menu,
13640
+ .tf-hovercard,
13641
+ .tf-selectmenu-list,
13642
+ .tf-navmenu-panel,
13643
+ .tf-palette,
13644
+ .tf-modal,
13645
+ .tf-drawer,
13646
+ .tf-glass
13647
+ )
13648
+ *
13649
+ ):not(.tf-solid),
13650
+ :where([data-kit="pro"]) [data-surface="glass"]
13651
+ :is(
13652
+ .tf-panel,
13653
+ .tf-card,
13654
+ .tf-stat,
13655
+ .tf-dock,
13656
+ .tf-sidebar,
13657
+ .tf-map-legend,
13658
+ .tf-map-ctl,
13659
+ .tf-map-pop
13660
+ ):not(
13661
+ :is(
13662
+ .tf-panel,
13663
+ .tf-card,
13664
+ .tf-stat,
13665
+ .tf-dock,
13666
+ .tf-sidebar,
13667
+ .tf-popover,
13668
+ .tf-menu,
13669
+ .tf-hovercard,
13670
+ .tf-selectmenu-list,
13671
+ .tf-navmenu-panel,
13672
+ .tf-palette,
13673
+ .tf-modal,
13674
+ .tf-drawer,
13675
+ .tf-glass
13676
+ )
13677
+ *
13678
+ ):not(.tf-solid),
13679
+ :where([data-kit="pro"])[data-surface="glass"]
13680
+ :is(
13681
+ .tf-popover,
13682
+ .tf-menu:not(.tf-menu-static),
13683
+ .tf-hovercard,
13684
+ .tf-selectmenu-list,
13685
+ .tf-navmenu-panel,
13686
+ .tf-palette,
13687
+ .tf-modal,
13688
+ .tf-drawer
13689
+ ):not(.tf-solid),
13690
+ :where([data-kit="pro"]) [data-surface="glass"]
13691
+ :is(
13692
+ .tf-popover,
13693
+ .tf-menu:not(.tf-menu-static),
13694
+ .tf-hovercard,
13695
+ .tf-selectmenu-list,
13696
+ .tf-navmenu-panel,
13697
+ .tf-palette,
13698
+ .tf-modal,
13699
+ .tf-drawer
13700
+ ):not(.tf-solid) {
13701
+ --glass-fill: var(--glass);
13702
+ background:
13703
+ linear-gradient(to bottom, var(--glass-sheen), transparent 56px) border-box,
13704
+ linear-gradient(var(--glass-tinted), var(--glass-tinted)) border-box,
13705
+ var(--glass-fill);
13706
+ --glass-tinted: color-mix(in srgb, var(--tint, transparent) var(--glass-tint), transparent);
13707
+ -webkit-backdrop-filter: var(--glass-filter);
13708
+ backdrop-filter: var(--glass-filter);
13709
+ border-color: var(--glass-border);
13710
+ box-shadow:
13711
+ inset 0 1px 0 0 var(--glass-highlight),
13712
+ inset 0 0 0 1px var(--glass-border),
13713
+ var(--shadow-glass);
13714
+ color: var(--foreground);
13715
+ /* what sits on the glass */
13716
+ --surface: var(--glass-control);
13717
+ --secondary: var(--glass-control);
13718
+ --bg-100: var(--glass-control);
13719
+ --surface-sunken: var(--glass-well);
13720
+ --muted: var(--glass-well);
13721
+ --canvas: var(--glass-well);
13722
+ --bg-200: var(--glass-well);
13723
+ --accent: var(--glass-hover);
13724
+ --bg-300: var(--glass-hover);
13725
+ /* the faintest text steps up one shade: glass gives up some contrast to what is behind */
13726
+ --ink-subtle: var(--muted-foreground);
13727
+ --fg-300: var(--muted-foreground);
13728
+ }
13729
+
13730
+ /* floating layers carry more text: a stronger fill */
13731
+ :where([data-kit="pro"]) :is(
13732
+ .tf-popover,
13733
+ .tf-menu,
13734
+ .tf-hovercard,
13735
+ .tf-selectmenu-list,
13736
+ .tf-navmenu-panel,
13737
+ .tf-palette,
13738
+ .tf-modal,
13739
+ .tf-drawer
13740
+ ).tf-glass,
13741
+ :where([data-kit="pro"])[data-surface="glass"]
13742
+ :is(
13743
+ .tf-popover,
13744
+ .tf-menu:not(.tf-menu-static),
13745
+ .tf-hovercard,
13746
+ .tf-selectmenu-list,
13747
+ .tf-navmenu-panel,
13748
+ .tf-palette,
13749
+ .tf-modal,
13750
+ .tf-drawer
13751
+ ):not(.tf-solid),
13752
+ :where([data-kit="pro"]) [data-surface="glass"]
13753
+ :is(
13754
+ .tf-popover,
13755
+ .tf-menu:not(.tf-menu-static),
13756
+ .tf-hovercard,
13757
+ .tf-selectmenu-list,
13758
+ .tf-navmenu-panel,
13759
+ .tf-palette,
13760
+ .tf-modal,
13761
+ .tf-drawer
13762
+ ):not(.tf-solid) {
13763
+ --glass-fill: var(--glass-strong);
13764
+ }
13765
+
13766
+ /* Controls floating on their own (not on a surface) become small glass pills: a search field or
13767
+ zoom buttons over a map */
13768
+ :where([data-kit="pro"])[data-surface="glass"]
13769
+ :is(
13770
+ .tf-search,
13771
+ .tf-seg,
13772
+ .tf-btngroup,
13773
+ .tf-iconbtn-soft,
13774
+ .tf-iconbtn-outline,
13775
+ .tf-btn-secondary,
13776
+ .tf-chip:not([aria-pressed="true"])
13777
+ ):not(
13778
+ :is(
13779
+ .tf-panel,
13780
+ .tf-card,
13781
+ .tf-dock,
13782
+ .tf-popover,
13783
+ .tf-menu,
13784
+ .tf-hovercard,
13785
+ .tf-selectmenu-list,
13786
+ .tf-navmenu-panel,
13787
+ .tf-palette,
13788
+ .tf-modal,
13789
+ .tf-drawer,
13790
+ .tf-glass,
13791
+ .tf-btngroup,
13792
+ .tf-map-ctl,
13793
+ .tf-topbar
13794
+ )
13795
+ *
13796
+ ):not(.tf-solid),
13797
+ :where([data-kit="pro"]) [data-surface="glass"]
13798
+ :is(
13799
+ .tf-search,
13800
+ .tf-seg,
13801
+ .tf-btngroup,
13802
+ .tf-iconbtn-soft,
13803
+ .tf-iconbtn-outline,
13804
+ .tf-btn-secondary,
13805
+ .tf-chip:not([aria-pressed="true"])
13806
+ ):not(
13807
+ :is(
13808
+ .tf-panel,
13809
+ .tf-card,
13810
+ .tf-dock,
13811
+ .tf-popover,
13812
+ .tf-menu,
13813
+ .tf-hovercard,
13814
+ .tf-selectmenu-list,
13815
+ .tf-navmenu-panel,
13816
+ .tf-palette,
13817
+ .tf-modal,
13818
+ .tf-drawer,
13819
+ .tf-glass,
13820
+ .tf-btngroup,
13821
+ .tf-map-ctl,
13822
+ .tf-topbar
13823
+ )
13824
+ *
13825
+ ):not(.tf-solid) {
13826
+ background:
13827
+ linear-gradient(to bottom, var(--glass-sheen), transparent) border-box,
13828
+ var(--glass);
13829
+ -webkit-backdrop-filter: var(--glass-filter);
13830
+ backdrop-filter: var(--glass-filter);
13831
+ box-shadow:
13832
+ inset 0 1px 0 0 var(--glass-highlight),
13833
+ inset 0 0 0 1px var(--glass-border),
13834
+ var(--shadow-glass);
13835
+ color: var(--foreground);
13836
+ --surface: var(--glass-control);
13837
+ --secondary: var(--glass-control);
13838
+ --surface-sunken: var(--glass-well);
13839
+ --bg-200: var(--glass-well);
13840
+ --accent: var(--glass-hover);
13841
+ --bg-300: var(--glass-hover);
13842
+ }
13843
+ :where([data-kit="pro"])[data-surface="glass"]
13844
+ :is(.tf-iconbtn-soft, .tf-iconbtn-outline, .tf-btn-secondary, .tf-chip):not(
13845
+ :is(.tf-panel, .tf-card, .tf-dock, .tf-popover, .tf-menu, .tf-modal, .tf-drawer, .tf-glass) *
13846
+ ):not(.tf-solid):not([aria-pressed="true"]):hover, :where([data-kit="pro"]) [data-surface="glass"]
13847
+ :is(.tf-iconbtn-soft, .tf-iconbtn-outline, .tf-btn-secondary, .tf-chip):not(
13848
+ :is(.tf-panel, .tf-card, .tf-dock, .tf-popover, .tf-menu, .tf-modal, .tf-drawer, .tf-glass) *
13849
+ ):not(.tf-solid):not([aria-pressed="true"]):hover {
13850
+ background:
13851
+ linear-gradient(var(--glass-hover), var(--glass-hover)) border-box,
13852
+ var(--glass);
13853
+ }
13854
+
13855
+ /* AppShell on glass: the same layout as the solid shell, the frame turned to glass. Top bar and
13856
+ rail sit on it without a fill of their own, the sheet clears so the backdrop shows through,
13857
+ and everything drawn on the frame (nav, user, rail) reads the glass colours */
13858
+ :where([data-kit="pro"])[data-surface="glass"] .tf-shell, :where([data-kit="pro"]) [data-surface="glass"] .tf-shell {
13859
+ background:
13860
+ linear-gradient(to bottom, var(--glass-sheen), transparent 56px) border-box,
13861
+ var(--glass);
13862
+ -webkit-backdrop-filter: var(--glass-filter);
13863
+ backdrop-filter: var(--glass-filter);
13864
+ box-shadow:
13865
+ inset 0 1px 0 0 var(--glass-highlight),
13866
+ inset 0 0 0 1px var(--glass-border),
13867
+ var(--shadow-glass);
13868
+ --frame: var(--glass);
13869
+ --frame-hover: var(--glass-hover);
13870
+ --frame-active: var(--glass-hover);
13871
+ --frame-strong: var(--glass-control);
13872
+ --on-frame: var(--foreground);
13873
+ --on-frame-muted: var(--muted-foreground);
13874
+ }
13875
+ :where([data-kit="pro"])[data-surface="glass"] .tf-shell .tf-sheet, :where([data-kit="pro"]) [data-surface="glass"] .tf-shell .tf-sheet {
13876
+ background: transparent;
13877
+ }
13878
+ :where([data-kit="pro"])[data-surface="glass"] .tf-shell .tf-topbar, :where([data-kit="pro"]) [data-surface="glass"] .tf-shell .tf-topbar {
13879
+ background: transparent;
13880
+ }
13881
+
13882
+ /* switch knobs stay solid on glass */
13883
+ :where([data-kit="pro"]) .tf-glass .tf-switch::after,
13884
+ :where([data-kit="pro"])[data-surface="glass"] .tf-switch::after,
13885
+ :where([data-kit="pro"]) [data-surface="glass"] .tf-switch::after {
13886
+ background: var(--card);
13887
+ }
13888
+
13889
+ /* Reduced transparency, more contrast, forced colours and browsers without backdrop blur switch
13890
+ the glass tokens themselves (see tokens.css). Forced colours drop shadows, so glass keeps an
13891
+ edge there. */
13892
+ @media (forced-colors: active) {
13893
+ :where([data-kit="pro"]) .tf-glass,
13894
+ :where([data-kit="pro"])[data-surface="glass"]
13895
+ :is(
13896
+ .tf-panel,
13897
+ .tf-card,
13898
+ .tf-stat,
13899
+ .tf-dock,
13900
+ .tf-sidebar,
13901
+ .tf-map-legend,
13902
+ .tf-map-ctl,
13903
+ .tf-map-pop
13904
+ ),
13905
+ :where([data-kit="pro"]) [data-surface="glass"]
13906
+ :is(
13907
+ .tf-panel,
13908
+ .tf-card,
13909
+ .tf-stat,
13910
+ .tf-dock,
13911
+ .tf-sidebar,
13912
+ .tf-map-legend,
13913
+ .tf-map-ctl,
13914
+ .tf-map-pop
13915
+ ) {
13916
+ outline: 1px solid CanvasText;
13917
+ outline-offset: -1px;
13918
+ }
13919
+ }
13920
+
13921
+ /* FloatingLayout: UI along the edges of a full-bleed background */
13922
+ :where([data-kit="pro"]) .tf-floating {
13923
+ position: relative;
13924
+ overflow: hidden;
13925
+ isolation: isolate;
13926
+ border-radius: var(--radius-lg);
13927
+ background: var(--surface-sunken);
13928
+ container: tf-floating / inline-size;
13929
+ }
13930
+ :where([data-kit="pro"]) .tf-floating-bg {
13931
+ position: absolute;
13932
+ inset: 0;
13933
+ }
13934
+ :where([data-kit="pro"]) .tf-floating-bg > * {
13935
+ width: 100%;
13936
+ height: 100%;
13937
+ }
13938
+ :where([data-kit="pro"]) .tf-floating-ui {
13939
+ position: absolute;
13940
+ inset: 0;
13941
+ z-index: 1;
13942
+ display: grid;
13943
+ grid-template-columns: minmax(0, 320px) minmax(0, 1fr) minmax(0, 340px);
13944
+ grid-template-rows: auto minmax(0, 1fr) auto;
13945
+ grid-template-areas:
13946
+ "top top top"
13947
+ "start . end"
13948
+ "bottom bottom bottom";
13949
+ gap: var(--space-4);
13950
+ padding: var(--space-4);
13951
+ overflow-y: auto;
13952
+ /* the background stays usable between the slots */
13953
+ pointer-events: none;
13954
+ }
13955
+ :where([data-kit="pro"]) .tf-floating-ui > * {
13956
+ pointer-events: auto;
13957
+ min-width: 0;
13958
+ }
13959
+ :where([data-kit="pro"]) .tf-floating-top {
13960
+ grid-area: top;
13961
+ display: flex;
13962
+ flex-wrap: wrap;
13963
+ align-items: center;
13964
+ gap: var(--space-2);
13965
+ }
13966
+ :where([data-kit="pro"]) .tf-floating-start {
13967
+ grid-area: start;
13968
+ align-self: start;
13969
+ }
13970
+ :where([data-kit="pro"]) .tf-floating-end {
13971
+ grid-area: end;
13972
+ align-self: start;
13973
+ }
13974
+ :where([data-kit="pro"]) .tf-floating-bottom {
13975
+ grid-area: bottom;
13976
+ justify-self: center;
13977
+ }
13978
+ :where([data-kit="pro"]) .tf-floating-ui > :is(.tf-floating-top, .tf-floating-bottom) {
13979
+ pointer-events: none;
13980
+ }
13981
+ :where([data-kit="pro"]) .tf-floating-ui > :is(.tf-floating-top, .tf-floating-bottom) > * {
13982
+ pointer-events: auto;
13983
+ }
13984
+ @container tf-floating (max-width: 720px) {
13985
+ /* on a phone the layout grows with its slots and the background fills behind them */
13986
+ :where([data-kit="pro"]) .tf-floating-ui {
13987
+ position: relative;
13988
+ min-height: inherit;
13989
+ overflow: visible;
13990
+ grid-template-columns: minmax(0, 1fr);
13991
+ grid-template-rows: auto auto minmax(120px, 1fr) auto auto;
13992
+ grid-template-areas:
13993
+ "top"
13994
+ "start"
13995
+ "."
13996
+ "end"
13997
+ "bottom";
13998
+ gap: var(--space-3);
13999
+ padding: var(--space-3);
14000
+ }
14001
+ }
14002
+
14003
+ /* 09-motion.css */
14004
+ /* Generated by scripts/pro-css.ts from packages/halo/css. Do not edit; the Pro look lives in 90-pro-look.css. */
14005
+ /* Motion: leaving layers, reveal on scroll, page transitions, the expressive level.
14006
+ *
14007
+ * Levels come from `data-motion` (tokens.css): "standard", "expressive" (longer, staggered page
14008
+ * entrances, more travel) and "off". The reader's reduced-motion setting always means off. Only
14009
+ * transform, opacity and (expressive Halo) a short blur move; everything else stays put.
14010
+ */
14011
+
14012
+ /* ── Leaving: layers animate out for --dur-exit, then unmount (usePresence) ── */
14013
+ @keyframes tf-pro-out {
14014
+ to {
14015
+ opacity: 0;
14016
+ translate: 0 calc(6px * var(--motion-travel));
14017
+ scale: 0.98;
14018
+ }
14019
+ }
14020
+ @keyframes tf-pro-out-fade {
14021
+ to {
14022
+ opacity: 0;
14023
+ }
14024
+ }
14025
+ @keyframes tf-pro-out-right {
14026
+ to {
14027
+ opacity: 0;
14028
+ translate: calc(40px * var(--motion-travel)) 0;
14029
+ }
14030
+ }
14031
+ @keyframes tf-pro-out-left {
14032
+ to {
14033
+ opacity: 0;
14034
+ translate: calc(-40px * var(--motion-travel)) 0;
14035
+ }
14036
+ }
14037
+ @keyframes tf-pro-out-up {
14038
+ to {
14039
+ opacity: 0;
14040
+ translate: 0 calc(-40px * var(--motion-travel));
14041
+ }
14042
+ }
14043
+ @keyframes tf-pro-out-down {
14044
+ to {
14045
+ opacity: 0;
14046
+ translate: 0 calc(16px * var(--motion-travel));
14047
+ }
14048
+ }
14049
+ :where([data-kit="pro"])[data-closing], :where([data-kit="pro"]) [data-closing] {
14050
+ pointer-events: none;
14051
+ }
14052
+ :where([data-kit="pro"]) .tf-popover[data-closing],
14053
+ :where([data-kit="pro"]) .tf-hovercard[data-closing],
14054
+ :where([data-kit="pro"]) .tf-modal-wrap[data-closing] .tf-modal,
14055
+ :where([data-kit="pro"]) .tf-overlay[data-closing] :is(.tf-modal, .tf-confirm),
14056
+ :where([data-kit="pro"]) .tf-palette-wrap[data-closing] .tf-palette {
14057
+ animation: tf-pro-out var(--dur-exit) var(--ease-in-out) forwards;
14058
+ }
14059
+ :where([data-kit="pro"]) .tf-tooltip[data-closing],
14060
+ :where([data-kit="pro"]) .tf-modal-wrap[data-closing] .tf-backdrop,
14061
+ :where([data-kit="pro"]) .tf-overlay[data-closing] .tf-backdrop,
14062
+ :where([data-kit="pro"]) .tf-palette-wrap[data-closing],
14063
+ :where([data-kit="pro"]) .tf-drawer-wrap[data-closing] {
14064
+ animation: tf-pro-out-fade var(--dur-exit) var(--ease-in-out) forwards;
14065
+ }
14066
+ :where([data-kit="pro"]) .tf-drawer-wrap[data-closing] .tf-drawer {
14067
+ animation: tf-pro-out-right var(--dur-exit) var(--ease-in-out) forwards;
14068
+ }
14069
+ :where([data-kit="pro"]) .tf-drawer-wrap[data-closing] .tf-drawer.side-left {
14070
+ animation-name: tf-pro-out-left;
14071
+ }
14072
+ :where([data-kit="pro"]) .tf-drawer-wrap[data-closing] .tf-drawer.side-top {
14073
+ animation-name: tf-pro-out-up;
14074
+ }
14075
+ :where([data-kit="pro"]) .tf-drawer-wrap[data-closing] .tf-drawer.side-bottom,
14076
+ :where([data-kit="pro"]) .tf-toast[data-closing] {
14077
+ animation: tf-pro-out-down var(--dur-exit) var(--ease-in-out) forwards;
14078
+ }
14079
+
14080
+ /* ── Reveal: a Stagger below the fold waits until it scrolls into view ── */
14081
+ :where([data-kit="pro"]) .tf-stagger[data-reveal="waiting"] > *,
14082
+ :where([data-kit="pro"]) .tf-stagger[data-reveal="waiting"] > * * {
14083
+ animation-play-state: paused;
14084
+ }
14085
+
14086
+ /* ── Page transitions (startViewTransition, Next.js and React view transitions) ── */
14087
+ @keyframes tf-pro-vt-out {
14088
+ to {
14089
+ opacity: 0;
14090
+ translate: 0 calc(-6px * var(--motion-travel));
14091
+ }
14092
+ }
14093
+ @keyframes tf-pro-vt-in {
14094
+ from {
14095
+ opacity: 0;
14096
+ translate: 0 calc(10px * var(--motion-travel));
14097
+ }
14098
+ }
14099
+ :where([data-kit="pro"])::view-transition-old(root) {
14100
+ animation: tf-pro-vt-out var(--dur-base) var(--ease-in-out) both;
14101
+ }
14102
+ :where([data-kit="pro"])::view-transition-new(root) {
14103
+ animation: tf-pro-vt-in var(--dur-enter) var(--ease-out) both;
14104
+ }
14105
+
14106
+ /* ── Expressive: things come into focus as they rise (Halo; Pro keeps a blur of 0) ── */
14107
+ @keyframes tf-pro-focus-in {
14108
+ from {
14109
+ filter: blur(var(--motion-blur));
14110
+ }
14111
+ to {
14112
+ filter: none;
14113
+ }
14114
+ }
14115
+ :where([data-kit="pro"])[data-motion="expressive"] :is(.tf-stagger > *, .tf-in), :where([data-kit="pro"]) [data-motion="expressive"] :is(.tf-stagger > *, .tf-in) {
14116
+ animation-name: tf-pro-rise, tf-pro-focus-in;
14117
+ }
14118
+ :where([data-kit="pro"])[data-motion="expressive"] .tf-topbar, :where([data-kit="pro"]) [data-motion="expressive"] .tf-topbar {
14119
+ animation-name: tf-pro-drop, tf-pro-focus-in;
14120
+ }
14121
+
14122
+ /* 10-ambient.css */
14123
+ /* Generated by scripts/pro-css.ts from packages/halo/css. Do not edit; the Pro look lives in 90-pro-look.css. */
14124
+ /* Ambient: a calm, living background for glass UI. Soft colour fields from the kit (pastels in
14125
+ * Halo, a faint aurora in Pro) drift slowly; a photo or video can take their place under a scrim.
14126
+ * The drift only moves (transform), stops with motion off and pauses off screen.
14127
+ */
14128
+ :where([data-kit="pro"]) :where(:has(> .tf-ambient:not(.fixed))) {
14129
+ position: relative;
14130
+ isolation: isolate;
14131
+ }
14132
+ :where([data-kit="pro"]) .tf-ambient {
14133
+ position: absolute;
14134
+ inset: 0;
14135
+ z-index: -1;
14136
+ overflow: hidden;
14137
+ background: var(--ambient-base);
14138
+ pointer-events: none;
14139
+ }
14140
+ :where([data-kit="pro"]) .tf-ambient.fixed {
14141
+ position: fixed;
14142
+ }
14143
+ :where([data-kit="pro"]) .tf-ambient-field {
14144
+ position: absolute;
14145
+ width: 75%;
14146
+ aspect-ratio: 1;
14147
+ border-radius: var(--radius-1);
14148
+ background: radial-gradient(closest-side, var(--field), transparent);
14149
+ animation: tf-pro-ambient-drift 34s var(--ease-in-out) infinite alternate;
14150
+ }
14151
+ :where([data-kit="pro"]) .tf-ambient-field:nth-child(1) {
14152
+ top: -30%;
14153
+ left: -15%;
14154
+ }
14155
+ :where([data-kit="pro"]) .tf-ambient-field:nth-child(2) {
14156
+ top: -10%;
14157
+ right: -25%;
14158
+ animation-duration: 41s;
14159
+ animation-direction: alternate-reverse;
14160
+ }
14161
+ :where([data-kit="pro"]) .tf-ambient-field:nth-child(3) {
14162
+ bottom: -35%;
14163
+ left: 10%;
14164
+ animation-duration: 47s;
14165
+ }
14166
+ :where([data-kit="pro"]) .tf-ambient-field:nth-child(4) {
14167
+ bottom: -25%;
14168
+ right: -10%;
14169
+ animation-duration: 38s;
14170
+ animation-direction: alternate-reverse;
14171
+ }
14172
+ :where([data-kit="pro"]) .tf-ambient-field:nth-child(n + 5) {
14173
+ top: 20%;
14174
+ left: 30%;
14175
+ width: 55%;
14176
+ animation-duration: 52s;
14177
+ }
14178
+ @keyframes tf-pro-ambient-drift {
14179
+ to {
14180
+ translate: 12% 9%;
14181
+ scale: 1.15;
14182
+ }
14183
+ }
14184
+ :where([data-kit="pro"]) .tf-ambient.still .tf-ambient-field,
14185
+ :where([data-kit="pro"]) .tf-ambient[data-paused] .tf-ambient-field {
14186
+ animation-play-state: paused;
14187
+ }
14188
+ :where([data-kit="pro"]) .tf-ambient-media {
14189
+ position: absolute;
14190
+ inset: 0;
14191
+ width: 100%;
14192
+ height: 100%;
14193
+ object-fit: cover;
14194
+ }
14195
+ :where([data-kit="pro"]) .tf-ambient.media::after {
14196
+ content: "";
14197
+ position: absolute;
14198
+ inset: 0;
14199
+ background: var(--ambient-scrim);
14200
+ }
14201
+ @media (prefers-reduced-motion: reduce) {
14202
+ :where([data-kit="pro"]) .tf-ambient-field {
14203
+ animation: none;
14204
+ }
14205
+ }
14206
+ :where([data-kit="pro"])[data-motion="off"] .tf-ambient-field, :where([data-kit="pro"]) [data-motion="off"] .tf-ambient-field {
14207
+ animation: none;
14208
+ }
14209
+
13357
14210
  /* 90-pro-look.css */
13358
14211
  /* Pro look ("Clean Dark Pro", reference/pro): monochrome surfaces on a visible 1px hairline grid,
13359
14212
  square corners (2px on controls), Geist and Geist Mono, colour only for state, dense by default.