llms-py 3.0.0b2__py3-none-any.whl → 3.0.0b4__py3-none-any.whl

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 (51) hide show
  1. llms/__pycache__/main.cpython-314.pyc +0 -0
  2. llms/index.html +2 -1
  3. llms/llms.json +50 -17
  4. llms/main.py +484 -544
  5. llms/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
  6. llms/providers/__pycache__/chutes.cpython-314.pyc +0 -0
  7. llms/providers/__pycache__/google.cpython-314.pyc +0 -0
  8. llms/providers/__pycache__/nvidia.cpython-314.pyc +0 -0
  9. llms/providers/__pycache__/openai.cpython-314.pyc +0 -0
  10. llms/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
  11. llms/providers/anthropic.py +189 -0
  12. llms/providers/chutes.py +152 -0
  13. llms/providers/google.py +306 -0
  14. llms/providers/nvidia.py +107 -0
  15. llms/providers/openai.py +159 -0
  16. llms/providers/openrouter.py +70 -0
  17. llms/providers-extra.json +356 -0
  18. llms/providers.json +1 -1
  19. llms/ui/App.mjs +132 -60
  20. llms/ui/ai.mjs +76 -10
  21. llms/ui/app.css +65 -28
  22. llms/ui/ctx.mjs +196 -0
  23. llms/ui/index.mjs +75 -171
  24. llms/ui/lib/charts.mjs +9 -13
  25. llms/ui/markdown.mjs +6 -0
  26. llms/ui/{Analytics.mjs → modules/analytics.mjs} +76 -64
  27. llms/ui/{Main.mjs → modules/chat/ChatBody.mjs} +59 -135
  28. llms/ui/{SettingsDialog.mjs → modules/chat/SettingsDialog.mjs} +8 -8
  29. llms/ui/{ChatPrompt.mjs → modules/chat/index.mjs} +242 -46
  30. llms/ui/modules/layout.mjs +267 -0
  31. llms/ui/modules/model-selector.mjs +851 -0
  32. llms/ui/{Recents.mjs → modules/threads/Recents.mjs} +0 -2
  33. llms/ui/{Sidebar.mjs → modules/threads/index.mjs} +46 -44
  34. llms/ui/{threadStore.mjs → modules/threads/threadStore.mjs} +10 -7
  35. llms/ui/utils.mjs +82 -123
  36. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/METADATA +1 -1
  37. llms_py-3.0.0b4.dist-info/RECORD +65 -0
  38. llms/ui/Avatar.mjs +0 -86
  39. llms/ui/Brand.mjs +0 -52
  40. llms/ui/OAuthSignIn.mjs +0 -61
  41. llms/ui/ProviderIcon.mjs +0 -36
  42. llms/ui/ProviderStatus.mjs +0 -104
  43. llms/ui/SignIn.mjs +0 -65
  44. llms/ui/Welcome.mjs +0 -8
  45. llms/ui/model-selector.mjs +0 -686
  46. llms/ui.json +0 -1069
  47. llms_py-3.0.0b2.dist-info/RECORD +0 -58
  48. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/WHEEL +0 -0
  49. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/entry_points.txt +0 -0
  50. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/licenses/LICENSE +0 -0
  51. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/top_level.txt +0 -0
llms/ui/App.mjs CHANGED
@@ -1,42 +1,119 @@
1
- import { inject, ref, watch, onMounted, onUnmounted } from "vue"
1
+ import { ref, computed, watch, inject, onMounted, onUnmounted } from "vue"
2
2
  import { useRouter, useRoute } from "vue-router"
3
- import Sidebar from "./Sidebar.mjs"
3
+ import { AppContext } from "./ctx.mjs"
4
+
5
+ // Vertical Sidebar Icons
6
+ const LeftBar = {
7
+ template: `
8
+ <div class="flex flex-col space-y-2 pt-2.5 px-1">
9
+ <div v-for="(icon, id) in $ctx.left" :key="id" class="relative flex items-center justify-center">
10
+ <component :is="icon.component"
11
+ class="size-7 p-1 cursor-pointer text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 rounded block"
12
+ :class="{ 'bg-gray-200 dark:bg-gray-700' : icon.isActive({ ...$layout }) }"
13
+ @mouseenter="tooltip = icon.id"
14
+ @mouseleave="tooltip = ''"
15
+ />
16
+ <div v-if="tooltip === icon.id && !icon.isActive({ ...$layout })"
17
+ class="absolute left-full top-1/2 -translate-y-1/2 ml-2 px-2 py-1 text-xs text-white bg-gray-900 dark:bg-gray-800 rounded shadow-md z-50 whitespace-nowrap pointer-events-none" style="z-index: 60">
18
+ {{icon.name}}
19
+ </div>
20
+ </div>
21
+ </div>
22
+ `,
23
+ setup() {
24
+ const tooltip = ref('')
25
+ return {
26
+ tooltip,
27
+ }
28
+ }
29
+ }
30
+
31
+ const LeftPanel = {
32
+ template: `
33
+ <div v-if="component" class="flex flex-col h-full border-r border-gray-200 dark:border-gray-700">
34
+ <button type="button" @click="$emit('toggle-sidebar')" class="absolute top-2 right-2 p-1 rounded-md text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700 lg:hidden z-20">
35
+ <svg class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
36
+ </button>
37
+ <component :is="component" />
38
+ </div>
39
+ `,
40
+ setup() {
41
+ /**@type {AppContext} */
42
+ const ctx = inject('ctx')
43
+ const component = computed(() => ctx.component(ctx.layout.left))
44
+ return {
45
+ component,
46
+ }
47
+ }
48
+ }
49
+
50
+ const TopBar = {
51
+ template: `
52
+ <div class="flex space-x-2">
53
+ <div v-for="(icon, id) in $ctx.top" :key="id" class="relative flex items-center justify-center">
54
+ <component :is="icon.component"
55
+ class="size-7 p-1 cursor-pointer text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 block"
56
+ :class="{ 'bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded' : icon.isActive({ ...$layout }) }"
57
+ @mouseenter="tooltip = icon.id"
58
+ @mouseleave="tooltip = ''"
59
+ />
60
+ <div v-if="tooltip === icon.id && !icon.isActive({ ...$layout })"
61
+ class="absolute top-full mt-2 px-2 py-1 text-xs text-white bg-gray-900 dark:bg-gray-800 rounded shadow-md z-50 whitespace-nowrap pointer-events-none"
62
+ :class="last2.includes(id) ? 'right-0' : 'left-1/2 -translate-x-1/2'">
63
+ {{icon.name}}
64
+ </div>
65
+ </div>
66
+ </div>
67
+ `,
68
+ setup() {
69
+ const tooltip = ref('')
70
+ const last2 = ref(Object.keys($ctx.top).slice(-2))
71
+ return {
72
+ tooltip,
73
+ last2,
74
+ }
75
+ }
76
+ }
77
+
78
+ const TopPanel = {
79
+ template: `
80
+ <component v-if="component" :is="component" class="mb-2" />
81
+ `,
82
+ setup() {
83
+ /**@type {AppContext} */
84
+ const ctx = inject('ctx')
85
+ const component = computed(() => ctx.component(ctx.layout.top))
86
+ return {
87
+ component,
88
+ }
89
+ }
90
+ }
4
91
 
5
92
  export default {
6
93
  components: {
7
- Sidebar,
94
+ LeftBar,
95
+ LeftPanel,
96
+ TopBar,
97
+ TopPanel,
8
98
  },
9
- props: ['config', 'models'],
10
- setup(props) {
99
+ setup() {
11
100
  const router = useRouter()
12
101
  const route = useRoute()
13
102
 
103
+ /**@type {AppContext} */
14
104
  const ctx = inject('ctx')
15
105
  const ai = ctx.ai
16
106
  const isMobile = ref(false)
17
107
  const modal = ref()
18
108
 
19
109
  const checkMobile = () => {
20
- const wasMobile = isMobile.value
21
- isMobile.value = window.innerWidth < 1024 // lg breakpoint
110
+ //const wasMobile = isMobile.value
111
+ isMobile.value = window.innerWidth < 640 // sm breakpoint
22
112
 
113
+ //console.log('checkMobile', wasMobile, isMobile.value)
23
114
  // Only auto-adjust sidebar state when transitioning between mobile/desktop
24
- if (wasMobile !== isMobile.value) {
25
- if (isMobile.value) {
26
- ai.isSidebarOpen = false
27
- } else {
28
- ai.isSidebarOpen = true
29
- }
30
- }
31
- }
32
-
33
- const toggleSidebar = () => {
34
- ai.isSidebarOpen = !ai.isSidebarOpen
35
- }
36
-
37
- const closeSidebar = () => {
38
115
  if (isMobile.value) {
39
- ai.isSidebarOpen = false
116
+ ctx.toggleLayout('left', false)
40
117
  }
41
118
  }
42
119
 
@@ -58,61 +135,56 @@ export default {
58
135
 
59
136
  watch(() => route.query.open, (newVal) => {
60
137
  modal.value = ctx.modalComponents[newVal]
61
- console.log('open', newVal)
138
+ console.log('open', newVal, modal.value)
62
139
  })
63
140
 
64
- return { ai, modal, isMobile, toggleSidebar, closeSidebar, closeModal }
141
+ watch(() => ctx.state.selectedModel, (newVal) => {
142
+ ctx.chat.setSelectedModel(ctx.chat.getModel(newVal))
143
+ })
144
+
145
+ return { ai, modal, isMobile, closeModal }
65
146
  },
66
147
  template: `
67
- <div class="flex h-screen bg-white dark:bg-gray-900">
148
+ <div class="flex h-screen">
68
149
  <!-- Mobile Overlay -->
69
150
  <div
70
- v-if="isMobile && ai.isSidebarOpen && !(ai.requiresAuth && !ai.auth)"
71
- @click="closeSidebar"
151
+ v-if="isMobile && $ctx.layoutVisible('left') && $ai.hasAccess"
152
+ @click="$ctx.toggleLayout('left')"
72
153
  class="fixed inset-0 bg-black/50 z-40 lg:hidden"
73
154
  ></div>
74
155
 
75
- <!-- Sidebar (hidden when auth required and not authenticated) -->
76
- <div
77
- v-if="!(ai.requiresAuth && !ai.auth) && ai.isSidebarOpen"
78
- :class="[
79
- 'transition-transform duration-300 ease-in-out z-50',
80
- 'w-72 xl:w-80 flex-shrink-0',
81
- 'lg:relative',
82
- 'fixed inset-y-0 left-0'
83
- ]"
84
- >
85
- <Sidebar @thread-selected="closeSidebar" @toggle-sidebar="toggleSidebar" />
156
+ <div id="sidebar" class="z-100 relative flex bg-gray-50 dark:bg-gray-800">
157
+ <LeftBar />
158
+ <LeftPanel
159
+ v-if="$ai.hasAccess && $ctx.layoutVisible('left')"
160
+ :class="[
161
+ 'transition-transform duration-300 ease-in-out z-50',
162
+ 'w-72 xl:w-80 flex-shrink-0',
163
+ 'lg:relative',
164
+ 'fixed inset-y-0 left-[2.25rem] lg:left-0',
165
+ 'bg-gray-50 dark:bg-gray-800'
166
+ ]"
167
+ @thread-selected="$ctx.toggleLayout('left',false)" @toggle-sidebar="$ctx.toggleLayout('left')"
168
+ />
86
169
  </div>
87
170
 
88
171
  <!-- Main Area -->
89
172
  <div class="flex-1 flex flex-col">
90
- <!-- Collapsed Sidebar Toggle Button -->
91
- <div
92
- v-if="!(ai.requiresAuth && !ai.auth) && !ai.isSidebarOpen"
93
- class="fixed top-4 left-0"
94
- >
95
- <button type="button"
96
- @click="toggleSidebar"
97
- class="group p-1 text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
98
- title="Open sidebar"
99
- >
100
- <div class="relative w-5 h-5">
101
- <!-- Default sidebar icon -->
102
- <svg class="absolute inset-0 group-hover:hidden" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
103
- <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
104
- <line x1="9" y1="3" x2="9" y2="21"></line>
105
- </svg>
106
- <!-- Hover state: |→ icon -->
107
- <svg class="absolute inset-0 hidden group-hover:block" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="m17.172 11l-4.657-4.657l1.414-1.414L21 12l-7.071 7.071l-1.414-1.414L17.172 13H8v-2zM4 19V5h2v14z"/></svg>
173
+ <div class="flex flex-col h-full w-full overflow-hidden">
174
+ <div class="py-1 pr-1 flex items-center justify-between shrink-0">
175
+ <div>
176
+ <ModelSelector :models="$state.models" v-model="$state.selectedModel" />
108
177
  </div>
109
- </button>
178
+ <TopBar />
179
+ </div>
180
+ <TopPanel class="shrink-0" />
181
+ <div class="flex-1 overflow-hidden min-h-0 flex flex-col">
182
+ <RouterView class="h-full" />
183
+ </div>
110
184
  </div>
111
-
112
- <RouterView />
113
185
  </div>
114
186
 
115
- <component v-if="modal" :is="modal" @done="closeModal" />
187
+ <component v-if="modal" :is="modal" class="!z-[200]" @done="closeModal" />
116
188
  </div>
117
189
  `,
118
190
  }
llms/ui/ai.mjs CHANGED
@@ -1,12 +1,11 @@
1
1
  import { reactive } from "vue"
2
- import { useThreadStore } from "./threadStore.mjs"
3
2
 
4
3
  const base = ''
5
4
  const headers = { 'Accept': 'application/json' }
6
5
  const prefsKey = 'llms.prefs'
7
6
 
8
7
  export const o = {
9
- version: '3.0.0b2',
8
+ version: '3.0.0b4',
10
9
  base,
11
10
  prefsKey,
12
11
  welcome: 'Welcome to llms.py',
@@ -15,6 +14,7 @@ export const o = {
15
14
  authType: 'apikey', // 'oauth' or 'apikey' - controls which SignIn component to use
16
15
  headers,
17
16
  isSidebarOpen: true, // Shared sidebar state (default open for lg+ screens)
17
+ cacheUrlInfo: {},
18
18
 
19
19
  get hasAccess() {
20
20
  return !this.requiresAuth || this.auth
@@ -29,6 +29,17 @@ export const o = {
29
29
  headers: Object.assign({}, this.headers, options?.headers),
30
30
  })
31
31
  },
32
+ async getJson(url, options) {
33
+ const res = await this.get(url, options)
34
+ let txt = ''
35
+ try {
36
+ txt = await res.text()
37
+ return JSON.parse(txt)
38
+ } catch (e) {
39
+ console.error('Failed to parse JSON from GET', url, e, txt)
40
+ return { responseStatus: { errorCode: 'Error', message: `GET failed: ${e.message ?? e}` } }
41
+ }
42
+ },
32
43
  post(url, options) {
33
44
  return fetch(this.resolveUrl(url), {
34
45
  method: 'POST',
@@ -36,6 +47,17 @@ export const o = {
36
47
  headers: Object.assign({ 'Content-Type': 'application/json' }, this.headers, options?.headers),
37
48
  })
38
49
  },
50
+ async postJson(url, options) {
51
+ const res = await this.post(url, options)
52
+ let txt = ''
53
+ try {
54
+ txt = await res.text()
55
+ return JSON.parse(txt)
56
+ } catch (e) {
57
+ console.error('Failed to parse JSON from POST', url, e, txt)
58
+ return { responseStatus: { errorCode: 'Error', message: `POST failed: ${e.message ?? e}` } }
59
+ }
60
+ },
39
61
 
40
62
  async getConfig() {
41
63
  return this.get('/config')
@@ -72,18 +94,17 @@ export const o = {
72
94
  if (this.headers.Authorization) {
73
95
  delete this.headers.Authorization
74
96
  }
75
- localStorage.removeItem('llms:auth')
76
97
  },
77
- async init() {
98
+ async init(ctx) {
78
99
  // Load models and prompts
79
- const { initDB } = useThreadStore()
80
- const [_, configRes, modelsRes] = await Promise.all([
81
- initDB(),
100
+ const [configRes, modelsRes, extensionsRes] = await Promise.all([
82
101
  this.getConfig(),
83
102
  this.getModels(),
103
+ this.get('/ext'),
84
104
  ])
85
105
  const config = await configRes.json()
86
106
  const models = await modelsRes.json()
107
+ const extensions = await extensionsRes.json()
87
108
 
88
109
  // Update auth settings from server config
89
110
  if (config.requiresAuth != null) {
@@ -100,14 +121,59 @@ export const o = {
100
121
  : null
101
122
  if (auth?.responseStatus?.errorCode) {
102
123
  console.error(auth.responseStatus.errorCode, auth.responseStatus.message)
103
- // Clear invalid session from localStorage
104
- localStorage.removeItem('llms:auth')
105
124
  } else {
106
125
  this.signIn(auth)
107
126
  }
108
- return { config, models, auth }
127
+ return { config, models, extensions, auth }
128
+ },
129
+
130
+
131
+ async uploadFile(file) {
132
+ const formData = new FormData()
133
+ formData.append('file', file)
134
+ const response = await fetch(this.resolveUrl('/upload'), {
135
+ method: 'POST',
136
+ body: formData
137
+ })
138
+ if (!response.ok) {
139
+ throw new Error(`Upload failed: ${response.statusText}`)
140
+ }
141
+ return response.json()
142
+ },
143
+
144
+
145
+ getCacheInfo(url) {
146
+ return this.cacheUrlInfo[url]
147
+ },
148
+ async fetchCacheInfos(urls) {
149
+ const infos = {}
150
+ const fetchInfos = []
151
+ for (const url of urls) {
152
+ const info = this.getCacheInfo(url)
153
+ if (info) {
154
+ infos[url] = info
155
+ } else {
156
+ fetchInfos.push(fetch(this.resolveUrl(url + "?info")))
157
+ }
158
+ }
159
+ const responses = await Promise.all(fetchInfos)
160
+ for (let i = 0; i < urls.length; i++) {
161
+ try {
162
+ const info = await responses[i].json()
163
+ this.setCacheInfo(urls[i], info)
164
+ infos[urls[i]] = info
165
+ } catch (e) {
166
+ console.error('Failed to fetch info for', urls[i], e)
167
+ }
168
+ }
169
+ return infos
170
+ },
171
+ setCacheInfo(url, info) {
172
+ this.cacheUrlInfo[url] = info
109
173
  }
174
+
110
175
  }
111
176
 
177
+
112
178
  let ai = reactive(o)
113
179
  export default ai
llms/ui/app.css CHANGED
@@ -21,7 +21,6 @@
21
21
  --color-yellow-50: oklch(98.7% 0.026 102.212);
22
22
  --color-yellow-200: oklch(94.5% 0.129 101.54);
23
23
  --color-yellow-400: oklch(85.2% 0.199 91.936);
24
- --color-yellow-500: oklch(79.5% 0.184 86.047);
25
24
  --color-yellow-700: oklch(55.4% 0.135 66.442);
26
25
  --color-green-50: oklch(98.2% 0.018 155.826);
27
26
  --color-green-100: oklch(96.2% 0.044 156.743);
@@ -81,6 +80,7 @@
81
80
  --color-purple-700: oklch(49.6% 0.265 301.924);
82
81
  --color-purple-800: oklch(43.8% 0.218 303.724);
83
82
  --color-purple-900: oklch(38.1% 0.176 304.987);
83
+ --color-fuchsia-600: oklch(59.1% 0.293 322.896);
84
84
  --color-slate-50: oklch(98.4% 0.003 247.858);
85
85
  --color-slate-200: oklch(92.9% 0.013 255.508);
86
86
  --color-slate-400: oklch(70.4% 0.04 256.788);
@@ -344,9 +344,6 @@
344
344
  .inset-y-0 {
345
345
  inset-block: calc(var(--spacing) * 0);
346
346
  }
347
- .-top-12 {
348
- top: calc(var(--spacing) * -12);
349
- }
350
347
  .top-0 {
351
348
  top: calc(var(--spacing) * 0);
352
349
  }
@@ -368,6 +365,9 @@
368
365
  .right-2 {
369
366
  right: calc(var(--spacing) * 2);
370
367
  }
368
+ .right-4 {
369
+ right: calc(var(--spacing) * 4);
370
+ }
371
371
  .bottom-2 {
372
372
  bottom: calc(var(--spacing) * 2);
373
373
  }
@@ -380,9 +380,15 @@
380
380
  .left-3 {
381
381
  left: calc(var(--spacing) * 3);
382
382
  }
383
+ .left-\[2\.25rem\] {
384
+ left: 2.25rem;
385
+ }
383
386
  .left-full {
384
387
  left: 100%;
385
388
  }
389
+ .\!z-\[200\] {
390
+ z-index: 200 !important;
391
+ }
386
392
  .z-0 {
387
393
  z-index: 0;
388
394
  }
@@ -398,9 +404,15 @@
398
404
  .z-50 {
399
405
  z-index: 50;
400
406
  }
407
+ .z-100 {
408
+ z-index: 100;
409
+ }
401
410
  .z-\[100\] {
402
411
  z-index: 100;
403
412
  }
413
+ .z-\[101\] {
414
+ z-index: 101;
415
+ }
404
416
  .col-span-2 {
405
417
  grid-column: span 2 / span 2;
406
418
  }
@@ -500,6 +512,9 @@
500
512
  .mr-3 {
501
513
  margin-right: calc(var(--spacing) * 3);
502
514
  }
515
+ .mr-4 {
516
+ margin-right: calc(var(--spacing) * 4);
517
+ }
503
518
  .mr-16 {
504
519
  margin-right: calc(var(--spacing) * 16);
505
520
  }
@@ -663,9 +678,6 @@
663
678
  .max-h-96 {
664
679
  max-height: calc(var(--spacing) * 96);
665
680
  }
666
- .max-h-120 {
667
- max-height: calc(var(--spacing) * 120);
668
- }
669
681
  .max-h-\[90vh\] {
670
682
  max-height: 90vh;
671
683
  }
@@ -777,9 +789,6 @@
777
789
  .min-w-0 {
778
790
  min-width: calc(var(--spacing) * 0);
779
791
  }
780
- .min-w-48 {
781
- min-width: calc(var(--spacing) * 48);
782
- }
783
792
  .min-w-\[120px\] {
784
793
  min-width: 120px;
785
794
  }
@@ -945,6 +954,9 @@
945
954
  .gap-1 {
946
955
  gap: calc(var(--spacing) * 1);
947
956
  }
957
+ .gap-1\.5 {
958
+ gap: calc(var(--spacing) * 1.5);
959
+ }
948
960
  .gap-2 {
949
961
  gap: calc(var(--spacing) * 2);
950
962
  }
@@ -967,6 +979,13 @@
967
979
  margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)));
968
980
  }
969
981
  }
982
+ .space-y-2 {
983
+ :where(& > :not(:last-child)) {
984
+ --tw-space-y-reverse: 0;
985
+ margin-block-start: calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));
986
+ margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)));
987
+ }
988
+ }
970
989
  .space-y-4 {
971
990
  :where(& > :not(:last-child)) {
972
991
  --tw-space-y-reverse: 0;
@@ -1238,6 +1257,9 @@
1238
1257
  .bg-cyan-600 {
1239
1258
  background-color: var(--color-cyan-600);
1240
1259
  }
1260
+ .bg-fuchsia-600 {
1261
+ background-color: var(--color-fuchsia-600);
1262
+ }
1241
1263
  .bg-gray-50 {
1242
1264
  background-color: var(--color-gray-50);
1243
1265
  }
@@ -1328,18 +1350,9 @@
1328
1350
  .bg-white {
1329
1351
  background-color: var(--color-white);
1330
1352
  }
1331
- .bg-white\/10 {
1332
- background-color: color-mix(in srgb, #fff 10%, transparent);
1333
- @supports (color: color-mix(in lab, red, red)) {
1334
- background-color: color-mix(in oklab, var(--color-white) 10%, transparent);
1335
- }
1336
- }
1337
1353
  .bg-yellow-50 {
1338
1354
  background-color: var(--color-yellow-50);
1339
1355
  }
1340
- .bg-yellow-500 {
1341
- background-color: var(--color-yellow-500);
1342
- }
1343
1356
  .mask-repeat {
1344
1357
  mask-repeat: repeat;
1345
1358
  }
@@ -1442,6 +1455,9 @@
1442
1455
  .pt-2 {
1443
1456
  padding-top: calc(var(--spacing) * 2);
1444
1457
  }
1458
+ .pt-2\.5 {
1459
+ padding-top: calc(var(--spacing) * 2.5);
1460
+ }
1445
1461
  .pt-4 {
1446
1462
  padding-top: calc(var(--spacing) * 4);
1447
1463
  }
@@ -1496,6 +1512,9 @@
1496
1512
  .pl-1 {
1497
1513
  padding-left: calc(var(--spacing) * 1);
1498
1514
  }
1515
+ .pl-1\.5 {
1516
+ padding-left: calc(var(--spacing) * 1.5);
1517
+ }
1499
1518
  .pl-2 {
1500
1519
  padding-left: calc(var(--spacing) * 2);
1501
1520
  }
@@ -1505,15 +1524,9 @@
1505
1524
  .pl-3 {
1506
1525
  padding-left: calc(var(--spacing) * 3);
1507
1526
  }
1508
- .pl-4 {
1509
- padding-left: calc(var(--spacing) * 4);
1510
- }
1511
1527
  .pl-5 {
1512
1528
  padding-left: calc(var(--spacing) * 5);
1513
1529
  }
1514
- .pl-6 {
1515
- padding-left: calc(var(--spacing) * 6);
1516
- }
1517
1530
  .pl-10 {
1518
1531
  padding-left: calc(var(--spacing) * 10);
1519
1532
  }
@@ -2293,12 +2306,12 @@
2293
2306
  }
2294
2307
  }
2295
2308
  }
2296
- .hover\:bg-white\/20 {
2309
+ .hover\:bg-white\/10 {
2297
2310
  &:hover {
2298
2311
  @media (hover: hover) {
2299
- background-color: color-mix(in srgb, #fff 20%, transparent);
2312
+ background-color: color-mix(in srgb, #fff 10%, transparent);
2300
2313
  @supports (color: color-mix(in lab, red, red)) {
2301
- background-color: color-mix(in oklab, var(--color-white) 20%, transparent);
2314
+ background-color: color-mix(in oklab, var(--color-white) 10%, transparent);
2302
2315
  }
2303
2316
  }
2304
2317
  }
@@ -3037,11 +3050,21 @@
3037
3050
  display: table-cell;
3038
3051
  }
3039
3052
  }
3053
+ .md\:w-auto {
3054
+ @media (width >= 48rem) {
3055
+ width: auto;
3056
+ }
3057
+ }
3040
3058
  .md\:max-w-xl {
3041
3059
  @media (width >= 48rem) {
3042
3060
  max-width: var(--container-xl);
3043
3061
  }
3044
3062
  }
3063
+ .md\:min-w-48 {
3064
+ @media (width >= 48rem) {
3065
+ min-width: calc(var(--spacing) * 48);
3066
+ }
3067
+ }
3045
3068
  .md\:grid-cols-2 {
3046
3069
  @media (width >= 48rem) {
3047
3070
  grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -3087,6 +3110,11 @@
3087
3110
  inset-block: calc(var(--spacing) * 0);
3088
3111
  }
3089
3112
  }
3113
+ .lg\:left-0 {
3114
+ @media (width >= 64rem) {
3115
+ left: calc(var(--spacing) * 0);
3116
+ }
3117
+ }
3090
3118
  .lg\:z-10 {
3091
3119
  @media (width >= 64rem) {
3092
3120
  z-index: 10;
@@ -3703,6 +3731,15 @@
3703
3731
  }
3704
3732
  }
3705
3733
  }
3734
+ .dark\:hover\:border-gray-700 {
3735
+ &:where(.dark, .dark *) {
3736
+ &:hover {
3737
+ @media (hover: hover) {
3738
+ border-color: var(--color-gray-700);
3739
+ }
3740
+ }
3741
+ }
3742
+ }
3706
3743
  .dark\:hover\:border-red-600 {
3707
3744
  &:where(.dark, .dark *) {
3708
3745
  &:hover {