@tonyclaw/agent-inspector 2.1.15 → 2.1.16

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 (65) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-BcEd6V-V.js → CompareDrawer-Ccrrcx1j.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-DLqClc9A.js +106 -0
  4. package/.output/public/assets/{ReplayDialog-BNpC0548.js → ReplayDialog-C7axhr-l.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-Ds1uRLVB.js → RequestAnatomy-WOptg8j_.js} +1 -1
  6. package/.output/public/assets/{ResponseView-7KPVqKl5.js → ResponseView-CSAcxh_M.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-BHQT261s.js → StreamingChunkSequence-DJS5KhPx.js} +1 -1
  8. package/.output/public/assets/_sessionId-DUSalzKH.js +1 -0
  9. package/.output/public/assets/index-BPpA21dY.css +1 -0
  10. package/.output/public/assets/index-Bt0Az2I2.js +1 -0
  11. package/.output/public/assets/{index-DjKt8XKe.js → index-DMPNh46t.js} +1 -1
  12. package/.output/public/assets/{json-viewer-CkCu-rka.js → json-viewer-inX5QSa3.js} +1 -1
  13. package/.output/public/assets/{main-DpD1N0S8.js → main-aCAKYGSD.js} +2 -2
  14. package/.output/server/_libs/lucide-react.mjs +207 -171
  15. package/.output/server/{_sessionId-DF9Sy8cP.mjs → _sessionId-C0fhvQnn.mjs} +2 -2
  16. package/.output/server/_ssr/{CompareDrawer-BoxztaO7.mjs → CompareDrawer-CO-Ti5sg.mjs} +3 -3
  17. package/.output/server/_ssr/{ProxyViewerContainer-CRBkqFlJ.mjs → ProxyViewerContainer-N4J7uBCX.mjs} +807 -386
  18. package/.output/server/_ssr/{ReplayDialog-Cc1dyDuK.mjs → ReplayDialog-J1VxC0In.mjs} +4 -4
  19. package/.output/server/_ssr/{RequestAnatomy-CMGSsz5Z.mjs → RequestAnatomy-DBH-F3rq.mjs} +3 -3
  20. package/.output/server/_ssr/{ResponseView-Cp10DM1D.mjs → ResponseView-DLFwV7Hd.mjs} +3 -3
  21. package/.output/server/_ssr/{StreamingChunkSequence-B1VGxy3A.mjs → StreamingChunkSequence-BywmuND0.mjs} +3 -3
  22. package/.output/server/_ssr/{index-47XVPghS.mjs → index-CStymIc0.mjs} +2 -2
  23. package/.output/server/_ssr/index.mjs +2 -2
  24. package/.output/server/_ssr/{json-viewer-zDE2rrmJ.mjs → json-viewer-DlQu0N1x.mjs} +3 -3
  25. package/.output/server/_ssr/{router-DVeuZFqI.mjs → router-CQ4Zxhmr.mjs} +112 -46
  26. package/.output/server/{_tanstack-start-manifest_v-Bp8JxtPW.mjs → _tanstack-start-manifest_v-BHeJBGfo.mjs} +1 -1
  27. package/.output/server/index.mjs +72 -72
  28. package/package.json +1 -1
  29. package/src/components/ProxyViewer.tsx +146 -105
  30. package/src/components/ProxyViewerContainer.tsx +77 -67
  31. package/src/components/alerts/AlertsDialog.tsx +2 -1
  32. package/src/components/clients/ClientLogo.tsx +1 -1
  33. package/src/components/groups/GroupsDialog.tsx +19 -1
  34. package/src/components/providers/ProviderCard.tsx +1 -1
  35. package/src/components/providers/ProviderForm.tsx +18 -18
  36. package/src/components/providers/ProviderLogo.tsx +6 -1
  37. package/src/components/providers/ProvidersPanel.tsx +6 -6
  38. package/src/components/providers/SettingsDialog.tsx +13 -6
  39. package/src/components/proxy-viewer/AgentTraceSummary.tsx +6 -6
  40. package/src/components/proxy-viewer/ConversationGroup.tsx +43 -32
  41. package/src/components/proxy-viewer/ConversationGroupList.tsx +452 -89
  42. package/src/components/proxy-viewer/ConversationHeader.tsx +44 -32
  43. package/src/components/proxy-viewer/LogEntry.tsx +21 -17
  44. package/src/components/proxy-viewer/LogEntryHeader.tsx +38 -45
  45. package/src/components/proxy-viewer/ProviderLogoStack.tsx +2 -2
  46. package/src/components/proxy-viewer/RequestToolsPanel.tsx +9 -9
  47. package/src/components/proxy-viewer/ThreadConnector.tsx +4 -4
  48. package/src/components/proxy-viewer/TurnGroup.tsx +16 -11
  49. package/src/components/proxy-viewer/TurnGroupList.tsx +3 -0
  50. package/src/components/proxy-viewer/viewerState.ts +0 -4
  51. package/src/components/ui/icon-trigger.ts +2 -0
  52. package/src/components/ui/transient-toast.tsx +104 -0
  53. package/src/lib/sessionInfoContract.ts +4 -0
  54. package/src/mcp/server.ts +71 -27
  55. package/src/mcp/toolHandlers.ts +23 -4
  56. package/src/proxy/formats/openai/alibabaProvider.ts +0 -4
  57. package/src/proxy/sessionInfo.ts +31 -2
  58. package/src/proxy/sessionSupervisor.ts +20 -1
  59. package/src/proxy/store.ts +1 -1
  60. package/src/routes/api/providers.$providerId.test.log.ts +8 -4
  61. package/styles/globals.css +180 -180
  62. package/.output/public/assets/ProxyViewerContainer-h851qWNp.js +0 -106
  63. package/.output/public/assets/_sessionId-DWePGjnS.js +0 -1
  64. package/.output/public/assets/index-CI1-G8ua.js +0 -1
  65. package/.output/public/assets/index-DdhFqPsI.css +0 -1
@@ -60,6 +60,18 @@ function normalizeExplicitSessionId(sessionId: string | null | undefined): strin
60
60
  return trimmed.length > 0 ? trimmed : null;
61
61
  }
62
62
 
63
+ export function buildProviderTestSessionId(providerId: string): string {
64
+ const normalizedProviderId = normalizeExplicitSessionId(providerId);
65
+ if (normalizedProviderId === null) return PROVIDER_TEST_SESSION_ID;
66
+ return `${PROVIDER_TEST_SESSION_ID}:${normalizedProviderId}`;
67
+ }
68
+
69
+ function isProviderTestSessionId(sessionId: string): boolean {
70
+ return (
71
+ sessionId === PROVIDER_TEST_SESSION_ID || sessionId.startsWith(`${PROVIDER_TEST_SESSION_ID}:`)
72
+ );
73
+ }
74
+
63
75
  function buildClientSessionId(clientInfo: SessionClientInfo): SessionIdentity {
64
76
  const projectFolder = normalizeExplicitSessionId(clientInfo.projectFolder);
65
77
 
@@ -88,11 +100,18 @@ export function resolveSessionIdentity(input: {
88
100
  clientInfo?: SessionClientInfo;
89
101
  isTest?: boolean;
90
102
  }): SessionIdentity {
103
+ const explicit = normalizeExplicitSessionId(input.explicitSessionId);
104
+
91
105
  if (input.isTest === true) {
106
+ if (explicit !== null) {
107
+ return {
108
+ id: explicit,
109
+ source: isProviderTestSessionId(explicit) ? "provider-test" : "explicit",
110
+ };
111
+ }
92
112
  return { id: PROVIDER_TEST_SESSION_ID, source: "provider-test" };
93
113
  }
94
114
 
95
- const explicit = normalizeExplicitSessionId(input.explicitSessionId);
96
115
  if (explicit !== null) {
97
116
  return { id: explicit, source: "explicit" };
98
117
  }
@@ -322,7 +322,7 @@ function prepareLogForList(log: CapturedLog, includeBodies: boolean): CapturedLo
322
322
 
323
323
  /**
324
324
  * Add a test log entry to the in-memory store and persistent log file.
325
- * This is used by the provider test endpoint to seed the provider-test session.
325
+ * This is used by the provider test endpoint to seed provider-test sessions.
326
326
  */
327
327
  export async function addTestLogEntry(entry: Omit<CapturedLog, "id">): Promise<CapturedLog> {
328
328
  const id = await getNextLogId();
@@ -2,6 +2,7 @@ import { createFileRoute } from "@tanstack/react-router";
2
2
  import { getProvider, getModelUsageName } from "../../proxy/providers";
3
3
  import { addTestLogEntry } from "../../proxy/store";
4
4
  import { getConfig } from "../../proxy/config";
5
+ import { buildProviderTestSessionId } from "../../proxy/sessionSupervisor";
5
6
  import { buildProviderTestRequestBody } from "../../lib/providerTestPrompt";
6
7
  import {
7
8
  ProviderTestResultsSchema,
@@ -52,6 +53,7 @@ function getResultTokensPerSecond(result: TestResult): number | null {
52
53
  async function logModelResults(
53
54
  displayName: string,
54
55
  providerName: string,
56
+ providerSessionId: string,
55
57
  anthropicUrl: string | undefined,
56
58
  openaiUrl: string | undefined,
57
59
  modelResults: {
@@ -76,7 +78,7 @@ async function logModelResults(
76
78
  method: "POST",
77
79
  path: "/v1/messages",
78
80
  model: nonStreamingResult.model ?? displayName,
79
- sessionId: null,
81
+ sessionId: providerSessionId,
80
82
  rawRequestBody: requestBody,
81
83
  responseStatus: getResultResponseStatus(nonStreamingResult),
82
84
  responseText: getResultResponseText(nonStreamingResult),
@@ -106,7 +108,7 @@ async function logModelResults(
106
108
  method: "POST",
107
109
  path: "/v1/messages",
108
110
  model: streamingResult.model ?? displayName,
109
- sessionId: null,
111
+ sessionId: providerSessionId,
110
112
  rawRequestBody: streamingRequestBody,
111
113
  responseStatus: getResultResponseStatus(streamingResult),
112
114
  responseText: getResultResponseText(streamingResult),
@@ -144,7 +146,7 @@ async function logModelResults(
144
146
  method: "POST",
145
147
  path: "/v1/chat/completions",
146
148
  model: nonStreamingResult.model ?? displayName,
147
- sessionId: null,
149
+ sessionId: providerSessionId,
148
150
  rawRequestBody: requestBody,
149
151
  responseStatus: getResultResponseStatus(nonStreamingResult),
150
152
  responseText: getResultResponseText(nonStreamingResult),
@@ -174,7 +176,7 @@ async function logModelResults(
174
176
  method: "POST",
175
177
  path: "/v1/chat/completions",
176
178
  model: streamingResult.model ?? displayName,
177
- sessionId: null,
179
+ sessionId: providerSessionId,
178
180
  rawRequestBody: streamingRequestBody,
179
181
  responseStatus: getResultResponseStatus(streamingResult),
180
182
  responseText: getResultResponseText(streamingResult),
@@ -224,6 +226,7 @@ export const Route = createFileRoute("/api/providers/$providerId/test/log")({
224
226
  }
225
227
 
226
228
  const results = parsed.data;
229
+ const providerSessionId = buildProviderTestSessionId(params.providerId);
227
230
  const captureFullDetails = getConfig().captureMode === "full";
228
231
  const anthropicUrl =
229
232
  provider.anthropicBaseUrl !== undefined && provider.anthropicBaseUrl.length > 0
@@ -241,6 +244,7 @@ export const Route = createFileRoute("/api/providers/$providerId/test/log")({
241
244
  logModelResults(
242
245
  modelName,
243
246
  provider.name,
247
+ providerSessionId,
244
248
  anthropicUrl,
245
249
  openaiUrl,
246
250
  modelResult,
@@ -1,183 +1,183 @@
1
- @import "tailwindcss";
2
- @import "tw-animate-css";
3
- @plugin "@tailwindcss/typography";
4
-
5
- @custom-variant dark (&:is(.dark *));
6
-
7
- @theme inline {
8
- --color-background: var(--background);
9
- --color-foreground: var(--foreground);
10
- --color-sidebar-ring: var(--sidebar-ring);
11
- --color-sidebar-border: var(--sidebar-border);
12
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
13
- --color-sidebar-accent: var(--sidebar-accent);
14
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
15
- --color-sidebar-primary: var(--sidebar-primary);
16
- --color-sidebar-foreground: var(--sidebar-foreground);
17
- --color-sidebar: var(--sidebar);
18
- --color-chart-5: var(--chart-5);
19
- --color-chart-4: var(--chart-4);
20
- --color-chart-3: var(--chart-3);
21
- --color-chart-2: var(--chart-2);
22
- --color-chart-1: var(--chart-1);
23
- --color-ring: var(--ring);
24
- --color-input: var(--input);
25
- --color-border: var(--border);
26
- --color-destructive: var(--destructive);
27
- --color-accent-foreground: var(--accent-foreground);
28
- --color-accent: var(--accent);
29
- --color-muted-foreground: var(--muted-foreground);
30
- --color-muted: var(--muted);
31
- --color-secondary-foreground: var(--secondary-foreground);
32
- --color-secondary: var(--secondary);
33
- --color-primary-foreground: var(--primary-foreground);
34
- --color-primary: var(--primary);
35
- --color-popover-foreground: var(--popover-foreground);
36
- --color-popover: var(--popover);
37
- --color-card-foreground: var(--card-foreground);
38
- --color-card: var(--card);
39
- --radius-sm: calc(var(--radius) - 4px);
40
- --radius-md: calc(var(--radius) - 2px);
41
- --radius-lg: var(--radius);
42
- --radius-xl: calc(var(--radius) + 4px);
43
- --animate-crab-crawl: crab-crawl-down 0.6s ease-in-out infinite;
44
- --animate-crab-appear: crab-appear 300ms ease-out;
45
- --animate-crab-settle: crab-settle 400ms ease-in-out;
46
- --animate-crab-piano-pop: crab-piano-pop 400ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
47
- }
48
-
49
- :root {
50
- --radius: 0.625rem;
51
- --background: oklch(1 0 0);
52
- --foreground: oklch(0.145 0 0);
53
- --card: oklch(1 0 0);
54
- --card-foreground: oklch(0.145 0 0);
55
- --popover: oklch(1 0 0);
56
- --popover-foreground: oklch(0.145 0 0);
57
- --primary: oklch(0.205 0 0);
58
- --primary-foreground: oklch(0.985 0 0);
59
- --secondary: oklch(0.97 0 0);
60
- --secondary-foreground: oklch(0.205 0 0);
61
- --muted: oklch(0.97 0 0);
62
- --muted-foreground: oklch(0.556 0 0);
63
- --accent: oklch(0.97 0 0);
64
- --accent-foreground: oklch(0.205 0 0);
65
- --destructive: oklch(0.577 0.245 27.325);
66
- --border: oklch(0.922 0 0);
67
- --input: oklch(0.922 0 0);
68
- --ring: oklch(0.708 0 0);
69
- --chart-1: oklch(0.646 0.222 41.116);
70
- --chart-2: oklch(0.6 0.118 184.704);
71
- --chart-3: oklch(0.398 0.07 227.392);
72
- --chart-4: oklch(0.828 0.189 84.429);
73
- --chart-5: oklch(0.769 0.188 70.08);
74
- --sidebar: oklch(0.985 0 0);
75
- --sidebar-foreground: oklch(0.145 0 0);
76
- --sidebar-primary: oklch(0.205 0 0);
77
- --sidebar-primary-foreground: oklch(0.985 0 0);
78
- --sidebar-accent: oklch(0.97 0 0);
79
- --sidebar-accent-foreground: oklch(0.205 0 0);
80
- --sidebar-border: oklch(0.922 0 0);
81
- --sidebar-ring: oklch(0.708 0 0);
82
- }
83
-
84
- .dark {
85
- --background: oklch(0.145 0 0);
86
- --foreground: oklch(0.985 0 0);
87
- --card: oklch(0.205 0 0);
88
- --card-foreground: oklch(0.985 0 0);
89
- --popover: oklch(0.205 0 0);
90
- --popover-foreground: oklch(0.985 0 0);
91
- --primary: oklch(0.922 0 0);
92
- --primary-foreground: oklch(0.205 0 0);
93
- --secondary: oklch(0.269 0 0);
94
- --secondary-foreground: oklch(0.985 0 0);
95
- --muted: oklch(0.269 0 0);
96
- --muted-foreground: oklch(0.708 0 0);
97
- --accent: oklch(0.269 0 0);
98
- --accent-foreground: oklch(0.985 0 0);
99
- --destructive: oklch(0.704 0.191 22.216);
100
- --border: oklch(1 0 0 / 10%);
101
- --input: oklch(1 0 0 / 15%);
102
- --ring: oklch(0.556 0 0);
103
- --chart-1: oklch(0.488 0.243 264.376);
104
- --chart-2: oklch(0.696 0.17 162.48);
105
- --chart-3: oklch(0.769 0.188 70.08);
106
- --chart-4: oklch(0.627 0.265 303.9);
107
- --chart-5: oklch(0.645 0.246 16.439);
108
- --sidebar: oklch(0.205 0 0);
109
- --sidebar-foreground: oklch(0.985 0 0);
110
- --sidebar-primary: oklch(0.488 0.243 264.376);
111
- --sidebar-primary-foreground: oklch(0.985 0 0);
112
- --sidebar-accent: oklch(0.269 0 0);
113
- --sidebar-accent-foreground: oklch(0.985 0 0);
114
- --sidebar-border: oklch(1 0 0 / 10%);
115
- --sidebar-ring: oklch(0.556 0 0);
116
- }
117
-
118
- @keyframes crab-crawl-down {
119
- 0%, 100% {
120
- transform: translateY(0px);
121
- }
122
- 25% {
123
- transform: translateY(2px);
124
- }
125
- 75% {
126
- transform: translateY(-1px);
127
- }
128
- }
129
-
130
- @keyframes crab-appear {
131
- 0% {
132
- transform: scale(0.5);
133
- opacity: 0;
134
- }
135
- 100% {
136
- transform: scale(1);
137
- opacity: 1;
138
- }
139
- }
140
-
141
- @keyframes crab-settle {
142
- 0% {
143
- transform: scale(1);
144
- }
145
- 50% {
146
- transform: scale(1.15);
147
- }
148
- 100% {
149
- transform: scale(1);
150
- }
151
- }
152
-
153
- @keyframes crab-piano-pop {
154
- 0% {
155
- transform: scale(0) translateY(0);
156
- opacity: 0;
157
- }
158
- 60% {
159
- transform: scale(1.3) translateY(-4px);
160
- opacity: 1;
161
- }
162
- 100% {
163
- transform: scale(1) translateY(0);
164
- opacity: 1;
165
- }
166
- }
167
-
168
- @media (prefers-reduced-motion: reduce) {
169
- .animate-crab-piano-pop {
170
- animation: none !important;
171
- }
172
- }
173
-
174
- [data-deep-link-highlight="true"] {
175
- background: color-mix(in oklch, var(--chart-2) 18%, transparent);
176
- box-shadow:
177
- inset 0 0 0 1px color-mix(in oklch, var(--chart-2) 65%, transparent),
178
- 0 0 0 3px color-mix(in oklch, var(--chart-2) 20%, transparent);
179
- }
180
-
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @plugin "@tailwindcss/typography";
4
+
5
+ @custom-variant dark (&:is(.dark *));
6
+
7
+ @theme inline {
8
+ --color-background: var(--background);
9
+ --color-foreground: var(--foreground);
10
+ --color-sidebar-ring: var(--sidebar-ring);
11
+ --color-sidebar-border: var(--sidebar-border);
12
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
13
+ --color-sidebar-accent: var(--sidebar-accent);
14
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
15
+ --color-sidebar-primary: var(--sidebar-primary);
16
+ --color-sidebar-foreground: var(--sidebar-foreground);
17
+ --color-sidebar: var(--sidebar);
18
+ --color-chart-5: var(--chart-5);
19
+ --color-chart-4: var(--chart-4);
20
+ --color-chart-3: var(--chart-3);
21
+ --color-chart-2: var(--chart-2);
22
+ --color-chart-1: var(--chart-1);
23
+ --color-ring: var(--ring);
24
+ --color-input: var(--input);
25
+ --color-border: var(--border);
26
+ --color-destructive: var(--destructive);
27
+ --color-accent-foreground: var(--accent-foreground);
28
+ --color-accent: var(--accent);
29
+ --color-muted-foreground: var(--muted-foreground);
30
+ --color-muted: var(--muted);
31
+ --color-secondary-foreground: var(--secondary-foreground);
32
+ --color-secondary: var(--secondary);
33
+ --color-primary-foreground: var(--primary-foreground);
34
+ --color-primary: var(--primary);
35
+ --color-popover-foreground: var(--popover-foreground);
36
+ --color-popover: var(--popover);
37
+ --color-card-foreground: var(--card-foreground);
38
+ --color-card: var(--card);
39
+ --radius-sm: calc(var(--radius) - 4px);
40
+ --radius-md: calc(var(--radius) - 2px);
41
+ --radius-lg: var(--radius);
42
+ --radius-xl: calc(var(--radius) + 4px);
43
+ --animate-crab-crawl: crab-crawl-down 0.6s ease-in-out infinite;
44
+ --animate-crab-appear: crab-appear 300ms ease-out;
45
+ --animate-crab-settle: crab-settle 400ms ease-in-out;
46
+ --animate-crab-piano-pop: crab-piano-pop 400ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
47
+ }
48
+
49
+ :root {
50
+ --radius: 0.625rem;
51
+ --background: oklch(1 0 0);
52
+ --foreground: oklch(0.145 0 0);
53
+ --card: oklch(1 0 0);
54
+ --card-foreground: oklch(0.145 0 0);
55
+ --popover: oklch(1 0 0);
56
+ --popover-foreground: oklch(0.145 0 0);
57
+ --primary: oklch(0.205 0 0);
58
+ --primary-foreground: oklch(0.985 0 0);
59
+ --secondary: oklch(0.97 0 0);
60
+ --secondary-foreground: oklch(0.205 0 0);
61
+ --muted: oklch(0.97 0 0);
62
+ --muted-foreground: oklch(0.556 0 0);
63
+ --accent: oklch(0.97 0 0);
64
+ --accent-foreground: oklch(0.205 0 0);
65
+ --destructive: oklch(0.577 0.245 27.325);
66
+ --border: oklch(0.922 0 0);
67
+ --input: oklch(0.922 0 0);
68
+ --ring: oklch(0.708 0 0);
69
+ --chart-1: oklch(0.646 0.222 41.116);
70
+ --chart-2: oklch(0.6 0.118 184.704);
71
+ --chart-3: oklch(0.398 0.07 227.392);
72
+ --chart-4: oklch(0.828 0.189 84.429);
73
+ --chart-5: oklch(0.769 0.188 70.08);
74
+ --sidebar: oklch(0.985 0 0);
75
+ --sidebar-foreground: oklch(0.145 0 0);
76
+ --sidebar-primary: oklch(0.205 0 0);
77
+ --sidebar-primary-foreground: oklch(0.985 0 0);
78
+ --sidebar-accent: oklch(0.97 0 0);
79
+ --sidebar-accent-foreground: oklch(0.205 0 0);
80
+ --sidebar-border: oklch(0.922 0 0);
81
+ --sidebar-ring: oklch(0.708 0 0);
82
+ }
83
+
84
+ .dark {
85
+ --background: oklch(0.145 0 0);
86
+ --foreground: oklch(0.985 0 0);
87
+ --card: oklch(0.205 0 0);
88
+ --card-foreground: oklch(0.985 0 0);
89
+ --popover: oklch(0.205 0 0);
90
+ --popover-foreground: oklch(0.985 0 0);
91
+ --primary: oklch(0.922 0 0);
92
+ --primary-foreground: oklch(0.205 0 0);
93
+ --secondary: oklch(0.269 0 0);
94
+ --secondary-foreground: oklch(0.985 0 0);
95
+ --muted: oklch(0.269 0 0);
96
+ --muted-foreground: oklch(0.708 0 0);
97
+ --accent: oklch(0.269 0 0);
98
+ --accent-foreground: oklch(0.985 0 0);
99
+ --destructive: oklch(0.704 0.191 22.216);
100
+ --border: oklch(1 0 0 / 10%);
101
+ --input: oklch(1 0 0 / 15%);
102
+ --ring: oklch(0.556 0 0);
103
+ --chart-1: oklch(0.488 0.243 264.376);
104
+ --chart-2: oklch(0.696 0.17 162.48);
105
+ --chart-3: oklch(0.769 0.188 70.08);
106
+ --chart-4: oklch(0.627 0.265 303.9);
107
+ --chart-5: oklch(0.645 0.246 16.439);
108
+ --sidebar: oklch(0.205 0 0);
109
+ --sidebar-foreground: oklch(0.985 0 0);
110
+ --sidebar-primary: oklch(0.488 0.243 264.376);
111
+ --sidebar-primary-foreground: oklch(0.985 0 0);
112
+ --sidebar-accent: oklch(0.269 0 0);
113
+ --sidebar-accent-foreground: oklch(0.985 0 0);
114
+ --sidebar-border: oklch(1 0 0 / 10%);
115
+ --sidebar-ring: oklch(0.556 0 0);
116
+ }
117
+
118
+ @keyframes crab-crawl-down {
119
+ 0%, 100% {
120
+ transform: translateY(0px);
121
+ }
122
+ 25% {
123
+ transform: translateY(2px);
124
+ }
125
+ 75% {
126
+ transform: translateY(-1px);
127
+ }
128
+ }
129
+
130
+ @keyframes crab-appear {
131
+ 0% {
132
+ transform: scale(0.5);
133
+ opacity: 0;
134
+ }
135
+ 100% {
136
+ transform: scale(1);
137
+ opacity: 1;
138
+ }
139
+ }
140
+
141
+ @keyframes crab-settle {
142
+ 0% {
143
+ transform: scale(1);
144
+ }
145
+ 50% {
146
+ transform: scale(1.15);
147
+ }
148
+ 100% {
149
+ transform: scale(1);
150
+ }
151
+ }
152
+
153
+ @keyframes crab-piano-pop {
154
+ 0% {
155
+ transform: scale(0) translateY(0);
156
+ opacity: 0;
157
+ }
158
+ 60% {
159
+ transform: scale(1.3) translateY(-4px);
160
+ opacity: 1;
161
+ }
162
+ 100% {
163
+ transform: scale(1) translateY(0);
164
+ opacity: 1;
165
+ }
166
+ }
167
+
168
+ @media (prefers-reduced-motion: reduce) {
169
+ .animate-crab-piano-pop {
170
+ animation: none !important;
171
+ }
172
+ }
173
+
174
+ [data-deep-link-highlight="true"] {
175
+ background: color-mix(in oklch, var(--chart-2) 18%, transparent);
176
+ box-shadow:
177
+ inset 0 0 0 1px color-mix(in oklch, var(--chart-2) 65%, transparent),
178
+ 0 0 0 3px color-mix(in oklch, var(--chart-2) 20%, transparent);
179
+ }
180
+
181
181
  @layer base {
182
182
  * {
183
183
  @apply border-border outline-ring/50;