@cueplusplus/brand-tokens 0.13.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/BRAND.md ADDED
@@ -0,0 +1,133 @@
1
+ # CUE++ brand — seed
2
+
3
+ The CUE++ brand has never had a repository. It has a *de facto* home — the marketing site —
4
+ where the ramp, the type stack, the `//` motif and the marks have been consistent for long
5
+ enough to count as decisions. This package is those decisions, lifted out and named, so that
6
+ the next surface that needs them does not have to read someone else's Tailwind classes to
7
+ find out what the brand is.
8
+
9
+ It is a **seed**, in two senses:
10
+
11
+ - It is deliberately small. Colour, type, one ornament, three animations, four marks. No
12
+ components, no layout, no build step.
13
+ - It is meant to move. `cueplusplus/brand-design-system` exists and is empty; when it is
14
+ filled, this package is what it starts from. Until then it lives here because here is
15
+ where it gets used and tested.
16
+
17
+ ## What this is not
18
+
19
+ It is **not** the product theme. Product surfaces consume `@cueplusplus/tokens` and the `cue`
20
+ preset, which is this brand *translated* into the semantic contract — most visibly, the
21
+ product ramp starts at `#0a0a0a` rather than the marketing brand's pure `#000`, because a
22
+ console UI needs elevation and pure black has nowhere to go. Where the two disagree, the
23
+ theme wins for product and this package wins for brand. There is no build coupling between
24
+ them, on purpose: the `cue` theme's token files carry a comment pointing here, and that is the
25
+ whole relationship.
26
+
27
+ Importing `brand.css` paints nothing. Every rule is either a custom property on `:root` or a
28
+ `.brand-*` utility you have to ask for. The one exception is the reduced-motion clamp, which
29
+ is global and meant to be.
30
+
31
+ ## Provenance
32
+
33
+ Read out of `cue++/site` at commit `79b5bf8` on **2026-08-18**, read-only. Nothing in this
34
+ package is generated from that repository at build time; it was transcribed once, and these
35
+ are the paths to re-read if it needs re-transcribing.
36
+
37
+ | What | Source |
38
+ | --- | --- |
39
+ | White-alpha ramp | `src/**/*.tsx` — a census of every `white/<n>` Tailwind class (~19 distinct alphas, ~700 uses) plus the literal `rgba(255,255,255,…)` in `src/app/globals.css` |
40
+ | Brand black / white | `src/app/globals.css` — `body { background-color: #000; color: #fff }` |
41
+ | JetBrains Mono stack | `src/app/layout.tsx` (`next/font/google`, `--font-mono`) + `tailwind.config.ts` (both `sans` and `mono` point at it) |
42
+ | Eyebrow treatment | `src/app/page.tsx:112`, `src/app/products/page.tsx:74`, `src/app/faq/page.tsx:22`, `src/components/services-approach.tsx:91` and ~20 more — all `text-[10px] uppercase tracking-[0.3em] text-violet-400` prefixed with a literal `// ` |
43
+ | Motion keyframes | `src/app/globals.css` — `@keyframes float / slide-up / nudge-x`; the `float` timing from its one call site, `src/app/page.tsx:94` |
44
+ | Reduced-motion clamp | `src/app/globals.css`, the `@media (prefers-reduced-motion: reduce)` block |
45
+ | Scrollbar + selection | `src/app/globals.css`, the `::-webkit-scrollbar*` and `::selection` rules |
46
+ | Wordmark (light/dark) | `external-assets/CUE++ VIsualPack/{cue++,dark cue++}.svg` — the light one is byte-identical to `public/logo.svg` |
47
+ | Plussie (light/dark) | `external-assets/CUE++ VIsualPack/{plussie,dark plussie}.svg` |
48
+ | Voice | `docs/brand-voice.md` — **not** copied here; it is prose, it is maintained there, and it is the authority on how CUE++ writes about itself. Read it before writing brand copy. |
49
+
50
+ ### What was regularised on the way in
51
+
52
+ Transcription is not photocopying, and three things changed. They are listed here so the next
53
+ person can disagree with them on the evidence.
54
+
55
+ 1. **The ramp was snapped to a grid.** The site reaches for 19 distinct white alphas, several
56
+ of them used once (`white/65`, `white/85`, `rgba(255,255,255,0.022)`). The package declares
57
+ 15 steps — 5-point increments to `a60`, then decades — which covers every alpha with more
58
+ than a handful of uses. The one-offs round to a neighbour.
59
+ 2. **Utility classes were namespaced, keyframes were not.** The site's `.animate-slide-up` and
60
+ `.scrollbar-hide` became `.brand-animate-slide-up` and `.brand-scrollbar-hide`, because a
61
+ published package that claims `.animate-*` will collide with somebody's Tailwind plugin.
62
+ The keyframe *names* stayed `float` / `slide-up` / `nudge-x`: an `animation` shorthand
63
+ quotes a keyframe name literally, so renaming them would change the token values that are
64
+ the point of shipping them.
65
+ 3. **The scrollbar and selection rules became opt-in.** The site styles the document
66
+ scrollbar and `::selection` globally, which is correct for a site and wrong for a package —
67
+ importing a stylesheet should not repaint an app's chrome. They are `.brand-scrollbar`,
68
+ `.brand-scrollbar-hide` and `.brand-selection` here. Apply them at the root of a brand
69
+ surface to get the site's behaviour back.
70
+
71
+ The site's fourth animation, `sparkle`, was left behind: it belongs to one component on one
72
+ page rather than to the brand.
73
+
74
+ ## The editorial accents
75
+
76
+ The site uses violet, sky, amber and emerald as *editorial* colour — section accents on
77
+ marketing pages. Only the eyebrow violet (`--brand-eyebrow-accent`, Tailwind `violet-400`
78
+ `#a78bfa`) is seeded, and it carries a standing rule from the design-system spec (§3):
79
+
80
+ > the site's violet/sky/amber/emerald are editorial accents and must NOT become semantic
81
+ > status colors.
82
+
83
+ If a brand surface needs more of that palette, add it here as `--brand-editorial-*`. Do not
84
+ add it to a theme.
85
+
86
+ ## Contents
87
+
88
+ ```
89
+ src/brand.css the tokens + the opt-in utilities
90
+ src/index.ts the token names, class names and asset specifiers, typed
91
+ assets/ cueplusplus-wordmark{,-dark}.svg · plussie{,-dark}.svg
92
+ ```
93
+
94
+ ### Reading the mark names
95
+
96
+ `-dark` names the **ink, not the ground** — the convention the source visual pack uses.
97
+
98
+ | File | Ink | Put it on |
99
+ | --- | --- | --- |
100
+ | `cueplusplus-wordmark.svg` | white | a dark ground |
101
+ | `cueplusplus-wordmark-dark.svg` | black | a light ground |
102
+ | `plussie.svg` | white disc, `#1E1E1E` glyph | a dark ground |
103
+ | `plussie-dark.svg` | black disc, white glyph | a light ground |
104
+
105
+ Both wordmarks are drawn on a `0 0 778 367` artboard, both Plussies on `0 0 367 367`. The
106
+ `#1E1E1E` glyph inside the light badge is the only non-monochrome value in the identity —
107
+ it stops the badge reading as a hole punched in the page — and it is exported as
108
+ `--brand-plussie-ink`.
109
+
110
+ ## Usage
111
+
112
+ ```css
113
+ @import "@cueplusplus/brand-tokens/brand.css";
114
+ ```
115
+
116
+ ```tsx
117
+ import { BRAND_ASSETS } from "@cueplusplus/brand-tokens";
118
+
119
+ <p className="brand-eyebrow">Work with us</p> {/* → // WORK WITH US */}
120
+ <img src={BRAND_ASSETS.wordmark} alt="CUE++" />
121
+ ```
122
+
123
+ ```css
124
+ .hairline { border: 1px solid var(--brand-white-a10); }
125
+ .caption { color: var(--brand-white-a40); font-family: var(--brand-font-mono); }
126
+ ```
127
+
128
+ ## When the brand repo happens
129
+
130
+ Move `src/`, `assets/` and this file across, keep the package name, and replace this package
131
+ with a dependency on the published one. The tests in `test/` move with it — they are the
132
+ transcription's proof, and they are worth more in the repo that owns the brand than in the one
133
+ that borrowed it.
package/CHANGELOG.md ADDED
@@ -0,0 +1,251 @@
1
+ # @cueplusplus/brand-tokens
2
+
3
+ ## 0.13.0
4
+
5
+ ### Patch Changes
6
+
7
+ - eb59eaf: **`@cueplusplus/brand-tokens` ships compiled JavaScript instead of TypeScript source.**
8
+
9
+ Its main export pointed at `./src/index.ts`. Inside this repository that was invisible — every
10
+ consumer reads it through TypeScript — but an installed package cannot assume that. Node refuses it
11
+ outright (`ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`: "Stripping types is currently unsupported
12
+ for files under node_modules"), and a bundler only handles it if you have opted this dependency into
13
+ transpilation — `transpilePackages` in Next.js, or equivalent. Anyone who had not was met with an
14
+ import error for a module that is nothing but string constants.
15
+
16
+ The entry is now `dist/index.mjs` with `dist/index.d.mts` beside it, built by tsdown the way every
17
+ other published package here is built. **Nothing about the module changed** — the same nine exports,
18
+ the same names, the same values; the types are unchanged because they are generated from the same
19
+ source.
20
+
21
+ `brand.css` and `assets/` are untouched and still ship verbatim: `@cueplusplus/brand-tokens/brand.css`
22
+ and `@cueplusplus/brand-tokens/assets/*` resolve exactly as before. The stylesheet remains the source
23
+ of truth, and this module remains its typed index.
24
+
25
+ If you were already importing this package successfully, nothing changes for you. If you were working
26
+ around it with a transpilation rule, you can drop the rule.
27
+
28
+ - b1c2f25: **Every package now ships the licence it declares.** All sixteen have said `"license": "MIT"` in
29
+ their manifest since they were first published, and none of them carried the text. Installing one
30
+ gave you a licence field and nothing to read; anyone auditing their dependency tree found a package
31
+ that claimed a licence it did not include. Each package root now holds the MIT notice, and npm packs
32
+ a root `LICENSE` whether or not `files` lists it, so it is in the tarball you install.
33
+
34
+ `@cueplusplus/ui` additionally ships `NOTICE.md`, the third-party notice for the assistant-ui code
35
+ vendored into its elements. That one is not automatic — `files` had to name it — and it is byte-for-byte
36
+ the notice that already sat beside the source it covers, because a notice that travels without the
37
+ bytes it describes is not a notice.
38
+
39
+ Nothing else about these packages changed: same exports, same versions of every dependency, same
40
+ registry. If you are upgrading only for this, the diff you receive is licence text.
41
+
42
+ ## 0.12.0
43
+
44
+ ## 0.11.1
45
+
46
+ ## 0.11.0
47
+
48
+ ## 0.10.0
49
+
50
+ ### Patch Changes
51
+
52
+ - 64b4bab: Every package manifest's `repository` field now names `cueplusplus/cue-ui`, following the
53
+ repository's rename from an earlier working title.
54
+
55
+ **Nothing to do.** No code, no exports, no types, and no package name: the scope is the
56
+ organisation, not the repository, so every specifier you already import is the one you keep
57
+ importing. What moves is metadata — GitHub Packages matches a package to a repository through that
58
+ field, so from this release the "source" link on each package's registry page, and the repository
59
+ the next publish is attributed to, name `cue-ui`. The `directory` beside it is unchanged, so each
60
+ link still lands on that package rather than on the monorepo root.
61
+
62
+ If you have a bookmark or a script pointing at the old URL, GitHub's rename redirect answers it;
63
+ updating it to `https://github.com/cueplusplus/cue-ui` is tidiness rather than repair.
64
+
65
+ ## 0.9.0
66
+
67
+ ### Patch Changes
68
+
69
+ - cf80a87: No published behaviour changes. These packages gain a `lint` script and its two
70
+ dev dependencies, because `pnpm lint` now runs ESLint over every package that
71
+ holds source rather than resolving to an empty task graph, and a package with no
72
+ script is a package the gate is silently green about.
73
+ - 5eb0da2: The ten colour presets leave `@cueplusplus/tokens` and become packages of their
74
+ own. `@cueplusplus/ui/styles.css` now ships the blank base instead of a palette,
75
+ so a theme is something you install, import and register — the same way a
76
+ third-party theme always should have been, and now is.
77
+
78
+ `@cueplusplus/tokens` keeps the two axes it actually owns: the five density
79
+ rungs and the eight font pairings, plus the contracts, `base.json` and the
80
+ primitives a theme source aliases. It emits `axes.css` and no colour at all.
81
+ Each preset is `@cueplusplus/theme-<name>` — `cue`, `dusk`, `hivehub`, `luma`,
82
+ `quotamate`, `requestport`, `signal`, `snuffle`, `terminal`, `venu` — carrying
83
+ the stylesheet it always carried, byte for byte: nothing about any shipped
84
+ palette moved, and a frozen snapshot of what `tokens@0.8.0` emitted is committed
85
+ so that stays checkable rather than merely asserted.
86
+
87
+ ## Migrating
88
+
89
+ **The unattributed default stops being `cue`.** An app that imports
90
+ `@cueplusplus/ui/styles.css` and registers nothing now paints the blank base.
91
+ Nothing errors and nothing falls back: a `data-theme` value is styled by
92
+ whichever stylesheet declares it, and with no theme package imported, none does.
93
+
94
+ Ten custom properties move in dark and seven in light. Measured on a root
95
+ stamped `data-theme="cue"`, which is what every `ThemeProvider` stamped before
96
+ this release and still stamps, so this is the delta for an app that changes
97
+ nothing:
98
+
99
+ | token | dark: `cue` → blank base | light: `cue` → blank base |
100
+ | ---------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------ |
101
+ | `--cue-accent` | `#ffffff` → `#8a93a6` | `#0a0a0a` → `#3f4759` |
102
+ | `--cue-accent-hover` | `rgba(255,255,255,0.85)` → `#9aa3b6` | `rgba(0,0,0,0.85)` → `#333a4a` |
103
+ | `--cue-accent-soft` | follows `--cue-accent`: it is a 14% `color-mix` of it | same |
104
+ | `--cue-focus` | `#ffffff` → `#8a93a6` | `#0a0a0a` → `#3f4759` |
105
+ | `--cue-font-theme-mono` | JetBrains Mono → nothing; the base declares no theme mono | same as dark |
106
+ | `--cue-font-mono` | resolves through the line above, so JetBrains Mono → the platform stack | same as dark |
107
+ | `--cue-fg` | `#f5f5f7` → `#f5f5f5` | unchanged |
108
+ | `--cue-hair`, `--cue-hair-strong`, `--cue-row-hover` | follow `--cue-fg`: each is a `color-mix` of it (6%, 12%, 3.5%) | unchanged |
109
+ | `--cue-accent-fg` | unchanged | `#fcfcfc` → `#ffffff` |
110
+
111
+ The last four rows are the ones an eye catches and a list of "the accent and the
112
+ focus ring" would not have mentioned: four of the ten dark changes and the one
113
+ light change are tokens no theme file names directly, because they are mixes of
114
+ two that do.
115
+
116
+ To get `cue` back, exactly as it was:
117
+
118
+ ```bash
119
+ pnpm add @cueplusplus/theme-cue
120
+ ```
121
+
122
+ ```css
123
+ @import "@cueplusplus/ui/styles.css";
124
+ @import "@cueplusplus/theme-cue/theme.css";
125
+ ```
126
+
127
+ ```tsx
128
+ import cue from "@cueplusplus/theme-cue";
129
+
130
+ <ThemeProvider themes={[cue]} theme="cue">
131
+ {children}
132
+ </ThemeProvider>;
133
+ ```
134
+
135
+ The import order is load-bearing: a `[data-theme]` block and the base's bare
136
+ `:root` tie at (0,1,0), so the one declared later wins. Importing the theme
137
+ before `styles.css` paints the blank base over it. Importing the package from
138
+ its root, rather than the `manifest.json` subpath, also closes `ThemeName` to
139
+ the themes you installed, so a misspelt `theme=` is a type error.
140
+
141
+ Then the rest:
142
+
143
+ - **`@cueplusplus/tokens/theme.css` is a deprecated alias** of `axes.css` for
144
+ one minor. It still resolves and still delivers the geometry and type axes, so
145
+ a stylesheet naming it keeps building — it simply carries no palette. Change
146
+ the line to `@cueplusplus/tokens/axes.css`, or drop it: `ui/styles.css` already
147
+ brings the axes in through `@cueplusplus/theme-base/base.css`.
148
+ - **Gone from `@cueplusplus/tokens`:** the `themes/*.css` and
149
+ `registry/theme-*.json` subpaths, and the `THEMES`, `ThemeName`,
150
+ `THEME_SUPPORTS_LIGHT` and `DEFAULT_THEME` exports. `ThemeName` now comes from
151
+ `@cueplusplus/theme-base` (re-exported by `@cueplusplus/ui`) and widens with
152
+ each theme package installed, rather than naming the ten that happened to be
153
+ compiled in; whether a theme ships a light block is `supportsLight` on its own
154
+ `manifest.json`; and there is no default palette to name, because the library
155
+ contains none.
156
+ - **`@cueplusplus/tokens`' root entry is now `dist/tokens.js`**, with
157
+ `dist/tokens.d.ts` beside it, where it used to be the TypeScript source
158
+ `dist/tokens.ts`. The import specifier, the exported names and their values
159
+ are unchanged — `import { DENSITIES } from "@cueplusplus/tokens"` is the same
160
+ line it was — but the file behind it is one Node can execute. It could not
161
+ before: Node refuses to strip types for anything under `node_modules`, so the
162
+ package worked in a workspace and failed from a registry install, taking
163
+ `@cueplusplus/theme-base` and the `cue-theme` CLI with it. If you added
164
+ `@cueplusplus/tokens` to your bundler's transpile list to work around that
165
+ (Next.js' `transpilePackages`, or the equivalent), take it out.
166
+ - **`@cueplusplus/tokens` gains `base.json`'s `fonts.handshake`**: the three
167
+ literals of the monospace resolution (`font-pairing-mono`, `font-theme-mono`,
168
+ and the `var()` that resolves them), published as data so a theme built
169
+ anywhere spells them the same way this build does.
170
+ - **`@cueplusplus/ui`'s `THEME_NAME_PATTERN` and `RESOLVED_MONO` are now
171
+ re-exports** of `@cueplusplus/theme-base`'s. Same names, same values, one
172
+ definition instead of three.
173
+ - **`/r/tokens.json`'s `themes` are objects**, not strings:
174
+ `{ name, package, supportsLight, densities }`. A consumer reading the registry
175
+ for a theme list wants to know which package delivers it.
176
+ - **Every published tarball now carries a `README.md`.** On a registry the
177
+ package page _is_ the README, and `tokens`, `ui` and `brand-tokens` shipped
178
+ without one; `packages/release/test/publishable-packages.test.mjs` holds all
179
+ fifteen to it now, beside the same check for `CHANGELOG.md`.
180
+ - **`@cueplusplus/ui` depends on `@cueplusplus/theme-base@^1`**, a range rather
181
+ than a pin, deliberately: two copies of `theme-base` in one tree would break
182
+ the type registry, because a theme's `declare module` augments one copy while
183
+ `ui`'s re-exported `ThemeName` resolves against the other, and neither errors.
184
+
185
+ ## 0.8.0
186
+
187
+ ## 0.7.0
188
+
189
+ ## 0.6.0
190
+
191
+ ## 0.5.0
192
+
193
+ ## 0.4.0
194
+
195
+ ## 0.3.0
196
+
197
+ ### Minor Changes
198
+
199
+ - 31e3607: Ship the linked RequestPort preset release across tokens, UI, and brand tokens.
200
+
201
+ The release adds the typed RequestPort preset and its generated dark, light, and
202
+ system selectors; system SSR, prepaint, provider, and portal behavior; the
203
+ `persistPreferences={false}` and authoritative prepaint options contracts; the
204
+ typed `fontFamilies` provider/portal override; the deterministic package
205
+ manifest and companion checksums; and the accessible `TableScrollRegion`.
206
+
207
+ All three linked tarballs receive the same minor version and changelog entry.
208
+ The Version Packages path regenerates the package manifest after applying those
209
+ versions and rejects stale or nondeterministic output before publication.
210
+
211
+ ## 0.2.0
212
+
213
+ ### Patch Changes
214
+
215
+ - 6ce0c7d: The release notes now ship inside the package.
216
+
217
+ `files` was `dist` alone, so the `CHANGELOG.md` this repository writes on every
218
+ release stayed in a private git repository and reached nobody: `npm pack` left it
219
+ out, and the tarball a consumer installs from GitHub Packages carried the code
220
+ with no record of what had changed in it. Anyone asking "what moved between the
221
+ version I have and the version I am upgrading to" had to have access to the
222
+ source repository to find out.
223
+
224
+ `CHANGELOG.md` is now on the `files` allowlist of all three published packages,
225
+ so it lands in `node_modules/@cueplusplus/<package>/CHANGELOG.md` beside the code
226
+ it describes. `packages/release` has the test that keeps it there.
227
+
228
+ No code changes and no API changes — the same `dist`, plus one file.
229
+
230
+ The same notes are published, alongside the CUE++ agent skills' own, at
231
+ <https://skills.cueplusplus.com/releases>.
232
+
233
+ ## 0.1.0
234
+
235
+ ### Minor Changes
236
+
237
+ - First release of the CUE++ design system.
238
+
239
+ `@cueplusplus/tokens` ships eight theme presets (`cue`, `terminal`, `signal`, `venu`, `hivehub`,
240
+ `dusk`, `luma`, `snuffle`) in dark and light, three density levels (`ultra-compact`, `normal`,
241
+ `large`), and the Tailwind v4 `@theme inline` mapping — colour scoped to `[data-theme]`, geometry to
242
+ `[data-density]`, never mixed.
243
+
244
+ `@cueplusplus/ui` ships 146 components on Base UI: the core entry plus the `/layout`, `/forms`,
245
+ `/overlays`, `/chrome`, `/instruments`, `/chat`, `/theming`, `/configurator`, `/color`, `/date`
246
+ subpaths and the four opt-in ones (`/charts`, `/dmx`, `/midi`, `/flow`) whose heavy dependencies stay
247
+ optional peers. `ThemeProvider`, the density islands, `createTheme()` with its contrast report and the
248
+ floating `ThemeConfigurator` come with it.
249
+
250
+ `@cueplusplus/brand-tokens` ships the CUE++ brand layer — the white-alpha ramp, the mono stack, the
251
+ eyebrow and motion treatments, and the wordmark and Plussie marks.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CUE++ contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # @cueplusplus/brand-tokens
2
+
3
+ The CUE++ brand itself, transcribed out of the marketing site and dated, for whoever is building a
4
+ CUE++-branded surface rather than a product screen: the white-alpha ramp, the monochrome ground,
5
+ the JetBrains Mono stack, the `//` eyebrow motif, the motion keyframes and the four brand marks.
6
+
7
+ This is **not** a product dependency and it is not a theme. `@cueplusplus/theme-cue` is the
8
+ product translation of this brand; this package is the brand as it was found, kept so that the
9
+ translation can be argued with. It is a seed for the (currently empty) brand repository.
10
+
11
+ ## Install
12
+
13
+ The `@cueplusplus` scope is served by **GitHub Packages**, not npmjs.com, and GitHub Packages
14
+ authenticates *every* install. That is two settings, in two places, and the split is not
15
+ cosmetic — pnpm ignores an env-expanded credential in a project `.npmrc` and the install fails
16
+ with `401`.
17
+
18
+ Commit the scope routing, and nothing else, at the root of your project:
19
+
20
+ ```ini
21
+ # .npmrc
22
+ @cueplusplus:registry=https://npm.pkg.github.com
23
+ ```
24
+
25
+ Then write the credential once, at the **user** level, where pnpm reads it from. It is a
26
+ **classic** personal access token with `read:packages` — GitHub Packages accepts neither
27
+ fine-grained PATs nor OIDC:
28
+
29
+ ```sh
30
+ pnpm config set //npm.pkg.github.com/:_authToken ghp_…
31
+ ```
32
+
33
+ ```sh
34
+ pnpm add @cueplusplus/brand-tokens
35
+ ```
36
+
37
+ No peers and no dependencies.
38
+
39
+ CI, Vercel and the token's expiry are in
40
+ [`docs/CONSUMING.md` §1](https://github.com/cueplusplus/cue-ui/blob/main/docs/CONSUMING.md#1-registry-access).
41
+
42
+ ## Quick start
43
+
44
+ The stylesheet is the source of truth and the only thing that emits CSS; the module gives you the
45
+ *names*. Import both — nothing here resolves without the sheet, and the sheet paints nothing by
46
+ itself until you use one of its custom properties or opt-in classes.
47
+
48
+ ```ts
49
+ import "@cueplusplus/brand-tokens/brand.css";
50
+ import { BRAND_ASSETS, BRAND_WHITE_ALPHA_RAMP } from "@cueplusplus/brand-tokens";
51
+
52
+ const hairline = `1px solid var(${BRAND_WHITE_ALPHA_RAMP[1]})`; // --brand-white-a10
53
+ const wordmark = BRAND_ASSETS.wordmark; // the white-ink mark, for a dark ground
54
+ ```
55
+
56
+ A repo test asserts both directions of that correspondence, so a token added to the sheet and
57
+ forgotten in the index — or the reverse — fails the build rather than a consumer's `var()`.
58
+
59
+ ## What it ships
60
+
61
+ | subpath | what it is |
62
+ | --- | --- |
63
+ | `@cueplusplus/brand-tokens` | the typed index: `BRAND_STYLESHEET`, `BRAND_WHITE_ALPHA_RAMP`, `BRAND_TOKENS`, `BRAND_CLASSES`, `BRAND_ASSETS`, and a type per set |
64
+ | `./brand.css` | the stylesheet: every `--brand-*` custom property, the keyframes, and seven opt-in utility classes |
65
+ | `./assets/*` | the four marks as SVG — `cueplusplus-wordmark.svg`, `cueplusplus-wordmark-dark.svg`, `plussie.svg`, `plussie-dark.svg` |
66
+
67
+ `BRAND_ASSETS` names each mark by its import specifier, so the four rows above are reachable by
68
+ key rather than by retyping a path. "Dark" names the **ink**, not the ground: the unsuffixed marks
69
+ are drawn for a dark ground, the `-dark` marks for a light one.
70
+
71
+ ## Where the rest is
72
+
73
+ - The reasoning, the provenance of every value and the date it was taken: [`BRAND.md`](./BRAND.md), which ships beside this file
74
+ - Installing and using it from another project: [`docs/CONSUMING.md`](https://github.com/cueplusplus/cue-ui/blob/main/docs/CONSUMING.md)
75
+ - The product translation of this brand: <https://ui.cueplusplus.com/docs/theming>
76
+ - What changed in the version you have: `node_modules/@cueplusplus/brand-tokens/CHANGELOG.md`
@@ -0,0 +1,6 @@
1
+ <svg width="778" height="367" viewBox="0 0 778 367" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M778 183.5C778 284.844 698.492 367 600.413 367C502.335 367 422.826 284.844 422.826 183.5C422.826 82.1558 502.335 0 600.413 0C698.492 0 778 82.1558 778 183.5ZM478.899 236.4V197.004H440.773V170.343H478.899V130.947H504.701V170.343H542.827V197.004H504.701V236.4H478.899ZM588.834 197.004V236.4H614.636V197.004H652.762V170.343H614.636V130.947H588.834V170.343H550.707V197.004H588.834Z" fill="black"/>
3
+ <path d="M136.396 160.524H103.981C103.389 156.289 102.18 152.529 100.354 149.241C98.5289 145.903 96.1853 143.064 93.3237 140.723C90.4621 138.382 87.1564 136.588 83.4067 135.343C79.7063 134.098 75.6852 133.475 71.3434 133.475C63.4986 133.475 56.6652 135.443 50.8433 139.378C45.0213 143.263 40.5069 148.942 37.2999 156.414C34.0929 163.836 32.4894 172.852 32.4894 183.463C32.4894 194.372 34.0929 203.537 37.2999 210.96C40.5562 218.382 45.0953 223.986 50.9173 227.772C56.7392 231.557 63.4739 233.45 71.1214 233.45C75.4138 233.45 79.3856 232.878 83.0366 231.732C86.737 230.586 90.018 228.917 92.8796 226.726C95.7413 224.484 98.1095 221.769 99.9844 218.581C101.909 215.393 103.241 211.757 103.981 207.672L136.396 207.821C135.557 214.845 133.461 221.62 130.106 228.145C126.8 234.621 122.335 240.424 116.71 245.555C111.135 250.636 104.474 254.671 96.7281 257.66C89.0312 260.599 80.323 262.068 70.6033 262.068C57.0846 262.068 44.9967 258.98 34.3396 252.803C23.7318 246.626 15.3443 237.685 9.17695 225.978C3.05898 214.272 0 200.1 0 183.463C0 166.775 3.10832 152.578 9.32497 140.872C15.5416 129.166 23.9785 120.25 34.6356 114.122C45.2927 107.946 57.2819 104.857 70.6033 104.857C79.3856 104.857 87.5264 106.103 95.0259 108.593C102.575 111.084 109.26 114.72 115.082 119.502C120.904 124.235 125.64 130.038 129.291 136.912C132.992 143.786 135.36 151.657 136.396 160.524Z" fill="black"/>
4
+ <path d="M249.036 106.949H281.081V206.327C281.081 217.485 278.441 227.249 273.162 235.617C267.932 243.986 260.605 250.511 251.182 255.194C241.758 259.827 230.78 262.143 218.248 262.143C205.667 262.143 194.665 259.827 185.241 255.194C175.817 250.511 168.491 243.986 163.261 235.617C158.031 227.249 155.416 217.485 155.416 206.327V106.949H187.461V203.562C187.461 209.391 188.719 214.571 191.236 219.104C193.801 223.637 197.403 227.199 202.041 229.789C206.679 232.379 212.081 233.675 218.248 233.675C224.465 233.675 229.868 232.379 234.456 229.789C239.094 227.199 242.671 223.637 245.187 219.104C247.753 214.571 249.036 209.391 249.036 203.562V106.949Z" fill="black"/>
5
+ <path d="M303.486 259.976V106.949H405.617V133.624H335.532V170.088H400.362V196.763H335.532V233.301H405.913V259.976H303.486Z" fill="black"/>
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg width="778" height="367" viewBox="0 0 778 367" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M778 183.5C778 284.844 698.492 367 600.413 367C502.335 367 422.826 284.844 422.826 183.5C422.826 82.1558 502.335 0 600.413 0C698.492 0 778 82.1558 778 183.5ZM478.899 236.4V197.004H440.773V170.343H478.899V130.947H504.701V170.343H542.828V197.004H504.701V236.4H478.899ZM588.834 197.004V236.4H614.636V197.004H652.762V170.343H614.636V130.947H588.834V170.343H550.707V197.004H588.834Z" fill="white"/>
3
+ <path d="M136.396 160.524H103.981C103.389 156.289 102.18 152.529 100.354 149.241C98.5289 145.903 96.1853 143.064 93.3237 140.723C90.4621 138.382 87.1564 136.588 83.4067 135.343C79.7063 134.098 75.6852 133.475 71.3434 133.475C63.4986 133.475 56.6652 135.443 50.8433 139.378C45.0213 143.263 40.5069 148.942 37.2999 156.414C34.0929 163.836 32.4894 172.852 32.4894 183.463C32.4894 194.372 34.0929 203.537 37.2999 210.96C40.5562 218.382 45.0953 223.986 50.9173 227.772C56.7392 231.557 63.4739 233.45 71.1214 233.45C75.4138 233.45 79.3856 232.877 83.0366 231.732C86.737 230.586 90.018 228.917 92.8796 226.726C95.7413 224.484 98.1095 221.769 99.9844 218.581C101.909 215.393 103.241 211.757 103.981 207.672L136.396 207.821C135.557 214.845 133.461 221.62 130.106 228.145C126.8 234.621 122.335 240.424 116.71 245.555C111.135 250.636 104.474 254.671 96.7281 257.66C89.0312 260.599 80.323 262.068 70.6033 262.068C57.0846 262.068 44.9967 258.98 34.3396 252.803C23.7318 246.626 15.3443 237.684 9.17695 225.978C3.05898 214.272 0 200.1 0 183.463C0 166.775 3.10832 152.578 9.32497 140.872C15.5416 129.166 23.9785 120.249 34.6356 114.122C45.2927 107.946 57.2819 104.857 70.6033 104.857C79.3856 104.857 87.5264 106.102 95.0259 108.593C102.575 111.084 109.26 114.72 115.082 119.502C120.904 124.235 125.64 130.038 129.291 136.912C132.992 143.786 135.36 151.657 136.396 160.524Z" fill="white"/>
4
+ <path d="M249.036 106.949H281.081V206.327C281.081 217.485 278.441 227.249 273.162 235.617C267.932 243.986 260.605 250.511 251.182 255.194C241.758 259.826 230.78 262.143 218.248 262.143C205.667 262.143 194.665 259.826 185.241 255.194C175.817 250.511 168.491 243.986 163.261 235.617C158.031 227.249 155.416 217.485 155.416 206.327V106.949H187.461V203.562C187.461 209.39 188.719 214.571 191.236 219.104C193.801 223.637 197.403 227.199 202.041 229.789C206.679 232.379 212.081 233.674 218.248 233.674C224.465 233.674 229.868 232.379 234.456 229.789C239.094 227.199 242.671 223.637 245.187 219.104C247.753 214.571 249.036 209.39 249.036 203.562V106.949Z" fill="white"/>
5
+ <path d="M303.486 259.976V106.949H405.617V133.624H335.532V170.088H400.362V196.763H335.532V233.301H405.913V259.976H303.486Z" fill="white"/>
6
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="367" height="367" viewBox="0 0 367 367" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <circle cx="183.5" cy="183.5" r="183.5" fill="black"/>
3
+ <path d="M57.9395 236.4V130.947H84.6006V236.4H57.9395ZM18.5436 197.004V170.343H123.997V197.004H18.5436Z" fill="white"/>
4
+ <path d="M171.535 236.4V130.947H198.196V236.4H171.535ZM132.139 197.004V170.343H237.592V197.004H132.139Z" fill="white"/>
5
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="367" height="367" viewBox="0 0 367 367" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <circle cx="183.5" cy="183.5" r="183.5" fill="white"/>
3
+ <path d="M57.9395 236.4V130.947H84.6006V236.4H57.9395ZM18.5436 197.004V170.343H123.997V197.004H18.5436Z" fill="#1E1E1E"/>
4
+ <path d="M171.535 236.4V130.947H198.196V236.4H171.535ZM132.139 197.004V170.343H237.592V197.004H132.139Z" fill="#1E1E1E"/>
5
+ </svg>
@@ -0,0 +1,80 @@
1
+ //#region src/index.d.ts
2
+ /**
3
+ * @cueplusplus/brand-tokens — the typed index of `brand.css`.
4
+ *
5
+ * The stylesheet is the source of truth; nothing here emits CSS. What this
6
+ * module gives a consumer is the *names*: the custom properties it can read
7
+ * with `var()` or `getComputedStyle`, and the import specifiers for the four
8
+ * brand marks. A repo test asserts both directions of the correspondence, so a
9
+ * token added to one file and forgotten in the other fails the build.
10
+ *
11
+ * ```ts
12
+ * import "@cueplusplus/brand-tokens/brand.css";
13
+ * import { BRAND_ASSETS, BRAND_WHITE_ALPHA_RAMP } from "@cueplusplus/brand-tokens";
14
+ * ```
15
+ */
16
+ /** The stylesheet a consumer must import for any of these names to resolve. */
17
+ declare const BRAND_STYLESHEET = "@cueplusplus/brand-tokens/brand.css";
18
+ /**
19
+ * The white-alpha ink ladder, darkest to brightest.
20
+ *
21
+ * White at an opacity over the brand's black ground — the brand has no greys.
22
+ * `a10` is the hairline border, `a40` the default secondary ink, `a90` the
23
+ * brightest step short of pure white.
24
+ */
25
+ declare const BRAND_WHITE_ALPHA_RAMP: readonly ["--brand-white-a05", "--brand-white-a10", "--brand-white-a15", "--brand-white-a20", "--brand-white-a25", "--brand-white-a30", "--brand-white-a35", "--brand-white-a40", "--brand-white-a45", "--brand-white-a50", "--brand-white-a55", "--brand-white-a60", "--brand-white-a70", "--brand-white-a80", "--brand-white-a90"];
26
+ /** One step of the white-alpha ramp. */
27
+ type BrandWhiteAlpha = (typeof BRAND_WHITE_ALPHA_RAMP)[number];
28
+ /**
29
+ * Every custom property `brand.css` declares, grouped the way the sheet is.
30
+ *
31
+ * Grouped rather than flat because the groups are the contract: a brand surface
32
+ * takes the ramp wholesale, but picks one eyebrow treatment and one motion
33
+ * shorthand.
34
+ */
35
+ declare const BRAND_TOKENS: {
36
+ /** Pure monochrome. The near-black product ramp belongs to the `cue` theme. */
37
+ readonly ground: readonly ["--brand-black", "--brand-white"];
38
+ /** The ink ladder — see {@link BRAND_WHITE_ALPHA_RAMP}. */
39
+ readonly whiteAlpha: readonly ["--brand-white-a05", "--brand-white-a10", "--brand-white-a15", "--brand-white-a20", "--brand-white-a25", "--brand-white-a30", "--brand-white-a35", "--brand-white-a40", "--brand-white-a45", "--brand-white-a50", "--brand-white-a55", "--brand-white-a60", "--brand-white-a70", "--brand-white-a80", "--brand-white-a90"];
40
+ /** One voice: `--brand-font-sans` is an alias of the mono stack, not a second face. */
41
+ readonly type: readonly ["--brand-font-mono", "--brand-font-sans"];
42
+ /** The `// SECTION` micro-label. The accent is editorial and never a status colour. */
43
+ readonly eyebrow: readonly ["--brand-eyebrow-size", "--brand-eyebrow-tracking", "--brand-eyebrow-transform", "--brand-eyebrow-prefix", "--brand-eyebrow-accent"];
44
+ /** `animation` shorthands for the `float` / `slide-up` / `nudge-x` keyframes. */
45
+ readonly motion: readonly ["--brand-motion-float", "--brand-motion-slide-up", "--brand-motion-nudge-x"];
46
+ /** Consumed by `.brand-scrollbar`; usable directly on a custom rail. */
47
+ readonly scrollbar: readonly ["--brand-scrollbar-size", "--brand-scrollbar-radius", "--brand-scrollbar-track", "--brand-scrollbar-thumb", "--brand-scrollbar-thumb-hover"];
48
+ /** Consumed by `.brand-selection`. */
49
+ readonly selection: readonly ["--brand-selection-bg", "--brand-selection-fg"];
50
+ /** Values that belong to the marks themselves rather than to a surface. */
51
+ readonly marks: readonly ["--brand-plussie-ink"];
52
+ };
53
+ /** Any custom property this package declares. */
54
+ type BrandToken = (typeof BRAND_TOKENS)[keyof typeof BRAND_TOKENS][number];
55
+ /** The utility classes `brand.css` ships. All opt-in; the sheet paints nothing by itself. */
56
+ declare const BRAND_CLASSES: readonly ["brand-eyebrow", "brand-animate-float", "brand-animate-slide-up", "brand-animate-nudge-x", "brand-scrollbar", "brand-scrollbar-hide", "brand-selection"];
57
+ /** A utility class from {@link BRAND_CLASSES}. */
58
+ type BrandClass = (typeof BRAND_CLASSES)[number];
59
+ /**
60
+ * The four brand marks, as import specifiers.
61
+ *
62
+ * Naming follows the source visual pack, where "dark" names the *ink*, not the
63
+ * ground: the unsuffixed marks are drawn for a dark ground (white wordmark,
64
+ * white Plussie disc), the `-dark` marks for a light one (black wordmark, black
65
+ * Plussie disc). Pick by the surface the mark sits on, not by the app's mode.
66
+ */
67
+ declare const BRAND_ASSETS: {
68
+ /** CUE++ wordmark, white ink — for a dark ground. */
69
+ readonly wordmark: "@cueplusplus/brand-tokens/assets/cueplusplus-wordmark.svg";
70
+ /** CUE++ wordmark, black ink — for a light ground. */
71
+ readonly wordmarkDark: "@cueplusplus/brand-tokens/assets/cueplusplus-wordmark-dark.svg";
72
+ /** Plussie badge, white disc with `--brand-plussie-ink` glyph — for a dark ground. */
73
+ readonly plussie: "@cueplusplus/brand-tokens/assets/plussie.svg";
74
+ /** Plussie badge, black disc with a white glyph — for a light ground. */
75
+ readonly plussieDark: "@cueplusplus/brand-tokens/assets/plussie-dark.svg";
76
+ };
77
+ /** A key of {@link BRAND_ASSETS}. */
78
+ type BrandAsset = keyof typeof BRAND_ASSETS;
79
+ //#endregion
80
+ export { BRAND_ASSETS, BRAND_CLASSES, BRAND_STYLESHEET, BRAND_TOKENS, BRAND_WHITE_ALPHA_RAMP, BrandAsset, BrandClass, BrandToken, BrandWhiteAlpha };
package/dist/index.mjs ADDED
@@ -0,0 +1,112 @@
1
+ //#region src/index.ts
2
+ /**
3
+ * @cueplusplus/brand-tokens — the typed index of `brand.css`.
4
+ *
5
+ * The stylesheet is the source of truth; nothing here emits CSS. What this
6
+ * module gives a consumer is the *names*: the custom properties it can read
7
+ * with `var()` or `getComputedStyle`, and the import specifiers for the four
8
+ * brand marks. A repo test asserts both directions of the correspondence, so a
9
+ * token added to one file and forgotten in the other fails the build.
10
+ *
11
+ * ```ts
12
+ * import "@cueplusplus/brand-tokens/brand.css";
13
+ * import { BRAND_ASSETS, BRAND_WHITE_ALPHA_RAMP } from "@cueplusplus/brand-tokens";
14
+ * ```
15
+ */
16
+ /** The stylesheet a consumer must import for any of these names to resolve. */
17
+ const BRAND_STYLESHEET = "@cueplusplus/brand-tokens/brand.css";
18
+ /**
19
+ * The white-alpha ink ladder, darkest to brightest.
20
+ *
21
+ * White at an opacity over the brand's black ground — the brand has no greys.
22
+ * `a10` is the hairline border, `a40` the default secondary ink, `a90` the
23
+ * brightest step short of pure white.
24
+ */
25
+ const BRAND_WHITE_ALPHA_RAMP = [
26
+ "--brand-white-a05",
27
+ "--brand-white-a10",
28
+ "--brand-white-a15",
29
+ "--brand-white-a20",
30
+ "--brand-white-a25",
31
+ "--brand-white-a30",
32
+ "--brand-white-a35",
33
+ "--brand-white-a40",
34
+ "--brand-white-a45",
35
+ "--brand-white-a50",
36
+ "--brand-white-a55",
37
+ "--brand-white-a60",
38
+ "--brand-white-a70",
39
+ "--brand-white-a80",
40
+ "--brand-white-a90"
41
+ ];
42
+ /**
43
+ * Every custom property `brand.css` declares, grouped the way the sheet is.
44
+ *
45
+ * Grouped rather than flat because the groups are the contract: a brand surface
46
+ * takes the ramp wholesale, but picks one eyebrow treatment and one motion
47
+ * shorthand.
48
+ */
49
+ const BRAND_TOKENS = {
50
+ /** Pure monochrome. The near-black product ramp belongs to the `cue` theme. */
51
+ ground: ["--brand-black", "--brand-white"],
52
+ /** The ink ladder — see {@link BRAND_WHITE_ALPHA_RAMP}. */
53
+ whiteAlpha: BRAND_WHITE_ALPHA_RAMP,
54
+ /** One voice: `--brand-font-sans` is an alias of the mono stack, not a second face. */
55
+ type: ["--brand-font-mono", "--brand-font-sans"],
56
+ /** The `// SECTION` micro-label. The accent is editorial and never a status colour. */
57
+ eyebrow: [
58
+ "--brand-eyebrow-size",
59
+ "--brand-eyebrow-tracking",
60
+ "--brand-eyebrow-transform",
61
+ "--brand-eyebrow-prefix",
62
+ "--brand-eyebrow-accent"
63
+ ],
64
+ /** `animation` shorthands for the `float` / `slide-up` / `nudge-x` keyframes. */
65
+ motion: [
66
+ "--brand-motion-float",
67
+ "--brand-motion-slide-up",
68
+ "--brand-motion-nudge-x"
69
+ ],
70
+ /** Consumed by `.brand-scrollbar`; usable directly on a custom rail. */
71
+ scrollbar: [
72
+ "--brand-scrollbar-size",
73
+ "--brand-scrollbar-radius",
74
+ "--brand-scrollbar-track",
75
+ "--brand-scrollbar-thumb",
76
+ "--brand-scrollbar-thumb-hover"
77
+ ],
78
+ /** Consumed by `.brand-selection`. */
79
+ selection: ["--brand-selection-bg", "--brand-selection-fg"],
80
+ /** Values that belong to the marks themselves rather than to a surface. */
81
+ marks: ["--brand-plussie-ink"]
82
+ };
83
+ /** The utility classes `brand.css` ships. All opt-in; the sheet paints nothing by itself. */
84
+ const BRAND_CLASSES = [
85
+ "brand-eyebrow",
86
+ "brand-animate-float",
87
+ "brand-animate-slide-up",
88
+ "brand-animate-nudge-x",
89
+ "brand-scrollbar",
90
+ "brand-scrollbar-hide",
91
+ "brand-selection"
92
+ ];
93
+ /**
94
+ * The four brand marks, as import specifiers.
95
+ *
96
+ * Naming follows the source visual pack, where "dark" names the *ink*, not the
97
+ * ground: the unsuffixed marks are drawn for a dark ground (white wordmark,
98
+ * white Plussie disc), the `-dark` marks for a light one (black wordmark, black
99
+ * Plussie disc). Pick by the surface the mark sits on, not by the app's mode.
100
+ */
101
+ const BRAND_ASSETS = {
102
+ /** CUE++ wordmark, white ink — for a dark ground. */
103
+ wordmark: "@cueplusplus/brand-tokens/assets/cueplusplus-wordmark.svg",
104
+ /** CUE++ wordmark, black ink — for a light ground. */
105
+ wordmarkDark: "@cueplusplus/brand-tokens/assets/cueplusplus-wordmark-dark.svg",
106
+ /** Plussie badge, white disc with `--brand-plussie-ink` glyph — for a dark ground. */
107
+ plussie: "@cueplusplus/brand-tokens/assets/plussie.svg",
108
+ /** Plussie badge, black disc with a white glyph — for a light ground. */
109
+ plussieDark: "@cueplusplus/brand-tokens/assets/plussie-dark.svg"
110
+ };
111
+ //#endregion
112
+ export { BRAND_ASSETS, BRAND_CLASSES, BRAND_STYLESHEET, BRAND_TOKENS, BRAND_WHITE_ALPHA_RAMP };
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@cueplusplus/brand-tokens",
3
+ "version": "0.13.0",
4
+ "description": "CUE++ brand primitives extracted from the marketing site: the white-alpha ramp, the monochrome ground, the JetBrains Mono stack, the // eyebrow motif, the motion keyframes and the four brand marks.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/cueplusplus/cue-ui",
10
+ "directory": "packages/brand-tokens"
11
+ },
12
+ "publishConfig": {
13
+ "registry": "https://registry.npmjs.org",
14
+ "access": "public"
15
+ },
16
+ "sideEffects": [
17
+ "**/*.css"
18
+ ],
19
+ "engines": {
20
+ "node": ">=22"
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.mts",
25
+ "default": "./dist/index.mjs"
26
+ },
27
+ "./brand.css": "./src/brand.css",
28
+ "./assets/*": "./assets/*",
29
+ "./package.json": "./package.json"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "src/brand.css",
34
+ "assets",
35
+ "BRAND.md",
36
+ "README.md",
37
+ "CHANGELOG.md"
38
+ ],
39
+ "devDependencies": {
40
+ "eslint": "^9.17.0",
41
+ "publint": "^0.3.23",
42
+ "tsdown": "0.22.14",
43
+ "@repo/typescript-config": "0.0.0",
44
+ "@repo/eslint-config": "0.0.0"
45
+ },
46
+ "scripts": {
47
+ "build": "tsdown",
48
+ "check:publish": "publint",
49
+ "lint": "eslint . --max-warnings 0",
50
+ "test": "node --test \"test/*.test.mjs\""
51
+ }
52
+ }
package/src/brand.css ADDED
@@ -0,0 +1,233 @@
1
+ /**
2
+ * @cueplusplus/brand-tokens — the CUE++ brand, transcribed.
3
+ *
4
+ * Every value below was read out of the marketing site (cue++/site) rather than
5
+ * designed here; BRAND.md records the exact source file for each group and the
6
+ * date it was read. This sheet is a *seed*: it declares the brand's primitives
7
+ * and offers opt-in utilities, and it deliberately paints nothing. Importing it
8
+ * must never change how an app already looks.
9
+ *
10
+ * @import "@cueplusplus/brand-tokens/brand.css";
11
+ *
12
+ * Product surfaces do not consume this file — they consume the `cue` theme in
13
+ * @cueplusplus/tokens, which is where these primitives were already translated
14
+ * into the semantic contract (near-black ramp instead of pure #000, and so on).
15
+ * This package exists for brand surfaces: marketing pages, decks, the marks.
16
+ */
17
+
18
+ :root {
19
+ /* --- Ground ------------------------------------------------------------
20
+ * The marketing brand is pure monochrome. The near-black product ramp
21
+ * (#0a0a0a and up) belongs to the `cue` theme, not to the brand.
22
+ */
23
+ --brand-black: #000000;
24
+ --brand-white: #ffffff;
25
+
26
+ /* --- White-alpha ramp --------------------------------------------------
27
+ * The brand's entire ink ladder: white at an opacity, over black. The site
28
+ * reaches for ~19 distinct alphas; this is that usage regularised onto
29
+ * 5-point steps to 60, then decades. a10 is the hairline border, a40 the
30
+ * default secondary ink, a90 the brightest non-white text.
31
+ */
32
+ --brand-white-a05: rgba(255, 255, 255, 0.05);
33
+ --brand-white-a10: rgba(255, 255, 255, 0.10);
34
+ --brand-white-a15: rgba(255, 255, 255, 0.15);
35
+ --brand-white-a20: rgba(255, 255, 255, 0.20);
36
+ --brand-white-a25: rgba(255, 255, 255, 0.25);
37
+ --brand-white-a30: rgba(255, 255, 255, 0.30);
38
+ --brand-white-a35: rgba(255, 255, 255, 0.35);
39
+ --brand-white-a40: rgba(255, 255, 255, 0.40);
40
+ --brand-white-a45: rgba(255, 255, 255, 0.45);
41
+ --brand-white-a50: rgba(255, 255, 255, 0.50);
42
+ --brand-white-a55: rgba(255, 255, 255, 0.55);
43
+ --brand-white-a60: rgba(255, 255, 255, 0.60);
44
+ --brand-white-a70: rgba(255, 255, 255, 0.70);
45
+ --brand-white-a80: rgba(255, 255, 255, 0.80);
46
+ --brand-white-a90: rgba(255, 255, 255, 0.90);
47
+
48
+ /* --- Type --------------------------------------------------------------
49
+ * One voice: the site's Tailwind config points `sans` and `mono` at the same
50
+ * JetBrains Mono stack, so a consumer reaching for a sans gets the brand.
51
+ */
52
+ --brand-font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
53
+ --brand-font-sans: var(--brand-font-mono);
54
+
55
+ /* --- Eyebrow -----------------------------------------------------------
56
+ * The section-label motif: a 10px uppercase micro-label at 0.3em tracking,
57
+ * prefixed with a literal `// ` — the brand's one piece of ornament, read as
58
+ * a code comment. The accent is Tailwind violet-400 as the site uses it and
59
+ * is EDITORIAL ONLY: it must never become a semantic status colour (spec §3).
60
+ */
61
+ --brand-eyebrow-size: 10px;
62
+ --brand-eyebrow-tracking: 0.3em;
63
+ --brand-eyebrow-transform: uppercase;
64
+ --brand-eyebrow-prefix: "// ";
65
+ --brand-eyebrow-accent: #a78bfa;
66
+
67
+ /* --- Motion ------------------------------------------------------------
68
+ * Three `animation` shorthands, timings included, matching the keyframes
69
+ * below. Tokenised so a consumer can restyle the duration without forking
70
+ * the utility class.
71
+ */
72
+ --brand-motion-float: float 2.4s ease-in-out infinite;
73
+ --brand-motion-slide-up: slide-up 0.3s ease-out forwards;
74
+ --brand-motion-nudge-x: nudge-x 1.4s ease-in-out infinite;
75
+
76
+ /* --- Scrollbar ---------------------------------------------------------
77
+ * A 6px rail with no track and a white-alpha thumb that brightens on hover.
78
+ */
79
+ --brand-scrollbar-size: 6px;
80
+ --brand-scrollbar-radius: 3px;
81
+ --brand-scrollbar-track: transparent;
82
+ --brand-scrollbar-thumb: var(--brand-white-a10);
83
+ --brand-scrollbar-thumb-hover: var(--brand-white-a20);
84
+
85
+ /* --- Selection --------------------------------------------------------- */
86
+ --brand-selection-bg: var(--brand-white-a20);
87
+ --brand-selection-fg: var(--brand-white);
88
+
89
+ /* --- Marks -------------------------------------------------------------
90
+ * The one non-monochrome value in the identity: the "++" glyph inside the
91
+ * light Plussie badge is #1E1E1E, not #000 — it keeps the badge from reading
92
+ * as a hole punched in the page.
93
+ */
94
+ --brand-plussie-ink: #1E1E1E;
95
+ }
96
+
97
+ /* --- Eyebrow utility -----------------------------------------------------
98
+ * `<p class="brand-eyebrow">Work with us</p>` renders `// WORK WITH US`.
99
+ * The prefix lives in ::before so the motif never reaches the accessibility
100
+ * tree or a copy-paste.
101
+ */
102
+ .brand-eyebrow {
103
+ font-family: var(--brand-font-mono);
104
+ font-size: var(--brand-eyebrow-size);
105
+ letter-spacing: var(--brand-eyebrow-tracking);
106
+ text-transform: var(--brand-eyebrow-transform);
107
+ color: var(--brand-eyebrow-accent);
108
+ }
109
+
110
+ .brand-eyebrow::before {
111
+ content: var(--brand-eyebrow-prefix);
112
+ }
113
+
114
+ /* --- Motion --------------------------------------------------------------
115
+ * Keyframes transcribed frame for frame. The names stay unprefixed because an
116
+ * `animation` shorthand quotes a keyframe name literally and the brand's
117
+ * shorthands are part of the contract; a consumer that already owns a `float`
118
+ * animation should import this sheet before its own.
119
+ */
120
+ @keyframes float {
121
+ 0%,
122
+ 100% {
123
+ transform: translateY(0);
124
+ opacity: 0.4;
125
+ }
126
+ 50% {
127
+ transform: translateY(6px);
128
+ opacity: 0.7;
129
+ }
130
+ }
131
+
132
+ @keyframes slide-up {
133
+ from {
134
+ transform: translateY(100%);
135
+ opacity: 0;
136
+ }
137
+ to {
138
+ transform: translateY(0);
139
+ opacity: 1;
140
+ }
141
+ }
142
+
143
+ @keyframes nudge-x {
144
+ 0%,
145
+ 100% {
146
+ transform: translateX(0);
147
+ }
148
+ 50% {
149
+ transform: translateX(3px);
150
+ }
151
+ }
152
+
153
+ .brand-animate-float {
154
+ animation: var(--brand-motion-float);
155
+ }
156
+
157
+ .brand-animate-slide-up {
158
+ animation: var(--brand-motion-slide-up);
159
+ }
160
+
161
+ .brand-animate-nudge-x {
162
+ animation: var(--brand-motion-nudge-x);
163
+ }
164
+
165
+ /* --- Scrollbar utilities -------------------------------------------------
166
+ * Opt-in, unlike the site: `.brand-scrollbar` on the scroll container, or
167
+ * `.brand-scrollbar-hide` to remove the rail entirely. A package that styled
168
+ * ::-webkit-scrollbar globally would repaint the chrome of any app that merely
169
+ * imported it.
170
+ */
171
+ .brand-scrollbar {
172
+ scrollbar-width: thin;
173
+ scrollbar-color: var(--brand-scrollbar-thumb) var(--brand-scrollbar-track);
174
+ }
175
+
176
+ .brand-scrollbar::-webkit-scrollbar {
177
+ width: var(--brand-scrollbar-size);
178
+ height: var(--brand-scrollbar-size);
179
+ }
180
+
181
+ .brand-scrollbar::-webkit-scrollbar-track {
182
+ background: var(--brand-scrollbar-track);
183
+ }
184
+
185
+ .brand-scrollbar::-webkit-scrollbar-thumb {
186
+ background: var(--brand-scrollbar-thumb);
187
+ border-radius: var(--brand-scrollbar-radius);
188
+ }
189
+
190
+ .brand-scrollbar::-webkit-scrollbar-thumb:hover {
191
+ background: var(--brand-scrollbar-thumb-hover);
192
+ }
193
+
194
+ .brand-scrollbar-hide {
195
+ -ms-overflow-style: none;
196
+ scrollbar-width: none;
197
+ }
198
+
199
+ .brand-scrollbar-hide::-webkit-scrollbar {
200
+ display: none;
201
+ }
202
+
203
+ /* --- Selection -----------------------------------------------------------
204
+ * Opt-in for the same reason: scoped to a `.brand-selection` ancestor rather
205
+ * than declared on a bare ::selection.
206
+ */
207
+ .brand-selection::selection,
208
+ .brand-selection ::selection {
209
+ background-color: var(--brand-selection-bg);
210
+ color: var(--brand-selection-fg);
211
+ }
212
+
213
+ /* --- Reduced motion ------------------------------------------------------
214
+ * The site's clamp, kept whole: the brand's position is that a reader who asks
215
+ * for less motion gets it everywhere, not only from the three animations this
216
+ * sheet happens to ship. This is the one rule here that reaches outside the
217
+ * `.brand-*` namespace, and it is deliberate.
218
+ */
219
+ @media (prefers-reduced-motion: reduce) {
220
+ .brand-animate-float,
221
+ .brand-animate-slide-up,
222
+ .brand-animate-nudge-x {
223
+ animation: none;
224
+ }
225
+
226
+ *,
227
+ *::before,
228
+ *::after {
229
+ animation-duration: 0.01ms !important;
230
+ animation-iteration-count: 1 !important;
231
+ transition-duration: 0.01ms !important;
232
+ }
233
+ }