@retrivora-ai/rag-engine 2.2.5 → 2.2.6

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/server.js CHANGED
@@ -4808,7 +4808,7 @@ var ConfigValidator = class {
4808
4808
  // package.json
4809
4809
  var package_default = {
4810
4810
  name: "@retrivora-ai/rag-engine",
4811
- version: "2.2.5",
4811
+ version: "2.2.6",
4812
4812
  description: "Retrivora AI is a plug-and-play AI engine for RAG chat experiences \u2014 generic vector DB + LLM provider, embeddable or standalone.",
4813
4813
  author: "Abhinav Alkuchi",
4814
4814
  license: "UNLICENSED",
package/dist/server.mjs CHANGED
@@ -4711,7 +4711,7 @@ var ConfigValidator = class {
4711
4711
  // package.json
4712
4712
  var package_default = {
4713
4713
  name: "@retrivora-ai/rag-engine",
4714
- version: "2.2.5",
4714
+ version: "2.2.6",
4715
4715
  description: "Retrivora AI is a plug-and-play AI engine for RAG chat experiences \u2014 generic vector DB + LLM provider, embeddable or standalone.",
4716
4716
  author: "Abhinav Alkuchi",
4717
4717
  license: "UNLICENSED",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retrivora-ai/rag-engine",
3
- "version": "2.2.5",
3
+ "version": "2.2.6",
4
4
  "description": "Retrivora AI is a plug-and-play AI engine for RAG chat experiences — generic vector DB + LLM provider, embeddable or standalone.",
5
5
  "author": "Abhinav Alkuchi",
6
6
  "license": "UNLICENSED",
@@ -1,10 +1,9 @@
1
- 'use client';
2
-
3
1
  import React, { useState } from 'react';
4
- import { MessageSquare, X } from 'lucide-react';
2
+ import { MessageSquare, X, AlertTriangle } from 'lucide-react';
5
3
  import { ChatWindow } from './ChatWindow';
6
4
  import { useConfig } from './ConfigProvider';
7
5
  import { ChatWidgetProps } from '../types';
6
+ import { SDK_VERSION } from '../version';
8
7
 
9
8
  const DEFAULT_DIMENSIONS = { width: 380, height: 600 };
10
9
 
@@ -54,6 +53,8 @@ export function ChatWidget({ position = 'bottom-right', onAddToCart, apiUrl, ret
54
53
  const [isResizing, setIsResizing] = useState(false);
55
54
  const [isMaximized, setIsMaximized] = useState(false);
56
55
  const [prevDimensions, setPrevDimensions] = useState(DEFAULT_DIMENSIONS);
56
+ const [widgetError, setWidgetError] = useState<string | null>(null);
57
+ const [isValidating, setIsValidating] = useState(false);
57
58
 
58
59
  if (ui.showWidget === false) return null;
59
60
 
@@ -67,9 +68,50 @@ export function ChatWidget({ position = 'bottom-right', onAddToCart, apiUrl, ret
67
68
  ? 'bottom-20 left-6'
68
69
  : 'bottom-20 right-6';
69
70
 
70
- const handleOpen = () => {
71
- setIsOpen(true);
72
- setHasUnread(false);
71
+ const handleOpen = async () => {
72
+ setIsValidating(true);
73
+ try {
74
+ const base = retrivoraApiBase || '/api/retrivora';
75
+ const configUrl = `${base.replace(/\/$/, '')}/config?sdkVersion=${SDK_VERSION}`;
76
+ const res = await fetch(configUrl, {
77
+ method: 'GET',
78
+ cache: 'no-store',
79
+ headers: {
80
+ 'Content-Type': 'application/json',
81
+ 'x-sdk-version': SDK_VERSION,
82
+ ...(headers || {})
83
+ },
84
+ });
85
+
86
+ if (!res.ok) {
87
+ const data = await res.json().catch(() => ({}));
88
+ if (res.status === 426 || data.code === 'SDK_VERSION_OUTDATED') {
89
+ const msg = data.error || 'Your Retrivora SDK package version is outdated. Please update your package to the latest version to continue.';
90
+ setWidgetError(msg);
91
+ setIsOpen(false); // DO NOT OPEN CHAT WIDGET
92
+ return;
93
+ }
94
+ if (
95
+ res.status === 403 ||
96
+ res.status === 401 ||
97
+ (typeof data.error === 'string' && data.error.toLowerCase().includes('license'))
98
+ ) {
99
+ const msg = (typeof data.error === 'string' ? data.error : data.error?.message) || 'Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.';
100
+ setWidgetError(msg);
101
+ setIsOpen(false); // DO NOT OPEN CHAT WIDGET
102
+ return;
103
+ }
104
+ }
105
+
106
+ setWidgetError(null);
107
+ setIsOpen(true);
108
+ setHasUnread(false);
109
+ } catch {
110
+ // Fallback
111
+ setIsOpen(true);
112
+ } finally {
113
+ setIsValidating(false);
114
+ }
73
115
  };
74
116
 
75
117
  const handleResizeStart = (e: React.MouseEvent) => {
@@ -157,6 +199,33 @@ export function ChatWidget({ position = 'bottom-right', onAddToCart, apiUrl, ret
157
199
  />
158
200
  </div>
159
201
 
202
+ {/* ── Widget Error Toast/Pop-over (when opening is blocked) ── */}
203
+ {widgetError && !isOpen && (
204
+ <div
205
+ className={`fixed z-[9999] max-w-sm p-4 rounded-2xl shadow-2xl border border-rose-200 dark:border-rose-900/60 bg-white/95 dark:bg-[#0f0f1a]/95 backdrop-blur-xl transition-all duration-300 animate-in fade-in slide-in-from-bottom-3 ${
206
+ position === 'bottom-left' ? 'bottom-24 left-6' : 'bottom-24 right-6'
207
+ }`}
208
+ >
209
+ <div className="flex items-start gap-3">
210
+ <div className="w-8 h-8 rounded-xl bg-rose-100 dark:bg-rose-900/40 text-rose-600 dark:text-rose-400 flex items-center justify-center shrink-0 mt-0.5">
211
+ <AlertTriangle className="w-4 h-4" />
212
+ </div>
213
+ <div className="flex-1 space-y-1">
214
+ <h5 className="text-xs font-bold text-slate-900 dark:text-white">Access Blocked</h5>
215
+ <p className="text-[11px] text-slate-600 dark:text-slate-300 leading-relaxed font-medium">
216
+ {widgetError}
217
+ </p>
218
+ </div>
219
+ <button
220
+ onClick={() => setWidgetError(null)}
221
+ className="text-slate-400 hover:text-slate-600 dark:hover:text-white transition-colors p-1"
222
+ >
223
+ <X className="w-3.5 h-3.5" />
224
+ </button>
225
+ </div>
226
+ </div>
227
+ )}
228
+
160
229
  {/* ── Floating Action Button ── */}
161
230
  <button
162
231
  onClick={isOpen ? () => setIsOpen(false) : handleOpen}
@@ -7,6 +7,7 @@ import {
7
7
  X,
8
8
  Sparkles,
9
9
  ArrowUp,
10
+ ArrowUpCircle,
10
11
  TriangleAlert,
11
12
  RotateCcw,
12
13
  Maximize2,
@@ -21,6 +22,7 @@ import { useConfig } from './ConfigProvider';
21
22
  import { useRagChat } from '../hooks/useRagChat';
22
23
  import { BORDER_RADIUS_MAP, CHAT_SUGGESTIONS } from '../config/uiConstants';
23
24
  import { ChatWindowProps } from '../types';
25
+ import { SDK_VERSION } from '../version';
24
26
 
25
27
  interface SpeechRecognitionEvent {
26
28
  resultIndex: number;
@@ -86,8 +88,58 @@ export function ChatWindow({
86
88
 
87
89
  const [isListening, setIsListening] = useState(false);
88
90
  const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
91
+ const [licenseError, setLicenseError] = useState<string | null>(null);
92
+ const [versionError, setVersionError] = useState<string | null>(null);
89
93
  const recognitionRef = useRef<ISpeechRecognition | null>(null);
90
94
 
95
+ // Validate server license and SDK version on ChatWindow session initialization
96
+ useEffect(() => {
97
+ let isMounted = true;
98
+ async function validateSessionLicense() {
99
+ try {
100
+ const base = retrivoraApiBase || '/api/retrivora';
101
+ const configUrl = `${base.replace(/\/$/, '')}/config?sdkVersion=${SDK_VERSION}`;
102
+ const res = await fetch(configUrl, {
103
+ method: 'GET',
104
+ cache: 'no-store',
105
+ headers: {
106
+ 'Content-Type': 'application/json',
107
+ 'x-sdk-version': SDK_VERSION,
108
+ ...(headers || {})
109
+ },
110
+ });
111
+
112
+ if (!res.ok) {
113
+ const data = await res.json().catch(() => ({}));
114
+ if (res.status === 426 || data.code === 'SDK_VERSION_OUTDATED') {
115
+ if (isMounted) {
116
+ setVersionError(data.error || 'Your Retrivora SDK package is outdated. Please update your package to the latest version to continue.');
117
+ }
118
+ } else if (
119
+ res.status === 403 ||
120
+ res.status === 401 ||
121
+ (typeof data.error === 'string' && data.error.toLowerCase().includes('license'))
122
+ ) {
123
+ if (isMounted) {
124
+ const errMsg = typeof data.error === 'string' ? data.error : data.error?.message || 'Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.';
125
+ setLicenseError(errMsg);
126
+ }
127
+ }
128
+ } else {
129
+ if (isMounted) {
130
+ setLicenseError(null);
131
+ setVersionError(null);
132
+ }
133
+ }
134
+ } catch {
135
+ // Non-blocking fallback
136
+ }
137
+ }
138
+
139
+ validateSessionLicense();
140
+ return () => { isMounted = false; };
141
+ }, [retrivoraApiBase, headers]);
142
+
91
143
  // Initialize SpeechRecognition
92
144
  useEffect(() => {
93
145
  if (typeof window !== 'undefined') {
@@ -345,7 +397,36 @@ export function ChatWindow({
345
397
  </div>
346
398
 
347
399
  <div className="flex-1 overflow-y-auto px-4 py-4 space-y-5 scrollbar-thin scrollbar-thumb-slate-200 dark:scrollbar-thumb-white/10 scrollbar-track-transparent min-h-0 bg-slate-50 dark:bg-transparent">
348
- {!mounted || isEmpty ? (
400
+ {versionError ? (
401
+ <div className="h-full flex flex-col items-center justify-center text-center p-6 space-y-4 bg-amber-50/70 dark:bg-amber-950/20 rounded-2xl border border-amber-200/80 dark:border-amber-800/40 my-auto">
402
+ <div className="w-14 h-14 rounded-2xl bg-amber-100 dark:bg-amber-900/40 text-amber-600 dark:text-amber-400 flex items-center justify-center shadow-sm shrink-0">
403
+ <ArrowUpCircle className="w-7 h-7 animate-bounce" />
404
+ </div>
405
+ <div className="space-y-2 max-w-xs">
406
+ <h4 className="text-base font-extrabold text-slate-900 dark:text-white tracking-tight">Package Update Required</h4>
407
+ <p className="text-xs text-slate-600 dark:text-slate-300 leading-relaxed font-medium">
408
+ {versionError}
409
+ </p>
410
+ <div className="pt-2">
411
+ <code className="block bg-slate-900 text-amber-300 text-[10px] font-mono py-2 px-3 rounded-xl select-all border border-slate-800">
412
+ npm i @retrivora-ai/rag-engine@latest
413
+ </code>
414
+ </div>
415
+ </div>
416
+ </div>
417
+ ) : licenseError ? (
418
+ <div className="h-full flex flex-col items-center justify-center text-center p-6 space-y-4 bg-rose-50/50 dark:bg-rose-950/20 rounded-2xl border border-rose-200/60 dark:border-rose-800/40 my-auto">
419
+ <div className="w-14 h-14 rounded-2xl bg-rose-100 dark:bg-rose-900/40 text-rose-600 dark:text-rose-400 flex items-center justify-center shadow-sm shrink-0">
420
+ <TriangleAlert className="w-7 h-7" />
421
+ </div>
422
+ <div className="space-y-2 max-w-xs">
423
+ <h4 className="text-base font-extrabold text-slate-900 dark:text-white tracking-tight">License Invalid</h4>
424
+ <p className="text-xs text-slate-600 dark:text-slate-300 leading-relaxed font-medium">
425
+ {licenseError}
426
+ </p>
427
+ </div>
428
+ </div>
429
+ ) : !mounted || isEmpty ? (
349
430
  /* Welcome state */
350
431
  <div className="h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-4">
351
432
  <div
@@ -408,7 +489,7 @@ export function ChatWindow({
408
489
  )}
409
490
 
410
491
  {/* Error */}
411
- {error && (
492
+ {error && !licenseError && (
412
493
  <div className="flex items-center gap-2 text-rose-500 dark:text-rose-400 text-sm bg-rose-50 dark:bg-rose-400/10 border border-rose-200 dark:border-rose-400/20 rounded-xl px-4 py-3">
413
494
  <TriangleAlert className="w-4 h-4 flex-shrink-0" />
414
495
  <span>{error}</span>
@@ -479,7 +560,7 @@ export function ChatWindow({
479
560
  onKeyDown={handleKeyDown}
480
561
  placeholder={ui.placeholder}
481
562
  rows={1}
482
- disabled={isLoading}
563
+ disabled={isLoading || !!licenseError || !!versionError}
483
564
  className="flex-1 bg-transparent text-slate-900 dark:text-white/90 placeholder-slate-400 dark:placeholder-white/30 text-sm resize-none outline-none py-1.5 px-2 max-h-32 leading-relaxed disabled:opacity-50"
484
565
  style={{ scrollbarWidth: 'none' }}
485
566
  />
@@ -488,7 +569,7 @@ export function ChatWindow({
488
569
  <button
489
570
  type="button"
490
571
  onClick={toggleListening}
491
- disabled={isLoading}
572
+ disabled={isLoading || !!licenseError || !!versionError}
492
573
  className={`flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:active:scale-100 ${isListening
493
574
  ? 'bg-rose-500 text-white animate-pulse shadow-md shadow-rose-500/20'
494
575
  : 'text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10'
@@ -503,7 +584,8 @@ export function ChatWindow({
503
584
  <button
504
585
  type="button"
505
586
  onClick={() => setIsUploadModalOpen(true)}
506
- className="flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10"
587
+ disabled={isLoading || !!licenseError || !!versionError}
588
+ className="flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed"
507
589
  title="Upload Document"
508
590
  >
509
591
  <Paperclip className="w-4 h-4" />
@@ -521,14 +603,10 @@ export function ChatWindow({
521
603
  ) : (
522
604
  <button
523
605
  onClick={sendMessage}
524
- disabled={!input.trim()}
525
- className="flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all disabled:opacity-30 disabled:cursor-not-allowed hover:scale-105 active:scale-95 shadow-md"
526
- style={{
527
- background:
528
- input.trim()
529
- ? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})`
530
- : 'rgba(148, 163, 184, 0.2)', // slate-400/20 for light mode disabled
531
- }}
606
+ disabled={!input.trim() || !!licenseError || !!versionError}
607
+ className={`flex-shrink-0 w-9 h-9 flex items-center justify-center transition-all shadow-md active:scale-95 cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed disabled:active:scale-100 ${ui.borderRadius === 'full' ? 'rounded-full' : 'rounded-xl'}`}
608
+ style={{ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
609
+ title="Send message"
532
610
  >
533
611
  <ArrowUp className="w-4 h-4 text-white" />
534
612
  </button>
@@ -154,7 +154,15 @@ export function useRagChat(
154
154
 
155
155
  if (!response.ok) {
156
156
  const errorData = await response.json().catch(() => ({}));
157
- throw new Error(errorData.error || `Server returned ${response.status}`);
157
+ if (
158
+ response.status === 403 ||
159
+ response.status === 401 ||
160
+ (typeof errorData.error === 'string' && errorData.error.toLowerCase().includes('license')) ||
161
+ errorData.error?.type === 'license_revoked'
162
+ ) {
163
+ throw new Error('Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.');
164
+ }
165
+ throw new Error(errorData.error?.message || errorData.error || `Server returned ${response.status}`);
158
166
  }
159
167
 
160
168
  if (!response.body) {
package/src/index.css CHANGED
@@ -96,6 +96,9 @@
96
96
  --color-rose-400: oklch(71.2% 0.194 13.428);
97
97
  --color-rose-500: oklch(64.5% 0.246 16.439);
98
98
  --color-rose-600: oklch(58.6% 0.253 17.585);
99
+ --color-rose-800: oklch(45.5% 0.188 13.697);
100
+ --color-rose-900: oklch(41% 0.159 10.272);
101
+ --color-rose-950: oklch(27.1% 0.105 12.094);
99
102
  --color-slate-50: oklch(98.4% 0.003 247.858);
100
103
  --color-slate-100: oklch(96.8% 0.007 247.896);
101
104
  --color-slate-200: oklch(92.9% 0.013 255.508);
@@ -370,6 +373,9 @@
370
373
  .bottom-20 {
371
374
  bottom: calc(var(--spacing) * 20);
372
375
  }
376
+ .bottom-24 {
377
+ bottom: calc(var(--spacing) * 24);
378
+ }
373
379
  .-left-4 {
374
380
  left: calc(var(--spacing) * -4);
375
381
  }
@@ -451,6 +457,9 @@
451
457
  .my-6 {
452
458
  margin-block: calc(var(--spacing) * 6);
453
459
  }
460
+ .my-auto {
461
+ margin-block: auto;
462
+ }
454
463
  .mt-0\.5 {
455
464
  margin-top: calc(var(--spacing) * 0.5);
456
465
  }
@@ -1121,6 +1130,12 @@
1121
1130
  .border-amber-200 {
1122
1131
  border-color: var(--color-amber-200);
1123
1132
  }
1133
+ .border-amber-200\/80 {
1134
+ border-color: color-mix(in srgb, oklch(92.4% 0.12 95.746) 80%, transparent);
1135
+ @supports (color: color-mix(in lab, red, red)) {
1136
+ border-color: color-mix(in oklab, var(--color-amber-200) 80%, transparent);
1137
+ }
1138
+ }
1124
1139
  .border-emerald-100 {
1125
1140
  border-color: var(--color-emerald-100);
1126
1141
  }
@@ -1157,6 +1172,12 @@
1157
1172
  .border-rose-200 {
1158
1173
  border-color: var(--color-rose-200);
1159
1174
  }
1175
+ .border-rose-200\/60 {
1176
+ border-color: color-mix(in srgb, oklch(89.2% 0.058 10.001) 60%, transparent);
1177
+ @supports (color: color-mix(in lab, red, red)) {
1178
+ border-color: color-mix(in oklab, var(--color-rose-200) 60%, transparent);
1179
+ }
1180
+ }
1160
1181
  .border-slate-100 {
1161
1182
  border-color: var(--color-slate-100);
1162
1183
  }
@@ -1217,6 +1238,12 @@
1217
1238
  .bg-amber-50 {
1218
1239
  background-color: var(--color-amber-50);
1219
1240
  }
1241
+ .bg-amber-50\/70 {
1242
+ background-color: color-mix(in srgb, oklch(98.7% 0.022 95.277) 70%, transparent);
1243
+ @supports (color: color-mix(in lab, red, red)) {
1244
+ background-color: color-mix(in oklab, var(--color-amber-50) 70%, transparent);
1245
+ }
1246
+ }
1220
1247
  .bg-amber-100 {
1221
1248
  background-color: var(--color-amber-100);
1222
1249
  }
@@ -1322,6 +1349,15 @@
1322
1349
  .bg-rose-50 {
1323
1350
  background-color: var(--color-rose-50);
1324
1351
  }
1352
+ .bg-rose-50\/50 {
1353
+ background-color: color-mix(in srgb, oklch(96.9% 0.015 12.422) 50%, transparent);
1354
+ @supports (color: color-mix(in lab, red, red)) {
1355
+ background-color: color-mix(in oklab, var(--color-rose-50) 50%, transparent);
1356
+ }
1357
+ }
1358
+ .bg-rose-100 {
1359
+ background-color: var(--color-rose-100);
1360
+ }
1325
1361
  .bg-rose-500 {
1326
1362
  background-color: var(--color-rose-500);
1327
1363
  }
@@ -1409,6 +1445,12 @@
1409
1445
  background-color: color-mix(in oklab, var(--color-white) 90%, transparent);
1410
1446
  }
1411
1447
  }
1448
+ .bg-white\/95 {
1449
+ background-color: color-mix(in srgb, #fff 95%, transparent);
1450
+ @supports (color: color-mix(in lab, red, red)) {
1451
+ background-color: color-mix(in oklab, var(--color-white) 95%, transparent);
1452
+ }
1453
+ }
1412
1454
  .bg-gradient-to-br {
1413
1455
  --tw-gradient-position: to bottom right in oklab;
1414
1456
  background-image: linear-gradient(var(--tw-gradient-stops));
@@ -1619,6 +1661,9 @@
1619
1661
  .whitespace-pre-wrap {
1620
1662
  white-space: pre-wrap;
1621
1663
  }
1664
+ .text-amber-300 {
1665
+ color: var(--color-amber-300);
1666
+ }
1622
1667
  .text-amber-400 {
1623
1668
  color: var(--color-amber-400);
1624
1669
  }
@@ -1950,6 +1995,10 @@
1950
1995
  --tw-outline-style: none;
1951
1996
  outline-style: none;
1952
1997
  }
1998
+ .select-all {
1999
+ -webkit-user-select: all;
2000
+ user-select: all;
2001
+ }
1953
2002
  .select-none {
1954
2003
  -webkit-user-select: none;
1955
2004
  user-select: none;
@@ -2391,6 +2440,14 @@
2391
2440
  }
2392
2441
  }
2393
2442
  }
2443
+ .dark\:border-amber-800\/40 {
2444
+ @media (prefers-color-scheme: dark) {
2445
+ border-color: color-mix(in srgb, oklch(47.3% 0.137 46.201) 40%, transparent);
2446
+ @supports (color: color-mix(in lab, red, red)) {
2447
+ border-color: color-mix(in oklab, var(--color-amber-800) 40%, transparent);
2448
+ }
2449
+ }
2450
+ }
2394
2451
  .dark\:border-emerald-400\/20 {
2395
2452
  @media (prefers-color-scheme: dark) {
2396
2453
  border-color: color-mix(in srgb, oklch(76.5% 0.177 163.223) 20%, transparent);
@@ -2463,6 +2520,22 @@
2463
2520
  }
2464
2521
  }
2465
2522
  }
2523
+ .dark\:border-rose-800\/40 {
2524
+ @media (prefers-color-scheme: dark) {
2525
+ border-color: color-mix(in srgb, oklch(45.5% 0.188 13.697) 40%, transparent);
2526
+ @supports (color: color-mix(in lab, red, red)) {
2527
+ border-color: color-mix(in oklab, var(--color-rose-800) 40%, transparent);
2528
+ }
2529
+ }
2530
+ }
2531
+ .dark\:border-rose-900\/60 {
2532
+ @media (prefers-color-scheme: dark) {
2533
+ border-color: color-mix(in srgb, oklch(41% 0.159 10.272) 60%, transparent);
2534
+ @supports (color: color-mix(in lab, red, red)) {
2535
+ border-color: color-mix(in oklab, var(--color-rose-900) 60%, transparent);
2536
+ }
2537
+ }
2538
+ }
2466
2539
  .dark\:border-slate-700 {
2467
2540
  @media (prefers-color-scheme: dark) {
2468
2541
  border-color: var(--color-slate-700);
@@ -2515,6 +2588,11 @@
2515
2588
  background-color: color-mix(in oklab, #0f0f1a 90%, transparent);
2516
2589
  }
2517
2590
  }
2591
+ .dark\:bg-\[\#0f0f1a\]\/95 {
2592
+ @media (prefers-color-scheme: dark) {
2593
+ background-color: color-mix(in oklab, #0f0f1a 95%, transparent);
2594
+ }
2595
+ }
2518
2596
  .dark\:bg-\[\#080811\] {
2519
2597
  @media (prefers-color-scheme: dark) {
2520
2598
  background-color: #080811;
@@ -2560,6 +2638,22 @@
2560
2638
  }
2561
2639
  }
2562
2640
  }
2641
+ .dark\:bg-amber-900\/40 {
2642
+ @media (prefers-color-scheme: dark) {
2643
+ background-color: color-mix(in srgb, oklch(41.4% 0.112 45.904) 40%, transparent);
2644
+ @supports (color: color-mix(in lab, red, red)) {
2645
+ background-color: color-mix(in oklab, var(--color-amber-900) 40%, transparent);
2646
+ }
2647
+ }
2648
+ }
2649
+ .dark\:bg-amber-950\/20 {
2650
+ @media (prefers-color-scheme: dark) {
2651
+ background-color: color-mix(in srgb, oklch(27.9% 0.077 45.635) 20%, transparent);
2652
+ @supports (color: color-mix(in lab, red, red)) {
2653
+ background-color: color-mix(in oklab, var(--color-amber-950) 20%, transparent);
2654
+ }
2655
+ }
2656
+ }
2563
2657
  .dark\:bg-amber-950\/40 {
2564
2658
  @media (prefers-color-scheme: dark) {
2565
2659
  background-color: color-mix(in srgb, oklch(27.9% 0.077 45.635) 40%, transparent);
@@ -2826,6 +2920,22 @@
2826
2920
  }
2827
2921
  }
2828
2922
  }
2923
+ .dark\:bg-rose-900\/40 {
2924
+ @media (prefers-color-scheme: dark) {
2925
+ background-color: color-mix(in srgb, oklch(41% 0.159 10.272) 40%, transparent);
2926
+ @supports (color: color-mix(in lab, red, red)) {
2927
+ background-color: color-mix(in oklab, var(--color-rose-900) 40%, transparent);
2928
+ }
2929
+ }
2930
+ }
2931
+ .dark\:bg-rose-950\/20 {
2932
+ @media (prefers-color-scheme: dark) {
2933
+ background-color: color-mix(in srgb, oklch(27.1% 0.105 12.094) 20%, transparent);
2934
+ @supports (color: color-mix(in lab, red, red)) {
2935
+ background-color: color-mix(in oklab, var(--color-rose-950) 20%, transparent);
2936
+ }
2937
+ }
2938
+ }
2829
2939
  .dark\:bg-slate-700 {
2830
2940
  @media (prefers-color-scheme: dark) {
2831
2941
  background-color: var(--color-slate-700);
@@ -3372,6 +3482,15 @@
3372
3482
  }
3373
3483
  }
3374
3484
  }
3485
+ .dark\:hover\:text-white {
3486
+ @media (prefers-color-scheme: dark) {
3487
+ &:hover {
3488
+ @media (hover: hover) {
3489
+ color: var(--color-white);
3490
+ }
3491
+ }
3492
+ }
3493
+ }
3375
3494
  .dark\:hover\:text-white\/60 {
3376
3495
  @media (prefers-color-scheme: dark) {
3377
3496
  &:hover {