Home

cfg-playground @main - refs - log -
-
https://git.jolheiser.com/cfg-playground.git
cfg playground
tree log patch
add nix, catppuccin, and copy button Signed-off-by: jolheiser <git@jolheiser.com>
Signature
-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgBTEvCQk6VqUAdN2RuH6bj1dNkY oOpbPWj+jw4ua1B1cAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQK2CgRSTixZ6mrUQTdMNZafLLTS3QGPxabfuiCAq+7q2sY6Y7z4AcTO4AKTilkcXKw vKx3Kb5rXidikz2M4dWww= -----END SSH SIGNATURE-----
jolheiser <git@jolheiser.com>
8 months ago
7 changed files, 311 additions(+), 71 deletions(-)
flake.lockflake.nixmain.gostatic/generate.gostatic/index.htmlstatic/tailwind.config.jsstatic/tailwind.go
I flake.lock
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000000000000000000000000000000000000..b661afae8a514851e6a5bcc172db0ebe9d7c237b
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,69 @@
+{
+  "nodes": {
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1728217273,
+        "narHash": "sha256-p/gvyVf24WFs0bted3c71uSQk++ZOYRWbg3bjRoePu4=",
+        "owner": "nixos",
+        "repo": "nixpkgs",
+        "rev": "50b3bd3fed0442bcbf7f58355e990da84af1749d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nixos",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "nixpkgs": "nixpkgs",
+        "tailwind-ctp": "tailwind-ctp",
+        "tailwind-ctp-lsp": "tailwind-ctp-lsp"
+      }
+    },
+    "tailwind-ctp": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1695841587,
+        "narHash": "sha256-fgiZd5AV+hi8Ne0bJ8SyAx5nppseW4aXJQEIDSr0VNA=",
+        "ref": "refs/heads/main",
+        "rev": "afca060674b20e0ccecde2d6fe88c887790219a5",
+        "revCount": 1,
+        "type": "git",
+        "url": "https://git.jolheiser.com/tailwind-ctp"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://git.jolheiser.com/tailwind-ctp"
+      }
+    },
+    "tailwind-ctp-lsp": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1699401590,
+        "narHash": "sha256-nx8ExuBRUux9eXSUgkWp1LJMvA3dmA76+2xggZjHTU0=",
+        "ref": "refs/heads/master",
+        "rev": "b321333ad08bf21db242f246b10ad4a50b8fc8a0",
+        "revCount": 848,
+        "type": "git",
+        "url": "https://git.jolheiser.com/tailwind-ctp-intellisense"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://git.jolheiser.com/tailwind-ctp-intellisense"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
I flake.nix
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000000000000000000000000000000000000..40aaf495202c80107d414a9e34f6706bcc3cfb93
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,58 @@
+{
+  description = "cfg playground";
+
+  inputs = {
+    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
+    tailwind-ctp = {
+      url = "git+https://git.jolheiser.com/tailwind-ctp";
+      inputs.nixpkgs.follows = "nixpkgs";
+    };
+    tailwind-ctp-lsp = {
+      url = "git+https://git.jolheiser.com/tailwind-ctp-intellisense";
+      inputs.nixpkgs.follows = "nixpkgs";
+    };
+  };
+
+  outputs =
+    {
+      self,
+      nixpkgs,
+      tailwind-ctp,
+      tailwind-ctp-lsp,
+    }:
+    let
+      systems = [
+        "x86_64-linux"
+        "i686-linux"
+        "x86_64-darwin"
+        "aarch64-linux"
+        "armv6l-linux"
+        "armv7l-linux"
+      ];
+      forAllSystems = f: nixpkgs.lib.genAttrs systems f;
+      tctp = forAllSystems (system: tailwind-ctp.packages.${system}.default);
+      tctpl = forAllSystems (system: tailwind-ctp-lsp.packages.${system}.default);
+    in
+    {
+      # packages = forAllSystems (system: import ./nix { pkgs = import nixpkgs { inherit system; }; });
+      devShells = forAllSystems (
+        system:
+        let
+          pkgs = import nixpkgs { inherit system; };
+        in
+        {
+          default = pkgs.mkShell {
+            nativeBuildInputs = with pkgs; [
+              go
+              gopls
+              templ
+              tctp.${system}
+              tctpl.${system}
+              vscode-langservers-extracted
+            ];
+          };
+        }
+      );
+      nixosModules.default = import ./nix/module.nix;
+    };
+}
M main.gomain.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
diff --git a/main.go b/main.go
index 24d8ec98b54ef8ecd4ca3bbfd32fc913180abe29..17e84304237551b18683def41cfde7c49b4f76b0 100644
--- a/main.go
+++ b/main.go
@@ -1,11 +1,10 @@
 package main
 
 import (
-	"embed"
+	_ "embed"
 	"encoding/json"
 	"flag"
 	"fmt"
-	iofs "io/fs"
 	"log/slog"
 	"net/http"
 	"os"
@@ -13,12 +12,13 @@ 	"os/signal"
 
 	"github.com/peterbourgon/ff/v3"
 	"go.jolheiser.com/cfg"
+	"go.jolheiser.com/cfg-playground/static"
 	"go.jolheiser.com/ffjsonnet"
 	"go.jolheiser.com/tailroute"
 )
 
-//go:embed static
-var static embed.FS
+//go:embed static/index.html
+var indexHTML []byte
 
 type args struct {
 	hostname string
@@ -60,11 +60,8 @@ 		os.Setenv("TS_AUTHKEY", args.authKey)
 	}
 
 	mux := http.NewServeMux()
-	s, err := iofs.Sub(static, "static")
-	if err != nil {
-		panic(err)
-	}
-	mux.Handle("GET /", http.FileServer(http.FS(s)))
+	mux.HandleFunc("GET /", index)
+	mux.HandleFunc("GET /tailwind.css", static.TailwindHandler)
 	mux.HandleFunc("POST /convert", convert)
 
 	tr := tailroute.Router{
@@ -83,6 +80,13 @@ 	<-ch
 	return nil
 }
 
+func index(w http.ResponseWriter, r *http.Request) {
+	if _, err := w.Write(indexHTML); err != nil {
+		slog.Debug("could not write output", slog.Any("error", err))
+		return
+	}
+}
+
 func convert(w http.ResponseWriter, r *http.Request) {
 	payload := struct {
 		Input string
@@ -90,7 +94,7 @@ 		From  string
 		To    string
 	}{}
 	if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
-		fmt.Println(err)
+		slog.Debug("could not decode JSON body", slog.Any("error", err))
 		return
 	}
 	defer r.Body.Close()
I static/generate.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
diff --git a/static/generate.go b/static/generate.go
new file mode 100644
index 0000000000000000000000000000000000000000..88d179a9e872fd1eda29f60ca7286a514591c363
--- /dev/null
+++ b/static/generate.go
@@ -0,0 +1,72 @@
+//go:build generate
+
+package main
+
+import (
+	"bytes"
+	_ "embed"
+	"fmt"
+	"go/format"
+	"os"
+	"os/exec"
+)
+
+var tailwindCSS = `
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+`
+
+//go:generate templ generate
+//go:generate go run generate.go
+func main() {
+	if err := tailwind(); err != nil {
+		panic(err)
+	}
+}
+
+// Generate tailwind code from templ templates and combine with other misc CSS
+func tailwind() error {
+	fmt.Println("generating tailwind...")
+
+	tmp, err := os.CreateTemp(os.TempDir(), "cfg-tailwind*")
+	if err != nil {
+		return err
+	}
+	defer os.Remove(tmp.Name())
+	if _, err := tmp.WriteString(tailwindCSS); err != nil {
+		return err
+	}
+	tmp.Close()
+
+	styles, err := os.Create("tailwind.go")
+	if err != nil {
+		return err
+	}
+	defer styles.Close()
+
+	var buf bytes.Buffer
+	cmd := exec.Command("tailwind-ctp", "-i", tmp.Name(), "--minify")
+	cmd.Stdout = &buf
+	if err := cmd.Run(); err != nil {
+		return err
+	}
+
+	code := fmt.Sprintf(`// Code generated by generate.go - DO NOT EDIT.
+package static
+
+		import "net/http"
+		
+		func TailwindHandler(w http.ResponseWriter, r *http.Request) {
+			w.Header().Set("Content-Type", "text/css")
+			w.Write([]byte(%q))
+		}`, buf.String())
+	formatted, err := format.Source([]byte(code))
+	if err != nil {
+		return err
+	}
+	styles.Write(formatted)
+
+	fmt.Println("finished generating tailwind")
+	return nil
+}
M static/index.htmlstatic/index.html
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
diff --git a/static/index.html b/static/index.html
index e0106c6913fd8159be80b8b10eaddae83d3b394e..b6fcfb5c4d149a8b97d6e97770263e4e91a8274a 100644
--- a/static/index.html
+++ b/static/index.html
@@ -1,70 +1,92 @@
 <!DOCTYPE html>
 <html lang="en">
+
 <head>
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>cfg</title>
-    <script src="https://cdn.tailwindcss.com"></script>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>cfg</title>
+  <link rel="stylesheet" href="/tailwind.css" />
 </head>
-<body class="bg-gray-100">
-    <div class="flex h-screen">
-        <div class="flex-1 flex flex-col p-4">
-            <h2 class="text-2xl font-bold mb-4">Input</h2>
-            <select id="from" class="w-full mb-2 p-2 border rounded">
-                <option value="json">json(c)</option>
-                <option value="jsonnet">jsonnet</option>
-                <option value="yaml">yaml</option>
-                <option value="toml">toml</option>
-                <option value="nix">nix</option>
-                <option value="dhall">dhall</option>
-                <option value="kdl">kdl</option>
-            </select>
-            <textarea id="input" class="flex-1 p-2 border rounded" placeholder="Paste your config here..."></textarea>
-        </div>
-        <div class="flex-1 flex flex-col p-4">
-            <h2 class="text-2xl font-bold mb-4">Output</h2>
-            <select id="to" class="w-full mb-2 p-2 border rounded">
-                <option value="json">json</option>
-                <option value="yaml">yaml</option>
-                <option value="toml">toml</option>
-                <option value="nix">nix</option>
-                <option value="kdl">kdl</option>
-            </select>
-            <textarea id="output" class="flex-1 p-2 border rounded" placeholder="Converted output will appear here..." readonly></textarea>
-        </div>
+
+<body class="latte dark:mocha bg-base/50 dark:bg-base/95 text-text">
+  <div class="flex h-screen">
+    <div class="flex-1 flex flex-col p-4">
+      <h2 class="text-2xl font-bold mb-4">Input</h2>
+      <select id="from" class="bg-base dark:bg-base/50 w-full mb-2 p-2 border rounded">
+        <option value="json">json(c)</option>
+        <option value="jsonnet">jsonnet</option>
+        <option value="yaml">yaml</option>
+        <option value="toml">toml</option>
+        <option value="nix">nix</option>
+        <option value="dhall">dhall</option>
+        <option value="kdl">kdl</option>
+      </select>
+      <textarea id="input" class="bg-base dark:bg-base/50 flex-1 p-2 border rounded"
+        placeholder="Paste your config here..."></textarea>
     </div>
+    <div class="flex-1 flex flex-col p-4">
+      <h2 class="text-2xl font-bold mb-4">Output</h2>
+      <select id="to" class="bg-base dark:bg-base/50 w-full mb-2 p-2 border rounded">
+        <option value="json">json</option>
+        <option value="yaml">yaml</option>
+        <option value="toml">toml</option>
+        <option value="nix">nix</option>
+        <option value="kdl">kdl</option>
+      </select>
+      <textarea id="output" class="bg-base dark:bg-base/50 flex-1 p-2 border rounded"
+        placeholder="Converted output will appear here..." readonly></textarea>
+    </div>
+  </div>
+  <button id="copy" class="hidden fixed bottom-4 right-4 rounded bg-text hover:bg-text/50">📋</button>
 
-    <script>
-        const $inputFormat = document.getElementById('from');
-        const $outputFormat = document.getElementById('to');
-        const $inputText = document.getElementById('input');
-        const $outputText = document.getElementById('output');
+  <script>
+    const $inputFormat = document.getElementById('from');
+    const $outputFormat = document.getElementById('to');
+    const $inputText = document.getElementById('input');
+    const $outputText = document.getElementById('output');
+    const $copyButton = document.getElementById('copy');
 
-        $inputFormat.addEventListener("input", convert);
-        $outputFormat.addEventListener("input", convert);
-        $inputText.addEventListener("input", convert);
+    $inputFormat.addEventListener("input", convert);
+    $outputFormat.addEventListener("input", convert);
+    $inputText.addEventListener("input", convert);
 
-        function convert() {
-            fetch('/convert', {
-                method: 'POST',
-                headers: {
-                    'Content-Type': 'application/json',
-                },
-                body: JSON.stringify({
-                    from: $inputFormat.value,
-                    to: $outputFormat.value,
-                    input: $inputText.value,
-                }),
-            })
-            .then(response => response.text())
-            .then(data => {
-                $outputText.value = data;
-            })
-            .catch(error => {
-                console.error('Error:', error);
-                $outputText.value = 'An error occurred during conversion.';
-            });
-        }
-    </script>
+    $inputText.addEventListener("keydown", function (event) {
+      if (event.keyCode == 9) {
+        event.preventDefault();
+        const start = this.selectionStart;
+        const end = this.selectionEnd;
+        this.value = this.value.substring(0, start) + "  " + this.value.substring(end);
+        this.selectionStart = this.selectionEnd = start + 2;
+      }
+    });
+
+    if (navigator.clipboard && navigator.clipboard.writeText) $copyButton.classList.remove("hidden");
+    $copyButton.addEventListener("click", () => {
+      navigator.clipboard.writeText($outputText.value);
+    });
+
+    function convert() {
+      fetch('/convert', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          from: $inputFormat.value,
+          to: $outputFormat.value,
+          input: $inputText.value,
+        }),
+      })
+        .then(response => response.text())
+        .then(data => {
+          $outputText.value = data;
+        })
+        .catch(error => {
+          console.error('Error:', error);
+          $outputText.value = 'An error occurred during conversion.';
+        });
+    }
+  </script>
 </body>
-</html>
+
+</html>
\ No newline at end of file
I static/tailwind.config.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
diff --git a/static/tailwind.config.js b/static/tailwind.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..600667950eda206436172ec59f665db8c61baa91
--- /dev/null
+++ b/static/tailwind.config.js
@@ -0,0 +1,6 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+  content: ["./index.html"],
+  plugins: [require("@catppuccin/tailwindcss")],
+}
+
I static/tailwind.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
diff --git a/static/tailwind.go b/static/tailwind.go
new file mode 100644
index 0000000000000000000000000000000000000000..7c70c6b54db944956c516a329f8ecd7c5e76fbc4
--- /dev/null
+++ b/static/tailwind.go
@@ -0,0 +1,9 @@
+// Code generated by generate.go - DO NOT EDIT.
+package static
+
+import "net/http"
+
+func TailwindHandler(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/css")
+	w.Write([]byte("/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:\"\"}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}.latte{--ctp-rosewater:220,138,120;--ctp-flamingo:221,120,120;--ctp-pink:234,118,203;--ctp-mauve:136,57,239;--ctp-red:210,15,57;--ctp-maroon:230,69,83;--ctp-peach:254,100,11;--ctp-yellow:223,142,29;--ctp-green:64,160,43;--ctp-teal:23,146,153;--ctp-sky:4,165,229;--ctp-sapphire:32,159,181;--ctp-blue:30,102,245;--ctp-lavender:114,135,253;--ctp-text:76,79,105;--ctp-subtext1:92,95,119;--ctp-subtext0:108,111,133;--ctp-overlay2:124,127,147;--ctp-overlay1:140,143,161;--ctp-overlay0:156,160,176;--ctp-surface2:172,176,190;--ctp-surface1:188,192,204;--ctp-surface0:204,208,218;--ctp-base:239,241,245;--ctp-mantle:230,233,239;--ctp-crust:220,224,232}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.fixed{position:fixed}.bottom-4{bottom:1rem}.right-4{right:1rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.flex{display:flex}.hidden{display:none}.h-screen{height:100vh}.w-full{width:100%}.flex-1{flex:1 1 0%}.flex-col{flex-direction:column}.rounded{border-radius:.25rem}.border{border-width:1px}.bg-base{--tw-bg-opacity:1;background-color:rgba(var(--ctp-base),var(--tw-bg-opacity))}.bg-base\\/50{background-color:rgba(var(--ctp-base),.5)}.bg-text{--tw-bg-opacity:1;background-color:rgba(var(--ctp-text),var(--tw-bg-opacity))}.p-2{padding:.5rem}.p-4{padding:1rem}.text-2xl{font-size:1.5rem;line-height:2rem}.font-bold{font-weight:700}.text-text{--tw-text-opacity:1;color:rgba(var(--ctp-text),var(--tw-text-opacity))}@media (prefers-color-scheme:dark){.dark\\:mocha{--ctp-rosewater:245,224,220;--ctp-flamingo:242,205,205;--ctp-pink:245,194,231;--ctp-mauve:203,166,247;--ctp-red:243,139,168;--ctp-maroon:235,160,172;--ctp-peach:250,179,135;--ctp-yellow:249,226,175;--ctp-green:166,227,161;--ctp-teal:148,226,213;--ctp-sky:137,220,235;--ctp-sapphire:116,199,236;--ctp-blue:137,180,250;--ctp-lavender:180,190,254;--ctp-text:205,214,244;--ctp-subtext1:186,194,222;--ctp-subtext0:166,173,200;--ctp-overlay2:147,153,178;--ctp-overlay1:127,132,156;--ctp-overlay0:108,112,134;--ctp-surface2:88,91,112;--ctp-surface1:69,71,90;--ctp-surface0:49,50,68;--ctp-base:30,30,46;--ctp-mantle:24,24,37;--ctp-crust:17,17,27}}.hover\\:bg-text\\/50:hover{background-color:rgba(var(--ctp-text),.5)}@media (prefers-color-scheme:dark){.dark\\:bg-base\\/50{background-color:rgba(var(--ctp-base),.5)}.dark\\:bg-base\\/95{background-color:rgba(var(--ctp-base),.95)}}"))
+}