cursedbelt 4.7.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +36 -0
  2. package/dist/react/chat/index.d.ts +1 -0
  3. package/dist/react/chat/index.d.ts.map +1 -1
  4. package/dist/react/chat/index.js +1 -0
  5. package/dist/react/chat/index.js.map +1 -1
  6. package/dist/react/chat/usePresence.d.ts +75 -0
  7. package/dist/react/chat/usePresence.d.ts.map +1 -0
  8. package/dist/react/chat/usePresence.js +109 -0
  9. package/dist/react/chat/usePresence.js.map +1 -0
  10. package/dist/react/components/SecretInput.d.ts +7 -2
  11. package/dist/react/components/SecretInput.d.ts.map +1 -1
  12. package/dist/react/components/SecretInput.js +5 -2
  13. package/dist/react/components/SecretInput.js.map +1 -1
  14. package/dist/react/components/TooltipImpl.d.ts.map +1 -1
  15. package/dist/react/components/TooltipImpl.js +52 -3
  16. package/dist/react/components/TooltipImpl.js.map +1 -1
  17. package/dist/react/index.d.ts +1 -0
  18. package/dist/react/index.d.ts.map +1 -1
  19. package/dist/react/index.js +1 -0
  20. package/dist/react/index.js.map +1 -1
  21. package/dist/react/master-lock/MasterLockDialog.d.ts.map +1 -1
  22. package/dist/react/master-lock/MasterLockDialog.js +2 -1
  23. package/dist/react/master-lock/MasterLockDialog.js.map +1 -1
  24. package/dist/react/master-lock/MasterLockProvider.d.ts +12 -18
  25. package/dist/react/master-lock/MasterLockProvider.d.ts.map +1 -1
  26. package/dist/react/master-lock/MasterLockProvider.js +14 -20
  27. package/dist/react/master-lock/MasterLockProvider.js.map +1 -1
  28. package/dist/react/media/MediaUploadControl.d.ts +3 -7
  29. package/dist/react/media/MediaUploadControl.d.ts.map +1 -1
  30. package/dist/react/media/MediaUploadControl.js +4 -13
  31. package/dist/react/media/MediaUploadControl.js.map +1 -1
  32. package/dist/react/media/fileUploadClient.d.ts +0 -8
  33. package/dist/react/media/fileUploadClient.d.ts.map +1 -1
  34. package/dist/react/media/fileUploadClient.js +0 -8
  35. package/dist/react/media/fileUploadClient.js.map +1 -1
  36. package/dist/react/media/hlsSource.d.ts.map +1 -1
  37. package/dist/react/media/hlsSource.js +4 -2
  38. package/dist/react/media/hlsSource.js.map +1 -1
  39. package/dist/react/media/index.d.ts +0 -4
  40. package/dist/react/media/index.d.ts.map +1 -1
  41. package/dist/react/media/index.js +0 -4
  42. package/dist/react/media/index.js.map +1 -1
  43. package/dist/react/sessionAuth.d.ts +1 -2
  44. package/dist/react/sessionAuth.d.ts.map +1 -1
  45. package/dist/react/sessionAuth.js +2 -3
  46. package/dist/react/sessionAuth.js.map +1 -1
  47. package/dist/scripts/guardrailsEnforce.d.ts.map +1 -1
  48. package/dist/styles-areas/activity-bar.css +1 -1
  49. package/dist/styles-areas/auth.css +1 -1
  50. package/dist/styles-areas/charts.css +1 -1
  51. package/dist/styles-areas/chat.css +1 -1
  52. package/dist/styles-areas/core.css +1 -1
  53. package/dist/styles-areas/data-table.css +1 -1
  54. package/dist/styles-areas/disk-usage.css +1 -1
  55. package/dist/styles-areas/fields.css +1 -1
  56. package/dist/styles-areas/master-detail.css +1 -1
  57. package/dist/styles-areas/master-lock.css +108 -2
  58. package/dist/styles-areas/media-gallery.css +1 -1
  59. package/dist/styles-areas/media.css +1 -17
  60. package/dist/styles-areas/nav.css +1 -1
  61. package/dist/styles-areas/notifications.css +1 -1
  62. package/dist/styles-areas/spreadsheet.css +1 -1
  63. package/dist/styles-areas/stats.css +1 -1
  64. package/dist/styles-areas/wizard.css +1 -1
  65. package/dist/styles-areas/workbook-viewer.css +1 -1
  66. package/dist/styles-utilities.css +0 -16
  67. package/dist/testing/_noBun.d.ts +2 -0
  68. package/dist/testing/_noBun.d.ts.map +1 -0
  69. package/dist/testing/_noBun.js +10 -0
  70. package/dist/testing/_noBun.js.map +1 -0
  71. package/package.json +42 -19
  72. package/scripts/checkAreaStyles.spec.ts +71 -0
  73. package/scripts/checkAreaStyles.ts +150 -0
  74. package/scripts/guardrailsEnforce.spec.ts +43 -0
  75. package/scripts/guardrailsEnforce.ts +46 -1
  76. package/scripts/styleAreas.ts +1 -2
  77. package/src/barrelsReachNoOptionalPeer.spec.ts +6 -3
  78. package/src/bundlerOnlyEntries.spec.ts +101 -0
  79. package/src/declaredImports.spec.ts +4 -0
  80. package/src/optionalPeersTable.spec.ts +127 -0
  81. package/src/react/chat/index.ts +8 -0
  82. package/src/react/chat/usePresence.spec.tsx +138 -0
  83. package/src/react/chat/usePresence.ts +185 -0
  84. package/src/react/components/SecretInput.tsx +12 -1
  85. package/src/react/components/TooltipImpl.tsx +54 -5
  86. package/src/react/index.ts +8 -0
  87. package/src/react/master-lock/MasterLockDialog.tsx +13 -9
  88. package/src/react/master-lock/MasterLockProvider.spec.tsx +17 -0
  89. package/src/react/master-lock/MasterLockProvider.tsx +16 -19
  90. package/src/react/media/MediaUploadControl.tsx +8 -29
  91. package/src/react/media/fileUploadClient.ts +7 -17
  92. package/src/react/media/hlsSource.ts +4 -1
  93. package/src/react/media/index.ts +0 -16
  94. package/src/react/sessionAuth.ts +2 -3
  95. package/src/scriptsResolve.spec.ts +66 -0
  96. package/src/styles-areas/activity-bar.css +1 -1
  97. package/src/styles-areas/auth.css +1 -1
  98. package/src/styles-areas/charts.css +1 -1
  99. package/src/styles-areas/chat.css +1 -1
  100. package/src/styles-areas/core.css +1 -1
  101. package/src/styles-areas/data-table.css +1 -1
  102. package/src/styles-areas/disk-usage.css +1 -1
  103. package/src/styles-areas/fields.css +1 -1
  104. package/src/styles-areas/master-detail.css +1 -1
  105. package/src/styles-areas/master-lock.css +108 -2
  106. package/src/styles-areas/media-gallery.css +1 -1
  107. package/src/styles-areas/media.css +1 -17
  108. package/src/styles-areas/nav.css +1 -1
  109. package/src/styles-areas/notifications.css +1 -1
  110. package/src/styles-areas/spreadsheet.css +1 -1
  111. package/src/styles-areas/stats.css +1 -1
  112. package/src/styles-areas/wizard.css +1 -1
  113. package/src/styles-areas/workbook-viewer.css +1 -1
  114. package/src/styles-utilities.css +0 -16
  115. package/src/testing/_noBun.ts +12 -0
  116. package/src/verifyGraph.spec.ts +11 -0
  117. package/dist/react/media/PrivateIndexView.d.ts +0 -6
  118. package/dist/react/media/PrivateIndexView.d.ts.map +0 -1
  119. package/dist/react/media/PrivateIndexView.js +0 -44
  120. package/dist/react/media/PrivateIndexView.js.map +0 -1
  121. package/dist/react/media/PrivateModeBadge.d.ts +0 -17
  122. package/dist/react/media/PrivateModeBadge.d.ts.map +0 -1
  123. package/dist/react/media/PrivateModeBadge.js +0 -24
  124. package/dist/react/media/PrivateModeBadge.js.map +0 -1
  125. package/dist/react/media/privateClient.d.ts +0 -34
  126. package/dist/react/media/privateClient.d.ts.map +0 -1
  127. package/dist/react/media/privateClient.js +0 -36
  128. package/dist/react/media/privateClient.js.map +0 -1
  129. package/dist/react/media/usePrivateUnlock.d.ts +0 -25
  130. package/dist/react/media/usePrivateUnlock.d.ts.map +0 -1
  131. package/dist/react/media/usePrivateUnlock.js +0 -68
  132. package/dist/react/media/usePrivateUnlock.js.map +0 -1
  133. package/src/react/media/PrivateIndexView.tsx +0 -113
  134. package/src/react/media/PrivateModeBadge.tsx +0 -50
  135. package/src/react/media/privateClient.spec.ts +0 -113
  136. package/src/react/media/privateClient.ts +0 -82
  137. package/src/react/media/usePrivateUnlock.ts +0 -132
@@ -1,7 +1,6 @@
1
1
  import { Upload } from 'lucide-react';
2
2
  import { type ReactNode, useMemo, useRef, useState } from 'react';
3
3
  import { Button } from '../components/Button.js';
4
- import { Checkbox } from '../components/Checkbox.js';
5
4
  import { Input } from '../components/Input.js';
6
5
  import { cn } from '../lib/cn.js';
7
6
  import { createFileUploadClient } from './fileUploadClient.js';
@@ -12,8 +11,8 @@ import { createFileUploadClient } from './fileUploadClient.js';
12
11
  // no ENGINE-model consumer, but three shipping plugins render it
13
12
  // (`plugin-photo-gallery`, `plugin-video-gallery`, `plugin-media-gallery`), so
14
13
  // deleting it would break them. It speaks the legacy chunked `/_files` protocol
15
- // (`createFileUploadClient` + `createFilesStack`), including the tag list and the
16
- // X-Unlock-Token private mode that protocol supports.
14
+ // (`createFileUploadClient` + `createFilesStack`), including the tag list. (Its private
15
+ // mode went with the server's private-media module — task 108.)
17
16
  //
18
17
  // The ENGINE model uploads through `POST /api/asset/vault/upload` — raw bytes,
19
18
  // `x-cc-filename`, checksum computed while streaming, content-addressed dedupe —
@@ -25,19 +24,16 @@ import { createFileUploadClient } from './fileUploadClient.js';
25
24
  //
26
25
  // ── Media upload control ─────────────────────────────────────────────────────────
27
26
  // The one "⬆ Upload" affordance media galleries share: a disclosure button opening a
28
- // compact form — comma-separated tags, a Private toggle (only while an unlock token is
29
- // present), and a file picker — feeding the shared upload client (chunked-aware, private
30
- // via X-Unlock-Token). Consumers own only WHERE it sits and what happens after.
27
+ // compact form — comma-separated tags and a file picker — feeding the shared upload client
28
+ // (chunked-aware). Consumers own only WHERE it sits and what happens after.
31
29
 
32
30
  export interface MediaUploadControlProps {
33
31
  /** File-picker accept filter, e.g. "video/*" or "image/*". */
34
32
  accept: string;
35
33
  /** Mount prefix of the host's file routes (createFilesStack filesBasePath). */
36
34
  basePath: string;
37
- /** Unlock token while private mode is on — reveals the Private toggle. */
38
- privateToken?: string | null;
39
- /** After every successful batch: `wasPrivate` says which list to refresh. */
40
- onUploaded: (result: { wasPrivate: boolean }) => void;
35
+ /** After every successful batch. */
36
+ onUploaded: () => void;
41
37
  label?: ReactNode;
42
38
  className?: string;
43
39
  }
@@ -45,14 +41,12 @@ export interface MediaUploadControlProps {
45
41
  export function MediaUploadControl({
46
42
  accept,
47
43
  basePath,
48
- privateToken = null,
49
44
  onUploaded,
50
45
  label = 'Upload',
51
46
  className,
52
47
  }: MediaUploadControlProps) {
53
48
  const [open, setOpen] = useState(false);
54
49
  const [tags, setTags] = useState('');
55
- const [asPrivate, setAsPrivate] = useState(false);
56
50
  const [busy, setBusy] = useState(false);
57
51
  const [error, setError] = useState<string | null>(null);
58
52
  const inputRef = useRef<HTMLInputElement>(null);
@@ -62,19 +56,13 @@ export function MediaUploadControl({
62
56
  const uploadFiles = async (list: FileList) => {
63
57
  setBusy(true);
64
58
  setError(null);
65
- const wantPrivate = asPrivate && !!privateToken;
66
59
  const parsedTags = tags
67
60
  .split(',')
68
61
  .map((t) => t.trim())
69
62
  .filter(Boolean);
70
63
  try {
71
64
  for (const file of Array.from(list)) {
72
- const res = wantPrivate
73
- ? await client.uploadPrivate(file, {
74
- tags: parsedTags,
75
- unlockToken: privateToken,
76
- })
77
- : await client.uploadAuto(file, { tags: parsedTags });
65
+ const res = await client.uploadAuto(file, { tags: parsedTags });
78
66
  if (!res.ok) {
79
67
  setError(res.error);
80
68
  return;
@@ -82,8 +70,7 @@ export function MediaUploadControl({
82
70
  }
83
71
  setOpen(false);
84
72
  setTags('');
85
- setAsPrivate(false);
86
- onUploaded({ wasPrivate: wantPrivate });
73
+ onUploaded();
87
74
  } finally {
88
75
  setBusy(false);
89
76
  }
@@ -113,14 +100,6 @@ export function MediaUploadControl({
113
100
  className='max-w-[200px]'
114
101
  aria-label='Upload tags'
115
102
  />
116
- {privateToken ? (
117
- <Checkbox
118
- checked={asPrivate}
119
- onCheckedChange={(checked) => setAsPrivate(checked === true)}
120
- disabled={busy}
121
- label='Private'
122
- />
123
- ) : null}
124
103
  <Button
125
104
  size='sm'
126
105
  disabled={busy}
@@ -4,8 +4,13 @@ import { sessionAuthHeaders } from '../sessionAuth.js';
4
4
  // ── File-upload client (hook-free) ───────────────────────────────────────────────
5
5
  // The one client for mountFileRoutes' upload edge, shared by every consumer (the files
6
6
  // plugin, gallery upload buttons, the video editor's save-back) so the header protocol
7
- // (X-Filename / X-Tags / X-Unlock-Token) and the chunked-vs-streamed decision live in
8
- // exactly one place. Hook-free like privateClient: plugins hold no upload state.
7
+ // (X-Filename / X-Tags) and the chunked-vs-streamed decision live in exactly one place.
8
+ // Hook-free: plugins hold no upload state.
9
+ //
10
+ // 🔴 There is no private upload any more (task 108, 2026-09-23). `uploadPrivate` PUT to
11
+ // `/_files/upload-private`, a route `cursedbelt-server` deleted with its private-media module
12
+ // (task 00-urgent-24), so the method was a 404 waiting for a caller. It went, with the rest of
13
+ // the private-media client tier, rather than staying as a method that cannot succeed.
9
14
 
10
15
  /** The FileRecord subset consumers act on after an upload (full shape: server files/types). */
11
16
  export type UploadedFile = {
@@ -35,12 +40,6 @@ export interface FileUploadClientConfig {
35
40
  export interface FileUploadClient {
36
41
  /** Streamed single-PUT public upload. */
37
42
  upload(file: File | Blob, opts?: { name?: string; tags?: string[] }): Promise<UploadOutcome>;
38
- /** Private (encrypted) upload — pass the unlock token of the already-unlocked session, or a
39
- * password for a deniable set; neither ⇒ the standard server-key set. */
40
- uploadPrivate(
41
- file: File | Blob,
42
- opts?: { name?: string; tags?: string[]; unlockToken?: string | null; password?: string },
43
- ): Promise<UploadOutcome>;
44
43
  /** Overwrite an existing file's bytes in place (same id; tags/collections survive). */
45
44
  replace(
46
45
  fileId: string,
@@ -163,15 +162,6 @@ export function createFileUploadClient(cfg: FileUploadClientConfig = {}): FileUp
163
162
  return {
164
163
  upload,
165
164
 
166
- async uploadPrivate(file, opts) {
167
- const headers = commonHeaders(file, opts);
168
- if (opts?.unlockToken) headers['X-Unlock-Token'] = opts.unlockToken;
169
- else if (opts?.password) headers['X-Private-Password'] = opts.password;
170
- return outcome(
171
- await doFetch(`${base}/upload-private`, { method: 'PUT', headers, body: file }),
172
- );
173
- },
174
-
175
165
  async replace(fileId, file, opts) {
176
166
  return outcome(
177
167
  await doFetch(`${base}/replace/${fileId}`, {
@@ -339,7 +339,10 @@ export function attachHlsSource(
339
339
  // guidance: calling `recoverMediaError()` twice for the same stall recovers
340
340
  // nothing, and the audio-codec swap is what clears the case that keeps recurring.
341
341
  if (attempt === 0) hls.recoverMediaError();
342
- else hls.swapAudioCodec?.(), hls.recoverMediaError();
342
+ else {
343
+ hls.swapAudioCodec?.();
344
+ hls.recoverMediaError();
345
+ }
343
346
  return;
344
347
  }
345
348
  if (data.type === Hls.ErrorTypes.NETWORK_ERROR) {
@@ -145,15 +145,6 @@ export {
145
145
  probeMediaDurationFromUrl,
146
146
  useMediaDuration,
147
147
  } from './mediaProbe.js';
148
- export { PrivateIndexView } from './PrivateIndexView.js';
149
- export { PrivateModeBadge, type PrivateModeBadgeProps } from './PrivateModeBadge.js';
150
- export {
151
- type PrivateClientConfig,
152
- privateFileUrlWithToken,
153
- privateHlsUrlWithToken,
154
- revealPrivateWithPassword,
155
- revealPrivateWithToken,
156
- } from './privateClient.js';
157
148
  export type {
158
149
  ImageEditorMode,
159
150
  ImageEditorOperation,
@@ -168,13 +159,6 @@ export type {
168
159
  export { type UseAudioPeaksOptions, useAudioPeaks } from './useAudioPeaks.js';
169
160
  export { useIntersectionObserver } from './useIntersectionObserver.js';
170
161
  export { useObjectUrl } from './useObjectUrl.js';
171
- export {
172
- type PrivateIndexRow,
173
- type PrivateUnlock,
174
- type RevealedItem,
175
- type UsePrivateUnlockOptions,
176
- usePrivateUnlock,
177
- } from './usePrivateUnlock.js';
178
162
  // Attaching an adaptive ladder to a bare `<video>` — native HLS first, hls.js second, the
179
163
  // progressive remux always. Exported because three surfaces in the fleet drive a plain
180
164
  // element rather than Vidstack and each was carrying its own copy of the decision.
@@ -1,6 +1,6 @@
1
1
  // ── Session auth headers (hook-free) ────────────────────────────────────────
2
2
  // One source of truth for "turn the browser session into a Bearer header". Plugins
3
- // that call guarded endpoints (uploads, the private-media client, RPC over fetch)
3
+ // that call guarded endpoints (uploads, RPC over fetch)
4
4
  // all need the same header shape; before this they each re-rolled the cookie read.
5
5
  //
6
6
  // NOTE (genapp-34): a generated app's `session` cookie is now `HttpOnly`, so this
@@ -19,8 +19,7 @@
19
19
  *
20
20
  * Shaped as a plain function (not a hook) so it can be passed straight to helpers
21
21
  * that expect an `authHeaders: () => Record<string, string>` callback
22
- * (`revealPrivateWithToken`, `privateHlsUrlWithToken`, …) and spread into a
23
- * `fetch` init's headers.
22
+ * (`createFileUploadClient`'s, for one) and spread into a `fetch` init's headers.
24
23
  */
25
24
  export function sessionAuthHeaders(): Record<string, string> {
26
25
  const token =
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Every `bun run <x>` a script calls, and every command the app manifest names, is a script
3
+ * that EXISTS in this `package.json`.
4
+ *
5
+ * 🔴 Task 102, 2026-09-18: `done:serial` was `typecheck && lint && test && build`, and there was
6
+ * no `lint` script — so it had never once reached `test` or `build`, and the 31 lint errors a
7
+ * `lint` would have shown sat unseen. `format` was named in `cursed.app.extraCommands` too.
8
+ * Neither was in the gate, which is exactly why nobody noticed; this spec is in the gate.
9
+ */
10
+ import { describe, expect, it } from 'bun:test';
11
+ import pkg from '../package.json';
12
+
13
+ const scripts = (pkg as { scripts: Record<string, string> }).scripts;
14
+
15
+ /** The script names a command line invokes through `bun run` / `npm run`. */
16
+ export function calledScripts(command: string): string[] {
17
+ const out: string[] = [];
18
+ for (const m of command.matchAll(/\b(?:bun|npm|pnpm|yarn) run\s+([A-Za-z0-9:_./-]+)/g)) {
19
+ // A path (`bun run scripts/x.ts`) is a file, not a script name.
20
+ if (m[1] && !m[1].includes('/') && !/\.[cm]?[jt]sx?$/.test(m[1])) out.push(m[1]);
21
+ }
22
+ return out;
23
+ }
24
+
25
+ describe('package.json scripts resolve', () => {
26
+ it('reads `bun run <name>` and skips `bun run <file>`', () => {
27
+ expect(calledScripts('bun run typecheck && bun run lint && bun run scripts/gate.ts')).toEqual([
28
+ 'typecheck',
29
+ 'lint',
30
+ ]);
31
+ });
32
+
33
+ it('🔴 fails on a script that calls one that is not there — the task-102 shape', () => {
34
+ const fake = { 'done:serial': 'bun run typecheck && bun run lint', typecheck: 'tsc' };
35
+ const dangling = Object.values(fake)
36
+ .flatMap(calledScripts)
37
+ .filter((name) => !(name in fake));
38
+ expect(dangling).toEqual(['lint']);
39
+ });
40
+
41
+ it('every `bun run <script>` inside a script names a script that exists', () => {
42
+ const dangling: string[] = [];
43
+ for (const [name, command] of Object.entries(scripts)) {
44
+ for (const called of calledScripts(command)) {
45
+ if (!(called in scripts)) dangling.push(`${name} → ${called}`);
46
+ }
47
+ }
48
+ expect(dangling).toEqual([]);
49
+ });
50
+
51
+ it('every command the `cursed.app` manifest names is a script', () => {
52
+ const app = (pkg as { cursed?: { app?: Record<string, unknown> } }).cursed?.app ?? {};
53
+ const named: string[] = [];
54
+ for (const key of ['commands', 'extraCommands']) {
55
+ const block = app[key] as Record<string, string> | undefined;
56
+ if (block) named.push(...Object.values(block));
57
+ }
58
+ expect(named.length).toBeGreaterThan(0);
59
+ expect(named.filter((n) => !(n in scripts))).toEqual([]);
60
+ });
61
+
62
+ it('every gate stage is a script', () => {
63
+ const stages = (pkg as { gate?: { stages?: { script: string }[] } }).gate?.stages ?? [];
64
+ expect(stages.map((s) => s.script).filter((n) => !(n in scripts))).toEqual([]);
65
+ });
66
+ });
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 72 candidate(s) scanned.
18
+ * when this file is stale. 71 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 300 candidate(s) scanned.
18
+ * when this file is stale. 303 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 463 candidate(s) scanned.
18
+ * when this file is stale. 462 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 348 candidate(s) scanned.
18
+ * when this file is stale. 388 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
15
15
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
16
- * when this file is stale. 5187 candidate(s) scanned.
16
+ * when this file is stale. 5197 candidate(s) scanned.
17
17
  *
18
18
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
19
19
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 1349 candidate(s) scanned.
18
+ * when this file is stale. 1350 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 290 candidate(s) scanned.
18
+ * when this file is stale. 289 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 613 candidate(s) scanned.
18
+ * when this file is stale. 616 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 195 candidate(s) scanned.
18
+ * when this file is stale. 198 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,12 +15,118 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 147 candidate(s) scanned.
18
+ * when this file is stale. 189 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
22
22
  * import closures rather than a hand-written list, is scripts/styleAreas.ts.
23
23
  */
24
24
  /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
25
+ @layer properties;
25
26
  @layer theme, base, components, utilities;
26
- @layer utilities;
27
+ @layer utilities {
28
+ .self-stretch {
29
+ align-self: stretch;
30
+ }
31
+ .focus-within\:border-field-ring:focus-within {
32
+ border-color: var(--field-ring);
33
+ }
34
+ .focus-within\:ring-2:focus-within {
35
+ --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
36
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
37
+ }
38
+ .focus-within\:ring-field-ring\/30:focus-within {
39
+ --tw-ring-color: var(--field-ring);
40
+ @supports (color: color-mix(in lab, red, red)) {
41
+ --tw-ring-color: color-mix(in oklab, var(--field-ring) 30%, transparent);
42
+ }
43
+ }
44
+ .has-\[\[aria-invalid\=true\]\]\:border-field-error:has(:is([aria-invalid=true])) {
45
+ border-color: var(--field-error);
46
+ }
47
+ }
48
+ @property --tw-shadow {
49
+ syntax: "*";
50
+ inherits: false;
51
+ initial-value: 0 0 #0000;
52
+ }
53
+ @property --tw-shadow-color {
54
+ syntax: "*";
55
+ inherits: false;
56
+ }
57
+ @property --tw-shadow-alpha {
58
+ syntax: "<percentage>";
59
+ inherits: false;
60
+ initial-value: 100%;
61
+ }
62
+ @property --tw-inset-shadow {
63
+ syntax: "*";
64
+ inherits: false;
65
+ initial-value: 0 0 #0000;
66
+ }
67
+ @property --tw-inset-shadow-color {
68
+ syntax: "*";
69
+ inherits: false;
70
+ }
71
+ @property --tw-inset-shadow-alpha {
72
+ syntax: "<percentage>";
73
+ inherits: false;
74
+ initial-value: 100%;
75
+ }
76
+ @property --tw-ring-color {
77
+ syntax: "*";
78
+ inherits: false;
79
+ }
80
+ @property --tw-ring-shadow {
81
+ syntax: "*";
82
+ inherits: false;
83
+ initial-value: 0 0 #0000;
84
+ }
85
+ @property --tw-inset-ring-color {
86
+ syntax: "*";
87
+ inherits: false;
88
+ }
89
+ @property --tw-inset-ring-shadow {
90
+ syntax: "*";
91
+ inherits: false;
92
+ initial-value: 0 0 #0000;
93
+ }
94
+ @property --tw-ring-inset {
95
+ syntax: "*";
96
+ inherits: false;
97
+ }
98
+ @property --tw-ring-offset-width {
99
+ syntax: "<length>";
100
+ inherits: false;
101
+ initial-value: 0px;
102
+ }
103
+ @property --tw-ring-offset-color {
104
+ syntax: "*";
105
+ inherits: false;
106
+ initial-value: #fff;
107
+ }
108
+ @property --tw-ring-offset-shadow {
109
+ syntax: "*";
110
+ inherits: false;
111
+ initial-value: 0 0 #0000;
112
+ }
113
+ @layer properties {
114
+ @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
115
+ *, ::before, ::after, ::backdrop {
116
+ --tw-shadow: 0 0 #0000;
117
+ --tw-shadow-color: initial;
118
+ --tw-shadow-alpha: 100%;
119
+ --tw-inset-shadow: 0 0 #0000;
120
+ --tw-inset-shadow-color: initial;
121
+ --tw-inset-shadow-alpha: 100%;
122
+ --tw-ring-color: initial;
123
+ --tw-ring-shadow: 0 0 #0000;
124
+ --tw-inset-ring-color: initial;
125
+ --tw-inset-ring-shadow: 0 0 #0000;
126
+ --tw-ring-inset: initial;
127
+ --tw-ring-offset-width: 0px;
128
+ --tw-ring-offset-color: #fff;
129
+ --tw-ring-offset-shadow: 0 0 #0000;
130
+ }
131
+ }
132
+ }
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 2162 candidate(s) scanned.
18
+ * when this file is stale. 2159 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 2849 candidate(s) scanned.
18
+ * when this file is stale. 2777 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -156,9 +156,6 @@
156
156
  border-block-style: var(--tw-border-style);
157
157
  border-block-width: 2px;
158
158
  }
159
- .border-\[color\:var\(--border-strong\)\] {
160
- border-color: var(--border-strong);
161
- }
162
159
  .border-accent {
163
160
  border-color: var(--accent);
164
161
  }
@@ -171,12 +168,6 @@
171
168
  border-color: color-mix(in oklab, var(--color-white) 90%, transparent);
172
169
  }
173
170
  }
174
- .bg-\[color\:color-mix\(in_srgb\,var\(--accent-solid\)_8\%\,transparent\)\] {
175
- background-color: var(--accent-solid);
176
- @supports (color: color-mix(in lab, red, red)) {
177
- background-color: color-mix(in srgb,var(--accent-solid) 8%,transparent);
178
- }
179
- }
180
171
  .bg-accent\/15 {
181
172
  background-color: var(--accent);
182
173
  @supports (color: color-mix(in lab, red, red)) {
@@ -283,9 +274,6 @@
283
274
  .text-\[color\:var\(--accent\)\] {
284
275
  color: var(--accent);
285
276
  }
286
- .text-\[color\:var\(--muted-foreground\)\] {
287
- color: var(--muted-foreground);
288
- }
289
277
  .accent-white {
290
278
  accent-color: var(--color-white);
291
279
  }
@@ -322,10 +310,6 @@
322
310
  .group-focus-within\:opacity-100:is(:where(.group):focus-within *) {
323
311
  opacity: 100%;
324
312
  }
325
- .last\:border-b-0:last-child {
326
- border-bottom-style: var(--tw-border-style);
327
- border-bottom-width: 0px;
328
- }
329
313
  .focus-within\:opacity-100:focus-within {
330
314
  opacity: 100%;
331
315
  }
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 800 candidate(s) scanned.
18
+ * when this file is stale. 799 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 232 candidate(s) scanned.
18
+ * when this file is stale. 231 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 166 candidate(s) scanned.
18
+ * when this file is stale. 165 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 361 candidate(s) scanned.
18
+ * when this file is stale. 360 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 389 candidate(s) scanned.
18
+ * when this file is stale. 392 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 247 candidate(s) scanned.
18
+ * when this file is stale. 246 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -1591,9 +1591,6 @@
1591
1591
  --tw-border-style: solid;
1592
1592
  border-style: solid;
1593
1593
  }
1594
- .border-\[color\:var\(--border-strong\)\] {
1595
- border-color: var(--border-strong);
1596
- }
1597
1594
  .border-\[var\(--border\)\] {
1598
1595
  border-color: var(--border);
1599
1596
  }
@@ -1741,12 +1738,6 @@
1741
1738
  .border-l-warning {
1742
1739
  border-left-color: var(--warning);
1743
1740
  }
1744
- .bg-\[color\:color-mix\(in_srgb\,var\(--accent-solid\)_8\%\,transparent\)\] {
1745
- background-color: var(--accent-solid);
1746
- @supports (color: color-mix(in lab, red, red)) {
1747
- background-color: color-mix(in srgb,var(--accent-solid) 8%,transparent);
1748
- }
1749
- }
1750
1741
  .bg-\[var\(--accent\)\]\/12 {
1751
1742
  background-color: var(--accent);
1752
1743
  @supports (color: color-mix(in lab, red, red)) {
@@ -2626,9 +2617,6 @@
2626
2617
  .text-\[color\:var\(--accent\)\] {
2627
2618
  color: var(--accent);
2628
2619
  }
2629
- .text-\[color\:var\(--muted-foreground\)\] {
2630
- color: var(--muted-foreground);
2631
- }
2632
2620
  .text-\[var\(--danger\)\] {
2633
2621
  color: var(--danger);
2634
2622
  }
@@ -3299,10 +3287,6 @@
3299
3287
  border-right-style: var(--tw-border-style);
3300
3288
  border-right-width: 0px;
3301
3289
  }
3302
- .last\:border-b-0:last-child {
3303
- border-bottom-style: var(--tw-border-style);
3304
- border-bottom-width: 0px;
3305
- }
3306
3290
  .last\:pr-1:last-child {
3307
3291
  padding-right: var(--spacing);
3308
3292
  }