cursedbelt 2.3.0 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/styles.css CHANGED
@@ -6,32 +6,54 @@
6
6
  * This `@source` makes Tailwind v4 scan cursedbelt's source files so the utility
7
7
  * classes used by its components are generated in the app's stylesheet.
8
8
  *
9
- * ── Two entry points, and which one an app wants ─────────────────────────────
9
+ * ── Two ways in, and which one an app wants ──────────────────────────────────
10
10
  * `@source "."` is the expensive half: it points Tailwind's JIT at cursedbelt's
11
11
  * ENTIRE source tree, so the app emits the union of the whole design system
12
- * (113 KB / 846 selectors, measured in the previous generation) whether it
13
- * renders three components or eighty. Everything else in this file is CSS the
14
- * components genuinely need and no app can do without.
12
+ * whether it renders three components or eighty, and its own build walks 827
13
+ * files it does not own. Everything else in this file is CSS the components
14
+ * genuinely need and no app can do without.
15
15
  *
16
- * A CSS `@import` takes the whole file, so the split is a second subpath:
16
+ * A CSS `@import` takes the whole file, so the split is two more subpaths:
17
17
  *
18
- * cursedbelt/styles.css this file — the real CSS + the `@source` scan
19
- * cursedbelt/styles-static.css the same file MINUS the `@source` line
18
+ * cursedbelt/styles.css this file — the real CSS + the `@source` scan
19
+ * cursedbelt/styles-static.css the same file MINUS the `@source` line
20
+ * cursedbelt/styles-utilities.css the utilities that `@source` line would have
21
+ * produced, precompiled at cursedbelt's build
20
22
  *
21
- * The static one is for an app that pays for its own scanning — it gets the
22
- * tooltip pointer-events fix, the Progress keyframes, the lightbox bridge, the
23
- * ambient/glass layer and `tw-animate-css`, and emits none of cursedbelt's
24
- * utility classes, so whatever component utilities it needs must come from
25
- * sources IT registers. Do not hand-list cursedbelt's component files to get
26
- * them back: a relative `@source` reaching into this package's source tree is a
27
- * `file:` dependency wearing a stylesheet's clothes, and it is the thing the
28
- * previous generation's 29-line-per-app arrangement is remembered for.
23
+ * The second two are a PAIR and neither is usable alone — `styles-static.css` on
24
+ * its own gets the tooltip pointer-events fix, the Progress keyframes, the
25
+ * lightbox bridge, the ambient/glass layer and `tw-animate-css`, and emits none
26
+ * of cursedbelt's utility classes, i.e. an unstyled app:
29
27
  *
30
- * 🔴 This header is in BOTH files, because one is generated from the other and a
31
- * test holds them byte-identical apart from the `@source` line. Always edit
32
- * `src/styles.css`; never `src/styles-static.css`, which
28
+ * @import "tailwindcss";
29
+ * @import "cursedbelt/styles-static.css";
30
+ * @import "cursedbelt/styles-utilities.css";
31
+ * @import "cursedbelt/theme.css";
32
+ *
33
+ * 🔴 Do NOT hand-list cursedbelt's component files to get the utilities back.
34
+ * Tailwind v4 resolves every `@source` to a DIRECTORY and scans it recursively —
35
+ * a file path and a glob are both silently widened to their parent — and
36
+ * `VirtualList`/`VirtualCardGrid` live at the root of `src/react/`, so the finest
37
+ * grain an app can write is the whole design system. A relative `@source` reaching
38
+ * into this package's source tree is also a `file:` dependency wearing a
39
+ * stylesheet's clothes, and it buys nothing: it is the thing the previous
40
+ * generation's 29-line-per-app arrangement is remembered for, and those 29 lines
41
+ * were never file-level scoping either.
42
+ *
43
+ * The pair is not SMALLER than this file — measured, both routes emit the same
44
+ * rules within 54 bytes. What it buys is a build that scans nothing of another
45
+ * package's source tree, and a `styles-static.css` that finally has a correct
46
+ * use. The measurements, and what would actually shrink a consumer, are in the
47
+ * header of `scripts/generateUtilityStyles.ts`.
48
+ *
49
+ * 🔴 This header is in BOTH of the first two files, because one is generated from
50
+ * the other and a test holds them byte-identical apart from the `@source` line.
51
+ * Always edit `src/styles.css`; never `src/styles-static.css`, which
33
52
  * `scripts/generateStaticStyles.ts` rewrites on every `bun run build` and
34
- * `src/stylesStaticMatches.spec.ts` fails on when it is stale.
53
+ * `src/stylesStaticMatches.spec.ts` fails on when it is stale. Editing this file
54
+ * invalidates `src/styles-utilities.css` too — it is compiled against the static
55
+ * variant, `scripts/generateUtilityStyles.ts` rewrites it in the same build step,
56
+ * and `src/stylesUtilitiesMatches.spec.ts` is what fails when it is stale.
35
57
  */
36
58
 
37
59
  /* Animation utilities (animate-in/out, fade/zoom/slide-in-from-*) consumed by the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt",
3
- "version": "2.3.0",
3
+ "version": "2.5.1",
4
4
  "license": "ISC",
5
5
  "type": "module",
6
6
  "description": "Shared Bun + React framework",
@@ -30,13 +30,14 @@
30
30
  "guardrails:report": "bun run scripts/guardrailsEnforce.ts no-raw-action-button,no-raw-overflow,no-raw-inputs,no-hardcoded-colors,no-raw-modal-footer,no-unguarded-editing-modal,control-height-tokens,no-raw-zindex,no-raw-data-table,no-tailwind-palette,no-raw-title-attr,micro-typography-floor,choice-needs-empty-state,no-select-as-action-menu,no-native-dialog,no-fast-tooltip --scope cursedbelt src/react src/styles.css",
31
31
  "format": "biome format --write .",
32
32
  "styles:static": "bun run scripts/generateStaticStyles.ts",
33
+ "styles:utilities": "bun run scripts/generateUtilityStyles.ts",
33
34
  "test": "NODE_ENV=development bun test src",
34
35
  "test:pg": "bun run scripts/testPg.ts",
35
36
  "demo": "vite --config demo/vite.config.ts",
36
37
  "demo:build": "vite build --config demo/vite.config.ts",
37
38
  "demo:serve": "bun run demo:build && vite preview --config demo/vite.config.ts",
38
39
  "prebuild": "bun run verify:gate",
39
- "build": "rm -rf dist.next dist.prev && bun run scripts/generateStaticStyles.ts && tsc --project tsconfig.build.json --outDir dist.next && tsc --project tsconfig.build.server.json --outDir dist.next && CURSEDBELT_DIST_DIR=dist.next bun run scripts/copyDistAssets.ts && { [ -d dist ] && mv dist dist.prev || true; } && mv dist.next dist && rm -rf dist.prev",
40
+ "build": "rm -rf dist.next dist.prev && bun run scripts/generateStaticStyles.ts && bun run scripts/generateUtilityStyles.ts && tsc --project tsconfig.build.json --outDir dist.next && tsc --project tsconfig.build.server.json --outDir dist.next && CURSEDBELT_DIST_DIR=dist.next bun run scripts/copyDistAssets.ts && { [ -d dist ] && mv dist dist.prev || true; } && mv dist.next dist && rm -rf dist.prev",
40
41
  "e2e": "playwright test --config e2e/playwright.config.ts",
41
42
  "e2e:filter-rail": "playwright test --config e2e/playwright.config.ts filter-rail.spec.ts",
42
43
  "e2e:table-layout": "playwright test --config e2e/playwright.config.ts table-layout.spec.ts",
@@ -488,7 +489,13 @@
488
489
  "source": "./src/server/index.ts",
489
490
  "import": "./dist/server/index.js"
490
491
  },
491
- "./server/guard/revocations": {
492
+ "./server/login-throttle": {
493
+ "types": "./dist/server/auth/loginThrottle.d.ts",
494
+ "bun": "./src/server/auth/loginThrottle.ts",
495
+ "source": "./src/server/auth/loginThrottle.ts",
496
+ "import": "./dist/server/auth/loginThrottle.js"
497
+ },
498
+ "./server/guard/revocations": {
492
499
  "types": "./dist/server/guard/revocationStore.d.ts",
493
500
  "bun": "./src/server/guard/revocationStore.ts",
494
501
  "source": "./src/server/guard/revocationStore.ts",
@@ -514,6 +521,7 @@
514
521
  },
515
522
  "./styles.css": "./src/styles.css",
516
523
  "./styles-static.css": "./src/styles-static.css",
524
+ "./styles-utilities.css": "./src/styles-utilities.css",
517
525
  "./theme.css": "./src/theme.css",
518
526
  "./workspace.css": "./src/workspace.css",
519
527
  "./react/keep-awake": {
@@ -771,6 +779,8 @@
771
779
  "@lezer/highlight": "^1.2.3",
772
780
  "@node-rs/argon2": "^2.0.2",
773
781
  "@playwright/test": "^1.61.0",
782
+ "@tailwindcss/node": "^4.3.1",
783
+ "@tailwindcss/oxide": "^4.3.1",
774
784
  "@tailwindcss/vite": "^4.3.1",
775
785
  "@tanstack/react-query": "5.101.2",
776
786
  "@testing-library/dom": "^10.4.1",
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Generate `src/styles-utilities.css` — cursedbelt's component utilities, PRECOMPILED.
3
+ *
4
+ * ── The hole this fills ─────────────────────────────────────────────────────
5
+ * `src/styles-static.css` (the sibling generator, `generateStaticStyles.ts`) is
6
+ * `styles.css` minus its `@source "."`. It was shipped for "an app that pays for
7
+ * its own scanning" — and until this file existed, no app could pay. Tailwind v4
8
+ * (4.3.3, measured) resolves every `@source` to a DIRECTORY and scans it
9
+ * recursively: a file path is silently widened to its parent, a glob is widened
10
+ * the same way, and `@source not` over a package's own tree subtracts nothing.
11
+ * All four of these emit byte-for-byte identical CSS in a consuming app:
12
+ *
13
+ * @source ".../cursedbelt/src/react/index.*";
14
+ * @source ".../cursedbelt/src/react/styling.*";
15
+ * @source ".../cursedbelt/src/react/Virtual*.tsx";
16
+ * @source ".../cursedbelt/src/react/*.{ts,tsx}";
17
+ *
18
+ * `VirtualList` and `VirtualCardGrid` sit at the ROOT of `src/react/`, so the
19
+ * finest grain an app can ask for is that directory — whose recursive contents
20
+ * are the whole design system. Scanning it is the union; not scanning it is an
21
+ * UNSTYLED app. There was no third option, which made `styles-static.css` as
22
+ * published a subpath with no correct use. (It also retires a long-standing
23
+ * misreading: the previous generation's hand-written 29-line `@source` list in
24
+ * `satellite-kit` was never file-level scoping — every line was widened to its
25
+ * parent directory, which is why that arrangement still emitted ~113 KB.)
26
+ *
27
+ * So the utilities become a BUILD ARTIFACT: compiled once, here, and shipped.
28
+ * The consumer scans nothing.
29
+ *
30
+ * ── What it is worth, measured, so nobody re-runs this blind ────────────────
31
+ * 🔴 It is NOT smaller. Compiling cursedbelt's own surface both ways (this repo,
32
+ * tailwindcss 4.3.3, lightningcss-minified):
33
+ *
34
+ * @import "cursedbelt/styles.css" 131,795 B · 22,490 gz
35
+ * styles-static.css + styles-utilities.css 131,741 B · 22,462 gz
36
+ *
37
+ * — a 54-byte difference, i.e. the same stylesheet by another route. The union
38
+ * is the union however it is assembled. The 10.3 kB gzip saving flix measured
39
+ * came from scanning exactly the 29 modules Rollup put in its chunk, and that is
40
+ * per-app tree-shaking, which no single shared artifact can do. What this DOES
41
+ * buy: `styles-static.css` gains a correct use, a consuming app stops reaching
42
+ * into another package's source tree from its CSS (a `file:` dependency wearing
43
+ * a stylesheet's clothes), and the app's Tailwind build stops walking 827 files
44
+ * it does not own. Reaching the 16 KB-of-utilities floor flix measured needs
45
+ * per-module CSS the bundler can tree-shake — a different, larger change.
46
+ *
47
+ * ── Why GENERATED, and what holds it honest ─────────────────────────────────
48
+ * Same bargain as `styles-static.css`: this script writes it, `bun run build`
49
+ * runs this script, and `src/stylesUtilitiesMatches.spec.ts` fails when what is
50
+ * on disk is not what `src/react/**` currently produces. That spec does not
51
+ * compare SIZE — an unstyled app is invisible to a byte count read in one
52
+ * direction — it compiles a consumer both ways and compares the emitted rules.
53
+ *
54
+ * Usage:
55
+ * bun run styles:utilities # write src/styles-utilities.css
56
+ * bun run styles:utilities --check # exit 1 if it is stale, write nothing
57
+ */
58
+ import { compile } from '@tailwindcss/node';
59
+ import { Scanner } from '@tailwindcss/oxide';
60
+ import { REPO_ROOT, STATIC_STYLESHEET, readStylesheets } from './generateStaticStyles';
61
+
62
+ export { REPO_ROOT };
63
+
64
+ export const UTILITY_STYLESHEET = 'src/styles-utilities.css';
65
+
66
+ /** Every relative specifier below resolves against `src/`, like `styles.css` does. */
67
+ export const STYLES_BASE = `${REPO_ROOT}/src`;
68
+
69
+ /**
70
+ * The compile input.
71
+ *
72
+ * `@reference` rather than `@import` for the two cursedbelt stylesheets: it makes
73
+ * their `@theme` tokens, `@custom-variant dark` and `tw-animate-css`'s `@utility`
74
+ * definitions available to the compiler while emitting NONE of their CSS — the
75
+ * consumer imports those files itself, and duplicating them here would be the
76
+ * drift this whole arrangement exists to prevent. Dropping the
77
+ * `@reference "./styles-static.css"` line costs 41 rules: every `animate-in` /
78
+ * `fade-out` / `slide-in-from-*` / `data-[state=open]:*` utility the dialog,
79
+ * tooltip and collapsible families animate with, plus
80
+ * `.animate-progress-indeterminate`.
81
+ *
82
+ * `./react` and not `.`: `.` would scan `src/` — including this file's own output,
83
+ * making each generation depend on the last one. It buys nothing anyway; the whole
84
+ * of `src/` outside `src/react` adds 32 bytes.
85
+ */
86
+ export const UTILITY_INPUT = `@layer theme, base, components, utilities;
87
+ @import "tailwindcss/theme.css" layer(theme);
88
+ @reference "./styles-static.css";
89
+ @reference "./theme.css";
90
+ @import "tailwindcss/utilities.css" layer(utilities);
91
+ @source "./react";
92
+ `;
93
+
94
+ /**
95
+ * What a consuming app's CSS is, today and after adoption — the two inputs
96
+ * `src/stylesUtilitiesMatches.spec.ts` compiles and compares rule by rule.
97
+ *
98
+ * `source(none)` on the second one is the point of the exercise: it forbids
99
+ * Tailwind from scanning anything at all, so whatever comes out is what the
100
+ * precompiled artifact supplies and nothing else. A real app drops it and keeps
101
+ * scanning its OWN sources.
102
+ */
103
+ export const CONSUMER_SCANNING = '@import "tailwindcss";\n@import "./styles.css";\n@import "./theme.css";\n';
104
+ export const CONSUMER_PRECOMPILED =
105
+ '@import "tailwindcss" source(none);\n' +
106
+ '@import "./styles-static.css";\n' +
107
+ '@import "./styles-utilities.css";\n' +
108
+ '@import "./theme.css";\n';
109
+
110
+ /**
111
+ * A floor on the scan, because the failure this artifact can have is SILENT.
112
+ * If `src/react` moves, or a `.gitignore` starts swallowing it, or oxide's walk
113
+ * returns nothing, the compile still succeeds — it just emits an empty utility
114
+ * layer, and every consumer ships an unstyled app. 16,594 candidates today; this
115
+ * is a collapse tripwire, not a ratchet.
116
+ */
117
+ export const MIN_CANDIDATES = 1_000;
118
+
119
+ /** cursedbelt's stylesheets are self-contained — nothing here loads a JS config. */
120
+ const noDependency = (): void => {};
121
+
122
+ /** Compile one of the inputs above against `src/`. */
123
+ export const compileStylesheet = (
124
+ input: string,
125
+ ): ReturnType<typeof compile> => compile(input, { base: STYLES_BASE, onDependency: noDependency });
126
+
127
+ /** The banner the artifact carries, so a reader never mistakes it for a source file. */
128
+ export const BANNER = `/*
129
+ * cursedbelt component utilities — GENERATED BUILD ARTIFACT. Never hand-edit.
130
+ *
131
+ * Every Tailwind utility class cursedbelt's own components (\`src/react/**\`) use,
132
+ * compiled once at this package's build time so a consuming app does not have to
133
+ * scan this package's source tree — which Tailwind v4 cannot do at any grain
134
+ * finer than "the whole design system" anyway. Import it after Tailwind itself,
135
+ * beside the static entry point:
136
+ *
137
+ * @import "tailwindcss";
138
+ * @import "cursedbelt/styles-static.css";
139
+ * @import "cursedbelt/styles-utilities.css";
140
+ * @import "cursedbelt/theme.css";
141
+ *
142
+ * That pair emits the same rules as \`@import "cursedbelt/styles.css"\` — proved
143
+ * rule by rule, not by byte count, in src/stylesUtilitiesMatches.spec.ts. It is
144
+ * not SMALLER; see the header of scripts/generateUtilityStyles.ts for the
145
+ * measurements and for what it does buy.
146
+ *
147
+ * Written by scripts/generateUtilityStyles.ts (\`bun run styles:utilities\`),
148
+ * which \`bun run build\` runs. src/stylesUtilitiesMatches.spec.ts fails when what
149
+ * is on disk is not what src/react/** currently produces.
150
+ */
151
+ `;
152
+
153
+ /**
154
+ * Compile the utility layer from `src/react/**`.
155
+ *
156
+ * Refuses to run against a stale `styles-static.css`, rather than quietly baking
157
+ * the stale one's tokens in: the two artifacts are generated from the same
158
+ * `styles.css`, and `bun run build` orders them, but `bun run styles:utilities`
159
+ * on its own would not.
160
+ */
161
+ export const buildUtilityStyles = async (): Promise<{ css: string; candidates: string[] }> => {
162
+ const { expected, onDisk } = await readStylesheets();
163
+ if (onDisk !== expected) {
164
+ throw new Error(
165
+ `${STATIC_STYLESHEET} is ${onDisk === null ? 'missing' : 'stale'}, and this artifact is compiled\n` +
166
+ `against it (\`@reference\`), so it would bake in the wrong tokens. Run:\n` +
167
+ ` cd ${REPO_ROOT} && bun run styles:static`,
168
+ );
169
+ }
170
+ const compiled = await compileStylesheet(UTILITY_INPUT);
171
+ const candidates = new Scanner({ sources: compiled.sources }).scan();
172
+ if (candidates.length < MIN_CANDIDATES) {
173
+ throw new Error(
174
+ `the scan of src/react found ${candidates.length} candidates (floor ${MIN_CANDIDATES}).\n` +
175
+ 'That is a collapsed scan, not a small design system — the artifact it would write\n' +
176
+ 'emits an empty utility layer and every consuming app ships UNSTYLED. Check that\n' +
177
+ `${STYLES_BASE}/react exists and is not excluded by a .gitignore.`,
178
+ );
179
+ }
180
+ return { css: `${BANNER}${compiled.build(candidates)}`, candidates };
181
+ };
182
+
183
+ /** The artifact's expected contents and what is on disk right now. */
184
+ export const readUtilityStylesheet = async (): Promise<{
185
+ expected: string;
186
+ onDisk: string | null;
187
+ candidates: string[];
188
+ }> => {
189
+ const { css, candidates } = await buildUtilityStyles();
190
+ const target = Bun.file(`${REPO_ROOT}/${UTILITY_STYLESHEET}`);
191
+ return { expected: css, onDisk: (await target.exists()) ? await target.text() : null, candidates };
192
+ };
193
+
194
+ if (import.meta.main) {
195
+ const { expected, onDisk, candidates } = await readUtilityStylesheet();
196
+ if (process.argv.includes('--check')) {
197
+ if (onDisk === expected) {
198
+ console.log(`✅ ${UTILITY_STYLESHEET} is current (${candidates.length} candidates).`);
199
+ process.exit(0);
200
+ }
201
+ console.error(
202
+ `❌ ${UTILITY_STYLESHEET} is ${onDisk === null ? 'missing' : 'stale'}. Run:\n` +
203
+ ` cd ${REPO_ROOT} && bun run styles:utilities`,
204
+ );
205
+ process.exit(1);
206
+ }
207
+ if (onDisk === expected) {
208
+ console.log(`✅ ${UTILITY_STYLESHEET} already current (${candidates.length} candidates).`);
209
+ } else {
210
+ await Bun.write(`${REPO_ROOT}/${UTILITY_STYLESHEET}`, expected);
211
+ console.log(
212
+ `✅ wrote ${UTILITY_STYLESHEET} — ${candidates.length} candidates scanned from src/react.`,
213
+ );
214
+ }
215
+ }
@@ -6,32 +6,54 @@
6
6
  * This `@source` makes Tailwind v4 scan cursedbelt's source files so the utility
7
7
  * classes used by its components are generated in the app's stylesheet.
8
8
  *
9
- * ── Two entry points, and which one an app wants ─────────────────────────────
9
+ * ── Two ways in, and which one an app wants ──────────────────────────────────
10
10
  * `@source "."` is the expensive half: it points Tailwind's JIT at cursedbelt's
11
11
  * ENTIRE source tree, so the app emits the union of the whole design system
12
- * (113 KB / 846 selectors, measured in the previous generation) whether it
13
- * renders three components or eighty. Everything else in this file is CSS the
14
- * components genuinely need and no app can do without.
12
+ * whether it renders three components or eighty, and its own build walks 827
13
+ * files it does not own. Everything else in this file is CSS the components
14
+ * genuinely need and no app can do without.
15
15
  *
16
- * A CSS `@import` takes the whole file, so the split is a second subpath:
16
+ * A CSS `@import` takes the whole file, so the split is two more subpaths:
17
17
  *
18
- * cursedbelt/styles.css this file — the real CSS + the `@source` scan
19
- * cursedbelt/styles-static.css the same file MINUS the `@source` line
18
+ * cursedbelt/styles.css this file — the real CSS + the `@source` scan
19
+ * cursedbelt/styles-static.css the same file MINUS the `@source` line
20
+ * cursedbelt/styles-utilities.css the utilities that `@source` line would have
21
+ * produced, precompiled at cursedbelt's build
20
22
  *
21
- * The static one is for an app that pays for its own scanning — it gets the
22
- * tooltip pointer-events fix, the Progress keyframes, the lightbox bridge, the
23
- * ambient/glass layer and `tw-animate-css`, and emits none of cursedbelt's
24
- * utility classes, so whatever component utilities it needs must come from
25
- * sources IT registers. Do not hand-list cursedbelt's component files to get
26
- * them back: a relative `@source` reaching into this package's source tree is a
27
- * `file:` dependency wearing a stylesheet's clothes, and it is the thing the
28
- * previous generation's 29-line-per-app arrangement is remembered for.
23
+ * The second two are a PAIR and neither is usable alone — `styles-static.css` on
24
+ * its own gets the tooltip pointer-events fix, the Progress keyframes, the
25
+ * lightbox bridge, the ambient/glass layer and `tw-animate-css`, and emits none
26
+ * of cursedbelt's utility classes, i.e. an unstyled app:
29
27
  *
30
- * 🔴 This header is in BOTH files, because one is generated from the other and a
31
- * test holds them byte-identical apart from the `@source` line. Always edit
32
- * `src/styles.css`; never `src/styles-static.css`, which
28
+ * @import "tailwindcss";
29
+ * @import "cursedbelt/styles-static.css";
30
+ * @import "cursedbelt/styles-utilities.css";
31
+ * @import "cursedbelt/theme.css";
32
+ *
33
+ * 🔴 Do NOT hand-list cursedbelt's component files to get the utilities back.
34
+ * Tailwind v4 resolves every `@source` to a DIRECTORY and scans it recursively —
35
+ * a file path and a glob are both silently widened to their parent — and
36
+ * `VirtualList`/`VirtualCardGrid` live at the root of `src/react/`, so the finest
37
+ * grain an app can write is the whole design system. A relative `@source` reaching
38
+ * into this package's source tree is also a `file:` dependency wearing a
39
+ * stylesheet's clothes, and it buys nothing: it is the thing the previous
40
+ * generation's 29-line-per-app arrangement is remembered for, and those 29 lines
41
+ * were never file-level scoping either.
42
+ *
43
+ * The pair is not SMALLER than this file — measured, both routes emit the same
44
+ * rules within 54 bytes. What it buys is a build that scans nothing of another
45
+ * package's source tree, and a `styles-static.css` that finally has a correct
46
+ * use. The measurements, and what would actually shrink a consumer, are in the
47
+ * header of `scripts/generateUtilityStyles.ts`.
48
+ *
49
+ * 🔴 This header is in BOTH of the first two files, because one is generated from
50
+ * the other and a test holds them byte-identical apart from the `@source` line.
51
+ * Always edit `src/styles.css`; never `src/styles-static.css`, which
33
52
  * `scripts/generateStaticStyles.ts` rewrites on every `bun run build` and
34
- * `src/stylesStaticMatches.spec.ts` fails on when it is stale.
53
+ * `src/stylesStaticMatches.spec.ts` fails on when it is stale. Editing this file
54
+ * invalidates `src/styles-utilities.css` too — it is compiled against the static
55
+ * variant, `scripts/generateUtilityStyles.ts` rewrites it in the same build step,
56
+ * and `src/stylesUtilitiesMatches.spec.ts` is what fails when it is stale.
35
57
  */
36
58
 
37
59
  /* Animation utilities (animate-in/out, fade/zoom/slide-in-from-*) consumed by the