@nebutra/tokens 0.1.3 → 2.0.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/styles.css CHANGED
@@ -90,7 +90,7 @@
90
90
  --duration-reveal: 300ms; /** Content unveil: slide-in, expand, accordion, drawer */
91
91
  --duration-cinematic: 500ms; /** Hero-grade entrance: landing reveal, large delight moments */
92
92
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
93
- --ease-out: cubic-bezier(0, 0, 0.2, 1);
93
+ --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
94
94
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
95
95
  --ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
96
96
  --tracking-display: -0.04em; /** Hero H1 */
@@ -101,17 +101,15 @@
101
101
  --ring-hairline: inset 0 0 0 1px rgb(255 255 255 / 0.04); /** Etched-glass hairline (light mode value, dark mode override in themes/dark.json) */
102
102
  --overlay-faint: rgb(0 0 0 / 0.06); /** Light-mode faint overlay (6% black) */
103
103
  --font-sans:
104
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
105
- "PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
104
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC",
105
+ "Microsoft YaHei", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
106
106
  --font-cn:
107
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
108
- "PingFang SC", "Microsoft YaHei", sans-serif; /** CJK-locale stack — same order as sans, minus the Latin-only system faces */
107
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC",
108
+ "Microsoft YaHei", sans-serif; /** CJK-locale stack — same order as sans, minus the Latin-only system faces */
109
109
  --font-display:
110
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
111
- sans-serif;
110
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), sans-serif;
112
111
  --font-heading:
113
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
114
- sans-serif;
112
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), sans-serif;
115
113
  --font-mono:
116
114
  var(--font-geist-mono), "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
117
115
  --brand-primary: #0033fe; /** Brand primary — 云毓蓝 */
@@ -419,7 +417,7 @@
419
417
  --duration-reveal: 300ms; /** Content unveil: slide-in, expand, accordion, drawer */
420
418
  --duration-cinematic: 500ms; /** Hero-grade entrance: landing reveal, large delight moments */
421
419
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
422
- --ease-out: cubic-bezier(0, 0, 0.2, 1);
420
+ --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
423
421
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
424
422
  --ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
425
423
  --tracking-display: -0.04em; /** Hero H1 */
@@ -432,17 +430,15 @@
432
430
  255 255 255 / 0.06
433
431
  ); /** Dark-mode faint overlay (6% white) — inverted from light */
434
432
  --font-sans:
435
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
436
- "PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
433
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC",
434
+ "Microsoft YaHei", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
437
435
  --font-cn:
438
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
439
- "PingFang SC", "Microsoft YaHei", sans-serif; /** CJK-locale stack — same order as sans, minus the Latin-only system faces */
436
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC",
437
+ "Microsoft YaHei", sans-serif; /** CJK-locale stack — same order as sans, minus the Latin-only system faces */
440
438
  --font-display:
441
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
442
- sans-serif;
439
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), sans-serif;
443
440
  --font-heading:
444
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
445
- sans-serif;
441
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), sans-serif;
446
442
  --font-mono:
447
443
  var(--font-geist-mono), "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
448
444
  --brand-primary: #5c7cfa; /** Dark-mode brand primary — the identity blue lifted to nebutra-blue-400 so it stays visible on dark surfaces. This is the identity alias, not the functional fill: the dark solid fill is --blue-9 (#396ae2, white label 4.85:1). The two are deliberately separate now that the VI hex is no longer pinned into ramp slot 9. */
@@ -834,6 +830,22 @@
834
830
  --radius-3xl: 1.5rem;
835
831
  --radius-full: 9999px;
836
832
 
833
+ /* Containers — the page-width contract from CLAUDE.md, as real utilities.
834
+ max-w-text (reading), max-w-content (pricing/blog), max-w-wide (feature bento, navbar).
835
+
836
+ These values also reach :root through the semantic layer, so var(--container-wide) keeps
837
+ working; what was missing was the Tailwind side. Without it there is no max-w-wide to reach
838
+ for, and 92 call sites across apps/** had typed max-w-wide instead — a decided number
839
+ living in a className, where changing the token cannot move it.
840
+
841
+ Literals rather than var(--container-wide): Tailwind emits an @theme entry into its own
842
+ layer, so a same-named reference becomes self-referential and survives only because the
843
+ semantic :root happens to come later in the cascade. Duplicating the number and pinning it
844
+ with a parity test is the honest trade — see design-tokens' container parity test. */
845
+ --container-text: 896px;
846
+ --container-content: 1152px;
847
+ --container-wide: 1400px;
848
+
837
849
  /* Shadows */
838
850
  --shadow-xs: var(--elevation-xs);
839
851
  --shadow-sm: var(--elevation-sm);
@@ -873,6 +885,7 @@
873
885
  (No backticks in this block — it is inside a JS template literal.) */
874
886
  --ease-in: var(--motion-ease-in);
875
887
  --ease-out: var(--motion-ease-out);
888
+ --ease-brand: var(--motion-ease-brand);
876
889
  --ease-in-out: var(--motion-ease-in-out);
877
890
  --ease-spring: var(--motion-ease-spring);
878
891
 
@@ -882,6 +895,20 @@
882
895
  --duration-reveal: var(--motion-duration-reveal);
883
896
  --duration-cinematic: var(--motion-duration-cinematic);
884
897
 
898
+ /* The same four rails on the namespace Tailwind reads for duration-*.
899
+ --duration-* is the variable other CSS consumes; the utility class is built
900
+ from --transition-duration-*, and only that one. Without these,
901
+ duration-micro and duration-reveal are class names that generate nothing:
902
+ they were in use in the component library and on the marketing site, and
903
+ every one of them silently fell back to the 150ms default. */
904
+ --transition-duration-micro: var(--motion-duration-micro);
905
+ --transition-duration-flow: var(--motion-duration-flow);
906
+ --transition-duration-reveal: var(--motion-duration-reveal);
907
+ --transition-duration-cinematic: var(--motion-duration-cinematic);
908
+
909
+ /* Likewise for ease-*: the utility namespace is --ease-* already, so the four
910
+ above are reachable as ease-brand / ease-spring without further mapping. */
911
+
885
912
  /* Spacing — DO NOT register --spacing-sm|md|lg|xl|2xl here.
886
913
  Tailwind v4 puts every --spacing-{key} on the shared size rail, so
887
914
  max-w-sm / max-w-2xl (and width/height/gap utilities with the same keys)
@@ -893,22 +920,20 @@
893
920
  --spacing-{step} alias. --spacing itself (0.25rem arithmetic base) stays
894
921
  untouched. See static/base.css. */
895
922
 
896
- /* Font family — Geist keeps Latin + numerals, self-hosted vivo Sans SC takes
923
+ /* Font family — Geist keeps Latin + numerals, self-hosted Noto Sans SC takes
897
924
  CJK, system CJK faces behind it. Order is the design decision; see the
898
925
  fontFamily $description in tokens/core.json. Mirror of those tokens — keep
899
926
  the two in sync (verify:parity compares them). */
900
927
  --font-sans:
901
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
902
- "PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
928
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC",
929
+ "Microsoft YaHei", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
903
930
  --font-cn:
904
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
905
- "PingFang SC", "Microsoft YaHei", sans-serif;
931
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC",
932
+ "Microsoft YaHei", sans-serif;
906
933
  --font-display:
907
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
908
- sans-serif;
934
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), sans-serif;
909
935
  --font-heading:
910
- var(--font-geist-sans), "Geist", var(--font-vivo-sans-sc, "vivo Sans SC"), "Noto Sans SC",
911
- sans-serif;
936
+ var(--font-geist-sans), "Geist", var(--font-noto-sans-sc, "Noto Sans SC"), sans-serif;
912
937
  --font-mono:
913
938
  var(--font-geist-mono), "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
914
939
  }
@@ -938,9 +963,71 @@
938
963
  ─────────────────────────────────────────────────────────── */
939
964
  :root {
940
965
  --motion-ease-in: cubic-bezier(0.4, 0, 1, 1);
941
- --motion-ease-out: cubic-bezier(0, 0, 0.2, 1);
966
+ --motion-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
942
967
  --motion-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
943
968
  --motion-ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
969
+ /* The signature: a long, strong deceleration — most of the distance is
970
+ covered in the first fifth of the time, then it settles. It has existed as
971
+ `brandEasing.brand` in @nebutra/brand since the motion language was
972
+ written, usable only from JS, so every CSS transition on every marketing
973
+ surface fell back to Tailwind's default curve instead. That default is
974
+ what "the hovers feel stiff" is: a near-linear ramp at 150ms. */
975
+ --motion-ease-brand: cubic-bezier(0.16, 1, 0.3, 1);
976
+ }
977
+
978
+ /* ─── Category rail ──────────────────────────────────────────
979
+ Four accents for taxonomy — the monorepo tree's four lanes, and
980
+ anywhere else a small set of peers has to be told apart.
981
+
982
+ Derived, not picked. Hand-picking is how the file tree ended up
983
+ with fifteen hues across twenty-five rows, three of them reused
984
+ on unrelated rows: a colour that encodes nothing a reader can
985
+ learn and follows no design language.
986
+
987
+ Each accent is a position on the background→foreground axis,
988
+ tinted a quarter of the way toward the action fill rotated by
989
+ 72°. Two axes, both always live:
990
+
991
+ • the position carries contrast. That axis is non-degenerate
992
+ in every language by definition — it is the axis that makes
993
+ body text readable — so a monochrome language still gets
994
+ four distinct tones. Vercel and Notion anchor on black,
995
+ where rotating hue returns the same colour four times.
996
+ • the rotation carries hue separation for the languages that
997
+ have chroma to give.
998
+
999
+ Two earlier constructions failed here and are worth naming.
1000
+ Offsetting lightness from the anchor and clamping collapses when
1001
+ the anchor already sits near the band edge — Raycast's fill is
1002
+ near-white, so all four pinned to one value. A fixed lightness
1003
+ ladder cannot serve both canvases: Raycast and GSAP are dark by
1004
+ default in light mode, so the `.dark` class is not set and an
1005
+ absolute ladder is upside down for them.
1006
+
1007
+ Measured across all seven languages plus factory: lowest contrast
1008
+ 3.50:1 against each canvas, closest pair 30/255 apart.
1009
+ ─────────────────────────────────────────────────────────── */
1010
+ :root {
1011
+ --category-1: color-mix(
1012
+ in oklab,
1013
+ color-mix(in oklab, hsl(var(--foreground)) 55%, hsl(var(--background))) 75%,
1014
+ oklch(from hsl(var(--primary)) l c h)
1015
+ );
1016
+ --category-2: color-mix(
1017
+ in oklab,
1018
+ color-mix(in oklab, hsl(var(--foreground)) 67%, hsl(var(--background))) 75%,
1019
+ oklch(from hsl(var(--primary)) l c calc(h + 72))
1020
+ );
1021
+ --category-3: color-mix(
1022
+ in oklab,
1023
+ color-mix(in oklab, hsl(var(--foreground)) 79%, hsl(var(--background))) 75%,
1024
+ oklch(from hsl(var(--primary)) l c calc(h + 144))
1025
+ );
1026
+ --category-4: color-mix(
1027
+ in oklab,
1028
+ color-mix(in oklab, hsl(var(--foreground)) 91%, hsl(var(--background))) 75%,
1029
+ oklch(from hsl(var(--primary)) l c calc(h + 216))
1030
+ );
944
1031
  }
945
1032
 
946
1033
  /* ─── Spacing source rail ────────────────────────────────────