@cosxai/ui 0.25.0 → 1.0.0-alpha.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.
Files changed (133) hide show
  1. package/CHANGELOG.md +577 -0
  2. package/NOTICE +11 -0
  3. package/README.md +52 -0
  4. package/package.json +33 -7
  5. package/src/fonts.css +20 -0
  6. package/src/index.ts +8 -25
  7. package/src/lib/cn.ts +23 -6
  8. package/src/styles.css +17 -0
  9. package/src/theme.css +132 -0
  10. package/src/tokens/colors.css +112 -0
  11. package/src/tokens/compat.css +36 -0
  12. package/src/tokens/elevation.css +14 -0
  13. package/src/tokens/motion.css +42 -0
  14. package/src/tokens/spacing.css +55 -0
  15. package/src/tokens/typography-cjk.css +42 -0
  16. package/src/tokens/typography.css +81 -0
  17. package/src/actionbar/ActionBar.tsx +0 -837
  18. package/src/actionbar/ActionBarButton.tsx +0 -111
  19. package/src/actionbar/ActionBarMenuGroup.tsx +0 -116
  20. package/src/actionbar/ActionBarModeHandle.tsx +0 -171
  21. package/src/actionbar/ActionBarProvider.tsx +0 -91
  22. package/src/actionbar/actionbar-context.ts +0 -45
  23. package/src/actionbar/index.ts +0 -28
  24. package/src/actionbar/types.ts +0 -147
  25. package/src/actionbar/useActionBarItems.ts +0 -60
  26. package/src/actionbar/useActionBarMode.ts +0 -144
  27. package/src/actionbar/useActionBarPanel.ts +0 -56
  28. package/src/actionbar/useActionBarStatusDot.ts +0 -49
  29. package/src/actionbar/useActionBarToast.ts +0 -33
  30. package/src/ambient/AmbientBackdrop.tsx +0 -74
  31. package/src/ambient/CommandInput.tsx +0 -107
  32. package/src/ambient/SuperbarStrip.tsx +0 -36
  33. package/src/ambient/index.ts +0 -6
  34. package/src/bento/BentoCell.tsx +0 -66
  35. package/src/bento/BentoGrid.tsx +0 -42
  36. package/src/bento/index.ts +0 -2
  37. package/src/command/CommandPalette.tsx +0 -329
  38. package/src/command/CommandProvider.tsx +0 -57
  39. package/src/command/command-context.ts +0 -12
  40. package/src/command/index.ts +0 -6
  41. package/src/command/rank.ts +0 -50
  42. package/src/command/types.ts +0 -37
  43. package/src/command/useCommandSource.ts +0 -37
  44. package/src/dialogs/DialogsProvider.tsx +0 -216
  45. package/src/dialogs/Modal.tsx +0 -260
  46. package/src/dialogs/Toast.tsx +0 -85
  47. package/src/dialogs/dialogs-context.ts +0 -6
  48. package/src/dialogs/index.ts +0 -10
  49. package/src/dialogs/types.ts +0 -37
  50. package/src/dialogs/useDialogs.ts +0 -8
  51. package/src/editorial/EditorialSpotlight.tsx +0 -63
  52. package/src/editorial/Folio.tsx +0 -52
  53. package/src/editorial/PlateMarker.tsx +0 -33
  54. package/src/editorial/RomanSection.tsx +0 -65
  55. package/src/editorial/RunningMarginalia.tsx +0 -65
  56. package/src/editorial/index.ts +0 -10
  57. package/src/hooks/index.ts +0 -5
  58. package/src/hooks/useKeyboardHotkey.ts +0 -93
  59. package/src/hooks/useReducedMotion.ts +0 -20
  60. package/src/hooks/useViewport.ts +0 -61
  61. package/src/layout/Breadcrumb.tsx +0 -74
  62. package/src/layout/LeftNavRail.tsx +0 -139
  63. package/src/layout/MobileTabBar.tsx +0 -101
  64. package/src/layout/NavItem.tsx +0 -128
  65. package/src/layout/NavSearchTrigger.tsx +0 -88
  66. package/src/layout/NavSection.tsx +0 -40
  67. package/src/layout/RightSidebarPanel.tsx +0 -111
  68. package/src/layout/Shell.tsx +0 -91
  69. package/src/layout/SidePanel.tsx +0 -316
  70. package/src/layout/StickyBanner.tsx +0 -83
  71. package/src/layout/Topbar.tsx +0 -68
  72. package/src/layout/index.ts +0 -24
  73. package/src/layout/useNavRailState.ts +0 -69
  74. package/src/lib/time-utils.ts +0 -44
  75. package/src/neobrutalism/Marquee.tsx +0 -81
  76. package/src/neobrutalism/Sticker.tsx +0 -71
  77. package/src/neobrutalism/index.ts +0 -4
  78. package/src/primitives/Avatar.tsx +0 -53
  79. package/src/primitives/Button.tsx +0 -67
  80. package/src/primitives/Card.tsx +0 -41
  81. package/src/primitives/Checkbox.tsx +0 -87
  82. package/src/primitives/Chip.tsx +0 -191
  83. package/src/primitives/Combobox.tsx +0 -507
  84. package/src/primitives/CopyField.tsx +0 -139
  85. package/src/primitives/CountBadge.tsx +0 -50
  86. package/src/primitives/Input.tsx +0 -204
  87. package/src/primitives/Kbd.tsx +0 -45
  88. package/src/primitives/MentionCombobox.tsx +0 -612
  89. package/src/primitives/MultiCombobox.tsx +0 -327
  90. package/src/primitives/PageHeader.tsx +0 -77
  91. package/src/primitives/Radio.tsx +0 -131
  92. package/src/primitives/SegmentedControl.tsx +0 -135
  93. package/src/primitives/Select.tsx +0 -779
  94. package/src/primitives/SignaturePad.tsx +0 -461
  95. package/src/primitives/Tag.tsx +0 -56
  96. package/src/primitives/Textarea.tsx +0 -62
  97. package/src/primitives/ToggleSwitch.tsx +0 -79
  98. package/src/primitives/Tooltip.tsx +0 -213
  99. package/src/primitives/index.ts +0 -53
  100. package/src/pwa/InstallPromptBanner.tsx +0 -132
  101. package/src/pwa/index.ts +0 -4
  102. package/src/pwa/manifest.template.json +0 -20
  103. package/src/pwa/registerSW.ts +0 -55
  104. package/src/riso/Halftone.tsx +0 -85
  105. package/src/riso/Misregister.tsx +0 -63
  106. package/src/riso/RisoStamp.tsx +0 -76
  107. package/src/riso/index.ts +0 -3
  108. package/src/sketch/HandUnderline.tsx +0 -53
  109. package/src/sketch/RoughArrow.tsx +0 -91
  110. package/src/sketch/RoughBox.tsx +0 -73
  111. package/src/sketch/StickyNote.tsx +0 -56
  112. package/src/sketch/index.ts +0 -4
  113. package/src/styles/base.css +0 -186
  114. package/src/styles/chrome-ambient.css +0 -235
  115. package/src/styles/chrome-bento.css +0 -192
  116. package/src/styles/chrome-editorial.css +0 -168
  117. package/src/styles/chrome-neobrutalism.css +0 -326
  118. package/src/styles/chrome-riso.css +0 -339
  119. package/src/styles/chrome-sketch.css +0 -362
  120. package/src/styles/chrome-swiss.css +0 -265
  121. package/src/styles/chrome-terminal.css +0 -272
  122. package/src/styles/fonts.css +0 -1034
  123. package/src/styles/index.css +0 -343
  124. package/src/styles/tokens.css +0 -941
  125. package/src/terminal/AsciiBox.tsx +0 -65
  126. package/src/terminal/BrailleSpinner.tsx +0 -46
  127. package/src/terminal/index.ts +0 -4
  128. package/src/theme/ThemeProvider.tsx +0 -99
  129. package/src/theme/index.ts +0 -6
  130. package/src/theme/inline-script.ts +0 -40
  131. package/src/theme/theme-context.ts +0 -7
  132. package/src/theme/types.ts +0 -39
  133. package/src/theme/useTheme.ts +0 -8
package/package.json CHANGED
@@ -1,18 +1,23 @@
1
1
  {
2
2
  "name": "@cosxai/ui",
3
- "version": "0.25.0",
4
- "description": "COSX design system \u2014 React 19 component primitives shared across product-meta and other consumers",
3
+ "version": "1.0.0-alpha.0",
4
+ "description": "COSX Design System 3.0 — tokens, Tailwind v4 theme and React components",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
7
7
  "main": "./src/index.ts",
8
8
  "types": "./src/index.ts",
9
9
  "exports": {
10
10
  ".": "./src/index.ts",
11
- "./styles.css": "./src/styles/index.css"
11
+ "./styles.css": "./src/styles.css",
12
+ "./theme.css": "./src/theme.css",
13
+ "./tokens/*": "./src/tokens/*"
12
14
  },
13
15
  "files": [
14
16
  "src",
15
- "README.md"
17
+ "!src/**/*.test.ts",
18
+ "README.md",
19
+ "CHANGELOG.md",
20
+ "NOTICE"
16
21
  ],
17
22
  "repository": {
18
23
  "type": "git",
@@ -24,15 +29,36 @@
24
29
  "registry": "https://registry.npmjs.org/"
25
30
  },
26
31
  "scripts": {
27
- "typecheck": "tsc --noEmit"
32
+ "typecheck": "tsc --noEmit",
33
+ "test": "vitest run",
34
+ "check:css": "tailwindcss -i test/fixture.css -o test/out.css"
28
35
  },
29
36
  "peerDependencies": {
30
37
  "react": "^19.0.0",
31
- "react-dom": "^19.0.0"
38
+ "react-dom": "^19.0.0",
39
+ "tailwindcss": "^4.0.0"
32
40
  },
33
41
  "devDependencies": {
42
+ "@tailwindcss/cli": "^4",
43
+ "@types/node": "^26.6.3",
34
44
  "@types/react": "^19.0.0",
35
45
  "@types/react-dom": "^19.0.0",
36
- "typescript": "^5.6.0"
46
+ "tailwindcss": "^4",
47
+ "typescript": "^5.6.0",
48
+ "vitest": "^3.2.0"
49
+ },
50
+ "sideEffects": [
51
+ "**/*.css"
52
+ ],
53
+ "dependencies": {
54
+ "@fontsource-variable/geist": "^5.3.0",
55
+ "@fontsource-variable/noto-sans-sc": "^5.3.0",
56
+ "clsx": "^2.1.1",
57
+ "tailwind-merge": "^3.3.1"
58
+ },
59
+ "peerDependenciesMeta": {
60
+ "tailwindcss": {
61
+ "optional": true
62
+ }
37
63
  }
38
64
  }
package/src/fonts.css ADDED
@@ -0,0 +1,20 @@
1
+ /* @cosxai/ui — self-hosted fonts.
2
+ *
3
+ * The 3.0 tokens load Geist and Noto Sans SC from Google Fonts
4
+ * (tokens/fonts.css in the design system, not shipped here). The kit
5
+ * serves them from the consumer's own bundle instead: Fontsource
6
+ * variable builds, OFL-1.1, split by unicode range so a page downloads
7
+ * only the glyphs it shows.
8
+ *
9
+ * Fontsource names the families "… Variable"; the stacks below put those
10
+ * first and keep the design system's own names after them. Loaded after
11
+ * the tokens (styles.css), so these stacks are the ones in effect.
12
+ */
13
+ @import "@fontsource-variable/geist";
14
+ @import "@fontsource-variable/noto-sans-sc";
15
+
16
+ :root {
17
+ --font-sans: "Geist Variable", "Geist", "Helvetica Neue", Helvetica, Arial, sans-serif;
18
+ --font-cjk: "Noto Sans SC Variable", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
19
+ --font-sans-cjk: "Geist Variable", "Geist", "Noto Sans SC Variable", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
20
+ }
package/src/index.ts CHANGED
@@ -1,25 +1,8 @@
1
- // Entry point — re-exports everything consumers need.
2
- // Components, hooks, theme, and helpers are organised under
3
- // /primitives, /layout, /actionbar, /command, /dialogs, /hooks,
4
- // /theme, /pwa, /lib. As the kit grows, each phase adds exports
5
- // here. Consumers pull individual modules (`import { Button }
6
- // from "@cosxai/ui"`) or copy source files directly per the
7
- // shadcn-style distribution model.
8
-
9
- export * from "./primitives";
10
- export * from "./lib/cn";
11
- export * from "./lib/time-utils";
12
- export * from "./theme";
13
- export * from "./hooks";
14
- export * from "./layout";
15
- export * from "./dialogs";
16
- export * from "./actionbar";
17
- export * from "./command";
18
- export * from "./pwa";
19
- export * from "./editorial";
20
- export * from "./neobrutalism";
21
- export * from "./ambient";
22
- export * from "./terminal";
23
- export * from "./bento";
24
- export * from "./riso";
25
- export * from "./sketch";
1
+ /**
2
+ * @cosxai/ui 1.x — the COSX Design System 3.0 in React.
3
+ *
4
+ * Foundations: import "@cosxai/ui/styles.css" (tokens + fonts) and, in a
5
+ * Tailwind v4 app, "@cosxai/ui/theme.css". Components arrive in the 1.0
6
+ * alphas (docs/workdocs/2026-09-29_feature-ui-1.0).
7
+ */
8
+ export { cn } from './lib/cn';
package/src/lib/cn.ts CHANGED
@@ -1,7 +1,24 @@
1
- // Lightweight className merge. Filters falsy values and joins with a
2
- // single space. Sufficient for component composition; if a consumer
3
- // needs tailwind-merge / clsx semantics they can swap implementations
4
- // without touching call sites.
5
- export function cn(...inputs: Array<string | false | null | undefined>): string {
6
- return inputs.filter(Boolean).join(" ");
1
+ import { clsx, type ClassValue } from 'clsx';
2
+ import { extendTailwindMerge } from 'tailwind-merge';
3
+
4
+ /**
5
+ * cn — join class names and let the later Tailwind class win on conflict
6
+ * (`cn('p-2', cond && 'p-4')` → `p-4`).
7
+ *
8
+ * tailwind-merge only knows Tailwind's default scales; the kit's theme
9
+ * (theme.css) replaces font sizes with its own names, taught here so
10
+ * `text-ui` and `text-fg` are not mistaken for each other (one is a
11
+ * size, one a colour).
12
+ */
13
+ const merge = extendTailwindMerge({
14
+ extend: {
15
+ theme: {
16
+ text: ['meta', 'small', 'ui', 'body', 'h3', 'lede', 'title', 'figure', 'h2', 'h1', 'display'],
17
+ radius: ['xs', 'sm', 'md', 'lg', 'xl', 'pill'],
18
+ },
19
+ },
20
+ });
21
+
22
+ export function cn(...inputs: ClassValue[]): string {
23
+ return merge(clsx(inputs));
7
24
  }
package/src/styles.css ADDED
@@ -0,0 +1,17 @@
1
+ /* @cosxai/ui — the COSX Design System 3.0 foundations.
2
+ *
3
+ * tokens/ are the design system's own files, copied unchanged from the
4
+ * "COSX Design System 3.0" project. Edit them there and copy again; the
5
+ * kit's additions live in fonts.css and theme.css.
6
+ *
7
+ * Ink (dark) mode: set data-mode="ink" on <html>, or put .ink-mode on a
8
+ * subtree (colors.css).
9
+ */
10
+ @import "./tokens/colors.css";
11
+ @import "./tokens/typography.css";
12
+ @import "./tokens/typography-cjk.css";
13
+ @import "./tokens/spacing.css";
14
+ @import "./tokens/elevation.css";
15
+ @import "./tokens/motion.css";
16
+ @import "./tokens/compat.css";
17
+ @import "./fonts.css";
package/src/theme.css ADDED
@@ -0,0 +1,132 @@
1
+ /* @cosxai/ui — Tailwind v4 theme for the COSX Design System 3.0.
2
+ *
3
+ * @import "tailwindcss";
4
+ * @import "@cosxai/ui/theme.css";
5
+ * @import "@cosxai/ui/styles.css";
6
+ * @source "../node_modules/@cosxai/ui/src"; (so the kit's classes are generated)
7
+ *
8
+ * Utilities point at the 3.0 variables ("inline"), so ink mode —
9
+ * data-mode="ink" / .ink-mode — switches them with no dark: variants.
10
+ *
11
+ * Tailwind's own palette, radii, shadows, fonts and easings are cleared:
12
+ * only what the design system defines exists (no bg-blue-500, no
13
+ * shadow-lg — 3.0 has no shadows).
14
+ *
15
+ * Names never collide with a 3.0 variable unless the value is the same
16
+ * (theme.test.ts). In particular font sizes avoid --text-primary /
17
+ * --text-secondary / --text-label, which are colours in 3.0.
18
+ */
19
+ @theme inline {
20
+ --color-*: initial;
21
+ --radius-*: initial;
22
+ --shadow-*: initial;
23
+ --inset-shadow-*: initial;
24
+ --drop-shadow-*: initial;
25
+ --font-*: initial;
26
+ --ease-*: initial;
27
+ --text-*: initial;
28
+ --font-weight-*: initial;
29
+ --tracking-*: initial;
30
+
31
+ /* Materials — fixed, do not switch with ink mode */
32
+ --color-paper: var(--paper);
33
+ --color-linen: var(--linen);
34
+ --color-sunk-2: var(--sunk-2);
35
+ --color-sunk-3: var(--sunk-3);
36
+ --color-ink: var(--ink);
37
+ --color-ink-raised: var(--ink-raised);
38
+ --color-grey: var(--grey);
39
+ --color-grey-inverse: var(--grey-inverse);
40
+
41
+ /* The yellow — one hue, by area */
42
+ --color-yellow: var(--yellow);
43
+ --color-yellow-accent: var(--yellow-accent);
44
+ --color-yellow-accent-hover: var(--yellow-accent-hover);
45
+ --color-yellow-light: var(--yellow-light);
46
+ --color-yellow-hover: var(--yellow-hover);
47
+ --color-yellow-1: var(--yellow-1);
48
+ --color-yellow-2: var(--yellow-2);
49
+ --color-yellow-3: var(--yellow-3);
50
+ --color-yellow-4: var(--yellow-4);
51
+ --color-yellow-5: var(--yellow-5);
52
+ --color-yellow-wash-12: var(--yellow-12);
53
+ --color-yellow-wash-20: var(--yellow-20);
54
+ --color-yellow-wash-32: var(--yellow-32);
55
+ --color-yellow-wash-50: var(--yellow-50);
56
+ --color-marker: var(--marker);
57
+
58
+ /* Semantic — switch with ink mode. Product code uses these. */
59
+ --color-page: var(--bg-page);
60
+ --color-sunk: var(--bg-sunk);
61
+ --color-well: var(--bg-well);
62
+ --color-chrome: var(--bg-chrome);
63
+ --color-field: var(--bg-field);
64
+ --color-fg: var(--text-primary);
65
+ --color-fg-secondary: var(--text-secondary);
66
+ --color-fg-label: var(--text-label);
67
+ --color-fg-on-yellow-secondary: var(--text-on-yellow-secondary);
68
+ --color-rule: var(--rule);
69
+ --color-rule-soft: var(--rule-soft);
70
+ --color-hover: var(--hover);
71
+ --color-scrim: var(--scrim);
72
+
73
+ /* On an ink surface inside a paper page */
74
+ --color-inv: var(--inv-bg);
75
+ --color-inv-raised: var(--inv-bg-raised);
76
+ --color-inv-fg: var(--inv-text);
77
+ --color-inv-fg-secondary: var(--inv-text-secondary);
78
+ --color-inv-rule: var(--inv-rule);
79
+
80
+ /* Product status: yellow, ink and one red. Progress is an ink outline and
81
+ complete a grey dot — they take no colour of their own. */
82
+ --color-attention: var(--status-attention);
83
+ --color-attention-wash: var(--status-attention-wash);
84
+ --color-error: var(--status-error);
85
+ --color-error-text: var(--status-error-text);
86
+ --color-error-wash: var(--status-error-wash);
87
+
88
+ --color-transparent: transparent;
89
+ --color-current: currentColor;
90
+ --color-white: #fff;
91
+
92
+ /* Radius ladder — same names and values as 3.0 spacing.css */
93
+ --radius-xs: 4px;
94
+ --radius-sm: 6px;
95
+ --radius-md: 8px;
96
+ --radius-lg: 16px;
97
+ --radius-xl: 24px;
98
+ --radius-pill: 999px;
99
+
100
+ /* One family. Same stacks as fonts.css (the ones in effect): font-sans
101
+ for Latin, font-sans-cjk for Chinese pages (Geist for Latin and
102
+ figures, Noto Sans SC for hanzi). */
103
+ --font-sans: "Geist Variable", "Geist", "Helvetica Neue", Helvetica, Arial, sans-serif;
104
+ --font-sans-cjk: "Geist Variable", "Geist", "Noto Sans SC Variable", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
105
+
106
+ --font-weight-normal: 400;
107
+ --font-weight-medium: 500;
108
+ --font-weight-semibold: 600;
109
+ --font-weight-bold: 700;
110
+
111
+ /* Type scale (typography.css). Product UI body is 14px, content 15px. */
112
+ --text-meta: 12px;
113
+ --text-small: 13.5px;
114
+ --text-ui: 14px;
115
+ --text-body: 15px;
116
+ --text-h3: 18px;
117
+ --text-lede: 20px;
118
+ --text-title: 22px;
119
+ --text-figure: 32px;
120
+ --text-h2: var(--size-h2);
121
+ --text-h1: var(--size-h1);
122
+ --text-display: var(--size-display);
123
+
124
+ --tracking-display: -0.025em;
125
+ --tracking-heading: -0.015em;
126
+ --tracking-figure: -0.03em;
127
+
128
+ /* Motion — flat for state, ease-out for entry; nothing bounces */
129
+ --ease-standard: cubic-bezier(.2,0,.2,1);
130
+ --ease-out: cubic-bezier(.16,1,.3,1);
131
+ --ease-in: cubic-bezier(.4,0,1,1);
132
+ }
@@ -0,0 +1,112 @@
1
+ /* COSX 3.0 — colour. Warm white is the page, ink is every letter, yellow is the only
2
+ thing that is neither. Every value has one job. */
3
+ :root {
4
+ /* Light end */
5
+ --paper: #FEFDFB; /* the page. Ink 18.57:1 */
6
+ --linen: #F5F2EC; /* sunk 1 — sidebars, table heads, inputs */
7
+ --sunk-2: #ECE9E3; /* wells, disabled fields */
8
+ --sunk-3: #E3E0DA; /* deepest chrome */
9
+
10
+ /* Dark end */
11
+ --ink: #111111; /* all type. The dark ground. */
12
+ --ink-raised: #1B1B1B; /* raised surface on the ink ground */
13
+
14
+ /* Two greys, one per end — never interchangeable */
15
+ --grey: #696969; /* secondary text on paper. 5.40:1 */
16
+ --grey-inverse: #9E9E9E; /* secondary text on ink. 7.05:1 */
17
+
18
+ /* Structure — ink at low alpha adopts whichever paper it sits on */
19
+ --rule: rgba(17,17,17,.10);
20
+ --rule-soft: rgba(17,17,17,.06);
21
+ --rule-inverse: rgba(245,242,236,.18);
22
+ --rule-soft-inverse: rgba(245,242,236,.09);
23
+ --hover: #F7F6F4; /* ink 3% over paper. Hover goes darker. */
24
+ --scrim: rgba(17,17,17,.40);
25
+
26
+ /* The yellow. One material: a warm paper, OKLCH L .92 C .09 h 85. Every variant changes
27
+ lightness only, never chroma, so all of them read as the same sheet at different depths.
28
+ Grounds, selected tabs, panels on ink. It never writes a letter on paper. Contrast is ink's job.
29
+ On INK the area rule flips: headline type, marker blocks and buttons are small against the dark
30
+ ground and take the accent; the field there reads as cream. */
31
+ --yellow: #FFE3A0; /* ink on it 15:1 — large areas */
32
+ --yellow-accent: #FFD166; /* same hue, more chroma, for SMALL areas only: marker, chart blocks, dots,
33
+ and everything yellow on ink (headline, marker block, button). Small areas need more chroma to read as the same
34
+ colour as a large field; at field size it would shout. Ink on it 13:1 */
35
+ --yellow-accent-hover: #F5C455;
36
+ --yellow-light: #FFF1D6; /* row washes, the pale end of a ladder */
37
+ --yellow-hover: #F7D98F; /* hover on a yellow fill — same chroma, one step down */
38
+ --yellow-field: var(--yellow); /* alias */
39
+ --yellow-mark: var(--yellow-accent); /* alias */
40
+ --yellow-deep: var(--yellow-hover); /* retired */
41
+ --amber: var(--yellow-accent); /* retired */
42
+
43
+ /* Marker — the highlighter stroke behind a headline phrase. Small area: accent. */
44
+ --marker: var(--yellow-accent);
45
+
46
+ /* Wash ladder over paper — rows and areas. Lightness steps toward the yellow. */
47
+ --yellow-12: #FFFAF0;
48
+ --yellow-20: #FFF6E3;
49
+ --yellow-32: #FFF1D6;
50
+ --yellow-50: #FFEBC2;
51
+
52
+ /* Intensity ladder — treemaps, single-hue series. Light = less; the accent = most.
53
+ Step 4 is the yellow itself. Monotonic in luminance. */
54
+ --yellow-1: #FFF8EA;
55
+ --yellow-2: #FFF3DC;
56
+ --yellow-3: #FFEECE;
57
+ --yellow-4: #FFE3A0;
58
+ --yellow-5: #FFD166;
59
+ --yellow-6: #F5C455; /* hover only */
60
+ --yellow-7: #EAB84A; /* pressed only */
61
+ --series-hairline: rgba(17,17,17,.12); /* pale blocks take this so they hold on paper */
62
+
63
+ /* Product status — PRODUCT UI ONLY. Never on brand, marketing or deck surfaces. */
64
+ --status-error: #E0362F; /* white on it 4.6 · ink on wash */
65
+ --status-error-text: #C4261F; /* 5.9 on paper */
66
+ --status-error-wash: #FDE4E2;
67
+ --status-attention: var(--yellow-accent); /* ink on it 13:1 · never as type on paper */
68
+ --status-attention-wash: var(--yellow-32);
69
+ --status-progress: #2A7DE1; /* white on it 4.5 */
70
+ --status-progress-text: #1F63B8; /* 5.8 on paper */
71
+ --status-progress-wash: #DCEAFB;
72
+ --status-complete: #17A96A; /* ink on it 6.3 */
73
+ --status-complete-text: #0E7A4A; /* 5.5 on paper */
74
+ --status-complete-wash: #D6F3E5;
75
+
76
+ /* Semantic aliases — product code consumes these */
77
+ --bg-page: var(--paper);
78
+ --bg-sunk: var(--linen);
79
+ --bg-well: var(--sunk-2);
80
+ --bg-chrome: var(--sunk-3);
81
+ --text-primary: var(--ink);
82
+ --text-secondary: var(--grey);
83
+ --text-label: var(--grey);
84
+ --highlight: var(--yellow);
85
+ --bg-field: var(--yellow-field);
86
+ --focus-ring: 0 0 0 3px var(--bg-page), 0 0 0 5px var(--ink);
87
+ --text-on-yellow-secondary: rgba(17,17,17,.7); /* secondary text on the yellow; --grey fails there */
88
+ --disabled-opacity: 0.4; /* @kind other */
89
+
90
+ /* Inverted-surface aliases, for a component placed on ink inside a paper page */
91
+ --inv-bg: var(--ink);
92
+ --inv-bg-raised: var(--ink-raised);
93
+ --inv-text: var(--linen);
94
+ --inv-text-secondary: var(--grey-inverse);
95
+ --inv-rule: var(--rule-inverse);
96
+ }
97
+
98
+ /* Ink mode. The dark page. Yellow carries the headline here. */
99
+ :root[data-mode="ink"],
100
+ .ink-mode {
101
+ --bg-page: var(--ink);
102
+ --bg-sunk: var(--ink-raised);
103
+ --bg-well: #232221;
104
+ --bg-chrome: #2B2A28;
105
+ --text-primary: var(--linen);
106
+ --text-secondary: var(--grey-inverse);
107
+ --text-label: var(--grey-inverse);
108
+ --rule: var(--rule-inverse);
109
+ --rule-soft: var(--rule-soft-inverse);
110
+ --hover: #1F1E1D;
111
+ --focus-ring: 0 0 0 3px var(--ink), 0 0 0 5px var(--yellow);
112
+ }
@@ -0,0 +1,36 @@
1
+ /* COSX 3.0 — older token names mapped onto current values. Do not use in new work. */
2
+ :root {
3
+ --stone: var(--grey);
4
+ --brass: var(--grey);
5
+ --white: var(--paper);
6
+ --brass-30: var(--rule);
7
+ --brass-20: var(--rule);
8
+ --brass-12: var(--rule-soft);
9
+ --brass-07: var(--rule-soft);
10
+ --ink-08: rgba(17,17,17,.08);
11
+ --ink-04: rgba(17,17,17,.04);
12
+ --marigold: var(--yellow);
13
+ --marigold-hover: var(--yellow-deep);
14
+ --marigold-press: var(--yellow-7);
15
+ --marigold-tint: var(--yellow-12);
16
+ --ink-hover: #2A2825;
17
+ --ink-press: #000000;
18
+ --status-ok: var(--status-complete);
19
+ --status-warn: var(--status-attention);
20
+ --status-info: var(--status-progress);
21
+ --status-ok-tint: var(--status-complete-wash);
22
+ --status-error-tint: var(--status-error-wash);
23
+ --surface-card: var(--paper);
24
+ --hairline: var(--rule);
25
+ --hairline-soft: var(--rule-soft);
26
+ --grid-line: var(--rule-soft);
27
+ --grid-line-inv: var(--rule-soft-inverse);
28
+ --accent: var(--yellow);
29
+ --inv-text-strong: var(--paper);
30
+ --inv-structure: var(--grey-inverse);
31
+ --inv-hairline: var(--rule-inverse);
32
+ /* amber-era names from the 3.0 draft */
33
+ --amber-12: var(--yellow-12); --amber-20: var(--yellow-20); --amber-32: var(--yellow-32); --amber-50: var(--yellow-50);
34
+ --amber-critical: var(--yellow-7); --amber-high: var(--yellow-6); --amber-medium: var(--yellow-5); --amber-low: var(--yellow-3); --amber-clear: var(--yellow-1);
35
+ --series-1: var(--yellow-1); --series-2: var(--yellow-2); --series-3: var(--yellow-3); --series-4: var(--yellow-4); --series-5: var(--yellow-5); --series-6: var(--yellow-6);
36
+ }
@@ -0,0 +1,14 @@
1
+ /* COSX 3.0 — elevation. There are no shadows. Depth is cut into the page, so this
2
+ scale runs downward only. An overlay is lifted by the scrim behind it. */
3
+ :root {
4
+ --elev-page: var(--bg-page);
5
+ --elev-sunk-1: var(--bg-sunk);
6
+ --elev-sunk-2: var(--bg-well);
7
+ --elev-sunk-3: var(--bg-chrome);
8
+ --shadow-none: none;
9
+ /* v2 shadow tokens resolve to nothing — kept so old surfaces do not break */
10
+ --shadow-card: none;
11
+ --shadow-raised: none;
12
+ --shadow-overlay: none;
13
+ --shadow-hairline: inset 0 0 0 1px var(--rule);
14
+ }
@@ -0,0 +1,42 @@
1
+ /* COSX 3.0 — motion. "Paper settling." Two registers:
2
+ state quick and flat — colour, border, opacity on hover/focus/toggle. 120–320ms.
3
+ entry one choreographed settle when a surface appears — blocks rise a few px, the marker
4
+ draws, figures count, the pill glides. Each element ≤ 640ms; a whole sequence ≤ 1.4s
5
+ with a 70ms stagger. Ease-out only: things arrive and stop, they never bounce. */
6
+ :root {
7
+ --motion-colour: 120ms; /* @kind other */
8
+ --motion-fade: 180ms; /* @kind other */
9
+ --motion-max: 320ms; /* @kind other */
10
+ --motion-reveal: 640ms; /* @kind other */ /* entry: rise, draw, glide */
11
+ --motion-count: 1400ms; /* @kind other */ /* figures counting up */
12
+ --motion-stagger: 70ms; /* @kind other */
13
+ --easing: cubic-bezier(.2,0,.2,1); /* @kind other */
14
+ --easing-out: cubic-bezier(.16,1,.3,1); /* @kind other */
15
+ --rise-distance: 10px;
16
+ /* v2 aliases */
17
+ --dur-fast: var(--motion-colour); /* @kind other */
18
+ --dur-base: var(--motion-fade); /* @kind other */
19
+ --dur-slow: var(--motion-max); /* @kind other */
20
+ --ease-standard: var(--easing); /* @kind other */
21
+ --ease-out: var(--easing-out); /* @kind other */
22
+ --ease-in: cubic-bezier(.4,0,1,1); /* @kind other */
23
+ --press-inset: none;
24
+ }
25
+ /* Entry vocabulary */
26
+ @keyframes cosx-rise { from { opacity: 0; transform: translateY(var(--rise-distance)); } to { opacity: 1; transform: none; } }
27
+ @keyframes cosx-draw { from { background-size: 0% 100%; } to { background-size: 100% 100%; } }
28
+ @keyframes cosx-settle { from { opacity: 0; transform: scale(.92); } to { opacity: 1; transform: none; } }
29
+ @keyframes cosx-grow { from { transform: scaleY(0); } to { transform: none; } }
30
+ @keyframes cosx-wipe { from { clip-path: inset(0 100% 0 0 round 8px); } to { clip-path: inset(0 0 0 0 round 8px); } }
31
+ .rise { animation: cosx-rise var(--motion-reveal) var(--easing-out) both; }
32
+ .marker.draw { background-repeat: no-repeat; animation: cosx-draw var(--motion-reveal) var(--easing-out) .35s both; }
33
+ .settle { animation: cosx-settle var(--motion-reveal) var(--easing-out) both; } /* chart blocks, tiles — staggered */
34
+ .grow { transform-origin: bottom; animation: cosx-grow var(--motion-reveal) var(--easing-out) both; } /* columns */
35
+ .wipe { animation: cosx-wipe var(--motion-reveal) var(--easing-out) both; } /* yellow field or strip revealing left→right */
36
+ /* Stagger helper: set --i on each child */
37
+ .rise, .settle, .grow, .wipe { animation-delay: calc(var(--i, 0) * var(--motion-stagger) + var(--delay, 0ms)); }
38
+ /* Glide: the selected pill / active indicator moves, it does not blink */
39
+ .glide { transition: transform var(--motion-reveal) var(--easing-out), width var(--motion-reveal) var(--easing-out), left var(--motion-reveal) var(--easing-out); }
40
+ @media (prefers-reduced-motion: reduce) {
41
+ :root { --motion-colour: 0ms; /* @kind other */ --motion-fade: 0ms; /* @kind other */ --motion-max: 0ms; /* @kind other */ --motion-reveal: 0ms; /* @kind other */ --motion-count: 0ms; /* @kind other */ --motion-stagger: 0ms; /* @kind other */ }
42
+ }
@@ -0,0 +1,55 @@
1
+ /* COSX 3.0 — spacing, shape, rules. Rounded, not square: 8px is the system radius. */
2
+ :root {
3
+ --space-1: 4px;
4
+ --space-2: 8px;
5
+ --space-3: 12px;
6
+ --space-4: 16px;
7
+ --space-5: 22px;
8
+ --space-6: 32px;
9
+ --space-7: 48px;
10
+ --space-8: 72px;
11
+
12
+ /* Shape */
13
+ --radius-0: 0;
14
+ --radius-xs: 4px; /* checkboxes, tiny chips */
15
+ --radius-sm: 6px; /* tags, badges */
16
+ --radius-md: 8px; /* buttons, inputs, chart blocks */
17
+ --radius-lg: 16px; /* panels, dialogs, cards, social blocks */
18
+ --radius-xl: 24px; /* whole sections and page-level fields */
19
+ --radius-pill: 999px; /* dots, switch tracks */
20
+
21
+ /* Rules come in three widths */
22
+ --rule-hair: 1px;
23
+ --rule-accent: 4px; /* yellow underline under the wordmark or an eyebrow; status left-rule */
24
+ --rule-band: 8px;
25
+
26
+ --border-hairline: 1px solid var(--rule);
27
+ --border-soft: 1px solid var(--rule-soft);
28
+ --border-ink: 1px solid var(--ink);
29
+
30
+ /* Layout */
31
+ --grid-cols: 12; /* @kind other */
32
+ --grid-gutter: 24px;
33
+ --grid-max: 1180px;
34
+
35
+ /* Social artboard 1080x1350 */
36
+ --social-w: 1080px;
37
+ --social-h: 1350px;
38
+ --social-margin: 72px;
39
+
40
+ /* Deck grid, at the 1280x720 artboard */
41
+ --deck-w: 1280px;
42
+ --deck-h: 720px;
43
+ --deck-margin: 72px;
44
+ --deck-content: 1136px;
45
+ --deck-y-eyebrow: 44px;
46
+ --deck-y-heading: 96px;
47
+ --deck-y-body: 200px;
48
+ --deck-y-footrule: 648px;
49
+
50
+ /* v2 aliases */
51
+ --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 22px; --s-6: 32px; --s-7: 48px; --s-8: 72px; --s-9: 96px; --s-10: 128px;
52
+ --pad-card: 32px;
53
+ --pad-compact: 16px 20px;
54
+ --r-none: 0px; --r-sm: 6px; --r-md: 8px; --r-pill: 999px;
55
+ }
@@ -0,0 +1,42 @@
1
+ /* COSX 3.0 — Chinese typography (Noto Sans SC). Everything hangs off :lang(zh): mark a page or an element
2
+ lang="zh" (or zh-CN / zh-Hans) and the face, leading, tracking and marker switch over.
3
+ Latin, digits and ASCII punctuation stay in Geist; hanzi fall through to Noto Sans SC. */
4
+ :root {
5
+ --font-cjk: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
6
+ --font-sans-cjk: "Geist", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
7
+ --fw-cjk-body: 400; /* @kind font */
8
+ --fw-cjk-heading: 500; /* @kind font */
9
+ --size-body-cjk: 16px; /* Latin body 15 + 1 */
10
+ --size-small-cjk: 14px;
11
+ --size-label-cjk: 12px; /* same as Latin: sentence-style, untracked */
12
+ --leading-body-cjk: 1.8; /* @kind font */
13
+ --leading-heading-cjk: 1.3; /* @kind font */
14
+ --leading-display-cjk: 1.2; /* @kind font */
15
+ --track-cjk: 0; /* @kind font */ /* never the Latin's negative tracking */
16
+ --measure-cjk: 36em; /* ≈ 30–38 hanzi per line */
17
+ --marker-start-cjk: 50%; /* hanzi fill the em box; the band starts lower than Latin's 40% */
18
+ --bilingual-secondary: .72em; /* English line under a Chinese lead */
19
+ }
20
+ :lang(zh) {
21
+ font-family: var(--font-sans-cjk);
22
+ letter-spacing: var(--track-cjk);
23
+ line-height: var(--leading-body-cjk);
24
+ text-autospace: normal; /* quarter-space between hanzi and Latin/digits */
25
+ text-spacing-trim: normal; /* trims doubled full-width punctuation */
26
+ font-synthesis: none; /* no fake bold, no fake italic */
27
+ line-break: strict;
28
+ word-break: normal;
29
+ }
30
+ :lang(zh) h1, :lang(zh) h2, :lang(zh) h3, :lang(zh) .cjk-heading {
31
+ letter-spacing: var(--track-cjk);
32
+ line-height: var(--leading-heading-cjk);
33
+ font-weight: var(--fw-cjk-heading);
34
+ }
35
+ :lang(zh) em, :lang(zh) i { font-style: normal; font-weight: var(--fw-cjk-heading); }
36
+ :lang(zh) b, :lang(zh) strong { font-weight: var(--fw-cjk-heading); }
37
+ :lang(zh) .tabular, :lang(zh) .figure { letter-spacing: 0; font-variant-numeric: tabular-nums; }
38
+ :lang(zh) .marker {
39
+ background: linear-gradient(transparent var(--marker-start-cjk), var(--marker) var(--marker-start-cjk), var(--marker) 96%, transparent 96%);
40
+ }
41
+ :lang(zh) .ink-mode .marker, .ink-mode :lang(zh) .marker, :lang(zh) .marker.on-ink { background: none; }
42
+ .bilingual-en { display: block; font-family: var(--font-sans); font-size: var(--bilingual-secondary); line-height: 1.4; letter-spacing: 0; color: var(--text-secondary); margin-top: .35em; font-weight: 400; }