Hack in a simple dark mode for the page

#2
by SadP0i - opened
Files changed (2) hide show
  1. index.html +510 -575
  2. styles.css +950 -928
index.html CHANGED
@@ -1,575 +1,510 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <script>
7
- function strToHtml(str) {
8
- let parser = new DOMParser();
9
- return parser.parseFromString(str, "text/html");
10
- }
11
-
12
- //Short, jQuery-independent function to read html table and write them into an Array.
13
- //Kudos to RobG at StackOverflow
14
- function tableToObj(table) {
15
- var rows = table.rows;
16
- var propCells = rows[0].cells;
17
- var propNames = [];
18
- var results = [];
19
- var obj, row, cells;
20
-
21
- // Use the first row for the property names
22
- // Could use a header section but result is the same if
23
- // there is only one header row
24
- for (var i = 0, iLen = propCells.length; i < iLen; i++) {
25
- propNames.push(
26
- (propCells[i].textContent || propCells[i].innerText).trim()
27
- );
28
- }
29
-
30
- // Use the rows for data
31
- // Could use tbody rows here to exclude header & footer
32
- // but starting from 1 gives required result
33
- for (var j = 1, jLen = rows.length; j < jLen; j++) {
34
- cells = rows[j].cells;
35
- obj = {};
36
-
37
- for (var k = 0; k < iLen; k++) {
38
- obj[propNames[k]] = (
39
- cells[k].textContent || cells[k].innerText
40
- ).trim();
41
- }
42
- results.push(obj);
43
- }
44
- return results;
45
- }
46
-
47
- function formatGpu(gpus) {
48
- return gpus.map(
49
- (g) => `${g["Product Name"]} - ${g["Memory"].split(",")[0]}`
50
- );
51
- }
52
-
53
- const gguf_quants = {
54
- "IQ1_S": 1.56,
55
- "IQ1_M": 1.75,
56
- "IQ2_XXS": 2.06,
57
- "IQ2_XS": 2.31,
58
- "IQ2_S": 2.5,
59
- "IQ3_XXS": 3.06,
60
- "IQ3_XS": 3.3,
61
- "IQ3_S": 3.44,
62
- "IQ3_M": 3.66,
63
- "Q2_K": 3.35,
64
- "Q3_K_S": 3.5,
65
- "Q3_K_M": 3.91,
66
- "Q3_K_L": 4.27,
67
- "IQ4_XS": 4.25,
68
- "Q4_0": 4.55,
69
- "Q4_K_S": 4.58,
70
- "Q4_K_M": 4.85,
71
- "Q5_0": 5.54,
72
- "Q5_K_S": 5.54,
73
- "Q5_K_M": 5.69,
74
- "Q6_K": 6.59,
75
- "Q8_0": 8.5,
76
- }
77
-
78
- async function modelConfig(hf_model) {
79
- let config = await fetch(
80
- `https://huggingface.co/${hf_model}/raw/main/config.json`
81
- ).then(r => r.json())
82
- let model_size = 0
83
- try {
84
- model_size = (await fetch(`https://huggingface.co/${hf_model}/resolve/main/model.safetensors.index.json`).then(r => r.json()))["metadata"]["total_size"] / 2
85
- if (isNaN(model_size)) {
86
- throw new Erorr("no size in safetensors metadata")
87
- }
88
- } catch (e) {
89
- try {
90
- model_size = (await fetch(`https://huggingface.co/${hf_model}/resolve/main/pytorch_model.bin.index.json`).then(r => r.json()))["metadata"]["total_size"] / 2
91
- if (isNaN(model_size)) {
92
- throw new Erorr("no size in pytorch metadata")
93
- }
94
- } catch {
95
- let model_page = await fetch(
96
- "https://corsproxy.io/?" + encodeURIComponent(`https://huggingface.co/${hf_model}`)
97
- ).then(r => r.text())
98
- let el = document.createElement( 'html' );
99
- el.innerHTML = model_page
100
- let params_el = el.querySelector('div[data-target="ModelSafetensorsParams"]')
101
- if (params_el !== null) {
102
- model_size = JSON.parse(params_el.attributes.getNamedItem("data-props").value)["safetensors"]["total"]
103
- } else {
104
- params_el = el.querySelector('div[data-target="ModelHeader"]')
105
- model_size = JSON.parse(params_el.attributes.getNamedItem("data-props").value)["model"]["safetensors"]["total"]
106
- }
107
- }
108
- }
109
- config.parameters = model_size
110
- return config
111
- }
112
-
113
- function inputBuffer(context=8192, model_config, bsz=512) {
114
- /* Calculation taken from github:ggerganov/llama.cpp/llama.cpp:11248
115
- ctx->inp_tokens = ggml_new_tensor_1d(ctx->ctx_input, GGML_TYPE_I32, cparams.n_batch);
116
- ctx->inp_embd = ggml_new_tensor_2d(ctx->ctx_input, GGML_TYPE_F32, hparams.n_embd, cparams.n_batch);
117
- ctx->inp_pos = ggml_new_tensor_1d(ctx->ctx_input, GGML_TYPE_I32, cparams.n_batch);
118
- ctx->inp_KQ_mask = ggml_new_tensor_2d(ctx->ctx_input, GGML_TYPE_F32, cparams.n_ctx, cparams.n_batch);
119
- ctx->inp_K_shift = ggml_new_tensor_1d(ctx->ctx_input, GGML_TYPE_I32, cparams.n_ctx);
120
- ctx->inp_sum = ggml_new_tensor_2d(ctx->ctx_input, GGML_TYPE_F32, 1, cparams.n_batch);
121
-
122
- n_embd is hidden size (github:ggeranov/llama.cpp/convert.py:248)
123
- */
124
- const inp_tokens = bsz
125
- const inp_embd = model_config["hidden_size"] * bsz
126
- const inp_pos = bsz
127
- const inp_KQ_mask = context * bsz
128
- const inp_K_shift = context
129
- const inp_sum = bsz
130
-
131
- return inp_tokens + inp_embd + inp_pos + inp_KQ_mask + inp_K_shift + inp_sum
132
- }
133
-
134
- function computeBuffer(context=8192, model_config, bsz=512) {
135
- if (bsz != 512) {
136
- alert("batch size other than 512 is currently not supported for the compute buffer, using batchsize 512 for compute buffer calculation, end result result will be an overestimatition")
137
- }
138
- return (context / 1024 * 2 + 0.75) * model_config["num_attention_heads"] * 1024 * 1024
139
- }
140
-
141
- function kvCache(context=8192, model_config, cache_bit=16) {
142
- const n_gqa = model_config["num_attention_heads"] / model_config["num_key_value_heads"]
143
- const n_embd_gqa = model_config["hidden_size"] / n_gqa
144
- const n_elements = n_embd_gqa * (model_config["num_hidden_layers"] * context)
145
- const size = 2 * n_elements
146
- return size * (cache_bit / 8)
147
- }
148
-
149
- function contextSize(context=8192, model_config, bsz=512, cache_bit=16) {
150
- return Number.parseFloat((inputBuffer(context, model_config, bsz) + kvCache(context, model_config, cache_bit) + computeBuffer(context, model_config, bsz)).toFixed(2))
151
- }
152
-
153
- function modelSize(model_config, bpw=4.5) {
154
- return Number.parseFloat((model_config["parameters"] * bpw / 8).toFixed(2))
155
- }
156
-
157
- async function calculateSizes(format, context_loc) {
158
-
159
- format = "gguf"
160
-
161
- try {
162
- const model_config = await modelConfig(document.getElementById("modelsearch").value)
163
- const context = parseInt(document.getElementById("contextsize").value)
164
- let bsz = 512
165
- let cache_bit = 16
166
- let bpw = 0
167
- if (format === "gguf") {
168
- bsz = parseInt(document.getElementById("batchsize").value)
169
- bpw = gguf_quants[document.getElementById("quantsize").innerText]
170
-
171
- } else if (format == "exl2") {
172
- cache_bit = Number.parseInt(document.getElementById("kvCache").value)
173
- bpw = Number.parseFloat(document.getElementById("bpw").value)
174
- }
175
-
176
- const model_size = modelSize(model_config, bpw)
177
- const context_size = contextSize(context, model_config, bsz, cache_bit)
178
- const total_size = ((model_size + context_size) / 2**30)
179
- document.getElementById("resultmodel").innerText = (model_size / 2**30).toFixed(2)
180
- document.getElementById("resultcontext").innerText = (context_size / 2**30).toFixed(2)
181
- const result_total_el = document.getElementById("resulttotal");
182
- result_total_el.innerText = total_size.toFixed(2)
183
-
184
- const allocated_vram = Number.parseInt(document.getElementById("maxvram").value);
185
- const vram = allocated_vram
186
- if (vram - total_size > 0.5) {
187
- result_total_el.style.backgroundColor = "#bef264"
188
- } else if (vram - total_size > 0) {
189
- result_total_el.style.backgroundColor = "#facc15"
190
- } else {
191
- result_total_el.style.backgroundColor = "#ef4444"
192
- }
193
-
194
- const layer_size = ((model_size / 2**30) / model_config["num_hidden_layers"])
195
- const layer_size_el = document.getElementById("layersize");
196
- layer_size_el.innerText = layer_size.toFixed(2)
197
-
198
- const context_dealloc = context_loc === "vram" ? (context_size / 2**30) : 0;
199
- const layers_offload = Math.floor((allocated_vram - context_dealloc) / layer_size)
200
-
201
- const layers_offload_el = document.getElementById("layersoffload");
202
- layers_offload_el.innerText = `${layers_offload > model_config["num_hidden_layers"] ? model_config["num_hidden_layers"] : Math.max(0, layers_offload)}/${model_config["num_hidden_layers"]}`
203
-
204
- } catch(e) {
205
- alert(e);
206
- }
207
- }
208
- </script>
209
- <link href="./styles.css" rel="stylesheet">
210
- <title>Can I split it? - GGUF VRAM Calculator</title>
211
- </head>
212
- <body class="p-8">
213
- <div x-data="{ format: 'gguf', context_loc: 'vram' }" class="flex flex-col max-h-screen items-center mt-16 gap-10">
214
- <div style="text-align: center;">
215
- <h1 class="text-xl font-semibold leading-6 text-gray-900">
216
- GGUF Model, Can I split it?
217
- </h1>
218
- <h3 class="font-semibold leading-6 text-gray-900">
219
- Based on <a href="https://huggingface.co/NyxKrage" style="color: blue;">NyxKrage</a>'s <a href="https://huggingface.co/spaces/NyxKrage/LLM-Model-VRAM-Calculator" style="color: blue;">LLM VRAM calculator</a>
220
- </h3>
221
- </div>
222
- <div class="flex flex-col gap-10">
223
- <div class="w-auto flex flex-col gap-4">
224
- <div class="relative">
225
- <label
226
- for="maxvram"
227
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
228
- >
229
- Max Allocated VRAM
230
- </label>
231
- <input
232
- value="24"
233
- type="number"
234
- name="maxvram"
235
- id="maxvram"
236
- step="1"
237
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
238
- />
239
- </div>
240
-
241
- <!-- Model Selector -->
242
-
243
-
244
- <div class="flex flex-row gap-4 relative">
245
- <label
246
- for="contextsize"
247
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
248
- >
249
- Model (unquantized)
250
- </label>
251
- <div
252
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
253
- x-data="{
254
- open: false,
255
- value: 'Nexusflow/Starling-LM-7B-beta',
256
- results: null,
257
- toggle() {
258
- if (this.open) {
259
- return this.close()
260
- }
261
-
262
- this.$refs.input.focus()
263
-
264
- this.open = true
265
- },
266
- close(focusAfter) {
267
- if (! this.open) return
268
-
269
- this.open = false
270
-
271
- focusAfter && focusAfter.focus()
272
- }
273
- }"
274
- x-on:keydown.escape.prevent.stop="close($refs.input)"
275
- x-id="['model-typeahead']"
276
- class="relative"
277
- >
278
- <!-- Input -->
279
- <input
280
- id="modelsearch"
281
- x-ref="input"
282
- x-on:click="toggle()"
283
- @keypress.debounce.150ms="results = (await
284
- fetch('https://huggingface.co/api/quicksearch?type=model&q=' +
285
- encodeURIComponent(value)).then(r => r.json())).models.filter(m => !m.id.includes('GGUF') && !m.id.includes('AWQ') && !m.id.includes('GPTQ') && !m.id.includes('exl2'));"
286
- :aria-expanded="open"
287
- :aria-controls="$id('model-typeahead')"
288
- x-model="value"
289
- class="flex justify-between items-center gap-2 w-full"
290
- />
291
-
292
- <!-- Panel -->
293
- <div
294
- x-ref="panel"
295
- x-show="open"
296
- x-transition.origin.top.left
297
- x-on:click.outside="close($refs.input)"
298
- :id="$id('model-typeahead')"
299
- style="display: none"
300
- class="absolute left-0 mt-4 w-full rounded-md bg-white shadow-sm ring-1 ring-inset ring-gray-300 z-10"
301
- >
302
- <template x-for="result in results">
303
- <a
304
- @click="value = result.id; close($refs.input)"
305
- x-text="result.id"
306
- class="flex cursor-pointer items-center gap-2 w-full first-of-type:rounded-t-md last-of-type:rounded-b-md px-4 py-2.5 text-left text-sm hover:bg-gray-500/5 disabled:text-gray-500"
307
- ></a>
308
- </template>
309
- </div>
310
- </div>
311
- </div>
312
-
313
-
314
- <!-- Context Size Selector -->
315
- <div class="relative">
316
- <label
317
- for="contextsize"
318
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
319
- >
320
- Context Size
321
- </label>
322
- <input
323
- value="8192"
324
- type="number"
325
- name="contextsize"
326
- id="contextsize"
327
- step="1024"
328
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
329
- />
330
- </div>
331
-
332
- <div class="relative">
333
- <label
334
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
335
- >Context offloaded to</label
336
- >
337
- <fieldset
338
- x-model="context_loc"
339
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
340
- >
341
- <legend class="sr-only">Context location</legend>
342
- <div
343
- class="space-y-4 sm:flex sm:items-center sm:space-x-10 sm:space-y-0"
344
- >
345
- <div class="flex items-center">
346
- <input
347
- id="context-vram"
348
- name="context-allocation"
349
- type="radio"
350
- value="vram"
351
- checked
352
- class="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-600"
353
- />
354
- <label
355
- for="context-vram"
356
- class="ml-3 block text-sm font-medium leading-6 text-gray-900"
357
- >VRAM</label
358
- >
359
- </div>
360
- <div class="flex items-center">
361
- <input
362
- id="context-ram"
363
- name="context-allocation"
364
- type="radio"
365
- value="ram"
366
- class="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-600"
367
- />
368
- <label
369
- for="context-ram"
370
- class="ml-3 block text-sm font-medium leading-6 text-gray-900"
371
- >RAM</label
372
- >
373
- </div>
374
- </div>
375
- </fieldset>
376
- </div>
377
-
378
- <!-- GGUF Options -->
379
- <div x-show="format === 'gguf'" class="relative">
380
- <div class="flex flex-row gap-4">
381
- <label
382
- for="contextsize"
383
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
384
- >
385
- Quantization Size
386
- </label>
387
- <div
388
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
389
- x-data="{
390
- open: false,
391
- value: '',
392
- toggle() {
393
- if (this.open) {
394
- return this.close()
395
- }
396
-
397
- this.$refs.button.focus()
398
-
399
- this.open = true
400
- },
401
- close(focusAfter) {
402
- if (! this.open) return
403
-
404
- this.open = false
405
-
406
- focusAfter && focusAfter.focus()
407
- }
408
- }"
409
- x-on:keydown.escape.prevent.stop="close($refs.button)"
410
- x-id="['dropdown-button']"
411
- class="relative"
412
- >
413
- <!-- Button -->
414
- <button
415
- x-ref="button"
416
- x-on:click="toggle()"
417
- :aria-expanded="open"
418
- :aria-controls="$id('dropdown-button')"
419
- type="button"
420
- id="quantsize"
421
- x-text="value.length === 0 ? 'Q4_K_S' : value"
422
- class="flex justify-between items-center gap-2 w-full"
423
- >
424
- Q4_K_S
425
-
426
- <!-- Heroicon: chevron-down -->
427
- <svg
428
- xmlns="http://www.w3.org/2000/svg"
429
- class="h-5 w-5 text-gray-400"
430
- viewBox="0 0 20 20"
431
- fill="currentColor"
432
- >
433
- <path
434
- fill-rule="evenodd"
435
- d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
436
- clip-rule="evenodd"
437
- />
438
- </svg>
439
- </button>
440
-
441
- <!-- Panel -->
442
- <div
443
- x-data="{ quants: [
444
- 'IQ1_S',
445
- 'IQ1_M',
446
- 'IQ2_XXS',
447
- 'IQ2_XS',
448
- 'IQ2_S',
449
- 'IQ3_XXS',
450
- 'IQ3_XS',
451
- 'IQ3_S',
452
- 'IQ3_M',
453
- 'Q2_K',
454
- 'Q3_K_S',
455
- 'Q3_K_M',
456
- 'Q3_K_L',
457
- 'IQ4_XS',
458
- 'Q4_0',
459
- 'Q4_K_S',
460
- 'Q4_K_M',
461
- 'Q5_0',
462
- 'Q5_K_S',
463
- 'Q5_K_M',
464
- 'Q6_K',
465
- 'Q8_0'
466
- ]}"
467
- x-ref="panel"
468
- x-show="open"
469
- x-transition.origin.top.left
470
- x-on:click.outside="close($refs.button)"
471
- :id="$id('dropdown-button')"
472
- style="display: none"
473
- class="absolute left-0 mt-4 w-full rounded-md bg-white shadow-sm ring-1 ring-inset ring-gray-300 z-10"
474
- >
475
- <template x-for="quant in quants">
476
- <a
477
- @click="value = quant; close($refs.button)"
478
- x-text="quant"
479
- class="flex cursor-pointer items-center gap-2 w-full first-of-type:rounded-t-md last-of-type:rounded-b-md px-4 py-2.5 text-left text-sm hover:bg-gray-500/5 disabled:text-gray-500"
480
- ></a>
481
- </template>
482
- </div>
483
- </div>
484
- <div class="relative">
485
- <label
486
- for="batchsize"
487
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
488
- >
489
- Batch Size
490
- </label>
491
- <input
492
- value="512"
493
- type="number"
494
- step="128"
495
- id="batchsize"
496
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
497
- />
498
- </div>
499
- </div>
500
- </div>
501
- <button
502
- type="button"
503
- class="rounded-md bg-slate-800 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-slate-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
504
- @click="calculateSizes(format, context_loc)"
505
- >
506
- Submit
507
- </button>
508
- </div>
509
- <div class="w-auto flex flex-col gap-4">
510
- <div class="relative">
511
- <label
512
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
513
- >
514
- Model Size (GB)
515
- </label>
516
- <div
517
- id="resultmodel"
518
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
519
- >4.20</div>
520
- </div>
521
- <div class="relative">
522
- <label
523
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
524
- >
525
- Context Size (GB)
526
- </label>
527
- <div
528
- id="resultcontext"
529
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
530
- >6.90</div>
531
- </div>
532
- <div class="relative">
533
- <label
534
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
535
- >
536
- Total Size (GB)
537
- </label>
538
- <div
539
- id="resulttotal"
540
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
541
- >420.69</div>
542
- </div>
543
- <div class="relative">
544
- <label
545
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
546
- >
547
- Layer size (GB)
548
- </label>
549
- <div
550
- id="layersize"
551
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
552
- >42.69</div>
553
- </div>
554
- <div class="relative">
555
- <label
556
- class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
557
- >
558
- Layers offloaded to GPU (out of total)
559
- </label>
560
- <div
561
- id="layersoffload"
562
- class="block w-full rounded-md border-0 p-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
563
- >42</div>
564
- </div>
565
- </div>
566
- </div>
567
- </div>
568
- <script
569
- src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"
570
- ></script>
571
- <script defer>
572
- calculateSizes("gguf", "vram")
573
- </script>
574
- </body>
575
- </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <script>
8
+ document.addEventListener('DOMContentLoaded', (event) => {
9
+ if (localStorage.getItem('darkMode') === 'enabled') {
10
+ document.body.classList.add('dark-mode');
11
+ }
12
+ });
13
+
14
+ function toggleDarkMode() {
15
+ let isDark = document.body.classList.toggle('dark-mode');
16
+ localStorage.setItem('darkMode', isDark ? 'enabled' : 'disabled');
17
+ }
18
+
19
+ function strToHtml(str) {
20
+ let parser = new DOMParser();
21
+ return parser.parseFromString(str, "text/html");
22
+ }
23
+
24
+ //Short, jQuery-independent function to read html table and write them into an Array.
25
+ //Kudos to RobG at StackOverflow
26
+ function tableToObj(table) {
27
+ var rows = table.rows;
28
+ var propCells = rows[0].cells;
29
+ var propNames = [];
30
+ var results = [];
31
+ var obj, row, cells;
32
+
33
+ // Use the first row for the property names
34
+ // Could use a header section but result is the same if
35
+ // there is only one header row
36
+ for (var i = 0, iLen = propCells.length; i < iLen; i++) {
37
+ propNames.push(
38
+ (propCells[i].textContent || propCells[i].innerText).trim()
39
+ );
40
+ }
41
+
42
+ // Use the rows for data
43
+ // Could use tbody rows here to exclude header & footer
44
+ // but starting from 1 gives required result
45
+ for (var j = 1, jLen = rows.length; j < jLen; j++) {
46
+ cells = rows[j].cells;
47
+ obj = {};
48
+
49
+ for (var k = 0; k < iLen; k++) {
50
+ obj[propNames[k]] = (
51
+ cells[k].textContent || cells[k].innerText
52
+ ).trim();
53
+ }
54
+ results.push(obj);
55
+ }
56
+ return results;
57
+ }
58
+
59
+ function formatGpu(gpus) {
60
+ return gpus.map(
61
+ (g) => `${g["Product Name"]} - ${g["Memory"].split(",")[0]}`
62
+ );
63
+ }
64
+
65
+ const gguf_quants = {
66
+ "IQ1_S": 1.56,
67
+ "IQ1_M": 1.75,
68
+ "IQ2_XXS": 2.06,
69
+ "IQ2_XS": 2.31,
70
+ "IQ2_S": 2.5,
71
+ "IQ3_XXS": 3.06,
72
+ "IQ3_XS": 3.3,
73
+ "IQ3_S": 3.44,
74
+ "IQ3_M": 3.66,
75
+ "Q2_K": 3.35,
76
+ "Q3_K_S": 3.5,
77
+ "Q3_K_M": 3.91,
78
+ "Q3_K_L": 4.27,
79
+ "IQ4_XS": 4.25,
80
+ "Q4_0": 4.55,
81
+ "Q4_K_S": 4.58,
82
+ "Q4_K_M": 4.85,
83
+ "Q5_0": 5.54,
84
+ "Q5_K_S": 5.54,
85
+ "Q5_K_M": 5.69,
86
+ "Q6_K": 6.59,
87
+ "Q8_0": 8.5,
88
+ }
89
+
90
+ function sanitize(string) {
91
+ const map = {
92
+ '&': '&amp;',
93
+ '<': '&lt;',
94
+ '>': '&gt;',
95
+ '"': '&quot;',
96
+ "'": '&#x27;',
97
+ "/": '_',
98
+ '(': '',
99
+ ')': '',
100
+ '{': '',
101
+ '}': '',
102
+ '[': '',
103
+ ']': '',
104
+ };
105
+ const reg = /[&<>"'/\[\]\(\)\{\}]/ig;
106
+ return string.replace(reg, (match) => (map[match]));
107
+ }
108
+
109
+ async function modelConfig(hf_model) {
110
+ let config = {};
111
+ let responseText;
112
+
113
+ try {
114
+ let modelInfoPromise = fetch(
115
+ `https://huggingface.co/${hf_model}/raw/main/config.json`
116
+ );
117
+ responseText = await modelInfoPromise.then(r => r.text());
118
+ config = JSON.parse(responseText);
119
+ } catch (err) {
120
+ alert(sanitize(responseText))
121
+ return config;
122
+ }
123
+
124
+ let model_size = 0
125
+ try {
126
+ model_size = (await fetch(`https://huggingface.co/${hf_model}/resolve/main/model.safetensors.index.json`).then(r => r.json()))["metadata"]["total_size"] / 2
127
+ if (isNaN(model_size)) {
128
+ throw new Erorr("no size in safetensors metadata")
129
+ }
130
+ } catch (e) {
131
+ try {
132
+ model_size = (await fetch(`https://huggingface.co/${hf_model}/resolve/main/pytorch_model.bin.index.json`).then(r => r.json()))["metadata"]["total_size"] / 2
133
+ if (isNaN(model_size)) {
134
+ throw new Erorr("no size in pytorch metadata")
135
+ }
136
+ } catch {
137
+ let model_page = await fetch(
138
+ "https://corsproxy.io/?" + encodeURIComponent(`https://huggingface.co/${hf_model}`)
139
+ ).then(r => r.text())
140
+ let el = document.createElement('html');
141
+ el.innerHTML = model_page
142
+ let params_el = el.querySelector('div[data-target="ModelSafetensorsParams"]')
143
+ if (params_el !== null) {
144
+ model_size = JSON.parse(params_el.attributes.getNamedItem("data-props").value)["safetensors"]["total"]
145
+ } else {
146
+ params_el = el.querySelector('div[data-target="ModelHeader"]')
147
+ model_size = JSON.parse(params_el.attributes.getNamedItem("data-props").value)["model"]["safetensors"]["total"]
148
+ }
149
+ }
150
+ }
151
+ config.parameters = model_size
152
+ return config
153
+ }
154
+
155
+ function inputBuffer(context = 8192, model_config, bsz = 512) {
156
+ /* Calculation taken from github:ggerganov/llama.cpp/llama.cpp:11248
157
+ ctx->inp_tokens = ggml_new_tensor_1d(ctx->ctx_input, GGML_TYPE_I32, cparams.n_batch);
158
+ ctx->inp_embd = ggml_new_tensor_2d(ctx->ctx_input, GGML_TYPE_F32, hparams.n_embd, cparams.n_batch);
159
+ ctx->inp_pos = ggml_new_tensor_1d(ctx->ctx_input, GGML_TYPE_I32, cparams.n_batch);
160
+ ctx->inp_KQ_mask = ggml_new_tensor_2d(ctx->ctx_input, GGML_TYPE_F32, cparams.n_ctx, cparams.n_batch);
161
+ ctx->inp_K_shift = ggml_new_tensor_1d(ctx->ctx_input, GGML_TYPE_I32, cparams.n_ctx);
162
+ ctx->inp_sum = ggml_new_tensor_2d(ctx->ctx_input, GGML_TYPE_F32, 1, cparams.n_batch);
163
+
164
+ n_embd is hidden size (github:ggeranov/llama.cpp/convert.py:248)
165
+ */
166
+ const inp_tokens = bsz
167
+ const inp_embd = model_config["hidden_size"] * bsz
168
+ const inp_pos = bsz
169
+ const inp_KQ_mask = context * bsz
170
+ const inp_K_shift = context
171
+ const inp_sum = bsz
172
+
173
+ return inp_tokens + inp_embd + inp_pos + inp_KQ_mask + inp_K_shift + inp_sum
174
+ }
175
+
176
+ function computeBuffer(context = 8192, model_config, bsz = 512) {
177
+ if (bsz != 512) {
178
+ alert("batch size other than 512 is currently not supported for the compute buffer, using batchsize 512 for compute buffer calculation, end result result will be an overestimatition")
179
+ }
180
+ return (context / 1024 * 2 + 0.75) * model_config["num_attention_heads"] * 1024 * 1024
181
+ }
182
+
183
+ function kvCache(context = 8192, model_config, cache_bit = 16) {
184
+ const n_gqa = model_config["num_attention_heads"] / model_config["num_key_value_heads"]
185
+ const n_embd_gqa = model_config["hidden_size"] / n_gqa
186
+ const n_elements = n_embd_gqa * (model_config["num_hidden_layers"] * context)
187
+ const size = 2 * n_elements
188
+ return size * (cache_bit / 8)
189
+ }
190
+
191
+ function contextSize(context = 8192, model_config, bsz = 512, cache_bit = 16) {
192
+ return Number.parseFloat((inputBuffer(context, model_config, bsz) + kvCache(context, model_config, cache_bit) + computeBuffer(context, model_config, bsz)).toFixed(2))
193
+ }
194
+
195
+ function modelSize(model_config, bpw = 4.5) {
196
+ return Number.parseFloat((model_config["parameters"] * bpw / 8).toFixed(2))
197
+ }
198
+
199
+ async function calculateSizes(format, context_loc) {
200
+
201
+ format = "gguf"
202
+
203
+ try {
204
+ const model_config = await modelConfig(document.getElementById("modelsearch").value)
205
+ const context = parseInt(document.getElementById("contextsize").value)
206
+ let bsz = 512
207
+ let cache_bit = 16
208
+ let bpw = 0
209
+ if (format === "gguf") {
210
+ bsz = parseInt(document.getElementById("batchsize").value)
211
+ bpw = gguf_quants[document.getElementById("quantsize").innerText]
212
+
213
+ } else if (format == "exl2") {
214
+ cache_bit = Number.parseInt(document.getElementById("kvCache").value)
215
+ bpw = Number.parseFloat(document.getElementById("bpw").value)
216
+ }
217
+
218
+ const model_size = modelSize(model_config, bpw)
219
+ const context_size = contextSize(context, model_config, bsz, cache_bit)
220
+ const total_size = ((model_size + context_size) / 2 ** 30)
221
+ document.getElementById("resultmodel").innerText = (model_size / 2 ** 30).toFixed(2)
222
+ document.getElementById("resultcontext").innerText = (context_size / 2 ** 30).toFixed(2)
223
+ const result_total_el = document.getElementById("resulttotal");
224
+ result_total_el.innerText = total_size.toFixed(2)
225
+
226
+ const allocated_vram = Number.parseInt(document.getElementById("maxvram").value);
227
+ const vram = allocated_vram
228
+ if (vram - total_size > 0.5) {
229
+ result_total_el.style.backgroundColor = "#bef264"
230
+ } else if (vram - total_size > 0) {
231
+ result_total_el.style.backgroundColor = "#facc15"
232
+ } else {
233
+ result_total_el.style.backgroundColor = "#ef4444"
234
+ }
235
+
236
+ result_total_el.style.color = "#000000"
237
+
238
+ const layer_size = ((model_size / 2 ** 30) / model_config["num_hidden_layers"])
239
+ const layer_size_el = document.getElementById("layersize");
240
+ layer_size_el.innerText = layer_size.toFixed(2)
241
+
242
+ const context_dealloc = context_loc === "vram" ? (context_size / 2 ** 30) : 0;
243
+ const layers_offload = Math.floor((allocated_vram - context_dealloc) / layer_size)
244
+
245
+ const layers_offload_el = document.getElementById("layersoffload");
246
+ layers_offload_el.innerText = `${layers_offload > model_config["num_hidden_layers"] ? model_config["num_hidden_layers"] : Math.max(0, layers_offload)}/${model_config["num_hidden_layers"]}`
247
+
248
+ } catch (e) {
249
+ alert(e);
250
+ }
251
+ }
252
+ </script>
253
+ <link href="./styles.css" rel="stylesheet">
254
+ <title>Can I split it? - GGUF VRAM Calculator</title>
255
+ </head>
256
+
257
+ <body class="p-8">
258
+ <div>
259
+ <button onclick="toggleDarkMode()">Toggle Dark Mode</button>
260
+ </div>
261
+ <div x-data="{ format: 'gguf', context_loc: 'vram' }" class="flex flex-col max-h-screen items-center mt-16 gap-10">
262
+ <div style="text-align: center;">
263
+ <h1 class="text-xl font-semibold leading-6">
264
+ GGUF Model, Can I split it?
265
+ </h1>
266
+ <h3 class="font-semibold leading-6">
267
+ Based on <a href="https://huggingface.co/NyxKrage" style="color: blue;">NyxKrage</a>'s <a
268
+ href="https://huggingface.co/spaces/NyxKrage/LLM-Model-VRAM-Calculator" style="color: blue;">LLM VRAM
269
+ calculator</a>
270
+ </h3>
271
+ </div>
272
+ <div class="flex flex-col gap-10">
273
+ <div class="w-auto flex flex-col gap-4">
274
+ <div class="relative">
275
+ <label for="maxvram"
276
+ class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
277
+ Max Allocated VRAM
278
+ </label>
279
+ <input value="24" type="number" name="maxvram" id="maxvram" step="1"
280
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" />
281
+ </div>
282
+
283
+ <!-- Model Selector -->
284
+
285
+
286
+ <div class="flex flex-row gap-4 relative">
287
+ <label for="contextsize"
288
+ class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
289
+ Model (unquantized)
290
+ </label>
291
+ <div
292
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
293
+ x-data="{
294
+ open: false,
295
+ value: 'Nexusflow/Starling-LM-7B-beta',
296
+ results: null,
297
+ toggle() {
298
+ if (this.open) {
299
+ return this.close()
300
+ }
301
+
302
+ this.$refs.input.focus()
303
+
304
+ this.open = true
305
+ },
306
+ close(focusAfter) {
307
+ if (! this.open) return
308
+
309
+ this.open = false
310
+
311
+ focusAfter && focusAfter.focus()
312
+ }
313
+ }" x-on:keydown.escape.prevent.stop="close($refs.input)" x-id="['model-typeahead']"
314
+ class="relative">
315
+ <!-- Input -->
316
+ <input id="modelsearch" x-ref="input" x-on:click="toggle()"
317
+ @keypress.debounce.150ms="results = (await
318
+ fetch('https://huggingface.co/api/quicksearch?type=model&q=' +
319
+ encodeURIComponent(value)).then(r => r.json())).models.filter(m => !m.id.includes('GGUF') && !m.id.includes('AWQ') && !m.id.includes('GPTQ') && !m.id.includes('exl2'));"
320
+ :aria-expanded="open" :aria-controls="$id('model-typeahead')" x-model="value"
321
+ class="flex justify-between items-center gap-2 w-full" />
322
+
323
+ <!-- Panel -->
324
+ <div x-ref="panel" x-show="open" x-transition.origin.top.left x-on:click.outside="close($refs.input)"
325
+ :id="$id('model-typeahead')" style="display: none"
326
+ class="absolute left-0 mt-4 w-full rounded-md bg-white shadow-sm ring-1 ring-inset ring-gray-300 z-10">
327
+ <template x-for="result in results">
328
+ <a @click="value = result.id; close($refs.input)" x-text="result.id"
329
+ class="flex cursor-pointer items-center gap-2 w-full first-of-type:rounded-t-md last-of-type:rounded-b-md px-4 py-2.5 text-left text-sm hover:bg-gray-500/5 disabled:text-gray-500"></a>
330
+ </template>
331
+ </div>
332
+ </div>
333
+ </div>
334
+
335
+
336
+ <!-- Context Size Selector -->
337
+ <div class="relative">
338
+ <label for="contextsize"
339
+ class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
340
+ Context Size
341
+ </label>
342
+ <input value="8192" type="number" name="contextsize" id="contextsize" step="1024"
343
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" />
344
+ </div>
345
+
346
+ <div class="relative">
347
+ <label class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">Context
348
+ offloaded to</label>
349
+ <fieldset x-model="context_loc"
350
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
351
+ <legend class="sr-only">Context location</legend>
352
+ <div class="space-y-4 sm:flex sm:items-center sm:space-x-10 sm:space-y-0">
353
+ <div class="flex items-center">
354
+ <input id="context-vram" name="context-allocation" type="radio" value="vram" checked
355
+ class="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-600" />
356
+ <label for="context-vram" class="ml-3 block text-sm font-medium leading-6">VRAM</label>
357
+ </div>
358
+ <div class="flex items-center">
359
+ <input id="context-ram" name="context-allocation" type="radio" value="ram"
360
+ class="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-600" />
361
+ <label for="context-ram" class="ml-3 block text-sm font-medium leading-6">RAM</label>
362
+ </div>
363
+ </div>
364
+ </fieldset>
365
+ </div>
366
+
367
+ <!-- GGUF Options -->
368
+ <div x-show="format === 'gguf'" class="relative">
369
+ <div class="flex flex-row gap-4">
370
+ <label for="contextsize"
371
+ class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
372
+ Quantization Size
373
+ </label>
374
+ <div
375
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
376
+ x-data="{
377
+ open: false,
378
+ value: '',
379
+ toggle() {
380
+ if (this.open) {
381
+ return this.close()
382
+ }
383
+
384
+ this.$refs.button.focus()
385
+
386
+ this.open = true
387
+ },
388
+ close(focusAfter) {
389
+ if (! this.open) return
390
+
391
+ this.open = false
392
+
393
+ focusAfter && focusAfter.focus()
394
+ }
395
+ }" x-on:keydown.escape.prevent.stop="close($refs.button)" x-id="['dropdown-button']" class="relative">
396
+ <!-- Button -->
397
+ <button x-ref="button" x-on:click="toggle()" :aria-expanded="open" :aria-controls="$id('dropdown-button')"
398
+ type="button" id="quantsize" x-text="value.length === 0 ? 'Q4_K_S' : value"
399
+ class="flex justify-between items-center gap-2 w-full">
400
+ Q4_K_S
401
+
402
+ <!-- Heroicon: chevron-down -->
403
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400" viewBox="0 0 20 20"
404
+ fill="currentColor">
405
+ <path fill-rule="evenodd"
406
+ d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
407
+ clip-rule="evenodd" />
408
+ </svg>
409
+ </button>
410
+
411
+ <!-- Panel -->
412
+ <div x-data="{ quants: [
413
+ 'IQ1_S',
414
+ 'IQ1_M',
415
+ 'IQ2_XXS',
416
+ 'IQ2_XS',
417
+ 'IQ2_S',
418
+ 'IQ3_XXS',
419
+ 'IQ3_XS',
420
+ 'IQ3_S',
421
+ 'IQ3_M',
422
+ 'Q2_K',
423
+ 'Q3_K_S',
424
+ 'Q3_K_M',
425
+ 'Q3_K_L',
426
+ 'IQ4_XS',
427
+ 'Q4_0',
428
+ 'Q4_K_S',
429
+ 'Q4_K_M',
430
+ 'Q5_0',
431
+ 'Q5_K_S',
432
+ 'Q5_K_M',
433
+ 'Q6_K',
434
+ 'Q8_0'
435
+ ]}" x-ref="panel" x-show="open" x-transition.origin.top.left x-on:click.outside="close($refs.button)"
436
+ :id="$id('dropdown-button')" style="display: none"
437
+ class="absolute left-0 mt-4 w-full rounded-md bg-white shadow-sm ring-1 ring-inset ring-gray-300 z-10">
438
+ <template x-for="quant in quants">
439
+ <a @click="value = quant; close($refs.button)" x-text="quant"
440
+ class="flex cursor-pointer items-center gap-2 w-full first-of-type:rounded-t-md last-of-type:rounded-b-md px-4 py-2.5 text-left text-sm hover:bg-gray-500/5 disabled:text-gray-500"></a>
441
+ </template>
442
+ </div>
443
+ </div>
444
+ <div class="relative">
445
+ <label for="batchsize"
446
+ class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
447
+ Batch Size
448
+ </label>
449
+ <input value="512" type="number" step="128" id="batchsize"
450
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" />
451
+ </div>
452
+ </div>
453
+ </div>
454
+ <button type="button"
455
+ class="rounded-md bg-slate-800 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-slate-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
456
+ @click="calculateSizes(format, context_loc)">
457
+ Submit
458
+ </button>
459
+ </div>
460
+ <div class="w-auto flex flex-col gap-4">
461
+ <div class="relative">
462
+ <label class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
463
+ Model Size (GB)
464
+ </label>
465
+ <div id="resultmodel"
466
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
467
+ 4.20</div>
468
+ </div>
469
+ <div class="relative">
470
+ <label class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
471
+ Context Size (GB)
472
+ </label>
473
+ <div id="resultcontext"
474
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
475
+ 6.90</div>
476
+ </div>
477
+ <div class="relative">
478
+ <label class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
479
+ Total Size (GB)
480
+ </label>
481
+ <div id="resulttotal"
482
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
483
+ 420.69</div>
484
+ </div>
485
+ <div class="relative">
486
+ <label class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
487
+ Layer size (GB)
488
+ </label>
489
+ <div id="layersize"
490
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
491
+ 42.69</div>
492
+ </div>
493
+ <div class="relative">
494
+ <label class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium">
495
+ Layers offloaded to GPU (out of total)
496
+ </label>
497
+ <div id="layersoffload"
498
+ class="block w-full rounded-md border-0 p-3 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
499
+ 42</div>
500
+ </div>
501
+ </div>
502
+ </div>
503
+ </div>
504
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
505
+ <script defer>
506
+ calculateSizes("gguf", "vram")
507
+ </script>
508
+ </body>
509
+
510
+ </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
styles.css CHANGED
@@ -1,928 +1,950 @@
1
- /*
2
- ! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com
3
- */
4
-
5
- /*
6
- 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
7
- 2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
8
- */
9
-
10
- *,
11
- ::before,
12
- ::after {
13
- box-sizing: border-box;
14
- /* 1 */
15
- border-width: 0;
16
- /* 2 */
17
- border-style: solid;
18
- /* 2 */
19
- border-color: #e5e7eb;
20
- /* 2 */
21
- }
22
-
23
- ::before,
24
- ::after {
25
- --tw-content: '';
26
- }
27
-
28
- /*
29
- 1. Use a consistent sensible line-height in all browsers.
30
- 2. Prevent adjustments of font size after orientation changes in iOS.
31
- 3. Use a more readable tab size.
32
- 4. Use the user's configured `sans` font-family by default.
33
- 5. Use the user's configured `sans` font-feature-settings by default.
34
- 6. Use the user's configured `sans` font-variation-settings by default.
35
- 7. Disable tap highlights on iOS
36
- */
37
-
38
- html,
39
- :host {
40
- line-height: 1.5;
41
- /* 1 */
42
- -webkit-text-size-adjust: 100%;
43
- /* 2 */
44
- -moz-tab-size: 4;
45
- /* 3 */
46
- -o-tab-size: 4;
47
- tab-size: 4;
48
- /* 3 */
49
- font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
50
- /* 4 */
51
- font-feature-settings: normal;
52
- /* 5 */
53
- font-variation-settings: normal;
54
- /* 6 */
55
- -webkit-tap-highlight-color: transparent;
56
- /* 7 */
57
- }
58
-
59
- /*
60
- 1. Remove the margin in all browsers.
61
- 2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
62
- */
63
-
64
- body {
65
- margin: 0;
66
- /* 1 */
67
- line-height: inherit;
68
- /* 2 */
69
- }
70
-
71
- /*
72
- 1. Add the correct height in Firefox.
73
- 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
74
- 3. Ensure horizontal rules are visible by default.
75
- */
76
-
77
- hr {
78
- height: 0;
79
- /* 1 */
80
- color: inherit;
81
- /* 2 */
82
- border-top-width: 1px;
83
- /* 3 */
84
- }
85
-
86
- /*
87
- Add the correct text decoration in Chrome, Edge, and Safari.
88
- */
89
-
90
- abbr:where([title]) {
91
- -webkit-text-decoration: underline dotted;
92
- text-decoration: underline dotted;
93
- }
94
-
95
- /*
96
- Remove the default font size and weight for headings.
97
- */
98
-
99
- h1,
100
- h2,
101
- h3,
102
- h4,
103
- h5,
104
- h6 {
105
- font-size: inherit;
106
- font-weight: inherit;
107
- }
108
-
109
- /*
110
- Reset links to optimize for opt-in styling instead of opt-out.
111
- */
112
-
113
- a {
114
- color: inherit;
115
- text-decoration: inherit;
116
- }
117
-
118
- /*
119
- Add the correct font weight in Edge and Safari.
120
- */
121
-
122
- b,
123
- strong {
124
- font-weight: bolder;
125
- }
126
-
127
- /*
128
- 1. Use the user's configured `mono` font-family by default.
129
- 2. Use the user's configured `mono` font-feature-settings by default.
130
- 3. Use the user's configured `mono` font-variation-settings by default.
131
- 4. Correct the odd `em` font sizing in all browsers.
132
- */
133
-
134
- code,
135
- kbd,
136
- samp,
137
- pre {
138
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
139
- /* 1 */
140
- font-feature-settings: normal;
141
- /* 2 */
142
- font-variation-settings: normal;
143
- /* 3 */
144
- font-size: 1em;
145
- /* 4 */
146
- }
147
-
148
- /*
149
- Add the correct font size in all browsers.
150
- */
151
-
152
- small {
153
- font-size: 80%;
154
- }
155
-
156
- /*
157
- Prevent `sub` and `sup` elements from affecting the line height in all browsers.
158
- */
159
-
160
- sub,
161
- sup {
162
- font-size: 75%;
163
- line-height: 0;
164
- position: relative;
165
- vertical-align: baseline;
166
- }
167
-
168
- sub {
169
- bottom: -0.25em;
170
- }
171
-
172
- sup {
173
- top: -0.5em;
174
- }
175
-
176
- /*
177
- 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
178
- 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
179
- 3. Remove gaps between table borders by default.
180
- */
181
-
182
- table {
183
- text-indent: 0;
184
- /* 1 */
185
- border-color: inherit;
186
- /* 2 */
187
- border-collapse: collapse;
188
- /* 3 */
189
- }
190
-
191
- /*
192
- 1. Change the font styles in all browsers.
193
- 2. Remove the margin in Firefox and Safari.
194
- 3. Remove default padding in all browsers.
195
- */
196
-
197
- button,
198
- input,
199
- optgroup,
200
- select,
201
- textarea {
202
- font-family: inherit;
203
- /* 1 */
204
- font-feature-settings: inherit;
205
- /* 1 */
206
- font-variation-settings: inherit;
207
- /* 1 */
208
- font-size: 100%;
209
- /* 1 */
210
- font-weight: inherit;
211
- /* 1 */
212
- line-height: inherit;
213
- /* 1 */
214
- color: inherit;
215
- /* 1 */
216
- margin: 0;
217
- /* 2 */
218
- padding: 0;
219
- /* 3 */
220
- }
221
-
222
- /*
223
- Remove the inheritance of text transform in Edge and Firefox.
224
- */
225
-
226
- button,
227
- select {
228
- text-transform: none;
229
- }
230
-
231
- /*
232
- 1. Correct the inability to style clickable types in iOS and Safari.
233
- 2. Remove default button styles.
234
- */
235
-
236
- button,
237
- [type='button'],
238
- [type='reset'],
239
- [type='submit'] {
240
- -webkit-appearance: button;
241
- /* 1 */
242
- background-color: transparent;
243
- /* 2 */
244
- background-image: none;
245
- /* 2 */
246
- }
247
-
248
- /*
249
- Use the modern Firefox focus style for all focusable elements.
250
- */
251
-
252
- :-moz-focusring {
253
- outline: auto;
254
- }
255
-
256
- /*
257
- Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
258
- */
259
-
260
- :-moz-ui-invalid {
261
- box-shadow: none;
262
- }
263
-
264
- /*
265
- Add the correct vertical alignment in Chrome and Firefox.
266
- */
267
-
268
- progress {
269
- vertical-align: baseline;
270
- }
271
-
272
- /*
273
- Correct the cursor style of increment and decrement buttons in Safari.
274
- */
275
-
276
- ::-webkit-inner-spin-button,
277
- ::-webkit-outer-spin-button {
278
- height: auto;
279
- }
280
-
281
- /*
282
- 1. Correct the odd appearance in Chrome and Safari.
283
- 2. Correct the outline style in Safari.
284
- */
285
-
286
- [type='search'] {
287
- -webkit-appearance: textfield;
288
- /* 1 */
289
- outline-offset: -2px;
290
- /* 2 */
291
- }
292
-
293
- /*
294
- Remove the inner padding in Chrome and Safari on macOS.
295
- */
296
-
297
- ::-webkit-search-decoration {
298
- -webkit-appearance: none;
299
- }
300
-
301
- /*
302
- 1. Correct the inability to style clickable types in iOS and Safari.
303
- 2. Change font properties to `inherit` in Safari.
304
- */
305
-
306
- ::-webkit-file-upload-button {
307
- -webkit-appearance: button;
308
- /* 1 */
309
- font: inherit;
310
- /* 2 */
311
- }
312
-
313
- /*
314
- Add the correct display in Chrome and Safari.
315
- */
316
-
317
- summary {
318
- display: list-item;
319
- }
320
-
321
- /*
322
- Removes the default spacing and border for appropriate elements.
323
- */
324
-
325
- blockquote,
326
- dl,
327
- dd,
328
- h1,
329
- h2,
330
- h3,
331
- h4,
332
- h5,
333
- h6,
334
- hr,
335
- figure,
336
- p,
337
- pre {
338
- margin: 0;
339
- }
340
-
341
- fieldset {
342
- margin: 0;
343
- padding: 0;
344
- }
345
-
346
- legend {
347
- padding: 0;
348
- }
349
-
350
- ol,
351
- ul,
352
- menu {
353
- list-style: none;
354
- margin: 0;
355
- padding: 0;
356
- }
357
-
358
- /*
359
- Reset default styling for dialogs.
360
- */
361
-
362
- dialog {
363
- padding: 0;
364
- }
365
-
366
- /*
367
- Prevent resizing textareas horizontally by default.
368
- */
369
-
370
- textarea {
371
- resize: vertical;
372
- }
373
-
374
- /*
375
- 1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
376
- 2. Set the default placeholder color to the user's configured gray 400 color.
377
- */
378
-
379
- input::-moz-placeholder, textarea::-moz-placeholder {
380
- opacity: 1;
381
- /* 1 */
382
- color: #9ca3af;
383
- /* 2 */
384
- }
385
-
386
- input::placeholder,
387
- textarea::placeholder {
388
- opacity: 1;
389
- /* 1 */
390
- color: #9ca3af;
391
- /* 2 */
392
- }
393
-
394
- /*
395
- Set the default cursor for buttons.
396
- */
397
-
398
- button,
399
- [role="button"] {
400
- cursor: pointer;
401
- }
402
-
403
- /*
404
- Make sure disabled buttons don't get the pointer cursor.
405
- */
406
-
407
- :disabled {
408
- cursor: default;
409
- }
410
-
411
- /*
412
- 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
413
- 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
414
- This can trigger a poorly considered lint error in some tools but is included by design.
415
- */
416
-
417
- img,
418
- svg,
419
- video,
420
- canvas,
421
- audio,
422
- iframe,
423
- embed,
424
- object {
425
- display: block;
426
- /* 1 */
427
- vertical-align: middle;
428
- /* 2 */
429
- }
430
-
431
- /*
432
- Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
433
- */
434
-
435
- img,
436
- video {
437
- max-width: 100%;
438
- height: auto;
439
- }
440
-
441
- /* Make elements with the HTML hidden attribute stay hidden by default */
442
-
443
- [hidden] {
444
- display: none;
445
- }
446
-
447
- *, ::before, ::after {
448
- --tw-border-spacing-x: 0;
449
- --tw-border-spacing-y: 0;
450
- --tw-translate-x: 0;
451
- --tw-translate-y: 0;
452
- --tw-rotate: 0;
453
- --tw-skew-x: 0;
454
- --tw-skew-y: 0;
455
- --tw-scale-x: 1;
456
- --tw-scale-y: 1;
457
- --tw-pan-x: ;
458
- --tw-pan-y: ;
459
- --tw-pinch-zoom: ;
460
- --tw-scroll-snap-strictness: proximity;
461
- --tw-gradient-from-position: ;
462
- --tw-gradient-via-position: ;
463
- --tw-gradient-to-position: ;
464
- --tw-ordinal: ;
465
- --tw-slashed-zero: ;
466
- --tw-numeric-figure: ;
467
- --tw-numeric-spacing: ;
468
- --tw-numeric-fraction: ;
469
- --tw-ring-inset: ;
470
- --tw-ring-offset-width: 0px;
471
- --tw-ring-offset-color: #fff;
472
- --tw-ring-color: rgb(59 130 246 / 0.5);
473
- --tw-ring-offset-shadow: 0 0 #0000;
474
- --tw-ring-shadow: 0 0 #0000;
475
- --tw-shadow: 0 0 #0000;
476
- --tw-shadow-colored: 0 0 #0000;
477
- --tw-blur: ;
478
- --tw-brightness: ;
479
- --tw-contrast: ;
480
- --tw-grayscale: ;
481
- --tw-hue-rotate: ;
482
- --tw-invert: ;
483
- --tw-saturate: ;
484
- --tw-sepia: ;
485
- --tw-drop-shadow: ;
486
- --tw-backdrop-blur: ;
487
- --tw-backdrop-brightness: ;
488
- --tw-backdrop-contrast: ;
489
- --tw-backdrop-grayscale: ;
490
- --tw-backdrop-hue-rotate: ;
491
- --tw-backdrop-invert: ;
492
- --tw-backdrop-opacity: ;
493
- --tw-backdrop-saturate: ;
494
- --tw-backdrop-sepia: ;
495
- }
496
-
497
- ::backdrop {
498
- --tw-border-spacing-x: 0;
499
- --tw-border-spacing-y: 0;
500
- --tw-translate-x: 0;
501
- --tw-translate-y: 0;
502
- --tw-rotate: 0;
503
- --tw-skew-x: 0;
504
- --tw-skew-y: 0;
505
- --tw-scale-x: 1;
506
- --tw-scale-y: 1;
507
- --tw-pan-x: ;
508
- --tw-pan-y: ;
509
- --tw-pinch-zoom: ;
510
- --tw-scroll-snap-strictness: proximity;
511
- --tw-gradient-from-position: ;
512
- --tw-gradient-via-position: ;
513
- --tw-gradient-to-position: ;
514
- --tw-ordinal: ;
515
- --tw-slashed-zero: ;
516
- --tw-numeric-figure: ;
517
- --tw-numeric-spacing: ;
518
- --tw-numeric-fraction: ;
519
- --tw-ring-inset: ;
520
- --tw-ring-offset-width: 0px;
521
- --tw-ring-offset-color: #fff;
522
- --tw-ring-color: rgb(59 130 246 / 0.5);
523
- --tw-ring-offset-shadow: 0 0 #0000;
524
- --tw-ring-shadow: 0 0 #0000;
525
- --tw-shadow: 0 0 #0000;
526
- --tw-shadow-colored: 0 0 #0000;
527
- --tw-blur: ;
528
- --tw-brightness: ;
529
- --tw-contrast: ;
530
- --tw-grayscale: ;
531
- --tw-hue-rotate: ;
532
- --tw-invert: ;
533
- --tw-saturate: ;
534
- --tw-sepia: ;
535
- --tw-drop-shadow: ;
536
- --tw-backdrop-blur: ;
537
- --tw-backdrop-brightness: ;
538
- --tw-backdrop-contrast: ;
539
- --tw-backdrop-grayscale: ;
540
- --tw-backdrop-hue-rotate: ;
541
- --tw-backdrop-invert: ;
542
- --tw-backdrop-opacity: ;
543
- --tw-backdrop-saturate: ;
544
- --tw-backdrop-sepia: ;
545
- }
546
-
547
- .sr-only {
548
- position: absolute;
549
- width: 1px;
550
- height: 1px;
551
- padding: 0;
552
- margin: -1px;
553
- overflow: hidden;
554
- clip: rect(0, 0, 0, 0);
555
- white-space: nowrap;
556
- border-width: 0;
557
- }
558
-
559
- .absolute {
560
- position: absolute;
561
- }
562
-
563
- .relative {
564
- position: relative;
565
- }
566
-
567
- .-top-2 {
568
- top: -0.5rem;
569
- }
570
-
571
- .left-0 {
572
- left: 0px;
573
- }
574
-
575
- .left-2 {
576
- left: 0.5rem;
577
- }
578
-
579
- .z-10 {
580
- z-index: 10;
581
- }
582
-
583
- .ml-3 {
584
- margin-left: 0.75rem;
585
- }
586
-
587
- .mt-16 {
588
- margin-top: 4rem;
589
- }
590
-
591
- .mt-4 {
592
- margin-top: 1rem;
593
- }
594
-
595
- .block {
596
- display: block;
597
- }
598
-
599
- .inline-block {
600
- display: inline-block;
601
- }
602
-
603
- .flex {
604
- display: flex;
605
- }
606
-
607
- .table {
608
- display: table;
609
- }
610
-
611
- .hidden {
612
- display: none;
613
- }
614
-
615
- .h-4 {
616
- height: 1rem;
617
- }
618
-
619
- .h-5 {
620
- height: 1.25rem;
621
- }
622
-
623
- .h-full {
624
- height: 100%;
625
- }
626
-
627
- .max-h-screen {
628
- max-height: 100vh;
629
- }
630
-
631
- .w-4 {
632
- width: 1rem;
633
- }
634
-
635
- .w-5 {
636
- width: 1.25rem;
637
- }
638
-
639
- .w-auto {
640
- width: auto;
641
- }
642
-
643
- .w-fit {
644
- width: -moz-fit-content;
645
- width: fit-content;
646
- }
647
-
648
- .w-full {
649
- width: 100%;
650
- }
651
-
652
- .flex-shrink {
653
- flex-shrink: 1;
654
- }
655
-
656
- .flex-grow {
657
- flex-grow: 1;
658
- }
659
-
660
- .cursor-pointer {
661
- cursor: pointer;
662
- }
663
-
664
- .flex-row {
665
- flex-direction: row;
666
- }
667
-
668
- .flex-col {
669
- flex-direction: column;
670
- }
671
-
672
- .items-center {
673
- align-items: center;
674
- }
675
-
676
- .justify-center {
677
- justify-content: center;
678
- }
679
-
680
- .justify-between {
681
- justify-content: space-between;
682
- }
683
-
684
- .gap-10 {
685
- gap: 2.5rem;
686
- }
687
-
688
- .gap-2 {
689
- gap: 0.5rem;
690
- }
691
-
692
- .gap-4 {
693
- gap: 1rem;
694
- }
695
-
696
- .space-y-4 > :not([hidden]) ~ :not([hidden]) {
697
- --tw-space-y-reverse: 0;
698
- margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
699
- margin-bottom: calc(1rem * var(--tw-space-y-reverse));
700
- }
701
-
702
- .rounded-md {
703
- border-radius: 0.375rem;
704
- }
705
-
706
- .border-0 {
707
- border-width: 0px;
708
- }
709
-
710
- .border-gray-300 {
711
- --tw-border-opacity: 1;
712
- border-color: rgb(209 213 219 / var(--tw-border-opacity));
713
- }
714
-
715
- .bg-slate-800 {
716
- --tw-bg-opacity: 1;
717
- background-color: rgb(30 41 59 / var(--tw-bg-opacity));
718
- }
719
-
720
- .bg-white {
721
- --tw-bg-opacity: 1;
722
- background-color: rgb(255 255 255 / var(--tw-bg-opacity));
723
- }
724
-
725
- .p-3 {
726
- padding: 0.75rem;
727
- }
728
-
729
- .p-8 {
730
- padding: 2rem;
731
- }
732
-
733
- .px-1 {
734
- padding-left: 0.25rem;
735
- padding-right: 0.25rem;
736
- }
737
-
738
- .px-3 {
739
- padding-left: 0.75rem;
740
- padding-right: 0.75rem;
741
- }
742
-
743
- .px-4 {
744
- padding-left: 1rem;
745
- padding-right: 1rem;
746
- }
747
-
748
- .py-2 {
749
- padding-top: 0.5rem;
750
- padding-bottom: 0.5rem;
751
- }
752
-
753
- .py-2\.5 {
754
- padding-top: 0.625rem;
755
- padding-bottom: 0.625rem;
756
- }
757
-
758
- .text-left {
759
- text-align: left;
760
- }
761
-
762
- .text-sm {
763
- font-size: 0.875rem;
764
- line-height: 1.25rem;
765
- }
766
-
767
- .text-xl {
768
- font-size: 1.25rem;
769
- line-height: 1.75rem;
770
- }
771
-
772
- .text-xs {
773
- font-size: 0.75rem;
774
- line-height: 1rem;
775
- }
776
-
777
- .font-medium {
778
- font-weight: 500;
779
- }
780
-
781
- .font-semibold {
782
- font-weight: 600;
783
- }
784
-
785
- .leading-6 {
786
- line-height: 1.5rem;
787
- }
788
-
789
- .text-gray-400 {
790
- --tw-text-opacity: 1;
791
- color: rgb(156 163 175 / var(--tw-text-opacity));
792
- }
793
-
794
- .text-gray-900 {
795
- --tw-text-opacity: 1;
796
- color: rgb(17 24 39 / var(--tw-text-opacity));
797
- }
798
-
799
- .text-indigo-600 {
800
- --tw-text-opacity: 1;
801
- color: rgb(79 70 229 / var(--tw-text-opacity));
802
- }
803
-
804
- .text-white {
805
- --tw-text-opacity: 1;
806
- color: rgb(255 255 255 / var(--tw-text-opacity));
807
- }
808
-
809
- .shadow-sm {
810
- --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
811
- --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
812
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
813
- }
814
-
815
- .ring-1 {
816
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
817
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
818
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
819
- }
820
-
821
- .ring-inset {
822
- --tw-ring-inset: inset;
823
- }
824
-
825
- .ring-gray-300 {
826
- --tw-ring-opacity: 1;
827
- --tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity));
828
- }
829
-
830
- .filter {
831
- filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
832
- }
833
-
834
- .placeholder\:text-gray-400::-moz-placeholder {
835
- --tw-text-opacity: 1;
836
- color: rgb(156 163 175 / var(--tw-text-opacity));
837
- }
838
-
839
- .placeholder\:text-gray-400::placeholder {
840
- --tw-text-opacity: 1;
841
- color: rgb(156 163 175 / var(--tw-text-opacity));
842
- }
843
-
844
- .first-of-type\:rounded-t-md:first-of-type {
845
- border-top-left-radius: 0.375rem;
846
- border-top-right-radius: 0.375rem;
847
- }
848
-
849
- .last-of-type\:rounded-b-md:last-of-type {
850
- border-bottom-right-radius: 0.375rem;
851
- border-bottom-left-radius: 0.375rem;
852
- }
853
-
854
- .hover\:bg-gray-500\/5:hover {
855
- background-color: rgb(107 114 128 / 0.05);
856
- }
857
-
858
- .hover\:bg-slate-700:hover {
859
- --tw-bg-opacity: 1;
860
- background-color: rgb(51 65 85 / var(--tw-bg-opacity));
861
- }
862
-
863
- .focus\:ring-2:focus {
864
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
865
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
866
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
867
- }
868
-
869
- .focus\:ring-inset:focus {
870
- --tw-ring-inset: inset;
871
- }
872
-
873
- .focus\:ring-indigo-600:focus {
874
- --tw-ring-opacity: 1;
875
- --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity));
876
- }
877
-
878
- .focus-visible\:outline:focus-visible {
879
- outline-style: solid;
880
- }
881
-
882
- .focus-visible\:outline-2:focus-visible {
883
- outline-width: 2px;
884
- }
885
-
886
- .focus-visible\:outline-offset-2:focus-visible {
887
- outline-offset: 2px;
888
- }
889
-
890
- .focus-visible\:outline-indigo-600:focus-visible {
891
- outline-color: #4f46e5;
892
- }
893
-
894
- .disabled\:text-gray-500:disabled {
895
- --tw-text-opacity: 1;
896
- color: rgb(107 114 128 / var(--tw-text-opacity));
897
- }
898
-
899
- @media (min-width: 640px) {
900
- .sm\:flex {
901
- display: flex;
902
- }
903
-
904
- .sm\:items-center {
905
- align-items: center;
906
- }
907
-
908
- .sm\:space-x-10 > :not([hidden]) ~ :not([hidden]) {
909
- --tw-space-x-reverse: 0;
910
- margin-right: calc(2.5rem * var(--tw-space-x-reverse));
911
- margin-left: calc(2.5rem * calc(1 - var(--tw-space-x-reverse)));
912
- }
913
-
914
- .sm\:space-y-0 > :not([hidden]) ~ :not([hidden]) {
915
- --tw-space-y-reverse: 0;
916
- margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));
917
- margin-bottom: calc(0px * var(--tw-space-y-reverse));
918
- }
919
-
920
- .sm\:text-sm {
921
- font-size: 0.875rem;
922
- line-height: 1.25rem;
923
- }
924
-
925
- .sm\:leading-6 {
926
- line-height: 1.5rem;
927
- }
928
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ ! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com
3
+ */
4
+
5
+ /*
6
+ 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
7
+ 2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
8
+ */
9
+
10
+ *,
11
+ ::before,
12
+ ::after {
13
+ box-sizing: border-box;
14
+ /* 1 */
15
+ border-width: 0;
16
+ /* 2 */
17
+ border-style: solid;
18
+ /* 2 */
19
+ border-color: #e5e7eb;
20
+ /* 2 */
21
+ }
22
+
23
+ ::before,
24
+ ::after {
25
+ --tw-content: '';
26
+ }
27
+
28
+ /*
29
+ 1. Use a consistent sensible line-height in all browsers.
30
+ 2. Prevent adjustments of font size after orientation changes in iOS.
31
+ 3. Use a more readable tab size.
32
+ 4. Use the user's configured `sans` font-family by default.
33
+ 5. Use the user's configured `sans` font-feature-settings by default.
34
+ 6. Use the user's configured `sans` font-variation-settings by default.
35
+ 7. Disable tap highlights on iOS
36
+ */
37
+
38
+ html,
39
+ :host {
40
+ line-height: 1.5;
41
+ /* 1 */
42
+ -webkit-text-size-adjust: 100%;
43
+ /* 2 */
44
+ -moz-tab-size: 4;
45
+ /* 3 */
46
+ -o-tab-size: 4;
47
+ tab-size: 4;
48
+ /* 3 */
49
+ font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
50
+ /* 4 */
51
+ font-feature-settings: normal;
52
+ /* 5 */
53
+ font-variation-settings: normal;
54
+ /* 6 */
55
+ -webkit-tap-highlight-color: transparent;
56
+ /* 7 */
57
+ }
58
+
59
+ /*
60
+ 1. Remove the margin in all browsers.
61
+ 2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
62
+ */
63
+
64
+ body {
65
+ margin: 0;
66
+ /* 1 */
67
+ line-height: inherit;
68
+ /* 2 */
69
+ }
70
+
71
+ /*
72
+ 1. Add the correct height in Firefox.
73
+ 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
74
+ 3. Ensure horizontal rules are visible by default.
75
+ */
76
+
77
+ hr {
78
+ height: 0;
79
+ /* 1 */
80
+ color: inherit;
81
+ /* 2 */
82
+ border-top-width: 1px;
83
+ /* 3 */
84
+ }
85
+
86
+ /*
87
+ Add the correct text decoration in Chrome, Edge, and Safari.
88
+ */
89
+
90
+ abbr:where([title]) {
91
+ -webkit-text-decoration: underline dotted;
92
+ text-decoration: underline dotted;
93
+ }
94
+
95
+ /*
96
+ Remove the default font size and weight for headings.
97
+ */
98
+
99
+ h1,
100
+ h2,
101
+ h3,
102
+ h4,
103
+ h5,
104
+ h6 {
105
+ font-size: inherit;
106
+ font-weight: inherit;
107
+ }
108
+
109
+ /*
110
+ Reset links to optimize for opt-in styling instead of opt-out.
111
+ */
112
+
113
+ a {
114
+ color: inherit;
115
+ text-decoration: inherit;
116
+ }
117
+
118
+ /*
119
+ Add the correct font weight in Edge and Safari.
120
+ */
121
+
122
+ b,
123
+ strong {
124
+ font-weight: bolder;
125
+ }
126
+
127
+ /*
128
+ 1. Use the user's configured `mono` font-family by default.
129
+ 2. Use the user's configured `mono` font-feature-settings by default.
130
+ 3. Use the user's configured `mono` font-variation-settings by default.
131
+ 4. Correct the odd `em` font sizing in all browsers.
132
+ */
133
+
134
+ code,
135
+ kbd,
136
+ samp,
137
+ pre {
138
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
139
+ /* 1 */
140
+ font-feature-settings: normal;
141
+ /* 2 */
142
+ font-variation-settings: normal;
143
+ /* 3 */
144
+ font-size: 1em;
145
+ /* 4 */
146
+ }
147
+
148
+ /*
149
+ Add the correct font size in all browsers.
150
+ */
151
+
152
+ small {
153
+ font-size: 80%;
154
+ }
155
+
156
+ /*
157
+ Prevent `sub` and `sup` elements from affecting the line height in all browsers.
158
+ */
159
+
160
+ sub,
161
+ sup {
162
+ font-size: 75%;
163
+ line-height: 0;
164
+ position: relative;
165
+ vertical-align: baseline;
166
+ }
167
+
168
+ sub {
169
+ bottom: -0.25em;
170
+ }
171
+
172
+ sup {
173
+ top: -0.5em;
174
+ }
175
+
176
+ /*
177
+ 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
178
+ 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
179
+ 3. Remove gaps between table borders by default.
180
+ */
181
+
182
+ table {
183
+ text-indent: 0;
184
+ /* 1 */
185
+ border-color: inherit;
186
+ /* 2 */
187
+ border-collapse: collapse;
188
+ /* 3 */
189
+ }
190
+
191
+ /*
192
+ 1. Change the font styles in all browsers.
193
+ 2. Remove the margin in Firefox and Safari.
194
+ 3. Remove default padding in all browsers.
195
+ */
196
+
197
+ button,
198
+ input,
199
+ optgroup,
200
+ select,
201
+ textarea {
202
+ font-family: inherit;
203
+ /* 1 */
204
+ font-feature-settings: inherit;
205
+ /* 1 */
206
+ font-variation-settings: inherit;
207
+ /* 1 */
208
+ font-size: 100%;
209
+ /* 1 */
210
+ font-weight: inherit;
211
+ /* 1 */
212
+ line-height: inherit;
213
+ /* 1 */
214
+ color: inherit;
215
+ /* 1 */
216
+ margin: 0;
217
+ /* 2 */
218
+ padding: 0;
219
+ /* 3 */
220
+ }
221
+
222
+ /*
223
+ Remove the inheritance of text transform in Edge and Firefox.
224
+ */
225
+
226
+ button,
227
+ select {
228
+ text-transform: none;
229
+ }
230
+
231
+ /*
232
+ 1. Correct the inability to style clickable types in iOS and Safari.
233
+ 2. Remove default button styles.
234
+ */
235
+
236
+ button,
237
+ [type='button'],
238
+ [type='reset'],
239
+ [type='submit'] {
240
+ -webkit-appearance: button;
241
+ /* 1 */
242
+ background-color: transparent;
243
+ /* 2 */
244
+ background-image: none;
245
+ /* 2 */
246
+ }
247
+
248
+ /*
249
+ Use the modern Firefox focus style for all focusable elements.
250
+ */
251
+
252
+ :-moz-focusring {
253
+ outline: auto;
254
+ }
255
+
256
+ /*
257
+ Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
258
+ */
259
+
260
+ :-moz-ui-invalid {
261
+ box-shadow: none;
262
+ }
263
+
264
+ /*
265
+ Add the correct vertical alignment in Chrome and Firefox.
266
+ */
267
+
268
+ progress {
269
+ vertical-align: baseline;
270
+ }
271
+
272
+ /*
273
+ Correct the cursor style of increment and decrement buttons in Safari.
274
+ */
275
+
276
+ ::-webkit-inner-spin-button,
277
+ ::-webkit-outer-spin-button {
278
+ height: auto;
279
+ }
280
+
281
+ /*
282
+ 1. Correct the odd appearance in Chrome and Safari.
283
+ 2. Correct the outline style in Safari.
284
+ */
285
+
286
+ [type='search'] {
287
+ -webkit-appearance: textfield;
288
+ /* 1 */
289
+ outline-offset: -2px;
290
+ /* 2 */
291
+ }
292
+
293
+ /*
294
+ Remove the inner padding in Chrome and Safari on macOS.
295
+ */
296
+
297
+ ::-webkit-search-decoration {
298
+ -webkit-appearance: none;
299
+ }
300
+
301
+ /*
302
+ 1. Correct the inability to style clickable types in iOS and Safari.
303
+ 2. Change font properties to `inherit` in Safari.
304
+ */
305
+
306
+ ::-webkit-file-upload-button {
307
+ -webkit-appearance: button;
308
+ /* 1 */
309
+ font: inherit;
310
+ /* 2 */
311
+ }
312
+
313
+ /*
314
+ Add the correct display in Chrome and Safari.
315
+ */
316
+
317
+ summary {
318
+ display: list-item;
319
+ }
320
+
321
+ /*
322
+ Removes the default spacing and border for appropriate elements.
323
+ */
324
+
325
+ blockquote,
326
+ dl,
327
+ dd,
328
+ h1,
329
+ h2,
330
+ h3,
331
+ h4,
332
+ h5,
333
+ h6,
334
+ hr,
335
+ figure,
336
+ p,
337
+ pre {
338
+ margin: 0;
339
+ }
340
+
341
+ fieldset {
342
+ margin: 0;
343
+ padding: 0;
344
+ }
345
+
346
+ legend {
347
+ padding: 0;
348
+ }
349
+
350
+ ol,
351
+ ul,
352
+ menu {
353
+ list-style: none;
354
+ margin: 0;
355
+ padding: 0;
356
+ }
357
+
358
+ /*
359
+ Reset default styling for dialogs.
360
+ */
361
+
362
+ dialog {
363
+ padding: 0;
364
+ }
365
+
366
+ /*
367
+ Prevent resizing textareas horizontally by default.
368
+ */
369
+
370
+ textarea {
371
+ resize: vertical;
372
+ }
373
+
374
+ /*
375
+ 1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
376
+ 2. Set the default placeholder color to the user's configured gray 400 color.
377
+ */
378
+
379
+ input::-moz-placeholder, textarea::-moz-placeholder {
380
+ opacity: 1;
381
+ /* 1 */
382
+ color: #9ca3af;
383
+ /* 2 */
384
+ }
385
+
386
+ input::placeholder,
387
+ textarea::placeholder {
388
+ opacity: 1;
389
+ /* 1 */
390
+ color: #9ca3af;
391
+ /* 2 */
392
+ }
393
+
394
+ /*
395
+ Set the default cursor for buttons.
396
+ */
397
+
398
+ button,
399
+ [role="button"] {
400
+ cursor: pointer;
401
+ }
402
+
403
+ /*
404
+ Make sure disabled buttons don't get the pointer cursor.
405
+ */
406
+
407
+ :disabled {
408
+ cursor: default;
409
+ }
410
+
411
+ /*
412
+ 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
413
+ 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
414
+ This can trigger a poorly considered lint error in some tools but is included by design.
415
+ */
416
+
417
+ img,
418
+ svg,
419
+ video,
420
+ canvas,
421
+ audio,
422
+ iframe,
423
+ embed,
424
+ object {
425
+ display: block;
426
+ /* 1 */
427
+ vertical-align: middle;
428
+ /* 2 */
429
+ }
430
+
431
+ /*
432
+ Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
433
+ */
434
+
435
+ img,
436
+ video {
437
+ max-width: 100%;
438
+ height: auto;
439
+ }
440
+
441
+ /* Make elements with the HTML hidden attribute stay hidden by default */
442
+
443
+ [hidden] {
444
+ display: none;
445
+ }
446
+
447
+ *, ::before, ::after {
448
+ --tw-border-spacing-x: 0;
449
+ --tw-border-spacing-y: 0;
450
+ --tw-translate-x: 0;
451
+ --tw-translate-y: 0;
452
+ --tw-rotate: 0;
453
+ --tw-skew-x: 0;
454
+ --tw-skew-y: 0;
455
+ --tw-scale-x: 1;
456
+ --tw-scale-y: 1;
457
+ --tw-pan-x: ;
458
+ --tw-pan-y: ;
459
+ --tw-pinch-zoom: ;
460
+ --tw-scroll-snap-strictness: proximity;
461
+ --tw-gradient-from-position: ;
462
+ --tw-gradient-via-position: ;
463
+ --tw-gradient-to-position: ;
464
+ --tw-ordinal: ;
465
+ --tw-slashed-zero: ;
466
+ --tw-numeric-figure: ;
467
+ --tw-numeric-spacing: ;
468
+ --tw-numeric-fraction: ;
469
+ --tw-ring-inset: ;
470
+ --tw-ring-offset-width: 0px;
471
+ --tw-ring-offset-color: #fff;
472
+ --tw-ring-color: rgb(59 130 246 / 0.5);
473
+ --tw-ring-offset-shadow: 0 0 #0000;
474
+ --tw-ring-shadow: 0 0 #0000;
475
+ --tw-shadow: 0 0 #0000;
476
+ --tw-shadow-colored: 0 0 #0000;
477
+ --tw-blur: ;
478
+ --tw-brightness: ;
479
+ --tw-contrast: ;
480
+ --tw-grayscale: ;
481
+ --tw-hue-rotate: ;
482
+ --tw-invert: ;
483
+ --tw-saturate: ;
484
+ --tw-sepia: ;
485
+ --tw-drop-shadow: ;
486
+ --tw-backdrop-blur: ;
487
+ --tw-backdrop-brightness: ;
488
+ --tw-backdrop-contrast: ;
489
+ --tw-backdrop-grayscale: ;
490
+ --tw-backdrop-hue-rotate: ;
491
+ --tw-backdrop-invert: ;
492
+ --tw-backdrop-opacity: ;
493
+ --tw-backdrop-saturate: ;
494
+ --tw-backdrop-sepia: ;
495
+ }
496
+
497
+ ::backdrop {
498
+ --tw-border-spacing-x: 0;
499
+ --tw-border-spacing-y: 0;
500
+ --tw-translate-x: 0;
501
+ --tw-translate-y: 0;
502
+ --tw-rotate: 0;
503
+ --tw-skew-x: 0;
504
+ --tw-skew-y: 0;
505
+ --tw-scale-x: 1;
506
+ --tw-scale-y: 1;
507
+ --tw-pan-x: ;
508
+ --tw-pan-y: ;
509
+ --tw-pinch-zoom: ;
510
+ --tw-scroll-snap-strictness: proximity;
511
+ --tw-gradient-from-position: ;
512
+ --tw-gradient-via-position: ;
513
+ --tw-gradient-to-position: ;
514
+ --tw-ordinal: ;
515
+ --tw-slashed-zero: ;
516
+ --tw-numeric-figure: ;
517
+ --tw-numeric-spacing: ;
518
+ --tw-numeric-fraction: ;
519
+ --tw-ring-inset: ;
520
+ --tw-ring-offset-width: 0px;
521
+ --tw-ring-offset-color: #fff;
522
+ --tw-ring-color: rgb(59 130 246 / 0.5);
523
+ --tw-ring-offset-shadow: 0 0 #0000;
524
+ --tw-ring-shadow: 0 0 #0000;
525
+ --tw-shadow: 0 0 #0000;
526
+ --tw-shadow-colored: 0 0 #0000;
527
+ --tw-blur: ;
528
+ --tw-brightness: ;
529
+ --tw-contrast: ;
530
+ --tw-grayscale: ;
531
+ --tw-hue-rotate: ;
532
+ --tw-invert: ;
533
+ --tw-saturate: ;
534
+ --tw-sepia: ;
535
+ --tw-drop-shadow: ;
536
+ --tw-backdrop-blur: ;
537
+ --tw-backdrop-brightness: ;
538
+ --tw-backdrop-contrast: ;
539
+ --tw-backdrop-grayscale: ;
540
+ --tw-backdrop-hue-rotate: ;
541
+ --tw-backdrop-invert: ;
542
+ --tw-backdrop-opacity: ;
543
+ --tw-backdrop-saturate: ;
544
+ --tw-backdrop-sepia: ;
545
+ }
546
+
547
+ .sr-only {
548
+ position: absolute;
549
+ width: 1px;
550
+ height: 1px;
551
+ padding: 0;
552
+ margin: -1px;
553
+ overflow: hidden;
554
+ clip: rect(0, 0, 0, 0);
555
+ white-space: nowrap;
556
+ border-width: 0;
557
+ }
558
+
559
+ .absolute {
560
+ position: absolute;
561
+ }
562
+
563
+ .relative {
564
+ position: relative;
565
+ }
566
+
567
+ .-top-2 {
568
+ top: -0.5rem;
569
+ }
570
+
571
+ .left-0 {
572
+ left: 0px;
573
+ }
574
+
575
+ .left-2 {
576
+ left: 0.5rem;
577
+ }
578
+
579
+ .z-10 {
580
+ z-index: 10;
581
+ }
582
+
583
+ .ml-3 {
584
+ margin-left: 0.75rem;
585
+ }
586
+
587
+ .mt-16 {
588
+ margin-top: 4rem;
589
+ }
590
+
591
+ .mt-4 {
592
+ margin-top: 1rem;
593
+ }
594
+
595
+ .block {
596
+ display: block;
597
+ }
598
+
599
+ .inline-block {
600
+ display: inline-block;
601
+ }
602
+
603
+ .flex {
604
+ display: flex;
605
+ }
606
+
607
+ .table {
608
+ display: table;
609
+ }
610
+
611
+ .hidden {
612
+ display: none;
613
+ }
614
+
615
+ .h-4 {
616
+ height: 1rem;
617
+ }
618
+
619
+ .h-5 {
620
+ height: 1.25rem;
621
+ }
622
+
623
+ .h-full {
624
+ height: 100%;
625
+ }
626
+
627
+ .max-h-screen {
628
+ max-height: 100vh;
629
+ }
630
+
631
+ .w-4 {
632
+ width: 1rem;
633
+ }
634
+
635
+ .w-5 {
636
+ width: 1.25rem;
637
+ }
638
+
639
+ .w-auto {
640
+ width: auto;
641
+ }
642
+
643
+ .w-fit {
644
+ width: -moz-fit-content;
645
+ width: fit-content;
646
+ }
647
+
648
+ .w-full {
649
+ width: 100%;
650
+ }
651
+
652
+ .flex-shrink {
653
+ flex-shrink: 1;
654
+ }
655
+
656
+ .flex-grow {
657
+ flex-grow: 1;
658
+ }
659
+
660
+ .cursor-pointer {
661
+ cursor: pointer;
662
+ }
663
+
664
+ .flex-row {
665
+ flex-direction: row;
666
+ }
667
+
668
+ .flex-col {
669
+ flex-direction: column;
670
+ }
671
+
672
+ .items-center {
673
+ align-items: center;
674
+ }
675
+
676
+ .justify-center {
677
+ justify-content: center;
678
+ }
679
+
680
+ .justify-between {
681
+ justify-content: space-between;
682
+ }
683
+
684
+ .gap-10 {
685
+ gap: 2.5rem;
686
+ }
687
+
688
+ .gap-2 {
689
+ gap: 0.5rem;
690
+ }
691
+
692
+ .gap-4 {
693
+ gap: 1rem;
694
+ }
695
+
696
+ .space-y-4 > :not([hidden]) ~ :not([hidden]) {
697
+ --tw-space-y-reverse: 0;
698
+ margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
699
+ margin-bottom: calc(1rem * var(--tw-space-y-reverse));
700
+ }
701
+
702
+ .rounded-md {
703
+ border-radius: 0.375rem;
704
+ }
705
+
706
+ .border-0 {
707
+ border-width: 0px;
708
+ }
709
+
710
+ .border-gray-300 {
711
+ --tw-border-opacity: 1;
712
+ border-color: rgb(209 213 219 / var(--tw-border-opacity));
713
+ }
714
+
715
+ .bg-slate-800 {
716
+ --tw-bg-opacity: 1;
717
+ background-color: rgb(30 41 59 / var(--tw-bg-opacity));
718
+ }
719
+
720
+ .bg-white {
721
+ --tw-bg-opacity: 1;
722
+ background-color: rgb(255 255 255 / var(--tw-bg-opacity));
723
+ }
724
+
725
+ .p-3 {
726
+ padding: 0.75rem;
727
+ }
728
+
729
+ .p-8 {
730
+ padding: 2rem;
731
+ }
732
+
733
+ .px-1 {
734
+ padding-left: 0.25rem;
735
+ padding-right: 0.25rem;
736
+ }
737
+
738
+ .px-3 {
739
+ padding-left: 0.75rem;
740
+ padding-right: 0.75rem;
741
+ }
742
+
743
+ .px-4 {
744
+ padding-left: 1rem;
745
+ padding-right: 1rem;
746
+ }
747
+
748
+ .py-2 {
749
+ padding-top: 0.5rem;
750
+ padding-bottom: 0.5rem;
751
+ }
752
+
753
+ .py-2\.5 {
754
+ padding-top: 0.625rem;
755
+ padding-bottom: 0.625rem;
756
+ }
757
+
758
+ .text-left {
759
+ text-align: left;
760
+ }
761
+
762
+ .text-sm {
763
+ font-size: 0.875rem;
764
+ line-height: 1.25rem;
765
+ }
766
+
767
+ .text-xl {
768
+ font-size: 1.25rem;
769
+ line-height: 1.75rem;
770
+ }
771
+
772
+ .text-xs {
773
+ font-size: 0.75rem;
774
+ line-height: 1rem;
775
+ }
776
+
777
+ .font-medium {
778
+ font-weight: 500;
779
+ }
780
+
781
+ .font-semibold {
782
+ font-weight: 600;
783
+ }
784
+
785
+ .leading-6 {
786
+ line-height: 1.5rem;
787
+ }
788
+
789
+ .text-gray-400 {
790
+ --tw-text-opacity: 1;
791
+ color: rgb(156 163 175 / var(--tw-text-opacity));
792
+ }
793
+
794
+ .text-gray-900 {
795
+ --tw-text-opacity: 1;
796
+ color: rgb(17 24 39 / var(--tw-text-opacity));
797
+ }
798
+
799
+ .text-indigo-600 {
800
+ --tw-text-opacity: 1;
801
+ color: rgb(79 70 229 / var(--tw-text-opacity));
802
+ }
803
+
804
+ .text-white {
805
+ --tw-text-opacity: 1;
806
+ color: rgb(255 255 255 / var(--tw-text-opacity));
807
+ }
808
+
809
+ .shadow-sm {
810
+ --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
811
+ --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
812
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
813
+ }
814
+
815
+ .ring-1 {
816
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
817
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
818
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
819
+ }
820
+
821
+ .ring-inset {
822
+ --tw-ring-inset: inset;
823
+ }
824
+
825
+ .ring-gray-300 {
826
+ --tw-ring-opacity: 1;
827
+ --tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity));
828
+ }
829
+
830
+ .filter {
831
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
832
+ }
833
+
834
+ .placeholder\:text-gray-400::-moz-placeholder {
835
+ --tw-text-opacity: 1;
836
+ color: rgb(156 163 175 / var(--tw-text-opacity));
837
+ }
838
+
839
+ .placeholder\:text-gray-400::placeholder {
840
+ --tw-text-opacity: 1;
841
+ color: rgb(156 163 175 / var(--tw-text-opacity));
842
+ }
843
+
844
+ .first-of-type\:rounded-t-md:first-of-type {
845
+ border-top-left-radius: 0.375rem;
846
+ border-top-right-radius: 0.375rem;
847
+ }
848
+
849
+ .last-of-type\:rounded-b-md:last-of-type {
850
+ border-bottom-right-radius: 0.375rem;
851
+ border-bottom-left-radius: 0.375rem;
852
+ }
853
+
854
+ .hover\:bg-gray-500\/5:hover {
855
+ background-color: rgb(107 114 128 / 0.05);
856
+ }
857
+
858
+ .hover\:bg-slate-700:hover {
859
+ --tw-bg-opacity: 1;
860
+ background-color: rgb(51 65 85 / var(--tw-bg-opacity));
861
+ }
862
+
863
+ .focus\:ring-2:focus {
864
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
865
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
866
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
867
+ }
868
+
869
+ .focus\:ring-inset:focus {
870
+ --tw-ring-inset: inset;
871
+ }
872
+
873
+ .focus\:ring-indigo-600:focus {
874
+ --tw-ring-opacity: 1;
875
+ --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity));
876
+ }
877
+
878
+ .focus-visible\:outline:focus-visible {
879
+ outline-style: solid;
880
+ }
881
+
882
+ .focus-visible\:outline-2:focus-visible {
883
+ outline-width: 2px;
884
+ }
885
+
886
+ .focus-visible\:outline-offset-2:focus-visible {
887
+ outline-offset: 2px;
888
+ }
889
+
890
+ .focus-visible\:outline-indigo-600:focus-visible {
891
+ outline-color: #4f46e5;
892
+ }
893
+
894
+ .disabled\:text-gray-500:disabled {
895
+ --tw-text-opacity: 1;
896
+ color: rgb(107 114 128 / var(--tw-text-opacity));
897
+ }
898
+
899
+ @media (min-width: 640px) {
900
+ .sm\:flex {
901
+ display: flex;
902
+ }
903
+
904
+ .sm\:items-center {
905
+ align-items: center;
906
+ }
907
+
908
+ .sm\:space-x-10 > :not([hidden]) ~ :not([hidden]) {
909
+ --tw-space-x-reverse: 0;
910
+ margin-right: calc(2.5rem * var(--tw-space-x-reverse));
911
+ margin-left: calc(2.5rem * calc(1 - var(--tw-space-x-reverse)));
912
+ }
913
+
914
+ .sm\:space-y-0 > :not([hidden]) ~ :not([hidden]) {
915
+ --tw-space-y-reverse: 0;
916
+ margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));
917
+ margin-bottom: calc(0px * var(--tw-space-y-reverse));
918
+ }
919
+
920
+ .sm\:text-sm {
921
+ font-size: 0.875rem;
922
+ line-height: 1.25rem;
923
+ }
924
+
925
+ .sm\:leading-6 {
926
+ line-height: 1.5rem;
927
+ }
928
+ }
929
+
930
+ :root {
931
+ --background-color-light: #ffffff;
932
+ --text-color-light: #000000;
933
+ --background-color-dark: #121212;
934
+ --text-color-dark: #ffffff;
935
+ }
936
+
937
+ .dark-mode {
938
+ background-color: var(--background-color-dark);
939
+ color: var(--text-color-dark);
940
+
941
+ input, textarea {
942
+ background-color: var(--background-color-dark);
943
+ color: var(--text-color-dark);
944
+ }
945
+
946
+ .bg-white {
947
+ --tw-bg-opacity: 1;
948
+ background-color: var(--background-color-dark);
949
+ }
950
+ }